Merge lp:~aacid/unity8/list_on_bottom_swipe into lp:unity8

Proposed by Albert Astals Cid
Status: Merged
Approved by: Albert Astals Cid
Approved revision: 1347
Merged at revision: 1479
Proposed branch: lp:~aacid/unity8/list_on_bottom_swipe
Merge into: lp:unity8
Diff against target: 2435 lines (+792/-1116)
20 files modified
debian/control (+1/-1)
po/unity8.pot (+41/-45)
qml/Dash/Dash.qml (+89/-127)
qml/Dash/DashContent.qml (+11/-1)
qml/Dash/GenericScopeView.qml (+1/-1)
qml/Dash/PageHeader.qml (+11/-1)
qml/Dash/ScopesList.qml (+127/-0)
qml/Dash/ScopesListCategory.qml (+176/-0)
qml/Dash/ScopesListCategoryItem.qml (+104/-0)
qml/Dash/ScopesOverview.qml (+0/-575)
qml/Dash/ScopesOverviewAll.qml (+0/-54)
qml/Dash/ScopesOverviewFavorites.qml (+0/-73)
qml/Dash/ScopesOverviewTab.qml (+0/-74)
tests/mocks/Unity/CMakeLists.txt (+1/-1)
tests/mocks/Unity/fake_scopes.cpp (+57/-3)
tests/mocks/Unity/fake_scopes.h (+8/-3)
tests/mocks/Unity/fake_scopesoverview.cpp (+77/-11)
tests/mocks/Unity/fake_scopesoverview.h (+18/-3)
tests/qmltests/Dash/tst_Dash.qml (+70/-142)
tests/qmltests/Dash/tst_GenericScopeView.qml (+0/-1)
To merge this branch: bzr merge lp:~aacid/unity8/list_on_bottom_swipe
Reviewer Review Type Date Requested Status
Nick Dedekind (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Benjamin Keyser (community) design Approve
Review via email: mp+235266@code.launchpad.net

Commit message

Replace Scopes Overview by the new Manage Dash

Description of the change

The unity-scopes-shell change is not needed if you only want to run tests or use make tryDash

 * Are there any related MPs required for this MP to build/function as expected?
https://code.launchpad.net/~stolowski/unity-scopes-shell/feeds
https://code.launchpad.net/~aacid/unity-api/setMoveFavorite/+merge/238936

 * 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?
This is a design driven change

To post a comment you must log in.
Michał Sawicz (saviq) wrote :

Would be nice if the tab with ^ (the hint alone) at the bottom absorbed touches so you couldn't activate items through it.

Omer Akram (om26er) wrote :

When do we plan to land this branch ? The bottom edge interaction seems quite complex and ineffective in its current form. Would really love to see this change land soon.

Albert Astals Cid (aacid) wrote :

@Omer: As you can see on the bug this is targetted for ota-1

Nick Dedekind (nick-dedekind) wrote :

TestCase:
1) Open dash management
2) Enter edit mode
3) Tap an item

Expected: Scope lifts and releases in same position.
Actual: Scope is switched with the next scope in the list.

It should only switch position when it's been removed from the list?

review: Needs Information
Albert Astals Cid (aacid) wrote :

Wops, yes that needs fixing.

Albert Astals Cid (aacid) wrote :

> TestCase:
> 1) Open dash management
> 2) Enter edit mode
> 3) Tap an item
>
> Expected: Scope lifts and releases in same position.
> Actual: Scope is switched with the next scope in the list.
>
> It should only switch position when it's been removed from the list?

Fixed

Nick Dedekind (nick-dedekind) wrote :

Should we bump the libunity-api requirement to 7.93? If so, can you add https://code.launchpad.net/~aacid/unity-api/setMoveFavorite/+merge/238936 to the related MPs.

review: Needs Information
Albert Astals Cid (aacid) wrote :

> Should we bump the libunity-api requirement to 7.93? If so, can you add
> https://code.launchpad.net/~aacid/unity-api/setMoveFavorite/+merge/238936 to
> the related MPs.

Yep, Done :)

Nick Dedekind (nick-dedekind) wrote :

 * 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.
No, will not pass due to requirements

 * Did you make sure that the branch does not contain spurious tags?
Yes

review: Approve
Nick Dedekind (nick-dedekind) wrote :

Added a few comments when looking over the ScopesList code again. Sorry!

review: Needs Information
Albert Astals Cid (aacid) wrote :

> Should we not be able to favourite things that aren't in the "other" category? I would think we can [un]favourite anything.

Thigns in search tha are not favorites or others can't be favorited (e.g. a result to wikipedia when you search for metallica)

Albert Astals Cid (aacid) wrote :

> not really sure about this "other" feed. In this context isn't "other" everything except category == "home".

"other" is the new name for "the non favorite", there's "the other other" (e.g. search results that link to wikipedia)

Albert Astals Cid (aacid) wrote :

> where does "name" come from? I feel this is putting a bit too much context inside a fairly generic component. Should we not have a root level property for "title" and give the alternative "Home"/"Other" from the usage:

Done

Nick Dedekind (nick-dedekind) wrote :

Ok, all good again :)

review: Approve
Benjamin Keyser (bjkeyser) wrote :

Hi, this is my first merge review :) James should do the review, but he's out of the office until Thursday so I'm filling in what I know were the last agreed design asks.

1. The category headings should be Medium weight not light: so "home" and "other" headings should be medium.

2. Please change the "Other" heading to "Also installed" ... this change is just a change of mind because now that I see it, it doesn't make as much sense.

Please include the launcher "nudge out of the way" animation when the list item is being moved up and down, so a small space opens between the items before you drop it in. Check the launcher for the comparison.

review: Needs Fixing (design)
Albert Astals Cid (aacid) wrote :

> 1. The category headings should be Medium weight not light: so "home" and "other" headings should be medium.
They are medium font size, effectively they use the same code we use for the category in the rest of the dash.

> 2. Please change the "Other" heading to "Also installed" ... this change is just a change of mind because now that I see it, it doesn't make as much sense.
Changed

> Please include the launcher "nudge out of the way" animation when the list item is being moved up and down, so a small space opens between the items before you drop it in. Check the launcher for the comparison.
Working on it

Albert Astals Cid (aacid) wrote :

> > Please include the launcher "nudge out of the way" animation when the list
> item is being moved up and down, so a small space opens between the items
> before you drop it in. Check the launcher for the comparison.
> Working on it

This is now done.

Benjamin Keyser (bjkeyser) :
review: Approve (design)
Nick Dedekind (nick-dedekind) wrote :

Looks good to me.

review: Approve
Albert Astals Cid (aacid) wrote :

I moved to Needs Review thinking i wanted CI to run but then realized it didn't make sense since CI can't run here because of the dependencies so now it looks like i top approved myself but it was in fact Nick Dedekind

1348. By Albert Astals Cid on 2014-12-05

Merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-12-03 17:22:51 +0000
3+++ debian/control 2014-12-05 10:47:59 +0000
4@@ -25,7 +25,7 @@
5 libqmenumodel-dev (>= 0.2.8),
6 libqt5xmlpatterns5-dev,
7 libsystemsettings-dev,
8- libunity-api-dev (>= 7.93),
9+ libunity-api-dev (>= 7.94),
10 libusermetricsoutput1-dev,
11 libxcb1-dev,
12 pkg-config,
13
14=== modified file 'po/unity8.pot'
15--- po/unity8.pot 2014-11-07 09:59:15 +0000
16+++ po/unity8.pot 2014-12-05 10:47:59 +0000
17@@ -8,7 +8,7 @@
18 msgstr ""
19 "Project-Id-Version: unity8\n"
20 "Report-Msgid-Bugs-To: \n"
21-"POT-Creation-Date: 2014-11-07 10:59+0100\n"
22+"POT-Creation-Date: 2014-11-20 12:00+0100\n"
23 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
24 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
25 "Language-Team: LANGUAGE <LL@li.org>\n"
26@@ -172,20 +172,24 @@
27 msgid "See all"
28 msgstr ""
29
30-#: qml/Dash/GenericScopeView.qml:496 qml/Dash/PageHeader.qml:258
31+#: qml/Dash/GenericScopeView.qml:496 qml/Dash/PageHeader.qml:267
32 #: qml/Panel/SearchIndicator.qml:27
33 msgid "Search"
34 msgstr ""
35
36-#: qml/Dash/PageHeader.qml:268
37+#: qml/Dash/PageHeader.qml:260
38+msgid "Store"
39+msgstr ""
40+
41+#: qml/Dash/PageHeader.qml:277
42 msgid "Settings"
43 msgstr ""
44
45-#: qml/Dash/PageHeader.qml:275
46+#: qml/Dash/PageHeader.qml:284
47 msgid "Remove from Favorites"
48 msgstr ""
49
50-#: qml/Dash/PageHeader.qml:275
51+#: qml/Dash/PageHeader.qml:284
52 msgid "Add to Favorites"
53 msgstr ""
54
55@@ -217,31 +221,23 @@
56 msgid "Release to refresh…"
57 msgstr ""
58
59-#: qml/Dash/ScopesOverview.qml:215
60-msgid "Manage Scopes"
61-msgstr ""
62-
63-#: qml/Dash/ScopesOverview.qml:437
64-msgid "Done"
65-msgstr ""
66-
67-#: qml/Dash/ScopesOverview.qml:463
68-msgid "Store"
69-msgstr ""
70-
71-#: qml/Dash/ScopesOverviewTab.qml:36
72-msgid "Favorites"
73-msgstr ""
74-
75-#: qml/Dash/ScopesOverviewTab.qml:54
76-msgid "All"
77+#: qml/Dash/ScopesList.qml:63
78+msgid "Manage"
79+msgstr ""
80+
81+#: qml/Dash/ScopesList.qml:105
82+msgid "Home"
83+msgstr ""
84+
85+#: qml/Dash/ScopesList.qml:106
86+msgid "Also installed"
87 msgstr ""
88
89 #: qml/Greeter/Greeter.qml:174
90 msgid "Unlock"
91 msgstr ""
92
93-#: qml/Notifications/NotificationMenuItemFactory.qml:116
94+#: qml/Notifications/NotificationMenuItemFactory.qml:128
95 msgid "Show password"
96 msgstr ""
97
98@@ -289,55 +285,55 @@
99 msgid "Roaming"
100 msgstr ""
101
102+#: qml/Shell.qml:390
103+msgid "Enter passphrase"
104+msgstr ""
105+
106 #: qml/Shell.qml:391
107-msgid "Enter passphrase"
108+msgid "Sorry, incorrect passphrase"
109 msgstr ""
110
111 #: qml/Shell.qml:392
112-msgid "Sorry, incorrect passphrase"
113-msgstr ""
114-
115-#: qml/Shell.qml:393
116 msgid "Please re-enter"
117 msgstr ""
118
119+#: qml/Shell.qml:394
120+msgid "Enter passcode"
121+msgstr ""
122+
123 #: qml/Shell.qml:395
124-msgid "Enter passcode"
125-msgstr ""
126-
127-#: qml/Shell.qml:396
128 msgid "Sorry, incorrect passcode"
129 msgstr ""
130
131+#: qml/Shell.qml:398
132+#, qt-format
133+msgid "Enter %1"
134+msgstr ""
135+
136 #: qml/Shell.qml:399
137 #, qt-format
138-msgid "Enter %1"
139-msgstr ""
140-
141-#: qml/Shell.qml:400
142-#, qt-format
143 msgid "Sorry, incorrect %1"
144 msgstr ""
145
146+#: qml/Shell.qml:440
147+msgid "Sorry, incorrect passphrase."
148+msgstr ""
149+
150 #: qml/Shell.qml:441
151-msgid "Sorry, incorrect passphrase."
152+msgid "Sorry, incorrect passcode."
153 msgstr ""
154
155 #: qml/Shell.qml:442
156-msgid "Sorry, incorrect passcode."
157-msgstr ""
158-
159-#: qml/Shell.qml:443
160 msgid "This will be your last attempt."
161 msgstr ""
162
163-#: qml/Shell.qml:445
164+#: qml/Shell.qml:444
165 msgid ""
166 "If passphrase is entered incorrectly, your phone will conduct a factory "
167 "reset and all personal data will be deleted."
168 msgstr ""
169
170-#: qml/Shell.qml:446
171+#: qml/Shell.qml:445
172 msgid ""
173 "If passcode is entered incorrectly, your phone will conduct a factory reset "
174 "and all personal data will be deleted."
175
176=== modified file 'qml/Dash/Dash.qml'
177--- qml/Dash/Dash.qml 2014-12-02 09:25:12 +0000
178+++ qml/Dash/Dash.qml 2014-12-05 10:47:59 +0000
179@@ -31,16 +31,13 @@
180 DashCommunicatorService {
181 objectName: "dashCommunicatorService"
182 onSetCurrentScopeRequested: {
183- if (!isSwipe || !window.active || overviewController.progress != 0 || scopeItem.scope || dashContent.subPageShown) {
184- if (overviewController.progress != 0 && window.active) animate = false;
185+ if (!isSwipe || !window.active || bottomEdgeController.progress != 0 || scopeItem.scope || dashContent.subPageShown) {
186+ if (bottomEdgeController.progress != 0 && window.active) animate = false;
187 dashContent.setCurrentScopeAtIndex(index, animate, isSwipe)
188 // Close dash overview and nested temp scopes in it
189- if (overviewController.progress != 0) {
190- if (window.active) {
191- dashContentCache.scheduleUpdate();
192- }
193- overviewController.enableAnimation = window.active && !scopesOverview.showingNonFavoriteScope;
194- overviewController.progress = 0;
195+ if (bottomEdgeController.progress != 0) {
196+ bottomEdgeController.enableAnimation = window.active && !scopesOverview.showingNonFavoriteScope;
197+ bottomEdgeController.progress = 0;
198 scopesOverview.closeTempScope();
199 }
200 // Close normal temp scopes (e.g. App Store)
201@@ -92,8 +89,8 @@
202 }
203
204 QtObject {
205- id: overviewController
206- objectName: "overviewController"
207+ id: bottomEdgeController
208+ objectName: "bottomEdgeController"
209
210 property alias enableAnimation: progressAnimation.enabled
211 property real progress: 0
212@@ -101,108 +98,40 @@
213 id: progressAnimation
214 UbuntuNumberAnimation { }
215 }
216- }
217
218- ScopesOverview {
219- id: scopesOverview
220- objectName: "scopesOverview"
221- anchors.fill: parent
222- scope: scopes.overviewScope
223- progress: overviewController.progress
224- scopeScale: scopeItem.scope ? 0.4 : (1 - overviewController.progress * 0.6)
225- visible: scopeScale != 1
226- currentIndex: dashContent.currentIndex
227- onDone: {
228- if (currentTab == 1) {
229- animateDashFromAll(dashContent.currentScopeId);
230- }
231- hide();
232- }
233- onFavoriteSelected: {
234- setCurrentScope(scopeId, false, false);
235- dashContentCache.scheduleUpdate();
236- hide();
237- }
238- onAllFavoriteSelected: {
239- setCurrentScope(scopeId, false, false);
240- dashContentCache.scheduleUpdate();
241- animateDashFromAll(dashContent.currentScopeId);
242- hide();
243- }
244- onSearchSelected: {
245- var scopeIndex = -1;
246- for (var i = 0; i < scopes.count; ++i) {
247- if (scopes.getScope(i).id == scopeId) {
248- scopeIndex = i;
249- break;
250- }
251- }
252- if (scopeIndex >= 0) {
253- // Is a favorite one
254- setCurrentScope(scopeId, false, false);
255- dashContentCache.scheduleUpdate();
256- showDashFromPos(pos, size);
257- hide();
258- } else {
259- // Is not a favorite one, activate and get openScope
260- scope.activate(result);
261- }
262- }
263- function hide() {
264- overviewController.enableAnimation = true;
265- overviewController.progress = 0;
266- }
267 onProgressChanged: {
268- if (progress == 0) {
269- currentTab = scopeItem.scope ? 1 : 0;
270+ // FIXME This is to workaround a Qt bug with the model moving the current item
271+ // when the list is ListView.SnapOneItem and ListView.StrictlyEnforceRange
272+ // together with the code in DashContent.qml
273+ if (dashContent.workaroundRestoreIndex != -1) {
274+ dashContent.currentIndex = dashContent.workaroundRestoreIndex;
275+ dashContent.workaroundRestoreIndex = -1;
276 }
277 }
278 }
279
280- ShaderEffectSource {
281- id: dashContentCache
282- parent: scopesOverview.dashItemEater
283- z: 1
284- sourceItem: dashContent
285- height: sourceItem.height
286- width: sourceItem.width
287- opacity: 1 - overviewController.progress
288- visible: overviewController.progress != 0 && scopeItem.scope === null
289- live: false
290- }
291-
292 DashContent {
293 id: dashContent
294
295- property var scopeThatOpenedScope: null
296-
297 objectName: "dashContent"
298 width: dash.width
299 height: dash.height
300 scopes: scopes
301- visible: !scopesOverview.showingNonFavoriteScope && x != -width
302+ visible: x != -width
303 onGotoScope: {
304 dash.setCurrentScope(scopeId, true, false);
305 }
306 onOpenScope: {
307- scopeThatOpenedScope = currentScope;
308+ scopeItem.scopeThatOpenedScope = currentScope;
309 scopeItem.scope = scope;
310- scopesOverview.currentTab = 1;
311- scopesOverview.ensureAllScopeVisible(scope.id);
312 x = -width;
313 }
314- clip: scale != 1.0 || scopeItem.visible || overviewController.progress != 0
315 Behavior on x {
316 UbuntuNumberAnimation {
317- duration: overviewController.progress != 0 ? 0 : UbuntuAnimation.FastDuration
318 onRunningChanged: {
319 if (!running && dashContent.x == 0) {
320- dashContent.scopeThatOpenedScope.closeScope(scopeItem.scope);
321+ scopeItem.scopeThatOpenedScope.closeScope(scopeItem.scope);
322 scopeItem.scope = null;
323- if (overviewController.progress == 0) {
324- // Set tab to Favorites only if we are not showing the overview
325- scopesOverview.currentTab = 0;
326- }
327 }
328 }
329 }
330@@ -214,47 +143,78 @@
331 // about whether that touch was indeed performing a directional drag gesture.
332 forceNonInteractive: overviewDragHandle.status != DirectionalDragArea.WaitingForTouch
333
334- enabled: overviewController.progress == 0
335- opacity: enabled ? 1 : 0
336+ enabled: bottomEdgeController.progress == 0
337+ }
338+
339+ Rectangle {
340+ color: "black"
341+ opacity: bottomEdgeController.progress
342+ anchors.fill: dashContent
343+ }
344+
345+ ScopesList {
346+ id: scopesList
347+ objectName: "scopesList"
348+ width: dash.width
349+ height: dash.height
350+ scope: scopes.overviewScope
351+ y: dash.height * (1 - bottomEdgeController.progress)
352+ visible: bottomEdgeController.progress != 0
353+ onBackClicked: {
354+ bottomEdgeController.enableAnimation = true;
355+ bottomEdgeController.progress = 0;
356+ }
357+ onStoreClicked: {
358+ bottomEdgeController.enableAnimation = true;
359+ bottomEdgeController.progress = 0;
360+ dashContent.currentScope.performQuery("scope://com.canonical.scopes.clickstore");
361+ }
362+ onRequestFavorite: {
363+ scopes.setFavorite(scopeId, favorite);
364+ }
365+ onRequestFavoriteMoveTo: {
366+ scopes.moveFavoriteTo(scopeId, index);
367+ }
368+
369+ Binding {
370+ target: scopesList.scope
371+ property: "isActive"
372+ value: bottomEdgeController.progress === 1
373+ }
374+
375+ Connections {
376+ target: scopesList.scope
377+ onOpenScope: {
378+ bottomEdgeController.enableAnimation = true;
379+ bottomEdgeController.progress = 0;
380+ scopeItem.scopeThatOpenedScope = scopesList.scope;
381+ scopeItem.scope = scope;
382+ dashContent.x = -dashContent.width;
383+ }
384+ onGotoScope: {
385+ bottomEdgeController.enableAnimation = true;
386+ bottomEdgeController.progress = 0;
387+ dashContent.gotoScope(scopeId);
388+ }
389+ }
390 }
391
392 DashBackground
393 {
394 anchors.fill: scopeItem
395 visible: scopeItem.visible
396- parent: scopeItem.parent
397- scale: scopeItem.scale
398- opacity: scopeItem.opacity
399 }
400
401 GenericScopeView {
402 id: scopeItem
403 objectName: "dashTempScopeItem"
404
405- readonly property real targetOverviewScale: {
406- if (scopesOverview.currentTab == 0) {
407- return 0.4;
408- } else {
409- return scopesOverview.allCardSize.width / scopeItem.width;
410- }
411- }
412- readonly property real overviewProgressScale: (1 - overviewController.progress * (1 - targetOverviewScale))
413- readonly property var targetOverviewPosition: scope ? scopesOverview.allScopeCardPosition(scope.id) : null
414- readonly property real overviewProgressX: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ?
415- overviewController.progress * (targetOverviewPosition.x - (width - scopesOverview.allCardSize.width) / 2)
416- : 0
417- readonly property real overviewProgressY: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ?
418- overviewController.progress * (targetOverviewPosition.y - (height - scopesOverview.allCardSize.height) / 2)
419- : 0
420+ property var scopeThatOpenedScope: null
421
422- x: overviewController.progress == 0 ? dashContent.x + width : overviewProgressX
423- y: overviewController.progress == 0 ? dashContent.y : overviewProgressY
424+ x: dashContent.x + width
425+ y: dashContent.y
426 width: parent.width
427 height: parent.height
428- scale: overviewProgressScale
429- enabled: opacity == 1
430- opacity: 1 - overviewController.progress
431- clip: scale != 1.0
432 visible: scope != null
433 hasBackAction: true
434 isCurrent: visible
435@@ -288,7 +248,7 @@
436 opacity: 0
437 visible: opacity > 0
438
439- readonly property bool processing: dashContent.processing || scopeItem.processing || scopesOverview.processing
440+ readonly property bool processing: dashContent.processing || scopeItem.processing || scopesList.processing
441
442 Behavior on opacity {
443 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
444@@ -345,12 +305,17 @@
445 source: "graphics/overview_hint.png"
446 anchors.horizontalCenter: parent.horizontalCenter
447 opacity: (scopeItem.scope ? scopeItem.pageHeaderTotallyVisible : dashContent.pageHeaderTotallyVisible) &&
448- (overviewDragHandle.enabled || overviewController.progress != 0) ? 1 : 0
449+ (overviewDragHandle.enabled || bottomEdgeController.progress != 0) ? 1 : 0
450 Behavior on opacity {
451- enabled: overviewController.progress == 0
452+ enabled: bottomEdgeController.progress == 0
453 UbuntuNumberAnimation {}
454 }
455- y: parent.height - height * (1 - overviewController.progress * 4)
456+ y: parent.height - height * (1 - bottomEdgeController.progress * 4)
457+ MouseArea {
458+ // Eat direct presses on the overview hint so that they do not end up in the card below
459+ anchors.fill: parent
460+ enabled: parent.opacity != 0
461+ }
462 }
463
464 EdgeDragArea {
465@@ -361,22 +326,19 @@
466 enabled: !dashContent.subPageShown &&
467 dashContent.currentScope &&
468 dashContent.currentScope.searchQuery == "" &&
469- !scopeItem.subPageShown &&
470- (overviewController.progress == 0 || dragging)
471+ !scopeItem.scope &&
472+ (bottomEdgeController.progress == 0 || dragging)
473
474- readonly property real fullMovement: units.gu(20)
475+ readonly property real fullMovement: dash.height
476
477 anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
478 height: units.gu(2)
479
480 onSceneDistanceChanged: {
481 if (status == DirectionalDragArea.Recognized && initialSceneDistance != -1) {
482- if (overviewController.enableAnimation) {
483- dashContentCache.scheduleUpdate();
484- }
485- overviewController.enableAnimation = false;
486+ bottomEdgeController.enableAnimation = false;
487 var deltaDistance = sceneDistance - initialSceneDistance;
488- overviewController.progress = Math.max(0, Math.min(1, deltaDistance / fullMovement));
489+ bottomEdgeController.progress = Math.max(0, Math.min(1, deltaDistance / fullMovement));
490 }
491 }
492
493@@ -392,8 +354,8 @@
494 initialSceneDistance = sceneDistance;
495 } else if (status == DirectionalDragArea.WaitingForTouch &&
496 previousStatus == DirectionalDragArea.Recognized) {
497- overviewController.enableAnimation = true;
498- overviewController.progress = (overviewController.progress > 0.7) ? 1 : 0;
499+ bottomEdgeController.enableAnimation = true;
500+ bottomEdgeController.progress = (bottomEdgeController.progress > 0.2) ? 1 : 0;
501 initialSceneDistance = -1;
502 }
503 }
504
505=== modified file 'qml/Dash/DashContent.qml'
506--- qml/Dash/DashContent.qml 2014-10-30 21:43:18 +0000
507+++ qml/Dash/DashContent.qml 2014-12-05 10:47:59 +0000
508@@ -25,7 +25,8 @@
509
510 property bool forceNonInteractive: false
511 property alias scopes: dashContentList.model
512- readonly property alias currentIndex: dashContentList.currentIndex
513+ property alias currentIndex: dashContentList.currentIndex
514+ property int workaroundRestoreIndex: -1
515 readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : ""
516 readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
517 readonly property bool subPageShown: dashContentList.currentItem && dashContentList.currentItem.item ?
518@@ -51,6 +52,15 @@
519 set_current_index = undefined;
520 }
521 }
522+ onRowsMoved: {
523+ // FIXME This is to workaround a Qt bug with the model moving the current item
524+ // when the list is ListView.SnapOneItem and ListView.StrictlyEnforceRange
525+ // together with the code in Dash.qml
526+ if (row == dashContentList.currentIndex || start == dashContentList.currentIndex) {
527+ dashContent.workaroundRestoreIndex = dashContentList.currentIndex;
528+ dashContentList.currentIndex = -1;
529+ }
530+ }
531 }
532
533 Connections {
534
535=== modified file 'qml/Dash/GenericScopeView.qml'
536--- qml/Dash/GenericScopeView.qml 2014-11-06 15:25:51 +0000
537+++ qml/Dash/GenericScopeView.qml 2014-12-05 10:47:59 +0000
538@@ -494,7 +494,7 @@
539 showBackButton: scopeView.hasBackAction
540 searchEntryEnabled: true
541 settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false
542- favoriteEnabled: scopeView.scope && scopeView.scope.id !== "clickscope"
543+ favoriteEnabled: scopeView.scope
544 favorite: scopeView.scope && scopeView.scope.favorite
545 scopeStyle: scopeView.scopeStyle
546 paginationCount: scopeView.paginationCount
547
548=== modified file 'qml/Dash/PageHeader.qml'
549--- qml/Dash/PageHeader.qml 2014-11-07 14:31:39 +0000
550+++ qml/Dash/PageHeader.qml 2014-12-05 10:47:59 +0000
551@@ -28,8 +28,10 @@
552 implicitHeight: headerContainer.height + bottomContainer.height + (showSignatureLine ? units.gu(2) : 0)
553
554 property bool showBackButton: false
555+ property bool backIsClose: false
556 property string title
557
558+ property bool storeEntryEnabled: false
559 property bool searchEntryEnabled: false
560 property bool settingsEnabled: false
561 property bool favoriteEnabled: false
562@@ -46,6 +48,7 @@
563 property var scopeStyle: null
564
565 signal backClicked()
566+ signal storeClicked()
567 signal settingsClicked()
568 signal favoriteClicked()
569
570@@ -246,13 +249,20 @@
571 property var config: PageHeadConfiguration {
572 foregroundColor: root.scopeStyle ? root.scopeStyle.headerForeground : Theme.palette.normal.baseText
573 backAction: Action {
574- iconName: "back"
575+ iconName: backIsClose ? "close" : "back"
576 visible: root.showBackButton
577 onTriggered: root.backClicked()
578 }
579
580 actions: [
581 Action {
582+ objectName: "store"
583+ text: i18n.tr("Store")
584+ iconName: "ubuntu-store-symbolic"
585+ visible: root.storeEntryEnabled
586+ onTriggered: root.storeClicked();
587+ },
588+ Action {
589 objectName: "search"
590 text: i18n.tr("Search")
591 iconName: "search"
592
593=== added file 'qml/Dash/ScopesList.qml'
594--- qml/Dash/ScopesList.qml 1970-01-01 00:00:00 +0000
595+++ qml/Dash/ScopesList.qml 2014-12-05 10:47:59 +0000
596@@ -0,0 +1,127 @@
597+/*
598+ * Copyright (C) 2014 Canonical, Ltd.
599+ *
600+ * This program is free software; you can redistribute it and/or modify
601+ * it under the terms of the GNU General Public License as published by
602+ * the Free Software Foundation; version 3.
603+ *
604+ * This program is distributed in the hope that it will be useful,
605+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
606+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
607+ * GNU General Public License for more details.
608+ *
609+ * You should have received a copy of the GNU General Public License
610+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
611+ */
612+
613+import QtQuick 2.3
614+import Dash 0.1
615+
616+Item {
617+ id: root
618+
619+ // Properties set by parent
620+ property var scope: null
621+
622+ // Properties used by parent
623+ readonly property bool processing: scope ? scope.searchInProgress : false
624+
625+ // Signals
626+ signal backClicked()
627+ signal storeClicked()
628+ signal requestFavorite(string scopeId, bool favorite)
629+ signal requestFavoriteMoveTo(string scopeId, int index)
630+
631+ state: "browse"
632+
633+ onStateChanged: {
634+ if (state == "edit") {
635+ // As per design entering edit mode clears the possible existing search
636+ header.resetSearch(false /* false == unfocus */);
637+ }
638+ }
639+
640+ DashBackground {
641+ anchors.fill: parent
642+ }
643+
644+ Binding {
645+ target: root.scope
646+ property: "searchQuery"
647+ value: header.searchQuery
648+ }
649+
650+ Binding {
651+ target: header
652+ property: "searchQuery"
653+ value: root.scope ? root.scope.searchQuery : ""
654+ }
655+
656+ PageHeader {
657+ id: header
658+ objectName: "pageHeader"
659+ title: i18n.tr("Manage")
660+ width: parent.width
661+ showBackButton: true
662+ backIsClose: root.state == "edit"
663+ storeEntryEnabled: root.state == "browse"
664+ searchEntryEnabled: false // Disable search for now
665+ onBackClicked: {
666+ if (backIsClose) {
667+ root.state = "browse"
668+ } else {
669+ root.backClicked()
670+ }
671+ }
672+ onStoreClicked: root.storeClicked();
673+ z: 1
674+ }
675+
676+ Flickable {
677+ anchors {
678+ top: header.bottom
679+ bottom: parent.bottom
680+ left: parent.left
681+ right: parent.right
682+ }
683+ clip: true
684+ contentWidth: root.width
685+ contentHeight: column.height
686+ onContentHeightChanged: returnToBounds();
687+ Column {
688+ id: column
689+ Repeater {
690+ model: scope ? scope.categories : null
691+
692+ delegate: Loader {
693+ asynchronous: true
694+ width: root.width
695+ active: results.count > 0
696+ visible: active
697+ sourceComponent: ScopesListCategory {
698+ objectName: "scopesListCategory" + categoryId
699+
700+ model: results
701+
702+ title: {
703+ if (isFavoritesFeed) return i18n.tr("Home");
704+ else if (isAlsoInstalled) return i18n.tr("Also installed");
705+ else return name;
706+ }
707+
708+ editMode: root.state == "edit"
709+
710+ scopeStyle: root.scope.scopeStyle
711+ isFavoritesFeed: categoryId == "favorites"
712+ isAlsoInstalled: categoryId == "other"
713+
714+ onRequestFavorite: root.requestFavorite(scopeId, favorite);
715+ onRequestEditMode: root.state = "edit";
716+ onRequestScopeMoveTo: root.requestFavoriteMoveTo(scopeId, index);
717+ onRequestActivate: root.scope.activate(result);
718+ }
719+ }
720+ }
721+ }
722+ }
723+}
724
725=== added file 'qml/Dash/ScopesListCategory.qml'
726--- qml/Dash/ScopesListCategory.qml 1970-01-01 00:00:00 +0000
727+++ qml/Dash/ScopesListCategory.qml 2014-12-05 10:47:59 +0000
728@@ -0,0 +1,176 @@
729+/*
730+ * Copyright (C) 2014 Canonical, Ltd.
731+ *
732+ * This program is free software; you can redistribute it and/or modify
733+ * it under the terms of the GNU General Public License as published by
734+ * the Free Software Foundation; version 3.
735+ *
736+ * This program is distributed in the hope that it will be useful,
737+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
738+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
739+ * GNU General Public License for more details.
740+ *
741+ * You should have received a copy of the GNU General Public License
742+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
743+ */
744+
745+import QtQuick 2.3
746+import Ubuntu.Components 1.1
747+import Dash 0.1
748+import "../Components/ListItems" as ListItems
749+
750+Item {
751+ id: root
752+
753+ property alias model: list.model
754+ property alias title: header.text
755+ property var scopeStyle
756+ property bool editMode: false
757+ property bool isFavoritesFeed: false
758+ property bool isAlsoInstalled: false
759+
760+ visible: !editMode || isFavoritesFeed
761+
762+ signal requestFavorite(string scopeId, bool favorite)
763+ signal requestEditMode()
764+ signal requestScopeMoveTo(string scopeId, int index)
765+ signal requestActivate(var result)
766+
767+ implicitHeight: visible ? childrenRect.height : 0
768+
769+ ListItems.Header {
770+ id: header
771+ width: root.width
772+ height: units.gu(5)
773+ color: scopeStyle ? scopeStyle.foreground : Theme.palette.normal.baseText
774+ }
775+
776+ readonly property double listItemHeight: units.gu(6)
777+
778+ ListView {
779+ id: list
780+ objectName: "scopesListCategoryInnerList"
781+
782+ readonly property double targetHeight: model.count * listItemHeight
783+ clip: height != targetHeight
784+ height: targetHeight
785+ Behavior on height { enabled: visible; UbuntuNumberAnimation { } }
786+ width: parent.width
787+ interactive: false
788+
789+ anchors.top: header.bottom
790+ delegate: Loader {
791+ id: loader
792+ readonly property bool addDropHint: {
793+ if (dragMarker.visible) {
794+ if (dragItem.originalIndex > index) {
795+ return dragMarker.index == index;
796+ } else {
797+ return dragMarker.index == index - 1;
798+ }
799+ } else {
800+ return false;
801+ }
802+ }
803+ asynchronous: true
804+ width: root.width
805+ height: listItemHeight + (addDropHint ? units.gu(2) : 0)
806+ clip: height < listItemHeight
807+ Behavior on height { enabled: visible; UbuntuNumberAnimation { } }
808+ sourceComponent: ScopesListCategoryItem {
809+ objectName: "delegate" + index
810+
811+ width: root.width
812+ topMargin: height > listItemHeight ? height - listItemHeight : 0
813+
814+ icon: model.art || model.mascot || ""
815+ text: model.title || ""
816+ subtext: model.subtitle || ""
817+ showStar: root.isFavoritesFeed || root.isAlsoInstalled
818+ isFavorite: root.isFavoritesFeed
819+
820+ hideChildren: dragItem.loaderToShrink == loader
821+
822+ onClicked: {
823+ if (!editMode) {
824+ root.requestActivate(result);
825+ }
826+ }
827+ onPressAndHold: {
828+ if (!editMode) {
829+ root.requestEditMode();
830+ }
831+ }
832+ onRequestFavorite: root.requestFavorite(model.scopeId, favorite);
833+ onHandlePressed: {
834+ if (editMode) {
835+ handle.drag.target = dragItem;
836+ handle.drag.maximumX = units.gu(1);
837+ handle.drag.minimumX = units.gu(1);
838+ handle.drag.minimumY = list.y - dragItem.height / 2;
839+ handle.drag.maximumY = list.y + list.height - dragItem.height / 2
840+ dragItem.icon = icon;
841+ dragItem.text = text;
842+ dragItem.subtext = subtext;
843+ dragItem.originalY = mapToItem(root, 0, 0).y;
844+ dragItem.originalIndex = index;
845+ dragItem.y = dragItem.originalY;
846+ dragItem.x = units.gu(1);
847+ dragItem.visible = true;
848+ dragItem.loaderToShrink = loader;
849+ }
850+ }
851+ onHandleReleased: {
852+ if (dragItem.visible) {
853+ handle.drag.target = undefined;
854+ dragItem.visible = false;
855+ if (dragMarker.visible && dragMarker.index != index) {
856+ root.requestScopeMoveTo(model.scopeId, dragMarker.index);
857+ }
858+ dragMarker.visible = false;
859+ dragItem.loaderToShrink.height = listItemHeight;
860+ dragItem.loaderToShrink = null;
861+ }
862+ }
863+ }
864+ }
865+ }
866+
867+ ListItems.ThinDivider {
868+ id: dragMarker
869+ visible: false
870+ anchors {
871+ leftMargin: units.gu(1)
872+ rightMargin: units.gu(1)
873+ }
874+ property int index: {
875+ var i = Math.round((dragItem.y - list.y + dragItem.height/2) / listItemHeight);
876+ if (i < 0) i = 0;
877+ if (i >= model.count - 1) i = model.count - 1;
878+ return i;
879+ }
880+ y: list.y + index * listItemHeight + units.gu(1)
881+ }
882+
883+ ScopesListCategoryItem {
884+ id: dragItem
885+
886+ property real originalY
887+ property int originalIndex
888+ property var loaderToShrink: null
889+
890+ objectName: "dragItem"
891+ visible: false
892+ showStar: false
893+ width: root.width
894+ height: listItemHeight
895+ opacity: 0.9
896+
897+ onYChanged: {
898+ if (!dragMarker.visible && Math.abs(y - originalY) > height / 2) {
899+ dragMarker.visible = true;
900+ loaderToShrink.height = 0;
901+ }
902+ }
903+ }
904+}
905
906=== added file 'qml/Dash/ScopesListCategoryItem.qml'
907--- qml/Dash/ScopesListCategoryItem.qml 1970-01-01 00:00:00 +0000
908+++ qml/Dash/ScopesListCategoryItem.qml 2014-12-05 10:47:59 +0000
909@@ -0,0 +1,104 @@
910+/*
911+ * Copyright (C) 2014 Canonical, Ltd.
912+ *
913+ * This program is free software; you can redistribute it and/or modify
914+ * it under the terms of the GNU General Public License as published by
915+ * the Free Software Foundation; version 3.
916+ *
917+ * This program is distributed in the hope that it will be useful,
918+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
920+ * GNU General Public License for more details.
921+ *
922+ * You should have received a copy of the GNU General Public License
923+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
924+ */
925+
926+import QtQuick 2.3
927+import QtQuick.Layouts 1.1
928+import Ubuntu.Components 1.1
929+
930+MouseArea {
931+ id: root
932+
933+ signal requestFavorite(string scopeId, bool favorite)
934+ signal handlePressed(var handle)
935+ signal handleReleased(var handle)
936+
937+ property real topMargin: 0
938+ property alias icon: shapeImage.source
939+ property alias text: titleLabel.text
940+ property alias subtext: subtitleLabel.text
941+ property alias showStar: star.visible
942+
943+ property bool isFavorite: false
944+ property bool hideChildren: false
945+
946+ Item {
947+ id: holder
948+ anchors.fill: parent
949+ anchors.topMargin: root.topMargin
950+
951+ UbuntuShape {
952+ id: shape
953+ anchors {
954+ left: parent.left
955+ leftMargin: units.gu(1)
956+ verticalCenter: parent.verticalCenter
957+ }
958+ width: units.gu(5)
959+ height: units.gu(5)
960+ visible: !hideChildren
961+ image: Image {
962+ id: shapeImage
963+ cache: true
964+ fillMode: Image.PreserveAspectCrop
965+ }
966+ }
967+
968+ ColumnLayout {
969+ visible: !hideChildren
970+ anchors {
971+ left: shape.right
972+ leftMargin: units.gu(1)
973+ right: starArea.right
974+ rightMargin: units.gu(1)
975+ verticalCenter: parent.verticalCenter
976+ }
977+ Label {
978+ id: titleLabel
979+ elide: Text.ElideRight
980+ wrapMode: Text.Wrap
981+ maximumLineCount: 1
982+ verticalAlignment: Text.AlignHCenter
983+ }
984+ Label {
985+ id: subtitleLabel
986+ elide: Text.ElideRight
987+ fontSize: "xx-small"
988+ wrapMode: Text.Wrap
989+ maximumLineCount: 1
990+ verticalAlignment: Text.AlignHCenter
991+ visible: text != ""
992+ }
993+ }
994+ MouseArea {
995+ id: starArea
996+ height: parent.height
997+ width: height
998+ anchors.right: parent.right
999+ onClicked: if (!editMode) root.requestFavorite(model.scopeId, !isFavorite);
1000+ onPressed: if (editMode) root.handlePressed(starArea);
1001+ onReleased: if (editMode) root.handleReleased(starArea);
1002+ Icon {
1003+ id: star
1004+ anchors.centerIn: parent
1005+ height: units.gu(2)
1006+ width: units.gu(2)
1007+ visible: !hideChildren
1008+ // TODO is view-grid-symbolic what we really want here? Looks good but seems semantically wrong
1009+ source: editMode ? "image://theme/view-grid-symbolic" : isFavorite ? "image://theme/starred" : "image://theme/non-starred"
1010+ }
1011+ }
1012+ }
1013+}
1014
1015=== removed file 'qml/Dash/ScopesOverview.qml'
1016--- qml/Dash/ScopesOverview.qml 2014-10-09 14:04:53 +0000
1017+++ qml/Dash/ScopesOverview.qml 1970-01-01 00:00:00 +0000
1018@@ -1,575 +0,0 @@
1019-/*
1020- * Copyright (C) 2014 Canonical, Ltd.
1021- *
1022- * This program is free software; you can redistribute it and/or modify
1023- * it under the terms of the GNU General Public License as published by
1024- * the Free Software Foundation; version 3.
1025- *
1026- * This program is distributed in the hope that it will be useful,
1027- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1028- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1029- * GNU General Public License for more details.
1030- *
1031- * You should have received a copy of the GNU General Public License
1032- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1033- */
1034-
1035-import QtQuick 2.0
1036-import Dash 0.1
1037-import Ubuntu.Components 0.1
1038-import "../Components"
1039-
1040-Item {
1041- id: root
1042-
1043- // Properties set by parent
1044- property real progress: 0
1045- property var scope: null
1046- property int currentIndex: 0
1047- property real scopeScale: 1
1048-
1049- // Properties set and used by parent
1050- property alias currentTab: tabBar.currentTab
1051-
1052- // Properties used by parent
1053- readonly property bool processing: searchResultsViewer.processing || tempScopeItem.processing || previewListView.processing
1054- property bool growingDashFromPos: false
1055- readonly property bool searching: scope && scope.searchQuery == ""
1056- readonly property bool showingNonFavoriteScope: tempScopeItem.scope != null
1057- readonly property var dashItemEater: {
1058- if (!forceXYScalerEater && tabBar.currentTab == 0 && middleItems.count > 0) {
1059- var loaderItem = middleItems.itemAt(0).item;
1060- return loaderItem && loaderItem.currentItem ? loaderItem.currentItem : null;
1061- }
1062- return scopesOverviewXYScaler;
1063- }
1064- readonly property size allCardSize: {
1065- if (middleItems.count > 1) {
1066- var loaderItem = middleItems.itemAt(1).item;
1067- if (loaderItem) {
1068- var cardTool = loaderItem.cardTool;
1069- return Qt.size(cardTool.cardWidth, cardTool.cardHeight);
1070- }
1071- }
1072- return Qt.size(0, 0);
1073- }
1074-
1075- // Internal properties
1076- property bool forceXYScalerEater: false
1077-
1078- signal done()
1079- signal favoriteSelected(var scopeId)
1080- signal allFavoriteSelected(var scopeId)
1081- signal searchSelected(var scopeId, var result, var pos, var size)
1082-
1083- Connections {
1084- target: scope
1085- onOpenScope: {
1086- var itemPos = scopesOverviewXYScaler.restorePosition;
1087- var itemSize = scopesOverviewXYScaler.restoreSize;
1088- scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
1089- if (itemPos) {
1090- scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
1091- scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
1092- } else {
1093- scopesOverviewXYScaler.x = 0;
1094- scopesOverviewXYScaler.y = 0;
1095- }
1096- scopesOverviewXYScaler.opacity = 0;
1097- tempScopeItem.scope = scope;
1098- middleItems.overrideOpacity = 0;
1099- scopesOverviewXYScaler.scale = 1;
1100- scopesOverviewXYScaler.x = 0;
1101- scopesOverviewXYScaler.y = 0;
1102- scopesOverviewXYScaler.opacity = 1;
1103- }
1104- onGotoScope: {
1105- if (tabBar.currentTab == 0) {
1106- root.favoriteSelected(scopeId);
1107- } else {
1108- root.allFavoriteSelected(scopeId);
1109- }
1110- previewListView.open = false;
1111- }
1112- }
1113-
1114- Binding {
1115- target: scope
1116- property: "isActive"
1117- value: progress === 1
1118- }
1119-
1120- function closeTempScope() {
1121- if (tempScopeItem.scope) {
1122- root.scope.closeScope(tempScopeItem.scope);
1123- tempScopeItem.scope = null;
1124- tempScopeItem.backClicked()
1125- }
1126- }
1127-
1128- function animateDashFromAll(scopeId) {
1129- var currentScopePos = allScopeCardPosition(scopeId);
1130- if (currentScopePos) {
1131- showDashFromPos(currentScopePos, allCardSize);
1132- } else {
1133- console.log("Warning: Could not find Dash OverView All card position for scope", dashContent.currentScopeId);
1134- }
1135- }
1136-
1137- function showDashFromPos(itemPos, itemSize) {
1138- scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
1139- scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
1140- scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
1141- scopesOverviewXYScaler.opacity = 0;
1142- root.growingDashFromPos = true;
1143- scopesOverviewXYScaler.scale = 1;
1144- scopesOverviewXYScaler.x = 0;
1145- scopesOverviewXYScaler.y = 0;
1146- scopesOverviewXYScaler.opacity = 1;
1147- }
1148-
1149- function allScopeCardPosition(scopeId) {
1150- if (middleItems.count > 1) {
1151- var loaderItem = middleItems.itemAt(1).item;
1152- if (loaderItem) {
1153- var pos = loaderItem.scopeCardPosition(scopeId);
1154- return loaderItem.mapToItem(null, pos.x, pos.y);
1155- }
1156- }
1157- }
1158-
1159- function ensureAllScopeVisible(scopeId) {
1160- if (middleItems.count > 1) {
1161- var loaderItem = middleItems.itemAt(1).item;
1162- if (loaderItem) {
1163- var pos = loaderItem.scopeCardPosition(scopeId);
1164- loaderItem.contentY = Math.min(pos.y, loaderItem.contentHeight - loaderItem.height);
1165- }
1166- }
1167- }
1168-
1169- onProgressChanged: {
1170- if (progress == 0) {
1171- pageHeader.resetSearch();
1172- pageHeader.unfocus(); // Shouldn't the previous call do this too?
1173- }
1174- }
1175-
1176- ScopeStyle {
1177- id: overviewScopeStyle
1178- style: { "foreground-color" : "white",
1179- "background-color" : "transparent",
1180- "page-header": {
1181- "background": "color:///transparent"
1182- }
1183- }
1184- }
1185-
1186- DashBackground {
1187- anchors.fill: parent
1188- source: "graphics/dark_background.jpg"
1189- }
1190-
1191- Connections {
1192- target: pageHeader
1193- onSearchQueryChanged: {
1194- // Need this in order, otherwise something gets unhappy in rendering
1195- // of the overlay in carousels because the parent of the dash dies for
1196- // a moment, this way we make sure it's reparented first
1197- // by forceXYScalerEater making dashItemEater return scopesOverviewXYScaler
1198- // before we kill the previous parent by scope.searchQuery
1199- root.forceXYScalerEater = true;
1200- root.scope.searchQuery = pageHeader.searchQuery;
1201- root.forceXYScalerEater = false;
1202- }
1203- }
1204-
1205- Binding {
1206- target: pageHeader
1207- property: "searchQuery"
1208- value: scope ? scope.searchQuery : ""
1209- }
1210-
1211- Item {
1212- id: scopesOverviewContent
1213- x: previewListView.open ? -width : 0
1214- Behavior on x { UbuntuNumberAnimation { } }
1215- width: parent.width
1216- height: parent.height
1217-
1218- PageHeader {
1219- id: pageHeader
1220- objectName: "scopesOverviewPageHeader"
1221-
1222- readonly property real yDisplacement: pageHeader.height + tabBar.height + tabBar.anchors.margins
1223-
1224- y: {
1225- if (root.progress < 0.5) {
1226- return -yDisplacement;
1227- } else {
1228- return -yDisplacement + (root.progress - 0.5) * yDisplacement * 2;
1229- }
1230- }
1231- width: parent.width
1232- clip: true
1233- title: i18n.tr("Manage Scopes")
1234- scopeStyle: overviewScopeStyle
1235- showSignatureLine: false
1236- searchEntryEnabled: true
1237- }
1238-
1239- ScopesOverviewTab {
1240- id: tabBar
1241- anchors {
1242- left: parent.left
1243- right: parent.right
1244- top: pageHeader.bottom
1245- margins: units.gu(2)
1246- }
1247- height: units.gu(4)
1248-
1249- enabled: opacity == 1
1250- opacity: !scope || scope.searchQuery == "" ? 1 : 0
1251- Behavior on opacity { UbuntuNumberAnimation { } }
1252- }
1253-
1254- Repeater {
1255- id: middleItems
1256- objectName: "scopesOverviewRepeater"
1257- property real overrideOpacity: -1
1258- model: scope && scope.searchQuery == "" ? scope.categories : null
1259- delegate: Loader {
1260- id: loader
1261- objectName: "scopesOverviewRepeaterChild" + index
1262-
1263- height: {
1264- if (index == 0) {
1265- return root.height;
1266- } else {
1267- return root.height - pageHeader.height - tabBar.height - tabBar.anchors.margins - units.gu(2);
1268- }
1269- }
1270- width: {
1271- if (index == 0) {
1272- return root.width / scopeScale;
1273- } else {
1274- return root.width;
1275- }
1276- }
1277- x: {
1278- if (index == 0) {
1279- return (root.width - width) / 2;
1280- } else {
1281- return 0;
1282- }
1283- }
1284- anchors {
1285- bottom: scopesOverviewContent.bottom
1286- }
1287-
1288- scale: index == 0 ? scopeScale : 1
1289-
1290- opacity: {
1291- if (middleItems.overrideOpacity >= 0)
1292- return middleItems.overrideOpacity;
1293-
1294- if (tabBar.currentTab != index)
1295- return 0;
1296-
1297- return index == 0 ? 1 : root.progress;
1298- }
1299- Behavior on opacity {
1300- enabled: root.progress == 1
1301- UbuntuNumberAnimation { }
1302- }
1303- enabled: opacity == 1
1304-
1305- clip: index == 1
1306-
1307- CardTool {
1308- id: cardTool
1309- objectName: "cardTool"
1310- count: results.count
1311- template: model.renderer
1312- components: model.components
1313- viewWidth: parent.width
1314- }
1315-
1316- source: {
1317- if (index == 0 && categoryId == "favorites") return "ScopesOverviewFavorites.qml";
1318- else if (index == 1 && categoryId == "all") return "ScopesOverviewAll.qml";
1319- else return "";
1320- }
1321-
1322- onLoaded: {
1323- item.model = Qt.binding(function() { return results; });
1324- item.cardTool = cardTool;
1325- if (index == 0) {
1326- item.scopeWidth = Qt.binding(function() { return root.width; });
1327- item.scopeHeight = Qt.binding(function() { return root.height; });
1328- item.appliedScale = Qt.binding(function() { return loader.scale });
1329- item.currentIndex = Qt.binding(function() { return root.currentIndex });
1330- } else if (index == 1) {
1331- item.extraHeight = bottomBar.height;
1332- }
1333- }
1334-
1335- Connections {
1336- target: loader.item
1337- onClicked: {
1338- pageHeader.unfocus();
1339- if (tabBar.currentTab == 0) {
1340- root.favoriteSelected(itemModel.scopeId);
1341- } else {
1342- var favoriteScopesItem = middleItems.itemAt(0).item;
1343- var scopeIndex = favoriteScopesItem.model.scopeIndex(itemModel.scopeId);
1344- if (scopeIndex >= 0) {
1345- root.allFavoriteSelected(itemModel.scopeId);
1346- } else {
1347- // Will result in an openScope from root.scope
1348- scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
1349- scopesOverviewXYScaler.restoreSize = allCardSize;
1350- root.scope.activate(result);
1351- }
1352- }
1353- }
1354- onPressAndHold: {
1355- // Preview can call openScope so make sure restorePosition and restoreSize are set
1356- scopesOverviewXYScaler.restorePosition = undefined;
1357- scopesOverviewXYScaler.restoreSize = allCardSize;
1358-
1359- previewListView.model = target.model;
1360- previewListView.currentIndex = -1;
1361- previewListView.currentIndex = index;
1362- previewListView.open = true;
1363- }
1364- }
1365- }
1366- }
1367-
1368- GenericScopeView {
1369- id: searchResultsViewer
1370- objectName: "searchResultsViewer"
1371- anchors {
1372- top: pageHeader.bottom
1373- right: parent.right
1374- left: parent.left
1375- bottom: parent.bottom
1376- }
1377- scope: root.scope && root.scope.searchQuery != "" ? root.scope : null
1378- scopeStyle: overviewScopeStyle
1379- enabled: opacity == 1
1380- showPageHeader: false
1381- clip: true
1382- opacity: searchResultsViewer.scope ? 1 : 0
1383- isCurrent: true
1384- Behavior on opacity { UbuntuNumberAnimation { } }
1385-
1386- function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) {
1387- pageHeader.unfocus();
1388- pageHeader.closePopup();
1389- if (itemModel.scopeId) {
1390- // This can end up in openScope so save restorePosition and restoreSize
1391- scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
1392- scopesOverviewXYScaler.restoreSize = Qt.size(item.width, item.height);
1393- root.searchSelected(itemModel.scopeId, result, item.mapToItem(null, 0, 0), Qt.size(item.width, item.height));
1394- } else {
1395- // Not a scope, just activate it
1396- searchResultsViewer.scope.activate(result);
1397- }
1398- }
1399-
1400- function itemPressedAndHeld(index, itemModel, resultsModel, limitedCategoryItemCount) {
1401- if (itemModel.uri.indexOf("scope://") === 0) {
1402- // Preview can call openScope so make sure restorePosition and restoreSize are set
1403- scopesOverviewXYScaler.restorePosition = undefined;
1404- scopesOverviewXYScaler.restoreSize = allCardSize;
1405-
1406- previewListView.model = resultsModel;
1407- previewListView.currentIndex = -1;
1408- previewListView.currentIndex = index;
1409- previewListView.open = true;
1410- }
1411- }
1412- }
1413-
1414- Rectangle {
1415- id: bottomBar
1416- objectName: "bottomBar"
1417- color: "black"
1418- height: units.gu(8)
1419- width: parent.width
1420- enabled: opacity == 1
1421- opacity: scope && scope.searchQuery == "" ? 1 : 0
1422- Behavior on opacity { UbuntuNumberAnimation { } }
1423- y: {
1424- if (root.progress < 0.5) {
1425- return parent.height;
1426- } else {
1427- return parent.height - (root.progress - 0.5) * height * 2;
1428- }
1429- }
1430-
1431- MouseArea {
1432- // Just eat any other press since this parent is black opaque
1433- anchors.fill: parent
1434- }
1435-
1436- AbstractButton {
1437- objectName: "scopesOverviewDoneButton"
1438- width: Math.max(label.width + units.gu(2), units.gu(10))
1439- height: units.gu(4)
1440- anchors {
1441- left: parent.left
1442- leftMargin: units.gu(2)
1443- verticalCenter: parent.verticalCenter
1444- }
1445- Rectangle {
1446- anchors.fill: parent
1447- border.color: "white"
1448- border.width: units.dp(1)
1449- radius: units.dp(10)
1450- color: parent.pressed ? Theme.palette.normal.baseText : "transparent"
1451- }
1452- Label {
1453- id: label
1454- anchors.centerIn: parent
1455- text: i18n.tr("Done")
1456- color: parent.pressed ? "black" : "white"
1457- }
1458- onClicked: root.done();
1459- }
1460-
1461- AbstractButton {
1462- objectName: "scopesOverviewStoreButton"
1463- width: Math.max(storeLabel.width, units.gu(10))
1464- height: units.gu(4)
1465- anchors {
1466- right: parent.right
1467- verticalCenter: parent.verticalCenter
1468- }
1469- Icon {
1470- id: storeImage
1471- name: "ubuntu-store-symbolic"
1472- color: "white"
1473- anchors.horizontalCenter: parent.horizontalCenter
1474- width: units.gu(2)
1475- height: units.gu(2)
1476- }
1477- Label {
1478- id: storeLabel
1479- anchors.horizontalCenter: parent.horizontalCenter
1480- anchors.top: storeImage.bottom
1481- text: i18n.tr("Store")
1482- color: "white"
1483- }
1484- onClicked: {
1485- // Just zoom from the middle
1486- scopesOverviewXYScaler.restorePosition = undefined;
1487- scopesOverviewXYScaler.restoreSize = allCardSize;
1488- scope.performQuery("scope://com.canonical.scopes.clickstore");
1489- }
1490- }
1491- }
1492- }
1493-
1494- PreviewListView {
1495- id: previewListView
1496- objectName: "scopesOverviewPreviewListView"
1497- scope: root.scope
1498- scopeStyle: overviewScopeStyle
1499- showSignatureLine: false
1500- visible: x != width
1501- width: parent.width
1502- height: parent.height
1503- anchors.left: scopesOverviewContent.right
1504-
1505- onBackClicked: open = false
1506- }
1507-
1508- Item {
1509- id: scopesOverviewXYScaler
1510- width: parent.width
1511- height: parent.height
1512-
1513- clip: scale != 1.0
1514- enabled: scale == 1
1515-
1516- property bool animationsEnabled: root.showingNonFavoriteScope || root.growingDashFromPos
1517-
1518- property var restorePosition
1519- property var restoreSize
1520-
1521- Behavior on x {
1522- enabled: scopesOverviewXYScaler.animationsEnabled
1523- UbuntuNumberAnimation { }
1524- }
1525- Behavior on y {
1526- enabled: scopesOverviewXYScaler.animationsEnabled
1527- UbuntuNumberAnimation { }
1528- }
1529- Behavior on opacity {
1530- enabled: scopesOverviewXYScaler.animationsEnabled
1531- UbuntuNumberAnimation { }
1532- }
1533- Behavior on scale {
1534- enabled: scopesOverviewXYScaler.animationsEnabled
1535- UbuntuNumberAnimation {
1536- onRunningChanged: {
1537- if (!running) {
1538- if (root.showingNonFavoriteScope && scopesOverviewXYScaler.scale != 1) {
1539- root.scope.closeScope(tempScopeItem.scope);
1540- tempScopeItem.scope = null;
1541- } else if (root.growingDashFromPos) {
1542- root.growingDashFromPos = false;
1543- }
1544- }
1545- }
1546- }
1547- }
1548-
1549- DashBackground {
1550- anchors.fill: tempScopeItem
1551- visible: tempScopeItem.visible
1552- parent: tempScopeItem.parent
1553- }
1554-
1555- GenericScopeView {
1556- id: tempScopeItem
1557- objectName: "scopesOverviewTempScopeItem"
1558-
1559- width: parent.width
1560- height: parent.height
1561- clip: scale != 1.0
1562- visible: scope != null
1563- hasBackAction: true
1564- isCurrent: visible
1565- onBackClicked: {
1566- var v = scopesOverviewXYScaler.restoreSize.width / tempScopeItem.width;
1567- scopesOverviewXYScaler.scale = v;
1568- if (scopesOverviewXYScaler.restorePosition) {
1569- scopesOverviewXYScaler.x = scopesOverviewXYScaler.restorePosition.x -(tempScopeItem.width - tempScopeItem.width * v) / 2;
1570- scopesOverviewXYScaler.y = scopesOverviewXYScaler.restorePosition.y -(tempScopeItem.height - tempScopeItem.height * v) / 2;
1571- } else {
1572- scopesOverviewXYScaler.x = 0;
1573- scopesOverviewXYScaler.y = 0;
1574- }
1575- scopesOverviewXYScaler.opacity = 0;
1576- middleItems.overrideOpacity = -1;
1577- }
1578- // TODO Add tests for these connections
1579- Connections {
1580- target: tempScopeItem.scope
1581- onOpenScope: {
1582- // TODO Animate the newly opened scope into the foreground (stacked on top of the current scope)
1583- tempScopeItem.scope = scope;
1584- }
1585- onGotoScope: {
1586- tempScopeItem.backClicked();
1587- root.currentTab = 0;
1588- root.scope.gotoScope(scopeId);
1589- }
1590- }
1591- }
1592- }
1593-}
1594
1595=== removed file 'qml/Dash/ScopesOverviewAll.qml'
1596--- qml/Dash/ScopesOverviewAll.qml 2014-11-05 08:37:55 +0000
1597+++ qml/Dash/ScopesOverviewAll.qml 1970-01-01 00:00:00 +0000
1598@@ -1,54 +0,0 @@
1599-/*
1600- * Copyright (C) 2014 Canonical, Ltd.
1601- *
1602- * This program is free software; you can redistribute it and/or modify
1603- * it under the terms of the GNU General Public License as published by
1604- * the Free Software Foundation; version 3.
1605- *
1606- * This program is distributed in the hope that it will be useful,
1607- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1608- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1609- * GNU General Public License for more details.
1610- *
1611- * You should have received a copy of the GNU General Public License
1612- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1613- */
1614-
1615-import QtQuick 2.0
1616-import Ubuntu.Components 0.1
1617-
1618-Flickable {
1619- id: root
1620-
1621- property alias model: cardGrid.model
1622- property alias cardTool: cardGrid.cardTool
1623-
1624- property real extraHeight: 0
1625-
1626- signal clicked(int index, var result, var item, var itemModel)
1627- signal pressAndHold(int index)
1628-
1629- contentHeight: cardGrid.expandedHeight + extraHeight
1630- contentWidth: cardGrid.width
1631- flickableDirection: Flickable.VerticalFlick
1632-
1633- function scopeCardPosition(scopeId) {
1634- var index = model.scopeIndex(scopeId);
1635- var pos = cardGrid.cardPosition(index);
1636- pos.y = pos.y - root.contentY;
1637- return pos;
1638- }
1639-
1640- CardGrid {
1641- id: cardGrid
1642- width: root.width
1643- height: parent.height
1644-
1645- onClicked: {
1646- root.clicked(index, result, item, itemModel);
1647- }
1648- onPressAndHold: {
1649- root.pressAndHold(index);
1650- }
1651- }
1652-}
1653
1654=== removed file 'qml/Dash/ScopesOverviewFavorites.qml'
1655--- qml/Dash/ScopesOverviewFavorites.qml 2014-10-23 11:59:22 +0000
1656+++ qml/Dash/ScopesOverviewFavorites.qml 1970-01-01 00:00:00 +0000
1657@@ -1,73 +0,0 @@
1658-/*
1659- * Copyright (C) 2014 Canonical, Ltd.
1660- *
1661- * This program is free software; you can redistribute it and/or modify
1662- * it under the terms of the GNU General Public License as published by
1663- * the Free Software Foundation; version 3.
1664- *
1665- * This program is distributed in the hope that it will be useful,
1666- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1667- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1668- * GNU General Public License for more details.
1669- *
1670- * You should have received a copy of the GNU General Public License
1671- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1672- */
1673-
1674-import QtQuick 2.0
1675-
1676-Flickable {
1677- id: root
1678-
1679- signal clicked(int index, var result, var itemModel)
1680- signal pressAndHold(int index)
1681-
1682- property var cardTool: null
1683- property real scopeHeight: 0
1684- property real scopeWidth: 0
1685- property real appliedScale: 1
1686- property int currentIndex: -1
1687- property var currentItem: currentIndex < repeater.count ? repeater.itemAt(currentIndex) : null
1688-
1689- property alias model: repeater.model
1690-
1691- contentHeight: height
1692- contentWidth: repeater.count * root.scopeWidth + units.gu(2) / appliedScale * (repeater.count - 1)
1693-
1694- contentX: {
1695- var indexX = currentIndex * scopeWidth + units.gu(2) / appliedScale * currentIndex;
1696- var newContentX = indexX - (width - scopeWidth) / 2;
1697- newContentX = Math.min(Math.max(newContentX, 0), contentWidth - width);
1698- return newContentX;
1699- }
1700-
1701- Repeater {
1702- id: repeater
1703- objectName: "scopesOverviewFavoritesRepeater"
1704-
1705- delegate: Loader {
1706- id: loader
1707-
1708- x: index * root.scopeWidth + units.gu(2) / appliedScale * index
1709- asynchronous: true
1710-
1711- sourceComponent: cardTool.cardComponent
1712- onLoaded: {
1713- item.fixedArtShapeSize = Qt.binding(function() { return Qt.size(root.scopeWidth, root.scopeHeight); });
1714- item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight / appliedScale; });
1715- item.fontScale = Qt.binding(function() { return 1 / appliedScale; });
1716- item.height = Qt.binding(function() { return root.scopeHeight; });
1717- item.width = Qt.binding(function() { return root.scopeWidth; });
1718- item.cardData = Qt.binding(function() { return model; });
1719- item.template = Qt.binding(function() { return cardTool.template; });
1720- item.components = Qt.binding(function() { return cardTool.components; });
1721- item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
1722- }
1723-
1724- Connections {
1725- target: loader.item
1726- onClicked: root.clicked(index, result, model)
1727- }
1728- }
1729- }
1730-}
1731
1732=== removed file 'qml/Dash/ScopesOverviewTab.qml'
1733--- qml/Dash/ScopesOverviewTab.qml 2014-07-21 11:10:06 +0000
1734+++ qml/Dash/ScopesOverviewTab.qml 1970-01-01 00:00:00 +0000
1735@@ -1,74 +0,0 @@
1736-/*
1737- * Copyright (C) 2014 Canonical, Ltd.
1738- *
1739- * This program is free software; you can redistribute it and/or modify
1740- * it under the terms of the GNU General Public License as published by
1741- * the Free Software Foundation; version 3.
1742- *
1743- * This program is distributed in the hope that it will be useful,
1744- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1745- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1746- * GNU General Public License for more details.
1747- *
1748- * You should have received a copy of the GNU General Public License
1749- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1750- */
1751-
1752-import QtQuick 2.3
1753-import Ubuntu.Components 0.1
1754-
1755-Item {
1756- id: root
1757-
1758- property int currentTab: 0
1759-
1760- AbstractButton {
1761- id: tab1
1762- height: parent.height
1763- width: parent.width / 2
1764- Rectangle {
1765- anchors.fill: parent
1766- color: root.currentTab == 0 && root.enabled ? "white" : "transparent"
1767- radius: units.dp(10)
1768- }
1769- Label {
1770- anchors.centerIn: parent
1771- text: i18n.tr("Favorites")
1772- color: root.currentTab == 0 && root.enabled ? "black" : "white"
1773- }
1774- onClicked: root.currentTab = 0
1775- }
1776- AbstractButton {
1777- id: tab2
1778- objectName: "scopesOverviewAllTabButton"
1779- x: width
1780- height: parent.height
1781- width: parent.width / 2
1782- Rectangle {
1783- anchors.fill: parent
1784- color: root.currentTab == 1 && root.enabled ? "white" : "transparent"
1785- radius: units.dp(10)
1786- }
1787- Label {
1788- anchors.centerIn: parent
1789- text: i18n.tr("All")
1790- color: root.currentTab == 1 && root.enabled ? "black" : "white"
1791- }
1792- onClicked: root.currentTab = 1
1793- }
1794- Rectangle {
1795- id: centerPiece
1796- width: root.enabled ? units.dp(10) : units.dp(1)
1797- height: parent.height
1798- color: "white"
1799- x: root.currentTab == 1 ? tab2.x : tab2.x - width
1800- }
1801- Rectangle {
1802- id: border
1803- anchors.fill: parent
1804- radius: units.dp(10)
1805- color: "transparent"
1806- border.color: centerPiece.color
1807- border.width: units.dp(1)
1808- }
1809-}
1810
1811=== modified file 'tests/mocks/Unity/CMakeLists.txt'
1812--- tests/mocks/Unity/CMakeLists.txt 2014-10-28 12:29:43 +0000
1813+++ tests/mocks/Unity/CMakeLists.txt 2014-12-05 10:47:59 +0000
1814@@ -6,7 +6,7 @@
1815 add_subdirectory(DashCommunicator)
1816
1817 pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
1818-pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=4)
1819+pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=5)
1820
1821 include_directories(
1822 ${CMAKE_CURRENT_BINARY_DIR}
1823
1824=== modified file 'tests/mocks/Unity/fake_scopes.cpp'
1825--- tests/mocks/Unity/fake_scopes.cpp 2014-09-16 04:44:37 +0000
1826+++ tests/mocks/Unity/fake_scopes.cpp 2014-12-05 10:47:59 +0000
1827@@ -165,14 +165,68 @@
1828 return m_scopesOverview;
1829 }
1830
1831-QList<Scope*> Scopes::scopes() const
1832+void Scopes::setFavorite(const QString& scopeId, bool favorite)
1833+{
1834+ if (favorite) {
1835+ for (Scope *scope : m_scopes) {
1836+ // Check it's not already there
1837+ Q_ASSERT(scope->id() != scopeId);
1838+ }
1839+ for (Scope *scope : m_allScopes) {
1840+ if (scope->id() == scopeId) {
1841+ const int index = rowCount();
1842+ beginInsertRows(QModelIndex(), index, index);
1843+ m_scopes << scope;
1844+ endInsertRows();
1845+ m_scopesOverview->setFavorite(scope, true);
1846+ return;
1847+ }
1848+ }
1849+ Q_ASSERT(false && "Unknown scopeId");
1850+ } else {
1851+ for (Scope *scope : m_scopes) {
1852+ if (scope->id() == scopeId) {
1853+ const int index = m_scopes.indexOf(scope);
1854+ beginRemoveRows(QModelIndex(), index, index);
1855+ m_scopes.removeAt(index);
1856+ endRemoveRows();
1857+ m_scopesOverview->setFavorite(scope, false);
1858+ return;
1859+ }
1860+ }
1861+ Q_ASSERT(false && "Unknown scopeId");
1862+ }
1863+}
1864+
1865+void Scopes::moveFavoriteTo(const QString& scopeId, int to)
1866+{
1867+ int from = -1;
1868+ for (int i = 0; i < m_scopes.count(); ++i) {
1869+ if (m_scopes[i]->id() == scopeId) {
1870+ from = i;
1871+ break;
1872+ }
1873+ }
1874+ Q_ASSERT(from != -1);
1875+ beginMoveRows(QModelIndex(), from, from, QModelIndex(), to + (to > from ? 1 : 0));
1876+ m_scopes.move(from, to);
1877+ endMoveRows();
1878+ m_scopesOverview->moveFavoriteTo(m_scopes[to], to);
1879+}
1880+
1881+QList<Scope*> Scopes::favScopes() const
1882 {
1883 return m_scopes;
1884 }
1885
1886-QList<Scope*> Scopes::allScopes() const
1887+QList<Scope*> Scopes::nonFavScopes() const
1888 {
1889- return m_allScopes;
1890+ QList<Scope*> res;
1891+ for (Scope *scope : m_allScopes) {
1892+ if (!m_scopes.contains(scope))
1893+ res << scope;
1894+ }
1895+ return res;
1896 }
1897
1898 void Scopes::addScope(Scope* scope)
1899
1900=== modified file 'tests/mocks/Unity/fake_scopes.h'
1901--- tests/mocks/Unity/fake_scopes.h 2014-08-25 14:13:24 +0000
1902+++ tests/mocks/Unity/fake_scopes.h 2014-12-05 10:47:59 +0000
1903@@ -28,6 +28,8 @@
1904 #include <QList>
1905 #include <QTimer>
1906
1907+class ScopesOverview;
1908+
1909 class Scopes : public unity::shell::scopes::ScopesInterface
1910 {
1911 Q_OBJECT
1912@@ -53,9 +55,12 @@
1913 int count() const override;
1914 unity::shell::scopes::ScopeInterface* overviewScope() const override;
1915
1916+ Q_INVOKABLE void setFavorite(const QString& scopeId, bool favorite) override;
1917+ Q_INVOKABLE void moveFavoriteTo(const QString& scopeId, int index) override;
1918+
1919 // This is used as part of implementation of the other C++ code, not API
1920- QList<Scope*> scopes() const;
1921- QList<Scope*> allScopes() const;
1922+ QList<Scope*> favScopes() const;
1923+ QList<Scope*> nonFavScopes() const;
1924 Q_INVOKABLE Scope* getScopeFromAll(const QString& scope_id) const;
1925
1926 private Q_SLOTS:
1927@@ -64,7 +69,7 @@
1928 private:
1929 QList<Scope*> m_scopes; // the favorite ones
1930 QList<Scope*> m_allScopes;
1931- Scope *m_scopesOverview;
1932+ ScopesOverview *m_scopesOverview;
1933 bool m_loaded;
1934 QTimer timer;
1935 };
1936
1937=== modified file 'tests/mocks/Unity/fake_scopesoverview.cpp'
1938--- tests/mocks/Unity/fake_scopesoverview.cpp 2014-08-13 23:26:36 +0000
1939+++ tests/mocks/Unity/fake_scopesoverview.cpp 2014-12-05 10:47:59 +0000
1940@@ -44,8 +44,22 @@
1941 Q_INVOKABLE void ScopesOverview::activate(QVariant const& result)
1942 {
1943 Scopes *scopes = dynamic_cast<Scopes*>(parent());
1944- m_openScope = scopes->getScopeFromAll(result.toString());
1945- Q_EMIT openScope(m_openScope);
1946+ if (scopes->getScope(result.toString())) {
1947+ Q_EMIT gotoScope(result.toString());
1948+ } else {
1949+ m_openScope = scopes->getScopeFromAll(result.toString());
1950+ Q_EMIT openScope(m_openScope);
1951+ }
1952+}
1953+
1954+void ScopesOverview::setFavorite(Scope *scope, bool favorite)
1955+{
1956+ m_scopesOverviewCategories->setFavorite(scope, favorite);
1957+}
1958+
1959+void ScopesOverview::moveFavoriteTo(Scope *scope, int index)
1960+{
1961+ m_scopesOverviewCategories->moveFavoriteTo(scope, index);
1962 }
1963
1964 ScopesOverviewCategories::ScopesOverviewCategories(Scopes *scopes, QObject* parent)
1965@@ -69,19 +83,41 @@
1966 qFatal("Using un-implemented ScopesOverviewCategories::overrideCategoryJson");
1967 }
1968
1969-QVariant
1970-ScopesOverviewCategories::data(const QModelIndex& index, int role) const
1971+void ScopesOverviewCategories::setFavorite(Scope *scope, bool favorite)
1972+{
1973+ if (m_resultsModels.value(0)) {
1974+ if (favorite) {
1975+ m_resultsModels[0]->appendScope(scope);
1976+ } else {
1977+ m_resultsModels[0]->removeScope(scope);
1978+ }
1979+ }
1980+ if (m_resultsModels.value(1)) {
1981+ if (favorite) {
1982+ m_resultsModels[1]->removeScope(scope);
1983+ } else {
1984+ m_resultsModels[1]->appendScope(scope);
1985+ }
1986+ }
1987+}
1988+
1989+void ScopesOverviewCategories::moveFavoriteTo(Scope *scope, int index)
1990+{
1991+ m_resultsModels[0]->moveScopeTo(scope, index);
1992+}
1993+
1994+QVariant ScopesOverviewCategories::data(const QModelIndex& index, int role) const
1995 {
1996 if (!index.isValid()) {
1997 return QVariant();
1998 }
1999
2000- const QString categoryId = index.row() == 0 ? "favorites" : "all";
2001+ const QString categoryId = index.row() == 0 ? "favorites" : "other";
2002
2003- unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()];
2004+ ScopesOverviewResultsModel *resultsModel = m_resultsModels[index.row()];
2005 if (!resultsModel) {
2006 QObject *that = const_cast<ScopesOverviewCategories*>(this);
2007- QList<Scope*> scopes = index.row() == 0 ? m_scopes->scopes() : m_scopes->allScopes();
2008+ QList<Scope*> scopes = index.row() == 0 ? m_scopes->favScopes() : m_scopes->nonFavScopes();
2009 resultsModel = new ScopesOverviewResultsModel(scopes, categoryId, that);
2010 m_resultsModels[index.row()] = resultsModel;
2011 }
2012@@ -89,7 +125,7 @@
2013 case RoleCategoryId:
2014 return categoryId;
2015 case RoleName:
2016- return index.row() == 0 ? "Favorites" : "All";
2017+ return index.row() == 0 ? "Favorites" : "Non Favorites";
2018 case RoleIcon:
2019 return QVariant();
2020 case RoleRawRendererTemplate:
2021@@ -157,7 +193,7 @@
2022
2023 const QString categoryId = index.row() == 0 ? "searchA" : "searchB";
2024
2025- unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()];
2026+ ScopesOverviewResultsModel *resultsModel = m_resultsModels[index.row()];
2027 if (!resultsModel) {
2028 QObject *that = const_cast<ScopesOverviewSearchCategories*>(this);
2029 QList<Scope *> scopes;
2030@@ -256,8 +292,7 @@
2031 return rowCount();
2032 }
2033
2034-QVariant
2035-ScopesOverviewResultsModel::data(const QModelIndex& index, int role) const
2036+QVariant ScopesOverviewResultsModel::data(const QModelIndex& index, int role) const
2037 {
2038 unity::shell::scopes::ScopeInterface *scope = m_scopes[index.row()];
2039 switch (role) {
2040@@ -269,6 +304,8 @@
2041 return scope ? scope->id() : QString("Result.%1.%2").arg(categoryId()).arg(index.row());
2042 case RoleTitle:
2043 return scope ? scope->name() : QString("Title.%1.%2").arg(categoryId()).arg(index.row());
2044+ case RoleSubtitle:
2045+ return scope && scope->name() == "Videos" ? "tube, movies, cinema" : QString();
2046 case RoleArt:
2047 return qmlDirectory() + "graphics/applicationIcons/dash.png";
2048 case RoleMascot:
2049@@ -281,3 +318,32 @@
2050 return QVariant();
2051 }
2052 }
2053+
2054+void ScopesOverviewResultsModel::appendScope(Scope *scope)
2055+{
2056+ Q_ASSERT(!m_scopes.contains(scope));
2057+ const int index = rowCount();
2058+ beginInsertRows(QModelIndex(), index, index);
2059+ m_scopes << scope;
2060+ endInsertRows();
2061+ Q_EMIT countChanged();
2062+}
2063+
2064+void ScopesOverviewResultsModel::removeScope(Scope *scope)
2065+{
2066+ const int index = m_scopes.indexOf(scope);
2067+ Q_ASSERT(index != -1);
2068+ beginRemoveRows(QModelIndex(), index, index);
2069+ m_scopes.removeAt(index);
2070+ endRemoveRows();
2071+ Q_EMIT countChanged();
2072+}
2073+
2074+void ScopesOverviewResultsModel::moveScopeTo(Scope *scope, int to)
2075+{
2076+ const int from = m_scopes.indexOf(scope);
2077+ Q_ASSERT(from!= -1);
2078+ beginMoveRows(QModelIndex(), from, from, QModelIndex(), to + (to > from ? 1 : 0));
2079+ m_scopes.move(from, to);
2080+ endMoveRows();
2081+}
2082
2083=== modified file 'tests/mocks/Unity/fake_scopesoverview.h'
2084--- tests/mocks/Unity/fake_scopesoverview.h 2014-08-07 08:52:59 +0000
2085+++ tests/mocks/Unity/fake_scopesoverview.h 2014-12-05 10:47:59 +0000
2086@@ -21,6 +21,8 @@
2087 #include <unity/shell/scopes/ResultsModelInterface.h>
2088
2089 class Scopes;
2090+class ScopesOverviewCategories;
2091+class ScopesOverviewResultsModel;
2092
2093 class ScopesOverview : public Scope
2094 {
2095@@ -32,8 +34,12 @@
2096 void setSearchQuery(const QString& search_query) override;
2097 Q_INVOKABLE void activate(QVariant const& result) override;
2098
2099+ // This is implementation detail
2100+ void setFavorite(Scope *scope, bool favorite);
2101+ void moveFavoriteTo(Scope *scope, int index);
2102+
2103 private:
2104- unity::shell::scopes::CategoriesInterface *m_scopesOverviewCategories;
2105+ ScopesOverviewCategories *m_scopesOverviewCategories;
2106 unity::shell::scopes::CategoriesInterface *m_searchCategories;
2107 };
2108
2109@@ -50,8 +56,12 @@
2110 Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override;
2111 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
2112
2113+ // This is implementation detail
2114+ void setFavorite(Scope *scope, bool favorite);
2115+ void moveFavoriteTo(Scope *scope, int index);
2116+
2117 private:
2118- mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels;
2119+ mutable QHash<int, ScopesOverviewResultsModel*> m_resultsModels;
2120
2121 Scopes *m_scopes;
2122 };
2123@@ -70,7 +80,7 @@
2124 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
2125
2126 private:
2127- mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels;
2128+ mutable QHash<int, ScopesOverviewResultsModel*> m_resultsModels;
2129
2130 Scopes *m_scopes;
2131 };
2132@@ -96,6 +106,11 @@
2133 Q_INVOKABLE int scopeIndex(QString const& id) const;
2134 QHash<int, QByteArray> roleNames() const override;
2135
2136+ // This is implementation detail
2137+ void appendScope(Scope *scope);
2138+ void removeScope(Scope *scope);
2139+ void moveScopeTo(Scope *scope, int index);
2140+
2141 private:
2142 QList<Scope *> m_scopes;
2143 QString m_categoryId;
2144
2145=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
2146--- tests/qmltests/Dash/tst_Dash.qml 2014-12-02 09:25:01 +0000
2147+++ tests/qmltests/Dash/tst_Dash.qml 2014-12-05 10:47:59 +0000
2148@@ -79,175 +79,108 @@
2149 return get_scope_data()
2150 }
2151
2152- function test_dash_overview_show_select_same_favorite() {
2153- // Show the overview
2154- touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
2155- var overviewController = findInvisibleChild(dash, "overviewController");
2156- tryCompare(overviewController, "progress", 1);
2157-
2158- // Make sure tab is where it should
2159- var scopesOverview = findChild(dash, "scopesOverview");
2160- compare(scopesOverview.currentTab, 0);
2161+ function test_manage_dash_select_same_favorite() {
2162+ // Show the manage dash
2163+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
2164+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
2165+ tryCompare(bottomEdgeController, "progress", 1);
2166
2167 // Make sure stuff is loaded
2168- var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater");
2169- tryCompare(scopesOverviewFavoritesRepeater, "count", 6);
2170- tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true);
2171- waitForRendering(scopesOverviewFavoritesRepeater.itemAt(0).item);
2172+ var favScopesListCategory = findChild(dash, "scopesListCategoryfavorites");
2173+ var favScopesListCategoryList = findChild(favScopesListCategory, "scopesListCategoryInnerList");
2174+ tryCompare(favScopesListCategoryList, "currentIndex", 0);
2175
2176 // Click in first item
2177- mouseClick(scopesOverviewFavoritesRepeater.itemAt(0).item, 0, 0);
2178+ mouseClick(favScopesListCategoryList.currentItem, 0, 0);
2179
2180 // Make sure animation went back
2181- tryCompare(overviewController, "progress", 0);
2182+ tryCompare(bottomEdgeController, "progress", 0);
2183
2184 var dashContentList = findChild(dash, "dashContentList");
2185 compare(dashContentList.currentIndex, 0);
2186 }
2187
2188- function test_dash_overview_show_select_different_favorite() {
2189- // Show the overview
2190- touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
2191- var overviewController = findInvisibleChild(dash, "overviewController");
2192- tryCompare(overviewController, "progress", 1);
2193-
2194- // Make sure tab is where it should
2195- var scopesOverview = findChild(dash, "scopesOverview");
2196- compare(scopesOverview.currentTab, 0);
2197+ function test_manage_dash_select_different_favorite() {
2198+ // Show the manage dash
2199+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
2200+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
2201+ tryCompare(bottomEdgeController, "progress", 1);
2202
2203 // Make sure stuff is loaded
2204- var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater");
2205- tryCompare(scopesOverviewFavoritesRepeater, "count", 6);
2206- tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true);
2207- waitForRendering(scopesOverviewFavoritesRepeater.itemAt(1).item);
2208+ var favScopesListCategory = findChild(dash, "scopesListCategoryfavorites");
2209+ var favScopesListCategoryList = findChild(favScopesListCategory, "scopesListCategoryInnerList");
2210+ tryCompare(favScopesListCategoryList, "currentIndex", 0);
2211
2212- // Click in first item
2213- mouseClick(scopesOverviewFavoritesRepeater.itemAt(1).item, 0, 0);
2214+ // Click in second item
2215+ favScopesListCategoryList.currentIndex = 1;
2216+ mouseClick(favScopesListCategoryList.currentItem, 0, 0);
2217
2218 // Make sure animation went back
2219- tryCompare(overviewController, "progress", 0);
2220+ tryCompare(bottomEdgeController, "progress", 0);
2221 var dashContentList = findChild(dash, "dashContentList");
2222 compare(dashContentList.currentIndex, 1);
2223 }
2224
2225- function test_dash_overview_all_temp_scope_done_from_all() {
2226- // Show the overview
2227- touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
2228- var overviewController = findInvisibleChild(dash, "overviewController");
2229- tryCompare(overviewController, "progress", 1);
2230-
2231- // Make sure tab is where it should
2232- var scopesOverview = findChild(dash, "scopesOverview");
2233- compare(scopesOverview.currentTab, 0);
2234+ function test_manage_dash_select_non_favorite() {
2235+ // Show the manage dash
2236+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
2237+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
2238+ tryCompare(bottomEdgeController, "progress", 1);
2239
2240 // Make sure stuff is loaded
2241- var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater");
2242- tryCompare(scopesOverviewFavoritesRepeater, "count", 6);
2243- tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true);
2244- waitForRendering(scopesOverviewFavoritesRepeater.itemAt(1).item);
2245-
2246- // Click on the all tab
2247- var scopesOverviewAllTabButton = findChild(dash, "scopesOverviewAllTabButton");
2248- mouseClick(scopesOverviewAllTabButton, 0, 0);
2249-
2250- // Wait for all tab to be enabled (animation finish)
2251- var scopesOverviewAllView = findChild(dash, "scopesOverviewRepeaterChild1");
2252- tryCompare(scopesOverviewAllView, "enabled", true);
2253-
2254- // Click in the middle of the black bar (nothing happens)
2255- var bottomBar = findChild(scopesOverview, "bottomBar");
2256- mouseClick(bottomBar, bottomBar.width / 2, bottomBar.height / 2);
2257- // Check temp scope is not there
2258- var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
2259- expectFailContinue("", "Clicking in the middle of bottom bar should not open a temp scope");
2260- tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
2261-
2262- // Click on a temp scope
2263- var tempScopeCard = findChild(scopesOverviewAllView, "delegate1");
2264- mouseClick(tempScopeCard, 0, 0);
2265-
2266- // Check the bottom edge (overview) is disabled from temp scope
2267+ var nonfavScopesListCategory = findChild(dash, "scopesListCategoryother");
2268+ var nonfavScopesListCategoryList = findChild(nonfavScopesListCategory, "scopesListCategoryInnerList");
2269+ tryCompare(nonfavScopesListCategoryList, "currentIndex", 0);
2270+
2271+ // Click on a non favorite scope
2272+ mouseClick(nonfavScopesListCategoryList.currentItem, 0, 0);
2273+
2274+ // Check the bottom edge (manage dash) is disabled from temp scope
2275 var overviewDragHandle = findChild(dash, "overviewDragHandle");
2276 compare(overviewDragHandle.enabled, false);
2277
2278 // Check temp scope is there
2279- tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
2280- tryCompare(scopesOverviewTempScopeItem, "enabled", true);
2281+ var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
2282+ tryCompare(dashTempScopeItem, "x", 0);
2283+ tryCompare(dashTempScopeItem, "visible", true);
2284+
2285+ // Check the manage dash is gone
2286+ tryCompare(bottomEdgeController, "progress", 0);
2287
2288 // Go back
2289- var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader");
2290- var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton");
2291+ var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
2292+ var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "backButton");
2293 mouseClick(backButton, 0, 0);
2294
2295 // Check temp scope is gone
2296- var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
2297- tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true);
2298- tryCompare(scopesOverviewTempScopeItem, "enabled", false);
2299-
2300- // Press on done
2301- var scopesOverviewDoneButton = findChild(scopesOverview, "scopesOverviewDoneButton");
2302- mouseClick(scopesOverviewDoneButton, 0, 0);
2303-
2304- // Check the dash overview is gone
2305- tryCompare(overviewController, "progress", 0);
2306+ tryCompare(dashTempScopeItem, "x", dash.width);
2307+ tryCompare(dashTempScopeItem, "visible", false);
2308
2309 // Original list is still on 0
2310 var dashContentList = findChild(dash, "dashContentList");
2311 compare(dashContentList.currentIndex, 0);
2312 }
2313
2314- function test_temp_scope_dash_overview_all_search_temp_scope_favorite_from_all() {
2315- // Swipe right to Apps scope
2316- var dashContentList = findChild(dash, "dashContentList");
2317- touchFlick(dash, dash.width - 1, units.gu(1), dash.width - units.gu(10), units.gu(1));
2318- tryCompare(dashContentList, "contentX", dashContentList.width);
2319- tryCompare(dashContentList, "currentIndex", 1);
2320-
2321- // Click on card that opens temp scope
2322- var categoryListView = findChild(dashContentList.currentItem, "categoryListView");
2323- var dashCategory2 = findChild(categoryListView, "dashCategory2");
2324- tryCompareFunction(function() {
2325- if (dashCategory2.y < 200) return true;
2326- categoryListView.contentY += 100;
2327- return false;
2328- }, true);
2329- var card2 = findChild(dashCategory2, "delegate2");
2330- waitForRendering(card2);
2331- mouseClick(card2, card2.width / 2, card2.height / 2);
2332-
2333- // Wait for temp scope to be there
2334- var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
2335- tryCompare(dashTempScopeItem, "x", 0);
2336-
2337- // Show the overview
2338- touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
2339- var overviewController = findInvisibleChild(dash, "overviewController");
2340- tryCompare(overviewController, "progress", 1);
2341-
2342- // Make sure tab is where it should
2343- var scopesOverview = findChild(dash, "scopesOverview");
2344- compare(scopesOverview.currentTab, 1);
2345+ function test_manage_dash_search_temp_scope() {
2346+ // Show the manage dash
2347+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, units.gu(2));
2348+ var bottomEdgeController = findInvisibleChild(dash, "bottomEdgeController");
2349+ tryCompare(bottomEdgeController, "progress", 1);
2350
2351 // Do a search
2352- var scopesOverviewPageHeader = findChild(scopesOverview, "scopesOverviewPageHeader");
2353- var searchButton = findChild(scopesOverviewPageHeader, "search_header_button");
2354+ var scopesList = findChild(dash, "scopesList");
2355+ var scopesListPageHeader = findChild(scopesList, "pageHeader");
2356+ var searchButton = findChild(scopesListPageHeader, "search_header_button");
2357 mouseClick(searchButton, 0, 0);
2358
2359 // Type something
2360 keyClick(Qt.Key_H);
2361
2362- // Check results grid is there and the other lists are not
2363- var searchResultsViewer = findChild(scopesOverview, "searchResultsViewer");
2364- var scopesOverviewRepeater = findChild(dash, "scopesOverviewRepeater");
2365- tryCompare(searchResultsViewer, "opacity", 1);
2366- tryCompare(scopesOverviewRepeater, "count", 0);
2367-
2368 // Click on a temp scope in the search
2369- tryCompareFunction( function() {
2370- return findChild(findChild(searchResultsViewer, "dashCategorysearchA"), "delegate2") != null;
2371- }, true);
2372- var cardTempScope = findChild(findChild(searchResultsViewer, "dashCategorysearchA"), "delegate2");
2373- verify(cardTempScope, "Could not find delegate2");
2374+ tryCompareFunction( function() { return findChild(scopesList, "scopesListCategorysearchA") != null; }, true);
2375+ var dashCategorysearchA = findChild(scopesList, "scopesListCategorysearchA");
2376+ tryCompareFunction( function() { return findChild(dashCategorysearchA, "delegate2") != null; }, true);
2377+ var cardTempScope = findChild(dashCategorysearchA, "delegate2");
2378
2379 waitForRendering(cardTempScope);
2380 mouseClick(cardTempScope, cardTempScope.width / 2, cardTempScope.height / 2);
2381@@ -257,29 +190,24 @@
2382 compare(overviewDragHandle.enabled, false);
2383
2384 // Check temp scope is there
2385- var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
2386- tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
2387- tryCompare(scopesOverviewTempScopeItem, "enabled", true);
2388+ var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
2389+ tryCompare(dashTempScopeItem, "x", 0);
2390+ tryCompare(dashTempScopeItem, "visible", true);
2391+
2392+ // Check the manage dash is gone
2393+ tryCompare(bottomEdgeController, "progress", 0);
2394
2395 // Go back
2396- var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader");
2397- var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton");
2398+ var dashTempScopeItemHeader = findChild(dashTempScopeItem, "scopePageHeader");
2399+ var backButton = findChild(findChild(dashTempScopeItemHeader, "innerPageHeader"), "backButton");
2400 mouseClick(backButton, 0, 0);
2401
2402 // Check temp scope is gone
2403- var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
2404- tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true);
2405- tryCompare(scopesOverviewTempScopeItem, "enabled", false);
2406-
2407- // Press on a favorite
2408- var dashCategorysearchB = findChild(searchResultsViewer, "dashCategorysearchB");
2409- var cardFavSearch = findChild(dashCategorysearchB, "delegate3");
2410- mouseClick(cardFavSearch, 0, 0);
2411-
2412- // Check the dash overview is gone
2413- tryCompare(overviewController, "progress", 0);
2414-
2415- // Original list went to the favorite
2416+ tryCompare(dashTempScopeItem, "x", dash.width);
2417+ tryCompare(dashTempScopeItem, "visible", false);
2418+
2419+ // Original list is still on 0
2420+ var dashContentList = findChild(dash, "dashContentList");
2421 compare(dashContentList.currentIndex, 0);
2422 }
2423
2424
2425=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
2426--- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-11-26 08:27:45 +0000
2427+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-12-05 10:47:59 +0000
2428@@ -574,7 +574,6 @@
2429 var innerHeader = findChild(header, "innerPageHeader");
2430 verify(innerHeader, "Could not find the inner header");
2431
2432- expectFail("Apps", "Click scope should not have a favorite button");
2433 var favoriteAction = findChild(innerHeader, "favorite_header_button");
2434 verify(favoriteAction, "Could not find the favorite action.");
2435 mouseClick(favoriteAction, favoriteAction.width / 2, favoriteAction.height / 2);

Subscribers

People subscribed via source and target branches