Merge lp:~saviq/unity8/dash-header-style into lp:unity8

Proposed by Michał Sawicz
Status: Superseded
Proposed branch: lp:~saviq/unity8/dash-header-style
Merge into: lp:unity8
Diff against target: 1402 lines (+435/-471)
28 files modified
.project (+1/-1)
.pydevproject (+3/-1)
.settings/Autopilot List.launch (+14/-0)
.settings/Autopilot Run.launch (+14/-0)
plugins/Dash/ScopeStyle.qml (+6/-0)
qml/Components/Background.qml (+77/-0)
qml/Components/FilterGrid.qml (+0/-124)
qml/Components/PageHeader.qml (+6/-1)
qml/Components/ResponsiveGridView.qml (+2/-1)
qml/Dash/CardCarousel.qml (+2/-7)
qml/Dash/CardGrid.qml (+22/-23)
qml/Dash/CardVerticalJournal.qml (+2/-21)
qml/Dash/DashRenderer.qml (+3/-12)
qml/Dash/GenericScopeView.qml (+52/-27)
tests/autopilot/unity8/shell/emulators/dash.py (+6/-3)
tests/autopilot/unity8/shell/tests/test_emulators.py (+5/-5)
tests/mocks/Ubuntu/Telephony/CMakeLists.txt (+1/-9)
tests/mocks/Unity/fake_categories.cpp (+4/-1)
tests/mocks/Unity/fake_scope.cpp (+8/-6)
tests/mocks/Unity/fake_scope.h (+1/-1)
tests/mocks/Unity/fake_scopes.cpp (+1/-0)
tests/plugins/Dash/tst_ScopeStyle.qml (+27/-2)
tests/qmltests/CMakeLists.txt (+1/-1)
tests/qmltests/Components/tst_Background.qml (+90/-0)
tests/qmltests/Components/tst_FilterGrid.qml (+0/-190)
tests/qmltests/Dash/tst_Dash.qml (+1/-1)
tests/qmltests/Dash/tst_DashContent.qml (+15/-6)
tests/qmltests/Dash/tst_GenericScopeView.qml (+71/-28)
To merge this branch: bzr merge lp:~saviq/unity8/dash-header-style
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Albert Astals Cid (community) Approve
Review via email: mp+227522@code.launchpad.net

This proposal has been superseded by a proposal from 2014-07-21.

Commit message

Add dash PageHeader styling.

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?
N/A

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~saviq/unity8/dash-header-style updated
1064. By Michał Sawicz

More background tests.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) 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, but the failing tests are known to fail/be unstable so that's fine.

review: Approve
lp:~saviq/unity8/dash-header-style updated
1065. By Michał Sawicz

Merge trunk.

1066. By Michał Sawicz

Merge drop-filtergrid

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed file 'tests/autopilot/.project' => '.project'
2--- tests/autopilot/.project 2013-11-18 12:05:58 +0000
3+++ .project 2014-07-21 23:38:21 +0000
4@@ -1,6 +1,6 @@
5 <?xml version="1.0" encoding="UTF-8"?>
6 <projectDescription>
7- <name>Unity8 Autopilot</name>
8+ <name>Unity8</name>
9 <comment></comment>
10 <projects>
11 </projects>
12
13=== renamed file 'tests/autopilot/.pydevproject' => '.pydevproject'
14--- tests/autopilot/.pydevproject 2013-11-18 12:05:58 +0000
15+++ .pydevproject 2014-07-21 23:38:21 +0000
16@@ -1,7 +1,9 @@
17 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
18 <?eclipse-pydev version="1.0"?><pydev_project>
19 <pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
20-<path>/Unity8 Autopilot</path>
21+<path>/Unity8/tests/autopilot</path>
22+<path>/Unity8/.bazaar</path>
23+<path>/Unity8/tests/whitespace</path>
24 </pydev_pathproperty>
25 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
26 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
27
28=== added directory '.settings'
29=== added file '.settings/Autopilot List.launch'
30--- .settings/Autopilot List.launch 1970-01-01 00:00:00 +0000
31+++ .settings/Autopilot List.launch 2014-07-21 23:38:21 +0000
32@@ -0,0 +1,14 @@
33+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
34+<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
35+<stringAttribute key="bad_container_name" value="/Unity8/.pyd"/>
36+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
37+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
38+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
39+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
40+</listAttribute>
41+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/autopilot"/>
42+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value=""/>
43+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="list unity8"/>
44+<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
45+<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Unity8"/>
46+</launchConfiguration>
47
48=== added file '.settings/Autopilot Run.launch'
49--- .settings/Autopilot Run.launch 1970-01-01 00:00:00 +0000
50+++ .settings/Autopilot Run.launch 2014-07-21 23:38:21 +0000
51@@ -0,0 +1,14 @@
52+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
53+<launchConfiguration type="org.python.pydev.debug.regularLaunchConfigurationType">
54+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"/>
55+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"/>
56+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
57+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
58+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
59+</listAttribute>
60+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/usr/bin/autopilot"/>
61+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_OTHER_WORKING_DIRECTORY" value=""/>
62+<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="run ${string_prompt:the test suite to run:unity8}"/>
63+<stringAttribute key="org.python.pydev.debug.ATTR_INTERPRETER" value="__default"/>
64+<stringAttribute key="org.python.pydev.debug.ATTR_PROJECT" value="Unity8"/>
65+</launchConfiguration>
66
67=== modified file 'plugins/Dash/ScopeStyle.qml'
68--- plugins/Dash/ScopeStyle.qml 2014-07-08 08:30:46 +0000
69+++ plugins/Dash/ScopeStyle.qml 2014-07-21 23:38:21 +0000
70@@ -70,6 +70,12 @@
71 /// Source of the logo image for the header
72 readonly property url headerLogo: "logo" in d.headerStyle ? d.headerStyle["logo"] : ""
73
74+ /// Background style for the header
75+ readonly property url headerBackground: "background" in d.headerStyle ? d.headerStyle["background"] : ""
76+
77+ /// Foreground color for the header
78+ readonly property color headerForeground: "foreground-color" in d.headerStyle ? d.headerStyle["foreground-color"] : foreground
79+
80 //! @cond
81 property var d: QtObject {
82 readonly property real foregroundLuminance: luminance(foreground)
83
84=== added file 'qml/Components/Background.qml'
85--- qml/Components/Background.qml 1970-01-01 00:00:00 +0000
86+++ qml/Components/Background.qml 2014-07-21 23:38:21 +0000
87@@ -0,0 +1,77 @@
88+/*
89+ * Copyright (C) 2014 Canonical, Ltd.
90+ *
91+ * This program is free software; you can redistribute it and/or modify
92+ * it under the terms of the GNU General Public License as published by
93+ * the Free Software Foundation; version 3.
94+ *
95+ * This program is distributed in the hope that it will be useful,
96+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
97+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98+ * GNU General Public License for more details.
99+ *
100+ * You should have received a copy of the GNU General Public License
101+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
102+ */
103+
104+import QtQuick 2.0
105+
106+Loader {
107+ id: root
108+ anchors.fill: parent
109+
110+ property url style
111+ readonly property var parsedStyle: String(style)
112+ .match(/^(color|gradient):\/\/\/(?:(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))(?:\/(#(?:[0-9a-f]{3,4}){1,2}|[a-z]{3,}))?\/?$/i)
113+
114+ sourceComponent: {
115+ if (style == "") return null;
116+ if (!parsedStyle) return image;
117+ if (parsedStyle[1] === "color") return solid
118+ if (parsedStyle[1] === "gradient") return gradient
119+ }
120+
121+ onLoaded: if (item.hasOwnProperty("parsedStyle")) {
122+ item.parsedStyle = Qt.binding(function() { return root.parsedStyle } );
123+ }
124+
125+ Component {
126+ id: solid
127+
128+ Rectangle {
129+ objectName: "solid"
130+
131+ property var parsedStyle
132+
133+ color: parsedStyle ? parsedStyle[2] : "#ffffff"
134+ }
135+ }
136+
137+ Component {
138+ id: gradient
139+
140+ Rectangle {
141+ objectName: "gradient"
142+
143+ property var parsedStyle
144+
145+ gradient: Gradient {
146+ GradientStop { position: 0; color: parsedStyle ? parsedStyle[2] : "#000000" }
147+ GradientStop { position: 1; color: parsedStyle ? parsedStyle[3] : "#000000" }
148+ }
149+ }
150+ }
151+
152+ Component {
153+ id: image
154+
155+ Image {
156+ objectName: "image"
157+
158+ source: width > 0 && height > 0 && root.style
159+
160+ sourceSize.width: width
161+ sourceSize.height: height
162+ }
163+ }
164+}
165
166=== removed file 'qml/Components/FilterGrid.qml'
167--- qml/Components/FilterGrid.qml 2014-05-23 13:52:36 +0000
168+++ qml/Components/FilterGrid.qml 1970-01-01 00:00:00 +0000
169@@ -1,124 +0,0 @@
170-/*
171- * Copyright (C) 2013 Canonical, Ltd.
172- *
173- * This program is free software; you can redistribute it and/or modify
174- * it under the terms of the GNU General Public License as published by
175- * the Free Software Foundation; version 3.
176- *
177- * This program is distributed in the hope that it will be useful,
178- * but WITHOUT ANY WARRANTY; without even the implied warranty of
179- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
180- * GNU General Public License for more details.
181- *
182- * You should have received a copy of the GNU General Public License
183- * along with this program. If not, see <http://www.gnu.org/licenses/>.
184- */
185-
186-import QtQuick 2.0
187-import Ubuntu.Components 0.1
188-import Utils 0.1
189-import "../Components"
190-
191-/*
192- A ResponsiveGridView that can optionally have the number of rows being displayed
193- reduced to collapsedRowCount, in which case a button saying "View all (123)"
194- will be shown at the bottom. If clicked, FilterGrid will them expand vertically
195- to display all rows.
196- */
197-Item {
198- id: root
199-
200- /* Whether, when collapsed, a button should be displayed enabling the user to expand
201- the grid to its full size. */
202- readonly property bool expandable: model.count > rowsWhenCollapsed * iconTileGrid.columns
203-
204- property var model: null
205-
206- /* Maximum number of rows to be show when filter=true. */
207- property int collapsedRowCount: 2
208- property int uncollapsedRowCount: Math.ceil(model.count / columns)
209- /* Never show more rows than model would fill up. */
210- readonly property int rowsWhenCollapsed: Math.min(collapsedRowCount, uncollapsedRowCount)
211- readonly property int collapsedHeight: iconTileGrid.contentHeightForRows(rowsWhenCollapsed)
212- readonly property int uncollapsedHeight: iconTileGrid.contentHeightForRows(uncollapsedRowCount)
213-
214- property alias minimumHorizontalSpacing: iconTileGrid.minimumHorizontalSpacing
215- property alias maximumNumberOfColumns: iconTileGrid.maximumNumberOfColumns
216- property alias columns: iconTileGrid.columns
217- property alias delegateWidth: iconTileGrid.delegateWidth
218- property alias delegateHeight: iconTileGrid.delegateHeight
219- property alias verticalSpacing: iconTileGrid.verticalSpacing
220- readonly property alias margins: iconTileGrid.margins
221- property alias delegate: iconTileGrid.delegate
222- property alias cellWidth: iconTileGrid.cellWidth
223- property alias cellHeight: iconTileGrid.cellHeight
224- property alias displayMarginBeginning: iconTileGrid.displayMarginBeginning
225- property alias displayMarginEnd: iconTileGrid.displayMarginEnd
226- readonly property alias originY: iconTileGrid.originY
227- readonly property alias flicking: iconTileGrid.flicking
228- readonly property alias moving: iconTileGrid.moving
229- readonly property alias pressDelay: iconTileGrid.pressDelay
230- property alias highlightIndex: iconTileGrid.highlightIndex
231- readonly property alias currentItem: iconTileGrid.currentItem
232- readonly property alias filtered: d.filter
233-
234- QtObject {
235- id: d
236- // We do have filter and collapsed properties because we need to decouple
237- // the real filtering with the animation since the closing animation
238- // i.e. setFilter(false. true) we still need to not be filtering until
239- // the animation finishes otherwise we hide the items when the animation
240- // is still running
241- property bool filter: true
242- property bool collapsed: true
243- }
244-
245- height: d.collapsed ? root.collapsedHeight : root.uncollapsedHeight
246- clip: filterAnimation.running
247-
248- Behavior on height {
249- id: heightBehaviour
250- enabled: false
251- NumberAnimation {
252- id: filterAnimation
253- // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
254- // otherwise since both animations can run at the same time you'll get
255- // some visual weirdness.
256- duration: 200
257- easing.type: Easing.InOutQuad
258- onRunningChanged: {
259- if (!running) {
260- d.filter = d.collapsed;
261- }
262- heightBehaviour.enabled = false;
263- }
264- }
265- }
266-
267- function setFilter(filter, animate) {
268- heightBehaviour.enabled = animate;
269- d.collapsed = filter;
270- if (!animate || !filter) {
271- d.filter = filter;
272- }
273- }
274-
275- ResponsiveGridView {
276- id: iconTileGrid
277-
278- anchors { left: parent.left; right: parent.right }
279- height: totalContentHeight
280- interactive: false
281-
282- minimumHorizontalSpacing: units.gu(0.5)
283- maximumNumberOfColumns: 6
284- delegateWidth: units.gu(11)
285- delegateHeight: units.gu(9.5)
286- verticalSpacing: units.gu(2)
287-
288- model: LimitProxyModel {
289- model: root.model
290- limit: d.filter ? rowsWhenCollapsed * iconTileGrid.columns : -1
291- }
292- }
293-}
294
295=== modified file 'qml/Components/PageHeader.qml'
296--- qml/Components/PageHeader.qml 2014-07-09 19:44:02 +0000
297+++ qml/Components/PageHeader.qml 2014-07-21 23:38:21 +0000
298@@ -127,6 +127,11 @@
299 property bool showSearch: false
300 property var popover: null
301
302+ Background {
303+ objectName: "headerBackground"
304+ style: scopeStyle.headerBackground
305+ }
306+
307 Behavior on contentY {
308 UbuntuNumberAnimation {
309 id: openSearchAnimation
310@@ -225,7 +230,7 @@
311 height: headerContainer.height
312 contentHeight: height
313 separatorSource: ""
314- textColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
315+ textColor: root.scopeStyle ? root.scopeStyle.headerForeground : "grey"
316 property var styledItem: header
317 property string title: root.title
318 property var config: PageHeadConfiguration {
319
320=== modified file 'qml/Components/ResponsiveGridView.qml'
321--- qml/Components/ResponsiveGridView.qml 2014-05-15 14:50:23 +0000
322+++ qml/Components/ResponsiveGridView.qml 2014-07-21 23:38:21 +0000
323@@ -44,10 +44,11 @@
324 property alias displayMarginBeginning: gridView.displayMarginBeginning
325 property alias displayMarginEnd: gridView.displayMarginEnd
326 property alias highlightIndex: gridView.highlightIndex
327+ property alias cacheBuffer: gridView.cacheBuffer
328 readonly property alias currentItem: gridView.currentItem
329
330 function contentHeightForRows(rows) {
331- return rows * cellHeight + verticalSpacing
332+ return rows * cellHeight;
333 }
334
335 GridView {
336
337=== modified file 'qml/Dash/CardCarousel.qml'
338--- qml/Dash/CardCarousel.qml 2014-07-09 19:44:02 +0000
339+++ qml/Dash/CardCarousel.qml 2014-07-21 23:38:21 +0000
340@@ -21,13 +21,8 @@
341 DashRenderer {
342 id: cardCarousel
343
344- property alias cacheBuffer: carousel.cacheBuffer
345- property alias itemComponent: carousel.itemComponent
346- property alias minimumTileWidth: carousel.minimumTileWidth
347- property alias selectedItemScaleFactor: carousel.selectedItemScaleFactor
348- property alias tileAspectRatio: carousel.tileAspectRatio
349-
350- height: carousel.implicitHeight + units.gu(6)
351+ expandedHeight: carousel.implicitHeight + units.gu(6)
352+ collapsedHeight: expandedHeight
353
354 Carousel {
355 id: carousel
356
357=== renamed file 'qml/Dash/CardFilterGrid.qml' => 'qml/Dash/CardGrid.qml'
358--- qml/Dash/CardFilterGrid.qml 2014-07-08 08:30:46 +0000
359+++ qml/Dash/CardGrid.qml 2014-07-21 23:38:21 +0000
360@@ -18,33 +18,32 @@
361 import "../Components"
362
363 DashRenderer {
364- id: genericFilterGrid
365-
366- expandable: filterGrid.expandable
367- collapsedHeight: filterGrid.collapsedHeight
368- uncollapsedHeight: filterGrid.uncollapsedHeight
369- originY: filterGrid.originY
370- height: filterGrid.height
371- filtered: filterGrid.filtered
372-
373- function setFilter(filter, animate) {
374- filterGrid.setFilter(filter, animate)
375+ id: root
376+
377+ readonly property int collapsedRows: {
378+ if (!cardTool || !cardTool.template || typeof cardTool.template["collapsed-rows"] != "number") return 2;
379+ return cardTool.template["collapsed-rows"];
380 }
381
382- FilterGrid {
383- id: filterGrid
384- width: genericFilterGrid.width
385+ expandedHeight: grid.totalContentHeight
386+ collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows), expandedHeight)
387+ originY: grid.originY
388+
389+ ResponsiveGridView {
390+ id: grid
391+ anchors.fill: parent
392 minimumHorizontalSpacing: units.gu(1)
393 delegateWidth: cardTool.cardWidth
394 delegateHeight: cardTool.cardHeight
395 verticalSpacing: units.gu(1)
396- model: genericFilterGrid.model
397- collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
398- displayMarginBeginning: genericFilterGrid.displayMarginBeginning
399- displayMarginEnd: genericFilterGrid.displayMarginEnd
400+ model: root.model
401+ displayMarginBeginning: root.displayMarginBeginning
402+ displayMarginEnd: root.displayMarginEnd
403+ cacheBuffer: 0
404+ interactive: false
405 delegate: Item {
406- width: filterGrid.cellWidth
407- height: filterGrid.cellHeight
408+ width: grid.cellWidth
409+ height: grid.cellHeight
410 Loader {
411 id: loader
412 sourceComponent: cardTool.cardComponent
413@@ -58,12 +57,12 @@
414 item.template = Qt.binding(function() { return cardTool.template; });
415 item.components = Qt.binding(function() { return cardTool.components; });
416 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
417- item.scopeStyle = genericFilterGrid.scopeStyle;
418+ item.scopeStyle = root.scopeStyle;
419 }
420 Connections {
421 target: loader.item
422- onClicked: genericFilterGrid.clicked(index, result)
423- onPressAndHold: genericFilterGrid.pressAndHold(index)
424+ onClicked: root.clicked(index, result)
425+ onPressAndHold: root.pressAndHold(index)
426 }
427 }
428 }
429
430=== modified file 'qml/Dash/CardVerticalJournal.qml'
431--- qml/Dash/CardVerticalJournal.qml 2014-07-09 19:44:02 +0000
432+++ qml/Dash/CardVerticalJournal.qml 2014-07-21 23:38:21 +0000
433@@ -23,33 +23,14 @@
434
435 readonly property double collapseLimit: units.gu(35)
436
437- uncollapsedHeight: cardVerticalJournal.implicitHeight
438- collapsedHeight: Math.min(collapseLimit, cardVerticalJournal.implicitHeight)
439- expandable: uncollapsedHeight > collapseLimit
440+ expandedHeight: Math.max(cardVerticalJournal.implicitHeight, minHeight)
441+ collapsedHeight: Math.max(Math.min(collapseLimit, cardVerticalJournal.implicitHeight), minHeight)
442
443 // This minHeight is used as bootstrapper for the height. Vertical Journal
444 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
445 // enough height that it can start creating its children so we make sure it has enough height for that
446 // in case the model is non empty
447 readonly property double minHeight: root.model.count >= 1 ? cardVerticalJournal.rowSpacing + 1 : 0
448- height: filtered ? Math.max(collapsedHeight, minHeight) : uncollapsedHeight
449-
450- Behavior on height {
451- id: heightBehaviour
452- enabled: false
453- animation: UbuntuNumberAnimation {
454- onRunningChanged: {
455- if (!running) {
456- heightBehaviour.enabled = false
457- }
458- }
459- }
460- }
461-
462- function setFilter(filter, animate) {
463- heightBehaviour.enabled = animate;
464- filtered = filter;
465- }
466
467 ResponsiveVerticalJournal {
468 id: cardVerticalJournal
469
470=== modified file 'qml/Dash/DashRenderer.qml'
471--- qml/Dash/DashRenderer.qml 2014-07-08 08:30:46 +0000
472+++ qml/Dash/DashRenderer.qml 2014-07-21 23:38:21 +0000
473@@ -17,15 +17,9 @@
474 import QtQuick 2.0
475
476 Item {
477- // Can the item be expanded?
478- property bool expandable: false
479-
480- // In case it can be expanded, is it filtered
481- property bool filtered: true
482-
483- property int collapsedHeight: height
484-
485- property int uncollapsedHeight: height
486+ property int collapsedHeight
487+
488+ property int expandedHeight
489
490 property int displayMarginBeginning: 0
491
492@@ -50,7 +44,4 @@
493 /// Emitted when the user pressed and held on an item
494 /// @param index is the index of the held item
495 signal pressAndHold(int index)
496-
497- function setFilter(filter, animate) {
498- }
499 }
500
501=== modified file 'qml/Dash/GenericScopeView.qml'
502--- qml/Dash/GenericScopeView.qml 2014-07-17 13:10:45 +0000
503+++ qml/Dash/GenericScopeView.qml 2014-07-21 23:38:21 +0000
504@@ -128,11 +128,21 @@
505 highlightWhenPressed: false
506 showDivider: false
507
508- readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
509- readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
510+ readonly property bool expandable: {
511+ if (categoryView.model.count === 1) return false;
512+ if (cardTool.template && cardTool.template["collapsed-rows"] === 0) return false;
513+ if (item && item.expandedHeight > item.collapsedHeight) return true;
514+ return false;
515+ }
516+ property bool expanded: false
517 readonly property string category: categoryId
518 readonly property var item: rendererLoader.item
519
520+ function expand(expand, animate) {
521+ heightBehaviour.enabled = animate;
522+ expanded = expand;
523+ }
524+
525 CardTool {
526 id: cardTool
527 objectName: "cardTool"
528@@ -142,6 +152,18 @@
529 viewWidth: parent.width
530 }
531
532+ onExpandableChanged: {
533+ // This can happen with the VJ that doesn't know how height it will be on creation
534+ // so doesn't set expandable until a bit too late for onLoaded
535+ if (expandable) {
536+ var shouldExpand = baseItem.category === categoryView.expandedCategoryId;
537+ baseItem.expand(shouldExpand, false /*animate*/);
538+ }
539+ }
540+
541+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
542+ onYChanged: rendererLoader.updateDelegateCreationRange();
543+
544 Loader {
545 id: rendererLoader
546 anchors {
547@@ -151,13 +173,27 @@
548 topMargin: hasSectionHeader ? 0 : units.gu(2)
549 }
550
551+ Behavior on height {
552+ id: heightBehaviour
553+ enabled: false
554+ animation: UbuntuNumberAnimation {
555+ onRunningChanged: {
556+ if (!running) {
557+ heightBehaviour.enabled = false
558+ }
559+ }
560+ }
561+ }
562+
563+ height: baseItem.expandable && !baseItem.expanded ? item.collapsedHeight : item.expandedHeight
564+
565 source: {
566 switch (cardTool.categoryLayout) {
567 case "carousel": return "CardCarousel.qml";
568 case "vertical-journal": return "CardVerticalJournal.qml";
569 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
570 case "grid":
571- default: return "CardFilterGrid.qml";
572+ default: return "CardGrid.qml";
573 }
574 }
575
576@@ -176,9 +212,9 @@
577 }
578 item.objectName = Qt.binding(function() { return categoryId })
579 item.scopeStyle = scopeView.scopeStyle;
580- if (item.expandable) {
581- var shouldFilter = categoryId != categoryView.expandedCategoryId;
582- item.setFilter(shouldFilter, false /*animate*/);
583+ if (baseItem.expandable) {
584+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
585+ baseItem.expand(shouldExpand, false /*animate*/);
586 }
587 updateDelegateCreationRange();
588 item.cardTool = cardTool;
589@@ -211,14 +247,6 @@
590 previewListView.currentIndex = index;
591 previewListView.open = true
592 }
593- onExpandableChanged: {
594- // This can happen with the VJ that doesn't know how height it will be on creation
595- // so doesn't set expandable until a bit too late for onLoaded
596- if (rendererLoader.item.expandable) {
597- var shouldFilter = baseItem.category != categoryView.expandedCategoryId;
598- rendererLoader.item.setFilter(shouldFilter, false /*animate*/);
599- }
600- }
601 }
602 Connections {
603 target: categoryView
604@@ -227,17 +255,17 @@
605 }
606 function collapseAllButExpandedCategory() {
607 var item = rendererLoader.item;
608- if (item.expandable) {
609- var shouldFilter = categoryId != categoryView.expandedCategoryId;
610- if (shouldFilter != item.filter) {
611+ if (baseItem.expandable) {
612+ var shouldExpand = categoryId === categoryView.expandedCategoryId;
613+ if (shouldExpand != baseItem.expanded) {
614 // If the filter animation will be seen start it, otherwise, just flip the switch
615- var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
616- var growingVisible = !shouldFilter && y + height < categoryView.height;
617- if (!previewListView.open || !shouldFilter) {
618+ var shrinkingVisible = !shouldExpand && y + item.collapsedHeight < categoryView.height;
619+ var growingVisible = shouldExpand && y + height < categoryView.height;
620+ if (!previewListView.open || shouldExpand) {
621 var animate = shrinkingVisible || growingVisible;
622- item.setFilter(shouldFilter, animate)
623- if (!shouldFilter && !previewListView.open) {
624- categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
625+ baseItem.expand(shouldExpand, animate)
626+ if (shouldExpand && !previewListView.open) {
627+ categoryView.maximizeVisibleArea(index, item.expandedHeight);
628 }
629 }
630 }
631@@ -304,9 +332,6 @@
632 z: -1
633 }
634 }
635-
636- onHeightChanged: rendererLoader.updateDelegateCreationRange();
637- onYChanged: rendererLoader.updateDelegateCreationRange();
638 }
639
640 sectionProperty: "name"
641@@ -318,7 +343,7 @@
642 textColor: scopeStyle ? scopeStyle.foreground : "grey"
643 image: {
644 if (delegate && delegate.expandable)
645- return delegate.filtered ? "graphics/header_handlearrow.png" : "graphics/header_handlearrow2.png"
646+ return delegate.expanded ? "graphics/header_handlearrow2.png" : "graphics/header_handlearrow.png"
647 return "";
648 }
649 onClicked: {
650
651=== modified file 'tests/autopilot/unity8/shell/emulators/dash.py'
652--- tests/autopilot/unity8/shell/emulators/dash.py 2014-07-09 18:31:52 +0000
653+++ tests/autopilot/unity8/shell/emulators/dash.py 2014-07-21 23:38:21 +0000
654@@ -40,7 +40,7 @@
655
656 def get_applications_grid(self):
657 get_grid = self.get_scope('clickscope').wait_select_single(
658- 'CardFilterGrid', objectName='local')
659+ 'CardGrid', objectName='local')
660 return get_grid
661
662 def get_application_icon(self, text):
663@@ -196,9 +196,12 @@
664 category_element = self._get_category_element(category)
665 application_cards = category_element.select_many('AbstractButton')
666
667- # sort by y, x
668+ # sort by y, x, filter those out of view
669+ categoryBottom = category_element.globalRect.y \
670+ + category_element.height
671 application_cards = sorted(
672- application_cards,
673+ (card for card in application_cards
674+ if card.globalRect.y < categoryBottom),
675 key=lambda card: (card.globalRect.y, card.globalRect.x))
676
677 result = []
678
679=== modified file 'tests/autopilot/unity8/shell/tests/test_emulators.py'
680--- tests/autopilot/unity8/shell/tests/test_emulators.py 2014-07-09 13:16:20 +0000
681+++ tests/autopilot/unity8/shell/tests/test_emulators.py 2014-07-21 23:38:21 +0000
682@@ -191,9 +191,9 @@
683 def _get_number_of_application_slots(self, category):
684 category_element = self.applications_scope._get_category_element(
685 category)
686- grid = category_element.select_single('CardFilterGrid')
687- filtergrid = grid.select_single('FilterGrid')
688- if (grid.filtered):
689- return filtergrid.collapsedRowCount * filtergrid.columns
690+ cardgrid = category_element.select_single('CardGrid')
691+ if (category_element.expanded):
692+ return cardgrid.select_single('QQuickGridView').count
693 else:
694- return filtergrid.uncollapsedRowCount * filtergrid.columns
695+ return cardgrid.collapsedRows \
696+ * cardgrid.select_single('ResponsiveGridView').columns
697
698=== modified file 'tests/mocks/Ubuntu/Telephony/CMakeLists.txt'
699--- tests/mocks/Ubuntu/Telephony/CMakeLists.txt 2014-04-30 18:06:38 +0000
700+++ tests/mocks/Ubuntu/Telephony/CMakeLists.txt 2014-07-21 23:38:21 +0000
701@@ -11,12 +11,4 @@
702
703 qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
704
705-# copy files into build directory for shadow builds
706-add_custom_target(UbuntuTelephonyQmlDirFile ALL
707- COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
708- DEPENDS qmldir
709-)
710-
711-install(TARGETS FakeUbuntuTelephonyQml
712- DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/Telephony
713- )
714+add_unity8_mock(Ubuntu.Telephony 0.1 Ubuntu/Telephony TARGETS FakeUbuntuTelephonyQml)
715
716=== modified file 'tests/mocks/Unity/fake_categories.cpp'
717--- tests/mocks/Unity/fake_categories.cpp 2014-07-08 11:04:55 +0000
718+++ tests/mocks/Unity/fake_categories.cpp 2014-07-21 23:38:21 +0000
719@@ -145,9 +145,12 @@
720 } else {
721 map["category-layout"] = "carousel";
722 map["card-size"] = "medium";
723- map["collapsed-rows"] = 2;
724 map["overlay"] = true;
725 }
726+ if (index.row() == 19) {
727+ map["category-layout"] = "grid";
728+ map["collapsed-rows"] = 0;
729+ }
730 map["card-size"] = "small";
731 return map;
732 }
733
734=== modified file 'tests/mocks/Unity/fake_scope.cpp'
735--- tests/mocks/Unity/fake_scope.cpp 2014-07-09 19:44:02 +0000
736+++ tests/mocks/Unity/fake_scope.cpp 2014-07-21 23:38:21 +0000
737@@ -24,7 +24,7 @@
738 {
739 }
740
741-Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
742+Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent, int categories)
743 : unity::shell::scopes::ScopeInterface(parent)
744 , m_id(id)
745 , m_name(name)
746@@ -33,7 +33,7 @@
747 , m_isActive(false)
748 , m_currentDeparment("root")
749 , m_previewRendererName("preview-generic")
750- , m_categories(new Categories(20, this))
751+ , m_categories(new Categories(categories, this))
752 {
753 }
754
755@@ -182,14 +182,16 @@
756
757 QVariantMap Scope::customizations() const
758 {
759- QVariantMap m;
760+ QVariantMap m, h;
761 if (m_id == "clickscope") {
762+ h["foreground-color"] = "yellow";
763 m["background-color"] = "red";
764 m["foreground-color"] = "blue";
765+ m["page-header"] = h;
766 } else if (m_id == "MockScope5") {
767- QVariantMap pageHeader;
768- pageHeader["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
769- m["page-header"] = pageHeader;
770+ h["background"] = "gradient:///lightgrey/grey";
771+ h["logo"] = QUrl("../../../tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg");
772+ m["page-header"] = h;
773 }
774 return m;
775 }
776
777=== modified file 'tests/mocks/Unity/fake_scope.h'
778--- tests/mocks/Unity/fake_scope.h 2014-07-08 09:23:14 +0000
779+++ tests/mocks/Unity/fake_scope.h 2014-07-21 23:38:21 +0000
780@@ -30,7 +30,7 @@
781
782 public:
783 Scope(QObject* parent = 0);
784- Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0);
785+ Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0, int categories = 20);
786
787 /* getters */
788 QString id() const override;
789
790=== modified file 'tests/mocks/Unity/fake_scopes.cpp'
791--- tests/mocks/Unity/fake_scopes.cpp 2014-06-12 14:08:54 +0000
792+++ tests/mocks/Unity/fake_scopes.cpp 2014-07-21 23:38:21 +0000
793@@ -46,6 +46,7 @@
794 addScope(new Scope("MockScope2", "Music", false, this));
795 addScope(new Scope("clickscope", "Apps", true, this));
796 addScope(new Scope("MockScope5", "Videos", true, this));
797+ addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
798
799 if (!m_loaded) {
800 m_loaded = true;
801
802=== modified file 'tests/plugins/Dash/tst_ScopeStyle.qml'
803--- tests/plugins/Dash/tst_ScopeStyle.qml 2014-07-08 08:30:46 +0000
804+++ tests/plugins/Dash/tst_ScopeStyle.qml 2014-07-21 23:38:21 +0000
805@@ -36,8 +36,8 @@
806 property var styles: [
807 {},
808 { "foreground-color": "red", "background-color": "black", "page-header": { "logo": "/foo/bar" } },
809- { "foreground-color": "green", "background-color": "white" },
810- { "foreground-color": "blue", "background-color": "darkgrey" },
811+ { "foreground-color": "green", "background-color": "white", "page-header": { "foreground-color": "black" } },
812+ { "foreground-color": "blue", "background-color": "darkgrey", "page-header": { "background": "gradient:///white/blue" } },
813 ]
814
815 function cleanup() {
816@@ -147,5 +147,30 @@
817 tool.style = testCase.styles[data.index];
818 compare(tool.headerLogo, data.headerLogo, "Header logo was incorrect.");
819 }
820+
821+ function test_headerForeground_data() {
822+ return [
823+ { tag: "default", index: 0, headerForeground: "grey" },
824+ { tag: "black", index: 2, headerForeground: "black" },
825+ ];
826+ }
827+
828+ function test_headerForeground(data) {
829+ tool.style = testCase.styles[data.index];
830+ verify(Qt.colorEqual(tool.headerForeground, data.headerForeground),
831+ "Header foreground not equal: %1 != %2".arg(tool.headerForeground).arg(data.headerForeground));
832+ }
833+
834+ function test_headerBackground_data() {
835+ return [
836+ { tag: "default", index: 0, headerBackground: "" },
837+ { tag: "black", index: 3, headerBackground: "gradient:///white/blue" },
838+ ];
839+ }
840+
841+ function test_headerBackground(data) {
842+ tool.style = testCase.styles[data.index];
843+ compare(tool.headerBackground, data.headerBackground, "Header background was incorrect.");
844+ }
845 }
846 }
847
848=== modified file 'tests/qmltests/CMakeLists.txt'
849--- tests/qmltests/CMakeLists.txt 2014-07-15 14:14:59 +0000
850+++ tests/qmltests/CMakeLists.txt 2014-07-21 23:38:21 +0000
851@@ -21,10 +21,10 @@
852
853 add_qml_test(. Shell ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
854 add_qml_test(. ShellWithPin ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single-pin")
855+add_qml_test(Components Background)
856 add_qml_test(Components Carousel)
857 add_qml_test(Components DraggingArea)
858 add_qml_test(Components EdgeDemoOverlay)
859-add_qml_test(Components FilterGrid)
860 add_qml_test(Components LazyImage)
861 add_qml_test(Components Rating)
862 add_qml_test(Components ResponsiveFlowView)
863
864=== added file 'tests/qmltests/Components/tst_Background.qml'
865--- tests/qmltests/Components/tst_Background.qml 1970-01-01 00:00:00 +0000
866+++ tests/qmltests/Components/tst_Background.qml 2014-07-21 23:38:21 +0000
867@@ -0,0 +1,90 @@
868+/*
869+ * Copyright (C) 2014 Canonical, Ltd.
870+ *
871+ * This program is free software; you can redistribute it and/or modify
872+ * it under the terms of the GNU General Public License as published by
873+ * the Free Software Foundation; version 3.
874+ *
875+ * This program is distributed in the hope that it will be useful,
876+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
878+ * GNU General Public License for more details.
879+ *
880+ * You should have received a copy of the GNU General Public License
881+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
882+ */
883+
884+import QtQuick 2.2
885+import QtTest 1.0
886+import Unity.Test 0.1
887+
888+import "../../../qml/Components"
889+
890+Rectangle {
891+ width: units.gu(40)
892+ height: units.gu(71)
893+
894+ Background {
895+ id: background
896+ }
897+
898+ UnityTestCase {
899+ id: testCase
900+ name: "Background"
901+ when: windowShown
902+
903+ SignalSpy {
904+ id: loadedSpy
905+ target: background
906+ signalName: "loaded"
907+ }
908+
909+ function cleanup() {
910+ background.style = "";
911+ loadedSpy.clear();
912+ }
913+
914+ function test_style_data() {
915+ return [
916+ { tag: "empty", style: "" },
917+ { tag: "solid", style: "color:///black" },
918+ { tag: "gradient", style: "gradient:///black/red" },
919+ { tag: "image", style: "/some/path" },
920+ ];
921+ }
922+
923+ function test_style(data) {
924+ background.style = data.style;
925+ expectFail("empty", "Empty style should not create a background.");
926+ loadedSpy.wait();
927+ compare(background.item.objectName, data.tag, "Background should be %1".arg(data.style));
928+ }
929+
930+ function test_solid() {
931+ background.style = "color:///black";
932+ loadedSpy.wait();
933+
934+ verify(Qt.colorEqual(background.item.color, "black"),
935+ "Solid color not equal: %1 != black".arg(background.item.color));
936+ }
937+
938+ function test_gradient() {
939+ background.style = "gradient:///black/red";
940+ loadedSpy.wait();
941+
942+ var stops = background.item.gradient.stops;
943+
944+ verify(Qt.colorEqual(stops[0].color, "black"),
945+ "Top gradient color not equal: %1 != black".arg(stops[0].color));
946+ verify(Qt.colorEqual(stops[1].color, "red"),
947+ "Bottom gradient color not equal: %1 != black".arg(stops[1].color));
948+ }
949+
950+ function test_image() {
951+ background.style = "/some/path";
952+ loadedSpy.wait();
953+
954+ compare(background.item.source, Qt.resolvedUrl("/some/path"), "Image path is incorrect.");
955+ }
956+ }
957+}
958
959=== removed file 'tests/qmltests/Components/tst_FilterGrid.qml'
960--- tests/qmltests/Components/tst_FilterGrid.qml 2014-05-01 14:25:18 +0000
961+++ tests/qmltests/Components/tst_FilterGrid.qml 1970-01-01 00:00:00 +0000
962@@ -1,190 +0,0 @@
963-/*
964- * Copyright 2013 Canonical Ltd.
965- *
966- * This program is free software; you can redistribute it and/or modify
967- * it under the terms of the GNU General Public License as published by
968- * the Free Software Foundation; version 3.
969- *
970- * This program is distributed in the hope that it will be useful,
971- * but WITHOUT ANY WARRANTY; without even the implied warranty of
972- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
973- * GNU General Public License for more details.
974- *
975- * You should have received a copy of the GNU General Public License
976- * along with this program. If not, see <http://www.gnu.org/licenses/>.
977- */
978-
979-import QtQuick 2.0
980-import QtTest 1.0
981-import "../../../qml/Components"
982-import Ubuntu.Components.ListItems 0.1 as ListItem
983-import Ubuntu.Components 0.1
984-import Unity.Test 0.1 as UT
985-import Utils 0.1
986-
987-/*
988- You should see 6 green squares (from "A" to "F") and a button "View all (12)".
989- Once you press that button other 6 green squares (from "G" to "L") should show up.
990-*/
991-Rectangle {
992- width: gridRect.width + controls.width
993- height: units.gu(50)
994- color: "white"
995-
996- Column {
997- id: controls
998- width: units.gu(30)
999- height: parent.height
1000- anchors.top: parent.top
1001- anchors.right: parent.right
1002- ListItem.ValueSelector {
1003- id: collapsedRowCountSelector
1004- text: "collapsedRowCount"
1005- values: [1,2,3,4]
1006- selectedIndex: 1
1007- }
1008- Row {
1009- spacing: units.gu(1)
1010- Label { anchors.verticalCenter: parent.verticalCenter
1011- text: "Filter" }
1012- CheckBox {
1013- id: filterCheckBox
1014- checked: true
1015- onCheckedChanged: filterGrid.setFilter(checked, false /*animate*/)
1016- }
1017- }
1018- }
1019-
1020- ListModel {
1021- id: fakeModel
1022- ListElement { name: "A" }
1023- ListElement { name: "B" }
1024- ListElement { name: "C" }
1025- ListElement { name: "D" }
1026- ListElement { name: "E" }
1027- ListElement { name: "F" }
1028- ListElement { name: "G" }
1029- ListElement { name: "H" }
1030- ListElement { name: "I" }
1031- ListElement { name: "J" }
1032- ListElement { name: "K" }
1033- ListElement { name: "L" }
1034- }
1035-
1036- ListModel {
1037- id: fakeModelTwoItems
1038- ListElement { name: "A" }
1039- ListElement { name: "B" }
1040- }
1041-
1042- ListModel {
1043- id: fakeModelFourItems
1044- ListElement { name: "A" }
1045- ListElement { name: "B" }
1046- ListElement { name: "C" }
1047- ListElement { name: "D" }
1048- }
1049-
1050- Rectangle {
1051- id: gridRect
1052- width: units.gu(30)
1053- height: parent.height
1054- color: "grey"
1055- anchors.top: parent.top
1056- anchors.left: parent.left
1057-
1058- FilterGrid {
1059- id: filterGrid
1060- anchors.fill: parent
1061- model: fakeModel
1062- maximumNumberOfColumns: 3
1063- collapsedRowCount:
1064- collapsedRowCountSelector.values[collapsedRowCountSelector.selectedIndex]
1065- minimumHorizontalSpacing: units.gu(1)
1066- delegateWidth: units.gu(6)
1067- delegateHeight: units.gu(6)
1068- verticalSpacing: units.gu(1)
1069-
1070- delegate: Rectangle {
1071- // So that it can be identified by countVisibleDelegates()
1072- property bool isGridDelegate: true
1073-
1074- color: "green"
1075- width: units.gu(6)
1076- height: units.gu(6)
1077- Text {
1078- anchors.centerIn: parent
1079- text: name
1080- }
1081- }
1082- }
1083- }
1084-
1085- UT.UnityTestCase {
1086- name: "FilterGrid"
1087- when: windowShown
1088-
1089- function init() {
1090- filterGrid.model = fakeModel
1091- }
1092-
1093- function cleanup() {
1094- filterCheckBox.checked = true
1095- collapsedRowCountSelector.selectedIndex = 1
1096- }
1097-
1098- function test_turningFilterOffShowsAllElements() {
1099- tryCompareFunction(countVisibleDelegates, 6)
1100-
1101- filterCheckBox.checked = false
1102-
1103- tryCompareFunction(countVisibleDelegates, 12)
1104- }
1105-
1106- function test_collapsedRowCount() {
1107- for (var i = 0; i < 4; ++i) {
1108- collapsedRowCountSelector.selectedIndex = i
1109- // We have 3 elements per row.
1110- // row count == index + 1
1111- tryCompareFunction(countVisibleDelegates, 3*(i+1))
1112- }
1113- }
1114-
1115- function test_modelSizeAffectsCollapsedRowCount_data() {
1116- return [
1117- { tag: "2 items, collapsedRows 1", model: fakeModelTwoItems, collapsedRowCountIndex: 0,
1118- rowsWhenCollapsed: 1, visibleDelegates: 2 },
1119- { tag: "2 items, collapsedRows 2", model: fakeModelTwoItems, collapsedRowCountIndex: 1,
1120- rowsWhenCollapsed: 1, visibleDelegates: 2 },
1121- { tag: "4 items, collapsedRows 1", model: fakeModelFourItems, collapsedRowCountIndex: 0,
1122- rowsWhenCollapsed: 1, visibleDelegates: 3 },
1123- { tag: "4 items, collapsedRows 2", model: fakeModelFourItems, collapsedRowCountIndex: 1,
1124- rowsWhenCollapsed: 2, visibleDelegates: 4 },
1125- ]
1126- }
1127-
1128- function test_modelSizeAffectsCollapsedRowCount(data) {
1129- filterGrid.model = data.model
1130- collapsedRowCountSelector.selectedIndex = data.collapsedRowCountIndex
1131-
1132- tryCompare(filterGrid, "rowsWhenCollapsed", data.rowsWhenCollapsed)
1133- tryCompareFunction(countVisibleDelegates, data.visibleDelegates)
1134- }
1135-
1136- function countVisibleDelegates() {
1137- return __countVisibleDelegates(filterGrid.visibleChildren, 0)
1138- }
1139-
1140- function __countVisibleDelegates(objList, total) {
1141- for (var i = 0; i < objList.length; ++i) {
1142- var child = objList[i];
1143- if (child.isGridDelegate !== undefined) {
1144- ++total;
1145- } else {
1146- total = __countVisibleDelegates(child.visibleChildren, total)
1147- }
1148- }
1149- return total
1150- }
1151- }
1152-}
1153
1154=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
1155--- tests/qmltests/Dash/tst_Dash.qml 2014-07-03 11:15:16 +0000
1156+++ tests/qmltests/Dash/tst_Dash.qml 2014-07-21 23:38:21 +0000
1157@@ -86,7 +86,7 @@
1158 tryCompare(dashContentList, "count", 0);
1159 scopes.load();
1160 tryCompare(scopes, "loaded", true);
1161- tryCompare(dashContentList, "count", 3);
1162+ tryCompare(dashContentList, "count", 4);
1163
1164 verify(dashContentList != undefined);
1165 tryCompare(dashContentList, "currentIndex", data.visualIndex);
1166
1167=== modified file 'tests/qmltests/Dash/tst_DashContent.qml'
1168--- tests/qmltests/Dash/tst_DashContent.qml 2014-07-15 08:22:19 +0000
1169+++ tests/qmltests/Dash/tst_DashContent.qml 2014-07-21 23:38:21 +0000
1170@@ -61,6 +61,11 @@
1171 signalName: "movementStarted"
1172 }
1173
1174+ SignalSpy {
1175+ id: loadedSpy
1176+ signalName: "loaded"
1177+ }
1178+
1179 UT.UnityTestCase {
1180 name: "DashContent"
1181 when: scopesModel.loaded && windowShown
1182@@ -78,6 +83,7 @@
1183
1184 function cleanup() {
1185 movementStartedSpy.clear();
1186+ loadedSpy.clear();
1187 dashContent.visible = true;
1188
1189 var dashContentList = findChild(dashContent, "dashContentList");
1190@@ -116,10 +122,11 @@
1191
1192 function test_show_header_on_list_movement() {
1193 var dashContentList = findChild(dashContent, "dashContentList");
1194- verify(dashContentList != undefined);
1195- var categoryListView = findChild(dashContentList, "categoryListView");
1196- verify(categoryListView != undefined);
1197+ verify(dashContentList !== null);
1198+ var scope = findChild(dashContent, "MockScope1 loader");
1199+ waitForRendering(scope);
1200
1201+ var categoryListView = findChild(scope, "categoryListView");
1202 waitForRendering(categoryListView);
1203
1204 categoryListView.contentY = units.gu(15);
1205@@ -133,10 +140,12 @@
1206
1207 function test_set_current_scope_reset() {
1208 var dashContentList = findChild(dashContent, "dashContentList");
1209- verify(dashContentList != undefined);
1210+ verify(dashContentList, "Couldn't find dashContentList");
1211+ var scope = findChild(dashContent, "MockScope1 loader");
1212+
1213+ tryCompare(scope, "status", Loader.Ready);
1214+
1215 var categoryListView = findChild(dashContentList, "categoryListView");
1216- verify(categoryListView != undefined);
1217-
1218 categoryListView.contentY = units.gu(10);
1219
1220 compare(dashContentList.currentItem.item.objectName, "MockScope1")
1221
1222=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
1223--- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-07-14 14:15:25 +0000
1224+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-07-21 23:38:21 +0000
1225@@ -54,12 +54,13 @@
1226 when: scopes.loaded && windowShown
1227
1228 property Item previewListView: findChild(genericScopeView, "previewListView")
1229+ property Item header: findChild(genericScopeView, "scopePageHeader")
1230
1231 function init() {
1232 genericScopeView.scope = scopes.getScope(1)
1233 shell.width = units.gu(120)
1234 genericScopeView.categoryView.positionAtBeginning();
1235- tryCompare(genericScopeView.categoryView, "contentY", 0)
1236+ waitForRendering(genericScopeView.categoryView);
1237 }
1238
1239 function test_isActive() {
1240@@ -105,8 +106,6 @@
1241 }
1242
1243 function test_filter_expand_collapse() {
1244- // wait for the item to be there
1245- waitForRendering(genericScopeView);
1246 tryCompareFunction(function() { return findChild(genericScopeView, "dashSectionHeader0") != null; }, true);
1247
1248 var header = findChild(genericScopeView, "dashSectionHeader0")
1249@@ -114,18 +113,18 @@
1250
1251 waitForRendering(header);
1252 verify(category.expandable);
1253- verify(category.filtered);
1254+ verify(!category.expanded);
1255
1256 var initialHeight = category.height;
1257 var middleHeight;
1258 mouseClick(header, header.width / 2, header.height / 2);
1259 tryCompareFunction(function() { middleHeight = category.height; return category.height > initialHeight; }, true);
1260- tryCompare(category, "filtered", false);
1261+ tryCompare(category, "expanded", true);
1262 tryCompareFunction(function() { return category.height > middleHeight; }, true);
1263
1264 mouseClick(header, header.width / 2, header.height / 2);
1265 verify(category.expandable);
1266- tryCompare(category, "filtered", true);
1267+ tryCompare(category, "expanded", false);
1268 }
1269
1270 function test_filter_expand_expand_collapse() {
1271@@ -137,51 +136,75 @@
1272
1273 var header2 = findChild(genericScopeView, "dashSectionHeader2")
1274 var category2 = findChild(genericScopeView, "dashCategory2")
1275- var category2FilterGrid = category2.children[1].children[2];
1276- verify(UT.Util.isInstanceOf(category2FilterGrid, "CardFilterGrid"));
1277
1278 waitForRendering(header2);
1279 verify(category2.expandable);
1280- verify(category2.filtered);
1281+ verify(!category2.expanded);
1282
1283 mouseClick(header2, header2.width / 2, header2.height / 2);
1284- tryCompare(category2, "filtered", false);
1285- tryCompare(category2FilterGrid, "filtered", false);
1286+ tryCompare(category2, "expanded", true);
1287
1288 categoryListView.positionAtBeginning();
1289
1290 var header0 = findChild(genericScopeView, "dashSectionHeader0")
1291 var category0 = findChild(genericScopeView, "dashCategory0")
1292 mouseClick(header0, header0.width / 2, header0.height / 2);
1293- tryCompare(category0, "filtered", false);
1294- tryCompare(category2, "filtered", true);
1295- tryCompare(category2FilterGrid, "filtered", true);
1296+ tryCompare(category0, "expanded", true);
1297+ tryCompare(category2, "expanded", false);
1298 mouseClick(header0, header0.width / 2, header0.height / 2);
1299- tryCompare(category0, "filtered", true);
1300- tryCompare(category2, "filtered", true);
1301+ tryCompare(category0, "expanded", false);
1302+ tryCompare(category2, "expanded", false);
1303 }
1304
1305 function test_narrow_delegate_ranges_expand() {
1306- tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
1307+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") !== null; }, true);
1308 var category = findChild(genericScopeView, "dashCategory0")
1309- tryCompare(category, "filtered", true);
1310+ tryCompare(category, "expanded", false);
1311
1312 shell.width = units.gu(20)
1313 var categoryListView = findChild(genericScopeView, "categoryListView");
1314 categoryListView.contentY = units.gu(20);
1315 var header0 = findChild(genericScopeView, "dashSectionHeader0")
1316 mouseClick(header0, header0.width / 2, header0.height / 2);
1317- tryCompare(category, "filtered", false);
1318+ tryCompare(category, "expanded", true);
1319 tryCompareFunction(function() { return category.item.height == genericScopeView.height - category.item.displayMarginBeginning - category.item.displayMarginEnd; }, true);
1320 mouseClick(header0, header0.width / 2, header0.height / 2);
1321- tryCompare(category, "filtered", true);
1322+ tryCompare(category, "expanded", false);
1323+ }
1324+
1325+ function test_forced_category_expansion() {
1326+ tryCompareFunction(function() {
1327+ mouseFlick(genericScopeView, genericScopeView.width/2, genericScopeView.height,
1328+ genericScopeView.width/2, genericScopeView.y)
1329+ return findChild(genericScopeView, "dashCategory19") !== null;
1330+ }, true);
1331+ var category = findChild(genericScopeView, "dashCategory19")
1332+ compare(category.expandable, false, "Category with collapsed-rows: 0 should not be expandable");
1333+
1334+ var grid = findChild(category, "19");
1335+ verify(grid, "Could not find the category renderer.");
1336+
1337+ compare(grid.height, grid.expandedHeight, "Category with collapsed-rows: 0 should always be expanded.");
1338+ }
1339+
1340+ function test_single_category_expansion() {
1341+ genericScopeView.scope = scopes.getScope(4);
1342+
1343+ tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
1344+ var category = findChild(genericScopeView, "dashCategory0")
1345+ compare(category.expandable, false, "Only category should not be expandable.");
1346+
1347+ var grid = findChild(category, "0");
1348+ verify(grid, "Could not find the category renderer.");
1349+
1350+ compare(grid.height, grid.expandedHeight, "Only category should always be expanded");
1351 }
1352
1353 function openPreview() {
1354 tryCompareFunction(function() {
1355- var filterGrid = findChild(genericScopeView, "0");
1356- if (filterGrid != null) {
1357- var tile = findChild(filterGrid, "delegate0");
1358+ var cardGrid = findChild(genericScopeView, "0");
1359+ if (cardGrid != null) {
1360+ var tile = findChild(cardGrid, "delegate0");
1361 return tile != null;
1362 }
1363 return false;
1364@@ -257,13 +280,33 @@
1365 closePreview();
1366 }
1367
1368- function test_haeder_logo() {
1369- genericScopeView.scope = scopes.getScope(3);
1370+ function test_header_style_data() {
1371+ return [
1372+ { tag: "Default", index: 0, foreground: "grey", background: "", logo: "" },
1373+ { tag: "Foreground", index: 2, foreground: "yellow", background: "", logo: "" },
1374+ { tag: "Logo+Background", index: 3, foreground: "grey", background: "gradient:///lightgrey/grey",
1375+ logo: Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg") },
1376+ ];
1377+ }
1378+
1379+ function test_header_style(data) {
1380+ genericScopeView.scope = scopes.getScope(data.index);
1381+ waitForRendering(genericScopeView);
1382+ verify(header, "Could not find the header.");
1383+
1384+ var innerHeader = findChild(header, "innerPageHeader");
1385+ verify(innerHeader, "Could not find the inner header");
1386+ verify(Qt.colorEqual(innerHeader.textColor, data.foreground),
1387+ "Foreground color not equal: %1 != %2".arg(innerHeader.textColor).arg(data.foreground));
1388+
1389+ var background = findChild(header, "headerBackground");
1390+ verify(background, "Could not find the background");
1391+ compare(background.style, data.background);
1392
1393 var image = findChild(genericScopeView, "titleImage");
1394- verify(image, "Could not find the title image");
1395- compare(image.source, Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg"), "Title image has the wrong source");
1396-
1397+ if (data.logo == "") expectFail(data.tag, "Title image should not exist.");
1398+ verify(image, "Could not find the title image.");
1399+ compare(image.source, data.logo, "Title image has the wrong source");
1400 }
1401 }
1402 }

Subscribers

People subscribed via source and target branches