on xenial help sign in
Fix for black preview zoomable images, use fullscreen preview
commite0142d13cf6ea9dd896c5f25447bca11c1208f13 authorAndrea Cimitan <andrea.cimitan@gmail.com> dateTue 21 Oct 2014, 22:16 (12 years ago) parent1ff2631
4 files changed+166−48
qml/Components/ZoomableImage.qml+17−14 qml/Dash/Previews/PreviewZoomableImage.qml+103−5 tests/qmltests/Components/tst_ZoomableImage.qml+21−21 tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml+25−8
qml/Components/ZoomableImage.qml+17−14
@@ -26,16 +26,15 @@ import "Flickables" as Flickables
2626
2727Item {
2828 id: root
29− property alias source: lazyImage.source
29+ property alias source: imageRenderer.source
3030 property var zoomable: false
31− property alias imageState: lazyImage.state
32− property alias scaleTo: lazyImage.scaleTo
33− property alias asynchronous: lazyImage.asynchronous
31+ property alias imageStatus: imageRenderer.status
32+ property alias asynchronous: imageRenderer.asynchronous
3433
3534 Flickables.Flickable {
3635 id: flickable
3736 objectName: "flickable"
38− clip: true
37+ clip: true // FIXME maybe we can remove this, or just not clip in few cases
3938 contentHeight: imageContainer.height
4039 contentWidth: imageContainer.width
4140
@@ -52,30 +51,34 @@ Item {
5251 Item {
5352 id: image
5453 objectName: "image"
55− property alias imageState: lazyImage.state
54+ property alias imageStatus: imageRenderer.status
5655 property var prevScale
5756 anchors.centerIn: parent
5857
5958 signal imageReloaded
6059
61− LazyImage {
62− id: lazyImage
63− objectName: "lazyImage"
60+ Image {
61+ id: imageRenderer
62+ objectName: "imageRenderer"
6463 smooth: !flickable.movingVertically
6564 anchors.fill: parent
6665 fillMode: Image.PreserveAspectFit
67− scaleTo: "fit"
6866
69− onStateChanged: {
70− if (state == "ready") {
67+ readonly property int sourceSizeMultiplier: 3
68+
69+ sourceSize.width: root.width * sourceSizeMultiplier <= root.height * sourceSizeMultiplier ? root.width * sourceSizeMultiplier : 0
70+ sourceSize.height: root.height * sourceSizeMultiplier <= root.width * sourceSizeMultiplier ? root.height * sourceSizeMultiplier : 0
71+
72+ onStatusChanged: {
73+ if (status === Image.Ready) {
7174 image.imageReloaded();
7275 }
7376 }
7477 }
7578
7679 onImageReloaded: {
77− image.height = lazyImage.sourceImage.implicitHeight
78− image.width = lazyImage.sourceImage.implicitWidth
80+ image.height = imageRenderer.implicitHeight
81+ image.width = imageRenderer.implicitWidth
7982 image.resetScale();
8083 }
8184
qml/Dash/Previews/PreviewZoomableImage.qml+103−5
@@ -28,11 +28,109 @@ PreviewWidget {
2828 id: root
2929 implicitHeight: units.gu(22)
3030
31− ZoomableImage {
32− id: image
33− objectName: "image"
31+ property Item rootItem: QuickUtils.rootItem(root)
32+
33+ LazyImage {
34+ id: lazyImage
35+ objectName: "lazyImage"
36+ anchors {
37+ top: parent.top
38+ bottom: parent.bottom
39+ }
40+ scaleTo: "height"
3441 source: widgetData["source"]
35− zoomable: widgetData["zoomable"] ? widgetData["zoomable"] : false
36− anchors.fill: parent
42+
43+ borderSource: mouseArea.pressed ? "radius_pressed.sci" : "radius_idle.sci"
44+
45+ MouseArea {
46+ id: mouseArea
47+ anchors.fill: parent
48+ onClicked: {
49+ zoomableImageContainer.initialX = rootItem.mapFromItem(parent, 0, 0).x
50+ zoomableImageContainer.initialY = rootItem.mapFromItem(parent, 0, 0).y
51+ zoomableImageContainer.visible = true;
52+ }
53+ }
54+ }
55+
56+ Rectangle {
57+ id: zoomableImageContainer
58+ objectName: "zoomableImageContainer"
59+
60+ readonly property real initialScale: lazyImage.height / rootItem.height
61+ readonly property real scaleProgress: (scale - initialScale) / (1.0 - initialScale)
62+ property real initialX: 0
63+ property real initialY: 0
64+
65+ parent: rootItem
66+ width: parent.width
67+ height: parent.height
68+ visible: false
69+ clip: visible && scale < 1.0
70+ scale: visible ? 1.0 : initialScale
71+ transformOrigin: Item.TopLeft
72+ transform: Translate {
73+ x: zoomableImageContainer.initialX - zoomableImageContainer.initialX * zoomableImageContainer.scaleProgress
74+ y: zoomableImageContainer.initialY - zoomableImageContainer.initialY * zoomableImageContainer.scaleProgress
75+ }
76+ color: "black"
77+ radius: units.gu(1) - units.gu(1) * zoomableImageContainer.scaleProgress
78+
79+ Behavior on scale {
80+ enabled: !zoomableImageContainer.visible
81+ UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
82+ }
83+
84+ ZoomableImage {
85+ id: screenshot
86+ anchors.fill: parent
87+ source: widgetData["source"]
88+ zoomable: widgetData["zoomable"] ? widgetData["zoomable"] : false
89+ }
90+
91+ Rectangle {
92+ id: zoomableImageHeader
93+
94+ anchors {
95+ left: parent.left
96+ right: parent.right
97+ }
98+ height: units.gu(7)
99+ visible: opacity > 0
100+ opacity: zoomableImageContainer.scaleProgress > 0.6 ? 0.8 : 0
101+ color: "black"
102+
103+ Behavior on opacity {
104+ UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
105+ }
106+
107+ AbstractButton {
108+ id: zoomableImageCloseButton
109+ objectName: "zoomableImageCloseButton"
110+ anchors {
111+ top: parent.top
112+ bottom: parent.bottom
113+ }
114+ width: units.gu(8)
115+ height: width
116+
117+ onClicked: zoomableImageContainer.visible = false
118+
119+ Rectangle {
120+ anchors.fill: parent
121+ color: Qt.rgba(1.0, 1.0, 1.0, 0.3)
122+ visible: zoomableImageCloseButton.pressed
123+ }
124+
125+ Icon {
126+ id: icon
127+ anchors.centerIn: parent
128+ width: units.gu(2.5)
129+ height: width
130+ color: Theme.palette.normal.foregroundText
131+ name: "close"
132+ }
133+ }
134+ }
37135 }
38136}
tests/qmltests/Components/tst_ZoomableImage.qml+21−21
@@ -56,23 +56,23 @@ Rectangle {
5656 when: windowShown
5757
5858 function test_loadImage() {
59− var lazyImage = findChild(zoomableImage, "lazyImage");
59+ var imageRenderer = findChild(zoomableImage, "imageRenderer");
6060
6161 zoomableImage.source = widgetData0["source"];
6262 zoomableImage.zoomable = widgetData0["zoomable"];
6363 waitForRendering(zoomableImage);
64− tryCompare(zoomableImage, "imageState", "default");
64+ tryCompare(zoomableImage, "imageStatus", Image.Null);
6565
66− signalSpy.signalName = "onStateChanged";
67− signalSpy.target = lazyImage;
66+ signalSpy.signalName = "onStatusChanged";
67+ signalSpy.target = imageRenderer;
6868 signalSpy.clear();
6969
7070 zoomableImage.source = widgetData1["source"];
7171 zoomableImage.zoomable = widgetData1["zoomable"];
72− waitForRendering(lazyImage);
73− tryCompareFunction(function() { return get_filename(lazyImage.source.toString()) === get_filename(widgetData1["source"]); }, true);
72+ waitForRendering(imageRenderer);
73+ tryCompareFunction(function() { return get_filename(imageRenderer.source.toString()) === get_filename(widgetData1["source"]); }, true);
7474 waitForRendering(zoomableImage);
75− tryCompare(zoomableImage, "imageState", "ready");
75+ tryCompare(zoomableImage, "imageStatus", Image.Ready);
7676 compare (signalSpy.count, 1);
7777 }
7878
@@ -84,15 +84,15 @@ Rectangle {
8484
8585 function test_mousewheel() {
8686 var image = findChild(zoomableImage, "image");
87− var lazyImage = findChild(zoomableImage, "lazyImage");
87+ var imageRenderer = findChild(zoomableImage, "imageRenderer");
8888 var flickable = findChild(zoomableImage, "flickable");
8989
9090 zoomableImage.source = widgetData2["source"];
9191 zoomableImage.zoomable = true;
9292 waitForRendering(zoomableImage);
9393
94− tryCompare(zoomableImage, "imageState", "ready");
95− tryCompareFunction(function() { return get_filename(lazyImage.source.toString()) === get_filename(widgetData2["source"]); }, true);
94+ tryCompare(zoomableImage, "imageStatus", Image.Ready);
95+ tryCompareFunction(function() { return get_filename(imageRenderer.source.toString()) === get_filename(widgetData2["source"]); }, true);
9696 waitForRendering(image);
9797
9898 // move mouse to center
@@ -105,16 +105,16 @@ Rectangle {
105105 for (var i=0; i<10; i++) {
106106 mouseWheel(zoomableImage, zoomableImage.width / 2, zoomableImage.height / 2, 0, 10);
107107 tryCompare(image, "scale", oldScale + (i + 1) * 0.1);
108− compare(flickable.contentWidth, Math.max(lazyImage.width * image.scale, flickable.width));
109− compare(flickable.contentHeight, Math.max(lazyImage.height * image.scale, flickable.height));
108+ compare(flickable.contentWidth, Math.max(imageRenderer.width * image.scale, flickable.width));
109+ compare(flickable.contentHeight, Math.max(imageRenderer.height * image.scale, flickable.height));
110110 }
111111
112112 // zoom out
113113 for (var i=0; i<10; i++) {
114114 mouseWheel(zoomableImage, zoomableImage.width / 2, zoomableImage.height / 2, 0, -10);
115115 tryCompare(image, "scale", oldScale + 1.0 - (i + 1) * 0.1);
116− compare(flickable.contentWidth, Math.max(lazyImage.width * image.scale, flickable.width));
117− compare(flickable.contentHeight, Math.max(lazyImage.height * image.scale, flickable.height));
116+ compare(flickable.contentWidth, Math.max(imageRenderer.width * image.scale, flickable.width));
117+ compare(flickable.contentHeight, Math.max(imageRenderer.height * image.scale, flickable.height));
118118 }
119119 }
120120 }
@@ -135,7 +135,7 @@ Rectangle {
135135
136136 function test_pinch(data) {
137137 var image = findChild(zoomableImage, "image");
138− var lazyImage = findChild(zoomableImage, "lazyImage");
138+ var imageRenderer = findChild(zoomableImage, "imageRenderer");
139139 var flickable = findChild(zoomableImage, "flickable");
140140
141141 signalSpy.signalName = "onScaleChanged";
@@ -146,8 +146,8 @@ Rectangle {
146146 zoomableImage.zoomable = data.zoomable;
147147 waitForRendering(zoomableImage);
148148
149− tryCompare(zoomableImage, "imageState", "ready");
150− tryCompareFunction(function() { return get_filename(lazyImage.source.toString()) === get_filename(data.source); }, true);
149+ tryCompare(zoomableImage, "imageStatus", Image.Ready);
150+ tryCompareFunction(function() { return get_filename(imageRenderer.source.toString()) === get_filename(data.source); }, true);
151151 waitForRendering(image);
152152
153153 var x1Start = zoomableImage.width * 2 / 6;
@@ -179,15 +179,15 @@ Rectangle {
179179 compare(newScale > oldScale, data.answer2, "scale factor didn't changed");
180180 compare(signalSpy.count == 0, data.answer3, "scale signal count error");
181181 compare(image.scale, newScale, "scale factor error");
182− compare(flickable.contentWidth, Math.max(lazyImage.width * image.scale, flickable.width));
183− compare(flickable.contentHeight, Math.max(lazyImage.height * image.scale, flickable.height));
182+ compare(flickable.contentWidth, Math.max(imageRenderer.width * image.scale, flickable.width));
183+ compare(flickable.contentHeight, Math.max(imageRenderer.height * image.scale, flickable.height));
184184
185185 wait(3000); // have to delay between two consequent pinch event.
186186 // pinch zoom-out
187187 touchPinch(zoomableImage, x1End, y1End, x1Start, y1Start, x2End, y2End, x2Start, y2Start);
188188 tryCompare(image, "scale", oldScale);
189− compare(flickable.contentWidth, Math.max(lazyImage.width * image.scale, flickable.width));
190− compare(flickable.contentHeight, Math.max(lazyImage.height * image.scale, flickable.height));
189+ compare(flickable.contentWidth, Math.max(imageRenderer.width * image.scale, flickable.width));
190+ compare(flickable.contentHeight, Math.max(imageRenderer.height * image.scale, flickable.height));
191191 }
192192 }
193193 }
tests/qmltests/Dash/Previews/tst_PreviewZoomableImage.qml+25−8
@@ -36,26 +36,43 @@ Rectangle {
3636
3737 PreviewZoomableImage {
3838 id: zoomableImage
39− anchors.fill: parent
40− widgetData: widgetData1
39+ anchors.centerIn: parent
40+ widgetData: widgetData0
4141 }
4242
4343 UT.UnityTestCase {
4444 name: "PreviewZoomableImageTest"
4545 when: windowShown
4646
47− function test_loadImage() {
48− var image = findChild(zoomableImage, "image");
47+ property Item lazyImage: findChild(zoomableImage, "lazyImage");
48+ property Item zoomableImageContainer: findChild(zoomableImage.rootItem, "zoomableImageContainer");
49+
50+ function cleanup() {
51+ zoomableImageContainer.visible = false;
52+ zoomableImage.widgetData = widgetData0;
53+ waitForRendering(zoomableImage);
54+ }
4955
56+ function test_loadImage() {
5057 zoomableImage.widgetData = widgetData0;
5158 waitForRendering(zoomableImage);
52− waitForRendering(image);
53− tryCompare(image, "imageState", "ready");
59+ waitForRendering(lazyImage);
60+ tryCompare(lazyImage, "state", "ready");
5461
5562 zoomableImage.widgetData = widgetData1;
5663 waitForRendering(zoomableImage);
57− waitForRendering(image);
58− tryCompare(image, "imageState", "default");
64+ waitForRendering(lazyImage);
65+ tryCompare(lazyImage, "state", "default");
66+ }
67+
68+ function test_1zoomableImageOpenClose() {
69+ var zoomableImageCloseButton = findChild(zoomableImageContainer, "zoomableImageCloseButton");
70+ mouseClick(lazyImage, lazyImage.width / 2, lazyImage.height / 2);
71+ tryCompare(zoomableImageContainer, "visible", true);
72+ tryCompare(zoomableImageContainer, "scale", 1.0);
73+ tryCompare(zoomableImageCloseButton, "visible", true);
74+ mouseClick(zoomableImageCloseButton, zoomableImageCloseButton.width / 2, zoomableImageCloseButton.height / 2);
75+ tryCompare(zoomableImageContainer, "visible", false);
5976 }
6077 }
6178}