Merge lp:~lukas-kde/unity8/closeAppsFromQuicklist into lp:unity8

Proposed by Lukáš Tinkl
Status: Superseded
Proposed branch: lp:~lukas-kde/unity8/closeAppsFromQuicklist
Merge into: lp:unity8
Diff against target: 736 lines (+184/-59)
16 files modified
plugins/Unity/Launcher/asadapter.cpp (+2/-2)
plugins/Unity/Launcher/asadapter.h (+1/-1)
plugins/Unity/Launcher/launcheritem.cpp (+10/-0)
plugins/Unity/Launcher/launcheritem.h (+1/-0)
plugins/Unity/Launcher/launchermodel.cpp (+38/-22)
plugins/Unity/Launcher/quicklistentry.cpp (+6/-2)
plugins/Unity/Launcher/quicklistentry.h (+3/-1)
plugins/Unity/Launcher/quicklistmodel.cpp (+12/-1)
plugins/Unity/Launcher/quicklistmodel.h (+3/-1)
qml/Launcher/LauncherPanel.qml (+24/-15)
src/MouseTouchAdaptor.cpp (+6/-6)
tests/mocks/Unity/Launcher/MockLauncherItem.cpp (+3/-0)
tests/mocks/Unity/Launcher/MockLauncherItem.h (+1/-0)
tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+4/-1)
tests/plugins/Unity/Launcher/launchermodeltest.cpp (+41/-0)
tests/qmltests/Launcher/tst_Launcher.qml (+29/-7)
To merge this branch: bzr merge lp:~lukas-kde/unity8/closeAppsFromQuicklist
Reviewer Review Type Date Requested Status
Daniel d'Andrada (community) Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+261614@code.launchpad.net

This proposal has been superseded by a proposal from 2015-06-18.

Commit message

launcher parity: close apps from quicklist

Description of the change

launcher parity: close apps from quicklist

- adds a Quit item to the launcher quicklist
- reverts the visual appearance to the old design of popup menus
- invokes the popup menu also on the right mouse click

 * Are there any related MPs required for this MP to build/function as expected? Please list.

No

 * Did you perform an exploratory manual test run of your code change and any related functionality?

Yes

 * Did you make sure that your branch does not contain spurious tags?

Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?

N/A

 * If you changed the UI, has there been a design review?

No (however, there is a revert to the old design)

 * Did you have a look at the warnings when running tests? Can they be reduced?

Yes

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

I see you have lp:~lukas-kde/unity8/highdpi-mousetouchadaptor in this branch. Either remove those changes or make lp:~lukas-kde/unity8/highdpi-mousetouchadaptor a prerequisite.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

In qml/Launcher/LauncherPanel.qml

"""
- __foregroundColor: "black"
+ __foregroundColor: Theme.palette.selected.backgroundText
"""

"Theme" is deprecated. Please use the context variable "theme" instead. We have tons of warnings on this already. See https://code.launchpad.net/~dandrader/unity8/deprecatedTheme/+merge/262216

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

I would like to see a qml test launches an app and then closes it using this "quit" quick list menu entry.

I should also be able to manually test this feature or try it out (eg, via "make tryShell"), without having to flash a device for that.

review: Needs Fixing
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

> I would like to see a qml test launches an app and then closes it using this
> "quit" quick list menu entry.

There is already a test for this, albeit not a QML one: launchermodeltest.cp, void testQuitMenuItem()

> I should also be able to manually test this feature or try it out (eg, via
> "make tryShell"), without having to flash a device for that.

Right, I'll see what I can do with that but I'd prefer doing that in a separate MP; it goes a bit beyond the scope of this review, none of the current quick list actions are testable from QML yet (Pin/Unpin etc).

1812. By Lukáš Tinkl

address MP issues

1813. By Lukáš Tinkl

[ Albert Astals Cid ]
* Refactor QmlTest.cmake module so that all tests can go through it.
  Also a bit of cleanup around tests.
* Support fallback images for dash card and preview widgets (LP:
  #1324142)
[ CI Train Bot ]
* New rebuild forced.
* Resync trunk.
[ Daniel d'Andrada ]
* Fix Shell tests
[ Josh Arenson ]
* Refactor greeter emulator to unlock the greeter via dbus
[ Lukáš Tinkl ]
* respect target window's devicePixelRatio in MouseTouchAdaptor
[ Michael Zanetti ]
* Refactor QmlTest.cmake module so that all tests can go through it.
  Also a bit of cleanup around tests.
[ Michał Sawicz ]
* Refactor QmlTest.cmake module so that all tests can go through it.
  Also a bit of cleanup around tests.
[ handsome_feng ]
* Forbid closing apps during the edge gesture. (LP: #1445572)
* Removed the horizonal rule on pin unlock screen. (LP: #1368798)
[ handsome_feng<email address hidden> ]
* Forbid closing apps during the edge gesture. (LP: #1445572)
* No-change rebuild against Qt 5.4.2.
[ Michał Sawicz ]
* Implement full-shell rotation (LP: #1210199)
[ CI Train Bot ]
* New rebuild forced.
* Resync trunk.
[ Daniel d'Andrada ]
* Implemented autopilot-test and fake-sensors for shell-rotation.
[ Mirco Müller ]
* Implemented autopilot-test and fake-sensors for shell-rotation.

1814. By Lukáš Tinkl

restore light menu color, arrow pointing always towards the launcher

1815. By Lukáš Tinkl

calculate the arrow's offset correctly

1816. By Lukáš Tinkl

implement missing bits of the "running" interfaces

1817. By Lukáš Tinkl

fix white-on-white text in the quicklist

1818. By Lukáš Tinkl

emit dataChanged

1819. By Lukáš Tinkl

emit dataChanged(Running) correctly when the app appears/disappears

1820. By Lukáš Tinkl

no need to emit RoleRunning twice

1821. By Lukáš Tinkl

sync items when changing running state; set the initial running state in refresh()

1822. By Lukáš Tinkl

set the running status also for the already pinned apps

1823. By Lukáš Tinkl

sset the item to "running" in all cases when it appears

1824. By Lukáš Tinkl

merge and fix conflict

1825. By Lukáš Tinkl

drop dbusinterface changes

1826. By Lukáš Tinkl

rebase on top of lp:~macslow/unity8/use-set-progress-api

1827. By Lukáš Tinkl

re-merge again on top of use-set-progress-api to fix failing QML tests

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Unity/Launcher/asadapter.cpp'
2--- plugins/Unity/Launcher/asadapter.cpp 2015-02-11 14:13:26 +0000
3+++ plugins/Unity/Launcher/asadapter.cpp 2015-06-18 11:46:46 +0000
4@@ -34,12 +34,12 @@
5 m_accounts->deleteLater();
6 }
7
8-void ASAdapter::syncItems(QList<LauncherItem *> m_list)
9+void ASAdapter::syncItems(const QList<LauncherItem*> &list)
10 {
11 if (m_accounts && !m_user.isEmpty()) {
12 QList<QVariantMap> items;
13
14- Q_FOREACH(LauncherItem *item, m_list) {
15+ Q_FOREACH(LauncherItem *item, list) {
16 items << itemToVariant(item);
17 }
18
19
20=== modified file 'plugins/Unity/Launcher/asadapter.h'
21--- plugins/Unity/Launcher/asadapter.h 2015-02-11 14:13:26 +0000
22+++ plugins/Unity/Launcher/asadapter.h 2015-06-18 11:46:46 +0000
23@@ -29,7 +29,7 @@
24 ASAdapter();
25 ~ASAdapter();
26
27- void syncItems(QList<LauncherItem*> m_list);
28+ void syncItems(const QList<LauncherItem*> &list);
29
30 private:
31 QVariantMap itemToVariant(LauncherItem *item) const;
32
33=== modified file 'plugins/Unity/Launcher/launcheritem.cpp'
34--- plugins/Unity/Launcher/launcheritem.cpp 2014-11-19 17:43:09 +0000
35+++ plugins/Unity/Launcher/launcheritem.cpp 2015-06-18 11:46:46 +0000
36@@ -40,10 +40,15 @@
37 nameAction.setActionId("launch_item");
38 nameAction.setText(m_name);
39 m_quickList->appendAction(nameAction);
40+
41 QuickListEntry pinningAction;
42 pinningAction.setActionId("pin_item");
43 pinningAction.setText(gettext("Pin shortcut"));
44 m_quickList->appendAction(pinningAction);
45+
46+ m_quitAction.setActionId("stop_item");
47+ m_quitAction.setIcon("application-exit");
48+ m_quitAction.setText(gettext("Quit"));
49 }
50
51 QString LauncherItem::appId() const
52@@ -110,6 +115,11 @@
53 {
54 if (m_running != running) {
55 m_running = running;
56+ if (m_running) { // add the quit action
57+ m_quickList->appendAction(m_quitAction);
58+ } else { // remove the quit action
59+ m_quickList->removeAction(m_quitAction);
60+ }
61 Q_EMIT runningChanged(running);
62 }
63 }
64
65=== modified file 'plugins/Unity/Launcher/launcheritem.h'
66--- plugins/Unity/Launcher/launcheritem.h 2014-09-02 18:22:37 +0000
67+++ plugins/Unity/Launcher/launcheritem.h 2015-06-18 11:46:46 +0000
68@@ -70,6 +70,7 @@
69 bool m_countVisible;
70 bool m_focused;
71 QuickListModel *m_quickList;
72+ QuickListEntry m_quitAction;
73
74 friend class LauncherModel;
75 };
76
77=== modified file 'plugins/Unity/Launcher/launchermodel.cpp'
78--- plugins/Unity/Launcher/launchermodel.cpp 2015-03-30 17:36:42 +0000
79+++ plugins/Unity/Launcher/launchermodel.cpp 2015-06-18 11:46:46 +0000
80@@ -82,9 +82,14 @@
81 return item->progress();
82 case RoleFocused:
83 return item->focused();
84+ case RoleRunning:
85+ return item->running();
86+ default:
87+ qWarning() << Q_FUNC_INFO << "missing role, implement me";
88+ return QVariant();
89 }
90
91- return QVariant();
92+ return LauncherModelInterface::data(index, role);
93 }
94
95 unity::shell::launcher::LauncherItemInterface *LauncherModel::get(int index) const
96@@ -134,7 +139,7 @@
97 if (index == -1 || index == currentIndex) {
98 m_list.at(currentIndex)->setPinned(true);
99 QModelIndex modelIndex = this->index(currentIndex);
100- Q_EMIT dataChanged(modelIndex, modelIndex, QVector<int>() << RolePinned);
101+ Q_EMIT dataChanged(modelIndex, modelIndex, {RolePinned});
102 } else {
103 move(currentIndex, index);
104 // move() will store the list to the backend itself, so just exit at this point.
105@@ -147,7 +152,7 @@
106
107 DesktopFileHandler desktopFile(appId);
108 if (!desktopFile.isValid()) {
109- qWarning() << "Can't pin this application, there is no .destkop file available.";
110+ qWarning() << "Can't pin this application, there is no .desktop file available.";
111 return;
112 }
113
114@@ -172,7 +177,7 @@
115
116 void LauncherModel::quickListActionInvoked(const QString &appId, int actionIndex)
117 {
118- int index = findApplication(appId);
119+ const int index = findApplication(appId);
120 if (index < 0) {
121 return;
122 }
123@@ -180,7 +185,7 @@
124 LauncherItem *item = m_list.at(index);
125 QuickListModel *model = qobject_cast<QuickListModel*>(item->quickList());
126 if (model) {
127- QString actionId = model->get(actionIndex).actionId();
128+ const QString actionId = model->get(actionIndex).actionId();
129
130 // Check if this is one of the launcher actions we handle ourselves
131 if (actionId == "pin_item") {
132@@ -191,7 +196,8 @@
133 }
134 } else if (actionId == "launch_item") {
135 QDesktopServices::openUrl(getUrlForAppId(appId));
136-
137+ } else if (actionId == "stop_item") { // Quit
138+ m_appManager->stopApplication(appId);
139 // Nope, we don't know this action, let the backend forward it to the application
140 } else {
141 // TODO: forward quicklist action to app, possibly via m_dbusIface
142@@ -272,6 +278,7 @@
143
144 void LauncherModel::setOnlyPinned(bool onlyPinned) {
145 Q_UNUSED(onlyPinned);
146+ // FIXME implement showing only pinned apps
147 qWarning() << "This launcher implementation does not support showing only pinned apps";
148 }
149
150@@ -289,7 +296,7 @@
151
152 void LauncherModel::unpin(const QString &appId)
153 {
154- int index = findApplication(appId);
155+ const int index = findApplication(appId);
156 if (index < 0) {
157 return;
158 }
159@@ -298,7 +305,7 @@
160 if (m_list.at(index)->pinned()) {
161 m_list.at(index)->setPinned(false);
162 QModelIndex modelIndex = this->index(index);
163- Q_EMIT dataChanged(modelIndex, modelIndex, QVector<int>() << RolePinned);
164+ Q_EMIT dataChanged(modelIndex, modelIndex, {RolePinned});
165 }
166 } else {
167 beginRemoveRows(QModelIndex(), index, index);
168@@ -320,21 +327,21 @@
169
170 void LauncherModel::progressChanged(const QString &appId, int progress)
171 {
172- int idx = findApplication(appId);
173+ const int idx = findApplication(appId);
174 if (idx >= 0) {
175 LauncherItem *item = m_list.at(idx);
176 item->setProgress(progress);
177- Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleProgress);
178+ Q_EMIT dataChanged(index(idx), index(idx), {RoleProgress});
179 }
180 }
181
182 void LauncherModel::countChanged(const QString &appId, int count)
183 {
184- int idx = findApplication(appId);
185+ const int idx = findApplication(appId);
186 if (idx >= 0) {
187 LauncherItem *item = m_list.at(idx);
188 item->setCount(count);
189- Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleCount);
190+ Q_EMIT dataChanged(index(idx), index(idx), {RoleCount});
191 m_asAdapter->syncItems(m_list);
192 }
193 }
194@@ -345,7 +352,7 @@
195 if (idx >= 0) {
196 LauncherItem *item = m_list.at(idx);
197 item->setCountVisible(countVisible);
198- Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleCountVisible);
199+ Q_EMIT dataChanged(index(idx), index(idx), {RoleCountVisible});
200
201 // If countVisible goes to false, and the item is neither pinned nor recent we can drop it
202 if (!countVisible && !item->pinned() && !item->recent()) {
203@@ -387,7 +394,7 @@
204 item->setName(desktopFile.displayName());
205 item->setIcon(desktopFile.icon());
206 item->setPinned(item->pinned()); // update pinned text if needed
207- Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleName << RoleIcon);
208+ Q_EMIT dataChanged(index(idx), index(idx), {RoleName, RoleIcon});
209 }
210 }
211
212@@ -405,7 +412,7 @@
213
214 // Now walk through settings and see if we need to add something
215 for (int settingsIndex = 0; settingsIndex < m_settings->storedApplications().count(); ++settingsIndex) {
216- QString entry = m_settings->storedApplications().at(settingsIndex);
217+ const QString entry = m_settings->storedApplications().at(settingsIndex);
218 int itemIndex = -1;
219 for (int i = 0; i < m_list.count(); ++i) {
220 if (m_list.at(i)->appId() == entry) {
221@@ -468,18 +475,19 @@
222 return;
223 }
224
225- int itemIndex = findApplication(app->appId());
226+ const int itemIndex = findApplication(app->appId());
227 if (itemIndex != -1) {
228 LauncherItem *item = m_list.at(itemIndex);
229 if (!item->recent()) {
230 item->setRecent(true);
231 m_asAdapter->syncItems(m_list);
232- Q_EMIT dataChanged(index(itemIndex), index(itemIndex), QVector<int>() << RoleRecent);
233+ Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRecent});
234 }
235- // Shall we paint some running/recent app highlight? If yes, do it here.
236+ // TODO Shall we paint some running/recent app highlight? If yes, do it here.
237 } else {
238 LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
239 item->setRecent(true);
240+ item->setRunning(true);
241 item->setFocused(app->focused());
242
243 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
244@@ -501,7 +509,15 @@
245 }
246 }
247
248- if (appIndex > -1 && !m_list.at(appIndex)->pinned()) {
249+ if (appIndex < 0) {
250+ qWarning() << Q_FUNC_INFO << "appIndex not found";
251+ return;
252+ }
253+
254+ LauncherItem * item = m_list.at(appIndex);
255+ item->setRunning(false);
256+
257+ if (!item->pinned()) {
258 beginRemoveRows(QModelIndex(), appIndex, appIndex);
259 m_list.takeAt(appIndex)->deleteLater();
260 endRemoveRows();
261@@ -511,15 +527,15 @@
262
263 void LauncherModel::focusedAppIdChanged()
264 {
265- QString appId = m_appManager->focusedApplicationId();
266+ const QString appId = m_appManager->focusedApplicationId();
267 for (int i = 0; i < m_list.count(); ++i) {
268 LauncherItem *item = m_list.at(i);
269 if (!item->focused() && item->appId() == appId) {
270 item->setFocused(true);
271- Q_EMIT dataChanged(index(i), index(i), QVector<int>() << RoleFocused);
272+ Q_EMIT dataChanged(index(i), index(i), {RoleFocused});
273 } else if (item->focused() && item->appId() != appId) {
274 item->setFocused(false);
275- Q_EMIT dataChanged(index(i), index(i), QVector<int>() << RoleFocused);
276+ Q_EMIT dataChanged(index(i), index(i), {RoleFocused});
277 }
278 }
279 }
280
281=== modified file 'plugins/Unity/Launcher/quicklistentry.cpp'
282--- plugins/Unity/Launcher/quicklistentry.cpp 2014-08-26 11:34:22 +0000
283+++ plugins/Unity/Launcher/quicklistentry.cpp 2015-06-18 11:46:46 +0000
284@@ -1,4 +1,4 @@
285-/* Copyright (C) 2013 Canonical, Ltd.
286+/* Copyright (C) 2013, 2015 Canonical, Ltd.
287 *
288 * Authors:
289 * Michael Zanetti <michael.zanetti@canonical.com>
290@@ -20,7 +20,6 @@
291
292 QuickListEntry::QuickListEntry()
293 {
294-
295 }
296
297 QString QuickListEntry::actionId() const
298@@ -57,3 +56,8 @@
299 {
300 return !m_actionId.isEmpty();
301 }
302+
303+bool QuickListEntry::operator==(const QuickListEntry &other)
304+{
305+ return !other.actionId().isEmpty() && other.actionId() == m_actionId;
306+}
307
308=== modified file 'plugins/Unity/Launcher/quicklistentry.h'
309--- plugins/Unity/Launcher/quicklistentry.h 2014-08-26 11:34:22 +0000
310+++ plugins/Unity/Launcher/quicklistentry.h 2015-06-18 11:46:46 +0000
311@@ -1,4 +1,4 @@
312-/* Copyright (C) 2013 Canonical, Ltd.
313+/* Copyright (C) 2013, 2015 Canonical, Ltd.
314 *
315 * Authors:
316 * Michael Zanetti <michael.zanetti@canonical.com>
317@@ -37,6 +37,8 @@
318
319 bool clickable() const;
320
321+ bool operator==(const QuickListEntry & other);
322+
323 private:
324 QString m_actionId;
325 QString m_text;
326
327=== modified file 'plugins/Unity/Launcher/quicklistmodel.cpp'
328--- plugins/Unity/Launcher/quicklistmodel.cpp 2013-10-02 11:00:53 +0000
329+++ plugins/Unity/Launcher/quicklistmodel.cpp 2015-06-18 11:46:46 +0000
330@@ -1,5 +1,5 @@
331 /*
332- * Copyright 2013 Canonical Ltd.
333+ * Copyright 2013, 2015 Canonical Ltd.
334 *
335 * This program is free software; you can redistribute it and/or modify
336 * it under the terms of the GNU Lesser General Public License as published by
337@@ -48,6 +48,17 @@
338 }
339 }
340
341+void QuickListModel::removeAction(const QuickListEntry &entry)
342+{
343+ const int start = m_list.indexOf(entry);
344+ if (start > -1) {
345+ beginRemoveRows(QModelIndex(), start, start);
346+ m_list.removeOne(entry);
347+ Q_EMIT dataChanged(index(start), index(start));
348+ endRemoveRows();
349+ }
350+}
351+
352 QuickListEntry QuickListModel::get(int index) const
353 {
354 return m_list.at(index);
355
356=== modified file 'plugins/Unity/Launcher/quicklistmodel.h'
357--- plugins/Unity/Launcher/quicklistmodel.h 2015-04-30 09:31:51 +0000
358+++ plugins/Unity/Launcher/quicklistmodel.h 2015-06-18 11:46:46 +0000
359@@ -1,5 +1,5 @@
360 /*
361- * Copyright 2013 Canonical Ltd.
362+ * Copyright 201, 2015 Canonical Ltd.
363 *
364 * This program is free software; you can redistribute it and/or modify
365 * it under the terms of the GNU Lesser General Public License as published by
366@@ -46,6 +46,8 @@
367 */
368 void updateAction(const QuickListEntry &entry);
369
370+ void removeAction(const QuickListEntry &entry);
371+
372 QuickListEntry get(int index) const;
373
374 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
375
376=== modified file 'qml/Launcher/LauncherPanel.qml'
377--- qml/Launcher/LauncherPanel.qml 2015-04-17 13:31:27 +0000
378+++ qml/Launcher/LauncherPanel.qml 2015-06-18 11:46:46 +0000
379@@ -15,7 +15,7 @@
380 */
381
382 import QtQuick 2.3
383-import Ubuntu.Components 1.1
384+import Ubuntu.Components 1.3
385 import Ubuntu.Components.ListItems 1.0 as ListItems
386 import Unity.Launcher 0.1
387 import Ubuntu.Components.Popups 0.1
388@@ -286,6 +286,7 @@
389 MouseArea {
390 id: dndArea
391 objectName: "dndArea"
392+ acceptedButtons: Qt.LeftButton | Qt.RightButton
393 anchors {
394 fill: parent
395 topMargin: launcherListView.topMargin
396@@ -297,7 +298,7 @@
397 property int draggedIndex: -1
398 property var selectedItem
399 property bool preDragging: false
400- property bool dragging: selectedItem !== undefined && selectedItem !== null && selectedItem.dragging
401+ property bool dragging: !!selectedItem && selectedItem.dragging
402 property bool postDragging: false
403 property int startX
404 property int startY
405@@ -315,6 +316,15 @@
406 return;
407 }
408
409+ if (mouse.button & Qt.RightButton) { // context menu
410+ // Opening QuickList
411+ quickList.item = clickedItem;
412+ quickList.model = launcherListView.model.get(index).quickList;
413+ quickList.appId = launcherListView.model.get(index).appId;
414+ quickList.state = "open";
415+ return
416+ }
417+
418 // First/last item do the scrolling at more than 12 degrees
419 if (index == 0 || index == launcherListView.count - 1) {
420 if (clickedItem.angle > 12) {
421@@ -508,7 +518,7 @@
422 id: quickListShape
423 objectName: "quickListShape"
424 anchors.fill: quickList
425- opacity: quickList.state === "open" ? 0.96 : 0
426+ opacity: quickList.state === "open" ? 0.8 : 0
427 visible: opacity > 0
428 rotation: root.rotation
429
430@@ -520,15 +530,15 @@
431
432 Image {
433 anchors {
434- left: parent.left
435- leftMargin: (quickList.item.width - units.gu(1)) / 2 - width / 2
436+ right: parent.left
437+ rightMargin: -units.dp(4)
438 verticalCenter: parent.verticalCenter
439- verticalCenterOffset: (parent.height / 2 + units.dp(3)) * (quickList.offset > 0 ? 1 : -1) * (root.inverted ? 1 : -1)
440+ verticalCenterOffset: -quickList.offset * (root.inverted ? 1 : -1)
441 }
442 height: units.gu(1)
443 width: units.gu(2)
444 source: "graphics/quicklist_tooltip.png"
445- rotation: (quickList.offset > 0 ? 0 : 180) + (root.inverted ? 0 : 180)
446+ rotation: root.inverted ? 90 : 270
447 }
448
449 InverseMouseArea {
450@@ -544,18 +554,18 @@
451 Rectangle {
452 id: quickList
453 objectName: "quickList"
454- color: "#f5f5f5"
455+ color: "#221e1c"
456 // Because we're setting left/right anchors depending on orientation, it will break the
457 // width setting after rotating twice. This makes sure we also re-apply width on rotation
458 width: root.inverted ? units.gu(30) : units.gu(30)
459 height: quickListColumn.height
460 visible: quickListShape.visible
461 anchors {
462- left: root.inverted ? undefined : parent.left
463- right: root.inverted ? parent.right : undefined
464+ left: root.inverted ? undefined : parent.right
465+ right: root.inverted ? parent.left : undefined
466 margins: units.gu(1)
467 }
468- y: itemCenter + offset
469+ y: itemCenter - (height / 2) + offset
470 rotation: root.rotation
471
472 property var model
473@@ -564,9 +574,8 @@
474
475 // internal
476 property int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) : units.gu(1)
477- property int offset: itemCenter + (item.height/2) + height + units.gu(1) > parent.height ?
478- -(item.height/2) - height - units.gu(.5) :
479- (item.height/2) + units.gu(.5)
480+ property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
481+ itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
482
483 Column {
484 id: quickListColumn
485@@ -585,7 +594,7 @@
486 // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
487 // ListItems don't know that they are sitting in a themed Popover where the color
488 // needs to be inverted.
489- __foregroundColor: "black"
490+ __foregroundColor: theme.palette.selected.backgroundText
491
492 onClicked: {
493 if (!model.clickable) {
494
495=== modified file 'src/MouseTouchAdaptor.cpp'
496--- src/MouseTouchAdaptor.cpp 2015-03-02 12:41:17 +0000
497+++ src/MouseTouchAdaptor.cpp 2015-06-18 11:46:46 +0000
498@@ -104,10 +104,10 @@
499 if (button != Qt::LeftButton)
500 return true;
501
502- QPoint windowPos(pressEvent->event_x, pressEvent->event_y);
503-
504 QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(pressEvent->event));
505
506+ QPoint windowPos(pressEvent->event_x / targetWindow->devicePixelRatio(), pressEvent->event_y / targetWindow->devicePixelRatio());
507+
508 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
509 false /* autoCommit */);
510 touchEvent.press(0 /* touchId */, windowPos);
511@@ -125,10 +125,10 @@
512 if (button != Qt::LeftButton)
513 return true;
514
515- QPoint windowPos(releaseEvent->event_x, releaseEvent->event_y);
516-
517 QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(releaseEvent->event));
518
519+ QPoint windowPos(releaseEvent->event_x / targetWindow->devicePixelRatio(), releaseEvent->event_y / targetWindow->devicePixelRatio());
520+
521 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
522 false /* autoCommit */);
523 touchEvent.release(0 /* touchId */, windowPos);
524@@ -144,10 +144,10 @@
525 return true;
526 }
527
528- QPoint windowPos(event->event_x, event->event_y);
529-
530 QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(event->event));
531
532+ QPoint windowPos(event->event_x / targetWindow->devicePixelRatio(), event->event_y / targetWindow->devicePixelRatio());
533+
534 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
535 false /* autoCommit */);
536 touchEvent.move(0 /* touchId */, windowPos);
537
538=== modified file 'tests/mocks/Unity/Launcher/MockLauncherItem.cpp'
539--- tests/mocks/Unity/Launcher/MockLauncherItem.cpp 2014-09-03 13:30:52 +0000
540+++ tests/mocks/Unity/Launcher/MockLauncherItem.cpp 2015-06-18 11:46:46 +0000
541@@ -39,7 +39,10 @@
542 m_focused(false),
543 m_quickList(new MockQuickListModel(this))
544 {
545+}
546
547+MockLauncherItem::~MockLauncherItem()
548+{
549 }
550
551 QString MockLauncherItem::appId() const
552
553=== modified file 'tests/mocks/Unity/Launcher/MockLauncherItem.h'
554--- tests/mocks/Unity/Launcher/MockLauncherItem.h 2015-04-30 09:31:51 +0000
555+++ tests/mocks/Unity/Launcher/MockLauncherItem.h 2015-06-18 11:46:46 +0000
556@@ -31,6 +31,7 @@
557 Q_OBJECT
558 public:
559 MockLauncherItem(const QString &appId, const QString& desktopFile, const QString& name, const QString& icon, QObject* parent = 0);
560+ ~MockLauncherItem();
561
562 QString appId() const override;
563 QString desktopFile() const;
564
565=== modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp'
566--- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-03-06 04:44:11 +0000
567+++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-06-18 11:46:46 +0000
568@@ -43,6 +43,7 @@
569 item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
570 item->setCount(1);
571 item->setCountVisible(true);
572+ item->setRunning(true);
573 m_list.append(item);
574 item = new MockLauncherItem("twitter-webapp", "/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter", this);
575 item->setCount(12);
576@@ -174,7 +175,9 @@
577 int index = findApp(appId);
578 if (index >= 0) {
579 beginRemoveRows(QModelIndex(), index, 0);
580- m_list.takeAt(index)->deleteLater();
581+ MockLauncherItem * item = m_list.takeAt(index);
582+ item->setRunning(false);
583+ item->deleteLater();
584 endRemoveRows();
585 }
586 }
587
588=== modified file 'tests/plugins/Unity/Launcher/launchermodeltest.cpp'
589--- tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-06-12 16:07:43 +0000
590+++ tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-06-18 11:46:46 +0000
591@@ -68,6 +68,7 @@
592 Q_OBJECT
593 public:
594 MockAppManager(QObject *parent = 0): ApplicationManagerInterface(parent) {}
595+ ~MockAppManager() {}
596 int rowCount(const QModelIndex &) const override { return m_list.count(); }
597 QVariant data(const QModelIndex &, int ) const override { return QVariant(); }
598 QString focusedApplicationId() const override {
599@@ -325,6 +326,46 @@
600 QCOMPARE(launcherModel->get(0)->appId(), QLatin1String("abs-icon"));
601 }
602
603+ void testQuitMenuItem() {
604+ // we have 2 apps running, both should have the Quit action in its quick list
605+ QCOMPARE(launcherModel->rowCount(), 2);
606+
607+ // stop the second one keeping it pinned so that it doesn't go away
608+ launcherModel->pin("no-icon");
609+ appManager->stopApplication("no-icon");
610+
611+ // find the first Quit item, should be there
612+ QuickListModel *model = qobject_cast<QuickListModel*>(launcherModel->get(0)->quickList());
613+ int quitActionIndex = -1;
614+ for (int i = 0; i < model->rowCount(); ++i) {
615+ if (model->get(i).actionId() == "stop_item") {
616+ quitActionIndex = i;
617+ break;
618+ }
619+ }
620+ QVERIFY(quitActionIndex >= 0);
621+
622+ // find the second Quit item, should NOT be there, the app is stopped
623+ QuickListModel *model2 = qobject_cast<QuickListModel*>(launcherModel->get(1)->quickList());
624+ int quitActionIndex2 = -1;
625+ for (int i = 0; i < model2->rowCount(); ++i) {
626+ if (model2->get(i).actionId() == "stop_item") {
627+ quitActionIndex2 = i;
628+ break;
629+ }
630+ }
631+ QVERIFY(quitActionIndex2 == -1);
632+
633+ // trigger the first quit item quicklist action
634+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), quitActionIndex);
635+ // first app should be gone...
636+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
637+ // ... the second app (now at index 0) should still be there, pinned and stopped
638+ QCOMPARE(launcherModel->get(0)->appId(), QStringLiteral("no-icon"));
639+ QCOMPARE(launcherModel->get(0)->pinned(), true);
640+ QCOMPARE(launcherModel->get(0)->running(), false);
641+ }
642+
643 void testGetUrlForAppId() {
644 QCOMPARE(launcherModel->getUrlForAppId(QString()), QString());
645 QCOMPARE(launcherModel->getUrlForAppId(""), QString());
646
647=== modified file 'tests/qmltests/Launcher/tst_Launcher.qml'
648--- tests/qmltests/Launcher/tst_Launcher.qml 2015-04-24 09:53:37 +0000
649+++ tests/qmltests/Launcher/tst_Launcher.qml 2015-06-18 11:46:46 +0000
650@@ -146,7 +146,7 @@
651 startX+units.gu(8), startY);
652
653 var panel = findChild(launcher, "launcherPanel");
654- verify(panel != undefined);
655+ verify(!!panel);
656
657 // wait until it gets fully extended
658 tryCompare(panel, "x", 0);
659@@ -157,7 +157,7 @@
660 mouseMove(root, 1, root.height / 2);
661
662 var panel = findChild(launcher, "launcherPanel");
663- verify(panel != undefined);
664+ verify(!!panel);
665
666 // wait until it gets fully extended
667 tryCompare(panel, "x", 0);
668@@ -187,7 +187,7 @@
669 waitUntilLauncherDisappears();
670
671 var panel = findChild(launcher, "launcherPanel")
672- verify(panel != undefined)
673+ verify(!!panel)
674
675 // it starts out hidden just left of the left launcher edge
676 compare(panel.x, -panel.width)
677@@ -225,7 +225,7 @@
678
679 var appIcon = findChild(launcher, "launcherDelegate0");
680
681- verify(appIcon != undefined);
682+ verify(!!appIcon);
683
684 if (data.mouse) {
685 mouseClick(appIcon);
686@@ -248,7 +248,7 @@
687 dragLauncherIntoView()
688
689 var dashIcon = findChild(launcher, "dashItem")
690- verify(dashIcon != undefined)
691+ verify(!!dashIcon)
692
693 mouseClick(dashIcon)
694
695@@ -538,7 +538,7 @@
696
697 // Doing longpress
698 mousePress(draggedItem);
699- tryCompare(quickListShape, "opacity", 0.96);
700+ tryCompare(quickListShape, "opacity", 0.8);
701 mouseRelease(draggedItem);
702
703 verify(quickList.y >= units.gu(1));
704@@ -623,9 +623,31 @@
705 tryCompare(quickList, "state", "");
706 }
707
708+ function test_quickListMenuOnRMB() {
709+ dragLauncherIntoView();
710+ var clickedItem = findChild(launcher, "launcherDelegate5")
711+ var quickList = findChild(launcher, "quickList")
712+ var quickListShape = findChild(launcher, "quickListShape")
713+ var dndArea = findChild(launcher, "dndArea");
714+
715+ // Initial state
716+ tryCompare(quickListShape, "visible", false)
717+
718+ // Doing RMB click
719+ mouseClick(clickedItem, clickedItem.width / 2, clickedItem.height / 2, Qt.RightButton)
720+ tryCompare(quickListShape, "visible", true)
721+ verify(quickList, "state", "open")
722+ verify(dndArea, "dragging", false)
723+
724+ // Click somewhere in the empty space to dismiss the quicklist
725+ mouseClick(launcher, launcher.width - units.gu(1), units.gu(1));
726+ tryCompare(quickListShape, "visible", false);
727+ verify(quickList, "state", "")
728+ }
729+
730 function test_revealByHover() {
731 var panel = findChild(launcher, "launcherPanel");
732- verify(panel != undefined);
733+ verify(!!panel);
734
735 revealByHover();
736 tryCompare(launcher, "state", "visibleTemporary");

Subscribers

People subscribed via source and target branches