diff --git a/src/bugzillaintegration/reportassistantdialog.cpp b/src/bugzillaintegration/reportassistantdialog.cpp index 48cd16c9..15881216 100644 --- a/src/bugzillaintegration/reportassistantdialog.cpp +++ b/src/bugzillaintegration/reportassistantdialog.cpp @@ -1,382 +1,398 @@ /******************************************************************* * reportassistantdialog.cpp * Copyright 2009,2010 Dario Andres Rodriguez +* Copyright 2019 Harald Sitter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ******************************************************************/ #include "reportassistantdialog.h" #include #include #include #include #include "drkonqi.h" #include "parser/backtraceparser.h" #include "debuggermanager.h" #include "backtracegenerator.h" #include "crashedapplication.h" #include "aboutbugreportingdialog.h" #include "reportassistantpages_base.h" #include "reportassistantpages_bugzilla.h" #include "reportassistantpages_bugzilla_duplicates.h" #include "reportinterface.h" static const char KDE_BUGZILLA_DESCRIPTION[] = I18N_NOOP("the KDE Bug Tracking System"); ReportAssistantDialog::ReportAssistantDialog(QWidget * parent) : KAssistantDialog(parent), m_aboutBugReportingDialog(nullptr), m_reportInterface(new ReportInterface(this)), m_canClose(false) { setAttribute(Qt::WA_DeleteOnClose, true); //Set window properties setWindowTitle(i18nc("@title:window","Crash Reporting Assistant")); setWindowIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"))); connect(this, &ReportAssistantDialog::currentPageChanged, this, &ReportAssistantDialog::currentPageChanged_slot); connect(button(QDialogButtonBox::Help), &QPushButton::clicked, this, &ReportAssistantDialog::showHelp); //Create the assistant pages //-Introduction Page KConfigGroup group(KSharedConfig::openConfig(), "ReportAssistant"); const bool skipIntroduction = group.readEntry("SkipIntroduction", false); if (!skipIntroduction) { IntroductionPage * m_introduction = new IntroductionPage(this); KPageWidgetItem * m_introductionPage = new KPageWidgetItem(m_introduction, QLatin1String(PAGE_INTRODUCTION_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_INTRODUCTION_ID),m_introductionPage); m_introductionPage->setHeader(i18nc("@title","Welcome to the Reporting Assistant")); m_introductionPage->setIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"))); addPage(m_introductionPage); } //-Bug Awareness Page BugAwarenessPage * m_awareness = new BugAwarenessPage(this); connectSignals(m_awareness); KPageWidgetItem * m_awarenessPage = new KPageWidgetItem(m_awareness, QLatin1String(PAGE_AWARENESS_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_AWARENESS_ID),m_awarenessPage); m_awarenessPage->setHeader(i18nc("@title","What do you know about the crash?")); m_awarenessPage->setIcon(QIcon::fromTheme(QStringLiteral("checkbox"))); //-Crash Information Page CrashInformationPage * m_backtrace = new CrashInformationPage(this); connectSignals(m_backtrace); KPageWidgetItem * m_backtracePage = new KPageWidgetItem(m_backtrace, QLatin1String(PAGE_CRASHINFORMATION_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_CRASHINFORMATION_ID),m_backtracePage); m_backtracePage->setHeader(i18nc("@title","Fetching the Backtrace (Automatic Crash Information)")); m_backtracePage->setIcon(QIcon::fromTheme(QStringLiteral("run-build"))); //-Results Page ConclusionPage * m_conclusions = new ConclusionPage(this); connectSignals(m_conclusions); KPageWidgetItem * m_conclusionsPage = new KPageWidgetItem(m_conclusions, QLatin1String(PAGE_CONCLUSIONS_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_CONCLUSIONS_ID),m_conclusionsPage); m_conclusionsPage->setHeader(i18nc("@title","Results of the Analyzed Crash Details")); m_conclusionsPage->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information"))); connect(m_conclusions, &ConclusionPage::finished, this, &ReportAssistantDialog::assistantFinished); //-Bugzilla Login BugzillaLoginPage * m_bugzillaLogin = new BugzillaLoginPage(this); connectSignals(m_bugzillaLogin); KPageWidgetItem * m_bugzillaLoginPage = new KPageWidgetItem(m_bugzillaLogin, QLatin1String(PAGE_BZLOGIN_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_BZLOGIN_ID),m_bugzillaLoginPage); m_bugzillaLoginPage->setHeader(i18nc("@title", "Login into %1", i18n(KDE_BUGZILLA_DESCRIPTION))); m_bugzillaLoginPage->setIcon(QIcon::fromTheme(QStringLiteral("user-identity"))); connect(m_bugzillaLogin, &BugzillaLoginPage::loggedTurnToNextPage, this, &ReportAssistantDialog::loginFinished); //-Bugzilla duplicates BugzillaDuplicatesPage * m_bugzillaDuplicates = new BugzillaDuplicatesPage(this); connectSignals(m_bugzillaDuplicates); KPageWidgetItem * m_bugzillaDuplicatesPage = new KPageWidgetItem(m_bugzillaDuplicates, QLatin1String(PAGE_BZDUPLICATES_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_BZDUPLICATES_ID),m_bugzillaDuplicatesPage); m_bugzillaDuplicatesPage->setHeader(i18nc("@title","Look for Possible Duplicate Reports")); m_bugzillaDuplicatesPage->setIcon(QIcon::fromTheme(QStringLiteral("repository"))); //-Bugzilla information BugzillaInformationPage * m_bugzillaInformation = new BugzillaInformationPage(this); connectSignals(m_bugzillaInformation); KPageWidgetItem * m_bugzillaInformationPage = new KPageWidgetItem(m_bugzillaInformation, QLatin1String(PAGE_BZDETAILS_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_BZDETAILS_ID),m_bugzillaInformationPage); m_bugzillaInformationPage->setHeader(i18nc("@title","Enter the Details about the Crash")); m_bugzillaInformationPage->setIcon(QIcon::fromTheme(QStringLiteral("document-edit"))); //-Bugzilla Report Preview BugzillaPreviewPage * m_bugzillaPreview = new BugzillaPreviewPage(this); KPageWidgetItem * m_bugzillaPreviewPage = new KPageWidgetItem(m_bugzillaPreview, QLatin1String(PAGE_BZPREVIEW_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_BZPREVIEW_ID),m_bugzillaPreviewPage); m_bugzillaPreviewPage->setHeader(i18nc("@title","Preview the Report")); m_bugzillaPreviewPage->setIcon(QIcon::fromTheme(QStringLiteral("document-preview"))); //-Bugzilla commit BugzillaSendPage * m_bugzillaSend = new BugzillaSendPage(this); KPageWidgetItem * m_bugzillaSendPage = new KPageWidgetItem(m_bugzillaSend, QLatin1String(PAGE_BZSEND_ID)); m_pageWidgetMap.insert(QLatin1String(PAGE_BZSEND_ID),m_bugzillaSendPage); m_bugzillaSendPage->setHeader(i18nc("@title","Sending the Crash Report")); m_bugzillaSendPage->setIcon(QIcon::fromTheme(QStringLiteral("applications-internet"))); connect(m_bugzillaSend, &BugzillaSendPage::finished, this, &ReportAssistantDialog::assistantFinished); //TODO Remember to keep the pages ordered addPage(m_awarenessPage); addPage(m_backtracePage); addPage(m_conclusionsPage); addPage(m_bugzillaLoginPage); addPage(m_bugzillaDuplicatesPage); addPage(m_bugzillaInformationPage); addPage(m_bugzillaPreviewPage); addPage(m_bugzillaSendPage); // Force a 16:9 ratio for nice appearance by default. QSize aspect(16, 9); aspect.scale(sizeHint(), Qt::KeepAspectRatioByExpanding); resize(aspect); } ReportAssistantDialog::~ReportAssistantDialog() { } +void ReportAssistantDialog::setAboutToSend(bool aboutTo) +{ + if (aboutTo) { + m_nextButtonIconCache = nextButton()->icon(); + m_nextButtonTextCache = nextButton()->text(); + nextButton()->setIcon(QIcon::fromTheme(QStringLiteral("document-send"))); + nextButton()->setText(i18nc("@action button to submit report", "Submit")); + return; + } + nextButton()->setIcon(m_nextButtonIconCache); + nextButton()->setText(m_nextButtonTextCache); + m_nextButtonIconCache = QIcon(); + m_nextButtonTextCache = QString(); +} + void ReportAssistantDialog::connectSignals(ReportAssistantPage * page) { //React to the changes in the assistant pages connect(page, &ReportAssistantPage::completeChanged, this, &ReportAssistantDialog::completeChanged); } void ReportAssistantDialog::currentPageChanged_slot(KPageWidgetItem * current , KPageWidgetItem * before) { //Page changed buttonBox()->button(QDialogButtonBox::Cancel)->setEnabled(true); m_canClose = false; //Save data of the previous page if (before) { ReportAssistantPage* beforePage = dynamic_cast(before->widget()); beforePage->aboutToHide(); } //Load data of the current(new) page if (current) { ReportAssistantPage* currentPage = dynamic_cast(current->widget()); nextButton()->setEnabled(currentPage->isComplete()); currentPage->aboutToShow(); } //If the current page is the last one, disable all the buttons until the bug is sent if (current->name() == QLatin1String(PAGE_BZSEND_ID)) { nextButton()->setEnabled(false); backButton()->setEnabled(false); finishButton()->setEnabled(false); } } void ReportAssistantDialog::completeChanged(ReportAssistantPage* page, bool isComplete) { if (page == dynamic_cast(currentPage()->widget())) { nextButton()->setEnabled(isComplete); } } void ReportAssistantDialog::assistantFinished(bool showBack) { //The assistant finished: allow the user to close the dialog normally nextButton()->setEnabled(false); backButton()->setEnabled(showBack); finishButton()->setEnabled(true); buttonBox()->button(QDialogButtonBox::Cancel)->setEnabled(false); m_canClose = true; } void ReportAssistantDialog::loginFinished() { //Bugzilla login finished, go to the next page if (currentPage()->name() == QLatin1String(PAGE_BZLOGIN_ID)) { next(); } } void ReportAssistantDialog::showHelp() { //Show the bug reporting guide dialog if (!m_aboutBugReportingDialog) { m_aboutBugReportingDialog = new AboutBugReportingDialog(); } m_aboutBugReportingDialog->show(); m_aboutBugReportingDialog->raise(); m_aboutBugReportingDialog->activateWindow(); m_aboutBugReportingDialog->showSection(QLatin1String(PAGE_HELP_BEGIN_ID)); m_aboutBugReportingDialog->showSection(currentPage()->name()); } //Override KAssistantDialog "next" page implementation void ReportAssistantDialog::next() { //Allow the widget to Ask a question to the user before changing the page ReportAssistantPage * page = dynamic_cast(currentPage()->widget()); if (page) { if (!page->showNextPage()) { return; } } const QString name = currentPage()->name(); //If the information the user can provide is not useful, skip the backtrace page if (name == QLatin1String(PAGE_AWARENESS_ID)) { //Force save settings in the current page page->aboutToHide(); if (!(m_reportInterface->isBugAwarenessPageDataUseful())) { setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_CONCLUSIONS_ID))); return; } } else if (name == QLatin1String(PAGE_CRASHINFORMATION_ID)){ //Force save settings in current page page->aboutToHide(); //If the crash is worth reporting and it is BKO, skip the Conclusions page if (m_reportInterface->isWorthReporting() && DrKonqi::crashedApplication()->bugReportAddress().isKdeBugzilla()) { setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_BZLOGIN_ID))); return; } } else if (name == QLatin1String(PAGE_BZDUPLICATES_ID)) { //a duplicate has been found, yet the report is not being attached if (m_reportInterface->duplicateId() && !m_reportInterface->attachToBugNumber()) { setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_CONCLUSIONS_ID))); return; } } KAssistantDialog::next(); } //Override KAssistantDialog "back"(previous) page implementation //It has to mirror the custom next() implementation void ReportAssistantDialog::back() { if (currentPage()->name() == QLatin1String(PAGE_CONCLUSIONS_ID)) { if (m_reportInterface->duplicateId() && !m_reportInterface->attachToBugNumber()) { setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_BZDUPLICATES_ID))); return; } if (!(m_reportInterface->isBugAwarenessPageDataUseful())) { setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_AWARENESS_ID))); return; } } if (currentPage()->name() == QLatin1String(PAGE_BZLOGIN_ID)) { if (m_reportInterface->isWorthReporting() && DrKonqi::crashedApplication()->bugReportAddress().isKdeBugzilla()) { setCurrentPage(m_pageWidgetMap.value(QLatin1String(PAGE_CRASHINFORMATION_ID))); return; } } KAssistantDialog::back(); } void ReportAssistantDialog::reject() { close(); } void ReportAssistantDialog::closeEvent(QCloseEvent * event) { //Handle the close event if (!m_canClose) { //If the assistant didn't finished yet, offer the user the possibilities to //Close, Cancel, or Save the bug report and Close" KGuiItem closeItem = KStandardGuiItem::close(); closeItem.setText(i18nc("@action:button", "Close the assistant")); KGuiItem keepOpenItem = KStandardGuiItem::cancel(); keepOpenItem.setText(i18nc("@action:button", "Cancel")); BacktraceParser::Usefulness use = DrKonqi::debuggerManager()->backtraceGenerator()->parser()->backtraceUsefulness(); if (use == BacktraceParser::ReallyUseful || use == BacktraceParser::MayBeUseful) { //Backtrace is still useful, let the user save it. KGuiItem saveBacktraceItem = KStandardGuiItem::save(); saveBacktraceItem.setText(i18nc("@action:button", "Save information and close")); int ret = KMessageBox::questionYesNoCancel(this, xi18nc("@info","Do you really want to close the bug reporting assistant? " "The crash information is still valid, so " "you can save the report before closing if you want."), i18nc("@title:window","Close the Assistant"), closeItem, saveBacktraceItem, keepOpenItem, QString(), KMessageBox::Dangerous); if(ret == KMessageBox::Yes) { event->accept(); } else if (ret == KMessageBox::No) { //Save backtrace and accept event (dialog will be closed) DrKonqi::saveReport(reportInterface()->generateReportFullText(false)); event->accept(); } else { event->ignore(); } } else { if (KMessageBox::questionYesNo(this, i18nc("@info","Do you really want to close the bug " "reporting assistant?"), i18nc("@title:window","Close the Assistant"), closeItem, keepOpenItem, QString(), KMessageBox::Dangerous) == KMessageBox::Yes) { event->accept(); } else { event->ignore(); } } } else { event->accept(); } } diff --git a/src/bugzillaintegration/reportassistantdialog.h b/src/bugzillaintegration/reportassistantdialog.h index 89013bdc..237a8058 100644 --- a/src/bugzillaintegration/reportassistantdialog.h +++ b/src/bugzillaintegration/reportassistantdialog.h @@ -1,73 +1,80 @@ /******************************************************************* * reportassistantdialog.h * Copyright 2009 Dario Andres Rodriguez +* Copyright 2019 Harald Sitter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ******************************************************************/ #ifndef REPORTASSISTANTDIALOG__H #define REPORTASSISTANTDIALOG__H +#include #include #include class ReportAssistantPage; class AboutBugReportingDialog; class ReportInterface; class QCloseEvent; class ReportAssistantDialog: public KAssistantDialog { Q_OBJECT public: explicit ReportAssistantDialog(QWidget * parent = nullptr); ~ReportAssistantDialog() override; ReportInterface *reportInterface() const { return m_reportInterface; } + void setAboutToSend(bool aboutTo); + private Q_SLOTS: void currentPageChanged_slot(KPageWidgetItem *, KPageWidgetItem *); void completeChanged(ReportAssistantPage*, bool); void loginFinished(); void assistantFinished(bool); void showHelp(); void next() override; void back() override; //Override default reject method void reject() override; private: void connectSignals(ReportAssistantPage *); void closeEvent(QCloseEvent*) override; QHash m_pageWidgetMap; QPointer m_aboutBugReportingDialog; ReportInterface * m_reportInterface = nullptr; bool m_canClose; + + QIcon m_nextButtonIconCache; + QString m_nextButtonTextCache; }; #endif diff --git a/src/bugzillaintegration/reportassistantpages_bugzilla.cpp b/src/bugzillaintegration/reportassistantpages_bugzilla.cpp index 9de4c43f..065233d0 100644 --- a/src/bugzillaintegration/reportassistantpages_bugzilla.cpp +++ b/src/bugzillaintegration/reportassistantpages_bugzilla.cpp @@ -1,851 +1,858 @@ /******************************************************************* * reportassistantpages_bugzilla.cpp * Copyright 2009, 2010, 2011 Dario Andres Rodriguez +* Copyright 2019 Harald Sitter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ******************************************************************/ #include "reportassistantpages_bugzilla.h" #include #include #include #include #include #include #include #include #include #include #include #include "drkonqi_debug.h" #include #include #include #include #include /* Unhandled error dialog includes */ #include #include #include #include #include "reportinterface.h" #include "systeminformation.h" #include "crashedapplication.h" #include "bugzillalib.h" #include "statuswidget.h" #include "drkonqi.h" #include "drkonqi_globals.h" #include "applicationdetailsexamples.h" static const char kWalletEntryName[] = "drkonqi_bugzilla"; static const char kWalletEntryUsername[] = "username"; static const char kWalletEntryPassword[] = "password"; static QString konquerorKWalletEntryName = KDE_BUGZILLA_URL + QStringLiteral("index.cgi#login"); static const char konquerorKWalletEntryUsername[] = "Bugzilla_login"; static const char konquerorKWalletEntryPassword[] = "Bugzilla_password"; //BEGIN BugzillaLoginPage BugzillaLoginPage::BugzillaLoginPage(ReportAssistantDialog * parent) : ReportAssistantPage(parent), m_wallet(nullptr), m_walletWasOpenedBefore(false), m_bugzillaVersionFound(false) { connect(bugzillaManager(), &BugzillaManager::bugzillaVersionFound, this, &BugzillaLoginPage::bugzillaVersionFound); connect(bugzillaManager(), &BugzillaManager::loginFinished, this, &BugzillaLoginPage::loginFinished); connect(bugzillaManager(), &BugzillaManager::loginError, this, &BugzillaLoginPage::loginError); ui.setupUi(this); ui.m_statusWidget->setIdle(i18nc("@info:status '1' is replaced with the short URL of the bugzilla ", "You need to login with your %1 account in order to proceed.", QLatin1String(KDE_BUGZILLA_SHORT_URL))); KGuiItem::assign(ui.m_loginButton, KGuiItem2(i18nc("@action:button", "Login"), QIcon::fromTheme(QStringLiteral("network-connect")), i18nc("@info:tooltip", "Use this button to login " "to the KDE bug tracking system using the provided " "e-mail address and password."))); ui.m_loginButton->setEnabled(false); connect(ui.m_loginButton, &QPushButton::clicked, this, &BugzillaLoginPage::loginClicked); connect(ui.m_userEdit, &KLineEdit::returnPressed, this, &BugzillaLoginPage::loginClicked); connect(ui.m_passwordEdit->lineEdit(), &QLineEdit::returnPressed, this, &BugzillaLoginPage::loginClicked); connect(ui.m_userEdit, &KLineEdit::textChanged, this, &BugzillaLoginPage::updateLoginButtonStatus); connect(ui.m_passwordEdit, &KPasswordLineEdit::passwordChanged, this, &BugzillaLoginPage::updateLoginButtonStatus); ui.m_noticeLabel->setText( xi18nc("@info/rich","You need a user account on the " "KDE bug tracking system in order to " "file a bug report, because we may need to contact you later " "for requesting further information. If you do not have " "one, you can freely create one here. " "Please do not use disposable email accounts.", DrKonqi::crashedApplication()->bugReportAddress(), KDE_BUGZILLA_CREATE_ACCOUNT_URL)); } bool BugzillaLoginPage::isComplete() { return bugzillaManager()->getLogged(); } void BugzillaLoginPage::bugzillaVersionFound() { // Login depends on first knowing the Bugzilla software version number. m_bugzillaVersionFound = true; updateLoginButtonStatus(); } void BugzillaLoginPage::updateLoginButtonStatus() { ui.m_loginButton->setEnabled( !ui.m_userEdit->text().isEmpty() && !ui.m_passwordEdit->password().isEmpty() && m_bugzillaVersionFound ); } void BugzillaLoginPage::loginError(const QString & err, const QString & extendedMessage) { loginFinished(false); ui.m_statusWidget->setIdle(xi18nc("@info:status","Error when trying to login: " "%1", err)); if (!extendedMessage.isEmpty()) { new UnhandledErrorDialog(this, err, extendedMessage); } } void BugzillaLoginPage::aboutToShow() { if (bugzillaManager()->getLogged()) { ui.m_loginButton->setEnabled(false); ui.m_userEdit->setEnabled(false); ui.m_userEdit->clear(); ui.m_passwordEdit->setEnabled(false); ui.m_passwordEdit->clear(); ui.m_loginButton->setVisible(false); ui.m_userEdit->setVisible(false); ui.m_passwordEdit->setVisible(false); ui.m_userLabel->setVisible(false); ui.m_passwordLabel->setVisible(false); ui.m_savePasswordCheckBox->setVisible(false); ui.m_noticeLabel->setVisible(false); ui.m_statusWidget->setIdle(i18nc("@info:status the user is logged at the bugtracker site " "as USERNAME", "Logged in at the KDE bug tracking system (%1) as: %2.", QLatin1String(KDE_BUGZILLA_SHORT_URL), bugzillaManager()->getUsername())); } else { //Try to show wallet dialog once this dialog is shown QTimer::singleShot(100, this, &BugzillaLoginPage::walletLogin); } } bool BugzillaLoginPage::kWalletEntryExists(const QString& entryName) { return !KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::FormDataFolder(), entryName); } void BugzillaLoginPage::openWallet() { //Store if the wallet was previously opened so we can know if we should close it later m_walletWasOpenedBefore = KWallet::Wallet::isOpen(KWallet::Wallet::NetworkWallet()); //Request open the wallet m_wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), static_cast(this->parent())->winId()); } void BugzillaLoginPage::walletLogin() { if (!m_wallet) { if (kWalletEntryExists(QLatin1String(kWalletEntryName))) { //Key exists! openWallet(); ui.m_savePasswordCheckBox->setCheckState(Qt::Checked); //Was the wallet opened? if (m_wallet) { m_wallet->setFolder(KWallet::Wallet::FormDataFolder()); //Use wallet data to try login QMap values; m_wallet->readMap(QLatin1String(kWalletEntryName), values); QString username = values.value(QLatin1String(kWalletEntryUsername)); QString password = values.value(QLatin1String(kWalletEntryPassword)); if (!username.isEmpty() && !password.isEmpty()) { ui.m_userEdit->setText(username); ui.m_passwordEdit->setPassword(password); } } } else if (kWalletEntryExists(konquerorKWalletEntryName)) { //If the DrKonqi entry is empty, but a Konqueror entry exists, use and copy it. openWallet(); if (m_wallet) { m_wallet->setFolder(KWallet::Wallet::FormDataFolder()); //Fetch Konqueror data QMap values; m_wallet->readMap(konquerorKWalletEntryName, values); QString username = values.value(QLatin1String(konquerorKWalletEntryUsername)); QString password = values.value(QLatin1String(konquerorKWalletEntryPassword)); if (!username.isEmpty() && !password.isEmpty()) { //Copy to DrKonqi own entries values.clear(); values.insert(QLatin1String(kWalletEntryUsername), username); values.insert(QLatin1String(kWalletEntryPassword), password); m_wallet->writeMap(QLatin1String(kWalletEntryName), values); ui.m_savePasswordCheckBox->setCheckState(Qt::Checked); ui.m_userEdit->setText(username); ui.m_passwordEdit->setPassword(password); } } } if (canLogin()) { loginClicked(); } } } void BugzillaLoginPage::loginClicked() { if (!canLogin()) { loginFinished(false); return; } updateWidget(false); if (ui.m_savePasswordCheckBox->checkState()==Qt::Checked) { //Wants to save data if (!m_wallet) { openWallet(); } //Got wallet open ? if (m_wallet) { m_wallet->setFolder(KWallet::Wallet::FormDataFolder()); QMap values; values.insert(QLatin1String(kWalletEntryUsername), ui.m_userEdit->text()); values.insert(QLatin1String(kWalletEntryPassword), ui.m_passwordEdit->password()); m_wallet->writeMap(QLatin1String(kWalletEntryName), values); } } else { //User doesn't want to save or wants to remove. if (kWalletEntryExists(QLatin1String(kWalletEntryName))) { if (!m_wallet) { openWallet(); } //Got wallet open ? if (m_wallet) { m_wallet->setFolder(KWallet::Wallet::FormDataFolder()); m_wallet->removeEntry(QLatin1String(kWalletEntryName)); } } } login(); } bool BugzillaLoginPage::canLogin() const { return (!(ui.m_userEdit->text().isEmpty() || ui.m_passwordEdit->password().isEmpty())); } void BugzillaLoginPage::login() { Q_ASSERT(canLogin()); ui.m_statusWidget->setBusy(i18nc("@info:status '1' is a url, '2' the e-mail address", "Performing login at %1 as %2...", QLatin1String(KDE_BUGZILLA_SHORT_URL), ui.m_userEdit->text())); bugzillaManager()->tryLogin(ui.m_userEdit->text(), ui.m_passwordEdit->password()); } void BugzillaLoginPage::updateWidget(bool enabled) { ui.m_loginButton->setEnabled(enabled); ui.m_userLabel->setEnabled(enabled); ui.m_passwordLabel->setEnabled(enabled); ui.m_userEdit->setEnabled(enabled); ui.m_passwordEdit->setEnabled(enabled); ui.m_savePasswordCheckBox->setEnabled(enabled); } void BugzillaLoginPage::loginFinished(bool logged) { if (logged) { emitCompleteChanged(); aboutToShow(); if (m_wallet) { if (m_wallet->isOpen() && !m_walletWasOpenedBefore) { m_wallet->lockWallet(); } } emit loggedTurnToNextPage(); } else { ui.m_statusWidget->setIdle(i18nc("@info:status", "Error: Invalid e-mail address or password")); updateWidget(true); ui.m_userEdit->setFocus(Qt::OtherFocusReason); } } BugzillaLoginPage::~BugzillaLoginPage() { //Close wallet if we close the assistant in this step if (m_wallet) { if (m_wallet->isOpen() && !m_walletWasOpenedBefore) { m_wallet->lockWallet(); } delete m_wallet; } } //END BugzillaLoginPage //BEGIN BugzillaInformationPage BugzillaInformationPage::BugzillaInformationPage(ReportAssistantDialog * parent) : ReportAssistantPage(parent), m_textsOK(false), m_distributionComboSetup(false), m_distroComboVisible(false), m_requiredCharacters(1) { ui.setupUi(this); m_textCompleteBar = new KCapacityBar(KCapacityBar::DrawTextInline, this); ui.horizontalLayout_2->addWidget(m_textCompleteBar); connect(ui.m_titleEdit, &KLineEdit::textChanged, this, &BugzillaInformationPage::checkTexts); connect(ui.m_detailsEdit, &QTextEdit::textChanged, this, &BugzillaInformationPage::checkTexts); connect(ui.m_titleLabel, &QLabel::linkActivated, this, &BugzillaInformationPage::showTitleExamples); connect(ui.m_detailsLabel, &QLabel::linkActivated, this, &BugzillaInformationPage::showDescriptionHelpExamples); ui.m_compiledSourcesCheckBox->setChecked( DrKonqi::systemInformation()->compiledSources()); } void BugzillaInformationPage::aboutToShow() { if (!m_distributionComboSetup) { //Autodetecting distro failed ? if (DrKonqi::systemInformation()->bugzillaPlatform() == QLatin1String("unspecified")) { m_distroComboVisible = true; ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Unspecified"),QStringLiteral("unspecified")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Archlinux"), QStringLiteral("Archlinux Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Chakra"), QStringLiteral("Chakra")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Debian stable"), QStringLiteral("Debian stable")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Debian testing"), QStringLiteral("Debian testing")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Debian unstable"), QStringLiteral("Debian unstable")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Exherbo"), QStringLiteral("Exherbo Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Fedora"), QStringLiteral("Fedora RPMs")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Gentoo"), QStringLiteral("Gentoo Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Mageia"), QStringLiteral("Mageia RPMs")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Mandriva"), QStringLiteral("Mandriva RPMs")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Neon"), QStringLiteral("Neon Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "OpenSUSE"), QStringLiteral("openSUSE RPMs")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Pardus"), QStringLiteral("Pardus Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "RedHat"), QStringLiteral("RedHat RPMs")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Slackware"), QStringLiteral("Slackware Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Ubuntu (and derivatives)"), QStringLiteral("Ubuntu Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "FreeBSD (Ports)"), QStringLiteral("FreeBSD Ports")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "NetBSD (pkgsrc)"), QStringLiteral("NetBSD pkgsrc")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "OpenBSD"), QStringLiteral("OpenBSD Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Mac OS X"), QStringLiteral("MacPorts Packages")); ui.m_distroChooserCombo->addItem(i18nc("@label:listbox KDE distribution method", "Solaris"), QStringLiteral("Solaris Packages")); //Restore previously selected bugzilla platform (distribution) KConfigGroup config(KSharedConfig::openConfig(), "BugzillaInformationPage"); QString entry = config.readEntry("BugzillaPlatform","unspecified"); int index = ui.m_distroChooserCombo->findData(entry); if ( index == -1 ) index = 0; ui.m_distroChooserCombo->setCurrentIndex(index); } else { ui.m_distroChooserCombo->setVisible(false); } m_distributionComboSetup = true; } //Calculate the minimum number of characters required for a description //If creating a new report: minimum 40, maximum 80 //If attaching to an existent report: minimum 30, maximum 50 int multiplier = (reportInterface()->attachToBugNumber() == 0) ? 10 : 5; m_requiredCharacters = 20 + (reportInterface()->selectedOptionsRating() * multiplier); //Fill the description textedit with some headings: QString descriptionTemplate; if (ui.m_detailsEdit->toPlainText().isEmpty()) { if (reportInterface()->userCanProvideActionsAppDesktop()) { descriptionTemplate += QLatin1String("- What I was doing when the application crashed:\n\n"); } if (reportInterface()->userCanProvideUnusualBehavior()) { descriptionTemplate += QLatin1String("- Unusual behavior I noticed:\n\n"); } if (reportInterface()->userCanProvideApplicationConfigDetails()) { descriptionTemplate += QLatin1String("- Custom settings of the application:\n\n"); } ui.m_detailsEdit->setText(descriptionTemplate); } checkTexts(); //May be the options (canDetail) changed and we need to recheck } int BugzillaInformationPage::currentDescriptionCharactersCount() { QString description = ui.m_detailsEdit->toPlainText(); //Do not count template messages, and other misc chars description.remove(QStringLiteral("What I was doing when the application crashed")); description.remove(QStringLiteral("Unusual behavior I noticed")); description.remove(QStringLiteral("Custom settings of the application")); description.remove(QLatin1Char('\n')); description.remove(QLatin1Char('-')); description.remove(QLatin1Char(':')); description.remove(QLatin1Char(' ')); return description.size(); } void BugzillaInformationPage::checkTexts() { //If attaching this report to an existing one then the title is not needed bool showTitle = (reportInterface()->attachToBugNumber() == 0); ui.m_titleEdit->setVisible(showTitle); ui.m_titleLabel->setVisible(showTitle); bool ok = !((ui.m_titleEdit->isVisible() && ui.m_titleEdit->text().isEmpty()) || ui.m_detailsEdit->toPlainText().isEmpty()); QString message; int percent = currentDescriptionCharactersCount() * 100 / m_requiredCharacters; if (percent >= 100) { percent = 100; message = i18nc("the minimum required length of a text was reached", "Minimum length reached"); } else { message = i18nc("the minimum required length of a text wasn't reached yet", "Provide more information"); } m_textCompleteBar->setValue(percent); m_textCompleteBar->setText(message); if (ok != m_textsOK) { m_textsOK = ok; emitCompleteChanged(); } } bool BugzillaInformationPage::showNextPage() { checkTexts(); if (m_textsOK) { bool detailsShort = currentDescriptionCharactersCount() < m_requiredCharacters; if (detailsShort) { //The user input is less than we want.... encourage to write more QString message = i18nc("@info","The description about the crash details does not provide " "enough information yet.

"); message += QLatin1Char(' ') + i18nc("@info","The amount of required information is proportional to " "the quality of the other information like the backtrace " "or the reproducibility rate." "

"); if (reportInterface()->userCanProvideActionsAppDesktop() || reportInterface()->userCanProvideUnusualBehavior() || reportInterface()->userCanProvideApplicationConfigDetails()) { message += QLatin1Char(' ') + i18nc("@info","Previously, you told DrKonqi that you could provide some " "contextual information. Try writing more details about your situation. " "(even little ones could help us.)

"); } message += QLatin1Char(' ') + i18nc("@info","If you cannot provide more information, your report " "will probably waste developers' time. Can you tell us more?"); KGuiItem yesItem = KStandardGuiItem::yes(); yesItem.setText(i18n("Yes, let me add more information")); KGuiItem noItem = KStandardGuiItem::no(); noItem.setText(i18n("No, I cannot add any other information")); if (KMessageBox::warningYesNo(this, message, i18nc("@title:window","We need more information"), yesItem, noItem) == KMessageBox::No) { //Request the assistant to close itself (it will prompt for confirmation anyways) assistant()->close(); return false; } } else { return true; } } return false; } bool BugzillaInformationPage::isComplete() { return m_textsOK; } void BugzillaInformationPage::aboutToHide() { //Save fields data reportInterface()->setTitle(ui.m_titleEdit->text()); reportInterface()->setDetailText(ui.m_detailsEdit->toPlainText()); if (m_distroComboVisible) { //Save bugzilla platform (distribution) QString bugzillaPlatform = ui.m_distroChooserCombo->itemData( ui.m_distroChooserCombo->currentIndex()).toString(); KConfigGroup config(KSharedConfig::openConfig(), "BugzillaInformationPage"); config.writeEntry("BugzillaPlatform", bugzillaPlatform); DrKonqi::systemInformation()->setBugzillaPlatform(bugzillaPlatform); } bool compiledFromSources = ui.m_compiledSourcesCheckBox->checkState() == Qt::Checked; DrKonqi::systemInformation()->setCompiledSources(compiledFromSources); } void BugzillaInformationPage::showTitleExamples() { QString titleExamples = xi18nc("@info:tooltip examples of good bug report titles", "Examples of good titles:\"Plasma crashed after adding the Notes " "widget and writing on it\"\"Konqueror crashed when accessing the Facebook " "application 'X'\"\"Kopete suddenly closed after resuming the computer and " "talking to a MSN buddy\"\"Kate closed while editing a log file and pressing the " "Delete key a couple of times\""); QToolTip::showText(QCursor::pos(), titleExamples); } void BugzillaInformationPage::showDescriptionHelpExamples() { QString descriptionHelp = i18nc("@info:tooltip help and examples of good bug descriptions", "Describe in as much detail as possible the crash circumstances:"); if (reportInterface()->userCanProvideActionsAppDesktop()) { descriptionHelp += QStringLiteral("
") + i18nc("@info:tooltip help and examples of good bug descriptions", "- Detail which actions were you taking inside and outside the " "application an instant before the crash."); } if (reportInterface()->userCanProvideUnusualBehavior()) { descriptionHelp += QStringLiteral("
") + i18nc("@info:tooltip help and examples of good bug descriptions", "- Note if you noticed any unusual behavior in the application " "or in the whole environment."); } if (reportInterface()->userCanProvideApplicationConfigDetails()) { descriptionHelp += QStringLiteral("
") + i18nc("@info:tooltip help and examples of good bug descriptions", "- Note any non-default configuration in the application."); if (reportInterface()->appDetailsExamples()->hasExamples()) { descriptionHelp += QLatin1Char(' ') + i18nc("@info:tooltip examples of configuration details. " "the examples are already translated", "Examples: %1", reportInterface()->appDetailsExamples()->examples()); } } QToolTip::showText(QCursor::pos(), descriptionHelp); } //END BugzillaInformationPage //BEGIN BugzillaPreviewPage BugzillaPreviewPage::BugzillaPreviewPage(ReportAssistantDialog * parent) : ReportAssistantPage(parent) { ui.setupUi(this); } void BugzillaPreviewPage::aboutToShow() { ui.m_previewEdit->setText(reportInterface()->generateReportFullText(true)); + assistant()->setAboutToSend(true); +} + +void BugzillaPreviewPage::aboutToHide() +{ + assistant()->setAboutToSend(false); } //END BugzillaPreviewPage //BEGIN BugzillaSendPage BugzillaSendPage::BugzillaSendPage(ReportAssistantDialog * parent) : ReportAssistantPage(parent), m_contentsDialog(nullptr) { connect(reportInterface(), &ReportInterface::reportSent, this, &BugzillaSendPage::sent); connect(reportInterface(), &ReportInterface::sendReportError, this, &BugzillaSendPage::sendError); ui.setupUi(this); KGuiItem::assign(ui.m_retryButton, KGuiItem2(i18nc("@action:button", "Retry..."), QIcon::fromTheme(QStringLiteral("view-refresh")), i18nc("@info:tooltip", "Use this button to retry " "sending the crash report if it failed before."))); KGuiItem::assign(ui.m_showReportContentsButton, KGuiItem2(i18nc("@action:button", "Sho&w Contents of the Report"), QIcon::fromTheme(QStringLiteral("document-preview")), i18nc("@info:tooltip", "Use this button to show the generated " "report information about this crash."))); connect(ui.m_showReportContentsButton, &QPushButton::clicked, this, &BugzillaSendPage::openReportContents); ui.m_retryButton->setVisible(false); connect(ui.m_retryButton, &QAbstractButton::clicked, this , &BugzillaSendPage::retryClicked); ui.m_launchPageOnFinish->setVisible(false); ui.m_restartAppOnFinish->setVisible(false); connect(assistant()->finishButton(), &QPushButton::clicked, this, &BugzillaSendPage::finishClicked); } void BugzillaSendPage::retryClicked() { ui.m_retryButton->setEnabled(false); aboutToShow(); } void BugzillaSendPage::aboutToShow() { ui.m_statusWidget->setBusy(i18nc("@info:status","Sending crash report... (please wait)")); // Trigger relogin. If the user took a long time to prepare the login our // token might have gone invalid in the meantime. As a cheap way to prevent // this we'll simply refresh the token regardless. It's plenty cheap and // should reliably ensure that the token is current. // Disconnect everything first though, this function may get called a bunch // of times, so we don't want duplicated submissions. disconnect(bugzillaManager(), &BugzillaManager::loginFinished, reportInterface(), &ReportInterface::sendBugReport); disconnect(bugzillaManager(), &BugzillaManager::loginError, this, nullptr); connect(bugzillaManager(), &BugzillaManager::loginFinished, reportInterface(), &ReportInterface::sendBugReport); connect(bugzillaManager(), &BugzillaManager::loginError, this, [this](const QString &error) { sendError(error, QString()); }); bugzillaManager()->refreshToken(); } void BugzillaSendPage::sent(int bug_id) { // Disconnect login->submit chain again. disconnect(bugzillaManager(), &BugzillaManager::loginFinished, reportInterface(), &ReportInterface::sendBugReport); disconnect(bugzillaManager(), &BugzillaManager::loginError, this, nullptr); ui.m_statusWidget->setVisible(false); ui.m_retryButton->setEnabled(false); ui.m_retryButton->setVisible(false); ui.m_showReportContentsButton->setVisible(false); ui.m_launchPageOnFinish->setVisible(true); ui.m_restartAppOnFinish->setVisible(!DrKonqi::crashedApplication()->hasBeenRestarted()); ui.m_restartAppOnFinish->setChecked(false); reportUrl = bugzillaManager()->urlForBug(bug_id); ui.m_finishedLabel->setText(xi18nc("@info/rich","Crash report sent." "URL: %1" "Thank you for being part of KDE. " "You can now close this window.", reportUrl)); emit finished(false); } void BugzillaSendPage::sendError(const QString & errorString, const QString & extendedMessage) { ui.m_statusWidget->setIdle(xi18nc("@info:status","Error sending the crash report: " "%1.", errorString)); ui.m_retryButton->setEnabled(true); ui.m_retryButton->setVisible(true); if (!extendedMessage.isEmpty()) { new UnhandledErrorDialog(this,errorString, extendedMessage); } } void BugzillaSendPage::finishClicked() { if (ui.m_launchPageOnFinish->isChecked() && !reportUrl.isEmpty()) { QDesktopServices::openUrl(QUrl(reportUrl)); } if (ui.m_restartAppOnFinish->isChecked()) { DrKonqi::crashedApplication()->restart(); } } void BugzillaSendPage::openReportContents() { if (!m_contentsDialog) { QString report = reportInterface()->generateReportFullText(false) + QLatin1Char('\n') + i18nc("@info report to KDE bugtracker address","Report to %1", DrKonqi::crashedApplication()->bugReportAddress()); m_contentsDialog = new ReportInformationDialog(report); } m_contentsDialog->show(); m_contentsDialog->raise(); m_contentsDialog->activateWindow(); } //END BugzillaSendPage /* Dialog for Unhandled Bugzilla Errors */ /* The user can save the bugzilla html output to check the error and/or to report this as a DrKonqi bug */ //BEGIN UnhandledErrorDialog UnhandledErrorDialog::UnhandledErrorDialog(QWidget * parent, const QString & error, const QString & extendedMessage) : QDialog(parent) { setWindowTitle(i18nc("@title:window", "Unhandled Bugzilla Error")); setWindowModality(Qt::ApplicationModal); QPushButton* saveButton = new QPushButton(this); saveButton->setText(i18nc("@action:button save html to a file","Save to a file")); saveButton->setIcon(QIcon::fromTheme(QStringLiteral("document-save"))); connect(saveButton, &QPushButton::clicked, this, &UnhandledErrorDialog::saveErrorMessage); setAttribute(Qt::WA_DeleteOnClose); QTextBrowser * htmlView = new QTextBrowser(this); QLabel * iconLabel = new QLabel(this); iconLabel->setFixedSize(32, 32); iconLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-warning")).pixmap(32, 32)); QLabel * mainLabel = new QLabel(this); mainLabel->setWordWrap(true); mainLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); QHBoxLayout * titleLayout = new QHBoxLayout(); titleLayout->setContentsMargins(5,2,5,2); titleLayout->setSpacing(5); titleLayout->addWidget(iconLabel); titleLayout->addWidget(mainLabel); QDialogButtonBox* buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons(QDialogButtonBox::Close); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); QVBoxLayout * layout = new QVBoxLayout(this); layout->addLayout(titleLayout); layout->addWidget(htmlView); layout->addWidget(buttonBox); m_extendedHTMLError = extendedMessage; mainLabel->setText(i18nc("@label", "There was an unhandled Bugzilla error: %1.
" "Below is the HTML that DrKonqi received. " "Try to perform the action again or save this error page " "to submit a bug against DrKonqi.").arg(error)); htmlView->setHtml(extendedMessage); show(); } void UnhandledErrorDialog::saveErrorMessage() { QString defaultName = QLatin1String("drkonqi-unhandled-bugzilla-error.html"); QPointer dlg(new QFileDialog(this)); dlg->selectFile(defaultName); dlg->setWindowTitle(i18nc("@title:window","Select Filename")); dlg->setAcceptMode(QFileDialog::AcceptSave); dlg->setFileMode(QFileDialog::AnyFile); dlg->setConfirmOverwrite(true); if ( dlg->exec() == QDialog::Accepted ) { if (!dlg) { //Dialog closed externally (ex. via DBus) return; } QUrl fileUrl; if(!dlg->selectedUrls().isEmpty()) fileUrl = dlg->selectedUrls().first(); if (fileUrl.isValid()) { QTemporaryFile tf; if (tf.open()) { QTextStream ts(&tf); ts << m_extendedHTMLError; ts.flush(); } else { KMessageBox::sorry(this, xi18nc("@info","Cannot open file %1 " "for writing.", tf.fileName())); delete dlg; return; } KIO::FileCopyJob* job = KIO::file_copy(QUrl::fromLocalFile(tf.fileName()), fileUrl); KJobWidgets::setWindow(job, this); if (!job->exec()) { KMessageBox::sorry(this, job->errorString()); } } } delete dlg; } //END UnhandledErrorDialog diff --git a/src/bugzillaintegration/reportassistantpages_bugzilla.h b/src/bugzillaintegration/reportassistantpages_bugzilla.h index bfcd67d3..c20ada1d 100644 --- a/src/bugzillaintegration/reportassistantpages_bugzilla.h +++ b/src/bugzillaintegration/reportassistantpages_bugzilla.h @@ -1,165 +1,167 @@ /******************************************************************* * reportassistantpages_bugzilla.h * Copyright 2009, 2011 Dario Andres Rodriguez +* Copyright 2019 Harald Sitter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ******************************************************************/ #ifndef REPORTASSISTANTPAGES__BUGZILLA__H #define REPORTASSISTANTPAGES__BUGZILLA__H #include "reportassistantpage.h" #include "reportassistantpages_base.h" #include "ui_assistantpage_bugzilla_login.h" #include "ui_assistantpage_bugzilla_information.h" #include "ui_assistantpage_bugzilla_preview.h" #include "ui_assistantpage_bugzilla_send.h" namespace KWallet { class Wallet; } class KCapacityBar; /** Bugzilla login **/ class BugzillaLoginPage: public ReportAssistantPage { Q_OBJECT public: explicit BugzillaLoginPage(ReportAssistantDialog *); ~BugzillaLoginPage() override; void aboutToShow() override; bool isComplete() override; private Q_SLOTS: void bugzillaVersionFound(); void loginClicked(); bool canLogin() const; void login(); void loginFinished(bool); void loginError(const QString &, const QString &); void walletLogin(); void updateLoginButtonStatus(); Q_SIGNALS: void loggedTurnToNextPage(); private: void updateWidget(bool enabled); bool kWalletEntryExists(const QString&); void openWallet(); Ui::AssistantPageBugzillaLogin ui; KWallet::Wallet * m_wallet; bool m_walletWasOpenedBefore; bool m_bugzillaVersionFound; }; /** Title and details page **/ class BugzillaInformationPage : public ReportAssistantPage { Q_OBJECT public: explicit BugzillaInformationPage(ReportAssistantDialog *); void aboutToShow() override; void aboutToHide() override; bool isComplete() override; bool showNextPage() override; private Q_SLOTS: void showTitleExamples(); void showDescriptionHelpExamples(); void checkTexts(); private: int currentDescriptionCharactersCount(); Ui::AssistantPageBugzillaInformation ui; KCapacityBar * m_textCompleteBar; bool m_textsOK; bool m_distributionComboSetup; bool m_distroComboVisible; int m_requiredCharacters; }; /** Preview report page **/ class BugzillaPreviewPage : public ReportAssistantPage { Q_OBJECT public: explicit BugzillaPreviewPage(ReportAssistantDialog *); void aboutToShow() override; + void aboutToHide() override; private: Ui::AssistantPageBugzillaPreview ui; }; /** Send crash report page **/ class BugzillaSendPage : public ReportAssistantPage { Q_OBJECT public: explicit BugzillaSendPage(ReportAssistantDialog *); void aboutToShow() override; private Q_SLOTS: void sent(int); void sendError(const QString &, const QString &); void retryClicked(); void finishClicked(); void openReportContents(); private: Ui::AssistantPageBugzillaSend ui; QString reportUrl; QPointer m_contentsDialog; Q_SIGNALS: void finished(bool); }; class UnhandledErrorDialog: public QDialog { Q_OBJECT public: UnhandledErrorDialog(QWidget * parent, const QString &, const QString &); private Q_SLOTS: void saveErrorMessage(); private: QString m_extendedHTMLError; }; #endif