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

Proposed by Albert Astals Cid
Status: Superseded
Proposed branch: lp:~aacid/unity8/filtergrid_bindingloop
Merge into: lp:unity8
Diff against target: 887 lines (+328/-182)
13 files modified
cmake/modules/QmlTest.cmake (+16/-1)
qml/Components/FilterGrid.qml (+40/-23)
qml/Dash/Card.qml (+109/-89)
qml/Dash/CardCarousel.qml (+1/-1)
qml/Dash/CardFilterGrid.qml (+5/-10)
qml/Dash/CardHeader.qml (+42/-32)
qml/Dash/DashRenderer.qml (+1/-4)
qml/Dash/GenericScopeView.qml (+5/-10)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Components/tst_FilterGrid.qml (+1/-1)
tests/qmltests/Dash/tst_Card.qml (+12/-10)
tests/qmltests/Dash/tst_CardBenchmark.qml (+94/-0)
tests/qmltests/Dash/tst_CardHeader.qml (+1/-1)
To merge this branch: bzr merge lp:~aacid/unity8/filtergrid_bindingloop
Reviewer Review Type Date Requested Status
Unity Team Pending
Review via email: mp+216145@code.launchpad.net

This proposal has been superseded by a proposal from 2014-04-16.

Commit message

Fix binding loop in FilterGrid height

To post a comment you must log in.
832. By Albert Astals Cid

A bit more of reog

833. By Albert Astals Cid

reog++

834. By Albert Astals Cid

reorg++

835. By Albert Astals Cid

don't need the id anymroe

836. By Albert Astals Cid

property rename

837. By Albert Astals Cid

Merge

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmake/modules/QmlTest.cmake'
2--- cmake/modules/QmlTest.cmake 2014-04-02 12:08:51 +0000
3+++ cmake/modules/QmlTest.cmake 2014-04-16 15:47:25 +0000
4@@ -58,7 +58,15 @@
5
6 endmacro(add_manual_qml_test)
7
8+macro(add_qml_benchmark SUBPATH COMPONENT_NAME ITERATIONS)
9+ add_qml_test_internal(${SUBPATH} ${COMPONENT_NAME} ${ITERATIONS} ${ARGN})
10+endmacro(add_qml_benchmark)
11+
12 macro(add_qml_test SUBPATH COMPONENT_NAME)
13+ add_qml_test_internal(${SUBPATH} ${COMPONENT_NAME} 0 ${ARGN})
14+endmacro(add_qml_test)
15+
16+macro(add_qml_test_internal SUBPATH COMPONENT_NAME ITERATIONS)
17 set(options NO_ADD_TEST NO_TARGETS)
18 set(multi_value_keywords IMPORT_PATHS TARGETS PROPERTIES ENVIRONMENT)
19
20@@ -88,10 +96,17 @@
21 set(function_ARGS "")
22 endif()
23
24+ if (${ITERATIONS} GREATER 0)
25+ set(ITERATIONS_STRING "-iterations" ${ITERATIONS})
26+ else()
27+ set(ITERATIONS_STRING "")
28+ endif()
29+
30 set(qmltest_command
31 env ${qmltest_ENVIRONMENT}
32 ${qmltestrunner_exe} -input ${CMAKE_CURRENT_SOURCE_DIR}/${qmltest_FILE}.qml
33 ${qmltestrunner_imports}
34+ ${ITERATIONS_STRING}
35 -o ${CMAKE_BINARY_DIR}/${qmltest_TARGET}.xml,xunitxml
36 -o -,txt
37 ${function_ARGS}
38@@ -114,7 +129,7 @@
39 add_qmltest_target(${qmltest_TARGET} "${qmltest_command}" TRUE ${qmltest_NO_ADD_TEST})
40 add_qmltest_target(${qmltest_xvfb_TARGET} "${qmltest_xvfb_command}" ${qmltest_NO_TARGETS} TRUE)
41 add_manual_qml_test(${SUBPATH} ${COMPONENT_NAME} ${ARGN})
42-endmacro(add_qml_test)
43+endmacro(add_qml_test_internal)
44
45 macro(add_binary_qml_test CLASS_NAME LD_PATH DEPS)
46 set(testCommand
47
48=== modified file 'qml/Components/FilterGrid.qml'
49--- qml/Components/FilterGrid.qml 2014-04-08 13:32:59 +0000
50+++ qml/Components/FilterGrid.qml 2014-04-16 15:47:25 +0000
51@@ -28,10 +28,13 @@
52 Item {
53 id: root
54
55- /* If true, the number of elements displayed will be limited by collapsedRowCount.
56- If false, all elements will be displayed, effectively looking the same as a regular
57- ResponsiveGridView. */
58- property bool filter: true
59+ QtObject {
60+ id: d
61+ /* If true, the number of elements displayed will be limited by collapsedRowCount.
62+ If false, all elements will be displayed, effectively looking the same as a regular
63+ ResponsiveGridView. Manipulate this property through setFilter */
64+ property bool filter: true
65+ }
66
67 /* Whether, when collapsed, a button should be displayed enabling the user to expand
68 the grid to its full size. */
69@@ -66,29 +69,35 @@
70 property alias highlightIndex: iconTileGrid.highlightIndex
71 readonly property alias currentItem: iconTileGrid.currentItem
72
73- height: !filterAnimation.running ? childrenRect.height : height
74+ height: filter ? root.collapsedHeight : root.uncollapsedHeight
75 clip: filterAnimation.running
76
77- NumberAnimation {
78- property bool filterEndValue
79- id: filterAnimation
80- target: root
81- property: "height"
82- to: filterEndValue ? root.collapsedHeight : root.uncollapsedHeight
83- // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
84- // otherwise since both animations can run at the same time you'll get
85- // some visual weirdness.
86- duration: 200
87- easing.type: Easing.InOutQuad
88- onStopped: {
89- root.filter = filterEndValue;
90+ Behavior on height {
91+ id: heightBehaviour
92+ enabled: false
93+ NumberAnimation {
94+ id: filterAnimation
95+ // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
96+ // otherwise since both animations can run at the same time you'll get
97+ // some visual weirdness.
98+ duration: 200
99+ easing.type: Easing.InOutQuad
100+ onRunningChanged: {
101+ if (!running) {
102+ limitModel.filter = d.filter;
103+ }
104+ heightBehaviour.enabled = false;
105+ }
106 }
107 }
108
109- function startFilterAnimation(filter) {
110- filterAnimation.filterEndValue = filter
111- filterAnimation.start();
112- }
113+ function setFilter(filter, animate) {
114+ heightBehaviour.enabled = animate;
115+ d.filter = filter;
116+ if (!animate || !filter) {
117+ limitModel.filter = filter;
118+ }
119+ }
120
121 ResponsiveGridView {
122 id: iconTileGrid
123@@ -104,8 +113,16 @@
124 verticalSpacing: units.gu(2)
125
126 model: LimitProxyModel {
127+ id: limitModel
128+ // We do have another filter property here because
129+ // we can't directly use filter from the root since we need to decouple
130+ // the real filtering with the animation since the closing animation
131+ // i.e. filter=false we still need to not be filtering until
132+ // t he animation finishes otherwise we hide the items when the animation
133+ // is still running
134+ property bool filter: true
135 model: root.model
136- limit: (filter && !filterAnimation.running) ? rowsWhenCollapsed * iconTileGrid.columns : -1
137+ limit: filter ? rowsWhenCollapsed * iconTileGrid.columns : -1
138 }
139 }
140 }
141
142=== modified file 'qml/Dash/Card.qml'
143--- qml/Dash/Card.qml 2014-04-01 22:56:38 +0000
144+++ qml/Dash/Card.qml 2014-04-16 15:47:25 +0000
145@@ -25,47 +25,53 @@
146 property var components
147 property var cardData
148
149- property alias fontScale: header.fontScale
150- property alias headerAlignment: header.headerAlignment
151- property alias headerHeight: header.height
152- readonly property alias title: header.title
153+ property real fontScale: 1.0
154+ property int headerAlignment: Text.AlignLeft
155+ readonly property int headerHeight: headerLoader.item ? headerLoader.item.height : 0
156+ property int fixedHeaderHeight: -1
157+ readonly property string title: cardData && cardData["title"] || ""
158
159 property bool showHeader: true
160
161 implicitWidth: childrenRect.width
162- implicitHeight: summary.y + summary.height + (summary.text && background.visible ? units.gu(1) : 0)
163-
164- UbuntuShape {
165- id: background
166- objectName: "background"
167- radius: "medium"
168- visible: template["card-layout"] !== "horizontal" && (template["card-background"] || components["background"]
169- || artAndSummary)
170- property bool artAndSummary: components["art"]["field"] && components["summary"] || false
171- color: getColor(0) || "white"
172- gradientColor: getColor(1) || color
173+ implicitHeight: summary.y + summary.height + (summary.text && backgroundLoader.active ? units.gu(1) : 0)
174+
175+ Loader {
176+ id: backgroundLoader
177+ objectName: "backgroundLoader"
178+
179+ readonly property bool artAndSummary: components["art"]["field"] && components["summary"] || false
180+ active: template["card-layout"] !== "horizontal" && (template["card-background"] || components["background"] || artAndSummary)
181 anchors.fill: parent
182- image: backgroundImage.source ? backgroundImage : null
183-
184- property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b
185-
186- property Image backgroundImage: Image {
187- objectName: "backgroundImage"
188- source: {
189- if (cardData && typeof cardData["background"] === "string") return cardData["background"]
190- else if (template && typeof template["card-background"] === "string") return template["card-background"]
191- else return ""
192- }
193- }
194-
195- function getColor(index) {
196- if (cardData && typeof cardData["background"] === "object"
197- && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
198- return cardData["background"]["elements"][index];
199- } else if (template && typeof template["card-background"] === "object"
200- && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
201- return template["card-background"]["elements"][index];
202- } else return undefined;
203+
204+ sourceComponent: UbuntuShape {
205+ objectName: "background"
206+ radius: "medium"
207+ color: getColor(0) || "white"
208+ gradientColor: getColor(1) || color
209+ anchors.fill: parent
210+ image: backgroundImage.source ? backgroundImage : null
211+
212+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b
213+
214+ property Image backgroundImage: Image {
215+ objectName: "backgroundImage"
216+ source: {
217+ if (cardData && typeof cardData["background"] === "string") return cardData["background"]
218+ else if (template && typeof template["card-background"] === "string") return template["card-background"]
219+ else return ""
220+ }
221+ }
222+
223+ function getColor(index) {
224+ if (cardData && typeof cardData["background"] === "object"
225+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
226+ return cardData["background"]["elements"][index];
227+ } else if (template && typeof template["card-background"] === "object"
228+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
229+ return template["card-background"]["elements"][index];
230+ } else return undefined;
231+ }
232 }
233 }
234
235@@ -111,7 +117,7 @@
236 function updateWidthHeightBindings() {
237 if (isHorizontal) {
238 width = Qt.binding(function() { return height * artShape.aspect });
239- height = Qt.binding(function() { return header.height });
240+ height = Qt.binding(function() { return root.headerHeight });
241 } else {
242 width = Qt.binding(function() { return root.width });
243 height = Qt.binding(function() { return width / artShape.aspect });
244@@ -120,53 +126,58 @@
245 }
246 }
247
248- ShaderEffect {
249- id: overlay
250+ Loader {
251+ id: overlayLoader
252 anchors {
253 left: artShape.left
254 right: artShape.right
255 bottom: artShape.bottom
256 }
257-
258- height: header.height
259- opacity: header.opacity * 0.6
260- visible: template && template["overlay"] && artShape.visible && artShape.image.status === Image.Ready || false
261-
262- property var source: ShaderEffectSource {
263- id: shaderSource
264- sourceItem: artShape
265- onVisibleChanged: if (visible) scheduleUpdate()
266- live: false
267- sourceRect: Qt.rect(0, artShape.height - overlay.height, artShape.width, overlay.height)
268+ active: template && template["overlay"] && artShape.visible && artShape.image.status === Image.Ready || false
269+
270+ sourceComponent: ShaderEffect {
271+ id: overlay
272+
273+ height: headerLoader.item ? headerLoader.item.height : 0
274+ opacity: headerLoader.item ? headerLoader.item.opacity * 0.6 : 0
275+
276+ property var source: ShaderEffectSource {
277+ id: shaderSource
278+ sourceItem: artShape
279+ onVisibleChanged: if (visible) scheduleUpdate()
280+ live: false
281+ sourceRect: Qt.rect(0, artShape.height - overlay.height, artShape.width, overlay.height)
282+ }
283+
284+ vertexShader: "
285+ uniform highp mat4 qt_Matrix;
286+ attribute highp vec4 qt_Vertex;
287+ attribute highp vec2 qt_MultiTexCoord0;
288+ varying highp vec2 coord;
289+ void main() {
290+ coord = qt_MultiTexCoord0;
291+ gl_Position = qt_Matrix * qt_Vertex;
292+ }"
293+
294+ fragmentShader: "
295+ varying highp vec2 coord;
296+ uniform sampler2D source;
297+ uniform lowp float qt_Opacity;
298+ void main() {
299+ lowp vec4 tex = texture2D(source, coord);
300+ gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
301+ }"
302 }
303-
304- vertexShader: "
305- uniform highp mat4 qt_Matrix;
306- attribute highp vec4 qt_Vertex;
307- attribute highp vec2 qt_MultiTexCoord0;
308- varying highp vec2 coord;
309- void main() {
310- coord = qt_MultiTexCoord0;
311- gl_Position = qt_Matrix * qt_Vertex;
312- }"
313-
314- fragmentShader: "
315- varying highp vec2 coord;
316- uniform sampler2D source;
317- uniform lowp float qt_Opacity;
318- void main() {
319- lowp vec4 tex = texture2D(source, coord);
320- gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
321- }"
322 }
323
324- CardHeader {
325- id: header
326- objectName: "cardHeader"
327+ Loader {
328+ id: headerLoader
329+ objectName: "cardHeaderLoader"
330+
331 anchors {
332 top: {
333 if (template) {
334- if (template["overlay"]) return overlay.top;
335+ if (template["overlay"]) return overlayLoader.top;
336 if (template["card-layout"] === "horizontal") return artShape.top;
337 }
338 return artShape.bottom;
339@@ -179,29 +190,38 @@
340 }
341 right: parent.right
342 }
343-
344- mascot: cardData && cardData["mascot"] || ""
345- title: cardData && cardData["title"] || ""
346- subtitle: cardData && cardData["subtitle"] || ""
347-
348- titleWeight: components && components["subtitle"] ? Font.DemiBold : Font.Normal
349-
350- opacity: showHeader ? 1 : 0
351- inOverlay: root.template && root.template["overlay"] === true
352- fontColor: inOverlay ? "white" : summary.color
353- useMascotShape: !background.visible && !inOverlay
354-
355- Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
356+ active: cardData && cardData["title"] || cardData && cardData["mascot"] || false
357+
358+ sourceComponent: CardHeader {
359+ id: header
360+ objectName: "cardHeader"
361+
362+ mascot: cardData && cardData["mascot"] || ""
363+ title: root.title
364+ subtitle: cardData && cardData["subtitle"] || ""
365+
366+ titleWeight: components && components["subtitle"] ? Font.DemiBold : Font.Normal
367+
368+ opacity: showHeader ? 1 : 0
369+ inOverlay: root.template && root.template["overlay"] === true
370+ fontColor: inOverlay ? "white" : summary.color
371+ useMascotShape: !backgroundLoader.active && !inOverlay
372+ headerAlignment: root.headerAlignment
373+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight
374+ fontScale: root.fontScale
375+
376+ Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
377+ }
378 }
379
380 Label {
381 id: summary
382 objectName: "summaryLabel"
383 anchors {
384- top: header.visible ? header.bottom : artShape.bottom
385+ top: headerLoader.active ? headerLoader.bottom : artShape.bottom
386 left: parent.left
387 right: parent.right
388- margins: background.visible ? units.gu(1) : 0
389+ margins: backgroundLoader.active ? units.gu(1) : 0
390 topMargin: 0
391 }
392 wrapMode: Text.Wrap
393@@ -211,6 +231,6 @@
394 height: text ? implicitHeight : 0
395 fontSize: "small"
396 // TODO karni: Change "grey" to Ubuntu.Components.Palette color once updated.
397- color: background.visible && background.luminance < 0.7 ? "white" : "grey"
398+ color: backgroundLoader.active && backgroundLoader.item.luminance < 0.7 ? "white" : "grey"
399 }
400 }
401
402=== modified file 'qml/Dash/CardCarousel.qml'
403--- qml/Dash/CardCarousel.qml 2014-03-17 10:38:03 +0000
404+++ qml/Dash/CardCarousel.qml 2014-04-16 15:47:25 +0000
405@@ -52,7 +52,7 @@
406 itemComponent: Card {
407 id: card
408 objectName: "carouselDelegate" + index
409- headerHeight: carousel.headerHeight
410+ fixedHeaderHeight: carousel.headerHeight
411 cardData: model
412 template: cardTool.template
413 components: cardTool.components
414
415=== modified file 'qml/Dash/CardFilterGrid.qml'
416--- qml/Dash/CardFilterGrid.qml 2014-04-08 13:32:59 +0000
417+++ qml/Dash/CardFilterGrid.qml 2014-04-16 15:47:25 +0000
418@@ -29,8 +29,8 @@
419 currentItem: filterGrid.currentItem
420 height: filterGrid.height
421
422- function startFilterAnimation(filter) {
423- filterGrid.startFilterAnimation(filter)
424+ function setFilter(filter, animate) {
425+ filterGrid.setFilter(filter, animate)
426 }
427
428 FilterGrid {
429@@ -41,18 +41,18 @@
430 delegateHeight: cardTool.cardHeight
431 verticalSpacing: genericFilterGrid.verticalSpacing
432 model: genericFilterGrid.model
433- filter: genericFilterGrid.filter
434 collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
435 delegateCreationBegin: genericFilterGrid.delegateCreationBegin
436 delegateCreationEnd: genericFilterGrid.delegateCreationEnd
437- delegate: Item {
438+ delegate: Loader {
439+ asynchronous: true
440 width: filterGrid.cellWidth
441 height: filterGrid.cellHeight
442 Card {
443 id: card
444 width: cardTool.cardWidth
445 height: cardTool.cardHeight
446- headerHeight: cardTool.headerHeight
447+ fixedHeaderHeight: cardTool.headerHeight
448 anchors.horizontalCenter: parent.horizontalCenter
449 objectName: "delegate" + index
450 cardData: model
451@@ -65,10 +65,5 @@
452 onPressAndHold: genericFilterGrid.pressAndHold(index, card.y)
453 }
454 }
455-
456- onFilterChanged: {
457- genericFilterGrid.filter = filter
458- filter = Qt.binding(function() { return genericFilterGrid.filter })
459- }
460 }
461 }
462
463=== modified file 'qml/Dash/CardHeader.qml'
464--- qml/Dash/CardHeader.qml 2014-03-17 11:42:38 +0000
465+++ qml/Dash/CardHeader.qml 2014-04-16 15:47:25 +0000
466@@ -19,9 +19,9 @@
467
468 Item {
469 id: root
470- property alias mascot: mascotImage.source
471+ property url mascot: ""
472 property alias title: titleLabel.text
473- property alias subtitle: subtitleLabel.text
474+ property var subtitle
475
476 property alias titleWeight: titleLabel.font.weight
477 property alias titleSize: titleLabel.fontSize
478@@ -35,8 +35,8 @@
479 property bool useMascotShape: true
480 property color fontColor: Theme.palette.selected.backgroundText
481
482- visible: mascotImage.status === Image.Ready || title
483- height: row.height > 0 ? row.height + row.margins * 2 : 0
484+ visible: mascot != "" || title
485+ implicitHeight: row.height > 0 ? row.height + row.margins * 2 : 0
486
487 Row {
488 id: row
489@@ -44,7 +44,7 @@
490
491 property real margins: units.gu(1)
492
493- spacing: mascotShape.visible || mascotImage.visible || inOverlay ? margins : 0
494+ spacing: mascotShapeLoader.active || mascotImageLoader.active || inOverlay ? margins : 0
495 anchors {
496 top: parent.top; left: parent.left; right: parent.right
497 margins: margins
498@@ -52,33 +52,40 @@
499 rightMargin: spacing
500 }
501
502- UbuntuShape {
503- id: mascotShape
504- objectName: "mascotShape"
505+ Loader {
506+ id: mascotShapeLoader
507+ objectName: "mascotShapeLoader"
508
509+ active: useMascotShape && mascotImageLoader.item && mascotImageLoader.item.status === Image.Ready
510+ visible: active
511+ anchors.verticalCenter: parent.verticalCenter
512 // TODO karni: Icon aspect-ratio is 8:7.5. Revisit these values to avoid fraction of pixels.
513 width: units.gu(6)
514 height: units.gu(5.625)
515- anchors.verticalCenter: parent.verticalCenter
516- visible: useMascotShape && image && image.status === Image.Ready
517 readonly property int maxSize: Math.max(width, height) * 4
518
519- image: useMascotShape ? mascotImage : null
520+ sourceComponent: UbuntuShape {
521+ image: mascotImageLoader.item
522+ }
523 }
524
525- Image {
526- id: mascotImage
527- objectName: "mascotImage"
528-
529- width: source ? mascotShape.width : 0
530- height: mascotShape.height
531+ Loader {
532+ id: mascotImageLoader
533+ active: root.mascot != ""
534+ visible: active && !useMascotShape && item.status === Image.Ready
535 anchors.verticalCenter: parent.verticalCenter
536- visible: !useMascotShape && status === Image.Ready
537-
538- sourceSize { width: mascotShape.maxSize; height: mascotShape.maxSize }
539- fillMode: Image.PreserveAspectCrop
540- horizontalAlignment: Image.AlignHCenter
541- verticalAlignment: Image.AlignVCenter
542+ sourceComponent: Image {
543+ objectName: "mascotImage"
544+
545+ source: root.mascot
546+ width: source ? mascotShapeLoader.width : 0
547+ height: mascotShapeLoader.height
548+
549+ sourceSize { width: mascotShapeLoader.maxSize; height: mascotShapeLoader.maxSize }
550+ fillMode: Image.PreserveAspectCrop
551+ horizontalAlignment: Image.AlignHCenter
552+ verticalAlignment: Image.AlignVCenter
553+ }
554 }
555
556 Column {
557@@ -100,16 +107,19 @@
558 color: fontColor
559 }
560
561- Label {
562- id: subtitleLabel
563- objectName: "subtitleLabel"
564+ Loader {
565+ active: titleLabel.text && root.subtitle
566 anchors { left: parent.left; right: parent.right }
567- elide: Text.ElideRight
568- fontSize: "small"
569- font.weight: Font.Light
570- visible: titleLabel.text && text
571- font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
572- color: fontColor
573+ sourceComponent: Label {
574+ id: subtitleLabel
575+ objectName: "subtitleLabel"
576+ elide: Text.ElideRight
577+ fontSize: "small"
578+ font.weight: Font.Light
579+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale)
580+ color: fontColor
581+ text: root.subtitle
582+ }
583 }
584 }
585 }
586
587=== modified file 'qml/Dash/DashRenderer.qml'
588--- qml/Dash/DashRenderer.qml 2014-04-08 13:32:59 +0000
589+++ qml/Dash/DashRenderer.qml 2014-04-16 15:47:25 +0000
590@@ -20,9 +20,6 @@
591 // Can the item be expanded?
592 property bool expandable: false
593
594- // In case it can be expanded, should we filter it
595- property bool filter: true
596-
597 property int collapsedHeight: height
598
599 property int margins: 0
600@@ -58,6 +55,6 @@
601 /// @param itemY is y of the held delegate
602 signal pressAndHold(int index, real itemY)
603
604- function startFilterAnimation(filter) {
605+ function setFilter(filter, animate) {
606 }
607 }
608
609=== modified file 'qml/Dash/GenericScopeView.qml'
610--- qml/Dash/GenericScopeView.qml 2014-04-08 13:32:59 +0000
611+++ qml/Dash/GenericScopeView.qml 2014-04-16 15:47:25 +0000
612@@ -121,7 +121,7 @@
613 showDivider: false
614
615 readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
616- readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filter : true
617+ readonly property bool filtered: categoryView.expandedCategoryId != categoryId
618 readonly property string category: categoryId
619 readonly property var item: rendererLoader.item
620
621@@ -167,9 +167,7 @@
622 item.objectName = Qt.binding(function() { return categoryId })
623 if (item.expandable) {
624 var shouldFilter = categoryId != categoryView.expandedCategoryId;
625- if (shouldFilter != item.filter) {
626- item.filter = shouldFilter;
627- }
628+ item.setFilter(shouldFilter, false /*animate*/);
629 }
630 updateDelegateCreationRange();
631 item.cardTool = cardTool;
632@@ -218,11 +216,8 @@
633 var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
634 var growingVisible = !shouldFilter && y + height < categoryView.height;
635 if (!previewListView.open || !shouldFilter) {
636- if (shrinkingVisible || growingVisible) {
637- item.startFilterAnimation(shouldFilter)
638- } else {
639- item.filter = shouldFilter;
640- }
641+ var animate = shrinkingVisible || growingVisible;
642+ item.setFilter(shouldFilter, animate)
643 if (!shouldFilter && !previewListView.open) {
644 categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
645 }
646@@ -241,7 +236,7 @@
647 // to the stable position and delete/create items without any reason
648 if (categoryView.contentY < categoryView.originY) {
649 return;
650- } else if (categoryView.contentY + categoryView.height > categoryView.contentHeight) {
651+ } else if (categoryView.contentHeight > categoryView.height && categoryView.contentY + categoryView.height > categoryView.contentHeight) {
652 return;
653 }
654
655
656=== modified file 'tests/qmltests/CMakeLists.txt'
657--- tests/qmltests/CMakeLists.txt 2014-04-03 10:38:06 +0000
658+++ tests/qmltests/CMakeLists.txt 2014-04-16 15:47:25 +0000
659@@ -36,6 +36,7 @@
660 add_qml_test(Dash Dash IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
661 add_qml_test(Dash DashContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
662 add_qml_test(Dash Card)
663+add_qml_benchmark(Dash CardBenchmark 1000)
664 add_qml_test(Dash CardHeader)
665 add_qml_test(Dash CardTool)
666 add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
667
668=== modified file 'tests/qmltests/Components/tst_FilterGrid.qml'
669--- tests/qmltests/Components/tst_FilterGrid.qml 2014-01-29 13:37:23 +0000
670+++ tests/qmltests/Components/tst_FilterGrid.qml 2014-04-16 15:47:25 +0000
671@@ -50,6 +50,7 @@
672 CheckBox {
673 id: filterCheckBox
674 checked: true
675+ onCheckedChanged: filterGrid.setFilter(checked, false /*animate*/)
676 }
677 }
678 }
679@@ -99,7 +100,6 @@
680 maximumNumberOfColumns: 3
681 collapsedRowCount:
682 collapsedRowCountSelector.values[collapsedRowCountSelector.selectedIndex]
683- filter: filterCheckBox.checked
684 minimumHorizontalSpacing: units.gu(1)
685 delegateWidth: units.gu(6)
686 delegateHeight: units.gu(6)
687
688=== modified file 'tests/qmltests/Dash/tst_Card.qml'
689--- tests/qmltests/Dash/tst_Card.qml 2014-03-12 10:55:37 +0000
690+++ tests/qmltests/Dash/tst_Card.qml 2014-04-16 15:47:25 +0000
691@@ -182,11 +182,13 @@
692 when: windowShown
693
694 property Item header: findChild(card, "cardHeader")
695+ property Item headerLoader: findChild(card, "cardHeaderLoader")
696 property Item title: findChild(header, "titleLabel")
697 property Item art: findChild(card, "artShape")
698 property Item artImage: findChild(card, "artImage")
699 property Item summary: findChild(card, "summaryLabel")
700 property Item background: findChild(card, "background")
701+ property Item backgroundLoader: findChild(card, "backgroundLoader")
702 property Item backgroundImage: findChild(card, "backgroundImage")
703
704 function initTestCase() {
705@@ -244,8 +246,8 @@
706 { tag: "Wide", width: units.gu(18.5), aspect: 0.5, index: 0 },
707 { tag: "Horizontal", width: units.gu(38), index: 5 },
708 // Make sure card ends with header when there's no summary
709- { tag: "NoSummary", height: function() { return header.y + header.height }, index: 6 },
710- { tag: "HorizontalNoSummary", height: function() { return header.height }, card_layout: "horizontal", index: 6 },
711+ { tag: "NoSummary", height: function() { return headerLoader.y + headerLoader.height }, index: 6 },
712+ { tag: "HorizontalNoSummary", height: function() { return headerLoader.height }, card_layout: "horizontal", index: 6 },
713 ]
714 }
715
716@@ -288,7 +290,7 @@
717 { tag: "Fit", height: units.gu(38), size: "large", width: units.gu(19), index: 4 },
718 { tag: "VerticalWidth", width: function() { return header.width }, index: 0 },
719 { tag: "HorizontalHeight", height: function() { return header.height }, index: 5 },
720- { tag: "HorizontalWidth", width: function() { return header.x }, index: 5 },
721+ { tag: "HorizontalWidth", width: function() { return headerLoader.x }, index: 5 },
722 ]
723 }
724
725@@ -332,7 +334,7 @@
726 function test_art_layout(data) {
727 selector.selectedIndex = data.index;
728
729- tryCompare(testCase.header, "x", data.left());
730+ tryCompare(testCase.headerLoader, "x", data.left());
731 }
732
733 function test_header_layout_data() {
734@@ -349,13 +351,13 @@
735 function test_header_layout(data) {
736 selector.selectedIndex = data.index;
737
738- tryCompareFunction(function() { return testCase.header.y === data.top() }, true);
739- tryCompareFunction(function() { return testCase.header.x === data.left() }, true);
740+ tryCompareFunction(function() { return testCase.headerLoader.y === data.top() }, true);
741+ tryCompareFunction(function() { return testCase.headerLoader.x === data.left() }, true);
742 }
743
744 function test_summary_layout_data() {
745 return [
746- { tag: "With header", top: function() { return header.y + header.height }, index: 0 },
747+ { tag: "With header", top: function() { return headerLoader.y + headerLoader.height }, index: 0 },
748 { tag: "Without header", top: function() { return art.y + art.height }, index: 7 },
749 ]
750 }
751@@ -400,7 +402,7 @@
752
753 waitForRendering(card);
754
755- tryCompare(background, "visible", data.visible);
756+ tryCompare(backgroundLoader, "active", data.visible);
757
758 if (data.hasOwnProperty("color")) {
759 tryCompare(background, "color", data.color);
760@@ -467,13 +469,13 @@
761 function test_mascotShape(data) {
762 selector.selectedIndex = data.index;
763
764- var shape = findChild(card, "mascotShape");
765+ var shape = findChild(card, "mascotShapeLoader");
766 var image = findChild(card, "mascotImage");
767
768 verify(shape, "Could not find shape.");
769 verify(image, "Could not find image.");
770
771- tryCompare(shape, "visible", data.shape);
772+ tryCompare(shape, "active", data.shape);
773 tryCompare(image, "visible", !data.shape);
774 }
775 }
776
777=== added file 'tests/qmltests/Dash/tst_CardBenchmark.qml'
778--- tests/qmltests/Dash/tst_CardBenchmark.qml 1970-01-01 00:00:00 +0000
779+++ tests/qmltests/Dash/tst_CardBenchmark.qml 2014-04-16 15:47:25 +0000
780@@ -0,0 +1,94 @@
781+/*
782+ * Copyright (C) 2014 Canonical, Ltd.
783+ *
784+ * This program is free software; you can redistribute it and/or modify
785+ * it under the terms of the GNU General Public License as published by
786+ * the Free Software Foundation; version 3.
787+ *
788+ * This program is distributed in the hope that it will be useful,
789+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
790+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
791+ * GNU General Public License for more details.
792+ *
793+ * You should have received a copy of the GNU General Public License
794+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
795+ */
796+
797+import QtQuick 2.0
798+import QtTest 1.0
799+import Ubuntu.Components 0.1
800+import Unity.Test 0.1 as UT
801+import "../../../qml/Dash"
802+import "CardHelpers.js" as Helpers
803+
804+Rectangle {
805+ id: root
806+ width: units.gu(80)
807+ height: units.gu(72)
808+ color: "#88FFFFFF"
809+
810+ property string cardData: '
811+ {
812+ "art": "../../tests/qmltests/Dash/artwork/music-player-design.png",
813+ "mascot": "../../tests/qmltests/Dash/artwork/avatar.png",
814+ "title": "foo",
815+ "subtitle": "bar",
816+ "summary": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
817+ }'
818+
819+ property string currentModel: '{}'
820+ property string cardTitleArtSubtitleMascotSummaryModel: '{ "components": { "title": "title", "art": "art", "subtitle": "subtitle", "mascot": "mascot", "summary": "summary" } }'
821+ property string cardTitleArtSubtitleMascotModel: '{ "components": { "title": "title", "art": "art", "subtitle": "subtitle", "mascot": "mascot" } }'
822+ property string cardTitleArtSubtitleModel: '{ "components": { "title": "title", "art": "art", "subtitle": "subtitle" } }'
823+ property string cardTitleArtModel: '{ "components": { "title": "title", "art": "art" } }'
824+ property string cardArtModel: '{ "components": { "art": "art" } }'
825+ property string cardTitleModel: '{ "components": { "title": "title" } }'
826+
827+ CardTool {
828+ id: cardTool
829+ template: Helpers.update(JSON.parse(Helpers.defaultLayout), JSON.parse(currentModel))['template'];
830+ components: Helpers.update(JSON.parse(Helpers.defaultLayout), JSON.parse(currentModel))['components'];
831+ viewWidth: units.gu(48)
832+ }
833+
834+ Repeater {
835+ id: cardRepeater
836+ model: 0
837+ Card {
838+ width: cardTool.cardWidth || implicitWidth
839+ height: cardTool.cardHeight || implicitHeight
840+
841+ template: cardTool.template
842+ components: cardTool.components
843+ cardData: Helpers.mapData(root.cardData, components)
844+ }
845+ }
846+
847+ UT.UnityTestCase {
848+ id: testCase
849+ name: "CardBenchmark"
850+
851+ when: windowShown
852+
853+ function init() {
854+ wait(1);
855+ }
856+
857+ function benchmark_time_data() {
858+ return [
859+ { tag: "cardTitleArtSubtitleMascotSummaryModel", model: cardTitleArtSubtitleMascotSummaryModel },
860+ { tag: "cardTitleArtSubtitleMascotModel", model: cardTitleArtSubtitleMascotModel },
861+ { tag: "cardTitleArtSubtitleModel", model: cardTitleArtSubtitleModel },
862+ { tag: "cardTitleArtModel", model: cardTitleArtModel },
863+ { tag: "cardArtModel", model: cardArtModel },
864+ { tag: "cardTitleModel", model: cardTitleModel },
865+ ];
866+ }
867+
868+ function benchmark_time(data) {
869+ currentModel = data.model;
870+ cardRepeater.model = 1;
871+ cardRepeater.model = 0;
872+ }
873+ }
874+}
875
876=== modified file 'tests/qmltests/Dash/tst_CardHeader.qml'
877--- tests/qmltests/Dash/tst_CardHeader.qml 2014-03-17 11:44:05 +0000
878+++ tests/qmltests/Dash/tst_CardHeader.qml 2014-04-16 15:47:25 +0000
879@@ -43,7 +43,7 @@
880
881 when: windowShown
882
883- property Item mascot: findChild(cardHeader, "mascotShape")
884+ property Item mascot: findChild(cardHeader, "mascotShapeLoader")
885 property Item titleLabel: findChild(cardHeader, "titleLabel")
886 property Item subtitleLabel: findChild(cardHeader, "subtitleLabel")
887 property Item oldPriceLabel: findChild(cardHeader, "oldPriceLabel")

Subscribers

People subscribed via source and target branches