Only quit if there are no visible widgets or windows.
authorStephen Kelly <stephen.kelly@kdab.com>
Mon, 14 May 2012 14:58:26 +0000 (16:58 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 12 Jun 2012 02:30:18 +0000 (04:30 +0200)
We need to let the QGuiApplication determine whether quitting is appropriate
based on whether there are visible top level QWindows after the last top-level
QWidget was closed.

This solves the issue raised here: http://thread.gmane.org/gmane.comp.lib.qt.user/1880

The transientParent is the QWindow equivalent of parentWidget on QWidget, so the test
in QGuiApplication::shouldQuit is similar to the one in QApplication::shouldQuit.

Change-Id: I500eff8d5887f24415180134b3a4be3c630a896f
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
src/gui/kernel/qguiapplication.cpp
src/gui/kernel/qwindow.cpp
src/widgets/kernel/qapplication.cpp
tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp

index 3e999be..846b7d0 100644 (file)
@@ -2129,7 +2129,7 @@ bool QGuiApplicationPrivate::shouldQuit()
     QWindowList list = QGuiApplication::topLevelWindows();
     for (int i = 0; i < list.size(); ++i) {
         QWindow *w = list.at(i);
-        if (w->isVisible())
+        if (w->isVisible() && !w->transientParent())
             return false;
     }
     return true;
index 8fe62bb..f30a794 100644 (file)
@@ -1708,7 +1708,7 @@ void QWindowPrivate::maybeQuitOnLastWindowClosed()
         bool lastWindowClosed = true;
         for (int i = 0; i < list.size(); ++i) {
             QWindow *w = list.at(i);
-            if (!w->isVisible())
+            if (!w->isVisible() || w->transientParent())
                 continue;
             lastWindowClosed = false;
             break;
index e9003e8..0553dab 100644 (file)
@@ -2950,7 +2950,7 @@ bool QApplicationPrivate::shouldQuit()
         if (w->isVisible() && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose))
             return false;
     }
-    return true;
+    return QGuiApplicationPrivate::shouldQuit();
 }
 
 /*! \reimp
index 578ea9f..372dd65 100644 (file)
@@ -57,6 +57,7 @@ private slots:
     void changeFocusWindow();
     void keyboardModifiers();
     void modalWindow();
+    void quitOnLastWindowClosed();
 };
 
 class DummyWindow : public QWindow
@@ -491,5 +492,67 @@ void tst_QGuiApplication::modalWindow()
     delete window1;
 }
 
+void tst_QGuiApplication::quitOnLastWindowClosed()
+{
+    {
+        int argc = 0;
+        QGuiApplication app(argc, 0);
+
+        QTimer timer;
+        timer.setInterval(100);
+
+        QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
+        QSignalSpy spy2(&timer, SIGNAL(timeout()));
+
+        QPointer<QWindow> mainWindow = new QWindow;
+        QPointer<QWindow> dialog = new QWindow;
+
+        dialog->setTransientParent(mainWindow);
+
+        QVERIFY(app.quitOnLastWindowClosed());
+
+        mainWindow->show();
+        dialog->show();
+
+        timer.start();
+        QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
+        QTimer::singleShot(2000, &app, SLOT(quit()));        // This makes sure we quit even if it didn't
+
+        app.exec();
+
+        QCOMPARE(spy.count(), 1);
+        QVERIFY(spy2.count() < 15);      // Should be around 10 if closing caused the quit
+    }
+    {
+        int argc = 0;
+        QGuiApplication app(argc, 0);
+
+        QTimer timer;
+        timer.setInterval(100);
+
+        QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
+        QSignalSpy spy2(&timer, SIGNAL(timeout()));
+
+        QPointer<QWindow> mainWindow = new QWindow;
+        QPointer<QWindow> dialog = new QWindow;
+
+        QVERIFY(!dialog->transientParent());
+        QVERIFY(app.quitOnLastWindowClosed());
+
+        mainWindow->show();
+        dialog->show();
+
+        timer.start();
+        QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should not quit the application
+        QTimer::singleShot(2000, &app, SLOT(quit()));
+
+        app.exec();
+
+        QCOMPARE(spy.count(), 1);
+        QVERIFY(spy2.count() > 15);      // Should be around 20 if closing did not cause the quit
+    }
+}
+
+
 QTEST_APPLESS_MAIN(tst_QGuiApplication)
 #include "tst_qguiapplication.moc"
index 000eea8..120ed91 100644 (file)
@@ -718,6 +718,30 @@ void tst_QApplication::quitOnLastWindowClosed()
         QCOMPARE(timerSpy.count(), 1);
         QCOMPARE(appSpy.count(), 2);
     }
+    {
+        int argc = 0;
+        QApplication app(argc, 0, QApplication::GuiServer);
+        QVERIFY(app.quitOnLastWindowClosed());
+
+        QTimer timer;
+        timer.setInterval(100);
+        QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
+
+        QWindow w;
+        w.show();
+
+        QWidget wid;
+        wid.show();
+
+        timer.start();
+        QTimer::singleShot(1000, &wid, SLOT(close())); // This should NOT quit the application because the
+                                                       // QWindow is still there.
+        QTimer::singleShot(2000, &app, SLOT(quit()));  // This causes the quit.
+
+        app.exec();
+
+        QVERIFY(timerSpy.count() > 15);      // Should be around 20 if closing did not caused the quit
+    }
 }
 
 class PromptOnCloseWidget : public QWidget