diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2013-08-29 17:18:06 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-17 18:29:51 +0200 |
commit | a6bdcc1bd1818260bd649e0643c7ca7b3cc5ca6b (patch) | |
tree | d9b1fff79febd850abc0f4ab401615d98f16b0df | |
parent | 886b1b1424816a32874ddd6d68b44de63fd6a877 (diff) |
Expose "Qt.application.state".
This deprecates Qt.application.active.
The new property can indicate more states than just active or inactive
(currently Suspended and Hidden exists in addition to the
aforementioned).
Change-Id: I8d5bf72f89a357c13daf1625c20e8e7311dac013
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Alan Alpert <aalpert@blackberry.com>
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 53 | ||||
-rw-r--r-- | src/quick/util/qquickapplication.cpp | 8 | ||||
-rw-r--r-- | src/quick/util/qquickapplication_p.h | 5 | ||||
-rw-r--r-- | tests/auto/quick/qquickapplication/tst_qquickapplication.cpp | 66 |
4 files changed, 123 insertions, 9 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 39c3399917..5b39aba65e 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -411,14 +411,50 @@ The following functions are also on the Qt object. \row \li \c application.active \li - This read-only property indicates whether the application is the top-most and focused - application, and the user is able to interact with the application. The property - is false when the application is in the background, the device keylock or screen - saver is active, the screen backlight is turned off, or the global system dialog - is being displayed on top of the application. It can be used for stopping and - pausing animations, timers and active processing of data in order to save device - battery power and free device memory and processor load when the application is not - active. + Deprecated, use Qt.application.state == Qt.ApplicationActive instead. + + \row + \li \c application.state + \li + This read-only property indicates the current state of the application. + + Possible values are: + + \list + \li Qt.ApplicationActive - The application is the top-most and focused application, and the + user is able to interact with the application. + \li Qt.ApplicationInactive - The application is visible or partially visible, but not selected + to be in front, the user cannot interact with the application. + On desktop platforms, this typically means that the user activated + another application. On mobile platforms, it is more common to + enter this state when the OS is interrupting the user with for + example incoming calls, SMS-messages or dialogs. This is usually a + transient state during which the application is paused. The user + may return focus to your application, but most of the time it will + be the first indication that the application is going to be suspended. + While in this state, consider pausing or stopping any activity that + should not continue when the user cannot interact with your + application, such as a video, a game, animations, or sensors. + You should also avoid performing CPU-intensive tasks which might + slow down the application in front. + \li Qt.ApplicationSuspended - The application is suspended and not visible to the user. On + mobile platforms, the application typically enters this state when + the user returns to the home screen or switches to another + application. While in this state, the application should ensure + that the user perceives it as always alive and does not lose his + progress, saving any persistent data. The application should cease + all activities and be prepared for code execution to stop. While + suspended, the application can be killed at any time without + further warnings (for example when low memory forces the OS to purge + suspended applications). + \li Qt.ApplicationHidden - The application is hidden and runs in the background. This is the + normal state for applications that need to do background processing, + like playing music, while the user interacts with other applications. + The application should free up all graphical resources when entering + this state. A Qt Quick application should not usually handle this state + at the QML level. Instead, you should unload the entire UI and reload + the QML files whenever the application becomes active again. + \endlist \row \li \c application.layoutDirection @@ -469,6 +505,7 @@ The following functions are also on the Qt object. Note that when using QML without a QGuiApplication, the following properties will be undefined: \list \li application.active + \li application.state \li application.layoutDirection \endlist */ diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp index 2de28a9509..244e13888c 100644 --- a/src/quick/util/qquickapplication.cpp +++ b/src/quick/util/qquickapplication.cpp @@ -75,6 +75,9 @@ QQuickApplication::QQuickApplication(QObject *parent) { if (qApp) { qApp->installEventFilter(this); + + connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), + this, SIGNAL(stateChanged(Qt::ApplicationState))); } } @@ -99,6 +102,11 @@ bool QQuickApplication::supportsMultipleWindows() const return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows); } +Qt::ApplicationState QQuickApplication::state() const +{ + return QGuiApplication::applicationState(); +} + bool QQuickApplication::eventFilter(QObject *, QEvent *event) { Q_D(QQuickApplication); diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h index cccc024282..780fb1ffa6 100644 --- a/src/quick/util/qquickapplication_p.h +++ b/src/quick/util/qquickapplication_p.h @@ -54,9 +54,10 @@ class QQuickApplicationPrivate; class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication { Q_OBJECT - Q_PROPERTY(bool active READ active NOTIFY activeChanged) + Q_PROPERTY(bool active READ active NOTIFY activeChanged) // deprecated, use 'state' instead Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(bool supportsMultipleWindows READ supportsMultipleWindows CONSTANT) + Q_PROPERTY(Qt::ApplicationState state READ state NOTIFY stateChanged) public: explicit QQuickApplication(QObject *parent = 0); @@ -64,10 +65,12 @@ public: bool active() const; Qt::LayoutDirection layoutDirection() const; bool supportsMultipleWindows() const; + Qt::ApplicationState state() const; Q_SIGNALS: void activeChanged(); void layoutDirectionChanged(); + void stateChanged(Qt::ApplicationState state); private: bool eventFilter(QObject *, QEvent *event); diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp index b8986fbf85..ef27445920 100644 --- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp +++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp @@ -46,6 +46,8 @@ #include <QtQuick/qquickview.h> #include <QtGui/qinputmethod.h> #include <qpa/qwindowsysteminterface.h> +#include <qpa/qplatformintegration.h> +#include <private/qguiapplication_p.h> class tst_qquickapplication : public QObject { @@ -55,6 +57,7 @@ public: private slots: void active(); + void state(); void layoutDirection(); void inputMethod(); @@ -103,6 +106,69 @@ void tst_qquickapplication::active() QVERIFY(!item->property("active2").toBool()); } +void tst_qquickapplication::state() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0; " + "Item { " + " property int state: Qt.application.state; " + " property int state2: Qt.ApplicationInactive; " + " Connections { " + " target: Qt.application; " + " onStateChanged: state2 = Qt.application.state; " + " } " + "}", QUrl::fromLocalFile("")); + QQuickItem *item = qobject_cast<QQuickItem *>(component.create()); + QVERIFY(item); + QQuickWindow window; + item->setParentItem(window.contentItem()); + + // initial state should be ApplicationInactive + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive); + + // If the platform plugin has the ApplicationState capability, state changes originate from it + // as a result of a system event. We therefore have to simulate these events here. + if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState)) { + + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + QTest::waitForEvents(); + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive); + + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + QTest::waitForEvents(); + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive); + + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended); + QTest::waitForEvents(); + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationSuspended); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationSuspended); + + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden); + QTest::waitForEvents(); + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationHidden); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationHidden); + + } else { + // Otherwise, the application can only be in two states, Active and Inactive. These are + // triggered by window activation. + window.show(); + window.requestActivate(); + QTest::qWaitForWindowActive(&window); + QVERIFY(QGuiApplication::focusWindow() == &window); + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationActive); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationActive); + + // not active again + QWindowSystemInterface::handleWindowActivated(0); + QTRY_VERIFY(QGuiApplication::focusWindow() != &window); + QCOMPARE(Qt::ApplicationState(item->property("state").toInt()), Qt::ApplicationInactive); + QCOMPARE(Qt::ApplicationState(item->property("state2").toInt()), Qt::ApplicationInactive); + } +} + void tst_qquickapplication::layoutDirection() { |