on xenial help sign in
Merge lp:unity8
commit92b7b91f22751434b909b1e6f01e9e882625bbf0 authorAlbert Astals <albert.astals@canonical.com> dateMon 12 Jan 2015, 09:31 (12 years ago) parent0042e2d513e2af
100 files changed+2010−728
cmake/modules/QmlTest.cmake+3 debian/changelog+46 debian/control+7−5 plugins/LightDM/CMakeLists.txt+1−1 plugins/LightDM/UsersModel.cpp+1−1 plugins/LightDM/UsersModel.h+2−2 plugins/Lights/Lights.cpp+9−24 plugins/Unity/Indicators/CMakeLists.txt+3−1 plugins/Unity/Indicators/Indicators.qmltypes+18−7 plugins/Unity/Indicators/actionrootstate.cpp+97 plugins/Unity/Indicators/actionrootstate.h+55 plugins/Unity/Indicators/modelactionrootstate.cpp+127 plugins/Unity/Indicators/modelactionrootstate.h+61 plugins/Unity/Indicators/plugin.cpp+4−2 plugins/Unity/Indicators/rootactionstate.cpp → plugins/Unity/Indicators/rootstateparser.cpp+74−141 plugins/Unity/Indicators/rootactionstate.h → plugins/Unity/Indicators/rootstateparser.h+18−34 plugins/Utils/CMakeLists.txt+1−1 plugins/Utils/plugin.cpp+2−2 plugins/Utils/qsortfilterproxymodelqml.cpp → plugins/Utils/unitysortfilterproxymodelqml.cpp+15−15 plugins/Utils/qsortfilterproxymodelqml.h → plugins/Utils/unitysortfilterproxymodelqml.h+5−5 po/fa.po+96−88 po/ro.po+101−90 qml/Dash/Dash.qml+4−10 qml/Dash/DashContent.qml+2−2 qml/Dash/DashNavigation.qml+4 qml/Dash/DashNavigationButton.qml+2 qml/Dash/GenericScopeView.qml+3−3 qml/Dash/ScopesList.qml+1 qml/Greeter/Clock.qml+1−1 qml/Greeter/Infographics.qml+9−7 qml/Notifications/Notifications.qml+1−1 qml/Panel/IndicatorItem.qml−8 qml/Panel/Indicators/IndicatorBase.qml+1−1 qml/Panel/Indicators/IndicatorsLight.qml+19−1 qml/Panel/Indicators/VisibleIndicators.qml+2−2 qml/Panel/IndicatorsMenu.qml+5 qml/Shell.qml+21−3 src/main.cpp−6 tests/autopilot/unity8/shell/emulators/create_interactive_notification.py−1 tests/autopilot/unity8/shell/emulators/edges_demo.py+140 tests/autopilot/unity8/shell/fixture_setup.py+38 tests/autopilot/unity8/shell/tests/test_edges_demo.py+52 tests/mocks/CMakeLists.txt+1 tests/mocks/LightDM/CMakeLists.txt+1−1 tests/mocks/LightDM/Greeter.cpp+6 tests/mocks/LightDM/Greeter.h+3 tests/mocks/Lights/CMakeLists.txt+8 tests/mocks/Lights/Lights.cpp+84 tests/mocks/Lights/Lights.h+66 tests/mocks/Lights/Lights.qmltypes+45 tests/mocks/Lights/plugin.cpp+33 tests/mocks/Lights/plugin.h+32 tests/mocks/Lights/qmldir+3 tests/mocks/QMenuModel/CMakeLists.txt+1 tests/mocks/QMenuModel/QDBusActionGroup.qml+20−67 tests/mocks/QMenuModel/actiondata.h+52 tests/mocks/QMenuModel/plugin.cpp+10 tests/mocks/Unity/Indicators/ActionRootState.qml+46 tests/mocks/Unity/Indicators/RootActionState.qml → tests/mocks/Unity/Indicators/ModelActionRootState.qml tests/mocks/Unity/Indicators/qmldir+2−1 tests/plugins/LightDM/CMakeLists.txt+4−8 tests/plugins/LightDM/dbus.cpp+11−2 tests/plugins/Unity/Indicators/rootactionstatetest.cpp+4−4 tests/plugins/Utils/CMakeLists.txt+1−1 tests/plugins/Utils/qsortfilterproxymodeltest.cpp → tests/plugins/Utils/unitysortfilterproxymodeltest.cpp+14−14 tests/qmltests/CMakeLists.txt+1 tests/qmltests/Components/tst_Carousel.qml+5−5 tests/qmltests/Components/tst_Lockscreen.qml+1−1 tests/qmltests/Components/tst_ResponsiveVerticalJournal.qml+1−1 tests/qmltests/Dash/Previews/tst_PreviewActions.qml+3−3 tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml+5−5 tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml+2−2 tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml+6−6 tests/qmltests/Dash/Previews/tst_PreviewPayments.qml+5−5 tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qml+1−1 tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qml+2−2 tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml+2−2 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml+2−2 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml+3−3 tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml+2−2 tests/qmltests/Dash/tst_Card.qml+2−2 tests/qmltests/Dash/tst_Dash.qml+42−25 tests/qmltests/Dash/tst_DashContent.qml+48−27 tests/qmltests/Dash/tst_GenericScopeView.qml+26−26 tests/qmltests/Dash/tst_PageHeader.qml+1−1 tests/qmltests/Dash/tst_PreviewListView.qml+2−2 tests/qmltests/Launcher/tst_Launcher.qml+8−8 tests/qmltests/Notifications/tst_Notifications.qml+6−6 tests/qmltests/Notifications/tst_OptionToggle.qml+7−7 tests/qmltests/Notifications/tst_SwipeToAct.qml+1−1 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+2−2 tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qml+129 tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+52−1 tests/qmltests/Panel/tst_IndicatorsBar.qml+1−1 tests/qmltests/Stages/tst_PhoneStage.qml+2 tests/qmltests/Wizard/tst_Wizard.qml+36−12 tests/qmltests/tst_Shell.qml+3−3 tests/qmltests/tst_ShellWithPin.qml+31 tests/qmltests/tst_TabletShell.qml+1−1 tests/utils/modules/Unity/Test/UnityTestCase.qml+71
cmake/modules/QmlTest.cmake+3
@@ -153,7 +153,9 @@ endmacro(add_qml_test_internal)
153153
154154macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS ENVVAR)
155155 set(testCommand
156+ ${ENVVAR}
156157 LD_LIBRARY_PATH=${LD_PATH}
158+ dbus-launch
157159 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
158160 -o ${CMAKE_BINARY_DIR}/test${CLASS_NAME}.xml,xunitxml
159161 -o -,txt)
@@ -171,6 +173,7 @@ macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS ENVVAR)
171173 ${ENVVAR}
172174 LD_LIBRARY_PATH=${LD_PATH}
173175 xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum
176+ dbus-launch
174177 ${CMAKE_CURRENT_BINARY_DIR}/${CLASS_NAME}TestExec
175178 -o ${CMAKE_BINARY_DIR}/test${CLASS_NAME}.xml,xunitxml
176179 -o -,txt)
debian/changelog+46
@@ -1,3 +1,49 @@
1+unity8 (8.02+15.04.20150109.2-0ubuntu1) vivid; urgency=low
2+
3+ [ Michał Sawicz ]
4+ * We don't need the SIGSTOP in main() any more.
5+ * Add a test to make sure the shell always starts disabled until it is
6+ enabled by a complete PAM interaction.
7+
8+ [ Leo Arias ]
9+ * Added an autopilot test for the edges demo.
10+
11+ [ Nick Dedekind ]
12+ * Unhook Lights interface from indicator widgets (LP: #1385331)
13+
14+ [ Albert Astals ]
15+ * Fix going to scopes when the Manage Dash is open (LP: #1403464)
16+ * QSortFilterProxyModelQML -> UnitySortFilterProxyModelQML
17+ * Clip the Scopes List header
18+ * Fix ScopesList not being under finger
19+ * Make waitForRendering with no item fail instead of crash
20+ * Disable Dash horizontal scroll while Navigation InverseMouseArea is
21+ pressed (LP: #1403048)
22+ * Test: Make sure the mouse area is enabled before clicking into it
23+ * Test: We actually need to click on the customBackButton and not on
24+ backButton
25+ * Test: By default mouseX act on the middle
26+
27+ [ Michael Terry ]
28+ * Don't block handling power events on loading the greeter's qml and
29+ the background image.
30+ * Show OSK above the wizard. (LP: #1401213)
31+ * Unify the name of the Greeter DBus test, make it use our standard
32+ binary test macro (which also nicely exports xml results), and make
33+ the test a little more robust against timing issues.
34+ * Add a test to make sure the shell always starts disabled until it is
35+ enabled by a complete PAM interaction.
36+
37+ [ Martin Pitt ]
38+ * tests: Fix Notify.Notification.add_action invocation to work also
39+ with unpatched libnotify API. (LP: #1223401)
40+
41+ [ Rodney Dawes ]
42+ * Depend on :native version of g++ to allow cross-compiling to work.
43+ (LP: #1353855)
44+
45+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 09 Jan 2015 10:43:06 +0000
46+
147unity8 (8.02+15.04.20141216.1-0ubuntu1) vivid; urgency=low
248
349 [ Ubuntu daily release ]
debian/control+7−5
@@ -10,8 +10,10 @@ Build-Depends: cmake,
1010 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
1111# We rely on C++11 features, and to prevent from ABI breaks
1212# in libstdc++ causing us issues, we explicitly select a G++
13−# version.
14− g++-4.9,
13+# version. To allow cross-compiling to work, we also must
14+# append :native to g++-4.9 so we don't try to run armhf g++
15+# on an x86 CPU for eaxmple, when cross-compiling.
16+ g++-4.9:native,
1517 libconnectivity-qt1-dev,
1618 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
1719 libgl1-mesa-dri,
@@ -22,7 +24,7 @@ Build-Depends: cmake,
2224 libpam0g-dev,
2325 libpay2-dev,
2426 libpulse-dev,
25− libqmenumodel-dev (>= 0.2.8),
27+ libqmenumodel-dev (>= 0.2.9),
2628 libqt5xmlpatterns5-dev,
2729 libsystemsettings-dev,
2830 libunity-api-dev (>= 7.94),
@@ -61,7 +63,7 @@ X-Ubuntu-Use-Langpack: yes
6163
6264Package: indicators-client
6365Architecture: amd64 armhf i386
64−Depends: qmenumodel-qml (>= 0.2.8),
66+Depends: qmenumodel-qml (>= 0.2.9),
6567 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
6668 unity8 (= ${binary:Version}),
6769 ${misc:Depends},
@@ -85,7 +87,7 @@ Provides: indicator-renderer,
8587Depends: gsettings-desktop-schemas,
8688 libcap2-bin,
8789 libglib2.0-bin,
88− qmenumodel-qml (>= 0.2.8),
90+ qmenumodel-qml (>= 0.2.9),
8991 qml-module-qt-labs-folderlistmodel,
9092 qml-module-qtquick-xmllistmodel,
9193 qtdeclarative5-gsettings1.0,
plugins/LightDM/CMakeLists.txt+1−1
@@ -15,7 +15,7 @@ include_directories(
1515)
1616
1717set(QMLPLUGIN_SRC
18− ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
18+ ../Utils/unitysortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
1919 DBusGreeter.cpp
2020 DBusGreeterList.cpp
2121 Greeter.cpp
plugins/LightDM/UsersModel.cpp+1−1
@@ -58,7 +58,7 @@ QVariant MangleModel::data(const QModelIndex &index, int role) const
5858// **** Now we continue with actual UsersModel class ****
5959
6060UsersModel::UsersModel(QObject* parent)
61− : QSortFilterProxyModelQML(parent)
61+ : UnitySortFilterProxyModelQML(parent)
6262{
6363 setModel(new MangleModel(this));
6464 setSortCaseSensitivity(Qt::CaseInsensitive);
plugins/LightDM/UsersModel.h+2−2
@@ -23,10 +23,10 @@
2323#ifndef UNITY_USERSMODEL_H
2424#define UNITY_USERSMODEL_H
2525
26−#include <qsortfilterproxymodelqml.h>
26+#include <unitysortfilterproxymodelqml.h>
2727#include <QtCore/QObject>
2828
29−class UsersModel : public QSortFilterProxyModelQML
29+class UsersModel : public UnitySortFilterProxyModelQML
3030{
3131 Q_OBJECT
3232
plugins/Lights/Lights.cpp+9−24
@@ -44,12 +44,20 @@ Lights::~Lights()
4444
4545void Lights::setState(Lights::State newState)
4646{
47+ if (!init()) {
48+ qWarning() << "No lights device";
49+ return;
50+ }
51+
4752 if (m_state != newState) {
4853 if (newState == Lights::On) {
4954 turnOn();
5055 } else {
5156 turnOff();
5257 }
58+
59+ m_state = newState;
60+ Q_EMIT stateChanged(m_state);
5361 }
5462}
5563
@@ -115,6 +123,7 @@ bool Lights::init()
115123 err = module->methods->open(module, LIGHT_ID_NOTIFICATIONS, &device);
116124 if (err == 0) {
117125 m_lightDevice = (light_device_t*)device;
126+ turnOff();
118127 return true;
119128 } else {
120129 qWarning() << "Failed to access notification lights";
@@ -127,15 +136,6 @@ bool Lights::init()
127136
128137void Lights::turnOn()
129138{
130− if (!init()) {
131− qWarning() << "No lights device";
132− return;
133− }
134−
135− if (m_state == Lights::On) {
136− return;
137− }
138−
139139 // pulse
140140 light_state_t state;
141141 memset(&state, 0, sizeof(light_state_t));
@@ -147,23 +147,11 @@ void Lights::turnOn()
147147
148148 if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
149149 qWarning() << "Failed to turn the light off";
150− } else {
151− m_state = Lights::On;
152− Q_EMIT stateChanged(m_state);
153150 }
154151}
155152
156153void Lights::turnOff()
157154{
158− if (!init()) {
159− qWarning() << "No lights device";
160− return;
161− }
162−
163− if (m_state == Lights::Off) {
164− return;
165− }
166−
167155 light_state_t state;
168156 memset(&state, 0, sizeof(light_state_t));
169157 state.color = 0x00000000;
@@ -174,8 +162,5 @@ void Lights::turnOff()
174162
175163 if (m_lightDevice->set_light(m_lightDevice, &state) != 0) {
176164 qWarning() << "Failed to turn the light off";
177− } else {
178− m_state = Lights::Off;
179− Q_EMIT stateChanged(m_state);
180165 }
181166}
plugins/Unity/Indicators/CMakeLists.txt+3−1
@@ -16,14 +16,16 @@ include_directories(
1616)
1717
1818set(IndicatorsQML_SOURCES
19+ actionrootstate.cpp
1920 indicator.cpp
2021 indicators.h
2122 indicatorsmanager.cpp
2223 indicatorsmodel.cpp
2324 menucontentactivator.cpp
25+ modelactionrootstate.cpp
2426 modelprinter.cpp
2527 plugin.cpp
26− rootactionstate.cpp
28+ rootstateparser.cpp
2729 sharedunitymenumodel.cpp
2830 unitymenumodelcache.cpp
2931 unitymenumodelstack.cpp
plugins/Unity/Indicators/Indicators.qmltypes+18−7
@@ -7,6 +7,14 @@ import QtQuick.tooling 1.1
77// 'qmlplugindump -notrelocatable Unity.Indicators 0.1 plugins'
88
99Module {
10+ Component {
11+ name: "ActionRootState"
12+ prototype: "RootStateObject"
13+ exports: ["Unity.Indicators/ActionRootState 0.1"]
14+ exportMetaObjectRevisions: [0]
15+ Property { name: "actionGroup"; type: "QDBusActionGroup"; isPointer: true }
16+ Property { name: "actionName"; type: "string" }
17+ }
1018 Component {
1119 name: "ActionState"
1220 prototype: "QObject"
@@ -23,7 +31,6 @@ Module {
2331 }
2432 }
2533 }
26− Component { name: "ActionStateParser"; prototype: "QObject" }
2734 Component {
2835 name: "FlatMenuProxyModelRole"
2936 prototype: "QObject"
@@ -146,6 +153,14 @@ Module {
146153 exportMetaObjectRevisions: [0]
147154 Property { name: "active"; type: "bool"; isReadonly: true }
148155 }
156+ Component {
157+ name: "ModelActionRootState"
158+ prototype: "RootStateObject"
159+ exports: ["Unity.Indicators/ModelActionRootState 0.1"]
160+ exportMetaObjectRevisions: [0]
161+ Property { name: "menu"; type: "UnityMenuModel"; isPointer: true }
162+ Signal { name: "indexChanged" }
163+ }
149164 Component {
150165 name: "ModelPrinter"
151166 prototype: "QObject"
@@ -192,11 +207,8 @@ Module {
192207 }
193208 Component { name: "QIdentityProxyModel"; prototype: "QAbstractProxyModel" }
194209 Component {
195− name: "RootActionState"
196− prototype: "ActionStateParser"
197− exports: ["Unity.Indicators/RootActionState 0.1"]
198− exportMetaObjectRevisions: [0]
199− Property { name: "menu"; type: "UnityMenuModel"; isPointer: true }
210+ name: "RootStateObject"
211+ prototype: "QObject"
200212 Property { name: "valid"; type: "bool"; isReadonly: true }
201213 Property { name: "title"; type: "string"; isReadonly: true }
202214 Property { name: "leftLabel"; type: "string"; isReadonly: true }
@@ -205,7 +217,6 @@ Module {
205217 Property { name: "accessibleName"; type: "string"; isReadonly: true }
206218 Property { name: "visible"; type: "bool"; isReadonly: true }
207219 Signal { name: "updated" }
208− Signal { name: "indexChanged" }
209220 }
210221 Component {
211222 name: "SharedUnityMenuModel"
plugins/Unity/Indicators/actionrootstate.cppnew file+97
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "actionrootstate.h"
18+
19+#include <qdbusactiongroup.h>
20+#include <QDebug>
21+
22+ActionRootState::ActionRootState(QObject *parent)
23+ : RootStateObject(parent)
24+ , m_actionGroup(nullptr)
25+{
26+}
27+
28+QDBusActionGroup *ActionRootState::actionGroup() const
29+{
30+ return m_actionGroup;
31+}
32+
33+void ActionRootState::setActionGroup(QDBusActionGroup *actionGroup)
34+{
35+ if (m_actionGroup != actionGroup) {
36+ bool wasValid = valid();
37+
38+ if (m_actionGroup) {
39+ disconnect(m_actionGroup, 0, this, 0);
40+ }
41+ m_actionGroup = actionGroup;
42+
43+ if (m_actionGroup) {
44+ connect(m_actionGroup, &QDBusActionGroup::statusChanged, this, [&](bool) { updateActionState(); });
45+ connect(m_actionGroup, &QDBusActionGroup::actionAppear, this, [&](const QString&) { updateActionState(); });
46+ connect(m_actionGroup, &QDBusActionGroup::actionVanish, this, [&](const QString&) { updateActionState(); });
47+ connect(m_actionGroup, &QDBusActionGroup::actionStateChanged, this, [&](QVariant) { updateActionState(); });
48+
49+ connect(m_actionGroup, &QObject::destroyed, this, [&](QObject*) { updateActionState(); });
50+ }
51+ updateActionState();
52+ Q_EMIT actionGroupChanged();
53+
54+ if (wasValid != valid()) Q_EMIT validChanged();
55+ }
56+}
57+
58+QString ActionRootState::actionName() const
59+{
60+ return m_actionName;
61+}
62+
63+void ActionRootState::setActionName(const QString &actionName)
64+{
65+ if (m_actionName != actionName) {
66+ bool wasValid = valid();
67+
68+ m_actionName = actionName;
69+ updateActionState();
70+
71+ Q_EMIT actionNameChanged();
72+
73+ if (wasValid != valid()) Q_EMIT validChanged();
74+ }
75+}
76+
77+bool ActionRootState::valid() const
78+{
79+ return m_actionGroup && m_actionGroup->status() == DBusEnums::Connected &&
80+ !m_actionName.isEmpty() && m_actionGroup->hasAction(m_actionName);
81+}
82+
83+void ActionRootState::updateActionState()
84+{
85+ if (valid()) {
86+ ActionStateParser* oldParser = m_actionGroup->actionStateParser();
87+ m_actionGroup->setActionStateParser(&m_parser);
88+
89+ QVariantMap state = m_actionGroup->actionState(m_actionName).toMap();
90+
91+ m_actionGroup->setActionStateParser(oldParser);
92+
93+ setCurrentState(state);
94+ } else {
95+ setCurrentState(QVariantMap());
96+ }
97+}
plugins/Unity/Indicators/actionrootstate.hnew file+55
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef ACTIONROOTSTATE_H
18+#define ACTIONROOTSTATE_H
19+
20+#include "unityindicatorsglobal.h"
21+
22+#include "rootstateparser.h"
23+
24+class QDBusActionGroup;
25+
26+class UNITYINDICATORS_EXPORT ActionRootState : public RootStateObject
27+{
28+ Q_OBJECT
29+ Q_PROPERTY(QDBusActionGroup* actionGroup READ actionGroup WRITE setActionGroup NOTIFY actionGroupChanged)
30+ Q_PROPERTY(QString actionName READ actionName WRITE setActionName NOTIFY actionNameChanged)
31+
32+public:
33+ ActionRootState(QObject *parent = 0);
34+
35+ QDBusActionGroup *actionGroup() const;
36+ void setActionGroup(QDBusActionGroup *actionGroup);
37+
38+ QString actionName() const;
39+ void setActionName(const QString& actionName);
40+
41+ bool valid() const override;
42+
43+Q_SIGNALS:
44+ void actionGroupChanged();
45+ void actionNameChanged();
46+
47+private Q_SLOTS:
48+ void updateActionState();
49+
50+private:
51+ QDBusActionGroup* m_actionGroup;
52+ QString m_actionName;
53+};
54+
55+#endif // ACTIONROOTSTATE_H
plugins/Unity/Indicators/modelactionrootstate.cppnew file+127
@@ -0,0 +1,127 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#include "modelactionrootstate.h"
21+#include "indicators.h"
22+
23+#include <unitymenumodel.h>
24+#include <QVariant>
25+#include <QIcon>
26+
27+extern "C" {
28+#include <glib.h>
29+#include <gio/gio.h>
30+}
31+
32+ModelActionRootState::ModelActionRootState(QObject *parent)
33+ : RootStateObject(parent),
34+ m_menu(nullptr)
35+{
36+}
37+
38+ModelActionRootState::~ModelActionRootState()
39+{
40+}
41+
42+UnityMenuModel* ModelActionRootState::menu() const
43+{
44+ return m_menu;
45+}
46+
47+void ModelActionRootState::setMenu(UnityMenuModel* menu)
48+{
49+ if (m_menu != menu) {
50+ bool wasValid = valid();
51+
52+ if (m_menu) {
53+ m_menu->disconnect(this);
54+ }
55+ m_menu = menu;
56+
57+ if (m_menu) {
58+ connect(m_menu, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(onModelRowsAdded(const QModelIndex&, int, int)));
59+ connect(m_menu, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(onModelRowsRemoved(const QModelIndex&, int, int)));
60+ connect(m_menu, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(onModelDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
61+
62+ connect(m_menu, SIGNAL(destroyed()), SLOT(reset()));
63+ }
64+ updateActionState();
65+ Q_EMIT menuChanged();
66+
67+ if (wasValid != valid())
68+ Q_EMIT validChanged();
69+ }
70+}
71+
72+bool ModelActionRootState::valid() const
73+{
74+ return m_menu && m_menu->rowCount() > 0;
75+}
76+
77+void ModelActionRootState::onModelRowsAdded(const QModelIndex& parent, int start, int end)
78+{
79+ Q_UNUSED(parent);
80+ if (start == 0 && end >= 0) {
81+ updateActionState();
82+ }
83+}
84+
85+void ModelActionRootState::onModelRowsRemoved(const QModelIndex& parent, int start, int end)
86+{
87+ Q_UNUSED(parent);
88+ if (start == 0 && end >= 0) {
89+ updateActionState();
90+ }
91+}
92+
93+void ModelActionRootState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
94+{
95+ Q_UNUSED(roles);
96+ if (!topLeft.isValid() || !bottomRight.isValid()) {
97+ return;
98+ }
99+
100+ if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
101+ updateActionState();
102+ }
103+}
104+
105+void ModelActionRootState::reset()
106+{
107+ m_menu = nullptr;
108+
109+ Q_EMIT menuChanged();
110+ setCurrentState(QVariantMap());
111+}
112+
113+void ModelActionRootState::updateActionState()
114+{
115+ if (m_menu && m_menu->rowCount() > 0) {
116+ ActionStateParser* oldParser = m_menu->actionStateParser();
117+ m_menu->setActionStateParser(&m_parser);
118+
119+ QVariantMap state = m_menu->get(0, "actionState").toMap();
120+
121+ m_menu->setActionStateParser(oldParser);
122+
123+ setCurrentState(state);
124+ } else {
125+ setCurrentState(QVariantMap());
126+ }
127+}
plugins/Unity/Indicators/modelactionrootstate.hnew file+61
@@ -0,0 +1,61 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#ifndef MODELACTIONROOTSTATE_H
21+#define MODELACTIONROOTSTATE_H
22+
23+#include "unityindicatorsglobal.h"
24+
25+#include "rootstateparser.h"
26+
27+class UnityMenuModel;
28+
29+class UNITYINDICATORS_EXPORT ModelActionRootState : public RootStateObject
30+{
31+ Q_OBJECT
32+ Q_PROPERTY(UnityMenuModel* menu READ menu WRITE setMenu NOTIFY menuChanged)
33+public:
34+ ModelActionRootState(QObject *parent = 0);
35+ virtual ~ModelActionRootState();
36+
37+ UnityMenuModel* menu() const;
38+ void setMenu(UnityMenuModel* menu);
39+
40+ int index() const;
41+ void setIndex(int index);
42+
43+ bool valid() const override;
44+
45+Q_SIGNALS:
46+ void menuChanged();
47+ void indexChanged();
48+
49+private Q_SLOTS:
50+ void onModelRowsAdded(const QModelIndex& parent, int start, int end);
51+ void onModelRowsRemoved(const QModelIndex& parent, int start, int end);
52+ void onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>&);
53+ void reset();
54+
55+private:
56+ void updateActionState();
57+
58+ UnityMenuModel* m_menu;
59+};
60+
61+#endif // MODELACTIONROOTSTATE_H
plugins/Unity/Indicators/plugin.cpp+4−2
@@ -24,12 +24,13 @@
2424#include "plugin.h"
2525
2626// local
27+#include "actionrootstate.h"
2728#include "indicators.h"
2829#include "indicatorsmanager.h"
2930#include "indicatorsmodel.h"
3031#include "menucontentactivator.h"
32+#include "modelactionrootstate.h"
3133#include "modelprinter.h"
32−#include "rootactionstate.h"
3334#include "sharedunitymenumodel.h"
3435#include "unitymenumodelcache.h"
3536#include "unitymenumodelstack.h"
@@ -51,7 +52,8 @@ void IndicatorsPlugin::registerTypes(const char *uri)
5152 qmlRegisterType<IndicatorsModel>(uri, 0, 1, "IndicatorsModel");
5253 qmlRegisterType<MenuContentActivator>(uri, 0, 1, "MenuContentActivator");
5354 qmlRegisterType<UnityMenuModelStack>(uri, 0, 1, "UnityMenuModelStack");
54− qmlRegisterType<RootActionState>(uri, 0, 1, "RootActionState");
55+ qmlRegisterType<ModelActionRootState>(uri, 0, 1, "ModelActionRootState");
56+ qmlRegisterType<ActionRootState>(uri, 0, 1, "ActionRootState");
5557 qmlRegisterType<ModelPrinter>(uri, 0, 1, "ModelPrinter");
5658 qmlRegisterType<VisibleIndicatorsModel>(uri, 0, 1, "VisibleIndicatorsModel");
5759 qmlRegisterType<SharedUnityMenuModel>(uri, 0, 1, "SharedUnityMenuModel");
plugins/Unity/Indicators/rootactionstate.cpp → plugins/Unity/Indicators/rootstateparser.cpprenamed+74−141
@@ -12,155 +12,18 @@
1212 *
1313 * You should have received a copy of the GNU Lesser General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors:
17− * Nick Dedekind <nick.dedekind@canonical.com>
1815 */
1916
20−#include "rootactionstate.h"
21−#include "indicators.h"
22−
23−#include <unitymenumodel.h>
24−#include <QVariant>
25−#include <QIcon>
17+#include "rootstateparser.h"
2618
2719extern "C" {
2820#include <glib.h>
2921#include <gio/gio.h>
3022}
3123
32−RootActionState::RootActionState(QObject *parent)
33− : ActionStateParser(parent),
34− m_menu(nullptr)
35−{
36−}
37−
38−RootActionState::~RootActionState()
39−{
40−}
41−
42−UnityMenuModel* RootActionState::menu() const
43−{
44− return m_menu;
45−}
46−
47−void RootActionState::setMenu(UnityMenuModel* menu)
48−{
49− if (m_menu != menu) {
50− if (m_menu) {
51− m_menu->disconnect(this);
52− }
53− m_menu = menu;
54−
55− if (m_menu) {
56− connect(m_menu, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(onModelRowsAdded(const QModelIndex&, int, int)));
57− connect(m_menu, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(onModelRowsRemoved(const QModelIndex&, int, int)));
58− connect(m_menu, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)), SLOT(onModelDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
59−
60− connect(m_menu, SIGNAL(destroyed()), SLOT(reset()));
61− }
62− updateActionState();
63− Q_EMIT menuChanged();
64− }
65−}
66−
67−void RootActionState::onModelRowsAdded(const QModelIndex& parent, int start, int end)
24+RootStateParser::RootStateParser(QObject* parent)
25+ : ActionStateParser(parent)
6826{
69− Q_UNUSED(parent);
70− if (start == 0 && end >= 0) {
71− updateActionState();
72− }
73−}
74−
75−void RootActionState::onModelRowsRemoved(const QModelIndex& parent, int start, int end)
76−{
77− Q_UNUSED(parent);
78− if (start == 0 && end >= 0) {
79− updateActionState();
80− }
81−}
82−
83−void RootActionState::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
84−{
85− Q_UNUSED(roles);
86− if (!topLeft.isValid() || !bottomRight.isValid()) {
87− return;
88− }
89−
90− if (topLeft.row() <= 0 && bottomRight.row() >= 0) {
91− updateActionState();
92− }
93−}
94−
95−void RootActionState::reset()
96−{
97− m_cachedState.clear();
98− m_menu = nullptr;
99−
100− Q_EMIT menuChanged();
101− Q_EMIT updated();
102−}
103−
104−void RootActionState::updateActionState()
105−{
106− if (m_menu && m_menu->rowCount() > 0) {
107− ActionStateParser* oldParser = m_menu->actionStateParser();
108− m_menu->setActionStateParser(this);
109−
110− m_cachedState = m_menu->get(0, "actionState").toMap();
111−
112− m_menu->setActionStateParser(oldParser);
113− } else {
114− m_cachedState.clear();
115− }
116− Q_EMIT updated();
117−}
118−
119−bool RootActionState::isValid() const
120−{
121− return m_menu && m_menu->rowCount() > 0;
122−}
123−
124−QString RootActionState::title() const
125−{
126− if (!isValid()) return QString();
127−
128− return m_cachedState.value("title", QVariant::fromValue(QString())).toString();
129−}
130−
131−QString RootActionState::leftLabel() const
132−{
133− if (!isValid()) return QString();
134−
135− return m_cachedState.value("pre-label", QVariant::fromValue(QString())).toString();
136−}
137−
138−QString RootActionState::rightLabel() const
139−{
140− if (!isValid()) return QString();
141−
142− return m_cachedState.value("label", QVariant::fromValue(QString())).toString();
143−}
144−
145−QStringList RootActionState::icons() const
146−{
147− if (!isValid()) return QStringList();
148−
149− return m_cachedState.value("icons", QVariant::fromValue(QStringList())).toStringList();
150−}
151−
152−QString RootActionState::accessibleName() const
153−{
154− if (!isValid()) return QString();
155−
156− return m_cachedState.value("accessible-desc", QVariant::fromValue(QString())).toString();
157−}
158−
159−bool RootActionState::indicatorVisible() const
160−{
161− if (!isValid()) return false;
162−
163− return m_cachedState.value("visible", QVariant::fromValue(true)).toBool();
16427}
16528
16629static QString iconUri(GIcon *icon)
@@ -209,7 +72,7 @@ static QString iconUri(GIcon *icon)
20972 return uri;
21073}
21174
212−QVariant RootActionState::toQVariant(GVariant* state) const
75+QVariant RootStateParser::toQVariant(GVariant* state) const
21376{
21477 if (!state) {
21578 return QVariant();
@@ -296,3 +159,73 @@ QVariant RootActionState::toQVariant(GVariant* state) const
296159 }
297160 return ActionStateParser::toQVariant(state);
298161}
162+
163+
164+RootStateObject::RootStateObject(QObject* parent)
165+ : QObject(parent)
166+{
167+}
168+
169+QString RootStateObject::title() const
170+{
171+ if (!valid()) return QString();
172+
173+ return m_currentState.value("title", QVariant::fromValue(QString())).toString();
174+}
175+
176+QString RootStateObject::leftLabel() const
177+{
178+ if (!valid()) return QString();
179+
180+ return m_currentState.value("pre-label", QVariant::fromValue(QString())).toString();
181+}
182+
183+QString RootStateObject::rightLabel() const
184+{
185+ if (!valid()) return QString();
186+
187+ return m_currentState.value("label", QVariant::fromValue(QString())).toString();
188+}
189+
190+QStringList RootStateObject::icons() const
191+{
192+ if (!valid()) return QStringList();
193+
194+ return m_currentState.value("icons", QVariant::fromValue(QStringList())).toStringList();
195+}
196+
197+QString RootStateObject::accessibleName() const
198+{
199+ if (!valid()) return QString();
200+
201+ return m_currentState.value("accessible-desc", QVariant::fromValue(QString())).toString();
202+}
203+
204+bool RootStateObject::indicatorVisible() const
205+{
206+ if (!valid()) return false;
207+
208+ return m_currentState.value("visible", QVariant::fromValue(true)).toBool();
209+}
210+
211+void RootStateObject::setCurrentState(const QVariantMap& newState)
212+{
213+ QString oldTitle = title();
214+ QString oldLeftLabel = leftLabel();
215+ QString oldRightLabel = rightLabel();
216+ QStringList oldIcons = icons();
217+ QString oldAccessibleName = accessibleName();
218+ bool oldIndicatorVisible = indicatorVisible();
219+
220+ if (m_currentState != newState) {
221+ m_currentState = newState;
222+ Q_EMIT updated();
223+
224+ if (oldTitle != title()) Q_EMIT titleChanged();
225+ if (oldLeftLabel != leftLabel()) Q_EMIT leftLabelChanged();
226+ if (oldRightLabel != rightLabel()) Q_EMIT rightLabelChanged();
227+ if (oldIcons != icons()) Q_EMIT iconsChanged();
228+ if (oldAccessibleName != accessibleName()) Q_EMIT accessibleNameChanged();
229+ if (oldIndicatorVisible != indicatorVisible()) Q_EMIT indicatorVisibleChanged();
230+ }
231+}
plugins/Unity/Indicators/rootactionstate.h → plugins/Unity/Indicators/rootstateparser.hrenamed+18−34
@@ -12,26 +12,27 @@
1212 *
1313 * You should have received a copy of the GNU Lesser General Public License
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors:
17− * Nick Dedekind <nick.dedekind@canonical.com>
1815 */
1916
20−#ifndef ROOTACTIONSTATE_H
21−#define ROOTACTIONSTATE_H
17+#ifndef ROOTSTATEPARSER_H
18+#define ROOTSTATEPARSER_H
2219
2320#include "unityindicatorsglobal.h"
2421
2522#include <actionstateparser.h>
2623
27−class UnityMenuModel;
24+class UNITYINDICATORS_EXPORT RootStateParser : public ActionStateParser
25+{
26+public:
27+ RootStateParser(QObject* parent = nullptr);
28+ virtual QVariant toQVariant(GVariant* state) const override;
29+};
2830
29−class UNITYINDICATORS_EXPORT RootActionState : public ActionStateParser
31+class UNITYINDICATORS_EXPORT RootStateObject : public QObject
3032{
3133 Q_OBJECT
32− Q_PROPERTY(UnityMenuModel* menu READ menu WRITE setMenu NOTIFY menuChanged)
3334
34− Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
35+ Q_PROPERTY(bool valid READ valid NOTIFY validChanged)
3536 Q_PROPERTY(QString title READ title NOTIFY titleChanged)
3637 Q_PROPERTY(QString leftLabel READ leftLabel NOTIFY leftLabelChanged)
3738 Q_PROPERTY(QString rightLabel READ rightLabel NOTIFY rightLabelChanged)
@@ -39,16 +40,10 @@ class UNITYINDICATORS_EXPORT RootActionState : public ActionStateParser
3940 Q_PROPERTY(QString accessibleName READ accessibleName NOTIFY accessibleNameChanged)
4041 Q_PROPERTY(bool indicatorVisible READ indicatorVisible NOTIFY indicatorVisibleChanged)
4142public:
42− RootActionState(QObject *parent = 0);
43− virtual ~RootActionState();
43+ RootStateObject(QObject* parent = 0);
4444
45− UnityMenuModel* menu() const;
46− void setMenu(UnityMenuModel* menu);
45+ virtual bool valid() const = 0;
4746
48− int index() const;
49− void setIndex(int index);
50−
51− bool isValid() const;
5247 QString title() const;
5348 QString leftLabel() const;
5449 QString rightLabel() const;
@@ -56,15 +51,12 @@ public:
5651 QString accessibleName() const;
5752 bool indicatorVisible() const;
5853
59− // from ActionStateParser
60− virtual QVariant toQVariant(GVariant* state) const override;
54+ QVariantMap currentState() const { return m_currentState; }
55+ void setCurrentState(const QVariantMap& currentState);
6156
6257Q_SIGNALS:
6358 void updated();
6459
65− void menuChanged();
66− void indexChanged();
67−
6860 void validChanged();
6961 void titleChanged();
7062 void leftLabelChanged();
@@ -73,17 +65,9 @@ Q_SIGNALS:
7365 void accessibleNameChanged();
7466 void indicatorVisibleChanged();
7567
76−private Q_SLOTS:
77− void onModelRowsAdded(const QModelIndex& parent, int start, int end);
78− void onModelRowsRemoved(const QModelIndex& parent, int start, int end);
79− void onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>&);
80− void reset();
81−
82−private:
83− void updateActionState();
84−
85− UnityMenuModel* m_menu;
86− QVariantMap m_cachedState;
68+protected:
69+ RootStateParser m_parser;
70+ QVariantMap m_currentState;
8771};
8872
89−#endif // ROOTACTIONSTATE_H
73+#endif // ROOTSTATEPARSER_H
plugins/Utils/CMakeLists.txt+1−1
@@ -12,7 +12,7 @@ include_directories(
1212
1313set(QMLPLUGIN_SRC
1414 qlimitproxymodelqml.cpp
15− qsortfilterproxymodelqml.cpp
15+ unitysortfilterproxymodelqml.cpp
1616 relativetimeformatter.cpp
1717 timeformatter.cpp
1818 unitymenumodelpaths.cpp
plugins/Utils/plugin.cpp+2−2
@@ -27,7 +27,7 @@
2727
2828// local
2929#include "qlimitproxymodelqml.h"
30−#include "qsortfilterproxymodelqml.h"
30+#include "unitysortfilterproxymodelqml.h"
3131#include "relativetimeformatter.h"
3232#include "timeformatter.h"
3333#include "unitymenumodelpaths.h"
@@ -39,7 +39,7 @@ void UtilsPlugin::registerTypes(const char *uri)
3939 Q_ASSERT(uri == QLatin1String("Utils"));
4040 qmlRegisterType<QAbstractItemModel>();
4141 qmlRegisterType<QLimitProxyModelQML>(uri, 0, 1, "LimitProxyModel");
42− qmlRegisterType<QSortFilterProxyModelQML>(uri, 0, 1, "SortFilterProxyModel");
42+ qmlRegisterType<UnitySortFilterProxyModelQML>(uri, 0, 1, "UnitySortFilterProxyModel");
4343 qmlRegisterType<UnityMenuModelPaths>(uri, 0, 1, "UnityMenuModelPaths");
4444 qmlRegisterType<TimeFormatter>(uri, 0, 1, "TimeFormatter");
4545 qmlRegisterType<WindowKeysFilter>(uri, 0, 1, "WindowKeysFilter");
plugins/Utils/qsortfilterproxymodelqml.cpp → plugins/Utils/unitysortfilterproxymodelqml.cpprenamed+15−15
@@ -15,12 +15,12 @@
1515 */
1616
1717// self
18−#include "qsortfilterproxymodelqml.h"
18+#include "unitysortfilterproxymodelqml.h"
1919
2020// Qt
2121#include <QDebug>
2222
23−QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent)
23+UnitySortFilterProxyModelQML::UnitySortFilterProxyModelQML(QObject *parent)
2424 : QSortFilterProxyModel(parent)
2525 , m_invertMatch(false)
2626{
@@ -32,7 +32,7 @@ QSortFilterProxyModelQML::QSortFilterProxyModelQML(QObject *parent)
3232/*
3333 * Enter row index of filtered/sorted model, returns row index of source model
3434 */
35−int QSortFilterProxyModelQML::mapRowToSource(int row)
35+int UnitySortFilterProxyModelQML::mapRowToSource(int row)
3636{
3737 if (sourceModel() == nullptr)
3838 return -1;
@@ -40,13 +40,13 @@ int QSortFilterProxyModelQML::mapRowToSource(int row)
4040 return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
4141}
4242
43−QHash<int, QByteArray> QSortFilterProxyModelQML::roleNames() const
43+QHash<int, QByteArray> UnitySortFilterProxyModelQML::roleNames() const
4444{
4545 return sourceModel() ? sourceModel()->roleNames() : QHash<int, QByteArray>();
4646}
4747
4848void
49−QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
49+UnitySortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
5050{
5151 if (itemModel == nullptr) {
5252 return;
@@ -69,7 +69,7 @@ QSortFilterProxyModelQML::setModel(QAbstractItemModel *itemModel)
6969}
7070
7171QVariantMap
72−QSortFilterProxyModelQML::get(int row)
72+UnitySortFilterProxyModelQML::get(int row)
7373{
7474 QVariantMap res;
7575 const QHash<int, QByteArray> roles = roleNames();
@@ -81,7 +81,7 @@ QSortFilterProxyModelQML::get(int row)
8181}
8282
8383QVariant
84−QSortFilterProxyModelQML::data(int row, int role)
84+UnitySortFilterProxyModelQML::data(int row, int role)
8585{
8686 if (sourceModel() == nullptr) {
8787 return QVariant();
@@ -91,7 +91,7 @@ QSortFilterProxyModelQML::data(int row, int role)
9191}
9292
9393int
94−QSortFilterProxyModelQML::totalCount() const
94+UnitySortFilterProxyModelQML::totalCount() const
9595{
9696 if (sourceModel() != nullptr) {
9797 return sourceModel()->rowCount();
@@ -101,19 +101,19 @@ QSortFilterProxyModelQML::totalCount() const
101101}
102102
103103int
104−QSortFilterProxyModelQML::count()
104+UnitySortFilterProxyModelQML::count()
105105{
106106 return rowCount();
107107}
108108
109109bool
110−QSortFilterProxyModelQML::invertMatch() const
110+UnitySortFilterProxyModelQML::invertMatch() const
111111{
112112 return m_invertMatch;
113113}
114114
115115void
116−QSortFilterProxyModelQML::setInvertMatch(bool invertMatch)
116+UnitySortFilterProxyModelQML::setInvertMatch(bool invertMatch)
117117{
118118 if (invertMatch != m_invertMatch) {
119119 m_invertMatch = invertMatch;
@@ -123,7 +123,7 @@ QSortFilterProxyModelQML::setInvertMatch(bool invertMatch)
123123}
124124
125125bool
126−QSortFilterProxyModelQML::filterAcceptsRow(int sourceRow,
126+UnitySortFilterProxyModelQML::filterAcceptsRow(int sourceRow,
127127 const QModelIndex &sourceParent) const
128128{
129129 // If there's no regexp set, always accept all rows indepenently of the invertMatch setting
@@ -136,7 +136,7 @@ QSortFilterProxyModelQML::filterAcceptsRow(int sourceRow,
136136}
137137
138138int
139−QSortFilterProxyModelQML::findFirst(int role, const QVariant& value) const
139+UnitySortFilterProxyModelQML::findFirst(int role, const QVariant& value) const
140140{
141141 QModelIndexList matches = match(index(0, 0), role, value, 1, Qt::MatchExactly);
142142 if (!matches.isEmpty()) {
@@ -147,7 +147,7 @@ QSortFilterProxyModelQML::findFirst(int role, const QVariant& value) const
147147}
148148
149149int
150−QSortFilterProxyModelQML::mapFromSource(int row)
150+UnitySortFilterProxyModelQML::mapFromSource(int row)
151151{
152152 if (sourceModel() != nullptr) {
153153 return QSortFilterProxyModel::mapFromSource(sourceModel()->index(row, 0)).row();
@@ -157,7 +157,7 @@ QSortFilterProxyModelQML::mapFromSource(int row)
157157}
158158
159159int
160−QSortFilterProxyModelQML::mapToSource(int row)
160+UnitySortFilterProxyModelQML::mapToSource(int row)
161161{
162162 if (sourceModel() != nullptr) {
163163 return QSortFilterProxyModel::mapToSource(index(row, 0)).row();
plugins/Utils/qsortfilterproxymodelqml.h → plugins/Utils/unitysortfilterproxymodelqml.hrenamed+5−5
@@ -14,12 +14,12 @@
1414 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1515 */
1616
17−#ifndef QSORTFILTERPROXYMODELQML_H
18−#define QSORTFILTERPROXYMODELQML_H
17+#ifndef UNITYSORTFILTERPROXYMODELQML_H
18+#define UNITYSORTFILTERPROXYMODELQML_H
1919
2020#include <QSortFilterProxyModel>
2121
22−class QSortFilterProxyModelQML : public QSortFilterProxyModel
22+class UnitySortFilterProxyModelQML : public QSortFilterProxyModel
2323{
2424 Q_OBJECT
2525
@@ -29,7 +29,7 @@ class QSortFilterProxyModelQML : public QSortFilterProxyModel
2929 Q_PROPERTY(bool invertMatch READ invertMatch WRITE setInvertMatch NOTIFY invertMatchChanged)
3030
3131public:
32− explicit QSortFilterProxyModelQML(QObject *parent = 0);
32+ explicit UnitySortFilterProxyModelQML(QObject *parent = 0);
3333
3434 Q_INVOKABLE QVariantMap get(int row); // Use with caution, it can be slow to query all the roles
3535 Q_INVOKABLE QVariant data(int row, int role);
@@ -60,4 +60,4 @@ private:
6060 bool m_invertMatch;
6161};
6262
63−#endif // QSORTFILTERPROXYMODELQML_H
63+#endif // UNITYSORTFILTERPROXYMODELQML_H
po/fa.po+96−88
@@ -8,26 +8,26 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-12-10 10:55+0100\n"
11−"PO-Revision-Date: 2014-12-10 12:53+0000\n"
11+"PO-Revision-Date: 2015-01-09 15:59+0000\n"
1212"Last-Translator: Danial Behzadi <dani.behzi@gmail.com>\n"
1313"Language-Team: Persian <fa@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2014-12-13 07:11+0000\n"
19−"X-Generator: Launchpad (build 17286)\n"
18+"X-Launchpad-Export-Date: 2015-01-10 07:18+0000\n"
19+"X-Generator: Launchpad (build 17298)\n"
2020
2121#: plugins/LightDM/Greeter.cpp:130
2222msgid "Password: "
2323msgstr "گذرواژه: "
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:45
26−#: plugins/Unity/Launcher/launcheritem.cpp:100
26+#: plugins/Unity/Launcher/launcheritem.cpp:91
2727msgid "Pin shortcut"
2828msgstr "سنجاق کردن میانبر"
2929
30−#: plugins/Unity/Launcher/launcheritem.cpp:100
30+#: plugins/Unity/Launcher/launcheritem.cpp:91
3131msgid "Unpin shortcut"
3232msgstr "برداشتن سنجاق میانبر"
3333
@@ -50,45 +50,45 @@ msgid "Please wait %1 minute and then try again…"
5050msgid_plural "Please wait %1 minutes and then try again…"
5151msgstr[0] "لطفاُ %1 دقیقه صبر نموده و سپس مجدّداً تلاش نمایید…"
5252
53−#: qml/Components/Dialogs.qml:70
53+#: qml/Components/Dialogs.qml:74
5454msgid "Log out"
5555msgstr "خروج از حساب"
5656
57−#: qml/Components/Dialogs.qml:71
57+#: qml/Components/Dialogs.qml:75
5858msgid "Are you sure you want to log out?"
5959msgstr "مطمئنید که می‌خواهید از حساب خارج شوید"
6060
61−#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
62−#: qml/Components/Dialogs.qml:122
61+#: qml/Components/Dialogs.qml:77 qml/Components/Dialogs.qml:101
62+#: qml/Components/Dialogs.qml:126
6363msgid "No"
6464msgstr "خیر"
6565
66−#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
67−#: qml/Components/Dialogs.qml:129
66+#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:108
67+#: qml/Components/Dialogs.qml:133
6868msgid "Yes"
6969msgstr "بله"
7070
71−#: qml/Components/Dialogs.qml:94
71+#: qml/Components/Dialogs.qml:98
7272msgid "Shut down"
7373msgstr "خاموش کردن"
7474
75−#: qml/Components/Dialogs.qml:95
75+#: qml/Components/Dialogs.qml:99
7676msgid "Are you sure you want to shut down?"
7777msgstr "مطمئنید که می‌خواهید خاموش کنید؟"
7878
79−#: qml/Components/Dialogs.qml:119
79+#: qml/Components/Dialogs.qml:123
8080msgid "Reboot"
8181msgstr "راه‌اندازی مجدّد"
8282
83−#: qml/Components/Dialogs.qml:120
83+#: qml/Components/Dialogs.qml:124
8484msgid "Are you sure you want to reboot?"
8585msgstr "مطمئنید که می‌خواهید مجدّداً راه‌اندازی کنسد؟"
8686
87−#: qml/Components/Dialogs.qml:144
87+#: qml/Components/Dialogs.qml:148
8888msgid "Power"
8989msgstr "توان"
9090
91−#: qml/Components/Dialogs.qml:145
91+#: qml/Components/Dialogs.qml:149
9292msgid ""
9393"Are you sure you would like\n"
9494"to power off?"
@@ -96,15 +96,15 @@ msgstr ""
9696"آیا مطمئن هستید که\n"
9797"می‌خواهید خاموش کنید؟"
9898
99−#: qml/Components/Dialogs.qml:147
99+#: qml/Components/Dialogs.qml:151
100100msgid "Power off"
101101msgstr "خاموش کردن"
102102
103−#: qml/Components/Dialogs.qml:157
103+#: qml/Components/Dialogs.qml:161
104104msgid "Restart"
105105msgstr "شروع مجدّد"
106106
107−#: qml/Components/Dialogs.qml:167
107+#: qml/Components/Dialogs.qml:171
108108msgid "Cancel"
109109msgstr "لغو"
110110
@@ -112,43 +112,43 @@ msgstr "لغو"
112112msgid "Skip intro"
113113msgstr "پرش از مقدّمه"
114114
115−#: qml/Components/EdgeDemo.qml:125
115+#: qml/Components/EdgeDemo.qml:112
116116msgid "Right edge"
117117msgstr "لبه‌ی راست"
118118
119−#: qml/Components/EdgeDemo.qml:126
119+#: qml/Components/EdgeDemo.qml:113
120120msgid "Try swiping from the right edge to unlock the phone"
121121msgstr "برای باز کردن قفل تلفن، از لبه‌ی راست بکشید"
122122
123−#: qml/Components/EdgeDemo.qml:157
123+#: qml/Components/EdgeDemo.qml:144
124124msgid "Top edge"
125125msgstr "لبه‌ی بالا"
126126
127−#: qml/Components/EdgeDemo.qml:158
127+#: qml/Components/EdgeDemo.qml:145
128128msgid "Try swiping from the top edge to access the indicators"
129129msgstr "برای دست‌رسی به نشانگرها، از لبه‌ی بالا بکشید"
130130
131−#: qml/Components/EdgeDemo.qml:183
131+#: qml/Components/EdgeDemo.qml:170
132132msgid "Close"
133133msgstr "بستن"
134134
135−#: qml/Components/EdgeDemo.qml:184
135+#: qml/Components/EdgeDemo.qml:171
136136msgid "Swipe up again to close the settings screen"
137137msgstr "برای بستن صفحه‌ی تنظیمات، دوباره به بالا بکشپد"
138138
139−#: qml/Components/EdgeDemo.qml:214
139+#: qml/Components/EdgeDemo.qml:201
140140msgid "Left edge"
141141msgstr "لبه‌ی چپ"
142142
143−#: qml/Components/EdgeDemo.qml:215
143+#: qml/Components/EdgeDemo.qml:202
144144msgid "Swipe from the left to reveal the launcher for quick access to apps"
145145msgstr "برای آشکار شدن اجراگر به منظور دست‌رسی سریع به اپ‌ها از سمت چپ بکشید"
146146
147−#: qml/Components/EdgeDemo.qml:242
147+#: qml/Components/EdgeDemo.qml:229
148148msgid "Well done"
149149msgstr "عالی بود"
150150
151−#: qml/Components/EdgeDemo.qml:243
151+#: qml/Components/EdgeDemo.qml:230
152152msgid ""
153153"You have now mastered the edge gestures and can start using the "
154154"phone<br><br>Tap on the screen to start"
@@ -156,44 +156,44 @@ msgstr ""
156156"هم اکنون در استفاده از ژست های حرکتی مهارت لازم را دارید و می‌توانید استفاده "
157157"از تلفن را آغاز کنید<br><br>برای شروع صفحه را لمس کنید"
158158
159−#: qml/Components/Lockscreen.qml:238
159+#: qml/Components/Lockscreen.qml:223
160160msgid "Return to Call"
161161msgstr "بازگشت به تماس"
162162
163−#: qml/Components/Lockscreen.qml:238
163+#: qml/Components/Lockscreen.qml:223
164164msgid "Emergency Call"
165165msgstr "تماس اضطراری"
166166
167−#: qml/Components/Lockscreen.qml:270
167+#: qml/Components/Lockscreen.qml:255
168168msgid "OK"
169169msgstr "قبول"
170170
171−#: qml/Dash/GenericScopeView.qml:431 qml/Dash/GenericScopeView.qml:588
171+#: qml/Dash/GenericScopeView.qml:434 qml/Dash/GenericScopeView.qml:591
172172msgid "See less"
173173msgstr "کم‌تر ببینید"
174174
175−#: qml/Dash/GenericScopeView.qml:431
175+#: qml/Dash/GenericScopeView.qml:434
176176msgid "See all"
177177msgstr "دیدن همه"
178178
179−#: qml/Dash/GenericScopeView.qml:493 qml/Dash/PageHeader.qml:267
179+#: qml/Dash/GenericScopeView.qml:496 qml/Dash/PageHeader.qml:268
180180#: qml/Panel/SearchIndicator.qml:27
181181msgid "Search"
182182msgstr "جست‌وجو"
183183
184−#: qml/Dash/PageHeader.qml:260
184+#: qml/Dash/PageHeader.qml:261
185185msgid "Store"
186186msgstr "فروشگاه"
187187
188−#: qml/Dash/PageHeader.qml:277
188+#: qml/Dash/PageHeader.qml:278
189189msgid "Settings"
190190msgstr "تنظیمات"
191191
192−#: qml/Dash/PageHeader.qml:284
192+#: qml/Dash/PageHeader.qml:285
193193msgid "Remove from Favorites"
194194msgstr "برداشتن از برگزیده‌ها"
195195
196−#: qml/Dash/PageHeader.qml:284
196+#: qml/Dash/PageHeader.qml:285
197197msgid "Add to Favorites"
198198msgstr "افزودن به برگزیده‌ها"
199199
@@ -289,49 +289,49 @@ msgstr "باز کردن قفل سیم‌کارت"
289289msgid "Roaming"
290290msgstr "رومینگ"
291291
292−#: qml/Shell.qml:367
292+#: qml/Shell.qml:402
293293#, qt-format
294294msgid "Enter %1"
295295msgstr "%1 را وارد کنید"
296296
297−#: qml/Shell.qml:368 qml/Wizard/Pages/passwd-set.qml:60
297+#: qml/Shell.qml:394
298298msgid "Enter passphrase"
299299msgstr "عبارت‌عبور را وارد کنید"
300300
301−#: qml/Shell.qml:369
301+#: qml/Shell.qml:398
302302msgid "Enter passcode"
303303msgstr "رمزعبور را وارد کنید"
304304
305−#: qml/Shell.qml:370
305+#: qml/Shell.qml:403
306306#, qt-format
307307msgid "Sorry, incorrect %1"
308308msgstr "متأسّفیم، %1 نادرست بود"
309309
310−#: qml/Shell.qml:371
310+#: qml/Shell.qml:395
311311msgid "Sorry, incorrect passphrase"
312312msgstr "متأسّفیم، عبارت‌عبور نادرست بود"
313313
314−#: qml/Shell.qml:372
314+#: qml/Shell.qml:396
315315msgid "Please re-enter"
316316msgstr "لطفاً دوباره وارد کنید"
317317
318−#: qml/Shell.qml:373
318+#: qml/Shell.qml:399
319319msgid "Sorry, incorrect passcode"
320320msgstr "متأسّفیم، رمزعبور نادرست بود"
321321
322−#: qml/Shell.qml:467 qml/Wizard/Pages/passwd-confirm.qml:53
322+#: qml/Shell.qml:444
323323msgid "Sorry, incorrect passphrase."
324324msgstr "متأسّفیم، عبارت‌عبور نادرست است."
325325
326−#: qml/Shell.qml:468 qml/Wizard/Pages/passwd-confirm.qml:54
326+#: qml/Shell.qml:445
327327msgid "Sorry, incorrect passcode."
328328msgstr "متأسّفیم، رمزعبور نادرست است."
329329
330−#: qml/Shell.qml:469
330+#: qml/Shell.qml:446
331331msgid "This will be your last attempt."
332332msgstr "این آخرین تلاش شما خواهد بود."
333333
334−#: qml/Shell.qml:471
334+#: qml/Shell.qml:448
335335msgid ""
336336"If passphrase is entered incorrectly, your phone will conduct a factory "
337337"reset and all personal data will be deleted."
@@ -339,7 +339,7 @@ msgstr ""
339339"اگر عبارت‌عبور نادرست وارد شود، تلفن شما بازنشانی کارخانه خواهد شد و تمامی "
340340"اطّلاعات شخصی حذف خواهند شد."
341341
342−#: qml/Shell.qml:472
342+#: qml/Shell.qml:449
343343msgid ""
344344"If passcode is entered incorrectly, your phone will conduct a factory reset "
345345"and all personal data will be deleted."
@@ -349,98 +349,100 @@ msgstr ""
349349
350350#: qml/Wizard/Page.qml:89
351351msgid "Back"
352−msgstr ""
352+msgstr "بازگشت"
353353
354354#: qml/Wizard/Pages/10-welcome.qml:27
355355msgid "Hi!"
356−msgstr ""
356+msgstr "سلام!"
357357
358358#: qml/Wizard/Pages/10-welcome.qml:44
359359msgid "Welcome to your Ubuntu phone."
360−msgstr ""
360+msgstr "به تلفن اوبونتوی خودتان خوش آمدید."
361361
362362#: qml/Wizard/Pages/10-welcome.qml:52
363363msgid "Let’s get started."
364−msgstr ""
364+msgstr "بیایید شروع کینم."
365365
366366#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
367367#: qml/Wizard/Pages/40-wifi.qml:197 qml/Wizard/Pages/50-location.qml:131
368368#: qml/Wizard/Pages/60-reporting.qml:50 qml/Wizard/Pages/passwd-confirm.qml:82
369369#: qml/Wizard/Pages/passwd-set.qml:90
370370msgid "Continue"
371−msgstr ""
371+msgstr "ادامه"
372372
373373#: qml/Wizard/Pages/20-sim.qml:25
374374msgid "Add a SIM card and restart your device"
375−msgstr ""
375+msgstr "سیم‌کارتی افزوده و دستگاهتان را شروع مجدّد کنید"
376376
377377#: qml/Wizard/Pages/20-sim.qml:55
378378msgid "Without it, you won’t be able to make calls or use text messaging."
379379msgstr ""
380+"بدون آن، نخواهید توانست تماس گرفته با از پیام‌رسانی متنی استفاده کنید."
380381
381382#: qml/Wizard/Pages/20-sim.qml:69 qml/Wizard/Pages/40-wifi.qml:197
382383msgid "Skip"
383−msgstr ""
384+msgstr "پرش"
384385
385386#: qml/Wizard/Pages/30-passwd-type.qml:39
386387msgid "Lock security"
387−msgstr ""
388+msgstr "امنیت قفل"
388389
389390#: qml/Wizard/Pages/30-passwd-type.qml:74
390391msgid "Please select how you’d like to unlock your phone."
391−msgstr ""
392+msgstr "لطفاً برگزینید که می‌خواهید چگونه قفل تلفنتان را باز کنید."
392393
393394#: qml/Wizard/Pages/30-passwd-type.qml:97
394395msgid "Swipe"
395−msgstr ""
396+msgstr "لغزش"
396397
397398#: qml/Wizard/Pages/30-passwd-type.qml:98
398399msgid "No security"
399−msgstr ""
400+msgstr "بدون امنیت"
400401
401402#: qml/Wizard/Pages/30-passwd-type.qml:100
402403msgid "Passcode"
403−msgstr ""
404+msgstr "رمزعبور"
404405
405406#: qml/Wizard/Pages/30-passwd-type.qml:101
406407msgid "4 digits only"
407−msgstr ""
408+msgstr "فقط ۴ رقم"
408409
409410#: qml/Wizard/Pages/30-passwd-type.qml:103
410411msgid "Passphrase"
411−msgstr ""
412+msgstr "عبارت‌عبور"
412413
413414#: qml/Wizard/Pages/30-passwd-type.qml:104
414415msgid "Numbers and letters"
415−msgstr ""
416+msgstr "اعداد و حروف"
416417
417418#: qml/Wizard/Pages/40-wifi.qml:28
418419msgid "Connect to Wi‑Fi"
419−msgstr ""
420+msgstr "اتّصال به بی‌سیم"
420421
421422#: qml/Wizard/Pages/40-wifi.qml:147
422423msgid "Available networks…"
423−msgstr ""
424+msgstr "شبکه‌های موجود…"
424425
425426#: qml/Wizard/Pages/40-wifi.qml:148
426427msgid "No available networks."
427−msgstr ""
428+msgstr "هیچ شبکه‌ای موجود نیست."
428429
429430#: qml/Wizard/Pages/50-location.qml:27
430431msgid "Location"
431−msgstr ""
432+msgstr "موقعیت"
432433
433434#: qml/Wizard/Pages/50-location.qml:62
434435msgid "Let the phone detect your location:"
435−msgstr ""
436+msgstr "اجازه به تلفن برای تشخیص موقعیّتتان:"
436437
437438#: qml/Wizard/Pages/50-location.qml:69
438439msgid "Using GPS only (less accurate)"
439−msgstr ""
440+msgstr "فقط با استفاده از جی‌پی‌اس (دقّت کم‌تر)"
440441
441442#: qml/Wizard/Pages/50-location.qml:86
442443msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
443444msgstr ""
445+"با استفاده از جی‌پی‌اس، بی‌سیم ناشناس و اطّلاعات شبکه‌ی سلّولی (پیشنهاد شده)"
444446
445447#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
446448#: qml/Wizard/Pages/50-location.qml:103
@@ -448,81 +450,87 @@ msgid ""
448450"By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
449451"conditions</a>."
450452msgstr ""
453+"با انتخاب این گزینه، با <a href='#'>شرایط و ضوابط</a> HERE نوکیا موافقت "
454+"می‌کنید."
451455
452456#: qml/Wizard/Pages/50-location.qml:112
453457msgid "Not at all"
454−msgstr ""
458+msgstr "به هیچ وجه"
455459
456460#: qml/Wizard/Pages/50-location.qml:124
457461msgid "You can change your mind later in <b>System Settings</b>."
458−msgstr ""
462+msgstr "می‌توانید بعدها نظرتان را در <b>تنظیمات سامانه</b> تغییر دهید."
459463
460464#: qml/Wizard/Pages/60-reporting.qml:24
461465msgid "Improving your experience"
462−msgstr ""
466+msgstr "ارتقای تجربه‌ی شما"
463467
464468#: qml/Wizard/Pages/60-reporting.qml:36
465469msgid ""
466470"Your phone is set up to automatically report errors to Canonical and its "
467471"partners, the makers of the operating system."
468472msgstr ""
473+"تلفن شما تنظیم شده تا خطاها را به صورت خودکار به سازندگان سیستم‌عامل یعنی "
474+"شرکت کنونیکال و شرکایش گزارش دهد."
469475
470476#: qml/Wizard/Pages/60-reporting.qml:43
471477msgid ""
472478"This can be disabled in <b>System Settings</b> under <b>Security &amp; "
473479"Privacy</b>"
474480msgstr ""
481+"این می‌تواند در <b>تنظیمات سامانه</b> ذیل <b>امنیت و محرمانگی</b> غیرفعَال "
482+"شود"
475483
476484#: qml/Wizard/Pages/80-finished.qml:24
477485msgid "All done"
478−msgstr ""
486+msgstr "همه‌چیز انجام شد"
479487
480488#: qml/Wizard/Pages/80-finished.qml:39
481489msgid "Nice work!"
482−msgstr ""
490+msgstr "عالی بود!"
483491
484492#: qml/Wizard/Pages/80-finished.qml:46
485493msgid "Your phone is now ready to use."
486−msgstr ""
494+msgstr "هم‌اکنون تلفن شما آماده‌ی استفاده است."
487495
488496#: qml/Wizard/Pages/80-finished.qml:53
489497msgid "Finish"
490−msgstr ""
498+msgstr "پایان"
491499
492500#: qml/Wizard/Pages/here-terms.qml:27
493501msgid "Terms & Conditions"
494−msgstr ""
502+msgstr "شرایط و ضوابط"
495503
496504#: qml/Wizard/Pages/passwd-confirm.qml:49
497505msgid "Confirm passphrase"
498−msgstr ""
506+msgstr "تأیید عبارت‌عبور"
499507
500508#: qml/Wizard/Pages/passwd-confirm.qml:50
501509msgid "Confirm passcode"
502−msgstr ""
510+msgstr "تأیید رمزعبور"
503511
504512#: qml/Wizard/Pages/passwd-confirm.qml:53
505513#: qml/Wizard/Pages/passwd-confirm.qml:54
506514msgid "Please try again."
507−msgstr ""
515+msgstr "لطفاً دوباره سعی کنید."
508516
509517#: qml/Wizard/Pages/passwd-set.qml:61
510518msgid "Choose your passcode"
511−msgstr ""
519+msgstr "رمزعبور خود را انتخاب کنید"
512520
513521#: qml/Wizard/Pages/passwd-set.qml:68
514522msgid "Passphrase must be 4 characters long"
515−msgstr ""
523+msgstr "عبارت‌عبور باید ۴ نویسه طول داشته باشد"
516524
517525#: qml/Wizard/StackButton.qml:39
518526#, qt-format
519527msgid "〈 %1"
520−msgstr ""
528+msgstr "〈 %1"
521529
522530#: qml/Wizard/StackButton.qml:42
523531#, qt-format
524532msgid "%1 〉"
525−msgstr ""
533+msgstr "%1 〉"
526534
527535#~ msgid "Type or say a command"
528536#~ msgstr "دستوری را بنویسید یا بگویید"
po/ro.po+101−90
@@ -8,7 +8,7 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-12-10 10:55+0100\n"
11−"PO-Revision-Date: 2014-11-18 12:09+0000\n"
11+"PO-Revision-Date: 2015-01-07 11:11+0000\n"
1212"Last-Translator: Marian Vasile <marianvasile1972@gmail.com>\n"
1313"Language-Team: Romanian <ro@li.org>\n"
1414"MIME-Version: 1.0\n"
@@ -16,19 +16,19 @@ msgstr ""
1616"Content-Transfer-Encoding: 8bit\n"
1717"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
1818"== 0) && (n != 0))) ? 2: 1));\n"
19−"X-Launchpad-Export-Date: 2014-12-13 07:11+0000\n"
20−"X-Generator: Launchpad (build 17286)\n"
19+"X-Launchpad-Export-Date: 2015-01-08 07:10+0000\n"
20+"X-Generator: Launchpad (build 17298)\n"
2121
2222#: plugins/LightDM/Greeter.cpp:130
2323msgid "Password: "
2424msgstr "Parolă: "
2525
2626#: plugins/Unity/Launcher/launcheritem.cpp:45
27−#: plugins/Unity/Launcher/launcheritem.cpp:100
27+#: plugins/Unity/Launcher/launcheritem.cpp:91
2828msgid "Pin shortcut"
2929msgstr "Fixează scurtătura"
3030
31−#: plugins/Unity/Launcher/launcheritem.cpp:100
31+#: plugins/Unity/Launcher/launcheritem.cpp:91
3232msgid "Unpin shortcut"
3333msgstr "Eliberează scurtătura"
3434
@@ -55,45 +55,45 @@ msgstr[0] "Așteptați %1 minut și apoi încercați din nou..."
5555msgstr[1] "Așteptați %1 minute și apoi încercați din nou..."
5656msgstr[2] "Așteptați %1 de minute și apoi încercați din nou..."
5757
58−#: qml/Components/Dialogs.qml:70
58+#: qml/Components/Dialogs.qml:74
5959msgid "Log out"
6060msgstr "Închide sesiunea"
6161
62−#: qml/Components/Dialogs.qml:71
62+#: qml/Components/Dialogs.qml:75
6363msgid "Are you sure you want to log out?"
6464msgstr "Sunteți sigur că doriți să închideți sesiunea?"
6565
66−#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
67−#: qml/Components/Dialogs.qml:122
66+#: qml/Components/Dialogs.qml:77 qml/Components/Dialogs.qml:101
67+#: qml/Components/Dialogs.qml:126
6868msgid "No"
6969msgstr "Nu"
7070
71−#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
72−#: qml/Components/Dialogs.qml:129
71+#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:108
72+#: qml/Components/Dialogs.qml:133
7373msgid "Yes"
7474msgstr "Da"
7575
76−#: qml/Components/Dialogs.qml:94
76+#: qml/Components/Dialogs.qml:98
7777msgid "Shut down"
7878msgstr "Închideți"
7979
80−#: qml/Components/Dialogs.qml:95
80+#: qml/Components/Dialogs.qml:99
8181msgid "Are you sure you want to shut down?"
8282msgstr "Sunteți sigur că doriți să închideți?"
8383
84−#: qml/Components/Dialogs.qml:119
84+#: qml/Components/Dialogs.qml:123
8585msgid "Reboot"
8686msgstr "Repornire"
8787
88−#: qml/Components/Dialogs.qml:120
88+#: qml/Components/Dialogs.qml:124
8989msgid "Are you sure you want to reboot?"
9090msgstr "Sunteți sigur că doriți să reporniți?"
9191
92−#: qml/Components/Dialogs.qml:144
92+#: qml/Components/Dialogs.qml:148
9393msgid "Power"
9494msgstr "Alimentare"
9595
96−#: qml/Components/Dialogs.qml:145
96+#: qml/Components/Dialogs.qml:149
9797msgid ""
9898"Are you sure you would like\n"
9999"to power off?"
@@ -101,15 +101,15 @@ msgstr ""
101101"Sunteți sigur că doriți să\n"
102102"opriți alimentarea?"
103103
104−#: qml/Components/Dialogs.qml:147
104+#: qml/Components/Dialogs.qml:151
105105msgid "Power off"
106106msgstr "Oprire"
107107
108−#: qml/Components/Dialogs.qml:157
108+#: qml/Components/Dialogs.qml:161
109109msgid "Restart"
110110msgstr "Repornire"
111111
112−#: qml/Components/Dialogs.qml:167
112+#: qml/Components/Dialogs.qml:171
113113msgid "Cancel"
114114msgstr "Anulează"
115115
@@ -117,46 +117,46 @@ msgstr "Anulează"
117117msgid "Skip intro"
118118msgstr "Sari peste introducere"
119119
120−#: qml/Components/EdgeDemo.qml:125
120+#: qml/Components/EdgeDemo.qml:112
121121msgid "Right edge"
122122msgstr "Marginea din dreapta"
123123
124−#: qml/Components/EdgeDemo.qml:126
124+#: qml/Components/EdgeDemo.qml:113
125125msgid "Try swiping from the right edge to unlock the phone"
126126msgstr "Glisați de la dreapta spre stânga pentru a debloca telefonul"
127127
128−#: qml/Components/EdgeDemo.qml:157
128+#: qml/Components/EdgeDemo.qml:144
129129msgid "Top edge"
130130msgstr "Marginea de sus"
131131
132−#: qml/Components/EdgeDemo.qml:158
132+#: qml/Components/EdgeDemo.qml:145
133133msgid "Try swiping from the top edge to access the indicators"
134134msgstr ""
135135"Glisați de la marginea de sus a ecranului pentru a accesa indicatorii"
136136
137−#: qml/Components/EdgeDemo.qml:183
137+#: qml/Components/EdgeDemo.qml:170
138138msgid "Close"
139139msgstr "Închide"
140140
141−#: qml/Components/EdgeDemo.qml:184
141+#: qml/Components/EdgeDemo.qml:171
142142msgid "Swipe up again to close the settings screen"
143143msgstr "Glisați în sus din nou pentru a închide ecranul configurărilor"
144144
145−#: qml/Components/EdgeDemo.qml:214
145+#: qml/Components/EdgeDemo.qml:201
146146msgid "Left edge"
147147msgstr "Marginea din stânga"
148148
149−#: qml/Components/EdgeDemo.qml:215
149+#: qml/Components/EdgeDemo.qml:202
150150msgid "Swipe from the left to reveal the launcher for quick access to apps"
151151msgstr ""
152152"Glisați din stânga ecranului pentru a afișa lansatorul care oferă acces "
153153"rapid la aplicații"
154154
155−#: qml/Components/EdgeDemo.qml:242
155+#: qml/Components/EdgeDemo.qml:229
156156msgid "Well done"
157157msgstr "Felicitări"
158158
159−#: qml/Components/EdgeDemo.qml:243
159+#: qml/Components/EdgeDemo.qml:230
160160msgid ""
161161"You have now mastered the edge gestures and can start using the "
162162"phone<br><br>Tap on the screen to start"
@@ -164,44 +164,44 @@ msgstr ""
164164"De acum stăpâniți gesturile de control și puteți începe să utilizați "
165165"telefonul<br><br>Atingeți ecranul pentru a începe"
166166
167−#: qml/Components/Lockscreen.qml:238
167+#: qml/Components/Lockscreen.qml:223
168168msgid "Return to Call"
169169msgstr "Reveniți la funcția de apelare"
170170
171−#: qml/Components/Lockscreen.qml:238
171+#: qml/Components/Lockscreen.qml:223
172172msgid "Emergency Call"
173173msgstr "Apel de urgență"
174174
175−#: qml/Components/Lockscreen.qml:270
175+#: qml/Components/Lockscreen.qml:255
176176msgid "OK"
177177msgstr "În regulă"
178178
179−#: qml/Dash/GenericScopeView.qml:431 qml/Dash/GenericScopeView.qml:588
179+#: qml/Dash/GenericScopeView.qml:434 qml/Dash/GenericScopeView.qml:591
180180msgid "See less"
181181msgstr "Afișează mai puține"
182182
183−#: qml/Dash/GenericScopeView.qml:431
183+#: qml/Dash/GenericScopeView.qml:434
184184msgid "See all"
185185msgstr "Afișează tot"
186186
187−#: qml/Dash/GenericScopeView.qml:493 qml/Dash/PageHeader.qml:267
187+#: qml/Dash/GenericScopeView.qml:496 qml/Dash/PageHeader.qml:268
188188#: qml/Panel/SearchIndicator.qml:27
189189msgid "Search"
190190msgstr "Căutare"
191191
192−#: qml/Dash/PageHeader.qml:260
192+#: qml/Dash/PageHeader.qml:261
193193msgid "Store"
194194msgstr "Magazin"
195195
196−#: qml/Dash/PageHeader.qml:277
196+#: qml/Dash/PageHeader.qml:278
197197msgid "Settings"
198198msgstr "Configurări"
199199
200−#: qml/Dash/PageHeader.qml:284
200+#: qml/Dash/PageHeader.qml:285
201201msgid "Remove from Favorites"
202202msgstr "Șterge din favorite"
203203
204−#: qml/Dash/PageHeader.qml:284
204+#: qml/Dash/PageHeader.qml:285
205205msgid "Add to Favorites"
206206msgstr "Adaugă la favorite"
207207
@@ -235,15 +235,15 @@ msgstr "Eliberați pentru a actualiza..."
235235
236236#: qml/Dash/ScopesList.qml:63
237237msgid "Manage"
238−msgstr ""
238+msgstr "Administrați"
239239
240240#: qml/Dash/ScopesList.qml:107
241241msgid "Home"
242−msgstr ""
242+msgstr "Acasă"
243243
244244#: qml/Dash/ScopesList.qml:108
245245msgid "Also installed"
246−msgstr ""
246+msgstr "Alte programe instalate"
247247
248248#: qml/Greeter/Greeter.qml:174
249249msgid "Unlock"
@@ -297,49 +297,49 @@ msgstr "Deblocare SIM"
297297msgid "Roaming"
298298msgstr "Roaming"
299299
300−#: qml/Shell.qml:367
300+#: qml/Shell.qml:402
301301#, qt-format
302302msgid "Enter %1"
303303msgstr "Introducere %1"
304304
305−#: qml/Shell.qml:368 qml/Wizard/Pages/passwd-set.qml:60
305+#: qml/Shell.qml:394
306306msgid "Enter passphrase"
307307msgstr "Introduceți fraza parolă"
308308
309−#: qml/Shell.qml:369
309+#: qml/Shell.qml:398
310310msgid "Enter passcode"
311311msgstr "Introduceți parola"
312312
313−#: qml/Shell.qml:370
313+#: qml/Shell.qml:403
314314#, qt-format
315315msgid "Sorry, incorrect %1"
316316msgstr "%1 incorectă"
317317
318−#: qml/Shell.qml:371
318+#: qml/Shell.qml:395
319319msgid "Sorry, incorrect passphrase"
320320msgstr "Frază secretă incorectă"
321321
322−#: qml/Shell.qml:372
322+#: qml/Shell.qml:396
323323msgid "Please re-enter"
324324msgstr "Introduceți din nou"
325325
326−#: qml/Shell.qml:373
326+#: qml/Shell.qml:399
327327msgid "Sorry, incorrect passcode"
328328msgstr "Parolă incorectă"
329329
330−#: qml/Shell.qml:467 qml/Wizard/Pages/passwd-confirm.qml:53
330+#: qml/Shell.qml:444
331331msgid "Sorry, incorrect passphrase."
332332msgstr "Frază parolă greșită"
333333
334−#: qml/Shell.qml:468 qml/Wizard/Pages/passwd-confirm.qml:54
334+#: qml/Shell.qml:445
335335msgid "Sorry, incorrect passcode."
336336msgstr "Parolă greșită"
337337
338−#: qml/Shell.qml:469
338+#: qml/Shell.qml:446
339339msgid "This will be your last attempt."
340340msgstr "Aceasta va fi ultima încercare"
341341
342−#: qml/Shell.qml:471
342+#: qml/Shell.qml:448
343343msgid ""
344344"If passphrase is entered incorrectly, your phone will conduct a factory "
345345"reset and all personal data will be deleted."
@@ -348,7 +348,7 @@ msgstr ""
348348"configurările inițiale, ale fabricantului, iar toate datele personale vor fi "
349349"șterse."
350350
351−#: qml/Shell.qml:472
351+#: qml/Shell.qml:449
352352msgid ""
353353"If passcode is entered incorrectly, your phone will conduct a factory reset "
354354"and all personal data will be deleted."
@@ -359,98 +359,101 @@ msgstr ""
359359
360360#: qml/Wizard/Page.qml:89
361361msgid "Back"
362−msgstr ""
362+msgstr "Înapoi"
363363
364364#: qml/Wizard/Pages/10-welcome.qml:27
365365msgid "Hi!"
366−msgstr ""
366+msgstr "Salut!"
367367
368368#: qml/Wizard/Pages/10-welcome.qml:44
369369msgid "Welcome to your Ubuntu phone."
370−msgstr ""
370+msgstr "Bun venit! Acesta este telefonul dumneavoastră Ubuntu."
371371
372372#: qml/Wizard/Pages/10-welcome.qml:52
373373msgid "Let’s get started."
374−msgstr ""
374+msgstr "Să începem."
375375
376376#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
377377#: qml/Wizard/Pages/40-wifi.qml:197 qml/Wizard/Pages/50-location.qml:131
378378#: qml/Wizard/Pages/60-reporting.qml:50 qml/Wizard/Pages/passwd-confirm.qml:82
379379#: qml/Wizard/Pages/passwd-set.qml:90
380380msgid "Continue"
381−msgstr ""
381+msgstr "Continuare"
382382
383383#: qml/Wizard/Pages/20-sim.qml:25
384384msgid "Add a SIM card and restart your device"
385−msgstr ""
385+msgstr "Adăugați un card SIM și reporniți dispozitivul dumneavoastră"
386386
387387#: qml/Wizard/Pages/20-sim.qml:55
388388msgid "Without it, you won’t be able to make calls or use text messaging."
389389msgstr ""
390+"Fără acesta, nu veți putea efectua apeluri sau utiliza mesajele text."
390391
391392#: qml/Wizard/Pages/20-sim.qml:69 qml/Wizard/Pages/40-wifi.qml:197
392393msgid "Skip"
393−msgstr ""
394+msgstr "Se omite"
394395
395396#: qml/Wizard/Pages/30-passwd-type.qml:39
396397msgid "Lock security"
397−msgstr ""
398+msgstr "Blocare de securitate"
398399
399400#: qml/Wizard/Pages/30-passwd-type.qml:74
400401msgid "Please select how you’d like to unlock your phone."
401−msgstr ""
402+msgstr "Alegeți cum doriți să vă deblocați telefonul."
402403
403404#: qml/Wizard/Pages/30-passwd-type.qml:97
404405msgid "Swipe"
405−msgstr ""
406+msgstr "Glisare"
406407
407408#: qml/Wizard/Pages/30-passwd-type.qml:98
408409msgid "No security"
409−msgstr ""
410+msgstr "Fară securitate"
410411
411412#: qml/Wizard/Pages/30-passwd-type.qml:100
412413msgid "Passcode"
413−msgstr ""
414+msgstr "Cod de acces"
414415
415416#: qml/Wizard/Pages/30-passwd-type.qml:101
416417msgid "4 digits only"
417−msgstr ""
418+msgstr "Doar 4 caractere"
418419
419420#: qml/Wizard/Pages/30-passwd-type.qml:103
420421msgid "Passphrase"
421−msgstr ""
422+msgstr "Frază parolă"
422423
423424#: qml/Wizard/Pages/30-passwd-type.qml:104
424425msgid "Numbers and letters"
425−msgstr ""
426+msgstr "Numere și litere"
426427
427428#: qml/Wizard/Pages/40-wifi.qml:28
428429msgid "Connect to Wi‑Fi"
429−msgstr ""
430+msgstr "Conectare la Wi-Fi"
430431
431432#: qml/Wizard/Pages/40-wifi.qml:147
432433msgid "Available networks…"
433−msgstr ""
434+msgstr "Rețele disponibile..."
434435
435436#: qml/Wizard/Pages/40-wifi.qml:148
436437msgid "No available networks."
437−msgstr ""
438+msgstr "Nu sunt rețele disponibile."
438439
439440#: qml/Wizard/Pages/50-location.qml:27
440441msgid "Location"
441−msgstr ""
442+msgstr "Loc"
442443
443444#: qml/Wizard/Pages/50-location.qml:62
444445msgid "Let the phone detect your location:"
445−msgstr ""
446+msgstr "Permiteți telefonului să detecteze locul în care vă aflați:"
446447
447448#: qml/Wizard/Pages/50-location.qml:69
448449msgid "Using GPS only (less accurate)"
449−msgstr ""
450+msgstr "Utilizând numai GPS (mai puțin precis)"
450451
451452#: qml/Wizard/Pages/50-location.qml:86
452453msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
453454msgstr ""
455+"Utilizând GPS, rețelele fără fir în modul anonim și informațiile furnizate "
456+"de rețeaua celulară (recomandat)"
454457
455458#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
456459#: qml/Wizard/Pages/50-location.qml:103
@@ -458,81 +461,89 @@ msgid ""
458461"By selecting this option you agree to the Nokia HERE <a href='#'>terms and "
459462"conditions</a>."
460463msgstr ""
464+"Prin selectarea acestei opțiuni sunteți de acord cu <a href='#'>termenii și "
465+"condițiile</a> Nokia HERE."
461466
462467#: qml/Wizard/Pages/50-location.qml:112
463468msgid "Not at all"
464−msgstr ""
469+msgstr "Deloc"
465470
466471#: qml/Wizard/Pages/50-location.qml:124
467472msgid "You can change your mind later in <b>System Settings</b>."
468473msgstr ""
474+"Puteți să modificați opțiunea utilizând <b>Configurări de sistem</b>."
469475
470476#: qml/Wizard/Pages/60-reporting.qml:24
471477msgid "Improving your experience"
472−msgstr ""
478+msgstr "Îmbunătățirea experienței în utilizare"
473479
474480#: qml/Wizard/Pages/60-reporting.qml:36
475481msgid ""
476482"Your phone is set up to automatically report errors to Canonical and its "
477483"partners, the makers of the operating system."
478484msgstr ""
485+"Telefonul dumneavoastră este configurat să trimită în mod automat rapoarte "
486+"de erori către Canonical și partenerii săi, producătorii sistemului de "
487+"operare."
479488
480489#: qml/Wizard/Pages/60-reporting.qml:43
481490msgid ""
482491"This can be disabled in <b>System Settings</b> under <b>Security &amp; "
483492"Privacy</b>"
484493msgstr ""
494+"Acest comportament poate fi dezactivat din <b>Configurări de sistem</b> "
495+"ramura <b>Securitate și confidențialitate</b>"
485496
486497#: qml/Wizard/Pages/80-finished.qml:24
487498msgid "All done"
488−msgstr ""
499+msgstr "Efectuat"
489500
490501#: qml/Wizard/Pages/80-finished.qml:39
491502msgid "Nice work!"
492−msgstr ""
503+msgstr "Bună treabă!"
493504
494505#: qml/Wizard/Pages/80-finished.qml:46
495506msgid "Your phone is now ready to use."
496−msgstr ""
507+msgstr "Telefonul dumneavoastră este gata de utilizare."
497508
498509#: qml/Wizard/Pages/80-finished.qml:53
499510msgid "Finish"
500−msgstr ""
511+msgstr "Sfârșit"
501512
502513#: qml/Wizard/Pages/here-terms.qml:27
503514msgid "Terms & Conditions"
504−msgstr ""
515+msgstr "Termeni și condiții"
505516
506517#: qml/Wizard/Pages/passwd-confirm.qml:49
507518msgid "Confirm passphrase"
508−msgstr ""
519+msgstr "Confirmați frază parolă"
509520
510521#: qml/Wizard/Pages/passwd-confirm.qml:50
511522msgid "Confirm passcode"
512−msgstr ""
523+msgstr "Confirmați codul de acces"
513524
514525#: qml/Wizard/Pages/passwd-confirm.qml:53
515526#: qml/Wizard/Pages/passwd-confirm.qml:54
516527msgid "Please try again."
517−msgstr ""
528+msgstr "Vă rugăm să încercați din nou."
518529
519530#: qml/Wizard/Pages/passwd-set.qml:61
520531msgid "Choose your passcode"
521−msgstr ""
532+msgstr "Alegeți codul dumneavoastră de acces"
522533
523534#: qml/Wizard/Pages/passwd-set.qml:68
524535msgid "Passphrase must be 4 characters long"
525−msgstr ""
536+msgstr "Codul de acces trebuie să conțină 4 caractere"
526537
527538#: qml/Wizard/StackButton.qml:39
528539#, qt-format
529540msgid "〈 %1"
530−msgstr ""
541+msgstr "〈 %1"
531542
532543#: qml/Wizard/StackButton.qml:42
533544#, qt-format
534545msgid "%1 〉"
535−msgstr ""
546+msgstr "%1 〉"
536547
537548#~ msgid "Confirm"
538549#~ msgstr "Confirmați"
qml/Dash/Dash.qml+4−10
@@ -36,9 +36,8 @@ Showable {
3636 dashContent.setCurrentScopeAtIndex(index, animate, isSwipe)
3737 // Close dash overview and nested temp scopes in it
3838 if (bottomEdgeController.progress != 0) {
39− bottomEdgeController.enableAnimation = window.active && !scopesOverview.showingNonFavoriteScope;
39+ bottomEdgeController.enableAnimation = window.active;
4040 bottomEdgeController.progress = 0;
41− scopesOverview.closeTempScope();
4241 }
4342 // Close normal temp scopes (e.g. App Store)
4443 if (scopeItem.scope) {
@@ -335,28 +334,23 @@ Showable {
335334 height: units.gu(2)
336335
337336 onSceneDistanceChanged: {
338− if (status == DirectionalDragArea.Recognized && initialSceneDistance != -1) {
337+ if (status == DirectionalDragArea.Recognized) {
339338 bottomEdgeController.enableAnimation = false;
340− var deltaDistance = sceneDistance - initialSceneDistance;
341− bottomEdgeController.progress = Math.max(0, Math.min(1, deltaDistance / fullMovement));
339+ bottomEdgeController.progress = Math.max(0, Math.min(1, sceneDistance / fullMovement));
342340 }
343341 }
344342
345343 property int previousStatus: -1
346344 property int currentStatus: DirectionalDragArea.WaitingForTouch
347− property real initialSceneDistance: -1
348345
349346 onStatusChanged: {
350347 previousStatus = currentStatus;
351348 currentStatus = status;
352349
353− if (status == DirectionalDragArea.Recognized) {
354− initialSceneDistance = sceneDistance;
355− } else if (status == DirectionalDragArea.WaitingForTouch &&
350+ if (status == DirectionalDragArea.WaitingForTouch &&
356351 previousStatus == DirectionalDragArea.Recognized) {
357352 bottomEdgeController.enableAnimation = true;
358353 bottomEdgeController.progress = (bottomEdgeController.progress > 0.2) ? 1 : 0;
359− initialSceneDistance = -1;
360354 }
361355 }
362356 }
qml/Dash/DashContent.qml+2−2
@@ -113,7 +113,7 @@ Item {
113113 objectName: "dashContentList"
114114
115115 interactive: !dashContent.forceNonInteractive && dashContent.scopes.loaded && currentItem
116− && !currentItem.moving && !currentItem.navigationShown && !currentItem.subPageShown
116+ && !currentItem.moving && !currentItem.navigationDisableParentInteractive && !currentItem.subPageShown
117117 anchors.fill: parent
118118 orientation: ListView.Horizontal
119119 boundsBehavior: Flickable.DragAndOvershootBounds
@@ -175,7 +175,7 @@ Item {
175175 objectName: "scopeLoader" + index
176176
177177 readonly property bool moving: item ? item.moving : false
178− readonly property bool navigationShown: item ? item.navigationShown : false
178+ readonly property bool navigationDisableParentInteractive: item ? item.navigationDisableParentInteractive : false
179179 readonly property bool subPageShown: item ? item.subPageShown : false
180180 readonly property var categoryView: item ? item.categoryView : null
181181 readonly property var theScope: scope
qml/Dash/DashNavigation.qml+4
@@ -33,6 +33,10 @@ Item {
3333 if (altNavigationButton.showList) return altNavigationButton.listView;
3434 return null;
3535 }
36+ readonly property bool disableParentInteractive: {
37+ return navigationButton.showList || altNavigationButton.showList ||
38+ navigationButton.inverseMousePressed || altNavigationButton.inverseMousePressed;
39+ }
3640
3741 // FIXME this is only here for highlight purposes (see Background.qml, too)
3842 readonly property var background: backgroundItem
qml/Dash/DashNavigationButton.qml+2
@@ -31,6 +31,7 @@ AbstractButton {
3131 // Used by parent
3232 readonly property var currentNavigation: scope && scope[hasNavigation] ? getNavigation(scope[currentNavigationId]) : null
3333 readonly property alias listView: navigationListView
34+ readonly property bool inverseMousePressed: inverseMouseArea.pressed
3435 property bool showList: false
3536
3637 // Internal
@@ -210,6 +211,7 @@ AbstractButton {
210211 onCurrentNavigationChanged: setNewNavigation();
211212
212213 InverseMouseArea {
214+ id: inverseMouseArea
213215 anchors.fill: navigationListView
214216 enabled: root.showList
215217 onPressed: root.showList = false
qml/Dash/GenericScopeView.qml+3−3
@@ -25,10 +25,10 @@ import "../Components/ListItems" as ListItems
2525FocusScope {
2626 id: scopeView
2727
28− readonly property bool navigationShown: pageHeaderLoader.item ? pageHeaderLoader.item.bottomItem[0].openList : false
28+ readonly property bool navigationDisableParentInteractive: pageHeaderLoader.item ? pageHeaderLoader.item.bottomItem[0].disableParentInteractive : false
2929 property bool forceNonInteractive: false
3030 property var scope: null
31− property SortFilterProxyModel categories: categoryFilter
31+ property UnitySortFilterProxyModel categories: categoryFilter
3232 property bool isCurrent: false
3333 property alias moving: categoryView.moving
3434 property bool hasBackAction: false
@@ -106,7 +106,7 @@ FocusScope {
106106 value: isCurrent && !subPageLoader.open
107107 }
108108
109− SortFilterProxyModel {
109+ UnitySortFilterProxyModel {
110110 id: categoryFilter
111111 model: scope ? scope.categories : null
112112 dynamicSortFilter: true
qml/Dash/ScopesList.qml+1
@@ -65,6 +65,7 @@ Item {
6565 objectName: "pageHeader"
6666 title: i18n.tr("Manage")
6767 width: parent.width
68+ clip: true
6869 showBackButton: true
6970 backIsClose: root.state == "edit"
7071 storeEntryEnabled: root.state == "browse"
qml/Greeter/Clock.qml+1−1
@@ -53,7 +53,7 @@ Item {
5353 menuObjectPath: clock.visible ? "/com/canonical/indicator/datetime/phone" : ""
5454 }
5555
56− Indicators.RootActionState {
56+ Indicators.ModelActionRootState {
5757 menu: timeModel.model
5858 onUpdated: {
5959 if (timeLabel.text != rightLabel) {
qml/Greeter/Infographics.qml+9−7
@@ -127,7 +127,7 @@ Item {
127127
128128 index: model.index
129129 count: pastCircles.count
130− radius: parent.width / 2
130+ radius: dataCircle.width / 2
131131 halfSize: pastCircle.width / 2
132132 posOffset: 0.0
133133
@@ -187,7 +187,7 @@ Item {
187187
188188 index: model.index
189189 count: presentCircles.count
190− radius: parent.width / 2
190+ radius: dataCircle.width / 2
191191 halfSize: presentCircle.width / 2
192192 posOffset: 0.0
193193
@@ -255,14 +255,16 @@ Item {
255255 interval: animDuration * 0.5; running: false; repeat: true
256256 onTriggered: {
257257 if (dotCounter < dots.count) {
258− var nextDot = dots.itemAt(dotCounter++)
259− nextDot.unlockAnimation.start()
258+ var nextDot = dots.itemAt(dotCounter);
259+ if (nextDot) {
260+ nextDot.unlockAnimation.start();
261+ if (++dotCounter == Math.round(dots.count / 2)) {
262+ circleChangeAnimTimer.startFromBeginning();
263+ }
264+ }
260265 } else {
261266 stop()
262267 }
263− if (dotCounter == Math.round(dots.count / 2)) {
264− circleChangeAnimTimer.startFromBeginning()
265− }
266268 }
267269
268270 function startFromBeginning() {
qml/Notifications/Notifications.qml+1−1
@@ -29,7 +29,7 @@ ListView {
2929 property real margin
3030 property bool useModal: snapDecisionProxyModel.count > 0
3131
32− SortFilterProxyModel {
32+ UnitySortFilterProxyModel {
3333 id: snapDecisionProxyModel
3434 objectName: "snapDecisionProxyModel"
3535
qml/Panel/IndicatorItem.qml−8
@@ -45,14 +45,6 @@ IndicatorDelegate {
4545 onClicked: parent.clicked()
4646 }
4747
48− // FIXME: For now we will enable led indicator support only for messaging indicator
49− // in the future we should export a led API insted of doing that,
50− Loader {
51− id: indicatorLed
52− // only load source Component if the icons contains the new message icon
53− source: (root.icons && (String(root.icons).indexOf("indicator-messages-new") != -1)) ? Qt.resolvedUrl("Indicators/IndicatorsLight.qml") : ""
54− }
55−
5648 Item {
5749 id: mainItems
5850 anchors.centerIn: parent
qml/Panel/Indicators/IndicatorBase.qml+1−1
@@ -40,7 +40,7 @@ Item {
4040 menuObjectPath: indicatorItem.menuObjectPath
4141 }
4242
43− RootActionState {
43+ ModelActionRootState {
4444 id: rootAction
4545 menu: menuModel ? menuModel : null
4646 onUpdated: indicatorItem.rootActionStateChanged()
qml/Panel/Indicators/IndicatorsLight.qml+19−1
@@ -20,16 +20,34 @@
2020import QtQuick 2.0
2121import Powerd 0.1
2222import Lights 0.1
23+import QMenuModel 0.1 as QMenuModel
24+import Unity.Indicators 0.1 as Indicators
2325
2426QtObject {
2527 id: root
2628
29+ property var _actionGroup: QMenuModel.QDBusActionGroup {
30+ busType: 1
31+ busName: "com.canonical.indicator.messages"
32+ objectPath: "/com/canonical/indicator/messages"
33+ }
34+
35+ property var _rootState: Indicators.ActionRootState {
36+ actionGroup: _actionGroup
37+ actionName: "messages"
38+ Component.onCompleted: actionGroup.start()
39+
40+ property bool hasMessages: valid && (String(icons).indexOf("indicator-messages-new") != -1)
41+ }
42+
2743 Component.onDestruction: Lights.state = Lights.Off
2844
2945 // QtObject does not have children
3046 property var _binding: Binding {
3147 target: Lights
3248 property: "state"
33− value: (Powerd.status === Powerd.Off) ? Lights.On : Lights.Off
49+ value: {
50+ return (Powerd.status === Powerd.Off && _rootState.hasMessages) ? Lights.On : Lights.Off
51+ }
3452 }
3553}
qml/Panel/Indicators/VisibleIndicators.qml+2−2
@@ -22,13 +22,13 @@ import Unity.Indicators 0.1 as Indicators
2222import Utils 0.1
2323
2424Item {
25− property SortFilterProxyModel model: filterModel
25+ property UnitySortFilterProxyModel model: filterModel
2626
2727 function initialise(profile) {
2828 indicatorsModel.load(profile);
2929 }
3030
31− SortFilterProxyModel {
31+ UnitySortFilterProxyModel {
3232 id: filterModel
3333 filterRole: Indicators.IndicatorsModelRole.IsVisible
3434 filterRegExp: RegExp("^true$")
qml/Panel/IndicatorsMenu.qml+5
@@ -18,6 +18,7 @@ import QtQuick 2.2
1818import Ubuntu.Components 1.1
1919import Ubuntu.Gestures 0.1
2020import "../Components"
21+import "Indicators"
2122
2223Showable {
2324 id: root
@@ -60,6 +61,10 @@ Showable {
6061 onUnitProgressChanged: d.updateState()
6162 clip: root.partiallyOpened
6263
64+ IndicatorsLight {
65+ id: indicatorLights
66+ }
67+
6368 // eater
6469 MouseArea {
6570 anchors.fill: parent
qml/Shell.qml+21−3
@@ -323,7 +323,7 @@ Item {
323323 id: inputMethod
324324 objectName: "inputMethod"
325325 anchors { fill: parent; topMargin: panel.panelHeight }
326− z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
326+ z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
327327 }
328328
329329 Connections {
@@ -400,7 +400,7 @@ Item {
400400
401401 function maybeShow() {
402402 if (!shell.forcedUnlock) {
403− show()
403+ showNow();
404404 }
405405 }
406406
@@ -594,6 +594,15 @@ Item {
594594 enabled = true;
595595 }
596596
597+ Timer {
598+ // See powerConnection for why this is useful
599+ id: showGreeterDelayed
600+ interval: 1
601+ onTriggered: {
602+ greeter.showNow();
603+ }
604+ }
605+
597606 onShownChanged: {
598607 if (shown) {
599608 // Disable everything so that user can't swipe greeter or
@@ -664,7 +673,16 @@ Item {
664673 onStatusChanged: {
665674 if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity &&
666675 !callManager.hasCalls && !edgeDemo.running) {
667− greeter.showNow()
676+ // We don't want to simply call greeter.showNow() here, because
677+ // that will take too long. Qt will delay button event
678+ // handling until the greeter is done loading and may think the
679+ // user held down the power button the whole time, leading to a
680+ // power dialog being shown. Instead, delay showing the
681+ // greeter until we've finished handling the event. We could
682+ // make the greeter load asynchronously instead, but that
683+ // introduces a whole host of timing issues, especially with
684+ // its animations. So this is simpler.
685+ showGreeterDelayed.start();
668686 }
669687 }
670688 }
src/main.cpp−6
@@ -147,12 +147,6 @@ Load the testability driver");
147147 view->setSource(source);
148148 QObject::connect(view->engine(), SIGNAL(quit()), application, SLOT(quit()));
149149
150− if (!isMirServer && qEnvironmentVariableIsSet("UNITY_MIR_EMITS_SIGSTOP")) {
151− // Emit SIGSTOP as expected by upstart, under Mir it's qtmir that will raise it.
152− // see http://upstart.ubuntu.com/cookbook/#expect-stop
153− raise(SIGSTOP);
154− }
155−
156150 if (isMirServer || parser.isSet(fullscreenOption)) {
157151 view->showFullScreen();
158152 } else {
tests/autopilot/unity8/shell/emulators/create_interactive_notification.py−1
@@ -88,7 +88,6 @@ if __name__ == '__main__':
8888 action_id,
8989 action_label,
9090 action_callback,
91− None,
9291 None
9392 )
9493
tests/autopilot/unity8/shell/emulators/edges_demo.pynew file+140
@@ -0,0 +1,140 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2014 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+import logging
21+import time
22+
23+import ubuntuuitoolkit
24+
25+import autopilot
26+from autopilot import introspection
27+
28+
29+logger = logging.getLogger(__name__)
30+
31+
32+class RightEdgeDemoOverlay(
33+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
34+
35+ @classmethod
36+ def validate_dbus_object(cls, path, state):
37+ name = introspection.get_classname_from_path(path)
38+ if name == b'EdgeDemoOverlay':
39+ if state['edge'][1] == 'right':
40+ return True
41+ return False
42+
43+ @autopilot.logging.log_action(logger.info)
44+ def swipe(self):
45+ """Swipe to the left to complete this demo step."""
46+ x, y, width, height = self.globalRect
47+ start_x = x + width
48+ stop_x = x
49+ start_y = stop_y = y + height // 2
50+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
51+ return self.get_root_instance().wait_select_single(
52+ edge='top', active=True)
53+
54+
55+class TopEdgeDemoOverlay(
56+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
57+
58+ @classmethod
59+ def validate_dbus_object(cls, path, state):
60+ name = introspection.get_classname_from_path(path)
61+ if name == b'EdgeDemoOverlay':
62+ if state['edge'][1] == 'top':
63+ return True
64+ return False
65+
66+ @autopilot.logging.log_action(logger.info)
67+ def swipe(self):
68+ """Swipe to the bottom to complete this demo step."""
69+ x, y, width, height = self.globalRect
70+ start_x = stop_x = x + width // 2
71+ start_y = y
72+ stop_y = y + height
73+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
74+ return self.get_root_instance().wait_select_single(
75+ edge='bottom', active=True)
76+
77+
78+class BottomEdgeDemoOverlay(
79+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
80+
81+ @classmethod
82+ def validate_dbus_object(cls, path, state):
83+ name = introspection.get_classname_from_path(path)
84+ if name == b'EdgeDemoOverlay':
85+ if state['edge'][1] == 'bottom':
86+ return True
87+ return False
88+
89+ @autopilot.logging.log_action(logger.info)
90+ def swipe(self):
91+ """Swipe to the top to complete this demo step."""
92+ x, y, width, height = self.globalRect
93+ start_x = stop_x = x + width // 2
94+ start_y = y + height
95+ stop_y = y
96+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
97+ return self.get_root_instance().wait_select_single(
98+ edge='left', active=True)
99+
100+
101+class LeftEdgeDemoOverlay(
102+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
103+
104+ @classmethod
105+ def validate_dbus_object(cls, path, state):
106+ name = introspection.get_classname_from_path(path)
107+ if name == b'EdgeDemoOverlay':
108+ if state['edge'][1] == 'left':
109+ return True
110+ return False
111+
112+ @autopilot.logging.log_action(logger.info)
113+ def swipe(self):
114+ """Swipe to the right to complete this demo step."""
115+ x, y, width, height = self.globalRect
116+ start_x = x
117+ stop_x = x + width
118+ start_y = stop_y = y + height // 2
119+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
120+ return self.get_root_instance().wait_select_single(
121+ edge='none', active=True)
122+
123+
124+class FinalEdgeDemoOverlay(
125+ ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
126+
127+ @classmethod
128+ def validate_dbus_object(cls, path, state):
129+ name = introspection.get_classname_from_path(path)
130+ if name == b'EdgeDemoOverlay':
131+ if state['edge'][1] == 'none':
132+ return True
133+ return False
134+
135+ @autopilot.logging.log_action(logger.info)
136+ def tap_to_start(self):
137+ """Tap to finish the demo and start using the Ubuntu Touch."""
138+ time.sleep(1)
139+ self.pointing_device.click_object(self)
140+ self.shown.wait_for(False)
tests/autopilot/unity8/shell/fixture_setup.py+38
@@ -20,6 +20,7 @@
2020"""Set up and clean up fixtures for the Unity acceptance tests."""
2121
2222import os
23+import subprocess
2324import sysconfig
2425
2526import fixtures
@@ -51,3 +52,40 @@ class FakeScopes(fixtures.Fixture):
5152 'Expected library path does not exists: %s.' % (
5253 ld_library_path))
5354 return ld_library_path
55+
56+
57+class EdgesDemo(fixtures.Fixture):
58+
59+ def __init__(self, enable):
60+ super().__init__()
61+ self.enable = enable
62+
63+ def setUp(self):
64+ super().setUp()
65+ original_state = self._is_edges_demo_enabled()
66+ if self.enable != original_state:
67+ self.addCleanup(self._set_edges_demo, original_state)
68+ self._set_edges_demo(self.enable)
69+
70+ def _is_edges_demo_enabled(self):
71+ command = [
72+ 'dbus-send', '--system', '--print-reply',
73+ '--dest=org.freedesktop.Accounts',
74+ '/org/freedesktop/Accounts/User32011',
75+ 'org.freedesktop.DBus.Properties.Get',
76+ 'string:com.canonical.unity.AccountsService',
77+ 'string:demo-edges'
78+ ]
79+ output = subprocess.check_output(command, universal_newlines=True)
80+ return True if output.count('true') else False
81+
82+ def _set_edges_demo(self, value):
83+ value_string = 'true' if value else 'false'
84+ command = [
85+ 'dbus-send', '--system', '--print-reply',
86+ '--dest=com.canonical.PropertyService',
87+ '/com/canonical/PropertyService',
88+ 'com.canonical.PropertyService.SetProperty',
89+ 'string:edge', 'boolean:{}'.format(value_string)
90+ ]
91+ subprocess.check_output(command)
tests/autopilot/unity8/shell/tests/test_edges_demo.pynew file+52
@@ -0,0 +1,52 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2014 Canonical
5+#
6+# This program is free software: you can redistribute it and/or modify
7+# it under the terms of the GNU General Public License as published by
8+# the Free Software Foundation, either version 3 of the License, or
9+# (at your option) any later version.
10+#
11+# This program is distributed in the hope that it will be useful,
12+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+# GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License
17+# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+#
19+
20+from autopilot.matchers import Eventually
21+from testtools.matchers import Equals
22+
23+from unity8.shell import (
24+ fixture_setup,
25+ tests
26+)
27+# unused import to load the edge emulators custom proxy objects.
28+from unity8.shell.emulators import edges_demo # NOQA
29+
30+
31+class EdgesDemoTestCase(tests.UnityTestCase):
32+
33+ def setUp(self):
34+ super().setUp()
35+ self._qml_mock_enabled = False
36+ self._data_dirs_mock_enabled = False
37+ self._lightdm_mock_type = False
38+
39+ self.useFixture(fixture_setup.EdgesDemo(True))
40+ self.unity = self.launch_unity()
41+
42+ def test_complete_edge_demo(self):
43+ edge_demo = self.unity.select_single('EdgeDemo')
44+ self.assertThat(edge_demo.running, Eventually(Equals(True)))
45+ right_edge_overlay = self.unity.wait_select_single(
46+ edge='right', active=True)
47+ top_edge_overlay = right_edge_overlay.swipe()
48+ bottom_edge_overlay = top_edge_overlay.swipe()
49+ left_edge_overlay = bottom_edge_overlay.swipe()
50+ final_overlay = left_edge_overlay.swipe()
51+ final_overlay.tap_to_start()
52+ self.assertThat(edge_demo.running, Eventually(Equals(False)))
tests/mocks/CMakeLists.txt+1
@@ -32,6 +32,7 @@ add_subdirectory(AccountsService)
3232add_subdirectory(GSettings.1.0)
3333add_subdirectory(libusermetrics)
3434add_subdirectory(LightDM)
35+add_subdirectory(Lights)
3536add_subdirectory(MeeGo)
3637add_subdirectory(Powerd)
3738add_subdirectory(QMenuModel)
tests/mocks/LightDM/CMakeLists.txt+1−1
@@ -24,7 +24,7 @@ set(QMLPLUGIN_SRC
2424 ${CMAKE_SOURCE_DIR}/plugins/LightDM/Greeter.cpp
2525 ${CMAKE_SOURCE_DIR}/plugins/LightDM/plugin.cpp
2626 ${CMAKE_SOURCE_DIR}/plugins/LightDM/UsersModel.cpp
27− ${CMAKE_SOURCE_DIR}/plugins/Utils/qsortfilterproxymodelqml.cpp
27+ ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
2828 )
2929
3030add_library(MockLightDM-qml MODULE
tests/mocks/LightDM/Greeter.cpp+6
@@ -129,6 +129,12 @@ void Greeter::authenticate(const QString &username)
129129 d->authenticated = false;
130130 d->authenticationUser = username;
131131 d->twoFactorDone = false;
132+ QTimer::singleShot(0, this, SLOT(delayedAuthentication()));
133+}
134+
135+void Greeter::delayedAuthentication()
136+{
137+ Q_D(Greeter);
132138 d->handleAuthenticate();
133139}
134140
tests/mocks/LightDM/Greeter.h+3
@@ -99,6 +99,9 @@ Q_SIGNALS:
9999protected:
100100 void sendAuthenticationComplete();
101101
102+private Q_SLOTS:
103+ void delayedAuthentication();
104+
102105private:
103106 GreeterPrivate *d_ptr;
104107 Q_DECLARE_PRIVATE(Greeter)
tests/mocks/Lights/CMakeLists.txtnew file+8
@@ -0,0 +1,8 @@
1+add_library(MockLights-qml MODULE
2+ plugin.cpp
3+ Lights.cpp
4+ )
5+
6+qt5_use_modules(MockLights-qml Qml Gui)
7+
8+add_unity8_mock(Lights 0.1 Lights TARGETS MockLights-qml)
tests/mocks/Lights/Lights.cppnew file+84
@@ -0,0 +1,84 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "Lights.h"
18+
19+#include <QDebug>
20+
21+Lights::Lights(QObject* parent)
22+ : QObject(parent),
23+ m_color("blue"),
24+ m_state(Lights::Off),
25+ m_onMs(1000),
26+ m_offMs(3000)
27+{
28+}
29+
30+Lights::~Lights()
31+{
32+}
33+
34+void Lights::setState(Lights::State newState)
35+{
36+ if (m_state != newState) {
37+ m_state = newState;
38+ Q_EMIT stateChanged(m_state);
39+ }
40+}
41+
42+Lights::State Lights::state() const
43+{
44+ return m_state;
45+}
46+
47+void Lights::setColor(const QColor &color)
48+{
49+ if (m_color != color) {
50+ m_color = color;
51+ Q_EMIT colorChanged(m_color);
52+ }
53+}
54+
55+QColor Lights::color() const
56+{
57+ return m_color;
58+}
59+
60+int Lights::onMillisec() const
61+{
62+ return m_onMs;
63+}
64+
65+void Lights::setOnMillisec(int onMs)
66+{
67+ if (m_onMs != onMs) {
68+ m_onMs = onMs;
69+ Q_EMIT onMillisecChanged(m_onMs);
70+ }
71+}
72+
73+int Lights::offMillisec() const
74+{
75+ return m_offMs;
76+}
77+
78+void Lights::setOffMillisec(int offMs)
79+{
80+ if (m_offMs != offMs) {
81+ m_offMs = offMs;
82+ Q_EMIT offMillisecChanged(m_offMs);
83+ }
84+}
tests/mocks/Lights/Lights.hnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef UNITY_MOCK_LIGHTS_H
18+#define UNITY_MOCK_LIGHTS_H
19+
20+#include <QtCore/QObject>
21+#include <QtGui/QColor>
22+
23+class Lights: public QObject
24+{
25+ Q_OBJECT
26+ Q_ENUMS(State)
27+ Q_PROPERTY(State state READ state WRITE setState NOTIFY stateChanged)
28+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
29+ Q_PROPERTY(int onMillisec READ onMillisec WRITE setOnMillisec NOTIFY onMillisecChanged)
30+ Q_PROPERTY(int offMillisec READ offMillisec WRITE setOffMillisec NOTIFY offMillisecChanged)
31+
32+public:
33+ enum State {
34+ Off,
35+ On,
36+ };
37+
38+ explicit Lights(QObject *parent = 0);
39+ ~Lights();
40+
41+ void setState(State newState);
42+ State state() const;
43+
44+ void setColor(const QColor &color);
45+ QColor color() const;
46+
47+ int onMillisec() const;
48+ void setOnMillisec(int onMs);
49+
50+ int offMillisec() const;
51+ void setOffMillisec(int offMs);
52+
53+Q_SIGNALS:
54+ void stateChanged(State newState);
55+ void colorChanged(const QColor &color);
56+ void onMillisecChanged(int onMs);
57+ void offMillisecChanged(int offMs);
58+
59+private:
60+ QColor m_color;
61+ State m_state;
62+ int m_onMs;
63+ int m_offMs;
64+};
65+
66+#endif
tests/mocks/Lights/Lights.qmltypesnew file+45
@@ -0,0 +1,45 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable Lights 0.1 tests/mocks'
8+
9+Module {
10+ Component {
11+ name: "Lights"
12+ prototype: "QObject"
13+ exports: ["Lights/Lights 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Enum {
18+ name: "State"
19+ values: {
20+ "Off": 0,
21+ "On": 1
22+ }
23+ }
24+ Property { name: "state"; type: "State" }
25+ Property { name: "color"; type: "QColor" }
26+ Property { name: "onMillisec"; type: "int" }
27+ Property { name: "offMillisec"; type: "int" }
28+ Signal {
29+ name: "stateChanged"
30+ Parameter { name: "newState"; type: "State" }
31+ }
32+ Signal {
33+ name: "colorChanged"
34+ Parameter { name: "color"; type: "QColor" }
35+ }
36+ Signal {
37+ name: "onMillisecChanged"
38+ Parameter { name: "onMs"; type: "int" }
39+ }
40+ Signal {
41+ name: "offMillisecChanged"
42+ Parameter { name: "offMs"; type: "int" }
43+ }
44+ }
45+}
tests/mocks/Lights/plugin.cppnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "plugin.h"
18+#include "Lights.h"
19+
20+#include <QtQml/qqml.h>
21+
22+static QObject *lights_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
23+{
24+ Q_UNUSED(engine)
25+ Q_UNUSED(scriptEngine)
26+ return new Lights();
27+}
28+
29+void PowerdPlugin::registerTypes(const char *uri)
30+{
31+ Q_ASSERT(uri == QLatin1String("Lights"));
32+ qmlRegisterSingletonType<Lights>(uri, 0, 1, "Lights", lights_provider);
33+}
tests/mocks/Lights/plugin.hnew file+32
@@ -0,0 +1,32 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MOCK_POWER_PLUGIN_H
18+#define MOCK_POWER_PLUGIN_H
19+
20+#include <QtQml/QQmlEngine>
21+#include <QtQml/QQmlExtensionPlugin>
22+
23+class PowerdPlugin : public QQmlExtensionPlugin
24+{
25+ Q_OBJECT
26+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
27+
28+public:
29+ void registerTypes(const char *uri);
30+};
31+
32+#endif
tests/mocks/Lights/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module Lights
2+plugin MockLights-qml
3+typeinfo Lights.qmltypes
tests/mocks/QMenuModel/CMakeLists.txt+1
@@ -4,6 +4,7 @@ include_directories(
44)
55
66set(QMenuModelQml_SOURCES
7+ actiondata.h
78 actionstateparser.cpp
89 dbus-enums.h
910 plugin.cpp
tests/mocks/QMenuModel/QDBusActionGroup.qml+20−67
@@ -19,81 +19,34 @@
1919
2020import QtQuick 2.0
2121import Ubuntu.Settings.Menus 0.1 as Menus
22+import QMenuModel 0.1
2223
2324QtObject {
2425 id: actionGroup
2526 property int busType
2627 property string busName
2728 property string objectPath
29+ property var actions: ActionData ? ActionData.data : undefined
30+
31+ signal dataChanged
32+
2833 function start() {}
34+
2935 function action(actionName) {
30− switch (actionName) {
31− case "transfer-state.queued":
32− return {
33− 'valid': true,
34− 'state': {
35− 'state': Menus.TransferState.Queued,
36− 'percent': 0.0
37− }
38− }
39− case "transfer-state.running":
40− return {
41− 'valid': true,
42− 'state': {
43− 'state': Menus.TransferState.Running,
44− 'seconds-left': 100,
45− 'percent': 0.1
46− }
47− }
48− case "transfer-state.paused":
49− return {
50− 'valid': true,
51− 'state': {
52− 'state': Menus.TransferState.Paused,
53− 'seconds-left': 100,
54− 'percent': 0.5
55− }
56− }
57− case "transfer-state.cancelled":
58− return {
59− 'valid': true,
60− 'state': {
61− 'state': Menus.TransferState.Canceled,
62− 'percent': 0.4
63− }
64− }
65− case "transfer-state.finished": return {
66− 'valid': true,
67− 'state': {
68− 'state': Menus.TransferState.Finished,
69− 'seconds-left': 0,
70− 'percent': 1.0
71− }
72− }
73− case "transfer-state.error":
74− return {
75− 'valid': true,
76− 'state': {
77− 'state': Menus.TransferState.Error,
78− 'seconds-left': 100,
79− 'percent': 0.0
80− }
81− }
82− case "gps-detection-enabled":
83− case "location-detection-enabled":
84− return Qt.createQmlObject("
85−import QtQuick 2.3
86−QtObject {
87− property bool valid: true
88− property bool state: false
89− function activate() {
90− state = !state;
91− }
92−}", actionGroup);
93− default:
94− break;
95− }
36+ return Qt.createQmlObject("
37+ import QtQuick 2.3
38+ import QMenuModel 0.1
39+
40+ QtObject {
41+ signal activated
42+
43+ property string actionName: \"" + actionName + "\"
44+ property bool valid: ActionData.data[actionName] != undefined ? ActionData.data[actionName].valid : false
45+ property var state: ActionData.data[actionName] != undefined ? ActionData.data[actionName].state : undefined
9646
97− return null;
47+ function activate() {
48+ activated();
49+ }
50+ }", actionGroup);
9851 }
9952}
tests/mocks/QMenuModel/actiondata.hnew file+52
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef ACTIONDATA_H
20+#define ACTIONDATA_H
21+
22+#include <QObject>
23+#include <QVariant>
24+
25+typedef struct _GVariant GVariant;
26+
27+class Q_DECL_EXPORT ActionData : public QObject
28+{
29+ Q_OBJECT
30+ Q_PROPERTY(QVariant data READ data WRITE setData NOTIFY dataChanged)
31+public:
32+ ActionData(QObject* parent = 0)
33+ : QObject(parent)
34+ {}
35+
36+ QVariant data() const { return m_data; }
37+ void setData(const QVariant& data)
38+ {
39+ if (m_data != data) {
40+ m_data = data;
41+ Q_EMIT dataChanged();
42+ }
43+ }
44+
45+Q_SIGNALS:
46+ void dataChanged();
47+
48+private:
49+ QVariant m_data;
50+};
51+
52+#endif // ACTIONDATA_H
tests/mocks/QMenuModel/plugin.cpp+10
@@ -18,11 +18,19 @@
1818
1919#include "plugin.h"
2020#include "unitymenumodel.h"
21+#include "actiondata.h"
2122#include "actionstateparser.h"
2223#include "dbus-enums.h"
2324
2425#include <QtQml/qqml.h>
2526
27+static QObject* actionDataSingleton(QQmlEngine* engine, QJSEngine* scriptEngine)
28+{
29+ Q_UNUSED(engine);
30+ Q_UNUSED(scriptEngine);
31+ return new ActionData;
32+}
33+
2634void QMenuModelPlugin::registerTypes(const char *uri)
2735{
2836 Q_ASSERT(uri == QLatin1String("QMenuModel"));
@@ -30,4 +38,6 @@ void QMenuModelPlugin::registerTypes(const char *uri)
3038 "DBus is only a namespace");
3139 qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
3240 qmlRegisterType<ActionStateParser>(uri, 0, 1, "ActionStateParser");
41+
42+ qmlRegisterSingletonType<ActionData>(uri, 0, 1, "ActionData", actionDataSingleton);
3343}
tests/mocks/Unity/Indicators/ActionRootState.qmlnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+
22+QtObject {
23+ property var actionGroup
24+ property var actionName
25+
26+ property var action: actionGroup ? actionGroup.actions[actionName] : undefined
27+ property var state: action && action.hasOwnProperty("state") ? action.state : undefined
28+
29+ property bool valid: action && action.hasOwnProperty("valid") ? action.valid : false
30+ property string title: state && state.hasOwnProperty("title") ? state["title"] : ""
31+ property string leftLabel: state && state.hasOwnProperty("pre-label") ? state["pre-label"] : ""
32+ property string rightLabel: state && state.hasOwnProperty("label") ? state["label"] : ""
33+ property var icons: state && state.hasOwnProperty("icons") ? state["icons"] : []
34+ property string accessibleName: state && state.hasOwnProperty("accessible-desc") ? state["accessible-desc"] : ""
35+ property bool visible: state && state.hasOwnProperty("visible") ? state["visible"] : true
36+
37+ signal updated
38+
39+ onValidChanged: updated()
40+ onTitleChanged: updated()
41+ onLeftLabelChanged: updated()
42+ onRightLabelChanged: updated()
43+ onIconsChanged: updated()
44+ onAccessibleNameChanged: updated()
45+ onVisibleChanged: updated()
46+}
tests/mocks/Unity/Indicators/RootActionState.qml → tests/mocks/Unity/Indicators/ModelActionRootState.qmlrenamed

The content is the same.

tests/mocks/Unity/Indicators/qmldir+2−1
@@ -2,5 +2,6 @@ module Unity.Indicators
22plugin IndicatorsFakeQml
33typeinfo Indicators.qmltypes
44
5+ActionRootState 0.1 ActionRootState.qml
56IndicatorsModel 0.1 IndicatorsModel.qml
6−RootActionState 0.1 RootActionState.qml
7+ModelActionRootState 0.1 ModelActionRootState.qml
tests/plugins/LightDM/CMakeLists.txt+4−8
@@ -1,8 +1,8 @@
1−add_executable(test-lightdm-dbus
1+add_executable(GreeterDBusTestExec
22 dbus.cpp
33 ${CMAKE_SOURCE_DIR}/plugins/LightDM/Greeter.cpp
44 )
5−qt5_use_modules(test-lightdm-dbus Core DBus Quick Test)
5+qt5_use_modules(GreeterDBusTestExec Core DBus Quick Test)
66
77include_directories(
88 ${CMAKE_CURRENT_BINARY_DIR}
@@ -11,15 +11,11 @@ include_directories(
1111 ${LIBLIGHTDM_INCLUDE_DIRS}
1212 )
1313
14−add_dependencies(test-lightdm-dbus MockLightDM-full)
15−target_link_libraries(test-lightdm-dbus
14+target_link_libraries(GreeterDBusTestExec
1615 -L${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full
1716 -llightdm-qt5-2
1817 )
1918
2019add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
2120
22−add_custom_target(testLightDMDBus xvfb-run --server-args "-screen 0 1024x768x24" --auto-servernum dbus-launch env QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full ${CMAKE_CURRENT_BINARY_DIR}/test-lightdm-dbus)
23−add_dependencies(testLightDMDBus test-lightdm-dbus)
24−
25−add_dependencies(qmluitests testLightDMDBus)
21+add_binary_qml_test(GreeterDBus "${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full" MockLightDM-full "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/tests/mocks")
tests/plugins/LightDM/dbus.cpp+11−2
@@ -16,6 +16,7 @@
1616
1717#include "Greeter.h"
1818
19+#include <QCoreApplication>
1920#include <QDBusInterface>
2021#include <QDBusReply>
2122#include <QSignalSpy>
@@ -149,9 +150,11 @@ private Q_SLOTS:
149150 QVERIFY(dbusList->property("EntryIsLocked").toBool());
150151
151152 greeter->authenticate("no-password");
153+ QCoreApplication::processEvents(); // wait for auth to finish
152154 QVERIFY(!dbusList->property("EntryIsLocked").toBool());
153155
154156 greeter->authenticate("has-password");
157+ QCoreApplication::processEvents(); // wait for auth to finish
155158 QVERIFY(dbusList->property("EntryIsLocked").toBool());
156159 }
157160
@@ -159,10 +162,16 @@ private Q_SLOTS:
159162 {
160163 QSignalSpy spy(this, SIGNAL(PropertiesChangedRelay(QString, QVariantMap, QStringList)));
161164 greeter->authenticate("no-password");
165+
166+ // Two property changed signals will be emitted, one for the IsLocked
167+ // property, one for the ActiveEntry; the first will be IsLocked.
162168 spy.wait();
169+ if (spy.count() < 2) {
170+ spy.wait();
171+ }
172+ QCOMPARE(spy.count(), 2);
163173
164− QCOMPARE(spy.count(), 2); // once for locked, once for user; first will be locked mode
165− QList<QVariant> arguments = spy.takeFirst();
174+ QList<QVariant> arguments = spy.takeLast();
166175 QVERIFY(arguments.at(0).toString() == "com.canonical.UnityGreeter.List");
167176 QVERIFY(arguments.at(1).toMap().contains("EntryIsLocked"));
168177 QVERIFY(arguments.at(1).toMap()["EntryIsLocked"] == false);
tests/plugins/Unity/Indicators/rootactionstatetest.cpp+4−4
@@ -17,7 +17,7 @@
1717 * Nick Dedekind <nick.dedekind@canonical.com>
1818 */
1919
20−#include "rootactionstate.h"
20+#include "modelactionrootstate.h"
2121
2222#include <unitymenumodel.h>
2323#include <QtTest>
@@ -32,7 +32,7 @@ private Q_SLOTS:
3232 {
3333 UnityMenuModel* menuModel = new UnityMenuModel();
3434 ActionStateParser* originalParser = menuModel->actionStateParser();
35− RootActionState* rootState = new RootActionState();
35+ ModelActionRootState* rootState = new ModelActionRootState();
3636
3737 rootState->setMenu(menuModel);
3838
@@ -44,7 +44,7 @@ private Q_SLOTS:
4444 void testDeleteUnityMenuModel()
4545 {
4646 UnityMenuModel* menuModel = new UnityMenuModel();
47− RootActionState* rootState = new RootActionState();
47+ ModelActionRootState* rootState = new ModelActionRootState();
4848
4949 rootState->setMenu(menuModel);
5050
@@ -77,7 +77,7 @@ private Q_SLOTS:
7777
7878 GVariant* params = g_variant_builder_end (&builderParams);
7979
80− RootActionState rootState;
80+ RootStateParser rootState;
8181 QVariant result = rootState.toQVariant(params);
8282 g_variant_unref(params);
8383
tests/plugins/Utils/CMakeLists.txt+1−1
@@ -23,7 +23,7 @@ endmacro(run_tests)
2323
2424run_tests(
2525 qlimitproxymodeltest
26− qsortfilterproxymodeltest
26+ unitysortfilterproxymodeltest
2727 timeformattertest
2828 )
2929
tests/plugins/Utils/qsortfilterproxymodeltest.cpp → tests/plugins/Utils/unitysortfilterproxymodeltest.cpprenamed+14−14
@@ -18,7 +18,7 @@
1818 */
1919
2020// local
21−#include "qsortfilterproxymodelqml.h"
21+#include "unitysortfilterproxymodelqml.h"
2222#include "modeltest.h"
2323
2424// Qt
@@ -91,7 +91,7 @@ private:
9191 QHash<int, QByteArray> m_roles;
9292};
9393
94−class QSortFilterProxyModelTest : public QObject
94+class UnitySortFilterProxyModelTest : public QObject
9595{
9696 Q_OBJECT
9797
@@ -103,7 +103,7 @@ private Q_SLOTS:
103103
104104 void testRoleNamesSetAfter()
105105 {
106− QSortFilterProxyModelQML proxy;
106+ UnitySortFilterProxyModelQML proxy;
107107 MockListModel model;
108108 QHash<int, QByteArray> roles;
109109
@@ -117,7 +117,7 @@ private Q_SLOTS:
117117
118118 void testRoleNamesSetBefore()
119119 {
120− QSortFilterProxyModelQML proxy;
120+ UnitySortFilterProxyModelQML proxy;
121121 MockListModel model;
122122 QHash<int, QByteArray> roles;
123123
@@ -131,7 +131,7 @@ private Q_SLOTS:
131131
132132 void testCountSetAfter()
133133 {
134− QSortFilterProxyModelQML proxy;
134+ UnitySortFilterProxyModelQML proxy;
135135 MockListModel model;
136136 model.insertRows(0, 5);
137137
@@ -144,7 +144,7 @@ private Q_SLOTS:
144144
145145 void testCountInsert()
146146 {
147− QSortFilterProxyModelQML proxy;
147+ UnitySortFilterProxyModelQML proxy;
148148 MockListModel model;
149149
150150 proxy.setModel(&model);
@@ -158,7 +158,7 @@ private Q_SLOTS:
158158
159159 void testCountRemove()
160160 {
161− QSortFilterProxyModelQML proxy;
161+ UnitySortFilterProxyModelQML proxy;
162162 MockListModel model;
163163 model.insertRows(0, 5);
164164
@@ -173,7 +173,7 @@ private Q_SLOTS:
173173 }
174174
175175 void testInvertMatch() {
176− QSortFilterProxyModelQML proxy;
176+ UnitySortFilterProxyModelQML proxy;
177177 MockListModel model;
178178
179179 proxy.setModel(&model);
@@ -215,7 +215,7 @@ private Q_SLOTS:
215215 }
216216
217217 void testNestedProxyRoleNames() {
218− QSortFilterProxyModelQML proxy1, proxy2;
218+ UnitySortFilterProxyModelQML proxy1, proxy2;
219219 MockListModel model;
220220 QHash<int, QByteArray> roles;
221221 roles[0] = "role0";
@@ -229,7 +229,7 @@ private Q_SLOTS:
229229 }
230230
231231 void testModelTest() {
232− QSortFilterProxyModelQML proxy;
232+ UnitySortFilterProxyModelQML proxy;
233233 MockListModel model;
234234
235235 proxy.setModel(&model);
@@ -246,7 +246,7 @@ private Q_SLOTS:
246246 }
247247
248248 void testModelChanged() {
249− QSortFilterProxyModelQML proxy;
249+ UnitySortFilterProxyModelQML proxy;
250250 MockListModel model, model2;
251251
252252 QSignalSpy spyOnModelChanged(&proxy, SIGNAL(modelChanged()));
@@ -265,7 +265,7 @@ private Q_SLOTS:
265265 }
266266
267267 void testData() {
268− QSortFilterProxyModelQML proxy;
268+ UnitySortFilterProxyModelQML proxy;
269269 MockListModel model, model2;
270270
271271 QStringList rows;
@@ -285,6 +285,6 @@ private Q_SLOTS:
285285 }
286286};
287287
288−QTEST_GUILESS_MAIN(QSortFilterProxyModelTest)
288+QTEST_GUILESS_MAIN(UnitySortFilterProxyModelTest)
289289
290−#include "qsortfilterproxymodeltest.moc"
290+#include "unitysortfilterproxymodeltest.moc"
tests/qmltests/CMakeLists.txt+1
@@ -79,6 +79,7 @@ add_qml_test(Panel IndicatorsMenu ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DI
7979add_qml_test(Panel MenuContent ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
8080add_qml_test(Panel Panel ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
8181add_qml_test(Panel SearchIndicator)
82+add_qml_test(Panel/Indicators IndicatorsLight ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
8283# These MenuItemFactory tests need the test/mocks/ to come before plugins/
8384add_qml_test(Panel/Indicators MenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
8485add_qml_test(Panel/Indicators MessageMenuItemFactory IMPORT_PATHS ${CMAKE_BINARY_DIR}/tests/mocks ${qmltest_DEFAULT_IMPORT_PATHS})
tests/qmltests/Components/tst_Carousel.qml+5−5
@@ -274,20 +274,20 @@ Item {
274274
275275 spy.signalName = "clicked";
276276 spy.target = carouselItem;
277− mouseClick(carouselItem, carouselItem.width / 2, carouselItem.height / 2);
277+ mouseClick(carouselItem);
278278 tryCompare(carouselList, "moving", false);
279279 tryCompare(carouselItem, "explicitlyScaled", true);
280− mouseClick(carouselItem, carouselItem.width / 2, carouselItem.height / 2);
280+ mouseClick(carouselItem);
281281 spy.wait();
282282
283283 spy.signalName = "pressAndHold";
284284 spy.target = carouselItem;
285− mouseClick(carouselItem, carouselItem.width / 2, carouselItem.height / 2);
285+ mouseClick(carouselItem);
286286 tryCompare(carouselList, "moving", false);
287287 tryCompare(carouselItem, "explicitlyScaled", true);
288− mousePress(carouselItem, carouselItem.width / 2, carouselItem.height / 2);
288+ mousePress(carouselItem);
289289 spy.wait();
290− mouseRelease(carouselItem, carouselItem.width / 2, carouselItem.height / 2);
290+ mouseRelease(carouselItem);
291291 }
292292 }
293293}
tests/qmltests/Components/tst_Lockscreen.qml+1−1
@@ -421,7 +421,7 @@ Rectangle {
421421 signalSpy.clear();
422422
423423 var okButton = findChild(root, "infoPopupOkButton");
424− mouseClick(okButton, okButton.width / 2, okButton.height / 2);
424+ mouseClick(okButton);
425425
426426 tryCompareFunction(function() { return findChild(root, "infoPopup") === null}, true);
427427
tests/qmltests/Components/tst_ResponsiveVerticalJournal.qml+1−1
@@ -79,7 +79,7 @@ Item {
7979 ListElement { name: "U" }
8080 }
8181
82− SortFilterProxyModel {
82+ UnitySortFilterProxyModel {
8383 id: wrappedFakeModel
8484 model: fakeModel
8585 }
tests/qmltests/Dash/Previews/tst_PreviewActions.qml+3−3
@@ -104,7 +104,7 @@ Rectangle {
104104 var button = findChild(root, "button" + id);
105105 verify(button != null);
106106 spy.target = target;
107− mouseClick(button, button.width / 2, button.height / 2);
107+ mouseClick(button);
108108 compare(spy.count, 1);
109109 compare(spy.signalArguments[0][0], target.widgetId);
110110 compare(spy.signalArguments[0][1], id);
@@ -137,11 +137,11 @@ Rectangle {
137137 var buttonColumn = findChild(root, "buttonColumn");
138138 verify(button != null);
139139 var twoActionsY = twoActions.y
140− mouseClick(button, button.width / 2, button.height / 2);
140+ mouseClick(button);
141141 tryCompareFunction(function () { return twoActions.y <= twoActionsY; }, false);
142142 tryCompare(buttonColumn, "height", buttonColumn.implicitHeight);
143143 checkButtonPressSignal(buttonAndCombo, data.id, data.buttonNumber);
144− mouseClick(button, button.width / 2, button.height / 2);
144+ mouseClick(button);
145145 tryCompare(twoActions, "y", twoActionsY);
146146 }
147147 }
tests/qmltests/Dash/Previews/tst_PreviewAudioPlayback.qml+5−5
@@ -131,7 +131,7 @@ Rectangle {
131131 compare(track2ProgressBar.visible, false);
132132
133133 // Playing track 0 should make progress bar 0 visible
134− mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
134+ mouseClick(track0PlayButton);
135135
136136 tryCompare(audio, "playbackState", Audio.PlayingState);
137137 checkPlayerSource(0);
@@ -141,18 +141,18 @@ Rectangle {
141141 tryCompare(track2ProgressBar, "visible", false);
142142
143143 // Clicking the button again should pause it. The progress bar should stay visible
144− mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
144+ mouseClick(track0PlayButton);
145145 tryCompare(audio, "playbackState", Audio.PausedState);
146146 checkPlayerSource(0);
147147 tryCompare(track0ProgressBar, "visible", true);
148148
149149 // Continue playback
150− mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
150+ mouseClick(track0PlayButton);
151151 tryCompare(audio, "playbackState", Audio.PlayingState);
152152 checkPlayerSource(0);
153153
154154 // Playing track 1 should make progress bar 1 visible and hide progress bar 0 again
155− mouseClick(track1PlayButton, track1PlayButton.width / 2, track1PlayButton.height / 2);
155+ mouseClick(track1PlayButton);
156156
157157 tryCompare(audio, "playbackState", Audio.PlayingState);
158158 checkPlayerSource(1);
@@ -162,7 +162,7 @@ Rectangle {
162162 tryCompare(track2ProgressBar, "visible", false);
163163
164164 // Playing track 2 should make progress bar 1 visible and hide progress bar 0 again
165− mouseClick(track2PlayButton, track2PlayButton.width / 2, track2PlayButton.height / 2);
165+ mouseClick(track2PlayButton);
166166
167167 tryCompare(audio, "playbackState", Audio.PlayingState);
168168 checkPlayerSource(2);
tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml+2−2
@@ -85,7 +85,7 @@ Rectangle {
8585
8686 function test_expand_collapse() {
8787 var expandButton = findChild(previewExpandable, "expandButton")
88− mouseClick(expandButton, expandButton.width / 2, expandButton.height / 2);
88+ mouseClick(expandButton);
8989
9090 var repeater = findChild(previewExpandable, "repeater")
9191 compare(repeater.count, 4)
@@ -99,7 +99,7 @@ Rectangle {
9999 compare (repeater.itemAt(2).expanded, true);
100100 compare (repeater.itemAt(3).expanded, true);
101101
102− mouseClick(expandButton, expandButton.width / 2, expandButton.height / 2);
102+ mouseClick(expandButton);
103103
104104 checkInitialState();
105105 }
tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml+6−6
@@ -67,23 +67,23 @@ Rectangle {
6767
6868 function test_overlayOpenClose() {
6969 var image0 = findChild(imageGallery, "previewImage0");
70− mouseClick(image0, image0.width / 2, image0.height / 2);
70+ mouseClick(image0);
7171 tryCompare(overlay, "visible", true);
7272 tryCompare(overlay, "scale", 1.0);
7373 tryCompare(overlayCloseButton, "visible", true);
74− mouseClick(overlayCloseButton, overlayCloseButton.width / 2, overlayCloseButton.height / 2);
74+ mouseClick(overlayCloseButton);
7575 tryCompare(overlay, "visible", false);
7676 }
7777
7878 function test_overlayShowHideHeader() {
7979 var image0 = findChild(imageGallery, "previewImage0");
80− mouseClick(image0, image0.width / 2, image0.height / 2);
80+ mouseClick(image0);
8181 tryCompare(overlay, "visible", true);
8282 tryCompare(overlay, "scale", 1.0);
8383 tryCompare(overlayCloseButton, "visible", true);
84− mouseClick(overlay, overlay.width / 2, overlay.height / 2);
84+ mouseClick(overlay);
8585 tryCompare(overlayCloseButton, "visible", false);
86− mouseClick(overlay, overlay.width / 2, overlay.height / 2);
86+ mouseClick(overlay);
8787 tryCompare(overlayCloseButton, "visible", true);
8888 }
8989
@@ -97,7 +97,7 @@ Rectangle {
9797
9898 function test_overlayOpenCorrectImage(data) {
9999 var image = findChild(imageGallery, "previewImage" + data.index);
100− mouseClick(image, image.width / 2, image.height / 2);
100+ mouseClick(image);
101101 tryCompare(overlay, "visible", true);
102102 tryCompare(overlay, "scale", 1.0);
103103 tryCompare(overlayListView, "currentIndex", data.index);
tests/qmltests/Dash/Previews/tst_PreviewPayments.qml+5−5
@@ -84,7 +84,7 @@ Rectangle {
8484 var button = findChild(previewPayments, "paymentButton");
8585 verify(button, "Button not found.");
8686
87− mouseClick(button, button.width / 2, button.height / 2);
87+ mouseClick(button);
8888
8989 paymentClient.process();
9090 spy.wait();
@@ -107,7 +107,7 @@ Rectangle {
107107 tryCompare(button, "visible", true);
108108 tryCompare(button, "opacity", 1);
109109
110− mouseClick(button, button.width / 2, button.height / 2);
110+ mouseClick(button);
111111
112112 paymentClient.process();
113113 spy.wait();
@@ -130,7 +130,7 @@ Rectangle {
130130 tryCompare(button, "visible", true);
131131 tryCompare(button, "opacity", 1);
132132
133− mouseClick(button, button.width / 2, button.height / 2);
133+ mouseClick(button);
134134
135135 tryCompare(progress, "visible", true);
136136 tryCompare(progress, "opacity", 1);
@@ -154,7 +154,7 @@ Rectangle {
154154 var button = findChild(previewPayments, "paymentButton");
155155 verify(button, "Button not found.");
156156
157− mouseClick(button, button.width / 2, button.height / 2);
157+ mouseClick(button);
158158
159159 paymentClient.process();
160160 spy.wait();
@@ -175,7 +175,7 @@ Rectangle {
175175 verify(button, "Button not found.");
176176 verify(progress, "Progress not found.");
177177
178− mouseClick(button, button.width / 2, button.height / 2);
178+ mouseClick(button);
179179
180180 tryCompare(progress, "visible", true);
181181 tryCompare(progress, "opacity", 1);
tests/qmltests/Dash/Previews/tst_PreviewRatingDisplay.qml+1−1
@@ -118,7 +118,7 @@ Rectangle {
118118 compare(rating.value, reviewsModel1["reviews"][1]["rating"]);
119119
120120 // Tap on first star
121− mouseClick(rating, 0, 0);
121+ mouseClick(rating);
122122 compare(rating.value, reviewsModel1["reviews"][1]["rating"]);
123123 }
124124 }
tests/qmltests/Dash/Previews/tst_PreviewRatingInput.qml+2−2
@@ -139,7 +139,7 @@ Rectangle {
139139 verify(reviewTextArea.visible === true);
140140
141141 reviewTextArea.text = data.inputText;
142− mouseClick(submitButton, submitButton.width / 2, submitButton.height / 2);
142+ mouseClick(submitButton);
143143 switch (data.widgetData["required"]) {
144144 case "rating": {
145145 if (rating.visible === false || data.inputRating < 0) {
@@ -187,7 +187,7 @@ Rectangle {
187187 if (data.inputRating > 0) rating.value = data.inputRating;
188188 if (data.inputText !== "") {
189189 reviewTextArea.text = data.inputText;
190− mouseClick(submitButton, submitButton.width / 2, submitButton.height / 2);
190+ mouseClick(submitButton);
191191 }
192192
193193 compare(spy.count, 1);
tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml+2−2
@@ -72,11 +72,11 @@ Rectangle {
7272
7373 function test_zoomableImageOpenClose() {
7474 var overlayCloseButton = findChild(overlay, "overlayCloseButton");
75− mouseClick(lazyImage, lazyImage.width / 2, lazyImage.height / 2);
75+ mouseClick(lazyImage);
7676 tryCompare(overlay, "visible", true);
7777 tryCompare(overlay, "scale", 1.0);
7878 tryCompare(overlayCloseButton, "visible", true);
79− mouseClick(overlayCloseButton, overlayCloseButton.width / 2, overlayCloseButton.height / 2);
79+ mouseClick(overlayCloseButton);
8080 tryCompare(overlay, "visible", false);
8181 }
8282 }
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingBoolean.qml+2−2
@@ -49,12 +49,12 @@ Rectangle {
4949
5050 function test_updated() {
5151 var control = findChild(scopeSetting, "control");
52− mouseClick(control, control.width / 2, control.height / 2);
52+ mouseClick(control);
5353 spy.wait();
5454 compare(spy.signalArguments[0][0], false);
5555
5656 spy.clear();
57− mouseClick(scopeSetting, scopeSetting.width / 2, scopeSetting.height / 2);
57+ mouseClick(scopeSetting);
5858 spy.wait();
5959 compare(spy.signalArguments[0][0], true);
6060 }
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingNumber.qml+3−3
@@ -57,7 +57,7 @@ Rectangle {
5757 }
5858
5959 function test_updated_on_unfocus() {
60− mouseClick(control, control.width / 2, control.height / 2);
60+ mouseClick(control);
6161 control.selectAll();
6262 control.cut();
6363 control.insert(0, newNumber);
@@ -67,7 +67,7 @@ Rectangle {
6767 }
6868
6969 function test_updated_on_accepted() {
70− mouseClick(control, control.width / 2, control.height / 2);
70+ mouseClick(control);
7171 control.selectAll();
7272 control.cut();
7373 control.insert(0, newNumber);
@@ -86,7 +86,7 @@ Rectangle {
8686 }
8787
8888 function test_unacceptable_input() {
89− mouseClick(control, control.width / 2, control.height / 2);
89+ mouseClick(control);
9090 control.selectAll();
9191 control.cut();
9292 control.insert(0, "not valid");
tests/qmltests/Dash/ScopeSettings/tst_ScopeSettingString.qml+2−2
@@ -57,7 +57,7 @@ Rectangle {
5757 }
5858
5959 function test_updated_on_unfocus() {
60− mouseClick(control, control.width / 2, control.height / 2);
60+ mouseClick(control);
6161 control.selectAll();
6262 control.cut();
6363 control.insert(0, newText);
@@ -67,7 +67,7 @@ Rectangle {
6767 }
6868
6969 function test_updated_on_accepted() {
70− mouseClick(control, control.width / 2, control.height / 2);
70+ mouseClick(control);
7171 control.selectAll();
7272 control.cut();
7373 control.insert(0, newText);
tests/qmltests/Dash/tst_Card.qml+2−2
@@ -539,9 +539,9 @@ Rectangle {
539539 var touchdown = findChild(card, "touchdown");
540540
541541 compare(touchdown.visible, false);
542− mousePress(card, card.width/2, card.height/2);
542+ mousePress(card);
543543 compare(touchdown.visible, true);
544− mouseRelease(card, card.width/2, card.height/2);
544+ mouseRelease(card);
545545 compare(touchdown.visible, false);
546546 }
547547
tests/qmltests/Dash/tst_Dash.qml+42−25
@@ -89,8 +89,8 @@ Item {
8989 // Go back
9090 var scopesList = findChild(dash, "scopesList");
9191 var scopesListPageHeader = findChild(scopesList, "pageHeader");
92− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
93− mouseClick(backButton, 0, 0);
92+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
93+ mouseClick(backButton);
9494 tryCompare(bottomEdgeController, "progress", 0);
9595 }
9696
@@ -106,7 +106,7 @@ Item {
106106 tryCompare(favScopesListCategoryList, "currentIndex", 0);
107107
108108 // Click in first item
109− mouseClick(favScopesListCategoryList.currentItem, 0, 0);
109+ mouseClick(favScopesListCategoryList.currentItem);
110110
111111 // Make sure animation went back
112112 tryCompare(bottomEdgeController, "progress", 0);
@@ -128,7 +128,7 @@ Item {
128128
129129 // Click in second item
130130 favScopesListCategoryList.currentIndex = 1;
131− mouseClick(favScopesListCategoryList.currentItem, 0, 0);
131+ mouseClick(favScopesListCategoryList.currentItem);
132132
133133 // Make sure animation went back
134134 tryCompare(bottomEdgeController, "progress", 0);
@@ -148,7 +148,7 @@ Item {
148148 tryCompare(nonfavScopesListCategoryList, "currentIndex", 0);
149149
150150 // Click on a non favorite scope
151− mouseClick(nonfavScopesListCategoryList.currentItem, 0, 0);
151+ mouseClick(nonfavScopesListCategoryList.currentItem);
152152
153153 // Check the bottom edge (manage dash) is disabled from temp scope
154154 var overviewDragHandle = findChild(dash, "overviewDragHandle");
@@ -164,8 +164,8 @@ Item {
164164
165165 // Go back
166166 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
167− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "backButton");
168− mouseClick(backButton, 0, 0);
167+ var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
168+ mouseClick(backButton);
169169
170170 // Check temp scope is gone
171171 tryCompare(dashTempScopeItem, "x", dash.width);
@@ -189,7 +189,7 @@ Item {
189189 var scopesList = findChild(dash, "scopesList");
190190 var scopesListPageHeader = findChild(scopesList, "pageHeader");
191191 var searchButton = findChild(scopesListPageHeader, "search_header_button");
192− mouseClick(searchButton, 0, 0);
192+ mouseClick(searchButton);
193193
194194 // Type something
195195 keyClick(Qt.Key_H);
@@ -201,7 +201,7 @@ Item {
201201 var cardTempScope = findChild(dashCategorysearchA, "delegate2");
202202
203203 waitForRendering(cardTempScope);
204− mouseClick(cardTempScope, cardTempScope.width / 2, cardTempScope.height / 2);
204+ mouseClick(cardTempScope);
205205
206206 // Check the bottom edge (overview) is disabled from temp scope
207207 var overviewDragHandle = findChild(dash, "overviewDragHandle");
@@ -217,8 +217,8 @@ Item {
217217
218218 // Go back
219219 var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
220− var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "backButton");
221− mouseClick(backButton, 0, 0);
220+ var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "customBackButton");
221+ mouseClick(backButton);
222222
223223 // Check temp scope is gone
224224 tryCompare(dashTempScopeItem, "x", dash.width);
@@ -243,8 +243,8 @@ Item {
243243 // Go back
244244 var scopesList = findChild(dash, "scopesList");
245245 var scopesListPageHeader = findChild(scopesList, "pageHeader");
246− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
247− mouseClick(backButton, 0, 0);
246+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
247+ mouseClick(backButton);
248248 tryCompare(bottomEdgeController, "progress", 0);
249249 }
250250
@@ -272,7 +272,7 @@ Item {
272272 var scopeLoader0 = findChild(dashContent, "scopeLoader0");
273273 var dashCategory0 = findChild(scopeLoader0, "dashCategory0");
274274 var delegate0 = findChild(dashCategory0, "delegate0");
275− mouseClick(delegate0, delegate0.width / 2, delegate0.height / 2);
275+ mouseClick(delegate0);
276276
277277 tryCompare(dashContent, "subPageShown", true)
278278 waitForRendering(dash);
@@ -320,7 +320,7 @@ Item {
320320 // Click on the store
321321 var scopesListPageHeader = findChild(scopesList, "pageHeader");
322322 var searchButton = findChild(scopesListPageHeader, "store_header_button");
323− mouseClick(searchButton, 0, 0);
323+ mouseClick(searchButton);
324324
325325 spy.wait();
326326 compare(spy.signalArguments[0][0], "scope://com.canonical.scopes.clickstore");
@@ -345,9 +345,9 @@ Item {
345345 // Enter edit mode
346346 var scopesList = findChild(dash, "scopesList");
347347 var clickScope = findChild(favScopesListCategoryList, "delegateclickscope");
348− mousePress(clickScope, 0, 0);
348+ mousePress(clickScope);
349349 tryCompare(scopesList, "state", "edit");
350− mouseRelease(clickScope, 0, 0);
350+ mouseRelease(clickScope);
351351
352352 var starArea = findChild(clickScope, "starArea");
353353 touchFlick(starArea, 0, 0, 0, -units.gu(10));
@@ -355,9 +355,9 @@ Item {
355355 // Exit edit mode and go back
356356 var scopesList = findChild(dash, "scopesList");
357357 var scopesListPageHeader = findChild(scopesList, "pageHeader");
358− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
359− mouseClick(backButton, 0, 0);
360− mouseClick(backButton, 0, 0);
358+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
359+ mouseClick(backButton);
360+ mouseClick(backButton);
361361 tryCompare(bottomEdgeController, "progress", 0);
362362
363363 tryCompare(dashContentList, "currentIndex", 0);
@@ -387,9 +387,9 @@ Item {
387387 // Enter edit mode
388388 var scopesList = findChild(dash, "scopesList");
389389 var clickScope = findChild(favScopesListCategoryList, "delegateclickscope");
390− mousePress(clickScope, 0, 0);
390+ mousePress(clickScope);
391391 tryCompare(scopesList, "state", "edit");
392− mouseRelease(clickScope, 0, 0);
392+ mouseRelease(clickScope);
393393
394394 var starArea = findChild(clickScope, "starArea");
395395 touchFlick(starArea, 0, 0, 0, -units.gu(10));
@@ -400,16 +400,33 @@ Item {
400400 // Exit edit mode
401401 var scopesList = findChild(dash, "scopesList");
402402 var scopesListPageHeader = findChild(scopesList, "pageHeader");
403− var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "backButton");
404− mouseClick(backButton, 0, 0);
403+ var backButton = findChild(findChild(scopesListPageHeader, "innerPageHeader"), "customBackButton");
404+ mouseClick(backButton);
405405
406406 // Click on third scope
407407 var mockScope5 = findChild(favScopesListCategoryList, "delegateMockScope5");
408408 waitForRendering(mockScope5)
409− mouseClick(mockScope5, 0, 0);
409+ mouseClick(mockScope5);
410410 tryCompare(bottomEdgeController, "progress", 0);
411411 tryCompare(dashContentList, "currentIndex", 2);
412412 compare(dashContentList.currentItem.scopeId, "MockScope5");
413413 }
414+
415+ function test_manage_dash_close_dashCommunicator() {
416+ var dashContentList = findChild(dash, "dashContentList");
417+ compare(dashContentList.currentIndex, 0);
418+ compare(dashContentList.currentItem.scopeId, "MockScope1");
419+
420+ // Show the manage dash
421+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
422+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
423+ tryCompare(bottomEdgeController, "progress", 1);
424+
425+ var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService");
426+ dashCommunicatorService.mockSetCurrentScope(1, true, false);
427+
428+ tryCompare(bottomEdgeController, "progress", 0);
429+ tryCompare(dashContentList, "currentIndex", 1)
430+ }
414431 }
415432}
tests/qmltests/Dash/tst_DashContent.qml+48−27
@@ -288,7 +288,7 @@ Item {
288288 var dashNavigationButton = findChild(dashContentList.currentItem, "navigationButton");
289289 compare(dashNavigationButton.showList, false);
290290 waitForRendering(dashNavigationButton);
291− mouseClick(dashNavigationButton, dashNavigationButton.width / 2, dashNavigationButton.height / 2);
291+ mouseClick(dashNavigationButton);
292292 compare(dashNavigationButton.showList, true);
293293
294294 var navigationListView = findChild(dashNavigationButton, "navigationListView");
@@ -304,30 +304,30 @@ Item {
304304 compare(allButton.visible, false);
305305
306306 var navigation = findChild(dashNavigationButton, "navigation0child3");
307− mouseClick(navigation, 0, 0);
307+ mouseClick(navigation);
308308 compare(dashNavigationButton.showList, false);
309309 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle3");
310310 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
311311
312− mouseClick(dashNavigationButton, 0, 0);
312+ mouseClick(dashNavigationButton);
313313 compare(dashNavigationButton.showList, true);
314314 waitForRendering(navigationListView);
315315 waitForRendering(navigationListView.currentItem);
316316 compare(allButton.visible, true);
317317
318− mouseClick(allButton, 0, 0);
318+ mouseClick(allButton);
319319 compare(dashNavigationButton.showList, false);
320320 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "root");
321321 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
322322
323− mouseClick(dashNavigationButton, 0, 0);
323+ mouseClick(dashNavigationButton);
324324 compare(dashNavigationButton.showList, true);
325325 waitForRendering(navigationListView);
326326 waitForRendering(navigationListView.currentItem);
327327 compare(allButton.visible, false);
328328
329329 navigation = findChild(dashNavigationButton, "navigation0child2");
330− mouseClick(navigation, 0, 0);
330+ mouseClick(navigation);
331331 compare(dashNavigationButton.showList, true);
332332 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
333333 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
@@ -340,12 +340,12 @@ Item {
340340
341341 tryCompare(navigationListView, "contentX", navigationList1.x);
342342 waitForRendering(navigationListView);
343− mouseClick(allButton, 0, 0);
343+ mouseClick(allButton);
344344 compare(dashNavigationButton.showList, false);
345345 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
346346 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
347347
348− mouseClick(dashNavigationButton, 0, 0);
348+ mouseClick(dashNavigationButton);
349349 compare(dashNavigationButton.showList, true);
350350 waitForRendering(navigationListView);
351351 waitForRendering(navigationListView.currentItem);
@@ -354,47 +354,47 @@ Item {
354354
355355 tryCompare(navigationList1.navigation, "loaded", true);
356356 navigation = findChild(dashNavigationButton, "navigation1child2");
357− mouseClick(navigation, 0, 0);
357+ mouseClick(navigation);
358358 compare(dashNavigationButton.showList, false);
359359 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "childmiddle22");
360360 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
361361
362− mouseClick(dashNavigationButton, 0, 0);
362+ mouseClick(dashNavigationButton);
363363 compare(dashNavigationButton.showList, true);
364364 waitForRendering(navigationListView);
365365 waitForRendering(navigationListView.currentItem);
366366
367367 tryCompare(navigationList1.navigation, "loaded", true);
368368 navigation = findChild(dashNavigationButton, "navigation1child3");
369− mouseClick(navigation, 0, 0);
369+ mouseClick(navigation);
370370 compare(dashNavigationButton.showList, false);
371371 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "childmiddle23");
372372 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
373373
374− mouseClick(dashNavigationButton, 0, 0);
374+ mouseClick(dashNavigationButton);
375375 compare(dashNavigationButton.showList, true);
376376 waitForRendering(navigationListView);
377377 waitForRendering(navigationListView.currentItem);
378− mouseClick(backButton, 0, 0);
378+ mouseClick(backButton);
379379
380380 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "root");
381381 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
382382 compare(dashNavigationButton.showList, true);
383− mouseClick(dashNavigationButton, 0, 0);
383+ mouseClick(dashNavigationButton);
384384 compare(dashNavigationButton.showList, false);
385385
386− mouseClick(dashNavigationButton, 0, 0);
386+ mouseClick(dashNavigationButton);
387387 compare(dashNavigationButton.showList, true);
388388 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
389389 navigation = findChild(dashNavigationButton, "navigation0child2");
390− mouseClick(navigation, 0, 0);
390+ mouseClick(navigation);
391391 compare(dashNavigationButton.showList, true);
392392 navigationList1 = findChild(dashNavigationButton, "navigation1");
393393 compare(navigationList1.navigation.loaded, false);
394394 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
395395 allButton = findChild(navigationList1, "allButton");
396396 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
397− mouseClick(allButton, 0, 0);
397+ mouseClick(allButton);
398398 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "middle2");
399399 }
400400
@@ -408,7 +408,7 @@ Item {
408408
409409 compare(dashNavigationButton.showList, false);
410410 waitForRendering(dashNavigationButton);
411− mouseClick(dashNavigationButton, 0, 0);
411+ mouseClick(dashNavigationButton);
412412 compare(dashNavigationButton.showList, true);
413413
414414 var navigationListView = findChild(dashNavigationButton, "navigationListView");
@@ -429,24 +429,24 @@ Item {
429429 compare(backButton.visible, false);
430430
431431 var navigation = findChild(dashNavigationButton, "navigation0child3");
432− mouseClick(navigation, 0, 0);
432+ mouseClick(navigation);
433433 compare(dashNavigationButton.showList, false);
434434 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "altrootChild3");
435435 tryCompare(navigationListView.currentItem.navigation, "navigationId", "altroot");
436436
437− mouseClick(dashNavigationButton, 0, 0);
437+ mouseClick(dashNavigationButton);
438438 compare(dashNavigationButton.showList, true);
439439 waitForRendering(navigationListView);
440440 waitForRendering(navigationListView.currentItem);
441441 compare(allButton.visible, false);
442442
443443 navigation = findChild(dashNavigationButton, "navigation0child2");
444− mouseClick(navigation, 0, 0);
444+ mouseClick(navigation);
445445 compare(dashNavigationButton.showList, false);
446446 tryCompare(dashNavigationButton.currentNavigation, "navigationId", "altrootChild2");
447447 tryCompare(navigationListView.currentItem.navigation, "navigationId", "altroot");
448448
449− mouseClick(dashNavigationButton, 0, 0);
449+ mouseClick(dashNavigationButton);
450450 compare(dashNavigationButton.showList, true);
451451 waitForRendering(navigationListView);
452452 waitForRendering(navigationListView.currentItem);
@@ -454,7 +454,7 @@ Item {
454454
455455 compare(navigationListView.count, 1, "There should be no second-level navigation");
456456
457− mouseClick(dashNavigationButton, 0, 0);
457+ mouseClick(dashNavigationButton);
458458 compare(dashNavigationButton.showList, false);
459459 }
460460
@@ -474,7 +474,7 @@ Item {
474474 compare(dashNavigationButton.showList, false);
475475 compare(dashAltNavigationButton.showList, false);
476476
477− mouseClick(dashNavigation, 0, 0);
477+ mouseClick(dashAltNavigationButton);
478478 compare(dashNavigationButton.showList, false);
479479 compare(dashAltNavigationButton.showList, true);
480480
@@ -487,24 +487,45 @@ Item {
487487 var blackRect = findChild(dashNavigation, "blackRect");
488488 tryCompare(blackRect, "opacity", 0.5);
489489
490− mouseClick(dashNavigation, dashNavigationButton.x, 0);
490+ mouseClick(dashNavigationButton);
491491 compare(dashNavigationButton.showList, false);
492492 compare(dashAltNavigationButton.showList, false);
493493
494494 tryCompare(navigationListView, "visible", false);
495495
496− mouseClick(dashNavigation, dashNavigationButton.x, 0);
496+ mouseClick(dashNavigationButton);
497497 compare(dashNavigationButton.showList, true);
498498 compare(dashAltNavigationButton.showList, false);
499499
500500 navigationListView = findChild(dashNavigationButton, "navigationListView");
501501 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
502502
503− mouseClick(dashNavigation, 0, 0);
503+ mouseClick(dashAltNavigationButton);
504504 compare(dashNavigationButton.showList, false);
505505 compare(dashAltNavigationButton.showList, false);
506506 }
507507
508+ function test_navigationsSwipeToNextScope() {
509+ var dashContentList = findChild(dashContent, "dashContentList");
510+ tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true);
511+ var dashNavigation = findChild(dashContentList.currentItem, "dashNavigation");
512+ tryCompare(dashNavigation, "visible", true);
513+ var dashNavigationButton = findChild(dashContentList.currentItem, "altNavigationButton");
514+ verify(dashNavigationButton, "Can't find navigation button");
515+
516+ compare(dashNavigationButton.showList, false);
517+ waitForRendering(dashNavigationButton);
518+ mouseClick(dashNavigationButton, 0, 0);
519+ compare(dashNavigationButton.showList, true);
520+
521+ mouseFlick(dashNavigationButton, dashNavigationButton.width - units.gu(1), units.gu(1), units.gu(1), units.gu(1));
522+ compare(dashNavigationButton.showList, false);
523+
524+ var dashContentList = findChild(dashContent, "dashContentList");
525+ expectFail("", "should not change the parent list.");
526+ tryCompare(dashContentList, "currentIndex", 1);
527+ }
528+
508529 function test_searchHint() {
509530 var dashContentList = findChild(dashContent, "dashContentList");
510531 verify(dashContentList !== null);
tests/qmltests/Dash/tst_GenericScopeView.qml+26−26
@@ -163,12 +163,12 @@ Item {
163163 verify(!category.expanded);
164164
165165 var initialHeight = category.height;
166− mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
166+ mouseClick(seeAll);
167167 verify(category.expanded);
168168 tryCompare(category, "height", category.item.expandedHeight + seeAll.height);
169169
170170 waitForRendering(seeAll);
171− mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
171+ mouseClick(seeAll);
172172 verify(!category.expanded);
173173 }
174174
@@ -186,17 +186,17 @@ Item {
186186 verify(category2.expandable);
187187 verify(!category2.expanded);
188188
189− mouseClick(seeAll2, seeAll2.width / 2, seeAll2.height / 2);
189+ mouseClick(seeAll2);
190190 tryCompare(category2, "expanded", true);
191191
192192 categoryListView.positionAtBeginning();
193193
194194 var category0 = findChild(genericScopeView, "dashCategory0")
195195 var seeAll0 = findChild(category0, "seeAll")
196− mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
196+ mouseClick(seeAll0);
197197 tryCompare(category0, "expanded", true);
198198 tryCompare(category2, "expanded", false);
199− mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
199+ mouseClick(seeAll0);
200200 tryCompare(category0, "expanded", false);
201201 tryCompare(category2, "expanded", false);
202202 }
@@ -208,7 +208,7 @@ Item {
208208 spy.target = genericScopeView.scope;
209209 spy.signalName = "performQuery";
210210
211− mouseClick(header, header.width / 2, header.height / 2);
211+ mouseClick(header);
212212
213213 spy.wait();
214214 compare(spy.signalArguments[0][0], genericScopeView.scope.categories.data(1, Categories.RoleHeaderLink));
@@ -248,13 +248,13 @@ Item {
248248 categoryListView.contentY = units.gu(20);
249249 var seeAll = findChild(category, "seeAll");
250250 var floatingSeeLess = findChild(genericScopeView, "floatingSeeLess");
251− mouseClick(seeAll, seeAll.width / 2, seeAll.height / 2);
251+ mouseClick(seeAll);
252252 tryCompare(category, "expanded", true);
253253 tryCompareFunction(function() {
254254 return category.item.height + floatingSeeLess.height ==
255255 genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd;
256256 }, true);
257− mouseClick(floatingSeeLess, floatingSeeLess.width / 2, floatingSeeLess.height / 2);
257+ mouseClick(floatingSeeLess);
258258 tryCompare(category, "expanded", false);
259259 }
260260
@@ -295,7 +295,7 @@ Item {
295295 true);
296296 var tile = findChild(findChild(genericScopeView, "dashCategory"+category), "delegate"+delegate);
297297 waitForRendering(tile);
298− mouseClick(tile, tile.width / 2, tile.height / 2);
298+ mouseClick(tile);
299299 tryCompare(testCase.subPageLoader, "open", true);
300300 tryCompare(testCase.subPageLoader, "x", 0);
301301 tryCompare(findChild(genericScopeView, "categoryListView"), "visible", false);
@@ -340,15 +340,15 @@ Item {
340340 tryCompare(testCase.subPageLoader, "open", false);
341341 tryCompare(testCase.subPageLoader, "visible", false);
342342
343− mouseClick(tile, tile.width / 2, tile.height / 2);
343+ mouseClick(tile);
344344
345345 tryCompare(testCase.subPageLoader, "open", false);
346346 tryCompare(testCase.subPageLoader, "visible", false);
347347
348− mousePress(tile, tile.width / 2, tile.height / 2);
348+ mousePress(tile);
349349 tryCompare(testCase.subPageLoader, "open", false);
350350 tryCompare(testCase.subPageLoader, "visible", false);
351− mouseRelease(tile, tile.width / 2, tile.height / 2);
351+ mouseRelease(tile);
352352 }
353353
354354 function test_showPreviewCarousel() {
@@ -359,18 +359,18 @@ Item {
359359 var tile = findChild(category, "carouselDelegate1");
360360 verify(tile, "Could not find delegate");
361361
362− mouseClick(tile, tile.width / 2, tile.height / 2);
362+ mouseClick(tile);
363363 tryCompare(tile, "explicitlyScaled", true);
364− mouseClick(tile, tile.width / 2, tile.height / 2);
364+ mouseClick(tile);
365365 tryCompare(testCase.subPageLoader, "open", true);
366366 tryCompare(testCase.subPageLoader, "x", 0);
367367
368368 closePreview();
369369
370− mousePress(tile, tile.width / 2, tile.height / 2);
370+ mousePress(tile);
371371 tryCompare(testCase.subPageLoader, "open", true);
372372 tryCompare(testCase.subPageLoader, "x", 0);
373− mouseRelease(tile, tile.width / 2, tile.height / 2);
373+ mouseRelease(tile);
374374
375375 closePreview();
376376 }
@@ -383,16 +383,16 @@ Item {
383383 var tile = findChild(category, "delegate1");
384384 verify(tile, "Could not find delegate");
385385
386− mouseClick(tile, tile.width / 2, tile.height / 2);
386+ mouseClick(tile);
387387 tryCompare(testCase.subPageLoader, "open", true);
388388 tryCompare(testCase.subPageLoader, "x", 0);
389389
390390 closePreview();
391391
392− mousePress(tile, tile.width / 2, tile.height / 2);
392+ mousePress(tile);
393393 tryCompare(testCase.subPageLoader, "open", true);
394394 tryCompare(testCase.subPageLoader, "x", 0);
395− mouseRelease(tile, tile.width / 2, tile.height / 2);
395+ mouseRelease(tile);
396396
397397 closePreview();
398398 }
@@ -429,7 +429,7 @@ Item {
429429 tryCompare(testCase.subPageLoader, "open", false);
430430 tryCompare(testCase.subPageLoader, "visible", false);
431431 var settings = findChild(innerHeader, "settings_header_button");
432− mouseClick(settings, settings.width / 2, settings.height / 2);
432+ mouseClick(settings);
433433 tryCompare(testCase.subPageLoader, "open", true);
434434 tryCompareFunction(function() { return (String(subPageLoader.source)).indexOf("ScopeSettingsPage.qml") != -1; }, true);
435435 tryCompare(genericScopeView, "subPageShown", true);
@@ -496,7 +496,7 @@ Item {
496496 verify(category0.expandable);
497497 verify(!category0.expanded);
498498
499− mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
499+ mouseClick(seeAll0);
500500 verify(category0.expanded);
501501 tryCompare(category0, "height", category0.item.expandedHeight + seeAll0.height);
502502 tryCompare(genericScopeView.categoryView, "contentY", units.gu(14));
@@ -509,7 +509,7 @@ Item {
509509 verify(category1.expandable);
510510 verify(!category1.expanded);
511511
512− mouseClick(seeAll1, seeAll1.width / 2, seeAll1.height / 2);
512+ mouseClick(seeAll1);
513513 verify(!category0.expanded);
514514 verify(category1.expanded);
515515 tryCompare(category1, "height", category1.item.expandedHeight + seeAll1.height);
@@ -539,7 +539,7 @@ Item {
539539 verify(category0.expandable);
540540 verify(!category0.expanded);
541541
542− mouseClick(seeAll0, seeAll0.width / 2, seeAll0.height / 2);
542+ mouseClick(seeAll0);
543543 verify(category0.expanded);
544544 tryCompare(category0, "height", category0.item.expandedHeight + seeAll0.height);
545545
@@ -550,7 +550,7 @@ Item {
550550 verify(category1.expandable);
551551 verify(!category1.expanded);
552552
553− mouseClick(seeAll1, seeAll1.width / 2, seeAll1.height / 2);
553+ mouseClick(seeAll1);
554554 verify(!category0.expanded);
555555 verify(category1.expanded);
556556 tryCompare(category1, "height", category1.item.expandedHeight + seeAll1.height);
@@ -578,7 +578,7 @@ Item {
578578 expectFail("Apps", "Click scope should not have a favorite button");
579579 var favoriteAction = findChild(innerHeader, "favorite_header_button");
580580 verify(favoriteAction, "Could not find the favorite action.");
581− mouseClick(favoriteAction, favoriteAction.width / 2, favoriteAction.height / 2);
581+ mouseClick(favoriteAction);
582582
583583 tryCompare(genericScopeView.scope, "favorite", !data.favorite);
584584
@@ -629,7 +629,7 @@ Item {
629629 var touchdown = findChild(item0, "touchdown");
630630
631631 compare(touchdown.visible, false);
632− mouseClick(item0, item0.width / 2, item0.height / 2);
632+ mouseClick(item0);
633633 compare(touchdown.visible, false);
634634
635635 cardTool.template["non-interactive"] = false;
tests/qmltests/Dash/tst_PageHeader.qml+1−1
@@ -157,7 +157,7 @@ Item {
157157 var recentSearches = findChild(headerContainer.popover, "recentSearches");
158158 verify(recentSearches, "Could not find recent searches in the popover");
159159 waitForRendering(recentSearches);
160− mouseClick(recentSearches.itemAt(0), 0, 0);
160+ mouseClick(recentSearches.itemAt(0));
161161
162162 compare(pageHeader.searchQuery, "Search2");
163163 tryCompareFunction(function() { return headerContainer.popover === null; }, true);
tests/qmltests/Dash/tst_PreviewListView.qml+2−2
@@ -73,7 +73,7 @@ Rectangle {
7373
7474 function test_notProcessing() {
7575 expectFail("", "processingMouseArea should not receive the click.");
76− mouseClick(listView, listView.width / 2, listView.height / 2);
76+ mouseClick(listView);
7777 clickedSpy.wait();
7878 }
7979
@@ -83,7 +83,7 @@ Rectangle {
8383
8484 tryCompare(listView, "processing", true);
8585
86− mouseClick(listView, listView.width / 2, listView.height / 2);
86+ mouseClick(listView);
8787 clickedSpy.wait();
8888 }
8989
tests/qmltests/Launcher/tst_Launcher.qml+8−8
@@ -154,7 +154,7 @@ Item {
154154 dragLauncherIntoView()
155155
156156 // tapping on the center of the screen should dismiss the launcher
157− mouseClick(launcher, launcher.width/2, launcher.height/2)
157+ mouseClick(launcher)
158158
159159 // should eventually get fully retracted (hidden)
160160 tryCompare(panel, "x", -launcher.panelWidth, 1000)
@@ -175,7 +175,7 @@ Item {
175175
176176 verify(appIcon != undefined)
177177
178− mouseClick(appIcon, appIcon.width/2, appIcon.height/2)
178+ mouseClick(appIcon)
179179
180180 tryCompare(launcher, "lastSelectedApplication",
181181 "dialer-app")
@@ -194,7 +194,7 @@ Item {
194194 var dashIcon = findChild(launcher, "dashItem")
195195 verify(dashIcon != undefined)
196196
197− mouseClick(dashIcon, dashIcon.width/2, dashIcon.height/2)
197+ mouseClick(dashIcon)
198198
199199 tryCompare(launcher, "showDashHome_count", 1)
200200
@@ -413,7 +413,7 @@ Item {
413413 compare(quickListShape.visible, false)
414414
415415 // Doing longpress
416− mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2)
416+ mousePress(draggedItem)
417417 tryCompare(fakeDragItem, "visible", true) // Wait longpress happening
418418 tryCompare(quickListShape, "visible", true)
419419
@@ -448,7 +448,7 @@ Item {
448448 }
449449
450450 // Doing longpress
451− mousePress(draggedItem, draggedItem.width / 2, draggedItem.height / 2);
451+ mousePress(draggedItem);
452452 tryCompare(quickListShape, "opacity", 0.96);
453453 mouseRelease(draggedItem);
454454
@@ -481,7 +481,7 @@ Item {
481481 tryCompare(quickListShape, "visible", false)
482482
483483 // Doing longpress
484− mousePress(clickedItem, clickedItem.width / 2, clickedItem.height / 2)
484+ mousePress(clickedItem)
485485 tryCompare(clickedItem, "itemOpacity", 0) // Wait for longpress to happen
486486 verify(quickListShape.visible, "QuickList must be visible")
487487
@@ -492,7 +492,7 @@ Item {
492492 signalSpy.clear();
493493 signalSpy.signalName = "quickListTriggered"
494494
495− mouseClick(quickListEntry, quickListEntry.width / 2, quickListEntry.height / 2)
495+ mouseClick(quickListEntry)
496496
497497 if (data.clickable) {
498498 // QuickList needs to be closed when some clickable item is clicked
@@ -524,7 +524,7 @@ Item {
524524 tryCompare(quickList, "state", "")
525525
526526 // Doing longpress
527− mousePress(clickedItem, clickedItem.width / 2, clickedItem.height / 2)
527+ mousePress(clickedItem)
528528 tryCompare(clickedItem, "itemOpacity", 0) // Wait for longpress to happen
529529 verify(quickList, "state", "open")
530530
tests/qmltests/Notifications/tst_Notifications.qml+6−6
@@ -547,7 +547,7 @@ Item {
547547 compare(valueLabel.visible, data.valueLabelVisible, "value-label visibility is incorrect")
548548
549549 // test input does not fall through
550− mouseClick(notification, notification.width / 2, notification.height / 2)
550+ mouseClick(notification)
551551 if(data.type == Notification.Interactive) {
552552 actionSpy.wait()
553553 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action")
@@ -568,7 +568,7 @@ Item {
568568
569569 // only test the left/cancel-button if two actions have been passed in
570570 if (data.actions.length == 2) {
571− tryCompareFunction(function() { mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2); return actionSpy.signalArguments.length > 0; }, true);
571+ tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
572572 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
573573 actionSpy.clear()
574574 }
@@ -577,7 +577,7 @@ Item {
577577 verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint")
578578
579579 // click the positive/right button
580− tryCompareFunction(function() { mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2); return actionSpy.signalArguments.length > 0; }, true);
580+ tryCompareFunction(function() { mouseClick(buttonAccept); return actionSpy.signalArguments.length > 0; }, true);
581581 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
582582 actionSpy.clear()
583583 waitForRendering (notification)
@@ -592,19 +592,19 @@ Item {
592592
593593 // try clicking on choices in expanded comboList
594594 var choiceButton1 = findChild(notification, "notify_button3")
595− tryCompareFunction(function() { mouseClick(choiceButton1, choiceButton1.width / 2, choiceButton1.height / 2); return actionSpy.signalArguments.length > 0; }, true);
595+ tryCompareFunction(function() { mouseClick(choiceButton1); return actionSpy.signalArguments.length > 0; }, true);
596596 compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1")
597597 actionSpy.clear()
598598
599599 var choiceButton2 = findChild(notification, "notify_button4")
600− tryCompareFunction(function() { mouseClick(choiceButton2, choiceButton2.width / 2, choiceButton2.height / 2); return actionSpy.signalArguments.length > 0; }, true);
600+ tryCompareFunction(function() { mouseClick(choiceButton2); return actionSpy.signalArguments.length > 0; }, true);
601601 compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2")
602602 actionSpy.clear()
603603
604604 // click to collapse
605605 //tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == false; }, true);
606606 } else {
607− mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
607+ mouseClick(buttonCancel)
608608 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
609609 }
610610 }
tests/qmltests/Notifications/tst_OptionToggle.qml+7−7
@@ -223,7 +223,7 @@ Row {
223223 }
224224
225225 // test input does not fall through
226− mouseClick(notification, notification.width / 2, notification.height / 2)
226+ mouseClick(notification)
227227 if(data.type == Notification.Interactive) {
228228 actionSpy.wait()
229229 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action")
@@ -244,7 +244,7 @@ Row {
244244
245245 // only test the left/cancel-button if two actions have been passed in
246246 if (data.actions.length == 2) {
247− tryCompareFunction(function() { mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2); return actionSpy.signalArguments.length > 0; }, true);
247+ tryCompareFunction(function() { mouseClick(buttonCancel); return actionSpy.signalArguments.length > 0; }, true);
248248 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
249249 actionSpy.clear()
250250 }
@@ -253,7 +253,7 @@ Row {
253253 verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint")
254254
255255 // click the positive/right button
256− tryCompareFunction(function() { mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2); return actionSpy.signalArguments.length > 0; }, true);
256+ tryCompareFunction(function() { mouseClick(buttonAccept); return actionSpy.signalArguments.length > 0; }, true);
257257 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id positive action")
258258 actionSpy.clear()
259259 waitForRendering(notification)
@@ -264,20 +264,20 @@ Row {
264264 tryCompareFunction(function() { return optionToggle.expanded == false; }, true);
265265
266266 // click to expand
267− tryCompareFunction(function() { mouseClick(optionToggle, optionToggle.width / 2, optionToggle.height / 2); return optionToggle.expanded == true; }, true);
267+ tryCompareFunction(function() { mouseClick(optionToggle); return optionToggle.expanded == true; }, true);
268268
269269 // try clicking on choices in expanded comboList
270270 var choiceButton1 = findChild(notification, "notify_button3")
271− tryCompareFunction(function() { mouseClick(choiceButton1, choiceButton1.width / 2, choiceButton1.height / 2); return actionSpy.signalArguments.length > 0; }, true);
271+ tryCompareFunction(function() { mouseClick(choiceButton1); return actionSpy.signalArguments.length > 0; }, true);
272272 compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1")
273273 actionSpy.clear()
274274
275275 var choiceButton2 = findChild(notification, "notify_button4")
276− tryCompareFunction(function() { mouseClick(choiceButton2, choiceButton2.width / 2, choiceButton2.height / 2); return actionSpy.signalArguments.length > 0; }, true);
276+ tryCompareFunction(function() { mouseClick(choiceButton2); return actionSpy.signalArguments.length > 0; }, true);
277277 compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2")
278278 actionSpy.clear()
279279 } else {
280− mouseClick(buttonCancel, buttonCancel.width / 2, buttonCancel.height / 2)
280+ mouseClick(buttonCancel)
281281 compare(actionSpy.signalArguments[0][0], data.actions[1]["id"], "got wrong id for negative action")
282282 }
283283 }
tests/qmltests/Notifications/tst_SwipeToAct.qml+1−1
@@ -240,7 +240,7 @@ Item {
240240 }
241241
242242 // test input does not fall through
243− mouseClick(notification, notification.width / 2, notification.height / 2)
243+ mouseClick(notification)
244244 if(data.type == Notification.Interactive) {
245245 actionSpy.wait()
246246 compare(actionSpy.signalArguments[0][0], data.actions[0]["id"], "got wrong id for interactive action")
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+2−2
@@ -214,7 +214,7 @@ Row {
214214
215215 // click/tap on each snap-decision and verify only one is in expanded-state at any time
216216 for (var index = 0; index < snap_decision.length; index++) {
217− mouseClick(snap_decision[index], snap_decision[index].width / 2, snap_decision[index].height / 2)
217+ mouseClick(snap_decision[index])
218218 for (var kindex = 0; kindex < snap_decision.length; kindex++) {
219219 if (kindex == index) {
220220 compare(snap_decision[kindex].state, "expanded", "state of "+ kindex + ".snap-decision is not expanded");
@@ -227,7 +227,7 @@ Row {
227227 // remove top-most and verify one of the remaining ones is still getting expanded
228228
229229 // make first snap-decision expand
230− mouseClick(snap_decision[0], snap_decision[0].width / 2, snap_decision[0].height / 2);
230+ mouseClick(snap_decision[0]);
231231
232232 for (var index = 1; index < snap_decision.length; index++) {
233233 removeTopMostNotification();
tests/qmltests/Panel/Indicators/tst_IndicatorsLight.qmlnew file+129
@@ -0,0 +1,129 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtQuick.Layouts 1.1
19+import Unity.Test 0.1 as UT
20+import Unity.Indicators 0.1 as Indicators
21+import Ubuntu.Components 1.1
22+import Powerd 0.1
23+import Lights 0.1
24+import QMenuModel 0.1
25+import "../../../../qml/Panel/Indicators"
26+
27+Item {
28+ id: root
29+ width: units.gu(30)
30+ height: units.gu(30)
31+
32+ property var newMessage: {
33+ "messages" : {
34+ 'valid': true,
35+ 'state': {
36+ 'icons': [ 'indicator-messages-new' ]
37+ }
38+ }
39+ };
40+ property var noNewMessage: {
41+ "messages" : {
42+ 'valid': true,
43+ 'state': {
44+ 'icons': [ 'indicator-messages' ]
45+ }
46+ }
47+ };
48+
49+ Component {
50+ id: light
51+ IndicatorsLight {}
52+ }
53+
54+ Loader {
55+ id: loader
56+ sourceComponent: light
57+ }
58+
59+ Component.onCompleted: {
60+ ActionData.data = newMessage;
61+ Powerd.status = Powerd.On
62+ }
63+
64+ RowLayout {
65+ anchors.fill: parent
66+ anchors.margins: units.gu(1)
67+
68+ Item {
69+ Layout.fillWidth: true
70+ Layout.fillHeight: true
71+
72+ Rectangle {
73+ width: units.gu(4)
74+ height: width
75+ radius: width / 2
76+ anchors.centerIn: parent
77+
78+ color: Lights.state === Lights.On ? Lights.color : "transparent"
79+
80+ border.color: "black"
81+ border.width: 1
82+ }
83+ }
84+
85+ ColumnLayout {
86+ Layout.alignment: Qt.AlignTop
87+ Layout.fillWidth: false
88+ Layout.preferredWidth: units.gu(15)
89+
90+ Button {
91+ Layout.fillWidth: true
92+ text: Powerd.status === Powerd.On ? "Power Off" : "Power On"
93+ onClicked: {
94+ if (Powerd.status === Powerd.On) Powerd.status = Powerd.Off;
95+ else Powerd.status = Powerd.On;
96+ }
97+ }
98+ }
99+ }
100+
101+ UT.UnityTestCase {
102+ name: "IndicatorsLight"
103+ when: windowShown
104+
105+ function init() {
106+ // reload
107+ ActionData.data = noNewMessage;
108+ loader.sourceComponent = undefined;
109+ loader.sourceComponent = light;
110+ Powerd.status = Powerd.On
111+ }
112+
113+ function test_LightsStatus_data() {
114+ return [
115+ { tag: "Powerd.On with No Message", powerd: Powerd.On, actionData: noNewMessage, expected: Lights.Off },
116+ { tag: "Powerd.Off with No Message", powerd: Powerd.Off, actionData: noNewMessage, expected: Lights.Off },
117+ { tag: "Powerd.On with New Message", powerd: Powerd.On, actionData: newMessage, expected: Lights.Off },
118+ { tag: "Powerd.Off with New Message", powerd: Powerd.Off, actionData: newMessage, expected: Lights.On },
119+ ]
120+ }
121+
122+ function test_LightsStatus(data) {
123+ Powerd.status = data.powerd;
124+ ActionData.data = data.actionData;
125+
126+ compare(Lights.state, data.expected, "Light does not match expected value");
127+ }
128+ }
129+}
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+52−1
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import QtTest 1.0
1919import Unity.Test 0.1 as UT
20+import Ubuntu.Settings.Menus 0.1 as Menus
2021import QMenuModel 0.1
2122import Utils 0.1 as Utils
2223import "../../../../qml/Panel/Indicators"
@@ -448,9 +449,59 @@ Item {
448449 }
449450
450451 function test_create_transferMenu(data) {
452+ ActionData.data = {
453+ "transfer-state.queued": {
454+ 'valid': true,
455+ 'state': {
456+ 'state': Menus.TransferState.Queued,
457+ 'percent': data.progress
458+ }
459+ },
460+ "transfer-state.running": {
461+ 'valid': true,
462+ 'state': {
463+ 'state': Menus.TransferState.Running,
464+ 'seconds-left': 100,
465+ 'percent': data.progress
466+ }
467+ },
468+ "transfer-state.paused": {
469+ 'valid': true,
470+ 'state': {
471+ 'state': Menus.TransferState.Paused,
472+ 'seconds-left': 100,
473+ 'percent': data.progress
474+ }
475+ },
476+ "transfer-state.cancelled": {
477+ 'valid': true,
478+ 'state': {
479+ 'state': Menus.TransferState.Canceled,
480+ 'percent': data.progress
481+ }
482+ },
483+ "transfer-state.finished": {
484+ 'valid': true,
485+ 'state': {
486+ 'state': Menus.TransferState.Finished,
487+ 'seconds-left': 0,
488+ 'percent': data.progress
489+ }
490+ },
491+ "transfer-state.error": {
492+ 'valid': true,
493+ 'state': {
494+ 'state': Menus.TransferState.Error,
495+ 'seconds-left': 100,
496+ 'percent': data.progress
497+ }
498+ }
499+ };
500+
451501 menuData.type = "com.canonical.indicator.transfer";
452502 menuData.label = data.label;
453503 menuData.sensitive = data.enabled;
504+ menuData.isToggled = data.active;
454505 menuData.icon = data.icon;
455506 menuData.ext = {
456507 'xCanonicalUid': data.tag
@@ -464,7 +515,7 @@ Item {
464515 compare(loader.item.text, data.label, "Label does not match data");
465516 compare(loader.item.iconSource, data.icon, "Icon does not match data");
466517 compare(loader.item.enabled, data.enabled, "Enabled does not match data");
467− compare(loader.item.progress, data.progress, "Icon does not match data");
518+ compare(loader.item.progress, data.progress, "Progress does not match data");
468519 compare(loader.item.active, data.active, "Active does not match data");
469520 compare(loader.item.stateText, data.stateText, "State text does not match data");
470521 }
tests/qmltests/Panel/tst_IndicatorsBar.qml+1−1
@@ -197,7 +197,7 @@ IndicatorTest {
197197 if (indicatorsBar.mapFromItem(dataItem, dataItem.width/2, dataItem.height/2).x < 0) {
198198 skip("Out of bounds");
199199 }
200− mouseClick(dataItem, dataItem.width/2, dataItem.height/2);
200+ mouseClick(dataItem);
201201 verify(dataItem.selected === true);
202202 }
203203
tests/qmltests/Stages/tst_PhoneStage.qml+2
@@ -205,6 +205,7 @@ Item {
205205
206206 if (data.targetPhase == 2) {
207207 var app2 = findChild(spreadView, "appDelegate2");
208+ tryCompare(app2, "swipeToCloseEnabled", true);
208209 mouseClick(app2, units.gu(1), units.gu(1));
209210 }
210211
@@ -249,6 +250,7 @@ Item {
249250 }
250251
251252 console.log("clicking app", data.index, "(", appId, ")")
253+ tryCompare(tile, "swipeToCloseEnabled", true);
252254 mouseClick(spreadView, tile.mapToItem(spreadView).x + units.gu(1), spreadView.height / 2)
253255 tryCompare(ApplicationManager, "focusedApplicationId", appId);
254256 tryCompare(spreadView, "phase", 0);
tests/qmltests/Wizard/tst_Wizard.qml+36−12
@@ -18,6 +18,7 @@ import QtQuick 2.3
1818import QtTest 1.0
1919import AccountsService 0.1
2020import MeeGo.QOfono 0.2
21+import QMenuModel 0.1
2122import Ubuntu.Components 1.1
2223import Ubuntu.SystemSettings.SecurityPrivacy 1.0
2324import Unity.Test 0.1 as UT
@@ -58,6 +59,16 @@ Item {
5859 signalName: "setSecurityCalled"
5960 }
6061
62+ SignalSpy {
63+ id: activateLocationSpy
64+ signalName: "activated"
65+ }
66+
67+ SignalSpy {
68+ id: activateGPSSpy
69+ signalName: "activated"
70+ }
71+
6172 function setup() {
6273 AccountsService.hereEnabled = false;
6374 AccountsService.hereLicensePath = Qt.resolvedUrl("licenses");
@@ -68,6 +79,19 @@ Item {
6879
6980 updateSessionLanguageSpy.clear();
7081 setSecuritySpy.clear();
82+ activateLocationSpy.clear();
83+ activateGPSSpy.clear();
84+
85+ ActionData.data = {
86+ "location-detection-enabled": {
87+ 'valid': true,
88+ 'state': false
89+ },
90+ "gps-detection-enabled": {
91+ 'valid': true,
92+ 'state': false
93+ }
94+ };
7195 }
7296
7397 Component.onCompleted: {
@@ -360,8 +384,8 @@ Item {
360384 var nopeCheck = findChild(page, "nopeCheck");
361385
362386 var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
363− tryCompare(locationActionGroup.location, "state", false);
364− tryCompare(locationActionGroup.gps, "state", false);
387+ activateLocationSpy.target = locationActionGroup.location;
388+ activateGPSSpy.target = locationActionGroup.gps;
365389
366390 tap(gpsCheck);
367391 tryCompare(gpsCheck, "checked", true);
@@ -370,8 +394,8 @@ Item {
370394
371395 tap(findChild(page, "forwardButton"));
372396 tryCompare(AccountsService, "hereEnabled", false);
373− tryCompare(locationActionGroup.location, "state", true);
374− tryCompare(locationActionGroup.gps, "state", true);
397+ tryCompare(activateLocationSpy, "count", 1)
398+ tryCompare(activateGPSSpy, "count", 1)
375399 }
376400
377401 function test_locationNope() {
@@ -381,8 +405,8 @@ Item {
381405 var nopeCheck = findChild(page, "nopeCheck");
382406
383407 var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
384− tryCompare(locationActionGroup.location, "state", false);
385− tryCompare(locationActionGroup.gps, "state", false);
408+ activateLocationSpy.target = locationActionGroup.location;
409+ activateGPSSpy.target = locationActionGroup.gps;
386410
387411 tap(nopeCheck);
388412 tryCompare(gpsCheck, "checked", false);
@@ -391,8 +415,8 @@ Item {
391415
392416 tap(findChild(page, "forwardButton"));
393417 tryCompare(AccountsService, "hereEnabled", false);
394− tryCompare(locationActionGroup.location, "state", false);
395− tryCompare(locationActionGroup.gps, "state", false);
418+ tryCompare(activateLocationSpy, "count", 0)
419+ tryCompare(activateGPSSpy, "count", 0)
396420 }
397421
398422 function test_locationHere() {
@@ -402,8 +426,8 @@ Item {
402426 var nopeCheck = findChild(page, "nopeCheck");
403427
404428 var locationActionGroup = findInvisibleChild(page, "locationActionGroup");
405− tryCompare(locationActionGroup.location, "state", false);
406− tryCompare(locationActionGroup.gps, "state", false);
429+ activateLocationSpy.target = locationActionGroup.location;
430+ activateGPSSpy.target = locationActionGroup.gps;
407431
408432 // no tap because HERE is the default
409433 tryCompare(gpsCheck, "checked", false);
@@ -412,8 +436,8 @@ Item {
412436
413437 tap(findChild(page, "forwardButton"));
414438 tryCompare(AccountsService, "hereEnabled", true);
415− tryCompare(locationActionGroup.location, "state", true);
416− tryCompare(locationActionGroup.gps, "state", true);
439+ tryCompare(activateLocationSpy, "count", 1)
440+ tryCompare(activateGPSSpy, "count", 1)
417441 }
418442
419443 function test_locationHereTerms() {
tests/qmltests/tst_Shell.qml+3−3
@@ -222,7 +222,7 @@ Item {
222222
223223 notifications.model = mockNotificationsModel;
224224
225− // FIXME: Hack: SortFilterProxyModelQML doesn't work with QML ListModels which we use
225+ // FIXME: Hack: UnitySortFilterProxyModelQML doesn't work with QML ListModels which we use
226226 // for mocking here (RoleType can't be found in the QML model). As we only need to show
227227 // one SnapDecision lets just disable the filtering and make appear any notification as a
228228 // SnapDecision.
@@ -245,7 +245,7 @@ Item {
245245
246246 // Clicking the button should dismiss the notification and return focus
247247 var buttonAccept = findChild(notification, "notify_button0");
248− mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2);
248+ mouseClick(buttonAccept);
249249
250250 // Make sure we're back to normal
251251 tryCompare(app.session.surface, "activeFocus", true);
@@ -463,7 +463,7 @@ Item {
463463 var launcher = findChild(shell, "launcherPanel")
464464 tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true);
465465 if (launcher.x === 0) {
466− mouseClick(shell, shell.width / 2, shell.height / 2)
466+ mouseClick(shell)
467467 }
468468 tryCompare(launcher, "x", -launcher.width)
469469
tests/qmltests/tst_ShellWithPin.qml+31
@@ -116,6 +116,12 @@ Item {
116116 signalName: "resettingDevice"
117117 }
118118
119+ SignalSpy {
120+ id: promptSpy
121+ target: LightDM.Greeter
122+ signalName: "showPrompt"
123+ }
124+
119125 Telephony.CallEntry {
120126 id: phoneCall
121127 phoneNumber: "+447812221111"
@@ -472,5 +478,30 @@ Item {
472478
473479 }
474480
481+ /* We had a bug (1395075) where if a user kept swiping as the greeter
482+ loaded, they would be able to get into the session before the
483+ lockscreen appeared. Make sure that doesn't happen. */
484+ function test_earlyDisable() {
485+ // Kill current shell
486+ shellLoader.itemDestroyed = false;
487+ shellLoader.active = false;
488+ tryCompare(shellLoader, "itemDestroyed", true);
489+ LightDM.Greeter.authenticate(""); // reset greeter
490+
491+ // Create new shell
492+ promptSpy.clear();
493+ shellLoader.active = true;
494+ tryCompareFunction(function() {return shell !== null}, true);
495+
496+ // Confirm that we start disabled
497+ compare(promptSpy.count, 0);
498+ verify(!shell.enabled);
499+
500+ // And that we only become enabled once the lockscreen is up
501+ tryCompare(shell, "enabled", true);
502+ verify(promptSpy.count > 0);
503+ var lockscreen = findChild(shell, "lockscreen");
504+ verify(lockscreen.shown);
505+ }
475506 }
476507}
tests/qmltests/tst_TabletShell.qml+1−1
@@ -211,7 +211,7 @@ Row {
211211 tryCompare(passwordMouseArea, "enabled", isButton)
212212
213213 var passwordInput = findChild(shell, "passwordInput")
214− mouseClick(passwordInput, passwordInput.width / 2, passwordInput.height / 2)
214+ mouseClick(passwordInput)
215215 }
216216
217217 function confirmLoggedIn(loggedIn) {
tests/utils/modules/Unity/Test/UnityTestCase.qml+71
@@ -37,6 +37,67 @@ TestCase {
3737 this.getCurrentTimeMs = function() {return this.currentTimeMs}
3838 }
3939
40+ function mouseClick(item, x, y, button, modifiers, delay) {
41+ if (button === undefined)
42+ button = Qt.LeftButton;
43+ if (modifiers === undefined)
44+ modifiers = Qt.NoModifier;
45+ if (delay === undefined)
46+ delay = -1;
47+ if (x === undefined)
48+ x = item.width / 2;
49+ if (y === undefined)
50+ y = item.height / 2;
51+ if (!qtest_events.mouseClick(item, x, y, button, modifiers, delay))
52+ qtest_fail("window not shown", 2);
53+ }
54+
55+ function mouseDoubleClick(item, x, y, button, modifiers, delay) {
56+ if (button === undefined)
57+ button = Qt.LeftButton;
58+ if (modifiers === undefined)
59+ modifiers = Qt.NoModifier;
60+ if (delay === undefined)
61+ delay = -1;
62+ if (x === undefined)
63+ x = item.width / 2;
64+ if (y === undefined)
65+ y = item.height / 2;
66+ if (!qtest_events.mouseDoubleClick(item, x, y, button, modifiers, delay))
67+ qtest_fail("window not shown", 2)
68+ }
69+
70+ function mousePress(item, x, y, button, modifiers, delay) {
71+ if (button === undefined)
72+ button = Qt.LeftButton;
73+ if (modifiers === undefined)
74+ modifiers = Qt.NoModifier;
75+ if (delay === undefined)
76+ delay = -1;
77+ if (x === undefined)
78+ x = item.width / 2;
79+ if (y === undefined)
80+ y = item.height / 2;
81+ if (!qtest_events.mousePress(item, x, y, button, modifiers, delay))
82+ qtest_fail("window not shown", 2)
83+ }
84+
85+ function mouseRelease(item, x, y, button, modifiers, delay) {
86+ if (button === undefined)
87+ button = Qt.LeftButton;
88+ if (modifiers === undefined)
89+ modifiers = Qt.NoModifier;
90+ if (delay === undefined)
91+ delay = -1;
92+ if (x === undefined)
93+ x = item.width / 2;
94+ if (y === undefined)
95+ y = item.height / 2;
96+ if (!qtest_events.mouseRelease(item, x, y, button, modifiers, delay))
97+ qtest_fail("window not shown", 2)
98+ }
99+
100+
40101 // Flickable won't recognise a single mouse move as dragging the flickable.
41102 // Use 5 steps because it's what
42103 // Qt uses in QQuickViewTestUtil::flick
@@ -381,4 +442,14 @@ TestCase {
381442 }
382443 }
383444 }
445+
446+ // TODO This function can be removed altogether once we use Qt 5.5 which has the same feature
447+ function waitForRendering(item, timeout) {
448+ if (timeout === undefined)
449+ timeout = 5000;
450+ if (!item)
451+ qtest_fail("No item given to waitForRendering", 1);
452+ return qtest_results.waitForRendering(item, timeout);
453+ }
454+
384455}