2 * Copyright (C) 2014 Canonical, Ltd.
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.
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.
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/>.
18 import Ubuntu.Components 1.3
22 \brief Tool for introspecting Card properties.
24 Some properties of Cards we need to determine category-wide (like card sizes in grid),
25 so we should not do them per-Card but in the category renderer.
27 This component creates an invisible card filled with maximum mapped data and calculates
28 or measures card properties for this configuration.
35 \brief Number of cards.
40 \brief Width of the category view.
42 property real viewWidth
45 \brief Scaling factor of selected Carousel item.
47 readonly property real carouselSelectedItemScaleFactor: 1.38 // XXX assuming 1.38 carousel scaling factor for cards
50 \brief Template supplied for the category.
55 \brief Component mapping supplied for the category.
57 property var components
60 \brief The category layout for this card tool.
62 property string categoryLayout: {
63 var layout = template["category-layout"];
65 // carousel fallback mode to grid
66 if (layout === "carousel" && count <= Math.ceil(carouselTool.realPathItemCount)) layout = "grid";
71 // Not readonly because gets overwritten from GenericScopeView in some cases
72 property string artShapeStyle: categoryLayout === "carousel" ? "shadow" : "inset"
74 // FIXME ? This seems like it should not be needed, but on Qt 5.4 + phone
75 // we are doing unneeded calls to getCardComponent with artShapeStyle and categoryLayout being empty
76 // Check when we move to newer Qts on the phone if we still need this
77 readonly property bool askForCardComponent: cardTool.template !== undefined &&
78 cardTool.components !== undefined &&
79 cardTool.artShapeStyle !== "" &&
80 cardTool.categoryLayout !== ""
82 property var cardComponent: askForCardComponent
83 ? CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, false, cardTool.artShapeStyle, cardTool.categoryLayout)
87 // Only way for the card below to actually be laid out completely.
88 // If invisible or in "data" array, some components are not taken into account.
94 type:real \brief Width to be enforced on the card in this configuration.
96 If -1, should use implicit width of the actual card.
98 property real cardWidth: {
99 switch (categoryLayout) {
101 case "vertical-journal":
102 var size = template["card-size"];
103 if (template["card-layout"] === "horizontal") size = "large";
106 if (viewWidth <= units.gu(45)) return units.gu(12);
107 else return units.gu(14);
110 if (viewWidth >= units.gu(70)) return units.gu(42);
111 else return viewWidth - units.gu(2);
114 if (viewWidth <= units.gu(45)) return units.gu(18);
115 else if (viewWidth >= units.gu(70)) return units.gu(20);
116 else return units.gu(23);
118 case "horizontal-list":
119 return carouselTool.minimumTileWidth;
129 type:real \brief Height to be enforced on the card in this configuration.
131 If -1, should use implicit height of the actual card.
133 readonly property real cardHeight: {
134 switch (categoryLayout) {
136 if (template["card-size"] >= 12 && template["card-size"] <= 38) return units.gu(template["card-size"]);
137 return units.gu(18.5);
139 case "horizontal-list":
140 return cardLoader.item ? cardLoader.item.implicitHeight : 0
142 return cardWidth / (components ? components["art"]["aspect-ratio"] : 1)
145 case "vertical-journal":
152 type:real \brief Height of the card's header.
154 readonly property int headerHeight: cardLoader.item ? cardLoader.item.headerHeight : 0
155 property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : Qt.size(0, 0)
160 property real minimumTileWidth: {
161 if (cardTool.viewWidth === undefined) return undefined;
162 if (cardTool.viewWidth <= units.gu(40)) return units.gu(18);
163 if (cardTool.viewWidth >= units.gu(128)) return units.gu(26);
164 return units.gu(18 + Math.round((cardTool.viewWidth - units.gu(40)) / units.gu(11)));
167 readonly property real pathItemCount: 4.8457 /// (848 / 175) reference values
169 property real realPathItemCount: {
170 var scaledMinimumTileWidth = minimumTileWidth / cardTool.carouselSelectedItemScaleFactor;
171 var tileWidth = Math.max(cardTool.viewWidth / pathItemCount, scaledMinimumTileWidth);
172 return Math.min(cardTool.viewWidth / tileWidth, pathItemCount);
178 property int numOfAttributes: 0
179 property var model: []
180 readonly property bool hasAttributes: {
181 var attributes = components["attributes"];
182 var hasAttributesFlag = (attributes != undefined) && (attributes["field"] != undefined);
184 if (hasAttributesFlag) {
185 if (attributes["max-count"]) {
186 numOfAttributes = attributes["max-count"];
189 return hasAttributesFlag
192 onNumOfAttributesChanged: {
194 for (var i = 0; i < numOfAttributes; i++) {
195 model.push( {"value":"text"+(i+1), "icon":"image://theme/ok" } );
201 id: socialActionsModel
202 property var model: []
203 readonly property bool hasActions: components["social-actions"] != undefined
205 onHasActionsChanged: {
208 model.push( {"id":"text", "icon":"image://theme/ok" } );
215 readonly property var cfields: ["art", "mascot", "title", "subtitle", "summary", "attributes", "social-actions"]
216 readonly property var dfields: ["art", "mascot", "title", "subtitle", "summary", "attributes", "socialActions"]
217 readonly property var maxData: {
218 "art": Qt.resolvedUrl("graphics/pixel.png"),
219 "mascot": Qt.resolvedUrl("graphics/pixel.png"),
222 "summary": "—\n—\n—\n—\n—",
223 "attributes": attributesModel.model,
224 "socialActions": socialActionsModel.model
226 sourceComponent: askForCardComponent
227 ? CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, true, cardTool.artShapeStyle, cardTool.categoryLayout)
230 item.objectName = "cardToolCard";
231 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
232 item.height = Qt.binding(function() { return cardTool.cardHeight !== -1 ? cardTool.cardHeight : item.implicitHeight; });
236 onTemplateChanged: cardLoader.updateCardData();
237 onComponentsChanged: cardLoader.updateCardData();
239 function updateCardData() {
241 for (var k in cfields) {
242 var ckey = cfields[k];
243 var component = cardTool.components[ckey];
244 if ((typeof component === "string" && component.length > 0) ||
245 (typeof component === "object" && component !== null
246 && typeof component["field"] === "string" && component["field"].length > 0)) {
247 var dkey = dfields[k];
248 data[dkey] = maxData[dkey];
251 item.cardData = data;