~elopio/gallery-app/revert_workaround-1302706-click_toolbar_button_failure

« back to all changes in this revision

Viewing changes to rc/qml/MediaViewer/SingleMediaViewer.qml

  • Committer: Leo Arias
  • Date: 2015-05-15 08:05:23 UTC
  • mfrom: (954.1.241 gallery-app)
  • Revision ID: leo.arias@canonical.com-20150515080523-i2of3vr8h7dioj59
Now the toolbar object is not needed at all.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2014 Canonical Ltd.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; version 3.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 */
 
16
 
 
17
import QtQuick 2.2
 
18
import QtMultimedia 5.0
 
19
import Ubuntu.Components 1.0
 
20
import Ubuntu.Components.ListItems 1.0 as ListItems
 
21
import Ubuntu.Components.Popups 1.0
 
22
import Ubuntu.Content 0.1
 
23
import Ubuntu.Thumbnailer 0.1
 
24
import Gallery 1.0
 
25
import "../Components"
 
26
 
 
27
Item {
 
28
    id: viewer
 
29
    property bool pinchInProgress: zoomPinchArea.active
 
30
    property var mediaSource
 
31
    property real maxDimension: 0.
 
32
    property bool showThumbnail: true
 
33
 
 
34
    property bool isVideo: mediaSource.type === MediaSource.Video
 
35
    property bool userInteracting: pinchInProgress || flickable.sizeScale != 1.0
 
36
    property bool fullyZoomed: flickable.sizeScale == zoomPinchArea.maximumZoom
 
37
    property bool fullyUnzoomed: flickable.sizeScale == zoomPinchArea.minimumZoom
 
38
    property bool animateMediaOnHeight: false
 
39
    property bool imageReady: image.status == Image.Ready
 
40
 
 
41
    property alias paintedHeight: image.paintedHeight
 
42
    property alias paintedWidth: image.paintedWidth
 
43
 
 
44
    signal clicked()
 
45
 
 
46
    onHeightChanged: {
 
47
        if (height > viewer.maxDimension)
 
48
            viewer.maxDimension = height;
 
49
    }
 
50
 
 
51
    onWidthChanged: {
 
52
        if (width > viewer.maxDimension)
 
53
            viewer.maxDimension = width;
 
54
    }
 
55
 
 
56
    function zoomIn(centerX, centerY, factor) {
 
57
        flickable.scaleCenterX = centerX / (flickable.sizeScale * flickable.width);
 
58
        flickable.scaleCenterY = centerY / (flickable.sizeScale * flickable.height);
 
59
        flickable.sizeScale = factor;
 
60
    }
 
61
 
 
62
    function zoomOut() {
 
63
        if (flickable.sizeScale != 1.0) {
 
64
            flickable.scaleCenterX = flickable.contentX / flickable.width / (flickable.sizeScale - 1);
 
65
            flickable.scaleCenterY = flickable.contentY / flickable.height / (flickable.sizeScale - 1);
 
66
            flickable.sizeScale = 1.0;
 
67
        }
 
68
    }
 
69
 
 
70
    function reset() {
 
71
        if (!viewer.isVideo)
 
72
            zoomOut()
 
73
    }
 
74
 
 
75
    ActivityIndicator {
 
76
        anchors.centerIn: parent
 
77
        visible: running
 
78
        running: image.status != Image.Ready
 
79
    }
 
80
 
 
81
    PinchArea {
 
82
        id: zoomPinchArea
 
83
        anchors.fill: parent
 
84
 
 
85
        property real initialZoom
 
86
        property real maximumScale: 3.0
 
87
        property real minimumZoom: 1.0
 
88
        property real maximumZoom: 3.0
 
89
        property bool active: false
 
90
        property var center
 
91
 
 
92
        onPinchStarted: {
 
93
            active = true;
 
94
            initialZoom = flickable.sizeScale;
 
95
            center = zoomPinchArea.mapToItem(media, pinch.startCenter.x, pinch.startCenter.y);
 
96
            zoomIn(center.x, center.y, initialZoom);
 
97
        }
 
98
        onPinchUpdated: {
 
99
            var zoomFactor = MathUtils.clamp(initialZoom * pinch.scale, minimumZoom, maximumZoom);
 
100
            flickable.sizeScale = zoomFactor;
 
101
        }
 
102
        onPinchFinished: {
 
103
            active = false;
 
104
        }
 
105
 
 
106
        Flickable {
 
107
            id: flickable
 
108
            anchors.fill: parent
 
109
            contentWidth: media.width
 
110
            contentHeight: media.height
 
111
            contentX: (sizeScale - 1) * scaleCenterX * width
 
112
            contentY: (sizeScale - 1) * scaleCenterY * height
 
113
            interactive: !viewer.pinchInProgress
 
114
 
 
115
            property real sizeScale: 1.0
 
116
            property real scaleCenterX: 0.0
 
117
            property real scaleCenterY: 0.0
 
118
            Behavior on sizeScale {
 
119
                enabled: !viewer.pinchInProgress
 
120
                UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration}
 
121
            }
 
122
            Behavior on scaleCenterX {
 
123
                UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration}
 
124
            }
 
125
            Behavior on scaleCenterY {
 
126
                UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration}
 
127
            }
 
128
 
 
129
            Item {
 
130
                id: media
 
131
 
 
132
                width: flickable.width * flickable.sizeScale
 
133
                height: flickable.height * flickable.sizeScale
 
134
 
 
135
                Connections {
 
136
                    target: mediaSource
 
137
                    onDataChanged: {
 
138
                        image.source = "";
 
139
                        image.source = "image://photo/" + mediaSource.path
 
140
 
 
141
                        rightResolutionImage.source = "";
 
142
                        rightResolutionImage.source = "image://photo/" + mediaSource.path
 
143
                    }
 
144
                }
 
145
 
 
146
                Behavior on height {
 
147
                    enabled: viewer.animateMediaOnHeight 
 
148
                    UbuntuNumberAnimation {}
 
149
                }
 
150
 
 
151
                Image {
 
152
                    id: image
 
153
                    anchors.fill: parent
 
154
                    asynchronous: true
 
155
                    cache: false
 
156
                    source: viewer.isVideo ? "image://thumbnailer/" + mediaSource.path : "image://photo/" + mediaSource.path
 
157
                    sourceSize {
 
158
                        width: viewer.maxDimension
 
159
                        height: viewer.maxDimension
 
160
                    }
 
161
                    fillMode: Image.PreserveAspectFit
 
162
                    visible: viewer.showThumbnail
 
163
                    opacity: status == Image.Ready ? 1.0 : 0.0
 
164
                    Behavior on opacity { UbuntuNumberAnimation {duration: UbuntuAnimation.FastDuration} }
 
165
 
 
166
                }
 
167
 
 
168
                Image {
 
169
                    id: highResolutionImage
 
170
                    anchors.fill: parent
 
171
                    asynchronous: true
 
172
                    cache: false
 
173
                    // Load image using the photo image provider to ensure EXIF orientation
 
174
                    source: flickable.sizeScale > 1.0 ? "image://photo/" + mediaSource.path : ""
 
175
                    sourceSize {
 
176
                        width: width
 
177
                        height: height
 
178
                    }
 
179
                    opacity: status == Image.Ready ? 1.0 : 0.0
 
180
                    fillMode: Image.PreserveAspectFit
 
181
                }
 
182
            }
 
183
 
 
184
            Icon {
 
185
                width: units.gu(5)
 
186
                height: units.gu(5)
 
187
                anchors.centerIn: parent
 
188
                name: "media-playback-start"
 
189
                color: "white"
 
190
                opacity: 0.8
 
191
                visible: viewer.isVideo
 
192
            }
 
193
 
 
194
            MouseArea {
 
195
                id: viewerMouseArea
 
196
                anchors.fill: parent
 
197
                property bool eventAccepted: false
 
198
 
 
199
                onDoubleClicked: {
 
200
                    if (viewerMouseArea.eventAccepted)
 
201
                        return;
 
202
 
 
203
                    clickTimer.stop();
 
204
                    viewer.animateMediaOnHeight = false
 
205
 
 
206
                    if (viewer.ListView.view.moving) {
 
207
                        // FIXME: workaround for Qt bug specific to touch:
 
208
                        // doubleClicked is received even though the MouseArea
 
209
                        // was tapped only once but another MouseArea was also
 
210
                        // tapped shortly before.
 
211
                        // Ref.: https://bugreports.qt.io/browse/QTBUG-39332
 
212
                        return;
 
213
                    }
 
214
                    if (viewer.isVideo) return;
 
215
 
 
216
                    if (flickable.sizeScale < zoomPinchArea.maximumZoom) {
 
217
                        zoomIn(mouse.x, mouse.y, zoomPinchArea.maximumZoom);
 
218
                    } else {
 
219
                        zoomOut();
 
220
                    }
 
221
                }
 
222
                onClicked: {
 
223
                    viewerMouseArea.eventAccepted = false
 
224
                    clickTimer.start()
 
225
                }
 
226
 
 
227
                Timer {
 
228
                    id: clickTimer
 
229
                    interval: 200 
 
230
                    onTriggered: {
 
231
                        viewerMouseArea.eventAccepted = true
 
232
                        viewer.animateMediaOnHeight = true
 
233
                        viewer.clicked()
 
234
                    }
 
235
                }
 
236
            }
 
237
 
 
238
            MouseArea {
 
239
                anchors.centerIn: parent
 
240
                width: units.gu(10)
 
241
                height: units.gu(10)
 
242
                enabled: viewer.isVideo
 
243
                onClicked: {
 
244
                    if (viewer.isVideo) {
 
245
                        var url = mediaSource.path.toString().replace("file://", "video://");
 
246
                        Qt.openUrlExternally(url);
 
247
                    }
 
248
                }
 
249
            }
 
250
        }
 
251
    }
 
252
}