on xenial help sign in
Merge and fix cardCreator test
commita30ca7e2687d5bb53d9205b408f63893ab0aab8d authorAndrea Cimitan <andrea.cimitan@gmail.com> dateMon 7 Mar 2016, 12:39 (11 years ago) parent21ac59346bc39e
33 files changed+1657−161
plugins/Dash/CardCreator.js+66−33 plugins/Dash/CardCreatorCache.qml+3−3 qml/Dash/CardCarousel.qml−1 qml/Dash/CardGrid.qml−1 qml/Dash/CardHorizontalList.qml−1 qml/Dash/CardTool.qml+2−26 qml/Dash/CardVerticalJournal.qml−1 tests/plugins/Dash/cardcreator/1.res+4−6 tests/plugins/Dash/cardcreator/1.res.cardcreator+119 tests/plugins/Dash/cardcreator/10.res+3−5 tests/plugins/Dash/cardcreator/10.res.cardcreator+137 tests/plugins/Dash/cardcreator/11.res+5−7 tests/plugins/Dash/cardcreator/11.res.cardcreator+210 tests/plugins/Dash/cardcreator/12.res+6−7 tests/plugins/Dash/cardcreator/2.res+3−5 tests/plugins/Dash/cardcreator/2.res.cardcreator+136 tests/plugins/Dash/cardcreator/3.res+3−5 tests/plugins/Dash/cardcreator/3.res.cardcreator+137 tests/plugins/Dash/cardcreator/4.res+3−5 tests/plugins/Dash/cardcreator/4.res.cardcreator+109 tests/plugins/Dash/cardcreator/5.res+5−7 tests/plugins/Dash/cardcreator/5.res.cardcreator+156 tests/plugins/Dash/cardcreator/6.res+2−4 tests/plugins/Dash/cardcreator/6.res.cardcreator+126 tests/plugins/Dash/cardcreator/7.res+3−5 tests/plugins/Dash/cardcreator/7.res.cardcreator+149 tests/plugins/Dash/cardcreator/8.res+3−5 tests/plugins/Dash/cardcreator/8.res.cardcreator+107 tests/plugins/Dash/cardcreator/9.res+2−4 tests/plugins/Dash/cardcreator/9.res.cardcreator+118 tests/plugins/Dash/cardcreatortest.cpp+32−22 tests/plugins/Dash/cardcreatortest.qml+4−4 tests/qmltests/Dash/tst_CardTool.qml+4−4
plugins/Dash/CardCreator.js+66−33
@@ -18,12 +18,13 @@
1818
1919// %1 is the template["card-background"]["elements"][0]
2020// %2 is the template["card-background"]["elements"][1]
21−// %3 is the template["card-background"] string
21+// %3 is whether the loader should be asynchronous or not
22+// %4 is the template["card-background"] string
2223var kBackgroundLoaderCode = 'Loader {\n\
2324 id: backgroundLoader; \n\
2425 objectName: "backgroundLoader"; \n\
2526 anchors.fill: parent; \n\
26− asynchronous: root.asynchronous; \n\
27+ asynchronous: %3; \n\
2728 visible: status == Loader.Ready; \n\
2829 sourceComponent: UbuntuShape { \n\
2930 objectName: "background"; \n\
@@ -46,7 +47,7 @@ var kBackgroundLoaderCode = 'Loader {\n\
4647 objectName: "backgroundImage"; \n\
4748 source: { \n\
4849 if (cardData && typeof cardData["background"] === "string") return cardData["background"]; \n\
49− else return %3; \n\
50+ else return %4; \n\
5051 } \n\
5152 } \n\
5253 function getColor(index) { \n\
@@ -63,8 +64,9 @@ var kBackgroundLoaderCode = 'Loader {\n\
6364// %3 is used as image height
6465// %4 is used for artShapeSource.hideSource and inner Loader visible
6566// %5 is used as aspect ratio fallback
66−// %6 is injected as code to artImage
67−// %7 is used as image fallback
67+// %6 is whether the loader should be asynchronous or not
68+// %7 is injected as code to artImage
69+// %8 is used as image fallback
6870var kArtShapeHolderCode = 'Item { \n\
6971 id: artShapeHolder; \n\
7072 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
@@ -73,9 +75,9 @@ var kArtShapeHolderCode = 'Item { \n\
7375 Loader { \n\
7476 id: artShapeLoader; \n\
7577 objectName: "artShapeLoader"; \n\
76− readonly property string cardArt: cardData && cardData["art"] || %7; \n\
78+ readonly property string cardArt: cardData && cardData["art"] || %8; \n\
7779 active: cardArt != ""; \n\
78− asynchronous: root.asynchronous; \n\
80+ asynchronous: %6; \n\
7981 visible: status == Loader.Ready; \n\
8082 sourceComponent: Item { \n\
8183 id: artShape; \n\
@@ -132,10 +134,10 @@ var kArtShapeHolderCode = 'Item { \n\
132134 id: artImage; \n\
133135 objectName: "artImage"; \n\
134136 source: artShapeLoader.cardArt; \n\
135− asynchronous: root.asynchronous; \n\
137+ asynchronous: %6; \n\
136138 width: %2; \n\
137139 height: %3; \n\
138− %6 \n\
140+ %7 \n\
139141 } \n\
140142 } \n\
141143 } \n\
@@ -187,12 +189,14 @@ var kAudioButtonCode = 'AbstractButton { \n\
187189 } \n\
188190 }';
189191
192+// %1 is whether the loader should be asynchronous or not
193+// %2 is the header height code
190194var kOverlayLoaderCode = 'Loader { \n\
191195 id: overlayLoader; \n\
192− readonly property real overlayHeight: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
196+ readonly property real overlayHeight: %2 + units.gu(2); \n\
193197 anchors.fill: artShapeHolder; \n\
194198 active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false; \n\
195− asynchronous: root.asynchronous; \n\
199+ asynchronous: %1; \n\
196200 visible: showHeader && status == Loader.Ready; \n\
197201 sourceComponent: UbuntuShapeOverlay { \n\
198202 id: overlay; \n\
@@ -211,17 +215,19 @@ function kHeaderRowCodeGenerator() {
211215 objectName: "outerRow"; \n\
212216 property real margins: units.gu(1); \n\
213217 spacing: margins; \n\
214− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight; \n\
218+ %2\
215219 anchors { %1 } \n\
216220 anchors.right: parent.right; \n\
217221 anchors.margins: margins; \n\
218222 anchors.rightMargin: 0; \n\
219223 data: [ \n\
220− %2 \n\
224+ %3 \n\
221225 ] \n\
222226 }\n';
223227 var args = Array.prototype.slice.call(arguments);
224− var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(args.join(',\n'));
228+ var isCardTool = args.shift();
229+ var heightCode = isCardTool ? "" : "height: root.fixedHeaderHeight; \n";
230+ var code = kHeaderRowCodeTemplate.arg(args.shift()).arg(heightCode).arg(args.join(',\n'));
225231 return code;
226232}
227233
@@ -242,10 +248,11 @@ function kHeaderContainerCodeGenerator() {
242248}
243249
244250// %1 is used as anchors of mascotShapeLoader
251+// %2 is whether the loader should be asynchronous or not
245252var kMascotShapeLoaderCode = 'Loader { \n\
246253 id: mascotShapeLoader; \n\
247254 objectName: "mascotShapeLoader"; \n\
248− asynchronous: root.asynchronous; \n\
255+ asynchronous: %2; \n\
249256 active: mascotImage.status === Image.Ready; \n\
250257 visible: showHeader && active && status == Loader.Ready; \n\
251258 width: units.gu(6); \n\
@@ -275,6 +282,7 @@ var kMascotImageCode = 'CroppedImageMinimumSourceSize { \n\
275282// %2 is used as color of titleLabel
276283// %3 is used as extra condition for visible of titleLabel
277284// %4 is used as title width
285+// %5 is used as horizontal alignment
278286var kTitleLabelCode = 'Label { \n\
279287 id: titleLabel; \n\
280288 objectName: "titleLabel"; \n\
@@ -289,7 +297,7 @@ var kTitleLabelCode = 'Label { \n\
289297 width: %4; \n\
290298 text: root.title; \n\
291299 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal; \n\
292− horizontalAlignment: root.titleAlignment; \n\
300+ horizontalAlignment: %5; \n\
293301 }\n';
294302
295303// %1 is used as extra anchors of emblemIcon
@@ -409,7 +417,7 @@ function sanitizeColor(colorString) {
409417 return colorString;
410418}
411419
412−function cardString(template, components) {
420+function cardString(template, components, isCardTool) {
413421 var code;
414422
415423 var templateInteractive = (template == null ? true : (template["non-interactive"] !== undefined ? !template["non-interactive"] : true)) ? "true" : "false";
@@ -421,16 +429,16 @@ function cardString(template, components) {
421429 property string backgroundShapeStyle: "inset"; \n\
422430 property real fontScale: 1.0; \n\
423431 property var scopeStyle: null; \n\
424− property int titleAlignment: Text.AlignLeft; \n\
425− property int fixedHeaderHeight: -1; \n\
432+ %2\
426433 property size fixedArtShapeSize: Qt.size(-1, -1); \n\
427434 readonly property string title: cardData && cardData["title"] || ""; \n\
428− property bool asynchronous: true; \n\
429435 property bool showHeader: true; \n\
430436 implicitWidth: childrenRect.width; \n\
431437 enabled: %1; \n\
432438 \n'.arg(templateInteractive);
433439
440+ code = code.arg(isCardTool ? "" : "property int fixedHeaderHeight: -1; \n");
441+
434442 var hasArt = components["art"] && components["art"]["field"] || false;
435443 var hasSummary = components["summary"] || false;
436444 var isConciergeMode = components["art"] && components["art"]["conciergeMode"] || false;
@@ -447,6 +455,7 @@ function cardString(template, components) {
447455 var hasAttributes = hasTitle && components["attributes"] && components["attributes"]["field"] || false;
448456 var hasSocialActions = hasTitle && components["socialActions"] || false;
449457 var isAudio = template["quick-preview-type"] === "audio";
458+ var asynchronous = isCardTool ? "false" : "true";
450459
451460 code += 'signal action(var actionId);\n';
452461 if (isAudio) {
@@ -481,7 +490,7 @@ function cardString(template, components) {
481490 backgroundElements1 = '"%1"'.arg(element1);
482491 }
483492 }
484− code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(templateCardBackground);
493+ code += kBackgroundLoaderCode.arg(backgroundElements0).arg(backgroundElements1).arg(asynchronous).arg(templateCardBackground);
485494 }
486495
487496 if (hasArt) {
@@ -510,23 +519,31 @@ function cardString(template, components) {
510519 if (isNaN(aspectRatio)) {
511520 aspectRatio = 1;
512521 }
513− var fallback = components["art"] && components["art"]["fallback"] || "";
522+ var fallback = !isCardTool && components["art"] && components["art"]["fallback"] || "";
514523 fallback = encodeURI(fallback);
515524 var fallbackStatusCode = "";
516525 var fallbackURICode = '""';
517526 if (fallback !== "") {
518527 // fallbackStatusCode has %6 in it because we want to substitute it for fallbackURICode
519− // which in kArtShapeHolderCode is %7
520− fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %7;';
528+ // which in kArtShapeHolderCode is %8
529+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %8;';
521530 fallbackURICode = 'decodeURI("%1")'.arg(fallback);
522531 }
523− code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode).arg(isConciergeMode ? "false" : "true").arg(aspectRatio).arg(fallbackStatusCode).arg(fallbackURICode);
532+ code += kArtShapeHolderCode.arg(artAnchors)
533+ .arg(widthCode)
534+ .arg(heightCode)
535+ .arg(isConciergeMode ? "false" : "true")
536+ .arg(aspectRatio)
537+ .arg(asynchronous)
538+ .arg(fallbackStatusCode)
539+ .arg(fallbackURICode);
524540 } else {
525541 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
526542 }
527543
528544 if (headerAsOverlay) {
529− code += kOverlayLoaderCode;
545+ var headerHeightCode = isCardTool ? "headerHeight" : "root.fixedHeaderHeight";
546+ code += kOverlayLoaderCode.arg(asynchronous).arg(headerHeightCode);
530547 }
531548
532549 var headerVerticalAnchors;
@@ -608,11 +625,11 @@ function cardString(template, components) {
608625 }
609626
610627 if (useMascotShape) {
611− mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors);
628+ mascotShapeCode = kMascotShapeLoaderCode.arg(mascotAnchors).arg(asynchronous);
612629 }
613630
614631 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
615− var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
632+ var fallback = !isCardTool && components["mascot"] && components["mascot"]["fallback"] || "";
616633 fallback = encodeURI(fallback);
617634 var fallbackStatusCode = "";
618635 var fallbackURICode = '""';
@@ -728,9 +745,24 @@ function cardString(template, components) {
728745 }
729746 }
730747
748+ var titleAlignment = "Text.AlignHCenter";
749+ if (template["card-layout"] === "horizontal"
750+ || typeof components["title"] !== "object"
751+ || components["title"]["align"] === "left") titleAlignment = "Text.AlignLeft";
752+ var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
753+ for (var key in keys) {
754+ key = keys[key];
755+ try {
756+ if (typeof components[key] === "string"
757+ || typeof components[key]["field"] === "string") titleAlignment = "Text.AlignLeft";
758+ } catch (e) {
759+ continue;
760+ }
761+ }
762+
731763 // code for different elements
732764 var titleLabelVisibleExtra = (headerAsOverlay ? '&& overlayLoader.active': '');
733− var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth);
765+ var titleCode = kTitleLabelCode.arg(titleAnchors).arg(titleColor).arg(titleLabelVisibleExtra).arg(titleWidth).arg(titleAlignment);
734766 var subtitleCode;
735767 var attributesCode;
736768
@@ -772,7 +804,7 @@ function cardString(template, components) {
772804 if (mascotShapeCode != '') {
773805 rowCode.unshift(mascotShapeCode);
774806 }
775− code += kHeaderRowCodeGenerator(headerVerticalAnchors + headerLeftAnchor, rowCode)
807+ code += kHeaderRowCodeGenerator(isCardTool, headerVerticalAnchors + headerLeftAnchor, rowCode)
776808 } else {
777809 code += mascotShapeCode + mascotCode + titleSubtitleCode;
778810 }
@@ -796,7 +828,8 @@ function cardString(template, components) {
796828 } else {
797829 audioButtonAnchorsFill = 'undefined';
798830 audioButtonWidth = 'height';
799− audioButtonHeight = '(root.fixedHeaderHeight > 0 ? root.fixedHeaderHeight : headerHeight) + 2 * units.gu(1)';
831+ audioButtonHeight = isCardTool ? 'headerHeight + 2 * units.gu(1)'
832+ : 'root.fixedHeaderHeight + 2 * units.gu(1)';
800833 }
801834 code += kAudioButtonCode.arg(audioButtonAnchorsFill).arg(audioButtonWidth).arg(audioButtonHeight);
802835 }
@@ -899,13 +932,13 @@ function cardString(template, components) {
899932 return code;
900933}
901934
902−function createCardComponent(parent, template, components, identifier) {
935+function createCardComponent(parent, template, components, isCardTool, identifier) {
903936 var imports = 'import QtQuick 2.4; \n\
904937 import Ubuntu.Components 1.3; \n\
905938 import Ubuntu.Settings.Components 0.1; \n\
906939 import Dash 0.1;\n\
907940 import Utils 0.1;\n';
908− var card = cardString(template, components);
941+ var card = cardString(template, components, isCardTool);
909942 var code = imports + 'Component {\n' + card + '}\n';
910943
911944 try {
plugins/Dash/CardCreatorCache.qml+3−3
@@ -23,16 +23,16 @@ QtObject {
2323
2424 property var cache: new Object();
2525
26− function getCardComponent(template, components) {
26+ function getCardComponent(template, components, isCardTool) {
2727 if (template === undefined || components === undefined)
2828 return undefined;
2929
3030 var tString = JSON.stringify(template);
3131 var cString = JSON.stringify(components);
32− var allString = tString + cString;
32+ var allString = tString + cString + isCardTool;
3333 var component = cache[allString];
3434 if (component === undefined) {
35− component = CardCreator.createCardComponent(root, template, components, allString);
35+ component = CardCreator.createCardComponent(root, template, components, isCardTool, allString);
3636 cache[allString] = component;
3737 }
3838 return component;
qml/Dash/CardCarousel.qml−1
@@ -66,7 +66,6 @@ DashRenderer {
6666 item.cardData = Qt.binding(function() { return model; });
6767 item.fontScale = Qt.binding(function() { return carousel.fontScale; });
6868 item.showHeader = Qt.binding(function() { return loader.explicitlyScaled; });
69− item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
7069 item.artShapeStyle = "shadow";
7170 item.scopeStyle = cardCarousel.scopeStyle;
7271 }
qml/Dash/CardGrid.qml−1
@@ -70,7 +70,6 @@ DashRenderer {
7070 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
7171 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
7272 item.cardData = Qt.binding(function() { return model; });
73− item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
7473 item.scopeStyle = root.scopeStyle;
7574 item.artShapeStyle = root.artShapeStyle;
7675 item.backgroundShapeStyle = root.backgroundShapeStyle;
qml/Dash/CardHorizontalList.qml−1
@@ -53,7 +53,6 @@ DashRenderer {
5353 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
5454 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
5555 item.cardData = Qt.binding(function() { return model; });
56− item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
5756 item.scopeStyle = root.scopeStyle;
5857 }
5958 Connections {
qml/Dash/CardTool.qml+2−26
@@ -66,7 +66,7 @@ Item {
6666 return layout;
6767 }
6868
69− property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components);
69+ property var cardComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, false);
7070
7171 // FIXME: Saviq
7272 // Only way for the card below to actually be laid out completely.
@@ -139,29 +139,6 @@ Item {
139139 readonly property int headerHeight: cardLoader.item ? cardLoader.item.headerHeight : 0
140140 property size artShapeSize: cardLoader.item ? cardLoader.item.artShapeSize : 0
141141
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;
149−
150− var keys = ["mascot", "emblem", "subtitle", "attributes", "summary"];
151−
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− }
161−
162− return Text.AlignHCenter;
163− }
164−
165142 QtObject {
166143 id: carouselTool
167144
@@ -241,10 +218,9 @@ Item {
241218 "attributes": attributesModel.model,
242219 "socialActions": socialActionsModel.model
243220 }
244− sourceComponent: cardTool.cardComponent
221+ sourceComponent: CardCreatorCache.getCardComponent(cardTool.template, cardTool.components, true);
245222 onLoaded: {
246223 item.objectName = "cardToolCard";
247− item.asynchronous = false;
248224 item.width = Qt.binding(function() { return cardTool.cardWidth !== -1 ? cardTool.cardWidth : item.implicitWidth; });
249225 item.height = Qt.binding(function() { return cardTool.cardHeight !== -1 ? cardTool.cardHeight : item.implicitHeight; });
250226 }
qml/Dash/CardVerticalJournal.qml−1
@@ -72,7 +72,6 @@ DashRenderer {
7272 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
7373 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
7474 item.cardData = Qt.binding(function() { return model; });
75− item.titleAlignment = Qt.binding(function() { return cardTool.titleAlignment; });
7675 item.scopeStyle = root.scopeStyle;
7776 }
7877 Connections {
tests/plugins/Dash/cardcreator/1.res+4−6
@@ -5,12 +5,10 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
13− property bool showHeader: true;
11+ property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
1614signal action(var actionId);
@@ -25,7 +23,7 @@ Item {
2523 objectName: "artShapeLoader";
2624 readonly property string cardArt: cardData && cardData["art"] || "";
2725 active: cardArt != "";
28− asynchronous: root.asynchronous;
26+ asynchronous: true;
2927 visible: status == Loader.Ready;
3028 sourceComponent: Item {
3129 id: artShape;
@@ -82,7 +80,7 @@ Item {
8280 id: artImage;
8381 objectName: "artImage";
8482 source: artShapeLoader.cardArt;
85− asynchronous: root.asynchronous;
83+ asynchronous: true;
8684 width: root.width;
8785 height: width / artShape.aspect;
8886 }
@@ -108,7 +106,7 @@ Label {
108106 width: undefined;
109107 text: root.title;
110108 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
111− horizontalAlignment: root.titleAlignment;
109+ horizontalAlignment: Text.AlignHCenter;
112110 }
113111UbuntuShape {
114112 id: touchdown;
tests/plugins/Dash/cardcreator/1.res.cardcreatornew file+119
@@ -0,0 +1,119 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
15+Item {
16+ id: artShapeHolder;
17+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
18+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
19+ anchors { horizontalCenter: parent.horizontalCenter; }
20+ Loader {
21+ id: artShapeLoader;
22+ objectName: "artShapeLoader";
23+ readonly property string cardArt: cardData && cardData["art"] || "";
24+ active: cardArt != "";
25+ asynchronous: false;
26+ visible: status == Loader.Ready;
27+ sourceComponent: Item {
28+ id: artShape;
29+ objectName: "artShape";
30+ visible: image.status == Image.Ready;
31+ readonly property alias image: artImage;
32+ ShaderEffectSource {
33+ id: artShapeSource;
34+ sourceItem: artImage;
35+ anchors.centerIn: parent;
36+ width: 1;
37+ height: 1;
38+ hideSource: true;
39+ }
40+ Loader {
41+ anchors.fill: parent;
42+ visible: true;
43+ sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
44+ Component {
45+ id: artShapeShapeComponent;
46+ UbuntuShape {
47+ source: artShapeSource;
48+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
49+ radius: "medium";
50+ aspect: {
51+ switch (root.artShapeStyle) {
52+ case "inset": return UbuntuShape.Inset;
53+ case "shadow": return UbuntuShape.DropShadow;
54+ default:
55+ case "flat": return UbuntuShape.Flat;
56+ }
57+ }
58+ }
59+ }
60+ Component {
61+ id: artShapeIconComponent;
62+ ProportionalShape { source: artShapeSource; aspect: UbuntuShape.DropShadow; }
63+ }
64+ }
65+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
66+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1.6;
67+ Component.onCompleted: { updateWidthHeightBindings(); }
68+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
69+ function updateWidthHeightBindings() {
70+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
71+ width = root.fixedArtShapeSize.width;
72+ height = root.fixedArtShapeSize.height;
73+ } else {
74+ width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width });
75+ height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height });
76+ }
77+ }
78+ CroppedImageMinimumSourceSize {
79+ id: artImage;
80+ objectName: "artImage";
81+ source: artShapeLoader.cardArt;
82+ asynchronous: false;
83+ width: root.width;
84+ height: width / artShape.aspect;
85+ }
86+ }
87+ }
88+ }
89+readonly property int headerHeight: titleLabel.height;
90+Label {
91+ id: titleLabel;
92+ objectName: "titleLabel";
93+ anchors { right: parent.right;
94+ left: parent.left;
95+ top: artShapeHolder.bottom;
96+ topMargin: units.gu(1);
97+ }
98+ elide: Text.ElideRight;
99+ fontSize: "small";
100+ wrapMode: Text.Wrap;
101+ maximumLineCount: 2;
102+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
103+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
104+ visible: showHeader ;
105+ width: undefined;
106+ text: root.title;
107+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
108+ horizontalAlignment: Text.AlignHCenter;
109+ }
110+UbuntuShape {
111+ id: touchdown;
112+ objectName: "touchdown";
113+ anchors { fill: artShapeHolder }
114+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
115+ radius: "medium";
116+ borderSource: "radius_pressed.sci"
117+}
118+implicitHeight: titleLabel.y + titleLabel.height + units.gu(1);
119+}
tests/plugins/Dash/cardcreator/10.res+3−5
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -18,7 +16,7 @@ Loader {
1816 id: backgroundLoader;
1917 objectName: "backgroundLoader";
2018 anchors.fill: parent;
21− asynchronous: root.asynchronous;
19+ asynchronous: true;
2220 visible: status == Loader.Ready;
2321 sourceComponent: UbuntuShape {
2422 objectName: "background";
@@ -59,7 +57,7 @@ Row {
5957 objectName: "outerRow";
6058 property real margins: units.gu(1);
6159 spacing: margins;
62− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
60+ height: root.fixedHeaderHeight;
6361 anchors { top: parent.top;
6462 topMargin: units.gu(1);
6563left: parent.left;
@@ -103,7 +101,7 @@ left: parent.left;
103101 width: undefined;
104102 text: root.title;
105103 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
106− horizontalAlignment: root.titleAlignment;
104+ horizontalAlignment: Text.AlignLeft;
107105 }
108106,Label {
109107 id: subtitleLabel;
tests/plugins/Dash/cardcreator/10.res.cardcreatornew file+137
@@ -0,0 +1,137 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+Loader {
15+ id: backgroundLoader;
16+ objectName: "backgroundLoader";
17+ anchors.fill: parent;
18+ asynchronous: false;
19+ visible: status == Loader.Ready;
20+ sourceComponent: UbuntuShape {
21+ objectName: "background";
22+ radius: "medium";
23+ aspect: {
24+ switch (root.backgroundShapeStyle) {
25+ case "inset": return UbuntuShape.Inset;
26+ case "shadow": return UbuntuShape.DropShadow;
27+ default:
28+ case "flat": return UbuntuShape.Flat;
29+ }
30+ }
31+ backgroundColor: getColor(0) || "white";
32+ secondaryBackgroundColor: getColor(1) || backgroundColor;
33+ backgroundMode: UbuntuShape.VerticalGradient;
34+ anchors.fill: parent;
35+ source: backgroundImage.source ? backgroundImage : null;
36+ property real luminance: Style.luminance(backgroundColor);
37+ property Image backgroundImage: Image {
38+ objectName: "backgroundImage";
39+ source: {
40+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
41+ else return "";
42+ }
43+ }
44+ function getColor(index) {
45+ if (cardData && typeof cardData["background"] === "object"
46+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
47+ return cardData["background"]["elements"][index];
48+ } else return index === 0 ? "" : "";
49+ }
50+ }
51+ }
52+readonly property size artShapeSize: Qt.size(-1, -1);
53+readonly property int headerHeight: row.height;
54+Row {
55+ id: row;
56+ objectName: "outerRow";
57+ property real margins: units.gu(1);
58+ spacing: margins;
59+ anchors { top: parent.top;
60+ topMargin: units.gu(1);
61+left: parent.left;
62+ }
63+ anchors.right: parent.right;
64+ anchors.margins: margins;
65+ anchors.rightMargin: 0;
66+ data: [
67+ CroppedImageMinimumSourceSize {
68+ id: mascotImage;
69+ objectName: "mascotImage";
70+ anchors { verticalCenter: parent.verticalCenter; }
71+ source: cardData && cardData["mascot"] || "";
72+ width: units.gu(6);
73+ height: units.gu(5.625);
74+ horizontalAlignment: Image.AlignHCenter;
75+ verticalAlignment: Image.AlignVCenter;
76+ visible: showHeader;
77+
78+ }
79+,Item {
80+ id: headerTitleContainer;
81+ anchors { verticalCenter: parent.verticalCenter; }
82+ width: parent.width - x;
83+ implicitHeight: titleLabel.height + subtitleLabel.height;
84+ data: [
85+ Label {
86+ id: titleLabel;
87+ objectName: "titleLabel";
88+ anchors { right: parent.right;
89+rightMargin: units.gu(1);
90+left: parent.left;
91+ top: parent.top; }
92+ elide: Text.ElideRight;
93+ fontSize: "small";
94+ wrapMode: Text.Wrap;
95+ maximumLineCount: 2;
96+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
98+ visible: showHeader ;
99+ width: undefined;
100+ text: root.title;
101+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
102+ horizontalAlignment: Text.AlignLeft;
103+ }
104+,Label {
105+ id: subtitleLabel;
106+ objectName: "subtitleLabel";
107+ anchors { right: parent.right;
108+ left: parent.left;
109+rightMargin: units.gu(1);
110+top: titleLabel.bottom;
111+ }
112+ anchors.topMargin: units.dp(2);
113+ elide: Text.ElideRight;
114+ maximumLineCount: 1;
115+ fontSize: "x-small";
116+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
117+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
118+ visible: titleLabel.visible && titleLabel.text;
119+ text: cardData && cardData["subtitle"] || "";
120+ font.weight: Font.Light;
121+ }
122+
123+ ]
124+ }
125+
126+ ]
127+ }
128+UbuntuShape {
129+ id: touchdown;
130+ objectName: "touchdown";
131+ anchors { fill: backgroundLoader }
132+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
133+ radius: "medium";
134+ borderSource: "radius_pressed.sci"
135+ }
136+implicitHeight: row.y + row.height + units.gu(1);
137+}
tests/plugins/Dash/cardcreator/11.res+5−7
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -18,7 +16,7 @@ Loader {
1816 id: backgroundLoader;
1917 objectName: "backgroundLoader";
2018 anchors.fill: parent;
21− asynchronous: root.asynchronous;
19+ asynchronous: true;
2220 visible: status == Loader.Ready;
2321 sourceComponent: UbuntuShape {
2422 objectName: "background";
@@ -63,7 +61,7 @@ Item {
6361 objectName: "artShapeLoader";
6462 readonly property string cardArt: cardData && cardData["art"] || decodeURI("%5C");
6563 active: cardArt != "";
66− asynchronous: root.asynchronous;
64+ asynchronous: true;
6765 visible: status == Loader.Ready;
6866 sourceComponent: Item {
6967 id: artShape;
@@ -120,7 +118,7 @@ Item {
120118 id: artImage;
121119 objectName: "artImage";
122120 source: artShapeLoader.cardArt;
123− asynchronous: root.asynchronous;
121+ asynchronous: true;
124122 width: root.width;
125123 height: width / artShape.aspect;
126124 onStatusChanged: if (status === Image.Error) source = decodeURI("%5C");
@@ -134,7 +132,7 @@ Row {
134132 objectName: "outerRow";
135133 property real margins: units.gu(1);
136134 spacing: margins;
137− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
135+ height: root.fixedHeaderHeight;
138136 anchors { top: artShapeHolder.bottom;
139137 topMargin: units.gu(1);
140138left: parent.left;
@@ -178,7 +176,7 @@ left: parent.left;
178176 width: undefined;
179177 text: root.title;
180178 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
181− horizontalAlignment: root.titleAlignment;
179+ horizontalAlignment: Text.AlignLeft;
182180 }
183181,Label {
184182 id: subtitleLabel;
tests/plugins/Dash/cardcreator/11.res.cardcreatornew file+210
@@ -0,0 +1,210 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+Loader {
15+ id: backgroundLoader;
16+ objectName: "backgroundLoader";
17+ anchors.fill: parent;
18+ asynchronous: false;
19+ visible: status == Loader.Ready;
20+ sourceComponent: UbuntuShape {
21+ objectName: "background";
22+ radius: "medium";
23+ aspect: {
24+ switch (root.backgroundShapeStyle) {
25+ case "inset": return UbuntuShape.Inset;
26+ case "shadow": return UbuntuShape.DropShadow;
27+ default:
28+ case "flat": return UbuntuShape.Flat;
29+ }
30+ }
31+ backgroundColor: getColor(0) || "white";
32+ secondaryBackgroundColor: getColor(1) || backgroundColor;
33+ backgroundMode: UbuntuShape.VerticalGradient;
34+ anchors.fill: parent;
35+ source: backgroundImage.source ? backgroundImage : null;
36+ property real luminance: Style.luminance(backgroundColor);
37+ property Image backgroundImage: Image {
38+ objectName: "backgroundImage";
39+ source: {
40+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
41+ else return "";
42+ }
43+ }
44+ function getColor(index) {
45+ if (cardData && typeof cardData["background"] === "object"
46+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
47+ return cardData["background"]["elements"][index];
48+ } else return index === 0 ? "#E9E9E9" : undefined;
49+ }
50+ }
51+ }
52+readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
53+Item {
54+ id: artShapeHolder;
55+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
56+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
57+ anchors { horizontalCenter: parent.horizontalCenter; }
58+ Loader {
59+ id: artShapeLoader;
60+ objectName: "artShapeLoader";
61+ readonly property string cardArt: cardData && cardData["art"] || "";
62+ active: cardArt != "";
63+ asynchronous: false;
64+ visible: status == Loader.Ready;
65+ sourceComponent: Item {
66+ id: artShape;
67+ objectName: "artShape";
68+ visible: image.status == Image.Ready;
69+ readonly property alias image: artImage;
70+ ShaderEffectSource {
71+ id: artShapeSource;
72+ sourceItem: artImage;
73+ anchors.centerIn: parent;
74+ width: 1;
75+ height: 1;
76+ hideSource: true;
77+ }
78+ Loader {
79+ anchors.fill: parent;
80+ visible: true;
81+ sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
82+ Component {
83+ id: artShapeShapeComponent;
84+ UbuntuShape {
85+ source: artShapeSource;
86+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
87+ radius: "medium";
88+ aspect: {
89+ switch (root.artShapeStyle) {
90+ case "inset": return UbuntuShape.Inset;
91+ case "shadow": return UbuntuShape.DropShadow;
92+ default:
93+ case "flat": return UbuntuShape.Flat;
94+ }
95+ }
96+ }
97+ }
98+ Component {
99+ id: artShapeIconComponent;
100+ ProportionalShape { source: artShapeSource; aspect: UbuntuShape.DropShadow; }
101+ }
102+ }
103+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
104+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
105+ Component.onCompleted: { updateWidthHeightBindings(); }
106+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
107+ function updateWidthHeightBindings() {
108+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
109+ width = root.fixedArtShapeSize.width;
110+ height = root.fixedArtShapeSize.height;
111+ } else {
112+ width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width });
113+ height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height });
114+ }
115+ }
116+ CroppedImageMinimumSourceSize {
117+ id: artImage;
118+ objectName: "artImage";
119+ source: artShapeLoader.cardArt;
120+ asynchronous: false;
121+ width: root.width;
122+ height: width / artShape.aspect;
123+ }
124+ }
125+ }
126+ }
127+readonly property int headerHeight: row.height;
128+Row {
129+ id: row;
130+ objectName: "outerRow";
131+ property real margins: units.gu(1);
132+ spacing: margins;
133+ anchors { top: artShapeHolder.bottom;
134+ topMargin: units.gu(1);
135+left: parent.left;
136+ }
137+ anchors.right: parent.right;
138+ anchors.margins: margins;
139+ anchors.rightMargin: 0;
140+ data: [
141+ CroppedImageMinimumSourceSize {
142+ id: mascotImage;
143+ objectName: "mascotImage";
144+ anchors { verticalCenter: parent.verticalCenter; }
145+ source: cardData && cardData["mascot"] || "";
146+ width: units.gu(6);
147+ height: units.gu(5.625);
148+ horizontalAlignment: Image.AlignHCenter;
149+ verticalAlignment: Image.AlignVCenter;
150+ visible: showHeader;
151+ }
152+,Item {
153+ id: headerTitleContainer;
154+ anchors { verticalCenter: parent.verticalCenter; }
155+ width: parent.width - x;
156+ implicitHeight: titleLabel.height + subtitleLabel.height;
157+ data: [
158+ Label {
159+ id: titleLabel;
160+ objectName: "titleLabel";
161+ anchors { right: parent.right;
162+rightMargin: units.gu(1);
163+left: parent.left;
164+ top: parent.top; }
165+ elide: Text.ElideRight;
166+ fontSize: "small";
167+ wrapMode: Text.Wrap;
168+ maximumLineCount: 2;
169+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
170+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
171+ visible: showHeader ;
172+ width: undefined;
173+ text: root.title;
174+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
175+ horizontalAlignment: Text.AlignLeft;
176+ }
177+,Label {
178+ id: subtitleLabel;
179+ objectName: "subtitleLabel";
180+ anchors { right: parent.right;
181+ left: parent.left;
182+rightMargin: units.gu(1);
183+top: titleLabel.bottom;
184+ }
185+ anchors.topMargin: units.dp(2);
186+ elide: Text.ElideRight;
187+ maximumLineCount: 1;
188+ fontSize: "x-small";
189+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
190+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
191+ visible: titleLabel.visible && titleLabel.text;
192+ text: cardData && cardData["subtitle"] || "";
193+ font.weight: Font.Light;
194+ }
195+
196+ ]
197+ }
198+
199+ ]
200+ }
201+UbuntuShape {
202+ id: touchdown;
203+ objectName: "touchdown";
204+ anchors { fill: backgroundLoader }
205+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
206+ radius: "medium";
207+ borderSource: "radius_pressed.sci"
208+ }
209+implicitHeight: row.y + row.height + units.gu(1);
210+}
tests/plugins/Dash/cardcreator/12.res+6−7
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -23,8 +21,9 @@ Item {
2321 Loader {
2422 id: artShapeLoader;
2523 objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
24+ readonly property string cardArt: cardData && cardData["art"] || "";
25+ active: cardArt != "";
26+ asynchronous: true;
2827 visible: status == Loader.Ready;
2928 sourceComponent: Item {
3029 id: artShape;
@@ -80,8 +79,8 @@ Item {
8079 CroppedImageMinimumSourceSize {
8180 id: artImage;
8281 objectName: "artImage";
83− source: cardData && cardData["art"] || "";
84− asynchronous: root.asynchronous;
82+ source: artShapeLoader.cardArt;
83+ asynchronous: true;
8584 width: root.width;
8685 height: width / artShape.aspect;
8786 }
@@ -107,7 +106,7 @@ Label {
107106 width: undefined;
108107 text: root.title;
109108 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
110− horizontalAlignment: root.titleAlignment;
109+ horizontalAlignment: Text.AlignLeft;
111110 }
112111Label {
113112 id: subtitleLabel;
tests/plugins/Dash/cardcreator/2.res+3−5
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -18,7 +16,7 @@ Loader {
1816 id: backgroundLoader;
1917 objectName: "backgroundLoader";
2018 anchors.fill: parent;
21− asynchronous: root.asynchronous;
19+ asynchronous: true;
2220 visible: status == Loader.Ready;
2321 sourceComponent: UbuntuShape {
2422 objectName: "background";
@@ -59,7 +57,7 @@ Row {
5957 objectName: "outerRow";
6058 property real margins: units.gu(1);
6159 spacing: margins;
62− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
60+ height: root.fixedHeaderHeight;
6361 anchors { top: parent.top;
6462 topMargin: units.gu(1);
6563 left: parent.left;
@@ -102,7 +100,7 @@ CroppedImageMinimumSourceSize {
102100 width: undefined;
103101 text: root.title;
104102 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
105− horizontalAlignment: root.titleAlignment;
103+ horizontalAlignment: Text.AlignLeft;
106104 }
107105 ,Label {
108106 id: subtitleLabel;
tests/plugins/Dash/cardcreator/2.res.cardcreatornew file+136
@@ -0,0 +1,136 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+Loader {
15+ id: backgroundLoader;
16+ objectName: "backgroundLoader";
17+ anchors.fill: parent;
18+ asynchronous: false;
19+ visible: status == Loader.Ready;
20+ sourceComponent: UbuntuShape {
21+ objectName: "background";
22+ radius: "medium";
23+ aspect: {
24+ switch (root.backgroundShapeStyle) {
25+ case "inset": return UbuntuShape.Inset;
26+ case "shadow": return UbuntuShape.DropShadow;
27+ default:
28+ case "flat": return UbuntuShape.Flat;
29+ }
30+ }
31+ backgroundColor: getColor(0) || "white";
32+ secondaryBackgroundColor: getColor(1) || backgroundColor;
33+ backgroundMode: UbuntuShape.VerticalGradient;
34+ anchors.fill: parent;
35+ source: backgroundImage.source ? backgroundImage : null;
36+ property real luminance: Style.luminance(backgroundColor);
37+ property Image backgroundImage: Image {
38+ objectName: "backgroundImage";
39+ source: {
40+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
41+ else return "";
42+ }
43+ }
44+ function getColor(index) {
45+ if (cardData && typeof cardData["background"] === "object"
46+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
47+ return cardData["background"]["elements"][index];
48+ } else return index === 0 ? "#E9E9E9" : undefined;
49+ }
50+ }
51+ }
52+readonly property size artShapeSize: Qt.size(-1, -1);
53+readonly property int headerHeight: row.height;
54+Row {
55+ id: row;
56+ objectName: "outerRow";
57+ property real margins: units.gu(1);
58+ spacing: margins;
59+ anchors { top: parent.top;
60+ topMargin: units.gu(1);
61+ left: parent.left;
62+ }
63+ anchors.right: parent.right;
64+ anchors.margins: margins;
65+ anchors.rightMargin: 0;
66+ data: [
67+CroppedImageMinimumSourceSize {
68+ id: mascotImage;
69+ objectName: "mascotImage";
70+ anchors { verticalCenter: parent.verticalCenter; }
71+ source: cardData && cardData["mascot"] || "";
72+ width: units.gu(6);
73+ height: units.gu(5.625);
74+ horizontalAlignment: Image.AlignHCenter;
75+ verticalAlignment: Image.AlignVCenter;
76+ visible: showHeader;
77+ }
78+,Item {
79+ id: headerTitleContainer;
80+ anchors { verticalCenter: parent.verticalCenter; }
81+ width: parent.width - x;
82+ implicitHeight: titleLabel.height + subtitleLabel.height;
83+ data: [
84+ Label {
85+ id: titleLabel;
86+ objectName: "titleLabel";
87+ anchors { right: parent.right;
88+ rightMargin: units.gu(1);
89+ left: parent.left;
90+ top: parent.top; }
91+ elide: Text.ElideRight;
92+ fontSize: "small";
93+ wrapMode: Text.Wrap;
94+ maximumLineCount: 2;
95+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
96+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
97+ visible: showHeader ;
98+ width: undefined;
99+ text: root.title;
100+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
101+ horizontalAlignment: Text.AlignLeft;
102+ }
103+ ,Label {
104+ id: subtitleLabel;
105+ objectName: "subtitleLabel";
106+ anchors { right: parent.right;
107+ left: parent.left;
108+ rightMargin: units.gu(1);
109+ top: titleLabel.bottom;
110+ }
111+ anchors.topMargin: units.dp(2);
112+ elide: Text.ElideRight;
113+ maximumLineCount: 1;
114+ fontSize: "x-small";
115+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
116+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
117+ visible: titleLabel.visible && titleLabel.text;
118+ text: cardData && cardData["subtitle"] || "";
119+ font.weight: Font.Light;
120+ }
121+
122+ ]
123+ }
124+
125+ ]
126+ }
127+UbuntuShape {
128+ id: touchdown;
129+ objectName: "touchdown";
130+ anchors { fill: backgroundLoader }
131+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
132+ radius: "medium";
133+ borderSource: "radius_pressed.sci"
134+}
135+implicitHeight: row.y + row.height + units.gu(1);
136+}
tests/plugins/Dash/cardcreator/3.res+3−5
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -25,7 +23,7 @@ Item {
2523 objectName: "artShapeLoader";
2624 readonly property string cardArt: cardData && cardData["art"] || decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
2725 active: cardArt != "";
28− asynchronous: root.asynchronous;
26+ asynchronous: true;
2927 visible: status == Loader.Ready;
3028 sourceComponent: Item {
3129 id: artShape;
@@ -82,7 +80,7 @@ Item {
8280 id: artImage;
8381 objectName: "artImage";
8482 source: artShapeLoader.cardArt;
85− asynchronous: root.asynchronous;
83+ asynchronous: true;
8684 width: root.width;
8785 height: width / artShape.aspect;
8886 onStatusChanged: if (status === Image.Error) source = decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
@@ -109,7 +107,7 @@ Label {
109107 width: undefined;
110108 text: root.title;
111109 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
112− horizontalAlignment: root.titleAlignment;
110+ horizontalAlignment: Text.AlignLeft;
113111 }
114112Label {
115113 id: subtitleLabel;
tests/plugins/Dash/cardcreator/3.res.cardcreatornew file+137
@@ -0,0 +1,137 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
15+Item {
16+ id: artShapeHolder;
17+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
18+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
19+ anchors { horizontalCenter: parent.horizontalCenter; }
20+ Loader {
21+ id: artShapeLoader;
22+ objectName: "artShapeLoader";
23+ readonly property string cardArt: cardData && cardData["art"] || "";
24+ active: cardArt != "";
25+ asynchronous: false;
26+ visible: status == Loader.Ready;
27+ sourceComponent: Item {
28+ id: artShape;
29+ objectName: "artShape";
30+ visible: image.status == Image.Ready;
31+ readonly property alias image: artImage;
32+ ShaderEffectSource {
33+ id: artShapeSource;
34+ sourceItem: artImage;
35+ anchors.centerIn: parent;
36+ width: 1;
37+ height: 1;
38+ hideSource: true;
39+ }
40+ Loader {
41+ anchors.fill: parent;
42+ visible: true;
43+ sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
44+ Component {
45+ id: artShapeShapeComponent;
46+ UbuntuShape {
47+ source: artShapeSource;
48+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
49+ radius: "medium";
50+ aspect: {
51+ switch (root.artShapeStyle) {
52+ case "inset": return UbuntuShape.Inset;
53+ case "shadow": return UbuntuShape.DropShadow;
54+ default:
55+ case "flat": return UbuntuShape.Flat;
56+ }
57+ }
58+ }
59+ }
60+ Component {
61+ id: artShapeIconComponent;
62+ ProportionalShape { source: artShapeSource; aspect: UbuntuShape.DropShadow; }
63+ }
64+ }
65+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
66+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 0.75;
67+ Component.onCompleted: { updateWidthHeightBindings(); }
68+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
69+ function updateWidthHeightBindings() {
70+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
71+ width = root.fixedArtShapeSize.width;
72+ height = root.fixedArtShapeSize.height;
73+ } else {
74+ width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width });
75+ height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height });
76+ }
77+ }
78+ CroppedImageMinimumSourceSize {
79+ id: artImage;
80+ objectName: "artImage";
81+ source: artShapeLoader.cardArt;
82+ asynchronous: false;
83+ width: root.width;
84+ height: width / artShape.aspect;
85+ }
86+ }
87+ }
88+ }
89+readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
90+Label {
91+ id: titleLabel;
92+ objectName: "titleLabel";
93+ anchors { right: parent.right;
94+ left: parent.left;
95+ top: artShapeHolder.bottom;
96+ topMargin: units.gu(1);
97+ }
98+ elide: Text.ElideRight;
99+ fontSize: "small";
100+ wrapMode: Text.Wrap;
101+ maximumLineCount: 2;
102+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
103+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
104+ visible: showHeader ;
105+ width: undefined;
106+ text: root.title;
107+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
108+ horizontalAlignment: Text.AlignLeft;
109+ }
110+Label {
111+ id: subtitleLabel;
112+ objectName: "subtitleLabel";
113+ anchors { left: titleLabel.left;
114+ leftMargin: titleLabel.leftMargin;
115+ right: titleLabel.right;
116+ top: titleLabel.bottom;
117+ }
118+ anchors.topMargin: units.dp(2);
119+ elide: Text.ElideRight;
120+ maximumLineCount: 1;
121+ fontSize: "x-small";
122+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
123+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
124+ visible: titleLabel.visible && titleLabel.text;
125+ text: cardData && cardData["subtitle"] || "";
126+ font.weight: Font.Light;
127+ }
128+UbuntuShape {
129+ id: touchdown;
130+ objectName: "touchdown";
131+ anchors { fill: artShapeHolder }
132+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
133+ radius: "medium";
134+ borderSource: "radius_pressed.sci"
135+}
136+implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
137+}
tests/plugins/Dash/cardcreator/4.res+3−5
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -21,7 +19,7 @@ Row {
2119 objectName: "outerRow";
2220 property real margins: units.gu(1);
2321 spacing: margins;
24− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
22+ height: root.fixedHeaderHeight;
2523 anchors { top: parent.top;
2624 topMargin: units.gu(1);
2725 left: parent.left;
@@ -33,7 +31,7 @@ data: [
3331Loader {
3432 id: mascotShapeLoader;
3533 objectName: "mascotShapeLoader";
36− asynchronous: root.asynchronous;
34+ asynchronous: true;
3735 active: mascotImage.status === Image.Ready;
3836 visible: showHeader && active && status == Loader.Ready;
3937 width: units.gu(6);
@@ -77,7 +75,7 @@ Label {
7775 width: undefined;
7876 text: root.title;
7977 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
80− horizontalAlignment: root.titleAlignment;
78+ horizontalAlignment: Text.AlignLeft;
8179 }
8280,Label {
8381 id: subtitleLabel;
tests/plugins/Dash/cardcreator/4.res.cardcreatornew file+109
@@ -0,0 +1,109 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+readonly property size artShapeSize: Qt.size(-1, -1);
15+readonly property int headerHeight: row.height;
16+Row {
17+ id: row;
18+ objectName: "outerRow";
19+ property real margins: units.gu(1);
20+ spacing: margins;
21+ anchors { top: parent.top;
22+ topMargin: units.gu(1);
23+ left: parent.left;
24+}
25+ anchors.right: parent.right;
26+ anchors.margins: margins;
27+ anchors.rightMargin: 0;
28+data: [
29+Loader {
30+ id: mascotShapeLoader;
31+ objectName: "mascotShapeLoader";
32+ asynchronous: false;
33+ active: mascotImage.status === Image.Ready;
34+ visible: showHeader && active && status == Loader.Ready;
35+ width: units.gu(6);
36+ height: units.gu(5.625);
37+ sourceComponent: UbuntuShape { image: mascotImage }
38+ anchors { verticalCenter: parent.verticalCenter; }
39+ }
40+
41+,CroppedImageMinimumSourceSize {
42+ id: mascotImage;
43+ objectName: "mascotImage";
44+ anchors { verticalCenter: parent.verticalCenter; }
45+ source: cardData && cardData["mascot"] || "";
46+ width: units.gu(6);
47+ height: units.gu(5.625);
48+ horizontalAlignment: Image.AlignHCenter;
49+ verticalAlignment: Image.AlignVCenter;
50+ visible: false;
51+ }
52+
53+,Item {
54+ id: headerTitleContainer;
55+ anchors { verticalCenter: parent.verticalCenter; }
56+ width: parent.width - x;
57+ implicitHeight: titleLabel.height + subtitleLabel.height;
58+ data: [
59+Label {
60+ id: titleLabel;
61+ objectName: "titleLabel";
62+ anchors { right: parent.right;
63+ rightMargin: units.gu(1);
64+ left: parent.left;
65+ top: parent.top; }
66+ elide: Text.ElideRight;
67+ fontSize: "small";
68+ wrapMode: Text.Wrap;
69+ maximumLineCount: 2;
70+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
71+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
72+ visible: showHeader ;
73+ width: undefined;
74+ text: root.title;
75+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
76+ horizontalAlignment: Text.AlignLeft;
77+ }
78+,Label {
79+ id: subtitleLabel;
80+ objectName: "subtitleLabel";
81+ anchors { right: parent.right;
82+ left: parent.left;
83+ rightMargin: units.gu(1);
84+ top: titleLabel.bottom;
85+ }
86+ anchors.topMargin: units.dp(2);
87+ elide: Text.ElideRight;
88+ maximumLineCount: 1;
89+ fontSize: "x-small";
90+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
92+ visible: titleLabel.visible && titleLabel.text;
93+ text: cardData && cardData["subtitle"] || "";
94+ font.weight: Font.Light;
95+ }
96+]
97+}
98+]
99+}
100+UbuntuShape {
101+ id: touchdown;
102+ objectName: "touchdown";
103+ anchors { fill: root }
104+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
105+ radius: "medium";
106+ borderSource: "radius_pressed.sci"
107+}
108+implicitHeight: row.y + row.height + units.gu(1);
109+}
tests/plugins/Dash/cardcreator/5.res+5−7
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: false;
@@ -25,7 +23,7 @@ Item {
2523 objectName: "artShapeLoader";
2624 readonly property string cardArt: cardData && cardData["art"] || "";
2725 active: cardArt != "";
28− asynchronous: root.asynchronous;
26+ asynchronous: true;
2927 visible: status == Loader.Ready;
3028 sourceComponent: Item {
3129 id: artShape;
@@ -82,7 +80,7 @@ Item {
8280 id: artImage;
8381 objectName: "artImage";
8482 source: artShapeLoader.cardArt;
85− asynchronous: root.asynchronous;
83+ asynchronous: true;
8684 width: root.width;
8785 height: width / artShape.aspect;
8886 }
@@ -91,10 +89,10 @@ Item {
9189 }
9290Loader {
9391 id: overlayLoader;
94− readonly property real overlayHeight: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
92+ readonly property real overlayHeight: root.fixedHeaderHeight + units.gu(2);
9593 anchors.fill: artShapeHolder;
9694 active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
97− asynchronous: root.asynchronous;
95+ asynchronous: true;
9896 visible: showHeader && status == Loader.Ready;
9997 sourceComponent: UbuntuShapeOverlay {
10098 id: overlay;
@@ -126,7 +124,7 @@ Label {
126124 width: undefined;
127125 text: root.title;
128126 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
129− horizontalAlignment: root.titleAlignment;
127+ horizontalAlignment: Text.AlignLeft;
130128 }
131129Label {
132130 id: subtitleLabel;
tests/plugins/Dash/cardcreator/5.res.cardcreatornew file+156
@@ -0,0 +1,156 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: false;
13+signal action(var actionId);
14+readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
15+Item {
16+ id: artShapeHolder;
17+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
18+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
19+ anchors { horizontalCenter: parent.horizontalCenter; }
20+ Loader {
21+ id: artShapeLoader;
22+ objectName: "artShapeLoader";
23+ readonly property string cardArt: cardData && cardData["art"] || "";
24+ active: cardArt != "";
25+ asynchronous: false;
26+ visible: status == Loader.Ready;
27+ sourceComponent: Item {
28+ id: artShape;
29+ objectName: "artShape";
30+ visible: image.status == Image.Ready;
31+ readonly property alias image: artImage;
32+ ShaderEffectSource {
33+ id: artShapeSource;
34+ sourceItem: artImage;
35+ anchors.centerIn: parent;
36+ width: 1;
37+ height: 1;
38+ hideSource: false;
39+ }
40+ Loader {
41+ anchors.fill: parent;
42+ visible: false;
43+ sourceComponent: root.artShapeStyle === "icon" ? artShapeIconComponent : artShapeShapeComponent;
44+ Component {
45+ id: artShapeShapeComponent;
46+ UbuntuShape {
47+ source: artShapeSource;
48+ sourceFillMode: UbuntuShape.PreserveAspectCrop;
49+ radius: "medium";
50+ aspect: {
51+ switch (root.artShapeStyle) {
52+ case "inset": return UbuntuShape.Inset;
53+ case "shadow": return UbuntuShape.DropShadow;
54+ default:
55+ case "flat": return UbuntuShape.Flat;
56+ }
57+ }
58+ }
59+ }
60+ Component {
61+ id: artShapeIconComponent;
62+ ProportionalShape { source: artShapeSource; aspect: UbuntuShape.DropShadow; }
63+ }
64+ }
65+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
66+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : 1;
67+ Component.onCompleted: { updateWidthHeightBindings(); }
68+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
69+ function updateWidthHeightBindings() {
70+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
71+ width = root.fixedArtShapeSize.width;
72+ height = root.fixedArtShapeSize.height;
73+ } else {
74+ width = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.width });
75+ height = Qt.binding(function() { return image.status !== Image.Ready ? 0 : image.height });
76+ }
77+ }
78+ CroppedImageMinimumSourceSize {
79+ id: artImage;
80+ objectName: "artImage";
81+ source: artShapeLoader.cardArt;
82+ asynchronous: false;
83+ width: root.width;
84+ height: width / artShape.aspect;
85+ }
86+ }
87+ }
88+ }
89+Loader {
90+ id: overlayLoader;
91+ readonly property real overlayHeight: headerHeight + units.gu(2);
92+ anchors.fill: artShapeHolder;
93+ active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
94+ asynchronous: false;
95+ visible: showHeader && status == Loader.Ready;
96+ sourceComponent: UbuntuShapeOverlay {
97+ id: overlay;
98+ property real luminance: Style.luminance(overlayColor);
99+ aspect: UbuntuShape.Flat;
100+ radius: "medium";
101+ overlayColor: cardData && cardData["overlayColor"] || "#99000000";
102+ overlayRect: Qt.rect(0, 1 - overlayLoader.overlayHeight / height, 1, 1);
103+ }
104+ }
105+readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
106+Label {
107+ id: titleLabel;
108+ objectName: "titleLabel";
109+ anchors { right: parent.right;
110+ rightMargin: units.gu(1);
111+ left: parent.left;
112+ leftMargin: units.gu(1);
113+ top: overlayLoader.top;
114+ topMargin: units.gu(1) + overlayLoader.height - overlayLoader.overlayHeight;
115+ }
116+ elide: Text.ElideRight;
117+ fontSize: "small";
118+ wrapMode: Text.Wrap;
119+ maximumLineCount: 2;
120+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
121+ color: root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
122+ visible: showHeader && overlayLoader.active;
123+ width: undefined;
124+ text: root.title;
125+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
126+ horizontalAlignment: Text.AlignLeft;
127+ }
128+Label {
129+ id: subtitleLabel;
130+ objectName: "subtitleLabel";
131+ anchors { left: titleLabel.left;
132+ leftMargin: titleLabel.leftMargin;
133+ rightMargin: units.gu(1);
134+ right: titleLabel.right;
135+ top: titleLabel.bottom;
136+ }
137+ anchors.topMargin: units.dp(2);
138+ elide: Text.ElideRight;
139+ maximumLineCount: 1;
140+ fontSize: "x-small";
141+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
142+ color: root.scopeStyle && overlayLoader.item ? root.scopeStyle.getTextColor(overlayLoader.item.luminance) : (overlayLoader.item && overlayLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
143+ visible: titleLabel.visible && titleLabel.text;
144+ text: cardData && cardData["subtitle"] || "";
145+ font.weight: Font.Light;
146+ }
147+UbuntuShape {
148+ id: touchdown;
149+ objectName: "touchdown";
150+ anchors { fill: artShapeHolder }
151+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
152+ radius: "medium";
153+ borderSource: "radius_pressed.sci"
154+}
155+implicitHeight: artShapeHolder.height;
156+}
tests/plugins/Dash/cardcreator/6.res+2−4
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -18,7 +16,7 @@ Loader {
1816 id: backgroundLoader;
1917 objectName: "backgroundLoader";
2018 anchors.fill: parent;
21− asynchronous: root.asynchronous;
19+ asynchronous: true;
2220 visible: status == Loader.Ready;
2321 sourceComponent: UbuntuShape {
2422 objectName: "background";
@@ -81,7 +79,7 @@ Item {
8179 width: undefined;
8280 text: root.title;
8381 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
84− horizontalAlignment: root.titleAlignment;
82+ horizontalAlignment: Text.AlignLeft;
8583 }
8684,Label {
8785 id: subtitleLabel;
tests/plugins/Dash/cardcreator/6.res.cardcreatornew file+126
@@ -0,0 +1,126 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+Loader {
15+ id: backgroundLoader;
16+ objectName: "backgroundLoader";
17+ anchors.fill: parent;
18+ asynchronous: false;
19+ visible: status == Loader.Ready;
20+ sourceComponent: UbuntuShape {
21+ objectName: "background";
22+ radius: "medium";
23+ aspect: {
24+ switch (root.backgroundShapeStyle) {
25+ case "inset": return UbuntuShape.Inset;
26+ case "shadow": return UbuntuShape.DropShadow;
27+ default:
28+ case "flat": return UbuntuShape.Flat;
29+ }
30+ }
31+ backgroundColor: getColor(0) || "white";
32+ secondaryBackgroundColor: getColor(1) || backgroundColor;
33+ backgroundMode: UbuntuShape.VerticalGradient;
34+ anchors.fill: parent;
35+ source: backgroundImage.source ? backgroundImage : null;
36+ property real luminance: Style.luminance(backgroundColor);
37+ property Image backgroundImage: Image {
38+ objectName: "backgroundImage";
39+ source: {
40+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
41+ else return decodeURI("http://assets.ubuntu.com/sites/ubuntu/latest/u/img/logos/logo-ubuntu-grey.png");
42+ }
43+ }
44+ function getColor(index) {
45+ if (cardData && typeof cardData["background"] === "object"
46+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
47+ return cardData["background"]["elements"][index];
48+ } else return index === 0 ? undefined : undefined;
49+ }
50+ }
51+ }
52+readonly property size artShapeSize: Qt.size(-1, -1);
53+readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
54+Item {
55+ id: headerTitleContainer;
56+ anchors { right: parent.right; left: parent.left;
57+ top: parent.top;
58+ topMargin: units.gu(1);
59+ leftMargin: units.gu(1);
60+ }
61+ width: parent.width - x;
62+ implicitHeight: titleLabel.height + subtitleLabel.height;
63+ data: [
64+ Label {
65+ id: titleLabel;
66+ objectName: "titleLabel";
67+ anchors { right: emblemIcon.left;
68+ rightMargin: emblemIcon.width > 0 ? units.gu(0.5) : 0;
69+ left: parent.left;
70+ top: parent.top; }
71+ elide: Text.ElideRight;
72+ fontSize: "small";
73+ wrapMode: Text.Wrap;
74+ maximumLineCount: 2;
75+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
76+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
77+ visible: showHeader ;
78+ width: undefined;
79+ text: root.title;
80+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
81+ horizontalAlignment: Text.AlignLeft;
82+ }
83+,Label {
84+ id: subtitleLabel;
85+ objectName: "subtitleLabel";
86+ anchors { right: parent.right;
87+ left: parent.left;
88+ rightMargin: units.gu(1);
89+ top: titleLabel.bottom;
90+ }
91+ anchors.topMargin: units.dp(2);
92+ elide: Text.ElideRight;
93+ maximumLineCount: 1;
94+ fontSize: "x-small";
95+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
96+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
97+ visible: titleLabel.visible && titleLabel.text;
98+ text: cardData && cardData["subtitle"] || "";
99+ font.weight: Font.Light;
100+ }
101+,Icon {
102+ id: emblemIcon;
103+ objectName: "emblemIcon";
104+ anchors {
105+ bottom: titleLabel.baseline;
106+ right: parent.right;
107+ rightMargin: units.gu(1);
108+ }
109+ source: cardData && cardData["emblem"] || "";
110+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
111+ height: source != "" ? titleLabel.font.pixelSize : 0;
112+ width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth;
113+ }
114+
115+ ]
116+ }
117+UbuntuShape {
118+ id: touchdown;
119+ objectName: "touchdown";
120+ anchors { fill: backgroundLoader }
121+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
122+ radius: "medium";
123+ borderSource: "radius_pressed.sci"
124+}
125+implicitHeight: headerTitleContainer.y + headerTitleContainer.height + units.gu(1);
126+}
tests/plugins/Dash/cardcreator/7.res+3−5
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -18,7 +16,7 @@ Loader {
1816 id: backgroundLoader;
1917 objectName: "backgroundLoader";
2018 anchors.fill: parent;
21− asynchronous: root.asynchronous;
19+ asynchronous: true;
2220 visible: status == Loader.Ready;
2321 sourceComponent: UbuntuShape {
2422 objectName: "background";
@@ -59,7 +57,7 @@ Row {
5957 objectName: "outerRow";
6058 property real margins: units.gu(1);
6159 spacing: margins;
62− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
60+ height: root.fixedHeaderHeight;
6361 anchors { top: parent.top;
6462 topMargin: units.gu(1);
6563 left: parent.left;
@@ -103,7 +101,7 @@ CroppedImageMinimumSourceSize {
103101 width: undefined;
104102 text: root.title;
105103 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
106− horizontalAlignment: root.titleAlignment;
104+ horizontalAlignment: Text.AlignLeft;
107105 }
108106,Label {
109107 id: subtitleLabel;
tests/plugins/Dash/cardcreator/7.res.cardcreatornew file+149
@@ -0,0 +1,149 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+Loader {
15+ id: backgroundLoader;
16+ objectName: "backgroundLoader";
17+ anchors.fill: parent;
18+ asynchronous: false;
19+ visible: status == Loader.Ready;
20+ sourceComponent: UbuntuShape {
21+ objectName: "background";
22+ radius: "medium";
23+ aspect: {
24+ switch (root.backgroundShapeStyle) {
25+ case "inset": return UbuntuShape.Inset;
26+ case "shadow": return UbuntuShape.DropShadow;
27+ default:
28+ case "flat": return UbuntuShape.Flat;
29+ }
30+ }
31+ backgroundColor: getColor(0) || "white";
32+ secondaryBackgroundColor: getColor(1) || backgroundColor;
33+ backgroundMode: UbuntuShape.VerticalGradient;
34+ anchors.fill: parent;
35+ source: backgroundImage.source ? backgroundImage : null;
36+ property real luminance: Style.luminance(backgroundColor);
37+ property Image backgroundImage: Image {
38+ objectName: "backgroundImage";
39+ source: {
40+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
41+ else return "";
42+ }
43+ }
44+ function getColor(index) {
45+ if (cardData && typeof cardData["background"] === "object"
46+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
47+ return cardData["background"]["elements"][index];
48+ } else return index === 0 ? "#E9E9E9" : "#E9AAE9";
49+ }
50+ }
51+ }
52+readonly property size artShapeSize: Qt.size(-1, -1);
53+readonly property int headerHeight: row.height;
54+Row {
55+ id: row;
56+ objectName: "outerRow";
57+ property real margins: units.gu(1);
58+ spacing: margins;
59+ anchors { top: parent.top;
60+ topMargin: units.gu(1);
61+ left: parent.left;
62+ }
63+ anchors.right: parent.right;
64+ anchors.margins: margins;
65+ anchors.rightMargin: 0;
66+ data: [
67+CroppedImageMinimumSourceSize {
68+ id: mascotImage;
69+ objectName: "mascotImage";
70+ anchors { verticalCenter: parent.verticalCenter; }
71+ source: cardData && cardData["mascot"] || "";
72+ width: units.gu(6);
73+ height: units.gu(5.625);
74+ horizontalAlignment: Image.AlignHCenter;
75+ verticalAlignment: Image.AlignVCenter;
76+ visible: showHeader;
77+ }
78+
79+,Item {
80+ id: headerTitleContainer;
81+ anchors { verticalCenter: parent.verticalCenter; }
82+ width: parent.width - x;
83+ implicitHeight: titleLabel.height + subtitleLabel.height + attributesRow.height;
84+ data: [
85+ Label {
86+ id: titleLabel;
87+ objectName: "titleLabel";
88+ anchors { right: parent.right;
89+ rightMargin: units.gu(1);
90+ left: parent.left;
91+ top: parent.top; }
92+ elide: Text.ElideRight;
93+ fontSize: "small";
94+ wrapMode: Text.Wrap;
95+ maximumLineCount: 2;
96+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
98+ visible: showHeader ;
99+ width: undefined;
100+ text: root.title;
101+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
102+ horizontalAlignment: Text.AlignLeft;
103+ }
104+,Label {
105+ id: subtitleLabel;
106+ objectName: "subtitleLabel";
107+ anchors { right: parent.right;
108+ left: parent.left;
109+ rightMargin: units.gu(1);
110+ top: titleLabel.bottom;
111+ }
112+ anchors.topMargin: units.dp(2);
113+ elide: Text.ElideRight;
114+ maximumLineCount: 1;
115+ fontSize: "x-small";
116+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
117+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
118+ visible: titleLabel.visible && titleLabel.text;
119+ text: cardData && cardData["subtitle"] || "";
120+ font.weight: Font.Light;
121+ }
122+,CardAttributes {
123+ id: attributesRow;
124+ objectName: "attributesRow";
125+ anchors { right: parent.right;
126+ left: parent.left;
127+ rightMargin: units.gu(1);
128+ top: subtitleLabel.bottom;
129+ }
130+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
131+ fontScale: root.fontScale;
132+ model: cardData && cardData["attributes"];
133+ }
134+
135+ ]
136+ }
137+
138+ ]
139+ }
140+UbuntuShape {
141+ id: touchdown;
142+ objectName: "touchdown";
143+ anchors { fill: backgroundLoader }
144+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
145+ radius: "medium";
146+ borderSource: "radius_pressed.sci"
147+}
148+implicitHeight: row.y + row.height + units.gu(1);
149+}
tests/plugins/Dash/cardcreator/8.res+3−5
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -18,7 +16,7 @@ Loader {
1816 id: backgroundLoader;
1917 objectName: "backgroundLoader";
2018 anchors.fill: parent;
21− asynchronous: root.asynchronous;
19+ asynchronous: true;
2220 visible: status == Loader.Ready;
2321 sourceComponent: UbuntuShape {
2422 objectName: "background";
@@ -59,7 +57,7 @@ Row {
5957 objectName: "outerRow";
6058 property real margins: units.gu(1);
6159 spacing: margins;
62− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
60+ height: root.fixedHeaderHeight;
6361 anchors { top: parent.top;
6462 topMargin: units.gu(1);
6563left: parent.left;
@@ -94,7 +92,7 @@ left: parent.left;
9492 width: parent.width - x;
9593 text: root.title;
9694 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
97− horizontalAlignment: root.titleAlignment;
95+ horizontalAlignment: Text.AlignLeft;
9896 }
9997
10098 ]
tests/plugins/Dash/cardcreator/8.res.cardcreatornew file+107
@@ -0,0 +1,107 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+Loader {
15+ id: backgroundLoader;
16+ objectName: "backgroundLoader";
17+ anchors.fill: parent;
18+ asynchronous: false;
19+ visible: status == Loader.Ready;
20+ sourceComponent: UbuntuShape {
21+ objectName: "background";
22+ radius: "medium";
23+ aspect: {
24+ switch (root.backgroundShapeStyle) {
25+ case "inset": return UbuntuShape.Inset;
26+ case "shadow": return UbuntuShape.DropShadow;
27+ default:
28+ case "flat": return UbuntuShape.Flat;
29+ }
30+ }
31+ backgroundColor: getColor(0) || "white";
32+ secondaryBackgroundColor: getColor(1) || backgroundColor;
33+ backgroundMode: UbuntuShape.VerticalGradient;
34+ anchors.fill: parent;
35+ source: backgroundImage.source ? backgroundImage : null;
36+ property real luminance: Style.luminance(backgroundColor);
37+ property Image backgroundImage: Image {
38+ objectName: "backgroundImage";
39+ source: {
40+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
41+ else return "";
42+ }
43+ }
44+ function getColor(index) {
45+ if (cardData && typeof cardData["background"] === "object"
46+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
47+ return cardData["background"]["elements"][index];
48+ } else return index === 0 ? "#E9E9E9" : "#E9AAE9";
49+ }
50+ }
51+ }
52+readonly property size artShapeSize: Qt.size(-1, -1);
53+readonly property int headerHeight: row.height;
54+Row {
55+ id: row;
56+ objectName: "outerRow";
57+ property real margins: units.gu(1);
58+ spacing: margins;
59+ anchors { top: parent.top;
60+ topMargin: units.gu(1);
61+left: parent.left;
62+ }
63+ anchors.right: parent.right;
64+ anchors.margins: margins;
65+ anchors.rightMargin: 0;
66+ data: [
67+ CroppedImageMinimumSourceSize {
68+ id: mascotImage;
69+ objectName: "mascotImage";
70+ anchors { verticalCenter: parent.verticalCenter; }
71+ source: cardData && cardData["mascot"] || "";
72+ width: units.gu(6);
73+ height: units.gu(5.625);
74+ horizontalAlignment: Image.AlignHCenter;
75+ verticalAlignment: Image.AlignVCenter;
76+ visible: showHeader;
77+ }
78+,Label {
79+ id: titleLabel;
80+ objectName: "titleLabel";
81+ anchors { verticalCenter: parent.verticalCenter;
82+ }
83+ elide: Text.ElideRight;
84+ fontSize: "small";
85+ wrapMode: Text.Wrap;
86+ maximumLineCount: 2;
87+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
88+ color: backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white");
89+ visible: showHeader ;
90+ width: parent.width - x;
91+ text: root.title;
92+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
93+ horizontalAlignment: Text.AlignLeft;
94+ }
95+
96+ ]
97+ }
98+UbuntuShape {
99+ id: touchdown;
100+ objectName: "touchdown";
101+ anchors { fill: backgroundLoader }
102+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
103+ radius: "medium";
104+ borderSource: "radius_pressed.sci"
105+}
106+implicitHeight: row.y + row.height + units.gu(1);
107+}
tests/plugins/Dash/cardcreator/9.res+2−4
@@ -5,11 +5,9 @@ AbstractButton {
55 property string backgroundShapeStyle: "inset";
66 property real fontScale: 1.0;
77 property var scopeStyle: null;
8− property int titleAlignment: Text.AlignLeft;
98 property int fixedHeaderHeight: -1;
109 property size fixedArtShapeSize: Qt.size(-1, -1);
1110 readonly property string title: cardData && cardData["title"] || "";
12− property bool asynchronous: true;
1311 property bool showHeader: true;
1412 implicitWidth: childrenRect.width;
1513 enabled: true;
@@ -36,7 +34,7 @@ top: parent.top;
3634 width: undefined;
3735 text: root.title;
3836 font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
39− horizontalAlignment: root.titleAlignment;
37+ horizontalAlignment: Text.AlignLeft;
4038 }
4139Label {
4240 id: subtitleLabel;
@@ -72,7 +70,7 @@ CardAudioProgress {
7270 id: audioButton;
7371 anchors.fill: undefined;
7472 width: height;
75− height: (root.fixedHeaderHeight > 0 ? root.fixedHeaderHeight : headerHeight) + 2 * units.gu(1);
73+ height: root.fixedHeaderHeight + 2 * units.gu(1);
7674 readonly property url source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || "";
7775 UbuntuShape {
7876 anchors.fill: parent;
tests/plugins/Dash/cardcreator/9.res.cardcreatornew file+118
@@ -0,0 +1,118 @@
1+AbstractButton {
2+ id: root;
3+ property var cardData;
4+ property string artShapeStyle: "inset";
5+ property string backgroundShapeStyle: "inset";
6+ property real fontScale: 1.0;
7+ property var scopeStyle: null;
8+ property size fixedArtShapeSize: Qt.size(-1, -1);
9+ readonly property string title: cardData && cardData["title"] || "";
10+ property bool showHeader: true;
11+ implicitWidth: childrenRect.width;
12+ enabled: true;
13+signal action(var actionId);
14+readonly property size artShapeSize: Qt.size(-1, -1);
15+readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin + audioProgressBar.height + audioProgressBar.anchors.topMargin;
16+Label {
17+ id: titleLabel;
18+ objectName: "titleLabel";
19+ anchors { right: parent.right;
20+rightMargin: units.gu(1);
21+left: audioButton.right;
22+ leftMargin: units.gu(1);
23+top: parent.top;
24+ topMargin: units.gu(1);
25+ }
26+ elide: Text.ElideRight;
27+ fontSize: "small";
28+ wrapMode: Text.Wrap;
29+ maximumLineCount: 2;
30+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
31+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
32+ visible: showHeader ;
33+ width: undefined;
34+ text: root.title;
35+ font.weight: cardData && cardData["subtitle"] ? Font.DemiBold : Font.Normal;
36+ horizontalAlignment: Text.AlignLeft;
37+ }
38+Label {
39+ id: subtitleLabel;
40+ objectName: "subtitleLabel";
41+ anchors { left: titleLabel.left;
42+ leftMargin: titleLabel.leftMargin;
43+rightMargin: units.gu(1);
44+right: titleLabel.right;
45+top: titleLabel.bottom;
46+ }
47+ anchors.topMargin: units.dp(2);
48+ elide: Text.ElideRight;
49+ maximumLineCount: 1;
50+ fontSize: "x-small";
51+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
52+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
53+ visible: titleLabel.visible && titleLabel.text;
54+ text: cardData && cardData["subtitle"] || "";
55+ font.weight: Font.Light;
56+ }
57+CardAudioProgress {
58+ id: audioProgressBar;
59+ duration: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["duration"]) || 0;
60+ source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || "";
61+ anchors {
62+ bottom: audioButton.bottom;
63+ left: audioButton.right;
64+ right: parent.right;
65+ margins: units.gu(1);
66+ }
67+ color: root.scopeStyle ? root.scopeStyle.foreground : theme.palette.normal.baseText;
68+ }AbstractButton {
69+ id: audioButton;
70+ anchors.fill: undefined;
71+ width: height;
72+ height: headerHeight + 2 * units.gu(1);
73+ readonly property url source: (cardData["quickPreviewData"] && cardData["quickPreviewData"]["uri"]) || "";
74+ UbuntuShape {
75+ anchors.fill: parent;
76+ visible: parent.pressed;
77+ radius: "medium";
78+ }
79+ Rectangle {
80+ color: Qt.rgba(0, 0, 0, 0.5);
81+ anchors.centerIn: parent;
82+ width: parent.width * 0.5;
83+ height: width;
84+ radius: width / 2;
85+ }
86+ Icon {
87+ anchors.centerIn: parent;
88+ width: parent.width * 0.3;
89+ height: width;
90+ opacity: 0.9;
91+ name: DashAudioPlayer.playing && AudioUrlComparer.compare(parent.source, DashAudioPlayer.currentSource) ? "media-playback-pause" : "media-playback-start";
92+ color: "white";
93+ }
94+ onClicked: {
95+ if (AudioUrlComparer.compare(source, DashAudioPlayer.currentSource)) {
96+ if (DashAudioPlayer.playing) {
97+ DashAudioPlayer.pause();
98+ } else {
99+ DashAudioPlayer.play();
100+ }
101+ } else {
102+ var playlist = (cardData["quickPreviewData"] && cardData["quickPreviewData"]["playlist"]) || null;
103+ DashAudioPlayer.playSource(source, playlist);
104+ }
105+ }
106+ onPressAndHold: {
107+ root.pressAndHold();
108+ }
109+ }UbuntuShape {
110+ id: touchdown;
111+ objectName: "touchdown";
112+ anchors { fill: root }
113+ visible: root.artShapeStyle != "shadow" && root.artShapeStyle != "icon" && root.pressed;
114+ radius: "medium";
115+ borderSource: "radius_pressed.sci"
116+ }
117+implicitHeight: audioButton.height;
118+}
tests/plugins/Dash/cardcreatortest.cpp+32−22
@@ -45,6 +45,30 @@ private Q_SLOTS:
4545 delete view;
4646 }
4747
48+ void compareFileContents(const QString &filePath, const QString cardStringResult)
49+ {
50+ QFile testResultFile(filePath);
51+ QVERIFY(testResultFile.open(QIODevice::ReadOnly));
52+ QTextStream ts2(&testResultFile);
53+
54+ // Record failed results to /tmp
55+ const QString executedResult = cardStringResult;
56+ QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "testCardCreatorFailedResultXXXXXX");
57+ tmpFile.open();
58+ tmpFile.setAutoRemove(false);
59+ tmpFile.write(executedResult.toUtf8().constData());
60+
61+ // Line by line comparison
62+ const QStringList expectedLines = ts2.readAll().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
63+ const QStringList cardStringResultLines = cardStringResult.trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
64+ for (int i = 0; i < expectedLines.size(); ++i) {
65+ QCOMPARE(cardStringResultLines[i].simplified(), expectedLines[i].simplified());
66+ }
67+
68+ // Remove the result if it passed
69+ tmpFile.setAutoRemove(true);
70+ }
71+
4872 void testKnownCases()
4973 {
5074 const QString templateString("template: ");
@@ -68,33 +92,19 @@ private Q_SLOTS:
6892 const QString templateJSON = lines[0].mid(templateString.length());
6993 const QString componentsJSON = lines[1].mid(componentsString.length());
7094 const QString resultFileName = lines[2].mid(resultString.length());
71−
7295 QVariant cardStringResult;
73− QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON));
74−
75− QFile testResultFile(testDirPath + resultFileName);
76− QVERIFY(testResultFile.open(QIODevice::ReadOnly));
77− QTextStream ts2(&testResultFile);
96+ QVariant createCardComponentResult;
7897
79− // Record failed results to /tmp
80− const QString executedResult = cardStringResult.toString();
81− QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "testCardCreatorFailedResultXXXXXX");
82− tmpFile.open();
83− tmpFile.setAutoRemove(false);
84− tmpFile.write(executedResult.toUtf8().constData());
98+ QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, false));
99+ compareFileContents(testDirPath + resultFileName, cardStringResult.toString());
85100
86− // Line by line comparison
87− const QStringList expectedLines = ts2.readAll().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
88− const QStringList cardStringResultLines = cardStringResult.toString().trimmed().replace(QRegExp("\n\\s*\n"),"\n").split("\n");
89− for (int i = 0; i < expectedLines.size(); ++i) {
90− QCOMPARE(cardStringResultLines[i].simplified(), expectedLines[i].simplified());
91− }
101+ QMetaObject::invokeMethod(view->rootObject(), "cardString", Q_RETURN_ARG(QVariant, cardStringResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, true));
102+ compareFileContents(testDirPath + resultFileName + ".cardcreator", cardStringResult.toString());
92103
93− // Remove the result if it passed
94− tmpFile.setAutoRemove(true);
104+ QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, false));
105+ QVERIFY(createCardComponentResult.toBool());
95106
96− QVariant createCardComponentResult;
97− QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON));
107+ QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON), Q_ARG(QVariant, true));
98108 QVERIFY(createCardComponentResult.toBool());
99109 }
100110 }
tests/plugins/Dash/cardcreatortest.qml+4−4
@@ -19,11 +19,11 @@ import "../../../plugins/Dash/CardCreator.js" as CardCreator
1919
2020Item {
2121 id: root
22− function cardString(template, components) {
23− return CardCreator.cardString(JSON.parse(template), JSON.parse(components));
22+ function cardString(template, components, isCardCreator) {
23+ return CardCreator.cardString(JSON.parse(template), JSON.parse(components), isCardCreator);
2424 }
2525
26− function createCardComponent(template, components) {
27− return CardCreator.createCardComponent(root, JSON.parse(template), JSON.parse(components)) !== null;
26+ function createCardComponent(template, components, isCardCreator) {
27+ return CardCreator.createCardComponent(root, JSON.parse(template), JSON.parse(components), isCardCreator) !== null;
2828 }
2929}
tests/qmltests/Dash/tst_CardTool.qml+4−4
@@ -339,22 +339,22 @@ Rectangle {
339339 function test_card_title_alignment(data) {
340340 selector.selectedIndex = data.index;
341341
342− tryCompare(cardTool, "titleAlignment", Text.AlignLeft);
342+ tryCompareFunction(function() { return findChild(internalCard, "titleLabel").horizontalAlignment == Text.AlignLeft; }, true);
343343
344344 cardTool.components['title'] = { "field": "title", "align": "center" };
345345 cardTool.componentsChanged();
346346
347− tryCompare(cardTool, "titleAlignment", data.value);
347+ tryCompareFunction(function() { return findChild(internalCard, "titleLabel").horizontalAlignment == data.value; }, true);
348348
349349 cardTool.components['title'] = { "field": "title" };
350350 cardTool.componentsChanged();
351351
352− tryCompare(cardTool, "titleAlignment", data.value);
352+ tryCompareFunction(function() { return findChild(internalCard, "titleLabel").horizontalAlignment == data.value; }, true);
353353
354354 cardTool.components['title'] = { "field": "title", "align": "left" };
355355 cardTool.componentsChanged();
356356
357− tryCompare(cardTool, "titleAlignment", Text.AlignLeft);
357+ tryCompareFunction(function() { return findChild(internalCard, "titleLabel").horizontalAlignment == Text.AlignLeft; }, true);
358358 }
359359
360360 function test_categoryLayout_data() {