00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include <qhbuttongroup.h>
00021
#include <qpushbutton.h>
00022
#include <qlabel.h>
00023
#include <qlayout.h>
00024
#include <qmultilineedit.h>
00025
#include <qradiobutton.h>
00026
#include <qwhatsthis.h>
00027
#include <qregexp.h>
00028
00029
#include <kaboutdata.h>
00030
#include <kapplication.h>
00031
#include <kconfig.h>
00032
#include <kdebug.h>
00033
#include <klineedit.h>
00034
#include <klocale.h>
00035
#include <kmessagebox.h>
00036
#include <kprocess.h>
00037
#include <kstandarddirs.h>
00038
#include <kstdguiitem.h>
00039
#include <kurl.h>
00040
#include <kurllabel.h>
00041
00042
#include "kbugreport.h"
00043
00044
#include <stdio.h>
00045
#include <pwd.h>
00046
#include <unistd.h>
00047
00048
#include <sys/utsname.h>
00049
00050
#include "kdepackages.h"
00051
#include <kcombobox.h>
00052
#include <config.h>
00053
#include <ktempfile.h>
00054
#include <qtextstream.h>
00055
#include <qfile.h>
00056
00057
class KBugReportPrivate {
00058
public:
00059
KComboBox *appcombo;
00060
QString lastError;
00061
QString kde_version;
00062
QString appname;
00063
QString os;
00064
KURLLabel *webFormLabel;
00065 };
00066
00067 KBugReport::KBugReport(
QWidget * parentw,
bool modal,
const KAboutData *aboutData )
00068 :
KDialogBase( Plain,
00069 i18n(
"Submit Bug Report"),
00070 Ok | Cancel,
00071 Ok,
00072 parentw,
00073
"KBugReport",
00074 modal,
00075 true
00076 )
00077 {
00078 d =
new KBugReportPrivate;
00079
00080
00081
00082 m_aboutData = aboutData
00083 ? aboutData
00084 : ( KGlobal::_activeInstance ? KGlobal::_activeInstance->
aboutData()
00085 :
KGlobal::instance()->
aboutData() );
00086 m_process = 0;
00087
QWidget * parent =
plainPage();
00088 d->webFormLabel = 0;
00089
00090
if ( m_aboutData->
bugAddress() == QString::fromLatin1(
"submit@bugs.kde.org") )
00091 {
00092
00093 d->webFormLabel =
new KURLLabel( parent );
00094
setButtonCancel( KStdGuiItem::close() );
00095 }
00096
00097
QLabel * tmpLabel;
00098
QVBoxLayout * lay =
new QVBoxLayout( parent, 0,
spacingHint() );
00099
00100
QGridLayout *glay =
new QGridLayout( lay, 4, 3 );
00101 glay->setColStretch( 1, 10 );
00102 glay->setColStretch( 2, 10 );
00103
00104
int row = 0;
00105
00106
if ( !d->webFormLabel )
00107 {
00108
00109
QString qwtstr = i18n(
"Your email address. If incorrect, use the Configure Email button to change it" );
00110 tmpLabel =
new QLabel( i18n(
"From:"), parent );
00111 glay->addWidget( tmpLabel, row,0 );
00112 QWhatsThis::add( tmpLabel, qwtstr );
00113 m_from =
new QLabel( parent );
00114 glay->addWidget( m_from, row, 1 );
00115 QWhatsThis::add( m_from, qwtstr );
00116
00117
00118
00119 m_configureEmail =
new QPushButton( i18n(
"Configure Email..."),
00120 parent );
00121 connect( m_configureEmail, SIGNAL( clicked() ),
this,
00122 SLOT(
slotConfigureEmail() ) );
00123 glay->addMultiCellWidget( m_configureEmail, 0, 2, 2, 2, AlignTop|AlignRight );
00124
00125
00126 qwtstr = i18n(
"The email address this bug report is sent to." );
00127 tmpLabel =
new QLabel( i18n(
"To:"), parent );
00128 glay->addWidget( tmpLabel, ++row,0 );
00129 QWhatsThis::add( tmpLabel, qwtstr );
00130 tmpLabel =
new QLabel( m_aboutData->
bugAddress(), parent );
00131 glay->addWidget( tmpLabel, row, 1 );
00132 QWhatsThis::add( tmpLabel, qwtstr );
00133
00134
setButtonOK(
KGuiItem( i18n(
"&Send"),
"mail_send", i18n(
"Send bug report." ),
00135 i18n(
"Send this bug report to %1." ).arg( m_aboutData->
bugAddress() ) ) );
00136
00137 }
00138
else
00139 {
00140 m_configureEmail = 0;
00141 m_from = 0;
00142
showButtonOK(
false );
00143 }
00144
00145
00146
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" );
00147 tmpLabel =
new QLabel( i18n(
"Application: "), parent );
00148 glay->addWidget( tmpLabel, ++row, 0 );
00149 QWhatsThis::add( tmpLabel, qwtstr );
00150 d->appcombo =
new KComboBox(
false, parent,
"app");
00151 QWhatsThis::add( d->appcombo, qwtstr );
00152 d->appcombo->insertStrList((
const char**)packages);
00153 connect(d->appcombo, SIGNAL(activated(
int)), SLOT(
appChanged(
int)));
00154 d->appname = QString::fromLatin1( m_aboutData
00155 ? m_aboutData->
productName()
00156 : qApp->name() );
00157 glay->addWidget( d->appcombo, row, 1 );
00158
int index = 0;
00159
for (; index < d->appcombo->count(); index++) {
00160
if (d->appcombo->text(index) == d->appname) {
00161
break;
00162 }
00163 }
00164
if (index == d->appcombo->count()) {
00165 d->appcombo->insertItem(d->appname);
00166 }
00167 d->appcombo->setCurrentItem(index);
00168
00169 QWhatsThis::add( tmpLabel, qwtstr );
00170
00171
00172 qwtstr = i18n(
"The version of this application - please make sure that no newer version is available before sending a bug report" );
00173 tmpLabel =
new QLabel( i18n(
"Version:"), parent );
00174 glay->addWidget( tmpLabel, ++row, 0 );
00175 QWhatsThis::add( tmpLabel, qwtstr );
00176
if (m_aboutData)
00177 m_strVersion = m_aboutData->
version();
00178
else
00179 m_strVersion = i18n(
"no version set (programmer error!)");
00180 d->kde_version = QString::fromLatin1( KDE_VERSION_STRING );
00181 d->kde_version +=
", " + QString::fromLatin1( KDE_DISTRIBUTION_TEXT );
00182
if ( !d->webFormLabel )
00183 m_strVersion +=
" " + d->kde_version;
00184 m_version =
new QLabel( m_strVersion, parent );
00185
00186 glay->addMultiCellWidget( m_version, row, row, 1, 2 );
00187 QWhatsThis::add( m_version, qwtstr );
00188
00189 tmpLabel =
new QLabel(i18n(
"OS:"), parent);
00190 glay->addWidget( tmpLabel, ++row, 0 );
00191
00192
struct utsname unameBuf;
00193 uname( &unameBuf );
00194 d->os = QString::fromLatin1( unameBuf.sysname ) +
00195
" (" + QString::fromLatin1( unameBuf.machine ) +
") "
00196
"release " + QString::fromLatin1( unameBuf.release );
00197
00198 tmpLabel =
new QLabel(d->os, parent);
00199 glay->addMultiCellWidget( tmpLabel, row, row, 1, 2 );
00200
00201 tmpLabel =
new QLabel(i18n(
"Compiler:"), parent);
00202 glay->addWidget( tmpLabel, ++row, 0 );
00203 tmpLabel =
new QLabel(QString::fromLatin1(KDE_COMPILER_VERSION), parent);
00204 glay->addMultiCellWidget( tmpLabel, row, row, 1, 2 );
00205
00206
if ( !d->webFormLabel )
00207 {
00208
00209 m_bgSeverity =
new QHButtonGroup( i18n(
"Se&verity"), parent );
00210
static const char *
const sevNames[5] = {
"critical",
"grave",
"normal",
"wishlist",
"i18n" };
00211
const QString sevTexts[5] = { i18n(
"Critical"), i18n(
"Grave"), i18n(
"normal severity",
"Normal"), i18n(
"Wishlist"), i18n(
"Translation") };
00212
00213
for (
int i = 0 ; i < 5 ; i++ )
00214 {
00215
00216
QRadioButton *rb =
new QRadioButton( sevTexts[i], m_bgSeverity, sevNames[i] );
00217
if (i==2) rb->setChecked(
true);
00218 }
00219
00220 lay->addWidget( m_bgSeverity );
00221
00222
00223
QHBoxLayout * hlay =
new QHBoxLayout( lay );
00224 tmpLabel =
new QLabel( i18n(
"S&ubject: "), parent );
00225 hlay->addWidget( tmpLabel );
00226 m_subject =
new KLineEdit( parent );
00227 m_subject->setFocus();
00228 tmpLabel->setBuddy(m_subject);
00229 hlay->addWidget( m_subject );
00230
00231
QString text = i18n(
""
00232
"Enter the text (in English if possible) that you wish to submit for the "
00233
"bug report.\n"
00234
"If you press \"Send\", a mail message will be sent to the maintainer of "
00235
"this program.\n");
00236 QLabel * label =
new QLabel( parent,
"label" );
00237
00238 label->setText( text );
00239 lay->addWidget( label );
00240
00241
00242 m_lineedit =
new QMultiLineEdit( parent,
"QMultiLineEdit" );
00243 m_lineedit->setMinimumHeight( 180 );
00244 m_lineedit->setWordWrap(QMultiLineEdit::WidgetWidth);
00245 lay->addWidget( m_lineedit, 10 );
00246
00247
slotSetFrom();
00248 }
else {
00249
00250
00251 lay->addSpacing(20);
00252
QString text = i18n(
"To submit a bug report, click on the link below.\n"
00253
"This will open a web browser window on http://bugs.kde.org where you'll find a form to fill in.\n"
00254
"The information displayed above will be transferred to that server.");
00255 QLabel * label =
new QLabel( text, parent,
"label");
00256 lay->addWidget( label );
00257 lay->addSpacing(20);
00258
00259
updateURL();
00260 d->webFormLabel->setText(
"http://bugs.kde.org/wizard.cgi" );
00261 lay->addWidget( d->webFormLabel );
00262 lay->addSpacing(20);
00263
00264 connect( d->webFormLabel, SIGNAL(leftClickedURL(
const QString &)),
00265
this, SLOT(
slotUrlClicked(
const QString &)));
00266 }
00267 }
00268
00269 KBugReport::~KBugReport()
00270 {
00271
delete d;
00272 }
00273
00274 void KBugReport::updateURL()
00275 {
00276
KURL url (
"http://bugs.kde.org/wizard.cgi" );
00277 url.
addQueryItem(
"os", d->os );
00278 url.
addQueryItem(
"compiler", KDE_COMPILER_VERSION );
00279 url.
addQueryItem(
"kdeVersion", d->kde_version );
00280 url.
addQueryItem(
"appVersion", m_strVersion );
00281 url.
addQueryItem(
"package", d->appcombo->currentText() );
00282 url.
addQueryItem(
"kbugreport",
"1" );
00283 d->webFormLabel->setURL( url.
url() );
00284 }
00285
00286 void KBugReport::appChanged(
int i)
00287 {
00288
QString appName = d->appcombo->text(i);
00289
int index = appName.find(
'/' );
00290
if ( index > 0 )
00291 appName = appName.left( index );
00292
kdDebug() <<
"appName " << appName <<
endl;
00293
00294
if (d->appname == appName && m_aboutData)
00295 m_strVersion = m_aboutData->
version();
00296
else
00297 m_strVersion = i18n(
"unknown program name",
"unknown");
00298
00299
if ( !d->webFormLabel )
00300 m_strVersion += d->kde_version;
00301
00302 m_version->setText(m_strVersion);
00303
if ( d->webFormLabel )
00304
updateURL();
00305 }
00306
00307 void KBugReport::slotConfigureEmail()
00308 {
00309
if (m_process)
return;
00310 m_process =
new KProcess;
00311 *m_process << QString::fromLatin1(
"kcmshell") << QString::fromLatin1(
"email");
00312 connect(m_process, SIGNAL(processExited(KProcess *)), SLOT(
slotSetFrom()));
00313
if (!m_process->
start())
00314 {
00315
kdDebug() <<
"Couldn't start kcmshell.." <<
endl;
00316
delete m_process;
00317 m_process = 0;
00318
return;
00319 }
00320 m_configureEmail->setEnabled(
false);
00321 }
00322
00323 void KBugReport::slotSetFrom()
00324 {
00325
delete m_process;
00326 m_process = 0;
00327 m_configureEmail->setEnabled(
true);
00328
00329
00330
KConfig emailConf( QString::fromLatin1(
"emaildefaults") );
00331
00332
00333 emailConf.
setGroup( QString::fromLatin1(
"Defaults") );
00334
QString profile = QString::fromLatin1(
"PROFILE_");
00335 profile += emailConf.
readEntry( QString::fromLatin1(
"Profile"),
00336 QString::fromLatin1(
"Default") );
00337
00338 emailConf.
setGroup( profile );
00339
QString fromaddr = emailConf.
readEntry( QString::fromLatin1(
"EmailAddress") );
00340
if (fromaddr.isEmpty()) {
00341
struct passwd *p;
00342 p = getpwuid(getuid());
00343 fromaddr = QString::fromLatin1(p->pw_name);
00344 }
else {
00345
QString name = emailConf.
readEntry( QString::fromLatin1(
"FullName"));
00346
if (!name.isEmpty())
00347 fromaddr = name + QString::fromLatin1(
" <") + fromaddr + QString::fromLatin1(
">");
00348 }
00349 m_from->setText( fromaddr );
00350 }
00351
00352 void KBugReport::slotUrlClicked(
const QString &urlText)
00353 {
00354
if ( kapp )
00355 kapp->invokeBrowser( urlText );
00356
00357
00358
00359
if ( d->webFormLabel )
00360
KDialogBase::slotCancel();
00361 }
00362
00363
00364 void KBugReport::slotOk(
void )
00365 {
00366
if ( d->webFormLabel)
00367
return;
00368
00369
if( m_lineedit->text().isEmpty() ==
true ||
00370 m_subject->text().isEmpty() ==
true )
00371 {
00372
QString msg = i18n(
"You must specify both a subject and a description "
00373
"before the report can be sent.");
00374
KMessageBox::error(
this,msg);
00375
return;
00376 }
00377
00378
switch ( m_bgSeverity->id( m_bgSeverity->selected() ) )
00379 {
00380
case 0:
00381
if (
KMessageBox::questionYesNo(
this, i18n(
00382
"<p>You chose the severity <b>Critical</b>. "
00383
"Please note that this severity is intended only for bugs that</p>"
00384
"<ul><li>break unrelated software on the system (or the whole system)</li>"
00385
"<li>cause serious data loss</li>"
00386
"<li>introduce a security hole on the system where the affected package is installed</li></ul>\n"
00387
"<p>Does the bug you are reporting cause any of the above damage? "
00388
"If it does not, please select a lower severity. Thank you!</p>" ) ) == KMessageBox::No )
00389
return;
00390
break;
00391
case 1:
00392
if (
KMessageBox::questionYesNo(
this, i18n(
00393
"<p>You chose the severity <b>Grave</b>. "
00394
"Please note that this severity is intended only for bugs that</p>"
00395
"<ul><li>make the package in question unusable or mostly so</li>"
00396
"<li>cause data loss</li>"
00397
"<li>introduce a security hole allowing access to the accounts of users who use the affected package</li></ul>\n"
00398
"<p>Does the bug you are reporting cause any of the above damage? "
00399
"If it does not, please select a lower severity. Thank you!</p>" ) ) == KMessageBox::No )
00400
return;
00401
break;
00402 }
00403
if( !
sendBugReport() )
00404 {
00405
QString msg = i18n(
""
00406
"Unable to send the bug report.\n"
00407
"Please submit a bug report manually...\n"
00408
"See http://bugs.kde.org/ for instructions.");
00409
KMessageBox::error(
this, msg +
"\n\n" + d->lastError);
00410
return;
00411 }
00412
00413
KMessageBox::information(
this,
00414 i18n(
"Bug report sent, thank you for your input."));
00415 accept();
00416 }
00417
00418 void KBugReport::slotCancel()
00419 {
00420
if( !d->webFormLabel && ( m_lineedit->edited() || m_subject->edited() ) )
00421 {
00422
int rc =
KMessageBox::warningYesNo(
this,
00423 i18n(
"Close and discard\nedited message?" ),
00424 i18n(
"Close Message" ), KStdGuiItem::discard(), KStdGuiItem::cont() );
00425
if( rc == KMessageBox::No )
00426
return;
00427 }
00428
KDialogBase::slotCancel();
00429 }
00430
00431
00432 QString KBugReport::text()
const
00433
{
00434
kdDebug() << m_bgSeverity->selected()->name() <<
endl;
00435
00436
QString severity = QString::fromLatin1(m_bgSeverity->selected()->name());
00437
QString appname = d->appcombo->currentText();
00438
QString os = QString::fromLatin1(
"OS: %1 (%2)\n").
00439 arg(KDE_COMPILING_OS).
00440 arg(KDE_DISTRIBUTION_TEXT);
00441
QString bodyText;
00442
for(
int i = 0; i < m_lineedit->numLines(); i++)
00443 {
00444
QString line = m_lineedit->textLine(i);
00445
if (!line.endsWith(
"\n"))
00446 line +=
'\n';
00447 bodyText += line;
00448 }
00449
00450
if (severity == QString::fromLatin1(
"i18n") &&
KGlobal::locale()->
language() !=
KLocale::defaultLanguage()) {
00451
00452
QString package = QString::fromLatin1("i18n_%1").arg(KGlobal::locale()->language());
00453
package = package.replace(QString::fromLatin1("_"), QString::fromLatin1("-"));
00454
return QString::fromLatin1(
"Package: %1").arg(package) +
00455 QString::fromLatin1(
"\n"
00456
"Application: %1\n"
00457
00458
"Version: %2\n").arg(appname).arg(m_strVersion)+
00459 os+QString::fromLatin1(
"\n")+bodyText;
00460 }
else {
00461 appname = appname.replace(QString::fromLatin1(
"_"), QString::fromLatin1(
"-"));
00462
00463
return QString::fromLatin1(
"Package: %1\n"
00464
"Version: %2\n"
00465
"Severity: %3\n")
00466 .arg(appname).arg(m_strVersion).arg(severity)+
00467 QString::fromLatin1(
"Compiler: %1\n").arg(KDE_COMPILER_VERSION)+
00468 os+QString::fromLatin1(
"\n")+bodyText;
00469 }
00470 }
00471
00472 bool KBugReport::sendBugReport()
00473 {
00474
QString recipient ( m_aboutData ?
00475 m_aboutData->
bugAddress() :
00476 QString::fromLatin1(
"submit@bugs.kde.org") );
00477
00478
QString command;
00479 command =
locate(
"exe",
"ksendbugmail");
00480
if (command.isEmpty())
00481 command =
KStandardDirs::findExe( QString::fromLatin1(
"ksendbugmail") );
00482
00483
KTempFile outputfile;
00484 outputfile.
close();
00485
00486
QString subject = m_subject->text();
00487 command +=
" --subject ";
00488 command +=
KProcess::quote(subject);
00489 command +=
" --recipient ";
00490 command +=
KProcess::quote(recipient);
00491 command +=
" > ";
00492 command +=
KProcess::quote(outputfile.
name());
00493
00494 fflush(stdin);
00495 fflush(stderr);
00496
00497 FILE * fd = popen(QFile::encodeName(command),
"w");
00498
if (!fd)
00499 {
00500
kdError() <<
"Unable to open a pipe to " << command <<
endl;
00501
return false;
00502 }
00503
00504
QString btext =
text();
00505 fwrite(btext.ascii(),btext.length(),1,fd);
00506 fflush(fd);
00507
00508
int error = pclose(fd);
00509
kdDebug() <<
"exit status1 " << error <<
" " << (WIFEXITED(error)) <<
" " << WEXITSTATUS(error) <<
endl;
00510
00511
if ((WIFEXITED(error)) && WEXITSTATUS(error) == 1) {
00512
QFile of(outputfile.
name());
00513
if (of.open(IO_ReadOnly )) {
00514
QTextStream is(&of);
00515 is.setEncoding(QTextStream::UnicodeUTF8);
00516
QString line;
00517
while (!is.eof())
00518 line = is.readLine();
00519 d->lastError = line;
00520 }
else {
00521 d->lastError = QString::null;
00522 }
00523 outputfile.
unlink();
00524
return false;
00525 }
00526 outputfile.
unlink();
00527
return true;
00528 }
00529
00530
void KBugReport::virtual_hook(
int id,
void* data )
00531 { KDialogBase::virtual_hook(
id, data ); }
00532
00533
#include "kbugreport.moc"