aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2013-08-29 17:18:06 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-17 18:29:51 +0200
commita6bdcc1bd1818260bd649e0643c7ca7b3cc5ca6b (patch)
treed9b1fff79febd850abc0f4ab401615d98f16b0df
parent886b1b1424816a32874ddd6d68b44de63fd6a877 (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.cpp53
-rw-r--r--src/quick/util/qquickapplication.cpp8
-rw-r--r--src/quick/util/qquickapplication_p.h5
-rw-r--r--tests/auto/quick/qquickapplication/tst_qquickapplication.cpp66
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()
{