on xenial help sign in
Fix implicitHeight.
dc13178Ying-Chun Liu
plugins/Dash/CardCreator.js+2
@@ -575,6 +575,8 @@ function cardString(template, components) {
575 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
575 code += 'implicitHeight: row.y + row.height + units.gu(1);\n';
576 } else if (hasMascot) {
576 } else if (hasMascot) {
577 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
577 code += 'implicitHeight: mascotImage.y + mascotImage.height;\n';
578+ } else if (hasAttributes) {
579+ code += 'implicitHeight: attributesRow.y + attributesRow.height + units.gu(1);\n';
578 } else if (hasSubtitle) {
580 } else if (hasSubtitle) {
579 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
581 code += 'implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);\n';
580 } else if (hasTitle) {
582 } else if (hasTitle) {
tests/plugins/Dash/cardcreator/1.res+63−61
@@ -5,8 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8− property var scopeStyle: null;
8+ property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
10 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
12 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -16,71 +16,73 @@ AbstractButton {
16onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
16onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
17readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
17readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
18Item {
18Item {
19− id: artShapeHolder;
19+ id: artShapeHolder;
20− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
20+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
21+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22− anchors { horizontalCenter: parent.horizontalCenter; }
22+ anchors { horizontalCenter: parent.horizontalCenter; }
23− Loader {
23+ Loader {
24− id: artShapeLoader;
24+ id: artShapeLoader;
25− objectName: "artShapeLoader";
25+ objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
26+ active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
28− visible: status == Loader.Ready;
29− sourceComponent: UbuntuShape {
30− id: artShape;
31− objectName: "artShape";
32− radius: "medium";
33− visible: image.status == Image.Ready;
34− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37− Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40− function updateWidthHeightBindings() {
41− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42− width = root.fixedArtShapeSize.width;
43− height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47− } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49− height = Qt.binding(function() { return !visible ? 0 : image.height });
50− }
51− }
52− image: Image {
53− objectName: "artImage";
54− source: cardData && cardData["art"] || "";
55− cache: true;
56 asynchronous: root.asynchronous;
27 asynchronous: root.asynchronous;
28+ visible: status == Loader.Ready;
29+ sourceComponent: UbuntuShape {
30+ id: artShape;
31+ objectName: "artShape";
32+ radius: "medium";
33+ visible: image.status == Image.Ready;
34+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36+ readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38+ onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40+ function updateWidthHeightBindings() {
41+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42+ width = root.fixedArtShapeSize.width;
43+ height = root.fixedArtShapeSize.height;
44+ } else if (aspectSmallerThanImageAspect) {
45+ width = Qt.binding(function() { return !visible ? 0 : image.width });
46+ height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47+ } else {
48+ width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49+ height = Qt.binding(function() { return !visible ? 0 : image.height });
50+ }
51+ }
52+ image: Image {
53+ objectName: "artImage";
54+ source: cardData && cardData["art"] || "";
55+ cache: true;
56+ asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
57+ fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
58+ readonly property real aspect: implicitWidth / implicitHeight;
59− width: root.width;
59+ width: root.width;
60− height: width / artShape.aspect;
60+ height: width / artShape.aspect;
61+ }
62+ }
61 }
63 }
62− }
64+ }
63− }
64− }
65readonly property int headerHeight: titleLabel.height;
65readonly property int headerHeight: titleLabel.height;
66Label {
66Label {
67− id: titleLabel;
67+ id: titleLabel;
68− objectName: "titleLabel";
68+ objectName: "titleLabel";
69− anchors { right: parent.right;left: parent.left;
69+ anchors { right: parent.right;
70+rightMargin: units.gu(1);
71+left: parent.left;
70top: artShapeHolder.bottom;
72top: artShapeHolder.bottom;
71 topMargin: units.gu(1);
73 topMargin: units.gu(1);
72leftMargin: units.gu(1);
74leftMargin: units.gu(1);
73− }
75+ }
74− elide: Text.ElideRight;
76+ elide: Text.ElideRight;
75− fontSize: "small";
77+ fontSize: "small";
76− wrapMode: Text.Wrap;
78+ wrapMode: Text.Wrap;
77− maximumLineCount: 2;
79+ maximumLineCount: 2;
78− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
80+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
79− color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
81+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
80− visible: showHeader ;
82+ visible: showHeader ;
81− text: root.title;
83+ text: root.title;
82− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
84+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
83− horizontalAlignment: root.headerAlignment;
85+ horizontalAlignment: root.headerAlignment;
84− }
86+ }
85implicitHeight: titleLabel.y + titleLabel.height + units.gu(1);
87implicitHeight: titleLabel.y + titleLabel.height + units.gu(1);
86}
88}
tests/plugins/Dash/cardcreator/2.res+94−91
@@ -5,8 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8− property var scopeStyle: null;
8+ property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
10 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
12 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -14,104 +14,107 @@ AbstractButton {
14 property bool showHeader: true;
14 property bool showHeader: true;
15 implicitWidth: childrenRect.width;
15 implicitWidth: childrenRect.width;
16Loader {
16Loader {
17− id: backgroundLoader;
17+ id: backgroundLoader;
18− objectName: "backgroundLoader";
18+ objectName: "backgroundLoader";
19− anchors.fill: parent;
19+ anchors.fill: parent;
20− asynchronous: root.asynchronous;
20+ asynchronous: root.asynchronous;
21− visible: status == Loader.Ready;
21+ visible: status == Loader.Ready;
22− sourceComponent: UbuntuShape {
22+ sourceComponent: UbuntuShape {
23− objectName: "background";
23+ objectName: "background";
24− radius: "medium";
24+ radius: "medium";
25− color: getColor(0) || "white";
25+ color: getColor(0) || "white";
26− gradientColor: getColor(1) || color;
26+ gradientColor: getColor(1) || color;
27− anchors.fill: parent;
27+ anchors.fill: parent;
28− image: backgroundImage.source ? backgroundImage : null;
28+ image: backgroundImage.source ? backgroundImage : null;
29− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
29+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
30− property Image backgroundImage: Image {
30+ property Image backgroundImage: Image {
31− objectName: "backgroundImage";
31+ objectName: "backgroundImage";
32− source: {
32+ source: {
33− if (cardData && typeof cardData["background"] === "string") return cardData["background"];
33+ if (cardData && typeof cardData["background"] === "string") return cardData["background"];
34− else if (template && typeof template["card-background"] === "string") return template["card-background"];
34+ else if (template && typeof template["card-background"] === "string") return template["card-background"];
35− else return "";
35+ else return "";
36− }
36+ }
37− }
37+ }
38− function getColor(index) {
38+ function getColor(index) {
39− if (cardData && typeof cardData["background"] === "object"
39+ if (cardData && typeof cardData["background"] === "object"
40− && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
40+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
41− return cardData["background"]["elements"][index];
41+ return cardData["background"]["elements"][index];
42− } else if (template && typeof template["card-background"] === "object"
42+ } else if (template && typeof template["card-background"] === "object"
43− && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
43+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
44− return template["card-background"]["elements"][index];
44+ return template["card-background"]["elements"][index];
45− } else return undefined;
45+ } else return undefined;
46− }
46+ }
47− }
47+ }
48− }
48+ }
49readonly property size artShapeSize: Qt.size(-1, -1);
49readonly property size artShapeSize: Qt.size(-1, -1);
50readonly property int headerHeight: row.height;
50readonly property int headerHeight: row.height;
51Row {
51Row {
52− id: row;
52+ id: row;
53− objectName: "outerRow";
53+ objectName: "outerRow";
54− property real margins: units.gu(1);
54+ property real margins: units.gu(1);
55− spacing: margins;
55+ spacing: margins;
56− height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
56+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight;
57− anchors { top: parent.top;
57+ anchors { top: parent.top;
58 topMargin: units.gu(1);
58 topMargin: units.gu(1);
59− left: parent.left;
59+left: parent.left;
60−}
60+ }
61− anchors.right: parent.right;
61+ anchors.right: parent.right;
62− anchors.margins: margins;
62+ anchors.margins: margins;
63−data: [ Image {
63+ data: [ Image {
64− id: mascotImage;
64+ id: mascotImage;
65− objectName: "mascotImage";
65+ objectName: "mascotImage";
66− anchors { verticalCenter: parent.verticalCenter; }
66+ anchors { verticalCenter: parent.verticalCenter; }
67− readonly property int maxSize: Math.max(width, height) * 4;
67+ readonly property int maxSize: Math.max(width, height) * 4;
68− source: cardData && cardData["mascot"];
68+ source: cardData && cardData["mascot"];
69− width: units.gu(6);
69+ width: units.gu(6);
70− height: units.gu(5.625);
70+ height: units.gu(5.625);
71− sourceSize { width: maxSize; height: maxSize }
71+ sourceSize { width: maxSize; height: maxSize }
72− fillMode: Image.PreserveAspectCrop;
72+ fillMode: Image.PreserveAspectCrop;
73− horizontalAlignment: Image.AlignHCenter;
73+ horizontalAlignment: Image.AlignHCenter;
74− verticalAlignment: Image.AlignVCenter;
74+ verticalAlignment: Image.AlignVCenter;
75− visible: showHeader;
76− }
77−,
78−Column {
79− anchors.verticalCenter: parent.verticalCenter;
80− spacing: units.dp(2);
81− width: parent.width - x;
82− data: [ Label {
83− id: titleLabel;
84− objectName: "titleLabel";
85− anchors { left: parent.left; right: parent.right }
86− elide: Text.ElideRight;
87− fontSize: "small";
88− wrapMode: Text.Wrap;
89− maximumLineCount: 2;
90− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
92− visible: showHeader ;
75+ visible: showHeader;
93− text: root.title;
76+ }
94− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
95− horizontalAlignment: root.headerAlignment;
96− }
97−,
98−Label {
99− id: subtitleLabel;
100− objectName: "subtitleLabel";
101− anchors { left: parent.left; right: parent.right }
102
77
78+ ,
79+ Column {
80+ anchors.verticalCenter: parent.verticalCenter;
81+ spacing: units.dp(2);
82+ width: parent.width - x;
83+ data: [ Label {
84+ id: titleLabel;
85+ objectName: "titleLabel";
86+ anchors { left: parent.left; right: parent.right }
103 elide: Text.ElideRight;
87 elide: Text.ElideRight;
104 fontSize: "small";
88 fontSize: "small";
89+ wrapMode: Text.Wrap;
90+ maximumLineCount: 2;
105 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
106− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
92+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
107− visible: titleLabel.visible && titleLabel.text;
93+ visible: showHeader ;
108− text: cardData && cardData["subtitle"] || "";
94+ text: root.title;
109− font.weight: Font.Light;
95+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
110 horizontalAlignment: root.headerAlignment;
96 horizontalAlignment: root.headerAlignment;
111 }
97 }
98+
99+ ,
100+ Label {
101+ id: subtitleLabel;
102+ objectName: "subtitleLabel";
103+ anchors { left: parent.left; right: parent.right }
104+ elide: Text.ElideRight;
105+ fontSize: "small";
106+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
107+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
108+ visible: titleLabel.visible && titleLabel.text;
109+ text: cardData && cardData["subtitle"] || "";
110+ font.weight: Font.Light;
111+ horizontalAlignment: root.headerAlignment;
112+ }
113+
112−]
114+ ]
113−}
115+ }
116+
114−]
117+ ]
115−}
118+ }
116implicitHeight: row.y + row.height + units.gu(1);
119implicitHeight: row.y + row.height + units.gu(1);
117}
120}
tests/plugins/Dash/cardcreator/3.res+77−74
@@ -5,8 +5,8 @@ AbstractButton {
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7 property real fontScale: 1.0;
7 property real fontScale: 1.0;
8− property var scopeStyle: null;
8+ property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
10 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
12 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -16,89 +16,92 @@ AbstractButton {
16onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
16onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
17readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
17readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
18Item {
18Item {
19− id: artShapeHolder;
19+ id: artShapeHolder;
20− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
20+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
21+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22− anchors { horizontalCenter: parent.horizontalCenter; }
22+ anchors { horizontalCenter: parent.horizontalCenter; }
23− Loader {
23+ Loader {
24− id: artShapeLoader;
24+ id: artShapeLoader;
25− objectName: "artShapeLoader";
25+ objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
26+ active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
28− visible: status == Loader.Ready;
29− sourceComponent: UbuntuShape {
30− id: artShape;
31− objectName: "artShape";
32− radius: "medium";
33− visible: image.status == Image.Ready;
34− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37− Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40− function updateWidthHeightBindings() {
41− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42− width = root.fixedArtShapeSize.width;
43− height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47− } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49− height = Qt.binding(function() { return !visible ? 0 : image.height });
50− }
51− }
52− image: Image {
53− objectName: "artImage";
54− source: cardData && cardData["art"] || "";
55− cache: true;
56 asynchronous: root.asynchronous;
27 asynchronous: root.asynchronous;
28+ visible: status == Loader.Ready;
29+ sourceComponent: UbuntuShape {
30+ id: artShape;
31+ objectName: "artShape";
32+ radius: "medium";
33+ visible: image.status == Image.Ready;
34+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36+ readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38+ onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40+ function updateWidthHeightBindings() {
41+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42+ width = root.fixedArtShapeSize.width;
43+ height = root.fixedArtShapeSize.height;
44+ } else if (aspectSmallerThanImageAspect) {
45+ width = Qt.binding(function() { return !visible ? 0 : image.width });
46+ height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47+ } else {
48+ width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49+ height = Qt.binding(function() { return !visible ? 0 : image.height });
50+ }
51+ }
52+ image: Image {
53+ objectName: "artImage";
54+ source: cardData && cardData["art"] || "";
55+ cache: true;
56+ asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
57+ fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
58+ readonly property real aspect: implicitWidth / implicitHeight;
59− width: root.width;
59+ width: root.width;
60− height: width / artShape.aspect;
60+ height: width / artShape.aspect;
61+ }
62+ }
61 }
63 }
62− }
64+ }
63− }
64− }
65readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
65readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
66Label {
66Label {
67− id: titleLabel;
67+ id: titleLabel;
68− objectName: "titleLabel";
68+ objectName: "titleLabel";
69− anchors { right: parent.right;left: parent.left;
69+ anchors { right: parent.right;
70+rightMargin: units.gu(1);
71+left: parent.left;
70top: artShapeHolder.bottom;
72top: artShapeHolder.bottom;
71 topMargin: units.gu(1);
73 topMargin: units.gu(1);
72leftMargin: units.gu(1);
74leftMargin: units.gu(1);
73−}
74− elide: Text.ElideRight;
75− fontSize: "small";
76− wrapMode: Text.Wrap;
77− maximumLineCount: 2;
78− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
79− color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
80− visible: showHeader ;
81− text: root.title;
82− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
83− horizontalAlignment: root.headerAlignment;
84− }
75+ }
85−Label {
86− id: subtitleLabel;
87− objectName: "subtitleLabel";
88− anchors { left: titleLabel.left;
89− leftMargin: titleLabel.leftMargin;
90− right: titleLabel.right;
91− top: titleLabel.bottom;
92− topMargin: units.dp(2);
93− }
94 elide: Text.ElideRight;
76 elide: Text.ElideRight;
95 fontSize: "small";
77 fontSize: "small";
78+ wrapMode: Text.Wrap;
79+ maximumLineCount: 2;
96 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
80 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
97− color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
81+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
98− visible: titleLabel.visible && titleLabel.text;
82+ visible: showHeader ;
99− text: cardData && cardData["subtitle"] || "";
83+ text: root.title;
100− font.weight: Font.Light;
84+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
101 horizontalAlignment: root.headerAlignment;
85 horizontalAlignment: root.headerAlignment;
102 }
86 }
87+Label {
88+ id: subtitleLabel;
89+ objectName: "subtitleLabel";
90+ anchors { left: titleLabel.left;
91+ leftMargin: titleLabel.leftMargin;
92+ right: titleLabel.right;
93+ rightMargin: titleLabel.rightMargin;
94+ top: titleLabel.bottom;
95+ topMargin: units.dp(2);
96+ }
97+ elide: Text.ElideRight;
98+ fontSize: "small";
99+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
100+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey";
101+ visible: titleLabel.visible && titleLabel.text;
102+ text: cardData && cardData["subtitle"] || "";
103+ font.weight: Font.Light;
104+ horizontalAlignment: root.headerAlignment;
105+ }
103implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
106implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
104}
107}
tests/plugins/Dash/cardcreator/5.res+119−117
@@ -4,9 +4,9 @@ AbstractButton {
4 property var components;
4 property var components;
5 property var cardData;
5 property var cardData;
6 property var artShapeBorderSource: undefined;
6 property var artShapeBorderSource: undefined;
7− property real fontScale: 1.0;
7+ property real fontScale: 1.0;
8− property var scopeStyle: null;
8+ property var scopeStyle: null;
9− property int headerAlignment: Text.AlignLeft;
9+ property int headerAlignment: Text.AlignLeft;
10 property int fixedHeaderHeight: -1;
10 property int fixedHeaderHeight: -1;
11 property size fixedArtShapeSize: Qt.size(-1, -1);
11 property size fixedArtShapeSize: Qt.size(-1, -1);
12 readonly property string title: cardData && cardData["title"] || "";
12 readonly property string title: cardData && cardData["title"] || "";
@@ -16,130 +16,132 @@ AbstractButton {
16onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
16onArtShapeBorderSourceChanged: { if (artShapeBorderSource !== undefined && artShapeLoader.item) artShapeLoader.item.borderSource = artShapeBorderSource; }
17readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
17readonly property size artShapeSize: artShapeLoader.item ? Qt.size(artShapeLoader.item.width, artShapeLoader.item.height) : Qt.size(-1, -1);
18Item {
18Item {
19− id: artShapeHolder;
19+ id: artShapeHolder;
20− height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
20+ height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height;
21− width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
21+ width: root.fixedArtShapeSize.width > 0 ? root.fixedArtShapeSize.width : artShapeLoader.width;
22− anchors { horizontalCenter: parent.horizontalCenter; }
22+ anchors { horizontalCenter: parent.horizontalCenter; }
23− Loader {
23+ Loader {
24− id: artShapeLoader;
24+ id: artShapeLoader;
25− objectName: "artShapeLoader";
25+ objectName: "artShapeLoader";
26− active: cardData && cardData["art"] || false;
26+ active: cardData && cardData["art"] || false;
27− asynchronous: root.asynchronous;
28− visible: status == Loader.Ready;
29− sourceComponent: UbuntuShape {
30− id: artShape;
31− objectName: "artShape";
32− radius: "medium";
33− visible: image.status == Image.Ready;
34− readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35− readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36− readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37− Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38− onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39− Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40− function updateWidthHeightBindings() {
41− if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42− width = root.fixedArtShapeSize.width;
43− height = root.fixedArtShapeSize.height;
44− } else if (aspectSmallerThanImageAspect) {
45− width = Qt.binding(function() { return !visible ? 0 : image.width });
46− height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47− } else {
48− width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49− height = Qt.binding(function() { return !visible ? 0 : image.height });
50− }
51− }
52− image: Image {
53− objectName: "artImage";
54− source: cardData && cardData["art"] || "";
55− cache: true;
56 asynchronous: root.asynchronous;
27 asynchronous: root.asynchronous;
28+ visible: status == Loader.Ready;
29+ sourceComponent: UbuntuShape {
30+ id: artShape;
31+ objectName: "artShape";
32+ radius: "medium";
33+ visible: image.status == Image.Ready;
34+ readonly property real fixedArtShapeSizeAspect: (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) ? root.fixedArtShapeSize.width / root.fixedArtShapeSize.height : -1;
35+ readonly property real aspect: fixedArtShapeSizeAspect > 0 ? fixedArtShapeSizeAspect : components !== undefined ? components["art"]["aspect-ratio"] : 1;
36+ readonly property bool aspectSmallerThanImageAspect: aspect < image.aspect;
37+ Component.onCompleted: { updateWidthHeightBindings(); if (artShapeBorderSource !== undefined) borderSource = artShapeBorderSource; }
38+ onAspectSmallerThanImageAspectChanged: updateWidthHeightBindings();
39+ Connections { target: root; onFixedArtShapeSizeChanged: updateWidthHeightBindings(); }
40+ function updateWidthHeightBindings() {
41+ if (root.fixedArtShapeSize.height > 0 && root.fixedArtShapeSize.width > 0) {
42+ width = root.fixedArtShapeSize.width;
43+ height = root.fixedArtShapeSize.height;
44+ } else if (aspectSmallerThanImageAspect) {
45+ width = Qt.binding(function() { return !visible ? 0 : image.width });
46+ height = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.height : width / image.aspect });
47+ } else {
48+ width = Qt.binding(function() { return !visible ? 0 : image.fillMode === Image.PreserveAspectCrop ? image.width : height * image.aspect });
49+ height = Qt.binding(function() { return !visible ? 0 : image.height });
50+ }
51+ }
52+ image: Image {
53+ objectName: "artImage";
54+ source: cardData && cardData["art"] || "";
55+ cache: true;
56+ asynchronous: root.asynchronous;
57− fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
57+ fillMode: components && components["art"]["fill-mode"] === "fit" ? Image.PreserveAspectFit: Image.PreserveAspectCrop;
58− readonly property real aspect: implicitWidth / implicitHeight;
58+ readonly property real aspect: implicitWidth / implicitHeight;
59− width: root.width;
59+ width: root.width;
60− height: width / artShape.aspect;
60+ height: width / artShape.aspect;
61+ }
62+ }
61 }
63 }
62− }
64+ }
63− }
64− }
65Loader {
65Loader {
66− id: overlayLoader;
66+ id: overlayLoader;
67− anchors {
67+ anchors {
68− left: artShapeHolder.left;
68+ left: artShapeHolder.left;
69− right: artShapeHolder.right;
69+ right: artShapeHolder.right;
70− bottom: artShapeHolder.bottom;
70+ bottom: artShapeHolder.bottom;
71− }
71+ }
72− active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
72+ active: artShapeLoader.active && artShapeLoader.item && artShapeLoader.item.image.status === Image.Ready || false;
73− asynchronous: root.asynchronous;
73+ asynchronous: root.asynchronous;
74− visible: showHeader && status == Loader.Ready;
74+ visible: showHeader && status == Loader.Ready;
75− sourceComponent: ShaderEffect {
75+ sourceComponent: ShaderEffect {
76− id: overlay;
76+ id: overlay;
77− height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
77+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
78− opacity: 0.6;
78+ opacity: 0.6;
79− property var source: ShaderEffectSource {
79+ property var source: ShaderEffectSource {
80− id: shaderSource;
80+ id: shaderSource;
81− sourceItem: artShapeLoader.item;
81+ sourceItem: artShapeLoader.item;
82− onVisibleChanged: if (visible) scheduleUpdate();
82+ onVisibleChanged: if (visible) scheduleUpdate();
83− live: false;
83+ live: false;
84− sourceRect: Qt.rect(0, artShapeLoader.height - overlay.height, artShapeLoader.width, overlay.height);
84+ sourceRect: Qt.rect(0, artShapeLoader.height - overlay.height, artShapeLoader.width, overlay.height);
85− }
85+ }
86− vertexShader: "
86+ vertexShader: "
87− uniform highp mat4 qt_Matrix;
87+ uniform highp mat4 qt_Matrix;
88− attribute highp vec4 qt_Vertex;
88+ attribute highp vec4 qt_Vertex;
89− attribute highp vec2 qt_MultiTexCoord0;
89+ attribute highp vec2 qt_MultiTexCoord0;
90− varying highp vec2 coord;
90+ varying highp vec2 coord;
91− void main() {
91+ void main() {
92− coord = qt_MultiTexCoord0;
92+ coord = qt_MultiTexCoord0;
93− gl_Position = qt_Matrix * qt_Vertex;
93+ gl_Position = qt_Matrix * qt_Vertex;
94− }";
94+ }";
95− fragmentShader: "
95+ fragmentShader: "
96− varying highp vec2 coord;
96+ varying highp vec2 coord;
97− uniform sampler2D source;
97+ uniform sampler2D source;
98− uniform lowp float qt_Opacity;
98+ uniform lowp float qt_Opacity;
99− void main() {
99+ void main() {
100− lowp vec4 tex = texture2D(source, coord);
100+ lowp vec4 tex = texture2D(source, coord);
101− gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
101+ gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
102− }";
102+ }";
103− }
103+ }
104− }
104+ }
105readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
105readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
106Label {
106Label {
107− id: titleLabel;
107+ id: titleLabel;
108− objectName: "titleLabel";
108+ objectName: "titleLabel";
109− anchors { left: parent.left;
109+ anchors { left: parent.left;
110− leftMargin: units.gu(1);
110+ leftMargin: units.gu(1);
111− right: parent.right;
111+ right: parent.right;
112− top: overlayLoader.top;
113− topMargin: units.gu(1);
112+ rightMargin: units.gu(1);
114−}
115− elide: Text.ElideRight;
116− fontSize: "small";
117− wrapMode: Text.Wrap;
118− maximumLineCount: 2;
119− font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
120− color: "white";
121− visible: showHeader && overlayLoader.active;
113+ top: overlayLoader.top;
122− text: root.title;
123− font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
124− horizontalAlignment: root.headerAlignment;
125− }
126−Label {
127− id: subtitleLabel;
128− objectName: "subtitleLabel";
129− anchors { left: titleLabel.left;
130− leftMargin: titleLabel.leftMargin;
131− right: titleLabel.right;
132− top: titleLabel.bottom;
133− topMargin: units.dp(2);
114+ topMargin: units.gu(1);
134− }
115+ }
135 elide: Text.ElideRight;
116 elide: Text.ElideRight;
136 fontSize: "small";
117 fontSize: "small";
118+ wrapMode: Text.Wrap;
119+ maximumLineCount: 2;
137 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
120 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
138 color: "white";
121 color: "white";
139− visible: titleLabel.visible && titleLabel.text;
122+ visible: showHeader && overlayLoader.active;
140− text: cardData && cardData["subtitle"] || "";
123+ text: root.title;
141− font.weight: Font.Light;
124+ font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
142 horizontalAlignment: root.headerAlignment;
125 horizontalAlignment: root.headerAlignment;
143 }
126 }
127+Label {
128+ id: subtitleLabel;
129+ objectName: "subtitleLabel";
130+ anchors { left: titleLabel.left;
131+ leftMargin: titleLabel.leftMargin;
132+ right: titleLabel.right;
133+ rightMargin: titleLabel.rightMargin;
134+ top: titleLabel.bottom;
135+ topMargin: units.dp(2);
136+ }
137+ elide: Text.ElideRight;
138+ fontSize: "small";
139+ font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
140+ color: "white";
141+ visible: titleLabel.visible && titleLabel.text;
142+ text: cardData && cardData["subtitle"] || "";
143+ font.weight: Font.Light;
144+ horizontalAlignment: root.headerAlignment;
145+ }
144implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
146implicitHeight: subtitleLabel.y + subtitleLabel.height + units.gu(1);
145}
147}
tests/plugins/Dash/cardcreator/7.res+1
@@ -115,6 +115,7 @@ CardAttributes {
115 id: attributesRow;
115 id: attributesRow;
116 objectName: "attributesRow";
116 objectName: "attributesRow";
117 anchors { left: parent.left; right: parent.right }
117 anchors { left: parent.left; right: parent.right }
118+ color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
118 model: cardData["attributes"]
119 model: cardData["attributes"]
119 }
120 }
120
121
tests/plugins/Dash/cardcreatortest.cpp+9−1
@@ -19,6 +19,7 @@
19#include <QQuickItem>
19#include <QQuickItem>
20#include <QQuickView>
20#include <QQuickView>
21#include <QtTestGui>
21#include <QtTestGui>
22+#include <QTemporaryFile>
22
23
23class CardCreatorTest : public QObject
24class CardCreatorTest : public QObject
24{
25{
@@ -74,7 +75,14 @@ private Q_SLOTS:
74 QVERIFY(testResultFile.open(QIODevice::ReadOnly));
75 QVERIFY(testResultFile.open(QIODevice::ReadOnly));
75 QTextStream ts2(&testResultFile);
76 QTextStream ts2(&testResultFile);
76 const QString expectedResult = ts2.readAll();
77 const QString expectedResult = ts2.readAll();
78+ const QString executedResult = cardStringResult.toString();
79+ // Record failed results to /tmp
80+ QTemporaryFile tmpFile(QDir::tempPath() + QDir::separator() + "testCardCreatorFailedResultXXXXXX");
81+ tmpFile.open();
82+ tmpFile.setAutoRemove(false);
83+ tmpFile.write(executedResult.toUtf8().constData());
77− QCOMPARE(cardStringResult.toString().simplified(), expectedResult.simplified());
84+ QCOMPARE(executedResult.simplified(), expectedResult.simplified());
85+ tmpFile.setAutoRemove(true); // Remove the result if it passed
78
86
79 QVariant createCardComponentResult;
87 QVariant createCardComponentResult;
80 QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON));
88 QMetaObject::invokeMethod(view->rootObject(), "createCardComponent", Q_RETURN_ARG(QVariant, createCardComponentResult), Q_ARG(QVariant, templateJSON), Q_ARG(QVariant, componentsJSON));