diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 36 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.h | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qeventloop.cpp | 105 | ||||
-rw-r--r-- | src/corelib/kernel/qeventloop.h | 17 | ||||
-rw-r--r-- | src/corelib/kernel/qeventloop_p.h | 83 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 11 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 20 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 20 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_p.h | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 19 |
12 files changed, 267 insertions, 58 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index ae30167a42..a248e18a6a 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -271,6 +271,8 @@ struct QCoreApplicationData { Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata) +static bool quitLockRefEnabled = true; + QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags) : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0), in_exec(false), aboutToQuitEmitted(false), threadData_clean(false) @@ -649,6 +651,29 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute) return QCoreApplicationPrivate::testAttribute(attribute); } +/*!/ + Returns true if the use of the QEventLoopLocker feature can cause the + application to quit, otherwise returns false. + + \sa QEventLoopLocker + */ +bool QCoreApplication::isQuitLockEnabled() +{ + return quitLockRefEnabled; +} + +/*! + Enables the ability of the QEventLoopLocker feature to quit + the application. + + If disabled, the use of QEventLoopLocker will not quit the application. + + \sa QEventLoopLocker + */ +void QCoreApplication::setQuitLockEnabled(bool enabled) +{ + quitLockRefEnabled = enabled; +} /*! \internal @@ -1476,6 +1501,17 @@ bool QCoreApplication::event(QEvent *e) \sa QObject::tr(), QObject::trUtf8(), QString::fromUtf8() */ +void QCoreApplicationPrivate::ref() +{ + quitLockRef.ref(); +} + +void QCoreApplicationPrivate::deref() +{ + if (!quitLockRef.deref() && in_exec && quitLockRefEnabled) + QCoreApplication::postEvent(qApp, new QEvent(QEvent::Quit)); +} + /*! Tells the application to exit with return code 0 (success). Equivalent to calling QCoreApplication::exit(0). diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 45583a67fa..d1fba3b63c 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -71,6 +71,7 @@ class Q_CORE_EXPORT QCoreApplication : public QObject Q_PROPERTY(QString applicationVersion READ applicationVersion WRITE setApplicationVersion) Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName) Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain) + Q_PROPERTY(bool quitLockEnabled READ isQuitLockEnabled WRITE setQuitLockEnabled) Q_DECLARE_PRIVATE(QCoreApplication) public: @@ -160,6 +161,9 @@ public: EventFilter setEventFilter(EventFilter filter); bool filterEvent(void *message, long *result); + static bool isQuitLockEnabled(); + static void setQuitLockEnabled(bool enabled); + public Q_SLOTS: static void quit(); @@ -183,7 +187,7 @@ private: void init(); static QCoreApplication *self; - + Q_DISABLE_COPY(QCoreApplication) friend class QEventDispatcherUNIXPrivate; diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index b5b6c0d5f2..861a046f16 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -89,6 +89,10 @@ public: static QString macMenuBarName(); #endif + QAtomicInt quitLockRef; + void ref(); + void deref(); + static QThread *theMainThread; static QThread *mainThread(); static bool checkInstance(const char *method); diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 0c1b8c77ff..8b0ec85679 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -43,24 +43,15 @@ #include "qabstracteventdispatcher.h" #include "qcoreapplication.h" +#include "qcoreapplication_p.h" #include "qelapsedtimer.h" #include "qobject_p.h" +#include "qeventloop_p.h" #include <private/qthread_p.h> QT_BEGIN_NAMESPACE -class QEventLoopPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QEventLoop) -public: - inline QEventLoopPrivate() - : exit(true), inExec(false), returnCode(-1) - { } - bool exit, inExec; - int returnCode; -}; - /*! \class QEventLoop \brief The QEventLoop class provides a means of entering and leaving an event loop. @@ -305,6 +296,17 @@ void QEventLoop::wakeUp() d->threadData->eventDispatcher->wakeUp(); } + +bool QEventLoop::event(QEvent *event) +{ + if (event->type() == QEvent::Quit) { + quit(); + return true; + } else { + return QObject::event(event); + } +} + /*! Tells the event loop to exit normally. @@ -315,4 +317,85 @@ void QEventLoop::wakeUp() void QEventLoop::quit() { exit(0); } + +class QEventLoopLockerPrivate +{ +public: + explicit QEventLoopLockerPrivate(QEventLoopPrivate *loop) + : loop(loop), app(0) + { + loop->ref(); + } + + explicit QEventLoopLockerPrivate(QCoreApplicationPrivate *app) + : loop(0), app(app) + { + app->ref(); + } + + ~QEventLoopLockerPrivate() + { + if (loop) + loop->deref(); + else + app->deref(); + } + +private: + QEventLoopPrivate *loop; + QCoreApplicationPrivate *app; +}; + +/*! + \class QEventLoopLocker + \brief The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed. + + The QEventLoopLocker operates on particular objects - either a QCoreApplication + instance or a QEventLoop instance. + + This makes it possible to, for example, run a batch of jobs with an event loop + and exit that event loop after the last job is finished. That is accomplished + by keeping a QEventLoopLocker with each job instance. + + The variant which operates on QCoreApplication makes it possible to finish + asynchronously running jobs after the last gui window has been closed. This + can be useful for example for running a job which uploads data to a network. + + \sa QEventLoop, QCoreApplication +*/ + +/*! + Creates an event locker operating on the \p app. + + The application will quit when there are no more QEventLoopLockers operating on it. + + \sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled() + */ +QEventLoopLocker::QEventLoopLocker() + : d_ptr(new QEventLoopLockerPrivate(static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance())))) +{ + +} + +/*! + Creates an event locker operating on the \p app. + + This particular QEventLoop will quit when there are no more QEventLoopLockers operating on it. + + \sa QEventLoop::quit() + */ +QEventLoopLocker::QEventLoopLocker(QEventLoop *loop) + : d_ptr(new QEventLoopLockerPrivate(static_cast<QEventLoopPrivate*>(QObjectPrivate::get(loop)))) +{ + +} + +/*! + Destroys this event loop locker object + */ +QEventLoopLocker::~QEventLoopLocker() +{ + delete d_ptr; +} + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventloop.h b/src/corelib/kernel/qeventloop.h index 3f5cce222f..0e7195d6a7 100644 --- a/src/corelib/kernel/qeventloop.h +++ b/src/corelib/kernel/qeventloop.h @@ -80,12 +80,29 @@ public: void wakeUp(); + bool event(QEvent *event); + public Q_SLOTS: void quit(); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QEventLoop::ProcessEventsFlags) + +class QEventLoopLockerPrivate; + +class Q_CORE_EXPORT QEventLoopLocker +{ +public: + QEventLoopLocker(); + explicit QEventLoopLocker(QEventLoop *loop); + ~QEventLoopLocker(); + +private: + Q_DISABLE_COPY(QEventLoopLocker) + QEventLoopLockerPrivate *d_ptr; +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/kernel/qeventloop_p.h b/src/corelib/kernel/qeventloop_p.h new file mode 100644 index 0000000000..5770ed0076 --- /dev/null +++ b/src/corelib/kernel/qeventloop_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEVENTLOOP_P_H +#define QEVENTLOOP_P_H + +#include "qobject_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QEventLoopPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QEventLoop) +public: + inline QEventLoopPrivate() + : exit(true), inExec(false), returnCode(-1) + { } + + QAtomicInt quitLockRef; + + bool exit, inExec; + int returnCode; + + void ref() + { + quitLockRef.ref(); + } + + void deref() + { + if (!quitLockRef.deref() && inExec) { + qApp->postEvent(q_ptr, new QEvent(QEvent::Quit)); + } + } +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QEVENTLOOP_P_H diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index ea562c75b8..9f7bc24119 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -107,8 +107,6 @@ 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; @@ -1388,14 +1386,14 @@ void QGuiApplicationPrivate::notifyActiveWindowChange(QWindow *) void QGuiApplication::setQuitOnLastWindowClosed(bool quit) { - QGuiApplicationPrivate::quitOnLastWindowClosed = quit; + QCoreApplication::setQuitLockEnabled(quit); } bool QGuiApplication::quitOnLastWindowClosed() { - return QGuiApplicationPrivate::quitOnLastWindowClosed; + return QCoreApplication::isQuitLockEnabled(); } @@ -1403,11 +1401,6 @@ bool QGuiApplication::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(); } } diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 6d3e650c32..2f1cfa509d 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -183,8 +183,6 @@ public: QStyleHints *styleHints; QInputPanel *inputPanel; - static bool quitOnLastWindowClosed; - static QList<QObject *> generic_plugin_list; #ifndef QT_NO_SHORTCUT QShortcutMap shortcutMap; diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index e85d8379fa..4436884359 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -165,6 +165,14 @@ void QWindow::setVisible(bool visible) return; d->visible = visible; emit visibleChanged(visible); + if (QCoreApplication::instance() && !transientParent()) { + QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance())); + if (visible) { + applicationPrivate->ref(); + } else { + applicationPrivate->deref(); + } + } if (!d->platformWindow) create(); @@ -499,7 +507,19 @@ void QWindow::setWindowState(Qt::WindowState state) void QWindow::setTransientParent(QWindow *parent) { Q_D(QWindow); + + QWindow *previousParent = d->transientParent; + d->transientParent = parent; + + if (QCoreApplication::instance() && d->visible) { + QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance())); + if (parent && !previousParent) { + applicationPrivate->deref(); + } else if (!parent && previousParent) { + applicationPrivate->ref(); + } + } } QWindow *QWindow::transientParent() const diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index f4d2856dbe..b0781c2064 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -143,8 +143,6 @@ QApplicationPrivate *QApplicationPrivate::self = 0; QInputContext *QApplicationPrivate::inputContext = 0; -bool QApplicationPrivate::quitOnLastWindowClosed = true; - #ifdef Q_WS_WINCE int QApplicationPrivate::autoMaximizeThreshold = -1; bool QApplicationPrivate::autoSipEnabled = false; @@ -161,8 +159,6 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T is_session_restored = false; #endif - quitOnLastWindowClosed = true; - #if defined(Q_WS_QWS) && !defined(QT_NO_DIRECTPAINTER) directPainters = 0; #endif @@ -4621,24 +4617,12 @@ bool QApplicationPrivate::inPopupMode() const void QApplication::setQuitOnLastWindowClosed(bool quit) { - QApplicationPrivate::quitOnLastWindowClosed = quit; + QCoreApplication::setQuitLockEnabled(quit); } bool QApplication::quitOnLastWindowClosed() { - return QApplicationPrivate::quitOnLastWindowClosed; -} - -void QApplicationPrivate::emitLastWindowClosed() -{ - if (qApp && qApp->d_func()->in_exec) { - if (QApplicationPrivate::quitOnLastWindowClosed) { - // get ready to quit, this event might be removed if the - // event loop is re-entered, however - QApplication::postEvent(qApp, new QEvent(QEvent::Quit)); - } - emit qApp->lastWindowClosed(); - } + return QCoreApplication::isQuitLockEnabled(); } /*! \variable QApplication::NormalColors diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index eccc1b8442..b6fbfa1684 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -188,8 +188,6 @@ public: static bool qws_apply_settings(); static QWidget *findWidget(const QObjectList&, const QPoint &, bool rec); #endif - static bool quitOnLastWindowClosed; - static void emitLastWindowClosed(); #ifdef Q_WS_WINCE static int autoMaximizeThreshold; #endif diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index a8f3808dce..e004e15252 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -92,6 +92,7 @@ #include <private/qpaintengine_raster_p.h> #include "qwidget_p.h" +#include <QtGui/private/qwindow_p.h> #include "qaction_p.h" #include "qlayout_p.h" #include "QtWidgets/qgraphicsproxywidget.h" @@ -7434,23 +7435,11 @@ bool QWidgetPrivate::close_helper(CloseMode mode) // Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible()); - if (quitOnClose) { - /* if there is no non-withdrawn primary window left (except - the ones without QuitOnClose), we emit the lastWindowClosed - signal */ - QWidgetList list = QApplication::topLevelWidgets(); - bool lastWindowClosed = true; - for (int i = 0; i < list.size(); ++i) { - QWidget *w = list.at(i); - if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose)) - continue; - lastWindowClosed = false; - break; - } - if (lastWindowClosed) - QApplicationPrivate::emitLastWindowClosed(); + if (quitOnClose && q->windowHandle()) { + static_cast<QWindowPrivate*>(QObjectPrivate::get(q->windowHandle()))->maybeQuitOnLastWindowClosed(); } + if (!that.isNull()) { data.is_closing = 0; if (q->testAttribute(Qt::WA_DeleteOnClose)) { |