Merge lp:~saviq/unity8/dash-activity-indicator into lp:unity8

Proposed by Michał Sawicz on 2014-08-06
Status: Merged
Approved by: Andrea Cimitan on 2014-08-07
Approved revision: 1087
Merged at revision: 1131
Proposed branch: lp:~saviq/unity8/dash-activity-indicator
Merge into: lp:unity8
Prerequisite: lp:~unity-team/unity8/scopes-v4
Diff against target: 473 lines (+150/-98)
12 files modified
plugins/Dash/ScopeStyle.qml (+11/-8)
qml/Components/PageHeader.qml (+1/-14)
qml/Dash/Dash.qml (+68/-1)
qml/Dash/DashContent.qml (+2/-0)
qml/Dash/DashNavigationList.qml (+0/-5)
qml/Dash/GenericScopeView.qml (+2/-1)
qml/Dash/PreviewListView.qml (+27/-31)
tests/autopilot/unity8/shell/emulators/dash.py (+1/-1)
tests/plugins/Dash/tst_ScopeStyle.qml (+14/-7)
tests/qmltests/Components/tst_PageHeader.qml (+0/-23)
tests/qmltests/Dash/tst_Dash.qml (+23/-6)
tests/qmltests/Dash/tst_GenericScopeView.qml (+1/-1)
To merge this branch: bzr merge lp:~saviq/unity8/dash-activity-indicator
Reviewer Review Type Date Requested Status
Andrea Cimitan (community) 2014-08-06 Approve on 2014-08-07
PS Jenkins bot (community) continuous-integration 2014-08-06 Needs Fixing on 2014-08-06
Albert Astals Cid 2014-08-06 Pending
Review via email: mp+229805@code.launchpad.net

This proposal supersedes a proposal from 2014-07-29.

Commit message

Refactor dash activity indicator.

Description of the change

 * 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?
Yes, there was. And will be again.

To post a comment you must log in.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Andrea Cimitan (cimi) wrote : Posted in a previous version of this proposal

See inline

review: Needs Fixing
Michał Sawicz (saviq) : Posted in a previous version of this proposal
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

Text conflict in tests/qmltests/Dash/tst_Dash.qml
1 conflicts encountered.

review: Needs Fixing
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

There are autopilot failures related to autopilot, can you have a look?

review: Needs Fixing
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

err, autopilot failures related to indicators i mean :D

review: Needs Fixing
Andrea Cimitan (cimi) wrote :

Apart seeing if CI will pass, I tested locally twice and works fine

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
 * Did CI run pass? If not, please explain why.
Waiting CI

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Dash/ScopeStyle.qml'
2--- plugins/Dash/ScopeStyle.qml 2014-07-18 18:09:13 +0000
3+++ plugins/Dash/ScopeStyle.qml 2014-08-06 14:50:51 +0000
4@@ -38,14 +38,20 @@
5 /// Color used for text and symbolic icons
6 readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
7
8+ /// Luminance of the foreground color
9+ readonly property real foregroundLuminance: foreground ? luminance(foreground) : d.defaultForegroundLuminance
10+
11 /// Color used for the overall background
12 readonly property color background: "background-color" in style ? style["background-color"] : "transparent"
13
14+ /// Luminance of the foreground color
15+ readonly property real backgroundLuminance: background ? luminance(background) : d.defaultBackgroundLuminance
16+
17 /*! \brief Luminance threshold for switching between fore and background color
18
19 \note If background colour is not fully opaque, it's not taken into account.
20 */
21- readonly property real threshold: background.a !== 1.0 ? d.foregroundLuminance : (d.foregroundLuminance + d.backgroundLuminance) / 2
22+ readonly property real threshold: background.a !== 1.0 ? foregroundLuminance : (foregroundLuminance + backgroundLuminance) / 2
23
24 /*! \brief The lighter of foreground and background colors
25
26@@ -53,8 +59,8 @@
27 and defaults to the theme-provided light color.
28 */
29 readonly property color light: {
30- if (background.a !== 1.0) return d.foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
31- return d.foregroundLuminance > d.backgroundLuminance ? foreground : background;
32+ if (background.a !== 1.0) return foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
33+ return foregroundLuminance > backgroundLuminance ? foreground : background;
34 }
35
36 /*! \brief The darker of foreground and background colors
37@@ -63,8 +69,8 @@
38 and defaults to the theme-provided dark color.
39 */
40 readonly property color dark: {
41- if (background.a !== 1.0) return d.foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
42- return d.foregroundLuminance < d.backgroundLuminance ? foreground : background;
43+ if (background.a !== 1.0) return foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
44+ return foregroundLuminance < backgroundLuminance ? foreground : background;
45 }
46
47 /// Source of the logo image for the header
48@@ -78,9 +84,6 @@
49
50 //! @cond
51 property var d: QtObject {
52- readonly property real foregroundLuminance: luminance(foreground)
53- readonly property real backgroundLuminance: luminance(background)
54-
55 // FIXME: should be taken from the theme
56 readonly property color defaultLight: "white"
57 readonly property color defaultDark: "grey"
58
59=== modified file 'qml/Components/PageHeader.qml'
60--- qml/Components/PageHeader.qml 2014-07-31 16:49:50 +0000
61+++ qml/Components/PageHeader.qml 2014-08-06 14:50:51 +0000
62@@ -32,7 +32,6 @@
63 property bool searchEntryEnabled: false
64 property ListModel searchHistory: SearchHistoryModel
65 property alias searchQuery: searchTextField.text
66- property bool searchInProgress: false
67
68 property alias bottomItem: bottomContainer.children
69
70@@ -200,25 +199,13 @@
71 anchors.fill: parent
72 anchors.margins: units.gu(.75)
73 source: "image://theme/clear"
74- opacity: searchTextField.text.length > 0 && !searchActivityIndicator.running
75+ opacity: searchTextField.text.length > 0
76 visible: opacity > 0
77 Behavior on opacity {
78 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
79 }
80 }
81
82- ActivityIndicator {
83- id: searchActivityIndicator
84- objectName: "searchIndicator"
85- anchors.fill: parent
86- anchors.margins: units.gu(.75)
87- running: root.searchInProgress
88- opacity: running ? 1 : 0
89- Behavior on opacity {
90- UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
91- }
92- }
93-
94 onClicked: {
95 root.resetSearch(true);
96 root.openSearchHistory();
97
98=== modified file 'qml/Dash/Dash.qml'
99--- qml/Dash/Dash.qml 2014-08-06 14:50:51 +0000
100+++ qml/Dash/Dash.qml 2014-08-06 14:50:51 +0000
101@@ -14,7 +14,7 @@
102 * along with this program. If not, see <http://www.gnu.org/licenses/>.
103 */
104
105-import QtQuick 2.0
106+import QtQuick 2.2
107 import Ubuntu.Components 0.1
108 import Unity 0.2
109 import Utils 0.1
110@@ -132,4 +132,71 @@
111 }
112 }
113 }
114+
115+ Rectangle {
116+ id: indicator
117+ objectName: "processingIndicator"
118+ anchors {
119+ left: parent.left
120+ right: parent.right
121+ bottom: parent.bottom
122+ }
123+ height: units.dp(3)
124+ color: scopeStyle.backgroundLuminance > 0.7 ? "#50000000" : "#50ffffff"
125+ opacity: 0
126+ visible: opacity > 0
127+
128+ readonly property bool processing: dashContent.processing || scopeItem.processing
129+
130+ Behavior on opacity {
131+ UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
132+ }
133+
134+ onProcessingChanged: {
135+ if (processing) delay.start();
136+ else if (!persist.running) indicator.opacity = 0;
137+ }
138+
139+ Timer {
140+ id: delay
141+ interval: 200
142+ onTriggered: if (indicator.processing) {
143+ persist.restart();
144+ indicator.opacity = 1;
145+ }
146+ }
147+
148+ Timer {
149+ id: persist
150+ interval: 2 * UbuntuAnimation.SleepyDuration - UbuntuAnimation.FastDuration
151+ onTriggered: if (!indicator.processing) indicator.opacity = 0
152+ }
153+
154+ Rectangle {
155+ id: orange
156+ anchors { top: parent.top; bottom: parent.bottom }
157+ width: parent.width / 4
158+ color: Theme.palette.selected.foreground
159+
160+ SequentialAnimation {
161+ running: indicator.visible
162+ loops: Animation.Infinite
163+ XAnimator {
164+ from: -orange.width / 2
165+ to: indicator.width - orange.width / 2
166+ duration: UbuntuAnimation.SleepyDuration
167+ easing.type: Easing.InOutSine
168+ target: orange
169+ }
170+ XAnimator {
171+ from: indicator.width - orange.width / 2
172+ to: -orange.width / 2
173+ duration: UbuntuAnimation.SleepyDuration
174+ easing.type: Easing.InOutSine
175+ target: orange
176+ }
177+ }
178+ }
179+ }
180+
181 }
182
183=== modified file 'qml/Dash/DashContent.qml'
184--- qml/Dash/DashContent.qml 2014-08-06 14:50:51 +0000
185+++ qml/Dash/DashContent.qml 2014-08-06 14:50:51 +0000
186@@ -25,6 +25,8 @@
187
188 property alias scopes: dashContentList.model
189 readonly property alias currentIndex: dashContentList.currentIndex
190+ readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
191+ && dashContentList.currentItem.item.processing || false
192
193 signal scopeLoaded(string scopeId)
194 signal gotoScope(string scopeId)
195
196=== modified file 'qml/Dash/DashNavigationList.qml'
197--- qml/Dash/DashNavigationList.qml 2014-08-06 14:50:51 +0000
198+++ qml/Dash/DashNavigationList.qml 2014-08-06 14:50:51 +0000
199@@ -35,11 +35,6 @@
200 anchors.fill: parent
201 }
202
203- ActivityIndicator {
204- id: loadingIndicator
205- anchors.centerIn: parent
206- running: !(navigation && navigation.loaded)
207- }
208 clip: true
209
210 Behavior on height {
211
212=== modified file 'qml/Dash/GenericScopeView.qml'
213--- qml/Dash/GenericScopeView.qml 2014-08-06 14:50:51 +0000
214+++ qml/Dash/GenericScopeView.qml 2014-08-06 14:50:51 +0000
215@@ -38,6 +38,8 @@
216 style: scope ? scope.customizations : {}
217 }
218
219+ readonly property bool processing: scope ? scope.searchInProgress || previewListView.processing : false
220+
221 signal backClicked()
222
223 function positionAtBeginning() {
224@@ -379,7 +381,6 @@
225 title: scopeView.scope ? scopeView.scope.name : ""
226 showBackButton: scopeView.hasBackAction
227 searchEntryEnabled: true
228- searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false
229 scopeStyle: scopeView.scopeStyle
230
231 bottomItem: DashNavigation {
232
233=== modified file 'qml/Dash/PreviewListView.qml'
234--- qml/Dash/PreviewListView.qml 2014-07-17 13:10:45 +0000
235+++ qml/Dash/PreviewListView.qml 2014-08-06 14:50:51 +0000
236@@ -32,6 +32,9 @@
237 property alias currentItem: previewListView.currentItem
238 property alias count: previewListView.count
239
240+ readonly property bool processing: currentItem && (!currentItem.previewModel.loaded
241+ || currentItem.previewModel.processingAction)
242+
243 PageHeader {
244 id: header
245 objectName: "pageHeader"
246@@ -83,39 +86,32 @@
247 }
248 }
249
250- delegate: Item {
251- objectName: "previewItem" + index
252+ delegate: Previews.Preview {
253+ id: preview
254+ objectName: "preview" + index
255 height: previewListView.height
256 width: previewListView.width
257
258- readonly property bool ready: preview.previewModel.loaded
259-
260- Previews.Preview {
261- id: preview
262- objectName: "preview" + index
263- anchors.fill: parent
264-
265- isCurrent: parent.ListView.isCurrentItem
266-
267- previewModel: {
268- var previewStack = root.scope.preview(result);
269- return previewStack.getPreviewModel(0);
270- }
271- scopeStyle: root.scopeStyle
272- }
273-
274- MouseArea {
275- id: processingMouseArea
276- objectName: "processingMouseArea"
277- anchors.fill: parent
278- enabled: !preview.previewModel.loaded || preview.previewModel.processingAction
279-
280- ActivityIndicator {
281- anchors.centerIn: parent
282- visible: root.open && parent.enabled
283- running: visible
284- }
285- }
286- }
287+ isCurrent: ListView.isCurrentItem
288+
289+ previewModel: {
290+ var previewStack = root.scope.preview(result);
291+ return previewStack.getPreviewModel(0);
292+ }
293+ scopeStyle: root.scopeStyle
294+ }
295+ }
296+
297+ MouseArea {
298+ id: processingMouseArea
299+ objectName: "processingMouseArea"
300+ anchors {
301+ left: parent.left
302+ right: parent.right
303+ top: pageHeader.bottom
304+ bottom: parent.bottom
305+ }
306+
307+ enabled: root.processing
308 }
309 }
310
311=== modified file 'tests/autopilot/unity8/shell/emulators/dash.py'
312--- tests/autopilot/unity8/shell/emulators/dash.py 2014-07-29 19:49:36 +0000
313+++ tests/autopilot/unity8/shell/emulators/dash.py 2014-08-06 14:50:51 +0000
314@@ -150,7 +150,7 @@
315 headerContainer.contentY.wait_for(0)
316 search_text_field = self._get_search_text_field()
317 search_text_field.write(query)
318- current_header.select_single(objectName="searchIndicator").running.wait_for(False)
319+ self.select_single(objectName="processingIndicator").visible.wait_for(False)
320
321 def _get_search_text_field(self):
322 page_header = self._get_current_page_header()
323
324=== modified file 'tests/plugins/Dash/tst_ScopeStyle.qml'
325--- tests/plugins/Dash/tst_ScopeStyle.qml 2014-07-19 07:56:55 +0000
326+++ tests/plugins/Dash/tst_ScopeStyle.qml 2014-08-06 14:50:51 +0000
327@@ -54,6 +54,9 @@
328 { tag: "lightgrey", luminance: 0.8275 },
329 { tag: "grey", luminance: 0.5020 },
330 { tag: "darkgrey", luminance: 0.6627 },
331+ { tag: "red", luminance: 0.2126 },
332+ { tag: "green", luminance: 0.3590 },
333+ { tag: "blue", luminance: 0.0722 },
334 ];
335 }
336
337@@ -64,10 +67,10 @@
338
339 function test_foreground_data() {
340 return [
341- { tag: "default", index: 0, foreground: "grey" },
342- { tag: "red on black", index: 1, foreground: "red" },
343- { tag: "green on white", index: 2, foreground: "green" },
344- { tag: "blue on darkgrey", index: 3, foreground: "blue" },
345+ { tag: "default", index: 0, foreground: "grey", luminance: 0.5020 },
346+ { tag: "red on black", index: 1, foreground: "red", luminance: 0.2126 },
347+ { tag: "green on white", index: 2, foreground: "green", luminance: 0.3590 },
348+ { tag: "blue on darkgrey", index: 3, foreground: "blue", luminance: 0.0722 },
349 ];
350 }
351
352@@ -75,14 +78,15 @@
353 tool.style = testCase.styles[data.index];
354 verify(Qt.colorEqual(tool.foreground, data.foreground),
355 "Foreground color not equal: %1 != %2".arg(tool.foreground).arg(data.foreground));
356+ compare(tool.foregroundLuminance.toFixed(4), data.luminance.toFixed(4));
357 }
358
359 function test_background_data() {
360 return [
361 { tag: "default", index: 0, background: "transparent" },
362- { tag: "red on black", index: 1, background: "black" },
363- { tag: "green on white", index: 2, background: "white" },
364- { tag: "blue on darkgrey", index: 3, background: "darkgrey" },
365+ { tag: "red on black", index: 1, background: "black", luminance: 0 },
366+ { tag: "green on white", index: 2, background: "white", luminance: 1 },
367+ { tag: "blue on darkgrey", index: 3, background: "darkgrey", luminance: 0.6627 },
368 ];
369 }
370
371@@ -90,6 +94,9 @@
372 tool.style = testCase.styles[data.index];
373 verify(Qt.colorEqual(tool.background, data.background),
374 "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));
375+ if (data.hasOwnProperty("luminance")) {
376+ compare(tool.backgroundLuminance.toFixed(4), data.luminance.toFixed(4));
377+ }
378 }
379
380 function test_threshold_data() {
381
382=== modified file 'tests/qmltests/Components/tst_PageHeader.qml'
383--- tests/qmltests/Components/tst_PageHeader.qml 2014-07-28 09:14:23 +0000
384+++ tests/qmltests/Components/tst_PageHeader.qml 2014-08-06 14:50:51 +0000
385@@ -119,29 +119,6 @@
386 compare(pageHeader.searchHistory.get(0).query, "humppa4")
387 }
388
389- function test_search_indicator() {
390- var searchIndicator = findChild(pageHeader, "searchIndicator")
391- var clearIcon = findChild(pageHeader, "clearIcon")
392-
393- pageHeader.triggerSearch()
394-
395- tryCompare(clearIcon, "visible", false)
396- pageHeader.searchQuery = "ubuntu"
397- tryCompare(clearIcon, "visible", true)
398-
399- pageHeader.searchInProgress = false
400- compare(searchIndicator.running, false, "Search indicator is running.")
401- tryCompare(clearIcon, "visible", true)
402-
403- pageHeader.searchInProgress = true
404- compare(searchIndicator.running, true, "Search indicator isn't running.")
405- tryCompare(clearIcon, "visible", false)
406-
407- pageHeader.searchInProgress = false;
408- compare(searchIndicator.running, false, "Search indicator is running.")
409- tryCompare(clearIcon, "visible", true)
410- }
411-
412 function test_titleImage() {
413
414 var titleImage = findChild(pageHeader, "titleImage");
415
416=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
417--- tests/qmltests/Dash/tst_Dash.qml 2014-08-06 14:50:51 +0000
418+++ tests/qmltests/Dash/tst_Dash.qml 2014-08-06 14:50:51 +0000
419@@ -45,12 +45,8 @@
420 name: "Dash"
421 when: windowShown
422
423- property var scopes
424-
425- Component.onCompleted: {
426- var dashContent = findChild(dash, "dashContent");
427- scopes = dashContent.scopes;
428- }
429+ readonly property Item dashContent: findChild(dash, "dashContent");
430+ readonly property var scopes: dashContent.scopes
431
432 function init() {
433 // clear and reload the scopes.
434@@ -106,5 +102,26 @@
435 dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
436 tryCompare(dashContentList, "currentIndex", 1)
437 }
438+
439+ function test_processing_indicator() {
440+ tryCompare(scopes, "loaded", true);
441+
442+ var processingIndicator = findChild(dash, "processingIndicator");
443+ verify(processingIndicator, "Can't find the processing indicator.");
444+
445+ verify(!processingIndicator.visible, "Processing indicator should be visible.");
446+
447+ tryCompareFunction(function() {
448+ return scopes.getScope(dashContent.currentIndex) != null;
449+ }, true);
450+ var currentScope = scopes.getScope(dashContent.currentIndex);
451+ verify(currentScope, "Can't find the current scope.");
452+
453+ currentScope.setSearchInProgress(true);
454+ tryCompare(processingIndicator, "visible", true);
455+
456+ currentScope.setSearchInProgress(false);
457+ tryCompare(processingIndicator, "visible", false);
458+ }
459 }
460 }
461
462=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
463--- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-07-24 20:40:57 +0000
464+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-08-06 14:50:51 +0000
465@@ -319,7 +319,7 @@
466 units.gu(2),
467 testCase.previewListView.height / 2);
468 tryCompare(previewListViewList, "moving", false);
469- tryCompare(testCase.previewListView.currentItem, "objectName", "previewItem" + i);
470+ tryCompare(testCase.previewListView.currentItem, "objectName", "preview" + i);
471
472 }
473 closePreview();

Subscribers

People subscribed via source and target branches