on xenial help sign in
Merged trunk
commit27640514d30dfab9f00d07a051b4c0d1192bf01a authorMarcus Tomlinson <marcus.tomlinson@canonical.com> dateTue 16 Sep 2014, 13:48 (12 years ago) parentb0c4cd7bd05eec
70 files changed+1168−491
debian/changelog+62 plugins/Dash/CardCreator.js+2−2 plugins/Dash/listviewwithpageheader.cpp+7−4 plugins/Dash/listviewwithpageheader.h+1−1 plugins/Powerd/Powerd.cpp+16−2 plugins/Powerd/Powerd.h+8−1 plugins/Powerd/Powerd.qmltypes+3−3 plugins/Unity/DashCommunicator/dashcommunicator.cpp+2−2 plugins/Unity/DashCommunicator/dashcommunicator.h+1−1 plugins/Unity/DashCommunicator/dashcommunicatorservice.h+1−1 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp+2−2 plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h+2−2 plugins/Unity/Launcher/CMakeLists.txt+1−1 plugins/Unity/Launcher/backend/launcherbackend.cpp+7 plugins/Unity/Launcher/launcheritem.cpp+1 plugins/Unity/Launcher/launchermodel.cpp+3 po/ca.po+8−6 po/de.po+7−7 po/gd.po+57−54 po/ku.po+345 po/sv.po+56−52 qml/Components/Background.qml+1−1 qml/Dash/CardTool.qml+7−10 qml/Dash/Dash.qml+12−1 qml/Dash/DashApplication.qml−6 qml/Dash/GenericScopeView.qml+1−2 qml/Dash/PageHeader.qml+19−14 qml/Dash/PreviewListView.qml+2−2 qml/Dash/Previews/PreviewPayments.qml+2 qml/Dash/ScopesOverview.qml+6 qml/Dash/graphics/checkers.png qml/Dash/graphics/pixel.png qml/Notifications/Notification.qml+132−46 qml/Notifications/NotificationMenuItemFactory.qml+4 qml/Notifications/Notifications.qml+1−1 qml/Panel/Indicators/IndicatorsLight.qml+4−7 qml/Shell.qml+9−20 qml/Stages/ApplicationWindow.qml+3−2 qml/Stages/PhoneStage.qml+6−1 qml/Stages/TabletStage.qml+5 qml/Stages/TransformedTabletSpreadDelegate.qml+2−1 run_on_device.sh+43−41 src/Dash/main.cpp+1 src/main.cpp+1 tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+4−2 tests/autopilot/unity8/process_helpers.py+12−17 tests/autopilot/unity8/shell/emulators/greeter.py+4−1 tests/autopilot/unity8/shell/tests/test_lock_screen.py+8−9 tests/autopilot/unity8/shell/tests/test_notifications.py+61−97 tests/mocks/Powerd/Powerd.cpp+15−1 tests/mocks/Powerd/Powerd.h+8−1 tests/mocks/Powerd/Powerd.qmltypes+3−3 tests/mocks/Ubuntu/Payments/MockPayments.cpp+10−7 tests/mocks/Ubuntu/Payments/MockPayments.h+1 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp+2−2 tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h+2−2 tests/mocks/Unity/fake_scope.cpp+1−1 tests/plugins/Dash/cardcreator/2.res+2−2 tests/plugins/Dash/cardcreator/5.res+2−2 tests/plugins/Dash/cardcreator/6.res+3−3 tests/plugins/Dash/cardcreator/7.res+3−3 tests/plugins/Unity/Launcher/CMakeLists.txt+1−1 tests/qmltests/Dash/Previews/tst_PreviewPayments.qml+49−9 tests/qmltests/Dash/tst_Dash.qml+9−2 tests/qmltests/Dash/tst_PreviewListView.qml+29−1 tests/qmltests/Notifications/tst_Notifications.qml+59−17 tests/qmltests/tst_Shell.qml+14−7 tools/registry-tracker.cpp+6 tools/scopetool.cpp+3 tools/unlock-device+4−5
debian/changelog+62
@@ -1,3 +1,65 @@
1+unity8 (8.00+14.10.20140910.1-0ubuntu1) utopic; urgency=low
2+
3+ [ Pete Woods ]
4+ * Disable OEM and Click scopes when system scopes are disabled
5+
6+ [ CI bot ]
7+ * Resync trunk
8+
9+ [ Pawel Stolowski ]
10+ * Set UNITY_SCOPES_NO_FAVORITES environment variable to make scopes
11+ plugin ignore favorite scopes and fix basic functionality of unity-
12+ scope-tool.
13+
14+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 10 Sep 2014 08:53:57 +0000
15+
16+unity8 (8.00+14.10.20140908.1-0ubuntu1) utopic; urgency=low
17+
18+ [ Michał Sawicz ]
19+ * Use a single white pixel instead of the heavier checkers image.
20+ * Add support to unlock-device for the new adbd coming down the
21+ pipeline. Also fix autopilot tests and run scripts for that.
22+ * Make LVWPH non interactive while on header animation
23+ * Improve references to scope/scopeStyle in PreviewListView and
24+ PageHeader, add tests.
25+
26+ [ Nick Dedekind ]
27+ * Support for nested prompt session. (LP: #1358388)
28+
29+ [ Albert Astals ]
30+ * Remove unused hasAttributes variable
31+ * Disable dash overview if in temp scope preview
32+ * Block mouse events under scope overview bottombar (LP: #1362206)
33+ * Fix regression in focus handling due to SDK change
34+ * Fix warning 'Background.qml:81:21: Unable to assign bool to QUrl'
35+ * Fix launcher internationalization
36+ * Make swipe and home button press in the launcher dismiss the
37+ overview
38+ * GSV: Use proper variable since altnav renames
39+ * Fix some "Cannot read property 'luminance' of null" warnings
40+ * Make LVWPH non interactive while on header animation
41+
42+ [ Mirco Müller ]
43+ * Implemented the needed visual updates on notifications requested by
44+ Design for RTM. (LP: #1348092)
45+
46+ [ Michael Terry ]
47+ * Don't show greeter when screen turns off during a call, even if
48+ proximity sensor isn't active. (LP: #1347001)
49+ * Add support to unlock-device for the new adbd coming down the
50+ pipeline. Also fix autopilot tests and run scripts for that.
51+
52+ [ Michael Zanetti ]
53+ * open the application when clicking on the title entry in the
54+ quicklist (LP: #1336380)
55+ * Don't animate x while dragging apps from the left edge (LP:
56+ #1360105)
57+
58+ [ Diego Sarmentero ]
59+ * Reset button state on cancel (LP: #1362622)
60+
61+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 08 Sep 2014 14:16:42 +0000
62+
163unity8 (8.00+14.10.20140903.1-0ubuntu1) utopic; urgency=low
264
365 [ Nick Dedekind ]
plugins/Dash/CardCreator.js+2−2
@@ -440,14 +440,14 @@ function cardString(template, components) {
440440 mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible);
441441 }
442442
443− var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white")';
443+ var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white")';
444444
445445 var hasTitleContainer = hasTitle && (hasEmblem || (hasMascot && (hasSubtitle || hasAttributes)));
446446 var titleSubtitleCode = '';
447447 if (hasTitle) {
448448 var titleColor;
449449 if (headerAsOverlay) {
450− titleColor = 'root.scopeStyle ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white")';
450+ titleColor = 'root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white")';
451451 } else if (hasSummary) {
452452 titleColor = 'summary.color';
453453 } else if (hasBackground) {
plugins/Dash/listviewwithpageheader.cpp+7−4
@@ -172,7 +172,7 @@ ListViewWithPageHeader::ListViewWithPageHeader()
172172 connect(this, SIGNAL(contentWidthChanged()), this, SLOT(onContentWidthChanged()));
173173 connect(this, SIGNAL(contentHeightChanged()), this, SLOT(onContentHeightChanged()));
174174 connect(this, SIGNAL(heightChanged()), this, SLOT(onHeightChanged()));
175− connect(m_contentYAnimation, SIGNAL(stopped()), this, SLOT(onShowHeaderAnimationFinished()));
175+ connect(m_contentYAnimation, SIGNAL(runningChanged(bool)), this, SLOT(contentYAnimationRunningChanged(bool)));
176176
177177 setFlickableDirection(VerticalFlick);
178178}
@@ -1056,10 +1056,13 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
10561056 m_contentHeightDirty = true;
10571057}
10581058
1059−void ListViewWithPageHeader::onShowHeaderAnimationFinished()
1059+void ListViewWithPageHeader::contentYAnimationRunningChanged(bool running)
10601060{
1061− m_contentHeightDirty = true;
1062− polish();
1061+ setInteractive(!running);
1062+ if (!running) {
1063+ m_contentHeightDirty = true;
1064+ polish();
1065+ }
10631066}
10641067
10651068void ListViewWithPageHeader::itemGeometryChanged(QQuickItem * /*item*/, const QRectF &newGeometry, const QRectF &oldGeometry)
plugins/Dash/listviewwithpageheader.h+1−1
@@ -118,7 +118,7 @@ private Q_SLOTS:
118118 void onContentWidthChanged();
119119 void onHeightChanged();
120120 void onModelUpdated(const QQmlChangeSet &changeSet, bool reset);
121− void onShowHeaderAnimationFinished();
121+ void contentYAnimationRunningChanged(bool running);
122122
123123private:
124124 class ListItem
plugins/Powerd/Powerd.cpp+16−2
@@ -39,7 +39,8 @@ void dimTimeoutChanged(GSettings *settings, const gchar *key, QDBusInterface *un
3939
4040Powerd::Powerd(QObject* parent)
4141 : QObject(parent),
42− unityScreen(nullptr)
42+ unityScreen(nullptr),
43+ cachedStatus(Status::On)
4344{
4445 unityScreen = new QDBusInterface("com.canonical.Unity.Screen",
4546 "/com/canonical/Unity/Screen",
@@ -51,7 +52,7 @@ Powerd::Powerd(QObject* parent)
5152 "com.canonical.Unity.Screen",
5253 "DisplayPowerStateChange",
5354 this,
54− SIGNAL(displayPowerStateChange(int, int)));
55+ SLOT(handleDisplayPowerStateChange(int, int)));
5556
5657 systemSettings = g_settings_new("com.ubuntu.touch.system");
5758 g_signal_connect(systemSettings, "changed::auto-brightness", G_CALLBACK(autoBrightnessChanged), unityScreen);
@@ -67,3 +68,16 @@ Powerd::~Powerd()
6768 g_signal_handlers_disconnect_by_data(systemSettings, unityScreen);
6869 g_object_unref(systemSettings);
6970}
71+
72+Powerd::Status Powerd::status() const
73+{
74+ return cachedStatus;
75+}
76+
77+void Powerd::handleDisplayPowerStateChange(int status, int reason)
78+{
79+ if (cachedStatus != (Status)status) {
80+ cachedStatus = (Status)status;
81+ Q_EMIT statusChanged((DisplayStateChangeReason)reason);
82+ }
83+}
plugins/Powerd/Powerd.h+8−1
@@ -29,6 +29,7 @@ class Powerd: public QObject
2929 Q_OBJECT
3030 Q_ENUMS(Status)
3131 Q_ENUMS(DisplayStateChangeReason)
32+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
3233
3334public:
3435 enum DisplayStateChangeReason {
@@ -46,12 +47,18 @@ public:
4647 explicit Powerd(QObject *parent = 0);
4748 ~Powerd();
4849
50+ Status status() const;
51+
4952Q_SIGNALS:
50− void displayPowerStateChange(int status, int reason);
53+ void statusChanged(DisplayStateChangeReason reason);
54+
55+private Q_SLOTS:
56+ void handleDisplayPowerStateChange(int status, int reason);
5157
5258private:
5359 QDBusInterface *unityScreen;
5460 GSettings *systemSettings;
61+ Status cachedStatus;
5562};
5663
5764#endif
plugins/Powerd/Powerd.qmltypes+3−3
@@ -30,10 +30,10 @@ Module {
3030 "On": 1
3131 }
3232 }
33+ Property { name: "status"; type: "Status"; isReadonly: true }
3334 Signal {
34− name: "displayPowerStateChange"
35− Parameter { name: "status"; type: "int" }
36− Parameter { name: "reason"; type: "int" }
35+ name: "statusChanged"
36+ Parameter { name: "reason"; type: "DisplayStateChangeReason" }
3737 }
3838 }
3939}
plugins/Unity/DashCommunicator/dashcommunicator.cpp+2−2
@@ -31,7 +31,7 @@ DashCommunicator::~DashCommunicator()
3131}
3232
3333
34−void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
34+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool isSwipe)
3535{
3636 QDBusConnection connection = QDBusConnection::sessionBus();
3737 QDBusInterface dashIface ("com.canonical.UnityDash",
@@ -39,5 +39,5 @@ void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, boo
3939 "",
4040 connection);
4141
42− dashIface.call("SetCurrentScope", scopeId, animate, reset);
42+ dashIface.call("SetCurrentScope", scopeId, animate, isSwipe);
4343}
plugins/Unity/DashCommunicator/dashcommunicator.h+1−1
@@ -29,7 +29,7 @@ public:
2929 ~DashCommunicator();
3030
3131public Q_SLOTS:
32− void setCurrentScope(const QString &scopeId, bool animate, bool reset);
32+ void setCurrentScope(const QString &scopeId, bool animate, bool isSwipe);
3333};
3434
3535#endif
plugins/Unity/DashCommunicator/dashcommunicatorservice.h+1−1
@@ -29,7 +29,7 @@ public:
2929 ~DashCommunicatorService();
3030
3131Q_SIGNALS:
32− void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
32+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool isSwipe);
3333
3434private:
3535 DBusDashCommunicatorService *m_dbusService;
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp+2−2
@@ -33,7 +33,7 @@ DBusDashCommunicatorService::~DBusDashCommunicatorService()
3333{
3434}
3535
36−void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool reset)
36+void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool isSwipe)
3737{
38− Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
38+ Q_EMIT setCurrentScopeRequested(scopeId, animate, isSwipe);
3939}
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h+2−2
@@ -29,10 +29,10 @@ public:
2929 ~DBusDashCommunicatorService();
3030
3131Q_SIGNALS:
32− void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
32+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool isSwipe);
3333
3434public Q_SLOTS:
35− Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool reset);
35+ Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool isSwipe);
3636
3737};
3838
plugins/Unity/Launcher/CMakeLists.txt+1−1
@@ -30,6 +30,6 @@ add_library(UnityLauncher-qml MODULE
3030
3131target_link_libraries(UnityLauncher-qml ${GSETTINGS_QT_LDFLAGS})
3232
33−qt5_use_modules(UnityLauncher-qml DBus Qml)
33+qt5_use_modules(UnityLauncher-qml DBus Qml Gui)
3434
3535add_unity8_plugin(Unity.Launcher 0.1 Unity/Launcher TARGETS UnityLauncher-qml)
plugins/Unity/Launcher/backend/launcherbackend.cpp+7
@@ -28,6 +28,8 @@
2828#include <QDebug>
2929#include <QStandardPaths>
3030
31+#include <libintl.h>
32+
3133class LauncherBackendItem
3234{
3335public:
@@ -350,7 +352,12 @@ LauncherBackendItem* LauncherBackend::parseDesktopFile(const QString &desktopFil
350352 QSettings settings(desktopFile, QSettings::IniFormat);
351353
352354 LauncherBackendItem* item = new LauncherBackendItem();
355+
353356 item->displayName = settings.value("Desktop Entry/Name").toString();
357+ const QString domain = settings.value("Desktop Entry/X-Ubuntu-Gettext-Domain").toString();
358+ if (!domain.isEmpty()) {
359+ item->displayName = dgettext(domain.toUtf8().constData(), item->displayName.toUtf8().constData());
360+ }
354361
355362 QString iconString = settings.value("Desktop Entry/Icon").toString();
356363 QString pathString = settings.value("Desktop Entry/Path").toString();
plugins/Unity/Launcher/launcheritem.cpp+1
@@ -36,6 +36,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
3636 m_quickList(new QuickListModel(this))
3737{
3838 QuickListEntry nameAction;
39+ nameAction.setActionId("launch_item");
3940 nameAction.setText(m_name);
4041 m_quickList->appendAction(nameAction);
4142 QuickListEntry pinningAction;
plugins/Unity/Launcher/launchermodel.cpp+3
@@ -23,6 +23,7 @@
2323
2424#include <unity/shell/application/ApplicationInfoInterface.h>
2525
26+#include <QDesktopServices>
2627#include <QDebug>
2728
2829using namespace unity::shell::application;
@@ -191,6 +192,8 @@ void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex
191192 } else {
192193 pin(appId);
193194 }
195+ } else if (actionId == "launch_item") {
196+ QDesktopServices::openUrl(getUrlForAppId(appId));
194197
195198 // Nope, we don't know this action, let the backend forward it to the application
196199 } else {
po/ca.po+8−6
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-08-26 18:24+0200\n"
11−"PO-Revision-Date: 2014-09-01 01:01+0000\n"
11+"PO-Revision-Date: 2014-09-07 04:05+0000\n"
1212"Last-Translator: David Planella <david.planella@ubuntu.com>\n"
1313"Language-Team: Catalan <ca@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-09-01 07:33+0000\n"
18−"X-Generator: Launchpad (build 17176)\n"
17+"X-Launchpad-Export-Date: 2014-09-08 06:58+0000\n"
18+"X-Generator: Launchpad (build 17196)\n"
1919
2020#: plugins/LightDM/Greeter.cpp:130
2121msgid "Password: "
@@ -50,11 +50,11 @@ msgstr "Sí"
5050
5151#: qml/Components/Dialogs.qml:94
5252msgid "Shut down"
53−msgstr ""
53+msgstr "Apaga"
5454
5555#: qml/Components/Dialogs.qml:95
5656msgid "Are you sure you want to shut down?"
57−msgstr ""
57+msgstr "Segur que voleu apagar?"
5858
5959#: qml/Components/Dialogs.qml:119
6060msgid "Reboot"
@@ -73,10 +73,12 @@ msgid ""
7373"Are you sure you would like\n"
7474"to power off?"
7575msgstr ""
76+"Segur que voleu\n"
77+"apagar?"
7678
7779#: qml/Components/Dialogs.qml:147
7880msgid "Power off"
79−msgstr "Apaga'l"
81+msgstr "Apaga"
8082
8183#: qml/Components/Dialogs.qml:157
8284msgid "Cancel"
po/de.po+7−7
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-08-26 18:24+0200\n"
11−"PO-Revision-Date: 2014-08-29 13:00+0000\n"
12−"Last-Translator: Martin Pitt <martin.pitt@ubuntu.com>\n"
11+"PO-Revision-Date: 2014-09-04 15:02+0000\n"
12+"Last-Translator: Niklas Wenzel <nikwen.developer@gmail.com>\n"
1313"Language-Team: German <de@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-30 07:46+0000\n"
18−"X-Generator: Launchpad (build 17176)\n"
17+"X-Launchpad-Export-Date: 2014-09-05 07:50+0000\n"
18+"X-Generator: Launchpad (build 17196)\n"
1919
2020#: plugins/LightDM/Greeter.cpp:130
2121msgid "Password: "
@@ -36,7 +36,7 @@ msgstr "Abmelden"
3636
3737#: qml/Components/Dialogs.qml:71
3838msgid "Are you sure you want to log out?"
39−msgstr "Sind Sie sicher dass Sie sich abmelden wollen?"
39+msgstr "Sind Sie sicher, dass Sie sich abmelden wollen?"
4040
4141#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
4242#: qml/Components/Dialogs.qml:122
@@ -54,7 +54,7 @@ msgstr "Herunterfahren"
5454
5555#: qml/Components/Dialogs.qml:95
5656msgid "Are you sure you want to shut down?"
57−msgstr "Sind Sie sicher dass Sie ausschalten wollen?"
57+msgstr "Sind Sie sicher, dass Sie herunterfahren wollen?"
5858
5959#: qml/Components/Dialogs.qml:119
6060msgid "Reboot"
@@ -62,7 +62,7 @@ msgstr "Neustart"
6262
6363#: qml/Components/Dialogs.qml:120
6464msgid "Are you sure you want to reboot?"
65−msgstr "Sind Sie sicher dass Sie neu starten wollen?"
65+msgstr "Sind Sie sicher, dass Sie neu starten wollen?"
6666
6767#: qml/Components/Dialogs.qml:144
6868msgid "Power"
po/gd.po+57−54
@@ -8,19 +8,19 @@ msgstr ""
88"Project-Id-Version: unity8\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-08-26 18:24+0200\n"
11−"PO-Revision-Date: 2014-08-13 00:21+0000\n"
12−"Last-Translator: Akerbeltz <fios@akerbeltz.org>\n"
13−"Language-Team: Fòram na Gàidhlig http://www.foramnagaidhlig.net\n"
11+"PO-Revision-Date: 2014-09-12 16:34+0000\n"
12+"Last-Translator: GunChleoc <Unknown>\n"
13+"Language-Team: Fòram na Gàidhlig\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-28 06:30+0000\n"
18−"X-Generator: Launchpad (build 17174)\n"
17+"X-Launchpad-Export-Date: 2014-09-13 08:40+0000\n"
18+"X-Generator: Launchpad (build 17196)\n"
1919"Language: gd\n"
2020
21−#: plugins/LightDM/Greeter.cpp:129
21+#: plugins/LightDM/Greeter.cpp:130
2222msgid "Password: "
23−msgstr ""
23+msgstr "Facal-faire: "
2424
2525#: plugins/Unity/Launcher/launcheritem.cpp:43
2626#: plugins/Unity/Launcher/launcheritem.cpp:73
@@ -33,53 +33,55 @@ msgstr "Neo-phrìnich an ath-ghoirid"
3333
3434#: qml/Components/Dialogs.qml:70
3535msgid "Log out"
36−msgstr ""
36+msgstr "Clàraich a-mach"
3737
3838#: qml/Components/Dialogs.qml:71
3939msgid "Are you sure you want to log out?"
40−msgstr ""
40+msgstr "A bheil thu cinnteach gu bheil thu airson clàradh a-mach?"
4141
4242#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
4343#: qml/Components/Dialogs.qml:122
4444msgid "No"
45−msgstr ""
45+msgstr "Chan eil"
4646
4747#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
4848#: qml/Components/Dialogs.qml:129
4949msgid "Yes"
50−msgstr ""
50+msgstr "Tha"
5151
5252#: qml/Components/Dialogs.qml:94
5353msgid "Shut down"
54−msgstr ""
54+msgstr "Dùin sìos"
5555
5656#: qml/Components/Dialogs.qml:95
5757msgid "Are you sure you want to shut down?"
58−msgstr ""
58+msgstr "A bheil thu cinnteach gu bheil thu airson a dhùnadh sìos?"
5959
6060#: qml/Components/Dialogs.qml:119
6161msgid "Reboot"
62−msgstr ""
62+msgstr "Ath-thòisich an siostam"
6363
6464#: qml/Components/Dialogs.qml:120
6565msgid "Are you sure you want to reboot?"
66−msgstr ""
66+msgstr "A bheil thu cinnteach gu bheil thu airson tòiseachadh às ùr?"
6767
6868#: qml/Components/Dialogs.qml:144
6969msgid "Power"
70−msgstr ""
70+msgstr "Cumhachd"
7171
7272#: qml/Components/Dialogs.qml:145
7373msgid ""
7474"Are you sure you would like\n"
7575"to power off?"
7676msgstr ""
77+"A bheil thu cinnteach gu bheil thu\n"
78+"airson a' chumhachd a chur dheth?"
7779
78−#: qml/Components/Dialogs.qml:144
80+#: qml/Components/Dialogs.qml:147
7981msgid "Power off"
8082msgstr "Cuir a' chumhachd dheth"
8183
82−#: qml/Components/Dialogs.qml:162
84+#: qml/Components/Dialogs.qml:157
8385msgid "Cancel"
8486msgstr "Sguir dheth"
8587
@@ -139,11 +141,11 @@ msgstr ""
139141
140142#: qml/Components/Lockscreen.qml:167
141143msgid "Please wait"
142−msgstr ""
144+msgstr "Fuirich ort"
143145
144146#: qml/Components/Lockscreen.qml:172
145147msgid "Too many incorrect attempts"
146−msgstr ""
148+msgstr "Cus oidhirpean leis nach do shoirbhich"
147149
148150#: qml/Components/Lockscreen.qml:206
149151msgid "Emergency Call"
@@ -170,21 +172,22 @@ msgstr "Seall nas lugha"
170172msgid "See all"
171173msgstr "Seall na h-uile"
172174
173−#: qml/Dash/GenericScopeView.qml:424 qml/Panel/SearchIndicator.qml:27
175+#: qml/Dash/GenericScopeView.qml:424 qml/Dash/PageHeader.qml:260
176+#: qml/Panel/SearchIndicator.qml:27
174177msgid "Search"
175178msgstr "Lorg"
176179
177180#: qml/Dash/PageHeader.qml:270
178181msgid "Settings"
179−msgstr ""
182+msgstr "Roghainnean"
180183
181184#: qml/Dash/PageHeader.qml:279
182185msgid "Remove from Favorites"
183−msgstr ""
186+msgstr "Thoir air falbh o na h-annsachdan"
184187
185188#: qml/Dash/PageHeader.qml:279
186189msgid "Add to Favorites"
187−msgstr ""
190+msgstr "Cuir ris na h-annsachdan"
188191
189192#: qml/Dash/Previews/PreviewActionCombo.qml:34
190193msgid "More..."
@@ -210,11 +213,11 @@ msgstr "Cuir"
210213msgid "Manage Dash"
211214msgstr "Stiùirich an deas-bhòrd"
212215
213−#: qml/Dash/ScopesOverview.qml:408
216+#: qml/Dash/ScopesOverview.qml:417
214217msgid "Done"
215218msgstr "Deiseil"
216219
217−#: qml/Dash/ScopesOverview.qml:434
220+#: qml/Dash/ScopesOverview.qml:443
218221msgid "Store"
219222msgstr "Am bùth"
220223
@@ -230,7 +233,7 @@ msgstr "Na h-uile"
230233msgid "Swipe to unlock"
231234msgstr "Dèan grad-shlaighdeadh gus a' ghlas a thoirt dheth"
232235
233−#: qml/Hud/HudParametrizedActionsPage.qml:132
236+#: qml/Hud/HudParametrizedActionsPage.qml:139
234237msgid "Confirm"
235238msgstr "Dearbhaich"
236239
@@ -256,11 +259,11 @@ msgstr "Seall am facal-faire"
256259
257260#: qml/Notifications/NotificationMenuItemFactory.qml:120
258261msgid "Enter SIM PIN"
259−msgstr ""
262+msgstr "Cuir a-steach PIN an t-SIM"
260263
261−#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
264+#: qml/Notifications/NotificationMenuItemFactory.qml:121
262265msgid "Sorry, incorrect PIN"
263−msgstr ""
266+msgstr "Duilich ach tha a' PIN cearr"
264267
265268#: qml/Panel/ActiveCallHint.qml:77
266269msgid "Tap to return to call..."
@@ -302,58 +305,58 @@ msgstr "Thoir a' ghlas far an SIM"
302305msgid "Roaming"
303306msgstr "Air fàrsan"
304307
305−#: qml/Shell.qml:266
308+#: qml/Shell.qml:279
306309msgid "Enter your passphrase"
307−msgstr ""
310+msgstr "Cuir an abairt-fhaire agad a-steach"
308311
309−#: qml/Shell.qml:267
312+#: qml/Shell.qml:280
310313msgid "Sorry, incorrect passphrase"
311−msgstr ""
314+msgstr "Duilich ach tha an abairt-fhaire cearr"
312315
313316#: qml/Shell.qml:282
314317msgid "Enter your passcode"
315−msgstr ""
318+msgstr "Cuir an còd-faire agad a-steach"
316319
317320#: qml/Shell.qml:283
318321msgid "Sorry, incorrect passcode"
319−msgstr ""
322+msgstr "Duilich ach tha an còd-faire cearr"
320323
321−#: qml/Shell.qml:273
324+#: qml/Shell.qml:286
322325#, qt-format
323326msgid "Enter your %1"
324−msgstr ""
327+msgstr "Cuir a-steach a' %1 agad"
325328
326−#: qml/Shell.qml:274
329+#: qml/Shell.qml:287
327330#, qt-format
328331msgid "Sorry, incorrect %1"
329−msgstr ""
332+msgstr "Duilich ach tha a' %1 cearr"
330333
331−#: qml/Shell.qml:310
334+#: qml/Shell.qml:323
332335msgid "Sorry, incorrect passphrase."
333−msgstr ""
336+msgstr "Duilich ach tha an abairt-fhaire cearr."
334337
335−#: qml/Shell.qml:311
338+#: qml/Shell.qml:324
336339msgid "Sorry, incorrect passcode."
337−msgstr ""
340+msgstr "Duilich ach tha an còd-faire cearr."
338341
339−#: qml/Shell.qml:312
342+#: qml/Shell.qml:325
340343msgid "This will be your last attempt."
341−msgstr ""
344+msgstr "Seo an oidhirp mu dheireadh agad."
342345
343−#: qml/Shell.qml:314
346+#: qml/Shell.qml:327
344347msgid ""
345348"If passphrase is entered incorrectly, your phone will conduct a factory "
346349"reset and all personal data will be deleted."
347350msgstr ""
351+"Ma thèid an abairt-fhaire a chur a-steach mar bu chòir, thèid an fhòn agad a "
352+"ath-shuidheachadh air roghainnean an fhactaraidh agus thèid gach dàta "
353+"pearsanta a sguabadh às."
348354
349−#: qml/Shell.qml:315
355+#: qml/Shell.qml:328
350356msgid ""
351357"If passcode is entered incorrectly, your phone will conduct a factory reset "
352358"and all personal data will be deleted."
353359msgstr ""
354−
355−#~ msgid "Are you sure you would like to turn power off?"
356−#~ msgstr "A bheil thu cinnteach gu bheil thu airson a chur dheth?"
357−
358−#~ msgid "Restart"
359−#~ msgstr "Ath-thòisich"
360+"Ma thèid an còd-faire a chur a-steach mar bu chòir, thèid an fhòn agad a ath-"
361+"shuidheachadh air roghainnean an fhactaraidh agus thèid gach dàta pearsanta "
362+"a sguabadh às."
po/ku.ponew file+345
@@ -0,0 +1,345 @@
1+# Kurdish translation for unity8
2+# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014
3+# This file is distributed under the same license as the unity8 package.
4+# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
5+#
6+msgid ""
7+msgstr ""
8+"Project-Id-Version: unity8\n"
9+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10+"POT-Creation-Date: 2014-08-26 18:24+0200\n"
11+"PO-Revision-Date: 2014-09-10 13:14+0000\n"
12+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13+"Language-Team: Kurdish <ku@li.org>\n"
14+"MIME-Version: 1.0\n"
15+"Content-Type: text/plain; charset=UTF-8\n"
16+"Content-Transfer-Encoding: 8bit\n"
17+"X-Launchpad-Export-Date: 2014-09-11 07:27+0000\n"
18+"X-Generator: Launchpad (build 17196)\n"
19+
20+#: plugins/LightDM/Greeter.cpp:130
21+msgid "Password: "
22+msgstr "Şîfre: "
23+
24+#: plugins/Unity/Launcher/launcheritem.cpp:43
25+#: plugins/Unity/Launcher/launcheritem.cpp:73
26+msgid "Pin shortcut"
27+msgstr ""
28+
29+#: plugins/Unity/Launcher/launcheritem.cpp:73
30+msgid "Unpin shortcut"
31+msgstr ""
32+
33+#: qml/Components/Dialogs.qml:70
34+msgid "Log out"
35+msgstr "Derkeve"
36+
37+#: qml/Components/Dialogs.qml:71
38+msgid "Are you sure you want to log out?"
39+msgstr "Ji dil dixwazî derkevî?"
40+
41+#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
42+#: qml/Components/Dialogs.qml:122
43+msgid "No"
44+msgstr "Na"
45+
46+#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
47+#: qml/Components/Dialogs.qml:129
48+msgid "Yes"
49+msgstr "Erê"
50+
51+#: qml/Components/Dialogs.qml:94
52+msgid "Shut down"
53+msgstr "Bigire"
54+
55+#: qml/Components/Dialogs.qml:95
56+msgid "Are you sure you want to shut down?"
57+msgstr "Ji dil dixwazî bigirî?"
58+
59+#: qml/Components/Dialogs.qml:119
60+msgid "Reboot"
61+msgstr "Dîsdestpêkirin"
62+
63+#: qml/Components/Dialogs.qml:120
64+msgid "Are you sure you want to reboot?"
65+msgstr "Ji dil dixwazî bidî destpêkirin?"
66+
67+#: qml/Components/Dialogs.qml:144
68+msgid "Power"
69+msgstr ""
70+
71+#: qml/Components/Dialogs.qml:145
72+msgid ""
73+"Are you sure you would like\n"
74+"to power off?"
75+msgstr ""
76+
77+#: qml/Components/Dialogs.qml:147
78+msgid "Power off"
79+msgstr ""
80+
81+#: qml/Components/Dialogs.qml:157
82+msgid "Cancel"
83+msgstr "Betal bike"
84+
85+#: qml/Components/EdgeDemoOverlay.qml:151
86+msgid "Skip intro"
87+msgstr ""
88+
89+#: qml/Components/EdgeDemo.qml:112
90+msgid "Right edge"
91+msgstr ""
92+
93+#: qml/Components/EdgeDemo.qml:113
94+msgid "Try swiping from the right edge to unlock the phone"
95+msgstr ""
96+
97+#: qml/Components/EdgeDemo.qml:144
98+msgid "Top edge"
99+msgstr ""
100+
101+#: qml/Components/EdgeDemo.qml:145
102+msgid "Try swiping from the top edge to access the indicators"
103+msgstr ""
104+
105+#: qml/Components/EdgeDemo.qml:170
106+msgid "Close"
107+msgstr "Bigire"
108+
109+#: qml/Components/EdgeDemo.qml:171
110+msgid "Swipe up again to close the settings screen"
111+msgstr ""
112+
113+#: qml/Components/EdgeDemo.qml:198
114+msgid "Left edge"
115+msgstr ""
116+
117+#: qml/Components/EdgeDemo.qml:199
118+msgid "Swipe from the left to reveal the launcher for quick access to apps"
119+msgstr ""
120+
121+#: qml/Components/EdgeDemo.qml:226
122+msgid "Well done"
123+msgstr "Aferim"
124+
125+#: qml/Components/EdgeDemo.qml:227
126+msgid ""
127+"You have now mastered the edge gestures and can start using the "
128+"phone<br><br>Tap on the screen to start"
129+msgstr ""
130+
131+#: qml/Components/Lockscreen.qml:167
132+msgid "Please wait"
133+msgstr "Tika ye li bendê bimîne"
134+
135+#: qml/Components/Lockscreen.qml:172
136+msgid "Too many incorrect attempts"
137+msgstr ""
138+
139+#: qml/Components/Lockscreen.qml:206
140+msgid "Emergency Call"
141+msgstr "Lêgerîna Lezgîn"
142+
143+#: qml/Components/Lockscreen.qml:226
144+msgid "OK"
145+msgstr "BAŞ E"
146+
147+#: qml/Components/PassphraseLockscreen.qml:61
148+#, qt-format
149+msgid "Hello %1"
150+msgstr "Silav %1"
151+
152+#: qml/Components/PassphraseLockscreen.qml:61
153+msgid "Hello"
154+msgstr "Silav"
155+
156+#: qml/Dash/GenericScopeView.qml:361
157+msgid "See less"
158+msgstr "Hindiktir bibîne"
159+
160+#: qml/Dash/GenericScopeView.qml:361
161+msgid "See all"
162+msgstr "Tevî bibîne"
163+
164+#: qml/Dash/GenericScopeView.qml:424 qml/Dash/PageHeader.qml:260
165+#: qml/Panel/SearchIndicator.qml:27
166+msgid "Search"
167+msgstr "Lêgerîn"
168+
169+#: qml/Dash/PageHeader.qml:270
170+msgid "Settings"
171+msgstr "Eyar"
172+
173+#: qml/Dash/PageHeader.qml:279
174+msgid "Remove from Favorites"
175+msgstr "Ji nav Bijareyan rake"
176+
177+#: qml/Dash/PageHeader.qml:279
178+msgid "Add to Favorites"
179+msgstr "Li Bijareyan zêde bike"
180+
181+#: qml/Dash/Previews/PreviewActionCombo.qml:34
182+msgid "More..."
183+msgstr "Zêdetir..."
184+
185+#: qml/Dash/Previews/PreviewActionCombo.qml:34
186+msgid "Less..."
187+msgstr "Hindiktir..."
188+
189+#: qml/Dash/Previews/PreviewRatingInput.qml:81
190+msgid "Rate this"
191+msgstr ""
192+
193+#: qml/Dash/Previews/PreviewRatingInput.qml:126
194+msgid "Add a review"
195+msgstr ""
196+
197+#: qml/Dash/Previews/PreviewRatingInput.qml:166
198+msgid "Send"
199+msgstr ""
200+
201+#: qml/Dash/ScopesOverview.qml:201
202+msgid "Manage Dash"
203+msgstr ""
204+
205+#: qml/Dash/ScopesOverview.qml:417
206+msgid "Done"
207+msgstr ""
208+
209+#: qml/Dash/ScopesOverview.qml:443
210+msgid "Store"
211+msgstr ""
212+
213+#: qml/Dash/ScopesOverviewTab.qml:36
214+msgid "Favorites"
215+msgstr ""
216+
217+#: qml/Dash/ScopesOverviewTab.qml:54
218+msgid "All"
219+msgstr ""
220+
221+#: qml/Greeter/Greeter.qml:157
222+msgid "Swipe to unlock"
223+msgstr ""
224+
225+#: qml/Hud/HudParametrizedActionsPage.qml:139
226+msgid "Confirm"
227+msgstr ""
228+
229+#: qml/Hud/Hud.qml:61 qml/Hud/Hud.qml:99 qml/Hud/Hud.qml:372
230+msgid "Type or say a command"
231+msgstr ""
232+
233+#: qml/Hud/Hud.qml:84
234+msgid "Loading. Please Wait..."
235+msgstr ""
236+
237+#: qml/Hud/Hud.qml:89
238+msgid "Speak Now..."
239+msgstr ""
240+
241+#: qml/Hud/Hud.qml:94
242+msgid "Speaking..."
243+msgstr ""
244+
245+#: qml/Notifications/NotificationMenuItemFactory.qml:105
246+msgid "Show password"
247+msgstr ""
248+
249+#: qml/Notifications/NotificationMenuItemFactory.qml:120
250+msgid "Enter SIM PIN"
251+msgstr ""
252+
253+#: qml/Notifications/NotificationMenuItemFactory.qml:121
254+msgid "Sorry, incorrect PIN"
255+msgstr ""
256+
257+#: qml/Panel/ActiveCallHint.qml:77
258+msgid "Tap to return to call..."
259+msgstr ""
260+
261+#: qml/Panel/ActiveCallHint.qml:90
262+msgid "Conference"
263+msgstr ""
264+
265+#: qml/Panel/Indicators/MenuItemFactory.qml:651
266+msgid "In queue…"
267+msgstr ""
268+
269+#: qml/Panel/Indicators/MenuItemFactory.qml:655
270+msgid "Downloading"
271+msgstr ""
272+
273+#: qml/Panel/Indicators/MenuItemFactory.qml:657
274+msgid "Paused, tap to resume"
275+msgstr ""
276+
277+#: qml/Panel/Indicators/MenuItemFactory.qml:659
278+msgid "Canceled"
279+msgstr ""
280+
281+#: qml/Panel/Indicators/MenuItemFactory.qml:661
282+msgid "Finished"
283+msgstr ""
284+
285+#: qml/Panel/Indicators/MenuItemFactory.qml:663
286+msgid "Failed, tap to retry"
287+msgstr ""
288+
289+#: qml/Panel/Indicators/ModemInfoItem.qml:105
290+msgid "Unlock SIM"
291+msgstr ""
292+
293+#: qml/Panel/Indicators/RoamingIndication.qml:27
294+msgid "Roaming"
295+msgstr ""
296+
297+#: qml/Shell.qml:279
298+msgid "Enter your passphrase"
299+msgstr ""
300+
301+#: qml/Shell.qml:280
302+msgid "Sorry, incorrect passphrase"
303+msgstr ""
304+
305+#: qml/Shell.qml:282
306+msgid "Enter your passcode"
307+msgstr ""
308+
309+#: qml/Shell.qml:283
310+msgid "Sorry, incorrect passcode"
311+msgstr ""
312+
313+#: qml/Shell.qml:286
314+#, qt-format
315+msgid "Enter your %1"
316+msgstr ""
317+
318+#: qml/Shell.qml:287
319+#, qt-format
320+msgid "Sorry, incorrect %1"
321+msgstr ""
322+
323+#: qml/Shell.qml:323
324+msgid "Sorry, incorrect passphrase."
325+msgstr ""
326+
327+#: qml/Shell.qml:324
328+msgid "Sorry, incorrect passcode."
329+msgstr ""
330+
331+#: qml/Shell.qml:325
332+msgid "This will be your last attempt."
333+msgstr ""
334+
335+#: qml/Shell.qml:327
336+msgid ""
337+"If passphrase is entered incorrectly, your phone will conduct a factory "
338+"reset and all personal data will be deleted."
339+msgstr ""
340+
341+#: qml/Shell.qml:328
342+msgid ""
343+"If passcode is entered incorrectly, your phone will conduct a factory reset "
344+"and all personal data will be deleted."
345+msgstr ""
po/sv.po+56−52
@@ -8,17 +8,17 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2014-08-26 18:24+0200\n"
11−"PO-Revision-Date: 2014-08-14 18:22+0000\n"
12−"Last-Translator: Erik Simmesgård <Unknown>\n"
11+"PO-Revision-Date: 2014-09-08 15:57+0000\n"
12+"Last-Translator: Josef Andersson <Unknown>\n"
1313"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2014-08-28 06:30+0000\n"
18−"X-Generator: Launchpad (build 17174)\n"
17+"X-Launchpad-Export-Date: 2014-09-10 08:02+0000\n"
18+"X-Generator: Launchpad (build 17196)\n"
1919"Language: sv\n"
2020
21−#: plugins/LightDM/Greeter.cpp:129
21+#: plugins/LightDM/Greeter.cpp:130
2222msgid "Password: "
2323msgstr "Lösenord: "
2424
@@ -33,53 +33,55 @@ msgstr "Släpp genväg"
3333
3434#: qml/Components/Dialogs.qml:70
3535msgid "Log out"
36−msgstr ""
36+msgstr "Logga ut"
3737
3838#: qml/Components/Dialogs.qml:71
3939msgid "Are you sure you want to log out?"
40−msgstr ""
40+msgstr "Är du säker på att du vill logga ut?"
4141
4242#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
4343#: qml/Components/Dialogs.qml:122
4444msgid "No"
45−msgstr ""
45+msgstr "Nej"
4646
4747#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
4848#: qml/Components/Dialogs.qml:129
4949msgid "Yes"
50−msgstr ""
50+msgstr "Ja"
5151
5252#: qml/Components/Dialogs.qml:94
5353msgid "Shut down"
54−msgstr ""
54+msgstr "Stäng av"
5555
5656#: qml/Components/Dialogs.qml:95
5757msgid "Are you sure you want to shut down?"
58−msgstr ""
58+msgstr "Är du säker på att du vill stänga av?"
5959
6060#: qml/Components/Dialogs.qml:119
6161msgid "Reboot"
62−msgstr ""
62+msgstr "Starta om"
6363
6464#: qml/Components/Dialogs.qml:120
6565msgid "Are you sure you want to reboot?"
66−msgstr ""
66+msgstr "Är du säker på att du vill starta om?"
6767
6868#: qml/Components/Dialogs.qml:144
6969msgid "Power"
70−msgstr ""
70+msgstr "Ström"
7171
7272#: qml/Components/Dialogs.qml:145
7373msgid ""
7474"Are you sure you would like\n"
7575"to power off?"
7676msgstr ""
77+"Är du säker på att du vill \n"
78+"stänga av?"
7779
78−#: qml/Components/Dialogs.qml:144
80+#: qml/Components/Dialogs.qml:147
7981msgid "Power off"
80−msgstr ""
82+msgstr "Stäng av"
8183
82−#: qml/Components/Dialogs.qml:162
84+#: qml/Components/Dialogs.qml:157
8385msgid "Cancel"
8486msgstr "Avbryt"
8587
@@ -137,7 +139,7 @@ msgstr "Var god vänta"
137139
138140#: qml/Components/Lockscreen.qml:172
139141msgid "Too many incorrect attempts"
140−msgstr ""
142+msgstr "För många felaktiga försök"
141143
142144#: qml/Components/Lockscreen.qml:206
143145msgid "Emergency Call"
@@ -164,21 +166,22 @@ msgstr "Visa mindre"
164166msgid "See all"
165167msgstr "Visa alla"
166168
167−#: qml/Dash/GenericScopeView.qml:424 qml/Panel/SearchIndicator.qml:27
169+#: qml/Dash/GenericScopeView.qml:424 qml/Dash/PageHeader.qml:260
170+#: qml/Panel/SearchIndicator.qml:27
168171msgid "Search"
169172msgstr "Sök"
170173
171174#: qml/Dash/PageHeader.qml:270
172175msgid "Settings"
173−msgstr ""
176+msgstr "Inställningar"
174177
175178#: qml/Dash/PageHeader.qml:279
176179msgid "Remove from Favorites"
177−msgstr ""
180+msgstr "Ta bort från Favoriter"
178181
179182#: qml/Dash/PageHeader.qml:279
180183msgid "Add to Favorites"
181−msgstr ""
184+msgstr "Lägg till Favoriter"
182185
183186#: qml/Dash/Previews/PreviewActionCombo.qml:34
184187msgid "More..."
@@ -202,15 +205,15 @@ msgstr "Skicka"
202205
203206#: qml/Dash/ScopesOverview.qml:201
204207msgid "Manage Dash"
205−msgstr ""
208+msgstr "Hantera Dash"
206209
207−#: qml/Dash/ScopesOverview.qml:408
210+#: qml/Dash/ScopesOverview.qml:417
208211msgid "Done"
209−msgstr ""
212+msgstr "Klar"
210213
211−#: qml/Dash/ScopesOverview.qml:434
214+#: qml/Dash/ScopesOverview.qml:443
212215msgid "Store"
213−msgstr ""
216+msgstr "Butik"
214217
215218#: qml/Dash/ScopesOverviewTab.qml:36
216219msgid "Favorites"
@@ -218,13 +221,13 @@ msgstr "Favoriter"
218221
219222#: qml/Dash/ScopesOverviewTab.qml:54
220223msgid "All"
221−msgstr ""
224+msgstr "Alla"
222225
223226#: qml/Greeter/Greeter.qml:157
224227msgid "Swipe to unlock"
225228msgstr "Svep för att låsa upp"
226229
227−#: qml/Hud/HudParametrizedActionsPage.qml:132
230+#: qml/Hud/HudParametrizedActionsPage.qml:139
228231msgid "Confirm"
229232msgstr "Bekräfta"
230233
@@ -250,11 +253,11 @@ msgstr "Visa lösenord"
250253
251254#: qml/Notifications/NotificationMenuItemFactory.qml:120
252255msgid "Enter SIM PIN"
253−msgstr ""
256+msgstr "Ange SIM PIN-kod"
254257
255−#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
258+#: qml/Notifications/NotificationMenuItemFactory.qml:121
256259msgid "Sorry, incorrect PIN"
257−msgstr ""
260+msgstr "Felaktig PIN"
258261
259262#: qml/Panel/ActiveCallHint.qml:77
260263msgid "Tap to return to call..."
@@ -296,55 +299,56 @@ msgstr "Lås upp SIM-kort"
296299msgid "Roaming"
297300msgstr "Roaming"
298301
299−#: qml/Shell.qml:266
302+#: qml/Shell.qml:279
300303msgid "Enter your passphrase"
301−msgstr ""
304+msgstr "Ange din lösenfras"
302305
303−#: qml/Shell.qml:267
306+#: qml/Shell.qml:280
304307msgid "Sorry, incorrect passphrase"
305−msgstr ""
308+msgstr "Felaktig lösenfras"
306309
307310#: qml/Shell.qml:282
308311msgid "Enter your passcode"
309−msgstr ""
312+msgstr "Ange din lösenkod"
310313
311314#: qml/Shell.qml:283
312315msgid "Sorry, incorrect passcode"
313−msgstr ""
316+msgstr "Felaktig lösenkod"
314317
315−#: qml/Shell.qml:273
318+#: qml/Shell.qml:286
316319#, qt-format
317320msgid "Enter your %1"
318321msgstr "Skriv in din %1"
319322
320−#: qml/Shell.qml:274
323+#: qml/Shell.qml:287
321324#, qt-format
322325msgid "Sorry, incorrect %1"
323−msgstr ""
326+msgstr "Felaktig %1"
324327
325−#: qml/Shell.qml:310
328+#: qml/Shell.qml:323
326329msgid "Sorry, incorrect passphrase."
327−msgstr ""
330+msgstr "Felaktig lösenfras."
328331
329−#: qml/Shell.qml:311
332+#: qml/Shell.qml:324
330333msgid "Sorry, incorrect passcode."
331−msgstr ""
334+msgstr "Felaktig lösenkod."
332335
333−#: qml/Shell.qml:312
336+#: qml/Shell.qml:325
334337msgid "This will be your last attempt."
335−msgstr ""
338+msgstr "Detta är ditt sista försök."
336339
337−#: qml/Shell.qml:314
340+#: qml/Shell.qml:327
338341msgid ""
339342"If passphrase is entered incorrectly, your phone will conduct a factory "
340343"reset and all personal data will be deleted."
341344msgstr ""
345+"Om lösenfrasen anges inkorrekt kommer telefonen att fabrikåterställas och "
346+"all personlig data kommer att tas bort."
342347
343−#: qml/Shell.qml:315
348+#: qml/Shell.qml:328
344349msgid ""
345350"If passcode is entered incorrectly, your phone will conduct a factory reset "
346351"and all personal data will be deleted."
347352msgstr ""
348−
349−#~ msgid "Restart"
350−#~ msgstr "Starta om"
353+"Om lösenkoden anges felaktigt kommer telefonen att fabrikåterställas och all "
354+"personlig data kommer att tas bort."
qml/Components/Background.qml+1−1
@@ -78,7 +78,7 @@ Loader {
7878 Image {
7979 objectName: "image"
8080
81− source: width > 0 && height > 0 && root.style
81+ source: width > 0 && height > 0 && root.style || ""
8282
8383 sourceSize.width: width
8484 sourceSize.height: height
qml/Dash/CardTool.qml+7−10
@@ -169,19 +169,16 @@ Item {
169169
170170 Item {
171171 id: attributesModel
172− property int numOfAttributes: 0
173− property var model: []
174− property bool hasAttributes: {
172+ property int numOfAttributes: {
175173 var attributes = components["attributes"];
176− var hasAttributesFlag = (attributes != undefined) && attributes["field"];
177−
178− if (hasAttributesFlag) {
174+ if ((attributes != undefined) && attributes["field"]) {
179175 if (attributes["max-count"]) {
180− numOfAttributes = attributes["max-count"];
176+ return attributes["max-count"];
181177 }
182178 }
183− return hasAttributesFlag
179+ return 0;
184180 }
181+ property var model: []
185182
186183 onNumOfAttributesChanged: {
187184 model = []
@@ -195,8 +192,8 @@ Item {
195192 id: cardLoader
196193 property var fields: ["art", "mascot", "title", "subtitle", "summary", "attributes"]
197194 property var maxData: {
198− "art": Qt.resolvedUrl("graphics/checkers.png"),
199− "mascot": Qt.resolvedUrl("graphics/checkers.png"),
195+ "art": Qt.resolvedUrl("graphics/pixel.png"),
196+ "mascot": Qt.resolvedUrl("graphics/pixel.png"),
200197 "title": "—\n—",
201198 "subtitle": "—",
202199 "summary": "—\n—\n—\n—\n—",
qml/Dash/Dash.qml+12−1
@@ -34,7 +34,17 @@ Showable {
3434 DashCommunicatorService {
3535 objectName: "dashCommunicatorService"
3636 onSetCurrentScopeRequested: {
37− dash.setCurrentScope(scopeId, animate, reset)
37+ if (!isSwipe || !window.active || overviewController.progress != 0) {
38+ if (overviewController.progress != 0 && window.active) animate = false;
39+ dash.setCurrentScope(scopeId, animate, isSwipe)
40+ if (overviewController.progress != 0) {
41+ if (window.active) {
42+ dashContentCache.scheduleUpdate();
43+ }
44+ overviewController.enableAnimation = window.active;
45+ overviewController.progress = 0;
46+ }
47+ }
3848 }
3949 }
4050
@@ -344,6 +354,7 @@ Showable {
344354 enabled: !dashContent.subPageShown &&
345355 dashContent.currentScope &&
346356 dashContent.currentScope.searchQuery == "" &&
357+ !scopeItem.subPageShown &&
347358 (overviewController.progress == 0 || dragging)
348359
349360 readonly property real fullMovement: units.gu(20)
qml/Dash/DashApplication.qml−6
@@ -24,12 +24,6 @@ MainView {
2424
2525 useDeprecatedToolbar: false
2626
27− Binding {
28− target: i18n
29− property: "domain"
30− value: "unity8"
31− }
32−
3327 Dash {
3428 anchors.fill: parent
3529 }
qml/Dash/GenericScopeView.qml+1−2
@@ -25,7 +25,7 @@ import "../Components/ListItems" as ListItems
2525FocusScope {
2626 id: scopeView
2727
28− readonly property bool navigationShown: pageHeaderLoader.item ? pageHeaderLoader.item.bottomItem[0].showList : false
28+ readonly property bool navigationShown: pageHeaderLoader.item ? pageHeaderLoader.item.bottomItem[0].openList : false
2929 property var scope: null
3030 property SortFilterProxyModel categories: categoryFilter
3131 property bool isCurrent: false
@@ -160,7 +160,6 @@ FocusScope {
160160 model: scopeView.categories
161161 forceNoClip: subPageLoader.open
162162 pixelAligned: true
163− interactive: !navigationShown
164163
165164 property Item expandedCategoryItem: null
166165
qml/Dash/PageHeader.qml+19−14
@@ -64,9 +64,12 @@ Item {
6464 }
6565 }
6666
67− function closePopup() {
67+ function closePopup(keepFocus) {
6868 if (headerContainer.popover != null) {
69+ headerContainer.popover.unfocusOnDestruction = !keepFocus;
6970 PopupUtils.close(headerContainer.popover);
71+ } else if (!keepFocus) {
72+ unfocus();
7073 }
7174 }
7275
@@ -74,11 +77,8 @@ Item {
7477 if (searchHistory) {
7578 searchHistory.addQuery(searchTextField.text);
7679 }
77− if (!keepFocus) {
78− unfocus();
79− }
8080 searchTextField.text = "";
81− closePopup();
81+ closePopup(keepFocus);
8282 }
8383
8484 function unfocus() {
@@ -102,7 +102,7 @@ Item {
102102 }
103103
104104 function refreshLogo() {
105− if (scopeStyle ? scopeStyle.headerLogo != "" : false) {
105+ if (root.scopeStyle ? root.scopeStyle.headerLogo != "" : false) {
106106 header.contents = imageComponent.createObject();
107107 } else if (header.contents) {
108108 header.contents.destroy();
@@ -119,11 +119,10 @@ Item {
119119 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
120120 visible: headerContainer.showSearch
121121 onPressed: {
122− closePopup();
122+ closePopup(/* keepFocus */false);
123123 if (!searchTextField.text) {
124124 headerContainer.showSearch = false;
125125 }
126− searchTextField.focus = false;
127126 mouse.accepted = false;
128127 }
129128 }
@@ -228,7 +227,7 @@ Item {
228227
229228 onTextChanged: {
230229 if (text != "") {
231− closePopup();
230+ closePopup(/* keepFocus */true);
232231 }
233232 }
234233 }
@@ -310,8 +309,13 @@ Item {
310309 id: popover
311310 autoClose: false
312311
312+ property bool unfocusOnDestruction: false
313+
313314 Component.onDestruction: {
314315 headerContainer.popover = null;
316+ if (unfocusOnDestruction) {
317+ root.unfocus();
318+ }
315319 }
316320
317321 Column {
@@ -332,8 +336,7 @@ Item {
332336 onClicked: {
333337 searchHistory.addQuery(text);
334338 searchTextField.text = text;
335− closePopup();
336− unfocus();
339+ closePopup(/* keepFocus */false);
337340 }
338341 }
339342 }
@@ -350,7 +353,7 @@ Item {
350353 bottom: bottomContainer.top
351354 }
352355
353− color: scopeStyle ? scopeStyle.headerDividerColor : "#e0e0e0"
356+ color: root.scopeStyle ? root.scopeStyle.headerDividerColor : "#e0e0e0"
354357
355358 Rectangle {
356359 anchors {
@@ -404,8 +407,10 @@ Item {
404407 Qt.lighter(Qt.rgba(bottomItem.background.topColor.r,
405408 bottomItem.background.topColor.g,
406409 bottomItem.background.topColor.b, 1.0), 1.2);
407− } else if (!bottomItem && scopeStyle) {
408− Qt.lighter(Qt.rgba(scopeStyle.background.r, scopeStyle.background.g, scopeStyle.background.b, 1.0), 1.2);
410+ } else if (!bottomItem && root.scopeStyle) {
411+ Qt.lighter(Qt.rgba(root.scopeStyle.background.r,
412+ root.scopeStyle.background.g,
413+ root.scopeStyle.background.b, 1.0), 1.2);
409414 } else "#CCFFFFFF"
410415 }
411416 }
qml/Dash/PreviewListView.qml+2−2
@@ -45,7 +45,7 @@ Item {
4545 id: header
4646 objectName: "pageHeader"
4747 width: parent.width
48− title: scope ? scope.name : ""
48+ title: root.scope ? root.scope.name : ""
4949 showBackButton: true
5050 searchEntryEnabled: false
5151 scopeStyle: root.scopeStyle
@@ -79,7 +79,7 @@ Item {
7979 if (previewListView.currentItem && previewListView.currentItem.previewData !== undefined) {
8080 previewListView.currentItem.previewData.cancelAction();
8181 }
82− scope.cancelActivation();
82+ root.scope.cancelActivation();
8383 model = undefined;
8484 }
8585 }
qml/Dash/Previews/PreviewPayments.qml+2
@@ -49,6 +49,7 @@ PreviewWidget {
4949
5050 Payments {
5151 id: paymentClient
52+ objectName: "paymentClient"
5253
5354 property var source: widgetData["source"]
5455
@@ -59,6 +60,7 @@ PreviewWidget {
5960 root.triggered(widgetId, "purchaseCompleted", source);
6061 }
6162 onPurchaseError: {
63+ paymentButton.opacity = 1;
6264 root.triggered(widgetId, "purchaseError", source);
6365 }
6466 }
qml/Dash/ScopesOverview.qml+6
@@ -386,6 +386,7 @@ Item {
386386
387387 Rectangle {
388388 id: bottomBar
389+ objectName: "bottomBar"
389390 color: "black"
390391 height: units.gu(8)
391392 width: parent.width
@@ -400,6 +401,11 @@ Item {
400401 }
401402 }
402403
404+ MouseArea {
405+ // Just eat any other press since this parent is black opaque
406+ anchors.fill: parent
407+ }
408+
403409 AbstractButton {
404410 objectName: "scopesOverviewDoneButton"
405411 width: Math.max(label.width + units.gu(2), units.gu(10))
qml/Dash/graphics/checkers.pngdeleted

Binary file not shown.

qml/Dash/graphics/pixel.pngnew file

Binary file not shown.

qml/Notifications/Notification.qml+132−46
@@ -39,19 +39,17 @@ Item {
3939 property bool fullscreen: false
4040 property int maxHeight
4141 property int margins
42− property Gradient greenGradient : Gradient {
43− GradientStop { position: 0.0; color: "#3fb24f" }
44− GradientStop { position: 1.0; color: "#3fb24f" }
45− }
46− property Gradient darkgreyGradient: Gradient {
47− GradientStop { position: 0.0; color: "#4d4745" }
48− GradientStop { position: 1.0; color: "#4d4745" }
49− }
42+ readonly property color red: "#fc4949"
43+ readonly property color green: "#3fb24f"
44+ readonly property color sdLightGrey: "#eaeaea"
45+ readonly property color sdDarkGrey: "#dddddd"
46+ readonly property color sdFontColor: "#5d5d5d"
47+ readonly property real contentSpacing: units.gu(2)
5048
5149 objectName: "background"
52− implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : contentColumn.height + contentColumn.spacing * 2) : 0
50+ implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : outterColumn.height + contentSpacing * 2) : 0
5351
54− color: Qt.rgba(0.132, 0.117, 0.109, 0.97)
52+ color: type == Notification.SnapDecision ? sdLightGrey : Qt.rgba(0.132, 0.117, 0.109, 0.97)
5553 opacity: 1 // FIXME: 1 because of LP: #1354406 workaround, has to be 0 really
5654
5755 state: {
@@ -107,7 +105,7 @@ Item {
107105 states:[
108106 State {
109107 name: "contracted"
110− PropertyChanges {target: notification; height: units.gu(8)}
108+ PropertyChanges {target: notification; height: units.gu(10)}
111109 },
112110 State {
113111 name: "expanded"
@@ -131,6 +129,7 @@ Item {
131129 color: parent.color
132130 opacity: parent.opacity
133131 radius: "medium"
132+ borderSource: "none"
134133 }
135134
136135 Rectangle {
@@ -199,50 +198,41 @@ Item {
199198 }
200199
201200 Column {
202− id: contentColumn
203− objectName: "contentColumn"
201+ id: outterColumn
204202
205203 anchors {
206204 left: parent.left
207205 right: parent.right
208206 top: parent.top
209− margins: fullscreen ? 0 : spacing
207+ margins: 0
208+ topMargin: fullscreen ? 0 : units.gu(2)
210209 }
211210
212− spacing: units.gu(1)
211+ spacing: units.gu(2)
213212
214213 Row {
215214 id: topRow
216215
217− spacing: contentColumn.spacing
216+ spacing: contentSpacing
218217 anchors {
219218 left: parent.left
220219 right: parent.right
220+ margins: contentSpacing
221221 }
222222
223223 ShapedIcon {
224224 id: icon
225225
226226 objectName: "icon"
227− width: units.gu(6)
228− height: units.gu(6)
227+ width: type == Notification.Ephemeral && !bodyLabel.visible ? units.gu(3) : units.gu(6)
228+ height: width
229229 shaped: notification.hints["x-canonical-non-shaped-icon"] == "true" ? false : true
230230 visible: iconSource !== undefined && iconSource != ""
231− }
232−
233− Image {
234− id: secondaryIcon
235−
236− objectName: "secondaryIcon"
237− width: units.gu(2)
238− height: units.gu(2)
239− visible: source !== undefined && source != ""
240− fillMode: Image.PreserveAspectCrop
241− }
231+ }
242232
243233 Column {
244234 id: labelColumn
245− width: parent.width - x
235+ width: secondaryIcon.visible ? parent.width - x - units.gu(4.5) : parent.width - x
246236
247237 anchors.verticalCenter: (icon.visible && !bodyLabel.visible) ? icon.verticalCenter : undefined
248238
@@ -255,8 +245,7 @@ Item {
255245 right: parent.right
256246 }
257247 fontSize: "medium"
258− font.bold: true
259− color: Theme.palette.selected.backgroundText
248+ color: type == Notification.SnapDecision ? sdFontColor : Theme.palette.selected.backgroundText
260249 elide: Text.ElideRight
261250 textFormat: Text.PlainText
262251 }
@@ -271,14 +260,27 @@ Item {
271260 }
272261 visible: body != ""
273262 fontSize: "small"
274− color: Theme.palette.selected.backgroundText
275− opacity: 0.6
263+ color: type == Notification.SnapDecision ? sdFontColor : Theme.palette.selected.backgroundText
276264 wrapMode: Text.WordWrap
277− maximumLineCount: 10
265+ maximumLineCount: 2
278266 elide: Text.ElideRight
279267 textFormat: Text.PlainText
280268 }
281269 }
270+
271+ Image {
272+ id: secondaryIcon
273+
274+ objectName: "secondaryIcon"
275+ width: units.gu(3)
276+ height: units.gu(3)
277+ visible: status === Image.Ready
278+ fillMode: Image.PreserveAspectCrop
279+ }
280+ }
281+
282+ ListItem.ThinDivider {
283+ visible: type == Notification.SnapDecision
282284 }
283285
284286 Column {
@@ -321,6 +323,74 @@ Item {
321323 }
322324 }
323325
326+ Column {
327+ id: oneOverTwoCase
328+
329+ anchors {
330+ left: parent.left
331+ right: parent.right
332+ margins: contentSpacing
333+ }
334+
335+ spacing: contentSpacing
336+
337+ visible: notification.type == Notification.SnapDecision && oneOverTwoRepeaterTop.count == 3
338+
339+ Repeater {
340+ id: oneOverTwoRepeaterTop
341+
342+ model: notification.actions
343+ delegate: Loader {
344+ id: oneOverTwoLoaderTop
345+
346+ property string actionId: id
347+ property string actionLabel: label
348+
349+ Component {
350+ id: oneOverTwoButtonTop
351+
352+ Button {
353+ objectName: "notify_oot_button" + index
354+ width: oneOverTwoCase.width
355+ text: oneOverTwoLoaderTop.actionLabel
356+ color: notification.hints["x-canonical-private-affirmative-tint"] == "true" ? green : sdDarkGrey
357+ onClicked: notification.notification.invokeAction(oneOverTwoLoaderTop.actionId)
358+ }
359+ }
360+ sourceComponent: index == 0 ? oneOverTwoButtonTop : undefined
361+ }
362+ }
363+
364+ Row {
365+ spacing: contentSpacing
366+
367+ Repeater {
368+ id: oneOverTwoRepeaterBottom
369+
370+ model: notification.actions
371+ delegate: Loader {
372+ id: oneOverTwoLoaderBottom
373+
374+ property string actionId: id
375+ property string actionLabel: label
376+
377+ Component {
378+ id: oneOverTwoButtonBottom
379+
380+ Button {
381+ objectName: "notify_oot_button" + index
382+ width: oneOverTwoCase.width / 2 - spacing * 2
383+ text: oneOverTwoLoaderBottom.actionLabel
384+ color: index == 1 && notification.hints["x-canonical-private-rejection-tint"] == "true" ? red : sdDarkGrey
385+ onClicked: notification.notification.invokeAction(oneOverTwoLoaderBottom.actionId)
386+ }
387+ }
388+ sourceComponent: (index == 1 || index == 2) ? oneOverTwoButtonBottom : undefined
389+ }
390+ }
391+ }
392+ }
393+
324394 Row {
325395 id: buttonRow
326396
@@ -328,9 +398,10 @@ Item {
328398 anchors {
329399 left: parent.left
330400 right: parent.right
401+ margins: contentSpacing
331402 }
332− visible: notification.type == Notification.SnapDecision && actionRepeater.count > 0
333− spacing: units.gu(1)
403+ visible: notification.type == Notification.SnapDecision && actionRepeater.count > 0 && !oneOverTwoCase.visible
404+ spacing: units.gu(2)
334405 layoutDirection: Qt.RightToLeft
335406
336407 Repeater {
@@ -347,10 +418,19 @@ Item {
347418 id: actionButton
348419
349420 Button {
350− objectName: "button" + index
351− width: buttonRow.width / 2 - spacing
421+ objectName: "notify_button" + index
422+ width: buttonRow.width / 2 - spacing*2
352423 text: loader.actionLabel
353− gradient: notification.hints["x-canonical-private-button-tint"] == "true" && index == 0 ? greenGradient : darkgreyGradient
424+ color: {
425+ var result = sdDarkGrey;
426+ if (index == 0 && notification.hints["x-canonical-private-affirmative-tint"] == "true") {
427+ result = green;
428+ }
429+ if (index == 1 && notification.hints["x-canonical-private-rejection-tint"] == "true") {
430+ result = red;
431+ }
432+ return result;
433+ }
354434 onClicked: notification.notification.invokeAction(loader.actionId)
355435 }
356436 }
@@ -362,10 +442,16 @@ Item {
362442 ComboButton {
363443 id: comboButton
364444
365− objectName: "button2"
445+ objectName: "notify_button2"
366446 width: parent.width
367− visible: notification.type == Notification.SnapDecision && actionRepeater.count > 3
368− gradient: darkgreyGradient
447+ anchors {
448+ left: parent.left
449+ right: parent.right
450+ margins: contentSpacing
451+ }
452+
453+ visible: notification.type == Notification.SnapDecision && actionRepeater.count > 3 && !oneOverTwoCase.visible
454+ color: sdDarkGrey
369455 onClicked: notification.notification.invokeAction(comboRepeater.itemAt(2).actionId)
370456 expanded: false
371457 expandedHeight: (comboRepeater.count - 2) * units.gu(4) + units.gu(.5)
@@ -399,7 +485,7 @@ Item {
399485 MouseArea {
400486 id: comboInputArea
401487
402− objectName: "button" + index
488+ objectName: "notify_button" + index
403489 width: comboButton.width
404490 height: comboIcon.height + units.gu(2)
405491
@@ -421,7 +507,7 @@ Item {
421507 }
422508 width: units.gu(2)
423509 height: units.gu(2)
424− color: "white"
510+ color: sdFontColor
425511 name: splitLabel[2]
426512 }
427513
@@ -434,7 +520,7 @@ Item {
434520 verticalCenter: comboIcon.verticalCenter
435521 }
436522 fontSize: "small"
437− color: "white"
523+ color: sdFontColor
438524 text: splitLabel[3]
439525 }
440526 }
qml/Notifications/NotificationMenuItemFactory.qml+4
@@ -55,6 +55,7 @@ Loader {
5555 anchors {
5656 left: parent.left
5757 right: parent.right
58+ margins: spacing
5859 }
5960
6061 Component.onCompleted: {
@@ -65,6 +66,7 @@ Loader {
6566
6667 Label {
6768 text: menuData.label
69+ color: notification.sdFontColor
6870 }
6971
7072 TextField {
@@ -98,11 +100,13 @@ Loader {
98100 id: checkBox
99101
100102 checked: false
103+ activeFocusOnPress: false
101104 }
102105
103106 Label {
104107 anchors.verticalCenter: checkBox.verticalCenter
105108 text: i18n.tr("Show password")
109+ color: notification.sdFontColor
106110 }
107111 }
108112 }
qml/Notifications/Notifications.qml+1−1
@@ -33,7 +33,7 @@ ListView {
3333 id: snapDecisionProxyModel
3434
3535 model: notificationList.model
36− filterRole: UnityNotifications.ModelInterface.RoleType
36+ filterRole: UnityNotifications.ModelInterface != undefined ? UnityNotifications.ModelInterface.RoleType : 0
3737 filterRegExp: RegExp(UnityNotifications.Notification.SnapDecision)
3838 }
3939
qml/Panel/Indicators/IndicatorsLight.qml+4−7
@@ -27,12 +27,9 @@ QtObject {
2727 Component.onDestruction: Lights.state = Lights.Off
2828
2929 // QtObject does not have children
30− property var _connections: Connections {
31− id: powerConnection
32−
33− target: Powerd
34− onDisplayPowerStateChange: {
35− Lights.state = (status === Powerd.Off) ? Lights.On : Lights.Off
36− }
30+ property var _binding: Binding {
31+ target: Lights
32+ property: "state"
33+ value: (Powerd.status === Powerd.Off) ? Lights.On : Lights.Off
3734 }
3835}
qml/Shell.qml+9−20
@@ -22,6 +22,7 @@ import Ubuntu.Components 0.1
2222import Ubuntu.Components.Popups 1.0
2323import Ubuntu.Gestures 0.1
2424import Ubuntu.SystemImage 0.1
25+import Ubuntu.Telephony 0.1 as Telephony
2526import Unity.Connectivity 0.1
2627import Unity.Launcher 0.1
2728import Utils 0.1
@@ -146,6 +147,7 @@ Item {
146147 lockscreen.show();
147148 }
148149 greeter.hide();
150+ launcher.hide();
149151 }
150152
151153 onFocusedApplicationIdChanged: {
@@ -164,6 +166,7 @@ Item {
164166 // for an emergency call or accepted an incoming call.
165167 setFakeActiveForApp(appId)
166168 }
169+ launcher.hide();
167170 }
168171 }
169172
@@ -457,18 +460,9 @@ Item {
457460 id: powerConnection
458461 target: Powerd
459462
460− onDisplayPowerStateChange: {
461− // We ignore any display-off signals when the proximity sensor
462− // is active. This usually indicates something like a phone call.
463− if (status == Powerd.Off && reason != Powerd.Proximity && !edgeDemo.running) {
464− greeter.showNow();
465− }
466−
467− // No reason to chew demo CPU when user isn't watching
468− if (status == Powerd.Off) {
469− edgeDemo.paused = true;
470− } else if (status == Powerd.On) {
471− edgeDemo.paused = false;
463+ onStatusChanged: {
464+ if (Powerd.status === Powerd.Off && !callManager.hasCalls && !edgeDemo.running) {
465+ greeter.showNow()
472466 }
473467 }
474468 }
@@ -544,7 +538,7 @@ Item {
544538 onShowDashHome: showHome()
545539 onDash: showDash()
546540 onDashSwipeChanged: {
547− if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
541+ if (dashSwipe) {
548542 dash.setCurrentScope("clickscope", false, true)
549543 }
550544 }
@@ -568,7 +562,7 @@ Item {
568562 visible: notifications.useModal && !greeter.shown && (notifications.state == "narrow")
569563 color: "#000000"
570564 anchors.fill: parent
571− opacity: 0.5
565+ opacity: 0.9
572566
573567 MouseArea {
574568 anchors.fill: parent
@@ -601,12 +595,6 @@ Item {
601595 }
602596 }
603597
604− Binding {
605− target: i18n
606− property: "domain"
607− value: "unity8"
608− }
609−
610598 Dialogs {
611599 id: dialogs
612600 anchors.fill: parent
@@ -637,6 +625,7 @@ Item {
637625 EdgeDemo {
638626 id: edgeDemo
639627 z: alphaDisclaimerLabel.z + 10
628+ paused: Powerd.status === Powerd.Off // Saves power
640629 greeter: greeter
641630 launcher: launcher
642631 indicators: panel.indicators
qml/Stages/ApplicationWindow.qml+3−2
@@ -55,7 +55,8 @@ Item {
5555 property bool surfaceInitialized: false
5656
5757 function forceSurfaceActiveFocusIfReady() {
58− if (sessionContainer.surface.focus &&
58+ if (sessionContainer.surface !== null &&
59+ sessionContainer.surface.focus &&
5960 sessionContainer.surface.parent === sessionContainer.surfaceContainer &&
6061 sessionContainer.surface.enabled) {
6162 sessionContainer.surface.forceActiveFocus();
@@ -114,10 +115,10 @@ Item {
114115 onSurfaceChanged: {
115116 if (sessionContainer.surface) {
116117 surfaceInitTimer.start();
118+ d.forceSurfaceActiveFocusIfReady();
117119 } else {
118120 d.surfaceInitialized = false;
119121 }
120− d.forceSurfaceActiveFocusIfReady();
121122 }
122123 }
123124
qml/Stages/PhoneStage.qml+6−1
@@ -44,6 +44,9 @@ Rectangle {
4444 }
4545
4646 onInverseProgressChanged: {
47+ // This can't be a simple binding because that would be triggered after this handler
48+ // while we need it active before doing the anition left/right
49+ priv.animateX = (inverseProgress == 0)
4750 if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
4851 // left edge drag released. Minimum distance is given by design.
4952 if (priv.oldInverseProgress > units.gu(22)) {
@@ -92,6 +95,7 @@ Rectangle {
9295 property var focusedAppDelegate: null
9396
9497 property real oldInverseProgress: 0
98+ property bool animateX: true
9599
96100 onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0);
97101
@@ -311,7 +315,8 @@ Rectangle {
311315 Behavior on x {
312316 enabled: root.spreadEnabled &&
313317 !spreadView.active &&
314− !snapAnimation.running
318+ !snapAnimation.running &&
319+ priv.animateX
315320 UbuntuNumberAnimation {
316321 duration: UbuntuAnimation.FastDuration
317322 onRunningChanged: {
qml/Stages/TabletStage.qml+5
@@ -36,6 +36,9 @@ Rectangle {
3636 property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3737
3838 onInverseProgressChanged: {
39+ // This can't be a simple binding because that would be triggered after this handler
40+ // while we need it active before doing the anition left/right
41+ spreadView.animateX = (inverseProgress == 0)
3942 if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
4043 // left edge drag released. Minimum distance is given by design.
4144 if (priv.oldInverseProgress > units.gu(22)) {
@@ -193,6 +196,8 @@ Rectangle {
193196 property int draggedDelegateCount: 0
194197 property int closingIndex: -1
195198
199+ property bool animateX: true
200+
196201 property bool sideStageDragging: sideStageDragHandle.dragging
197202 property real sideStageDragProgress: sideStageDragHandle.progress
198203
qml/Stages/TransformedTabletSpreadDelegate.qml+2−1
@@ -138,7 +138,8 @@ SpreadDelegate {
138138 enabled: !spreadView.active &&
139139 !snapAnimation.running &&
140140 model.appId !== "unity8-dash" &&
141− !spreadView.sideStageDragging
141+ !spreadView.sideStageDragging &&
142+ spreadView.animateX
142143 UbuntuNumberAnimation {
143144 duration: UbuntuAnimation.FastDuration
144145 }
run_on_device.sh+43−41
@@ -4,8 +4,8 @@ USER=phablet
44USER_ID=32011
55PACKAGE=unity8
66BINARY=unity8
7−TARGET_IP=${TARGET_IP-127.0.0.1}
8−TARGET_SSH_PORT=${TARGET_SSH_PORT-2222}
7+TARGET_IP=127.0.0.1
8+TARGET_SSH_PORT=2222
99TARGET_DEBUG_PORT=3768
1010RUN_OPTIONS=-qmljsdebugger=port:$TARGET_DEBUG_PORT
1111SETUP=false
@@ -14,18 +14,23 @@ PINLOCK=false
1414KEYLOCK=false
1515NUM_JOBS='$(( `grep -c ^processor /proc/cpuinfo` + 1 ))'
1616FLIPPED=false
17−CHROOT_PREFIX="/data/ubuntu"
1817SSH_WAS_STARTED=0
1918SSH_STARTED=0
19+PASSWORD=""
20+PASSFILE=""
2021
2122usage() {
22− echo "usage: run_on_device [OPTIONS]\n"
23− echo "Script to setup a build environment for the shell and sync build and run it on the device\n"
23+ echo "usage: run_on_device -a SUDO_PASSWORD [OPTIONS]"
24+ echo
25+ echo "Script to setup a build environment for the shell and sync build and run it on the device"
26+ echo
2427 echo "OPTIONS:"
25− echo " -s, --setup Setup the build environment"
26− echo " -p, --pinlock Enable a PIN lock screen when running"
27− echo " -k, --keylock Enable a Keyboard lock screen when running"
28− echo ""
28+ echo " -a, --password The sudo password to use"
29+ echo " -s, --setup Setup the build environment"
30+ echo " -g, --gdb Run with gdb"
31+ echo " -p, --pinlock Enable a PIN lock screen when running"
32+ echo " -k, --keylock Enable a Keyboard lock screen when running"
33+ echo
2934 echo "IMPORTANT:"
3035 echo " * Make sure to have networking setup on the device beforehand."
3136 echo " * Execute that script from a directory containing unity8 code."
@@ -34,7 +39,7 @@ usage() {
3439
3540start_ssh() {
3641 if [ $SSH_STARTED -eq 0 ]; then
37− exec_with_adb initctl start ssh
42+ adb_sudo initctl start ssh
3843 SSH_STARTED=1
3944 fi
4045}
@@ -44,25 +49,13 @@ exec_with_ssh() {
4449 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -t $USER@$TARGET_IP -p $TARGET_SSH_PORT sudo -u $USER -i bash -ic \"$@\"
4550}
4651
47−exec_with_adb() {
48− if $FLIPPED; then
49− adb shell $@
50− else
51− adb shell chroot /data/ubuntu /usr/bin/env -i PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin "$@"
52− fi
53−}
54−
55−adb_root() {
56− adb root
57− adb wait-for-device
52+adb_sudo() {
53+ adb shell "SUDO_ASKPASS=${PASSFILE} sudo --askpass $@"
5854}
5955
6056install_ssh_key() {
61− ssh-keygen -R $TARGET_IP
62− HOME_DIR="${CHROOT_PREFIX}/home/phablet"
57+ HOME_DIR="/home/phablet"
6358 adb push ~/.ssh/id_rsa.pub $HOME_DIR/.ssh/authorized_keys
64− adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh
65− adb shell chown $USER_ID:$USER_ID $HOME_DIR/.ssh/authorized_keys
6659 adb shell chmod 700 $HOME_DIR/.ssh
6760 adb shell chmod 600 $HOME_DIR/.ssh/authorized_keys
6861}
@@ -73,8 +66,14 @@ setup_adb_forwarding() {
7366}
7467
7568install_dependencies() {
76− exec_with_adb apt-get update
77− exec_with_adb apt-get -y --force-yes install build-essential rsync bzr ccache gdb ninja-build devscripts equivs unity-plugin-scopes
69+ phablet-config writable-image --remotepassword ${PASSWORD} -p build-essential \
70+ -p rsync \
71+ -p bzr \
72+ -p ccache \
73+ -p gdb \
74+ -p ninja-build \
75+ -p devscripts \
76+ -p equivs
7877}
7978
8079sync_code() {
@@ -108,12 +107,13 @@ run() {
108107 exec_with_ssh "start unity8"
109108}
110109
111−set -- `getopt -n$0 -u -a --longoptions="setup,gdb,pinlock,keylock,help" "sgpkh" "$@"`
110+set -- `getopt -n$0 -u -a --longoptions="password:,setup,gdb,pinlock,keylock,help" "a:sgpkh" "$@"`
112111
113112# FIXME: giving incorrect arguments does not call usage and exit
114113while [ $# -gt 0 ]
115114do
116115 case "$1" in
116+ -a|--password) PASSWORD=$2;;
117117 -s|--setup) SETUP=true;;
118118 -g|--gdb) GDB=true;;
119119 -p|--pinlock) PINLOCK=true;;
@@ -124,21 +124,21 @@ do
124124 shift
125125done
126126
127+if [ -z "${PASSWORD}" ]; then
128+ echo "ERROR: You need to provide a sudo password..."
129+ echo
130+ usage
131+fi
127132
128−adb_root
129−[ "${TARGET_IP}" = "127.0.0.1" ] && setup_adb_forwarding
133+PASSFILE=$( adb shell "FILE=\`mktemp\`
134+ echo \"#!/bin/sh\" > \$FILE
135+ echo \"echo \\\"${PASSWORD}\\\"\" >> \$FILE
136+ chmod +x \$FILE
137+ echo \$FILE" | tr -d '\r' )
130138
131−if [ "`adb shell 'grep -q Ubuntu /etc/lsb-release 2> /dev/null && echo -n FLIPPED'`" = "FLIPPED" ]; then
132− FLIPPED=true
133− CHROOT_PREFIX=""
134− if [ "${TARGET_IP}" != "127.0.0.1" ]; then
135− echo "ERROR: Flipped image detected, adb over TCP/IP isn't supported, yet :/"
136− echo "Unset TARGET_IP and try again."
137− exit 2
138− fi
139−fi
139+setup_adb_forwarding
140140
141−status_output=$(exec_with_adb initctl status ssh)
141+status_output=$(adb_sudo initctl status ssh)
142142if [[ $status_output == "ssh start/running, process "* ]]; then
143143 SSH_WAS_STARTED=1
144144fi
@@ -158,6 +158,8 @@ else
158158 run
159159fi
160160
161+adb shell "rm ${PASSFILE}"
162+
161163if [ $SSH_WAS_STARTED -eq 0 ]; then
162− exec_with_adb initctl stop ssh
164+ adb_sudo initctl stop ssh
163165fi
src/Dash/main.cpp+1
@@ -68,6 +68,7 @@ int main(int argc, const char *argv[])
6868 }
6969
7070 bindtextdomain("unity8", translationDirectory().toUtf8().data());
71+ textdomain("unity8");
7172
7273 QQuickView* view = new QQuickView();
7374 view->setResizeMode(QQuickView::SizeRootObjectToView);
src/main.cpp+1
@@ -108,6 +108,7 @@ Load the testability driver");
108108 }
109109
110110 bindtextdomain("unity8", translationDirectory().toUtf8().data());
111+ textdomain("unity8");
111112
112113 QQuickView* view = new QQuickView();
113114 view->setResizeMode(QQuickView::SizeRootObjectToView);
tests/autopilot/unity8/application_lifecycle/tests/test_application_lifecycle.py+4−2
@@ -97,7 +97,8 @@ class ApplicationLifecycleTests(tests.ApplicationLifeCycleTestCase):
9797 self.assertThat(greeter.created, Eventually(Equals(True)))
9898
9999 application_name = self.launch_fake_app()
100− self.assertThat(greeter.created, Eventually(Equals(False)))
100+ greeter.wait_swiped_away()
101+ process_helpers.unlock_unity()
101102 self.assert_current_focused_application(application_name)
102103
103104 def test_greeter_hides_on_app_focus(self):
@@ -113,7 +114,8 @@ class ApplicationLifecycleTests(tests.ApplicationLifeCycleTestCase):
113114 self.assertThat(greeter.created, Eventually(Equals(True)))
114115
115116 self.launch_upstart_application(application_name)
116− self.assertThat(greeter.created, Eventually(Equals(False)))
117+ greeter.wait_swiped_away()
118+ process_helpers.unlock_unity()
117119 self.assert_current_focused_application(application_name)
118120
119121 def test_click_dash_icon_must_unfocus_application(self):
tests/autopilot/unity8/process_helpers.py+12−17
@@ -20,6 +20,7 @@
2020import logging
2121import subprocess
2222import sys
23+import dbus
2324
2425# This has to work in both python 3 (ap 1.5) and py2 (ap legacy 1.4.1) so we
2526# pick the correct location in each case. Remove the py2 branch once we no
@@ -82,22 +83,16 @@ def unlock_unity(unity_proxy_obj=None):
8283 if greeter.created is False:
8384 raise RuntimeWarning("Greeter appears to be already unlocked.")
8485
85− # Because of potential input jerkiness under heavy load,
86− # retry unlocking the greeter two times.
87− # https://bugs.launchpad.net/ubuntu/+bug/1260113
88−
89− retries = 3
90− while retries > 0:
91− try:
92− greeter.swipe()
93− except AssertionError:
94− retries -= 1
95− if retries == 0:
96− raise
97− logger.info("Failed to unlock greeter, trying again...")
98− else:
99− logger.info("Greeter unlocked, continuing.")
100− break
86+ bus = dbus.SessionBus()
87+ dbus_proxy = bus.get_object("com.canonical.UnityGreeter", "/")
88+ try:
89+ dbus_proxy.HideGreeter()
90+ except dbus.DBusException:
91+ logger.info("Failed to unlock greeter")
92+ raise
93+ else:
94+ greeter.created.wait_for(False)
95+ logger.info("Greeter unlocked, continuing.")
10196
10297
10398def lock_unity(unity_proxy_obj=None):
@@ -198,7 +193,7 @@ def get_job_status(name):
198193 ], universal_newlines=True)
199194 except subprocess.CalledProcessError as error:
200195 raise JobError(
201− "Unable to get {}'s status: {}".format(name, error)
196+ "Unable to get {}'s status: {}".format(name, error)
202197 )
203198
204199
tests/autopilot/unity8/shell/emulators/greeter.py+4−1
@@ -25,6 +25,9 @@ from unity8.shell.emulators import UnityEmulatorBase
2525class Greeter(UnityEmulatorBase):
2626 """An emulator that understands the greeter screen."""
2727
28+ def wait_swiped_away(self):
29+ self.showProgress.wait_for(0)
30+
2831 def swipe(self):
2932 """Swipe the greeter screen away."""
3033 self.created.wait_for(True)
@@ -37,7 +40,7 @@ class Greeter(UnityEmulatorBase):
3740 stop_y = start_y
3841 self.pointing_device.drag(start_x, start_y, stop_x, stop_y)
3942
40− self.showProgress.wait_for(0)
43+ self.wait_swiped_away()
4144
4245 def get_prompt(self):
4346 return self.select_single(
tests/autopilot/unity8/shell/tests/test_lock_screen.py+8−9
@@ -20,7 +20,6 @@
2020
2121from __future__ import absolute_import
2222
23−from unity8.process_helpers import unlock_unity
2423from unity8.shell import with_lightdm_mock
2524from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
2625
@@ -45,11 +44,11 @@ class TestLockscreen(UnityTestCase):
4544 @with_lightdm_mock("single-pin")
4645 def test_can_unlock_pin_screen(self):
4746 """Must be able to unlock the PIN entry lock screen."""
48− unity_proxy = self.launch_unity()
47+ self.launch_unity()
4948 greeter = self.main_window.get_greeter()
5049
5150 if greeter.narrowMode:
52− unlock_unity(unity_proxy)
51+ greeter.swipe()
5352 lockscreen = self._wait_for_lockscreen()
5453 self.main_window.enter_pin_code("1234")
5554 self.assertThat(lockscreen.shown, Eventually(Equals(False)))
@@ -60,11 +59,11 @@ class TestLockscreen(UnityTestCase):
6059 @with_lightdm_mock("single-passphrase")
6160 def test_can_unlock_passphrase_screen(self):
6261 """Must be able to unlock the passphrase entry screen."""
63− unity_proxy = self.launch_unity()
62+ self.launch_unity()
6463 greeter = self.main_window.get_greeter()
6564
6665 if greeter.narrowMode:
67− unlock_unity(unity_proxy)
66+ greeter.swipe()
6867 lockscreen = self._wait_for_lockscreen()
6968 self._enter_pin_passphrase("password")
7069 self.assertThat(lockscreen.shown, Eventually(Equals(False)))
@@ -75,11 +74,11 @@ class TestLockscreen(UnityTestCase):
7574 @with_lightdm_mock("single-pin")
7675 def test_pin_screen_wrong_code(self):
7776 """Entering the wrong pin code must not dismiss the lock screen."""
78− unity_proxy = self.launch_unity()
77+ self.launch_unity()
7978 greeter = self.main_window.get_greeter()
8079
8180 if greeter.narrowMode:
82− unlock_unity(unity_proxy)
81+ greeter.swipe()
8382 lockscreen = self._wait_for_lockscreen()
8483 self.main_window.enter_pin_code("4321")
8584 pinentryField = self.main_window.get_pinentryField()
@@ -94,11 +93,11 @@ class TestLockscreen(UnityTestCase):
9493 @with_lightdm_mock("single-passphrase")
9594 def test_passphrase_screen_wrong_password(self):
9695 """Entering the wrong password must not dismiss the lock screen."""
97− unity_proxy = self.launch_unity()
96+ self.launch_unity()
9897 greeter = self.main_window.get_greeter()
9998
10099 if greeter.narrowMode:
101− unlock_unity(unity_proxy)
100+ greeter.swipe()
102101 lockscreen = self._wait_for_lockscreen()
103102 self._enter_pin_passphrase("foobar")
104103 pinentryField = self.main_window.get_pinentryField()
tests/autopilot/unity8/shell/tests/test_notifications.py+61−97
@@ -135,10 +135,7 @@ class InteractiveNotificationBase(NotificationsBase):
135135 actions = [("action_id", "dummy")]
136136 hints = [
137137 ("x-canonical-switch-to-application", "true"),
138− (
139− "x-canonical-secondary-icon",
140− self._get_icon_path('applicationIcons/dialer-app.png')
141− )
138+ ("x-canonical-secondary-icon","dialer")
142139 ]
143140
144141 self._create_interactive_notification(
@@ -170,20 +167,19 @@ class InteractiveNotificationBase(NotificationsBase):
170167 body = "Frank Zappa\n+44 (0)7736 027340"
171168 icon_path = self._get_icon_path('avatars/anna_olsson.png')
172169 hints = [
173− (
174− "x-canonical-secondary-icon",
175− self._get_icon_path('applicationIcons/dialer-app.png')
176− ),
170+ ("x-canonical-secondary-icon", "incoming-call"),
177171 ("x-canonical-snap-decisions", "true"),
172+ ("x-canonical-private-affirmative-tint", "true"),
173+ ("x-canonical-private-rejection-tint", "true"),
178174 ]
179175
180176 actions = [
181177 ('action_accept', 'Hold + Answer'),
182178 ('action_decline_1', 'End + Answer'),
183179 ('action_decline_2', 'Decline'),
184− ('action_decline_3', 'messages:I missed your call - can you call me now?'),
185− ('action_decline_4', 'messages:I\'m running late. I\'m on my way.'),
186− ('action_decline_5', 'messages:I\'m busy at the moment. I\'ll call later.'),
180+ ('action_decline_3', 'message:I missed your call - can you call me now?'),
181+ ('action_decline_4', 'message:I\'m running late. I\'m on my way.'),
182+ ('action_decline_5', 'message:I\'m busy at the moment. I\'ll call later.'),
187183 ('action_decline_6', 'edit:Custom'),
188184 ]
189185
@@ -204,13 +200,53 @@ class InteractiveNotificationBase(NotificationsBase):
204200 notification.pointing_device.click_object(
205201 notification.select_single(objectName="combobutton_dropdown"))
206202 self.assertThat(
207− notification.select_single(objectName="button2").expanded,
203+ notification.select_single(objectName="notify_button2").expanded,
208204 Eventually(Equals(True)))
209205 time.sleep(2)
210206 notification.pointing_device.click_object(
211− notification.select_single(objectName="button4"))
207+ notification.select_single(objectName="notify_button4"))
212208 self.assert_notification_action_id_was_called("action_decline_4")
213209
210+
211+ def test_sd_one_over_two_layout(self):
212+ """Snap-decision with three actions should use one-over two button layout."""
213+ unity_proxy = self.launch_unity()
214+ unlock_unity(unity_proxy)
215+
216+ summary = "Theatre at Ferria Stadium"
217+ body = "at Ferria Stadium in Bilbao, Spain\n07578545317"
218+ hints = [
219+ ("x-canonical-snap-decisions", "true"),
220+ ("x-canonical-non-shaped-icon", "true"),
221+ ("x-canonical-private-affirmative-tint", "true")
222+ ]
223+
224+ actions = [
225+ ('action_accept', 'Ok'),
226+ ('action_decline_1', 'Snooze'),
227+ ('action_decline_2', 'View'),
228+ ]
229+
230+ self._create_interactive_notification(
231+ summary,
232+ body,
233+ None,
234+ "NORMAL",
235+ actions,
236+ hints
237+ )
238+
239+ # verify and interact with the triggered snap-decision notification
240+ notify_list = self._get_notifications_list()
241+ get_notification = lambda: notify_list.wait_select_single(
242+ 'Notification', objectName='notification1')
243+ notification = get_notification()
244+ self._assert_notification(
245+ notification, summary, body, False, False, 1.0)
246+ notification.pointing_device.click_object(
247+ notification.select_single(objectName="notify_oot_button0"))
248+ self.assert_notification_action_id_was_called("action_accept")
249+
214250 def test_modal_sd_without_greeter(self):
215251 """Snap-decision should block input to shell without greeter."""
216252 unity_proxy = self.launch_unity()
@@ -222,6 +258,8 @@ class InteractiveNotificationBase(NotificationsBase):
222258 hints = [
223259 ("x-canonical-snap-decisions", "true"),
224260 ("x-canonical-non-shaped-icon", "true"),
261+ ("x-canonical-private-affirmative-tint", "true"),
262+ ("x-canonical-private-rejection-tint", "true"),
225263 ]
226264
227265 actions = [
@@ -253,7 +291,7 @@ class InteractiveNotificationBase(NotificationsBase):
253291 self._assert_notification(
254292 notification, summary, body, True, False, 1.0)
255293 notification.pointing_device.click_object(
256− notification.select_single(objectName="button0"))
294+ notification.select_single(objectName="notify_button0"))
257295 self.assert_notification_action_id_was_called("action_accept")
258296
259297 def test_modal_sd_with_greeter(self):
@@ -266,6 +304,8 @@ class InteractiveNotificationBase(NotificationsBase):
266304 hints = [
267305 ("x-canonical-snap-decisions", "true"),
268306 ("x-canonical-non-shaped-icon", "true"),
307+ ("x-canonical-private-affirmative-tint", "true"),
308+ ("x-canonical-private-rejection-tint", "true"),
269309 ]
270310
271311 actions = [
@@ -296,7 +336,7 @@ class InteractiveNotificationBase(NotificationsBase):
296336 self._assert_notification(
297337 notification, summary, body, True, False, 1.0)
298338 notification.pointing_device.click_object(
299− notification.select_single(objectName="button0"))
339+ notification.select_single(objectName="notify_button0"))
300340 self.assert_notification_action_id_was_called("action_accept")
301341
302342 def _create_interactive_notification(
@@ -438,10 +478,7 @@ class EphemeralNotificationsTests(NotificationsBase):
438478 "join me and Anna?"
439479 icon_path = self._get_icon_path('avatars/anna_olsson.png')
440480 hints = [
441− (
442− "x-canonical-secondary-icon",
443− self._get_icon_path('applicationIcons/dialer-app.png')
444− )
481+ ("x-canonical-secondary-icon", "message")
445482 ]
446483
447484 notification = shell.create_ephemeral_notification(
@@ -474,17 +511,13 @@ class EphemeralNotificationsTests(NotificationsBase):
474511 notify_list = self._get_notifications_list()
475512
476513 summary = "Upload of image completed"
477− hints = [
478− (
479− "x-canonical-secondary-icon",
480− self._get_icon_path('applicationIcons/facebook.png')
481− )
482− ]
514+ icon_path = self._get_icon_path('applicationIcons/facebook.png')
515+ hints=[]
483516
484517 notification = shell.create_ephemeral_notification(
485518 summary,
486519 None,
487− None,
520+ icon_path,
488521 hints,
489522 "NORMAL",
490523 )
@@ -497,8 +530,8 @@ class EphemeralNotificationsTests(NotificationsBase):
497530 notification(),
498531 summary,
499532 None,
500− False,
501533 True,
534+ False,
502535 1.0
503536 )
504537
@@ -683,7 +716,7 @@ class EphemeralNotificationsTests(NotificationsBase):
683716 body = 'This bubble uses the icon-title-body layout with a ' \
684717 'secondary icon.'
685718 icon_path = self._get_icon_path('avatars/anna_olsson.png')
686− hint_icon = self._get_icon_path('applicationIcons/dialer-app.png')
719+ hint_icon = 'dialer'
687720
688721 notification = shell.create_ephemeral_notification(
689722 summary,
@@ -718,72 +751,3 @@ class EphemeralNotificationsTests(NotificationsBase):
718751 self.assertThat(get_notification, Eventually(NotEquals(None)))
719752 self._assert_notification(
720753 get_notification(), summary, body, False, False, 1.0)
721−
722− def test_append_hint(self):
723− """Notification has to accumulate body-text using append-hint."""
724− unity_proxy = self.launch_unity()
725− unlock_unity(unity_proxy)
726−
727− notify_list = self._get_notifications_list()
728−
729− summary = 'Cole Raby'
730− body = 'Hey Bro Coly!'
731− icon_path = self._get_icon_path('avatars/amanda.png')
732− body_sum = body
733− notification = shell.create_ephemeral_notification(
734− summary,
735− body,
736− icon_path,
737− hints=[('x-canonical-append', 'true')]
738− )
739−
740− notification.show()
741−
742− get_notification = lambda: notify_list.wait_select_single(
743− 'Notification', objectName='notification1')
744−
745− notification = get_notification()
746− self._assert_notification(
747− notification,
748− summary,
749− body_sum,
750− True,
751− False,
752− 1.0
753− )
754−
755− bodies = [
756− 'What\'s up dude?',
757− 'Did you watch the air-race in Oshkosh last week?',
758− 'Phil owned the place like no one before him!',
759− 'Did really everything in the race work according to regulations?',
760− 'Somehow I think to remember Burt Williams did cut corners and '
761− 'was not punished for this.',
762− 'Hopefully the referees will watch the videos of the race.',
763− 'Burt could get fined with US$ 50000 for that rule-violation :)'
764− ]
765−
766− for new_body in bodies:
767− body = new_body
768− body_sum += '\n' + body
769− notification = shell.create_ephemeral_notification(
770− summary,
771− body,
772− icon_path,
773− hints=[('x-canonical-append', 'true')]
774− )
775− notification.show()
776−
777− get_notification = lambda: notify_list.wait_select_single(
778− 'Notification',
779− objectName='notification1'
780− )
781− notification = get_notification()
782− self._assert_notification(
783− notification,
784− summary,
785− body_sum,
786− True,
787− False,
788− 1.0
789− )
tests/mocks/Powerd/Powerd.cpp+15−1
@@ -19,6 +19,20 @@
1919#include "Powerd.h"
2020
2121Powerd::Powerd(QObject* parent)
22− : QObject(parent)
22+ : QObject(parent),
23+ m_status(Powerd::Status::On)
2324{
2425}
26+
27+void Powerd::setStatus(Powerd::Status status)
28+{
29+ if (m_status != status) {
30+ m_status = status;
31+ Q_EMIT statusChanged(DisplayStateChangeReason::Unknown);
32+ }
33+}
34+
35+Powerd::Status Powerd::status() const
36+{
37+ return m_status;
38+}
tests/mocks/Powerd/Powerd.h+8−1
@@ -26,6 +26,7 @@ class Powerd: public QObject
2626 Q_OBJECT
2727 Q_ENUMS(Status)
2828 Q_ENUMS(DisplayStateChangeReason)
29+ Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) // write only exists for tests
2930
3031public:
3132 enum DisplayStateChangeReason {
@@ -42,8 +43,14 @@ public:
4243
4344 explicit Powerd(QObject *parent = 0);
4445
46+ Status status() const;
47+ void setStatus(Status status);
48+
4549Q_SIGNALS:
46− void displayPowerStateChange(int status, int reason);
50+ void statusChanged(DisplayStateChangeReason reason);
51+
52+private:
53+ Status m_status;
4754};
4855
4956#endif
tests/mocks/Powerd/Powerd.qmltypes+3−3
@@ -30,10 +30,10 @@ Module {
3030 "On": 1
3131 }
3232 }
33+ Property { name: "status"; type: "Status" }
3334 Signal {
34− name: "displayPowerStateChange"
35− Parameter { name: "status"; type: "int" }
36− Parameter { name: "reason"; type: "int" }
35+ name: "statusChanged"
36+ Parameter { name: "reason"; type: "DisplayStateChangeReason" }
3737 }
3838 }
3939}
tests/mocks/Ubuntu/Payments/MockPayments.cpp+10−7
@@ -77,13 +77,16 @@ void MockPayments::setStoreItemId(const QString &store_item_id)
7777
7878void MockPayments::start()
7979{
80− if (!m_store_item_id.isEmpty()) {
81− if (m_store_item_id == "com.example.invalid") {
82− Q_EMIT purchaseError("Purchase failed.");
83− } else {
84− Q_EMIT purchaseCompleted();
85− }
86− } else {
80+ if (m_store_item_id.isEmpty()) {
8781 Q_EMIT purchaseError("No item ID supplied.");
8882 }
8983}
84+
85+void MockPayments::process()
86+{
87+ if (m_store_item_id == "com.example.invalid") {
88+ Q_EMIT purchaseError("Purchase failed.");
89+ } else {
90+ Q_EMIT purchaseCompleted();
91+ }
92+}
tests/mocks/Ubuntu/Payments/MockPayments.h+1
@@ -41,6 +41,7 @@ public:
4141 void setPrice(const double price);
4242 void setStoreItemId(const QString& store_item_id);
4343 Q_INVOKABLE void start();
44+ Q_INVOKABLE void process(); // only available for testing
4445
4546Q_SIGNALS:
4647 void currencyChanged(const QString& currency);
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp+2−2
@@ -27,7 +27,7 @@ DashCommunicatorService::~DashCommunicatorService()
2727
2828}
2929
30−void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool reset)
30+void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool isSwipe)
3131{
32− Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
32+ Q_EMIT setCurrentScopeRequested(scopeId, animate, isSwipe);
3333}
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h+2−2
@@ -27,10 +27,10 @@ public:
2727 ~DashCommunicatorService();
2828
2929Q_SIGNALS:
30− void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
30+ void setCurrentScopeRequested(const QString &scopeId, bool animate, bool isSwipe);
3131
3232public Q_SLOTS:
33− void mockSetCurrentScope(const QString &scopeId, bool animate, bool reset);
33+ void mockSetCurrentScope(const QString &scopeId, bool animate, bool isSwipe);
3434};
3535
3636#endif // DBUSUNITYSESSIONSERVICE_H
tests/mocks/Unity/fake_scope.cpp+1−1
@@ -24,7 +24,7 @@
2424#include "fake_scopes.h"
2525#include "fake_settingsmodel.h"
2626
27−Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent)
27+Scope::Scope(Scopes* parent) : Scope("MockScope5", "Mock Scope", false, parent)
2828{
2929}
3030
tests/plugins/Dash/cardcreator/2.res+2−2
@@ -94,7 +94,7 @@ Image {
9494 wrapMode: Text.Wrap;
9595 maximumLineCount: 2;
9696 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
97+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
9898 visible: showHeader ;
9999 text: root.title;
100100 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -112,7 +112,7 @@ Image {
112112 elide: Text.ElideRight;
113113 fontSize: "small";
114114 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
115− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
115+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
116116 visible: titleLabel.visible && titleLabel.text;
117117 text: cardData && cardData["subtitle"] || "";
118118 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/5.res+2−2
@@ -114,7 +114,7 @@ Label {
114114 wrapMode: Text.Wrap;
115115 maximumLineCount: 2;
116116 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
117− color: root.scopeStyle ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
117+ color: root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
118118 visible: showHeader && overlayLoader.active;
119119 text: root.title;
120120 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -133,7 +133,7 @@ Label {
133133 elide: Text.ElideRight;
134134 fontSize: "small";
135135 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
136− color: root.scopeStyle ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
136+ color: root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
137137 visible: titleLabel.visible && titleLabel.text;
138138 text: cardData && cardData["subtitle"] || "";
139139 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/6.res+3−3
@@ -70,7 +70,7 @@ Item {
7070 wrapMode: Text.Wrap;
7171 maximumLineCount: 2;
7272 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
73− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
73+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
7474 visible: showHeader ;
7575 text: root.title;
7676 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -88,7 +88,7 @@ Item {
8888 elide: Text.ElideRight;
8989 fontSize: "small";
9090 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
91+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
9292 visible: titleLabel.visible && titleLabel.text;
9393 text: cardData && cardData["subtitle"] || "";
9494 font.weight: Font.Light;
@@ -103,7 +103,7 @@ Item {
103103 rightMargin: units.gu(1);
104104 }
105105 source: cardData && cardData["emblem"] || "";
106− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
106+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
107107 width: height;
108108 height: source != "" ? titleLabel.font.pixelSize : 0;
109109 }
tests/plugins/Dash/cardcreator/7.res+3−3
@@ -95,7 +95,7 @@ Image {
9595 wrapMode: Text.Wrap;
9696 maximumLineCount: 2;
9797 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
98− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
98+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
9999 visible: showHeader ;
100100 text: root.title;
101101 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -113,7 +113,7 @@ Image {
113113 elide: Text.ElideRight;
114114 fontSize: "small";
115115 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
116− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
116+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
117117 visible: titleLabel.visible && titleLabel.text;
118118 text: cardData && cardData["subtitle"] || "";
119119 font.weight: Font.Light;
@@ -127,7 +127,7 @@ Image {
127127 rightMargin: units.gu(1);
128128 top: subtitleLabel.bottom;
129129 }
130− color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
130+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? Theme.palette.normal.baseText : "white");
131131 fontScale: root.fontScale;
132132 model: cardData && cardData["attributes"];
133133 }
tests/plugins/Unity/Launcher/CMakeLists.txt+1−1
@@ -50,7 +50,7 @@ add_executable(launchermodeltestExec
5050 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
5151 )
5252target_link_libraries(launchermodeltestExec ${GSETTINGS_QT_LDFLAGS})
53−qt5_use_modules(launchermodeltestExec Test Core DBus)
53+qt5_use_modules(launchermodeltestExec Test Core DBus Gui)
5454
5555# copy .desktop files into build directory for shadow builds
5656file(GLOB DESKTOP_FILES *.desktop)
tests/qmltests/Dash/Previews/tst_PreviewPayments.qml+49−9
@@ -48,19 +48,28 @@ Rectangle {
4848 UT.UnityTestCase {
4949 name: "PreviewPaymentsTest"
5050 when: windowShown
51+ property var paymentClient
52+
53+ function init()
54+ {
55+ paymentClient = findInvisibleChild(previewPayments, "paymentClient");
56+ verify(paymentClient, "Could not find the payment client object.");
57+ }
5158
5259 function cleanup()
5360 {
61+ paymentClient = null;
62+ previewPayments.widgetData = null;
5463 spy.clear();
55− var button = findChild(root, "paymentButton");
64+ var button = findChild(previewPayments, "paymentButton");
5665 button.opacity = 1;
5766 }
5867
5968 function test_purchase_text_display() {
6069 previewPayments.widgetData = jsonPurchase;
6170
62− var button = findChild(root, "paymentButton");
63− verify(button != null, "Button not found.");
71+ var button = findChild(previewPayments, "paymentButton");
72+ verify(button, "Button not found.");
6473 compare(button.text, "0.99USD");
6574 }
6675
@@ -68,11 +77,12 @@ Rectangle {
6877 // Exercise the purchaseCompleted signal here.
6978 previewPayments.widgetData = jsonPurchase;
7079
71− var button = findChild(root, "paymentButton");
72− verify(button != null, "Button not found.");
80+ var button = findChild(previewPayments, "paymentButton");
81+ verify(button, "Button not found.");
7382
7483 mouseClick(button, button.width / 2, button.height / 2);
7584
85+ paymentClient.process();
7686 spy.wait();
7787
7888 var args = spy.signalArguments[0];
@@ -85,8 +95,8 @@ Rectangle {
8595 // Make sure the progress bar is shown.
8696 previewPayments.widgetData = jsonPurchase;
8797
88− var button = findChild(root, "paymentButton");
89− var progress = findChild(root, "loadingBar");
98+ var button = findChild(previewPayments, "paymentButton");
99+ var progress = findChild(previewPayments, "loadingBar");
90100
91101 tryCompare(progress, "visible", false);
92102 tryCompare(progress, "opacity", 0);
@@ -95,6 +105,7 @@ Rectangle {
95105
96106 mouseClick(button, button.width / 2, button.height / 2);
97107
108+ paymentClient.process();
98109 spy.wait();
99110
100111 tryCompare(progress, "visible", true);
@@ -103,16 +114,45 @@ Rectangle {
103114 tryCompare(button, "opacity", 0);
104115 }
105116
117+ function test_progress_show_cancel() {
118+ // Make sure the progress bar is shown.
119+ previewPayments.widgetData = jsonPurchaseError;
120+
121+ var button = findChild(previewPayments, "paymentButton");
122+ var progress = findChild(previewPayments, "loadingBar");
123+
124+ tryCompare(progress, "visible", false);
125+ tryCompare(progress, "opacity", 0);
126+ tryCompare(button, "visible", true);
127+ tryCompare(button, "opacity", 1);
128+
129+ mouseClick(button, button.width / 2, button.height / 2);
130+
131+ tryCompare(progress, "visible", true);
132+ tryCompare(progress, "opacity", 1);
133+ tryCompare(button, "visible", false);
134+ tryCompare(button, "opacity", 0);
135+
136+ paymentClient.process();
137+ spy.wait();
138+
139+ tryCompare(progress, "visible", false);
140+ tryCompare(progress, "opacity", 0);
141+ tryCompare(button, "visible", true);
142+ tryCompare(button, "opacity", 1);
143+ }
144+
106145 function test_purchase_error() {
107146 // The mock Payments triggers an error when com.example.invalid is
108147 // passed to it as store_item_id. Exercise it here
109148 previewPayments.widgetData = jsonPurchaseError;
110149
111− var button = findChild(root, "paymentButton");
112− verify(button != null, "Button not found.");
150+ var button = findChild(previewPayments, "paymentButton");
151+ verify(button, "Button not found.");
113152
114153 mouseClick(button, button.width / 2, button.height / 2);
115154
155+ paymentClient.process();
116156 spy.wait();
117157
118158 var args = spy.signalArguments[0];
tests/qmltests/Dash/tst_Dash.qml+9−2
@@ -189,6 +189,14 @@ Item {
189189 var scopesOverviewAllView = findChild(dash, "scopesOverviewRepeaterChild1");
190190 tryCompare(scopesOverviewAllView, "enabled", true);
191191
192+ // Click in the middle of the black bar (nothing happens)
193+ var bottomBar = findChild(scopesOverview, "bottomBar");
194+ mouseClick(bottomBar, bottomBar.width / 2, bottomBar.height / 2);
195+ // Check temp scope is not there
196+ var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
197+ expectFailContinue("", "Clicking in the middle of bottom bar should not open a temp scope");
198+ tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
199+
192200 // Click on a temp scope
193201 var tempScopeCard = findChild(scopesOverviewAllView, "delegate1");
194202 mouseClick(tempScopeCard, 0, 0);
@@ -198,7 +206,6 @@ Item {
198206 compare(overviewDragHandle.enabled, false);
199207
200208 // Check temp scope is there
201− var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
202209 tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
203210 tryCompare(scopesOverviewTempScopeItem, "enabled", true);
204211
@@ -328,7 +335,7 @@ Item {
328335 mouseFlick(dash, startX, startY, stopX, stopY);
329336 compare(dashContentList.currentIndex, 2, "Could not flick to scope id 2");
330337 var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService");
331− dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
338+ dashCommunicatorService.mockSetCurrentScope("clickscope", true, false);
332339 tryCompare(dashContentList, "currentIndex", 1)
333340 }
334341
tests/qmltests/Dash/tst_PreviewListView.qml+29−1
@@ -16,6 +16,7 @@
1616
1717import QtQuick 2.0
1818import QtTest 1.0
19+import Ubuntu.Components 1.1
1920import "../../../qml/Dash"
2021import Unity.Test 0.1 as UT
2122import Unity 0.2 as Unity
@@ -43,7 +44,9 @@ Rectangle {
4344 id: listView
4445 anchors.fill: parent
4546 scope: mockScope
46− scopeStyle: ScopeStyle { }
47+ scopeStyle: ScopeStyle {
48+ style: mockScope.customizations
49+ }
4750 }
4851
4952 UT.UnityTestCase {
@@ -88,5 +91,30 @@ Rectangle {
8891 mouseClick(listView, listView.width / 2, listView.height / 2);
8992 clickedSpy.wait();
9093 }
94+
95+ function test_title() {
96+ var header = findChild(listView, "innerPageHeader");
97+ verify(header, "Could not find the preview header");
98+
99+ compare(header.title, "Mock Scope");
100+ }
101+
102+ function test_header_style() {
103+ var header = findChild(listView, "pageHeader");
104+ verify(header, "Could not find the header");
105+
106+ var innerHeader = findChild(header, "innerPageHeader");
107+ verify(innerHeader, "Could not find the inner header");
108+ verify(Qt.colorEqual(innerHeader.textColor, UbuntuColors.darkGrey),
109+ "Foreground color not equal: %1 != %2".arg(innerHeader.textColor).arg(UbuntuColors.darkGrey));
110+
111+ var background = findChild(header, "headerBackground");
112+ verify(background, "Could not find the background");
113+ compare(background.style, "gradient:///lightgrey/grey");
114+
115+ var image = findChild(header, "titleImage");
116+ verify(image, "Could not find the title image.");
117+ compare(image.source, Qt.resolvedUrl("../Dash/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
118+ }
91119 }
92120}
tests/qmltests/Notifications/tst_Notifications.qml+59−17
@@ -64,7 +64,7 @@ Row {
6464 function addSnapDecisionNotification() {
6565 var n = {
6666 type: Notification.SnapDecision,
67− hints: {"x-canonical-private-button-tint": "true"},
67+ hints: {"x-canonical-private-affirmative-tint": "true"},
6868 summary: "Tom Ato",
6969 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
7070 icon: "../graphics/avatars/funky.png",
@@ -79,6 +79,22 @@ Row {
7979 mockModel.append(n)
8080 }
8181
82+ function add2over1SnapDecisionNotification() {
83+ var n = {
84+ type: Notification.SnapDecision,
85+ hints: {"x-canonical-private-affirmative-tint": "true",},
86+ summary: "Theatre at Ferria Stadium",
87+ body: "at Ferria Stadium in Bilbao, Spain\n07578545317",
88+ icon: "",
89+ secondaryIcon: "",
90+ actions: [{ id: "ok_id", label: "Ok"},
91+ { id: "snooze_id", label: "Snooze"},
92+ { id: "view_id", label: "View"}]
93+ }
94+
95+ mockModel.append(n)
96+ }
97+
8298 function addEphemeralNotification() {
8399 var n = {
84100 type: Notification.Ephemeral,
@@ -181,6 +197,12 @@ Row {
181197 onClicked: addSnapDecisionNotification()
182198 }
183199
200+ Button {
201+ width: parent.width
202+ text: "add a 2over1 snap-decision"
203+ onClicked: add2over1SnapDecisionNotification()
204+ }
205+
184206 Button {
185207 width: parent.width
186208 text: "add an ephemeral"
@@ -229,7 +251,7 @@ Row {
229251 {
230252 tag: "Snap Decision with secondary icon and button-tint",
231253 type: Notification.SnapDecision,
232− hints: {"x-canonical-private-button-tint": "true"},
254+ hints: {"x-canonical-private-affirmative-tint": "true"},
233255 summary: "Tom Ato",
234256 body: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.",
235257 icon: "../graphics/avatars/funky.png",
@@ -249,10 +271,31 @@ Row {
249271 buttonTinted: true,
250272 hasSound: false
251273 },
274+ {
275+ tag: "2-over-1 Snap Decision with button-tint",
276+ type: Notification.SnapDecision,
277+ hints: {"x-canonical-private-affirmative-tint": "true"},
278+ summary: "Theatre at Ferria Stadium",
279+ body: "at Ferria Stadium in Bilbao, Spain\n07578545317",
280+ icon: "",
281+ secondaryIcon: "",
282+ actions: [{ id: "ok_id", label: "Ok"},
283+ { id: "snooze_id", label: "Snooze"},
284+ { id: "view_id", label: "View"}],
285+ summaryVisible: true,
286+ bodyVisible: true,
287+ iconVisible: false,
288+ shapedIcon: false,
289+ nonShapedIcon: false,
290+ secondaryIconVisible: false,
291+ buttonRowVisible: false,
292+ buttonTinted: true,
293+ hasSound: false
294+ },
252295 {
253296 tag: "Ephemeral notification - icon-summary layout",
254297 type: Notification.Ephemeral,
255− hints: {"x-canonical-private-button-tint": "false"},
298+ hints: {"x-canonical-private-affirmative-tint": "false"},
256299 summary: "Photo upload completed",
257300 body: "",
258301 icon: "",
@@ -271,7 +314,7 @@ Row {
271314 {
272315 tag: "Ephemeral notification - check suppression of secondary icon for icon-summary layout",
273316 type: Notification.Ephemeral,
274− hints: {"x-canonical-private-button-tint": "false",
317+ hints: {"x-canonical-private-affirmative-tint": "false",
275318 "sound-file": "dummy.ogg",
276319 "suppress-sound": "true"},
277320 summary: "New comment successfully published",
@@ -293,7 +336,7 @@ Row {
293336 {
294337 tag: "Interactive notification",
295338 type: Notification.Interactive,
296− hints: {"x-canonical-private-button-tint": "false",
339+ hints: {"x-canonical-private-affirmative-tint": "false",
297340 "sound-file": "dummy.ogg"},
298341 summary: "Interactive notification",
299342 body: "This is a notification that can be clicked",
@@ -313,7 +356,7 @@ Row {
313356 {
314357 tag: "Snap Decision without secondary icon and no button-tint",
315358 type: Notification.SnapDecision,
316− hints: {"x-canonical-private-button-tint": "false",
359+ hints: {"x-canonical-private-affirmative-tint": "false",
317360 "sound-file": "dummy.ogg"},
318361 summary: "Bro Coly",
319362 body: "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
@@ -334,7 +377,7 @@ Row {
334377 {
335378 tag: "Ephemeral notification",
336379 type: Notification.Ephemeral,
337− hints: {"x-canonical-private-button-tint": "false",
380+ hints: {"x-canonical-private-affirmative-tint": "false",
338381 "sound-file": "dummy.ogg"},
339382 summary: "Cole Raby",
340383 body: "I did not expect it to be that late.",
@@ -354,9 +397,8 @@ Row {
354397 {
355398 tag: "Ephemeral notification with non-shaped icon",
356399 type: Notification.Ephemeral,
357− hints: {"x-canonical-private-button-tint": "false",
358− "x-canonical-non-shaped-icon": "true",
359− "sound-file": "dummy.ogg"},
400+ hints: {"x-canonical-private-affirmative-tint": "false",
401+ "x-canonical-non-shaped-icon": "true"},
360402 summary: "Contacts",
361403 body: "Synchronised contacts-database with cloud-storage.",
362404 icon: "../graphics/applicationIcons/contacts-app.png",
@@ -370,7 +412,7 @@ Row {
370412 secondaryIconVisible: false,
371413 buttonRowVisible: false,
372414 buttonTinted: false,
373− hasSound: true
415+ hasSound: false
374416 }
375417 ]
376418 }
@@ -437,8 +479,8 @@ Row {
437479 tryCompare(audioItem, "playbackState", data.hasSound ? Audio.PlayingState : Audio.StoppedState)
438480
439481 if(data.buttonRowVisible) {
440− var buttonCancel = findChild(buttonRow, "button1")
441− var buttonAccept = findChild(buttonRow, "button0")
482+ var buttonCancel = findChild(buttonRow, "notify_button1")
483+ var buttonAccept = findChild(buttonRow, "notify_button0")
442484
443485 // only test the left/cancel-button if two actions have been passed in
444486 if (data.actions.length == 2) {
@@ -448,7 +490,7 @@ Row {
448490 }
449491
450492 // check the tinting of the positive/right button
451− verify(buttonAccept.gradient === data.buttonTinted ? UbuntuColors.orangeGradient : UbuntuColors.greyGradient, "button has the wrong color-tint")
493+ verify(buttonAccept.color === data.buttonTinted ? "#3fb24f" : "#dddddd", "button has the wrong color-tint")
452494
453495 // click the positive/right button
454496 tryCompareFunction(function() { mouseClick(buttonAccept, buttonAccept.width / 2, buttonAccept.height / 2); return actionSpy.signalArguments.length > 0; }, true);
@@ -458,19 +500,19 @@ Row {
458500
459501 // check if there's a ComboButton created due to more actions being passed
460502 if (data.actions.length > 2) {
461− var comboButton = findChild(notification, "button2")
503+ var comboButton = findChild(notification, "notify_button2")
462504 tryCompareFunction(function() { return comboButton.expanded == false; }, true);
463505
464506 // click to expand
465507 tryCompareFunction(function() { mouseClick(comboButton, comboButton.width - comboButton.__styleInstance.dropDownWidth / 2, comboButton.height / 2); return comboButton.expanded == true; }, true);
466508
467509 // try clicking on choices in expanded comboList
468− var choiceButton1 = findChild(notification, "button3")
510+ var choiceButton1 = findChild(notification, "notify_button3")
469511 tryCompareFunction(function() { mouseClick(choiceButton1, choiceButton1.width / 2, choiceButton1.height / 2); return actionSpy.signalArguments.length > 0; }, true);
470512 compare(actionSpy.signalArguments[0][0], data.actions[3]["id"], "got wrong id choice action 1")
471513 actionSpy.clear()
472514
473− var choiceButton2 = findChild(notification, "button4")
515+ var choiceButton2 = findChild(notification, "notify_button4")
474516 tryCompareFunction(function() { mouseClick(choiceButton2, choiceButton2.width / 2, choiceButton2.height / 2); return actionSpy.signalArguments.length > 0; }, true);
475517 compare(actionSpy.signalArguments[0][0], data.actions[4]["id"], "got wrong id choice action 2")
476518 actionSpy.clear()
tests/qmltests/tst_Shell.qml+14−7
@@ -21,6 +21,7 @@ import QtQuick 2.0
2121import QtTest 1.0
2222import GSettings 1.0
2323import LightDM 0.1 as LightDM
24+import Ubuntu.Telephony 0.1 as Telephony
2425import Unity.Application 0.1
2526import Unity.Connectivity 0.1
2627import Unity.Test 0.1 as UT
@@ -74,6 +75,11 @@ Item {
7475 signalName: "unlockingAllModems"
7576 }
7677
78+ Telephony.CallEntry {
79+ id: phoneCall
80+ phoneNumber: "+447812221111"
81+ }
82+
7783 UT.UnityTestCase {
7884 name: "Shell"
7985 when: windowShown
@@ -146,21 +152,22 @@ Item {
146152 verify(mainApp);
147153 tryCompare(mainApp, "state", ApplicationInfoInterface.Running);
148154
149− // Try to suspend while proximity is engaged...
150− Powerd.displayPowerStateChange(Powerd.Off, Powerd.Proximity);
155+ // Suspend while call is active...
156+ callManager.foregroundCall = phoneCall;
157+ Powerd.status = Powerd.Off;
151158 tryCompare(greeter, "showProgress", 0);
152159
153− // Now really suspend
154− print("suspending")
155− Powerd.displayPowerStateChange(Powerd.Off, 0);
156− print("done suspending")
160+ // Now try again after ending call
161+ callManager.foregroundCall = null;
162+ Powerd.status = Powerd.On;
163+ Powerd.status = Powerd.Off;
157164 tryCompare(greeter, "showProgress", 1);
158165
159166 tryCompare(ApplicationManager, "suspended", true);
160167 compare(mainApp.state, ApplicationInfoInterface.Suspended);
161168
162169 // And wake up
163− Powerd.displayPowerStateChange(Powerd.On, 0);
170+ Powerd.status = Powerd.On;
164171 tryCompare(greeter, "showProgress", 1);
165172
166173 // Swipe away greeter to focus app
tools/registry-tracker.cpp+6
@@ -119,6 +119,12 @@ void RegistryTracker::runRegistry()
119119 QString registry_ini = QString(REGISTRY_CONFIG).arg(m_mw_config.fileName()).arg(scopeInstallDir).arg(scopeRunnerBin);
120120 QString mw_ini = QString(MW_CONFIG).arg(m_endpoints_dir.path());
121121
122+ if (!m_systemScopes) {
123+ // Disable OEM and Click scopes when system scopes are disabled
124+ registry_ini += "OEM.InstallDir = /unused\n";
125+ registry_ini += "Click.InstallDir = /unused\n";
126+ }
127+
122128 m_runtime_config.write(runtime_ini.toUtf8());
123129 m_registry_config.write(registry_ini.toUtf8());
124130 m_mw_config.write(mw_ini.toUtf8());
tools/scopetool.cpp+3
@@ -44,6 +44,9 @@ int main(int argc, char *argv[])
4444 setenv("QML_FORCE_THREADED_RENDERER", "1", 1);
4545 setenv("QML_FIXED_ANIMATION_STEP", "1", 1);
4646
47+ // ignore favorites in unity-scopes-shell plugin
48+ setenv("UNITY_SCOPES_NO_FAVORITES", "1", 1);
49+
4750 QGuiApplication::setApplicationName("Unity Scope Tool");
4851 QGuiApplication *application;
4952 application = new QGuiApplication(argc, argv);
tools/unlock-device+4−5
@@ -19,13 +19,12 @@ done
1919
2020eval "$WAIT_COMMAND"
2121
22−# Force a sleep of twenty no matter what, since we may need to wait for unity8
22+# Force a sleep no matter what, since we may need to wait for unity8
2323# to finish coming up (it's hard to tell when the greeter is actually rendered)
24−sleep 20
24+sleep 30
2525
26−GDBUS_CMD="gdbus call --session --dest com.canonical.UnityGreeter --object-path / --method com.canonical.UnityGreeter.HideGreeter && echo Greeter unlocked"
27−
28−UNLOCK_OUTPUT=$(adb shell "if [ \"\$(id -u)\" = 0 ]; then sudo -u phablet -i $GDBUS_CMD; else $GDBUS_CMD; fi" 2>&1)
26+# We need to go through sudo to get a proper environment for dbus set up
27+UNLOCK_OUTPUT=$(adb shell "gdbus call --session --dest com.canonical.UnityGreeter --object-path / --method com.canonical.UnityGreeter.HideGreeter && echo Greeter unlocked" 2>&1)
2928if echo "$UNLOCK_OUTPUT" | grep 'Greeter unlocked' >/dev/null; then
3029 echo "I: Unlock passed"
3130 exit 0