on bbbdccd help sign in
unity8/qml/Dash/CardTool.qml
245 lines 8.6 kB history raw
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import QtQuick 2.4
18import Dash 0.1
20/*!
21 \brief Tool for introspecting Card properties.
23 Some properties of Cards we need to determine category-wide (like card sizes in grid),
24 so we should not do them per-Card but in the category renderer.
26 This component creates an invisible card filled with maximum mapped data and calculates
27 or measures card properties for this configuration.
28 */
30Item {
31 id: cardTool
33 /*!
34 \brief Number of cards.
35 */
36 property int count
38 /*!
39 \brief Width of the category view.
40 */
41 property real viewWidth
43 /*!
44 \brief Scaling factor of selected Carousel item.
45 */
46 readonly property real carouselSelectedItemScaleFactor: 1.38 // XXX assuming 1.38 carousel scaling factor for cards
48 /*!
49 \brief Template supplied for the category.
50 */
51 property var template
53 /*!
54 \brief Component mapping supplied for the category.
55 */
56 property var components
58 /*!
59 \brief The category layout for this card tool.
60 */
61 property string categoryLayout: {
62 var layout = template["category-layout"];
64 // carousel fallback mode to grid
65 if (layout === "carousel" && count <= Math.ceil(carouselTool.realPathItemCount)) layout = "grid";
66 return layout;
67 }
69 property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components);
71 // FIXME: Saviq
72 // Only way for the card below to actually be laid out completely.
73 // If invisible or in "data" array, some components are not taken into account.
74 width: 0
75 height: 0
76 clip: true
78 /*!
79 type:real \brief Width to be enforced on the card in this configuration.
81 If -1, should use implicit width of the actual card.
82 */
83 property real cardWidth: {
84 switch (categoryLayout) {
85 case "grid":
86 case "vertical-journal":
87 var size = template["card-size"];
88 if (template["card-layout"] === "horizontal") size = "large";
89 switch (size) {
90 case "small": {
91 if (viewWidth <= units.gu(45)) return units.gu(12);
92 else return units.gu(14);
93 }
94 case "large": {
95 if (viewWidth >= units.gu(70)) return units.gu(42);
96 else return viewWidth - units.gu(2);
97 }
98 }
99 if (viewWidth <= units.gu(45)) return units.gu(18);
100 else if (viewWidth >= units.gu(70)) return units.gu(20);
101 else return units.gu(23);
102 case "carousel":
103 case "horizontal-list":
104 return carouselTool.minimumTileWidth;
105 case undefined:
106 case "organic-grid":
107 case "journal":
108 default:
109 return -1;
110 }
111 }
113 /*!
114 type:real \brief Height to be enforced on the card in this configuration.
116 If -1, should use implicit height of the actual card.
117 */
118 readonly property real cardHeight: {
119 switch (categoryLayout) {
120 case "journal":
121 if (template["card-size"] >= 12 && template["card-size"] <= 38) return units.gu(template["card-size"]);
122 return units.gu(18.5);
123 case "grid":
124 case "horizontal-list":
125 return cardLoader.item ? cardLoader.item.implicitHeight : 0
126 case "carousel":
127 return cardWidth / (components ? components["art"]["aspect-ratio"] : 1)
128 case undefined:
129 case "organic-grid":
130 case "vertical-journal":
131 default:
132 return -1;
133 }
134 }
136 /*!
137 type:real \brief Height of the card's header.
138 */
139 readonly property int headerHeight: cardLoader.item ? cardLoader.item.headerHeight : 0
140 property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
142 /*!
143 \brief Desired alignment of title
144 */
145 readonly property int titleAlignment: {
146 if (template["card-layout"] === "horizontal"
147 || typeof components["title"] !== "object"
148 || components["title"]["align"] === "left") return Text.AlignLeft;
150 var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
152 for (var key in keys) {
153 key = keys[key];
154 try {
155 if (typeof components[key] === "string"
156 || typeof components[key]["field"] === "string") return Text.AlignLeft;
157 } catch (e) {
158 continue;
159 }
160 }
162 return Text.AlignHCenter;
163 }
165 QtObject {
166 id: carouselTool
168 property real minimumTileWidth: {
169 if (cardTool.viewWidth === undefined) return undefined;
170 if (cardTool.viewWidth <= units.gu(40)) return units.gu(18);
171 if (cardTool.viewWidth >= units.gu(128)) return units.gu(26);
172 return units.gu(18 + Math.round((cardTool.viewWidth - units.gu(40)) / units.gu(11)));
173 }
175 readonly property real pathItemCount: 4.8457 /// (848 / 175) reference values
177 property real realPathItemCount: {
178 var scaledMinimumTileWidth = minimumTileWidth / cardTool.carouselSelectedItemScaleFactor;
179 var tileWidth = Math.max(cardTool.viewWidth / pathItemCount, scaledMinimumTileWidth);
180 return Math.min(cardTool.viewWidth / tileWidth, pathItemCount);
181 }
182 }
184 Item {
185 id: attributesModel
186 property int numOfAttributes: 0
187 property var model: []
188 property bool hasAttributes: {
189 var attributes = components["attributes"];
190 var hasAttributesFlag = (attributes != undefined) && (attributes["field"] != undefined);
192 if (hasAttributesFlag) {
193 if (attributes["max-count"]) {
194 numOfAttributes = attributes["max-count"];
195 }
196 }
197 return hasAttributesFlag
198 }
200 onNumOfAttributesChanged: {
201 model = []
202 for (var i = 0; i < numOfAttributes; i++) {
203 model.push( {"value":"text"+(i+1), "icon":"image://theme/ok" } );
204 }
205 }
206 }
208 Loader {
209 id: cardLoader
210 readonly property var fields: ["art", "mascot", "title", "subtitle", "summary", "attributes"]
211 readonly property var maxData: {
212 "art": Qt.resolvedUrl("graphics/pixel.png"),
213 "mascot": Qt.resolvedUrl("graphics/pixel.png"),
214 "title": "—\n—",
215 "subtitle": "—",
216 "summary": "—\n—\n—\n—\n—",
217 "attributes": attributesModel.model
218 }
219 sourceComponent: cardTool.cardComponent
220 onLoaded: {
221 item.objectName = "cardToolCard";
222 item.asynchronous = false;
223 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
224 item.height = Qt.binding(function() { return cardTool.cardHeight !== -1 ? cardTool.cardHeight : item.implicitHeight; });
225 }
226 Connections {
227 target: cardTool
228 onTemplateChanged: cardLoader.updateCardData();
229 onComponentsChanged: cardLoader.updateCardData();
230 }
231 function updateCardData() {
232 var data = {};
233 for (var k in fields) {
234 var component = cardTool.components[fields[k]];
235 var key = fields[k];
236 if ((typeof component === "string" && component.length > 0) ||
237 (typeof component === "object" && component !== null
238 && typeof component["field"] === "string" && component["field"].length > 0)) {
239 data[key] = maxData[key];
240 }
241 }
242 item.cardData = data;
243 }
244 }