diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch) | |
tree | 5ac38a06f3dde268dc7927dc155896926aaf7012 /kdeui/kbugreport.cpp | |
download | tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdeui/kbugreport.cpp')
-rw-r--r-- | kdeui/kbugreport.cpp | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/kdeui/kbugreport.cpp b/kdeui/kbugreport.cpp new file mode 100644 index 000000000..f6f529197 --- /dev/null +++ b/kdeui/kbugreport.cpp @@ -0,0 +1,536 @@ +/* This file is part of the KDE project + Copyright (C) 1999 David Faure <faure@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qhbuttongroup.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qmultilineedit.h> +#include <qradiobutton.h> +#include <qwhatsthis.h> +#include <qregexp.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kstdguiitem.h> +#include <kurl.h> +#include <kurllabel.h> + +#include "kbugreport.h" + +#include <stdio.h> +#include <pwd.h> +#include <unistd.h> + +#include <sys/utsname.h> + +#include "kdepackages.h" +#include <kcombobox.h> +#include <config.h> +#include <ktempfile.h> +#include <qtextstream.h> +#include <qfile.h> + +class KBugReportPrivate { +public: + KComboBox *appcombo; + QString lastError; + QString kde_version; + QString appname; + QString os; + QPushButton *submitBugButton; + KURL url; +}; + +KBugReport::KBugReport( QWidget * parentw, bool modal, const KAboutData *aboutData ) + : KDialogBase( Plain, + i18n("Submit Bug Report"), + Ok | Cancel, + Ok, + parentw, + "KBugReport", + modal, // modal + true // separator + ) +{ + d = new KBugReportPrivate; + + // Use supplied aboutdata, otherwise the one from the active instance + // otherwise the KGlobal one. _activeInstance should neved be 0L in theory. + m_aboutData = aboutData + ? aboutData + : ( KGlobal::_activeInstance ? KGlobal::_activeInstance->aboutData() + : KGlobal::instance()->aboutData() ); + m_process = 0; + QWidget * parent = plainPage(); + d->submitBugButton = 0; + + if ( m_aboutData->bugAddress() == QString::fromLatin1("submit@bugs.kde.org") ) + { + // This is a core KDE application -> redirect to the web form + d->submitBugButton = new QPushButton( parent ); + setButtonCancel( KStdGuiItem::close() ); + } + + QLabel * tmpLabel; + QVBoxLayout * lay = new QVBoxLayout( parent, 0, spacingHint() ); + + QGridLayout *glay = new QGridLayout( lay, 4, 3 ); + glay->setColStretch( 1, 10 ); + glay->setColStretch( 2, 10 ); + + int row = 0; + + if ( !d->submitBugButton ) + { + // From + QString qwtstr = i18n( "Your email address. If incorrect, use the Configure Email button to change it" ); + tmpLabel = new QLabel( i18n("From:"), parent ); + glay->addWidget( tmpLabel, row,0 ); + QWhatsThis::add( tmpLabel, qwtstr ); + m_from = new QLabel( parent ); + glay->addWidget( m_from, row, 1 ); + QWhatsThis::add( m_from, qwtstr ); + + + // Configure email button + m_configureEmail = new QPushButton( i18n("Configure Email..."), + parent ); + connect( m_configureEmail, SIGNAL( clicked() ), this, + SLOT( slotConfigureEmail() ) ); + glay->addMultiCellWidget( m_configureEmail, 0, 2, 2, 2, AlignTop|AlignRight ); + + // To + qwtstr = i18n( "The email address this bug report is sent to." ); + tmpLabel = new QLabel( i18n("To:"), parent ); + glay->addWidget( tmpLabel, ++row,0 ); + QWhatsThis::add( tmpLabel, qwtstr ); + tmpLabel = new QLabel( m_aboutData->bugAddress(), parent ); + glay->addWidget( tmpLabel, row, 1 ); + QWhatsThis::add( tmpLabel, qwtstr ); + + setButtonOK( KGuiItem( i18n("&Send"), "mail_send", i18n( "Send bug report." ), + i18n( "Send this bug report to %1." ).arg( m_aboutData->bugAddress() ) ) ); + + } + else + { + m_configureEmail = 0; + m_from = 0; + showButtonOK( false ); + } + + // Program name + 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" ); + tmpLabel = new QLabel( i18n("Application: "), parent ); + glay->addWidget( tmpLabel, ++row, 0 ); + QWhatsThis::add( tmpLabel, qwtstr ); + d->appcombo = new KComboBox( false, parent, "app"); + QWhatsThis::add( d->appcombo, qwtstr ); + d->appcombo->insertStrList((const char**)packages); + connect(d->appcombo, SIGNAL(activated(int)), SLOT(appChanged(int))); + d->appname = QString::fromLatin1( m_aboutData + ? m_aboutData->productName() + : qApp->name() ); + glay->addWidget( d->appcombo, row, 1 ); + int index = 0; + for (; index < d->appcombo->count(); index++) { + if (d->appcombo->text(index) == d->appname) { + break; + } + } + if (index == d->appcombo->count()) { // not present + d->appcombo->insertItem(d->appname); + } + d->appcombo->setCurrentItem(index); + + QWhatsThis::add( tmpLabel, qwtstr ); + + // Version + qwtstr = i18n( "The version of this application - please make sure that no newer version is available before sending a bug report" ); + tmpLabel = new QLabel( i18n("Version:"), parent ); + glay->addWidget( tmpLabel, ++row, 0 ); + QWhatsThis::add( tmpLabel, qwtstr ); + if (m_aboutData) + m_strVersion = m_aboutData->version(); + else + m_strVersion = i18n("no version set (programmer error!)"); + d->kde_version = QString::fromLatin1( KDE_VERSION_STRING ); + d->kde_version += ", " + QString::fromLatin1( KDE_DISTRIBUTION_TEXT ); + if ( !d->submitBugButton ) + m_strVersion += " " + d->kde_version; + m_version = new QLabel( m_strVersion, parent ); + //glay->addWidget( m_version, row, 1 ); + glay->addMultiCellWidget( m_version, row, row, 1, 2 ); + QWhatsThis::add( m_version, qwtstr ); + + tmpLabel = new QLabel(i18n("OS:"), parent); + glay->addWidget( tmpLabel, ++row, 0 ); + + struct utsname unameBuf; + uname( &unameBuf ); + d->os = QString::fromLatin1( unameBuf.sysname ) + + " (" + QString::fromLatin1( unameBuf.machine ) + ") " + "release " + QString::fromLatin1( unameBuf.release ); + + tmpLabel = new QLabel(d->os, parent); + glay->addMultiCellWidget( tmpLabel, row, row, 1, 2 ); + + tmpLabel = new QLabel(i18n("Compiler:"), parent); + glay->addWidget( tmpLabel, ++row, 0 ); + tmpLabel = new QLabel(QString::fromLatin1(KDE_COMPILER_VERSION), parent); + glay->addMultiCellWidget( tmpLabel, row, row, 1, 2 ); + + if ( !d->submitBugButton ) + { + // Severity + m_bgSeverity = new QHButtonGroup( i18n("Se&verity"), parent ); + static const char * const sevNames[5] = { "critical", "grave", "normal", "wishlist", "i18n" }; + const QString sevTexts[5] = { i18n("Critical"), i18n("Grave"), i18n("normal severity","Normal"), i18n("Wishlist"), i18n("Translation") }; + + for (int i = 0 ; i < 5 ; i++ ) + { + // Store the severity string as the name + QRadioButton *rb = new QRadioButton( sevTexts[i], m_bgSeverity, sevNames[i] ); + if (i==2) rb->setChecked(true); // default : "normal" + } + + lay->addWidget( m_bgSeverity ); + + // Subject + QHBoxLayout * hlay = new QHBoxLayout( lay ); + tmpLabel = new QLabel( i18n("S&ubject: "), parent ); + hlay->addWidget( tmpLabel ); + m_subject = new KLineEdit( parent ); + m_subject->setFocus(); + tmpLabel->setBuddy(m_subject); + hlay->addWidget( m_subject ); + + QString text = i18n("Enter the text (in English if possible) that you wish to submit for the " + "bug report.\n" + "If you press \"Send\", a mail message will be sent to the maintainer of " + "this program.\n"); + QLabel * label = new QLabel( parent, "label" ); + + label->setText( text ); + lay->addWidget( label ); + + // The multiline-edit + m_lineedit = new QMultiLineEdit( parent, "QMultiLineEdit" ); + m_lineedit->setMinimumHeight( 180 ); // make it big + m_lineedit->setWordWrap(QMultiLineEdit::WidgetWidth); + lay->addWidget( m_lineedit, 10 /*stretch*/ ); + + slotSetFrom(); + } else { + // Point to the web form + + lay->addSpacing(10); + QString text = i18n("To submit a bug report, click on the button below.\n" + "This will open a web browser window on http://bugs.kde.org where you will find a form to fill in.\n" + "The information displayed above will be transferred to that server."); + QLabel * label = new QLabel( text, parent, "label"); + lay->addWidget( label ); + lay->addSpacing(10); + + updateURL(); + d->submitBugButton->setText( i18n("&Launch Bug Report Wizard") ); + d->submitBugButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); + lay->addWidget( d->submitBugButton ); + lay->addSpacing(10); + + connect( d->submitBugButton, SIGNAL(clicked()), + this, SLOT(slotOk())); + } +} + +KBugReport::~KBugReport() +{ + delete d; +} + +void KBugReport::updateURL() +{ + KURL url ( "http://bugs.kde.org/wizard.cgi" ); + url.addQueryItem( "os", d->os ); + url.addQueryItem( "compiler", KDE_COMPILER_VERSION ); + url.addQueryItem( "kdeVersion", d->kde_version ); + url.addQueryItem( "appVersion", m_strVersion ); + url.addQueryItem( "package", d->appcombo->currentText() ); + url.addQueryItem( "kbugreport", "1" ); + d->url = url; +} + +void KBugReport::appChanged(int i) +{ + QString appName = d->appcombo->text(i); + int index = appName.find( '/' ); + if ( index > 0 ) + appName = appName.left( index ); + kdDebug() << "appName " << appName << endl; + + if (d->appname == appName && m_aboutData) + m_strVersion = m_aboutData->version(); + else + m_strVersion = i18n("unknown program name", "unknown"); + + if ( !d->submitBugButton ) + m_strVersion += d->kde_version; + + m_version->setText(m_strVersion); + if ( d->submitBugButton ) + updateURL(); +} + +void KBugReport::slotConfigureEmail() +{ + if (m_process) return; + m_process = new KProcess; + *m_process << QString::fromLatin1("kcmshell") << QString::fromLatin1("kcm_useraccount"); + connect(m_process, SIGNAL(processExited(KProcess *)), SLOT(slotSetFrom())); + if (!m_process->start()) + { + kdDebug() << "Couldn't start kcmshell.." << endl; + delete m_process; + m_process = 0; + return; + } + m_configureEmail->setEnabled(false); +} + +void KBugReport::slotSetFrom() +{ + delete m_process; + m_process = 0; + m_configureEmail->setEnabled(true); + + // ### KDE4: why oh why is KEmailSettings in kio? + KConfig emailConf( QString::fromLatin1("emaildefaults") ); + + // find out the default profile + emailConf.setGroup( QString::fromLatin1("Defaults") ); + QString profile = QString::fromLatin1("PROFILE_"); + profile += emailConf.readEntry( QString::fromLatin1("Profile"), + QString::fromLatin1("Default") ); + + emailConf.setGroup( profile ); + QString fromaddr = emailConf.readEntry( QString::fromLatin1("EmailAddress") ); + if (fromaddr.isEmpty()) { + struct passwd *p; + p = getpwuid(getuid()); + fromaddr = QString::fromLatin1(p->pw_name); + } else { + QString name = emailConf.readEntry( QString::fromLatin1("FullName")); + if (!name.isEmpty()) + fromaddr = name + QString::fromLatin1(" <") + fromaddr + QString::fromLatin1(">"); + } + m_from->setText( fromaddr ); +} + +void KBugReport::slotUrlClicked(const QString &urlText) +{ + if ( kapp ) + kapp->invokeBrowser( urlText ); + + // When using the web form, a click can also close the window, as there's + // not much to do. It also gives the user a direct response to his click: + if ( d->submitBugButton ) + KDialogBase::slotCancel(); +} + + +void KBugReport::slotOk( void ) +{ + if ( d->submitBugButton ) { + if ( kapp ) + kapp->invokeBrowser( d->url.url() ); + return; + } + + if( m_lineedit->text().isEmpty() || + m_subject->text().isEmpty() ) + { + QString msg = i18n("You must specify both a subject and a description " + "before the report can be sent."); + KMessageBox::error(this,msg); + return; + } + + switch ( m_bgSeverity->id( m_bgSeverity->selected() ) ) + { + case 0: // critical + if ( KMessageBox::questionYesNo( this, i18n( + "<p>You chose the severity <b>Critical</b>. " + "Please note that this severity is intended only for bugs that</p>" + "<ul><li>break unrelated software on the system (or the whole system)</li>" + "<li>cause serious data loss</li>" + "<li>introduce a security hole on the system where the affected package is installed</li></ul>\n" + "<p>Does the bug you are reporting cause any of the above damage? " + "If it does not, please select a lower severity. Thank you!</p>" ),QString::null,KStdGuiItem::cont(),KStdGuiItem::cancel() ) == KMessageBox::No ) + return; + break; + case 1: // grave + if ( KMessageBox::questionYesNo( this, i18n( + "<p>You chose the severity <b>Grave</b>. " + "Please note that this severity is intended only for bugs that</p>" + "<ul><li>make the package in question unusable or mostly so</li>" + "<li>cause data loss</li>" + "<li>introduce a security hole allowing access to the accounts of users who use the affected package</li></ul>\n" + "<p>Does the bug you are reporting cause any of the above damage? " + "If it does not, please select a lower severity. Thank you!</p>" ),QString::null,KStdGuiItem::cont(),KStdGuiItem::cancel() ) == KMessageBox::No ) + return; + break; + } + if( !sendBugReport() ) + { + QString msg = i18n("Unable to send the bug report.\n" + "Please submit a bug report manually...\n" + "See http://bugs.kde.org/ for instructions."); + KMessageBox::error(this, msg + "\n\n" + d->lastError); + return; + } + + KMessageBox::information(this, + i18n("Bug report sent, thank you for your input.")); + accept(); +} + +void KBugReport::slotCancel() +{ + if( !d->submitBugButton && ( m_lineedit->edited() || m_subject->edited() ) ) + { + int rc = KMessageBox::warningYesNo( this, + i18n( "Close and discard\nedited message?" ), + i18n( "Close Message" ), KStdGuiItem::discard(), KStdGuiItem::cont() ); + if( rc == KMessageBox::No ) + return; + } + KDialogBase::slotCancel(); +} + + +QString KBugReport::text() const +{ + kdDebug() << m_bgSeverity->selected()->name() << endl; + // Prepend the pseudo-headers to the contents of the mail + QString severity = QString::fromLatin1(m_bgSeverity->selected()->name()); + QString appname = d->appcombo->currentText(); + QString os = QString::fromLatin1("OS: %1 (%2)\n"). + arg(KDE_COMPILING_OS). + arg(KDE_DISTRIBUTION_TEXT); + QString bodyText; + for(int i = 0; i < m_lineedit->numLines(); i++) + { + QString line = m_lineedit->textLine(i); + if (!line.endsWith("\n")) + line += '\n'; + bodyText += line; + } + + if (severity == QString::fromLatin1("i18n") && KGlobal::locale()->language() != KLocale::defaultLanguage()) { + // Case 1 : i18n bug + QString package = QString::fromLatin1("i18n_%1").arg(KGlobal::locale()->language()); + package = package.replace(QString::fromLatin1("_"), QString::fromLatin1("-")); + return QString::fromLatin1("Package: %1").arg(package) + + QString::fromLatin1("\n" + "Application: %1\n" + // not really i18n's version, so better here IMHO + "Version: %2\n").arg(appname).arg(m_strVersion)+ + os+QString::fromLatin1("\n")+bodyText; + } else { + appname = appname.replace(QString::fromLatin1("_"), QString::fromLatin1("-")); + // Case 2 : normal bug + return QString::fromLatin1("Package: %1\n" + "Version: %2\n" + "Severity: %3\n") + .arg(appname).arg(m_strVersion).arg(severity)+ + QString::fromLatin1("Compiler: %1\n").arg(KDE_COMPILER_VERSION)+ + os+QString::fromLatin1("\n")+bodyText; + } +} + +bool KBugReport::sendBugReport() +{ + QString recipient ( m_aboutData ? + m_aboutData->bugAddress() : + QString::fromLatin1("submit@bugs.kde.org") ); + + QString command; + command = locate("exe", "ksendbugmail"); + if (command.isEmpty()) + command = KStandardDirs::findExe( QString::fromLatin1("ksendbugmail") ); + + KTempFile outputfile; + outputfile.close(); + + QString subject = m_subject->text(); + command += " --subject "; + command += KProcess::quote(subject); + command += " --recipient "; + command += KProcess::quote(recipient); + command += " > "; + command += KProcess::quote(outputfile.name()); + + fflush(stdin); + fflush(stderr); + + FILE * fd = popen(QFile::encodeName(command), "w"); + if (!fd) + { + kdError() << "Unable to open a pipe to " << command << endl; + return false; + } + + QString btext = text(); + fwrite(btext.ascii(),btext.length(),1,fd); + fflush(fd); + + int error = pclose(fd); + kdDebug() << "exit status1 " << error << " " << (WIFEXITED(error)) << " " << WEXITSTATUS(error) << endl; + + if ((WIFEXITED(error)) && WEXITSTATUS(error) == 1) { + QFile of(outputfile.name()); + if (of.open(IO_ReadOnly )) { + QTextStream is(&of); + is.setEncoding(QTextStream::UnicodeUTF8); + QString line; + while (!is.eof()) + line = is.readLine(); + d->lastError = line; + } else { + d->lastError = QString::null; + } + outputfile.unlink(); + return false; + } + outputfile.unlink(); + return true; +} + +void KBugReport::virtual_hook( int id, void* data ) +{ KDialogBase::virtual_hook( id, data ); } + +#include "kbugreport.moc" |