File indexing completed on 2024-09-08 12:23:21
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kbugreport.h" 0009 0010 #include <QCloseEvent> 0011 #include <QDesktopServices> 0012 #include <QDialogButtonBox> 0013 #include <QFile> 0014 #include <QGridLayout> 0015 #include <QGroupBox> 0016 #include <QHBoxLayout> 0017 #include <QLabel> 0018 #include <QLineEdit> 0019 #include <QLocale> 0020 #include <QProcess> 0021 #include <QPushButton> 0022 #include <QRadioButton> 0023 #include <QStandardPaths> 0024 #include <QTextEdit> 0025 #include <QUrl> 0026 #include <QUrlQuery> 0027 0028 #include <KAboutData> 0029 #include <KConfig> 0030 #include <KEMailSettings> 0031 #include <KLocalizedString> 0032 #include <KMessageBox> 0033 #include <KMessageDialog> 0034 #include <KTitleWidget> 0035 0036 #include "../kxmlgui_version.h" 0037 #include "config-xmlgui.h" 0038 #include "debug.h" 0039 #include "systeminformation_p.h" 0040 0041 #include <array> 0042 0043 class KBugReportPrivate 0044 { 0045 public: 0046 KBugReportPrivate(KBugReport *qq) 0047 : q(qq) 0048 , m_aboutData(KAboutData::applicationData()) 0049 { 0050 } 0051 0052 enum BugDestination { 0053 BugsKdeOrg, 0054 CustomEmail, 0055 CustomUrl, 0056 }; 0057 0058 // Calls kcmshell5 System/email 0059 void slotConfigureEmail(); 0060 0061 // Sets the "From" field from the e-mail configuration. 0062 // Called at creation time, but also after "Configure email" is closed. 0063 void slotSetFrom(); 0064 0065 // Update the url to match the current OS, selected app, etc 0066 void updateUrl(); 0067 0068 KBugReport *const q; 0069 QProcess *m_process = nullptr; 0070 KAboutData m_aboutData; 0071 0072 QTextEdit *m_lineedit = nullptr; 0073 QLineEdit *m_subject = nullptr; 0074 QLabel *m_from = nullptr; 0075 QLabel *m_version = nullptr; 0076 QString m_strVersion; 0077 QGroupBox *m_bgSeverity = nullptr; 0078 QPushButton *m_configureEmail = nullptr; 0079 0080 QString lastError; 0081 QString kde_version; 0082 QString appname; 0083 QString os; 0084 QUrl url; 0085 QList<QRadioButton *> severityButtons; 0086 int currentSeverity() const 0087 { 0088 for (int i = 0; i < severityButtons.count(); i++) { 0089 if (severityButtons[i]->isChecked()) { 0090 return i; 0091 } 0092 } 0093 return -1; 0094 } 0095 BugDestination bugDestination; 0096 }; 0097 0098 KBugReport::KBugReport(const KAboutData &aboutData, QWidget *_parent) 0099 : QDialog(_parent) 0100 , d(new KBugReportPrivate(this)) 0101 { 0102 setWindowTitle(i18nc("@title:window", "Submit Bug Report")); 0103 0104 QDialogButtonBox *buttonBox = new QDialogButtonBox(this); 0105 buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0106 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0107 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0108 0109 d->m_aboutData = aboutData; 0110 d->m_process = nullptr; 0111 d->bugDestination = KBugReportPrivate::CustomEmail; 0112 0113 const QString bugAddress = d->m_aboutData.bugAddress(); 0114 if (bugAddress == QLatin1String("submit@bugs.kde.org")) { 0115 // This is a core KDE application -> redirect to the web form 0116 d->bugDestination = KBugReportPrivate::BugsKdeOrg; 0117 } else if (!QUrl(bugAddress).scheme().isEmpty()) { 0118 // The bug reporting address is a URL -> redirect to that 0119 d->bugDestination = KBugReportPrivate::CustomUrl; 0120 } 0121 0122 if (d->bugDestination != KBugReportPrivate::CustomEmail) { 0123 KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::close()); 0124 } 0125 0126 QLabel *tmpLabel; 0127 QVBoxLayout *lay = new QVBoxLayout(this); 0128 0129 KTitleWidget *title = new KTitleWidget(this); 0130 title->setText(i18n("Submit Bug Report")); 0131 title->setIconSize(QSize(32, 32)); 0132 title->setIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"))); 0133 lay->addWidget(title); 0134 0135 QGridLayout *glay = new QGridLayout(); 0136 lay->addLayout(glay); 0137 0138 int row = 0; 0139 0140 if (d->bugDestination == KBugReportPrivate::CustomEmail) { 0141 // From 0142 QString qwtstr = i18n("Your email address. If incorrect, use the Configure Email button to change it"); 0143 tmpLabel = new QLabel(i18nc("Email sender address", "From:"), this); 0144 glay->addWidget(tmpLabel, row, 0); 0145 tmpLabel->setWhatsThis(qwtstr); 0146 d->m_from = new QLabel(this); 0147 glay->addWidget(d->m_from, row, 1); 0148 d->m_from->setWhatsThis(qwtstr); 0149 0150 // Configure email button 0151 d->m_configureEmail = new QPushButton(i18nc("@action:button", "Configure Email..."), this); 0152 connect(d->m_configureEmail, &QPushButton::clicked, this, [this]() { 0153 d->slotConfigureEmail(); 0154 }); 0155 glay->addWidget(d->m_configureEmail, 0, 2, 3, 1, Qt::AlignTop | Qt::AlignRight); 0156 0157 // To 0158 qwtstr = i18n("The email address this bug report is sent to."); 0159 tmpLabel = new QLabel(i18nc("Email receiver address", "To:"), this); 0160 glay->addWidget(tmpLabel, ++row, 0); 0161 tmpLabel->setWhatsThis(qwtstr); 0162 tmpLabel = new QLabel(d->m_aboutData.bugAddress(), this); 0163 tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 0164 glay->addWidget(tmpLabel, row, 1); 0165 tmpLabel->setWhatsThis(qwtstr); 0166 0167 KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), 0168 KGuiItem(i18nc("@action:button", "&Send"), 0169 QStringLiteral("mail-send"), 0170 i18nc("@info:tooltip", "Send bug report."), 0171 i18nc("@info:whatsthis", "Send this bug report to %1.", d->m_aboutData.bugAddress()))); 0172 row++; 0173 } else { 0174 d->m_configureEmail = nullptr; 0175 d->m_from = nullptr; 0176 } 0177 0178 // Program name 0179 QString qwtstr = 0180 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"); 0181 tmpLabel = new QLabel(i18n("Application: "), this); 0182 glay->addWidget(tmpLabel, row, 0); 0183 tmpLabel->setWhatsThis(qwtstr); 0184 QLabel *appLabel = new QLabel(this); 0185 d->appname = d->m_aboutData.productName(); 0186 appLabel->setText(d->appname); 0187 glay->addWidget(appLabel, row, 1); 0188 tmpLabel->setWhatsThis(qwtstr); 0189 0190 // Version 0191 qwtstr = i18n("The version of this application - please make sure that no newer version is available before sending a bug report"); 0192 tmpLabel = new QLabel(i18n("Version:"), this); 0193 glay->addWidget(tmpLabel, ++row, 0); 0194 tmpLabel->setWhatsThis(qwtstr); 0195 d->m_strVersion = d->m_aboutData.version(); 0196 if (d->m_strVersion.isEmpty()) { 0197 d->m_strVersion = i18n("no version set (programmer error)"); 0198 } 0199 d->kde_version = QStringLiteral(KXMLGUI_VERSION_STRING) + QLatin1String(", ") + QStringLiteral(XMLGUI_DISTRIBUTION_TEXT); 0200 if (d->bugDestination != KBugReportPrivate::BugsKdeOrg) { 0201 d->m_strVersion += QLatin1Char(' ') + d->kde_version; 0202 } 0203 d->m_version = new QLabel(d->m_strVersion, this); 0204 d->m_version->setTextInteractionFlags(Qt::TextBrowserInteraction); 0205 // glay->addWidget( d->m_version, row, 1 ); 0206 glay->addWidget(d->m_version, row, 1, 1, 2); 0207 d->m_version->setWhatsThis(qwtstr); 0208 0209 tmpLabel = new QLabel(i18n("OS:"), this); 0210 glay->addWidget(tmpLabel, ++row, 0); 0211 0212 #ifdef Q_OS_WINDOWS 0213 d->os = i18nc("%1 is the operating system name, e.g. 'Windows 10', %2 is the CPU architecture, e.g. 'x86_64'", 0214 "%1 (%2)", 0215 QSysInfo::prettyProductName(), 0216 QSysInfo::currentCpuArchitecture()); 0217 #else 0218 if (QSysInfo::productVersion() != QLatin1String("unknown")) { 0219 d->os = i18nc( 0220 "%1 is the operating system name, e.g. 'Fedora Linux', %2 is the operating system version, e.g. '35', %3 is the CPU architecture, e.g. 'x86_64'", 0221 "%1 %2 (%3)", 0222 QSysInfo::prettyProductName(), 0223 QSysInfo::productVersion(), 0224 QSysInfo::currentCpuArchitecture()); 0225 } else { 0226 d->os = i18nc("%1 is the operating system name, e.g. 'Fedora Linux', %2 is the CPU architecture, e.g. 'x86_64'", 0227 "%1 (%2)", 0228 QSysInfo::prettyProductName(), 0229 QSysInfo::currentCpuArchitecture()); 0230 } 0231 #endif 0232 0233 tmpLabel = new QLabel(d->os, this); 0234 tmpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); 0235 glay->addWidget(tmpLabel, row, 1, 1, 2); 0236 0237 if (d->bugDestination == KBugReportPrivate::CustomEmail) { 0238 // Severity 0239 d->m_bgSeverity = new QGroupBox(i18nc("@title:group", "Se&verity"), this); 0240 0241 struct SeverityData { 0242 QString name; 0243 QString text; 0244 }; 0245 const std::array<SeverityData, 5> severityData = {{ 0246 {QStringLiteral("critical"), i18nc("bug severity", "Critical")}, 0247 {QStringLiteral("grave"), i18nc("bug severity", "Grave")}, 0248 {QStringLiteral("normal"), i18nc("bug severity", "Normal")}, 0249 {QStringLiteral("wishlist"), i18nc("bug severity", "Wishlist")}, 0250 {QStringLiteral("i18n"), i18nc("bug severity", "Translation")}, 0251 }}; 0252 0253 QHBoxLayout *severityLayout = new QHBoxLayout(d->m_bgSeverity); 0254 for (auto &severityDatum : severityData) { 0255 // Store the severity string as the name 0256 QRadioButton *rb = new QRadioButton(severityDatum.text, d->m_bgSeverity); 0257 rb->setObjectName(severityDatum.name); 0258 d->severityButtons.append(rb); 0259 severityLayout->addWidget(rb); 0260 } 0261 d->severityButtons[2]->setChecked(true); // default : "normal" 0262 0263 lay->addWidget(d->m_bgSeverity); 0264 0265 // Subject 0266 QHBoxLayout *hlay = new QHBoxLayout(); 0267 lay->addItem(hlay); 0268 tmpLabel = new QLabel(i18n("S&ubject: "), this); 0269 hlay->addWidget(tmpLabel); 0270 d->m_subject = new QLineEdit(this); 0271 d->m_subject->setClearButtonEnabled(true); 0272 d->m_subject->setFocus(); 0273 tmpLabel->setBuddy(d->m_subject); 0274 hlay->addWidget(d->m_subject); 0275 0276 QString text = i18n( 0277 "Enter the text (in English if possible) that you wish to submit for the " 0278 "bug report.\n" 0279 "If you press \"Send\", a mail message will be sent to the maintainer of " 0280 "this program.\n"); 0281 QLabel *label = new QLabel(this); 0282 0283 label->setText(text); 0284 lay->addWidget(label); 0285 0286 // The multiline-edit 0287 d->m_lineedit = new QTextEdit(this); 0288 d->m_lineedit->setMinimumHeight(180); // make it big 0289 d->m_lineedit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); 0290 d->m_lineedit->setLineWrapMode(QTextEdit::WidgetWidth); 0291 lay->addWidget(d->m_lineedit, 10 /*stretch*/); 0292 0293 d->slotSetFrom(); 0294 } else { 0295 // Point to the web form 0296 0297 QString text; 0298 if (d->bugDestination == KBugReportPrivate::BugsKdeOrg) { 0299 text = i18n( 0300 "<qt>To submit a bug report, click on the button below. This will open a web browser " 0301 "window on <a href=\"https://bugs.kde.org\">https://bugs.kde.org</a> where you will find " 0302 "a form to fill in. The information displayed above will be transferred to that server.</qt>"); 0303 d->updateUrl(); 0304 } else { 0305 text = i18n( 0306 "<qt>To submit a bug report, click on the button below. This will open a web browser " 0307 "window on <a href=\"%1\">%2</a>.</qt>", 0308 bugAddress, 0309 bugAddress); 0310 d->url = QUrl(bugAddress); 0311 } 0312 0313 lay->addSpacing(10); 0314 QLabel *label = new QLabel(text, this); 0315 label->setOpenExternalLinks(true); 0316 label->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard); 0317 label->setWordWrap(true); 0318 lay->addWidget(label); 0319 lay->addSpacing(10); 0320 0321 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); 0322 if (d->bugDestination == KBugReportPrivate::BugsKdeOrg) { 0323 okButton->setText(i18nc("@action:button", "&Launch Bug Report Wizard")); 0324 } else { 0325 okButton->setText(i18nc("@action:button", "&Submit Bug Report")); 0326 } 0327 okButton->setIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"))); 0328 } 0329 0330 lay->addWidget(buttonBox); 0331 setMinimumHeight(sizeHint().height() + 20); // WORKAROUND: prevent "cropped" qcombobox 0332 } 0333 0334 KBugReport::~KBugReport() = default; 0335 0336 QString KBugReport::messageBody() const 0337 { 0338 if (d->bugDestination == KBugReportPrivate::CustomEmail) { 0339 return d->m_lineedit->toPlainText(); 0340 } else { 0341 return QString(); 0342 } 0343 } 0344 0345 void KBugReport::setMessageBody(const QString &messageBody) 0346 { 0347 if (d->bugDestination == KBugReportPrivate::CustomEmail) { 0348 d->m_lineedit->setPlainText(messageBody); 0349 } 0350 } 0351 0352 void KBugReportPrivate::updateUrl() 0353 { 0354 url = QUrl(QStringLiteral("https://bugs.kde.org/enter_bug.cgi")); 0355 QUrlQuery query; 0356 query.addQueryItem(QStringLiteral("format"), QStringLiteral("guided")); // use the guided form 0357 0358 // the string format is product/component, where component is optional 0359 QStringList list = appname.split(QLatin1Char('/')); 0360 query.addQueryItem(QStringLiteral("product"), list[0]); 0361 if (list.size() == 2) { 0362 query.addQueryItem(QStringLiteral("component"), list[1]); 0363 } 0364 0365 query.addQueryItem(QStringLiteral("version"), m_strVersion); 0366 url.setQuery(query); 0367 0368 // TODO: guess and fill OS(sys_os) and Platform(rep_platform) fields 0369 } 0370 0371 void KBugReportPrivate::slotConfigureEmail() 0372 { 0373 if (m_process) { 0374 return; 0375 } 0376 0377 const QString exec = QStandardPaths::findExecutable(QStringLiteral("kcmshell5")); 0378 if (exec.isEmpty()) { 0379 const QString msg = i18nc("The second arg is 'kde-cli-tools' which is the package that contains kcmshell5 (the first arg)", 0380 "Could not find <application>%1</application> executable (usually it's part of the \"%2\" package).", 0381 QStringLiteral("kcmshell5"), 0382 QStringLiteral("kde-cli-tools")); 0383 auto *dlg = new KMessageDialog(KMessageDialog::Error, msg, q); 0384 dlg->setAttribute(Qt::WA_DeleteOnClose); 0385 dlg->setModal(true); 0386 dlg->show(); 0387 return; 0388 } 0389 0390 m_process = new QProcess; 0391 QObject::connect(m_process, &QProcess::finished, q, [this]() { 0392 slotSetFrom(); 0393 }); 0394 m_process->start(exec, QStringList{QStringLiteral("kcm_users")}); 0395 if (!m_process->waitForStarted()) { 0396 // qCDebug(DEBUG_KXMLGUI) << "Couldn't start kcmshell5.."; 0397 delete m_process; 0398 m_process = nullptr; 0399 return; 0400 } 0401 m_configureEmail->setEnabled(false); 0402 } 0403 0404 void KBugReportPrivate::slotSetFrom() 0405 { 0406 delete m_process; 0407 m_process = nullptr; 0408 m_configureEmail->setEnabled(true); 0409 0410 KEMailSettings emailSettings; 0411 QString fromaddr = emailSettings.getSetting(KEMailSettings::EmailAddress); 0412 if (fromaddr.isEmpty()) { 0413 fromaddr = SystemInformation::userName(); 0414 } else { 0415 QString name = emailSettings.getSetting(KEMailSettings::RealName); 0416 if (!name.isEmpty()) { 0417 fromaddr = name + QLatin1String(" <") + fromaddr + QLatin1Char('>'); 0418 } 0419 } 0420 m_from->setText(fromaddr); 0421 } 0422 0423 void KBugReport::accept() 0424 { 0425 if (d->bugDestination != KBugReportPrivate::CustomEmail) { 0426 QDesktopServices::openUrl(d->url); 0427 return; 0428 } 0429 0430 if (d->m_lineedit->toPlainText().isEmpty() || d->m_subject->text().isEmpty()) { 0431 QString msg = i18n( 0432 "You must specify both a subject and a description " 0433 "before the report can be sent."); 0434 KMessageBox::error(this, msg); 0435 return; 0436 } 0437 0438 switch (d->currentSeverity()) { 0439 case 0: // critical 0440 if (KMessageBox::questionTwoActions(this, 0441 i18n("<p>You chose the severity <b>Critical</b>. " 0442 "Please note that this severity is intended only for bugs that:</p>" 0443 "<ul><li>break unrelated software on the system (or the whole system)</li>" 0444 "<li>cause serious data loss</li>" 0445 "<li>introduce a security hole on the system where the affected package is installed</li></ul>\n" 0446 "<p>Does the bug you are reporting cause any of the above damage? " 0447 "If it does not, please select a lower severity. Thank you.</p>"), 0448 QString(), 0449 KStandardGuiItem::cont(), 0450 KStandardGuiItem::cancel()) 0451 == KMessageBox::SecondaryAction) { 0452 return; 0453 } 0454 break; 0455 case 1: // grave 0456 if (KMessageBox::questionTwoActions( 0457 this, 0458 i18n("<p>You chose the severity <b>Grave</b>. " 0459 "Please note that this severity is intended only for bugs that:</p>" 0460 "<ul><li>make the package in question unusable or mostly so</li>" 0461 "<li>cause data loss</li>" 0462 "<li>introduce a security hole allowing access to the accounts of users who use the affected package</li></ul>\n" 0463 "<p>Does the bug you are reporting cause any of the above damage? " 0464 "If it does not, please select a lower severity. Thank you.</p>"), 0465 QString(), 0466 KStandardGuiItem::cont(), 0467 KStandardGuiItem::cancel()) 0468 == KMessageBox::SecondaryAction) { 0469 return; 0470 } 0471 break; 0472 default: 0473 break; 0474 } 0475 if (!sendBugReport()) { 0476 QString msg = i18n( 0477 "Unable to send the bug report.\n" 0478 "Please submit a bug report manually....\n" 0479 "See https://bugs.kde.org/ for instructions."); 0480 KMessageBox::error(this, msg + QLatin1String("\n\n") + d->lastError); 0481 return; 0482 } 0483 0484 KMessageBox::information(this, i18n("Bug report sent, thank you for your input.")); 0485 QDialog::accept(); 0486 } 0487 0488 void KBugReport::closeEvent(QCloseEvent *e) 0489 { 0490 if (d->bugDestination == KBugReportPrivate::CustomEmail && ((d->m_lineedit->toPlainText().length() > 0) || d->m_subject->isModified())) { 0491 int rc = KMessageBox::warningTwoActions(this, 0492 i18n("Close and discard\nedited message?"), 0493 i18nc("@title:window", "Close Message"), 0494 KStandardGuiItem::discard(), 0495 KStandardGuiItem::cont()); 0496 if (rc == KMessageBox::SecondaryAction) { 0497 e->ignore(); 0498 return; 0499 } 0500 } 0501 QDialog::closeEvent(e); 0502 } 0503 0504 QString KBugReport::text() const 0505 { 0506 // qCDebug(DEBUG_KXMLGUI) << d->severityButtons[d->currentSeverity()]->objectName(); 0507 // Prepend the pseudo-headers to the contents of the mail 0508 QString severity = d->severityButtons[d->currentSeverity()]->objectName(); 0509 QString appname = d->appname; 0510 QString os = QStringLiteral("OS: %1 (%2)\n").arg(QStringLiteral(XMLGUI_COMPILING_OS), QStringLiteral(XMLGUI_DISTRIBUTION_TEXT)); 0511 QString bodyText; 0512 /* for(int i = 0; i < m_lineedit->numLines(); i++) 0513 { 0514 QString line = m_lineedit->textLine(i); 0515 if (!line.endsWith("\n")) 0516 line += '\n'; 0517 bodyText += line; 0518 } 0519 */ 0520 bodyText = d->m_lineedit->toPlainText(); 0521 if (bodyText.length() > 0) { 0522 if (bodyText[bodyText.length() - 1] != QLatin1Char('\n')) { 0523 bodyText += QLatin1Char('\n'); 0524 } 0525 } 0526 if (severity == QLatin1String("i18n") && QLocale().language() != QLocale::system().language()) { 0527 // Case 1 : i18n bug 0528 QString package = QLatin1String("i18n_") + QLocale::languageToString(QLocale().language()); 0529 package.replace(QLatin1Char('_'), QLatin1Char('-')); 0530 /* clang-format off */ 0531 return QLatin1String("Package: ") + package 0532 + QLatin1String("\nApplication: ") + appname 0533 + QLatin1String("\nVersion: ") + d->m_strVersion // not really i18n's version, so better here IMHO 0534 + QLatin1Char('\n') + os 0535 + QLatin1Char('\n') + bodyText; 0536 /* clang-format on */ 0537 } else { 0538 appname.replace(QLatin1Char('_'), QLatin1Char('-')); 0539 // Case 2 : normal bug 0540 /* clang-format off */ 0541 return QLatin1String("Package: ") + appname 0542 + QLatin1String("\nVersion: ") + d->m_strVersion 0543 + QLatin1String("\nSeverity: ") + severity 0544 + QLatin1Char('\n') + os 0545 + QLatin1Char('\n') + bodyText; 0546 /* clang-format on */ 0547 } 0548 } 0549 0550 bool KBugReport::sendBugReport() 0551 { 0552 QString recipient = d->m_aboutData.bugAddress(); 0553 if (recipient.isEmpty()) { 0554 recipient = QStringLiteral("submit@bugs.kde.org"); 0555 } 0556 0557 QString command = QStandardPaths::findExecutable(QStringLiteral("ksendbugmail")); 0558 if (command.isEmpty()) { 0559 command = QFile::decodeName(CMAKE_INSTALL_PREFIX "/" KDE_INSTALL_LIBEXECDIR_KF "/ksendbugmail"); 0560 } 0561 0562 QProcess proc; 0563 QStringList args; 0564 args << QStringLiteral("--subject") << d->m_subject->text() << QStringLiteral("--recipient") << recipient; 0565 proc.start(command, args); 0566 // qCDebug(DEBUG_KXMLGUI) << command << args; 0567 if (!proc.waitForStarted()) { 0568 qCCritical(DEBUG_KXMLGUI) << "Unable to open a pipe to " << command; 0569 return false; 0570 } 0571 proc.write(text().toUtf8()); 0572 proc.closeWriteChannel(); 0573 0574 proc.waitForFinished(); 0575 // qCDebug(DEBUG_KXMLGUI) << "kbugreport: sendbugmail exit, status " << proc.exitStatus() << " code " << proc.exitCode(); 0576 0577 QByteArray line; 0578 if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() != 0) { 0579 // XXX not stderr? 0580 while (!proc.atEnd()) { 0581 line = proc.readLine(); 0582 } 0583 d->lastError = QString::fromUtf8(line); 0584 return false; 0585 } 0586 return true; 0587 } 0588 0589 #include "moc_kbugreport.cpp"