diff options
Diffstat (limited to 'src/corelib/kernel')
-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 |
6 files changed, 239 insertions, 12 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 |