22 #include <QtCore/QProcess>
23 #include <QtCore/QCoreApplication>
24 #include <QtGui/QPushButton>
25 #include <QtGui/QLayout>
26 #include <QtGui/QRadioButton>
27 #include <QtGui/QGroupBox>
28 #include <QtGui/QCloseEvent>
46 #include <sys/utsname.h>
49 #include "kdeversion.h"
51 #include <config-compiler.h>
53 class KBugReportPrivate {
57 void _k_slotConfigureEmail();
58 void _k_slotSetFrom();
59 void _k_appChanged(
int);
81 int currentSeverity() {
82 for (
int i=0;i<severityButtons.count();i++)
83 if (severityButtons[i]->isChecked())
return i;
90 :
KDialog( _parent ), d( new KBugReportPrivate(this) )
98 d->m_aboutData = aboutData ? aboutData
103 d->submitBugWeb =
false;
105 if ( d->m_aboutData->bugAddress() == QLatin1String(
"submit@bugs.kde.org") )
108 d->submitBugWeb =
true;
113 QVBoxLayout * lay =
new QVBoxLayout( parent);
118 lay->addWidget( title );
120 QGridLayout *glay =
new QGridLayout();
121 lay->addLayout(glay);
125 if ( !d->submitBugWeb )
128 QString qwtstr =
i18n(
"Your email address. If incorrect, use the Configure Email button to change it" );
129 tmpLabel =
new QLabel(
i18nc(
"Email sender address",
"From:"), parent );
130 glay->addWidget( tmpLabel, row,0 );
131 tmpLabel->setWhatsThis(qwtstr );
132 d->m_from =
new QLabel( parent );
133 glay->addWidget( d->m_from, row, 1 );
134 d->m_from->setWhatsThis(qwtstr );
140 connect( d->m_configureEmail, SIGNAL(clicked()),
this,
141 SLOT(_k_slotConfigureEmail()) );
142 glay->addWidget( d->m_configureEmail, 0, 2, 3, 1, Qt::AlignTop|Qt::AlignRight );
145 qwtstr =
i18n(
"The email address this bug report is sent to." );
146 tmpLabel =
new QLabel(
i18nc(
"Email receiver address",
"To:"), parent );
147 glay->addWidget( tmpLabel, ++row,0 );
148 tmpLabel->setWhatsThis(qwtstr );
149 tmpLabel =
new QLabel( d->m_aboutData->bugAddress(), parent );
150 tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
151 glay->addWidget( tmpLabel, row, 1 );
152 tmpLabel->setWhatsThis(qwtstr );
155 i18n(
"Send this bug report to %1." , d->m_aboutData->bugAddress() ) ) );
160 d->m_configureEmail = 0;
165 QString qwtstr =
i18n(
"The application for which you wish to submit a bug report - if incorrect, please use the Report Bug menu item of the correct application" );
166 tmpLabel =
new QLabel(
i18n(
"Application: "), parent );
167 glay->addWidget( tmpLabel, row, 0 );
168 tmpLabel->setWhatsThis(qwtstr );
169 d->appcombo =
new KComboBox(
false, parent );
170 d->appcombo->setWhatsThis(qwtstr );
173 packageList << QString::fromLatin1(
packages[c]);
174 d->appcombo->addItems(packageList);
175 connect(d->appcombo, SIGNAL(activated(
int)), SLOT(_k_appChanged(
int)));
176 d->appname = d->m_aboutData
177 ? d->m_aboutData->productName()
178 : qApp->applicationName() ;
179 glay->addWidget( d->appcombo, row, 1 );
181 for (; index < d->appcombo->count(); index++) {
182 if (d->appcombo->itemText(index) == d->appname) {
186 if (index == d->appcombo->count()) {
187 d->appcombo->addItem(d->appname);
189 d->appcombo->setCurrentIndex(index);
191 tmpLabel->setWhatsThis(qwtstr );
194 qwtstr =
i18n(
"The version of this application - please make sure that no newer version is available before sending a bug report" );
195 tmpLabel =
new QLabel(
i18n(
"Version:"), parent );
196 glay->addWidget( tmpLabel, ++row, 0 );
197 tmpLabel->setWhatsThis(qwtstr );
199 d->m_strVersion = d->m_aboutData->version();
201 d->m_strVersion =
i18n(
"no version set (programmer error)");
203 d->kde_version +=
", " + QString::fromLatin1( KDE_DISTRIBUTION_TEXT );
204 if ( !d->submitBugWeb )
205 d->m_strVersion +=
' ' + d->kde_version;
206 d->m_version =
new QLabel( d->m_strVersion, parent );
207 d->m_version->setTextInteractionFlags(Qt::TextBrowserInteraction);
209 glay->addWidget( d->m_version, row, 1, 1, 2 );
210 d->m_version->setWhatsThis(qwtstr );
213 glay->addWidget( tmpLabel, ++row, 0 );
215 struct utsname unameBuf;
217 d->os = QString::fromLatin1( unameBuf.sysname ) +
218 " (" + QString::fromLatin1( unameBuf.machine ) +
") "
219 "release " + QString::fromLatin1( unameBuf.release );
221 tmpLabel =
new QLabel(d->os, parent);
222 tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
223 glay->addWidget( tmpLabel, row, 1, 1, 2 );
225 tmpLabel =
new QLabel(
i18n(
"Compiler:"), parent);
226 glay->addWidget( tmpLabel, ++row, 0 );
227 tmpLabel =
new QLabel(QString::fromLatin1(KDE_COMPILER_VERSION), parent);
228 tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
229 glay->addWidget( tmpLabel, row, 1, 1, 2 );
231 if ( !d->submitBugWeb )
234 d->m_bgSeverity =
new QGroupBox(
i18n(
"Se&verity"), parent );
235 static const char *
const sevNames[5] = {
"critical",
"grave",
"normal",
"wishlist",
"i18n" };
236 const QString sevTexts[5] = {
i18n(
"Critical"),
i18n(
"Grave"),
i18nc(
"normal severity",
"Normal"),
i18n(
"Wishlist"),
i18n(
"Translation") };
237 QHBoxLayout *severityLayout=
new QHBoxLayout(d->m_bgSeverity);
238 for (
int i = 0 ; i < 5 ; i++ )
241 QRadioButton *rb =
new QRadioButton( sevTexts[i], d->m_bgSeverity);
242 rb->setObjectName(sevNames[i] );
243 d->severityButtons.append(rb);
244 severityLayout->addWidget(rb);
245 if (i==2) rb->setChecked(
true);
248 lay->addWidget( d->m_bgSeverity );
251 QHBoxLayout * hlay =
new QHBoxLayout();
253 tmpLabel =
new QLabel(
i18n(
"S&ubject: "), parent );
254 hlay->addWidget( tmpLabel );
256 d->m_subject->setClearButtonShown(
true);
257 d->m_subject->setFocus();
258 tmpLabel->setBuddy( d->m_subject );
259 hlay->addWidget( d->m_subject );
261 QString text =
i18n(
"Enter the text (in English if possible) that you wish to submit for the "
263 "If you press \"Send\", a mail message will be sent to the maintainer of "
267 label->setText( text );
268 lay->addWidget( label );
272 d->m_lineedit->setMinimumHeight( 180 );
273 d->m_lineedit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
274 d->m_lineedit->setLineWrapMode(QTextEdit::WidgetWidth);
275 d->m_lineedit->setCheckSpellingEnabled(
true);
276 d->m_lineedit->setSpellCheckingLanguage(
"en");
277 lay->addWidget( d->m_lineedit, 10 );
284 QString text =
i18n(
"<qt>To submit a bug report, click on the button below. This will open a web browser "
285 "window on <a href=\"http://bugs.kde.org\">http://bugs.kde.org</a> where you will find "
286 "a form to fill in. The information displayed above will be transferred to that server.</qt>");
288 label->setOpenExternalLinks(
true );
289 label->setTextInteractionFlags( Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard );
290 label->setWordWrap(
true );
291 lay->addWidget( label );
294 d->appcombo->setFocus();
301 parent->setMinimumHeight( parent->sizeHint().height() + 20 );
312 if ( !d->submitBugWeb )
313 return d->m_lineedit->toPlainText();
320 if ( !d->submitBugWeb )
321 d->m_lineedit->setPlainText(messageBody);
324 void KBugReportPrivate::_k_updateUrl()
326 url =
KUrl(
"https://bugs.kde.org/enter_bug.cgi" );
327 url.addQueryItem(
"format",
"guided" );
330 QStringList list = appcombo->currentText().split(
'/');
331 url.addQueryItem(
"product", list[0] );
332 if (list.size() == 2) {
333 url.addQueryItem(
"component", list[1] );
336 url.addQueryItem(
"version", m_strVersion );
341 void KBugReportPrivate::_k_appChanged(
int i)
343 QString appName = appcombo->itemText(i);
344 int index = appName.indexOf(
'/' );
346 appName = appName.left( index );
347 kDebug() <<
"appName " << appName;
350 if (appname == appName && m_aboutData) {
351 m_strVersion = m_aboutData->version();
352 strDisplayVersion = m_strVersion;
354 m_strVersion = QLatin1String(
"unknown");
355 strDisplayVersion =
i18nc(
"unknown program name",
"unknown");
358 if ( !submitBugWeb ) {
359 m_strVersion +=
' ' + kde_version;
360 strDisplayVersion +=
' ' + kde_version;
363 m_version->setText(strDisplayVersion);
368 void KBugReportPrivate::_k_slotConfigureEmail()
370 if (m_process)
return;
372 QObject::connect( m_process, SIGNAL(finished(
int,QProcess::ExitStatus)), q, SLOT(_k_slotSetFrom()) );
373 m_process->start( QString::fromLatin1(
"kcmshell4"),
QStringList() << QString::fromLatin1(
"kcm_useraccount") );
374 if ( !m_process->waitForStarted() )
376 kDebug() <<
"Couldn't start kcmshell4..";
381 m_configureEmail->setEnabled(
false);
384 void KBugReportPrivate::_k_slotSetFrom()
388 m_configureEmail->setEnabled(
true);
391 KConfig emailConf( QString::fromLatin1(
"emaildefaults") );
395 QString profile = QString::fromLatin1(
"PROFILE_");
396 profile += cg.readEntry( QString::fromLatin1(
"Profile"),
397 QString::fromLatin1(
"Default") );
400 QString fromaddr = profileGrp.readEntry(
"EmailAddress" );
401 if (fromaddr.isEmpty()) {
403 p = getpwuid(getuid());
404 fromaddr = QString::fromLatin1(p->pw_name);
408 fromaddr = name + QString::fromLatin1(
" <") + fromaddr + QString::fromLatin1(
">");
410 m_from->setText( fromaddr );
415 if ( d->submitBugWeb ) {
420 if( d->m_lineedit->toPlainText().isEmpty() ||
421 d->m_subject->text().isEmpty() )
423 QString msg =
i18n(
"You must specify both a subject and a description "
424 "before the report can be sent.");
429 switch ( d->currentSeverity())
433 "<p>You chose the severity <b>Critical</b>. "
434 "Please note that this severity is intended only for bugs that:</p>"
435 "<ul><li>break unrelated software on the system (or the whole system)</li>"
436 "<li>cause serious data loss</li>"
437 "<li>introduce a security hole on the system where the affected package is installed</li></ul>\n"
438 "<p>Does the bug you are reporting cause any of the above damage? "
444 "<p>You chose the severity <b>Grave</b>. "
445 "Please note that this severity is intended only for bugs that:</p>"
446 "<ul><li>make the package in question unusable or mostly so</li>"
447 "<li>cause data loss</li>"
448 "<li>introduce a security hole allowing access to the accounts of users who use the affected package</li></ul>\n"
449 "<p>Does the bug you are reporting cause any of the above damage? "
458 QString msg =
i18n(
"Unable to send the bug report.\n"
459 "Please submit a bug report manually....\n"
460 "See http://bugs.kde.org/ for instructions.");
466 i18n(
"Bug report sent, thank you for your input."));
472 if( !d->submitBugWeb && ( (d->m_lineedit->toPlainText().length()>0) || d->m_subject->isModified() ) )
475 i18n(
"Close and discard\nedited message?" ),
489 kDebug() << d->severityButtons[d->currentSeverity()]->objectName();
491 QString severity = d->severityButtons[d->currentSeverity()]->objectName();
492 QString appname = d->appcombo->currentText();
493 QString os = QString::fromLatin1(
"OS: %1 (%2)\n").
494 arg(KDE_COMPILING_OS).
495 arg(KDE_DISTRIBUTION_TEXT);
505 bodyText=d->m_lineedit->toPlainText();
506 if (bodyText.length()>0)
507 if (bodyText[bodyText.length()-1]!=
'\n') bodyText+=
'\n';
510 QString package = QString::fromLatin1("i18n_%1").arg(KGlobal::locale()->language());
511 package = package.replace('_', '-');
512 return QString::fromLatin1(
"Package: %1").arg(package) +
513 QString::fromLatin1(
"\n"
516 "Version: %2\n").arg(appname).arg(d->m_strVersion)+
517 os+QString::fromLatin1(
"\n")+bodyText;
519 appname = appname.replace(
'_',
'-');
521 return QString::fromLatin1(
"Package: %1\n"
524 .arg(appname).arg(d->m_strVersion).arg(severity)+
525 QString::fromLatin1(
"Compiler: %1\n").arg(KDE_COMPILER_VERSION)+
526 os+QString::fromLatin1(
"\n")+bodyText;
532 QString recipient ( d->m_aboutData ?
533 d->m_aboutData->bugAddress() :
534 QString::fromLatin1(
"submit@bugs.kde.org") );
538 if (command.isEmpty())
543 args <<
"--subject" << d->m_subject->text() <<
"--recipient" << recipient;
544 proc.start( command, args );
546 if (!proc.waitForStarted())
548 kError() <<
"Unable to open a pipe to " << command << endl;
551 proc.write(
text().toUtf8() );
552 proc.closeWriteChannel();
554 proc.waitForFinished();
555 kDebug() <<
"kbugreport: sendbugmail exit, status " << proc.exitStatus() <<
" code " << proc.exitCode();
558 if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() != 0) {
560 while (!proc.atEnd())
561 line = proc.readLine();
562 d->lastError = QString::fromUtf8( line );
569 #include "kbugreport.moc"
KGuiItem cancel()
Returns the 'Cancel' gui item.
QString i18n(const char *text)
void setButtonGuiItem(ButtonCode id, const KGuiItem &item)
Sets the KGuiItem directly for the button instead of using 3 methods to set the text, tooltip and whatsthis strings.
QString messageBody() const
The message body of the bug report.
KGuiItem discard()
Returns the 'Discard' gui item.
virtual void closeEvent(QCloseEvent *e)
Detects when a dialog is being closed from the window manager controls.
static int warningYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous))
Display a "warning" dialog.
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected) ...
QString label(StandardShortcut id)
Returns a localized label for user-visible display.
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
Display an "Information" dialog.
static QString locate(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
void setMessageBody(const QString &messageBody)
Sets the message body of the bug report.
const char * name(StandardAction id)
This will return the internal name of a given standard action.
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
const KAboutData * aboutData() const
A dialog base class with standard buttons and predefined layouts.
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
virtual ~KBugReport()
Destructor.
#define KDE_VERSION_STRING
virtual void setCaption(const QString &caption)
Make a KDE compliant caption.
virtual void accept()
OK has been clicked.
QString i18nc(const char *ctxt, const char *text)
void setMainWidget(QWidget *widget)
Sets the main widget of the dialog.
A dialog box for sending bug reports.
An abstract class for GUI data such as ToolTip and Icon.
A wrapper around QIcon that provides KDE icon features.
KComponentData activeComponent()
void setButtons(ButtonCodes buttonMask)
Creates (or recreates) the button box and all the buttons in it.
void setButtonIcon(ButtonCode id, const KIcon &icon)
Sets the icon of any button.
static int questionYesNo(QWidget *parent, const QString &text, const QString &caption=QString(), const KGuiItem &buttonYes=KStandardGuiItem::yes(), const KGuiItem &buttonNo=KStandardGuiItem::no(), const QString &dontAskAgainName=QString(), Options options=Notify)
Display a simple "question" dialog.
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted) ...
const char *const packages[]
KGuiItem close()
Returns the 'Close' gui item.
KBugReport(QWidget *parent=0L, bool modal=true, const KAboutData *aboutData=0L)
Creates a bug-report dialog.
An enhanced QLineEdit widget for inputting text.
QString text() const
"Configure email" has been clicked - this calls kcmshell4 System/email
static QString findExe(const QString &appname, const QString &pathstr=QString(), SearchOptions options=NoSearchOptions)
bool sendBugReport()
Attempt to e-mail the bug report.
const KComponentData & mainComponent()
KGuiItem cont()
Returns the 'Continue' gui item.
void setButtonText(ButtonCode id, const QString &text)
Sets the text of any button.
virtual void closeEvent(QCloseEvent *e)
Detects when a dialog is being closed from the window manager controls.
static void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
Display an "Error" dialog.
static QString defaultLanguage()