From edd7224cd69dd270d860674192b150de22aa6017 Mon Sep 17 00:00:00 2001 From: con Date: Mon, 17 Jan 2011 13:52:14 +0100 Subject: [PATCH] Add "never ask again" option to dialog asking about killing applications The option is used for the stop button in the application output. Closing tabs will still ask unconditionally, also if applications would be killed as a side-effect, e.g. of closing Qt Creator. The Symbian controls also always ask, with a more descriptive text, because killing applications might have negative effect on the device in some cases. Reviewed-by: Friedemann Kleint Task-number: QTCREATORBUG-3119 --- src/libs/utils/checkablemessagebox.cpp | 20 +++++++ src/libs/utils/checkablemessagebox.h | 5 ++ src/plugins/debugger/debuggerrunner.cpp | 13 +++-- src/plugins/debugger/debuggerrunner.h | 2 +- src/plugins/projectexplorer/outputwindow.cpp | 36 +++++++++---- src/plugins/projectexplorer/outputwindow.h | 10 +++- src/plugins/projectexplorer/projectexplorer.cpp | 4 +- .../projectexplorer/projectexplorersettings.h | 7 +-- .../projectexplorersettingspage.cpp | 2 + .../projectexplorer/projectexplorersettingspage.ui | 15 +++--- src/plugins/projectexplorer/runconfiguration.cpp | 61 +++++++++++++++++----- src/plugins/projectexplorer/runconfiguration.h | 12 ++++- .../qt-s60/s60devicerunconfiguration.cpp | 18 +++++++ .../qt-s60/s60devicerunconfiguration.h | 2 + 14 files changed, 160 insertions(+), 47 deletions(-) diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp index b0a28492d1..25f04538aa 100644 --- a/src/libs/utils/checkablemessagebox.cpp +++ b/src/libs/utils/checkablemessagebox.cpp @@ -124,6 +124,16 @@ void CheckableMessageBox::setCheckBoxText(const QString &t) m_d->ui.checkBox->setText(t); } +bool CheckableMessageBox::isCheckBoxVisible() const +{ + return m_d->ui.checkBox->isVisible(); +} + +void CheckableMessageBox::setCheckBoxVisible(bool v) +{ + m_d->ui.checkBox->setVisible(v); +} + QDialogButtonBox::StandardButtons CheckableMessageBox::standardButtons() const { return m_d->ui.buttonBox->standardButtons(); @@ -134,6 +144,16 @@ void CheckableMessageBox::setStandardButtons(QDialogButtonBox::StandardButtons s m_d->ui.buttonBox->setStandardButtons(s); } +QPushButton *CheckableMessageBox::button(QDialogButtonBox::StandardButton b) const +{ + return m_d->ui.buttonBox->button(b); +} + +QPushButton *CheckableMessageBox::addButton(const QString &text, QDialogButtonBox::ButtonRole role) +{ + return m_d->ui.buttonBox->addButton(text, role); +} + QDialogButtonBox::StandardButton CheckableMessageBox::defaultButton() const { foreach (QAbstractButton *b, m_d->ui.buttonBox->buttons()) diff --git a/src/libs/utils/checkablemessagebox.h b/src/libs/utils/checkablemessagebox.h index 56f20d959c..31e377c865 100644 --- a/src/libs/utils/checkablemessagebox.h +++ b/src/libs/utils/checkablemessagebox.h @@ -79,8 +79,13 @@ public: QString checkBoxText() const; void setCheckBoxText(const QString &); + bool isCheckBoxVisible() const; + void setCheckBoxVisible(bool); + QDialogButtonBox::StandardButtons standardButtons() const; void setStandardButtons(QDialogButtonBox::StandardButtons s); + QPushButton *button(QDialogButtonBox::StandardButton b) const; + QPushButton *addButton(const QString &text, QDialogButtonBox::ButtonRole role); QDialogButtonBox::StandardButton defaultButton() const; void setDefaultButton(QDialogButtonBox::StandardButton s); diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 6012dc213e..b2cf4329cc 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -469,20 +469,19 @@ void DebuggerRunControl::showMessage(const QString &msg, int channel) } } -bool DebuggerRunControl::aboutToStop() const +bool DebuggerRunControl::promptToStop(bool *optionalPrompt) const { QTC_ASSERT(isRunning(), return true;) + if (optionalPrompt && !*optionalPrompt) + return true; + const QString question = tr("A debugging session is still in progress. " "Terminating the session in the current" " state can leave the target in an inconsistent state." " Would you still like to terminate it?"); - - const QMessageBox::StandardButton answer = - QMessageBox::question(debuggerCore()->mainWindow(), - tr("Close Debugging Session"), question, - QMessageBox::Yes|QMessageBox::No); - return answer == QMessageBox::Yes; + return showPromptToStopDialog(tr("Close Debugging Session"), question, + QString(), QString(), optionalPrompt); } RunControl::StopResult DebuggerRunControl::stop() diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 7894931fae..76e1b5cae5 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -85,7 +85,7 @@ public: // ProjectExplorer::RunControl void start(); - bool aboutToStop() const; + bool promptToStop(bool *prompt = 0) const; StopResult stop(); // Called from SnapshotWindow. bool isRunning() const; QString displayName() const; diff --git a/src/plugins/projectexplorer/outputwindow.cpp b/src/plugins/projectexplorer/outputwindow.cpp index 102d362d21..be044ae4f0 100644 --- a/src/plugins/projectexplorer/outputwindow.cpp +++ b/src/plugins/projectexplorer/outputwindow.cpp @@ -183,14 +183,14 @@ int OutputPane::tabWidgetIndexOf(int runControlIndex) const bool OutputPane::aboutToClose() const { foreach(const RunControlTab &rt, m_runControlTabs) - if (rt.runControl->isRunning() && !rt.runControl->aboutToStop()) + if (rt.runControl->isRunning() && !rt.runControl->promptToStop()) return false; return true; } void OutputPane::aboutToUnloadSession() { - closeTabs(true); + closeTabs(CloseTabWithPrompt); } QWidget *OutputPane::outputWidget(QWidget *) @@ -309,18 +309,18 @@ void OutputPane::stopRunControl() QTC_ASSERT(index != -1 && m_runControlTabs.at(index).runControl->isRunning(), return;) RunControl *rc = m_runControlTabs.at(index).runControl; - if (rc->isRunning() && rc->aboutToStop()) + if (rc->isRunning() && optionallyPromptToStop(rc)) rc->stop(); if (debug) qDebug() << "OutputPane::stopRunControl " << rc; } -bool OutputPane::closeTabs(bool prompt) +bool OutputPane::closeTabs(CloseTabMode mode) { bool allClosed = true; for (int t = m_tabWidget->count() - 1; t >= 0; t--) - if (!closeTab(t, prompt)) + if (!closeTab(t, mode)) allClosed = false; if (debug) qDebug() << "OutputPane::closeTabs() returns " << allClosed; @@ -329,10 +329,10 @@ bool OutputPane::closeTabs(bool prompt) bool OutputPane::closeTab(int index) { - return closeTab(index, true); + return closeTab(index, CloseTabWithPrompt); } -bool OutputPane::closeTab(int tabIndex, bool prompt) +bool OutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode) { const int index = indexOf(m_tabWidget->widget(tabIndex)); QTC_ASSERT(index != -1, return true;) @@ -344,8 +344,14 @@ bool OutputPane::closeTab(int tabIndex, bool prompt) << tab.window << tab.asyncClosing; // Prompt user to stop if (tab.runControl->isRunning()) { - if (prompt && !tab.runControl->aboutToStop()) - return false; + switch (closeTabMode) { + case CloseTabNoPrompt: + break; + case CloseTabWithPrompt: + if (!tab.runControl->promptToStop()) + return false; + break; + } if (tab.runControl->stop() == RunControl::AsynchronousStop) { tab.asyncClosing = true; return false; @@ -363,6 +369,16 @@ bool OutputPane::closeTab(int tabIndex, bool prompt) return true; } +bool OutputPane::optionallyPromptToStop(RunControl *runControl) +{ + ProjectExplorerPlugin *pe = ProjectExplorerPlugin::instance(); + ProjectExplorerSettings settings = pe->projectExplorerSettings(); + if (!runControl->promptToStop(&settings.prompToStopRunControl)) + return false; + pe->setProjectExplorerSettings(settings); + return true; +} + void OutputPane::projectRemoved() { tabChanged(m_tabWidget->currentIndex()); @@ -415,7 +431,7 @@ void OutputPane::runControlFinished() } // Check for asynchronous close. Close the tab. if (m_runControlTabs.at(senderIndex).asyncClosing) - closeTab(tabWidgetIndexOf(senderIndex), false); + closeTab(tabWidgetIndexOf(senderIndex), CloseTabNoPrompt); if (!isRunning()) emit allRunControlsFinished(); diff --git a/src/plugins/projectexplorer/outputwindow.h b/src/plugins/projectexplorer/outputwindow.h index 39f8a50e2e..76a439d7cf 100644 --- a/src/plugins/projectexplorer/outputwindow.h +++ b/src/plugins/projectexplorer/outputwindow.h @@ -70,6 +70,11 @@ class OutputPane : public Core::IOutputPane Q_OBJECT public: + enum CloseTabMode { + CloseTabNoPrompt, + CloseTabWithPrompt + }; + OutputPane(); virtual ~OutputPane(); @@ -93,7 +98,7 @@ public: void showTabFor(RunControl *rc); bool aboutToClose() const; - bool closeTabs(bool prompt); + bool closeTabs(CloseTabMode mode); signals: void allRunControlsFinished(); @@ -126,7 +131,8 @@ private: }; bool isRunning() const; - bool closeTab(int index, bool prompt); + bool closeTab(int index, CloseTabMode cm); + bool optionallyPromptToStop(RunControl *runControl); int indexOf(const RunControl *) const; int indexOf(const QWidget *outputWindow) const; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 2b451264d3..94106572f7 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -832,6 +832,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er d->m_projectExplorerSettings.wrapAppOutput = s->value("ProjectExplorer/Settings/WrapAppOutput", true).toBool(); d->m_projectExplorerSettings.useJom = s->value("ProjectExplorer/Settings/UseJom", true).toBool(); d->m_projectExplorerSettings.autorestoreLastSession = s->value("ProjectExplorer/Settings/AutoRestoreLastSession", false).toBool(); + d->m_projectExplorerSettings.prompToStopRunControl = s->value("ProjectExplorer/Settings/PromptToStopRunControl", false).toBool(); d->m_projectExplorerSettings.environmentId = QUuid(s->value("ProjectExplorer/Settings/EnvironmentId").toString()); if (d->m_projectExplorerSettings.environmentId.isNull()) d->m_projectExplorerSettings.environmentId = QUuid::createUuid(); @@ -988,7 +989,7 @@ ExtensionSystem::IPlugin::ShutdownFlag ProjectExplorerPlugin::aboutToShutdown() // Attempt to synchronously shutdown all run controls. // If that fails, fall back to asynchronous shutdown (Debugger run controls // might shutdown asynchronously). - if (d->m_outputPane->closeTabs(false /* No prompt any more */)) + if (d->m_outputPane->closeTabs(OutputPane::CloseTabNoPrompt /* No prompt any more */)) return SynchronousShutdown; connect(d->m_outputPane, SIGNAL(allRunControlsFinished()), this, SIGNAL(asynchronousShutdownFinished())); @@ -1092,6 +1093,7 @@ void ProjectExplorerPlugin::savePersistentSettings() s->setValue("ProjectExplorer/Settings/WrapAppOutput", d->m_projectExplorerSettings.wrapAppOutput); s->setValue("ProjectExplorer/Settings/UseJom", d->m_projectExplorerSettings.useJom); s->setValue("ProjectExplorer/Settings/AutoRestoreLastSession", d->m_projectExplorerSettings.autorestoreLastSession); + s->setValue("ProjectExplorer/Settings/PromptToStopRunControl", d->m_projectExplorerSettings.prompToStopRunControl); s->setValue("ProjectExplorer/Settings/EnvironmentId", d->m_projectExplorerSettings.environmentId.toString()); } } diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h index 078b40cf57..787512e5d1 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.h +++ b/src/plugins/projectexplorer/projectexplorersettings.h @@ -46,7 +46,7 @@ struct ProjectExplorerSettings saveBeforeBuild(false), showCompilerOutput(false), showRunOutput(true), cleanOldAppOutput(false), wrapAppOutput(true), useJom(true), - autorestoreLastSession(false) + autorestoreLastSession(false), prompToStopRunControl(false) { } bool buildBeforeDeploy; @@ -58,6 +58,7 @@ struct ProjectExplorerSettings bool wrapAppOutput; bool useJom; bool autorestoreLastSession; // This option is set in the Session Manager! + bool prompToStopRunControl; // Add a UUid which is used to identify the development environment. // This is used to warn the user when he is trying to open a .user file that was created @@ -75,10 +76,10 @@ inline bool operator==(const ProjectExplorerSettings &p1, const ProjectExplorerS && p1.cleanOldAppOutput == p2.cleanOldAppOutput && p1.wrapAppOutput == p2.wrapAppOutput && p1.useJom == p2.useJom - && p1.autorestoreLastSession == p2.autorestoreLastSession; + && p1.autorestoreLastSession == p2.autorestoreLastSession + && p1.prompToStopRunControl == p2.prompToStopRunControl; } - } // namespace ProjectExplorer } // namespace Internal diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettingspage.cpp index 56c8e5783a..bf385e0152 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp +++ b/src/plugins/projectexplorer/projectexplorersettingspage.cpp @@ -77,6 +77,7 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const pes.cleanOldAppOutput = m_ui.cleanOldAppOutputCheckBox->isChecked(); pes.wrapAppOutput = m_ui.wrapAppOutputCheckBox->isChecked(); pes.useJom = m_ui.jomCheckbox->isChecked(); + pes.prompToStopRunControl = m_ui.promptToStopRunControlCheckBox->isChecked(); return pes; } @@ -90,6 +91,7 @@ void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings & m_ui.cleanOldAppOutputCheckBox->setChecked(pes.cleanOldAppOutput); m_ui.wrapAppOutputCheckBox->setChecked(pes.wrapAppOutput); m_ui.jomCheckbox->setChecked(pes.useJom); + m_ui.promptToStopRunControlCheckBox->setChecked(pes.prompToStopRunControl); } QString ProjectExplorerSettingsWidget::projectsDirectory() const diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.ui b/src/plugins/projectexplorer/projectexplorersettingspage.ui index b645485cd4..422d0ae653 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.ui +++ b/src/plugins/projectexplorer/projectexplorersettingspage.ui @@ -2,14 +2,6 @@ ProjectExplorer::Internal::ProjectExplorerSettingsPageUi - - - 0 - 0 - 437 - 389 - - @@ -105,6 +97,13 @@ + + + Prompt to stop applications + + + + 0 diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 68f709d2ed..231f56a5cb 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -38,15 +38,18 @@ #include "target.h" #include "buildconfiguration.h" #include "projectexplorerconstants.h" - #include -#include + #include +#include + +#include #include +#include #include #include -#include +#include #ifdef Q_OS_MAC #include @@ -320,20 +323,50 @@ QString RunControl::displayName() const return m_displayName; } -bool RunControl::aboutToStop() const +bool RunControl::promptToStop(bool *optionalPrompt) const { QTC_ASSERT(isRunning(), return true;) - QMessageBox messageBox(QMessageBox::Warning, - tr("Application Still Running"), - tr("%1 is still running.").arg(displayName()), - QMessageBox::Cancel | QMessageBox::Yes, - Core::ICore::instance()->mainWindow()); - messageBox.setInformativeText(tr("Force it to quit?")); - messageBox.setDefaultButton(QMessageBox::Yes); - messageBox.button(QMessageBox::Yes)->setText(tr("Force Quit")); - messageBox.button(QMessageBox::Cancel)->setText(tr("Keep Running")); - return messageBox.exec() == QMessageBox::Yes; + if (optionalPrompt && !*optionalPrompt) + return true; + + const QString msg = tr("
%1 is still running.
" + "
Force it to quit?
").arg(displayName()); + return showPromptToStopDialog(tr("Application Still Running"), msg, + tr("Force Quit"), tr("Keep Running"), + optionalPrompt); +} + +// Utility to prompt to terminate application with checkable box. +bool RunControl::showPromptToStopDialog(const QString &title, + const QString &text, + const QString &stopButtonText, + const QString &cancelButtonText, + bool *prompt) const +{ + QTC_ASSERT(isRunning(), return true;) + // Show a question message box where user can uncheck this + // question for this class. + Utils::CheckableMessageBox messageBox(Core::ICore::instance()->mainWindow()); + messageBox.setWindowTitle(title); + messageBox.setText(text); + messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::Cancel); + if (!stopButtonText.isEmpty()) + messageBox.button(QDialogButtonBox::Yes)->setText(stopButtonText); + if (!cancelButtonText.isEmpty()) + messageBox.button(QDialogButtonBox::Cancel)->setText(cancelButtonText); + messageBox.setDefaultButton(QDialogButtonBox::Yes); + if (prompt) { + messageBox.setCheckBoxText(tr("Do not ask again")); + messageBox.setChecked(false); + } else { + messageBox.setCheckBoxVisible(false); + } + messageBox.exec(); + const bool close = messageBox.clickedStandardButton() == QDialogButtonBox::Yes; + if (close && prompt && messageBox.isChecked()) + *prompt = false; + return close; } bool RunControl::sameRunConfiguration(const RunControl *other) const diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index bd5d1a08d4..fa636b3a8d 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -191,7 +191,10 @@ public: explicit RunControl(RunConfiguration *runConfiguration, QString mode); virtual ~RunControl(); virtual void start() = 0; - virtual bool aboutToStop() const; + + // Prompt to stop. If 'optionalPrompt' is passed, a "Do not ask again"- + // checkbox will show and the result will be returned in '*optionalPrompt'. + virtual bool promptToStop(bool *optionalPrompt = 0) const; virtual StopResult stop() = 0; virtual bool isRunning() const = 0; virtual QString displayName() const; @@ -214,6 +217,13 @@ signals: private slots: void bringApplicationToForegroundInternal(); +protected: + // Utility to prompt to terminate application with checkable box. + bool showPromptToStopDialog(const QString &title, const QString &text, + const QString &stopButtonText = QString(), + const QString &cancelButtonText = QString(), + bool *prompt = 0) const; + private: QString m_displayName; QString m_runMode; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 6d10f09a8c..8c727672c5 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -625,6 +625,18 @@ bool S60DeviceRunControl::isRunning() const } } +bool S60DeviceRunControl::promptToStop(bool *) const +{ + // We override the settings prompt + QTC_ASSERT(isRunning(), return true;) + + const QString question = tr("
%1 is still running on the device.
" + "
Terminating it can leave the target in an inconsistent state.
" + "
Would you still like to terminate it?
").arg(displayName()); + return showPromptToStopDialog(tr("Application Still Running"), question, + tr("Force Quit"), tr("Keep Running")); +} + void S60DeviceRunControl::startLaunching() { QString errorMessage; @@ -1085,3 +1097,9 @@ void S60DeviceDebugRunControl::start() appendMessage(tr("Launching debugger..."), NormalMessageFormat); Debugger::DebuggerRunControl::start(); } + +bool S60DeviceDebugRunControl::promptToStop(bool *) const +{ + // We override the settings prompt + return Debugger::DebuggerRunControl::promptToStop(0); +} diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index c8e07e4d25..ba355fa12e 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -158,6 +158,7 @@ public: virtual void start(); virtual StopResult stop(); virtual bool isRunning() const; + virtual bool promptToStop(bool *optionalPrompt = 0) const; static QMessageBox *createTrkWaitingMessageBox(const QString &port, QWidget *parent = 0); @@ -251,6 +252,7 @@ public: explicit S60DeviceDebugRunControl(S60DeviceRunConfiguration *runConfiguration, const QString &mode); virtual void start(); + virtual bool promptToStop(bool *optionalPrompt = 0) const; }; } // namespace Internal -- 2.11.0