on xenial help sign in
added support for count emblems and progress overlays
a8c472cMichael Zanetti
Launcher/LauncherDelegate.qml+55
@@ -21,6 +21,8 @@ Item {
21 id: root
21 id: root
22
22
23 property string iconName
23 property string iconName
24+ property int count: -1
25+ property int progress: -1
24
26
25 property bool highlighted: false
27 property bool highlighted: false
26 property real maxAngle: 0
28 property real maxAngle: 0
@@ -70,6 +72,59 @@ Item {
70 property bool isSelected: root.highlighted
72 property bool isSelected: root.highlighted
71 onIsSelectedChanged: shaderEffectSource.scheduleUpdate();
73 onIsSelectedChanged: shaderEffectSource.scheduleUpdate();
72 }
74 }
75+
76+ BorderImage {
77+ objectName: "countEmblem"
78+ anchors {
79+ left: parent.left
80+ top: parent.top
81+ }
82+ width: Math.min(units.gu(7.5), Math.max(units.gu(4), countLabel.implicitWidth + units.gu(2)))
83+ height: units.gu(4)
84+ source: "graphics/notification@30.sci"
85+ visible: root.count > 0
86+
87+ Label {
88+ id: countLabel
89+ text: root.count
90+ anchors{
91+ left: parent.left
92+ right: parent.right
93+ margins: units.gu(0.5)
94+ verticalCenter: parent.verticalCenter
95+ }
96+ horizontalAlignment: Text.AlignHCenter
97+ elide: Text.ElideRight
98+ color: "white"
99+ }
100+ }
101+
102+ BorderImage {
103+ objectName: "progressOverlay"
104+ anchors {
105+ left: parent.left
106+ right: parent.right
107+ bottom: parent.bottom
108+ margins: units.dp(3)
109+ }
110+ visible: root.progress > -1
111+ source: "graphics/progressbar-trough@30.sci"
112+
113+ // For fill calculation we need to remove the 3 units of border defined in .sci file
114+ property int adjustedWidth: width - units.gu(3)
115+
116+ BorderImage {
117+ anchors {
118+ fill: parent
119+ rightMargin: parent.adjustedWidth - (Math.min(100, root.progress) * parent.adjustedWidth / 100)
120+ }
121+ source: "graphics/progressbar-fill@30.sci"
122+
123+ // Because of the borders in the borderimage we can't make it smaller than 10%
124+ // Let's just fade in from 0 to 10% instead and then fill the bar.
125+ opacity: root.progress / 10
126+ }
127+ }
73 }
128 }
74
129
75 ShaderEffect {
130 ShaderEffect {
Launcher/LauncherPanel.qml+2
@@ -131,6 +131,8 @@ Item {
131 width: itemWidth
131 width: itemWidth
132 height: itemHeight
132 height: itemHeight
133 iconName: model.icon
133 iconName: model.icon
134+ count: model.count
135+ progress: model.progress
134 inverted: root.inverted
136 inverted: root.inverted
135 highlighted: dragging && index === root.highlightIndex
137 highlighted: dragging && index === root.highlightIndex
136 z: -Math.abs(offset)
138 z: -Math.abs(offset)
Launcher/graphics/notification@30.pngnew file

Binary file not shown.

Launcher/graphics/notification@30.scinew file+5
@@ -0,0 +1,5 @@
1+border.left: 36
2+border.top: 36
3+border.bottom: 36
4+border.right: 36
5+source: notification@30.png
Launcher/graphics/progressbar-fill@30.pngnew file

Binary file not shown.

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

Binary file not shown.

Launcher/graphics/progressbar-trough@30.scinew file+5
@@ -0,0 +1,5 @@
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/MockLauncherItem.cpp+2−2
@@ -31,8 +31,8 @@ MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopF
31 m_pinned(false),
31 m_pinned(false),
32 m_running(false),
32 m_running(false),
33 m_recent(false),
33 m_recent(false),
34− m_progress(8),
34+ m_progress(-1),
35− m_count(8),
35+ m_count(0),
36 m_quickList(new MockQuickListModel(this))
36 m_quickList(new MockQuickListModel(this))
37{
37{
38
38
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+32−1
@@ -25,22 +25,33 @@ 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 m_list.append(item);
26 m_list.append(item);
27 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
27 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
28+ item->setCount(1234567);
29+ item->setProgress(150);
28 m_list.append(item);
30 m_list.append(item);
29 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
31 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
32+ item->setProgress(100);
30 m_list.append(item);
33 m_list.append(item);
31 item = new MockLauncherItem("facebook-webapp", "/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook", this);
34 item = new MockLauncherItem("facebook-webapp", "/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook", this);
35+ item->setCount(123456);
32 m_list.append(item);
36 m_list.append(item);
33 item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
37 item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
38+ item->setProgress(50);
34 m_list.append(item);
39 m_list.append(item);
35 item = new MockLauncherItem("twitter-webapp", "/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter", this);
40 item = new MockLauncherItem("twitter-webapp", "/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter", this);
41+ item->setCount(12345);
36 m_list.append(item);
42 m_list.append(item);
37 item = new MockLauncherItem("gmail-webapp", "/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail", this);
43 item = new MockLauncherItem("gmail-webapp", "/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail", this);
44+ item->setCount(123);
38 m_list.append(item);
45 m_list.append(item);
39 item = new MockLauncherItem("ubuntu-weather-app", "/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather", this);
46 item = new MockLauncherItem("ubuntu-weather-app", "/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather", this);
47+ item->setCount(12);
48+ item->setProgress(10);
40 m_list.append(item);
49 m_list.append(item);
41 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);
51+ item->setProgress(0);
42 m_list.append(item);
52 m_list.append(item);
43 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
53 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
54+ item->setCount(1);
44 m_list.append(item);
55 m_list.append(item);
45}
56}
46
57
@@ -91,9 +102,29 @@ unity::shell::launcher::LauncherItemInterface *MockLauncherModel::get(int index)
91
102
92void MockLauncherModel::move(int oldIndex, int newIndex)
103void MockLauncherModel::move(int oldIndex, int newIndex)
93{
104{
105+ // Make sure its not moved outside the lists
106+ if (newIndex < 0) {
107+ newIndex = 0;
108+ }
109+ if (newIndex >= m_list.count()) {
110+ newIndex = m_list.count()-1;
111+ }
112+
113+ // Nothing to do?
114+ if (oldIndex == newIndex) {
115+ return;
116+ }
117+
118+ // QList's and QAbstractItemModel's move implementation differ when moving an item up the list :/
119+ // While QList needs the index in the resulting list, beginMoveRows expects it to be in the current list
120+ // adjust the model's index by +1 in case we're moving upwards
121+ int newModelIndex = newIndex > oldIndex ? newIndex+1 : newIndex;
122+
94− beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
123+ beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newModelIndex);
95 m_list.move(oldIndex, newIndex);
124 m_list.move(oldIndex, newIndex);
96 endMoveRows();
125 endMoveRows();
126+
127+ pin(m_list.at(newIndex)->appId());
97}
128}
98
129
99void MockLauncherModel::pin(const QString &appId, int index)
130void MockLauncherModel::pin(const QString &appId, int index)
tests/qmltests/Launcher/tst_Launcher.qml+16
@@ -177,6 +177,22 @@ Item {
177 revealer.waitUntilLauncherDisappears();
177 revealer.waitUntilLauncherDisappears();
178 launcher.available = true;
178 launcher.available = true;
179 }
179 }
180+
181+ function test_countEmblems() {
182+ var launcherListView = findChild(launcher, "launcherListView");
183+ for (var i = 0; i < launcherListView.count; ++i) {
184+ var delegate = findChild(launcherListView, "launcherDelegate" + i)
185+ compare(findChild(delegate, "countEmblem").visible, LauncherModel.get(i).count > 0)
186+ }
187+ }
188+
189+ function test_progressOverlays() {
190+ var launcherListView = findChild(launcher, "launcherListView");
191+ for (var i = 0; i < launcherListView.count; ++i) {
192+ var delegate = findChild(launcherListView, "launcherDelegate" + i)
193+ compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
194+ }
195+ }
180 }
196 }
181
197
182 UT.UnityTestCase {
198 UT.UnityTestCase {