on xenial help sign in
add support for highlighting the currently focused app
4a9640bMichael Zanetti
Launcher/LauncherDelegate.qml+19−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,22 @@ Item {
136 }
138 }
137 }
139 }
138 }
140 }
141+ Image {
142+ anchors {
143+ right: parent.right
144+ verticalCenter: parent.verticalCenter
145+ }
146+ visible: root.itemFocused
147+ source: "graphics/focused_app_arrow.png"
148+ }
139 }
149 }
140
150
141 ShaderEffect {
151 ShaderEffect {
142 id: transformEffect
152 id: transformEffect
143 anchors.centerIn: parent
153 anchors.centerIn: parent
144 anchors.verticalCenterOffset: root.offset
154 anchors.verticalCenterOffset: root.offset
145− width: parent.itemWidth
155+ width: iconItem.width
146− height: parent.itemHeight
156+ height: iconItem.height
147 property real itemOpacity: root.itemOpacity
157 property real itemOpacity: root.itemOpacity
148 property real brightness: Math.max(-1, root.brightness)
158 property real brightness: Math.max(-1, root.brightness)
149 property real angle: root.angle
159 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
@@ -225,6 +225,9 @@ void LauncherBackend::syncFromAccounts()
225 if (entry.startsWith("application://")) {
225 if (entry.startsWith("application://")) {
226 QString appId = entry;
226 QString appId = entry;
227 appId.remove("application://");
227 appId.remove("application://");
228+ if (appId.endsWith(".desktop")) {
229+ appId.chop(8);
230+ }
228 QString df = findDesktopFile(appId);
231 QString df = findDesktopFile(appId);
229
232
230 if (!df.isEmpty()) {
233 if (!df.isEmpty()) {
@@ -265,18 +268,9 @@ QString LauncherBackend::findDesktopFile(const QString &appId) const
265 QStringList searchDirs;
268 QStringList searchDirs;
266 searchDirs << "/usr/share/applications";
269 searchDirs << "/usr/share/applications";
267
270
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
271+#ifdef LAUNCHER_TESTING
278 searchDirs << "";
272 searchDirs << "";
279−//#endif
273+#endif
280
274
281 do {
275 do {
282 if (dashPos != -1) {
276 if (dashPos != -1) {
@@ -284,6 +278,7 @@ QString LauncherBackend::findDesktopFile(const QString &appId) const
284 }
278 }
285
279
286 Q_FOREACH(const QString &searchDir, searchDirs) {
280 Q_FOREACH(const QString &searchDir, searchDirs) {
281+ qDebug() << "searching for desktop file:" << searchDir << helper + ".desktop";
287 QFileInfo fileInfo(QDir(searchDir), helper + ".desktop");
282 QFileInfo fileInfo(QDir(searchDir), helper + ".desktop");
288 if (fileInfo.exists()) {
283 if (fileInfo.exists()) {
289 return fileInfo.absoluteFilePath();
284 return fileInfo.absoluteFilePath();
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+34−6
@@ -21,6 +21,8 @@
21#include "launcheritem.h"
21#include "launcheritem.h"
22#include "backend/launcherbackend.h"
22#include "backend/launcherbackend.h"
23
23
24+#include <QDebug>
25+
24LauncherModel::LauncherModel(QObject *parent):
26LauncherModel::LauncherModel(QObject *parent):
25 LauncherModelInterface(parent),
27 LauncherModelInterface(parent),
26 m_backend(new LauncherBackend(true, this))
28 m_backend(new LauncherBackend(true, this))
@@ -74,6 +76,8 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
74 return item->count();
76 return item->count();
75 case RoleProgress:
77 case RoleProgress:
76 return item->progress();
78 return item->progress();
79+ case RoleFocused:
80+ return item->focused();
77 }
81 }
78
82
79 return QVariant();
83 return QVariant();
@@ -193,18 +197,41 @@ void LauncherModel::setUser(const QString &username)
193
197
194void LauncherModel::applicationFocused(const QString &appId)
198void LauncherModel::applicationFocused(const QString &appId)
195{
199{
200+ // Unfocus all apps
201+ for(int i = 0; i < m_list.count(); ++i) {
202+ LauncherItem *item = m_list.at(i);
203+ if (item->focused()) {
204+ item->setFocused(false);
205+ Q_EMIT dataChanged(this->index(i), this->index(i), QVector<int>() << RoleFocused);
206+ }
207+ }
208+
209+ if (appId.isEmpty()) {
210+ return;
211+ }
212+
213+ // FIXME: drop this once we get real appIds from the AppManager
214+ QString helper = appId.split('/').last();
215+ if (helper.endsWith(".desktop")) {
216+ helper.chop(8);
217+ }
218+
196− int index = findApplication(appId);
219+ int index = findApplication(helper);
220+ qDebug() << "################## found focused app index" << index << helper;
197
221
198 if (index >= 0) {
222 if (index >= 0) {
199− // TODO: Mark application as focued
223+ m_list.at(index)->setFocused(true);
224+ qDebug() << "set focused to true on" << m_list.at(index)->name();
225+ Q_EMIT dataChanged(this->index(index), this->index(index), QVector<int>() << RoleFocused);
200 } else {
226 } else {
201 // Add app to recent apps
227 // Add app to recent apps
202− QString desktopFile = m_backend->desktopFile(appId);
228+ QString desktopFile = m_backend->desktopFile(helper);
203− QString appName = m_backend->displayName(appId);
229+ QString appName = m_backend->displayName(helper);
204− QString icon = m_backend->icon(appId);
230+ QString icon = m_backend->icon(helper);
205
231
206− LauncherItem *item = new LauncherItem(appId, desktopFile, appName, icon);
232+ LauncherItem *item = new LauncherItem(helper, desktopFile, appName, icon);
207 item->setRecent(true);
233 item->setRecent(true);
234+ item->setFocused(true);
208 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
235 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
209 m_list.append(item);
236 m_list.append(item);
210 endInsertRows();
237 endInsertRows();
@@ -243,6 +270,7 @@ int LauncherModel::findApplication(const QString &appId)
243{
270{
244 for (int i = 0; i < m_list.count(); ++i) {
271 for (int i = 0; i < m_list.count(); ++i) {
245 LauncherItem *item = m_list.at(i);
272 LauncherItem *item = m_list.at(i);
273+ qDebug() << "checking app" << item->appId();
246 if (item->appId() == appId) {
274 if (item->appId() == appId) {
247 return i;
275 return i;
248 }
276 }