diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2012-02-11 01:33:55 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-16 01:56:27 +0100 |
commit | 66603985f2de74ac5f3bd5d259f0e65f710f62d7 (patch) | |
tree | 65049a5d31f1e8a978f60f5fc12d1dd26be73284 /tests/auto | |
parent | 90feedb6429df225b81bc279093ae1ca1278b391 (diff) |
Fix ref counted window close handling.
Instead of refcounting QWindow visibility, we ask the Application
subclass whether quitting is appropriate.
Task-Id: QTBUG-24120
Change-Id: Idd19cc1a3e5742fddded89c7638aaaa5e47c568d
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp | 513 |
1 files changed, 14 insertions, 499 deletions
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index c600956912..fcb6b93e99 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -137,16 +137,7 @@ private slots: void touchEventPropagation(); void qtbug_12673(); - - void testQuitLockRef(); - void testQuitLock1(); - void testQuitLock2(); - void testQuitLock3(); - void testQuitLock4(); - void testQuitLock5(); - void testQuitLock6(); - void testQuitLock7(); - void testQuitLock8(); + void noQuitOnHide(); void globalStaticObjectDestruction(); // run this last @@ -2060,506 +2051,30 @@ void tst_QApplication::qtbug_12673() QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit); } -class JobObject : public QObject -{ - Q_OBJECT -public: - JobObject(int milliseconds, QObject *parent = 0) - : QObject(parent) - { - QTimer::singleShot(milliseconds, this, SLOT(timeout())); - } - - JobObject(QObject *parent = 0) - : QObject(parent) - { - QTimer::singleShot(1000, this, SLOT(timeout())); - } - -private slots: - void timeout() - { - emit done(); - deleteLater(); - } - -signals: - void done(); - -private: - QEventLoopLocker locker; -}; - -class QuitLockRefTester : public QObject -{ - Q_OBJECT -public: - QuitLockRefTester(QObject *parent = 0) - : QObject(parent) - { - QTimer::singleShot(0, this, SLOT(doTest())); - } - -private slots: - void doTest() - { - QApplicationPrivate *privateClass = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp)); - - { - QDialog *win1 = new QDialog; - - // Test with a lock active so that the refcount doesn't drop to zero during these tests, causing a quit. - // (until we exit the scope) - QEventLoopLocker locker; - - QCOMPARE(privateClass->quitLockRef.load(), 1); - - win1->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QDialog *win2 = new QDialog; - - win2->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 3); - - delete win1; - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - delete win2; - - QCOMPARE(privateClass->quitLockRef.load(), 1); - - win1 = new QDialog; - - win1->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - JobObject *job1 = new JobObject(this); - - QCOMPARE(privateClass->quitLockRef.load(), 3); - - delete win1; - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - delete job1; - - QCOMPARE(privateClass->quitLockRef.load(), 1); - - QWidget *w1 = new QWidget; - - w1->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QWidget *w2 = new QMainWindow; - - w2->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 3); - - QWidget *w3 = new QWidget(0, Qt::Dialog); - - w3->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 4); - - delete w3; - - QCOMPARE(privateClass->quitLockRef.load(), 3); - - delete w2; - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QWidget *subWidget1 = new QWidget(w1, Qt::Window); - - // Even though We create a new widget and show it, - // the ref count does not go up because it is a child of - // w1, which is the top-level, and what we are actually - // refcounting. - subWidget1->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - // When we use setParent(0) and re-show, the - // ref count does increase: - QCOMPARE(subWidget1->isVisible(), true); - subWidget1->setParent(0); - QCOMPARE(subWidget1->isVisible(), false); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - subWidget1->show(); - QCOMPARE(subWidget1->isVisible(), true); - QCOMPARE(privateClass->quitLockRef.load(), 3); - - subWidget1->setParent(w1); - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QWidget *subWidget2 = new QWidget(w1); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - subWidget2->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - delete subWidget2; - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QWidget *subWidget3 = new QWidget(w1); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - subWidget3->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - subWidget3->hide(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - delete subWidget3; - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QWidget *subWidget4 = new QWidget(subWidget1); - QWidget *subWidget5 = new QWidget(subWidget1); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - QWidget *subWidget6 = new QWidget(subWidget4, Qt::Window); - - subWidget6->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - delete w1; - - QCOMPARE(privateClass->quitLockRef.load(), 1); - - w1 = new QWidget; - w2 = new QWidget; - w3 = new QWidget; - - QHBoxLayout *layout = new QHBoxLayout(w1); - - layout->addWidget(w2); - layout->addWidget(w3); - - QCOMPARE(privateClass->quitLockRef.load(), 1); - - w1->show(); - - QCOMPARE(privateClass->quitLockRef.load(), 2); - - w1->hide(); - QCOMPARE(privateClass->quitLockRef.load(), 1); - - delete w1; - - } - QCOMPARE(privateClass->quitLockRef.load(), 0); - } -}; - -void tst_QApplication::testQuitLockRef() -{ - int argc = 1; - char *argv[] = { "tst_qapplication" }; - QApplication app(argc, argv); - - QuitLockRefTester tester; - - app.exec(); -} - -void tst_QApplication::testQuitLock1() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - QWidget *w = new QWidget; - - w->show(); - - QMetaObject::invokeMethod(w, "close", Qt::QueuedConnection); - - app.exec(); - - // No hang = pass. -} - -void tst_QApplication::testQuitLock2() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - QWidget *w1 = new QWidget; - - w1->show(); - - QWidget *w2 = new QWidget; - - w2->show(); - - QMetaObject::invokeMethod(w1, "deleteLater", Qt::QueuedConnection); - QMetaObject::invokeMethod(w2, "hide", Qt::QueuedConnection); - - app.exec(); - - // No hang = pass. -} - -class Result : public QObject +class NoQuitOnHideWidget : public QWidget { Q_OBJECT public: - Result(QObject *parent = 0) - : QObject(parent), m_passes(false) + NoQuitOnHideWidget(QWidget *parent = 0) + : QWidget(parent) { - - } - - bool result() const - { - return m_passes; - } - -public slots: - - void setPasses() - { - setResult(true); - } - - void setFails() - { - setResult(false); - } - - void setResult(bool result) - { - m_passes = result; - } - -private: - bool m_passes; -}; - -void tst_QApplication::testQuitLock3() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - Result *result = new Result(&app); - - JobObject *job = new JobObject(&app); - - QObject::connect(job, SIGNAL(done()), result, SLOT(setPasses())); - - app.exec(); - - QVERIFY(result->result()); -} - -void tst_QApplication::testQuitLock4() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - QWidget *w = new QWidget; - - w->show(); - - Result *result = new Result(&app); - JobObject *job = new JobObject(1000, &app); - - QTimer::singleShot(500, w, SLOT(deleteLater())); - - QObject::connect(w, SIGNAL(destroyed()), result, SLOT(setFails())); - QObject::connect(job, SIGNAL(done()), result, SLOT(setPasses())); - - app.exec(); - - QVERIFY(result->result()); -} - -class JobBeforeWindowRunner : public QObject -{ - Q_OBJECT -public: - JobBeforeWindowRunner(QObject *parent = 0) - : QObject(parent), m_result(new Result(this)) - { - - } - - void start() - { - JobObject *job = new JobObject(this); - connect(job, SIGNAL(done()), m_result, SLOT(setFails())); - connect(job, SIGNAL(destroyed()), SLOT(showWindowDelayed()), Qt::QueuedConnection); + QTimer::singleShot(0, this, SLOT(hide())); + QTimer::singleShot(500, this, SLOT(exitApp())); } - bool result() const { return m_result->result(); } - private slots: - void showWindowDelayed() - { - qApp->setQuitLockEnabled(true); - QTimer::singleShot(500, this, SLOT(showWindow())); - } - - void showWindow() - { - QWidget *w = new QWidget; - w->show(); - w->deleteLater(); - connect(w, SIGNAL(destroyed()), m_result, SLOT(setPasses())); - } - -private: - Result * const m_result; -}; - -void tst_QApplication::testQuitLock5() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - app.setQuitLockEnabled(false); - // Run a job before showing a window, and only enable the refcounting - // after doing so. - // Although the job brings the refcount to zero, the app does not exit - // until setQuitLockEnabled is called and the feature re-enabled. - - JobBeforeWindowRunner *eventRunner = new JobBeforeWindowRunner(&app); - - eventRunner->start(); - - app.exec(); - - QVERIFY(eventRunner->result()); -} - -class JobDuringWindowRunner : public QObject -{ - Q_OBJECT -public: - JobDuringWindowRunner(QObject *parent = 0) - : QObject(parent), m_result(new Result(this)) - { - - } - - void start() - { - JobObject *job = new JobObject(this); - - QWidget *w = new QWidget; - w->show(); - w->deleteLater(); - - QObject::connect(w, SIGNAL(destroyed()), m_result, SLOT(setFails())); - QObject::connect(job, SIGNAL(done()), m_result, SLOT(setPasses())); - } - - bool result() const { return m_result->result(); } - -private: - Result * const m_result; -}; - -void tst_QApplication::testQuitLock6() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - // A job runs, and while it is running, a window is shown and closed, - // then the job ends, which causes the quit. - - JobDuringWindowRunner *eventRunner = new JobDuringWindowRunner(&app); - - eventRunner->start(); - - app.exec(); - - QVERIFY(eventRunner->result()); -} -class JobWindowJobWindowRunner : public QObject -{ - Q_OBJECT -public: - JobWindowJobWindowRunner(QObject *parent = 0) - : QObject(parent), m_result(new Result(this)) - { - - } - - void start() - { - JobObject *job = new JobObject(500, this); - - QWidget *w = new QWidget; - w->show(); - QTimer::singleShot(1000, w, SLOT(deleteLater())); - - QObject::connect(w, SIGNAL(destroyed()), m_result, SLOT(setPasses())); - QObject::connect(job, SIGNAL(done()), m_result, SLOT(setFails())); + void exitApp() { + qApp->exit(1); } - - bool result() const { return m_result->result(); } -private: - Result * const m_result; }; -void tst_QApplication::testQuitLock7() +void tst_QApplication::noQuitOnHide() { - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - // A job runs, and while it is running, a window is shown - // then the job ends, then the window is closed, which causes the quit. - - JobWindowJobWindowRunner *eventRunner = new JobWindowJobWindowRunner(&app); - - eventRunner->start(); - - app.exec(); - - QVERIFY(eventRunner->result()); -} - -void tst_QApplication::testQuitLock8() -{ - int argc = 1; - char *argv[] = { "tst_qcoreapplication" }; - QApplication app(argc, argv); - - QMainWindow *mw1 = new QMainWindow; - mw1->show(); - QMainWindow *mw2 = new QMainWindow; - mw2->show(); - - QMetaObject::invokeMethod(mw1, "close", Qt::QueuedConnection); - QMetaObject::invokeMethod(mw2, "close", Qt::QueuedConnection); - - app.exec(); - - // No hang = pass + int argc = 0; + QApplication app(argc, 0); + QWidget *window1 = new NoQuitOnHideWidget(false); + window1->show(); + QCOMPARE(app.exec(), 1); } class ShowCloseShowWidget : public QWidget |