Implement "quit on last window closed" logic for QWindow
authorGunnar Sletta <gunnar.sletta@nokia.com>
Wed, 10 Aug 2011 13:36:51 +0000 (15:36 +0200)
committerJørgen Lind <jorgen.lind@nokia.com>
Thu, 11 Aug 2011 06:20:55 +0000 (08:20 +0200)
Change-Id: Ide33578ad60796f3e267b09be76cda87eaf873d0
Reviewed-on: http://codereview.qt.nokia.com/2827
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
src/gui/kernel/qguiapplication.cpp
src/gui/kernel/qguiapplication.h
src/gui/kernel/qguiapplication_p.h
src/gui/kernel/qwindow.cpp
src/gui/kernel/qwindow_p.h

index f1edf52..1bcbb36 100644 (file)
@@ -101,6 +101,8 @@ int QGuiApplicationPrivate::mousePressX = 0;
 int QGuiApplicationPrivate::mousePressY = 0;
 int QGuiApplicationPrivate::mouse_double_click_distance = 5;
 
+bool QGuiApplicationPrivate::quitOnLastWindowClosed = true;
+
 static Qt::LayoutDirection layout_direction = Qt::LeftToRight;
 static bool force_reverse = false;
 
@@ -914,6 +916,48 @@ void QGuiApplicationPrivate::notifyActiveWindowChange(QWindow *)
 {
 }
 
+
+/*!
+    \property QGuiApplication::quitOnLastWindowClosed
+
+    \brief whether the application implicitly quits when the last window is
+    closed.
+
+    The default is true.
+
+    If this property is true, the applications quits when the last visible
+    primary window (i.e. window with no parent) is closed.
+
+    \sa quit(), QWindow::close()
+ */
+
+void QGuiApplication::setQuitOnLastWindowClosed(bool quit)
+{
+    QGuiApplicationPrivate::quitOnLastWindowClosed = quit;
+}
+
+
+
+bool QGuiApplication::quitOnLastWindowClosed()
+{
+    return QGuiApplicationPrivate::quitOnLastWindowClosed;
+}
+
+
+
+void QGuiApplicationPrivate::emitLastWindowClosed()
+{
+    if (qGuiApp && qGuiApp->d_func()->in_exec) {
+        if (QGuiApplicationPrivate::quitOnLastWindowClosed) {
+            // get ready to quit, this event might be removed if the
+            // event loop is re-entered, however
+            QGuiApplication::postEvent(qApp, new QEvent(QEvent::Quit));
+        }
+        emit qGuiApp->lastWindowClosed();
+    }
+}
+
+
 /*!
     \property QGuiApplication::layoutDirection
     \brief the default layout direction for this application
index 8338fa1..871e314 100644 (file)
@@ -76,6 +76,8 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication
     Q_PROPERTY(int doubleClickInterval  READ doubleClickInterval WRITE setDoubleClickInterval)
     Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval WRITE setKeyboardInputInterval)
 
+    Q_PROPERTY(bool quitOnLastWindowClosed  READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed)
+
 public:
     QGuiApplication(int &argc, char **argv, int = ApplicationFlags);
     virtual ~QGuiApplication();
@@ -123,12 +125,16 @@ public:
 
     static QPlatformNativeInterface *platformNativeInterface();
 
+    static void setQuitOnLastWindowClosed(bool quit);
+    static bool quitOnLastWindowClosed();
+
     static int exec();
     bool notify(QObject *, QEvent *);
 
 Q_SIGNALS:
     void fontDatabaseChanged();
     void screenAdded(QScreen *screen);
+    void lastWindowClosed();
 
 protected:
     bool event(QEvent *);
index fc6da6f..f7fa512 100644 (file)
@@ -142,6 +142,8 @@ public:
         return alignment;
     }
 
+    static void emitLastWindowClosed();
+
     QPixmap getPixmapCursor(Qt::CursorShape cshape);
 
     static QGuiApplicationPrivate *instance() { return self; }
@@ -170,6 +172,8 @@ public:
     static QList<QScreen *> screen_list;
 
     static QFont *app_font;
+
+    static bool quitOnLastWindowClosed;
 private:
     void init();
 
index 9eb011a..be96beb 100644 (file)
@@ -440,6 +440,7 @@ void QWindow::setWindowIcon(const QImage &icon) const
 void QWindow::destroy()
 {
     Q_D(QWindow);
+    setVisible(false);
     delete d->platformWindow;
     d->platformWindow = 0;
 }
@@ -569,9 +570,13 @@ bool QWindow::event(QEvent *event)
         break;
 #endif
 
-    case QEvent::Close:
+    case QEvent::Close: {
+        Q_D(QWindow);
+        bool wasVisible = visible();
         destroy();
-        break;
+        if (wasVisible);
+            d->maybeQuitOnLastWindowClosed();
+        break; }
 
     case QEvent::Expose:
         exposeEvent(static_cast<QExposeEvent *>(event));
@@ -630,4 +635,27 @@ Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window)
     return window->d_func();
 }
 
+void QWindowPrivate::maybeQuitOnLastWindowClosed()
+{
+    Q_Q(QWindow);
+
+    // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
+    bool quitOnClose = QGuiApplication::quitOnLastWindowClosed() && !q->parent();
+
+    if (quitOnClose) {
+        QWindowList list = QGuiApplication::topLevelWindows();
+        bool lastWindowClosed = true;
+        for (int i = 0; i < list.size(); ++i) {
+            QWindow *w = list.at(i);
+            if (!w->visible() || w->parent())
+                continue;
+            lastWindowClosed = false;
+            break;
+        }
+        if (lastWindowClosed)
+            QGuiApplicationPrivate::emitLastWindowClosed();
+    }
+
+}
+
 QT_END_NAMESPACE
index 2016c42..0a051ae 100644 (file)
@@ -56,6 +56,8 @@ QT_MODULE(Gui)
 
 class Q_GUI_EXPORT QWindowPrivate : public QObjectPrivate
 {
+    Q_DECLARE_PUBLIC(QWindow)
+
 public:
     QWindowPrivate()
         : QObjectPrivate()
@@ -77,6 +79,8 @@ public:
     {
     }
 
+    void maybeQuitOnLastWindowClosed();
+
     QWindow::SurfaceType surfaceType;
     Qt::WindowFlags windowFlags;
     QWindow *parentWindow;