on xenial help sign in
Make fallback also be fallback when the image is empty and not only on error

Fixes: #1531913 Approved by: Andrea Cimitan

commit76c1fc38770b1dcfbab488154598b8a2048b30b0 authorAlbert Astals Cid <albert.astals@canonical.com> dateFri 12 Feb 2016, 00:11 (11 years ago) parent1b8086e6ab3749
12 files changed+102−23
plugins/Dash/CardCreator.js+20−9 qml/Dash/Previews/PreviewHeader.qml+1−1 qml/Dash/Previews/PreviewImageGallery.qml+2−2 qml/Dash/Previews/PreviewZoomableImage.qml+2−2 tests/plugins/Dash/cardcreator/1.res+3−2 tests/plugins/Dash/cardcreator/11.res+4−3 tests/plugins/Dash/cardcreator/3.res+3−2 tests/plugins/Dash/cardcreator/5.res+3−2 tests/qmltests/Dash/Previews/tst_PreviewHeader.qml+15 tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml+19 tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml+12 tests/qmltests/Dash/tst_Card.qml+18
plugins/Dash/CardCreator.js+20−9
@@ -62,6 +62,7 @@ var kBackgroundLoaderCode = 'Loader {\n\
6262// %2 is used as image width
6363// %3 is used as image height
6464// %4 is injected as code to artImage
65+// %5 is used as image fallback
6566var kArtShapeHolderCode = 'Item { \n\
6667 id: artShapeHolder; \n\
6768 height: root.fixedArtShapeSize.height > 0 ? root.fixedArtShapeSize.height : artShapeLoader.height; \n\
@@ -70,7 +71,8 @@ var kArtShapeHolderCode = 'Item { \n\
7071 Loader { \n\
7172 id: artShapeLoader; \n\
7273 objectName: "artShapeLoader"; \n\
73− active: cardData && cardData["art"] || false; \n\
74+ readonly property string cardArt: cardData && cardData["art"] || %5; \n\
75+ active: cardArt != ""; \n\
7476 asynchronous: root.asynchronous; \n\
7577 visible: status == Loader.Ready; \n\
7678 sourceComponent: Item { \n\
@@ -128,7 +130,7 @@ var kArtShapeHolderCode = 'Item { \n\
128130 CroppedImageMinimumSourceSize { \n\
129131 id: artImage; \n\
130132 objectName: "artImage"; \n\
131− source: cardData && cardData["art"] || ""; \n\
133+ source: artShapeLoader.cardArt; \n\
132134 asynchronous: root.asynchronous; \n\
133135 width: %2; \n\
134136 height: %3; \n\
@@ -245,11 +247,12 @@ var kMascotShapeLoaderCode = 'Loader { \n\
245247// %1 is used as anchors of mascotImage
246248// %2 is used as visible of mascotImage
247249// %3 is injected as code to mascotImage
250+// %4 is used as fallback image
248251var kMascotImageCode = 'CroppedImageMinimumSourceSize { \n\
249252 id: mascotImage; \n\
250253 objectName: "mascotImage"; \n\
251254 anchors { %1 } \n\
252− source: cardData && cardData["mascot"] || ""; \n\
255+ source: cardData && cardData["mascot"] || %4; \n\
253256 width: units.gu(6); \n\
254257 height: units.gu(5.625); \n\
255258 horizontalAlignment: Image.AlignHCenter; \n\
@@ -482,11 +485,15 @@ function cardString(template, components) {
482485
483486 var fallback = components["art"] && components["art"]["fallback"] || "";
484487 fallback = encodeURI(fallback);
485− var fallbackCode = "";
488+ var fallbackStatusCode = "";
489+ var fallbackURICode = '""';
486490 if (fallback !== "") {
487− fallbackCode += 'onStatusChanged: if (status === Image.Error) source = decodeURI("%1");'.arg(fallback);
491+ // fallbackStatusCode has %5 in it because we want to substitute it for fallbackURICode
492+ // which in kArtShapeHolderCode is %5
493+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %5;';
494+ fallbackURICode = 'decodeURI("%1")'.arg(fallback);
488495 }
489− code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode).arg(fallbackCode);
496+ code += kArtShapeHolderCode.arg(artAnchors).arg(widthCode).arg(heightCode).arg(fallbackStatusCode).arg(fallbackURICode);
490497 } else {
491498 code += 'readonly property size artShapeSize: Qt.size(-1, -1);\n'
492499 }
@@ -580,11 +587,15 @@ function cardString(template, components) {
580587 var mascotImageVisible = useMascotShape ? 'false' : 'showHeader';
581588 var fallback = components["mascot"] && components["mascot"]["fallback"] || "";
582589 fallback = encodeURI(fallback);
583− var fallbackCode = "";
590+ var fallbackStatusCode = "";
591+ var fallbackURICode = '""';
584592 if (fallback !== "") {
585− fallbackCode += 'onStatusChanged: if (status === Image.Error) source = decodeURI("%1");'.arg(fallback);
593+ // fallbackStatusCode has %4 in it because we want to substitute it for fallbackURICode
594+ // which in kMascotImageCode is %4
595+ fallbackStatusCode += 'onStatusChanged: if (status === Image.Error) source = %4;';
596+ fallbackURICode = 'decodeURI("%1")'.arg(fallback);
586597 }
587− mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible).arg(fallbackCode);
598+ mascotCode = kMascotImageCode.arg(mascotAnchors).arg(mascotImageVisible).arg(fallbackStatusCode).arg(fallbackURICode);
588599 }
589600
590601 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && root.scopeStyle ? root.scopeStyle.getTextColor(backgroundLoader.item.luminance) : (backgroundLoader.item && backgroundLoader.item.luminance > 0.7 ? theme.palette.normal.baseText : "white")';
qml/Dash/Previews/PreviewHeader.qml+1−1
@@ -35,7 +35,7 @@ PreviewWidget {
3535 Item {
3636 id: headerRoot
3737 objectName: "innerPreviewHeader"
38− readonly property url mascot: root.widgetData["mascot"] || ""
38+ readonly property url mascot: root.widgetData["mascot"] || fallback
3939 readonly property url fallback: root.widgetData["fallback"] || ""
4040 readonly property string title: root.widgetData["title"] || ""
4141 readonly property string subtitle: root.widgetData["subtitle"] || ""
qml/Dash/Previews/PreviewImageGallery.qml+2−2
@@ -59,7 +59,7 @@ PreviewWidget {
5959 top: parent.top
6060 bottom: parent.bottom
6161 }
62− source: modelData ? modelData : ""
62+ source: modelData || root.widgetData["fallback"] || ""
6363 scaleTo: "height"
6464 initialWidth: units.gu(13)
6565 pressed: mouseArea.pressed
@@ -128,7 +128,7 @@ PreviewWidget {
128128 bottom: parent.bottom
129129 }
130130 width: overlay.width
131− source: modelData ? modelData : ""
131+ source: modelData || root.widgetData["fallback"] || ""
132132 fillMode: Image.PreserveAspectFit
133133 sourceSize { width: screenshot.width; height: screenshot.height }
134134
qml/Dash/Previews/PreviewZoomableImage.qml+2−2
@@ -42,7 +42,7 @@ PreviewWidget {
4242 right: parent.right
4343 }
4444 scaleTo: "width"
45− source: widgetData["source"]
45+ source: widgetData["source"] || widgetData["fallback"] || ""
4646 asynchronous: true
4747 useUbuntuShape: false
4848 pressed: mouseArea.pressed
@@ -86,7 +86,7 @@ PreviewWidget {
8686
8787 delegate: ZoomableImage {
8888 anchors.fill: parent
89− source: widgetData["source"]
89+ source: widgetData["source"] || widgetData["fallback"] || ""
9090 zoomable: widgetData["zoomable"] ? widgetData["zoomable"] : false
9191 // If modelData would change after failing to load it would not be
9292 // reloaded since the source binding is destroyed by the source = fallback
tests/plugins/Dash/cardcreator/1.res+3−2
@@ -24,7 +24,8 @@ Item {
2424 Loader {
2525 id: artShapeLoader;
2626 objectName: "artShapeLoader";
27− active: cardData && cardData["art"] || false;
27+ readonly property string cardArt: cardData && cardData["art"] || "";
28+ active: cardArt != "";
2829 asynchronous: root.asynchronous;
2930 visible: status == Loader.Ready;
3031 sourceComponent: Item {
@@ -82,7 +83,7 @@ Item {
8283 CroppedImageMinimumSourceSize {
8384 id: artImage;
8485 objectName: "artImage";
85− source: cardData && cardData["art"] || "";
86+ source: artShapeLoader.cardArt;
8687 asynchronous: root.asynchronous;
8788 width: root.width;
8889 height: width / artShape.aspect;
tests/plugins/Dash/cardcreator/11.res+4−3
@@ -62,7 +62,8 @@ Item {
6262 Loader {
6363 id: artShapeLoader;
6464 objectName: "artShapeLoader";
65− active: cardData && cardData["art"] || false;
65+ readonly property string cardArt: cardData && cardData["art"] || decodeURI("%5C");
66+ active: cardArt != "";
6667 asynchronous: root.asynchronous;
6768 visible: status == Loader.Ready;
6869 sourceComponent: Item {
@@ -120,7 +121,7 @@ Item {
120121 CroppedImageMinimumSourceSize {
121122 id: artImage;
122123 objectName: "artImage";
123− source: cardData && cardData["art"] || "";
124+ source: artShapeLoader.cardArt;
124125 asynchronous: root.asynchronous;
125126 width: root.width;
126127 height: width / artShape.aspect;
@@ -148,7 +149,7 @@ left: parent.left;
148149 id: mascotImage;
149150 objectName: "mascotImage";
150151 anchors { verticalCenter: parent.verticalCenter; }
151− source: cardData && cardData["mascot"] || "";
152+ source: cardData && cardData["mascot"] || decodeURI("%22");
152153 width: units.gu(6);
153154 height: units.gu(5.625);
154155 horizontalAlignment: Image.AlignHCenter;
tests/plugins/Dash/cardcreator/3.res+3−2
@@ -24,7 +24,8 @@ Item {
2424 Loader {
2525 id: artShapeLoader;
2626 objectName: "artShapeLoader";
27− active: cardData && cardData["art"] || false;
27+ readonly property string cardArt: cardData && cardData["art"] || decodeURI("IHAVE%5C%22ESCAPED%5C%22QUOTES%5C%22");
28+ active: cardArt != "";
2829 asynchronous: root.asynchronous;
2930 visible: status == Loader.Ready;
3031 sourceComponent: Item {
@@ -82,7 +83,7 @@ Item {
8283 CroppedImageMinimumSourceSize {
8384 id: artImage;
8485 objectName: "artImage";
85− source: cardData && cardData["art"] || "";
86+ source: artShapeLoader.cardArt;
8687 asynchronous: root.asynchronous;
8788 width: root.width;
8889 height: width / artShape.aspect;
tests/plugins/Dash/cardcreator/5.res+3−2
@@ -24,7 +24,8 @@ Item {
2424 Loader {
2525 id: artShapeLoader;
2626 objectName: "artShapeLoader";
27− active: cardData && cardData["art"] || false;
27+ readonly property string cardArt: cardData && cardData["art"] || "";
28+ active: cardArt != "";
2829 asynchronous: root.asynchronous;
2930 visible: status == Loader.Ready;
3031 sourceComponent: Item {
@@ -82,7 +83,7 @@ Item {
8283 CroppedImageMinimumSourceSize {
8384 id: artImage;
8485 objectName: "artImage";
85− source: cardData && cardData["art"] || "";
86+ source: artShapeLoader.cardArt;
8687 asynchronous: root.asynchronous;
8788 width: root.width;
8889 height: width / artShape.aspect;
tests/qmltests/Dash/Previews/tst_PreviewHeader.qml+15
@@ -54,6 +54,14 @@ Rectangle {
5454 "attributes": [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}]
5555 }
5656
57+ property var emptyfallbackheaderjson: {
58+ "title": "THE TITLE",
59+ "subtitle": "Something catchy",
60+ "mascot": "",
61+ "fallback": "../graphics/play_button.png",
62+ "attributes": [{"value":"text1","icon":"image://theme/ok"},{"value":"text2","icon":"image://theme/cancel"}]
63+ }
64+
5765 PreviewHeader {
5866 id: previewHeader
5967 widgetData: headerjson
@@ -150,6 +158,13 @@ Rectangle {
150158 var mascot = findChild(previewHeader, "mascotShape");
151159 tryCompare(mascot, "visible", true);
152160 tryCompare(mascot.source, "status", Image.Ready);
161+
162+ previewHeader.widgetData = {};
163+ previewHeader.widgetData = emptyfallbackheaderjson;
164+ tryCompareFunction(function() { return findChild(previewHeader, "mascotShape") != null }, true);
165+ var mascot = findChild(previewHeader, "mascotShape");
166+ tryCompare(mascot, "visible", true);
167+ tryCompare(mascot.source, "status", Image.Ready);
153168 }
154169 }
155170}
tests/qmltests/Dash/Previews/tst_PreviewImageGallery.qml+19
@@ -48,6 +48,16 @@ Rectangle {
4848 , "fallback": "../../../tests/graphics/clock@18.png"
4949 }
5050
51+ property var sourcesModelEmptyWithFallback: {
52+ "sources": [
53+ "../../graphics/phone_background.jpg",
54+ "../../graphics/tablet_background.jpg",
55+ "../../../tests/graphics/clock@18.png",
56+ ""
57+ ]
58+ , "fallback": "../../../tests/graphics/clock@18.png"
59+ }
60+
5161 PreviewImageGallery {
5262 id: imageGallery
5363 width: parent.width
@@ -123,5 +133,14 @@ Rectangle {
123133 image3 = findChild(imageGallery, "previewImage3");
124134 tryCompare(image3, "state", "ready");
125135 }
136+
137+ function test_empty_fallback() {
138+ var image3 = findChild(imageGallery, "previewImage3");
139+ tryCompare(image3, "state", "error");
140+ imageGallery.widgetData = sourcesModel0;
141+ imageGallery.widgetData = sourcesModelEmptyWithFallback;
142+ image3 = findChild(imageGallery, "previewImage3");
143+ tryCompare(image3, "state", "ready");
144+ }
126145 }
127146}
tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml+12
@@ -39,6 +39,11 @@ Rectangle {
3939 "fallback": "../../graphics/phone_background.jpg"
4040 }
4141
42+ property var widgetData3: {
43+ "source": "",
44+ "fallback": "../../graphics/phone_background.jpg"
45+ }
46+
4247 Loader {
4348 id: loader
4449 width: parent.width
@@ -100,5 +105,12 @@ Rectangle {
100105 waitForRendering(lazyImage);
101106 tryCompare(lazyImage, "state", "ready");
102107 }
108+
109+ function test_emptyfallback() {
110+ zoomableImage.widgetData = widgetData3;
111+ waitForRendering(zoomableImage);
112+ waitForRendering(lazyImage);
113+ tryCompare(lazyImage, "state", "ready");
114+ }
103115 }
104116}
tests/qmltests/Dash/tst_Card.qml+18
@@ -476,6 +476,15 @@ Rectangle {
476476 card.cardDataChanged();
477477 waitForRendering(card);
478478 tryCompare(art, "visible", true);
479+ compare(artImage.source, Qt.resolvedUrl("artwork/emblem.png"));
480+
481+ cardTool.components["art"]["fallback"] = Qt.resolvedUrl("artwork/checkers.png");
482+ cardTool.componentsChanged();
483+ card.cardData["art"] = "";
484+ card.cardDataChanged();
485+ waitForRendering(card);
486+ tryCompare(art, "visible", true);
487+ compare(artImage.source, Qt.resolvedUrl("artwork/checkers.png"));
479488
480489 card.cardData["mascot"] = "somethingbroken2";
481490 card.cardDataChanged();
@@ -487,6 +496,15 @@ Rectangle {
487496 card.cardDataChanged();
488497 waitForRendering(card);
489498 tryCompare(mascotImage, "status", Image.Ready);
499+ compare(mascotImage.source, Qt.resolvedUrl("artwork/emblem.png"));
500+
501+ cardTool.components["mascot"] = {"fallback": Qt.resolvedUrl("artwork/checkers.png")};
502+ cardTool.componentsChanged();
503+ card.cardData["mascot"] = "";
504+ card.cardDataChanged();
505+ waitForRendering(card);
506+ tryCompare(mascotImage, "status", Image.Ready);
507+ compare(mascotImage.source, Qt.resolvedUrl("artwork/checkers.png"));
490508 }
491509
492510 function test_font_weights_data() {