diff --git a/src/libs/utils/checkablemessagebox.cpp b/src/libs/utils/checkablemessagebox.cpp index b0a28492d183dca633557527eaae4af3d95bca11..25f04538aa57c485c8cd67d48583fdf5a9e51041 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 56f20d959ce689149a92e08a99b0e8c193dde145..31e377c865b7c0ae1cb698a552d0db0d3a7adfaa 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 6012dc213e3e88196a0f91955aed1af3650612e6..b2cf4329cc3106cd94a9b8ab34d0c72cee7a28ab 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 7894931fae471c7ecfcbc9c7f2c1b2ebc9476c7a..76e1b5cae5ef4e66e1af18eaafa63935c66591d4 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 102d362d21a732b96b87e7eb7cf3273ff5e8db1e..be044ae4f05bda28d5ed7e6b8bcb9b109513e811 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 39f8a50e2ea2e1d5d96239687c9e767fc8129220..76a439d7cfb0a082056e0f7f84011afa7626dc72 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 2b451264d37a5e0a0d9e07ece11eb7ad17bb21d8..94106572f7457ef4f3b7608a3b86213cbac8b2b4 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 078b40cf571c265653518c28084b60cd2992fc17..787512e5d138945f5c54e7d0791f08e90f8fe5e2 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 56c8e5783af158081cf22f6ef1d39669d2dffe31..bf385e015215ce53bb2f23ca73d696b9ffb26fe3 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 b645485cd4b215d461ad9ca6f1430639629ec71a..422d0ae653d1aa145299f87386051da6593a6581 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.ui +++ b/src/plugins/projectexplorer/projectexplorersettingspage.ui @@ -2,14 +2,6 @@ <ui version="4.0"> <class>ProjectExplorer::Internal::ProjectExplorerSettingsPageUi</class> <widget class="QWidget" name="ProjectExplorer::Internal::ProjectExplorerSettingsPageUi"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>437</width> - <height>389</height> - </rect> - </property> <layout class="QVBoxLayout" name="verticalLayout_3"> <item> <widget class="QGroupBox" name="directoryGroupBox"> @@ -104,6 +96,13 @@ </property> </widget> </item> + <item> + <widget class="QCheckBox" name="promptToStopRunControlCheckBox"> + <property name="text"> + <string>Prompt to stop applications</string> + </property> + </widget> + </item> <item> <layout class="QVBoxLayout" name="verticalLayout"> <property name="spacing"> diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 68f709d2ed177021f39a063a248d776df92436ce..231f56a5cbdff6a344304c2991ba57fd25dd9a70 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 <extensionsystem/pluginmanager.h> -#include <coreplugin/icore.h> + #include <utils/qtcassert.h> +#include <utils/checkablemessagebox.h> + +#include <coreplugin/icore.h> #include <QtCore/QTimer> +#include <QtCore/QSettings> #include <QtGui/QMainWindow> #include <QtGui/QMessageBox> -#include <QtGui/QAbstractButton> +#include <QtGui/QPushButton> #ifdef Q_OS_MAC #include <Carbon/Carbon.h> @@ -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("<html><head/><body><center><i>%1</i> is still running.<center/>" + "<center>Force it to quit?</center></body></html>").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 bd5d1a08d4852d7e336437eb65f37aa8c9883eb2..fa636b3a8dfc4147c9b828744c07861e2aef6dab 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 6d10f09a8c0b55de679d547d9c4dc97fa0df79bd..8c727672c5131f7c7d37fd12b6bf0187637033aa 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("<html><head/><body><center><i>%1</i> is still running on the device.<center/>" + "<center>Terminating it can leave the target in an inconsistent state.</center>" + "<center>Would you still like to terminate it?</center></body></html>").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 c8e07e4d259cc339ce2e89a6811064aa1a28ac17..ba355fa12eeb139c737c15a489646741b68b739a 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