• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

kbugreport.cpp

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

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal