kdeui Library API Documentation

kbugreport.cpp

00001 /* This file is part of the KDE project 00002 Copyright (C) 1999 David Faure <faure@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 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, // modal 00075 true // separator 00076 ) 00077 { 00078 d = new KBugReportPrivate; 00079 00080 // Use supplied aboutdata, otherwise the one from the active instance 00081 // otherwise the KGlobal one. _activeInstance should neved be 0L in theory. 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 // This is a core KDE application -> redirect to the web form 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 // From 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 // Configure email button 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 // To 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 // Program name 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()) { // not present 00165 d->appcombo->insertItem(d->appname); 00166 } 00167 d->appcombo->setCurrentItem(index); 00168 00169 QWhatsThis::add( tmpLabel, qwtstr ); 00170 00171 // Version 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 //glay->addWidget( m_version, row, 1 ); 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 // Severity 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 // Store the severity string as the name 00216 QRadioButton *rb = new QRadioButton( sevTexts[i], m_bgSeverity, sevNames[i] ); 00217 if (i==2) rb->setChecked(true); // default : "normal" 00218 } 00219 00220 lay->addWidget( m_bgSeverity ); 00221 00222 // Subject 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 // The multiline-edit 00242 m_lineedit = new QMultiLineEdit( parent, "QMultiLineEdit" ); 00243 m_lineedit->setMinimumHeight( 180 ); // make it big 00244 m_lineedit->setWordWrap(QMultiLineEdit::WidgetWidth); 00245 lay->addWidget( m_lineedit, 10 /*stretch*/ ); 00246 00247 slotSetFrom(); 00248 } else { 00249 // Point to the web form 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 // ### KDE4: why oh why is KEmailSettings in kio? 00330 KConfig emailConf( QString::fromLatin1("emaildefaults") ); 00331 00332 // find out the default profile 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 // When using the web form, a click can also close the window, as there's 00358 // not much to do. It also gives the user a direct response to his click: 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: // critical 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: // grave 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 // Prepend the pseudo-headers to the contents of the mail 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 // Case 1 : i18n bug 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 // not really i18n's version, so better here IMHO 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 // Case 2 : normal bug 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"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:27 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003