on xenial help sign in
merge appdrawer as prereq
f0a6e21Michael Zanetti
data/com.canonical.Unity8.gschema.xml+7−2
@@ -12,7 +12,7 @@
12 <description>The usage mode chosen will affect the Window Management behaviour.</description>
12 <description>The usage mode chosen will affect the Window Management behaviour.</description>
13 </key>
13 </key>
14 <key type="y" name="edge-barrier-sensitivity">
14 <key type="y" name="edge-barrier-sensitivity">
15− <default>35</default>
15+ <default>50</default>
16 <range min="1" max="100"/>
16 <range min="1" max="100"/>
17 <summary>Sensitivity of screen edge barriers for the mouse pointer.</summary>
17 <summary>Sensitivity of screen edge barriers for the mouse pointer.</summary>
18 <description>Some UI actions like revealing the launcher or the applications spread are triggered by pushing the mouse pointer against a screen edge. This key defines how much you have to push in order to trigger the associated action.</description>
18 <description>Some UI actions like revealing the launcher or the applications spread are triggered by pushing the mouse pointer against a screen edge. This key defines how much you have to push in order to trigger the associated action.</description>
@@ -23,7 +23,7 @@
23 <description>How much you have to push (in grid units)the mouse against an edge barrier when sensibility is 100.</description>
23 <description>How much you have to push (in grid units)the mouse against an edge barrier when sensibility is 100.</description>
24 </key>
24 </key>
25 <key type="u" name="edge-barrier-max-push">
25 <key type="u" name="edge-barrier-max-push">
26− <default>60</default>
26+ <default>120</default>
27 <summary>Maximum push needed to overcome edge barrier</summary>
27 <summary>Maximum push needed to overcome edge barrier</summary>
28 <description>How much you have to push (in grid units) the mouse against an edge barrier when sensibility is 1.</description>
28 <description>How much you have to push (in grid units) the mouse against an edge barrier when sensibility is 1.</description>
29 </key>
29 </key>
@@ -48,6 +48,11 @@
48 <summary>Enable or disable the launcher</summary>
48 <summary>Enable or disable the launcher</summary>
49 <description>Toggle the availability of the launcher</description>
49 <description>Toggle the availability of the launcher</description>
50 </key>
50 </key>
51+ <key type="b" name="enable-indicator-menu">
52+ <default>true</default>
53+ <summary>Enable or disable the indicator pull down menus</summary>
54+ <description>Toggle the availability of the indicator pull down menus</description>
55+ </key>
51 </schema>
56 </schema>
52
57
53 <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
58 <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
debian/changelog+46
@@ -1,3 +1,49 @@
1+unity8 (8.15+17.04.20161129-0ubuntu1) zesty; urgency=medium
2+
3+ [ Albert Astals Cid ]
4+ * Fix PreviewProgress implicitHeight (LP: #1641943)
5+ * Adapt to dummy notification being gone
6+ * Fix autopilot test_lock_screen tests
7+ * Autopilot: Add more applications to the list for wider screens
8+ * Fix autopilot DashHelperTestCase.test_search
9+ * Also install the Screens mock
10+ * Give default value to gu-px size
11+
12+ [ Andrea Azzarone ]
13+ * Set Mir.cursorName to "grabbing" on first mouse press on a window
14+ decoration. Don't wait for press+motion. (LP: #1618078)
15+ * Do not show a divider between each quicklist entry but just between
16+ each section, similar to how unity7 does. (LP: #1637478)
17+
18+ [ Andrea Cimitan ]
19+ * Fix white text (LP: #1644468)
20+ * Make MascotLoader in CardCreator flat
21+ * Make the remaining UbuntuShape flat
22+ * added dropshadow from panel indicators to dash page header extra
23+ panel, so there is right shadow when the extra panel is narrow
24+ * Look up for expandable template dash category flag
25+
26+ [ Brian Douglass ]
27+ * Added a setting to enable/disable the indicator dropdown menu.
28+
29+ [ Daniel d'Andrada ]
30+ * There's no need for WindowDecoration to access the appDelegate
31+
32+ [ Lukáš Tinkl ]
33+ * Enable brightness (laptop backlight) handling on desktop/laptop PCs
34+ (LP: #1595947)
35+
36+ [ Michael Zanetti ]
37+ * disable spread interaction while locked (LP: #1641578)
38+
39+ [ Andrea Azzarone, Michał Sawicz ]
40+ * Implement launcher tooltips.
41+
42+ [ Olivier Tilloy ]
43+ * Remove dependency on transitional package. (LP: #1583079)
44+
45+ -- Michał Sawicz <michal.sawicz@canonical.com> Tue, 29 Nov 2016 09:43:33 +0000
46+
1unity8 (8.15+17.04.20161116.1-0ubuntu1) zesty; urgency=medium
47unity8 (8.15+17.04.20161116.1-0ubuntu1) zesty; urgency=medium
2
48
3 [ Marco Trevisan (Treviño) ]
49 [ Marco Trevisan (Treviño) ]
debian/control+7−4
@@ -38,7 +38,7 @@ Build-Depends: cmake,
38 libubuntugestures5-private-dev (>= 1.3.2030),
38 libubuntugestures5-private-dev (>= 1.3.2030),
39 libudev-dev,
39 libudev-dev,
40 libudm-common-dev,
40 libudm-common-dev,
41− libunity-api-dev (>= 7.119),
41+ libunity-api-dev (>= 7.121),
42 libusermetricsoutput1-dev,
42 libusermetricsoutput1-dev,
43# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
43# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
44 libx11-dev[!arm64 !armhf],
44 libx11-dev[!arm64 !armhf],
@@ -49,6 +49,8 @@ Build-Depends: cmake,
49 python3-all:any,
49 python3-all:any,
50 python3-setuptools,
50 python3-setuptools,
51 qml-module-qt-labs-folderlistmodel,
51 qml-module-qt-labs-folderlistmodel,
52+ qml-module-qt-labs-settings,
53+ qml-module-qtqml-statemachine,
52 qml-module-qtmultimedia (>= 5.4.1-1ubuntu19~overlay2),
54 qml-module-qtmultimedia (>= 5.4.1-1ubuntu19~overlay2),
53 qml-module-qtquick-layouts,
55 qml-module-qtquick-layouts,
54 qml-module-qtquick-xmllistmodel,
56 qml-module-qtquick-xmllistmodel,
@@ -121,14 +123,15 @@ Depends: dmz-cursor-theme,
121 qmenumodel-qml (>= 0.2.10),
123 qmenumodel-qml (>= 0.2.10),
122 qml-module-biometryd,
124 qml-module-biometryd,
123 qml-module-qt-labs-folderlistmodel,
125 qml-module-qt-labs-folderlistmodel,
126+ qml-module-qt-labs-settings,
127+ qml-module-qtqml-statemachine,
124 qml-module-qtquick-xmllistmodel,
128 qml-module-qtquick-xmllistmodel,
125 qml-module-qtsysteminfo,
129 qml-module-qtsysteminfo,
126 qml-module-ubuntu-web,
130 qml-module-ubuntu-web,
127 qtdeclarative5-qtmir-plugin (>= 0.4.8),
131 qtdeclarative5-qtmir-plugin (>= 0.4.8),
128 qtdeclarative5-ubuntu-telephony0.1,
132 qtdeclarative5-ubuntu-telephony0.1,
129− qtdeclarative5-ubuntu-web-plugin,
130 ubuntu-system-settings (>= 0.4),
133 ubuntu-system-settings (>= 0.4),
131− unity-launcher-impl-7,
134+ unity-launcher-impl-10,
132 unity8-common (= ${source:Version}),
135 unity8-common (= ${source:Version}),
133 unity8-private (= ${binary:Version}),
136 unity8-private (= ${binary:Version}),
134 unity8-private | unity-launcher-impl,
137 unity8-private | unity-launcher-impl,
@@ -225,7 +228,7 @@ Depends: accountsservice-ubuntu-schemas (>= 0.0.7),
225 ${misc:Depends},
228 ${misc:Depends},
226 ${shlibs:Depends},
229 ${shlibs:Depends},
227Provides: unity-launcher-impl,
230Provides: unity-launcher-impl,
228− unity-launcher-impl-7,
231+ unity-launcher-impl-10,
229Description: Unity 8 private libs
232Description: Unity 8 private libs
230 The Unity 8 shell is the primary user interface for Ubuntu devices.
233 The Unity 8 shell is the primary user interface for Ubuntu devices.
231 .
234 .
plugins/Dash/CardCreator.js+1−1
@@ -269,7 +269,7 @@ var kMascotShapeLoaderCode = 'Loader { \n\
269 visible: showHeader && active && status === Loader.Ready; \n\
269 visible: showHeader && active && status === Loader.Ready; \n\
270 width: units.gu(6); \n\
270 width: units.gu(6); \n\
271 height: units.gu(5.625); \n\
271 height: units.gu(5.625); \n\
272− sourceComponent: UbuntuShape { image: mascotImage } \n\
272+ sourceComponent: UbuntuShape { aspect: UbuntuShape.Flat; image: mascotImage } \n\
273 anchors { %1 } \n\
273 anchors { %1 } \n\
274 }\n';
274 }\n';
275
275
plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=9)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
3
3
4add_definitions(-DSM_BUSNAME=systemBus)
4add_definitions(-DSM_BUSNAME=systemBus)
plugins/Greeter/Unity/Launcher/launcheritem.cpp+13
@@ -76,6 +76,19 @@ void LauncherItem::setIcon(const QString &icon)
76 }
76 }
77}
77}
78
78
79+QStringList LauncherItem::keywords() const
80+{
81+ return m_keywords;
82+}
83+
84+void LauncherItem::setKeywords(const QStringList &keywords)
85+{
86+ if (m_keywords != keywords) {
87+ m_keywords = keywords;
88+ Q_EMIT keywordsChanged(keywords);
89+ }
90+}
91+
79bool LauncherItem::pinned() const
92bool LauncherItem::pinned() const
80{
93{
81 return m_pinned;
94 return m_pinned;
plugins/Greeter/Unity/Launcher/launcheritem.h+3
@@ -34,6 +34,7 @@ public:
34 QString appId() const override;
34 QString appId() const override;
35 QString name() const override;
35 QString name() const override;
36 QString icon() const override;
36 QString icon() const override;
37+ QStringList keywords() const override;
37 bool pinned() const override;
38 bool pinned() const override;
38 bool running() const override;
39 bool running() const override;
39 bool recent() const override;
40 bool recent() const override;
@@ -49,6 +50,7 @@ public:
49private:
50private:
50 void setName(const QString &name);
51 void setName(const QString &name);
51 void setIcon(const QString &icon);
52 void setIcon(const QString &icon);
53+ void setKeywords(const QStringList &keywords);
52 void setPinned(bool pinned);
54 void setPinned(bool pinned);
53 void setRunning(bool running);
55 void setRunning(bool running);
54 void setRecent(bool recent);
56 void setRecent(bool recent);
@@ -63,6 +65,7 @@ private:
63 QString m_appId;
65 QString m_appId;
64 QString m_name;
66 QString m_name;
65 QString m_icon;
67 QString m_icon;
68+ QStringList m_keywords;
66 bool m_pinned;
69 bool m_pinned;
67 bool m_running;
70 bool m_running;
68 bool m_recent;
71 bool m_recent;
plugins/Unity/Indicators/indicatorsmanager.cpp+1−4
@@ -282,13 +282,10 @@ Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
282 // convergence:
282 // convergence:
283 // 1) enable session indicator
283 // 1) enable session indicator
284 // 2) enable keyboard indicator
284 // 2) enable keyboard indicator
285− // 3) on a PC, switch the battery/power indicator to desktop mode,
286− // can't control brightness for now and phone-on-desktop broken (FIXME)
287 //
285 //
288 // The rest of the indicators respect their default profile (which is "phone", even on desktop PCs)
286 // The rest of the indicators respect their default profile (which is "phone", even on desktop PCs)
289 if ((new_indicator->identifier() == QStringLiteral("indicator-session"))
287 if ((new_indicator->identifier() == QStringLiteral("indicator-session"))
290− || new_indicator->identifier() == QStringLiteral("indicator-keyboard")
288+ || new_indicator->identifier() == QStringLiteral("indicator-keyboard")) {
291− || (new_indicator->identifier() == QStringLiteral("indicator-power") && m_platform.isPC())) {
292 new_indicator->setProfile(QString(m_profile).replace(QStringLiteral("phone"), QStringLiteral("desktop")));
289 new_indicator->setProfile(QString(m_profile).replace(QStringLiteral("phone"), QStringLiteral("desktop")));
293 } else {
290 } else {
294 new_indicator->setProfile(m_profile);
291 new_indicator->setProfile(m_profile);
plugins/Unity/Launcher/CMakeLists.txt+4−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=9)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
3
3
4add_definitions(-DSM_BUSNAME=systemBus)
4add_definitions(-DSM_BUSNAME=systemBus)
@@ -25,6 +25,8 @@ set(QMLLAUNCHERPLUGIN_SRC
25 dbusinterface.cpp
25 dbusinterface.cpp
26 gsettings.cpp
26 gsettings.cpp
27 asadapter.cpp
27 asadapter.cpp
28+ appdrawermodel.cpp
29+ ualwrapper.cpp
28 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
30 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
29 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
31 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
30 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
32 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
@@ -32,6 +34,7 @@ set(QMLLAUNCHERPLUGIN_SRC
32 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
34 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
33 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
35 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
34 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
36 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
37+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/AppDrawerModelInterface.h
35 )
38 )
36
39
37add_library(UnityLauncher-qml MODULE
40add_library(UnityLauncher-qml MODULE
plugins/Unity/Launcher/appdrawermodel.cppnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "appdrawermodel.h"
18+#include "ualwrapper.h"
19+
20+#include <QDebug>
21+#include <QDateTime>
22+
23+AppDrawerModel::AppDrawerModel(QObject *parent):
24+ AppDrawerModelInterface(parent)
25+{
26+ Q_FOREACH (const QString &appId, UalWrapper::installedApps()) {
27+ UalWrapper::AppInfo info = UalWrapper::getApplicationInfo(appId);
28+ if (!info.valid) {
29+ qWarning() << "Failed to get app info for app" << appId;
30+ continue;
31+ }
32+ m_list.append(new LauncherItem(appId, info.name, info.icon, this));
33+ m_list.last()->setKeywords(info.keywords);
34+ }
35+ qsrand(QDateTime::currentMSecsSinceEpoch() / 100);
36+}
37+
38+int AppDrawerModel::rowCount(const QModelIndex &parent) const
39+{
40+ Q_UNUSED(parent)
41+ return m_list.count();
42+}
43+
44+QVariant AppDrawerModel::data(const QModelIndex &index, int role) const
45+{
46+ switch (role) {
47+ case RoleAppId:
48+ return m_list.at(index.row())->appId();
49+ case RoleName:
50+ return m_list.at(index.row())->name();
51+ case RoleIcon:
52+ return m_list.at(index.row())->icon();
53+ case RoleKeywords:
54+ return m_list.at(index.row())->keywords();
55+ case RoleUsage:
56+ // FIXME: u-a-l needs to provide API for usage stats.
57+ // don't forget to drop the qsrand() call in the ctor when dropping this.
58+ return qrand();
59+ }
60+
61+ return QVariant();
62+}
plugins/Unity/Launcher/appdrawermodel.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+
18+#include <unity/shell/launcher/AppDrawerModelInterface.h>
19+
20+#include "launcheritem.h"
21+
22+class AppDrawerModel: public AppDrawerModelInterface
23+{
24+ Q_OBJECT
25+public:
26+ AppDrawerModel(QObject* parent = nullptr);
27+
28+ int rowCount(const QModelIndex &parent) const override;
29+ QVariant data(const QModelIndex &index, int role) const override;
30+
31+private:
32+ QList<LauncherItem*> m_list;
33+};
plugins/Unity/Launcher/launcheritem.cpp+14
@@ -42,6 +42,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
42 QuickListEntry nameAction;
42 QuickListEntry nameAction;
43 nameAction.setActionId(QStringLiteral("launch_item"));
43 nameAction.setActionId(QStringLiteral("launch_item"));
44 nameAction.setText(m_name);
44 nameAction.setText(m_name);
45+ nameAction.setHasSeparator(true);
45 m_quickList->appendAction(nameAction);
46 m_quickList->appendAction(nameAction);
46
47
47 QuickListEntry pinningAction;
48 QuickListEntry pinningAction;
@@ -89,6 +90,19 @@ void LauncherItem::setIcon(const QString &icon)
89 }
90 }
90}
91}
91
92
93+QStringList LauncherItem::keywords() const
94+{
95+ return m_keywords;
96+}
97+
98+void LauncherItem::setKeywords(const QStringList &keywords)
99+{
100+ if (m_keywords != keywords) {
101+ m_keywords = keywords;
102+ Q_EMIT keywordsChanged(keywords);
103+ }
104+}
105+
92bool LauncherItem::pinned() const
106bool LauncherItem::pinned() const
93{
107{
94 return m_pinned;
108 return m_pinned;
plugins/Unity/Launcher/launcheritem.h+4
@@ -37,6 +37,7 @@ public:
37 QString appId() const override;
37 QString appId() const override;
38 QString name() const override;
38 QString name() const override;
39 QString icon() const override;
39 QString icon() const override;
40+ QStringList keywords() const override;
40 bool pinned() const override;
41 bool pinned() const override;
41 bool running() const override;
42 bool running() const override;
42 bool recent() const override;
43 bool recent() const override;
@@ -52,6 +53,7 @@ public:
52private:
53private:
53 void setName(const QString &name);
54 void setName(const QString &name);
54 void setIcon(const QString &icon);
55 void setIcon(const QString &icon);
56+ void setKeywords(const QStringList &keywords);
55 void setPinned(bool pinned);
57 void setPinned(bool pinned);
56 void setRunning(bool running);
58 void setRunning(bool running);
57 void setRecent(bool recent);
59 void setRecent(bool recent);
@@ -66,6 +68,7 @@ private:
66 QString m_appId;
68 QString m_appId;
67 QString m_name;
69 QString m_name;
68 QString m_icon;
70 QString m_icon;
71+ QStringList m_keywords;
69 bool m_pinned;
72 bool m_pinned;
70 bool m_running;
73 bool m_running;
71 bool m_recent;
74 bool m_recent;
@@ -79,6 +82,7 @@ private:
79 QuickListEntry m_quitAction;
82 QuickListEntry m_quitAction;
80
83
81 friend class LauncherModel;
84 friend class LauncherModel;
85+ friend class AppDrawerModel;
82};
86};
83
87
84#endif // LAUNCHERITEM_H
88#endif // LAUNCHERITEM_H
plugins/Unity/Launcher/launchermodel.cpp+6−37
@@ -19,18 +19,14 @@
19#include "gsettings.h"
19#include "gsettings.h"
20#include "dbusinterface.h"
20#include "dbusinterface.h"
21#include "asadapter.h"
21#include "asadapter.h"
22+#include "ualwrapper.h"
22
23
23−#include <ubuntu-app-launch/appid.h>
24−#include <ubuntu-app-launch/application.h>
25−#include <ubuntu-app-launch/registry.h>
26#include <unity/shell/application/ApplicationInfoInterface.h>
24#include <unity/shell/application/ApplicationInfoInterface.h>
27#include <unity/shell/application/MirSurfaceListInterface.h>
25#include <unity/shell/application/MirSurfaceListInterface.h>
28
26
29#include <QDesktopServices>
27#include <QDesktopServices>
30#include <QDebug>
28#include <QDebug>
31
29
32−namespace ual = ubuntu::app_launch;
33−
34using namespace unity::shell::application;
30using namespace unity::shell::application;
35
31
36LauncherModel::LauncherModel(QObject *parent):
32LauncherModel::LauncherModel(QObject *parent):
@@ -38,8 +34,7 @@ LauncherModel::LauncherModel(QObject *parent):
38 m_settings(new GSettings(this)),
34 m_settings(new GSettings(this)),
39 m_dbusIface(new DBusInterface(this)),
35 m_dbusIface(new DBusInterface(this)),
40 m_asAdapter(new ASAdapter()),
36 m_asAdapter(new ASAdapter()),
41− m_appManager(nullptr),
37+ m_appManager(nullptr)
42− m_ualRegistry(std::make_shared<ual::Registry>())
43{
38{
44 connect(m_dbusIface, &DBusInterface::countChanged, this, &LauncherModel::countChanged);
39 connect(m_dbusIface, &DBusInterface::countChanged, this, &LauncherModel::countChanged);
45 connect(m_dbusIface, &DBusInterface::countVisibleChanged, this, &LauncherModel::countVisibleChanged);
40 connect(m_dbusIface, &DBusInterface::countVisibleChanged, this, &LauncherModel::countVisibleChanged);
@@ -159,7 +154,7 @@ void LauncherModel::pin(const QString &appId, int index)
159 index = m_list.count();
154 index = m_list.count();
160 }
155 }
161
156
162− auto appInfo = getApplicationInfo(appId);
157+ UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(appId);
163 if (!appInfo.valid) {
158 if (!appInfo.valid) {
164 qWarning() << "Can't pin application, appId not found:" << appId;
159 qWarning() << "Can't pin application, appId not found:" << appId;
165 return;
160 return;
@@ -335,32 +330,6 @@ int LauncherModel::findApplication(const QString &appId)
335 return -1;
330 return -1;
336}
331}
337
332
338−LauncherModel::AppInfo LauncherModel::getApplicationInfo(const QString &appId)
339−{
340− AppInfo info;
341−
342− ual::AppID ualAppId = ual::AppID::find(m_ualRegistry, appId.toStdString());
343− if (ualAppId.empty()) {
344− return info;
345− }
346−
347− std::shared_ptr<ual::Application> ualApp;
348− try
349− {
350− ualApp = ual::Application::create(ualAppId, m_ualRegistry);
351− }
352− catch (std::runtime_error &e)
353− {
354− qWarning() << "Couldn't find application info for" << appId << "-" << e.what();
355− return info;
356− }
357−
358− info.valid = true;
359− info.name = QString::fromStdString(ualApp->info()->name());
360− info.icon = QString::fromStdString(ualApp->info()->iconPath());
361− return info;
362−}
363−
364void LauncherModel::progressChanged(const QString &appId, int progress)
333void LauncherModel::progressChanged(const QString &appId, int progress)
365{
334{
366 const int idx = findApplication(appId);
335 const int idx = findApplication(appId);
@@ -408,7 +377,7 @@ void LauncherModel::countVisibleChanged(const QString &appId, bool countVisible)
408 }
377 }
409 } else {
378 } else {
410 // Need to create a new LauncherItem and show the highlight
379 // Need to create a new LauncherItem and show the highlight
411− auto appInfo = getApplicationInfo(appId);
380+ UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(appId);
412 if (countVisible && appInfo.valid) {
381 if (countVisible && appInfo.valid) {
413 LauncherItem *item = new LauncherItem(appId,
382 LauncherItem *item = new LauncherItem(appId,
414 appInfo.name,
383 appInfo.name,
@@ -428,7 +397,7 @@ void LauncherModel::refresh()
428 // First walk through all the existing items and see if we need to remove something
397 // First walk through all the existing items and see if we need to remove something
429 QList<LauncherItem*> toBeRemoved;
398 QList<LauncherItem*> toBeRemoved;
430 Q_FOREACH (LauncherItem* item, m_list) {
399 Q_FOREACH (LauncherItem* item, m_list) {
431− auto appInfo = getApplicationInfo(item->appId());
400+ UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(item->appId());
432 if (!appInfo.valid) {
401 if (!appInfo.valid) {
433 // Application no longer available => drop it!
402 // Application no longer available => drop it!
434 toBeRemoved << item;
403 toBeRemoved << item;
@@ -480,7 +449,7 @@ void LauncherModel::refresh()
480 if (itemIndex == -1) {
449 if (itemIndex == -1) {
481 // Need to add it. Just add it into the addedIndex to keep same ordering as the list
450 // Need to add it. Just add it into the addedIndex to keep same ordering as the list
482 // in the settings.
451 // in the settings.
483− auto appInfo = getApplicationInfo(entry);
452+ UalWrapper::AppInfo appInfo = UalWrapper::getApplicationInfo(entry);
484 if (!appInfo.valid) {
453 if (!appInfo.valid) {
485 continue;
454 continue;
486 }
455 }
plugins/Unity/Launcher/launchermodel.h−14
@@ -27,12 +27,6 @@ class GSettings;
27class DBusInterface;
27class DBusInterface;
28class ASAdapter;
28class ASAdapter;
29
29
30−namespace ubuntu {
31− namespace app_launch {
32− class Registry;
33− }
34−}
35−
36using namespace unity::shell::launcher;
30using namespace unity::shell::launcher;
37using namespace unity::shell::application;
31using namespace unity::shell::application;
38
32
@@ -73,13 +67,6 @@ private:
73
67
74 void unpin(const QString &appId);
68 void unpin(const QString &appId);
75
69
76− struct AppInfo {
77− bool valid = false;
78− QString name;
79− QString icon;
80− };
81− AppInfo getApplicationInfo(const QString &appId);
82−
83private Q_SLOTS:
70private Q_SLOTS:
84 void countChanged(const QString &appId, int count);
71 void countChanged(const QString &appId, int count);
85 void countVisibleChanged(const QString &appId, bool count);
72 void countVisibleChanged(const QString &appId, bool count);
@@ -98,7 +85,6 @@ private:
98 ASAdapter *m_asAdapter;
85 ASAdapter *m_asAdapter;
99
86
100 ApplicationManagerInterface *m_appManager;
87 ApplicationManagerInterface *m_appManager;
101− std::shared_ptr<ubuntu::app_launch::Registry> m_ualRegistry;
102
88
103 friend class LauncherModelTest;
89 friend class LauncherModelTest;
104};
90};
plugins/Unity/Launcher/plugin.cpp+2−1
@@ -26,7 +26,7 @@
26// local
26// local
27#include "launchermodel.h"
27#include "launchermodel.h"
28#include "launcheritem.h"
28#include "launcheritem.h"
29−
29+#include "appdrawermodel.h"
30
30
31using namespace unity::shell::launcher;
31using namespace unity::shell::launcher;
32
32
@@ -46,4 +46,5 @@ void UnityLauncherPlugin::registerTypes(const char *uri)
46 qmlRegisterSingletonType<LauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
46 qmlRegisterSingletonType<LauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
47 qmlRegisterUncreatableType<LauncherItem>(uri, 0, 1, "LauncherItem", QStringLiteral("Can't create new Launcher Items in QML. Get them from the LauncherModel."));
47 qmlRegisterUncreatableType<LauncherItem>(uri, 0, 1, "LauncherItem", QStringLiteral("Can't create new Launcher Items in QML. Get them from the LauncherModel."));
48 qmlRegisterUncreatableType<QuickListModel>(uri, 0, 1, "QuickListModel", QStringLiteral("Can't create a QuickListModel in QML. Get them from the LauncherItems."));
48 qmlRegisterUncreatableType<QuickListModel>(uri, 0, 1, "QuickListModel", QStringLiteral("Can't create a QuickListModel in QML. Get them from the LauncherItems."));
49+ qmlRegisterType<AppDrawerModel>(uri, 0, 1, "AppDrawerModel");
49}
50}
plugins/Unity/Launcher/quicklistentry.cpp+11
@@ -19,6 +19,7 @@
19#include "quicklistentry.h"
19#include "quicklistentry.h"
20
20
21QuickListEntry::QuickListEntry()
21QuickListEntry::QuickListEntry()
22+ : m_hasSeparator(false)
22{
23{
23}
24}
24
25
@@ -57,6 +58,16 @@ bool QuickListEntry::clickable() const
57 return !m_actionId.isEmpty();
58 return !m_actionId.isEmpty();
58}
59}
59
60
61+void QuickListEntry::setHasSeparator(bool hasSeparator)
62+{
63+ m_hasSeparator = hasSeparator;
64+}
65+
66+bool QuickListEntry::hasSeparator() const
67+{
68+ return m_hasSeparator;
69+}
70+
60bool QuickListEntry::operator==(const QuickListEntry &other)
71bool QuickListEntry::operator==(const QuickListEntry &other)
61{
72{
62 return !other.actionId().isEmpty() && other.actionId() == m_actionId;
73 return !other.actionId().isEmpty() && other.actionId() == m_actionId;
plugins/Unity/Launcher/quicklistentry.h+4
@@ -37,12 +37,16 @@ public:
37
37
38 bool clickable() const;
38 bool clickable() const;
39
39
40+ void setHasSeparator(bool hasSeparator);
41+ bool hasSeparator() const;
42+
40 bool operator==(const QuickListEntry & other);
43 bool operator==(const QuickListEntry & other);
41
44
42private:
45private:
43 QString m_actionId;
46 QString m_actionId;
44 QString m_text;
47 QString m_text;
45 QString m_icon;
48 QString m_icon;
49+ bool m_hasSeparator;
46};
50};
47
51
48#endif // QUICKLISTENTRY
52#endif // QUICKLISTENTRY
plugins/Unity/Launcher/quicklistmodel.cpp+2
@@ -79,6 +79,8 @@ QVariant QuickListModel::data(const QModelIndex &index, int role) const
79 return m_list.at(index.row()).icon();
79 return m_list.at(index.row()).icon();
80 case RoleClickable:
80 case RoleClickable:
81 return m_list.at(index.row()).clickable();
81 return m_list.at(index.row()).clickable();
82+ case RoleHasSeparator:
83+ return m_list.at(index.row()).hasSeparator();
82 }
84 }
83 return QVariant();
85 return QVariant();
84}
86}
plugins/Unity/Launcher/ualwrapper.cppnew file+73
@@ -0,0 +1,73 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <QDebug>
18+
19+#include "ualwrapper.h"
20+
21+#include <ubuntu-app-launch/registry.h>
22+using namespace ubuntu::app_launch;
23+
24+UalWrapper::UalWrapper(QObject *parent):
25+ QObject(parent)
26+{
27+
28+}
29+
30+QStringList UalWrapper::installedApps()
31+{
32+ QStringList appIds;
33+ try {
34+ for (const std::shared_ptr<Application> &app : Registry::installedApps()) {
35+ if (!app->appId().package.value().empty()) {
36+ appIds << QString::fromStdString(app->appId().package.value() + "_" + app->appId().appname.value());
37+ } else {
38+ appIds << QString::fromStdString(app->appId().appname);
39+ }
40+ }
41+ } catch (const std::runtime_error &e) {
42+ qWarning() << "ubuntu-all-launch threw an exception listing apps:" << e.what();
43+ }
44+
45+ return appIds;
46+}
47+
48+UalWrapper::AppInfo UalWrapper::getApplicationInfo(const QString &appId)
49+{
50+ AppInfo info;
51+
52+ try {
53+ AppID ualAppId = AppID::find(appId.toStdString());
54+ if (ualAppId.empty()) {
55+ qWarning() << "Empty ualAppId result for" << appId;
56+ return info;
57+ }
58+
59+ std::shared_ptr<Application> ualApp;
60+ ualApp = Application::create(ualAppId, Registry::getDefault());
61+
62+ info.name = QString::fromStdString(ualApp->info()->name());
63+ info.icon = QString::fromStdString(ualApp->info()->iconPath());
64+ for (const std::string &keyword : ualApp->info()->keywords().value()) {
65+ info.keywords << QString::fromStdString(keyword);
66+ }
67+ info.valid = true;
68+ } catch (const std::runtime_error &e) {
69+ qWarning() << "ubuntu-app-launch threw an exception getting app info for appId:" << appId << ":" << e.what();
70+ }
71+
72+ return info;
73+}
plugins/Unity/Launcher/ualwrapper.hnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <QObject>
18+
19+class UalWrapper: public QObject
20+{
21+ Q_OBJECT
22+public:
23+ struct AppInfo {
24+ bool valid = false;
25+ QString name;
26+ QString icon;
27+ QStringList keywords;
28+ };
29+
30+ UalWrapper(QObject* parent = nullptr);
31+
32+ static QStringList installedApps();
33+ static AppInfo getApplicationInfo(const QString &appId);
34+
35+};
plugins/Utils/CMakeLists.txt+4
@@ -15,6 +15,10 @@ set(QMLPLUGIN_SRC
15 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
15 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
16 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
16 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
17 applicationsfiltermodel.cpp
17 applicationsfiltermodel.cpp
18+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/AppDrawerModelInterface.h
19+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
20+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
21+ appdrawerproxymodel.cpp
18 constants.cpp
22 constants.cpp
19 WindowInputMonitor.cpp
23 WindowInputMonitor.cpp
20 inputwatcher.cpp
24 inputwatcher.cpp
plugins/Utils/appdrawerproxymodel.cppnew file+189
@@ -0,0 +1,189 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "appdrawerproxymodel.h"
18+
19+#include <unity/shell/launcher/LauncherItemInterface.h>
20+
21+#include <QDebug>
22+
23+AppDrawerProxyModel::AppDrawerProxyModel(QObject *parent):
24+ QSortFilterProxyModel(parent)
25+{
26+ setSortRole(AppDrawerModelInterface::RoleName);
27+ setSortLocaleAware(true);
28+ sort(0);
29+
30+ connect(this, &QAbstractListModel::rowsInserted, this, &AppDrawerProxyModel::countChanged);
31+ connect(this, &QAbstractListModel::rowsRemoved, this, &AppDrawerProxyModel::countChanged);
32+ connect(this, &QAbstractListModel::layoutChanged, this, &AppDrawerProxyModel::countChanged);
33+}
34+
35+QAbstractItemModel *AppDrawerProxyModel::source() const
36+{
37+ return m_source;
38+}
39+
40+void AppDrawerProxyModel::setSource(QAbstractItemModel *source)
41+{
42+ if (m_source != source) {
43+ m_source = source;
44+ setSourceModel(m_source);
45+ setSortRole(m_sortBy == SortByAToZ ? AppDrawerModelInterface::RoleName : AppDrawerModelInterface::RoleUsage);
46+ connect(m_source, &QAbstractItemModel::rowsRemoved, this, &AppDrawerProxyModel::invalidateFilter);
47+ connect(m_source, &QAbstractItemModel::rowsInserted, this, &AppDrawerProxyModel::invalidateFilter);
48+ Q_EMIT sourceChanged();
49+ }
50+}
51+
52+AppDrawerProxyModel::GroupBy AppDrawerProxyModel::group() const
53+{
54+ return m_group;
55+}
56+
57+void AppDrawerProxyModel::setGroup(AppDrawerProxyModel::GroupBy group)
58+{
59+ if (m_group != group) {
60+ m_group = group;
61+ Q_EMIT groupChanged();
62+ invalidateFilter();
63+ }
64+}
65+
66+QString AppDrawerProxyModel::filterLetter() const
67+{
68+ return m_filterLetter;
69+}
70+
71+void AppDrawerProxyModel::setFilterLetter(const QString &filterLetter)
72+{
73+ if (m_filterLetter != filterLetter) {
74+ m_filterLetter = filterLetter;
75+ Q_EMIT filterLetterChanged();
76+ invalidateFilter();
77+ }
78+}
79+
80+QString AppDrawerProxyModel::filterString() const
81+{
82+ return m_filterString;
83+}
84+
85+void AppDrawerProxyModel::setFilterString(const QString &filterString)
86+{
87+ if (m_filterString != filterString) {
88+ m_filterString = filterString;
89+ Q_EMIT filterStringChanged();
90+ invalidateFilter();
91+ }
92+}
93+
94+AppDrawerProxyModel::SortBy AppDrawerProxyModel::sortBy() const
95+{
96+ return m_sortBy;
97+}
98+
99+void AppDrawerProxyModel::setSortBy(AppDrawerProxyModel::SortBy sortBy)
100+{
101+ if (m_sortBy != sortBy) {
102+ m_sortBy = sortBy;
103+ Q_EMIT sortByChanged();
104+ setSortRole(m_sortBy == SortByAToZ ? AppDrawerModelInterface::RoleName : AppDrawerModelInterface::RoleUsage);
105+ sort(0);
106+ }
107+}
108+
109+int AppDrawerProxyModel::count() const
110+{
111+ return rowCount();
112+}
113+
114+QVariant AppDrawerProxyModel::data(const QModelIndex &index, int role) const
115+{
116+ QModelIndex idx = mapToSource(index);
117+ if (role == Qt::UserRole) {
118+ QString name = m_source->data(idx, AppDrawerModelInterface::RoleName).toString();
119+ return name.length() > 0 ? QString(name.at(0)).toUpper() : QChar();
120+ }
121+ return m_source->data(idx, role);
122+}
123+
124+QHash<int, QByteArray> AppDrawerProxyModel::roleNames() const
125+{
126+ if (m_source) {
127+ QHash<int, QByteArray> roles = m_source->roleNames();
128+ roles.insert(Qt::UserRole, "letter");
129+ return roles;
130+ }
131+ return QHash<int, QByteArray>();
132+}
133+
134+bool AppDrawerProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
135+{
136+ Q_UNUSED(source_parent)
137+
138+ if (m_group == GroupByAToZ && source_row > 0) {
139+ QString currentName = m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString();
140+ QChar currentLetter = currentName.length() > 0 ? currentName.at(0) : QChar();
141+ QString previousName = m_source->data(m_source->index(source_row - 1,0 ), AppDrawerModelInterface::RoleName).toString();
142+ QChar previousLetter = previousName.length() > 0 ? previousName.at(0) : QChar();
143+ if (currentLetter.toLower() == previousLetter.toLower()) {
144+ return false;
145+ }
146+ } else if(m_group == GroupByAll && source_row > 0) {
147+ return false;
148+ }
149+ if (!m_filterLetter.isEmpty()) {
150+ QString currentName = m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString();
151+ QString currentLetter = currentName.length() > 0 ? QString(currentName.at(0)) : QString();
152+ if (currentLetter.toLower() != m_filterLetter.toLower()) {
153+ return false;
154+ }
155+ }
156+ if (!m_filterString.isEmpty()) {
157+ QStringList allWords = m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleKeywords).toStringList();
158+ allWords.prepend(m_source->data(m_source->index(source_row, 0), AppDrawerModelInterface::RoleName).toString());
159+ bool found = false;
160+ Q_FOREACH (const QString currentWord, allWords) {
161+ if (currentWord.toLower().startsWith(m_filterString.toLower())) {
162+ found = true;
163+ break;
164+ }
165+ }
166+ if (!found) {
167+ return false;
168+ }
169+ }
170+ return true;
171+}
172+
173+QString AppDrawerProxyModel::appId(int index) const
174+{
175+ if (index >= 0 && index < rowCount()) {
176+ QModelIndex sourceIndex = mapToSource(this->index(index, 0));
177+
178+ AppDrawerModelInterface* adm = dynamic_cast<AppDrawerModelInterface*>(m_source);
179+ if (adm) {
180+ return adm->data(sourceIndex, AppDrawerModelInterface::RoleAppId).toString();
181+ }
182+
183+ AppDrawerProxyModel* adpm = qobject_cast<AppDrawerProxyModel*>(m_source);
184+ if (adpm) {
185+ return adpm->appId(sourceIndex.row());
186+ }
187+ }
188+ return nullptr;
189+}
plugins/Utils/appdrawerproxymodel.hnew file+87
@@ -0,0 +1,87 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <QSortFilterProxyModel>
18+
19+#include <unity/shell/launcher/AppDrawerModelInterface.h>
20+
21+using namespace unity::shell::launcher;
22+
23+class AppDrawerProxyModel: public QSortFilterProxyModel
24+{
25+ Q_OBJECT
26+ Q_ENUMS(GroupBy)
27+ Q_ENUMS(SortBy)
28+ Q_PROPERTY(QAbstractItemModel* source READ source WRITE setSource NOTIFY sourceChanged)
29+ Q_PROPERTY(GroupBy group READ group WRITE setGroup NOTIFY groupChanged)
30+ Q_PROPERTY(QString filterLetter READ filterLetter WRITE setFilterLetter NOTIFY filterLetterChanged)
31+ Q_PROPERTY(QString filterString READ filterString WRITE setFilterString NOTIFY filterStringChanged)
32+ Q_PROPERTY(SortBy sortBy READ sortBy WRITE setSortBy NOTIFY sortByChanged)
33+ Q_PROPERTY(int count READ count NOTIFY countChanged)
34+
35+public:
36+ enum GroupBy {
37+ GroupByNone,
38+ GroupByAll,
39+ GroupByAToZ
40+ };
41+ enum SortBy {
42+ SortByAToZ,
43+ SortByUsage
44+ };
45+
46+ AppDrawerProxyModel(QObject* parent = nullptr);
47+
48+ QAbstractItemModel* source() const;
49+ void setSource(QAbstractItemModel* source);
50+
51+ GroupBy group() const;
52+ void setGroup(GroupBy group);
53+
54+ QString filterLetter() const;
55+ void setFilterLetter(const QString &filterLetter);
56+
57+ QString filterString() const;
58+ void setFilterString(const QString &filterString);
59+
60+ SortBy sortBy() const;
61+ void setSortBy(SortBy sortBy);
62+
63+ int count() const;
64+
65+ QVariant data(const QModelIndex &index, int role) const override;
66+ QHash<int, QByteArray> roleNames() const override;
67+
68+ Q_INVOKABLE QString appId(int index) const;
69+
70+protected:
71+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
72+
73+Q_SIGNALS:
74+ void sourceChanged();
75+ void groupChanged();
76+ void filterLetterChanged();
77+ void filterStringChanged();
78+ void sortByChanged();
79+ void countChanged();
80+
81+private:
82+ QAbstractItemModel* m_source = nullptr;
83+ GroupBy m_group = GroupByNone;
84+ QString m_filterLetter;
85+ QString m_filterString;
86+ SortBy m_sortBy = SortByAToZ;
87+};
plugins/Utils/plugin.cpp+2
@@ -39,6 +39,7 @@
39#include "deviceconfigparser.h"
39#include "deviceconfigparser.h"
40#include "globalfunctions.h"
40#include "globalfunctions.h"
41#include "URLDispatcher.h"
41#include "URLDispatcher.h"
42+#include "appdrawerproxymodel.h"
42
43
43static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
44static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
44{
45{
@@ -82,4 +83,5 @@ void UtilsPlugin::registerTypes(const char *uri)
82 qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
83 qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
83 qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions);
84 qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions);
84 qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher");
85 qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher");
86+ qmlRegisterType<AppDrawerProxyModel>(uri, 0, 1, "AppDrawerProxyModel");
85}
87}
po/aa.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/am.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ar.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/ast.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/az.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/be.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/bg.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/bn.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/br.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/bs.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/ca.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ca@valencia.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ce.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ckb.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/co.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/cs.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20"Language: cs\n"
20"Language: cs\n"
21
21
po/cy.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 && n != 11) ? "
17"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==2 ? 1 : (n != 8 && n != 11) ? "
18"2 : 3;\n"
18"2 : 3;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/da.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/de.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/el.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/en_AU.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/en_GB.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/eo.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/es.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/eu.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/fa.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/fi.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/fo.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/fr.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ga.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/gd.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
17"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : "
18"(n > 2 && n < 20) ? 2 : 3;\n"
18"(n > 2 && n < 20) ? 2 : 3;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21"Language: gd\n"
21"Language: gd\n"
22
22
po/gl.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/gv.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : (n == 2 ? 1 : 2);\n"
17"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : (n == 2 ? 1 : 2);\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/he.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/hi.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/hr.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/hu.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/hy.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ia.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/id.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/is.po+1−1
@@ -17,7 +17,7 @@ msgstr ""
17"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"
18"Content-Transfer-Encoding: 8bit\n"
19"Plural-Forms: nplurals=2; plural=n != 1;\n"
19"Plural-Forms: nplurals=2; plural=n != 1;\n"
20−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
20+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
21"X-Generator: Launchpad (build 18269)\n"
21"X-Generator: Launchpad (build 18269)\n"
22"Language: is\n"
22"Language: is\n"
23
23
po/it.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ja.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/km.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/kn.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ko.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ku.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ky.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/lo.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/lt.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"(n%100<10 || n%100>=20) ? 1 : 2;\n"
18"(n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/lv.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21"Language: lv\n"
21"Language: lv\n"
22
22
po/ml.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/mr.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ms.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/my.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/nb.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ne.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/nl.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/nn.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/oc.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/or.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n!=1;\n"
17"Plural-Forms: nplurals=2; plural=n!=1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/pa.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/pl.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
18"|| n%100>=20) ? 1 : 2;\n"
18"|| n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/pt.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/pt_BR.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ro.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
18"== 0) && (n != 0))) ? 2: 1));\n"
18"== 0) && (n != 0))) ? 2: 1));\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/ru.po+5−4
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
@@ -110,7 +110,7 @@ msgstr "Unity 8"
110
110
111#: qml/Components/KeyboardShortcutsOverlay.qml:62
111#: qml/Components/KeyboardShortcutsOverlay.qml:62
112msgid "PrtScr"
112msgid "PrtScr"
113−msgstr ""
113+msgstr "PrtScr"
114
114
115#: qml/Components/KeyboardShortcutsOverlay.qml:67
115#: qml/Components/KeyboardShortcutsOverlay.qml:67
116msgid "Takes a screenshot."
116msgid "Takes a screenshot."
@@ -142,7 +142,7 @@ msgstr "Предыдущая раскладка клавиатуры."
142
142
143#: qml/Components/KeyboardShortcutsOverlay.qml:118
143#: qml/Components/KeyboardShortcutsOverlay.qml:118
144msgid "Launcher"
144msgid "Launcher"
145−msgstr ""
145+msgstr "Панель запуска"
146
146
147#: qml/Components/KeyboardShortcutsOverlay.qml:125
147#: qml/Components/KeyboardShortcutsOverlay.qml:125
148msgid "Super (Hold)"
148msgid "Super (Hold)"
@@ -574,6 +574,7 @@ msgstr ""
574#: qml/Tutorial/TutorialLeft.qml:47
574#: qml/Tutorial/TutorialLeft.qml:47
575msgid "Short swipe from the left edge to open the launcher"
575msgid "Short swipe from the left edge to open the launcher"
576msgstr ""
576msgstr ""
577+"Кратко проведите пальцем от левого края, чтобы открыть панель запуска"
577
578
578#: qml/Tutorial/TutorialRight.qml:55
579#: qml/Tutorial/TutorialRight.qml:55
579msgid "Push your mouse against the right edge to view your open apps"
580msgid "Push your mouse against the right edge to view your open apps"
@@ -741,7 +742,7 @@ msgstr ""
741#: qml/Wizard/Pages/77-system-update.qml:76
742#: qml/Wizard/Pages/77-system-update.qml:76
742msgctxt "string identifying name of the update"
743msgctxt "string identifying name of the update"
743msgid "Ubuntu system"
744msgid "Ubuntu system"
744−msgstr ""
745+msgstr "Система Ubuntu"
745
746
746#: qml/Wizard/Pages/77-system-update.qml:83
747#: qml/Wizard/Pages/77-system-update.qml:83
747#, qt-format
748#, qt-format
po/shn.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=(n == 1) ? 0 : 1;\n"
17"Plural-Forms: nplurals=2; plural=(n == 1) ? 0 : 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/si.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/sk.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
17"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20"Language: sk\n"
20"Language: sk\n"
21
21
po/sl.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
18"n%100==4 ? 3 : 0);\n"
18"n%100==4 ? 3 : 0);\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/sq.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:06+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:34+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20"Language: sq\n"
20"Language: sq\n"
21
21
po/sr.po+1−1
@@ -17,7 +17,7 @@ msgstr ""
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
19"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
20−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
20+"X-Launchpad-Export-Date: 2016-11-23 06:35+0000\n"
21"X-Generator: Launchpad (build 18269)\n"
21"X-Generator: Launchpad (build 18269)\n"
22"Language: sr\n"
22"Language: sr\n"
23
23
po/sv.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20"Language: sv\n"
20"Language: sv\n"
21
21
po/sw.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ta.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20"Language: ta\n"
20"Language: ta\n"
21
21
po/te.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/th.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/tr.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:07+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/ug.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/uk.po+1−1
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
19+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
20"X-Generator: Launchpad (build 18269)\n"
20"X-Generator: Launchpad (build 18269)\n"
21
21
22#: plugins/LightDM/Greeter.cpp:123
22#: plugins/LightDM/Greeter.cpp:123
po/unity8.pot+10−10
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2016-11-16 10:44+0000\n"
11+"POT-Creation-Date: 2016-11-29 09:43+0000\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -22,16 +22,16 @@ msgstr ""
22msgid "Password: "
22msgid "Password: "
23msgstr ""
23msgstr ""
24
24
25−#: plugins/Unity/Launcher/launcheritem.cpp:49
25+#: plugins/Unity/Launcher/launcheritem.cpp:50
26−#: plugins/Unity/Launcher/launcheritem.cpp:108
26+#: plugins/Unity/Launcher/launcheritem.cpp:109
27msgid "Pin shortcut"
27msgid "Pin shortcut"
28msgstr ""
28msgstr ""
29
29
30−#: plugins/Unity/Launcher/launcheritem.cpp:54
30+#: plugins/Unity/Launcher/launcheritem.cpp:55
31msgid "Quit"
31msgid "Quit"
32msgstr ""
32msgstr ""
33
33
34−#: plugins/Unity/Launcher/launcheritem.cpp:108
34+#: plugins/Unity/Launcher/launcheritem.cpp:109
35msgid "Unpin shortcut"
35msgid "Unpin shortcut"
36msgstr ""
36msgstr ""
37
37
@@ -342,24 +342,24 @@ msgstr ""
342msgid "Reset"
342msgid "Reset"
343msgstr ""
343msgstr ""
344
344
345−#: qml/Dash/GenericScopeView.qml:545 qml/Dash/GenericScopeView.qml:716
345+#: qml/Dash/GenericScopeView.qml:547 qml/Dash/GenericScopeView.qml:718
346msgid "Show less"
346msgid "Show less"
347msgstr ""
347msgstr ""
348
348
349−#: qml/Dash/GenericScopeView.qml:545
349+#: qml/Dash/GenericScopeView.qml:547
350msgid "Show all"
350msgid "Show all"
351msgstr ""
351msgstr ""
352
352
353−#: qml/Dash/GenericScopeView.qml:576
353+#: qml/Dash/GenericScopeView.qml:578
354msgctxt "Label: Hint for dash search line edit"
354msgctxt "Label: Hint for dash search line edit"
355msgid "Search"
355msgid "Search"
356msgstr ""
356msgstr ""
357
357
358−#: qml/Dash/PageHeaderExtraPanel.qml:57
358+#: qml/Dash/PageHeaderExtraPanel.qml:67
359msgid "Recent Searches"
359msgid "Recent Searches"
360msgstr ""
360msgstr ""
361
361
362−#: qml/Dash/PageHeaderExtraPanel.qml:68
362+#: qml/Dash/PageHeaderExtraPanel.qml:78
363msgid "Clear All"
363msgid "Clear All"
364msgstr ""
364msgstr ""
365
365
po/ur.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/uz.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/vi.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/wo.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/xh.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/zh_CN.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/zh_HK.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20
20
21#: plugins/LightDM/Greeter.cpp:123
21#: plugins/LightDM/Greeter.cpp:123
po/zh_TW.po+1−1
@@ -15,7 +15,7 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2016-11-22 06:08+0000\n"
18+"X-Launchpad-Export-Date: 2016-11-23 06:36+0000\n"
19"X-Generator: Launchpad (build 18269)\n"
19"X-Generator: Launchpad (build 18269)\n"
20"Language: zh_TW\n"
20"Language: zh_TW\n"
21
21
qml/Components/BrightnessControl.qmlnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+import QMenuModel 0.1
20+import GlobalShortcut 1.0
21+
22+QtObject {
23+ objectName: "brightnessControl"
24+
25+ property GlobalShortcut brightnessUp: GlobalShortcut {
26+ shortcut: Qt.Key_MonBrightnessUp
27+ onTriggered: stepUp();
28+ }
29+
30+ property GlobalShortcut brightnessDown: GlobalShortcut {
31+ shortcut: Qt.Key_MonBrightnessDown
32+ onTriggered: stepDown();
33+ }
34+
35+ function stepUp() {
36+ actionGroup.brightness.updateState(MathUtils.clamp(actionGroup.brightness.state + 0.1, 0.01, 1.0));
37+ }
38+
39+ function stepDown() {
40+ actionGroup.brightness.updateState(MathUtils.clamp(actionGroup.brightness.state - 0.1, 0.01, 1.0));
41+ }
42+
43+ property QDBusActionGroup actionGroup: QDBusActionGroup {
44+ busType: DBus.SessionBus
45+ busName: "com.canonical.indicator.power"
46+ objectPath: "/com/canonical/indicator/power"
47+
48+ property variant brightness: action("brightness")
49+
50+ Component.onCompleted: {
51+ actionGroup.start();
52+ }
53+ }
54+}
qml/Components/KeyboardShortcutsOverlay.qml+13
@@ -173,6 +173,19 @@ Rectangle {
173 Layout.maximumWidth: maxTextSize
173 Layout.maximumWidth: maxTextSize
174 }
174 }
175
175
176+ Label {
177+ text: i18n.tr("Super + A")
178+ fontSize: "small"
179+ font.weight: Font.Medium
180+ }
181+ Label {
182+ text: i18n.tr("Opens the Application Drawer.")
183+ fontSize: "small"
184+ font.weight: Font.Light
185+ wrapMode: Text.Wrap
186+ Layout.maximumWidth: maxTextSize
187+ }
188+
176
189
177 // Scopes section
190 // Scopes section
178 Item { Layout.columnSpan: 2; height: units.gu(2) }
191 Item { Layout.columnSpan: 2; height: units.gu(2) }
qml/Components/LazyImage.qml+2
@@ -57,6 +57,7 @@ Item {
57 active: useUbuntuShape
57 active: useUbuntuShape
58 visible: opacity != 0
58 visible: opacity != 0
59 sourceComponent: UbuntuShape {
59 sourceComponent: UbuntuShape {
60+ aspect: UbuntuShape.Flat
60 backgroundColor: "#22FFFFFF"
61 backgroundColor: "#22FFFFFF"
61 }
62 }
62
63
@@ -92,6 +93,7 @@ Item {
92 visible: opacity != 0
93 visible: opacity != 0
93 sourceComponent: UbuntuShapeOverlay {
94 sourceComponent: UbuntuShapeOverlay {
94 property bool pressed: false
95 property bool pressed: false
96+ aspect: UbuntuShape.Flat
95 overlayColor: Qt.rgba(0, 0, 0, pressed ? 0.1 : 0)
97 overlayColor: Qt.rgba(0, 0, 0, pressed ? 0.1 : 0)
96 overlayRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
98 overlayRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
97 }
99 }
qml/Dash/DashPageHeader.qml+1−1
@@ -26,7 +26,6 @@ Item {
26 objectName: "pageHeader"
26 objectName: "pageHeader"
27 implicitHeight: headerContainer.height + signatureLineHeight
27 implicitHeight: headerContainer.height + signatureLineHeight
28 readonly property real signatureLineHeight: showSignatureLine ? units.gu(2.5) : headerBottomLine.height
28 readonly property real signatureLineHeight: showSignatureLine ? units.gu(2.5) : headerBottomLine.height
29− readonly property real headerDividerLuminance: Style.luminance(bottomBorder.color)
30
29
31 property int activeFiltersCount: 0
30 property int activeFiltersCount: 0
32 property bool scopeHasFilters: false
31 property bool scopeHasFilters: false
@@ -185,6 +184,7 @@ Item {
185
184
186 Column {
185 Column {
187 id: headersColumn
186 id: headersColumn
187+ objectName: "headersColumn"
188 anchors {
188 anchors {
189 left: parent.left
189 left: parent.left
190 right: parent.right
190 right: parent.right
qml/Dash/GenericScopeView.qml+4−2
@@ -243,8 +243,10 @@ FocusScope {
243
243
244 property Item seeAllButton: seeAll
244 property Item seeAllButton: seeAll
245
245
246+ readonly property bool forceNotExpandable: cardTool.template && cardTool.template["expandable"] === false
246 readonly property bool expandable: {
247 readonly property bool expandable: {
247 if (categoryView.model.count === 1) return false;
248 if (categoryView.model.count === 1) return false;
249+ if (forceNotExpandable) return false;
248 if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
250 if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
249 if (item && item.expandedHeight > item.collapsedHeight) return true;
251 if (item && item.expandedHeight > item.collapsedHeight) return true;
250 return false;
252 return false;
@@ -317,7 +319,7 @@ FocusScope {
317 }
319 }
318 }
320 }
319
321
320− readonly property bool expanded: baseItem.expanded || !baseItem.expandable
322+ readonly property bool expanded: !baseItem.forceNotExpandable && (baseItem.expanded || !baseItem.expandable)
321 height: expanded ? item.expandedHeight : item.collapsedHeight
323 height: expanded ? item.expandedHeight : item.collapsedHeight
322
324
323 source: {
325 source: {
@@ -657,7 +659,7 @@ FocusScope {
657 target: categoryView
659 target: categoryView
658
660
659 readonly property real contentY: categoryView.contentY - categoryView.originY
661 readonly property real contentY: categoryView.contentY - categoryView.originY
660− readonly property real headerDividerLuminance: categoryView.pageHeader.headerDividerLuminance
662+ readonly property color pullLabelColor: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
661 y: -contentY - units.gu(5)
663 y: -contentY - units.gu(5)
662
664
663 onRefresh: {
665 onRefresh: {
qml/Dash/PageHeaderExtraPanel.qml+10−11
@@ -43,6 +43,16 @@ Item {
43 dashNavigation.resetNavigation();
43 dashNavigation.resetNavigation();
44 }
44 }
45
45
46+ BorderImage {
47+ anchors {
48+ fill: parent
49+ leftMargin: -units.gu(1)
50+ rightMargin: -units.gu(1)
51+ bottomMargin: -units.gu(1)
52+ }
53+ source: "graphics/rectangular_dropshadow.sci"
54+ }
55+
46 Rectangle {
56 Rectangle {
47 color: "white"
57 color: "white"
48 anchors.fill: parent
58 anchors.fill: parent
@@ -188,15 +198,4 @@ Item {
188 onSingleSelectionFilterSelected: extraPanelOptionSelected()
198 onSingleSelectionFilterSelected: extraPanelOptionSelected()
189 }
199 }
190 }
200 }
191−
192− // This is outside the item
193− Image {
194− anchors {
195− top: parent.bottom
196− left: parent.left
197− right: parent.right
198− }
199− fillMode: Image.Stretch
200− source: "graphics/navigation_shadow.png"
201− }
202}
201}
qml/Dash/Previews/PreviewProgress.qml+1−1
@@ -28,7 +28,7 @@ import Ubuntu.DownloadDaemonListener 0.1
28PreviewWidget {
28PreviewWidget {
29 id: root
29 id: root
30
30
31− implicitHeight: progressBar.implicitHeight
31+ implicitHeight: progressBar.height
32 implicitWidth: progressBar.implicitWidth
32 implicitWidth: progressBar.implicitWidth
33
33
34 ProgressBar {
34 ProgressBar {
qml/Dash/PullToRefreshScopeStyle.qml+1−1
@@ -48,7 +48,7 @@ PullToRefreshStyle {
48 anchors.horizontalCenter: parent.horizontalCenter
48 anchors.horizontalCenter: parent.horizontalCenter
49 horizontalAlignment: Text.AlignHCenter
49 horizontalAlignment: Text.AlignHCenter
50 verticalAlignment: Text.AlignVCenter
50 verticalAlignment: Text.AlignVCenter
51− color: styledItem.headerDividerLuminance < 0.3 ? UbuntuColors.porcelain : UbuntuColors.jet
51+ color: styledItem.pullLabelColor
52 states: [
52 states: [
53 State {
53 State {
54 name: "pulling"
54 name: "pulling"
qml/Dash/ScopesListCategoryItem.qml+1
@@ -49,6 +49,7 @@ AbstractButton {
49 width: units.gu(5)
49 width: units.gu(5)
50 height: units.gu(5)
50 height: units.gu(5)
51 visible: !hideChildren
51 visible: !hideChildren
52+ aspect: UbuntuShape.Flat
52 sourceFillMode: UbuntuShape.PreserveAspectCrop
53 sourceFillMode: UbuntuShape.PreserveAspectCrop
53 source: Image {
54 source: Image {
54 id: shapeImage
55 id: shapeImage
qml/Dash/graphics/navigation_shadow@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/navigation_shadow_light@18.pngdeleted

Binary file not shown.

qml/Dash/graphics/rectangular_dropshadow@30.pngnew file

Binary file not shown.

qml/Dash/graphics/rectangular_dropshadow@30.scinew file+5
@@ -0,0 +1,5 @@
1+border.left: 30
2+border.top: 30
3+border.bottom: 30
4+border.right: 30
5+source: rectangular_dropshadow@30.png
qml/Launcher/BackgroundBlur.qmlnew file+81
@@ -0,0 +1,81 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+import QtGraphicalEffects 1.0
20+
21+Item {
22+ id: root
23+
24+ property int blurAmount: 32
25+ property Item sourceItem
26+ property rect blurRect: Qt.rect(0,0,0,0)
27+ property alias cached: fastBlur.cached
28+
29+ Rectangle {
30+ id: blurMask
31+ color: "yellow"
32+ x: blurRect.x
33+ y: blurRect.y
34+ width: blurRect.width
35+ height: blurRect.height
36+ }
37+
38+ ShaderEffect {
39+ id: maskedBlurEffect
40+ x: blurRect.x
41+ y: blurRect.y
42+ width: blurRect.width
43+ height: blurRect.height
44+
45+ property variant source: ShaderEffectSource {
46+ id: shaderEffectSource
47+ sourceItem: root.sourceItem
48+ hideSource: false
49+ sourceRect: root.blurRect
50+ }
51+
52+ property var mask: ShaderEffectSource {
53+ sourceItem: blurMask
54+ hideSource: true
55+ }
56+
57+ fragmentShader: "
58+ varying highp vec2 qt_TexCoord0;
59+ uniform sampler2D source;
60+ uniform sampler2D mask;
61+ void main(void)
62+ {
63+ highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
64+ highp vec4 maskColor = texture2D(mask, qt_TexCoord0);
65+
66+ sourceColor *= maskColor.a;
67+
68+ gl_FragColor = sourceColor;
69+ }"
70+ }
71+
72+ FastBlur {
73+ id: fastBlur
74+ x: blurRect.x
75+ y: blurRect.y
76+ width: blurRect.width
77+ height: blurRect.height
78+ source: maskedBlurEffect
79+ radius: Math.min(blurAmount, 128)
80+ }
81+ }
qml/Launcher/Drawer.qmlnew file+306
@@ -0,0 +1,306 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+import Unity.Launcher 0.1
20+import Utils 0.1
21+import "../Components"
22+import Qt.labs.settings 1.0
23+
24+FocusScope {
25+ id: root
26+
27+ property int panelWidth: 0
28+ readonly property bool moving: listLoader.item && listLoader.item.moving
29+
30+ signal applicationSelected(string appId)
31+
32+ property bool draggingHorizontally: false
33+ property int dragDistance: 0
34+
35+ onFocusChanged: {
36+ if (focus) {
37+ searchField.selectAll();
38+ }
39+ }
40+
41+ function focusInput() {
42+ searchField.selectAll();
43+ searchField.focus = true;
44+ }
45+
46+ Settings {
47+ property alias selectedTab: sections.selectedIndex
48+ }
49+
50+ MouseArea {
51+ anchors.fill: parent
52+ hoverEnabled: true
53+ acceptedButtons: Qt.AllButtons
54+ onWheel: wheel.accepted = true
55+ }
56+
57+ Rectangle {
58+ anchors.fill: parent
59+ color: "#BF000000"
60+
61+ AppDrawerModel {
62+ id: appDrawerModel
63+ }
64+
65+ AppDrawerProxyModel {
66+ id: sortProxyModel
67+ source: appDrawerModel
68+ filterString: searchField.displayText
69+ sortBy: AppDrawerProxyModel.SortByAToZ
70+ }
71+
72+ Item {
73+ id: contentContainer
74+ anchors.fill: parent
75+ anchors.leftMargin: root.panelWidth
76+
77+ TextField {
78+ id: searchField
79+ anchors { left: parent.left; top: parent.top; right: parent.right; margins: units.gu(1) }
80+ placeholderText: i18n.tr("Search…")
81+ focus: true
82+ onAccepted: {
83+ if (searchField.displayText != "" && listLoader.item && listLoader.item.currentItem) {
84+ root.applicationSelected(listLoader.item.getFirstAppId());
85+ }
86+ }
87+ }
88+
89+ Item {
90+ id: sectionsContainer
91+ anchors { left: parent.left; top: searchField.bottom; right: parent.right; }
92+ height: sections.height
93+ clip: true
94+ z: 2
95+
96+ Sections {
97+ id: sections
98+ width: parent.width
99+ actions: [
100+ Action {
101+ text: i18n.ctr("Apps sorted alphabetically", "A-Z")
102+ // TODO: Disabling this for now as we don't get the right input from u-a-l yet.
103+// },
104+// Action {
105+// text: i18n.ctr("Most used apps", "Most used")
106+ }
107+ ]
108+
109+ Rectangle {
110+ anchors.bottom: parent.bottom
111+ height: units.dp(1)
112+ color: 'gray'
113+ width: contentContainer.width
114+ }
115+ }
116+ }
117+
118+ Loader {
119+ id: listLoader
120+ anchors { left: parent.left; top: sectionsContainer.bottom; right: parent.right; bottom: parent.bottom; leftMargin: units.gu(1); rightMargin: units.gu(1) }
121+ sourceComponent: {
122+ switch (sections.selectedIndex) {
123+ case 0: return aToZComponent;
124+ case 1: return mostUsedComponent;
125+ }
126+ }
127+ Binding {
128+ target: listLoader.item || null
129+ property: "objectName"
130+ value: "drawerItemList"
131+ }
132+ }
133+
134+ MouseArea {
135+ parent: listLoader.item ? listLoader.item : null
136+ anchors.fill: parent
137+ propagateComposedEvents: true
138+ property int oldX: 0
139+ onPressed: {
140+ oldX = mouseX;
141+ }
142+ onMouseXChanged: {
143+ var diff = oldX - mouseX;
144+ root.draggingHorizontally |= diff > units.gu(2);
145+ if (!root.draggingHorizontally) {
146+ return;
147+ }
148+ propagateComposedEvents = false;
149+ parent.interactive = false;
150+ root.dragDistance += diff;
151+ oldX = mouseX
152+ }
153+ onReleased: {
154+ if (root.draggingHorizontally) {
155+ root.draggingHorizontally = false;
156+ parent.interactive = true;
157+ }
158+ reactivateTimer.start();
159+ }
160+ Timer {
161+ id: reactivateTimer
162+ interval: 0
163+ onTriggered: parent.propagateComposedEvents = true;
164+ }
165+ }
166+
167+ Component {
168+ id: mostUsedComponent
169+ DrawerListView {
170+
171+ header: MoreAppsHeader {
172+ width: parent.width
173+ height: units.gu(6)
174+ }
175+
176+ model: AppDrawerProxyModel {
177+ source: sortProxyModel
178+ group: AppDrawerProxyModel.GroupByAll
179+ sortBy: AppDrawerProxyModel.SortByUsage
180+ }
181+
182+ delegate: UbuntuShape {
183+ width: parent.width
184+ color: "#20ffffff"
185+ aspect: UbuntuShape.Flat
186+ // NOTE: Cannot use gridView.rows here as it would evaluate to 0 at first and only update later,
187+ // which messes up the ListView.
188+ height: (Math.ceil(mostUsedGridView.model.count / mostUsedGridView.columns) * mostUsedGridView.delegateHeight) + units.gu(2)
189+
190+ readonly property string appId: model.appId
191+
192+ DrawerGridView {
193+ id: mostUsedGridView
194+ anchors.fill: parent
195+ topMargin: units.gu(1)
196+ bottomMargin: units.gu(1)
197+ clip: true
198+
199+ model: sortProxyModel
200+
201+ delegateWidth: units.gu(8)
202+ delegateHeight: units.gu(10)
203+ delegate: drawerDelegateComponent
204+ }
205+ }
206+ }
207+ }
208+
209+ Component {
210+ id: aToZComponent
211+ DrawerListView {
212+
213+ header: MoreAppsHeader {
214+ width: parent.width
215+ height: units.gu(6)
216+ }
217+
218+ model: AppDrawerProxyModel {
219+ source: sortProxyModel
220+ sortBy: AppDrawerProxyModel.SortByAToZ
221+ group: AppDrawerProxyModel.GroupByAToZ
222+ }
223+
224+ delegate: UbuntuShape {
225+ width: parent.width
226+ color: "#20ffffff"
227+ aspect: UbuntuShape.Flat
228+
229+ readonly property string appId: model.appId
230+
231+ // NOTE: Cannot use gridView.rows here as it would evaluate to 0 at first and only update later,
232+ // which messes up the ListView.
233+ height: (Math.ceil(gridView.model.count / gridView.columns) * gridView.delegateHeight) +
234+ categoryNameLabel.implicitHeight + units.gu(2)
235+
236+ Label {
237+ id: categoryNameLabel
238+ anchors { left: parent.left; top: parent.top; right: parent.right; margins: units.gu(1) }
239+ text: model.letter
240+ }
241+
242+ DrawerGridView {
243+ id: gridView
244+ anchors { left: parent.left; top: categoryNameLabel.bottom; right: parent.right; topMargin: units.gu(1) }
245+ height: rows * delegateHeight
246+
247+ interactive: false
248+
249+ model: AppDrawerProxyModel {
250+ id: categoryModel
251+ source: sortProxyModel
252+ filterLetter: model.letter
253+ }
254+ delegateWidth: units.gu(8)
255+ delegateHeight: units.gu(10)
256+ delegate: drawerDelegateComponent
257+ }
258+ }
259+ }
260+ }
261+ }
262+
263+ Component {
264+ id: drawerDelegateComponent
265+ AbstractButton {
266+ width: GridView.view.cellWidth
267+ height: units.gu(10)
268+ objectName: "drawerItem_" + model.appId
269+
270+ onClicked: root.applicationSelected(model.appId)
271+
272+ Column {
273+ width: units.gu(8)
274+ anchors.horizontalCenter: parent.horizontalCenter
275+ height: childrenRect.height
276+ spacing: units.gu(1)
277+
278+ UbuntuShape {
279+ id: appIcon
280+ width: units.gu(6)
281+ height: 7.5 / 8 * width
282+ anchors.horizontalCenter: parent.horizontalCenter
283+ backgroundMode: UbuntuShape.SolidColor
284+ backgroundColor: UbuntuColors.lightGrey
285+ radius: "medium"
286+ borderSource: 'undefined'
287+ source: Image {
288+ id: sourceImage
289+ sourceSize.width: appIcon.width
290+ source: model.icon
291+ }
292+ sourceFillMode: UbuntuShape.PreserveAspectCrop
293+ }
294+
295+ Label {
296+ text: model.name
297+ width: parent.width
298+ horizontalAlignment: Text.AlignHCenter
299+ fontSize: "small"
300+ elide: Text.ElideRight
301+ }
302+ }
303+ }
304+ }
305+ }
306+}
qml/Launcher/DrawerGridView.qmlnew file+47
@@ -0,0 +1,47 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import "../Components"
19+
20+Item {
21+ id: root
22+
23+ property int delegateWidth: units.gu(10)
24+ property int delegateHeight: units.gu(10)
25+ property alias delegate: gridView.delegate
26+ property alias model: gridView.model
27+ property alias interactive: gridView.interactive
28+
29+ property alias header: gridView.header
30+ property alias topMargin: gridView.topMargin
31+ property alias bottomMargin: gridView.bottomMargin
32+
33+ readonly property int columns: width / delegateWidth
34+ readonly property int rows: Math.ceil(gridView.model.count / root.columns)
35+
36+ GridView {
37+ id: gridView
38+ anchors.fill: parent
39+ leftMargin: spacing
40+
41+ readonly property int overflow: width - (root.columns * root.delegateWidth)
42+ readonly property real spacing: overflow / (root.columns)
43+
44+ cellWidth: root.delegateWidth + spacing
45+ cellHeight: root.delegateHeight
46+ }
47+}
qml/Launcher/DrawerListView.qmlnew file+32
@@ -0,0 +1,32 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+import "../Components"
20+
21+ListView {
22+ id: root
23+ anchors.fill: parent
24+ topMargin: units.gu(1)
25+ bottomMargin: units.gu(1)
26+ spacing: units.gu(1)
27+ clip: true
28+
29+ function getFirstAppId() {
30+ return model.appId(0);
31+ }
32+}
qml/Launcher/Launcher.qml+173−31
@@ -27,10 +27,12 @@ FocusScope {
27 property bool lockedVisible: false
27 property bool lockedVisible: false
28 property bool available: true // can be used to disable all interactions
28 property bool available: true // can be used to disable all interactions
29 property alias inverted: panel.inverted
29 property alias inverted: panel.inverted
30+ property Item blurSource: null
31+ property int topPanelHeight: 0
32+ property bool drawerEnabled: true
30
33
31 property int panelWidth: units.gu(10)
34 property int panelWidth: units.gu(10)
32 property int dragAreaWidth: units.gu(1)
35 property int dragAreaWidth: units.gu(1)
33− property int minimizeDistance: units.gu(26)
34 property real progress: dragArea.dragging && dragArea.touchPosition.x > panelWidth ?
36 property real progress: dragArea.dragging && dragArea.touchPosition.x > panelWidth ?
35 (width * (dragArea.touchPosition.x-panelWidth) / (width - panelWidth)) : 0
37 (width * (dragArea.touchPosition.x-panelWidth) / (width - panelWidth)) : 0
36
38
@@ -43,13 +45,11 @@ FocusScope {
43 readonly property alias shortcutHintsShown: panel.shortcutHintsShown
45 readonly property alias shortcutHintsShown: panel.shortcutHintsShown
44
46
45 readonly property bool shown: panel.x > -panel.width
47 readonly property bool shown: panel.x > -panel.width
48+ readonly property bool drawerShown: drawer.x == 0
46
49
47 // emitted when an application is selected
50 // emitted when an application is selected
48 signal launcherApplicationSelected(string appId)
51 signal launcherApplicationSelected(string appId)
49
52
50− // emitted when the apps dash should be shown because of a swipe gesture
51− signal dash()
52−
53 // emitted when the dash icon in the launcher has been tapped
53 // emitted when the dash icon in the launcher has been tapped
54 signal showDashHome()
54 signal showDashHome()
55
55
@@ -62,6 +62,9 @@ FocusScope {
62 }
62 }
63
63
64 onSuperPressedChanged: {
64 onSuperPressedChanged: {
65+ if (state == "drawer")
66+ return;
67+
65 if (superPressed) {
68 if (superPressed) {
66 superPressTimer.start();
69 superPressTimer.start();
67 superLongPressTimer.start();
70 superLongPressTimer.start();
@@ -132,7 +135,7 @@ FocusScope {
132 }
135 }
133
136
134 function pushEdge(amount) {
137 function pushEdge(amount) {
135− if (root.state === "") {
138+ if (root.state === "" || root.state == "visible" || root.state == "visibleTemporary") {
136 edgeBarrier.push(amount);
139 edgeBarrier.push(amount);
137 }
140 }
138 }
141 }
@@ -143,6 +146,22 @@ FocusScope {
143 switchToNextState("visible")
146 switchToNextState("visible")
144 }
147 }
145
148
149+ function openDrawer(focusInputField) {
150+ if (!drawerEnabled) {
151+ return;
152+ }
153+
154+ panel.shortcutHintsShown = false;
155+ superPressTimer.stop();
156+ superLongPressTimer.stop();
157+ root.focus = true;
158+ drawer.focus = true;
159+ if (focusInputField) {
160+ drawer.focusInput();
161+ }
162+ switchToNextState("drawer")
163+ }
164+
146 Keys.onPressed: {
165 Keys.onPressed: {
147 switch (event.key) {
166 switch (event.key) {
148 case Qt.Key_Backtab:
167 case Qt.Key_Backtab:
@@ -278,7 +297,7 @@ FocusScope {
278 InverseMouseArea {
297 InverseMouseArea {
279 id: closeMouseArea
298 id: closeMouseArea
280 anchors.fill: panel
299 anchors.fill: panel
281− enabled: root.state == "visible" && (!root.lockedVisible || panel.highlightIndex >= -1)
300+ enabled: root.state == "visible" || root.state == "drawer"
282 visible: enabled
301 visible: enabled
283 onPressed: {
302 onPressed: {
284 mouse.accepted = false;
303 mouse.accepted = false;
@@ -307,23 +326,61 @@ FocusScope {
307 }
326 }
308 }
327 }
309
328
310− EdgeBarrier {
329+ BackgroundBlur {
311− id: edgeBarrier
330+ id: backgroundBlur
312− edge: Qt.LeftEdge
331+ anchors.fill: parent
332+ anchors.topMargin: root.inverted ? 0 : -root.topPanelHeight
333+ visible: root.blurSource && drawer.x > -drawer.width
334+ blurAmount: units.gu(6)
335+ sourceItem: root.blurSource
336+ blurRect: Qt.rect(panel.width,
337+ root.topPanelHeight,
338+ drawer.width + drawer.x - panel.width,
339+ height - root.topPanelHeight)
340+ cached: drawer.moving
341+ }
342+
343+ Drawer {
344+ id: drawer
345+ objectName: "drawer"
346+ anchors {
313− target: parent
347+ top: parent.top
314− enabled: root.available
348+ topMargin: root.inverted ? root.topPanelHeight : 0
349+ bottom: parent.bottom
350+ right: parent.left
351+ }
352+ width: Math.min(root.width, units.gu(90)) * .9
353+ panelWidth: panel.width
354+ visible: x > -width
355+
356+ Behavior on anchors.rightMargin {
357+ enabled: !dragArea.dragging && !launcherDragArea.drag.active && panel.animate && !drawer.draggingHorizontally
358+ NumberAnimation {
359+ duration: 300
360+ easing.type: Easing.OutCubic
361+ }
362+ }
363+
364+ onApplicationSelected: {
365+ root.hide();
366+ root.launcherApplicationSelected(appId)
367+ root.focus = false;
368+ }
369+
370+ Keys.onEscapePressed: {
315− onPassed: { root.switchToNextState("visibleTemporary"); }
371+ switchToNextState("");
316− material: Component {
372+ root.focus = false;
317− Item {
373+ }
318− Rectangle {
374+
319− width: parent.height
375+ onDragDistanceChanged: {
320− height: parent.width
376+ anchors.rightMargin = Math.max(-drawer.width, anchors.rightMargin + dragDistance);
321− rotation: -90
377+ }
322− anchors.centerIn: parent
378+ onDraggingHorizontallyChanged: {
323− gradient: Gradient {
379+ if (!draggingHorizontally) {
324− GradientStop { position: 0.0; color: Qt.rgba(panel.color.r, panel.color.g, panel.color.b, .5)}
380+ if (drawer.x < -units.gu(10)) {
325− GradientStop { position: 1.0; color: Qt.rgba(panel.color.r,panel.color.g,panel.color.b,0)}
381+ root.hide();
326− }
382+ } else {
383+ root.openDrawer();
327 }
384 }
328 }
385 }
329 }
386 }
@@ -332,7 +389,7 @@ FocusScope {
332 LauncherPanel {
389 LauncherPanel {
333 id: panel
390 id: panel
334 objectName: "launcherPanel"
391 objectName: "launcherPanel"
335− enabled: root.available && root.state == "visible" || root.state == "visibleTemporary"
392+ enabled: root.available && (root.state == "visible" || root.state == "visibleTemporary" || root.state == "drawer")
336 width: root.panelWidth
393 width: root.panelWidth
337 anchors {
394 anchors {
338 top: parent.top
395 top: parent.top
@@ -394,6 +451,38 @@ FocusScope {
394 }
451 }
395 }
452 }
396
453
454+ EdgeBarrier {
455+ id: edgeBarrier
456+ edge: Qt.LeftEdge
457+ target: parent
458+ enabled: root.available
459+ onProgressChanged: {
460+ if (progress > .5 && root.state != "visibleTemporary" && root.state != "drawer" && root.state != "visible") {
461+ root.switchToNextState("visibleTemporary");
462+ }
463+ }
464+ onPassed: {
465+ if (root.drawerEnabled) {
466+ root.switchToNextState("drawer");
467+ }
468+ }
469+
470+ material: Component {
471+ Item {
472+ Rectangle {
473+ width: parent.height
474+ height: parent.width
475+ rotation: -90
476+ anchors.centerIn: parent
477+ gradient: Gradient {
478+ GradientStop { position: 0.0; color: Qt.rgba(panel.color.r, panel.color.g, panel.color.b, .5)}
479+ GradientStop { position: 1.0; color: Qt.rgba(panel.color.r,panel.color.g,panel.color.b,0)}
480+ }
481+ }
482+ }
483+ }
484+ }
485+
397 SwipeArea {
486 SwipeArea {
398 id: dragArea
487 id: dragArea
399 objectName: "launcherDragArea"
488 objectName: "launcherDragArea"
@@ -405,25 +494,62 @@ FocusScope {
405 width: root.dragAreaWidth
494 width: root.dragAreaWidth
406 height: root.height
495 height: root.height
407
496
497+ function easeInOutCubic(t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 }
498+
499+ property var lastDragPoints: []
500+
501+ function dragDirection() {
502+ if (lastDragPoints.length < 5) {
503+ return "unknown";
504+ }
505+
506+ var toRight = true;
507+ var toLeft = true;
508+ for (var i = lastDragPoints.length - 5; i < lastDragPoints.length; i++) {
509+ if (toRight && lastDragPoints[i] < lastDragPoints[i-1]) {
510+ toRight = false;
511+ }
512+ if (toLeft && lastDragPoints[i] > lastDragPoints[i-1]) {
513+ toLeft = false;
514+ }
515+ }
516+ return toRight ? "right" : toLeft ? "left" : "unknown";
517+ }
518+
408 onDistanceChanged: {
519 onDistanceChanged: {
409− if (!dragging || launcher.state == "visible")
520+ if (dragging && launcher.state != "visible" && launcher.state != "drawer") {
410− return;
521+ panel.x = -panel.width + Math.min(Math.max(0, distance), panel.width);
522+ }
411
523
524+ if (root.drawerEnabled && dragging && launcher.state != "drawer") {
525+ lastDragPoints.push(distance)
526+ var drawerHintDistance = panel.width + units.gu(1)
527+ if (distance < drawerHintDistance) {
528+ drawer.anchors.rightMargin = -Math.min(Math.max(0, distance), drawer.width);
529+ } else {
412− panel.x = -panel.width + Math.min(Math.max(0, distance), panel.width);
530+ var linearDrawerX = Math.min(Math.max(0, distance - drawerHintDistance), drawer.width);
531+ var linearDrawerProgress = linearDrawerX / (drawer.width)
532+ var easedDrawerProgress = easeInOutCubic(linearDrawerProgress);
533+ drawer.anchors.rightMargin = -(drawerHintDistance + easedDrawerProgress * (drawer.width - drawerHintDistance));
534+ }
535+ }
413 }
536 }
414
537
415 onDraggingChanged: {
538 onDraggingChanged: {
416 if (!dragging) {
539 if (!dragging) {
417 if (distance > panel.width / 2) {
540 if (distance > panel.width / 2) {
418− root.switchToNextState("visible")
541+ if (root.drawerEnabled && distance > panel.width * 3 && dragDirection() !== "left") {
419− if (distance > minimizeDistance) {
542+ root.switchToNextState("drawer");
420− root.dash();
543+ root.focus = true;
544+ } else {
545+ root.switchToNextState("visible");
421 }
546 }
422 } else if (root.state === "") {
547 } else if (root.state === "") {
423 // didn't drag far enough. rollback
548 // didn't drag far enough. rollback
424− root.switchToNextState("")
549+ root.switchToNextState("");
425 }
550 }
426 }
551 }
552+ lastDragPoints = [];
427 }
553 }
428 }
554 }
429
555
@@ -434,6 +560,10 @@ FocusScope {
434 target: panel
560 target: panel
435 x: -root.panelWidth
561 x: -root.panelWidth
436 }
562 }
563+ PropertyChanges {
564+ target: drawer
565+ anchors.rightMargin: 0
566+ }
437 },
567 },
438 State {
568 State {
439 name: "visible"
569 name: "visible"
@@ -441,6 +571,18 @@ FocusScope {
441 target: panel
571 target: panel
442 x: -root.x // so we never go past panelWidth, even when teased by tutorial
572 x: -root.x // so we never go past panelWidth, even when teased by tutorial
443 }
573 }
574+ PropertyChanges {
575+ target: drawer
576+ anchors.rightMargin: 0
577+ }
578+ },
579+ State {
580+ name: "drawer"
581+ extend: "visible"
582+ PropertyChanges {
583+ target: drawer
584+ anchors.rightMargin: -drawer.width + root.x // so we never go past panelWidth, even when teased by tutorial
585+ }
444 },
586 },
445 State {
587 State {
446 name: "visibleTemporary"
588 name: "visibleTemporary"
qml/Launcher/LauncherDelegate.qml+1
@@ -22,6 +22,7 @@ Item {
22
22
23 property int itemIndex: 0
23 property int itemIndex: 0
24 property string iconName
24 property string iconName
25+ property string name
25 property int count: 0
26 property int count: 0
26 property bool countVisible: false
27 property bool countVisible: false
27 property int progress: -1
28 property int progress: -1
qml/Launcher/LauncherPanel.qml+80−3
@@ -15,6 +15,7 @@
15 */
15 */
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18+import QtQml.StateMachine 1.0 as DSM
18import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
19import Unity.Launcher 0.1
20import Unity.Launcher 0.1
20import Ubuntu.Components.Popups 1.3
21import Ubuntu.Components.Popups 1.3
@@ -31,7 +32,7 @@ Rectangle {
31 property bool dragging: false
32 property bool dragging: false
32 property bool moving: launcherListView.moving || launcherListView.flicking
33 property bool moving: launcherListView.moving || launcherListView.flicking
33 property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state === "open" || dndArea.pressed
34 property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state === "open" || dndArea.pressed
34− || mouseEventEater.containsMouse || dashItem.hovered
35+ || dndArea.containsMouse || dashItem.hovered
35 property int highlightIndex: -2
36 property int highlightIndex: -2
36 property bool shortcutHintsShown: false
37 property bool shortcutHintsShown: false
37
38
@@ -40,7 +41,7 @@ Rectangle {
40 signal kbdNavigationCancelled()
41 signal kbdNavigationCancelled()
41
42
42 onXChanged: {
43 onXChanged: {
43− if (quickList.state == "open") {
44+ if (quickList.state === "open") {
44 quickList.state = ""
45 quickList.state = ""
45 }
46 }
46 }
47 }
@@ -69,7 +70,6 @@ Rectangle {
69 id: mouseEventEater
70 id: mouseEventEater
70 anchors.fill: parent
71 anchors.fill: parent
71 acceptedButtons: Qt.AllButtons
72 acceptedButtons: Qt.AllButtons
72− hoverEnabled: true
73 onWheel: wheel.accepted = true;
73 onWheel: wheel.accepted = true;
74 }
74 }
75
75
@@ -225,6 +225,7 @@ Rectangle {
225 // the right app when running autopilot tests for
225 // the right app when running autopilot tests for
226 // multiple apps.
226 // multiple apps.
227 readonly property string appId: model.appId
227 readonly property string appId: model.appId
228+ name: model.name
228 itemIndex: index
229 itemIndex: index
229 itemHeight: launcherListView.itemHeight
230 itemHeight: launcherListView.itemHeight
230 itemWidth: launcherListView.itemWidth
231 itemWidth: launcherListView.itemWidth
@@ -399,6 +400,7 @@ Rectangle {
399 id: dndArea
400 id: dndArea
400 objectName: "dndArea"
401 objectName: "dndArea"
401 acceptedButtons: Qt.LeftButton | Qt.RightButton
402 acceptedButtons: Qt.LeftButton | Qt.RightButton
403+ hoverEnabled: true
402 anchors {
404 anchors {
403 fill: parent
405 fill: parent
404 topMargin: launcherListView.topMargin
406 topMargin: launcherListView.topMargin
@@ -795,6 +797,7 @@ Rectangle {
795 highlightColor: !model.clickable ? quickList.color : undefined // make disabled items visually unclickable
797 highlightColor: !model.clickable ? quickList.color : undefined // make disabled items visually unclickable
796 divider.colorFrom: UbuntuColors.inkstone
798 divider.colorFrom: UbuntuColors.inkstone
797 divider.colorTo: UbuntuColors.inkstone
799 divider.colorTo: UbuntuColors.inkstone
800+ divider.visible: model.hasSeparator
798
801
799 Label {
802 Label {
800 id: label
803 id: label
@@ -828,4 +831,78 @@ Rectangle {
828 }
831 }
829 }
832 }
830 }
833 }
834+
835+ Tooltip {
836+ id: tooltipShape
837+ objectName: "tooltipShape"
838+
839+ visible: tooltipShownState.active
840+ rotation: root.rotation
841+ y: itemCenter - (height / 2)
842+
843+ anchors {
844+ left: root.inverted ? undefined : parent.right
845+ right: root.inverted ? parent.left : undefined
846+ margins: units.gu(1)
847+ }
848+
849+ readonly property var hoveredItem: dndArea.containsMouse ? launcherListView.itemAt(dndArea.mouseX, dndArea.mouseY + launcherListView.realContentY) : null
850+ readonly property int itemCenter: !hoveredItem ? 0 : root.mapFromItem(hoveredItem, 0, 0).y + (hoveredItem.height / 2) + hoveredItem.offset
851+
852+ text: !hoveredItem ? "" : hoveredItem.name
853+ }
854+
855+ DSM.StateMachine {
856+ id: tooltipStateMachine
857+ initialState: tooltipHiddenState
858+ running: true
859+
860+ DSM.State {
861+ id: tooltipHiddenState
862+
863+ DSM.SignalTransition {
864+ targetState: tooltipShownState
865+ signal: tooltipShape.hoveredItemChanged
866+ // !dndArea.pressed allows us to filter out touch input events
867+ guard: tooltipShape.hoveredItem !== null && !dndArea.pressed && !root.moving
868+ }
869+ }
870+
871+ DSM.State {
872+ id: tooltipShownState
873+
874+ DSM.SignalTransition {
875+ targetState: tooltipHiddenState
876+ signal: tooltipShape.hoveredItemChanged
877+ guard: tooltipShape.hoveredItem === null
878+ }
879+
880+ DSM.SignalTransition {
881+ targetState: tooltipDismissedState
882+ signal: dndArea.onPressed
883+ }
884+
885+ DSM.SignalTransition {
886+ targetState: tooltipDismissedState
887+ signal: quickList.stateChanged
888+ guard: quickList.state === "open"
889+ }
890+ }
891+
892+ DSM.State {
893+ id: tooltipDismissedState
894+
895+ DSM.SignalTransition {
896+ targetState: tooltipHiddenState
897+ signal: dndArea.positionChanged
898+ guard: quickList.state != "open" && !dndArea.pressed && !dndArea.moving
899+ }
900+
901+ DSM.SignalTransition {
902+ targetState: tooltipHiddenState
903+ signal: dndArea.exited
904+ guard: quickList.state != "open"
905+ }
906+ }
907+ }
831}
908}
qml/Launcher/MoreAppsHeader.qmlnew file+46
@@ -0,0 +1,46 @@
1+import QtQuick 2.4
2+import Ubuntu.Components 1.3
3+
4+AbstractButton {
5+ id: root
6+
7+ onClicked: {
8+ // TODO: Make this point to the snappy store as soon as we stop landing to vivid
9+ Qt.openUrlExternally("scope://com.canonical.scopes.clickstore")
10+ }
11+
12+ UbuntuShape {
13+ width: parent.width
14+ height: parent.height - units.gu(1)
15+ color: "#20ffffff"
16+ aspect: UbuntuShape.Flat
17+
18+ Row {
19+ anchors.fill: parent
20+ anchors.margins: units.gu(1)
21+ spacing: units.gu(1)
22+
23+ Icon {
24+ height: units.gu(2.2)
25+ width: height
26+ name: "stock_application"
27+ anchors.verticalCenter: parent.verticalCenter
28+ color: "white"
29+ }
30+
31+ Label {
32+ text: i18n.tr("More apps in the store")
33+ anchors.verticalCenter: parent.verticalCenter
34+ fontSize: "small"
35+ }
36+
37+ Icon {
38+ height: units.gu(2.5)
39+ width: height
40+ anchors.verticalCenter: parent.verticalCenter
41+ name: "go-next"
42+ color: "white"
43+ }
44+ }
45+ }
46+}
qml/Launcher/Tooltip.qmlnew file+72
@@ -0,0 +1,72 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import Ubuntu.Components 1.3
19+
20+UbuntuShape {
21+ id: root
22+
23+ // This property holds the delay (milliseconds) after which the tool tip is shown.
24+ // A tooltip with a negative delay is shown immediately. The default value is 500 ms.
25+ property int delay: 500
26+
27+ // This property holds the text shown on the tool tip.
28+ property alias text: label.text
29+
30+ aspect: UbuntuShape.Flat
31+ color: theme.palette.normal.background
32+ width: label.implicitWidth + units.gu(4)
33+ height: label.implicitHeight + units.gu(2)
34+ opacity: 0
35+
36+ Image {
37+ anchors {
38+ right: parent.left
39+ rightMargin: -units.dp(4)
40+ verticalCenter: parent.verticalCenter
41+ }
42+ source: "graphics/quicklist_tooltip.png"
43+ rotation: 90
44+ }
45+
46+ Label {
47+ id: label
48+ anchors.centerIn: parent
49+ color: theme.palette.normal.backgroundText
50+ }
51+
52+ states: [
53+ State {
54+ name: "visible"
55+ when: root.visible
56+ PropertyChanges {
57+ target: root
58+ opacity: 0.95
59+ }
60+ }
61+ ]
62+
63+ transitions: [
64+ Transition {
65+ from: ""; to: "visible"
66+ SequentialAnimation {
67+ PauseAnimation { duration: root.delay }
68+ UbuntuNumberAnimation { target: root; property: "opacity"; duration: UbuntuAnimation.BriskDuration }
69+ }
70+ }
71+ ]
72+}
qml/Shell.qml+13−37
@@ -278,8 +278,6 @@ StyledItem {
278
278
279 dragAreaWidth: shell.edgeSize
279 dragAreaWidth: shell.edgeSize
280 background: wallpaperResolver.background
280 background: wallpaperResolver.background
281− leftEdgeDragProgress: !greeter || greeter.locked || !tutorial.launcherLongSwipeEnabled ? 0 :
282− Math.max(0, (launcher.dragDistance * (stage.width - launcher.panelWidth) / stage.width) - launcher.panelWidth)
283
281
284 applicationManager: ApplicationManager
282 applicationManager: ApplicationManager
285 topLevelSurfaceList: topLevelSurfaceList
283 topLevelSurfaceList: topLevelSurfaceList
@@ -301,18 +299,14 @@ StyledItem {
301
299
302 interactive: (!greeter || !greeter.shown)
300 interactive: (!greeter || !greeter.shown)
303 && panel.indicators.fullyClosed
301 && panel.indicators.fullyClosed
304− && launcher.progress == 0
305 && !notifications.useModal
302 && !notifications.useModal
306
303
307 onInteractiveChanged: { if (interactive) { focus = true; } }
304 onInteractiveChanged: { if (interactive) { focus = true; } }
308
305
309 leftMargin: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0
306 leftMargin: shell.usageScenario == "desktop" && !settings.autohideLauncher ? launcher.panelWidth: 0
310 suspended: greeter.shown
307 suspended: greeter.shown
311− keepDashRunning: launcher.shown || launcher.dashSwipe
312 altTabPressed: physicalKeysMapper.altTabPressed
308 altTabPressed: physicalKeysMapper.altTabPressed
313 oskEnabled: shell.oskEnabled
309 oskEnabled: shell.oskEnabled
314−
315− // TODO: This is not implemented yet in the new stage...
316 spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
310 spreadEnabled: tutorial.spreadEnabled && (!greeter || (!greeter.hasLockedApp && !greeter.shown))
317 }
311 }
318 }
312 }
@@ -325,7 +319,7 @@ StyledItem {
325 topMargin: panel.panelHeight
319 topMargin: panel.panelHeight
326 leftMargin: launcher.lockedVisible ? launcher.panelWidth : 0
320 leftMargin: launcher.lockedVisible ? launcher.panelWidth : 0
327 }
321 }
328− z: notifications.useModal || panel.indicators.shown || wizard.active || tutorial.running ? overlay.z + 1 : overlay.z - 1
322+ z: notifications.useModal || panel.indicators.shown || wizard.active || tutorial.running || launcher.drawerShown ? overlay.z + 1 : overlay.z - 1
329 }
323 }
330
324
331 Loader {
325 Loader {
@@ -347,7 +341,6 @@ StyledItem {
347 enabled: panel.indicators.fullyClosed // hides OSK when panel is open
341 enabled: panel.indicators.fullyClosed // hides OSK when panel is open
348 hides: [launcher, panel.indicators]
342 hides: [launcher, panel.indicators]
349 tabletMode: shell.usageScenario != "phone"
343 tabletMode: shell.usageScenario != "phone"
350− launcherOffset: launcher.progress
351 forcedUnlock: wizard.active || shell.mode === "full-shell"
344 forcedUnlock: wizard.active || shell.mode === "full-shell"
352 background: wallpaperResolver.cachedBackground
345 background: wallpaperResolver.cachedBackground
353 hasCustomBackground: wallpaperResolver.hasCustomBackground
346 hasCustomBackground: wallpaperResolver.hasCustomBackground
@@ -436,19 +429,6 @@ StyledItem {
436 }
429 }
437 }
430 }
438
431
439− function showDash() {
440− if (greeter.notifyShowingDashFromDrag()) {
441− launcher.fadeOut();
442− }
443−
444− if (!greeter.locked && tutorial.launcherLongSwipeEnabled
445− && (ApplicationManager.focusedApplicationId != "unity8-dash" || stage.spreadShown)) {
446− ApplicationManager.requestFocusApplication("unity8-dash")
447− launcher.fadeOut();
448− stage.closeSpread();
449− }
450− }
451−
452 Item {
432 Item {
453 id: overlay
433 id: overlay
454 z: 10
434 z: 10
@@ -465,6 +445,7 @@ StyledItem {
465 && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked)
445 && ((!greeter || !greeter.locked) || AccountsService.enableIndicatorsWhileLocked)
466 && (!greeter || !greeter.hasLockedApp)
446 && (!greeter || !greeter.hasLockedApp)
467 && !shell.waitingOnGreeter
447 && !shell.waitingOnGreeter
448+ && settings.enableIndicatorMenu
468 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
449 width: parent.width > units.gu(60) ? units.gu(40) : parent.width
469
450
470 minimizedPanelHeight: units.gu(3)
451 minimizedPanelHeight: units.gu(3)
@@ -498,15 +479,6 @@ StyledItem {
498 id: launcher
479 id: launcher
499 objectName: "launcher"
480 objectName: "launcher"
500
481
501− /*
502− * Since the Dash doesn't have the same controll over surfaces that the
503− * Shell does, it can't slowly move the scope out of the way, as the shell
504− * does with apps, and the dash is show instantly. This allows for some
505− * leeway and prevents accidental home swipes.
506− */
507− readonly property real offset: shell.focusedApplicationId == "unity8-dash" ? units.gu(12) : 0
508− readonly property bool dashSwipe: progress > offset
509−
510 anchors.top: parent.top
482 anchors.top: parent.top
511 anchors.topMargin: inverted ? 0 : panel.panelHeight
483 anchors.topMargin: inverted ? 0 : panel.panelHeight
512 anchors.bottom: parent.bottom
484 anchors.bottom: parent.bottom
@@ -522,14 +494,11 @@ StyledItem {
522 superTabPressed: physicalKeysMapper.superTabPressed
494 superTabPressed: physicalKeysMapper.superTabPressed
523 panelWidth: units.gu(settings.launcherWidth)
495 panelWidth: units.gu(settings.launcherWidth)
524 lockedVisible: shell.usageScenario == "desktop" && !settings.autohideLauncher && !panel.fullscreenMode
496 lockedVisible: shell.usageScenario == "desktop" && !settings.autohideLauncher && !panel.fullscreenMode
497+ blurSource: greeter.shown ? greeter : stages
498+ topPanelHeight: panel.panelHeight
499+ drawerEnabled: !greeter.shown
525
500
526 onShowDashHome: showHome()
501 onShowDashHome: showHome()
527− onDash: showDash()
528− onDashSwipeChanged: {
529− if (dashSwipe) {
530− dash.setCurrentScope(0, false, true)
531− }
532− }
533 onLauncherApplicationSelected: {
502 onLauncherApplicationSelected: {
534 greeter.notifyUserRequestedApp();
503 greeter.notifyUserRequestedApp();
535 shell.activateApplication(appId);
504 shell.activateApplication(appId);
@@ -545,6 +514,12 @@ StyledItem {
545 }
514 }
546 }
515 }
547
516
517+ GlobalShortcut {
518+ shortcut: Qt.MetaModifier | Qt.Key_A
519+ onTriggered: {
520+ launcher.openDrawer(true);
521+ }
522+ }
548 GlobalShortcut {
523 GlobalShortcut {
549 shortcut: Qt.AltModifier | Qt.Key_F1
524 shortcut: Qt.AltModifier | Qt.Key_F1
550 onTriggered: {
525 onTriggered: {
@@ -786,8 +761,9 @@ StyledItem {
786 Behavior on opacity { UbuntuNumberAnimation {} }
761 Behavior on opacity { UbuntuNumberAnimation {} }
787 }
762 }
788
763
789− // non-visual object
764+ // non-visual objects
790 KeymapSwitcher {}
765 KeymapSwitcher {}
766+ BrightnessControl {}
791
767
792 Rectangle {
768 Rectangle {
793 id: shutdownFadeOutRectangle
769 id: shutdownFadeOutRectangle
qml/Stage/DecoratedWindow.qml+1−1
@@ -149,7 +149,7 @@ FocusScope {
149
149
150 WindowDecoration {
150 WindowDecoration {
151 id: decoration
151 id: decoration
152− target: root.parent || null
152+ closeButtonVisible: root.application.appId !== "unity8-dash"
153 objectName: "appWindowDecoration"
153 objectName: "appWindowDecoration"
154 anchors { left: parent.left; top: parent.top; right: parent.right }
154 anchors { left: parent.left; top: parent.top; right: parent.right }
155 height: units.gu(3)
155 height: units.gu(3)
qml/Stage/MoveHandler.qml+8
@@ -54,6 +54,11 @@ QtObject {
54 property bool nearBottomLeftCorner: target.maximizedBottomLeft
54 property bool nearBottomLeftCorner: target.maximizedBottomLeft
55 property bool nearBottomRightCorner: target.maximizedBottomRight
55 property bool nearBottomRightCorner: target.maximizedBottomRight
56
56
57+ property Timer mouseDownTimer: Timer {
58+ interval: 175
59+ onTriggered: Mir.cursorName = "grabbing"
60+ }
61+
57 function resetEdges() {
62 function resetEdges() {
58 nearLeftEdge = false;
63 nearLeftEdge = false;
59 nearRightEdge = false;
64 nearRightEdge = false;
@@ -93,14 +98,17 @@ QtObject {
93 }
98 }
94
99
95 priv.dragging = true;
100 priv.dragging = true;
101+ priv.mouseDownTimer.start();
96 } else {
102 } else {
97 priv.dragging = false;
103 priv.dragging = false;
104+ priv.mouseDownTimer.stop();
98 Mir.cursorName = "";
105 Mir.cursorName = "";
99 }
106 }
100 }
107 }
101
108
102 function handlePositionChanged(mouse, sensingPoints) {
109 function handlePositionChanged(mouse, sensingPoints) {
103 if (priv.dragging) {
110 if (priv.dragging) {
111+ priv.mouseDownTimer.stop();
104 Mir.cursorName = "grabbing";
112 Mir.cursorName = "grabbing";
105
113
106 // restore from maximized when dragging away from edges/corners; guard against inadvertent changes when going into maximized state
114 // restore from maximized when dragging away from edges/corners; guard against inadvertent changes when going into maximized state
qml/Stage/Stage.qml+24−9
@@ -36,7 +36,6 @@ FocusScope {
36 property url background
36 property url background
37 property int dragAreaWidth
37 property int dragAreaWidth
38 property bool interactive
38 property bool interactive
39− property bool keepDashRunning: true
40 property real nativeHeight
39 property real nativeHeight
41 property real nativeWidth
40 property real nativeWidth
42 property QtObject orientations
41 property QtObject orientations
@@ -50,7 +49,6 @@ FocusScope {
50
49
51 // Configuration
50 // Configuration
52 property string mode: "staged"
51 property string mode: "staged"
53− property real leftEdgeDragProgress: 0
54
52
55 // Used by the tutorial code
53 // Used by the tutorial code
56 readonly property real rightEdgeDragProgress: rightEdgeDragArea.dragging ? rightEdgeDragArea.progress : 0 // How far left the stage has been dragged
54 readonly property real rightEdgeDragProgress: rightEdgeDragArea.dragging ? rightEdgeDragArea.progress : 0 // How far left the stage has been dragged
@@ -92,7 +90,9 @@ FocusScope {
92
90
93 onAltTabPressedChanged: {
91 onAltTabPressedChanged: {
94 if (altTabPressed) {
92 if (altTabPressed) {
93+ if (root.spreadEnabled) {
95− altTabDelayTimer.start();
94+ altTabDelayTimer.start();
95+ }
96 } else {
96 } else {
97 // Alt Tab has been released, did we already go to spread?
97 // Alt Tab has been released, did we already go to spread?
98 if (priv.goneToSpread) {
98 if (priv.goneToSpread) {
@@ -127,7 +127,9 @@ FocusScope {
127 function updateFocusedAppOrientation() { /* TODO */ }
127 function updateFocusedAppOrientation() { /* TODO */ }
128 function updateFocusedAppOrientationAnimated() { /* TODO */}
128 function updateFocusedAppOrientationAnimated() { /* TODO */}
129 function pushRightEdge(amount) {
129 function pushRightEdge(amount) {
130+ if (root.spreadEnabled) {
130− edgeBarrier.push(amount);
131+ edgeBarrier.push(amount);
132+ }
131 }
133 }
132
134
133 function closeSpread() {
135 function closeSpread() {
@@ -168,6 +170,7 @@ FocusScope {
168 GlobalShortcut {
170 GlobalShortcut {
169 id: showSpreadShortcut
171 id: showSpreadShortcut
170 shortcut: Qt.MetaModifier|Qt.Key_W
172 shortcut: Qt.MetaModifier|Qt.Key_W
173+ active: root.spreadEnabled
171 onTriggered: priv.goneToSpread = true
174 onTriggered: priv.goneToSpread = true
172 }
175 }
173
176
@@ -410,7 +413,7 @@ FocusScope {
410 // in staged mode, when it switches to Windowed mode it will suddenly
413 // in staged mode, when it switches to Windowed mode it will suddenly
411 // resume all those apps at once. We might want to avoid that.
414 // resume all those apps at once. We might want to avoid that.
412 value: root.mode === "windowed"
415 value: root.mode === "windowed"
413− || (isDash && root.keepDashRunning)
416+ || isDash
414 || (!root.suspended && model.application && priv.focusedAppDelegate &&
417 || (!root.suspended && model.application && priv.focusedAppDelegate &&
415 (priv.focusedAppDelegate.appId === model.application.appId ||
418 (priv.focusedAppDelegate.appId === model.application.appId ||
416 priv.mainStageAppId === model.application.appId ||
419 priv.mainStageAppId === model.application.appId ||
@@ -1056,7 +1059,6 @@ FocusScope {
1056 sideStageX: sideStage.x
1059 sideStageX: sideStage.x
1057 itemIndex: appDelegate.itemIndex
1060 itemIndex: appDelegate.itemIndex
1058 nextInStack: priv.nextInStack
1061 nextInStack: priv.nextInStack
1059− leftEdgeDragProgress: root.leftEdgeDragProgress
1060 }
1062 }
1061
1063
1062 StagedRightEdgeMaths {
1064 StagedRightEdgeMaths {
@@ -1530,9 +1532,21 @@ FocusScope {
1530 onRequestedHeightChanged: oldRequestedHeight = requestedHeight
1532 onRequestedHeightChanged: oldRequestedHeight = requestedHeight
1531
1533
1532 onCloseClicked: { appDelegate.close(); }
1534 onCloseClicked: { appDelegate.close(); }
1535+ onMaximizeClicked: {
1536+ if (appDelegate.canBeMaximized) {
1533− onMaximizeClicked: appDelegate.anyMaximized ? appDelegate.restoreFromMaximized() : appDelegate.maximize();
1537+ appDelegate.anyMaximized ? appDelegate.restoreFromMaximized() : appDelegate.maximize();
1538+ }
1539+ }
1540+ onMaximizeHorizontallyClicked: {
1541+ if (appDelegate.canBeMaximizedHorizontally) {
1534− onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
1542+ appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
1543+ }
1544+ }
1545+ onMaximizeVerticallyClicked: {
1546+ if (appDelegate.canBeMaximizedVertically) {
1535− onMaximizeVerticallyClicked: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
1547+ appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
1548+ }
1549+ }
1536 onMinimizeClicked: appDelegate.minimize()
1550 onMinimizeClicked: appDelegate.minimize()
1537 onDecorationPressed: { appDelegate.focus = true; }
1551 onDecorationPressed: { appDelegate.focus = true; }
1538 onDecorationReleased: fakeRectangle.commit();
1552 onDecorationReleased: fakeRectangle.commit();
@@ -1789,6 +1803,7 @@ FocusScope {
1789 direction: Direction.Leftwards
1803 direction: Direction.Leftwards
1790 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
1804 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
1791 width: root.dragAreaWidth
1805 width: root.dragAreaWidth
1806+ enabled: root.spreadEnabled
1792
1807
1793 property var gesturePoints: []
1808 property var gesturePoints: []
1794 property bool cancelled: false
1809 property bool cancelled: false
qml/Stage/StageMaths.qml+2−7
@@ -12,7 +12,6 @@ QtObject {
12 property int sideStageWidth: 0
12 property int sideStageWidth: 0
13 property int sideStageX: sceneWidth
13 property int sideStageX: sceneWidth
14 property bool animateX: false
14 property bool animateX: false
15− property int leftEdgeDragProgress: 0
16
15
17 property int stage: ApplicationInfoInterface.MainStage
16 property int stage: ApplicationInfoInterface.MainStage
18 property var thisDelegate: null
17 property var thisDelegate: null
@@ -26,10 +25,6 @@ QtObject {
26 // of the last focused order.
25 // of the last focused order.
27 readonly property int itemZ: {
26 readonly property int itemZ: {
28 // only shuffle when we've got a main and side stage
27 // only shuffle when we've got a main and side stage
29− if (thisDelegate.isDash && thisDelegate != mainStageDelegate && leftEdgeDragProgress > 0) {
30− return -1; // Keep the dash behind all other apps for the left edge gesture
31− }
32−
33 if (!sideStageDelegate) return itemIndex;
28 if (!sideStageDelegate) return itemIndex;
34
29
35 // don't shuffle indexes greater than "actives or next"
30 // don't shuffle indexes greater than "actives or next"
@@ -64,12 +59,12 @@ QtObject {
64
59
65 property int itemX: {
60 property int itemX: {
66 if (mainStageDelegate == thisDelegate) {
61 if (mainStageDelegate == thisDelegate) {
67− return thisDelegate.isDash ? 0 : leftEdgeDragProgress;
62+ return 0
68 }
63 }
69 if (sideStageDelegate == thisDelegate) {
64 if (sideStageDelegate == thisDelegate) {
70 return sideStageX;
65 return sideStageX;
71 }
66 }
72− return thisDelegate.isDash && leftEdgeDragProgress > 0 ? 0 : sceneWidth;
67+ return sceneWidth;
73 }
68 }
74 Behavior on itemX { enabled: root.animateX; UbuntuNumberAnimation {} }
69 Behavior on itemX { enabled: root.animateX; UbuntuNumberAnimation {} }
75
70
qml/Stage/WindowDecoration.qml+4−5
@@ -22,7 +22,7 @@ MouseArea {
22 id: root
22 id: root
23 clip: true
23 clip: true
24
24
25− property Item target // appDelegate
25+ property alias closeButtonVisible: buttons.closeButtonShown
26 property alias title: titleLabel.text
26 property alias title: titleLabel.text
27 property alias maximizeButtonShown: buttons.maximizeButtonShown
27 property alias maximizeButtonShown: buttons.maximizeButtonShown
28 property bool active: false
28 property bool active: false
@@ -40,7 +40,7 @@ MouseArea {
40 signal maximizeVerticallyClicked()
40 signal maximizeVerticallyClicked()
41
41
42 onDoubleClicked: {
42 onDoubleClicked: {
43− if (target.canBeMaximized && mouse.button == Qt.LeftButton) {
43+ if (mouse.button == Qt.LeftButton) {
44 root.maximizeClicked();
44 root.maximizeClicked();
45 }
45 }
46 }
46 }
@@ -77,9 +77,8 @@ MouseArea {
77 onCloseClicked: root.closeClicked();
77 onCloseClicked: root.closeClicked();
78 onMinimizeClicked: root.minimizeClicked();
78 onMinimizeClicked: root.minimizeClicked();
79 onMaximizeClicked: root.maximizeClicked();
79 onMaximizeClicked: root.maximizeClicked();
80− onMaximizeHorizontallyClicked: if (root.target.canBeMaximizedHorizontally) root.maximizeHorizontallyClicked();
80+ onMaximizeHorizontallyClicked: root.maximizeHorizontallyClicked();
81− onMaximizeVerticallyClicked: if (root.target.canBeMaximizedVertically) root.maximizeVerticallyClicked();
81+ onMaximizeVerticallyClicked: root.maximizeVerticallyClicked();
82− closeButtonShown: root.target.appId !== "unity8-dash"
83 }
82 }
84
83
85 Label {
84 Label {
qml/Tutorial/TutorialLeftLong.qml+1−1
@@ -25,7 +25,7 @@ TutorialPage {
25
25
26 // Unlike other tutorials, this one can't be skipped before we show it, so
26 // Unlike other tutorials, this one can't be skipped before we show it, so
27 // only set opacityOverride if we're already shown.
27 // only set opacityOverride if we're already shown.
28− opacityOverride: shown ? 1 - launcher.dragDistance / launcher.minimizeDistance : 1
28+ opacityOverride: shown ? 1 - launcher.dragDistance / (launcher.panelWidth * 3) : 1
29
29
30 mouseArea {
30 mouseArea {
31 anchors.leftMargin: launcher.dragAreaWidth
31 anchors.leftMargin: launcher.dragAreaWidth
tests/autopilot/unity8/dash.py+3−3
@@ -163,9 +163,9 @@ class Dash(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
163 search_button.globalRect.x + search_button.width / 2,
163 search_button.globalRect.x + search_button.width / 2,
164 search_button.globalRect.y + search_button.height / 2)
164 search_button.globalRect.y + search_button.height / 2)
165 self.pointing_device.click()
165 self.pointing_device.click()
166− headerContainer = current_header.select_single(
166+ headersColumn = current_header.select_single(
167− objectName="headerContainer")
167+ objectName="headersColumn")
168− headerContainer.contentY.wait_for(0)
168+ headersColumn.y.wait_for(0)
169 keyboard.type(query)
169 keyboard.type(query)
170 self.select_single(
170 self.select_single(
171 objectName="processingIndicator").visible.wait_for(False)
171 objectName="processingIndicator").visible.wait_for(False)
tests/autopilot/unity8/greeter/__init__.py+1−1
@@ -94,4 +94,4 @@ class Greeter(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
94
94
95 def get_prompt(self):
95 def get_prompt(self):
96 return self.select_single(
96 return self.select_single(
97− ubuntuuitoolkit.TextField, objectName='passwordInput')
97+ ubuntuuitoolkit.TextField, objectName='promptField')
tests/autopilot/unity8/shell/__init__.py+2
@@ -25,6 +25,8 @@ from functools import wraps
25import ubuntuuitoolkit
25import ubuntuuitoolkit
26from autopilot import logging as autopilot_logging
26from autopilot import logging as autopilot_logging
27from autopilot import input
27from autopilot import input
28+import gi
29+gi.require_version('Notify', '0.7')
28from gi.repository import Notify
30from gi.repository import Notify
29
31
30from unity8 import (
32from unity8 import (
tests/autopilot/unity8/shell/tests/__init__.py+4−1
@@ -156,7 +156,10 @@ class UnityTestCase(AutopilotTestCase):
156 def _setup_grid_size(self, scale_divisor):
156 def _setup_grid_size(self, scale_divisor):
157 """Use the grid size that may be supplied or use the default."""
157 """Use the grid size that may be supplied or use the default."""
158 if getattr(self, 'grid_unit_px', 0) == 0:
158 if getattr(self, 'grid_unit_px', 0) == 0:
159+ if os.getenv('GRID_UNIT_PX') == None:
160+ self.grid_size = 8
161+ else:
159− self.grid_size = int(os.getenv('GRID_UNIT_PX'))
162+ self.grid_size = int(os.getenv('GRID_UNIT_PX'))
160 else:
163 else:
161 self.grid_size = int(self.grid_unit_px / scale_divisor)
164 self.grid_size = int(self.grid_unit_px / scale_divisor)
162 self._environment["GRID_UNIT_PX"] = str(self.grid_size)
165 self._environment["GRID_UNIT_PX"] = str(self.grid_size)
tests/autopilot/unity8/shell/tests/test_helpers.py+2−1
@@ -129,7 +129,8 @@ class DashAppsHelperTestCase(tests.DashBaseTestCase):
129 available_applications = [
129 available_applications = [
130 'Title.2.0', 'Title.2.1', 'Title.2.2', 'Title.2.3', 'Title.2.4',
130 'Title.2.0', 'Title.2.1', 'Title.2.2', 'Title.2.3', 'Title.2.4',
131 'Title.2.5', 'Title.2.6', 'Title.2.7', 'Title.2.8', 'Title.2.9',
131 'Title.2.5', 'Title.2.6', 'Title.2.7', 'Title.2.8', 'Title.2.9',
132− 'Title.2.10', 'Title.2.11', 'Title.2.12']
132+ 'Title.2.10', 'Title.2.11', 'Title.2.12', 'Title.2.13', 'Title.2.14',
133+ 'Title.2.15', 'Title.2.16', 'Title.2.17', 'Title.2.18']
133
134
134 def setUp(self):
135 def setUp(self):
135 # Set up the fake scopes before launching unity.
136 # Set up the fake scopes before launching unity.
tests/autopilot/unity8/shell/tests/test_notifications.py+9−9
@@ -143,7 +143,7 @@ class InteractiveNotificationBase(NotificationsBase):
143 )
143 )
144
144
145 get_notification = lambda: notify_list.wait_select_single(
145 get_notification = lambda: notify_list.wait_select_single(
146− 'Notification', objectName='notification1')
146+ 'Notification', objectName='notification0')
147 notification = get_notification()
147 notification = get_notification()
148
148
149 notification.pointing_device.click_object(
149 notification.pointing_device.click_object(
@@ -185,7 +185,7 @@ class InteractiveNotificationBase(NotificationsBase):
185 # verify and interact with the triggered snap-decision notification
185 # verify and interact with the triggered snap-decision notification
186 notify_list = self._get_notifications_list()
186 notify_list = self._get_notifications_list()
187 get_notification = lambda: notify_list.wait_select_single(
187 get_notification = lambda: notify_list.wait_select_single(
188− 'Notification', objectName='notification1')
188+ 'Notification', objectName='notification0')
189 notification = get_notification()
189 notification = get_notification()
190 self._assert_notification(
190 self._assert_notification(
191 notification, summary, body, False, False, 1.0)
191 notification, summary, body, False, False, 1.0)
@@ -234,7 +234,7 @@ class InteractiveNotificationBase(NotificationsBase):
234 # verify and interact with the triggered snap-decision notification
234 # verify and interact with the triggered snap-decision notification
235 notify_list = self._get_notifications_list()
235 notify_list = self._get_notifications_list()
236 get_notification = lambda: notify_list.wait_select_single(
236 get_notification = lambda: notify_list.wait_select_single(
237− 'Notification', objectName='notification1')
237+ 'Notification', objectName='notification0')
238 notification = get_notification()
238 notification = get_notification()
239 self._assert_notification(
239 self._assert_notification(
240 notification, summary, body, True, False, 1.0)
240 notification, summary, body, True, False, 1.0)
@@ -282,7 +282,7 @@ class InteractiveNotificationBase(NotificationsBase):
282 # verify and interact with the triggered snap-decision notification
282 # verify and interact with the triggered snap-decision notification
283 notify_list = self._get_notifications_list()
283 notify_list = self._get_notifications_list()
284 get_notification = lambda: notify_list.wait_select_single(
284 get_notification = lambda: notify_list.wait_select_single(
285− 'Notification', objectName='notification1')
285+ 'Notification', objectName='notification0')
286 notification = get_notification()
286 notification = get_notification()
287 self._assert_notification(
287 self._assert_notification(
288 notification, summary, body, True, False, 1.0)
288 notification, summary, body, True, False, 1.0)
@@ -445,7 +445,7 @@ class EphemeralNotificationsTests(NotificationsBase):
445 notification.show()
445 notification.show()
446
446
447 notification = lambda: notify_list.wait_select_single(
447 notification = lambda: notify_list.wait_select_single(
448− 'Notification', objectName='notification1')
448+ 'Notification', objectName='notification0')
449 self._assert_notification(
449 self._assert_notification(
450 notification(),
450 notification(),
451 summary,
451 summary,
@@ -478,7 +478,7 @@ class EphemeralNotificationsTests(NotificationsBase):
478 notification.show()
478 notification.show()
479
479
480 notification = lambda: notify_list.wait_select_single(
480 notification = lambda: notify_list.wait_select_single(
481− 'Notification', objectName='notification1')
481+ 'Notification', objectName='notification0')
482 self._assert_notification(
482 self._assert_notification(
483 notification(),
483 notification(),
484 summary,
484 summary,
@@ -590,7 +590,7 @@ class EphemeralNotificationsTests(NotificationsBase):
590 notification.show()
590 notification.show()
591
591
592 notification = notify_list.wait_select_single(
592 notification = notify_list.wait_select_single(
593− 'Notification', objectName='notification1')
593+ 'Notification', objectName='notification0')
594
594
595 self._assert_notification(
595 self._assert_notification(
596 notification,
596 notification,
@@ -614,7 +614,7 @@ class EphemeralNotificationsTests(NotificationsBase):
614 notification.show()
614 notification.show()
615
615
616 notification = notify_list.wait_select_single(
616 notification = notify_list.wait_select_single(
617− 'Notification', objectName='notification1')
617+ 'Notification', objectName='notification0')
618
618
619 self._assert_notification(notification, summary, '', False, False, 1.0)
619 self._assert_notification(notification, summary, '', False, False, 1.0)
620
620
@@ -683,7 +683,7 @@ class EphemeralNotificationsTests(NotificationsBase):
683 notification.show()
683 notification.show()
684
684
685 get_notification = lambda: notify_list.wait_select_single(
685 get_notification = lambda: notify_list.wait_select_single(
686− 'Notification', objectName='notification1')
686+ 'Notification', objectName='notification0')
687
687
688 self._assert_notification(
688 self._assert_notification(
689 get_notification(),
689 get_notification(),
tests/mocks/GSettings.1.0/fake_gsettings.cpp+33
@@ -28,6 +28,7 @@ GSettingsControllerQml::GSettingsControllerQml()
28 , m_launcherWidth(8)
28 , m_launcherWidth(8)
29 , m_edgeDragWidth(2)
29 , m_edgeDragWidth(2)
30 , m_enableLauncher(true)
30 , m_enableLauncher(true)
31+ , m_enableIndicatorMenu(true)
31{
32{
32}
33}
33
34
@@ -159,6 +160,19 @@ bool GSettingsControllerQml::enableLauncher() const
159 return m_enableLauncher;
160 return m_enableLauncher;
160}
161}
161
162
163+bool GSettingsControllerQml::enableIndicatorMenu() const
164+{
165+ return m_enableIndicatorMenu;
166+}
167+
168+void GSettingsControllerQml::setEnableIndicatorMenu(bool enableIndicatorMenu)
169+{
170+ if (m_enableIndicatorMenu != enableIndicatorMenu) {
171+ m_enableIndicatorMenu = enableIndicatorMenu;
172+ Q_EMIT enableIndicatorMenuChanged(enableIndicatorMenu);
173+ }
174+}
175+
162GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
176GSettingsSchemaQml::GSettingsSchemaQml(QObject *parent): QObject(parent) {
163}
177}
164
178
@@ -225,6 +239,8 @@ void GSettingsQml::componentComplete()
225 this, &GSettingsQml::edgeDragWidthChanged);
239 this, &GSettingsQml::edgeDragWidthChanged);
226 connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::enableLauncherChanged,
240 connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::enableLauncherChanged,
227 this, &GSettingsQml::enableLauncherChanged);
241 this, &GSettingsQml::enableLauncherChanged);
242+ connect(GSettingsControllerQml::instance(), &GSettingsControllerQml::enableIndicatorMenuChanged,
243+ this, &GSettingsQml::enableIndicatorMenuChanged);
228
244
229 Q_EMIT disableHeightChanged();
245 Q_EMIT disableHeightChanged();
230 Q_EMIT pictureUriChanged();
246 Q_EMIT pictureUriChanged();
@@ -235,6 +251,7 @@ void GSettingsQml::componentComplete()
235 Q_EMIT launcherWidthChanged();
251 Q_EMIT launcherWidthChanged();
236 Q_EMIT edgeDragWidthChanged();
252 Q_EMIT edgeDragWidthChanged();
237 Q_EMIT enableLauncherChanged();
253 Q_EMIT enableLauncherChanged();
254+ Q_EMIT enableIndicatorMenuChanged();
238}
255}
239
256
240GSettingsSchemaQml * GSettingsQml::schema() const {
257GSettingsSchemaQml * GSettingsQml::schema() const {
@@ -350,6 +367,15 @@ QVariant GSettingsQml::enableLauncher() const
350 }
367 }
351}
368}
352
369
370+QVariant GSettingsQml::enableIndicatorMenu() const
371+{
372+ if (m_valid && m_schema->id() == "com.canonical.Unity8") {
373+ return GSettingsControllerQml::instance()->enableIndicatorMenu();
374+ } else {
375+ return QVariant();
376+ }
377+}
378+
353void GSettingsQml::setLifecycleExemptAppids(const QVariant &appIds)
379void GSettingsQml::setLifecycleExemptAppids(const QVariant &appIds)
354{
380{
355 if (m_valid && m_schema->id() == "com.canonical.qtmir") {
381 if (m_valid && m_schema->id() == "com.canonical.qtmir") {
@@ -384,3 +410,10 @@ void GSettingsQml::setEnableLauncher(const QVariant &enableLauncher)
384 GSettingsControllerQml::instance()->setEnableLauncher(enableLauncher.toBool());
410 GSettingsControllerQml::instance()->setEnableLauncher(enableLauncher.toBool());
385 }
411 }
386}
412}
413+
414+void GSettingsQml::setEnableIndicatorMenu(const QVariant &enableIndicatorMenu)
415+{
416+ if (m_valid && m_schema->id() == "com.canonical.Unity8") {
417+ GSettingsControllerQml::instance()->setEnableIndicatorMenu(enableIndicatorMenu.toBool());
418+ }
419+}
tests/mocks/GSettings.1.0/fake_gsettings.h+9
@@ -58,6 +58,7 @@ class GSettingsQml: public QObject, public QQmlParserStatus
58 Q_PROPERTY(QVariant launcherWidth READ launcherWidth WRITE setLauncherWidth NOTIFY launcherWidthChanged)
58 Q_PROPERTY(QVariant launcherWidth READ launcherWidth WRITE setLauncherWidth NOTIFY launcherWidthChanged)
59 Q_PROPERTY(QVariant edgeDragWidth READ edgeDragWidth WRITE setEdgeDragWidth NOTIFY edgeDragWidthChanged)
59 Q_PROPERTY(QVariant edgeDragWidth READ edgeDragWidth WRITE setEdgeDragWidth NOTIFY edgeDragWidthChanged)
60 Q_PROPERTY(QVariant enableLauncher READ enableLauncher WRITE setEnableLauncher NOTIFY enableLauncherChanged)
60 Q_PROPERTY(QVariant enableLauncher READ enableLauncher WRITE setEnableLauncher NOTIFY enableLauncherChanged)
61+ Q_PROPERTY(QVariant enableIndicatorMenu READ enableIndicatorMenu WRITE setEnableIndicatorMenu NOTIFY enableIndicatorMenuChanged)
61
62
62public:
63public:
63 GSettingsQml(QObject *parent = nullptr);
64 GSettingsQml(QObject *parent = nullptr);
@@ -75,6 +76,7 @@ public:
75 QVariant launcherWidth() const;
76 QVariant launcherWidth() const;
76 QVariant edgeDragWidth() const;
77 QVariant edgeDragWidth() const;
77 QVariant enableLauncher() const;
78 QVariant enableLauncher() const;
79+ QVariant enableIndicatorMenu() const;
78
80
79 void setDisableHeight(const QVariant &val);
81 void setDisableHeight(const QVariant &val);
80 void setPictureUri(const QVariant &str);
82 void setPictureUri(const QVariant &str);
@@ -85,6 +87,7 @@ public:
85 void setLauncherWidth(const QVariant &launcherWidth);
87 void setLauncherWidth(const QVariant &launcherWidth);
86 void setEdgeDragWidth(const QVariant &edgeDragWidth);
88 void setEdgeDragWidth(const QVariant &edgeDragWidth);
87 void setEnableLauncher(const QVariant &enableLauncher);
89 void setEnableLauncher(const QVariant &enableLauncher);
90+ void setEnableIndicatorMenu(const QVariant &enableIndicatorMenu);
88
91
89Q_SIGNALS:
92Q_SIGNALS:
90 void disableHeightChanged();
93 void disableHeightChanged();
@@ -97,6 +100,7 @@ Q_SIGNALS:
97 void launcherWidthChanged();
100 void launcherWidthChanged();
98 void edgeDragWidthChanged();
101 void edgeDragWidthChanged();
99 void enableLauncherChanged();
102 void enableLauncherChanged();
103+ void enableIndicatorMenuChanged();
100
104
101private:
105private:
102 GSettingsSchemaQml* m_schema;
106 GSettingsSchemaQml* m_schema;
@@ -140,6 +144,9 @@ public:
140 bool enableLauncher() const;
144 bool enableLauncher() const;
141 Q_INVOKABLE void setEnableLauncher(bool enableLauncher);
145 Q_INVOKABLE void setEnableLauncher(bool enableLauncher);
142
146
147+ bool enableIndicatorMenu() const;
148+ Q_INVOKABLE void setEnableIndicatorMenu(bool enableIndicatorMenu);
149+
143Q_SIGNALS:
150Q_SIGNALS:
144 void disableHeightChanged();
151 void disableHeightChanged();
145 void pictureUriChanged(const QString&);
152 void pictureUriChanged(const QString&);
@@ -150,6 +157,7 @@ Q_SIGNALS:
150 void launcherWidthChanged(int launcherWidth);
157 void launcherWidthChanged(int launcherWidth);
151 void edgeDragWidthChanged(uint edgeDragWidth);
158 void edgeDragWidthChanged(uint edgeDragWidth);
152 void enableLauncherChanged(bool enableLauncher);
159 void enableLauncherChanged(bool enableLauncher);
160+ void enableIndicatorMenuChanged(bool enableIndicatorMenu);
153
161
154private:
162private:
155 GSettingsControllerQml();
163 GSettingsControllerQml();
@@ -163,6 +171,7 @@ private:
163 int m_launcherWidth;
171 int m_launcherWidth;
164 uint m_edgeDragWidth;
172 uint m_edgeDragWidth;
165 bool m_enableLauncher;
173 bool m_enableLauncher;
174+ bool m_enableIndicatorMenu;
166
175
167 static GSettingsControllerQml* s_controllerInstance;
176 static GSettingsControllerQml* s_controllerInstance;
168 QList<GSettingsQml *> m_registeredGSettings;
177 QList<GSettingsQml *> m_registeredGSettings;
tests/mocks/Unity/Application/CMakeLists.txt+1
@@ -5,6 +5,7 @@ set(FakeUnityApplicationQml_SOURCES
5 MirSurface.cpp
5 MirSurface.cpp
6 MirSurfaceItem.cpp
6 MirSurfaceItem.cpp
7 MirSurfaceListModel.cpp
7 MirSurfaceListModel.cpp
8+ MirMock.cpp
8 ObjectListModel.h
9 ObjectListModel.h
9 SurfaceManager.cpp
10 SurfaceManager.cpp
10 VirtualKeyboard.cpp
11 VirtualKeyboard.cpp
tests/mocks/Unity/Application/MirMock.cppnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MirMock.h"
18+
19+MirMock *MirMock::the_mir = nullptr;
20+
21+MirMock *MirMock::instance()
22+{
23+ return the_mir;
24+}
25+
26+MirMock::MirMock()
27+{
28+ Q_ASSERT(the_mir == nullptr);
29+ the_mir = this;
30+}
31+
32+MirMock::~MirMock()
33+{
34+ Q_ASSERT(the_mir == this);
35+ the_mir = nullptr;
36+}
37+
38+void MirMock::setCursorName(const QString &cursorName)
39+{
40+ if (cursorName != m_cursorName) {
41+ m_cursorName = cursorName;
42+ Q_EMIT cursorNameChanged(m_cursorName);
43+ }
44+}
45+
46+QString MirMock::cursorName() const
47+{
48+ return m_cursorName;
49+}
tests/mocks/Unity/Application/MirMock.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef MIR_MOCK_H
18+#define MIR_MOCK_H
19+
20+#include <unity/shell/application/Mir.h>
21+
22+class MirMock : public ::Mir
23+{
24+ Q_OBJECT
25+public:
26+ explicit MirMock();
27+ virtual ~MirMock();
28+
29+ static MirMock *instance();
30+
31+ void setCursorName(const QString &cursorName) override;
32+ QString cursorName() const override;
33+
34+private:
35+ static MirMock *the_mir;
36+ QString m_cursorName;
37+};
38+
39+#endif
tests/mocks/Unity/Application/plugin.cpp+11−2
@@ -17,6 +17,7 @@
17#include "plugin.h"
17#include "plugin.h"
18#include "ApplicationInfo.h"
18#include "ApplicationInfo.h"
19#include "ApplicationManager.h"
19#include "ApplicationManager.h"
20+#include "MirMock.h"
20#include "MirSurfaceItem.h"
21#include "MirSurfaceItem.h"
21#include "SurfaceManager.h"
22#include "SurfaceManager.h"
22
23
@@ -38,6 +39,9 @@ void createUnityApplicationSharedSingletons()
38 if (!SurfaceManager::instance()) {
39 if (!SurfaceManager::instance()) {
39 new SurfaceManager;
40 new SurfaceManager;
40 }
41 }
42+ if (!MirMock::instance()) {
43+ new MirMock;
44+ }
41}
45}
42
46
43QObject* applicationManagerSingleton(QQmlEngine*, QJSEngine*)
47QObject* applicationManagerSingleton(QQmlEngine*, QJSEngine*)
@@ -46,6 +50,12 @@ QObject* applicationManagerSingleton(QQmlEngine*, QJSEngine*)
46 return new ApplicationManager;
50 return new ApplicationManager;
47}
51}
48
52
53+QObject* mirSingleton(QQmlEngine*, QJSEngine*)
54+{
55+ createUnityApplicationSharedSingletons();
56+ return MirMock::instance();
57+}
58+
49QObject* surfaceManagerSingleton(QQmlEngine*, QJSEngine*)
59QObject* surfaceManagerSingleton(QQmlEngine*, QJSEngine*)
50{
60{
51 createUnityApplicationSharedSingletons();
61 createUnityApplicationSharedSingletons();
@@ -78,9 +88,8 @@ void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
78 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
88 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
79
89
80 qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
90 qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
91+ qmlRegisterSingletonType<MirMock>(uri, 0, 1, "Mir", mirSingleton);
81 qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
92 qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
82−
83− qmlRegisterUncreatableType<Mir>(uri, 0, 1, "Mir", "Mir provides enum values, it can't be instantiated");
84}
93}
85
94
86void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
95void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/mocks/Unity/Launcher/CMakeLists.txt+5−1
@@ -1,7 +1,8 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=9)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
2
2
3include_directories(
3include_directories(
4 ${CMAKE_CURRENT_SOURCE_DIR}
4 ${CMAKE_CURRENT_SOURCE_DIR}
5+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/
5)
6)
6
7
7set(MockLauncherModel_SOURCES
8set(MockLauncherModel_SOURCES
@@ -9,10 +10,13 @@ set(MockLauncherModel_SOURCES
9 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
10 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
10 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
11 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
11 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
12 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
13+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/AppDrawerModelInterface.h
12 plugin.cpp
14 plugin.cpp
13 MockLauncherModel.cpp
15 MockLauncherModel.cpp
14 MockLauncherItem.cpp
16 MockLauncherItem.cpp
15 MockQuickListModel.cpp
17 MockQuickListModel.cpp
18+ MockAppDrawerModel.cpp
19+ ${CMAKE_SOURCE_DIR}/plugins/Utils/applicationsfiltermodel.cpp
16)
20)
17
21
18add_library(MockLauncherPlugin MODULE ${MockLauncherModel_SOURCES})
22add_library(MockLauncherPlugin MODULE ${MockLauncherModel_SOURCES})
tests/mocks/Unity/Launcher/MockAppDrawerModel.cppnew file+75
@@ -0,0 +1,75 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "MockAppDrawerModel.h"
18+
19+#include <QDebug>
20+#include <QDateTime>
21+
22+MockAppDrawerModel::MockAppDrawerModel(QObject *parent):
23+ AppDrawerModelInterface(parent)
24+{
25+ MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
26+ m_list.append(item);
27+ item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
28+ m_list.append(item);
29+ item = new MockLauncherItem("camera-app2", "/usr/share/applications/camera-app2.desktop", "Camera2", "camera", this);
30+ m_list.append(item);
31+ item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
32+ m_list.append(item);
33+ item = new MockLauncherItem("music-app", "/usr/share/applications/music-app.desktop", "Music", "soundcloud", this);
34+ m_list.append(item);
35+ item = new MockLauncherItem("facebook-webapp", "/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook", this);
36+ m_list.append(item);
37+ item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
38+ m_list.append(item);
39+ item = new MockLauncherItem("twitter-webapp", "/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter", this);
40+ m_list.append(item);
41+ item = new MockLauncherItem("gmail-webapp", "/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail", this);
42+ m_list.append(item);
43+ item = new MockLauncherItem("ubuntu-weather-app", "/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather", this);
44+ m_list.append(item);
45+ item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad", this);
46+ m_list.append(item);
47+ item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
48+ m_list.append(item);
49+ item = new MockLauncherItem("libreoffice", "/usr/share/applications/libreoffice.desktop","Libre Office", "libreoffice", this);
50+ m_list.append(item);
51+ qDebug() << "mock model created";
52+
53+ qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
54+}
55+
56+int MockAppDrawerModel::rowCount(const QModelIndex &parent) const
57+{
58+ return m_list.count();
59+}
60+
61+QVariant MockAppDrawerModel::data(const QModelIndex &index, int role) const
62+{
63+ switch (role) {
64+ case RoleAppId:
65+ return m_list.at(index.row())->appId();
66+ case RoleName:
67+ return m_list.at(index.row())->name();
68+ case RoleIcon:
69+ return m_list.at(index.row())->icon();
70+ case RoleUsage:
71+ return qrand();
72+ }
73+
74+ return QVariant();
75+}
tests/mocks/Unity/Launcher/MockAppDrawerModel.hnew file+32
@@ -0,0 +1,32 @@
1+/*
2+ * Copyright (C) 2016 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include <unity/shell/launcher/AppDrawerModelInterface.h>
18+
19+#include "MockLauncherItem.h"
20+
21+class MockAppDrawerModel: public AppDrawerModelInterface
22+{
23+ Q_OBJECT
24+public:
25+ MockAppDrawerModel(QObject* parent = nullptr);
26+
27+ int rowCount(const QModelIndex &parent) const override;
28+ QVariant data(const QModelIndex &index, int role) const override;
29+
30+private:
31+ QList<MockLauncherItem*> m_list;
32+};
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+13
@@ -67,6 +67,11 @@ QString MockLauncherItem::icon() const
67 return m_icon;
67 return m_icon;
68}
68}
69
69
70+QStringList MockLauncherItem::keywords() const
71+{
72+ return m_keywords;
73+}
74+
70bool MockLauncherItem::pinned() const
75bool MockLauncherItem::pinned() const
71{
76{
72 return m_pinned;
77 return m_pinned;
@@ -200,3 +205,11 @@ unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() c
200{
205{
201 return m_quickList;
206 return m_quickList;
202}
207}
208+
209+void MockLauncherItem::setKeywords(const QStringList &keywords)
210+{
211+ if (m_keywords != keywords) {
212+ m_keywords = keywords;
213+ Q_EMIT keywordsChanged(keywords);
214+ }
215+}
tests/mocks/Unity/Launcher/MockLauncherItem.h+6
@@ -22,6 +22,8 @@
22
22
23#include <unity/shell/launcher/LauncherItemInterface.h>
23#include <unity/shell/launcher/LauncherItemInterface.h>
24
24
25+#include <QStringList>
26+
25class MockQuickListModel;
27class MockQuickListModel;
26
28
27using namespace unity::shell::launcher;
29using namespace unity::shell::launcher;
@@ -37,6 +39,7 @@ public:
37 QString desktopFile() const;
39 QString desktopFile() const;
38 QString name() const override;
40 QString name() const override;
39 QString icon() const override;
41 QString icon() const override;
42+ QStringList keywords() const override;
40
43
41 bool pinned() const override;
44 bool pinned() const override;
42 bool running() const override;
45 bool running() const override;
@@ -51,6 +54,7 @@ public:
51 unity::shell::launcher::QuickListModelInterface *quickList() const override;
54 unity::shell::launcher::QuickListModelInterface *quickList() const override;
52
55
53private:
56private:
57+ void setKeywords(const QStringList &keywords);
54 void setPinned(bool pinned);
58 void setPinned(bool pinned);
55 void setRunning(bool running);
59 void setRunning(bool running);
56 void setRecent(bool recent);
60 void setRecent(bool recent);
@@ -65,6 +69,7 @@ private:
65 QString m_desktopFile;
69 QString m_desktopFile;
66 QString m_name;
70 QString m_name;
67 QString m_icon;
71 QString m_icon;
72+ QStringList m_keywords;
68 bool m_pinned;
73 bool m_pinned;
69 bool m_running;
74 bool m_running;
70 bool m_recent;
75 bool m_recent;
@@ -77,6 +82,7 @@ private:
77 MockQuickListModel *m_quickList;
82 MockQuickListModel *m_quickList;
78
83
79 friend class MockLauncherModel;
84 friend class MockLauncherModel;
85+ friend class MockAppDrawerModel;
80};
86};
81
87
82#endif // MOCKLAUNCHERITEM_H
88#endif // MOCKLAUNCHERITEM_H
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+3
@@ -36,6 +36,9 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
36 item = new MockLauncherItem("camera-app2", "/usr/share/applications/camera-app2.desktop", "Camera2", "camera", this);
36 item = new MockLauncherItem("camera-app2", "/usr/share/applications/camera-app2.desktop", "Camera2", "camera", this);
37 item->setPinned(true);
37 item->setPinned(true);
38 m_list.append(item);
38 m_list.append(item);
39+ item = new MockLauncherItem("camera-app3", "/usr/share/applications/camera-app2.desktop", "Camera2", "camera", this);
40+ item->setPinned(true);
41+ m_list.append(item);
39 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
42 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
40 item->setProgress(50);
43 item->setProgress(50);
41 item->setCountVisible(true);
44 item->setCountVisible(true);
tests/mocks/Unity/Launcher/MockQuickListModel.cpp+2
@@ -37,6 +37,8 @@ QVariant MockQuickListModel::data(const QModelIndex &index, int role) const
37 return QLatin1String("copy.png");
37 return QLatin1String("copy.png");
38 case RoleClickable:
38 case RoleClickable:
39 return index.row() == 1 ? false : true;
39 return index.row() == 1 ? false : true;
40+ case RoleHasSeparator:
41+ return index.row() <= 1 ? true : false;
40 }
42 }
41 return QVariant();
43 return QVariant();
42}
44}
tests/mocks/Unity/Launcher/plugin.cpp+4
@@ -21,9 +21,11 @@
21#include "MockLauncherModel.h"
21#include "MockLauncherModel.h"
22#include "MockLauncherItem.h"
22#include "MockLauncherItem.h"
23#include "MockQuickListModel.h"
23#include "MockQuickListModel.h"
24+#include "MockAppDrawerModel.h"
24
25
25#include <unity/shell/launcher/LauncherModelInterface.h>
26#include <unity/shell/launcher/LauncherModelInterface.h>
26#include <unity/shell/launcher/LauncherItemInterface.h>
27#include <unity/shell/launcher/LauncherItemInterface.h>
28+#include <unity/shell/launcher/AppDrawerModelInterface.h>
27
29
28#include <QtQml/qqml.h>
30#include <QtQml/qqml.h>
29
31
@@ -41,8 +43,10 @@ void TestLauncherPlugin::registerTypes(const char* uri)
41 qmlRegisterUncreatableType<LauncherModelInterface>(uri, 0, 1, "LauncherModelInterface", "Abstract Interface. Cannot be instantiated.");
43 qmlRegisterUncreatableType<LauncherModelInterface>(uri, 0, 1, "LauncherModelInterface", "Abstract Interface. Cannot be instantiated.");
42 qmlRegisterUncreatableType<LauncherItemInterface>(uri, 0, 1, "LauncherItemInterface", "Abstract Interface. Cannot be instantiated.");
44 qmlRegisterUncreatableType<LauncherItemInterface>(uri, 0, 1, "LauncherItemInterface", "Abstract Interface. Cannot be instantiated.");
43 qmlRegisterUncreatableType<QuickListModelInterface>(uri, 0, 1, "QuickListModelInterface", "Abstract Interface. Cannot be instantiated.");
45 qmlRegisterUncreatableType<QuickListModelInterface>(uri, 0, 1, "QuickListModelInterface", "Abstract Interface. Cannot be instantiated.");
46+ qmlRegisterUncreatableType<AppDrawerModelInterface>(uri, 0, 1, "AppDrawerModelInterface", "Abstract Interface. Cannot be instantiated.");
44
47
45 qmlRegisterSingletonType<MockLauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
48 qmlRegisterSingletonType<MockLauncherModel>(uri, 0, 1, "LauncherModel", modelProvider);
46 qmlRegisterUncreatableType<MockLauncherItem>(uri, 0, 1, "LauncherItem", "Can't create LauncherItems in QML. Get them from the LauncherModel");
49 qmlRegisterUncreatableType<MockLauncherItem>(uri, 0, 1, "LauncherItem", "Can't create LauncherItems in QML. Get them from the LauncherModel");
47 qmlRegisterUncreatableType<MockQuickListModel>(uri, 0, 1, "QuickListModel", "Can't create QuickLists in QML. Get them from the LauncherItems");
50 qmlRegisterUncreatableType<MockQuickListModel>(uri, 0, 1, "QuickListModel", "Can't create QuickLists in QML. Get them from the LauncherItems");
51+ qmlRegisterType<MockAppDrawerModel>(uri, 0, 1, "AppDrawerModel");
48}
52}
tests/mocks/Unity/Screens/CMakeLists.txt+1−1
@@ -11,4 +11,4 @@ add_library(MockScreensPlugin MODULE ${MockScreens_SOURCES})
11
11
12qt5_use_modules(MockScreensPlugin Gui Qml)
12qt5_use_modules(MockScreensPlugin Gui Qml)
13
13
14−add_unity8_mock(Unity.Screens 0.1 Unity/Screens TARGETS MockScreensPlugin)
14+add_unity8_mock(Unity.Screens 0.1 Unity/Screens PREFIX mocks TARGETS MockScreensPlugin)
tests/mocks/Unity/fake_categories.cpp+4
@@ -69,6 +69,10 @@ Categories::data(const QModelIndex& index, int role) const
69 } else {
69 } else {
70 map["category-layout"] = "carousel";
70 map["category-layout"] = "carousel";
71 }
71 }
72+ if (index.row() == 16) {
73+ map["expandable"] = false;
74+ map["collapsed-rows"] = 1;
75+ }
72 if (index.row() == 18) {
76 if (index.row() == 18) {
73 map["category-layout"] = "horizontal-list";
77 map["category-layout"] = "horizontal-list";
74 }
78 }
tests/mocks/Utils/CMakeLists.txt+4
@@ -24,11 +24,15 @@ set(QMLPLUGIN_SRC
24 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputeventgenerator.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/Utils/inputeventgenerator.cpp
25 ${CMAKE_SOURCE_DIR}/plugins/Utils/deviceconfigparser.cpp
25 ${CMAKE_SOURCE_DIR}/plugins/Utils/deviceconfigparser.cpp
26 ${CMAKE_SOURCE_DIR}/plugins/Utils/globalfunctions.cpp
26 ${CMAKE_SOURCE_DIR}/plugins/Utils/globalfunctions.cpp
27+ ${CMAKE_SOURCE_DIR}/plugins/Utils/appdrawerproxymodel.cpp
27 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
28 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
28 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
29 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
29 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
30 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
30 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
31 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
31 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
32 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
33+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/AppDrawerModelInterface.h
34+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
35+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
32 constants.cpp
36 constants.cpp
33 plugin.cpp
37 plugin.cpp
34 windowstatestorage.cpp
38 windowstatestorage.cpp
tests/mocks/Utils/plugin.cpp+2
@@ -40,6 +40,7 @@
40#include <inputeventgenerator.h>
40#include <inputeventgenerator.h>
41#include <deviceconfigparser.h>
41#include <deviceconfigparser.h>
42#include <globalfunctions.h>
42#include <globalfunctions.h>
43+#include <appdrawerproxymodel.h>
43
44
44static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
45static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
45{
46{
@@ -82,4 +83,5 @@ void FakeUtilsPlugin::registerTypes(const char *uri)
82 qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
83 qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser");
83 qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions);
84 qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions);
84 qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher");
85 qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher");
86+ qmlRegisterType<AppDrawerProxyModel>(uri, 0, 1, "AppDrawerProxyModel");
85}
87}
tests/plugins/Dash/cardcreator/4.res+1−1
@@ -34,7 +34,7 @@ Loader {
34 visible: showHeader && active && status === Loader.Ready;
34 visible: showHeader && active && status === Loader.Ready;
35 width: units.gu(6);
35 width: units.gu(6);
36 height: units.gu(5.625);
36 height: units.gu(5.625);
37− sourceComponent: UbuntuShape { image: mascotImage }
37+ sourceComponent: UbuntuShape { aspect: UbuntuShape.Flat; image: mascotImage }
38 anchors { verticalCenter: parent.verticalCenter; }
38 anchors { verticalCenter: parent.verticalCenter; }
39 }
39 }
40
40
tests/plugins/Dash/cardcreator/4.res.cardcreator+1−1
@@ -32,7 +32,7 @@ Loader {
32 visible: showHeader && active && status === Loader.Ready;
32 visible: showHeader && active && status === Loader.Ready;
33 width: units.gu(6);
33 width: units.gu(6);
34 height: units.gu(5.625);
34 height: units.gu(5.625);
35− sourceComponent: UbuntuShape { image: mascotImage }
35+ sourceComponent: UbuntuShape { aspect: UbuntuShape.Flat; image: mascotImage }
36 anchors { verticalCenter: parent.verticalCenter; }
36 anchors { verticalCenter: parent.verticalCenter; }
37 }
37 }
38
38
tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
2
2
3include_directories(
3include_directories(
4 ${CMAKE_CURRENT_SOURCE_DIR}
4 ${CMAKE_CURRENT_SOURCE_DIR}
tests/plugins/Unity/Launcher/CMakeLists.txt+2−1
@@ -1,5 +1,5 @@
1pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
1pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=8)
2+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=11)
3
3
4include_directories(
4include_directories(
5 ${CMAKE_CURRENT_SOURCE_DIR}
5 ${CMAKE_CURRENT_SOURCE_DIR}
@@ -30,6 +30,7 @@ add_executable(launchermodeltestExec
30 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistmodel.cpp
30 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistmodel.cpp
31 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/dbusinterface.cpp
31 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/dbusinterface.cpp
32 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistentry.cpp
32 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistentry.cpp
33+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/ualwrapper.cpp
33 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
34 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
34 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
35 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
35 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
36 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
tests/qmltests/CMakeLists.txt+1
@@ -71,6 +71,7 @@ add_unity8_qmltest(Greeter Infographics)
71add_unity8_qmltest(Greeter NarrowView)
71add_unity8_qmltest(Greeter NarrowView)
72add_unity8_qmltest(Greeter WideView)
72add_unity8_qmltest(Greeter WideView)
73add_unity8_qmltest(Launcher Launcher)
73add_unity8_qmltest(Launcher Launcher)
74+add_unity8_qmltest(Launcher Drawer)
74add_unity8_qmltest(Notifications Notifications)
75add_unity8_qmltest(Notifications Notifications)
75add_unity8_qmltest(Notifications VisualSnapDecisionsQueue)
76add_unity8_qmltest(Notifications VisualSnapDecisionsQueue)
76add_unity8_qmltest(Notifications OptionToggle)
77add_unity8_qmltest(Notifications OptionToggle)
tests/qmltests/Dash/tst_DashShell.qml−29
@@ -112,34 +112,5 @@ Item {
112 mouseClick(buttonShowDashHome);
112 mouseClick(buttonShowDashHome);
113 tryCompare(dashContentList, "currentIndex", 0);
113 tryCompare(dashContentList, "currentIndex", 0);
114 }
114 }
115−
116− function test_setShortLauncherMoveResetNonActiveDash() {
117− var dashContentList = findChild(dash, "dashContentList");
118− var startX = dash.width - units.gu(1);
119− var startY = dash.height / 2;
120− var stopX = units.gu(1)
121− var stopY = startY;
122− waitForRendering(dashContentList);
123− touchFlick(dash, startX, startY, stopX, stopY);
124− touchFlick(dash, startX, startY, stopX, stopY);
125− compare(dashContentList.currentIndex, 2, "Could not flick to scope id 2");
126−
127− // Pretend the dash is not active
128− dash.windowActive = false;
129−
130− // Flick the greeter away
131− var startX = shell.width - units.gu(1);
132− var startY = shell.height / 2;
133− var stopX = units.gu(1)
134− var stopY = startY;
135− touchFlick(shell, startX, startY, stopX, stopY);
136−
137− var greeter = findChild(shell, "greeter");
138− tryCompare(greeter, "shown", false);
139−
140− // Now do a small launcher movement
141− touchFlick(shell, stopX, startY, startX, stopY);
142− compare(dashContentList.currentIndex, 0, "Small launcher move did not reset dash on non active window");
143− }
144 }
115 }
145}
116}
tests/qmltests/Dash/tst_GenericScopeView.qml+26
@@ -168,6 +168,32 @@ Item {
168 tryCompare(genericScopeView.scope, "searchQuery", "test")
168 tryCompare(genericScopeView.scope, "searchQuery", "test")
169 }
169 }
170
170
171+ function test_forceNotExpandable() {
172+ // wait for the item to be there
173+ tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader14", 0 /* timeout */) != null; }, true);
174+
175+ var category14 = findChild(genericScopeView, "dashCategory14")
176+ var seeAll14 = findChild(category14, "seeAll")
177+
178+ compare(category14.forceNotExpandable, false);
179+ waitForRendering(seeAll14);
180+ verify(category14.expandable);
181+ verify(!category14.expanded);
182+ compare(seeAll14.visible, true);
183+
184+ // wait for the item to be there
185+ tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader16", 0 /* timeout */) != null; }, true);
186+
187+ var category16 = findChild(genericScopeView, "dashCategory16")
188+ var seeAll16 = findChild(category16, "seeAll")
189+
190+ compare(category16.forceNotExpandable, true);
191+ waitForRendering(seeAll16);
192+ verify(!category16.expandable);
193+ verify(!category16.expanded);
194+ compare(seeAll16.visible, false);
195+ }
196+
171 function test_expand_collapse() {
197 function test_expand_collapse() {
172 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0", 0 /* timeout */) != null; }, true);
198 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0", 0 /* timeout */) != null; }, true);
173
199
tests/qmltests/Launcher/tst_Drawer.qmlnew file+264
@@ -0,0 +1,264 @@
1+/*
2+ * Copyright 2013-2016 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.4
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 1.3
20+import ".."
21+import "../../../qml/Launcher"
22+import Unity.Launcher 0.1
23+import Utils 0.1 // For EdgeBarrierSettings
24+import Unity.Test 0.1
25+
26+StyledItem {
27+ id: root
28+ theme.name: "Ubuntu.Components.Themes.SuruDark"
29+
30+ width: units.gu(140)
31+ height: units.gu(70)
32+ Rectangle {
33+ anchors.fill: parent
34+ color: UbuntuColors.graphite // something neither white nor black
35+ }
36+
37+ Launcher {
38+ id: launcher
39+ x: 0
40+ y: 0
41+ width: units.gu(40)
42+ height: root.height
43+
44+ lockedVisible: lockedVisibleCheckBox.checked
45+
46+ property string lastSelectedApplication
47+ onLauncherApplicationSelected: {
48+ lastSelectedApplication = appId
49+ }
50+
51+ Component.onCompleted: {
52+ launcher.focus = true
53+ edgeBarrierControls.target = testCase.findChild(this, "edgeBarrierController");
54+ }
55+ }
56+
57+ ColumnLayout {
58+ anchors { bottom: parent.bottom; right: parent.right; margins: units.gu(1) }
59+ spacing: units.gu(1)
60+ width: childrenRect.width
61+
62+ RowLayout {
63+ CheckBox {
64+ id: lockedVisibleCheckBox
65+ checked: false
66+ }
67+ Label {
68+ text: "Launcher always visible"
69+ }
70+ }
71+
72+ Slider {
73+ id: widthSlider
74+ Layout.fillWidth: true
75+ minimumValue: 6
76+ maximumValue: 12
77+ value: 10
78+ }
79+
80+ MouseTouchEmulationCheckbox {}
81+
82+ EdgeBarrierControls {
83+ id: edgeBarrierControls
84+ text: "Drag here to pull out launcher"
85+ onDragged: { launcher.pushEdge(amount); }
86+ }
87+ }
88+
89+ UnityTestCase {
90+ id: testCase
91+ when: windowShown
92+ name: "Drawer"
93+
94+ function dragDrawerIntoView() {
95+ var startX = launcher.dragAreaWidth/2;
96+ var startY = launcher.height/2;
97+ touchFlick(launcher,
98+ startX, startY,
99+ startX+units.gu(35), startY);
100+
101+ var drawer = findChild(launcher, "drawer");
102+ verify(!!drawer);
103+
104+ // wait until it gets fully extended
105+ // a tryCompare doesn't work since
106+ // compare(-0.000005917593600024418, 0);
107+ // is true and in this case we want exactly 0 or will have pain later on
108+ tryCompareFunction( function(){ return drawer.x === 0; }, true );
109+ tryCompare(launcher, "state", "drawer");
110+ tryCompare(launcher, "drawerShown", true);
111+ }
112+
113+ function revealByEdgePush() {
114+ // Place the mouse against the window/screen edge and push beyond the barrier threshold
115+ // If the mouse did not move between two revealByEdgePush(), we need it to move out the
116+ // area to make sure we're not just accumulating to the previous push
117+ mouseMove(root, root.width, root.height / 2);
118+ mouseMove(root, 1, root.height / 2);
119+
120+ launcher.pushEdge(EdgeBarrierSettings.pushThreshold * 1.1);
121+
122+ var drawer = findChild(launcher, "drawer");
123+ verify(!!drawer);
124+
125+ // wait until it gets fully extended
126+ tryCompare(drawer, "x", 0);
127+ tryCompare(launcher, "state", "drawer");
128+ tryCompare(launcher, "drawerShown", true);
129+ }
130+
131+ function init() {
132+ launcher.lastSelectedApplication = "";
133+ launcher.lockedVisible = false;
134+ launcher.hide();
135+ var drawer = findChild(launcher, "drawer");
136+ tryCompare(drawer, "x", -drawer.width);
137+ }
138+
139+ function test_revealByEdgeDrag() {
140+ dragDrawerIntoView();
141+ }
142+
143+ function test_revealByEdgePush_data() {
144+ return [
145+ { tag: "autohide launcher", autohide: true },
146+ { tag: "locked launcher", autohide: false }
147+ ]
148+ }
149+
150+ function test_revealByEdgePush(data) {
151+ launcher.lockedVisible = !data.autohide;
152+
153+ var panel = findChild(launcher, "launcherPanel");
154+ tryCompare(panel, "x", data.autohide ? -panel.width : 0);
155+ tryCompare(launcher, "state", data.autohide ? "" : "visible");
156+ waitForRendering(launcher)
157+
158+ revealByEdgePush();
159+ }
160+
161+ function test_hideByDraggingDrawer_data() {
162+ return [
163+ {tag: "autohide", autohide: true, endState: ""},
164+ {tag: "locked", autohide: false, endState: "visible"}
165+ ]
166+ }
167+
168+ function test_hideByDraggingDrawer(data) {
169+ launcher.lockedVisible = !data.autohide;
170+
171+ dragDrawerIntoView();
172+ waitForRendering(launcher);
173+
174+ var drawer = findChild(launcher, "drawer");
175+
176+ mouseFlick(root, drawer.width - units.gu(1), drawer.height / 2, units.gu(2), drawer.height / 2, true, true);
177+
178+ tryCompare(drawer.anchors, "rightMargin", 0);
179+ tryCompare(launcher, "state", data.endState);
180+ launcher.lockedVisible = false;
181+ }
182+
183+ function test_hideByClickingOutside() {
184+ dragDrawerIntoView();
185+
186+ var drawer = findChild(launcher, "drawer");
187+
188+ mouseClick(root, drawer.width + units.gu(1), root.height / 2);
189+
190+ tryCompare(launcher, "state", "");
191+ }
192+
193+ function test_launchAppFromDrawer() {
194+ dragDrawerIntoView();
195+
196+ var drawerList = findChild(launcher, "drawerItemList");
197+ var dialerApp = findChild(drawerList, "drawerItem_dialer-app");
198+ mouseClick(dialerApp, dialerApp.width / 2, dialerApp.height / 2);
199+
200+ tryCompare(launcher, "lastSelectedApplication", "dialer-app");
201+
202+ tryCompare(launcher, "state", "");
203+ }
204+
205+ function test_launcherGivesUpFocusAfterLaunchingFromDrawer() {
206+ dragDrawerIntoView();
207+
208+ tryCompare(launcher, "focus", true);
209+
210+ var drawerList = findChild(launcher, "drawerItemList");
211+ var dialerApp = findChild(drawerList, "drawerItem_dialer-app");
212+ mouseClick(dialerApp, dialerApp.width / 2, dialerApp.height / 2);
213+
214+ tryCompare(launcher, "focus", false);
215+ }
216+
217+ function test_drawerDisabled() {
218+ launcher.drawerEnabled = false;
219+
220+ var startX = launcher.dragAreaWidth/2;
221+ var startY = launcher.height/2;
222+ touchFlick(launcher,
223+ startX, startY,
224+ startX+units.gu(35), startY);
225+
226+ var drawer = findChild(launcher, "drawer");
227+ verify(!!drawer);
228+
229+ tryCompare(launcher, "state", "visible");
230+ tryCompare(launcher, "drawerShown", false);
231+
232+ launcher.drawerEnabled = true;
233+ }
234+
235+ function test_search() {
236+ compare(launcher.lastSelectedApplication, "");
237+
238+ launcher.openDrawer(true)
239+ typeString("cam");
240+ keyClick(Qt.Key_Enter);
241+
242+ compare(launcher.lastSelectedApplication, "camera-app");
243+ }
244+
245+ function test_dragDirectionOnLeftEdgeDrag_data() {
246+ return [
247+ { tag: "reveal", direction: "right", endState: "drawer" },
248+ { tag: "cancel", direction: "left", endState: "visible" },
249+ ]
250+ }
251+
252+ function test_dragDirectionOnLeftEdgeDrag(data) {
253+ var startX = launcher.dragAreaWidth/2;
254+ var startY = launcher.height/2;
255+ var stopX = startX + units.gu(35);
256+ var endX = stopX + (units.gu(4) * (data.direction === "left" ? -1 : 1))
257+
258+ touchFlick(launcher, startX, startY, stopX, startY, true, false);
259+ touchFlick(launcher, stopX, startY, endX, startY, false, true);
260+
261+ tryCompare(launcher, "state", data.endState)
262+ }
263+ }
264+}
tests/qmltests/Launcher/tst_Launcher.qml+90−1
@@ -322,7 +322,7 @@ Rectangle {
322 function revealByEdgePush() {
322 function revealByEdgePush() {
323 // Place the mouse against the window/screen edge and push beyond the barrier threshold
323 // Place the mouse against the window/screen edge and push beyond the barrier threshold
324 mouseMove(root, 1, root.height / 2);
324 mouseMove(root, 1, root.height / 2);
325− launcher.pushEdge(EdgeBarrierSettings.pushThreshold * 1.1);
325+ launcher.pushEdge(EdgeBarrierSettings.pushThreshold * .6);
326
326
327 var panel = findChild(launcher, "launcherPanel");
327 var panel = findChild(launcher, "launcherPanel");
328 verify(!!panel);
328 verify(!!panel);
@@ -1369,6 +1369,95 @@ Rectangle {
1369 tryCompare(clickThroughSpy, "count", 0);
1369 tryCompare(clickThroughSpy, "count", 0);
1370 }
1370 }
1371
1371
1372+ function test_tooltip() {
1373+ launcher.lockedVisible = true;
1374+ revealByEdgePush();
1375+
1376+ var item = findChild(launcher, "launcherDelegate0");
1377+ var tooltipShape = findChild(launcher, "tooltipShape");
1378+
1379+ // Initial state
1380+ tryCompare(tooltipShape, "visible", false);
1381+ tryCompare(tooltipShape, "opacity", .0);
1382+
1383+ // Move the mouse on the launcher icon
1384+ mouseMove(item, item.width / 2, item.height / 2, 10);
1385+ mouseMove(item, item.width / 2 + 1, item.height / 2, 10);
1386+ tryCompare(tooltipShape, "visible", true);
1387+ tryCompare(tooltipShape, "opacity", .95);
1388+
1389+ // Move the mouse away
1390+ mouseMove(root, root.width, root.height / 2, 10);
1391+ tryCompare(tooltipShape, "visible", false);
1392+ tryCompare(tooltipShape, "opacity", .0);
1393+ }
1394+
1395+ function test_quicklist_dismisses_tooltip() {
1396+ launcher.lockedVisible = true;
1397+ revealByEdgePush();
1398+
1399+ var item = findChild(launcher, "launcherDelegate0");
1400+ var tooltipShape = findChild(launcher, "tooltipShape");
1401+ var quickListShape = findChild(launcher, "quickListShape");
1402+
1403+ // Initial state
1404+ tryCompare(tooltipShape, "visible", false);
1405+ tryCompare(tooltipShape, "opacity", .0);
1406+
1407+ // Move the mouse on the launcher icon
1408+ mouseMove(item, item.width / 2, item.height / 2, 10);
1409+ mouseMove(item, item.width / 2 + 1, item.height / 2, 10);
1410+ tryCompare(tooltipShape, "visible", true);
1411+ tryCompare(tooltipShape, "opacity", .95);
1412+
1413+ // Right click to show the quicklist
1414+ mouseClick(item, item.width / 2, item.height / 2, Qt.RightButton);
1415+ tryCompare(quickListShape, "visible", true);
1416+ tryCompare(tooltipShape, "visible", false);
1417+ tryCompare(tooltipShape, "opacity", .0);
1418+
1419+ // Left click hides the quicklist, tooltip is still dismissed
1420+ mouseClick(item, item.width / 2, item.height / 2, Qt.LefftButton);
1421+ tryCompare(quickListShape, "visible", false);
1422+ tryCompare(tooltipShape, "visible", false);
1423+ tryCompare(tooltipShape, "opacity", .0);
1424+
1425+ // Mouse motion should should show tooltip again
1426+ mouseMove(item, item.width / 2, item.height / 2, 10);
1427+ mouseMove(item, item.width / 2 + 1, item.height / 2, 10);
1428+ tryCompare(tooltipShape, "visible", true);
1429+ tryCompare(tooltipShape, "opacity", .95);
1430+ }
1431+
1432+ function test_click_dismisses_tooltip() {
1433+ launcher.lockedVisible = true;
1434+ revealByEdgePush();
1435+
1436+ var item = findChild(launcher, "launcherDelegate0");
1437+ var tooltipShape = findChild(launcher, "tooltipShape");
1438+
1439+ // Initial state
1440+ tryCompare(tooltipShape, "visible", false);
1441+ tryCompare(tooltipShape, "opacity", .0);
1442+
1443+ // Move the mouse on the launcher icon
1444+ mouseMove(item, item.width / 2, item.height / 2, 10);
1445+ mouseMove(item, item.width / 2 + 1, item.height / 2, 10);
1446+ tryCompare(tooltipShape, "visible", true);
1447+ tryCompare(tooltipShape, "opacity", .95);
1448+
1449+ // Left click should dismiss the tooltip
1450+ mouseClick(item, item.width / 2 + 1, item.height / 2, Qt.LeftButton);
1451+ tryCompare(tooltipShape, "visible", false);
1452+ tryCompare(tooltipShape, "opacity", .0);
1453+
1454+ // Mouse motion should should show tooltip again
1455+ mouseMove(item, item.width / 2, item.height / 2, 10);
1456+ mouseMove(item, item.width / 2 + 1, item.height / 2, 10);
1457+ tryCompare(tooltipShape, "visible", true);
1458+ tryCompare(tooltipShape, "opacity", .95);
1459+ }
1460+
1372 function test_launcherEnabledSetting() {
1461 function test_launcherEnabledSetting() {
1373 launcher.available = true;
1462 launcher.available = true;
1374
1463
tests/qmltests/Panel/tst_IndicatorsMenu.qml+17
@@ -286,5 +286,22 @@ IndicatorTest {
286 mouseClick(indicatorsMenu, indicatorsMenu.width/2, indicatorsMenu.height/2, Qt.RightButton);
286 mouseClick(indicatorsMenu, indicatorsMenu.width/2, indicatorsMenu.height/2, Qt.RightButton);
287 tryCompare(clickThroughSpy, "count", 0);
287 tryCompare(clickThroughSpy, "count", 0);
288 }
288 }
289+
290+ function test_enableMenuSetting_data() {
291+ return [
292+ {tag: "menu enabled", enabled: true},
293+ {tag: "menu disabled", enabled: false}
294+ ]
295+ }
296+
297+ function test_enableMenuSetting(data) {
298+ indicatorsMenu.available = data.enabled;
299+
300+ indicatorsMenu.show();
301+ tryCompare(indicatorsMenu, data.enabled ? "fullyOpened" : "fullyClosed", true);
302+
303+ indicatorsMenu.available = true;
304+ indicatorsMenu.hide();
305+ }
289 }
306 }
290}
307}
tests/qmltests/Stage/tst_DesktopStage.qml+16
@@ -789,5 +789,21 @@ Item {
789
789
790 tryCompare(dialerAppDelegate, "state", "maximized");
790 tryCompare(dialerAppDelegate, "state", "maximized");
791 }
791 }
792+
793+ function test_grabbingCursorOnDecorationPress() {
794+ var appDelegate = startApplication("dialer-app");
795+ verify(appDelegate);
796+ var decoration = findChild(appDelegate, "appWindowDecoration");
797+ verify(decoration);
798+
799+ mousePress(decoration, decoration.width/2, decoration.height/2, Qt.LeftButton);
800+ tryCompare(Mir, "cursorName", "grabbing");
801+
802+ mouseMove(decoration, decoration.width/2 + 1, decoration.height/2 + 1);
803+ tryCompare(Mir, "cursorName", "grabbing");
804+
805+ mouseRelease(decoration);
806+ tryCompare(Mir, "cursorName", "");
807+ }
792 }
808 }
793}
809}
tests/qmltests/Stage/tst_PhoneStage.qml−26
@@ -334,32 +334,6 @@ Item {
334 tryCompare(firstApp, "focused", true);
334 tryCompare(firstApp, "focused", true);
335 }
335 }
336
336
337− function test_leftEdge_data() {
338− return [
339− { tag: "normal", inSpread: false, leftEdgeDragWidth: units.gu(20), shouldMoveApp: true },
340− { tag: "inSpread", inSpread: true, leftEdgeDragWidth: units.gu(5), shouldMoveApp: false }
341− ]
342− }
343−
344− function test_leftEdge(data) {
345− addApps(2);
346−
347− if (data.inSpread) {
348− performEdgeSwipeToShowAppSpread();
349− }
350−
351− var focusedDelegate = findChild(stage, "appDelegate_" + topLevelSurfaceList.idAt(0));
352− var currentX = focusedDelegate.x;
353−
354− stage.leftEdgeDragProgress = data.leftEdgeDragWidth;
355−
356− tryCompare(focusedDelegate, "x", data.shouldMoveApp ? data.leftEdgeDragWidth : currentX);
357−
358− stage.leftEdgeDragProgress = 0;
359−
360− tryCompare(focusedDelegate, "x", currentX);
361− }
362−
363 function test_focusedAppIsTheOnlyRunningApp() {
337 function test_focusedAppIsTheOnlyRunningApp() {
364 addApps(2);
338 addApps(2);
365
339
tests/qmltests/tst_OrientedShell.qml+1−13
@@ -999,7 +999,7 @@ Rectangle {
999 var rotationStates = findInvisibleChild(orientedShell, "rotationStates");
999 var rotationStates = findInvisibleChild(orientedShell, "rotationStates");
1000 waitUntilTransitionsEnd(rotationStates);
1000 waitUntilTransitionsEnd(rotationStates);
1001
1001
1002− performLeftEdgeSwipeToSwitchToDash();
1002+ ApplicationManager.requestFocusApplication("unity8-dash");
1003
1003
1004 // Should be back to portrait
1004 // Should be back to portrait
1005 tryCompare(shell, "transformRotationAngle", 0);
1005 tryCompare(shell, "transformRotationAngle", 0);
@@ -1391,18 +1391,6 @@ Rectangle {
1391 waitUntilTransitionsEnd(rotationStates);
1391 waitUntilTransitionsEnd(rotationStates);
1392 }
1392 }
1393
1393
1394− function performLeftEdgeSwipeToSwitchToDash() {
1395− var swipeLength = shell.width * 0.7;
1396−
1397− var touchStartX = 1;
1398− var touchStartY = shell.height / 2;
1399− touchFlick(shell,
1400− touchStartX, touchStartY,
1401− touchStartX + swipeLength, touchStartY);
1402−
1403− tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
1404− }
1405−
1406 function performEdgeSwipeToSwitchToPreviousApp() {
1394 function performEdgeSwipeToSwitchToPreviousApp() {
1407 // swipe just enough to ensure an app switch action.
1395 // swipe just enough to ensure an app switch action.
1408 // If we swipe too much we will trigger the spread mode
1396 // If we swipe too much we will trigger the spread mode
tests/qmltests/tst_Shell.qml+66−143
@@ -605,38 +605,6 @@ Rectangle {
605 compare(ApplicationManager.get(0).appId, "unity8-dash");
605 compare(ApplicationManager.get(0).appId, "unity8-dash");
606 }
606 }
607
607
608− function test_phoneLeftEdgeDrag_data() {
609− return [
610− {tag: "without launcher",
611− revealLauncher: false, swipeLength: units.gu(30), appHides: true, focusedApp: "dialer-app",
612− launcherHides: true, greeterShown: false},
613−
614− {tag: "with launcher",
615− revealLauncher: true, swipeLength: units.gu(30), appHides: true, focusedApp: "dialer-app",
616− launcherHides: true, greeterShown: false},
617−
618− {tag: "small swipe",
619− revealLauncher: false, swipeLength: units.gu(25), appHides: false, focusedApp: "dialer-app",
620− launcherHides: false, greeterShown: false},
621−
622− {tag: "long swipe",
623− revealLauncher: false, swipeLength: units.gu(30), appHides: true, focusedApp: "dialer-app",
624− launcherHides: true, greeterShown: false},
625−
626− {tag: "small swipe with greeter",
627− revealLauncher: false, swipeLength: units.gu(25), appHides: false, focusedApp: "dialer-app",
628− launcherHides: false, greeterShown: true},
629−
630− {tag: "long swipe with greeter",
631− revealLauncher: false, swipeLength: units.gu(30), appHides: true, focusedApp: "dialer-app",
632− launcherHides: true, greeterShown: true},
633−
634− {tag: "swipe over dash",
635− revealLauncher: false, swipeLength: units.gu(30), appHides: true, focusedApp: "unity8-dash",
636− launcherHides: false, greeterShown: false},
637− ];
638− }
639−
640 function test_snapDecisionDismissalReturnsFocus() {
608 function test_snapDecisionDismissalReturnsFocus() {
641 loadShell("phone");
609 loadShell("phone");
642 swipeAwayGreeter();
610 swipeAwayGreeter();
@@ -701,80 +669,6 @@ Rectangle {
701 mockNotificationsModel.append(n)
669 mockNotificationsModel.append(n)
702 }
670 }
703
671
704− function test_phoneLeftEdgeDrag(data) {
705− loadShell("phone");
706− swipeAwayGreeter();
707− dragLauncherIntoView();
708− var appSurfaceId = topLevelSurfaceList.nextId;
709− tapOnAppIconInLauncher();
710− waitUntilAppWindowIsFullyLoaded(appSurfaceId);
711−
712− var greeter = findChild(shell, "greeter");
713− if (data.greeterShown) {
714− showGreeter();
715− }
716−
717− if (data.revealLauncher) {
718− dragLauncherIntoView();
719− }
720−
721− swipeFromLeftEdge(data.swipeLength);
722− if (data.appHides) {
723− waitUntilDashIsFocused();
724− tryCompare(greeter, "shown", false);
725− } else {
726− tryCompare(greeter, "fullyShown", data.greeterShown);
727− }
728−
729− var launcher = findChild(shell, "launcherPanel");
730− tryCompare(launcher, "x", data.launcherHides ? -launcher.width : 0)
731−
732− //FIXME: This check fails. Don't understand the rationale behind it.
733− /*
734− // Make sure the helper for sliding out the launcher wasn't touched. We want to fade it out here.
735− var animateTimer = findInvisibleChild(shell, "animateTimer");
736− compare(animateTimer.nextState, "visible");
737− */
738− }
739−
740− function test_tabletLeftEdgeDrag_data() {
741− return [
742− {tag: "without password", user: "no-password", loggedIn: true},
743− {tag: "with password", user: "has-password", loggedIn: false},
744− ]
745− }
746−
747− function test_tabletLeftEdgeDrag(data) {
748− setLightDMMockMode("full");
749− loadShell("tablet");
750−
751− selectUser(data.user)
752−
753− swipeFromLeftEdge(shell.width * 0.75)
754− wait(500) // to give time to handle dash() signal from Launcher
755− confirmLoggedIn(data.loggedIn)
756− }
757−
758− function test_longLeftEdgeSwipeTakesToAppsAndResetSearchString() {
759− loadShell("phone");
760− swipeAwayGreeter();
761− dragLauncherIntoView();
762− dashCommunicatorSpy.clear();
763−
764− var appSurfaceId = topLevelSurfaceList.nextId;
765− tapOnAppIconInLauncher();
766− waitUntilAppWindowIsFullyLoaded(appSurfaceId);
767−
768− tryCompareFunction(function() { return ApplicationManager.focusedApplicationId !== "unity8-dash"; }, true);
769−
770− //Long left swipe
771− swipeFromLeftEdge(units.gu(30));
772−
773− tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
774−
775− compare(dashCommunicatorSpy.count, 1);
776− }
777−
778 function test_ClickUbuntuIconInLauncherTakesToAppsAndResetSearchString() {
672 function test_ClickUbuntuIconInLauncherTakesToAppsAndResetSearchString() {
779 loadShell("phone");
673 loadShell("phone");
780 swipeAwayGreeter();
674 swipeAwayGreeter();
@@ -913,39 +807,6 @@ Rectangle {
913 LightDM.Users.mockMode = mode;
807 LightDM.Users.mockMode = mode;
914 }
808 }
915
809
916− /*
917− Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
918−
919− When the user minimizes an application (left-edge swipe) he should always end up in the
920− "Applications" scope view.
921−
922− Steps:
923− - reveal launcher and launch an app that covers the dash
924− - perform long left edge swipe to go minimize the app and go back to the dash.
925− - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
926− */
927− function test_minimizingAppTakesToDashApps() {
928− loadShell("phone");
929− swipeAwayGreeter();
930− dragLauncherIntoView();
931−
932− // Launch an app from the launcher
933− var appSurfaceId = topLevelSurfaceList.nextId;
934− tapOnAppIconInLauncher();
935− waitUntilAppWindowIsFullyLoaded(appSurfaceId);
936−
937− verify(ApplicationManager.focusedApplicationId !== "unity8-dash")
938−
939− dashCommunicatorSpy.clear();
940− // Minimize the application we just launched
941− swipeFromLeftEdge(shell.width * 0.75);
942−
943− tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
944−
945− compare(dashCommunicatorSpy.count, 1);
946− compare(dashCommunicatorSpy.signalArguments[0][0], 0);
947− }
948−
949 function test_showInputMethod() {
810 function test_showInputMethod() {
950 loadShell("phone");
811 loadShell("phone");
951 swipeAwayGreeter();
812 swipeAwayGreeter();
@@ -1166,7 +1027,7 @@ Rectangle {
1166
1027
1167 // Place the mouse against the window/screen edge and push beyond the barrier threshold
1028 // Place the mouse against the window/screen edge and push beyond the barrier threshold
1168 mouseMove(shell, 0, shell.height / 2);
1029 mouseMove(shell, 0, shell.height / 2);
1169− launcher.pushEdge(EdgeBarrierSettings.pushThreshold * 1.1);
1030+ launcher.pushEdge(EdgeBarrierSettings.pushThreshold * .8);
1170
1031
1171 var panel = findChild(launcher, "launcherPanel");
1032 var panel = findChild(launcher, "launcherPanel");
1172 verify(panel);
1033 verify(panel);
@@ -1186,9 +1047,7 @@ Rectangle {
1186 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1047 waitUntilAppWindowIsFullyLoaded(appSurfaceId);
1187
1048
1188 // Minimize the application we just launched
1049 // Minimize the application we just launched
1189− swipeFromLeftEdge(shell.width * 0.75);
1050+ swipeFromLeftEdge(units.gu(15));
1190−
1191− waitUntilDashIsFocused();
1192
1051
1193 showGreeter();
1052 showGreeter();
1194
1053
@@ -2779,5 +2638,69 @@ Rectangle {
2779
2638
2780 GSettingsController.setEnableLauncher(true);
2639 GSettingsController.setEnableLauncher(true);
2781 }
2640 }
2641+
2642+ function test_indicatorMenuEnabledSetting_data() {
2643+ return [
2644+ {tag: "indicator menu enabled", enabled: true},
2645+ {tag: "indicator menu disabled", enabled: false}
2646+ ]
2647+ }
2648+
2649+ function test_indicatorMenuEnabledSetting(data) {
2650+ loadShell("phone");
2651+
2652+ GSettingsController.setEnableIndicatorMenu(data.enabled);
2653+
2654+ var panel = findChild(shell, "panel");
2655+ compare(panel.indicators.available, data.enabled);
2656+
2657+ GSettingsController.setEnableIndicatorMenu(true);
2658+ }
2659+
2660+ function test_spreadDisabled_data() {
2661+ return [
2662+ { tag: "enabled", spreadEnabled: true },
2663+ { tag: "disabled", spreadEnabled: false }
2664+ ];
2665+ }
2666+
2667+ function test_spreadDisabled(data) {
2668+ loadShell("phone");
2669+ swipeAwayGreeter();
2670+ var stage = findChild(shell, "stage");
2671+ stage.spreadEnabled = data.spreadEnabled;
2672+
2673+ // Try swiping
2674+ touchFlick(shell, shell.width - 2, shell.height / 2, units.gu(1), shell.height / 2);
2675+ tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2676+
2677+ stage.closeSpread();
2678+ tryCompare(stage, "state", "staged");
2679+
2680+ // Try by edge push
2681+ mouseMove(stage, stage.width - 1, units.gu(10));
2682+ for (var i = 0; i < units.gu(10); i++) {
2683+ stage.pushRightEdge(1);
2684+ }
2685+ mouseMove(stage, stage.width - units.gu(5), units.gu(10));
2686+ tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2687+
2688+ stage.closeSpread();
2689+ tryCompare(stage, "state", "staged");
2690+
2691+ // Try by alt+tab
2692+ keyPress(Qt.Key_Alt);
2693+ keyClick(Qt.Key_Tab);
2694+ tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2695+ keyRelease(Qt.Key_Alt);
2696+
2697+ stage.closeSpread();
2698+ tryCompare(stage, "state", "staged");
2699+
2700+ // Try by Super+W
2701+ keyPress(Qt.Key_W, Qt.MetaModifier)
2702+ tryCompare(stage, "state", data.spreadEnabled ? "spread" : "staged");
2703+ keyRelease(Qt.Key_W, Qt.MetaModifier)
2704+ }
2782 }
2705 }
2783}
2706}
tests/qmltests/tst_ShellWithPin.qml−66
@@ -547,71 +547,5 @@ Item {
547 var lockscreen = findChild(shell, "lockscreen");
547 var lockscreen = findChild(shell, "lockscreen");
548 verify(lockscreen.shown);
548 verify(lockscreen.shown);
549 }
549 }
550−
551− /*
552− Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1393447
553−
554− Do a left edge drag that is long enough to start displacing the greeter
555− but short engough so that the greeter comes back into place once the
556− finger is lifted.
557−
558− In this situation the launcher should remaing fully shown and hide itself
559− only after its idle timeout is triggered.
560− */
561− function test_shortLeftEdgeSwipeMakesLauncherStayVisible() {
562− showGreeter();
563−
564− var launcher = testCase.findChild(shell, "launcher")
565− var launcherPanel = testCase.findChild(launcher, "launcherPanel");
566−
567− var toX = shell.width * 0.45;
568− touchFlick(shell,
569− 1 /* fromX */, shell.height * 0.5 /* fromY */,
570− toX /* toX */, shell.height * 0.5 /* toY */,
571− true /* beginTouch */, false /* endTouch */,
572− 50, 100);
573−
574− // Launcher must be fully shown by now
575− tryCompare(launcherPanel, "x", 0);
576−
577− // Greeter should be displaced
578− var coverPage = findChild(shell, "coverPage");
579− tryCompareFunction(function() { return coverPage.mapToItem(shell, 0, 0).x > shell.width*0.2; }, true);
580−
581− touchRelease(shell, toX, shell.height * 0.5);
582−
583− // Upon release the greeter should have slid back into full view
584− tryCompareFunction(function() { return coverPage.mapToItem(shell, 0, 0).x === 0; }, true);
585−
586− // And the launcher should stay fully shown
587− for (var i = 0; i < 10; ++i) {
588− wait(50);
589− compare(launcherPanel.x, 0);
590− }
591− }
592−
593− function test_longLeftEdgeDrags() {
594− var coverPage = findChild(shell, "coverPage");
595− var lockscreen = findChild(shell, "lockscreen");
596− var launcher = findChild(shell, "launcherPanel");
597− var galleryApp = ApplicationManager.startApplication("gallery-app");
598− tryCompare(shell, "mainApp", galleryApp);
599−
600− // Show greeter
601− showGreeter();
602−
603− // Swipe cover page away
604− touchFlick(shell, 2, shell.height / 2, units.gu(30), shell.height / 2);
605− tryCompare(launcher, "x", -launcher.width);
606− tryCompare(coverPage, "showProgress", 0);
607− compare(lockscreen.shown, true);
608− tryCompare(shell, "mainApp", galleryApp);
609−
610− // Now attempt a swipe on lockscreen
611− touchFlick(shell, 2, shell.height / 2, units.gu(30), shell.height / 2);
612− tryCompare(launcher, "x", 0);
613− compare(lockscreen.shown, true);
614− tryCompare(shell, "mainApp", galleryApp);
615− }
616 }
550 }
617}
551}