on xenial help sign in
merged with trunk
1b40225Nick Dedekind
CMakeLists.txt+2
@@ -105,6 +105,8 @@ declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
105set(SHELL_APP unity8)
105set(SHELL_APP unity8)
106set(DASH_APP unity8-dash)
106set(DASH_APP unity8-dash)
107set(SCOPE_TOOL unity-scope-tool)
107set(SCOPE_TOOL unity-scope-tool)
108+set(INDICATORS_CLIENT_APP indicators-client)
109+set(MOCK_INDICATOR_SERVICE_APP unity-mock-indicator-service)
108
110
109include_directories(
111include_directories(
110 ${CMAKE_SOURCE_DIR}/include
112 ${CMAKE_SOURCE_DIR}/include
CODING+1−1
@@ -186,7 +186,7 @@ $ make install
186
186
187To see the list of existing autopilot tests you can do
187To see the list of existing autopilot tests you can do
188
188
189−$ PYTHONPATH=../tests/autopilot autopilot list unity8
189+$ PYTHONPATH=../tests/autopilot autopilot3 list unity8
190
190
191And then run a single test with
191And then run a single test with
192
192
data/CMakeLists.txt+2
@@ -1,11 +1,13 @@
1# generate desktop files
1# generate desktop files
2configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
2configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
3configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
3configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
4+configure_file(${INDICATORS_CLIENT_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop @ONLY)
4
5
5# install desktop files
6# install desktop files
6install(FILES
7install(FILES
7 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
8 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
8 ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
9 ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
10+ ${CMAKE_CURRENT_BINARY_DIR}/${INDICATORS_CLIENT_APP}.desktop
9 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
11 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
10 )
12 )
11
13
data/indicators-client.desktop.innew file+9
@@ -0,0 +1,9 @@
1+[Desktop Entry]
2+Type=Application
3+Name=Indicators Client
4+Comment=Application for testing the Indicators system
5+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/indicators-client
6+Terminal=false
7+Icon=
8+NoDisplay=false
9+X-Ubuntu-Touch=true
data/unity-mock-indicator-service.confnew file+7
@@ -0,0 +1,7 @@
1+description "Unity Shell v8 Mock Indicator"
2+author "Nick Dedekind <nick.dedekind@canonical.com>"
3+
4+respawn
5+respawn limit 2 10
6+
7+exec ${BINARY:-unity-mock-indicator-service} $ARGS
debian/changelog+53
@@ -1,3 +1,56 @@
1+unity8 (8.02+15.04.20150409.1-0ubuntu1) vivid; urgency=medium
2+
3+ [ Albert Astals Cid ]
4+ * Focus the shutdown dialog (LP: #1417991)
5+ * Make url-dispatching scope activation when the dash is not on the
6+ main scopes (LP: #1364306)
7+ * We use autopilot3 now
8+
9+ [ CI Train Bot ]
10+ * New rebuild forced.
11+ * Resync trunk. added: po/or.po
12+
13+ [ Daniel d'Andrada ]
14+ * Make tst_PreviewListView and tst_GenericScopeView work in out-of-
15+ source builds
16+ * MouseArea that shows the indicators panel should cover the
17+ indicators bar only (LP: #1439318)
18+ * Surface gets active focus also with mouse clicks
19+
20+ [ Josh Arenson ]
21+ * Add a mode option to unity8 for selecting greeter mode in the future
22+ * Remove PkgConfig include from Launcher plugin to fix cross-compile
23+ (LP: #1437702)
24+
25+ [ Leo Arias ]
26+ * Fixed the check for string in the lock screen test. (LP: #1434518)
27+
28+ [ Michael Terry ]
29+ * Make sure the edge tutorial is destroyed when we receive a call
30+ during the wizard. (LP: #1436349)
31+ * Skip parts of the edge tutorial that require a touch device (like
32+ spread and bottom edge). (LP: #1434712)
33+
34+ [ Michael Zanetti ]
35+ * Don't hide stages just because they're empty (LP: #1439615)
36+ * [Launcher] fix bug where an item would disappear even though the app
37+ is running (LP: #1438172)
38+
39+ [ Nick Dedekind ]
40+ * Fixed autopilot test failures related to udev input failure for
41+ power button.
42+ * Made improvements for laggy indicator backends (lp#1390136). (LP:
43+ #1390136)
44+
45+ [ Pete Woods ]
46+ * GPS only goes active when the Dash is in the foreground (LP:
47+ #1434379)
48+
49+ [ handsome_feng<445865575@qq.com> ]
50+ * Modified the wrong time format in ScreenGrabber (LP: #1436006)
51+
52+ -- CI Train Bot <ci-train-bot@canonical.com> Thu, 09 Apr 2015 14:01:11 +0000
53+
1unity8 (8.02+15.04.20150320-0ubuntu1) vivid; urgency=medium
54unity8 (8.02+15.04.20150320-0ubuntu1) vivid; urgency=medium
2
55
3 [ Albert Astals Cid ]
56 [ Albert Astals Cid ]
debian/control+2−2
@@ -47,7 +47,7 @@ Build-Depends: cmake,
47 qtdeclarative5-dev-tools,
47 qtdeclarative5-dev-tools,
48 qtdeclarative5-private-dev (>= 5.2.1),
48 qtdeclarative5-private-dev (>= 5.2.1),
49 qtdeclarative5-qtmultimedia-plugin,
49 qtdeclarative5-qtmultimedia-plugin,
50− qtdeclarative5-ubuntu-settings-components (>= 0.5),
50+ qtdeclarative5-ubuntu-settings-components (>= 0.6),
51 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
51 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
52 qtdeclarative5-ubuntu-web-plugin,
52 qtdeclarative5-ubuntu-web-plugin,
53 ttf-ubuntu-font-family,
53 ttf-ubuntu-font-family,
@@ -119,7 +119,7 @@ Description: Unity 8 shell
119Package: unity8-common
119Package: unity8-common
120Architecture: all
120Architecture: all
121Depends: qml-module-qtquick-layouts,
121Depends: qml-module-qtquick-layouts,
122− qtdeclarative5-ubuntu-settings-components (>= 0.4),
122+ qtdeclarative5-ubuntu-settings-components (>= 0.6),
123 qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
123 qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
124 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
124 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
125 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
125 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
debian/indicators-client.install+1
@@ -1 +1,2 @@
1+usr/share/applications/indicators-client.desktop
1/usr/bin/indicators-client
2/usr/bin/indicators-client
debian/unity8-autopilot.install+3−1
@@ -1,2 +1,4 @@
1+data/unity-mock-indicator-service.conf usr/share/upstart/sessions/
2+usr/bin/unity-mock-indicator-service
1usr/lib/python*/*/unity*
3usr/lib/python*/*/unity*
2−usr/share/unity8/unlock-device
4+usr/share/unity8/unlock-device
include/paths.h.in+1−6
@@ -92,12 +92,7 @@ inline QString mockPluginsDir() {
92
92
93inline QStringList shellDataDirs() {
93inline QStringList shellDataDirs() {
94 QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
94 QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
95− if (!isRunningInstalled()) {
95+ if (isRunningInstalled()) {
96− if (getenv("UNITY_TEST_ENV")==nullptr) {
97− dirs.prepend("@CMAKE_BINARY_DIR@/share");
98− }
99− }
100− else {
101 // append so by default we use xdg files.
96 // append so by default we use xdg files.
102 dirs.append(qmlDirectory());
97 dirs.append(qmlDirectory());
103 }
98 }
plugins/Greeter/Unity/Launcher/CMakeLists.txt−1
@@ -1,4 +1,3 @@
1−include(FindPkgConfig)
2pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6)
1pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6)
3pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
2pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
4pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
3pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
plugins/ScreenGrabber/screengrabber.cpp+1−1
@@ -81,7 +81,7 @@ void ScreenGrabber::captureAndSave()
81QString ScreenGrabber::makeFileName()
81QString ScreenGrabber::makeFileName()
82{
82{
83 QString fileName(fileNamePrefix);
83 QString fileName(fileNamePrefix);
84− fileName.append(QDateTime::currentDateTime().toString("yyyymmdd_hhmmsszzz"));
84+ fileName.append(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmsszzz"));
85 fileName.append(".");
85 fileName.append(".");
86 fileName.append(getFormat());
86 fileName.append(getFormat());
87 return fileName;
87 return fileName;
plugins/Ubuntu/Gestures/TouchGate.cpp−2
@@ -53,8 +53,6 @@ void TouchGate::touchEvent(QTouchEvent *event)
53 m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested;
53 m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested;
54 m_touchInfoMap[touchPoint.id()].ended = false;
54 m_touchInfoMap[touchPoint.id()].ended = false;
55 TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(), this);
55 TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(), this);
56−
57− Q_EMIT pressed();
58 }
56 }
59
57
60 goodToGo &= m_touchInfoMap.contains(touchPoint.id())
58 goodToGo &= m_touchInfoMap.contains(touchPoint.id())
plugins/Ubuntu/Gestures/TouchGate.h−2
@@ -53,8 +53,6 @@ public:
53Q_SIGNALS:
53Q_SIGNALS:
54 void targetItemChanged(QQuickItem *item);
54 void targetItemChanged(QQuickItem *item);
55
55
56− void pressed();
57−
58protected:
56protected:
59 void touchEvent(QTouchEvent *event) override;
57 void touchEvent(QTouchEvent *event) override;
60private:
58private:
plugins/Unity/Launcher/launchermodel.cpp+7−7
@@ -468,14 +468,14 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
468 return;
468 return;
469 }
469 }
470
470
471− bool found = false;
471+ int itemIndex = findApplication(app->appId());
472+ if (itemIndex != -1) {
472− Q_FOREACH(LauncherItem *item, m_list) {
473+ LauncherItem *item = m_list.at(itemIndex);
473− if (app->appId() == item->appId()) {
474+ if (!item->recent()) {
474− found = true;
475+ item->setRecent(true);
475− break;
476+ m_asAdapter->syncItems(m_list);
477+ Q_EMIT dataChanged(index(itemIndex), index(itemIndex), QVector<int>() << RoleRecent);
476 }
478 }
477− }
478− if (found) {
479 // Shall we paint some running/recent app highlight? If yes, do it here.
479 // Shall we paint some running/recent app highlight? If yes, do it here.
480 } else {
480 } else {
481 LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
481 LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
plugins/Utils/CMakeLists.txt+2
@@ -8,6 +8,8 @@ include_directories(
8)
8)
9
9
10set(QMLPLUGIN_SRC
10set(QMLPLUGIN_SRC
11+ constants.cpp
12+ inputwatcher.cpp
11 qlimitproxymodelqml.cpp
13 qlimitproxymodelqml.cpp
12 unitysortfilterproxymodelqml.cpp
14 unitysortfilterproxymodelqml.cpp
13 relativetimeformatter.cpp
15 relativetimeformatter.cpp
plugins/Utils/constants.cppnew file+27
@@ -0,0 +1,27 @@
1+/*
2+ * Copyright 2015 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 "constants.h"
18+
19+Constants::Constants(QObject *parent)
20+ : QObject(parent)
21+{
22+ if (qgetenv("QT_LOAD_TESTABILITY").isEmpty()) {
23+ m_indicatorValueTimeout = 30000;
24+ } else {
25+ m_indicatorValueTimeout = 5000;
26+ }
27+}
plugins/Utils/constants.hnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright 2015 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 CONSTANTS_H
18+#define CONSTANTS_H
19+
20+#include <QObject>
21+
22+/**
23+ * @brief The Constants class
24+ *
25+ * This singleton class exposes contants to Qml
26+ *
27+ */
28+
29+class Constants: public QObject
30+{
31+ Q_OBJECT
32+ Q_PROPERTY(int indicatorValueTimeout READ indicatorValueTimeout CONSTANT)
33+
34+public:
35+ Constants(QObject *parent = 0);
36+
37+ int indicatorValueTimeout() const { return m_indicatorValueTimeout; }
38+
39+private:
40+ int m_indicatorValueTimeout;
41+};
42+
43+#endif
plugins/Utils/inputwatcher.cppnew file+118
@@ -0,0 +1,118 @@
1+/*
2+ * Copyright (C) 2015 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+
18+#include "inputwatcher.h"
19+
20+#include <QMouseEvent>
21+
22+InputWatcher::InputWatcher(QObject *parent)
23+ : QObject(parent)
24+ , m_mousePressed(false)
25+ , m_touchPressed(false)
26+{
27+}
28+
29+QObject *InputWatcher::target() const
30+{
31+ return m_target;
32+}
33+
34+void InputWatcher::setTarget(QObject *value)
35+{
36+ if (m_target == value) {
37+ return;
38+ }
39+
40+ if (m_target) {
41+ m_target->removeEventFilter(this);
42+ }
43+
44+ setMousePressed(false);
45+ setTouchPressed(false);
46+
47+ m_target = value;
48+ if (m_target) {
49+ m_target->installEventFilter(this);
50+ }
51+
52+ Q_EMIT targetChanged(value);
53+}
54+
55+bool InputWatcher::targetPressed() const
56+{
57+ return m_mousePressed || m_touchPressed;
58+}
59+
60+bool InputWatcher::eventFilter(QObject* /*watched*/, QEvent *event)
61+{
62+ switch (event->type()) {
63+ case QEvent::TouchBegin:
64+ setTouchPressed(true);
65+ break;
66+ case QEvent::TouchEnd:
67+ setTouchPressed(false);
68+ break;
69+ case QEvent::MouseButtonPress:
70+ {
71+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
72+ if (mouseEvent->button() == Qt::LeftButton) {
73+ setMousePressed(true);
74+ }
75+ }
76+ break;
77+ case QEvent::MouseButtonRelease:
78+ {
79+ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
80+ if (mouseEvent->button() == Qt::LeftButton) {
81+ setMousePressed(false);
82+ }
83+ }
84+ break;
85+ default:
86+ // Not interested
87+ break;
88+ }
89+
90+ // We never filter them out. We are just watching.
91+ return false;
92+}
93+
94+void InputWatcher::setMousePressed(bool value)
95+{
96+ if (value == m_mousePressed) {
97+ return;
98+ }
99+
100+ bool oldPressed = targetPressed();
101+ m_mousePressed = value;
102+ if (targetPressed() != oldPressed) {
103+ Q_EMIT targetPressedChanged(targetPressed());
104+ }
105+}
106+
107+void InputWatcher::setTouchPressed(bool value)
108+{
109+ if (value == m_touchPressed) {
110+ return;
111+ }
112+
113+ bool oldPressed = targetPressed();
114+ m_touchPressed = value;
115+ if (targetPressed() != oldPressed) {
116+ Q_EMIT targetPressedChanged(targetPressed());
117+ }
118+}
plugins/Utils/inputwatcher.hnew file+58
@@ -0,0 +1,58 @@
1+/*
2+ * Copyright (C) 2015 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+
18+#ifndef UNITY_INPUTWATCHER_H
19+#define UNITY_INPUTWATCHER_H
20+
21+#include <QObject>
22+#include <QPointer>
23+
24+/*
25+ Monitors the target object for input events to figure out whether it's pressed
26+ or not.
27+ */
28+class InputWatcher : public QObject
29+{
30+ Q_OBJECT
31+ Q_PROPERTY(QObject* target READ target WRITE setTarget NOTIFY targetChanged)
32+
33+ // Whether the target object is pressed (by either touch or mouse)
34+ Q_PROPERTY(bool targetPressed READ targetPressed NOTIFY targetPressedChanged)
35+public:
36+ InputWatcher(QObject *parent = nullptr);
37+
38+ QObject *target() const;
39+ void setTarget(QObject *value);
40+
41+ bool targetPressed() const;
42+
43+ bool eventFilter(QObject *watched, QEvent *event) override;
44+
45+Q_SIGNALS:
46+ void targetChanged(QObject *value);
47+ void targetPressedChanged(bool value);
48+
49+private:
50+ void setMousePressed(bool value);
51+ void setTouchPressed(bool value);
52+
53+ bool m_mousePressed;
54+ bool m_touchPressed;
55+ QPointer<QObject> m_target;
56+};
57+
58+#endif // UNITY_INPUTWATCHER_H
plugins/Utils/plugin.cpp+11
@@ -26,6 +26,7 @@
26#include "plugin.h"
26#include "plugin.h"
27
27
28// local
28// local
29+#include "inputwatcher.h"
29#include "qlimitproxymodelqml.h"
30#include "qlimitproxymodelqml.h"
30#include "unitysortfilterproxymodelqml.h"
31#include "unitysortfilterproxymodelqml.h"
31#include "relativetimeformatter.h"
32#include "relativetimeformatter.h"
@@ -34,6 +35,7 @@
34#include "windowkeysfilter.h"
35#include "windowkeysfilter.h"
35#include "easingcurve.h"
36#include "easingcurve.h"
36#include "windowstatestorage.h"
37#include "windowstatestorage.h"
38+#include "constants.h"
37
39
38static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
40static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
39{
41{
@@ -42,6 +44,13 @@ static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEn
42 return new WindowStateStorage();
44 return new WindowStateStorage();
43}
45}
44
46
47+static QObject *createConstants(QQmlEngine *engine, QJSEngine *scriptEngine)
48+{
49+ Q_UNUSED(engine)
50+ Q_UNUSED(scriptEngine)
51+ return new Constants();
52+}
53+
45void UtilsPlugin::registerTypes(const char *uri)
54void UtilsPlugin::registerTypes(const char *uri)
46{
55{
47 Q_ASSERT(uri == QLatin1String("Utils"));
56 Q_ASSERT(uri == QLatin1String("Utils"));
@@ -55,6 +64,8 @@ void UtilsPlugin::registerTypes(const char *uri)
55 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
64 qmlRegisterType<EasingCurve>(uri, 0, 1, "EasingCurve");
56 qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
65 qmlRegisterType<RelativeTimeFormatter>(uri, 0, 1, "RelativeTimeFormatter");
57 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
66 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
67+ qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
68+ qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
58}
69}
59
70
60void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
71void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
po/bg.po+38−39
@@ -15,35 +15,35 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2015-04-13 05:42+0000\n"
18+"X-Launchpad-Export-Date: 2015-04-14 05:33+0000\n"
19"X-Generator: Launchpad (build 17423)\n"
19"X-Generator: Launchpad (build 17423)\n"
20
20
21−#: plugins/LightDM/Greeter.cpp:130
21+#: plugins/LightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
23msgstr ""
23msgstr ""
24
24
25#: plugins/Unity/Launcher/launcheritem.cpp:45
25#: plugins/Unity/Launcher/launcheritem.cpp:45
26−#: plugins/Unity/Launcher/launcheritem.cpp:91
26+#: plugins/Unity/Launcher/launcheritem.cpp:100
27msgid "Pin shortcut"
27msgid "Pin shortcut"
28msgstr ""
28msgstr ""
29
29
30−#: plugins/Unity/Launcher/launcheritem.cpp:91
30+#: plugins/Unity/Launcher/launcheritem.cpp:100
31msgid "Unpin shortcut"
31msgid "Unpin shortcut"
32msgstr ""
32msgstr ""
33
33
34−#: qml/Components/DelayedLockscreen.qml:47
34+#: qml/Components/DelayedLockscreen.qml:49
35msgid "Device Locked"
35msgid "Device Locked"
36msgstr ""
36msgstr ""
37
37
38−#: qml/Components/DelayedLockscreen.qml:62
38+#: qml/Components/DelayedLockscreen.qml:64
39msgid "You have been locked out due to too many failed passphrase attempts."
39msgid "You have been locked out due to too many failed passphrase attempts."
40msgstr ""
40msgstr ""
41
41
42−#: qml/Components/DelayedLockscreen.qml:63
42+#: qml/Components/DelayedLockscreen.qml:65
43msgid "You have been locked out due to too many failed passcode attempts."
43msgid "You have been locked out due to too many failed passcode attempts."
44msgstr ""
44msgstr ""
45
45
46−#: qml/Components/DelayedLockscreen.qml:72
46+#: qml/Components/DelayedLockscreen.qml:74
47#, qt-format
47#, qt-format
48msgid "Please wait %1 minute and then try again…"
48msgid "Please wait %1 minute and then try again…"
49msgid_plural "Please wait %1 minutes and then try again…"
49msgid_plural "Please wait %1 minutes and then try again…"
@@ -55,7 +55,7 @@ msgctxt "Title: Lock/Log out dialog"
55msgid "Log out"
55msgid "Log out"
56msgstr ""
56msgstr ""
57
57
58−#: qml/Components/Dialogs.qml:75
58+#: qml/Components/Dialogs.qml:68
59msgid "Are you sure you want to log out?"
59msgid "Are you sure you want to log out?"
60msgstr ""
60msgstr ""
61
61
@@ -69,6 +69,7 @@ msgctxt "Button: Log out from the system"
69msgid "Log Out"
69msgid "Log Out"
70msgstr ""
70msgstr ""
71
71
72+#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:115
72#: qml/Components/Dialogs.qml:171
73#: qml/Components/Dialogs.qml:171
73msgid "Cancel"
74msgid "Cancel"
74msgstr ""
75msgstr ""
@@ -78,7 +79,7 @@ msgctxt "Title: Reboot/Shut down dialog"
78msgid "Shut down"
79msgid "Shut down"
79msgstr ""
80msgstr ""
80
81
81−#: qml/Components/Dialogs.qml:99
82+#: qml/Components/Dialogs.qml:97
82msgid "Are you sure you want to shut down?"
83msgid "Are you sure you want to shut down?"
83msgstr ""
84msgstr ""
84
85
@@ -97,17 +98,15 @@ msgctxt "Title: Reboot dialog"
97msgid "Reboot"
98msgid "Reboot"
98msgstr ""
99msgstr ""
99
100
100−#: qml/Components/Dialogs.qml:124
101+#: qml/Components/Dialogs.qml:128
101msgid "Are you sure you want to reboot?"
102msgid "Are you sure you want to reboot?"
102msgstr ""
103msgstr ""
103
104
104−#: qml/Components/Dialogs.qml:77 qml/Components/Dialogs.qml:101
105+#: qml/Components/Dialogs.qml:130
105−#: qml/Components/Dialogs.qml:126
106msgid "No"
106msgid "No"
107msgstr ""
107msgstr ""
108
108
109−#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:108
109+#: qml/Components/Dialogs.qml:136
110−#: qml/Components/Dialogs.qml:133
111msgid "Yes"
110msgid "Yes"
112msgstr ""
111msgstr ""
113
112
@@ -116,7 +115,7 @@ msgctxt "Title: Power off/Restart dialog"
116msgid "Power"
115msgid "Power"
117msgstr ""
116msgstr ""
118
117
119−#: qml/Components/Dialogs.qml:149
118+#: qml/Components/Dialogs.qml:151
120msgid ""
119msgid ""
121"Are you sure you would like\n"
120"Are you sure you would like\n"
122"to power off?"
121"to power off?"
@@ -134,23 +133,23 @@ msgctxt "Button: Restart the system"
134msgid "Restart"
133msgid "Restart"
135msgstr ""
134msgstr ""
136
135
137−#: qml/Components/Lockscreen.qml:223
136+#: qml/Components/Lockscreen.qml:238
138msgid "Return to Call"
137msgid "Return to Call"
139msgstr ""
138msgstr ""
140
139
141−#: qml/Components/Lockscreen.qml:223
140+#: qml/Components/Lockscreen.qml:238
142msgid "Emergency Call"
141msgid "Emergency Call"
143msgstr "Спешно повикване"
142msgstr "Спешно повикване"
144
143
145−#: qml/Components/Lockscreen.qml:255
144+#: qml/Components/Lockscreen.qml:270
146msgid "OK"
145msgid "OK"
147msgstr ""
146msgstr ""
148
147
149−#: qml/Dash/GenericScopeView.qml:434 qml/Dash/GenericScopeView.qml:591
148+#: qml/Dash/GenericScopeView.qml:533 qml/Dash/GenericScopeView.qml:691
150msgid "See less"
149msgid "See less"
151msgstr ""
150msgstr ""
152
151
153−#: qml/Dash/GenericScopeView.qml:434
152+#: qml/Dash/GenericScopeView.qml:533
154msgid "See all"
153msgid "See all"
155msgstr ""
154msgstr ""
156
155
@@ -174,11 +173,11 @@ msgctxt "Button: Show the current dash scope settings"
174msgid "Settings"
173msgid "Settings"
175msgstr ""
174msgstr ""
176
175
177−#: qml/Dash/PageHeader.qml:285
176+#: qml/Dash/PageHeader.qml:293
178msgid "Remove from Favorites"
177msgid "Remove from Favorites"
179msgstr ""
178msgstr ""
180
179
181−#: qml/Dash/PageHeader.qml:285
180+#: qml/Dash/PageHeader.qml:293
182msgid "Add to Favorites"
181msgid "Add to Favorites"
183msgstr ""
182msgstr ""
184
183
@@ -214,19 +213,19 @@ msgstr ""
214msgid "Enable location data"
213msgid "Enable location data"
215msgstr ""
214msgstr ""
216
215
217−#: qml/Dash/ScopesList.qml:63
216+#: qml/Dash/ScopesList.qml:66
218msgid "Manage"
217msgid "Manage"
219msgstr ""
218msgstr ""
220
219
221−#: qml/Dash/ScopesList.qml:107
220+#: qml/Dash/ScopesList.qml:112
222msgid "Home"
221msgid "Home"
223msgstr ""
222msgstr ""
224
223
225−#: qml/Dash/ScopesList.qml:108
224+#: qml/Dash/ScopesList.qml:113
226msgid "Also installed"
225msgid "Also installed"
227msgstr ""
226msgstr ""
228
227
229−#: qml/Greeter/Greeter.qml:174
228+#: qml/Greeter/CoverPage.qml:107
230msgid "Unlock"
229msgid "Unlock"
231msgstr ""
230msgstr ""
232
231
@@ -238,57 +237,57 @@ msgstr ""
238msgid "Tap to unlock"
237msgid "Tap to unlock"
239msgstr ""
238msgstr ""
240
239
241−#: qml/Shell.qml:444
240+#: qml/Greeter/NarrowView.qml:53 qml/Wizard/Pages/passwd-confirm.qml:53
242msgid "Sorry, incorrect passphrase."
241msgid "Sorry, incorrect passphrase."
243msgstr ""
242msgstr ""
244
243
245−#: qml/Shell.qml:445
244+#: qml/Greeter/NarrowView.qml:54 qml/Wizard/Pages/passwd-confirm.qml:54
246msgid "Sorry, incorrect passcode."
245msgid "Sorry, incorrect passcode."
247msgstr ""
246msgstr ""
248
247
249−#: qml/Shell.qml:446
248+#: qml/Greeter/NarrowView.qml:55
250msgid "This will be your last attempt."
249msgid "This will be your last attempt."
251msgstr ""
250msgstr ""
252
251
253−#: qml/Shell.qml:448
252+#: qml/Greeter/NarrowView.qml:57
254msgid ""
253msgid ""
255"If passphrase is entered incorrectly, your phone will conduct a factory "
254"If passphrase is entered incorrectly, your phone will conduct a factory "
256"reset and all personal data will be deleted."
255"reset and all personal data will be deleted."
257msgstr ""
256msgstr ""
258
257
259−#: qml/Shell.qml:449
258+#: qml/Greeter/NarrowView.qml:58
260msgid ""
259msgid ""
261"If passcode is entered incorrectly, your phone will conduct a factory reset "
260"If passcode is entered incorrectly, your phone will conduct a factory reset "
262"and all personal data will be deleted."
261"and all personal data will be deleted."
263msgstr ""
262msgstr ""
264
263
265−#: qml/Shell.qml:402
264+#: qml/Greeter/NarrowView.qml:115
266#, qt-format
265#, qt-format
267msgid "Enter %1"
266msgid "Enter %1"
268msgstr ""
267msgstr ""
269
268
270−#: qml/Shell.qml:394
269+#: qml/Greeter/NarrowView.qml:116 qml/Wizard/Pages/passwd-set.qml:60
271msgid "Enter passphrase"
270msgid "Enter passphrase"
272msgstr ""
271msgstr ""
273
272
274−#: qml/Shell.qml:398
273+#: qml/Greeter/NarrowView.qml:117
275msgid "Enter passcode"
274msgid "Enter passcode"
276msgstr ""
275msgstr ""
277
276
278−#: qml/Shell.qml:403
277+#: qml/Greeter/NarrowView.qml:118
279#, qt-format
278#, qt-format
280msgid "Sorry, incorrect %1"
279msgid "Sorry, incorrect %1"
281msgstr ""
280msgstr ""
282
281
283−#: qml/Shell.qml:395
282+#: qml/Greeter/NarrowView.qml:119
284msgid "Sorry, incorrect passphrase"
283msgid "Sorry, incorrect passphrase"
285msgstr ""
284msgstr ""
286
285
287−#: qml/Shell.qml:396
286+#: qml/Greeter/NarrowView.qml:120
288msgid "Please re-enter"
287msgid "Please re-enter"
289msgstr ""
288msgstr ""
290
289
291−#: qml/Shell.qml:399
290+#: qml/Greeter/NarrowView.qml:121
292msgid "Sorry, incorrect passcode"
291msgid "Sorry, incorrect passcode"
293msgstr ""
292msgstr ""
294
293
po/en_AU.po+38−39
@@ -15,35 +15,35 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2015-04-12 06:01+0000\n"
18+"X-Launchpad-Export-Date: 2015-04-14 05:33+0000\n"
19"X-Generator: Launchpad (build 17423)\n"
19"X-Generator: Launchpad (build 17423)\n"
20
20
21−#: plugins/LightDM/Greeter.cpp:130
21+#: plugins/LightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
23msgstr "Password: "
23msgstr "Password: "
24
24
25#: plugins/Unity/Launcher/launcheritem.cpp:45
25#: plugins/Unity/Launcher/launcheritem.cpp:45
26−#: plugins/Unity/Launcher/launcheritem.cpp:91
26+#: plugins/Unity/Launcher/launcheritem.cpp:100
27msgid "Pin shortcut"
27msgid "Pin shortcut"
28msgstr "Pin shortcut"
28msgstr "Pin shortcut"
29
29
30−#: plugins/Unity/Launcher/launcheritem.cpp:91
30+#: plugins/Unity/Launcher/launcheritem.cpp:100
31msgid "Unpin shortcut"
31msgid "Unpin shortcut"
32msgstr "Unpin shortcut"
32msgstr "Unpin shortcut"
33
33
34−#: qml/Components/DelayedLockscreen.qml:47
34+#: qml/Components/DelayedLockscreen.qml:49
35msgid "Device Locked"
35msgid "Device Locked"
36msgstr "Device Locked"
36msgstr "Device Locked"
37
37
38−#: qml/Components/DelayedLockscreen.qml:62
38+#: qml/Components/DelayedLockscreen.qml:64
39msgid "You have been locked out due to too many failed passphrase attempts."
39msgid "You have been locked out due to too many failed passphrase attempts."
40msgstr "You have been locked out due to too many failed passphrase attempts."
40msgstr "You have been locked out due to too many failed passphrase attempts."
41
41
42−#: qml/Components/DelayedLockscreen.qml:63
42+#: qml/Components/DelayedLockscreen.qml:65
43msgid "You have been locked out due to too many failed passcode attempts."
43msgid "You have been locked out due to too many failed passcode attempts."
44msgstr "You have been locked out due to too many failed passcode attempts."
44msgstr "You have been locked out due to too many failed passcode attempts."
45
45
46−#: qml/Components/DelayedLockscreen.qml:72
46+#: qml/Components/DelayedLockscreen.qml:74
47#, qt-format
47#, qt-format
48msgid "Please wait %1 minute and then try again…"
48msgid "Please wait %1 minute and then try again…"
49msgid_plural "Please wait %1 minutes and then try again…"
49msgid_plural "Please wait %1 minutes and then try again…"
@@ -55,7 +55,7 @@ msgctxt "Title: Lock/Log out dialog"
55msgid "Log out"
55msgid "Log out"
56msgstr "Log out"
56msgstr "Log out"
57
57
58−#: qml/Components/Dialogs.qml:75
58+#: qml/Components/Dialogs.qml:68
59msgid "Are you sure you want to log out?"
59msgid "Are you sure you want to log out?"
60msgstr "Are you sure you want to log out?"
60msgstr "Are you sure you want to log out?"
61
61
@@ -69,6 +69,7 @@ msgctxt "Button: Log out from the system"
69msgid "Log Out"
69msgid "Log Out"
70msgstr "Log Out"
70msgstr "Log Out"
71
71
72+#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:115
72#: qml/Components/Dialogs.qml:171
73#: qml/Components/Dialogs.qml:171
73msgid "Cancel"
74msgid "Cancel"
74msgstr "Cancel"
75msgstr "Cancel"
@@ -78,7 +79,7 @@ msgctxt "Title: Reboot/Shut down dialog"
78msgid "Shut down"
79msgid "Shut down"
79msgstr "Shut down"
80msgstr "Shut down"
80
81
81−#: qml/Components/Dialogs.qml:99
82+#: qml/Components/Dialogs.qml:97
82msgid "Are you sure you want to shut down?"
83msgid "Are you sure you want to shut down?"
83msgstr "Are you sure you want to shut down?"
84msgstr "Are you sure you want to shut down?"
84
85
@@ -97,17 +98,15 @@ msgctxt "Title: Reboot dialog"
97msgid "Reboot"
98msgid "Reboot"
98msgstr "Reboot"
99msgstr "Reboot"
99
100
100−#: qml/Components/Dialogs.qml:124
101+#: qml/Components/Dialogs.qml:128
101msgid "Are you sure you want to reboot?"
102msgid "Are you sure you want to reboot?"
102msgstr "Are you sure you want to reboot?"
103msgstr "Are you sure you want to reboot?"
103
104
104−#: qml/Components/Dialogs.qml:77 qml/Components/Dialogs.qml:101
105+#: qml/Components/Dialogs.qml:130
105−#: qml/Components/Dialogs.qml:126
106msgid "No"
106msgid "No"
107msgstr "No"
107msgstr "No"
108
108
109−#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:108
109+#: qml/Components/Dialogs.qml:136
110−#: qml/Components/Dialogs.qml:133
111msgid "Yes"
110msgid "Yes"
112msgstr "Yes"
111msgstr "Yes"
113
112
@@ -116,7 +115,7 @@ msgctxt "Title: Power off/Restart dialog"
116msgid "Power"
115msgid "Power"
117msgstr "Power"
116msgstr "Power"
118
117
119−#: qml/Components/Dialogs.qml:149
118+#: qml/Components/Dialogs.qml:151
120msgid ""
119msgid ""
121"Are you sure you would like\n"
120"Are you sure you would like\n"
122"to power off?"
121"to power off?"
@@ -134,23 +133,23 @@ msgctxt "Button: Restart the system"
134msgid "Restart"
133msgid "Restart"
135msgstr "Restart"
134msgstr "Restart"
136
135
137−#: qml/Components/Lockscreen.qml:223
136+#: qml/Components/Lockscreen.qml:238
138msgid "Return to Call"
137msgid "Return to Call"
139msgstr "Return to Call"
138msgstr "Return to Call"
140
139
141−#: qml/Components/Lockscreen.qml:223
140+#: qml/Components/Lockscreen.qml:238
142msgid "Emergency Call"
141msgid "Emergency Call"
143msgstr "Emergency Call"
142msgstr "Emergency Call"
144
143
145−#: qml/Components/Lockscreen.qml:255
144+#: qml/Components/Lockscreen.qml:270
146msgid "OK"
145msgid "OK"
147msgstr "OK"
146msgstr "OK"
148
147
149−#: qml/Dash/GenericScopeView.qml:434 qml/Dash/GenericScopeView.qml:591
148+#: qml/Dash/GenericScopeView.qml:533 qml/Dash/GenericScopeView.qml:691
150msgid "See less"
149msgid "See less"
151msgstr "See less"
150msgstr "See less"
152
151
153−#: qml/Dash/GenericScopeView.qml:434
152+#: qml/Dash/GenericScopeView.qml:533
154msgid "See all"
153msgid "See all"
155msgstr "See all"
154msgstr "See all"
156
155
@@ -174,11 +173,11 @@ msgctxt "Button: Show the current dash scope settings"
174msgid "Settings"
173msgid "Settings"
175msgstr "Settings"
174msgstr "Settings"
176
175
177−#: qml/Dash/PageHeader.qml:285
176+#: qml/Dash/PageHeader.qml:293
178msgid "Remove from Favorites"
177msgid "Remove from Favorites"
179msgstr "Remove from Favourites"
178msgstr "Remove from Favourites"
180
179
181−#: qml/Dash/PageHeader.qml:285
180+#: qml/Dash/PageHeader.qml:293
182msgid "Add to Favorites"
181msgid "Add to Favorites"
183msgstr "Add to Favourites"
182msgstr "Add to Favourites"
184
183
@@ -214,19 +213,19 @@ msgstr "Release to refresh…"
214msgid "Enable location data"
213msgid "Enable location data"
215msgstr "Enable location data"
214msgstr "Enable location data"
216
215
217−#: qml/Dash/ScopesList.qml:63
216+#: qml/Dash/ScopesList.qml:66
218msgid "Manage"
217msgid "Manage"
219msgstr "Manage"
218msgstr "Manage"
220
219
221−#: qml/Dash/ScopesList.qml:107
220+#: qml/Dash/ScopesList.qml:112
222msgid "Home"
221msgid "Home"
223msgstr "Home"
222msgstr "Home"
224
223
225−#: qml/Dash/ScopesList.qml:108
224+#: qml/Dash/ScopesList.qml:113
226msgid "Also installed"
225msgid "Also installed"
227msgstr "Also installed"
226msgstr "Also installed"
228
227
229−#: qml/Greeter/Greeter.qml:174
228+#: qml/Greeter/CoverPage.qml:107
230msgid "Unlock"
229msgid "Unlock"
231msgstr "Unlock"
230msgstr "Unlock"
232
231
@@ -238,19 +237,19 @@ msgstr "Retry"
238msgid "Tap to unlock"
237msgid "Tap to unlock"
239msgstr "Tap to unlock"
238msgstr "Tap to unlock"
240
239
241−#: qml/Shell.qml:444
240+#: qml/Greeter/NarrowView.qml:53 qml/Wizard/Pages/passwd-confirm.qml:53
242msgid "Sorry, incorrect passphrase."
241msgid "Sorry, incorrect passphrase."
243msgstr "Sorry, incorrect passphrase."
242msgstr "Sorry, incorrect passphrase."
244
243
245−#: qml/Shell.qml:445
244+#: qml/Greeter/NarrowView.qml:54 qml/Wizard/Pages/passwd-confirm.qml:54
246msgid "Sorry, incorrect passcode."
245msgid "Sorry, incorrect passcode."
247msgstr "Sorry, incorrect passcode."
246msgstr "Sorry, incorrect passcode."
248
247
249−#: qml/Shell.qml:446
248+#: qml/Greeter/NarrowView.qml:55
250msgid "This will be your last attempt."
249msgid "This will be your last attempt."
251msgstr "This will be your last attempt."
250msgstr "This will be your last attempt."
252
251
253−#: qml/Shell.qml:448
252+#: qml/Greeter/NarrowView.qml:57
254msgid ""
253msgid ""
255"If passphrase is entered incorrectly, your phone will conduct a factory "
254"If passphrase is entered incorrectly, your phone will conduct a factory "
256"reset and all personal data will be deleted."
255"reset and all personal data will be deleted."
@@ -258,7 +257,7 @@ msgstr ""
258"If passphrase is entered incorrectly, your phone will conduct a factory "
257"If passphrase is entered incorrectly, your phone will conduct a factory "
259"reset and all personal data will be deleted."
258"reset and all personal data will be deleted."
260
259
261−#: qml/Shell.qml:449
260+#: qml/Greeter/NarrowView.qml:58
262msgid ""
261msgid ""
263"If passcode is entered incorrectly, your phone will conduct a factory reset "
262"If passcode is entered incorrectly, your phone will conduct a factory reset "
264"and all personal data will be deleted."
263"and all personal data will be deleted."
@@ -266,33 +265,33 @@ msgstr ""
266"If passcode is entered incorrectly, your phone will conduct a factory reset "
265"If passcode is entered incorrectly, your phone will conduct a factory reset "
267"and all personal data will be deleted."
266"and all personal data will be deleted."
268
267
269−#: qml/Shell.qml:402
268+#: qml/Greeter/NarrowView.qml:115
270#, qt-format
269#, qt-format
271msgid "Enter %1"
270msgid "Enter %1"
272msgstr "Enter %1"
271msgstr "Enter %1"
273
272
274−#: qml/Shell.qml:394
273+#: qml/Greeter/NarrowView.qml:116 qml/Wizard/Pages/passwd-set.qml:60
275msgid "Enter passphrase"
274msgid "Enter passphrase"
276msgstr "Enter passphrase"
275msgstr "Enter passphrase"
277
276
278−#: qml/Shell.qml:398
277+#: qml/Greeter/NarrowView.qml:117
279msgid "Enter passcode"
278msgid "Enter passcode"
280msgstr "Enter passcode"
279msgstr "Enter passcode"
281
280
282−#: qml/Shell.qml:403
281+#: qml/Greeter/NarrowView.qml:118
283#, qt-format
282#, qt-format
284msgid "Sorry, incorrect %1"
283msgid "Sorry, incorrect %1"
285msgstr "Sorry, incorrect %1"
284msgstr "Sorry, incorrect %1"
286
285
287−#: qml/Shell.qml:395
286+#: qml/Greeter/NarrowView.qml:119
288msgid "Sorry, incorrect passphrase"
287msgid "Sorry, incorrect passphrase"
289msgstr "Sorry, incorrect passphrase"
288msgstr "Sorry, incorrect passphrase"
290
289
291−#: qml/Shell.qml:396
290+#: qml/Greeter/NarrowView.qml:120
292msgid "Please re-enter"
291msgid "Please re-enter"
293msgstr "Please re-enter"
292msgstr "Please re-enter"
294
293
295−#: qml/Shell.qml:399
294+#: qml/Greeter/NarrowView.qml:121
296msgid "Sorry, incorrect passcode"
295msgid "Sorry, incorrect passcode"
297msgstr "Sorry, incorrect passcode"
296msgstr "Sorry, incorrect passcode"
298
297
po/fa.po+38−39
@@ -15,36 +15,36 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2015-04-11 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2015-04-14 05:33+0000\n"
19"X-Generator: Launchpad (build 17423)\n"
19"X-Generator: Launchpad (build 17423)\n"
20
20
21−#: plugins/LightDM/Greeter.cpp:130
21+#: plugins/LightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
23msgstr "گذرواژه: "
23msgstr "گذرواژه: "
24
24
25#: plugins/Unity/Launcher/launcheritem.cpp:45
25#: plugins/Unity/Launcher/launcheritem.cpp:45
26−#: plugins/Unity/Launcher/launcheritem.cpp:91
26+#: plugins/Unity/Launcher/launcheritem.cpp:100
27msgid "Pin shortcut"
27msgid "Pin shortcut"
28msgstr "سنجاق کردن میانبر"
28msgstr "سنجاق کردن میانبر"
29
29
30−#: plugins/Unity/Launcher/launcheritem.cpp:91
30+#: plugins/Unity/Launcher/launcheritem.cpp:100
31msgid "Unpin shortcut"
31msgid "Unpin shortcut"
32msgstr "برداشتن سنجاق میانبر"
32msgstr "برداشتن سنجاق میانبر"
33
33
34−#: qml/Components/DelayedLockscreen.qml:47
34+#: qml/Components/DelayedLockscreen.qml:49
35msgid "Device Locked"
35msgid "Device Locked"
36msgstr "دستگاه قفل شد"
36msgstr "دستگاه قفل شد"
37
37
38−#: qml/Components/DelayedLockscreen.qml:62
38+#: qml/Components/DelayedLockscreen.qml:64
39msgid "You have been locked out due to too many failed passphrase attempts."
39msgid "You have been locked out due to too many failed passphrase attempts."
40msgstr ""
40msgstr ""
41"شما به دلیل تلاش‌های بسیار زیاد شکست خورده برای عبارت‌عبور قفل شده‌اید."
41"شما به دلیل تلاش‌های بسیار زیاد شکست خورده برای عبارت‌عبور قفل شده‌اید."
42
42
43−#: qml/Components/DelayedLockscreen.qml:63
43+#: qml/Components/DelayedLockscreen.qml:65
44msgid "You have been locked out due to too many failed passcode attempts."
44msgid "You have been locked out due to too many failed passcode attempts."
45msgstr "شما به دلیل تلاش‌های بسیار زیاد شکست خورده برای رمزعبور قفل شده‌اید."
45msgstr "شما به دلیل تلاش‌های بسیار زیاد شکست خورده برای رمزعبور قفل شده‌اید."
46
46
47−#: qml/Components/DelayedLockscreen.qml:72
47+#: qml/Components/DelayedLockscreen.qml:74
48#, qt-format
48#, qt-format
49msgid "Please wait %1 minute and then try again…"
49msgid "Please wait %1 minute and then try again…"
50msgid_plural "Please wait %1 minutes and then try again…"
50msgid_plural "Please wait %1 minutes and then try again…"
@@ -55,7 +55,7 @@ msgctxt "Title: Lock/Log out dialog"
55msgid "Log out"
55msgid "Log out"
56msgstr "خروج از حساب"
56msgstr "خروج از حساب"
57
57
58−#: qml/Components/Dialogs.qml:75
58+#: qml/Components/Dialogs.qml:68
59msgid "Are you sure you want to log out?"
59msgid "Are you sure you want to log out?"
60msgstr "مطمئنید که می‌خواهید از حساب خارج شوید"
60msgstr "مطمئنید که می‌خواهید از حساب خارج شوید"
61
61
@@ -69,6 +69,7 @@ msgctxt "Button: Log out from the system"
69msgid "Log Out"
69msgid "Log Out"
70msgstr "خروج"
70msgstr "خروج"
71
71
72+#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:115
72#: qml/Components/Dialogs.qml:171
73#: qml/Components/Dialogs.qml:171
73msgid "Cancel"
74msgid "Cancel"
74msgstr "لغو"
75msgstr "لغو"
@@ -78,7 +79,7 @@ msgctxt "Title: Reboot/Shut down dialog"
78msgid "Shut down"
79msgid "Shut down"
79msgstr "خاموش کردن"
80msgstr "خاموش کردن"
80
81
81−#: qml/Components/Dialogs.qml:99
82+#: qml/Components/Dialogs.qml:97
82msgid "Are you sure you want to shut down?"
83msgid "Are you sure you want to shut down?"
83msgstr "مطمئنید که می‌خواهید خاموش کنید؟"
84msgstr "مطمئنید که می‌خواهید خاموش کنید؟"
84
85
@@ -97,17 +98,15 @@ msgctxt "Title: Reboot dialog"
97msgid "Reboot"
98msgid "Reboot"
98msgstr "راه‌اندازی دوباره"
99msgstr "راه‌اندازی دوباره"
99
100
100−#: qml/Components/Dialogs.qml:124
101+#: qml/Components/Dialogs.qml:128
101msgid "Are you sure you want to reboot?"
102msgid "Are you sure you want to reboot?"
102msgstr "مطمئنید که می‌خواهید مجدّداً راه‌اندازی کنسد؟"
103msgstr "مطمئنید که می‌خواهید مجدّداً راه‌اندازی کنسد؟"
103
104
104−#: qml/Components/Dialogs.qml:77 qml/Components/Dialogs.qml:101
105+#: qml/Components/Dialogs.qml:130
105−#: qml/Components/Dialogs.qml:126
106msgid "No"
106msgid "No"
107msgstr "خیر"
107msgstr "خیر"
108
108
109−#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:108
109+#: qml/Components/Dialogs.qml:136
110−#: qml/Components/Dialogs.qml:133
111msgid "Yes"
110msgid "Yes"
112msgstr "بله"
111msgstr "بله"
113
112
@@ -116,7 +115,7 @@ msgctxt "Title: Power off/Restart dialog"
116msgid "Power"
115msgid "Power"
117msgstr "انرژی"
116msgstr "انرژی"
118
117
119−#: qml/Components/Dialogs.qml:149
118+#: qml/Components/Dialogs.qml:151
120msgid ""
119msgid ""
121"Are you sure you would like\n"
120"Are you sure you would like\n"
122"to power off?"
121"to power off?"
@@ -134,23 +133,23 @@ msgctxt "Button: Restart the system"
134msgid "Restart"
133msgid "Restart"
135msgstr "راه‌اندازی دوباره"
134msgstr "راه‌اندازی دوباره"
136
135
137−#: qml/Components/Lockscreen.qml:223
136+#: qml/Components/Lockscreen.qml:238
138msgid "Return to Call"
137msgid "Return to Call"
139msgstr "بازگشت به تماس"
138msgstr "بازگشت به تماس"
140
139
141−#: qml/Components/Lockscreen.qml:223
140+#: qml/Components/Lockscreen.qml:238
142msgid "Emergency Call"
141msgid "Emergency Call"
143msgstr "تماس اضطراری"
142msgstr "تماس اضطراری"
144
143
145−#: qml/Components/Lockscreen.qml:255
144+#: qml/Components/Lockscreen.qml:270
146msgid "OK"
145msgid "OK"
147msgstr "قبول"
146msgstr "قبول"
148
147
149−#: qml/Dash/GenericScopeView.qml:434 qml/Dash/GenericScopeView.qml:591
148+#: qml/Dash/GenericScopeView.qml:533 qml/Dash/GenericScopeView.qml:691
150msgid "See less"
149msgid "See less"
151msgstr "کم‌تر ببینید"
150msgstr "کم‌تر ببینید"
152
151
153−#: qml/Dash/GenericScopeView.qml:434
152+#: qml/Dash/GenericScopeView.qml:533
154msgid "See all"
153msgid "See all"
155msgstr "دیدن همه"
154msgstr "دیدن همه"
156
155
@@ -174,11 +173,11 @@ msgctxt "Button: Show the current dash scope settings"
174msgid "Settings"
173msgid "Settings"
175msgstr "تنظیمات"
174msgstr "تنظیمات"
176
175
177−#: qml/Dash/PageHeader.qml:285
176+#: qml/Dash/PageHeader.qml:293
178msgid "Remove from Favorites"
177msgid "Remove from Favorites"
179msgstr "برداشتن از برگزیده‌ها"
178msgstr "برداشتن از برگزیده‌ها"
180
179
181−#: qml/Dash/PageHeader.qml:285
180+#: qml/Dash/PageHeader.qml:293
182msgid "Add to Favorites"
181msgid "Add to Favorites"
183msgstr "افزودن به برگزیده‌ها"
182msgstr "افزودن به برگزیده‌ها"
184
183
@@ -214,19 +213,19 @@ msgstr "برای تازه‌سازی رها کنید…"
214msgid "Enable location data"
213msgid "Enable location data"
215msgstr "فعّال کردن داده‌های موقعیّت"
214msgstr "فعّال کردن داده‌های موقعیّت"
216
215
217−#: qml/Dash/ScopesList.qml:63
216+#: qml/Dash/ScopesList.qml:66
218msgid "Manage"
217msgid "Manage"
219msgstr "مدیریت"
218msgstr "مدیریت"
220
219
221−#: qml/Dash/ScopesList.qml:107
220+#: qml/Dash/ScopesList.qml:112
222msgid "Home"
221msgid "Home"
223msgstr "خانه"
222msgstr "خانه"
224
223
225−#: qml/Dash/ScopesList.qml:108
224+#: qml/Dash/ScopesList.qml:113
226msgid "Also installed"
225msgid "Also installed"
227msgstr "هم‌چنین نصب شده"
226msgstr "هم‌چنین نصب شده"
228
227
229−#: qml/Greeter/Greeter.qml:174
228+#: qml/Greeter/CoverPage.qml:107
230msgid "Unlock"
229msgid "Unlock"
231msgstr "بازکردن قفل"
230msgstr "بازکردن قفل"
232
231
@@ -238,19 +237,19 @@ msgstr "تلاش دوباره"
238msgid "Tap to unlock"
237msgid "Tap to unlock"
239msgstr "برای باز کردن قفل ضربه بزنید"
238msgstr "برای باز کردن قفل ضربه بزنید"
240
239
241−#: qml/Shell.qml:444
240+#: qml/Greeter/NarrowView.qml:53 qml/Wizard/Pages/passwd-confirm.qml:53
242msgid "Sorry, incorrect passphrase."
241msgid "Sorry, incorrect passphrase."
243msgstr "متأسّفیم، عبارت‌عبور نادرست است."
242msgstr "متأسّفیم، عبارت‌عبور نادرست است."
244
243
245−#: qml/Shell.qml:445
244+#: qml/Greeter/NarrowView.qml:54 qml/Wizard/Pages/passwd-confirm.qml:54
246msgid "Sorry, incorrect passcode."
245msgid "Sorry, incorrect passcode."
247msgstr "متأسّفیم، رمزعبور نادرست است."
246msgstr "متأسّفیم، رمزعبور نادرست است."
248
247
249−#: qml/Shell.qml:446
248+#: qml/Greeter/NarrowView.qml:55
250msgid "This will be your last attempt."
249msgid "This will be your last attempt."
251msgstr "این آخرین تلاش شما خواهد بود."
250msgstr "این آخرین تلاش شما خواهد بود."
252
251
253−#: qml/Shell.qml:448
252+#: qml/Greeter/NarrowView.qml:57
254msgid ""
253msgid ""
255"If passphrase is entered incorrectly, your phone will conduct a factory "
254"If passphrase is entered incorrectly, your phone will conduct a factory "
256"reset and all personal data will be deleted."
255"reset and all personal data will be deleted."
@@ -258,7 +257,7 @@ msgstr ""
258"اگر عبارت‌عبور نادرست وارد شود، تلفن شما بازنشانی کارخانه خواهد شد و تمامی "
257"اگر عبارت‌عبور نادرست وارد شود، تلفن شما بازنشانی کارخانه خواهد شد و تمامی "
259"اطّلاعات شخصی حذف خواهند شد."
258"اطّلاعات شخصی حذف خواهند شد."
260
259
261−#: qml/Shell.qml:449
260+#: qml/Greeter/NarrowView.qml:58
262msgid ""
261msgid ""
263"If passcode is entered incorrectly, your phone will conduct a factory reset "
262"If passcode is entered incorrectly, your phone will conduct a factory reset "
264"and all personal data will be deleted."
263"and all personal data will be deleted."
@@ -266,33 +265,33 @@ msgstr ""
266"اگر رمزعبور نادرست وارد شود، تلفن شما بازنشانی کارخانه خواهد شد و تمامی "
265"اگر رمزعبور نادرست وارد شود، تلفن شما بازنشانی کارخانه خواهد شد و تمامی "
267"اطّلاعات شخصی حذف خواهند شد."
266"اطّلاعات شخصی حذف خواهند شد."
268
267
269−#: qml/Shell.qml:402
268+#: qml/Greeter/NarrowView.qml:115
270#, qt-format
269#, qt-format
271msgid "Enter %1"
270msgid "Enter %1"
272msgstr "%1 را وارد کنید"
271msgstr "%1 را وارد کنید"
273
272
274−#: qml/Shell.qml:394
273+#: qml/Greeter/NarrowView.qml:116 qml/Wizard/Pages/passwd-set.qml:60
275msgid "Enter passphrase"
274msgid "Enter passphrase"
276msgstr "عبارت‌عبور را وارد کنید"
275msgstr "عبارت‌عبور را وارد کنید"
277
276
278−#: qml/Shell.qml:398
277+#: qml/Greeter/NarrowView.qml:117
279msgid "Enter passcode"
278msgid "Enter passcode"
280msgstr "رمزعبور را وارد کنید"
279msgstr "رمزعبور را وارد کنید"
281
280
282−#: qml/Shell.qml:403
281+#: qml/Greeter/NarrowView.qml:118
283#, qt-format
282#, qt-format
284msgid "Sorry, incorrect %1"
283msgid "Sorry, incorrect %1"
285msgstr "متأسّفیم، %1 نادرست بود"
284msgstr "متأسّفیم، %1 نادرست بود"
286
285
287−#: qml/Shell.qml:395
286+#: qml/Greeter/NarrowView.qml:119
288msgid "Sorry, incorrect passphrase"
287msgid "Sorry, incorrect passphrase"
289msgstr "متأسّفیم، عبارت‌عبور نادرست بود"
288msgstr "متأسّفیم، عبارت‌عبور نادرست بود"
290
289
291−#: qml/Shell.qml:396
290+#: qml/Greeter/NarrowView.qml:120
292msgid "Please re-enter"
291msgid "Please re-enter"
293msgstr "لطفاً دوباره وارد کنید"
292msgstr "لطفاً دوباره وارد کنید"
294
293
295−#: qml/Shell.qml:399
294+#: qml/Greeter/NarrowView.qml:121
296msgid "Sorry, incorrect passcode"
295msgid "Sorry, incorrect passcode"
297msgstr "متأسّفیم، رمزعبور نادرست بود"
296msgstr "متأسّفیم، رمزعبور نادرست بود"
298
297
po/sk.po+38−39
@@ -15,35 +15,35 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
18−"X-Launchpad-Export-Date: 2015-04-11 05:50+0000\n"
18+"X-Launchpad-Export-Date: 2015-04-14 05:33+0000\n"
19"X-Generator: Launchpad (build 17423)\n"
19"X-Generator: Launchpad (build 17423)\n"
20
20
21−#: plugins/LightDM/Greeter.cpp:130
21+#: plugins/LightDM/Greeter.cpp:112
22msgid "Password: "
22msgid "Password: "
23msgstr ""
23msgstr ""
24
24
25#: plugins/Unity/Launcher/launcheritem.cpp:45
25#: plugins/Unity/Launcher/launcheritem.cpp:45
26−#: plugins/Unity/Launcher/launcheritem.cpp:91
26+#: plugins/Unity/Launcher/launcheritem.cpp:100
27msgid "Pin shortcut"
27msgid "Pin shortcut"
28msgstr ""
28msgstr ""
29
29
30−#: plugins/Unity/Launcher/launcheritem.cpp:91
30+#: plugins/Unity/Launcher/launcheritem.cpp:100
31msgid "Unpin shortcut"
31msgid "Unpin shortcut"
32msgstr ""
32msgstr ""
33
33
34−#: qml/Components/DelayedLockscreen.qml:47
34+#: qml/Components/DelayedLockscreen.qml:49
35msgid "Device Locked"
35msgid "Device Locked"
36msgstr ""
36msgstr ""
37
37
38−#: qml/Components/DelayedLockscreen.qml:62
38+#: qml/Components/DelayedLockscreen.qml:64
39msgid "You have been locked out due to too many failed passphrase attempts."
39msgid "You have been locked out due to too many failed passphrase attempts."
40msgstr ""
40msgstr ""
41
41
42−#: qml/Components/DelayedLockscreen.qml:63
42+#: qml/Components/DelayedLockscreen.qml:65
43msgid "You have been locked out due to too many failed passcode attempts."
43msgid "You have been locked out due to too many failed passcode attempts."
44msgstr ""
44msgstr ""
45
45
46−#: qml/Components/DelayedLockscreen.qml:72
46+#: qml/Components/DelayedLockscreen.qml:74
47#, qt-format
47#, qt-format
48msgid "Please wait %1 minute and then try again…"
48msgid "Please wait %1 minute and then try again…"
49msgid_plural "Please wait %1 minutes and then try again…"
49msgid_plural "Please wait %1 minutes and then try again…"
@@ -55,7 +55,7 @@ msgctxt "Title: Lock/Log out dialog"
55msgid "Log out"
55msgid "Log out"
56msgstr ""
56msgstr ""
57
57
58−#: qml/Components/Dialogs.qml:75
58+#: qml/Components/Dialogs.qml:68
59msgid "Are you sure you want to log out?"
59msgid "Are you sure you want to log out?"
60msgstr ""
60msgstr ""
61
61
@@ -69,6 +69,7 @@ msgctxt "Button: Log out from the system"
69msgid "Log Out"
69msgid "Log Out"
70msgstr ""
70msgstr ""
71
71
72+#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:115
72#: qml/Components/Dialogs.qml:171
73#: qml/Components/Dialogs.qml:171
73msgid "Cancel"
74msgid "Cancel"
74msgstr ""
75msgstr ""
@@ -78,7 +79,7 @@ msgctxt "Title: Reboot/Shut down dialog"
78msgid "Shut down"
79msgid "Shut down"
79msgstr ""
80msgstr ""
80
81
81−#: qml/Components/Dialogs.qml:99
82+#: qml/Components/Dialogs.qml:97
82msgid "Are you sure you want to shut down?"
83msgid "Are you sure you want to shut down?"
83msgstr ""
84msgstr ""
84
85
@@ -97,17 +98,15 @@ msgctxt "Title: Reboot dialog"
97msgid "Reboot"
98msgid "Reboot"
98msgstr ""
99msgstr ""
99
100
100−#: qml/Components/Dialogs.qml:124
101+#: qml/Components/Dialogs.qml:128
101msgid "Are you sure you want to reboot?"
102msgid "Are you sure you want to reboot?"
102msgstr ""
103msgstr ""
103
104
104−#: qml/Components/Dialogs.qml:77 qml/Components/Dialogs.qml:101
105+#: qml/Components/Dialogs.qml:130
105−#: qml/Components/Dialogs.qml:126
106msgid "No"
106msgid "No"
107msgstr ""
107msgstr ""
108
108
109−#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:108
109+#: qml/Components/Dialogs.qml:136
110−#: qml/Components/Dialogs.qml:133
111msgid "Yes"
110msgid "Yes"
112msgstr ""
111msgstr ""
113
112
@@ -116,7 +115,7 @@ msgctxt "Title: Power off/Restart dialog"
116msgid "Power"
115msgid "Power"
117msgstr ""
116msgstr ""
118
117
119−#: qml/Components/Dialogs.qml:149
118+#: qml/Components/Dialogs.qml:151
120msgid ""
119msgid ""
121"Are you sure you would like\n"
120"Are you sure you would like\n"
122"to power off?"
121"to power off?"
@@ -132,23 +131,23 @@ msgctxt "Button: Restart the system"
132msgid "Restart"
131msgid "Restart"
133msgstr ""
132msgstr ""
134
133
135−#: qml/Components/Lockscreen.qml:223
134+#: qml/Components/Lockscreen.qml:238
136msgid "Return to Call"
135msgid "Return to Call"
137msgstr ""
136msgstr ""
138
137
139−#: qml/Components/Lockscreen.qml:223
138+#: qml/Components/Lockscreen.qml:238
140msgid "Emergency Call"
139msgid "Emergency Call"
141msgstr ""
140msgstr ""
142
141
143−#: qml/Components/Lockscreen.qml:255
142+#: qml/Components/Lockscreen.qml:270
144msgid "OK"
143msgid "OK"
145msgstr ""
144msgstr ""
146
145
147−#: qml/Dash/GenericScopeView.qml:434 qml/Dash/GenericScopeView.qml:591
146+#: qml/Dash/GenericScopeView.qml:533 qml/Dash/GenericScopeView.qml:691
148msgid "See less"
147msgid "See less"
149msgstr ""
148msgstr ""
150
149
151−#: qml/Dash/GenericScopeView.qml:434
150+#: qml/Dash/GenericScopeView.qml:533
152msgid "See all"
151msgid "See all"
153msgstr ""
152msgstr ""
154
153
@@ -172,11 +171,11 @@ msgctxt "Button: Show the current dash scope settings"
172msgid "Settings"
171msgid "Settings"
173msgstr ""
172msgstr ""
174
173
175−#: qml/Dash/PageHeader.qml:285
174+#: qml/Dash/PageHeader.qml:293
176msgid "Remove from Favorites"
175msgid "Remove from Favorites"
177msgstr ""
176msgstr ""
178
177
179−#: qml/Dash/PageHeader.qml:285
178+#: qml/Dash/PageHeader.qml:293
180msgid "Add to Favorites"
179msgid "Add to Favorites"
181msgstr ""
180msgstr ""
182
181
@@ -212,19 +211,19 @@ msgstr ""
212msgid "Enable location data"
211msgid "Enable location data"
213msgstr ""
212msgstr ""
214
213
215−#: qml/Dash/ScopesList.qml:63
214+#: qml/Dash/ScopesList.qml:66
216msgid "Manage"
215msgid "Manage"
217msgstr ""
216msgstr ""
218
217
219−#: qml/Dash/ScopesList.qml:107
218+#: qml/Dash/ScopesList.qml:112
220msgid "Home"
219msgid "Home"
221msgstr ""
220msgstr ""
222
221
223−#: qml/Dash/ScopesList.qml:108
222+#: qml/Dash/ScopesList.qml:113
224msgid "Also installed"
223msgid "Also installed"
225msgstr ""
224msgstr ""
226
225
227−#: qml/Greeter/Greeter.qml:174
226+#: qml/Greeter/CoverPage.qml:107
228msgid "Unlock"
227msgid "Unlock"
229msgstr ""
228msgstr ""
230
229
@@ -236,57 +235,57 @@ msgstr ""
236msgid "Tap to unlock"
235msgid "Tap to unlock"
237msgstr ""
236msgstr ""
238
237
239−#: qml/Shell.qml:444
238+#: qml/Greeter/NarrowView.qml:53 qml/Wizard/Pages/passwd-confirm.qml:53
240msgid "Sorry, incorrect passphrase."
239msgid "Sorry, incorrect passphrase."
241msgstr ""
240msgstr ""
242
241
243−#: qml/Shell.qml:445
242+#: qml/Greeter/NarrowView.qml:54 qml/Wizard/Pages/passwd-confirm.qml:54
244msgid "Sorry, incorrect passcode."
243msgid "Sorry, incorrect passcode."
245msgstr ""
244msgstr ""
246
245
247−#: qml/Shell.qml:446
246+#: qml/Greeter/NarrowView.qml:55
248msgid "This will be your last attempt."
247msgid "This will be your last attempt."
249msgstr ""
248msgstr ""
250
249
251−#: qml/Shell.qml:448
250+#: qml/Greeter/NarrowView.qml:57
252msgid ""
251msgid ""
253"If passphrase is entered incorrectly, your phone will conduct a factory "
252"If passphrase is entered incorrectly, your phone will conduct a factory "
254"reset and all personal data will be deleted."
253"reset and all personal data will be deleted."
255msgstr ""
254msgstr ""
256
255
257−#: qml/Shell.qml:449
256+#: qml/Greeter/NarrowView.qml:58
258msgid ""
257msgid ""
259"If passcode is entered incorrectly, your phone will conduct a factory reset "
258"If passcode is entered incorrectly, your phone will conduct a factory reset "
260"and all personal data will be deleted."
259"and all personal data will be deleted."
261msgstr ""
260msgstr ""
262
261
263−#: qml/Shell.qml:402
262+#: qml/Greeter/NarrowView.qml:115
264#, qt-format
263#, qt-format
265msgid "Enter %1"
264msgid "Enter %1"
266msgstr ""
265msgstr ""
267
266
268−#: qml/Shell.qml:394
267+#: qml/Greeter/NarrowView.qml:116 qml/Wizard/Pages/passwd-set.qml:60
269msgid "Enter passphrase"
268msgid "Enter passphrase"
270msgstr ""
269msgstr ""
271
270
272−#: qml/Shell.qml:398
271+#: qml/Greeter/NarrowView.qml:117
273msgid "Enter passcode"
272msgid "Enter passcode"
274msgstr ""
273msgstr ""
275
274
276−#: qml/Shell.qml:403
275+#: qml/Greeter/NarrowView.qml:118
277#, qt-format
276#, qt-format
278msgid "Sorry, incorrect %1"
277msgid "Sorry, incorrect %1"
279msgstr ""
278msgstr ""
280
279
281−#: qml/Shell.qml:395
280+#: qml/Greeter/NarrowView.qml:119
282msgid "Sorry, incorrect passphrase"
281msgid "Sorry, incorrect passphrase"
283msgstr ""
282msgstr ""
284
283
285−#: qml/Shell.qml:396
284+#: qml/Greeter/NarrowView.qml:120
286msgid "Please re-enter"
285msgid "Please re-enter"
287msgstr ""
286msgstr ""
288
287
289−#: qml/Shell.qml:399
288+#: qml/Greeter/NarrowView.qml:121
290msgid "Sorry, incorrect passcode"
289msgid "Sorry, incorrect passcode"
291msgstr ""
290msgstr ""
292
291
po/sr.po+33−32
@@ -9,16 +9,16 @@ msgstr ""
9"Project-Id-Version: unity\n"
9"Project-Id-Version: unity\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
11"POT-Creation-Date: 2015-03-19 16:03+0100\n"
11"POT-Creation-Date: 2015-03-19 16:03+0100\n"
12−"PO-Revision-Date: 2015-03-04 22:25+0000\n"
12+"PO-Revision-Date: 2015-04-13 15:19+0000\n"
13−"Last-Translator: Саша Петровић <salepetronije@gmail.com>\n"
13+"Last-Translator: Данило Шеган <Unknown>\n"
14"Language-Team: српски <xfce4@xfce4.org>\n"
14"Language-Team: српски <xfce4@xfce4.org>\n"
15"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
19"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
20−"X-Launchpad-Export-Date: 2015-03-25 06:05+0000\n"
20+"X-Launchpad-Export-Date: 2015-04-14 05:33+0000\n"
21−"X-Generator: Launchpad (build 17413)\n"
21+"X-Generator: Launchpad (build 17423)\n"
22"Language: sr\n"
22"Language: sr\n"
23
23
24#: plugins/LightDM/Greeter.cpp:112
24#: plugins/LightDM/Greeter.cpp:112
@@ -57,7 +57,7 @@ msgstr[2] "Молим, сачекајте %1 минута, па покушајт
57#: qml/Components/Dialogs.qml:67
57#: qml/Components/Dialogs.qml:67
58msgctxt "Title: Lock/Log out dialog"
58msgctxt "Title: Lock/Log out dialog"
59msgid "Log out"
59msgid "Log out"
60−msgstr ""
60+msgstr "Одјави се"
61
61
62#: qml/Components/Dialogs.qml:68
62#: qml/Components/Dialogs.qml:68
63msgid "Are you sure you want to log out?"
63msgid "Are you sure you want to log out?"
@@ -66,12 +66,12 @@ msgstr "Сигурно желите да се одјавите?"
66#: qml/Components/Dialogs.qml:70
66#: qml/Components/Dialogs.qml:70
67msgctxt "Button: Lock the system"
67msgctxt "Button: Lock the system"
68msgid "Lock"
68msgid "Lock"
69−msgstr ""
69+msgstr "Закључај"
70
70
71#: qml/Components/Dialogs.qml:77
71#: qml/Components/Dialogs.qml:77
72msgctxt "Button: Log out from the system"
72msgctxt "Button: Log out from the system"
73msgid "Log Out"
73msgid "Log Out"
74−msgstr ""
74+msgstr "Одјави се"
75
75
76#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:115
76#: qml/Components/Dialogs.qml:84 qml/Components/Dialogs.qml:115
77#: qml/Components/Dialogs.qml:171
77#: qml/Components/Dialogs.qml:171
@@ -81,7 +81,7 @@ msgstr "Откажи"
81#: qml/Components/Dialogs.qml:96
81#: qml/Components/Dialogs.qml:96
82msgctxt "Title: Reboot/Shut down dialog"
82msgctxt "Title: Reboot/Shut down dialog"
83msgid "Shut down"
83msgid "Shut down"
84−msgstr ""
84+msgstr "Угаси"
85
85
86#: qml/Components/Dialogs.qml:97
86#: qml/Components/Dialogs.qml:97
87msgid "Are you sure you want to shut down?"
87msgid "Are you sure you want to shut down?"
@@ -90,17 +90,17 @@ msgstr "Сигурно желите да угасите?"
90#: qml/Components/Dialogs.qml:99
90#: qml/Components/Dialogs.qml:99
91msgctxt "Button: Reboot the system"
91msgctxt "Button: Reboot the system"
92msgid "Reboot"
92msgid "Reboot"
93−msgstr ""
93+msgstr "Ресетуј"
94
94
95#: qml/Components/Dialogs.qml:107
95#: qml/Components/Dialogs.qml:107
96msgctxt "Button: Shut down the system"
96msgctxt "Button: Shut down the system"
97msgid "Shut down"
97msgid "Shut down"
98−msgstr ""
98+msgstr "Угаси"
99
99
100#: qml/Components/Dialogs.qml:127
100#: qml/Components/Dialogs.qml:127
101msgctxt "Title: Reboot dialog"
101msgctxt "Title: Reboot dialog"
102msgid "Reboot"
102msgid "Reboot"
103−msgstr ""
103+msgstr "Ресетуј"
104
104
105#: qml/Components/Dialogs.qml:128
105#: qml/Components/Dialogs.qml:128
106msgid "Are you sure you want to reboot?"
106msgid "Are you sure you want to reboot?"
@@ -117,7 +117,7 @@ msgstr "Да"
117#: qml/Components/Dialogs.qml:150
117#: qml/Components/Dialogs.qml:150
118msgctxt "Title: Power off/Restart dialog"
118msgctxt "Title: Power off/Restart dialog"
119msgid "Power"
119msgid "Power"
120−msgstr ""
120+msgstr "Напајање"
121
121
122#: qml/Components/Dialogs.qml:151
122#: qml/Components/Dialogs.qml:151
123msgid ""
123msgid ""
@@ -130,12 +130,12 @@ msgstr ""
130#: qml/Components/Dialogs.qml:153
130#: qml/Components/Dialogs.qml:153
131msgctxt "Button: Power off the system"
131msgctxt "Button: Power off the system"
132msgid "Power off"
132msgid "Power off"
133−msgstr ""
133+msgstr "Искључи"
134
134
135#: qml/Components/Dialogs.qml:162
135#: qml/Components/Dialogs.qml:162
136msgctxt "Button: Restart the system"
136msgctxt "Button: Restart the system"
137msgid "Restart"
137msgid "Restart"
138−msgstr ""
138+msgstr "Покрени поново"
139
139
140#: qml/Components/Lockscreen.qml:238
140#: qml/Components/Lockscreen.qml:238
141msgid "Return to Call"
141msgid "Return to Call"
@@ -160,22 +160,22 @@ msgstr "Опширније"
160#: qml/Dash/GenericScopeView.qml:595
160#: qml/Dash/GenericScopeView.qml:595
161msgctxt "Label: Hint for dash search line edit"
161msgctxt "Label: Hint for dash search line edit"
162msgid "Search"
162msgid "Search"
163−msgstr ""
163+msgstr "Претрага"
164
164
165#: qml/Dash/PageHeader.qml:269
165#: qml/Dash/PageHeader.qml:269
166msgctxt "Button: Open the Ubuntu Store"
166msgctxt "Button: Open the Ubuntu Store"
167msgid "Store"
167msgid "Store"
168−msgstr ""
168+msgstr "Продавница"
169
169
170#: qml/Dash/PageHeader.qml:276
170#: qml/Dash/PageHeader.qml:276
171msgctxt "Button: Start a search in the current dash scope"
171msgctxt "Button: Start a search in the current dash scope"
172msgid "Search"
172msgid "Search"
173−msgstr ""
173+msgstr "Тражи"
174
174
175#: qml/Dash/PageHeader.qml:286
175#: qml/Dash/PageHeader.qml:286
176msgctxt "Button: Show the current dash scope settings"
176msgctxt "Button: Show the current dash scope settings"
177msgid "Settings"
177msgid "Settings"
178−msgstr ""
178+msgstr "Подешавања"
179
179
180#: qml/Dash/PageHeader.qml:293
180#: qml/Dash/PageHeader.qml:293
181msgid "Remove from Favorites"
181msgid "Remove from Favorites"
@@ -235,11 +235,11 @@ msgstr "Откључај"
235
235
236#: qml/Greeter/LoginList.qml:236
236#: qml/Greeter/LoginList.qml:236
237msgid "Retry"
237msgid "Retry"
238−msgstr ""
238+msgstr "Покушај поново"
239
239
240#: qml/Greeter/LoginList.qml:237
240#: qml/Greeter/LoginList.qml:237
241msgid "Tap to unlock"
241msgid "Tap to unlock"
242−msgstr ""
242+msgstr "Додирните да откључате"
243
243
244#: qml/Greeter/NarrowView.qml:53 qml/Wizard/Pages/passwd-confirm.qml:53
244#: qml/Greeter/NarrowView.qml:53 qml/Wizard/Pages/passwd-confirm.qml:53
245msgid "Sorry, incorrect passphrase."
245msgid "Sorry, incorrect passphrase."
@@ -342,7 +342,7 @@ msgstr "Неуспешно, тапните да покушате поново"
342#: qml/Panel/Indicators/MessageMenuItemFactory.qml:149
342#: qml/Panel/Indicators/MessageMenuItemFactory.qml:149
343msgctxt "Label: Hint in message indicator line edit"
343msgctxt "Label: Hint in message indicator line edit"
344msgid "Reply"
344msgid "Reply"
345−msgstr ""
345+msgstr "Одговор"
346
346
347#: qml/Panel/Indicators/ModemInfoItem.qml:105
347#: qml/Panel/Indicators/ModemInfoItem.qml:105
348msgid "Unlock SIM"
348msgid "Unlock SIM"
@@ -354,7 +354,7 @@ msgstr "Роминг"
354
354
355#: qml/Tutorial/TutorialBottomFinish.qml:24
355#: qml/Tutorial/TutorialBottomFinish.qml:24
356msgid "This action does different things for different apps"
356msgid "This action does different things for different apps"
357−msgstr ""
357+msgstr "Ова радња ради различите ствари за различите програме"
358
358
359#: qml/Tutorial/TutorialBottomFinish.qml:25
359#: qml/Tutorial/TutorialBottomFinish.qml:25
360msgid "Tap here to finish."
360msgid "Tap here to finish."
@@ -366,7 +366,7 @@ msgstr "Отвори нарочите изборнике"
366
366
367#: qml/Tutorial/TutorialBottom.qml:29
367#: qml/Tutorial/TutorialBottom.qml:29
368msgid "Swipe up from the bottom edge."
368msgid "Swipe up from the bottom edge."
369−msgstr ""
369+msgstr "Превуците од доње ивице навише."
370
370
371#: qml/Tutorial/TutorialLeftFinish.qml:24
371#: qml/Tutorial/TutorialLeftFinish.qml:24
372msgid "These are the shortcuts to favorite apps"
372msgid "These are the shortcuts to favorite apps"
@@ -407,7 +407,7 @@ msgstr "Прегледајте покренуте задатке."
407#: qml/Wizard/Page.qml:89
407#: qml/Wizard/Page.qml:89
408msgctxt "Button: Go back one page in the Wizard"
408msgctxt "Button: Go back one page in the Wizard"
409msgid "Back"
409msgid "Back"
410−msgstr ""
410+msgstr "Назад"
411
411
412#: qml/Wizard/Pages/10-welcome.qml:27
412#: qml/Wizard/Pages/10-welcome.qml:27
413msgid "Hi!"
413msgid "Hi!"
@@ -415,7 +415,7 @@ msgstr "Здраво!"
415
415
416#: qml/Wizard/Pages/10-welcome.qml:44
416#: qml/Wizard/Pages/10-welcome.qml:44
417msgid "Welcome to your Ubuntu phone."
417msgid "Welcome to your Ubuntu phone."
418−msgstr ""
418+msgstr "Добродошли у свој Убунту телефон."
419
419
420#: qml/Wizard/Pages/10-welcome.qml:52
420#: qml/Wizard/Pages/10-welcome.qml:52
421msgid "Let’s get started."
421msgid "Let’s get started."
@@ -451,32 +451,32 @@ msgstr "Молим, изаберите како бисте желели да о
451#: qml/Wizard/Pages/30-passwd-type.qml:97
451#: qml/Wizard/Pages/30-passwd-type.qml:97
452msgctxt "Label: Type of security method"
452msgctxt "Label: Type of security method"
453msgid "Swipe"
453msgid "Swipe"
454−msgstr ""
454+msgstr "Превлачење"
455
455
456#: qml/Wizard/Pages/30-passwd-type.qml:98
456#: qml/Wizard/Pages/30-passwd-type.qml:98
457msgctxt "Label: Description of security method"
457msgctxt "Label: Description of security method"
458msgid "No security"
458msgid "No security"
459−msgstr ""
459+msgstr "Без заштите"
460
460
461#: qml/Wizard/Pages/30-passwd-type.qml:100
461#: qml/Wizard/Pages/30-passwd-type.qml:100
462msgctxt "Label: Type of security method"
462msgctxt "Label: Type of security method"
463msgid "Passcode"
463msgid "Passcode"
464−msgstr ""
464+msgstr "Код"
465
465
466#: qml/Wizard/Pages/30-passwd-type.qml:101
466#: qml/Wizard/Pages/30-passwd-type.qml:101
467msgctxt "Label: Description of security method"
467msgctxt "Label: Description of security method"
468msgid "4 digits only"
468msgid "4 digits only"
469−msgstr ""
469+msgstr "Само 4 цифре"
470
470
471#: qml/Wizard/Pages/30-passwd-type.qml:103
471#: qml/Wizard/Pages/30-passwd-type.qml:103
472msgctxt "Label: Type of security method"
472msgctxt "Label: Type of security method"
473msgid "Passphrase"
473msgid "Passphrase"
474−msgstr ""
474+msgstr "Лозинка"
475
475
476#: qml/Wizard/Pages/30-passwd-type.qml:104
476#: qml/Wizard/Pages/30-passwd-type.qml:104
477msgctxt "Label: Description of security method"
477msgctxt "Label: Description of security method"
478msgid "Numbers and letters"
478msgid "Numbers and letters"
479−msgstr ""
479+msgstr "Бројеви и слова"
480
480
481#: qml/Wizard/Pages/40-wifi.qml:29
481#: qml/Wizard/Pages/40-wifi.qml:29
482msgid "Connect to Wi‑Fi"
482msgid "Connect to Wi‑Fi"
@@ -505,6 +505,7 @@ msgstr "Користећи само ГПС (мања тачност)"
505#: qml/Wizard/Pages/50-location.qml:86
505#: qml/Wizard/Pages/50-location.qml:86
506msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
506msgid "Using GPS, anonymized Wi-Fi and cellular network info (recommended)"
507msgstr ""
507msgstr ""
508+"Помоћу GPS-a, заштићених података о бежичним и мобилним мрежама (препоручено)"
508
509
509#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
510#. TRANSLATORS: HERE is a trademark for Nokia's location service, you probably shouldn't translate it
510#: qml/Wizard/Pages/50-location.qml:103
511#: qml/Wizard/Pages/50-location.qml:103
@@ -582,7 +583,7 @@ msgstr "Изаберите своју шифру"
582
583
583#: qml/Wizard/Pages/passwd-set.qml:68
584#: qml/Wizard/Pages/passwd-set.qml:68
584msgid "Passphrase must be 4 characters long"
585msgid "Passphrase must be 4 characters long"
585−msgstr ""
586+msgstr "Лозинка мора имати бар 4 знака"
586
587
587#: qml/Wizard/StackButton.qml:39
588#: qml/Wizard/StackButton.qml:39
588#, qt-format
589#, qt-format
qml/Components/Dialogs.qml+2
@@ -51,11 +51,13 @@ Item {
51 if (!dialogLoader.active) {
51 if (!dialogLoader.active) {
52 dialogLoader.sourceComponent = powerDialogComponent;
52 dialogLoader.sourceComponent = powerDialogComponent;
53 dialogLoader.active = true;
53 dialogLoader.active = true;
54+ dialogLoader.item.forceActiveFocus();
54 }
55 }
55 }
56 }
56 }
57 }
57 Loader {
58 Loader {
58 id: dialogLoader
59 id: dialogLoader
60+ objectName: "dialogLoader"
59 anchors.fill: parent
61 anchors.fill: parent
60 active: false
62 active: false
61 }
63 }
qml/Dash/Dash.qml+27−14
@@ -28,29 +28,42 @@ Showable {
28
28
29 visible: shown
29 visible: shown
30
30
31+ Connections {
32+ target: UriHandler
33+ onOpened: {
34+ backToDashContent()
35+ dashContent.currentScope.performQuery(uris[0])
36+ }
37+ }
38+
31 DashCommunicatorService {
39 DashCommunicatorService {
32 objectName: "dashCommunicatorService"
40 objectName: "dashCommunicatorService"
33 onSetCurrentScopeRequested: {
41 onSetCurrentScopeRequested: {
34 if (!isSwipe || !window.active || bottomEdgeController.progress != 0 || scopeItem.scope || dashContent.subPageShown) {
42 if (!isSwipe || !window.active || bottomEdgeController.progress != 0 || scopeItem.scope || dashContent.subPageShown) {
35 if (bottomEdgeController.progress != 0 && window.active) animate = false;
43 if (bottomEdgeController.progress != 0 && window.active) animate = false;
36 dashContent.setCurrentScopeAtIndex(index, animate, isSwipe)
44 dashContent.setCurrentScopeAtIndex(index, animate, isSwipe)
37− // Close dash overview and nested temp scopes in it
45+ backToDashContent()
38− if (bottomEdgeController.progress != 0) {
39− bottomEdgeController.enableAnimation = window.active;
40− bottomEdgeController.progress = 0;
41− }
42− // Close normal temp scopes (e.g. App Store)
43− if (scopeItem.scope) {
44− scopeItem.backClicked();
45− }
46− // Close previews
47− if (dashContent.subPageShown) {
48− dashContent.closePreview();
49− }
50 }
46 }
51 }
47 }
52 }
48 }
53
49
50+ function backToDashContent()
51+ {
52+ // Close dash overview and nested temp scopes in it
53+ if (bottomEdgeController.progress != 0) {
54+ bottomEdgeController.enableAnimation = window.active;
55+ bottomEdgeController.progress = 0;
56+ }
57+ // Close normal temp scopes (e.g. App Store)
58+ if (scopeItem.scope) {
59+ scopeItem.backClicked();
60+ }
61+ // Close previews
62+ if (dashContent.subPageShown) {
63+ dashContent.closePreview();
64+ }
65+ }
66+
54 function setCurrentScope(scopeId, animate, reset) {
67 function setCurrentScope(scopeId, animate, reset) {
55 var scopeIndex = -1;
68 var scopeIndex = -1;
56 for (var i = 0; i < scopes.count; ++i) {
69 for (var i = 0; i < scopes.count; ++i) {
@@ -178,7 +191,7 @@ Showable {
178 Binding {
191 Binding {
179 target: scopesList.scope
192 target: scopesList.scope
180 property: "isActive"
193 property: "isActive"
181− value: bottomEdgeController.progress === 1
194+ value: bottomEdgeController.progress === 1 && (Qt.application.state == Qt.ApplicationActive)
182 }
195 }
183
196
184 Connections {
197 Connections {
qml/Dash/DashContent.qml−5
@@ -63,11 +63,6 @@ Item {
63 }
63 }
64 }
64 }
65
65
66− Connections {
67− target: UriHandler
68− onOpened: dashContentList.currentItem.theScope.performQuery(uris[0])
69− }
70−
71 function setCurrentScopeAtIndex(index, animate, reset) {
66 function setCurrentScopeAtIndex(index, animate, reset) {
72 // if the scopes haven't loaded yet, then wait until they are.
67 // if the scopes haven't loaded yet, then wait until they are.
73 if (!scopes.loaded) {
68 if (!scopes.loaded) {
qml/Dash/GenericScopeView.qml+1−2
@@ -19,7 +19,6 @@ import Ubuntu.Components 1.1
19import Utils 0.1
19import Utils 0.1
20import Unity 0.2
20import Unity 0.2
21import Dash 0.1
21import Dash 0.1
22−import Powerd 0.1
23import "../Components"
22import "../Components"
24import "../Components/ListItems" as ListItems
23import "../Components/ListItems" as ListItems
25
24
@@ -105,7 +104,7 @@ FocusScope {
105 Binding {
104 Binding {
106 target: scope
105 target: scope
107 property: "isActive"
106 property: "isActive"
108− value: isCurrent && !subPageLoader.open && (Powerd.status === Powerd.On)
107+ value: isCurrent && !subPageLoader.open && (Qt.application.state == Qt.ApplicationActive)
109 }
108 }
110
109
111 UnitySortFilterProxyModel {
110 UnitySortFilterProxyModel {
qml/Panel/Indicators/MenuItemFactory.qml+48−52
@@ -19,6 +19,7 @@
19
19
20import QtQuick 2.0
20import QtQuick 2.0
21import Ubuntu.Settings.Menus 0.1 as Menus
21import Ubuntu.Settings.Menus 0.1 as Menus
22+import Ubuntu.Settings.Components 0.1
22import QMenuModel 0.1
23import QMenuModel 0.1
23import Utils 0.1 as Utils
24import Utils 0.1 as Utils
24import Ubuntu.Components.ListItems 0.1 as ListItems
25import Ubuntu.Components.ListItems 0.1 as ListItems
@@ -84,6 +85,7 @@ Item {
84 id: sliderMenu;
85 id: sliderMenu;
85
86
86 Menus.SliderMenu {
87 Menus.SliderMenu {
88+ id: sliderItem
87 objectName: "sliderMenu"
89 objectName: "sliderMenu"
88 property QtObject menuData: null
90 property QtObject menuData: null
89 property var menuModel: menuFactory.menuModel
91 property var menuModel: menuFactory.menuModel
@@ -113,15 +115,6 @@ Item {
113 onMenuIndexChanged: {
115 onMenuIndexChanged: {
114 loadAttributes();
116 loadAttributes();
115 }
117 }
116− onServerValueChanged: {
117− // value can be changed by slider, so a binding won't work.
118− if (serverValue !== undefined) {
119− value = serverValue;
120− }
121− }
122− onUpdated: {
123− menuModel.changeState(menuIndex, value);
124− }
125
118
126 function loadAttributes() {
119 function loadAttributes() {
127 if (!menuModel || menuIndex == -1) return;
120 if (!menuModel || menuIndex == -1) return;
@@ -130,6 +123,20 @@ Item {
130 'min-icon': 'icon',
123 'min-icon': 'icon',
131 'max-icon': 'icon'});
124 'max-icon': 'icon'});
132 }
125 }
126+
127+ ServerPropertySynchroniser {
128+ objectName: "sync"
129+ syncTimeout: Utils.Constants.indicatorValueTimeout
130+ bufferedSyncTimeout: true
131+ maximumWaitBufferInterval: 16
132+
133+ serverTarget: sliderItem
134+ serverProperty: "serverValue"
135+ userTarget: sliderItem
136+ userProperty: "value"
137+
138+ onSyncTriggered: menuModel.changeState(menuIndex, value)
139+ }
133 }
140 }
134 }
141 }
135
142
@@ -280,6 +287,7 @@ Item {
280 id: checkableMenu;
287 id: checkableMenu;
281
288
282 Menus.CheckableMenu {
289 Menus.CheckableMenu {
290+ id: checkItem
283 objectName: "checkableMenu"
291 objectName: "checkableMenu"
284 property QtObject menuData: null
292 property QtObject menuData: null
285 property int menuIndex: -1
293 property int menuIndex: -1
@@ -290,26 +298,16 @@ Item {
290 checked: serverChecked
298 checked: serverChecked
291 highlightWhenPressed: false
299 highlightWhenPressed: false
292
300
293− onServerCheckedChanged: updateFromServer()
301+ ServerPropertySynchroniser {
294− onTriggered: {
302+ objectName: "sync"
295− menuModel.activate(menuIndex);
303+ syncTimeout: Utils.Constants.indicatorValueTimeout
296− resyncTimer.restart();
297− }
298
304
299− // value can be changed by menu, so a binding won't work.
305+ serverTarget: checkItem
300− function updateFromServer() {
301− resyncTimer.stop();
302− if (checked != serverChecked) {
306+ serverProperty: "serverChecked"
303− checked = serverChecked;
307+ userTarget: checkItem
304− }
308+ userProperty: "checked"
305− }
306
309
307− // Server value is not guaranteed to change to what we expect from an activation.
310+ onSyncTriggered: menuModel.activate(checkItem.menuIndex)
308− // In this case, we need to re-assert that we are presenting the UI with the set backend value.
309− Timer {
310− id: resyncTimer
311− interval: 1500
312− onTriggered: updateFromServer()
313 }
311 }
314 }
312 }
315 }
313 }
@@ -318,6 +316,7 @@ Item {
318 id: switchMenu;
316 id: switchMenu;
319
317
320 Menus.SwitchMenu {
318 Menus.SwitchMenu {
319+ id: switchItem
321 objectName: "switchMenu"
320 objectName: "switchMenu"
322 property QtObject menuData: null
321 property QtObject menuData: null
323 property int menuIndex: -1
322 property int menuIndex: -1
@@ -329,26 +328,16 @@ Item {
329 checked: serverChecked
328 checked: serverChecked
330 highlightWhenPressed: false
329 highlightWhenPressed: false
331
330
332− onServerCheckedChanged: updateFromServer()
331+ ServerPropertySynchroniser {
333− onTriggered: {
332+ objectName: "sync"
334− menuModel.activate(menuIndex);
333+ syncTimeout: Utils.Constants.indicatorValueTimeout
335− resyncTimer.restart();
336− }
337
334
338− // value can be changed by menu, so a binding won't work.
335+ serverTarget: switchItem
339− function updateFromServer() {
340− resyncTimer.stop();
341− if (checked != serverChecked) {
336+ serverProperty: "serverChecked"
342− checked = serverChecked;
337+ userTarget: switchItem
343− }
338+ userProperty: "checked"
344− }
345
339
346− // Server value is not guaranteed to change to what we expect from an activation.
340+ onSyncTriggered: menuModel.activate(switchItem.menuIndex);
347− // In this case, we need to re-assert that we are presenting the UI with the set backend value.
348− Timer {
349− id: resyncTimer
350− interval: 1500
351− onTriggered: updateFromServer()
352 }
341 }
353 }
342 }
354 }
343 }
@@ -464,6 +453,7 @@ Item {
464 id: accessPoint;
453 id: accessPoint;
465
454
466 Menus.AccessPointMenu {
455 Menus.AccessPointMenu {
456+ id: apItem
467 objectName: "accessPoint"
457 objectName: "accessPoint"
468 property QtObject menuData: null
458 property QtObject menuData: null
469 property var menuModel: menuFactory.menuModel
459 property var menuModel: menuFactory.menuModel
@@ -485,19 +475,12 @@ Item {
485 signalStrength: strengthAction.valid ? strengthAction.state : 0
475 signalStrength: strengthAction.valid ? strengthAction.state : 0
486 highlightWhenPressed: false
476 highlightWhenPressed: false
487
477
488− onServerCheckedChanged: {
489− // value can be changed by menu, so a binding won't work.
490− active = serverChecked;
491− }
492 onMenuModelChanged: {
478 onMenuModelChanged: {
493 loadAttributes();
479 loadAttributes();
494 }
480 }
495 onMenuIndexChanged: {
481 onMenuIndexChanged: {
496 loadAttributes();
482 loadAttributes();
497 }
483 }
498− onTriggered: {
499− menuModel.activate(menuIndex);
500− }
501
484
502 function loadAttributes() {
485 function loadAttributes() {
503 if (!menuModel || menuIndex == -1) return;
486 if (!menuModel || menuIndex == -1) return;
@@ -505,6 +488,19 @@ Item {
505 'x-canonical-wifi-ap-is-secure': 'bool',
488 'x-canonical-wifi-ap-is-secure': 'bool',
506 'x-canonical-wifi-ap-strength-action': 'string'});
489 'x-canonical-wifi-ap-strength-action': 'string'});
507 }
490 }
491+
492+ ServerPropertySynchroniser {
493+ objectName: "sync"
494+ syncTimeout: Utils.Constants.indicatorValueTimeout
495+
496+ serverTarget: apItem
497+ serverProperty: "serverChecked"
498+ userTarget: apItem
499+ userProperty: "active"
500+ userTrigger: "onTriggered"
501+
502+ onSyncTriggered: menuModel.activate(apItem.menuIndex)
503+ }
508 }
504 }
509 }
505 }
510
506
qml/Panel/Indicators/client/IndicatorsList.qml+2−2
@@ -31,8 +31,8 @@ Page {
31
31
32 Indicators.IndicatorsModel {
32 Indicators.IndicatorsModel {
33 id: indicatorsModel
33 id: indicatorsModel
34−
34+ profile: page.profile
35− Component.onCompleted: load(profile)
35+ Component.onCompleted: load()
36 }
36 }
37
37
38 ListView {
38 ListView {
qml/Panel/IndicatorsMenu.qml+5−1
@@ -88,6 +88,7 @@ Showable {
88
88
89 Handle {
89 Handle {
90 id: handle
90 id: handle
91+ objectName: "handle"
91 anchors {
92 anchors {
92 left: parent.left
93 left: parent.left
93 right: parent.right
94 right: parent.right
@@ -163,7 +164,10 @@ Showable {
163 }
164 }
164
165
165 MouseArea {
166 MouseArea {
166− anchors.fill: __showDragHandle
167+ anchors.bottom: parent.bottom
168+ anchors.left: parent.left
169+ anchors.right: parent.right
170+ height: minimizedPanelHeight
167 enabled: __showDragHandle.enabled
171 enabled: __showDragHandle.enabled
168 onClicked: {
172 onClicked: {
169 bar.selectItemAt(mouseX)
173 bar.selectItemAt(mouseX)
qml/Panel/Panel.qml+1
@@ -187,6 +187,7 @@ Item {
187
187
188 QtObject {
188 QtObject {
189 id: d
189 id: d
190+ objectName: "panelPriv"
190 readonly property real indicatorHeight: indicators.minimizedPanelHeight + indicatorOrangeLine.height
191 readonly property real indicatorHeight: indicators.minimizedPanelHeight + indicatorOrangeLine.height
191 }
192 }
192
193
qml/Shell.qml+28−18
@@ -79,6 +79,9 @@ Item {
79 }
79 }
80 }
80 }
81
81
82+ // This is _only_ used to expose the property to autopilot tests
83+ readonly property string testShellMode: shellMode
84+
82 function activateApplication(appId) {
85 function activateApplication(appId) {
83 if (ApplicationManager.findApplication(appId)) {
86 if (ApplicationManager.findApplication(appId)) {
84 ApplicationManager.requestFocusApplication(appId);
87 ApplicationManager.requestFocusApplication(appId);
@@ -181,7 +184,6 @@ Item {
181 objectName: "stages"
184 objectName: "stages"
182 width: parent.width
185 width: parent.width
183 height: parent.height
186 height: parent.height
184− visible: !ApplicationManager.empty
185
187
186 Connections {
188 Connections {
187 target: ApplicationManager
189 target: ApplicationManager
@@ -282,6 +284,31 @@ Item {
282 value: shell.background
284 value: shell.background
283 }
285 }
284 }
286 }
287+
288+ Tutorial {
289+ id: tutorial
290+ objectName: "tutorial"
291+ anchors.fill: parent
292+ active: AccountsService.demoEdges
293+ paused: LightDM.Greeter.active
294+ launcher: launcher
295+ panel: panel
296+ edgeSize: shell.edgeSize
297+
298+ // EdgeDragAreas don't work with mice. So to avoid trapping the user,
299+ // we'll tell the tutorial to avoid using them on the Desktop. The
300+ // Desktop doesn't use the same spread design anyway. The tutorial is
301+ // all a bit of a placeholder on non-phone form factors right now.
302+ // When the design team gives us more guidance, we can do something
303+ // more clever here.
304+ // TODO: use DeviceConfiguration instead of checking source
305+ useEdgeDragArea: applicationsDisplayLoader.source != Qt.resolvedUrl("Stages/DesktopStage.qml")
306+
307+ onFinished: {
308+ AccountsService.demoEdges = false;
309+ active = false; // for immediate response / if AS is having problems
310+ }
311+ }
285 }
312 }
286
313
287 InputMethod {
314 InputMethod {
@@ -579,23 +606,6 @@ Item {
579 }
606 }
580 }
607 }
581
608
582− Tutorial {
583− id: tutorial
584− objectName: "tutorial"
585− active: AccountsService.demoEdges
586− paused: LightDM.Greeter.active
587− launcher: launcher
588− panel: panel
589− stages: stages
590− overlay: overlay
591− edgeSize: shell.edgeSize
592−
593− onFinished: {
594− AccountsService.demoEdges = false;
595− active = false; // for immediate response / if AS is having problems
596− }
597− }
598−
599 Connections {
609 Connections {
600 target: SessionBroadcast
610 target: SessionBroadcast
601 onShowHome: showHome()
611 onShowHome: showHome()
qml/Stages/SurfaceContainer.qml+12−9
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2014 Canonical Ltd.
2+ * Copyright 2014-2015 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU Lesser General Public License as published by
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19import Ubuntu.Gestures 0.1 // For TouchGate
19import Ubuntu.Gestures 0.1 // For TouchGate
20+import Utils 0.1 // for InputWatcher
20
21
21FocusScope {
22FocusScope {
22 id: root
23 id: root
@@ -26,8 +27,6 @@ FocusScope {
26 property int orientation
27 property int orientation
27 property bool interactive
28 property bool interactive
28
29
29− signal surfacePressed()
30−
31 onSurfaceChanged: {
30 onSurfaceChanged: {
32 if (surface) {
31 if (surface) {
33 // Set the surface focus *after* it is added to the scene to
32 // Set the surface focus *after* it is added to the scene to
@@ -45,17 +44,21 @@ FocusScope {
45 Binding { target: surface; property: "enabled"; value: root.interactive; when: surface }
44 Binding { target: surface; property: "enabled"; value: root.interactive; when: surface }
46 Binding { target: surface; property: "antialiasing"; value: !root.interactive; when: surface }
45 Binding { target: surface; property: "antialiasing"; value: !root.interactive; when: surface }
47
46
47+ InputWatcher {
48+ target: root.surface
49+ onTargetPressedChanged: {
50+ if (targetPressed && root.interactive) {
51+ root.focus = true;
52+ root.forceActiveFocus();
53+ }
54+ }
55+ }
56+
48 TouchGate {
57 TouchGate {
49 targetItem: surface
58 targetItem: surface
50 anchors.fill: root
59 anchors.fill: root
51 enabled: root.surface ? root.surface.enabled : false
60 enabled: root.surface ? root.surface.enabled : false
52 z: 2
61 z: 2
53− onPressed: {
54− root.focus = true;
55− if (root.interactive) {
56− root.forceActiveFocus();
57− }
58− }
59 }
62 }
60
63
61 states: [
64 states: [
qml/Tutorial/Tutorial.qml+7−14
@@ -23,11 +23,10 @@ Item {
23 property alias active: loader.active
23 property alias active: loader.active
24 property bool paused
24 property bool paused
25 property real edgeSize
25 property real edgeSize
26+ property bool useEdgeDragArea
26
27
27 property Item launcher
28 property Item launcher
28 property Item panel
29 property Item panel
29− property Item stages
30− property Item overlay
31
30
32 readonly property bool launcherEnabled: loader.item ? loader.item.launcherEnabled : true
31 readonly property bool launcherEnabled: loader.item ? loader.item.launcherEnabled : true
33 readonly property bool spreadEnabled: loader.item ? loader.item.spreadEnabled : true
32 readonly property bool spreadEnabled: loader.item ? loader.item.spreadEnabled : true
@@ -62,26 +61,20 @@ Item {
62
61
63 Binding {
62 Binding {
64 target: loader.item
63 target: loader.item
65− property: "launcher"
64+ property: "useEdgeDragArea"
66− value: root.launcher
67− }
68−
69− Binding {
70− target: loader.item
71− property: "panel"
72− value: root.panel
65+ value: root.useEdgeDragArea
73 }
66 }
74
67
75 Binding {
68 Binding {
76 target: loader.item
69 target: loader.item
77− property: "stages"
70+ property: "launcher"
78− value: root.stages
71+ value: root.launcher
79 }
72 }
80
73
81 Binding {
74 Binding {
82 target: loader.item
75 target: loader.item
83− property: "overlay"
76+ property: "panel"
84− value: root.overlay
77+ value: root.panel
85 }
78 }
86
79
87 Connections {
80 Connections {
qml/Tutorial/TutorialContent.qml+9−8
@@ -22,8 +22,6 @@ Item {
22
22
23 property Item launcher
23 property Item launcher
24 property Item panel
24 property Item panel
25− property Item stages
26− property Item overlay
27
25
28 readonly property bool launcherEnabled: !running ||
26 readonly property bool launcherEnabled: !running ||
29 (!paused && tutorialLeft.shown)
27 (!paused && tutorialLeft.shown)
@@ -34,6 +32,7 @@ Item {
34
32
35 property bool paused: false
33 property bool paused: false
36 property real edgeSize
34 property real edgeSize
35+ property bool useEdgeDragArea
37
36
38 signal finished()
37 signal finished()
39
38
@@ -66,7 +65,6 @@ Item {
66 TutorialLeft {
65 TutorialLeft {
67 id: tutorialLeft
66 id: tutorialLeft
68 objectName: "tutorialLeft"
67 objectName: "tutorialLeft"
69− parent: root.stages
70 anchors.fill: parent
68 anchors.fill: parent
71 launcher: root.launcher
69 launcher: root.launcher
72 paused: !shown || root.paused
70 paused: !shown || root.paused
@@ -77,21 +75,26 @@ Item {
77 TutorialLeftFinish {
75 TutorialLeftFinish {
78 id: tutorialLeftFinish
76 id: tutorialLeftFinish
79 objectName: "tutorialLeftFinish"
77 objectName: "tutorialLeftFinish"
80− parent: root.stages
81 anchors.fill: parent
78 anchors.fill: parent
82 textXOffset: root.launcher.panelWidth
79 textXOffset: root.launcher.panelWidth
83 paused: !shown || root.paused
80 paused: !shown || root.paused
81+ text: root.useEdgeDragArea ? i18n.tr("Tap here to continue.") : i18n.tr("Click here to finish.")
84
82
85 onFinished: {
83 onFinished: {
86 root.launcher.hide();
84 root.launcher.hide();
85+ if (root.useEdgeDragArea) {
87− tutorialRight.show();
86+ tutorialRight.show();
87+ } else {
88+ // Last two screens use EdgeDragArea (right edge spread and
89+ // bottom edge). So just end tutorial here.
90+ root.finish();
91+ }
88 }
92 }
89 }
93 }
90
94
91 TutorialRight {
95 TutorialRight {
92 id: tutorialRight
96 id: tutorialRight
93 objectName: "tutorialRight"
97 objectName: "tutorialRight"
94− parent: root.stages
95 anchors.fill: parent
98 anchors.fill: parent
96 edgeSize: root.edgeSize
99 edgeSize: root.edgeSize
97 panel: root.panel
100 panel: root.panel
@@ -103,7 +106,6 @@ Item {
103 TutorialBottom {
106 TutorialBottom {
104 id: tutorialBottom
107 id: tutorialBottom
105 objectName: "tutorialBottom"
108 objectName: "tutorialBottom"
106− parent: root.stages
107 anchors.fill: parent
109 anchors.fill: parent
108 edgeSize: root.edgeSize
110 edgeSize: root.edgeSize
109 paused: !shown || root.paused
111 paused: !shown || root.paused
@@ -114,7 +116,6 @@ Item {
114 TutorialBottomFinish {
116 TutorialBottomFinish {
115 id: tutorialBottomFinish
117 id: tutorialBottomFinish
116 objectName: "tutorialBottomFinish"
118 objectName: "tutorialBottomFinish"
117− parent: root.stages
118 anchors.fill: parent
119 anchors.fill: parent
119 backgroundFadesOut: true
120 backgroundFadesOut: true
120 paused: !shown || root.paused
121 paused: !shown || root.paused
run.sh+1−1
@@ -65,6 +65,6 @@ else
65 echo "Unity8 is already running, please stop it first"
65 echo "Unity8 is already running, please stop it first"
66 exit 1
66 exit 1
67 fi
67 fi
68− /sbin/initctl start unity8 BINARY="`readlink -f $QML_PHONE_SHELL_PATH` $QML_PHONE_SHELL_ARGS $@" QML2_IMPORT_PATH=$QML2_IMPORT_PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH
68+ /sbin/initctl start unity8 BINARY="`readlink -f $QML_PHONE_SHELL_PATH` $QML_PHONE_SHELL_ARGS $@" XDG_DATA_DIRS=$XDG_DATA_DIRS QML2_IMPORT_PATH=$QML2_IMPORT_PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH
69 tailf -n 0 ~/.cache/upstart/unity8.log
69 tailf -n 0 ~/.cache/upstart/unity8.log
70fi
70fi
src/Panel/Indicators/client/CMakeLists.txt−2
@@ -1,5 +1,4 @@
1project(indicators_client)
1project(indicators_client)
2−set(INDICATORS_CLIENT_APP indicators-client)
3
2
4set(INDICATORS_CLIENT_SRC
3set(INDICATORS_CLIENT_SRC
5 main.cpp
4 main.cpp
@@ -15,7 +14,6 @@ add_executable(${INDICATORS_CLIENT_APP}
15)
14)
16
15
17qt5_use_modules(${INDICATORS_CLIENT_APP} Core Widgets Quick)
16qt5_use_modules(${INDICATORS_CLIENT_APP} Core Widgets Quick)
18−set_target_properties(${INDICATORS_CLIENT_APP} PROPERTIES COMPILE_FLAGS -fPIC)
19
17
20install(TARGETS ${INDICATORS_CLIENT_APP}
18install(TARGETS ${INDICATORS_CLIENT_APP}
21 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
19 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
src/main.cpp+26
@@ -70,6 +70,11 @@ int main(int argc, const char *argv[])
70Load the testability driver");
70Load the testability driver");
71 parser.addOption(testabilityOption);
71 parser.addOption(testabilityOption);
72
72
73+ QCommandLineOption modeOption("mode",
74+ "Whether to run greeter and/or shell [full-greeter, full-shell, greeter, shell]",
75+ "mode", "full-greeter");
76+ parser.addOption(modeOption);
77+
73 application = new QGuiApplication(argc, (char**)argv);
78 application = new QGuiApplication(argc, (char**)argv);
74
79
75 // Treat args with single dashes the same as arguments with two dashes
80 // Treat args with single dashes the same as arguments with two dashes
@@ -90,6 +95,26 @@ Load the testability driver");
90 qmlArgs.setSize(geom.at(0).toInt(), geom.at(1).toInt());
95 qmlArgs.setSize(geom.at(0).toInt(), geom.at(1).toInt());
91 }
96 }
92
97
98+ // If an invalid option was specified, set it to the default
99+ // If no default was provided in the QCommandLineOption constructor, abort.
100+ QString shellMode;
101+ if(!parser.isSet(modeOption) ||
102+ (parser.value(modeOption) != "full-greeter" &&
103+ parser.value(modeOption) != "full-shell" &&
104+ parser.value(modeOption) != "greeter" &&
105+ parser.value(modeOption) != "shell"))
106+ {
107+ if (modeOption.defaultValues().first() != nullptr) {
108+ shellMode = modeOption.defaultValues().first();
109+ qWarning() << "Mode argument was not provided or was set to an illegal value. Using default value of --mode=" << shellMode;
110+ } else {
111+ qFatal("Shell mode argument was not provided and there is no default mode,");
112+ }
113+
114+ } else {
115+ shellMode = parser.value(modeOption);
116+ }
117+
93 // The testability driver is only loaded by QApplication but not by QGuiApplication.
118 // The testability driver is only loaded by QApplication but not by QGuiApplication.
94 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
119 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
95 if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) {
120 if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) {
@@ -117,6 +142,7 @@ Load the testability driver");
117 view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
142 view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
118 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
143 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
119 view->rootContext()->setContextProperty("indicatorProfile", indicatorProfile);
144 view->rootContext()->setContextProperty("indicatorProfile", indicatorProfile);
145+ view->rootContext()->setContextProperty("shellMode", shellMode);
120 if (parser.isSet(framelessOption)) {
146 if (parser.isSet(framelessOption)) {
121 view->setFlags(Qt::FramelessWindowHint);
147 view->setFlags(Qt::FramelessWindowHint);
122 }
148 }
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+2−4
@@ -91,10 +91,9 @@ class ApplicationLifecycleTests(tests.ApplicationLifeCycleTestCase):
91 def test_greeter_hides_on_app_open(self):
91 def test_greeter_hides_on_app_open(self):
92 """Greeter should hide when an app is opened"""
92 """Greeter should hide when an app is opened"""
93 process_helpers.lock_unity()
93 process_helpers.lock_unity()
94− greeter = self.main_window.get_greeter()
95− self.assertThat(greeter.created, Eventually(Equals(True)))
96
94
97 application_name = self.launch_fake_app()
95 application_name = self.launch_fake_app()
96+ greeter = self.main_window.get_greeter()
98 greeter.wait_swiped_away()
97 greeter.wait_swiped_away()
99 process_helpers.unlock_unity()
98 process_helpers.unlock_unity()
100 self.assert_current_focused_application(application_name)
99 self.assert_current_focused_application(application_name)
@@ -108,10 +107,9 @@ class ApplicationLifecycleTests(tests.ApplicationLifeCycleTestCase):
108 self.assert_current_focused_application('unity8-dash')
107 self.assert_current_focused_application('unity8-dash')
109
108
110 process_helpers.lock_unity()
109 process_helpers.lock_unity()
111− greeter = self.main_window.get_greeter()
112− self.assertThat(greeter.created, Eventually(Equals(True)))
113
110
114 self.launch_upstart_application(application_name)
111 self.launch_upstart_application(application_name)
112+ greeter = self.main_window.get_greeter()
115 greeter.wait_swiped_away()
113 greeter.wait_swiped_away()
116 process_helpers.unlock_unity()
114 process_helpers.unlock_unity()
117 self.assert_current_focused_application(application_name)
115 self.assert_current_focused_application(application_name)
tests/autopilot/unity8/fixture_setup.py+46−1
@@ -19,12 +19,17 @@
19
19
20import fixtures
20import fixtures
21import subprocess
21import subprocess
22+import logging
22
23
23from autopilot import introspection
24from autopilot import introspection
24
25
25−from unity8 import process_helpers
26+from unity8 import (
27+ get_binary_path,
28+ process_helpers
29+)
26from unity8.shell import emulators
30from unity8.shell import emulators
27
31
32+logger = logging.getLogger(__name__)
28
33
29class LaunchDashApp(fixtures.Fixture):
34class LaunchDashApp(fixtures.Fixture):
30
35
@@ -96,3 +101,43 @@ class DisplayRotationLock(fixtures.Fixture):
96 'rotation-lock', value_string
101 'rotation-lock', value_string
97 ]
102 ]
98 subprocess.check_output(command)
103 subprocess.check_output(command)
104+
105+class LaunchMockIndicatorService(fixtures.Fixture):
106+
107+ """Fixture to launch the indicator test service."""
108+
109+ def __init__(self, action_delay, ensure_not_running=True):
110+ """Initialize an instance.
111+
112+ :param action_delay: The delay to use when activating actions.
113+ Measured in milliseconds. Value of -1 will result in infinite delay.
114+ :type action_delay: An integer.
115+ :param boolean ensure_not_running: Make sure service is not running
116+
117+ """
118+ super(LaunchMockIndicatorService, self).__init__()
119+ self.action_delay = action_delay
120+ self.ensure_not_running = ensure_not_running
121+
122+ def setUp(self):
123+ super(LaunchMockIndicatorService, self).setUp()
124+ if self.ensure_not_running:
125+ self.ensure_service_not_running()
126+ self.addCleanup(self.stop_service)
127+ self.application_proxy = self.launch_service()
128+
129+ def launch_service(self):
130+ logger.info("Starting unity-mock-indicator-service")
131+ binary_path = get_binary_path('unity-mock-indicator-service')
132+ binary_arg = 'BINARY={}'.format(binary_path)
133+ env_args = 'ARGS=-t {}'.format(self.action_delay)
134+ all_args = [binary_arg, env_args]
135+ process_helpers.start_job('unity-mock-indicator-service', *all_args)
136+
137+ def stop_service(self):
138+ logger.info("Stopping unity-mock-indicator-service")
139+ process_helpers.stop_job('unity-mock-indicator-service')
140+
141+ def ensure_service_not_running(self):
142+ if process_helpers.is_job_running('unity-mock-indicator-service'):
143+ self.stop_service()
tests/autopilot/unity8/greeter/__init__.pynew file

No changes to the content.

tests/autopilot/unity8/greeter/tests/__init__.pynew file+26
@@ -0,0 +1,26 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Autopilot Test Suite
4+# Copyright (C) 2015 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 unity8.shell.emulators import main_window as main_window_emulator
21+from unity8.shell.tests import UnityTestCase
22+
23+class GreeterTestCase(UnityTestCase):
24+ def get_shell(self, unity_proxy):
25+ main_window = unity_proxy.select_single(main_window_emulator.QQuickView)
26+ return main_window.select_single('Shell')
tests/autopilot/unity8/greeter/tests/test_args.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) 2015 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 unity8.greeter.tests import GreeterTestCase
21+
22+class GreeterArgsTest(GreeterTestCase):
23+
24+ DEFAULT_SHELL_MODE = 'full-greeter'
25+ NONEXISTENT_MODE = 'non-existent-mode'
26+
27+ def test_full_greeter_mode(self):
28+ unity_proxy = self.launch_unity(mode='full-greeter')
29+ shell = self.get_shell(unity_proxy)
30+ self.assertTrue(shell.testShellMode == 'full-greeter')
31+
32+ def test_full_shell_mode(self):
33+ unity_proxy = self.launch_unity(mode='full-shell')
34+ shell = self.get_shell(unity_proxy)
35+ self.assertTrue(shell.testShellMode == 'full-shell')
36+
37+ def test_greeter_mode(self):
38+ unity_proxy = self.launch_unity(mode='greeter')
39+ shell = self.get_shell(unity_proxy)
40+ self.assertTrue(shell.testShellMode == 'greeter')
41+
42+ def test_nonexistent_mode(self):
43+ unity_proxy = self.launch_unity(mode=self.NONEXISTENT_MODE)
44+ shell = self.get_shell(unity_proxy)
45+ self.assertTrue(shell.testShellMode == self.DEFAULT_SHELL_MODE,
46+ "Shell mode was {} but should have been {}".format(
47+ shell.testShellMode, self.DEFAULT_SHELL_MODE))
48+
49+ def test_shell_mode(self):
50+ unity_proxy = self.launch_unity(mode='shell')
51+ shell = self.get_shell(unity_proxy)
52+ self.assertTrue(shell.testShellMode == 'shell')
tests/autopilot/unity8/indicators/__init__.py+89−10
@@ -19,6 +19,7 @@ import ubuntuuitoolkit
19from autopilot import introspection
19from autopilot import introspection
20
20
21from unity8.shell import emulators
21from unity8.shell import emulators
22+from unity8 import fixture_setup
22
23
23
24
24class IndicatorPage(emulators.UnityEmulatorBase):
25class IndicatorPage(emulators.UnityEmulatorBase):
@@ -33,26 +34,25 @@ class IndicatorPage(emulators.UnityEmulatorBase):
33 def validate_dbus_object(cls, path, state):
34 def validate_dbus_object(cls, path, state):
34 return False
35 return False
35
36
37+class Indicator():
36
38
37−class DisplayIndicator():
38−
39− def __init__(self, main_window):
39+ def __init__(self, main_window, name):
40 self._main_window = main_window
40 self._main_window = main_window
41+ self._name = name
41
42
42 def is_indicator_icon_visible(self):
43 def is_indicator_icon_visible(self):
43 panel_item = self._main_window.wait_select_single(
44 panel_item = self._main_window.wait_select_single(
44− objectName='indicator-rotation-lock-panelItem')
45+ objectName=self._name+'-panelItem')
45 return panel_item.indicatorVisible
46 return panel_item.indicatorVisible
46
47
47 def open(self):
48 def open(self):
48− """Open the display indicator page.
49+ """Open the indicator page.
49
50
50− :return: The custom proxy object for the display indicator page.
51+ :return: The custom proxy object for the indicator page.
51
52
52 """
53 """
53 if self.is_indicator_icon_visible():
54 if self.is_indicator_icon_visible():
54− return self._main_window.open_indicator_page(
55+ return self._main_window.open_indicator_page(self._name)
55− 'indicator-rotation-lock')
56 else:
56 else:
57 return self._open_indicator_with_icon_not_visible()
57 return self._open_indicator_with_icon_not_visible()
58
58
@@ -61,10 +61,10 @@ class DisplayIndicator():
61 self._main_window.open_indicator_page('indicator-datetime')
61 self._main_window.open_indicator_page('indicator-datetime')
62 self._make_indicator_icon_visible()
62 self._make_indicator_icon_visible()
63 indicator_rotation_icon = self._main_window.select_single(
63 indicator_rotation_icon = self._main_window.select_single(
64− objectName='indicator-rotation-lock-panelItem')
64+ objectName=self._name+'-panelItem')
65 self._main_window.pointing_device.click_object(indicator_rotation_icon)
65 self._main_window.pointing_device.click_object(indicator_rotation_icon)
66 return self._main_window.wait_select_single(
66 return self._main_window.wait_select_single(
67− objectName='indicator-rotation-lock-page')
67+ objectName=self._name+'-page')
68
68
69 def _make_indicator_icon_visible(self):
69 def _make_indicator_icon_visible(self):
70 indicators_bar_flickable = self._main_window.select_single(
70 indicators_bar_flickable = self._main_window.select_single(
@@ -95,6 +95,13 @@ class DisplayIndicator():
95 self._main_window.close_indicator_page()
95 self._main_window.close_indicator_page()
96
96
97
97
98+class DisplayIndicator(Indicator):
99+
100+ def __init__(self, main_window):
101+ super(DisplayIndicator, self).__init__(main_window, 'indicator-rotation-lock')
102+ self._main_window = main_window
103+
104+
98class DisplayIndicatorPage(IndicatorPage):
105class DisplayIndicatorPage(IndicatorPage):
99
106
100 """Autopilot helper for the display indicator page."""
107 """Autopilot helper for the display indicator page."""
@@ -122,3 +129,75 @@ class DisplayIndicatorPage(IndicatorPage):
122 switcher = self._get_switcher()
129 switcher = self._get_switcher()
123 switcher.uncheck()
130 switcher.uncheck()
124 switcher.checked.wait_for(False)
131 switcher.checked.wait_for(False)
132+
133+
134+class TestIndicator(Indicator):
135+
136+ def __init__(self, main_window):
137+ super(TestIndicator, self).__init__(main_window, 'indicator-mock')
138+ self._main_window = main_window
139+
140+
141+class TestIndicatorPage(IndicatorPage):
142+
143+ """Autopilot helper for the mock indicator page."""
144+
145+ @classmethod
146+ def validate_dbus_object(cls, path, state):
147+ name = introspection.get_classname_from_path(path)
148+ if name == b'IndicatorPage':
149+ if state['objectName'][1] == 'indicator-mock-page':
150+ return True
151+ return False
152+
153+ def get_switcher(self):
154+ return self.select_single(
155+ ubuntuuitoolkit.CheckBox, objectName='switcher')
156+
157+ def get_switch_menu(self):
158+ return self.select_single(
159+ 'SwitchMenu', objectName='indicator.action.switch')
160+
161+ def get_slider(self):
162+ return self.select_single(objectName='slider')
163+
164+ def get_slider_menu(self):
165+ return self.select_single(objectName='indicator.action.slider')
166+
167+
168+class Slider(emulators.UnityEmulatorBase):
169+
170+ """Autopilot helper for the Slider component."""
171+
172+ # XXX Because of https://bugs.launchpad.net/autopilot-qt/+bug/1341671
173+ # we need to make sure it does not match in any selection.
174+ # --elopio - 2015-01-20
175+
176+ @classmethod
177+ def validate_dbus_object(cls, path, state):
178+ name = introspection.get_classname_from_path(path)
179+ if name == b'Slider':
180+ return True
181+ return False
182+
183+ def slide_left(self, timeout=10):
184+ x, y, width, height = self.globalRect
185+
186+ rate = 5
187+ start_x = x + width/2
188+ start_y = stop_y = y + height/2
189+ stop_x = x
190+
191+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
192+ self.value.wait_for(self.minimumValue, timeout);
193+
194+ def slide_right(self, timeout=10):
195+ x, y, width, height = self.globalRect
196+
197+ rate = 5
198+ start_x = x + width/2
199+ start_y = stop_y = y + height/2
200+ stop_x = x + width
201+
202+ self.pointing_device.drag(start_x, start_y, stop_x, stop_y, rate)
203+ self.value.wait_for(self.maximumValue, timeout);
tests/autopilot/unity8/indicators/tests/__init__.py+7
@@ -26,6 +26,13 @@ class IndicatorTestCase(tests.UnityTestCase):
26
26
27 device_emulation_scenarios = tests._get_device_emulation_scenarios()
27 device_emulation_scenarios = tests._get_device_emulation_scenarios()
28
28
29+ def setUp(self):
30+ super().setUp()
31+ self.unity_proxy = self.launch_unity()
32+ process_helpers.unlock_unity(self.unity_proxy)
33+
34+class DeviceIndicatorTestCase(IndicatorTestCase):
35+
29 def setUp(self):
36 def setUp(self):
30 if platform.model() == 'Desktop':
37 if platform.model() == 'Desktop':
31 self.skipTest('Test cannot be run on the desktop.')
38 self.skipTest('Test cannot be run on the desktop.')
tests/autopilot/unity8/indicators/tests/test_action_latency.pynew file+232
@@ -0,0 +1,232 @@
1+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2+#
3+# Unity Indicators Autopilot Test Suite
4+# Copyright (C) 2015 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+from testscenarios import multiply_scenarios
20+
21+from unity8 import (
22+ fixture_setup,
23+ indicators,
24+ process_helpers
25+)
26+from unity8.shell import tests
27+from unity8.indicators import tests
28+
29+from autopilot.matchers import Eventually
30+from testtools.matchers import Equals, NotEquals
31+import time
32+
33+
34+class TestIndicatorBaseTestCase(tests.IndicatorTestCase):
35+
36+ scenarios = [ tests.IndicatorTestCase.device_emulation_scenarios[0] ]
37+
38+ def setUp(self):
39+ super(TestIndicatorBaseTestCase, self).setUp()
40+
41+ self.launch_indicator_service()
42+
43+ # wait for the indicator to appear in unity
44+ self.indicator = indicators.TestIndicator(self.main_window)
45+ self.assertThat(
46+ self.indicator.is_indicator_icon_visible(),
47+ Eventually(Equals(True), timeout=20)
48+ )
49+ self.indicator_page = self.indicator.open()
50+
51+ def launch_indicator_service(self):
52+ launch_service_fixture = fixture_setup.LaunchMockIndicatorService(self.action_delay)
53+ self.useFixture(launch_service_fixture)
54+
55+
56+class TestServerValueUpdate(TestIndicatorBaseTestCase):
57+
58+ """Test that an action causes the server to update"""
59+
60+ time_scenarios = [
61+ ('Low', {'action_delay': 0}),
62+ ('Medium', {'action_delay': 2500}),
63+ ('High', {'action_delay': 8000}),
64+ ]
65+ scenarios = multiply_scenarios(
66+ time_scenarios,
67+ TestIndicatorBaseTestCase.scenarios
68+ )
69+
70+ def test_switch_reaches_server_value(self):
71+ switch = self.indicator_page.get_switcher()
72+ switch_menu = self.indicator_page.get_switch_menu()
73+
74+ switch.change_state()
75+
76+ self.assertThat(
77+ switch_menu.serverChecked,
78+ Eventually(Equals(switch.checked), timeout=20)
79+ )
80+
81+ def test_slider_reaches_server_value(self):
82+ slider = self.indicator_page.get_slider()
83+ slider_menu = self.indicator_page.get_slider_menu()
84+
85+ old_value = slider.value
86+ slider.slide_left()
87+
88+ self.assertThat(
89+ slider_menu.serverValue,
90+ Eventually(NotEquals(old_value), timeout=20)
91+ )
92+
93+ self.assertThat(
94+ slider_menu.serverValue,
95+ Eventually(Equals(slider.value), timeout=20)
96+ )
97+
98+class TestBuffering(TestIndicatorBaseTestCase):
99+
100+ """Test that switching multiple times will buffer activations
101+
102+ See https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1390136 .
103+ """
104+ action_delay = 2500
105+
106+ def test_switch_buffers_actvations(self):
107+
108+ switch = self.indicator_page.get_switcher()
109+ switch.change_state()
110+ intermediate_value = switch.checked;
111+
112+ # will buffer change until it receives the change from server
113+ switch.change_state()
114+ final_value = switch.checked;
115+
116+ # backend will respond to first switch.
117+ switch_menu = self.indicator_page.get_switch_menu()
118+ self.assertThat(
119+ switch_menu.serverChecked,
120+ Eventually(Equals(intermediate_value), timeout=20)
121+ )
122+ # The buffered activation should have gone to server now.
123+
124+ # front-end should not change as a result of server update while it is buffered
125+ self.assertThat(
126+ switch.checked,
127+ Equals(final_value)
128+ )
129+
130+ # server will respond to the second activate
131+ self.assertThat(
132+ switch_menu.serverChecked,
133+ Eventually(Equals(final_value), timeout=20)
134+ )
135+
136+ # make sure we've got the server value set.
137+ self.assertThat(
138+ switch.checked,
139+ Equals(switch_menu.serverChecked)
140+ )
141+
142+ def test_slider_buffers_activations(self):
143+
144+ slider = self.indicator_page.get_slider()
145+ original_value = slider.value;
146+ slider.slide_left()
147+
148+ # will buffer change until it receives the change from server
149+ slider.slide_right()
150+ final_value = slider.value;
151+
152+ # backend will respond to first slider. Since it's a live slider it'll probably
153+ # be a random value along the slide.
154+ slider_menu = self.indicator_page.get_slider_menu()
155+ self.assertThat(
156+ slider_menu.serverValue,
157+ Eventually(NotEquals(original_value), timeout=20)
158+ )
159+ # It wont yet have reached the final value due to the buffering
160+ # Second activate should have gone out by now
161+ self.assertThat(
162+ slider_menu.serverValue,
163+ NotEquals(final_value)
164+ )
165+
166+ # front-end should not change as a result of server update while it is buffered
167+ self.assertThat(
168+ slider.value,
169+ Equals(final_value)
170+ )
171+
172+ # server will respond to the second activate
173+ self.assertThat(
174+ slider_menu.serverValue,
175+ Eventually(Equals(final_value), timeout=20)
176+ )
177+
178+ # make sure we've got the server value set.
179+ self.assertThat(
180+ slider.value,
181+ Equals(slider_menu.serverValue)
182+ )
183+
184+
185+class TestClientRevertsToServerValue(TestIndicatorBaseTestCase):
186+
187+ """Test that an action which does not respond in time will revert
188+ to original value if not actioned in time.
189+
190+ See https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1390136 .
191+ """
192+ action_delay = -1 # never action.
193+
194+ def test_switch_reverts_on_late_response(self):
195+
196+ switch = self.indicator_page.get_switcher()
197+ switch_menu = self.indicator_page.get_switch_menu()
198+
199+ original_value = switch.checked;
200+ switch.change_state()
201+
202+ # switch should revert to original value after 5 seconds (30 seconds in real usage)
203+ self.assertThat(
204+ switch.checked,
205+ Eventually(Equals(original_value), timeout=20)
206+ )
207+
208+ # make sure we've got the server value set.
209+ self.assertThat(
210+ switch.checked,
211+ Equals(switch_menu.serverChecked)
212+ )
213+
214+ def test_slider_reverts_on_late_response(self):
215+
216+ slider = self.indicator_page.get_slider()
217+ slider_menu = self.indicator_page.get_slider_menu()
218+
219+ original_value = slider.value;
220+ slider.slide_left()
221+
222+ # slider should revert to original value after 5 seconds (30 seconds in real usage)
223+ self.assertThat(
224+ slider.value,
225+ Eventually(Equals(original_value), timeout=20)
226+ )
227+
228+ # make sure we've got the server value set.
229+ self.assertThat(
230+ slider.value,
231+ Equals(slider_menu.serverValue)
232+ )
tests/autopilot/unity8/indicators/tests/test_display_indicator.py+3−1
@@ -23,7 +23,9 @@ from unity8 import (
23from unity8.indicators import tests
23from unity8.indicators import tests
24
24
25
25
26−class DisplayIndicatorTestCase(tests.IndicatorTestCase):
26+class DisplayIndicatorTestCase(tests.DeviceIndicatorTestCase):
27+
28+ scenarios = tests.IndicatorTestCase.device_emulation_scenarios
27
29
28 def test_indicator_icon_must_be_visible_after_rotation_locked(self):
30 def test_indicator_icon_must_be_visible_after_rotation_locked(self):
29 rotation_unlocked = fixture_setup.DisplayRotationLock(False)
31 rotation_unlocked = fixture_setup.DisplayRotationLock(False)
tests/autopilot/unity8/indicators/tests/test_indicators.py+2−2
@@ -23,7 +23,7 @@ from autopilot import platform
23from unity8.indicators import tests
23from unity8.indicators import tests
24
24
25
25
26−class IndicatorExistsTestCase(tests.IndicatorTestCase):
26+class IndicatorExistsTestCase(tests.DeviceIndicatorTestCase):
27
27
28 indicator_scenarios = [
28 indicator_scenarios = [
29 ('Bluetooth', dict(indicator_name='indicator-bluetooth')),
29 ('Bluetooth', dict(indicator_name='indicator-bluetooth')),
@@ -51,7 +51,7 @@ class IndicatorExistsTestCase(tests.IndicatorTestCase):
51 )
51 )
52
52
53
53
54−class IndicatorPageTitleMatchesWidgetTestCase(tests.IndicatorTestCase):
54+class IndicatorPageTitleMatchesWidgetTestCase(tests.DeviceIndicatorTestCase):
55
55
56 indicator_scenarios = [
56 indicator_scenarios = [
57 ('Bluetooth', dict(indicator_name='indicator-bluetooth',
57 ('Bluetooth', dict(indicator_name='indicator-bluetooth',
tests/autopilot/unity8/process_helpers.py+47−14
@@ -89,20 +89,53 @@ def unlock_unity(unity_proxy_obj=None):
89
89
90
90
91def lock_unity(unity_proxy_obj=None):
91def lock_unity(unity_proxy_obj=None):
92− """Helper function that attempts to lock the unity greeter."""
92+ """Helper function that attempts to lock unity greeter.
93− import evdev
93+
94− import time
94+ If unity_proxy_object is None create a proxy object by querying for the
95− uinput = evdev.UInput(name='unity8-autopilot-power-button',
95+ running unity process.
96− devnode='/dev/autopilot-uinput')
96+ Otherwise re-use the passed proxy object.
97− # One press and release to turn screen off (locking unity)
97+
98− uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_POWER, 1)
98+ :raises RuntimeError: if the greeter attempts and fails to be locked.
99− uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_POWER, 0)
99+
100− uinput.syn()
100+ :raises RuntimeWarning: when the greeter is found because it is
101− time.sleep(1)
101+ already locked.
102− # And another press and release to turn screen back on
102+ :raises CannotAccessUnity: if unity is not introspectable or cannot be
103− uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_POWER, 1)
103+ found on dbus.
104− uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_POWER, 0)
104+ :raises CannotAccessUnity: if unity's upstart status is not "start" or the
105− uinput.syn()
105+ upstart job cannot be found at all.
106+
107+ """
108+ if unity_proxy_obj is None:
109+ try:
110+ pid = _get_unity_pid()
111+ unity = _get_unity_proxy_object(pid)
112+ main_window = unity.select_single(main_window_emulator.QQuickView)
113+ except ProcessSearchError as e:
114+ raise CannotAccessUnity(
115+ "Cannot introspect unity, make sure that it has been started "
116+ "with testability. Perhaps use the function "
117+ "'restart_unity_with_testability' this module provides."
118+ "(%s)"
119+ % str(e)
120+ )
121+ else:
122+ main_window = unity_proxy_obj.select_single(
123+ main_window_emulator.QQuickView)
124+
125+ greeter = main_window.get_greeter()
126+ if greeter.created is True:
127+ raise RuntimeWarning("Greeter appears to be already locked.")
128+
129+ bus = dbus.SessionBus()
130+ dbus_proxy = bus.get_object("com.canonical.UnityGreeter", "/")
131+ try:
132+ dbus_proxy.ShowGreeter()
133+ except dbus.DBusException:
134+ logger.info("Failed to lock greeter")
135+ raise
136+ else:
137+ greeter.created.wait_for(True)
138+ logger.info("Greeter locked, continuing.")
106
139
107
140
108def restart_unity_with_testability(*args):
141def restart_unity_with_testability(*args):
tests/autopilot/unity8/shell/tests/__init__.py+13−4
@@ -65,7 +65,6 @@ UNITYSHELL_GSETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
65UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
65UNITYSHELL_LAUNCHER_KEY = "launcher-hide-mode"
66UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
66UNITYSHELL_LAUNCHER_MODE = 1 # launcher hidden
67
67
68−
69def _get_device_emulation_scenarios(devices='All'):
68def _get_device_emulation_scenarios(devices='All'):
70 nexus4 = ('Desktop Nexus 4',
69 nexus4 = ('Desktop Nexus 4',
71 dict(app_width=768, app_height=1280, grid_unit_px=18))
70 dict(app_width=768, app_height=1280, grid_unit_px=18))
@@ -253,8 +252,14 @@ class UnityTestCase(AutopilotTestCase):
253 "%s=%s" % (key, value)
252 "%s=%s" % (key, value)
254 ], stderr=subprocess.STDOUT)
253 ], stderr=subprocess.STDOUT)
255
254
256− def launch_unity(self, **kwargs):
255+ def launch_unity(self, mode="full-greeter", *args):
256+ """
257− """Launch the unity shell, return a proxy object for it."""
257+ Launch the unity shell, return a proxy object for it.
258+
259+ :param str mode: The type of greeter/shell mode to use
260+ :param args: A list of aguments to pass to unity8
261+
262+ """
258 binary_path = get_binary_path()
263 binary_path = get_binary_path()
259 lib_path = get_lib_path()
264 lib_path = get_lib_path()
260
265
@@ -289,9 +294,13 @@ class UnityTestCase(AutopilotTestCase):
289 except OSError:
294 except OSError:
290 pass
295 pass
291
296
297+ unity8_cli_args_list = ["--mode={}".format(mode)]
298+ if len(args) != 0:
299+ unity8_cli_args_list += args
300+
292 app_proxy = self._launch_unity_with_upstart(
301 app_proxy = self._launch_unity_with_upstart(
293 binary_path,
302 binary_path,
294− self.unity_geometry_args,
303+ self.unity_geometry_args + unity8_cli_args_list
295 )
304 )
296
305
297 self._set_proxy(app_proxy)
306 self._set_proxy(app_proxy)
tests/autopilot/unity8/shell/tests/test_lock_screen.py+1−1
@@ -135,7 +135,7 @@ class TestLockscreen(UnityTestCase):
135 :raises: TypeError if passphrase is not a string.
135 :raises: TypeError if passphrase is not a string.
136
136
137 """
137 """
138− if not isinstance(passphrase, basestring):
138+ if not isinstance(passphrase, str):
139 raise TypeError(
139 raise TypeError(
140 "'passphrase' parameter must be a string, not %r."
140 "'passphrase' parameter must be a string, not %r."
141 % type(passphrase)
141 % type(passphrase)
tests/mocks/CMakeLists.txt+1
@@ -30,6 +30,7 @@ endmacro()
30
30
31add_subdirectory(AccountsService)
31add_subdirectory(AccountsService)
32add_subdirectory(GSettings.1.0)
32add_subdirectory(GSettings.1.0)
33+add_subdirectory(indicator-service)
33add_subdirectory(libusermetrics)
34add_subdirectory(libusermetrics)
34add_subdirectory(LightDM)
35add_subdirectory(LightDM)
35add_subdirectory(Lights)
36add_subdirectory(Lights)
tests/mocks/GSettings.1.0/fake_gsettings.cpp+47−50
@@ -17,11 +17,12 @@
17#include "fake_gsettings.h"
17#include "fake_gsettings.h"
18
18
19#include <QList>
19#include <QList>
20−#include <QDebug>
21
20
22GSettingsControllerQml* GSettingsControllerQml::s_controllerInstance = 0;
21GSettingsControllerQml* GSettingsControllerQml::s_controllerInstance = 0;
23
22
24−GSettingsControllerQml::GSettingsControllerQml() {
23+GSettingsControllerQml::GSettingsControllerQml()
24+ : m_usageMode("Staged")
25+{
25}
26}
26
27
27GSettingsControllerQml::~GSettingsControllerQml() {
28GSettingsControllerQml::~GSettingsControllerQml() {
@@ -35,50 +36,32 @@ GSettingsControllerQml* GSettingsControllerQml::instance() {
35 return s_controllerInstance;
36 return s_controllerInstance;
36}
37}
37
38
38−void GSettingsControllerQml::registerSettingsObject(GSettingsQml *obj) {
39+QString GSettingsControllerQml::pictureUri() const
39− m_registeredGSettings.append(obj);
40+{
40−}
41+ return m_pictureUri;
41−
42−void GSettingsControllerQml::unRegisterSettingsObject(GSettingsQml *obj) {
43− m_registeredGSettings.removeOne(obj);
44}
42}
45
43
46−void GSettingsControllerQml::setPictureUri(const QByteArray &schemaId, const QString &str)
44+void GSettingsControllerQml::setPictureUri(const QString &str)
47{
45{
48− if (m_pictureUri[schemaId] != str) {
46+ if (str != m_pictureUri) {
49− m_pictureUri[schemaId] = str;
47+ m_pictureUri = str;
50−
51− Q_FOREACH (GSettingsQml *obj, m_registeredGSettings) {
52− if (obj->schema()->id() == schemaId) {
53− Q_EMIT obj->pictureUriChanged(str);
48+ Q_EMIT pictureUriChanged(m_pictureUri);
54− }
55− }
56 }
49 }
57}
50}
58
51
59−QString GSettingsControllerQml::pictureUri(const QByteArray &schemaId) const
52+QString GSettingsControllerQml::usageMode() const
60{
53{
61− return m_pictureUri.value(schemaId, "");
54+ return m_usageMode;
62}
55}
63
56
64−void GSettingsControllerQml::setUsageMode(const QByteArray &schemaId, const QString &str)
57+void GSettingsControllerQml::setUsageMode(const QString &usageMode)
65{
58{
66− if (m_usageMode[schemaId] != str) {
59+ if (usageMode != m_usageMode) {
67− m_usageMode[schemaId] = str;
60+ m_usageMode = usageMode;
68−
69− Q_FOREACH (GSettingsQml *obj, m_registeredGSettings) {
70− if (obj->schema()->id() == schemaId) {
71− Q_EMIT obj->usageModeChanged(str);
61+ Q_EMIT usageModeChanged(m_usageMode);
72− }
73− }
74 }
62 }
75}
63}
76
64
77−QString GSettingsControllerQml::usageMode(const QByteArray &schemaId) const
78−{
79− return m_usageMode.value(schemaId, "Staged");
80−}
81−
82GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
65GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
83}
66}
84
67
@@ -93,7 +76,6 @@ void GSettingsSchemaQml::setId(const QByteArray &id) {
93 }
76 }
94
77
95 m_id = id;
78 m_id = id;
96− Q_EMIT idChanged(id);
97}
79}
98
80
99QByteArray GSettingsSchemaQml::path() const {
81QByteArray GSettingsSchemaQml::path() const {
@@ -109,33 +91,48 @@ void GSettingsSchemaQml::setPath(const QByteArray &path) {
109 m_path = path;
91 m_path = path;
110}
92}
111
93
112−GSettingsQml::GSettingsQml(QObject *parent): QObject(parent) {
94+GSettingsQml::GSettingsQml(QObject *parent)
95+ : QObject(parent)
96+{
113 m_schema = new GSettingsSchemaQml(this);
97 m_schema = new GSettingsSchemaQml(this);
114− GSettingsControllerQml::instance()->registerSettingsObject(this);
98+ connect(GSettingsControllerQml::instance(), SIGNAL(pictureUriChanged(const QString &)),
115−}
99+ this, SIGNAL(pictureUriChanged(const QString &)));
116−
117−GSettingsQml::~GSettingsQml() {
118− GSettingsControllerQml::instance()->unRegisterSettingsObject(this);
100+ connect(GSettingsControllerQml::instance(), SIGNAL(usageModeChanged(const QString &)),
101+ this, SIGNAL(usageModeChanged(const QString &)));
119}
102}
120
103
121GSettingsSchemaQml * GSettingsQml::schema() const {
104GSettingsSchemaQml * GSettingsQml::schema() const {
122 return m_schema;
105 return m_schema;
123}
106}
124
107
125−void GSettingsQml::setPictureUri(const QString &str) {
108+QString GSettingsQml::pictureUri() const
109+{
110+ if (m_schema->id() == "org.gnome.desktop.background") {
126− GSettingsControllerQml::instance()->setPictureUri(m_schema->id(), str);
111+ return GSettingsControllerQml::instance()->pictureUri();
112+ } else {
113+ return "";
114+ }
127}
115}
128
116
129−QString GSettingsQml::pictureUri() const {
117+void GSettingsQml::setPictureUri(const QString &str)
130− return GSettingsControllerQml::instance()->pictureUri(m_schema->id());
118+{
119+ if (m_schema->id() == "org.gnome.desktop.background") {
120+ GSettingsControllerQml::instance()->setPictureUri(str);
121+ }
131}
122}
132
123
133−void GSettingsQml::setUsageMode(const QString &str) {
124+QString GSettingsQml::usageMode() const
134− GSettingsControllerQml::instance()->setUsageMode(m_schema->id(), str);
125+{
126+ if (m_schema->id() == "com.canonical.Unity8") {
127+ return GSettingsControllerQml::instance()->usageMode();
128+ } else {
129+ return "";
130+ }
135}
131}
136
132
137−QString GSettingsQml::usageMode() const {
133+void GSettingsQml::setUsageMode(const QString &usageMode)
138− return GSettingsControllerQml::instance()->usageMode(m_schema->id());
134+{
139−
135+ if (m_schema->id() == "com.canonical.Unity8") {
136+ GSettingsControllerQml::instance()->setUsageMode(usageMode);
137+ }
140}
138}
141−
tests/mocks/GSettings.1.0/fake_gsettings.h+14−20
@@ -18,14 +18,13 @@
18#define FAKE_GSETTINGS_H
18#define FAKE_GSETTINGS_H
19
19
20#include <QList>
20#include <QList>
21−#include <QHash>
22#include <QObject>
21#include <QObject>
23
22
24class GSettingsSchemaQml: public QObject
23class GSettingsSchemaQml: public QObject
25{
24{
26 Q_OBJECT
25 Q_OBJECT
27
26
28− Q_PROPERTY(QByteArray id READ id WRITE setId NOTIFY idChanged)
27+ Q_PROPERTY(QByteArray id READ id WRITE setId)
29
28
30public:
29public:
31 GSettingsSchemaQml(QObject *parent = nullptr);
30 GSettingsSchemaQml(QObject *parent = nullptr);
@@ -36,9 +35,6 @@ public:
36 QByteArray path() const;
35 QByteArray path() const;
37 void setPath(const QByteArray &path);
36 void setPath(const QByteArray &path);
38
37
39−Q_SIGNALS:
40− void idChanged(const QByteArray &id);
41−
42private:
38private:
43 QByteArray m_id;
39 QByteArray m_id;
44 QByteArray m_path;
40 QByteArray m_path;
@@ -54,16 +50,14 @@ class GSettingsQml: public QObject
54
50
55public:
51public:
56 GSettingsQml(QObject *parent = nullptr);
52 GSettingsQml(QObject *parent = nullptr);
57− ~GSettingsQml();
58
53
59 GSettingsSchemaQml * schema() const;
54 GSettingsSchemaQml * schema() const;
60−
61− void setPictureUri(const QString &str);
62 QString pictureUri() const;
55 QString pictureUri() const;
63−
64− void setUsageMode(const QString &str);
65 QString usageMode() const;
56 QString usageMode() const;
66
57
58+ void setPictureUri(const QString &str);
59+ void setUsageMode(const QString &usageMode);
60+
67Q_SIGNALS:
61Q_SIGNALS:
68 void schemaChanged();
62 void schemaChanged();
69 void pictureUriChanged(const QString&);
63 void pictureUriChanged(const QString&);
@@ -71,7 +65,6 @@ Q_SIGNALS:
71
65
72private:
66private:
73 GSettingsSchemaQml* m_schema;
67 GSettingsSchemaQml* m_schema;
74− QString m_pictureUri;
75
68
76 friend class GSettingsSchemaQml;
69 friend class GSettingsSchemaQml;
77};
70};
@@ -84,23 +77,24 @@ public:
84 static GSettingsControllerQml* instance();
77 static GSettingsControllerQml* instance();
85 ~GSettingsControllerQml();
78 ~GSettingsControllerQml();
86
79
87− void registerSettingsObject(GSettingsQml *obj);
80+ QString pictureUri() const;
88− void unRegisterSettingsObject(GSettingsQml *obj);
81+ Q_INVOKABLE void setPictureUri(const QString &str);
89
82
83+ QString usageMode() const;
90− Q_INVOKABLE void setPictureUri(const QByteArray &id, const QString &str);
84+ Q_INVOKABLE void setUsageMode(const QString &usageMode);
91− QString pictureUri(const QByteArray &id) const;
92
85
93− Q_INVOKABLE void setUsageMode(const QByteArray &id, const QString &str);
86+Q_SIGNALS:
94− QString usageMode(const QByteArray &id) const;
87+ void pictureUriChanged(const QString&);
88+ void usageModeChanged(const QString&);
95
89
96private:
90private:
97 GSettingsControllerQml();
91 GSettingsControllerQml();
98
92
93+ QString m_pictureUri;
94+ QString m_usageMode;
95+
99 static GSettingsControllerQml* s_controllerInstance;
96 static GSettingsControllerQml* s_controllerInstance;
100 QList<GSettingsQml *> m_registeredGSettings;
97 QList<GSettingsQml *> m_registeredGSettings;
101−
102− QHash<QString, QString> m_pictureUri;
103− QHash<QString, QString> m_usageMode;
104};
98};
105
99
106#endif // FAKE_GSETTINGS_H
100#endif // FAKE_GSETTINGS_H
tests/mocks/Unity/Application/MirSurfaceItem.cpp+6
@@ -47,6 +47,12 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
47{
47{
48 qDebug() << "MirSurfaceItem::MirSurfaceItem() " << this->name();
48 qDebug() << "MirSurfaceItem::MirSurfaceItem() " << this->name();
49
49
50+ setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
51+ Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
52+ Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
53+ Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
54+ Qt::ExtraButton12 | Qt::ExtraButton13);
55+
50 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
56 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
51
57
52 connect(this, &QQuickItem::focusChanged,
58 connect(this, &QQuickItem::focusChanged,
tests/mocks/Unity/Application/MirSurfaceItem.h+5
@@ -104,6 +104,11 @@ Q_SIGNALS:
104protected:
104protected:
105 void touchEvent(QTouchEvent * event) override;
105 void touchEvent(QTouchEvent * event) override;
106
106
107+ // becaue the default implementation ignores the events
108+ void mousePressEvent(QMouseEvent *) override {}
109+ void mouseMoveEvent(QMouseEvent *) override {}
110+ void mouseReleaseEvent(QMouseEvent *) override {}
111+
107private Q_SLOTS:
112private Q_SLOTS:
108 void onFocusChanged();
113 void onFocusChanged();
109 void onComponentStatusChanged(QQmlComponent::Status status);
114 void onComponentStatusChanged(QQmlComponent::Status status);
tests/mocks/Unity/fake_scope.cpp+13−2
@@ -24,6 +24,8 @@
24#include "fake_scopes.h"
24#include "fake_scopes.h"
25#include "fake_settingsmodel.h"
25#include "fake_settingsmodel.h"
26
26
27+#include <paths.h> // from unity8/include
28+
27Scope::Scope(Scopes* parent) : Scope("MockScope5", "Mock Scope", false, parent)
29Scope::Scope(Scopes* parent) : Scope("MockScope5", "Mock Scope", false, parent)
28{
30{
29}
31}
@@ -249,11 +251,11 @@ QVariantMap Scope::customizations() const
249 m["foreground-color"] = "blue";
251 m["foreground-color"] = "blue";
250 m["page-header"] = h;
252 m["page-header"] = h;
251 } else if (m_id == "MockScope4") {
253 } else if (m_id == "MockScope4") {
252− h["navigation-background"] = QUrl("../../../tests/qmltests/Dash/artwork/background.png");
254+ h["navigation-background"] = QUrl(sourceDirectory() + "tests/qmltests/Dash/artwork/background.png");
253 m["page-header"] = h;
255 m["page-header"] = h;
254 } else if (m_id == "MockScope5") {
256 } else if (m_id == "MockScope5") {
255 h["background"] = "gradient:///lightgrey/grey";
257 h["background"] = "gradient:///lightgrey/grey";
256− h["logo"] = QUrl("../../../tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg");
258+ h["logo"] = QUrl(sourceDirectory() + "tests/qmltests/Dash/tst_PageHeader/logo-ubuntu-orange.svg");
257 h["divider-color"] = "red";
259 h["divider-color"] = "red";
258 h["navigation-background"] = "color:///black";
260 h["navigation-background"] = "color:///black";
259 m["page-header"] = h;
261 m["page-header"] = h;
@@ -310,3 +312,12 @@ void Scope::setNavigationState(const QString &navigationId, bool isAltNavigation
310 Q_EMIT currentNavigationIdChanged();
312 Q_EMIT currentNavigationIdChanged();
311 }
313 }
312}
314}
315+
316+void Scope::performQuery(const QString& query)
317+{
318+ Q_EMIT queryPerformed(query);
319+ if (query.startsWith("scopes://")) {
320+ QString scopeId = query.mid(9);
321+ Q_EMIT gotoScope(scopeId);
322+ }
323+}
tests/mocks/Unity/fake_scope.h+4−2
@@ -72,7 +72,7 @@ public:
72 Q_INVOKABLE unity::shell::scopes::NavigationInterface* getNavigation(QString const& navigationId) override;
72 Q_INVOKABLE unity::shell::scopes::NavigationInterface* getNavigation(QString const& navigationId) override;
73 Q_INVOKABLE unity::shell::scopes::NavigationInterface* getAltNavigation(QString const& altNavigationId) override;
73 Q_INVOKABLE unity::shell::scopes::NavigationInterface* getAltNavigation(QString const& altNavigationId) override;
74 Q_INVOKABLE void setNavigationState(const QString &navigationId, bool isAltNavigation) override;
74 Q_INVOKABLE void setNavigationState(const QString &navigationId, bool isAltNavigation) override;
75− Q_SIGNAL void performQuery(const QString& query) override;
75+ void performQuery(const QString& query) override;
76
76
77 Status status() const override;
77 Status status() const override;
78 QVariantMap customizations() const override;
78 QVariantMap customizations() const override;
@@ -80,7 +80,9 @@ public:
80 Q_INVOKABLE void refresh() override;
80 Q_INVOKABLE void refresh() override;
81
81
82Q_SIGNALS:
82Q_SIGNALS:
83− void refreshed(); // This is not in the Interface, here for testing benefits
83+ // These are not in the Interface, here for testing benefits
84+ void refreshed();
85+ void queryPerformed(const QString& query);
84
86
85protected:
87protected:
86
88
tests/mocks/data/unity/indicators/com.canonical.indicator.mocknew file+10
@@ -0,0 +1,10 @@
1+[Indicator Service]
2+Name=indicator-mock
3+ObjectPath=/com/canonical/indicator/mock
4+Position=0
5+
6+[phone]
7+ObjectPath=/com/canonical/indicator/mock/desktop
8+
9+[desktop]
10+ObjectPath=/com/canonical/indicator/mock/desktop
tests/mocks/indicator-service/CMakeLists.txtnew file+20
@@ -0,0 +1,20 @@
1+project(mock-indicator-service)
2+pkg_search_module(GIO REQUIRED gio-2.0)
3+
4+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
5+
6+include_directories(
7+ ${CMAKE_CURRENT_SOURCE_DIR}
8+ ${GIO_INCLUDE_DIRS}
9+)
10+
11+add_executable(${MOCK_INDICATOR_SERVICE_APP}
12+ mock-indicator-service.c
13+)
14+
15+target_link_libraries(${MOCK_INDICATOR_SERVICE_APP} ${GIO_LDFLAGS})
16+
17+set_target_properties(${MOCK_INDICATOR_SERVICE_APP} PROPERTIES COMPILE_FLAGS -fPIC)
18+
19+install(TARGETS ${MOCK_INDICATOR_SERVICE_APP}
20+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
tests/mocks/indicator-service/mock-indicator-service.cnew file+261
@@ -0,0 +1,261 @@
1+/*
2+ * Copyright (C) 2015 Canonical Ltd.
3+ *
4+ * This program is free software: you can redistribute it and/or modify it
5+ * under the terms of the GNU General Public License version 3, as published
6+ * by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope that it will be useful, but
9+ * WITHOUT ANY WARRANTY; without even the implied warranties of
10+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11+ * PURPOSE. See the GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License along
14+ * with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+#include <gio/gio.h>
17+#include <stdio.h>
18+#include <stdlib.h>
19+
20+G_DEFINE_QUARK (SLIDER_VALUE, slider_value)
21+
22+typedef struct
23+{
24+ GSimpleActionGroup *actions;
25+ GMenu *menu;
26+
27+ guint actions_export_id;
28+ guint menu_export_id;
29+ int action_delay;
30+} IndicatorTestService;
31+
32+static void
33+bus_acquired (GDBusConnection *connection,
34+ const gchar *name,
35+ gpointer user_data)
36+{
37+ (void) name;
38+ IndicatorTestService *indicator = user_data;
39+ GError *error = NULL;
40+
41+ indicator->actions_export_id = g_dbus_connection_export_action_group (connection,
42+ "/com/canonical/indicator/mock",
43+ G_ACTION_GROUP (indicator->actions),
44+ &error);
45+ if (indicator->actions_export_id == 0)
46+ {
47+ g_warning ("cannot export action group: %s", error->message);
48+ g_error_free (error);
49+ return;
50+ }
51+
52+ indicator->menu_export_id = g_dbus_connection_export_menu_model (connection,
53+ "/com/canonical/indicator/mock/desktop",
54+ G_MENU_MODEL (indicator->menu),
55+ &error);
56+ if (indicator->menu_export_id == 0)
57+ {
58+ g_warning ("cannot export menu: %s", error->message);
59+ g_error_free (error);
60+ return;
61+ }
62+}
63+
64+static void
65+name_lost (GDBusConnection *connection,
66+ const gchar *name,
67+ gpointer user_data)
68+{
69+ (void) name;
70+ IndicatorTestService *indicator = user_data;
71+
72+ if (indicator->actions_export_id)
73+ g_dbus_connection_unexport_action_group (connection, indicator->actions_export_id);
74+
75+ if (indicator->menu_export_id)
76+ g_dbus_connection_unexport_menu_model (connection, indicator->menu_export_id);
77+}
78+
79+static void
80+activate_show (GSimpleAction *action,
81+ GVariant *parameter,
82+ gpointer user_data)
83+{
84+ (void) action;
85+ (void) parameter;
86+ (void) user_data;
87+ g_message ("showing");
88+}
89+
90+static gboolean
91+actual_switch (gpointer user_data)
92+{
93+ GSimpleAction *action = user_data;
94+
95+ GVariant* v = g_action_get_state(G_ACTION(action));
96+ gboolean state = g_variant_get_boolean (v);
97+ GVariant *new_state = g_variant_new_boolean (state == TRUE ? FALSE : TRUE);
98+
99+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
100+
101+ g_variant_unref (v);
102+ g_message ("switching");
103+ return FALSE;
104+}
105+
106+static void
107+activate_switch (GSimpleAction *action,
108+ GVariant *parameter,
109+ gpointer user_data)
110+{
111+ (void) action;
112+ (void) parameter;
113+
114+ IndicatorTestService *indicator = user_data;
115+
116+ g_timeout_add(indicator->action_delay, actual_switch, action);
117+ g_message ("switch delay");
118+}
119+
120+static gboolean
121+actual_slide (gpointer user_data)
122+{
123+ GSimpleAction *action = user_data;
124+
125+ GVariant* new_state = g_object_get_qdata (G_OBJECT (action), slider_value_quark ());
126+
127+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
128+
129+ g_message ("switching");
130+ return FALSE;
131+}
132+
133+void change_slider (GSimpleAction *action,
134+ GVariant *value,
135+ gpointer user_data)
136+{
137+ IndicatorTestService *indicator = user_data;
138+
139+ g_object_set_qdata (G_OBJECT (action), slider_value_quark (), g_variant_ref(value));
140+
141+ g_timeout_add(indicator->action_delay, actual_slide, action);
142+ g_message ("slide delay %.03f", g_variant_get_double(value));
143+}
144+
145+int
146+main (int argc, char **argv)
147+{
148+ IndicatorTestService indicator = { 0 };
149+ indicator.action_delay = -1;
150+ GMenuItem *item;
151+ GMenu *submenu;
152+ GActionEntry entries[] = {
153+ { "_header", NULL, NULL, "{'title': <'Test'>,"
154+ " 'label': <'Test'>,"
155+ " 'visible': <true>,"
156+ " 'accessible-desc': <'Test indicator'> }", NULL },
157+ { "action.show", activate_show, NULL, NULL, NULL },
158+ { "action.switch", activate_switch, NULL, "true", NULL },
159+ { "action.checkbox", activate_switch, NULL, "true", NULL },
160+ { "action.accessPoint", activate_switch, NULL, "false", NULL },
161+ { "action.slider", NULL, NULL, "0.5", change_slider }
162+ };
163+ GMainLoop *loop;
164+
165+ int help = 0;
166+ if (argc > 1)
167+ {
168+ int i;
169+ for (i = 1; i < argc; i++) {
170+ const char *arg = argv[i];
171+
172+ if (arg[0] == '-') {
173+ switch (arg[1])
174+ {
175+ case 't':
176+ {
177+ arg += 2;
178+ if (!arg[0] && i < argc-1) {
179+ i++;
180+ int delay = -1;
181+
182+ if (sscanf(argv[i], "%d", &delay) == 1) {
183+ indicator.action_delay = delay;
184+ } else {
185+ printf("Invalid action delay value: %s\n", argv[i]);
186+ help = 1;
187+ }
188+ } else {
189+ printf("Invalid action delay value: %s\n", argv[i]);
190+ help = 1;
191+ }
192+ break;
193+ }
194+ case 'h':
195+ help = 1;
196+ break;
197+ }
198+ }
199+ }
200+ }
201+
202+ if (help) {
203+ printf("Usage: %s [<options>]\n"
204+ " -t DELAY Action activation delay\n"
205+ " -h Show this help text\n"
206+ , argv[0]);
207+ return 0;
208+ }
209+
210+ indicator.actions = g_simple_action_group_new ();
211+ g_action_map_add_action_entries (G_ACTION_MAP (indicator.actions), entries, G_N_ELEMENTS (entries), &indicator);
212+
213+ submenu = g_menu_new ();
214+ g_menu_append (submenu, "Show", "indicator.action.show");
215+
216+ // Switch
217+ item = g_menu_item_new("Switch", "indicator.action.switch");
218+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.switch");
219+ g_menu_append_item(submenu, item);
220+
221+ // Checkbox
222+ item = g_menu_item_new("Checkbox", "indicator.action.checkbox");
223+ g_menu_append_item(submenu, item);
224+
225+ // Slider
226+ item = g_menu_item_new("Slider", "indicator.action.slider");
227+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.slider");
228+ g_menu_append_item(submenu, item);
229+
230+ // Access Point
231+ item = g_menu_item_new("Access Point", "indicator.action.accessPoint");
232+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "unity.widgets.systemsettings.tablet.accesspoint");
233+ g_menu_append_item(submenu, item);
234+
235+
236+ item = g_menu_item_new (NULL, "indicator._header");
237+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.root");
238+ g_menu_item_set_submenu (item, G_MENU_MODEL (submenu));
239+ indicator.menu = g_menu_new ();
240+ g_menu_append_item (indicator.menu, item);
241+
242+ g_bus_own_name (G_BUS_TYPE_SESSION,
243+ "com.canonical.indicator.mock",
244+ G_BUS_NAME_OWNER_FLAGS_NONE,
245+ bus_acquired,
246+ NULL,
247+ name_lost,
248+ &indicator,
249+ NULL);
250+
251+ loop = g_main_loop_new (NULL, FALSE);
252+ g_main_loop_run (loop);
253+
254+ g_object_unref (submenu);
255+ g_object_unref (item);
256+ g_object_unref (indicator.actions);
257+ g_object_unref (indicator.menu);
258+ g_object_unref (loop);
259+
260+ return 1;
261+}
tests/plugins/Unity/Indicators/indicatorsmanagertest.cpp−2
@@ -31,13 +31,11 @@ private Q_SLOTS:
31
31
32 void initTestCase()
32 void initTestCase()
33 {
33 {
34− setenv("UNITY_TEST_ENV", "1", 1);
35 setenv("XDG_DATA_DIRS", (sourceDirectory() + "/tests/data").toLatin1().data(), 1);
34 setenv("XDG_DATA_DIRS", (sourceDirectory() + "/tests/data").toLatin1().data(), 1);
36 }
35 }
37
36
38 void cleanupTestCase()
37 void cleanupTestCase()
39 {
38 {
40− unsetenv("UNITY_TEST_ENV");
41 }
39 }
42
40
43 /*
41 /*
tests/plugins/Unity/Indicators/indicatorsmodeltest.cpp−2
@@ -32,13 +32,11 @@ private Q_SLOTS:
32
32
33 void initTestCase()
33 void initTestCase()
34 {
34 {
35− setenv("UNITY_TEST_ENV", "1", 1);
36 setenv("XDG_DATA_DIRS", (sourceDirectory() + "/tests/data").toLatin1().data(), 1);
35 setenv("XDG_DATA_DIRS", (sourceDirectory() + "/tests/data").toLatin1().data(), 1);
37 }
36 }
38
37
39 void cleanupTestCase()
38 void cleanupTestCase()
40 {
39 {
41− unsetenv("UNITY_TEST_ENV");
42 }
40 }
43
41
44 /*
42 /*
tests/plugins/Unity/Launcher/launchermodeltest.cpp+57
@@ -400,6 +400,63 @@ private Q_SLOTS:
400 QCOMPARE(launcherModel->get(index)->count(), 55);
400 QCOMPARE(launcherModel->get(index)->count(), 55);
401 }
401 }
402
402
403+ void testCountEmblemAddsRemovesItem_data() {
404+ QTest::addColumn<bool>("isPinned");
405+ QTest::addColumn<bool>("isRunning");
406+ QTest::addColumn<bool>("startWhenVisible");
407+ QTest::newRow("not pinned, not running") << false << false << false;
408+ QTest::newRow("pinned, not running") << true << false << false;
409+ QTest::newRow("not pinned, not running, starting from notification") << false << false << true;
410+ QTest::newRow("pinned, not running, starting from notification") << true << false << true;
411+ QTest::newRow("not pinned, running") << false << true << false;
412+ QTest::newRow("pinned, running") << true << true << false;
413+ }
414+
415+ void testCountEmblemAddsRemovesItem() {
416+ QFETCH(bool, isPinned);
417+ QFETCH(bool, isRunning);
418+ QFETCH(bool, startWhenVisible);
419+
420+ // Make sure item is here as expected after init() and that count is not visible
421+ int index = launcherModel->findApplication("abs-icon");
422+ QCOMPARE(index == -1, false);
423+ QCOMPARE(launcherModel->get(index)->countVisible(), false);
424+
425+ // Pin if we need to
426+ if (isPinned) {
427+ launcherModel->pin("abs-icon");
428+ }
429+ QCOMPARE(launcherModel->get(0)->pinned(), isPinned);
430+
431+ // Stop it if we need to
432+ if (!isRunning) {
433+ appManager->stopApplication("abs-icon");
434+ }
435+ QCOMPARE(launcherModel->findApplication("abs-icon") >= 0, isRunning || isPinned);
436+
437+
438+ // set the count emblem to visible
439+ QDBusInterface interface("com.canonical.Unity.Launcher", "/com/canonical/Unity/Launcher/abs_2Dicon", "org.freedesktop.DBus.Properties");
440+ interface.call("Set", "com.canonical.Unity.Launcher.Item", "count", QVariant::fromValue(QDBusVariant(55)));
441+ interface.call("Set", "com.canonical.Unity.Launcher.Item", "countVisible", QVariant::fromValue(QDBusVariant(true)));
442+
443+ // Make sure item is here and that count is visible
444+ index = launcherModel->findApplication("abs-icon");
445+ QCOMPARE(index == -1, false);
446+ QCOMPARE(launcherModel->get(index)->countVisible(), true);
447+
448+ if (!isRunning && startWhenVisible) {
449+ appManager->addApplication(new MockApp("abs-icon"));
450+ }
451+
452+ // Hide count emblem again
453+ interface.call("Set", "com.canonical.Unity.Launcher.Item", "countVisible", QVariant::fromValue(QDBusVariant(false)));
454+
455+ // Make sure item is shown/hidden as expected
456+ index = launcherModel->findApplication("abs-icon");
457+ QCOMPARE(index == -1, !isRunning && !isPinned && !startWhenVisible);
458+ }
459+
403 void testRefreshAfterDeletedDesktopFiles_data() {
460 void testRefreshAfterDeletedDesktopFiles_data() {
404 QTest::addColumn<bool>("deleted");
461 QTest::addColumn<bool>("deleted");
405 QTest::newRow("have .desktop files") << false;
462 QTest::newRow("have .desktop files") << false;
tests/qmltests/Components/tst_Dialogs.qml+4−2
@@ -79,7 +79,7 @@ Rectangle {
79 Column {
79 Column {
80 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
80 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
81 spacing: units.gu(1)
81 spacing: units.gu(1)
82− Button { text: "Power dialog"; onClicked: { testCase.showPowerDialog(); } }
82+ Button { text: "Power dialog"; onClicked: { testCase.test_showPowerDialog(); } }
83 Button { text: "Logout Requested"; onClicked: { fakeUnitySession.logoutRequested(); } }
83 Button { text: "Logout Requested"; onClicked: { fakeUnitySession.logoutRequested(); } }
84 Button { text: "Shutdown Requested"; onClicked: { fakeUnitySession.shutdownRequested(); } }
84 Button { text: "Shutdown Requested"; onClicked: { fakeUnitySession.shutdownRequested(); } }
85 Button { text: "Reboot Requested"; onClicked: { fakeUnitySession.rebootRequested(); } }
85 Button { text: "Reboot Requested"; onClicked: { fakeUnitySession.rebootRequested(); } }
@@ -96,9 +96,11 @@ Rectangle {
96 name: "Dialogs"
96 name: "Dialogs"
97 when: windowShown
97 when: windowShown
98
98
99− function showPowerDialog() {
99+ function test_showPowerDialog() {
100 var dialogsPrivate = findInvisibleChild(dialogs, "dialogsPrivate");
100 var dialogsPrivate = findInvisibleChild(dialogs, "dialogsPrivate");
101 dialogsPrivate.showPowerDialog();
101 dialogsPrivate.showPowerDialog();
102+ var dialogLoader = findInvisibleChild(dialogs, "dialogLoader");
103+ tryCompare(dialogLoader.item, "focus", true);
102 }
104 }
103 }
105 }
104}
106}
tests/qmltests/Dash/tst_Dash.qml+49−1
@@ -315,7 +315,7 @@ Item {
315
315
316 var scopesList = findChild(dash, "scopesList");
316 var scopesList = findChild(dash, "scopesList");
317 spy.target = scopesList.scope;
317 spy.target = scopesList.scope;
318− spy.signalName = "performQuery";
318+ spy.signalName = "queryPerformed";
319
319
320 // Click on the store
320 // Click on the store
321 var scopesListPageHeader = findChild(scopesList, "pageHeader");
321 var scopesListPageHeader = findChild(scopesList, "pageHeader");
@@ -517,5 +517,53 @@ Item {
517 tryCompare(dashTempScopeItem, "x", dash.width);
517 tryCompare(dashTempScopeItem, "x", dash.width);
518 tryCompare(dashTempScopeItem, "visible", false);
518 tryCompare(dashTempScopeItem, "visible", false);
519 }
519 }
520+
521+ function test_UriDispatcher()
522+ {
523+ var dashContentList = findChild(dash, "dashContentList");
524+
525+ UriHandler.opened("scopes://clickscope");
526+ tryCompare(dashContentList, "currentIndex", 1);
527+
528+ // Show the manage dash
529+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
530+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
531+ tryCompare(bottomEdgeController, "progress", 1);
532+
533+ // UriHandler changes to a scope and closes the manage scopes
534+ UriHandler.opened("scopes://MockScope1");
535+ tryCompare(dashContentList, "currentIndex", 0);
536+ tryCompare(bottomEdgeController, "progress", 0);
537+
538+ // Show a preview
539+ var scopeLoader0 = findChild(dashContent, "scopeLoader0");
540+ var dashCategory0 = findChild(scopeLoader0, "dashCategory0");
541+ var delegate0 = findChild(dashCategory0, "delegate0");
542+ mouseClick(delegate0);
543+ tryCompare(dashContent, "subPageShown", true)
544+
545+ // UriHandler changes to a scope and closes the manage scopes
546+ UriHandler.opened("scopes://clickscope");
547+ tryCompare(dashContentList, "currentIndex", 1);
548+ tryCompare(dashContent, "subPageShown", false);
549+
550+ // Go to a temp scope
551+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
552+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
553+ tryCompare(bottomEdgeController, "progress", 1);
554+ var nonfavScopesListCategory = findChild(dash, "scopesListCategoryother");
555+ var nonfavScopesListCategoryList = findChild(nonfavScopesListCategory, "scopesListCategoryInnerList");
556+ tryCompare(nonfavScopesListCategoryList, "currentIndex", 0);
557+ mouseClick(nonfavScopesListCategoryList.currentItem);
558+ var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
559+ tryCompare(dashTempScopeItem, "x", 0);
560+ tryCompare(dashTempScopeItem, "visible", true);
561+
562+ // UriHandler changes to a scope and closes the temp scope
563+ UriHandler.opened("scopes://MockScope1");
564+ tryCompare(dashContentList, "currentIndex", 0);
565+ tryCompare(dashTempScopeItem, "x", dashTempScopeItem.width);
566+ tryCompare(dashTempScopeItem, "visible", false);
567+ }
520 }
568 }
521}
569}
tests/qmltests/Dash/tst_GenericScopeView.qml+1−1
@@ -206,7 +206,7 @@ Item {
206 var header = findChild(genericScopeView, "dashSectionHeader1");
206 var header = findChild(genericScopeView, "dashSectionHeader1");
207
207
208 spy.target = genericScopeView.scope;
208 spy.target = genericScopeView.scope;
209− spy.signalName = "performQuery";
209+ spy.signalName = "queryPerformed";
210
210
211 mouseClick(header);
211 mouseClick(header);
212
212
tests/qmltests/Dash/tst_PreviewListView.qml+1−1
@@ -109,7 +109,7 @@ Rectangle {
109
109
110 var image = findChild(header, "titleImage");
110 var image = findChild(header, "titleImage");
111 verify(image, "Could not find the title image.");
111 verify(image, "Could not find the title image.");
112− compare(image.source, Qt.resolvedUrl("../Dash/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
112+ compare(image.source, Qt.resolvedUrl("tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
113 }
113 }
114 }
114 }
115}
115}
tests/qmltests/Panel/Indicators/tst_MenuItemFactory.qml+5−1
@@ -230,7 +230,7 @@ Item {
230 compare(loader.item.value, data.manualValue, "Slider value does not match manual set value");
230 compare(loader.item.value, data.manualValue, "Slider value does not match manual set value");
231
231
232 menuData.actionState = data.value2;
232 menuData.actionState = data.value2;
233− compare(loader.item.value, data.value2, "Value does not match new data");
233+ tryCompare(loader.item, "value", data.value2, 10000, "Value does not match new data");
234
234
235 menuData.actionState = undefined;
235 menuData.actionState = undefined;
236 compare(loader.item.value, data.value2, "Undefined state should not update slider value");
236 compare(loader.item.value, data.value2, "Undefined state should not update slider value");
@@ -819,6 +819,10 @@ Item {
819 loader.data = menuData;
819 loader.data = menuData;
820 loader.sourceComponent = factory.load(menuData);
820 loader.sourceComponent = factory.load(menuData);
821
821
822+ var sync = findInvisibleChild(loader.item, "sync");
823+ verify(sync);
824+ sync.syncTimeout = 500;
825+
822 compare(loader.item.checked, false, "Loader did not load check state");
826 compare(loader.item.checked, false, "Loader did not load check state");
823 mouseClick(loader.item,
827 mouseClick(loader.item,
824 loader.item.width / 2, loader.item.height / 2);
828 loader.item.width / 2, loader.item.height / 2);
tests/qmltests/Panel/tst_Panel.qml+52
@@ -390,5 +390,57 @@ IndicatorTest {
390 tap(panel, touchPosX, touchPosY);
390 tap(panel, touchPosX, touchPosY);
391 compare(backgroundPressedSpy.count, 2);
391 compare(backgroundPressedSpy.count, 2);
392 }
392 }
393+
394+ /*
395+ Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1439318
396+ When the panel is in fullscreen mode and the user taps near the top edge,
397+ the panel should take no action and the tap should reach the item behind the
398+ panel.
399+ */
400+ function test_tapNearTopEdgeWithPanelInFullscreenMode() {
401+ var indicatorArea = findChild(panel, "indicatorArea");
402+ verify(indicatorArea);
403+ var panelPriv = findInvisibleChild(panel, "panelPriv");
404+ verify(panelPriv);
405+
406+ panel.fullscreenMode = true;
407+ // wait until if finishes hiding itself
408+ tryCompare(indicatorArea, "y", -panelPriv.indicatorHeight);
409+
410+ compare(panel.indicators.shown, false);
411+ verify(panel.indicators.fullyClosed);
412+
413+ // tap near the very top of the screen
414+ tap(itemArea, itemArea.width / 2, 2);
415+
416+ // the tap should have reached the item behind the panel
417+ compare(backgroundPressedSpy.count, 2);
418+
419+ // give it a couple of event loop iterations for any animations etc to kick in
420+ wait(50);
421+
422+ compare(panel.indicators.shown, false);
423+ verify(panel.indicators.fullyClosed);
424+ }
425+
426+ function test_openAndClosePanelWithMouseClicks() {
427+ compare(panel.indicators.shown, false);
428+ verify(panel.indicators.fullyClosed);
429+
430+ mouseClick(panel.indicators,
431+ panel.indicators.width / 2,
432+ panel.indicators.minimizedPanelHeight / 2);
433+
434+ compare(panel.indicators.shown, true);
435+ tryCompare(panel.indicators, "fullyOpened", true);
436+
437+ var handle = findChild(panel.indicators, "handle");
438+ verify(handle);
439+
440+ mouseClick(handle);
441+
442+ compare(panel.indicators.shown, false);
443+ tryCompare(panel.indicators, "fullyClosed", true);
444+ }
393 }
445 }
394}
446}
tests/qmltests/Stages/tst_SurfaceContainer.qml+32−5
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2014 Canonical Ltd.
2+ * Copyright 2014-2015 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import QtTest 1.0
18import QtTest 1.0
19−import Unity.Test 0.1 as UT
19+import Unity.Test 0.1
20import ".."
20import ".."
21import "../../../qml/Stages"
21import "../../../qml/Stages"
22import Ubuntu.Components 0.1
22import Ubuntu.Components 0.1
@@ -32,6 +32,8 @@ Rectangle {
32 id: surfaceContainerComponent
32 id: surfaceContainerComponent
33 SurfaceContainer {
33 SurfaceContainer {
34 anchors.fill: parent
34 anchors.fill: parent
35+ orientation: Qt.PortraitOrientation
36+ interactive: interactiveCheckbox.checked
35 }
37 }
36 }
38 }
37 Loader {
39 Loader {
@@ -85,6 +87,12 @@ Rectangle {
85 CheckBox {id: fullscreenCheckbox; checked: true; }
87 CheckBox {id: fullscreenCheckbox; checked: true; }
86 Label { text: "fullscreen" }
88 Label { text: "fullscreen" }
87 }
89 }
90+ Row {
91+ anchors { left: parent.left; right: parent.right }
92+ CheckBox {id: interactiveCheckbox; checked: true; }
93+ Label { text: "interactive" }
94+ }
95+ MouseTouchEmulationCheckbox {}
88 }
96 }
89 }
97 }
90
98
@@ -94,7 +102,7 @@ Rectangle {
94 signalName: "surfaceDestroyed"
102 signalName: "surfaceDestroyed"
95 }
103 }
96
104
97− UT.UnityTestCase {
105+ UnityTestCase {
98 id: testCase
106 id: testCase
99 name: "SurfaceContainer"
107 name: "SurfaceContainer"
100 when: windowShown
108 when: windowShown
@@ -110,6 +118,8 @@ Rectangle {
110
118
111 tryCompare(surfaceContainerLoader.item, "surface", null);
119 tryCompare(surfaceContainerLoader.item, "surface", null);
112 surfaceSpy.clear();
120 surfaceSpy.clear();
121+
122+ interactiveCheckbox.checked = true;
113 }
123 }
114
124
115 /*
125 /*
@@ -145,14 +155,13 @@ Rectangle {
145 surfaceContainer.surface.touchPressCount = 0;
155 surfaceContainer.surface.touchPressCount = 0;
146 surfaceContainer.surface.touchReleaseCount = 0;
156 surfaceContainer.surface.touchReleaseCount = 0;
147
157
148− surfaceContainer.interactive = true;
149 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
158 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
150
159
151 // surface got touches as the surfaceContainer is interactive
160 // surface got touches as the surfaceContainer is interactive
152 compare(surfaceContainer.surface.touchPressCount, 1)
161 compare(surfaceContainer.surface.touchPressCount, 1)
153 compare(surfaceContainer.surface.touchReleaseCount, 1);
162 compare(surfaceContainer.surface.touchReleaseCount, 1);
154
163
155− surfaceContainer.interactive = false;
164+ interactiveCheckbox.checked = false;
156 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
165 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
157
166
158 // surface shouldn't get the touches from the second tap as the surfaceContainer
167 // surface shouldn't get the touches from the second tap as the surfaceContainer
@@ -160,5 +169,23 @@ Rectangle {
160 compare(surfaceContainer.surface.touchPressCount, 1)
169 compare(surfaceContainer.surface.touchPressCount, 1)
161 compare(surfaceContainer.surface.touchReleaseCount, 1);
170 compare(surfaceContainer.surface.touchReleaseCount, 1);
162 }
171 }
172+
173+ function test_surfaceGetsActiveFocusOnMousePress() {
174+ surfaceCheckbox.checked = true;
175+ verify(surfaceContainer.surface !== null);
176+
177+ compare(surfaceContainer.surface.activeFocus, false);
178+ mouseClick(surfaceContainer);
179+ compare(surfaceContainer.surface.activeFocus, true);
180+ }
181+
182+ function test_surfaceGetsActiveFocusOnTap() {
183+ surfaceCheckbox.checked = true;
184+ verify(surfaceContainer.surface !== null);
185+
186+ compare(surfaceContainer.surface.activeFocus, false);
187+ tap(surfaceContainer);
188+ compare(surfaceContainer.surface.activeFocus, true);
189+ }
163 }
190 }
164}
191}
tests/qmltests/Tutorial/tst_Tutorial.qml+22−5
@@ -17,6 +17,7 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import QtTest 1.0
18import QtTest 1.0
19import AccountsService 0.1
19import AccountsService 0.1
20+import GSettings 1.0
20import LightDM 0.1 as LightDM
21import LightDM 0.1 as LightDM
21import Ubuntu.Components 1.1
22import Ubuntu.Components 1.1
22import Unity.Application 0.1
23import Unity.Application 0.1
@@ -45,6 +46,11 @@ Item {
45 }
46 }
46 }
47 }
47
48
49+ GSettings {
50+ id: unity8Settings
51+ schema.id: "com.canonical.Unity8"
52+ }
53+
48 Component.onCompleted: {
54 Component.onCompleted: {
49 // must set the mock mode before loading the Shell
55 // must set the mock mode before loading the Shell
50 LightDM.Greeter.mockMode = "single-pin";
56 LightDM.Greeter.mockMode = "single-pin";
@@ -112,6 +118,7 @@ Item {
112
118
113 function init() {
119 function init() {
114 tryCompare(shell, "enabled", true); // enabled by greeter when ready
120 tryCompare(shell, "enabled", true); // enabled by greeter when ready
121+ unity8Settings.usageMode = "Staged";
115 AccountsService.demoEdges = false;
122 AccountsService.demoEdges = false;
116 AccountsService.demoEdges = true;
123 AccountsService.demoEdges = true;
117 swipeAwayGreeter();
124 swipeAwayGreeter();
@@ -185,17 +192,19 @@ Item {
185 }
192 }
186
193
187 function checkRightEdge() {
194 function checkRightEdge() {
195+ if (unity8Settings.usageMode === "Staged") {
188− touchFlick(shell, shell.width, halfHeight, halfWidth, halfHeight);
196+ touchFlick(shell, shell.width, halfHeight, halfWidth, halfHeight);
189
197
190− var stage = findChild(shell, "stage");
198+ var stage = findChild(shell, "stage");
191− var spreadView = findChild(stage, "spreadView");
199+ var spreadView = findChild(stage, "spreadView");
192− tryCompare(spreadView, "phase", 0);
200+ tryCompare(spreadView, "phase", 0);
201+ }
193 }
202 }
194
203
195 function checkBottomEdge() {
204 function checkBottomEdge() {
196 // Can't actually check effect of swipe, since dash isn't really loaded
205 // Can't actually check effect of swipe, since dash isn't really loaded
197 var applicationsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
206 var applicationsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
198− tryCompare(applicationsDisplayLoader.item, "interactive", false);
207+ tryCompare(applicationsDisplayLoader, "interactive", false);
199 }
208 }
200
209
201 function checkFinished() {
210 function checkFinished() {
@@ -256,6 +265,14 @@ Item {
256 goToPage(null);
265 goToPage(null);
257 }
266 }
258
267
268+ function test_walkthroughOnDesktop() {
269+ unity8Settings.usageMode = "Windowed";
270+ var page = goToPage("tutorialLeftFinish");
271+ var tick = findChild(page, "tick");
272+ tap(tick);
273+ checkFinished();
274+ }
275+
259 function test_launcherShortDrag() {
276 function test_launcherShortDrag() {
260 // goToPage does a normal launcher pull. But here we want to test
277 // goToPage does a normal launcher pull. But here we want to test
261 // just barely pulling the launcher out and letting go (i.e. not
278 // just barely pulling the launcher out and letting go (i.e. not
tests/qmltests/tst_Shell.qml+11−6
@@ -87,7 +87,7 @@ Rectangle {
87 }
87 }
88 StateChangeScript {
88 StateChangeScript {
89 script: {
89 script: {
90− GSettingsController.setUsageMode("com.canonical.Unity8", "Staged")
90+ GSettingsController.setUsageMode("Staged")
91 }
91 }
92 }
92 }
93 },
93 },
@@ -100,7 +100,7 @@ Rectangle {
100 }
100 }
101 StateChangeScript {
101 StateChangeScript {
102 script: {
102 script: {
103− GSettingsController.setUsageMode("com.canonical.Unity8", "Staged")
103+ GSettingsController.setUsageMode("Staged")
104 }
104 }
105 }
105 }
106 },
106 },
@@ -117,7 +117,7 @@ Rectangle {
117 }
117 }
118 StateChangeScript {
118 StateChangeScript {
119 script: {
119 script: {
120− GSettingsController.setUsageMode("com.canonical.Unity8", "Windowed")
120+ GSettingsController.setUsageMode("Windowed")
121 }
121 }
122 }
122 }
123 }
123 }
@@ -1034,6 +1034,11 @@ Rectangle {
1034 tryCompare(ApplicationManager, "focusedApplicationId", "gallery-app");
1034 tryCompare(ApplicationManager, "focusedApplicationId", "gallery-app");
1035 compare(wizard.shown, false);
1035 compare(wizard.shown, false);
1036 compare(tutorial.running, false);
1036 compare(tutorial.running, false);
1037+ tryCompare(AccountsService, "demoEdges", false);
1038+ tryCompare(Wizard.System, "wizardEnabled", false);
1039+
1040+ var tutorialLeft = findChild(tutorial, "tutorialLeft");
1041+ compare(tutorialLeft, null); // should be destroyed with tutorial
1037 }
1042 }
1038
1043
1039 function test_tapOnRightEdgeReachesApplicationSurface() {
1044 function test_tapOnRightEdgeReachesApplicationSurface() {
@@ -1131,10 +1136,10 @@ Rectangle {
1131 var buttonShowDashHome = findChild(launcher, "buttonShowDashHome");
1136 var buttonShowDashHome = findChild(launcher, "buttonShowDashHome");
1132 var startPos = buttonShowDashHome.mapToItem(shell,
1137 var startPos = buttonShowDashHome.mapToItem(shell,
1133 buttonShowDashHome.width * 0.2,
1138 buttonShowDashHome.width * 0.2,
1134− buttonShowDashHome.height * 0.2);
1139+ buttonShowDashHome.height * 0.8);
1135 var endPos = buttonShowDashHome.mapToItem(shell,
1140 var endPos = buttonShowDashHome.mapToItem(shell,
1136 buttonShowDashHome.width * 0.8,
1141 buttonShowDashHome.width * 0.8,
1137− buttonShowDashHome.height * 0.8);
1142+ buttonShowDashHome.height * 0.2);
1138 touchFlick(shell, startPos.x, startPos.y, endPos.x, endPos.y);
1143 touchFlick(shell, startPos.x, startPos.y, endPos.x, endPos.y);
1139 }
1144 }
1140
1145
@@ -1167,7 +1172,7 @@ Rectangle {
1167 loadShell("phone");
1172 loadShell("phone");
1168 swipeAwayGreeter();
1173 swipeAwayGreeter();
1169 AccountsService.backgroundFile = data.accounts;
1174 AccountsService.backgroundFile = data.accounts;
1170− GSettingsController.setPictureUri("org.gnome.desktop.background", data.gsettings);
1175+ GSettingsController.setPictureUri(data.gsettings);
1171
1176
1172 if (data.output === "defaultBackground") {
1177 if (data.output === "defaultBackground") {
1173 tryCompare(shell, "background", shell.defaultBackground);
1178 tryCompare(shell, "background", shell.defaultBackground);