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/>.
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.
34 \brief Number of cards.
39 \brief Width of the category view.
41 property real viewWidth
44 \brief Scaling factor of selected Carousel item.
46 readonly property real carouselSelectedItemScaleFactor: 1.38 // XXX assuming 1.38 carousel scaling factor for cards
49 \brief Template supplied for the category.
54 \brief Component mapping supplied for the category.
56 property var components
59 \brief The category layout for this card tool.
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";
69 property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, false);
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.
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.
83 property real cardWidth: {
84 switch (categoryLayout) {
86 case "vertical-journal":
87 var size = template["card-size"];
88 if (template["card-layout"] === "horizontal") size = "large";
91 if (viewWidth <= units.gu(45)) return units.gu(12);
92 else return units.gu(14);
95 if (viewWidth >= units.gu(70)) return units.gu(42);
96 else return viewWidth - units.gu(2);
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);
103 case "horizontal-list":
104 return carouselTool.minimumTileWidth;
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.
118 readonly property real cardHeight: {
119 switch (categoryLayout) {
121 if (template["card-size"] >= 12 && template["card-size"] <= 38) return units.gu(template["card-size"]);
122 return units.gu(18.5);
124 case "horizontal-list":
125 return cardLoader.item ? cardLoader.item.implicitHeight : 0
127 return cardWidth / (components ? components["art"]["aspect-ratio"] : 1)
130 case "vertical-journal":
137 type:real \brief Height of the card's header.
139 readonly property int headerHeight: cardLoader.item ? cardLoader.item.headerHeight : 0
140 property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
145 property real minimumTileWidth: {
146 if (cardTool.viewWidth === undefined) return undefined;
147 if (cardTool.viewWidth <= units.gu(40)) return units.gu(18);
148 if (cardTool.viewWidth >= units.gu(128)) return units.gu(26);
149 return units.gu(18 + Math.round((cardTool.viewWidth - units.gu(40)) / units.gu(11)));
152 readonly property real pathItemCount: 4.8457 /// (848 / 175) reference values
154 property real realPathItemCount: {
155 var scaledMinimumTileWidth = minimumTileWidth / cardTool.carouselSelectedItemScaleFactor;
156 var tileWidth = Math.max(cardTool.viewWidth / pathItemCount, scaledMinimumTileWidth);
157 return Math.min(cardTool.viewWidth / tileWidth, pathItemCount);
163 property int numOfAttributes: 0
164 property var model: []
165 property bool hasAttributes: {
166 var attributes = components["attributes"];
167 var hasAttributesFlag = (attributes != undefined) && (attributes["field"] != undefined);
169 if (hasAttributesFlag) {
170 if (attributes["max-count"]) {
171 numOfAttributes = attributes["max-count"];
174 return hasAttributesFlag
177 onNumOfAttributesChanged: {
179 for (var i = 0; i < numOfAttributes; i++) {
180 model.push( {"value":"text"+(i+1), "icon":"image://theme/ok" } );
187 readonly property var fields: ["art", "mascot", "title", "subtitle", "summary", "attributes"]
188 readonly property var maxData: {
189 "art": Qt.resolvedUrl("graphics/pixel.png"),
190 "mascot": Qt.resolvedUrl("graphics/pixel.png"),
193 "summary": "—\n—\n—\n—\n—",
194 "attributes": attributesModel.model
196 sourceComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, true);
198 item.objectName = "cardToolCard";
199 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
200 item.height = Qt.binding(function() { return cardTool.cardHeight !== -1 ? cardTool.cardHeight : item.implicitHeight; });
204 onTemplateChanged: cardLoader.updateCardData();
205 onComponentsChanged: cardLoader.updateCardData();
207 function updateCardData() {
209 for (var k in fields) {
210 var component = cardTool.components[fields[k]];
212 if ((typeof component === "string" && component.length > 0) ||
213 (typeof component === "object" && component !== null
214 && typeof component["field"] === "string" && component["field"].length > 0)) {
215 data[key] = maxData[key];
218 item.cardData = data;