on xenial help sign in
Implement launcher item backend via AccountsService.

Approved by Michael Zanetti, PS Jenkins bot.

commit33445d41beddf0e38f83babf4c964181fbd67fea authorMichael Terry <michael.terry@canonical.com> dateThu 29 Aug 2013, 15:43 (13 years ago) parent5aeae0677f8d9c
18 files changed+365−73
Launcher/LauncherDelegate.qml+1−1 Shell.qml+6 plugins/AccountsService/com.canonical.unity.AccountsService.xml+7 plugins/AccountsService/plugin.cpp+2 plugins/Unity/Launcher/CMakeLists.txt+5−1 plugins/Unity/Launcher/backend/launcherbackend.cpp+171−61 plugins/Unity/Launcher/backend/launcherbackend.h+38−5 plugins/Unity/Launcher/launchermodel.cpp+4−3 plugins/Unity/Launcher/launchermodel.h+1−1 tests/mocks/Unity/Launcher/CMakeLists.txt+2 tests/mocks/Unity/Launcher/MockLauncherItem.cpp+1−1 tests/plugins/Unity/CMakeLists.txt+1 tests/plugins/Unity/Launcher/CMakeLists.txt+22 tests/plugins/Unity/Launcher/abs-icon.desktop+3 tests/plugins/Unity/Launcher/launcherbackendtest.cpp+94 tests/plugins/Unity/Launcher/no-icon.desktop+2 tests/plugins/Unity/Launcher/no-name.desktop+2 tests/plugins/Unity/Launcher/rel-icon.desktop+3
Launcher/LauncherDelegate.qml+1−1
@@ -60,7 +60,7 @@ Item {
6060 id: iconImage
6161 sourceSize.width: iconShape.width
6262 sourceSize.height: iconShape.height
63− source: "../graphics/applicationIcons/" + root.iconName + ".png"
63+ source: root.iconName
6464 }
6565 }
6666
Shell.qml+6
@@ -19,6 +19,7 @@ import GSettings 1.0
1919import Ubuntu.Application 0.1
2020import Ubuntu.Components 0.1
2121import Ubuntu.Gestures 0.1
22+import Unity.Launcher 0.1
2223import LightDM 0.1 as LightDM
2324import Powerd 0.1
2425import "Dash"
@@ -465,6 +466,11 @@ FocusScope {
465466 }
466467
467468 onUnlocked: greeter.hide()
469+ onSelected: {
470+ // Update launcher items for new user
471+ var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
472+ LauncherModel.setUser(user);
473+ }
468474
469475 onLeftTeaserPressedChanged: {
470476 if (leftTeaserPressed) {
plugins/AccountsService/com.canonical.unity.AccountsService.xml+7
@@ -6,6 +6,9 @@
66 <annotation name="org.freedesktop.Accounts.Authentication.ChangeOwn"
77 value="com.canonical.unity.AccountsService.ModifyOwnUser"/>
88
9+ <annotation name="org.freedesktop.Accounts.Authentication.ReadAny"
10+ value="com.canonical.unity.AccountsService.ModifyAnyUser"/>
11+
912 <annotation name="org.freedesktop.Accounts.Authentication.ChangeAny"
1013 value="com.canonical.unity.AccountsService.ModifyAnyUser"/>
1114
@@ -13,5 +16,9 @@
1316 <annotation name="org.freedesktop.Accounts.DefaultValue" value="true"/>
1417 </property>
1518
19+ <property name="launcher-items" type="aa{sv}" access="readwrite">
20+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="[{'defaults': <true>}]"/>
21+ </property>
22+
1623 </interface>
1724</node>
plugins/AccountsService/plugin.cpp+2
@@ -19,6 +19,7 @@
1919#include "plugin.h"
2020#include "AccountsService.h"
2121
22+#include <QDBusMetaType>
2223#include <QtQml>
2324
2425static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
@@ -31,5 +32,6 @@ static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
3132void AccountsServicePlugin::registerTypes(const char *uri)
3233{
3334 Q_ASSERT(uri == QLatin1String("AccountsService"));
35+ qDBusRegisterMetaType<QList<QVariantMap>>();
3436 qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
3537}
plugins/Unity/Launcher/CMakeLists.txt+5−1
@@ -1,8 +1,11 @@
11include(FindPkgConfig)
22pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
33
4+add_definitions(-DSM_BUSNAME=systemBus)
5+
46include_directories(
57 ${CMAKE_CURRENT_SOURCE_DIR}
8+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
69)
710
811set(QMLLAUNCHERPLUGIN_SRC
@@ -12,6 +15,7 @@ set(QMLLAUNCHERPLUGIN_SRC
1215 quicklistmodel.cpp
1316 common/quicklistentry.cpp
1417 backend/launcherbackend.cpp
18+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
1519 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
1620 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
1721 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
@@ -21,7 +25,7 @@ add_library(UnityLauncher-qml MODULE
2125 ${QMLLAUNCHERPLUGIN_SRC}
2226 )
2327
24−qt5_use_modules(UnityLauncher-qml Qml)
28+qt5_use_modules(UnityLauncher-qml DBus Qml)
2529
2630# export the qmldir and qmltypes files
2731export_qmlfiles(Unity.Launcher Unity/Launcher)
plugins/Unity/Launcher/backend/launcherbackend.cpp+171−61
@@ -2,6 +2,7 @@
22 * Copyright (C) 2013 Canonical, Ltd.
33 *
44 * Authors:
5+ * Michael Terry <michael.terry@canonical.com>
56 * Michael Zanetti <michael.zanetti@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
@@ -17,104 +18,111 @@
1718 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1819 */
1920
21+#include "AccountsService.h"
2022#include "launcherbackend.h"
2123
22−#include <QHash>
24+#include <QDir>
25+#include <QDBusArgument>
26+#include <QFileInfo>
2327
24−LauncherBackend::LauncherBackend(QObject *parent):
25− QObject(parent)
28+LauncherBackend::LauncherBackend(bool useStorage, QObject *parent):
29+ QObject(parent),
30+ m_accounts(nullptr)
2631{
27−
28− // TODO: load default pinned ones from default config, instead of hardcoding here...
29−
30− m_storedApps <<
31− QLatin1String("dialer-app.desktop") <<
32− QLatin1String("messaging-app.desktop") <<
33− QLatin1String("address-book-app.desktop") <<
34− QLatin1String("camera-app.desktop") <<
35− QLatin1String("gallery-app.desktop") <<
36− QLatin1String("facebook-webapp.desktop") <<
37− QLatin1String("webbrowser-app.desktop") <<
38− QLatin1String("twitter-webapp.desktop") <<
39− QLatin1String("gmail-webapp.desktop") <<
40− QLatin1String("ubuntu-weather-app.desktop") <<
41− QLatin1String("notes-app.desktop") <<
42− QLatin1String("calendar-app.desktop");
43−
44− // TODO: get stuff from desktop files instead this hardcoded map
45− m_displayNameMap.insert("dialer-app.desktop", "Dialer");
46− m_displayNameMap.insert("messaging-app.desktop", "Messaging");
47− m_displayNameMap.insert("address-book-app.desktop", "Contacts");
48− m_displayNameMap.insert("camera-app.desktop", "Camera");
49− m_displayNameMap.insert("gallery-app.desktop", "Gallery");
50− m_displayNameMap.insert("facebook-webapp.desktop", "Facebook");
51− m_displayNameMap.insert("webbrowser-app.desktop", "Browser");
52− m_displayNameMap.insert("twitter-webapp.desktop", "Twitter");
53− m_displayNameMap.insert("gmail-webapp.desktop", "GMail");
54− m_displayNameMap.insert("ubuntu-weather-app.desktop", "Weather");
55− m_displayNameMap.insert("notes-app.desktop", "Notes");
56− m_displayNameMap.insert("calendar-app.desktop", "Calendar");
57−
58− // TODO: get stuff from desktop files instead this hardcoded map
59− m_iconMap.insert("dialer-app.desktop", "phone-app");
60− m_iconMap.insert("messaging-app.desktop", "messages-app");
61− m_iconMap.insert("address-book-app.desktop", "contacts-app");
62− m_iconMap.insert("camera-app.desktop", "camera");
63− m_iconMap.insert("gallery-app.desktop", "gallery");
64− m_iconMap.insert("facebook-webapp.desktop", "facebook");
65− m_iconMap.insert("webbrowser-app.desktop", "browser");
66− m_iconMap.insert("twitter-webapp.desktop", "twitter");
67− m_iconMap.insert("gmail-webapp.desktop", "gmail");
68− m_iconMap.insert("ubuntu-weather-app.desktop", "weather");
69− m_iconMap.insert("notes-app.desktop", "notepad");
70− m_iconMap.insert("calendar-app.desktop", "calendar");
71−
32+ if (useStorage) {
33+ m_accounts = new AccountsService(this);
34+ }
35+ setUser(qgetenv("USER"));
7236}
7337
7438LauncherBackend::~LauncherBackend()
7539{
40+ clearItems();
41+}
7642
43+void LauncherBackend::clearItems()
44+{
45+ for (LauncherBackendItem &app: m_storedApps) {
46+ delete app.settings;
47+ }
48+ m_storedApps.clear();
7749}
7850
7951QStringList LauncherBackend::storedApplications() const
8052{
81− return m_storedApps;
53+ auto files = QStringList();
54+ for (const LauncherBackendItem &app: m_storedApps) {
55+ files << app.settings->fileName();
56+ }
57+ return files;
8258}
8359
8460void LauncherBackend::setStoredApplications(const QStringList &appIds)
8561{
86− m_storedApps = appIds;
87− // TODO: Cleanup pinned state from settings for apps not in list any more.
62+ // Record all existing pinned apps, so we can notice them in new list
63+ auto pinnedItems = QStringList();
64+ for (LauncherBackendItem &app: m_storedApps) {
65+ if (app.pinned) {
66+ pinnedItems.append(app.settings->fileName());
67+ }
68+ }
69+
70+ clearItems();
71+
72+ for (const QString &appId: appIds) {
73+ loadApp(makeAppDetails(appId, pinnedItems.contains(desktopFile(appId))));
74+ }
75+
76+ syncToAccounts();
8877}
8978
9079QString LauncherBackend::desktopFile(const QString &appId) const
9180{
92− // TODO: return real path instead of this hardcoded one
93− return QLatin1String("/usr/share/applications/") + appId;
81+ QFileInfo fileInfo(QDir("/usr/share/applications"), appId);
82+ return fileInfo.absoluteFilePath();
9483}
9584
9685QString LauncherBackend::displayName(const QString &appId) const
9786{
98− return m_displayNameMap.value(appId);
87+ auto desktopFile = parseDesktopFile(appId);
88+ auto displayName = desktopFile->value("Desktop Entry/Name").toString();
89+ delete desktopFile;
90+ return displayName;
9991}
10092
10193QString LauncherBackend::icon(const QString &appId) const
10294{
103− return m_iconMap.value(appId);
95+ auto desktopFile = parseDesktopFile(appId);
96+ auto iconName = desktopFile->value("Desktop Entry/Icon").toString();
97+ delete desktopFile;
98+
99+ if (!iconName.isEmpty()) {
100+ QFileInfo iconFileInfo(iconName);
101+ if (iconFileInfo.isRelative()) {
102+ iconName = "image://gicon/" + iconName;
103+ }
104+ }
105+
106+ return iconName;
104107}
105108
106109bool LauncherBackend::isPinned(const QString &appId) const
107110{
108− // TODO: return app's pinned state from settings
109− Q_UNUSED(appId)
110− return false;
111+ auto index = findItem(appId);
112+ if (index < 0) {
113+ return false;
114+ } else {
115+ return m_storedApps[index].pinned;
116+ }
111117}
112118
113119void LauncherBackend::setPinned(const QString &appId, bool pinned)
114120{
115− // TODO: Store pinned state in settings.
116− Q_UNUSED(appId)
117− Q_UNUSED(pinned)
121+ auto index = findItem(appId);
122+ if (index >= 0 && !m_storedApps[index].pinned) {
123+ m_storedApps[index].pinned = pinned;
124+ syncToAccounts();
125+ }
118126}
119127
120128QList<QuickListEntry> LauncherBackend::quickList(const QString &appId) const
@@ -143,9 +151,111 @@ int LauncherBackend::count(const QString &appId) const
143151 return 0;
144152}
145153
154+void LauncherBackend::setUser(const QString &username)
155+{
156+ m_user = username;
157+ syncFromAccounts();
158+}
159+
146160void LauncherBackend::triggerQuickListAction(const QString &appId, const QString &quickListId)
147161{
148162 // TODO: execute the given quicklist action
149163 Q_UNUSED(appId)
150164 Q_UNUSED(quickListId)
151165}
166+
167+void LauncherBackend::syncFromAccounts()
168+{
169+ QList<QVariantMap> apps;
170+ bool defaults = true;
171+
172+ clearItems();
173+
174+ if (m_user != "" && m_accounts != nullptr) {
175+ auto variant = m_accounts->getUserProperty(m_user, "launcher-items");
176+ apps = qdbus_cast<QList<QVariantMap>>(variant.value<QDBusArgument>());
177+ defaults = isDefaultsItem(apps);
178+ }
179+
180+ // TODO: load default pinned ones from default config, instead of hardcoding here...
181+ if (defaults) {
182+ apps <<
183+ makeAppDetails("dialer-app.desktop", true) <<
184+ makeAppDetails("messaging-app.desktop", true) <<
185+ makeAppDetails("address-book-app.desktop", true) <<
186+ makeAppDetails("camera-app.desktop", true) <<
187+ makeAppDetails("gallery-app.desktop", true) <<
188+ makeAppDetails("facebook-webapp.desktop", true) <<
189+ makeAppDetails("webbrowser-app.desktop", true) <<
190+ makeAppDetails("twitter-webapp.desktop", true) <<
191+ makeAppDetails("gmail-webapp.desktop", true) <<
192+ makeAppDetails("ubuntu-weather-app.desktop", true) <<
193+ makeAppDetails("notes-app.desktop", true) <<
194+ makeAppDetails("calendar-app.desktop", true);
195+ }
196+
197+ for (const QVariant &app: apps) {
198+ loadApp(app.toMap());
199+ }
200+}
201+
202+void LauncherBackend::syncToAccounts()
203+{
204+ if (m_user != "" && m_accounts != nullptr) {
205+ QList<QVariantMap> items;
206+
207+ for (LauncherBackendItem &app: m_storedApps) {
208+ items << makeAppDetails(app.settings->fileName(), app.pinned);
209+ }
210+
211+ m_accounts->setUserProperty(m_user, "launcher-items", QVariant::fromValue(items));
212+ }
213+}
214+
215+QSettings *LauncherBackend::parseDesktopFile(const QString &appId) const
216+{
217+ auto fullAppId = desktopFile(appId);
218+ return new QSettings(fullAppId, QSettings::IniFormat);
219+}
220+
221+void LauncherBackend::loadApp(const QVariantMap &details)
222+{
223+ auto appId = details.value("id").toString();
224+ auto isPinned = details.value("is-pinned").toBool();
225+
226+ if (appId.isEmpty()) {
227+ return;
228+ }
229+
230+ LauncherBackendItem item;
231+ item.settings = parseDesktopFile(appId);
232+ item.pinned = isPinned;
233+ m_storedApps.append(item);
234+}
235+
236+QVariantMap LauncherBackend::makeAppDetails(const QString &appId, bool pinned) const
237+{
238+ QVariantMap details;
239+ details.insert("id", appId);
240+ details.insert("is-pinned", pinned);
241+ return details;
242+}
243+
244+bool LauncherBackend::isDefaultsItem(const QList<QVariantMap> &apps) const
245+{
246+ // To differentiate between an empty list and a list that hasn't been set
247+ // yet (and should thus be populated with the defaults), we use a special
248+ // list of one item with the 'defaults' field set to true.
249+ return (apps.size() == 1 && apps[0].value("defaults").toBool());
250+}
251+
252+int LauncherBackend::findItem(const QString &appId) const
253+{
254+ auto fullAppId = desktopFile(appId);
255+ for (int i = 0; i < m_storedApps.size(); ++i) {
256+ if (m_storedApps[i].settings->fileName() == fullAppId) {
257+ return i;
258+ }
259+ }
260+ return -1;
261+}
plugins/Unity/Launcher/backend/launcherbackend.h+38−5
@@ -22,8 +22,10 @@
2222#include "common/quicklistentry.h"
2323
2424#include <QObject>
25+#include <QSettings>
2526#include <QStringList>
26−#include <QHash>
27+
28+class AccountsService;
2729
2830/**
2931 * @brief An interface that provides all the data needed by the launcher.
@@ -35,7 +37,7 @@ class LauncherBackend : public QObject
3537
3638
3739public:
38− LauncherBackend(QObject *parent = 0);
40+ LauncherBackend(bool useStorage = true, QObject *parent = 0);
3941 virtual ~LauncherBackend();
4042
4143 /**
@@ -57,12 +59,18 @@ public:
5759
5860 /**
5961 * @brief Get the full path to the .desktop file.
62+ *
63+ * The application does not need to be in the list of stored applications.
64+ *
6065 * @returns The full path to the .dekstop file.
6166 */
6267 QString desktopFile(const QString &appId) const;
6368
6469 /**
6570 * @brief Get the user friendly name of an application.
71+ *
72+ * The application does not need to be in the list of stored applications.
73+ *
6674 * @param appId The ID of the application.
6775 * @returns The user friendly name of the application.
6876 */
@@ -70,6 +78,9 @@ public:
7078
7179 /**
7280 * @brief Get the icon of an application.
81+ *
82+ * The application does not need to be in the list of stored applications.
83+ *
7384 * @param appId The ID of the application.
7485 * @returns The full path to the icon for the application.
7586 */
@@ -118,15 +129,37 @@ public:
118129 */
119130 int count(const QString &appId) const;
120131
132+ /**
133+ * @brief Sets the username for which to look up launcher items.
134+ * @param username The username to use.
135+ */
136+ void setUser(const QString &username);
137+
121138Q_SIGNALS:
122139 void quickListChanged(const QString &appId, const QList<QuickListEntry> &quickList);
123140 void progressChanged(const QString &appId, int progress);
124141 void countChanged(const QString &appId, int count);
125142
126143private:
127− QStringList m_storedApps;
128− QHash<QString, QString> m_displayNameMap;
129− QHash<QString, QString> m_iconMap;
144+ QSettings *parseDesktopFile(const QString &appId) const;
145+ QVariantMap makeAppDetails(const QString &appId, bool pinned) const;
146+ void loadApp(const QVariantMap &details);
147+ int findItem(const QString &appId) const;
148+ bool isDefaultsItem(const QList<QVariantMap> &apps) const;
149+ void syncFromAccounts();
150+ void syncToAccounts();
151+ void clearItems();
152+
153+ class LauncherBackendItem
154+ {
155+ public:
156+ QSettings *settings;
157+ bool pinned;
158+ };
159+
160+ QList<LauncherBackendItem> m_storedApps;
161+ AccountsService *m_accounts;
162+ QString m_user;
130163};
131164
132165#endif // LAUNCHERBACKEND_H
plugins/Unity/Launcher/launchermodel.cpp+4−3
@@ -23,7 +23,7 @@
2323
2424LauncherModel::LauncherModel(QObject *parent):
2525 LauncherModelInterface(parent),
26− m_backend(new LauncherBackend(this))
26+ m_backend(new LauncherBackend(true, this))
2727{
2828 connect(m_backend, SIGNAL(countChanged(QString,int)), SLOT(countChanged(QString,int)));
2929 connect(m_backend, SIGNAL(progressChanged(QString,int)), SLOT(progressChanged(QString,int)));
@@ -123,6 +123,7 @@ void LauncherModel::pin(const QString &appId, int index)
123123 if (currentIndex >= 0) {
124124 if (index == -1 || index == currentIndex) {
125125 m_list.at(currentIndex)->setPinned(true);
126+ m_backend->setPinned(appId, true);
126127 QModelIndex modelIndex = this->index(currentIndex);
127128 Q_EMIT dataChanged(modelIndex, modelIndex);
128129 } else {
@@ -138,6 +139,7 @@ void LauncherModel::pin(const QString &appId, int index)
138139 m_backend->displayName(appId),
139140 m_backend->icon(appId));
140141 item->setPinned(true);
142+ m_backend->setPinned(appId, true);
141143 m_list.insert(index, item);
142144 endInsertRows();
143145 }
@@ -186,8 +188,7 @@ void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex
186188
187189void LauncherModel::setUser(const QString &username)
188190{
189− Q_UNUSED(username)
190− // TODO: Implement this...
191+ m_backend->setUser(username);
191192}
192193
193194void LauncherModel::storeAppList()
plugins/Unity/Launcher/launchermodel.h+1−1
@@ -17,7 +17,7 @@
1717 * Michael Zanetti <michael.zanetti@canonical.com>
1818 */
1919
20−#ifndef LAUNCHERMODELH
20+#ifndef LAUNCHERMODEL_H
2121#define LAUNCHERMODEL_H
2222
2323// unity-api
tests/mocks/Unity/Launcher/CMakeLists.txt+2
@@ -1,6 +1,8 @@
11include(FindPkgConfig)
22pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
33
4+add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
5+
46include_directories(
57 ${CMAKE_CURRENT_SOURCE_DIR}
68)
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+1−1
@@ -27,7 +27,7 @@ MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopF
2727 m_appId(appId),
2828 m_desktopFile(desktopFile),
2929 m_name(name),
30− m_icon(icon),
30+ m_icon(TOP_SRCDIR "/graphics/applicationIcons/" + icon + ".png"),
3131 m_pinned(false),
3232 m_running(false),
3333 m_recent(false),
tests/plugins/Unity/CMakeLists.txt+1
@@ -1,4 +1,5 @@
11add_subdirectory(Indicators)
2+add_subdirectory(Launcher)
23
34pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0)
45pkg_check_modules(LIBUNITYPROTO REQUIRED unity-protocol-private)
tests/plugins/Unity/Launcher/CMakeLists.txtnew file+22
@@ -0,0 +1,22 @@
1+include_directories(
2+ ${CMAKE_CURRENT_BINARY_DIR}
3+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService
4+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
5+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend
6+ )
7+
8+add_definitions(-DSM_BUSNAME=sessionBus)
9+add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
10+
11+set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/launcherbackendtestExec
12+ -o ${CMAKE_BINARY_DIR}/launcherbackendtest.xml,xunitxml
13+ -o -,txt)
14+add_test(NAME launcherbackendtest COMMAND ${testCommand})
15+add_custom_target(launcherbackendtest ${testCommand})
16+add_executable(launcherbackendtestExec
17+ launcherbackendtest.cpp
18+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
19+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend/launcherbackend.cpp
20+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/common/quicklistentry.cpp
21+ )
22+qt5_use_modules(launcherbackendtestExec Test Core DBus)
tests/plugins/Unity/Launcher/abs-icon.desktopnew file+3
@@ -0,0 +1,3 @@
1+[Desktop Entry]
2+Name=Absolute Icon
3+Icon=/path/to/icon.png
tests/plugins/Unity/Launcher/launcherbackendtest.cppnew file+94
@@ -0,0 +1,94 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Terry <michael.terry@canonical.com>
18+ */
19+
20+#include "launcherbackend.h"
21+
22+#include <QtTest>
23+#include <QDebug>
24+
25+class LauncherBackendTest : public QObject
26+{
27+ Q_OBJECT
28+
29+private Q_SLOTS:
30+ void testFileNames()
31+ {
32+ LauncherBackend backend(false);
33+
34+ backend.setStoredApplications(QStringList() << "relative.path" << "/full/path");
35+ QCOMPARE(backend.storedApplications(), QStringList() << "/usr/share/applications/relative.path" << "/full/path");
36+
37+ QCOMPARE(backend.desktopFile("one.desktop"), QString("/usr/share/applications/one.desktop"));
38+ QCOMPARE(backend.desktopFile("two"), QString("/usr/share/applications/two"));
39+ QCOMPARE(backend.desktopFile("/full"), QString("/full"));
40+
41+ QCOMPARE(backend.desktopFile("/usr/share/applications/one.desktop"), QString("/usr/share/applications/one.desktop"));
42+ }
43+
44+ void testDesktopReading()
45+ {
46+ LauncherBackend backend(false);
47+
48+ QCOMPARE(backend.displayName(SRCDIR "/rel-icon.desktop"), QString("Relative Icon"));
49+ QCOMPARE(backend.icon(SRCDIR "/rel-icon.desktop"), QString("image://gicon/rel-icon"));
50+
51+ QCOMPARE(backend.displayName(SRCDIR "/abs-icon.desktop"), QString("Absolute Icon"));
52+ QCOMPARE(backend.icon(SRCDIR "/abs-icon.desktop"), QString("/path/to/icon.png"));
53+
54+ QCOMPARE(backend.displayName(SRCDIR "/no-icon.desktop"), QString("No Icon"));
55+ QCOMPARE(backend.icon(SRCDIR "/no-icon.desktop"), QString(""));
56+
57+ QCOMPARE(backend.displayName(SRCDIR "/no-name.desktop"), QString(""));
58+ QCOMPARE(backend.icon(SRCDIR "/no-name.desktop"), QString("image://gicon/no-name"));
59+
60+ QCOMPARE(backend.displayName(SRCDIR "/no-exist.desktop"), QString(""));
61+ QCOMPARE(backend.icon(SRCDIR "/no-exist.desktop"), QString(""));
62+ }
63+
64+ void testPinning()
65+ {
66+ LauncherBackend backend(false);
67+
68+ // Confirm that default entries are all pinned
69+ auto defaultApps = backend.storedApplications();
70+ QVERIFY(defaultApps.size() > 0);
71+ for (auto app: defaultApps) {
72+ QCOMPARE(backend.isPinned(app), true);
73+ }
74+
75+ backend.setStoredApplications(QStringList() << "one" << "two");
76+ QCOMPARE(backend.isPinned("one"), false);
77+ QCOMPARE(backend.isPinned("two"), false);
78+
79+ backend.setPinned("two", true);
80+ QCOMPARE(backend.isPinned("two"), true);
81+
82+ backend.setStoredApplications(QStringList() << "one" << "two" << "three");
83+ QCOMPARE(backend.isPinned("two"), true);
84+ QCOMPARE(backend.isPinned("three"), false);
85+
86+ backend.setPinned("three", true);
87+ backend.setStoredApplications(QStringList() << "one" << "two");
88+ QCOMPARE(backend.isPinned("two"), true);
89+ QCOMPARE(backend.isPinned("three"), false); // doesn't exist anymore!
90+ }
91+};
92+
93+QTEST_GUILESS_MAIN(LauncherBackendTest)
94+#include "launcherbackendtest.moc"
tests/plugins/Unity/Launcher/no-icon.desktopnew file+2
@@ -0,0 +1,2 @@
1+[Desktop Entry]
2+Name=No Icon
tests/plugins/Unity/Launcher/no-name.desktopnew file+2
@@ -0,0 +1,2 @@
1+[Desktop Entry]
2+Icon=no-name
tests/plugins/Unity/Launcher/rel-icon.desktopnew file+3
@@ -0,0 +1,3 @@
1+[Desktop Entry]
2+Name=Relative Icon
3+Icon=rel-icon