on xenial help sign in
adds support for highlighting the currently focused application in the launcher, adds tests.
286fefdMichael Zanetti
Launcher/LauncherDelegate.qml+20−9
@@ -24,6 +24,7 @@ Item {
24 property int count: -1
24 property int count: -1
25 property int progress: -1
25 property int progress: -1
26 property bool highlighted: false
26 property bool highlighted: false
27+ property bool itemFocused: false
27 property real maxAngle: 0
28 property real maxAngle: 0
28 property bool inverted: false
29 property bool inverted: false
29
30
@@ -43,17 +44,18 @@ Item {
43 onCountChanged: shaderEffectSource.scheduleUpdate();
44 onCountChanged: shaderEffectSource.scheduleUpdate();
44 onProgressChanged: shaderEffectSource.scheduleUpdate();
45 onProgressChanged: shaderEffectSource.scheduleUpdate();
45 onHighlightedChanged: shaderEffectSource.scheduleUpdate();
46 onHighlightedChanged: shaderEffectSource.scheduleUpdate();
47+ onItemFocusedChanged: shaderEffectSource.scheduleUpdate();
46
48
47 Item {
49 Item {
48 id: iconItem
50 id: iconItem
49− width: parent.itemWidth
51+ width: parent.itemWidth + units.gu(1)
50− height: parent.itemHeight
52+ height: parent.itemHeight + units.gu(1)
51 anchors.centerIn: parent
53 anchors.centerIn: parent
52
54
53 UbuntuShape {
55 UbuntuShape {
54 id: iconShape
56 id: iconShape
55 anchors.fill: parent
57 anchors.fill: parent
56− anchors.margins: units.gu(0.5)
58+ anchors.margins: units.gu(1)
57 radius: "medium"
59 radius: "medium"
58
60
59 image: Image {
61 image: Image {
@@ -78,7 +80,7 @@ Item {
78 anchors {
80 anchors {
79 right: parent.right
81 right: parent.right
80 top: parent.top
82 top: parent.top
81− margins: -units.dp(1)
83+ margins: units.dp(3)
82 }
84 }
83 width: Math.min(root.itemWidth, Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
85 width: Math.min(root.itemWidth, Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
84 height: units.gu(3)
86 height: units.gu(3)
@@ -105,9 +107,9 @@ Item {
105 left: iconItem.left
107 left: iconItem.left
106 right: iconItem.right
108 right: iconItem.right
107 bottom: iconItem.bottom
109 bottom: iconItem.bottom
108− leftMargin: units.gu(0.5)
110+ leftMargin: units.gu(1)
109− rightMargin: units.gu(0.5)
111+ rightMargin: units.gu(1)
110− bottomMargin: units.gu(0.5)
112+ bottomMargin: units.gu(1)
111 }
113 }
112 height: units.gu(1.5)
114 height: units.gu(1.5)
113 visible: root.progress > -1
115 visible: root.progress > -1
@@ -136,14 +138,23 @@ Item {
136 }
138 }
137 }
139 }
138 }
140 }
141+ Image {
142+ objectName: "focusedHighlight"
143+ anchors {
144+ right: parent.right
145+ verticalCenter: parent.verticalCenter
146+ }
147+ visible: root.itemFocused
148+ source: "graphics/focused_app_arrow.png"
149+ }
139 }
150 }
140
151
141 ShaderEffect {
152 ShaderEffect {
142 id: transformEffect
153 id: transformEffect
143 anchors.centerIn: parent
154 anchors.centerIn: parent
144 anchors.verticalCenterOffset: root.offset
155 anchors.verticalCenterOffset: root.offset
145− width: parent.itemWidth
156+ width: iconItem.width
146− height: parent.itemHeight
157+ height: iconItem.height
147 property real itemOpacity: root.itemOpacity
158 property real itemOpacity: root.itemOpacity
148 property real brightness: Math.max(-1, root.brightness)
159 property real brightness: Math.max(-1, root.brightness)
149 property real angle: root.angle
160 property real angle: root.angle
Launcher/LauncherPanel.qml+3−2
@@ -50,8 +50,6 @@ Item {
50 id: mainColumn
50 id: mainColumn
51 anchors {
51 anchors {
52 fill: parent
52 fill: parent
53− leftMargin: units.gu(0.5)
54− rightMargin: units.gu(0.5)
55 }
53 }
56
54
57 MouseArea {
55 MouseArea {
@@ -94,6 +92,8 @@ Item {
94 fill: parent
92 fill: parent
95 topMargin: -extensionSize + units.gu(0.5)
93 topMargin: -extensionSize + units.gu(0.5)
96 bottomMargin: -extensionSize + units.gu(1)
94 bottomMargin: -extensionSize + units.gu(1)
95+ leftMargin: units.gu(0.5)
96+ rightMargin: units.gu(0.5)
97 }
97 }
98 topMargin: extensionSize
98 topMargin: extensionSize
99 bottomMargin: extensionSize
99 bottomMargin: extensionSize
@@ -156,6 +156,7 @@ Item {
156 iconName: model.icon
156 iconName: model.icon
157 count: model.count
157 count: model.count
158 progress: model.progress
158 progress: model.progress
159+ itemFocused: model.focused
159 inverted: root.inverted
160 inverted: root.inverted
160 z: -Math.abs(offset)
161 z: -Math.abs(offset)
161 maxAngle: 55
162 maxAngle: 55
Launcher/graphics/focused_app_arrow@30.pngnew file

Binary file not shown.

Shell.qml+5−1
@@ -98,7 +98,11 @@ FocusScope {
98
98
99 onMainStageFocusedApplicationChanged: {
99 onMainStageFocusedApplicationChanged: {
100 var app = applicationManager.mainStageFocusedApplication
100 var app = applicationManager.mainStageFocusedApplication
101+ if (app != null) {
101− LauncherModel.applicationFocused(app.desktopFile);
102+ LauncherModel.applicationFocused(app.desktopFile);
103+ } else {
104+ LauncherModel.applicationFocused("");
105+ }
102 }
106 }
103 }
107 }
104
108
plugins/Unity/Launcher/backend/launcherbackend.cpp+6−11
@@ -224,7 +224,11 @@ void LauncherBackend::syncFromAccounts()
224 Q_FOREACH(const QString &entry, gSettings.get("favorites").toStringList()) {
224 Q_FOREACH(const QString &entry, gSettings.get("favorites").toStringList()) {
225 if (entry.startsWith("application://")) {
225 if (entry.startsWith("application://")) {
226 QString appId = entry;
226 QString appId = entry;
227+ // Transform "application://foobar.desktop" to "foobar"
227 appId.remove("application://");
228 appId.remove("application://");
229+ if (appId.endsWith(".desktop")) {
230+ appId.chop(8);
231+ }
228 QString df = findDesktopFile(appId);
232 QString df = findDesktopFile(appId);
229
233
230 if (!df.isEmpty()) {
234 if (!df.isEmpty()) {
@@ -265,18 +269,9 @@ QString LauncherBackend::findDesktopFile(const QString &appId) const
265 QStringList searchDirs;
269 QStringList searchDirs;
266 searchDirs << "/usr/share/applications";
270 searchDirs << "/usr/share/applications";
267
271
268−// FIXME: Right now the appId can be (or rather is) a full path
269−// to a .desktop file. This will change in the future.
270−// Once the ApplicationManager has been switched over to use appIds,
271−// remove this chop() and enable the ifdef to only search the current
272−// working dir for testing. Also, this is the place to add the search
273−// paths for click apps in the next step.
274− if (helper.endsWith(".desktop")) {
275− helper.chop(8);
276− }
277−//#ifdef LAUNCHER_TESTING
272+#ifdef LAUNCHER_TESTING
278 searchDirs << "";
273 searchDirs << "";
279−//#endif
274+#endif
280
275
281 do {
276 do {
282 if (dashPos != -1) {
277 if (dashPos != -1) {
plugins/Unity/Launcher/launcheritem.cpp+14
@@ -31,6 +31,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &desktopFile, con
31 m_recent(false),
31 m_recent(false),
32 m_progress(-1),
32 m_progress(-1),
33 m_count(0),
33 m_count(0),
34+ m_focused(false),
34 m_quickList(new QuickListModel(this))
35 m_quickList(new QuickListModel(this))
35{
36{
36 QuickListEntry nameAction;
37 QuickListEntry nameAction;
@@ -131,6 +132,19 @@ void LauncherItem::setCount(int count)
131 }
132 }
132}
133}
133
134
135+bool LauncherItem::focused() const
136+{
137+ return m_focused;
138+}
139+
140+void LauncherItem::setFocused(bool focused)
141+{
142+ if (m_focused != focused) {
143+ m_focused = focused;
144+ Q_EMIT focusedChanged(focused);
145+ }
146+}
147+
134unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
148unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
135{
149{
136 return m_quickList;
150 return m_quickList;
plugins/Unity/Launcher/launcheritem.h+4
@@ -54,6 +54,9 @@ public:
54 int count() const;
54 int count() const;
55 void setCount(int count);
55 void setCount(int count);
56
56
57+ bool focused() const;
58+ void setFocused(bool focused);
59+
57 unity::shell::launcher::QuickListModelInterface *quickList() const;
60 unity::shell::launcher::QuickListModelInterface *quickList() const;
58
61
59Q_SIGNALS:
62Q_SIGNALS:
@@ -70,6 +73,7 @@ private:
70 bool m_recent;
73 bool m_recent;
71 int m_progress;
74 int m_progress;
72 int m_count;
75 int m_count;
76+ bool m_focused;
73 QuickListModel *m_quickList;
77 QuickListModel *m_quickList;
74};
78};
75
79
plugins/Unity/Launcher/launchermodel.cpp+28−6
@@ -74,6 +74,8 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
74 return item->count();
74 return item->count();
75 case RoleProgress:
75 case RoleProgress:
76 return item->progress();
76 return item->progress();
77+ case RoleFocused:
78+ return item->focused();
77 }
79 }
78
80
79 return QVariant();
81 return QVariant();
@@ -193,18 +195,38 @@ void LauncherModel::setUser(const QString &username)
193
195
194void LauncherModel::applicationFocused(const QString &appId)
196void LauncherModel::applicationFocused(const QString &appId)
195{
197{
196− int index = findApplication(appId);
198+ // Unfocus all apps
199+ for(int i = 0; i < m_list.count(); ++i) {
200+ LauncherItem *item = m_list.at(i);
201+ if (item->focused()) {
202+ item->setFocused(false);
203+ Q_EMIT dataChanged(this->index(i), this->index(i), QVector<int>() << RoleFocused);
204+ }
205+ }
206+
207+ if (appId.isEmpty()) {
208+ return;
209+ }
210+
211+ // FIXME: drop this once we get real appIds from the AppManager
212+ QString helper = appId.split('/').last();
213+ if (helper.endsWith(".desktop")) {
214+ helper.chop(8);
215+ }
197
216
217+ int index = findApplication(helper);
198 if (index >= 0) {
218 if (index >= 0) {
199− // TODO: Mark application as focued
219+ m_list.at(index)->setFocused(true);
220+ Q_EMIT dataChanged(this->index(index), this->index(index), QVector<int>() << RoleFocused);
200 } else {
221 } else {
201 // Add app to recent apps
222 // Add app to recent apps
202− QString desktopFile = m_backend->desktopFile(appId);
223+ QString desktopFile = m_backend->desktopFile(helper);
203− QString appName = m_backend->displayName(appId);
224+ QString appName = m_backend->displayName(helper);
204− QString icon = m_backend->icon(appId);
225+ QString icon = m_backend->icon(helper);
205
226
206− LauncherItem *item = new LauncherItem(appId, desktopFile, appName, icon);
227+ LauncherItem *item = new LauncherItem(helper, desktopFile, appName, icon);
207 item->setRecent(true);
228 item->setRecent(true);
229+ item->setFocused(true);
208 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
230 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
209 m_list.append(item);
231 m_list.append(item);
210 endInsertRows();
232 endInsertRows();
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+16
@@ -33,6 +33,7 @@ MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopF
33 m_recent(false),
33 m_recent(false),
34 m_progress(-1),
34 m_progress(-1),
35 m_count(0),
35 m_count(0),
36+ m_focused(false),
36 m_quickList(new MockQuickListModel(this))
37 m_quickList(new MockQuickListModel(this))
37{
38{
38
39
@@ -128,6 +129,21 @@ void MockLauncherItem::setCount(int count)
128 }
129 }
129}
130}
130
131
132+bool MockLauncherItem::focused() const
133+{
134+ return m_focused;
135+}
136+
137+void MockLauncherItem::setFocused(bool focused)
138+{
139+ if (m_focused != focused)
140+ {
141+ m_focused = focused;
142+ Q_EMIT focusedChanged(focused);
143+ }
144+}
145+
146+
131unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
147unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
132{
148{
133 return m_quickList;
149 return m_quickList;
tests/mocks/Unity/Launcher/MockLauncherItem.h+4
@@ -52,6 +52,9 @@ public:
52 int count() const;
52 int count() const;
53 void setCount(int count);
53 void setCount(int count);
54
54
55+ bool focused() const;
56+ void setFocused(bool focused);
57+
55 unity::shell::launcher::QuickListModelInterface *quickList() const;
58 unity::shell::launcher::QuickListModelInterface *quickList() const;
56
59
57private:
60private:
@@ -64,6 +67,7 @@ private:
64 bool m_recent;
67 bool m_recent;
65 int m_progress;
68 int m_progress;
66 int m_count;
69 int m_count;
70+ bool m_focused;
67 MockQuickListModel *m_quickList;
71 MockQuickListModel *m_quickList;
68};
72};
69
73
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+4
@@ -25,6 +25,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
25 MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
25 MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
26 item->setProgress(0);
26 item->setProgress(0);
27 m_list.append(item);
27 m_list.append(item);
28+ item->setFocused(true);
28 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
29 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
29 item->setProgress(10);
30 item->setProgress(10);
30 m_list.append(item);
31 m_list.append(item);
@@ -49,6 +50,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
49 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad", this);
50 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad", this);
50 item->setProgress(50);
51 item->setProgress(50);
51 item->setCount(5);
52 item->setCount(5);
53+ item->setFocused(true);
52 m_list.append(item);
54 m_list.append(item);
53 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
55 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
54 m_list.append(item);
56 m_list.append(item);
@@ -85,6 +87,8 @@ QVariant MockLauncherModel::data(const QModelIndex& index, int role) const
85 return item->progress();
87 return item->progress();
86 case RoleCount:
88 case RoleCount:
87 return item->count();
89 return item->count();
90+ case RoleFocused:
91+ return item->focused();
88 }
92 }
89
93
90 return QVariant();
94 return QVariant();
tests/plugins/Unity/Launcher/CMakeLists.txt+26−3
@@ -1,4 +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=2)
2
3
3include_directories(
4include_directories(
4 ${CMAKE_CURRENT_BINARY_DIR}
5 ${CMAKE_CURRENT_BINARY_DIR}
@@ -12,11 +13,12 @@ add_definitions(-DSM_BUSNAME=sessionBus)
12add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
13add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
13add_definitions(-DLAUNCHER_TESTING)
14add_definitions(-DLAUNCHER_TESTING)
14
15
16+### LauncherBackendTest
15−set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/launcherbackendtestExec
17+set(testBackendCommand ${CMAKE_CURRENT_BINARY_DIR}/launcherbackendtestExec
16 -o ${CMAKE_BINARY_DIR}/launcherbackendtest.xml,xunitxml
18 -o ${CMAKE_BINARY_DIR}/launcherbackendtest.xml,xunitxml
17 -o -,txt)
19 -o -,txt)
18−add_test(NAME launcherbackendtest COMMAND ${testCommand})
20+add_test(NAME launcherbackendtest COMMAND ${testBackendCommand})
19−add_custom_target(launcherbackendtest ${testCommand})
21+add_custom_target(launcherbackendtest ${testBackendCommand})
20add_executable(launcherbackendtestExec
22add_executable(launcherbackendtestExec
21 launcherbackendtest.cpp
23 launcherbackendtest.cpp
22 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
@@ -26,6 +28,27 @@ add_executable(launcherbackendtestExec
26target_link_libraries(launcherbackendtestExec ${GSETTINGS_QT_LDFLAGS})
28target_link_libraries(launcherbackendtestExec ${GSETTINGS_QT_LDFLAGS})
27qt5_use_modules(launcherbackendtestExec Test Core DBus)
29qt5_use_modules(launcherbackendtestExec Test Core DBus)
28
30
31+### LauncherModelTest
32+set(testModelCommand ${CMAKE_CURRENT_BINARY_DIR}/launchermodeltestExec
33+ -o ${CMAKE_BINARY_DIR}/launchermodeltest.xml,xunitxml
34+ -o -,txt)
35+add_test(NAME launchermodeltest COMMAND ${testModelCommand})
36+add_custom_target(launchermodeltest ${testModelCommand})
37+add_executable(launchermodeltestExec
38+ launchermodeltest.cpp
39+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launchermodel.cpp
40+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launcheritem.cpp
41+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistmodel.cpp
42+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
43+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend/launcherbackend.cpp
44+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/common/quicklistentry.cpp
45+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
46+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
47+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
48+ )
49+target_link_libraries(launchermodeltestExec ${GSETTINGS_QT_LDFLAGS} )
50+qt5_use_modules(launchermodeltestExec Test Core DBus)
51+
29# copy .desktop files into build directory for shadow builds
52# copy .desktop files into build directory for shadow builds
30file(GLOB DESKTOP_FILES *.desktop)
53file(GLOB DESKTOP_FILES *.desktop)
31
54
tests/plugins/Unity/Launcher/launcherbackendtest.cpp+2−2
@@ -30,8 +30,8 @@ private Q_SLOTS:
30 {
30 {
31 LauncherBackend backend(false);
31 LauncherBackend backend(false);
32
32
33− backend.setStoredApplications(QStringList() << "rel-icon.desktop" << "abs-icon" << "invalid");
33+ backend.setStoredApplications(QStringList() << "rel-icon" << "abs-icon" << "invalid");
34− QCOMPARE(backend.storedApplications(), QStringList() << "rel-icon.desktop" << "abs-icon");
34+ QCOMPARE(backend.storedApplications(), QStringList() << "rel-icon" << "abs-icon");
35 }
35 }
36
36
37 void testPinning()
37 void testPinning()
tests/plugins/Unity/Launcher/launchermodeltest.cppnew file+146
@@ -0,0 +1,146 @@
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 Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+// unity-api
21+#include <unity/shell/launcher/LauncherModelInterface.h>
22+
23+#include "launcheritem.h"
24+#include "launchermodel.h"
25+
26+#include <QtTest>
27+
28+class LauncherModelTest : public QObject
29+{
30+ Q_OBJECT
31+
32+private:
33+ LauncherModel *launcherModel;
34+
35+private Q_SLOTS:
36+
37+ void initTestCase() {
38+ launcherModel = new LauncherModel(this);
39+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
40+ }
41+
42+ void init() {
43+ qDebug() << "init";
44+ launcherModel->applicationFocused("abs-icon");
45+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
46+
47+ launcherModel->applicationFocused("no-icon.desktop");
48+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
49+
50+ launcherModel->applicationFocused(QString());
51+ }
52+
53+ void cleanup() {
54+ while (launcherModel->rowCount(QModelIndex()) > 0) {
55+ launcherModel->requestRemove(launcherModel->get(0)->appId());
56+ }
57+ }
58+
59+ void testMove() {
60+ QCOMPARE(launcherModel->get(0)->pinned(), false);
61+ QCOMPARE(launcherModel->get(1)->pinned(), false);
62+
63+ LauncherItemInterface *item0BeforeMove = launcherModel->get(0);
64+ LauncherItemInterface *item1BeforeMove = launcherModel->get(1);
65+ launcherModel->move(1, 0);
66+
67+ QCOMPARE(item0BeforeMove, launcherModel->get(1));
68+ QCOMPARE(item1BeforeMove, launcherModel->get(0));
69+
70+ // moved item must be pinned now
71+ QCOMPARE(item0BeforeMove->pinned(), false);
72+ QCOMPARE(item1BeforeMove->pinned(), true);
73+ }
74+
75+ void testPinning() {
76+ QCOMPARE(launcherModel->get(0)->pinned(), false);
77+ QCOMPARE(launcherModel->get(1)->pinned(), false);
78+ launcherModel->pin(launcherModel->get(0)->appId());
79+ QCOMPARE(launcherModel->get(0)->pinned(), true);
80+ QCOMPARE(launcherModel->get(1)->pinned(), false);
81+ }
82+
83+ void testRemove() {
84+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
85+ launcherModel->requestRemove(launcherModel->get(0)->appId());
86+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
87+ }
88+
89+ void testQuickListPinningRemoving() {
90+ // we start with 2 unpinned items
91+ QCOMPARE(launcherModel->get(0)->pinned(), false);
92+ QCOMPARE(launcherModel->get(1)->pinned(), false);
93+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
94+
95+ // find the Pin item in the quicklist
96+ QuickListModel *model = qobject_cast<QuickListModel*>(launcherModel->get(0)->quickList());
97+ int pinActionIndex = -1;
98+ for (int i = 0; i < model->rowCount(QModelIndex()); ++i) {
99+ if (model->get(i).actionId() == "pin_item") {
100+ pinActionIndex = i;
101+ break;
102+ }
103+ }
104+ QVERIFY(pinActionIndex >= 0);
105+
106+ // trigger pin item quicklist action => Item must be pinned now.
107+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
108+ QCOMPARE(launcherModel->get(0)->pinned(), true);
109+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
110+
111+ // quicklist needs to transform to remove item. trigger it and check it item goes away
112+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
113+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
114+ }
115+
116+ void testApplicationFocused() {
117+ // all apps unfocused at beginning...
118+ QCOMPARE(launcherModel->get(0)->focused(), false);
119+ QCOMPARE(launcherModel->get(1)->focused(), false);
120+
121+ launcherModel->applicationFocused("abs-icon");
122+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
123+ QCOMPARE(launcherModel->get(0)->focused(), true);
124+ QCOMPARE(launcherModel->get(1)->focused(), false);
125+
126+ launcherModel->applicationFocused("no-icon");
127+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
128+ QCOMPARE(launcherModel->get(0)->focused(), false);
129+ QCOMPARE(launcherModel->get(1)->focused(), true);
130+
131+ launcherModel->applicationFocused("rel-icon");
132+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 3);
133+ QCOMPARE(launcherModel->get(0)->focused(), false);
134+ QCOMPARE(launcherModel->get(1)->focused(), false);
135+ QCOMPARE(launcherModel->get(2)->focused(), true);
136+
137+ launcherModel->applicationFocused(QString());
138+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 3);
139+ QCOMPARE(launcherModel->get(0)->focused(), false);
140+ QCOMPARE(launcherModel->get(1)->focused(), false);
141+ QCOMPARE(launcherModel->get(2)->focused(), false);
142+ }
143+};
144+
145+QTEST_GUILESS_MAIN(LauncherModelTest)
146+#include "launchermodeltest.moc"
tests/qmltests/Launcher/tst_Launcher.qml+8
@@ -198,6 +198,14 @@ Item {
198 compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
198 compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
199 }
199 }
200 }
200 }
201+
202+ function test_focusedHighlight() {
203+ var launcherListView = findChild(launcher, "launcherListView");
204+ for (var i = 0; i < launcherListView.count; ++i) {
205+ var delegate = findChild(launcherListView, "launcherDelegate" + i)
206+ compare(findChild(delegate, "focusedHighlight").visible, LauncherModel.get(i).focused)
207+ }
208+ }
201 }
209 }
202
210
203 UT.UnityTestCase {
211 UT.UnityTestCase {