diff --git a/src/drkonqidialog.cpp b/src/drkonqidialog.cpp index 64dd6579..bac2ebe3 100644 --- a/src/drkonqidialog.cpp +++ b/src/drkonqidialog.cpp @@ -1,302 +1,306 @@ /******************************************************************* * drkonqidialog.cpp * Copyright 2009 Dario Andres Rodriguez * * 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 "drkonqidialog.h" #include #include #include #include #include #include #include #include #include "drkonqi.h" #include "backtracewidget.h" #include "aboutbugreportingdialog.h" #include "crashedapplication.h" #include "debuggermanager.h" #include "debuggerlaunchers.h" #include "drkonqi_globals.h" #include "config-drkonqi.h" #if HAVE_XMLRPCCLIENT #include "bugzillaintegration/reportassistantdialog.h" #endif static const char ABOUT_BUG_REPORTING_URL[] = "#aboutbugreporting"; static const char DRKONQI_REPORT_BUG_URL[] = KDE_BUGZILLA_URL "enter_bug.cgi?product=drkonqi&format=guided"; DrKonqiDialog::DrKonqiDialog(QWidget * parent) : QDialog(parent), m_aboutBugReportingDialog(0), m_backtraceWidget(0) { setAttribute(Qt::WA_DeleteOnClose, true); //Setting dialog title and icon setWindowTitle(DrKonqi::crashedApplication()->name()); setWindowIcon(QIcon::fromTheme(QStringLiteral("tools-report-bug"))); QVBoxLayout* l = new QVBoxLayout(this); m_tabWidget = new QTabWidget(this); l->addWidget(m_tabWidget); m_buttonBox = new QDialogButtonBox(this); connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accepted); connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::rejected); l->addWidget(m_buttonBox); connect(m_tabWidget, &QTabWidget::currentChanged, this, &DrKonqiDialog::tabIndexChanged); KConfigGroup config(KSharedConfig::openConfig(), "General"); if (!config.readEntry(QStringLiteral("ShowOnlyBacktrace"), false)) { buildIntroWidget(); m_tabWidget->addTab(m_introWidget, i18nc("@title:tab general information", "&General")); } m_backtraceWidget = new BacktraceWidget(DrKonqi::debuggerManager()->backtraceGenerator(), this); m_backtraceWidget->setMinimumSize(QSize(575, 240)); m_tabWidget->addTab(m_backtraceWidget, i18nc("@title:tab", "&Developer Information")); m_tabWidget->tabBar()->setVisible(m_tabWidget->count() > 1); buildDialogButtons(); setMinimumSize(QSize(640,320)); resize(minimumSize()); KWindowConfig::restoreWindowSize(windowHandle(), config); setLayout(l); } DrKonqiDialog::~DrKonqiDialog() { KConfigGroup config(KSharedConfig::openConfig(), "General"); KWindowConfig::saveWindowSize(windowHandle(), config); } void DrKonqiDialog::tabIndexChanged(int index) { if (index == m_tabWidget->indexOf(m_backtraceWidget)) { m_backtraceWidget->generateBacktrace(); } } void DrKonqiDialog::buildIntroWidget() { const CrashedApplication *crashedApp = DrKonqi::crashedApplication(); m_introWidget = new QWidget(this); ui.setupUi(m_introWidget); ui.titleLabel->setText(xi18nc("@info", "We are sorry, %1 " "closed unexpectedly.", crashedApp->name())); QString reportMessage; if (!crashedApp->bugReportAddress().isEmpty()) { if (crashedApp->fakeExecutableBaseName() == QLatin1String("drkonqi")) { //Handle own crashes reportMessage = xi18nc("@info", "As the Crash Handler itself has failed, the " "automatic reporting process is disabled to reduce the " "risks of failing again." "Please, manually report this error " "to the KDE bug tracking system. Do not forget to include " "the backtrace from the Developer Information " "tab.", QLatin1String(DRKONQI_REPORT_BUG_URL)); } else if (DrKonqi::isSafer()) { reportMessage = xi18nc("@info", "The reporting assistant is disabled because " "the crash handler dialog was started in safe mode." "You can manually report this bug to %1 " "(including the backtrace from the " "Developer Information " "tab.)", crashedApp->bugReportAddress()); } else { reportMessage = xi18nc("@info", "You can help us improve KDE Software by reporting " "this error.Learn " "more about bug reporting.It is " "safe to close this dialog if you do not want to report " "this bug.", QLatin1String(ABOUT_BUG_REPORTING_URL)); } } else { reportMessage = xi18nc("@info", "You cannot report this error, because " "%1 does not provide a bug reporting " "address.", crashedApp->name() ); } ui.infoLabel->setText(reportMessage); connect(ui.infoLabel, &QLabel::linkActivated, this, &DrKonqiDialog::linkActivated); ui.detailsTitleLabel->setText(QStringLiteral("%1").arg(i18nc("@label","Details:"))); ui.detailsLabel->setText(xi18nc("@info Note the time information is divided into date and time parts", "Executable: %1" " PID: %2 Signal: %3 (%4) " "Time: %5 %6", crashedApp->fakeExecutableBaseName(), crashedApp->pid(), crashedApp->signalName(), #if defined(Q_OS_UNIX) crashedApp->signalNumber(), #else //windows uses weird big numbers for exception codes, //so it doesn't make sense to display them in decimal QString().sprintf("0x%8x", crashedApp->signalNumber()), #endif crashedApp->datetime().date().toString(Qt::DefaultLocaleShortDate), crashedApp->datetime().time().toString() )); } void DrKonqiDialog::buildDialogButtons() { const CrashedApplication *crashedApp = DrKonqi::crashedApplication(); //Set dialog buttons m_buttonBox->setStandardButtons(QDialogButtonBox::Close); //Report bug button: User1 QPushButton* reportButton = new QPushButton(m_buttonBox); KGuiItem2 reportItem(i18nc("@action:button", "Report &Bug"), QIcon::fromTheme(QStringLiteral("tools-report-bug")), i18nc("@info:tooltip", "Starts the bug report assistant.")); KGuiItem::assign(reportButton, reportItem); m_buttonBox->addButton(reportButton, QDialogButtonBox::ActionRole); bool enableReportAssistant = !crashedApp->bugReportAddress().isEmpty() && crashedApp->fakeExecutableBaseName() != QLatin1String("drkonqi") && !DrKonqi::isSafer() && HAVE_XMLRPCCLIENT; reportButton->setEnabled(enableReportAssistant); connect(reportButton, &QPushButton::clicked, this, &DrKonqiDialog::startBugReportAssistant); //Default debugger button and menu (only for developer mode): User2 DebuggerManager *debuggerManager = DrKonqi::debuggerManager(); m_debugButton = new QPushButton(m_buttonBox); KGuiItem2 debugItem(i18nc("@action:button this is the debug menu button label which contains the debugging applications", "&Debug"), QIcon::fromTheme(QStringLiteral("applications-development")), i18nc("@info:tooltip", "Starts a program to debug " "the crashed application.")); KGuiItem::assign(m_debugButton, debugItem); m_debugButton->setVisible(debuggerManager->showExternalDebuggers()); - m_buttonBox->addButton(m_debugButton, QDialogButtonBox::ActionRole); + // Do not add the button unless it is visible, otherwise the Box will force + // it visible as it calls show() explicitly. + if (m_debugButton->isVisible()) { + m_buttonBox->addButton(m_debugButton, QDialogButtonBox::ActionRole); + } m_debugMenu = new QMenu(this); m_debugButton->setMenu(m_debugMenu); QList debuggers = debuggerManager->availableExternalDebuggers(); foreach(AbstractDebuggerLauncher *launcher, debuggers) { addDebugger(launcher); } connect(debuggerManager, &DebuggerManager::externalDebuggerAdded, this, &DrKonqiDialog::addDebugger); connect(debuggerManager, &DebuggerManager::externalDebuggerRemoved, this, &DrKonqiDialog::removeDebugger); connect(debuggerManager, &DebuggerManager::debuggerRunning, this, &DrKonqiDialog::enableDebugMenu); //Restart application button KGuiItem2 restartItem(i18nc("@action:button", "&Restart Application"), QIcon::fromTheme(QStringLiteral("system-reboot")), i18nc("@info:tooltip", "Use this button to restart " "the crashed application.")); m_restartButton = new QPushButton(m_buttonBox); KGuiItem::assign(m_restartButton, restartItem); m_restartButton->setEnabled(!crashedApp->hasBeenRestarted() && crashedApp->fakeExecutableBaseName() != QLatin1String("drkonqi")); m_buttonBox->addButton(m_restartButton, QDialogButtonBox::ActionRole); connect(m_restartButton, &QAbstractButton::clicked, crashedApp, &CrashedApplication::restart); connect(crashedApp, &CrashedApplication::restarted, this, &DrKonqiDialog::applicationRestarted); //Close button QString tooltipText = i18nc("@info:tooltip", "Close this dialog (you will lose the crash information.)"); m_buttonBox->button(QDialogButtonBox::Close)->setToolTip(tooltipText); m_buttonBox->button(QDialogButtonBox::Close)->setWhatsThis(tooltipText); m_buttonBox->button(QDialogButtonBox::Close)->setFocus(); } void DrKonqiDialog::addDebugger(AbstractDebuggerLauncher *launcher) { QAction *action = new QAction(QIcon::fromTheme(QStringLiteral("applications-development")), i18nc("@action:inmenu 1 is the debugger name", "Debug in %1", launcher->name()), m_debugMenu); m_debugMenu->addAction(action); connect(action, &QAction::triggered, launcher, &AbstractDebuggerLauncher::start); m_debugMenuActions.insert(launcher, action); } void DrKonqiDialog::removeDebugger(AbstractDebuggerLauncher *launcher) { QAction *action = m_debugMenuActions.take(launcher); if ( action ) { m_debugMenu->removeAction(action); action->deleteLater(); } else { qWarning() << "Invalid launcher"; } } void DrKonqiDialog::enableDebugMenu(bool debuggerRunning) { m_debugButton->setEnabled(!debuggerRunning); } void DrKonqiDialog::startBugReportAssistant() { #if HAVE_XMLRPCCLIENT ReportAssistantDialog * bugReportAssistant = new ReportAssistantDialog(); bugReportAssistant->show(); connect(bugReportAssistant, &QObject::destroyed, this, &DrKonqiDialog::reject); hide(); #endif } void DrKonqiDialog::linkActivated(const QString& link) { if (link == QLatin1String(ABOUT_BUG_REPORTING_URL)) { showAboutBugReporting(); } else if (link == QLatin1String(DRKONQI_REPORT_BUG_URL)) { QDesktopServices::openUrl(QUrl(link)); } else if (link.startsWith(QLatin1String("http"))) { qWarning() << "unexpected link"; QDesktopServices::openUrl(QUrl(link)); } } void DrKonqiDialog::showAboutBugReporting() { if (!m_aboutBugReportingDialog) { m_aboutBugReportingDialog = new AboutBugReportingDialog(); connect(this, &DrKonqiDialog::destroyed, m_aboutBugReportingDialog.data(), &AboutBugReportingDialog::close); } m_aboutBugReportingDialog->show(); m_aboutBugReportingDialog->raise(); m_aboutBugReportingDialog->activateWindow(); } void DrKonqiDialog::applicationRestarted(bool success) { m_restartButton->setEnabled(!success); }