on xenial help sign in
added support for count emblems and progress overlays on the launcher.

Approved by PS Jenkins bot, Michał Sawicz.

commit78832edf6507a9bd119c835a25b2b9b79278da47 authorMichael Zanetti <michael.zanetti@canonical.com> dateTue 20 Aug 2013, 17:39 (13 years ago) parent5e839a419b9e9b
11 files changed+141−10
Launcher/LauncherDelegate.qml+73−7 Launcher/LauncherPanel.qml+4 Launcher/graphics/notification@30.png Launcher/graphics/notification@30.sci+5 Launcher/graphics/progressbar-fill@30.png Launcher/graphics/progressbar-fill@30.sci+5 Launcher/graphics/progressbar-trough@30.png Launcher/graphics/progressbar-trough@30.sci+5 tests/mocks/Unity/Launcher/MockLauncherItem.cpp+2−2 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+31−1 tests/qmltests/Launcher/tst_Launcher.qml+16
Launcher/LauncherDelegate.qml+73−7
@@ -21,7 +21,8 @@ Item {
2121 id: root
2222
2323 property string iconName
24−
24+ property int count: -1
25+ property int progress: -1
2526 property bool highlighted: false
2627 property real maxAngle: 0
2728 property bool inverted: false
@@ -38,6 +39,11 @@ Item {
3839 property real itemOpacity: 1
3940 property real brightness: 0
4041
42+ onIconNameChanged: shaderEffectSource.scheduleUpdate();
43+ onCountChanged: shaderEffectSource.scheduleUpdate();
44+ onProgressChanged: shaderEffectSource.scheduleUpdate();
45+ onHighlightedChanged: shaderEffectSource.scheduleUpdate();
46+
4147 Item {
4248 id: iconItem
4349 width: parent.itemWidth
@@ -54,9 +60,7 @@ Item {
5460 id: iconImage
5561 sourceSize.width: iconShape.width
5662 sourceSize.height: iconShape.height
57− source: "../graphics/applicationIcons/" + iconName + ".png"
58− property string iconName: root.iconName
59− onIconNameChanged: shaderEffectSource.scheduleUpdate();
63+ source: "../graphics/applicationIcons/" + root.iconName + ".png"
6064 }
6165 }
6266
@@ -64,11 +68,73 @@ Item {
6468 id: overlayHighlight
6569 anchors.centerIn: iconItem
6670 rotation: inverted ? 180 : 0
67− source: isSelected ? "graphics/selected.sci" : "graphics/non-selected.sci"
71+ source: root.highlighted ? "graphics/selected.sci" : "graphics/non-selected.sci"
6872 width: root.itemWidth + units.gu(0.5)
6973 height: root.itemHeight + units.gu(0.5)
70− property bool isSelected: root.highlighted
71− onIsSelectedChanged: shaderEffectSource.scheduleUpdate();
74+ }
75+
76+ BorderImage {
77+ objectName: "countEmblem"
78+ anchors {
79+ right: parent.right
80+ top: parent.top
81+ margins: -units.dp(1)
82+ }
83+ width: Math.min(units.gu(7.5), Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
84+ height: units.gu(3)
85+ source: "graphics/notification.sci"
86+ visible: root.count > 0
87+
88+ Label {
89+ id: countLabel
90+ text: root.count
91+ anchors.centerIn: parent
92+ width: units.gu(6)
93+ horizontalAlignment: Text.AlignHCenter
94+ elide: Text.ElideRight
95+ color: "white"
96+ fontSize: "small"
97+ font.bold: true
98+ }
99+ }
100+
101+ BorderImage {
102+ id: progressOverlay
103+ objectName: "progressOverlay"
104+ anchors {
105+ left: iconItem.left
106+ right: iconItem.right
107+ bottom: iconItem.bottom
108+ leftMargin: units.gu(0.5)
109+ rightMargin: units.gu(0.5)
110+ bottomMargin: units.gu(0.5)
111+ }
112+ height: units.gu(1.5)
113+ visible: root.progress > -1
114+ source: "graphics/progressbar-trough.sci"
115+
116+ // For fill calculation we need to remove the 2 units of border defined in .sci file
117+ property int adjustedWidth: width - units.gu(2)
118+
119+ Item {
120+ anchors {
121+ left: parent.left
122+ top: parent.top
123+ bottom: parent.bottom
124+ }
125+ width: Math.min(100, root.progress) / 100 * parent.adjustedWidth + units.gu(1)
126+ clip: true
127+
128+ BorderImage {
129+ anchors {
130+ left: parent.left
131+ top: parent.top
132+ bottom: parent.bottom
133+ }
134+ width: progressOverlay.width
135+ source: "graphics/progressbar-fill.sci"
136+ }
137+ }
72138 }
73139 }
74140
Launcher/LauncherPanel.qml+4
@@ -133,6 +133,8 @@ Item {
133133 width: itemWidth
134134 height: itemHeight
135135 iconName: model.icon
136+ count: model.count
137+ progress: model.progress
136138 inverted: root.inverted
137139 highlighted: dragging && index === root.highlightIndex
138140 z: -Math.abs(offset)
@@ -322,6 +324,8 @@ Item {
322324 fakeDragItem.y = mouseY - yOffset + launcherListView.anchors.topMargin + launcherListView.topMargin
323325 fakeDragItem.angle = selectedItem.angle * (root.inverted ? -1 : 1)
324326 fakeDragItem.offset = selectedItem.offset * (root.inverted ? -1 : 1)
327+ fakeDragItem.count = LauncherModel.get(draggedIndex).count
328+ fakeDragItem.progress = LauncherModel.get(draggedIndex).progress
325329 fakeDragItem.flatten()
326330 drag.target = fakeDragItem
327331
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
3131 m_pinned(false),
3232 m_running(false),
3333 m_recent(false),
34− m_progress(8),
35− m_count(8),
34+ m_progress(-1),
35+ m_count(0),
3636 m_quickList(new MockQuickListModel(this))
3737{
3838
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+31−1
@@ -23,22 +23,32 @@
2323MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
2424{
2525 MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
26+ item->setProgress(0);
2627 m_list.append(item);
2728 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
29+ item->setProgress(10);
2830 m_list.append(item);
2931 item = new MockLauncherItem("gallery-app", "/usr/share/applications/gallery-app.desktop", "Gallery", "gallery", this);
32+ item->setProgress(50);
3033 m_list.append(item);
3134 item = new MockLauncherItem("facebook-webapp", "/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook", this);
35+ item->setProgress(150);
3236 m_list.append(item);
3337 item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
38+ item->setCount(1);
3439 m_list.append(item);
3540 item = new MockLauncherItem("twitter-webapp", "/usr/share/applications/twitter-webapp.desktop", "Twitter", "twitter", this);
41+ item->setCount(12);
3642 m_list.append(item);
3743 item = new MockLauncherItem("gmail-webapp", "/usr/share/applications/gmail-webapp.desktop", "GMail", "gmail", this);
44+ item->setCount(123);
3845 m_list.append(item);
3946 item = new MockLauncherItem("ubuntu-weather-app", "/usr/share/applications/ubuntu-weather-app.desktop", "Weather", "weather", this);
47+ item->setCount(1234567890);
4048 m_list.append(item);
4149 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad", this);
50+ item->setProgress(50);
51+ item->setCount(5);
4252 m_list.append(item);
4353 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
4454 m_list.append(item);
@@ -91,9 +101,29 @@ unity::shell::launcher::LauncherItemInterface *MockLauncherModel::get(int index)
91101
92102void MockLauncherModel::move(int oldIndex, int newIndex)
93103{
94− beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
104+ // Make sure its not moved outside the lists
105+ if (newIndex < 0) {
106+ newIndex = 0;
107+ }
108+ if (newIndex >= m_list.count()) {
109+ newIndex = m_list.count()-1;
110+ }
111+
112+ // Nothing to do?
113+ if (oldIndex == newIndex) {
114+ return;
115+ }
116+
117+ // QList's and QAbstractItemModel's move implementation differ when moving an item up the list :/
118+ // While QList needs the index in the resulting list, beginMoveRows expects it to be in the current list
119+ // adjust the model's index by +1 in case we're moving upwards
120+ int newModelIndex = newIndex > oldIndex ? newIndex+1 : newIndex;
121+
122+ beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newModelIndex);
95123 m_list.move(oldIndex, newIndex);
96124 endMoveRows();
125+
126+ pin(m_list.at(newIndex)->appId());
97127}
98128
99129void MockLauncherModel::pin(const QString &appId, int index)
tests/qmltests/Launcher/tst_Launcher.qml+16
@@ -182,6 +182,22 @@ Item {
182182 revealer.waitUntilLauncherDisappears();
183183 launcher.available = true;
184184 }
185+
186+ function test_countEmblems() {
187+ var launcherListView = findChild(launcher, "launcherListView");
188+ for (var i = 0; i < launcherListView.count; ++i) {
189+ var delegate = findChild(launcherListView, "launcherDelegate" + i)
190+ compare(findChild(delegate, "countEmblem").visible, LauncherModel.get(i).count > 0)
191+ }
192+ }
193+
194+ function test_progressOverlays() {
195+ var launcherListView = findChild(launcher, "launcherListView");
196+ for (var i = 0; i < launcherListView.count; ++i) {
197+ var delegate = findChild(launcherListView, "launcherDelegate" + i)
198+ compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
199+ }
200+ }
185201 }
186202
187203 UT.UnityTestCase {