on xenial help sign in
Added corresponding tests and visual tweaks to a launcher-item's progress-overlay.
9f578c0Mirco Müller
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+22−12
@@ -207,16 +207,24 @@ void LauncherModel::refresh()
207 Q_FOREACH (LauncherItem* item, m_list) {
207 Q_FOREACH (LauncherItem* item, m_list) {
208 bool found = false;
208 bool found = false;
209 Q_FOREACH(const QVariant &asItem, items) {
209 Q_FOREACH(const QVariant &asItem, items) {
210+ QVariantMap cachedMap = asItem.toMap();
210− if (asItem.toMap().value("id").toString() == item->appId()) {
211+ if (cachedMap.value("id").toString() == item->appId()) {
211 // Only keep and update it if we either show unpinned or it is pinned
212 // Only keep and update it if we either show unpinned or it is pinned
212− if (!m_onlyPinned || asItem.toMap().value("pinned").toBool()) {
213+ if (!m_onlyPinned || cachedMap.value("pinned").toBool()) {
213 found = true;
214 found = true;
214− item->setName(asItem.toMap().value("name").toString());
215+ item->setName(cachedMap.value("name").toString());
215− item->setIcon(asItem.toMap().value("icon").toString());
216+ item->setIcon(cachedMap.value("icon").toString());
216− item->setCount(asItem.toMap().value("count").toInt());
217+ item->setCount(cachedMap.value("count").toInt());
217− item->setCountVisible(asItem.toMap().value("countVisible").toBool());
218+ item->setCountVisible(cachedMap.value("countVisible").toBool());
219+ item->setProgress(cachedMap.value("progress").toInt());
218 int idx = m_list.indexOf(item);
220 int idx = m_list.indexOf(item);
219− Q_EMIT dataChanged(index(idx), index(idx), QVector<int>() << RoleName << RoleIcon);
221+ Q_EMIT dataChanged(index(idx),
222+ index(idx),
223+ {RoleName,
224+ RoleIcon,
225+ RoleCount,
226+ RoleCountVisible,
227+ RoleProgress});
220 }
228 }
221 break;
229 break;
222 }
230 }
@@ -254,14 +262,16 @@ void LauncherModel::refresh()
254 }
262 }
255
263
256 if (itemIndex == -1) {
264 if (itemIndex == -1) {
265+ QVariantMap chachedMap = entry.toMap();
257 // Need to add it. Just add it into the addedIndex to keep same ordering as the list in AS.
266 // Need to add it. Just add it into the addedIndex to keep same ordering as the list in AS.
258− LauncherItem *item = new LauncherItem(entry.toMap().value("id").toString(),
267+ LauncherItem *item = new LauncherItem(chachedMap.value("id").toString(),
259− entry.toMap().value("name").toString(),
268+ chachedMap.value("name").toString(),
260− entry.toMap().value("icon").toString(),
269+ chachedMap.value("icon").toString(),
261 this);
270 this);
262 item->setPinned(true);
271 item->setPinned(true);
263− item->setCount(entry.toMap().value("count").toInt());
272+ item->setCount(chachedMap.value("count").toInt());
264− item->setCountVisible(entry.toMap().value("countVisible").toBool());
273+ item->setCountVisible(chachedMap.value("countVisible").toBool());
274+ item->setProgress(chachedMap.value("progress").toInt());
265 beginInsertRows(QModelIndex(), newPosition, newPosition);
275 beginInsertRows(QModelIndex(), newPosition, newPosition);
266 m_list.insert(newPosition, item);
276 m_list.insert(newPosition, item);
267 endInsertRows();
277 endInsertRows();
plugins/Unity/Launcher/asadapter.cpp+1
@@ -56,5 +56,6 @@ QVariantMap ASAdapter::itemToVariant(LauncherItem *item) const
56 details.insert("count", item->count());
56 details.insert("count", item->count());
57 details.insert("countVisible", item->countVisible());
57 details.insert("countVisible", item->countVisible());
58 details.insert("pinned", item->pinned());
58 details.insert("pinned", item->pinned());
59+ details.insert("progress", item->progress());
59 return details;
60 return details;
60}
61}
plugins/Unity/Launcher/dbusinterface.cpp+16−4
@@ -62,6 +62,7 @@ QString DBusInterface::introspect(const QString &path) const
62 "<interface name=\"com.canonical.Unity.Launcher.Item\">"
62 "<interface name=\"com.canonical.Unity.Launcher.Item\">"
63 "<property name=\"count\" type=\"i\" access=\"readwrite\" />"
63 "<property name=\"count\" type=\"i\" access=\"readwrite\" />"
64 "<property name=\"countVisible\" type=\"b\" access=\"readwrite\" />"
64 "<property name=\"countVisible\" type=\"b\" access=\"readwrite\" />"
65+ "<property name=\"progress\" type=\"i\" access=\"readwrite\" />"
65 "<method name=\"Alert\" />"
66 "<method name=\"Alert\" />"
66 "</interface>";
67 "</interface>";
67 return nodeiface;
68 return nodeiface;
@@ -175,33 +176,44 @@ bool DBusInterface::handleMessage(const QDBusMessage& message, const QDBusConnec
175
176
176 QVariantList retval;
177 QVariantList retval;
177 if (message.member() == "Get") {
178 if (message.member() == "Get") {
179+ QString cachedString = message.arguments()[1].toString();
178 if (!item) {
180 if (!item) {
179 return false;
181 return false;
180 }
182 }
181− if (message.arguments()[1].toString() == "count") {
183+ if (cachedString == "count") {
182 retval.append(QVariant::fromValue(QDBusVariant(item->count())));
184 retval.append(QVariant::fromValue(QDBusVariant(item->count())));
183− } else if (message.arguments()[1].toString() == "countVisible") {
185+ } else if (cachedString == "countVisible") {
184 retval.append(QVariant::fromValue(QDBusVariant(item->countVisible())));
186 retval.append(QVariant::fromValue(QDBusVariant(item->countVisible())));
187+ } else if (cachedString == "progress") {
188+ retval.append(QVariant::fromValue(QDBusVariant(item->progress())));
185 }
189 }
186 } else if (message.member() == "Set") {
190 } else if (message.member() == "Set") {
187− if (message.arguments()[1].toString() == "count") {
191+ QString cachedString = message.arguments()[1].toString();
192+ if (cachedString == "count") {
188 int newCount = message.arguments()[2].value<QDBusVariant>().variant().toInt();
193 int newCount = message.arguments()[2].value<QDBusVariant>().variant().toInt();
189 if (!item || newCount != item->count()) {
194 if (!item || newCount != item->count()) {
190 Q_EMIT countChanged(appid, newCount);
195 Q_EMIT countChanged(appid, newCount);
191 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "count", QVariant(newCount));
196 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "count", QVariant(newCount));
192 }
197 }
193− } else if (message.arguments()[1].toString() == "countVisible") {
198+ } else if (cachedString == "countVisible") {
194 bool newVisible = message.arguments()[2].value<QDBusVariant>().variant().toBool();
199 bool newVisible = message.arguments()[2].value<QDBusVariant>().variant().toBool();
195 if (!item || newVisible != item->countVisible()) {
200 if (!item || newVisible != item->countVisible()) {
196 Q_EMIT countVisibleChanged(appid, newVisible);
201 Q_EMIT countVisibleChanged(appid, newVisible);
197 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "countVisible", newVisible);
202 notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "countVisible", newVisible);
198 }
203 }
204+ } else if (cachedString == "progress") {
205+ int newProgress = message.arguments()[2].value<QDBusVariant>().variant().toInt();
206+ if (!item || newProgress != item->progress()) {
207+ Q_EMIT progressChanged(appid, newProgress);
208+ notifyPropertyChanged("com.canonical.Unity.Launcher.Item", encodeAppId(appid), "progress", QVariant(newProgress));
209+ }
199 }
210 }
200 } else if (message.member() == "GetAll") {
211 } else if (message.member() == "GetAll") {
201 if (item) {
212 if (item) {
202 QVariantMap all;
213 QVariantMap all;
203 all.insert("count", item->count());
214 all.insert("count", item->count());
204 all.insert("countVisible", item->countVisible());
215 all.insert("countVisible", item->countVisible());
216+ all.insert("progress", item->progress());
205 retval.append(all);
217 retval.append(all);
206 }
218 }
207 } else {
219 } else {
plugins/Unity/Launcher/dbusinterface.h+1
@@ -36,6 +36,7 @@ public:
36Q_SIGNALS:
36Q_SIGNALS:
37 void countChanged(const QString &appId, int count);
37 void countChanged(const QString &appId, int count);
38 void countVisibleChanged(const QString &appId, bool countVisible);
38 void countVisibleChanged(const QString &appId, bool countVisible);
39+ void progressChanged(const QString &appId, int progress);
39 void refreshCalled();
40 void refreshCalled();
40 void alertCalled(const QString &appId);
41 void alertCalled(const QString &appId);
41
42
plugins/Unity/Launcher/launchermodel.cpp+1
@@ -40,6 +40,7 @@ LauncherModel::LauncherModel(QObject *parent):
40{
40{
41 connect(m_dbusIface, &DBusInterface::countChanged, this, &LauncherModel::countChanged);
41 connect(m_dbusIface, &DBusInterface::countChanged, this, &LauncherModel::countChanged);
42 connect(m_dbusIface, &DBusInterface::countVisibleChanged, this, &LauncherModel::countVisibleChanged);
42 connect(m_dbusIface, &DBusInterface::countVisibleChanged, this, &LauncherModel::countVisibleChanged);
43+ connect(m_dbusIface, &DBusInterface::progressChanged, this, &LauncherModel::progressChanged);
43 connect(m_dbusIface, &DBusInterface::refreshCalled, this, &LauncherModel::refresh);
44 connect(m_dbusIface, &DBusInterface::refreshCalled, this, &LauncherModel::refresh);
44 connect(m_dbusIface, &DBusInterface::alertCalled, this, &LauncherModel::alert);
45 connect(m_dbusIface, &DBusInterface::alertCalled, this, &LauncherModel::alert);
45
46
qml/Launcher/LauncherDelegate.qml+14−14
@@ -153,7 +153,7 @@ Item {
153 objectName: "countEmblem"
153 objectName: "countEmblem"
154 anchors {
154 anchors {
155 right: parent.right
155 right: parent.right
156− top: parent.top
156+ bottom: parent.bottom
157 margins: units.dp(3)
157 margins: units.dp(3)
158 }
158 }
159 width: Math.min(root.itemWidth, Math.max(units.gu(2), countLabel.implicitWidth + units.gu(1)))
159 width: Math.min(root.itemWidth, Math.max(units.gu(2), countLabel.implicitWidth + units.gu(1)))
@@ -178,23 +178,21 @@ Item {
178 }
178 }
179 }
179 }
180
180
181− BorderImage {
181+ UbuntuShape {
182 id: progressOverlay
182 id: progressOverlay
183 objectName: "progressOverlay"
183 objectName: "progressOverlay"
184+
184 anchors {
185 anchors {
185 left: iconItem.left
186 left: iconItem.left
186 right: iconItem.right
187 right: iconItem.right
187− bottom: iconItem.bottom
188+ verticalCenter: parent.verticalCenter
188− leftMargin: units.gu(1)
189+ leftMargin: units.gu(1.5)
189− rightMargin: units.gu(1)
190+ rightMargin: units.gu(1.5)
190− bottomMargin: units.gu(1)
191 }
191 }
192− height: units.gu(1.5)
192+ height: units.gu(1)
193 visible: root.progress > -1
193 visible: root.progress > -1
194− source: "graphics/progressbar-trough.sci"
194+ color: UbuntuColors.darkGrey
195−
195+ borderSource: "none"
196− // For fill calculation we need to remove the 2 units of border defined in .sci file
197− property int adjustedWidth: width - units.gu(2)
198
196
199 Item {
197 Item {
200 anchors {
198 anchors {
@@ -202,20 +200,22 @@ Item {
202 top: parent.top
200 top: parent.top
203 bottom: parent.bottom
201 bottom: parent.bottom
204 }
202 }
205− width: Math.min(100, root.progress) / 100 * parent.adjustedWidth + units.gu(1)
203+ width: Math.min(100, root.progress) / 100 * parent.width
206 clip: true
204 clip: true
207
205
208− BorderImage {
206+ UbuntuShape {
209 anchors {
207 anchors {
210 left: parent.left
208 left: parent.left
211 top: parent.top
209 top: parent.top
212 bottom: parent.bottom
210 bottom: parent.bottom
213 }
211 }
212+ color: "white"
213+ borderSource: "none"
214 width: progressOverlay.width
214 width: progressOverlay.width
215− source: "graphics/progressbar-fill.sci"
216 }
215 }
217 }
216 }
218 }
217 }
218+
219 Image {
219 Image {
220 objectName: "focusedHighlight"
220 objectName: "focusedHighlight"
221 anchors {
221 anchors {
qml/Launcher/graphics/progressbar-fill@30.pngdeleted

Binary file not shown.

qml/Launcher/graphics/progressbar-fill@30.scideleted−5
@@ -1,5 +0,0 @@
1−border.left: 36
2−border.top: 16
3−border.bottom: 28
4−border.right: 36
5−source: progressbar-fill@30.png
qml/Launcher/graphics/progressbar-trough@30.pngdeleted

Binary file not shown.

qml/Launcher/graphics/progressbar-trough@30.scideleted−5
@@ -1,5 +0,0 @@
1−border.left: 36
2−border.top: 16
3−border.bottom: 26
4−border.right: 36
5−source: progressbar-trough@30.png
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+10
@@ -215,6 +215,16 @@ int MockLauncherModel::findApp(const QString &appId)
215 return -1;
215 return -1;
216}
216}
217
217
218+void MockLauncherModel::setProgress(const QString &appId, int progress)
219+{
220+ int index = findApp(appId);
221+ if (index >= 0) {
222+ m_list.at(index)->setProgress(progress);
223+ QModelIndex modelIndex = this->index(index);
224+ Q_EMIT dataChanged(modelIndex, modelIndex, QVector<int>() << RoleProgress);
225+ }
226+}
227+
218void MockLauncherModel::setUser(const QString &username)
228void MockLauncherModel::setUser(const QString &username)
219{
229{
220 Q_UNUSED(username)
230 Q_UNUSED(username)
tests/mocks/Unity/Launcher/MockLauncherModel.h+1
@@ -55,6 +55,7 @@ public:
55
55
56 // For testing
56 // For testing
57 Q_INVOKABLE void emitHint();
57 Q_INVOKABLE void emitHint();
58+ Q_INVOKABLE void setProgress(const QString &appId, int progress);
58 Q_INVOKABLE void setCount(const QString &appId, int count);
59 Q_INVOKABLE void setCount(const QString &appId, int count);
59 Q_INVOKABLE void setCountVisible(const QString &appId, bool countVisible);
60 Q_INVOKABLE void setCountVisible(const QString &appId, bool countVisible);
60
61
tests/plugins/Greeter/Unity/Launcher/launchermodelastest.cpp+3
@@ -43,6 +43,7 @@ private Q_SLOTS:
43 item.insert("name", "Item 1");
43 item.insert("name", "Item 1");
44 item.insert("icon", "fake.svg");
44 item.insert("icon", "fake.svg");
45 item.insert("count", 0);
45 item.insert("count", 0);
46+ item.insert("progress", 0);
46 item.insert("countVisible", false);
47 item.insert("countVisible", false);
47 item.insert("pinned", true);
48 item.insert("pinned", true);
48 list.append(item);
49 list.append(item);
@@ -67,6 +68,7 @@ private Q_SLOTS:
67 inSync &= model->get(i)->name() == list.at(i).value("name").toString();
68 inSync &= model->get(i)->name() == list.at(i).value("name").toString();
68 inSync &= model->get(i)->icon() == list.at(i).value("icon").toString();
69 inSync &= model->get(i)->icon() == list.at(i).value("icon").toString();
69 inSync &= model->get(i)->count() == list.at(i).value("count").toInt();
70 inSync &= model->get(i)->count() == list.at(i).value("count").toInt();
71+ inSync &= model->get(i)->progress() == list.at(i).value("progress").toInt();
70 inSync &= model->get(i)->countVisible() == list.at(i).value("countVisible").toBool();
72 inSync &= model->get(i)->countVisible() == list.at(i).value("countVisible").toBool();
71 }
73 }
72 return inSync;
74 return inSync;
@@ -111,6 +113,7 @@ private Q_SLOTS:
111 newEntry.insert("name", "New app");
113 newEntry.insert("name", "New app");
112 newEntry.insert("icon", "some-icon.svg");
114 newEntry.insert("icon", "some-icon.svg");
113 newEntry.insert("count", 0);
115 newEntry.insert("count", 0);
116+ newEntry.insert("progress", 42);
114 newEntry.insert("countVisible", false);
117 newEntry.insert("countVisible", false);
115 newEntry.insert("pinned", true);
118 newEntry.insert("pinned", true);
116 newList.append(newEntry);
119 newList.append(newEntry);
tests/qmltests/Launcher/tst_Launcher.qml+40−3
@@ -94,16 +94,42 @@ Item {
94 Layout.fillWidth: true
94 Layout.fillWidth: true
95 }
95 }
96
96
97+ Row {
98+ spacing: units.gu(1)
99+
100+ Button {
101+ text: "35% bar"
102+ onClicked: LauncherModel.setProgress(LauncherModel.get(parseInt(appIdEntryBar.displayText)).appId, 35)
103+ Layout.fillWidth: true
104+ }
105+
106+ TextArea {
107+ id: appIdEntryBar
108+ anchors.verticalCenter: parent.verticalCenter
109+ width: units.gu(4)
110+ height: units.gu(4)
111+ autoSize: true
112+ text: "2"
113+ maximumLineCount: 1
114+ }
115+
116+ Button {
117+ text: "no bar"
118+ onClicked: LauncherModel.setProgress(LauncherModel.get(parseInt(appIdEntryBar.displayText)).appId, -1)
119+ Layout.fillWidth: true
120+ }
121+ }
122+
97 Row {
123 Row {
98 spacing: units.gu(1)
124 spacing: units.gu(1)
99
125
100 Button {
126 Button {
101 text: "set alert"
127 text: "set alert"
102− onClicked: LauncherModel.setAlerting(LauncherModel.get(parseInt(appIdEntry.displayText)).appId, true)
128+ onClicked: LauncherModel.setAlerting(LauncherModel.get(parseInt(appIdEntryAlert.displayText)).appId, true)
103 }
129 }
104
130
105 TextArea {
131 TextArea {
106− id: appIdEntry
132+ id: appIdEntryAlert
107 anchors.verticalCenter: parent.verticalCenter
133 anchors.verticalCenter: parent.verticalCenter
108 width: units.gu(5)
134 width: units.gu(5)
109 height: units.gu(4)
135 height: units.gu(4)
@@ -115,7 +141,7 @@ Item {
115
141
116 Button {
142 Button {
117 text: "unset alert"
143 text: "unset alert"
118− onClicked: LauncherModel.setAlerting(LauncherModel.get(parseInt(appIdEntry.displayText)).appId, false)
144+ onClicked: LauncherModel.setAlerting(LauncherModel.get(parseInt(appIdEntryAlert.displayText)).appId, false)
119 }
145 }
120 }
146 }
121 }
147 }
@@ -672,6 +698,17 @@ Item {
672 waitUntilLauncherDisappears();
698 waitUntilLauncherDisappears();
673 }
699 }
674
700
701+ function test_progressChangeViaModel() {
702+ dragLauncherIntoView();
703+ var item = findChild(launcher, "launcherDelegate0")
704+ verify(item != undefined)
705+ LauncherModel.setProgress(LauncherModel.get(0).appId, -1)
706+ compare(findChild(item, "progressOverlay").visible, false)
707+ LauncherModel.setProgress(LauncherModel.get(0).appId, 20)
708+ compare(findChild(item, "progressOverlay").visible, true)
709+ LauncherModel.setProgress(LauncherModel.get(0).appId, 0)
710+ }
711+
675 function test_alertPeekingIcon() {
712 function test_alertPeekingIcon() {
676 var listView = findChild(launcher, "launcherListView")
713 var listView = findChild(launcher, "launcherListView")
677 verify(listView != undefined)
714 verify(listView != undefined)
tests/scripts/README+4
@@ -3,3 +3,7 @@ This directory holds a few handy shell-scripts to simplify runtime-testing of DB
3launcher-icon related:
3launcher-icon related:
4 * list-launcher-icons.sh - get all icons of unity8-launcher
4 * list-launcher-icons.sh - get all icons of unity8-launcher
5 * alert-launcher-icon.sh - trigger alert/wiggle of unfocused launcher-icon
5 * alert-launcher-icon.sh - trigger alert/wiggle of unfocused launcher-icon
6+ * get-progress.sh - get progress-value of a launcher-icon
7+ * set-progress.sh - set progress-value of a launcher-icon
8+ * set-count.sh - set the count of a launcher-icon
9+ * set-count-visible.sh - set the count-visible flag of a launcher-icon
tests/scripts/get-progress.shnew file+3
@@ -0,0 +1,3 @@
1+#!/bin/sh
2+
3+qdbus com.canonical.Unity.Launcher /com/canonical/Unity/Launcher/$1 org.freedesktop.DBus.Properties.Get com.canonical.Unity.Launcher.Item progress
tests/scripts/set-count-visible.shnew file+3
@@ -0,0 +1,3 @@
1+#!/bin/sh
2+
3+qdbus com.canonical.Unity.Launcher /com/canonical/Unity/Launcher/$1 org.freedesktop.DBus.Properties.Set com.canonical.Unity.Launcher.Item countVisible $2
tests/scripts/set-count.shnew file+3
@@ -0,0 +1,3 @@
1+#!/bin/sh
2+
3+qdbus com.canonical.Unity.Launcher /com/canonical/Unity/Launcher/$1 org.freedesktop.DBus.Properties.Set com.canonical.Unity.Launcher.Item count $2
tests/scripts/set-progress.shnew file+3
@@ -0,0 +1,3 @@
1+#!/bin/sh
2+
3+qdbus com.canonical.Unity.Launcher /com/canonical/Unity/Launcher/$1 org.freedesktop.DBus.Properties.Set com.canonical.Unity.Launcher.Item progress $2