on xenial help sign in
Adds carousel dynamic switch
87a1299Albert Astals
qml/Dash/CardCarousel.qml+3−11
@@ -32,14 +32,6 @@ DashRenderer {
32 height: carousel.implicitHeight + units.gu(6)
32 height: carousel.implicitHeight + units.gu(6)
33 verticalSpacing: units.gu(3)
33 verticalSpacing: units.gu(3)
34
34
35− CardTool {
36− id: cardTool
37−
38− template: cardCarousel.template
39− components: cardCarousel.components
40− viewWidth: cardCarousel.width
41− }
42−
43 Carousel {
35 Carousel {
44 id: carousel
36 id: carousel
45 anchors.fill: parent
37 anchors.fill: parent
@@ -47,7 +39,7 @@ DashRenderer {
47 // FIXME we need to "reverse" the carousel to make the selected item the size
39 // FIXME we need to "reverse" the carousel to make the selected item the size
48 // and push others back.
40 // and push others back.
49 minimumTileWidth: cardTool.cardWidth / selectedItemScaleFactor
41 minimumTileWidth: cardTool.cardWidth / selectedItemScaleFactor
50− selectedItemScaleFactor: 1.38
42+ selectedItemScaleFactor: cardTool.carouselSelectedItemScaleFactor
51 cacheBuffer: 1404 // 18px * 13gu * 6
43 cacheBuffer: 1404 // 18px * 13gu * 6
52 model: cardCarousel.model
44 model: cardCarousel.model
53 highlightIndex: cardCarousel.highlightIndex
45 highlightIndex: cardCarousel.highlightIndex
@@ -63,8 +55,8 @@ DashRenderer {
63 objectName: "delegate" + index
55 objectName: "delegate" + index
64 headerHeight: carousel.headerHeight
56 headerHeight: carousel.headerHeight
65 cardData: model
57 cardData: model
66− template: cardCarousel.template
58+ template: cardTool.template
67− components: cardCarousel.components
59+ components: cardTool.components
68
60
69 property bool explicitlyScaled
61 property bool explicitlyScaled
70 property var model
62 property var model
qml/Dash/CardFilterGrid.qml+2−12
@@ -26,16 +26,6 @@ DashFilterGrid {
26 verticalSpacing: units.gu(1)
26 verticalSpacing: units.gu(1)
27 collapsedRowCount: Math.min(2, template && template["collapsed-rows"] || 2)
27 collapsedRowCount: Math.min(2, template && template["collapsed-rows"] || 2)
28
28
29− CardTool {
30− id: cardTool
31−
32− template: genericFilterGrid.template
33− // We can't trust the template since it may happen it is carousel
34− // that is being should as a grid because of the lack of elements
35− categoryLayout: "grid"
36− components: genericFilterGrid.components
37− }
38−
39 delegate: Item {
29 delegate: Item {
40 width: genericFilterGrid.cellWidth
30 width: genericFilterGrid.cellWidth
41 height: genericFilterGrid.cellHeight
31 height: genericFilterGrid.cellHeight
@@ -47,8 +37,8 @@ DashFilterGrid {
47 anchors.horizontalCenter: parent.horizontalCenter
37 anchors.horizontalCenter: parent.horizontalCenter
48 objectName: "delegate" + index
38 objectName: "delegate" + index
49 cardData: model
39 cardData: model
50− template: genericFilterGrid.template
40+ template: cardTool.template
51− components: genericFilterGrid.components
41+ components: cardTool.components
52
42
53 headerAlignment: cardTool.headerAlignment
43 headerAlignment: cardTool.headerAlignment
54
44
qml/Dash/CardTool.qml+43−10
@@ -28,6 +28,22 @@ import QtQuick 2.0
28
28
29Item {
29Item {
30 id: cardTool
30 id: cardTool
31+
32+ /*!
33+ \brief Number of cards.
34+ */
35+ property int count
36+
37+ /*!
38+ \brief Width of the category view.
39+ */
40+ property real viewWidth
41+
42+ /*!
43+ \brief Scaling factor of selected Carousel item.
44+ */
45+ readonly property real carouselSelectedItemScaleFactor: 1.38 // XXX assuming 1.38 carousel scaling factor for cards
46+
31 /*!
47 /*!
32 \brief Template supplied for the category.
48 \brief Template supplied for the category.
33 */
49 */
@@ -39,14 +55,15 @@ Item {
39 property var components
55 property var components
40
56
41 /*!
57 /*!
42− \brief Width of the view, based on which carousel width is calculated.
58+ \brief The category layout for this card tool.
43 */
59 */
44− property var viewWidth
60+ property string categoryLayout: {
61+ var layout = template["category-layout"];
45
62
46− /*!
63+ // carousel fallback mode to grid
47− \brief The category layout for this card tool
64+ if (layout === "carousel" && count <= Math.ceil(carouselTool.realPathItemCount)) layout = "grid";
48− */
65+ return layout;
49− property string categoryLayout: template ? template["category-layout"] : ""
66+ }
50
67
51 // FIXME: Saviq
68 // FIXME: Saviq
52 // Only way for the card below to actually be laid out completely.
69 // Only way for the card below to actually be laid out completely.
@@ -71,10 +88,7 @@ Item {
71 }
88 }
72 return units.gu(18.5);
89 return units.gu(18.5);
73 case "carousel":
90 case "carousel":
74− if (viewWidth === undefined) return undefined
91+ return carouselTool.minimumTileWidth;
75− if (viewWidth <= units.gu(40)) return units.gu(18)
76− if (viewWidth >= units.gu(128)) return units.gu(26)
77− return units.gu(18 + Math.round((viewWidth - units.gu(40))/ units.gu(11)))
78 case undefined:
92 case undefined:
79 case "organic-grid":
93 case "organic-grid":
80 case "journal":
94 case "journal":
@@ -128,6 +142,25 @@ Item {
128 return (template["card-layout"] === "horizontal") ? Text.AlignLeft : Text.AlignHCenter;
142 return (template["card-layout"] === "horizontal") ? Text.AlignLeft : Text.AlignHCenter;
129 }
143 }
130
144
145+ QtObject {
146+ id: carouselTool
147+
148+ property real minimumTileWidth: {
149+ if (cardTool.viewWidth === undefined) return undefined;
150+ if (cardTool.viewWidth <= units.gu(40)) return units.gu(18);
151+ if (cardTool.viewWidth >= units.gu(128)) return units.gu(26);
152+ return units.gu(18 + Math.round((cardTool.viewWidth - units.gu(40)) / units.gu(11)));
153+ }
154+
155+ readonly property real pathItemCount: 4.8457 /// (848 / 175) reference values
156+
157+ property real realPathItemCount: {
158+ var scaledMinimumTileWidth = minimumTileWidth / cardTool.carouselSelectedItemScaleFactor;
159+ var tileWidth = Math.max(cardTool.viewWidth / pathItemCount, scaledMinimumTileWidth);
160+ return Math.min(cardTool.viewWidth / tileWidth, pathItemCount);
161+ }
162+ }
163+
131 Card {
164 Card {
132 id: card
165 id: card
133 objectName: "card"
166 objectName: "card"
qml/Dash/DashRenderer.qml+5−6
@@ -50,6 +50,11 @@ Item {
50 // The model to renderer
50 // The model to renderer
51 property var model
51 property var model
52
52
53+ /*!
54+ \brief CardTool component.
55+ */
56+ property var cardTool
57+
53 /// Emitted when the user clicked on an item
58 /// Emitted when the user clicked on an item
54 /// @param index is the index of the clicked item
59 /// @param index is the index of the clicked item
55 /// @param itemY is y of the clicked delegate
60 /// @param itemY is y of the clicked delegate
@@ -62,10 +67,4 @@ Item {
62
67
63 function startFilterAnimation(filter) {
68 function startFilterAnimation(filter) {
64 }
69 }
65−
66− /// Category template definition from the scope
67− property var template
68−
69− /// Component mapping and configuration from the scope
70− property var components
71}
70}
qml/Dash/GenericScopeView.qml+18−22
@@ -138,6 +138,15 @@ FocusScope {
138 readonly property string category: categoryId
138 readonly property string category: categoryId
139 readonly property var item: rendererLoader.item
139 readonly property var item: rendererLoader.item
140
140
141+ CardTool {
142+ id: cardTool
143+
144+ count: results.count
145+ template: model.renderer
146+ components: model.components
147+ viewWidth: parent.width
148+ }
149+
141 Loader {
150 Loader {
142 id: rendererLoader
151 id: rendererLoader
143 anchors {
152 anchors {
@@ -146,7 +155,14 @@ FocusScope {
146 right: parent.right
155 right: parent.right
147 }
156 }
148
157
149− source: getRenderer(model.renderer, results)
158+ source: {
159+ switch (cardTool.categoryLayout) {
160+ case "carousel": return "CardCarousel.qml";
161+ case "running-apps": return "Apps/RunningApplicationsGrid.qml";
162+ case "grid":
163+ default: return "CardFilterGrid.qml";
164+ }
165+ }
150
166
151 onLoaded: {
167 onLoaded: {
152 if (item.enableHeightBehavior !== undefined && item.enableHeightBehaviorOnNextCreation !== undefined) {
168 if (item.enableHeightBehavior !== undefined && item.enableHeightBehaviorOnNextCreation !== undefined) {
@@ -170,9 +186,7 @@ FocusScope {
170 }
186 }
171 }
187 }
172 updateDelegateCreationRange();
188 updateDelegateCreationRange();
173− // FIXME: should be "template", not "renderer"
189+ item.cardTool = cardTool;
174− item.template = Qt.binding(function() { return model.renderer });
175− item.components = Qt.binding(function() { return model.components });
176 }
190 }
177
191
178 Component.onDestruction: {
192 Component.onDestruction: {
@@ -325,22 +339,4 @@ FocusScope {
325 }
339 }
326 }
340 }
327 }
341 }
328−
329− function getRenderer(template, results) {
330− var layout = template["category-layout"];
331−
332− if (layout == "running-apps") {
333− return "Apps/RunningApplicationsGrid.qml";
334− }
335−
336− if (layout === "carousel") {
337− // TODO: Selectively disable carousel, 4 is fixed for now, should change depending on form factor
338− if (results.count <= 4) layout = "grid";
339− }
340− switch (layout) {
341− case "carousel": return "CardCarousel.qml";
342− case "grid":
343− default: return "CardFilterGrid.qml";
344− }
345− }
346}
342}
tests/qmltests/Dash/tst_CardTool.qml+20
@@ -93,6 +93,7 @@ Rectangle {
93 CardTool {
93 CardTool {
94 id: cardTool
94 id: cardTool
95
95
96+ count: 8
96 template: Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['template'];
97 template: Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['template'];
97 components: Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['components'];
98 components: Helpers.update(JSON.parse(Helpers.defaultLayout), Helpers.tryParse(layoutArea.text, layoutError))['components'];
98 viewWidth: units.gu(Math.round(widthSlider.value))
99 viewWidth: units.gu(Math.round(widthSlider.value))
@@ -343,5 +344,24 @@ Rectangle {
343 tryCompare(cardTool, data.property, data.value);
344 tryCompare(cardTool, data.property, data.value);
344 }
345 }
345 }
346 }
347+
348+ function test_categoryLayout_data() {
349+ return [
350+ { tag: "Default Grid", layout_index: 0, count: 2, viewWidth: units.gu(40), layout: "grid" },
351+ { tag: "Long carousel", layout_index: 4, count: 6, viewWidth: units.gu(140), layout: "carousel" },
352+ { tag: "Long carousel fallback", layout_index: 4, count: 5, viewWidth: units.gu(140), layout: "grid" },
353+ { tag: "Short carousel", layout_index: 4, count: 4, viewWidth: units.gu(30), layout: "carousel" },
354+ { tag: "Short carousel fallback", layout_index: 4, count: 3, viewWidth: units.gu(30), layout: "grid" },
355+ { tag: "Journal", layout_index: 2, count: 8, viewWidth: units.gu(30), layout: "journal" }
356+ ]
357+ }
358+
359+ function test_categoryLayout(data) {
360+ selector.selectedIndex = 0;
361+ layoutSelector.selectedIndex = data.layout_index;
362+ cardTool.viewWidth = data.viewWidth;
363+ cardTool.count = data.count;
364+ compare(cardTool.categoryLayout, data.layout);
365+ }
346 }
366 }
347}
367}
tests/qmltests/Dash/tst_GenericScopeView.qml−15
@@ -300,21 +300,6 @@ Item {
300 tryCompare(category, "filtered", true);
300 tryCompare(category, "filtered", true);
301 }
301 }
302
302
303− function test_getRendererCarouselGridFallback() {
304− var template = new Object()
305− template["category-layout"] = "carousel"
306− var results = new Object()
307− var renderer
308−
309− results.count = 5
310− renderer = genericScopeView.getRenderer(template, results)
311− compare(renderer, "CardCarousel.qml")
312−
313− results.count = 4
314− renderer = genericScopeView.getRenderer(template, results)
315− compare(renderer, "CardFilterGrid.qml")
316− }
317−
318 function test_showPreviewCarousel() {
303 function test_showPreviewCarousel() {
319 tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != null; }, true);
304 tryCompareFunction(function() { return findChild(genericScopeView, "carouselDelegate") != null; }, true);
320 var tile = findChild(genericScopeView, "carouselDelegate");
305 var tile = findChild(genericScopeView, "carouselDelegate");