OSDN Git Service

Add "never ask again" option to dialog asking about killing applications
authorcon <qtc-committer@nokia.com>
Mon, 17 Jan 2011 12:52:14 +0000 (13:52 +0100)
committercon <qtc-committer@nokia.com>
Mon, 17 Jan 2011 12:52:33 +0000 (13:52 +0100)
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

14 files changed:
src/libs/utils/checkablemessagebox.cpp
src/libs/utils/checkablemessagebox.h
src/plugins/debugger/debuggerrunner.cpp
src/plugins/debugger/debuggerrunner.h
src/plugins/projectexplorer/outputwindow.cpp
src/plugins/projectexplorer/outputwindow.h
src/plugins/projectexplorer/projectexplorer.cpp
src/plugins/projectexplorer/projectexplorersettings.h
src/plugins/projectexplorer/projectexplorersettingspage.cpp
src/plugins/projectexplorer/projectexplorersettingspage.ui
src/plugins/projectexplorer/runconfiguration.cpp
src/plugins/projectexplorer/runconfiguration.h
src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h

index b0a2849..25f0453 100644 (file)
@@ -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())
index 56f20d9..31e377c 100644 (file)
@@ -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);
index 6012dc2..b2cf432 100644 (file)
@@ -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()
index 7894931..76e1b5c 100644 (file)
@@ -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;
index 102d362..be044ae 100644 (file)
@@ -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();
index 39f8a50..76a439d 100644 (file)
@@ -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;
index 2b45126..9410657 100644 (file)
@@ -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());
     }
 }
index 078b40c..787512e 100644 (file)
@@ -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
 
index 56c8e57..bf385e0 100644 (file)
@@ -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
index b645485..422d0ae 100644 (file)
@@ -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">
        </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">
          <number>0</number>
index 68f709d..231f56a 100644 (file)
 #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
index bd5d1a0..fa636b3 100644 (file)
@@ -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;
index 6d10f09..8c72767 100644 (file)
@@ -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);
+}
index c8e07e4..ba355fa 100644 (file)
@@ -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