Move PreviewImage underneath FocusReticle
[harmattan/cameraplus] / qml / PostCaptureView.qml
1 // -*- qml -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 import QtQuick 2.0
24 import CameraPlus 1.0
25 import QtCamera 1.0
26
27 Item {
28     property Camera camera: null
29     property bool pressed: view.currentItem ? view.currentItem.playing : false
30     property int policyMode: view.currentItem && view.currentItem.playing ?
31         CameraResources.Player : settings.mode == Camera.VideoMode ? CameraResources.Video :
32         CameraResources.Image
33     property bool available: view.currentItem ? view.currentItem.itemData.available : false
34
35     ShareHelper {
36         id: share
37         settings: platformSettings
38     }
39
40     GalleryHelper {
41         id: gallery
42         settings: platformSettings
43     }
44
45     ListView {
46         id: view
47         anchors.fill: parent
48         snapMode: ListView.SnapOneItem
49         cacheBuffer: height * 3
50         model: postCaptureModel
51         highlightRangeMode: ListView.StrictlyEnforceRange
52
53         delegate: PostCaptureItem {
54             width: view.width
55             height: view.height
56             onClicked: hideTimer.running = !hideTimer.running
57         }
58
59         onFlickingChanged: {
60             if (flicking && hideTimer.running) {
61                 restartTimer()
62             }
63         }
64     }
65
66     property variant postCaptureModel: postCaptureModelLoader.item ?
67         postCaptureModelLoader.item.model : null
68     property bool loadModel: mainView.currentIndex == 2 && Qt.application.active
69
70     Loader {
71         id: postCaptureModelLoader
72         sourceComponent: loadModel ? postCaptureModelComponent : undefined
73     }
74
75     // We have to do it that way because Loader does not support non-visual elements.
76     Component {
77         id: postCaptureModelComponent
78
79         Item {
80             property alias model: postCaptureModel
81
82             PostCaptureModel {
83                 id: postCaptureModel
84                 manufacturer: deviceInfo.manufacturer
85                 model: deviceInfo.model
86                 Component.onCompleted: reload()
87                 onError: {
88                     console.log("Error populating model " + msg)
89                     showError(qsTr("Failed to load captures"))
90                 }
91             }
92         }
93     }
94
95     Timer {
96         id: hideTimer
97         running: false
98         interval: 3000
99     }
100
101     CameraToolBar {
102         id: toolBar
103         expanded: true
104         hideBack: true
105         anchors.bottom: parent.bottom
106         anchors.bottomMargin: show ? 20 : -1 * (height + 20)
107         anchors.left: parent.left
108         anchors.leftMargin: 20
109         opacity: 0.8
110
111         property bool show: deleteDialog.isOpen || deleteDialog.isOpening ||
112             hideTimer.running || menu.isOpen || menu.isOpening ||
113             (view.currentItem && view.currentItem.error) && !view.currentItem.playing
114
115         Behavior on anchors.bottomMargin {
116             PropertyAnimation { duration: 200; }
117         }
118
119         items: [
120             CameraToolIcon {
121                 iconId: !available ? "icon-m-toolbar-favorite-mark-dimmed-white" : view.currentItem.itemData.favorite ? "icon-m-toolbar-favorite-mark-white" : "icon-m-toolbar-favorite-unmark-white"
122                 onClicked: {
123                     addOrRemoveFavorite()
124                     restartTimer()
125                 }
126             },
127             CameraToolIcon {
128                 iconId: available ? "icon-m-toolbar-share-white" : "icon-m-toolbar-share-dimmed-white"
129                 onClicked: {
130                     shareCurrentItem()
131                     restartTimer()
132                 }
133             },
134             CameraToolIcon {
135                 iconId: available ? "icon-m-toolbar-delete-white" : "icon-m-toolbar-delete-dimmed-white"
136                 onClicked: {
137                     deleteCurrentItem()
138                     restartTimer()
139                 }
140             },
141             CameraToolIcon {
142                 iconId: "icon-m-toolbar-view-menu-white"
143                 onClicked: {
144                     menu.open()
145                     restartTimer()
146                 }
147             }
148         ]
149     }
150
151     CameraQueryDialog {
152         id: deleteDialog
153         titleText: qsTr("Delete item?");
154         acceptButtonText: qsTr("Yes");
155         rejectButtonText: qsTr("No");
156
157         onStatusChanged: restartTimer()
158
159         onAccepted: {
160             if (!remove.remove(view.currentItem.itemData.url)) {
161                 showError(qsTr("Failed to delete item"))
162             } else {
163                 postCaptureModel.remove(view.currentItem.itemData);
164             }
165         }
166
167         DeleteHelper {
168             id: remove
169         }
170     }
171
172     CameraMenu {
173         id: menu
174         onStatusChanged: restartTimer()
175
176         actions: [
177             CameraMenuAction {
178                 text: qsTr("Captures in gallery")
179                 onClicked: launchGallery()
180             },
181             CameraMenuAction {
182                 // TODO: this is not working...
183                 text: qsTr("View in gallery")
184                 enabled: available
185                 onClicked: showInGallery()
186             }
187         ]
188     }
189
190     Rectangle {
191         opacity: toolBar.opacity
192         anchors.top: parent.top
193         anchors.topMargin: toolBar.show ? 20 : -1 * (height + 20)
194         anchors.left: parent.left
195         anchors.leftMargin: 20
196         anchors.right: parent.right
197         anchors.rightMargin: 20
198         visible: toolBar.visible
199         height: screen.isPortrait ? toolBar.height * 2 : toolBar.height
200         color: toolBar.color
201         border.color: toolBar.border.color
202         radius: toolBar.radius
203
204         Behavior on anchors.topMargin {
205             PropertyAnimation { duration: 200; }
206         }
207
208         Flow {
209             width: parent.width - 40
210             x: 20
211             height: parent.height
212
213             CameraLabel {
214                 text: view.currentItem ? view.currentItem.itemData.title : ""
215                 width: parent.width / 2
216                 height: parent.height
217                 font.bold: true
218                 verticalAlignment: Text.AlignVCenter
219                 horizontalAlignment: Text.AlignLeft
220             }
221
222             CameraLabel {
223                 text: view.currentItem ? view.currentItem.itemData.created : ""
224                 width: parent.width / 2
225                 height: parent.height
226                 font.bold: true
227                 verticalAlignment: Text.AlignVCenter
228                 horizontalAlignment: Text.AlignRight
229             }
230         }
231     }
232
233     function launchGallery() {
234         if (!gallery.launch()) {
235             showError(qsTr("Failed to launch gallery"))
236         }
237     }
238
239     function showInGallery() {
240         if (!available) {
241             return
242         }
243
244         if (!gallery.show(view.currentItem.itemUrl)) {
245             showError(qsTr("Failed to launch gallery"))
246         }
247     }
248
249     function deleteCurrentItem() {
250         if (!available) {
251             return
252         }
253
254         deleteDialog.message = view.currentItem.itemData.fileName
255         deleteDialog.open()
256     }
257
258     function shareCurrentItem() {
259         if (!available) {
260             return
261         }
262
263         if (!share.share(view.currentItem.itemData.url)) {
264             showError(qsTr("Failed to launch share service"))
265         }
266     }
267
268     function addOrRemoveFavorite() {
269         if (!available) {
270             return
271         }
272
273         if (view.currentItem.itemData.favorite) {
274             if (!trackerStore.removeFromFavorites(view.currentItem.itemData.url)) {
275                 showError(qsTr("Failed to remove favorite"))
276             } else {
277                 view.currentItem.itemData.favorite = false
278             }
279         } else {
280             if (!trackerStore.addToFavorites(view.currentItem.itemData.url)) {
281                 showError(qsTr("Failed to add favorite"))
282             } else {
283                 view.currentItem.itemData.favorite = true
284             }
285         }
286     }
287
288     function restartTimer() {
289         hideTimer.restart()
290     }
291
292     function policyLost() {
293         if (view.currentItem && view.currentItem.playing) {
294             view.currentItem.stopPlayback()
295         }
296     }
297 }