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