Put error label and play button in a column to prevent their overlap
[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_QT_QUICK@
24 import CameraPlus 1.0
25 import QtCamera 1.0
26
27 Item {
28     property bool pressed: view.currentItem ? view.currentItem.playing : false
29     property int policyMode: view.currentItem && view.currentItem.playing ?
30         CameraResources.Player : settings.mode == Camera.VideoMode ? CameraResources.Video :
31         CameraResources.Image
32     property bool available: view.currentItem ? view.currentItem.itemData.available : false
33
34     ShareHelper {
35         id: share
36         settings: platformSettings
37     }
38
39     GalleryHelper {
40         id: gallery
41         settings: platformSettings
42     }
43
44     ListView {
45         id: view
46         anchors.fill: parent
47         snapMode: ListView.SnapOneItem
48         cacheBuffer: height * 3
49         model: postCaptureModel
50         highlightRangeMode: ListView.StrictlyEnforceRange
51
52         delegate: PostCaptureItem {
53             width: view.width
54             height: view.height
55             onClicked: hideTimer.running = !hideTimer.running
56         }
57
58         onFlickingChanged: {
59             if (flicking && hideTimer.running) {
60                 restartTimer()
61             }
62         }
63     }
64
65     property variant postCaptureModel: postCaptureModelLoader.item ?
66         postCaptureModelLoader.item.model : null
67     property bool loadModel: mainView.currentIndex == 2 && Qt.application.active
68
69     Loader {
70         id: postCaptureModelLoader
71         sourceComponent: loadModel ? postCaptureModelComponent : undefined
72     }
73
74     // We have to do it that way because Loader does not support non-visual elements.
75     Component {
76         id: postCaptureModelComponent
77
78         Item {
79             property alias model: postCaptureModel
80
81             PostCaptureModel {
82                 id: postCaptureModel
83                 manufacturer: deviceInfo.manufacturer
84                 model: deviceInfo.model
85                 Component.onCompleted: reload()
86                 onError: {
87                     console.log("Error populating model " + msg)
88                     showError(qsTr("Failed to load captures"))
89                 }
90             }
91         }
92     }
93
94     Timer {
95         id: hideTimer
96         running: false
97         interval: 3000
98     }
99
100     CameraToolBar {
101         id: toolBar
102         expanded: true
103         hideBack: true
104         anchors.bottom: parent.bottom
105         anchors.bottomMargin: show ? 20 : -1 * (height + 20)
106         anchors.left: parent.left
107         anchors.leftMargin: 20
108         opacity: 0.8
109
110         property bool show: deleteDialog.isOpen || deleteDialog.isOpening ||
111             hideTimer.running || menu.isOpen || menu.isOpening ||
112             (view.currentItem && view.currentItem.error) && !view.currentItem.playing
113
114         Behavior on anchors.bottomMargin {
115             PropertyAnimation { duration: 200; }
116         }
117
118         items: [
119             CameraToolIcon {
120                 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"
121                 onClicked: {
122                     addOrRemoveFavorite()
123                     restartTimer()
124                 }
125             },
126             CameraToolIcon {
127                 iconId: available ? "icon-m-toolbar-share-white" : "icon-m-toolbar-share-dimmed-white"
128                 onClicked: {
129                     shareCurrentItem()
130                     restartTimer()
131                 }
132             },
133             CameraToolIcon {
134                 iconId: available ? "icon-m-toolbar-delete-white" : "icon-m-toolbar-delete-dimmed-white"
135                 onClicked: {
136                     deleteCurrentItem()
137                     restartTimer()
138                 }
139             },
140             CameraToolIcon {
141                 iconId: "icon-m-toolbar-view-menu-white"
142                 onClicked: {
143                     menu.open()
144                     restartTimer()
145                 }
146             }
147         ]
148     }
149
150     CameraQueryDialog {
151         id: deleteDialog
152         titleText: qsTr("Delete item?");
153         acceptButtonText: qsTr("Yes");
154         rejectButtonText: qsTr("No");
155
156         onStatusChanged: restartTimer()
157
158         onAccepted: {
159             if (!remove.remove(view.currentItem.itemData.url)) {
160                 showError(qsTr("Failed to delete item"))
161             } else {
162                 postCaptureModel.remove(view.currentItem.itemData);
163             }
164         }
165
166         DeleteHelper {
167             id: remove
168         }
169     }
170
171     CameraMenu {
172         id: menu
173         onStatusChanged: restartTimer()
174
175         actions: [
176             CameraMenuAction {
177                 text: qsTr("Captures in gallery")
178                 onClicked: launchGallery()
179             },
180             CameraMenuAction {
181                 // TODO: this is not working...
182                 text: qsTr("View in gallery")
183                 enabled: available
184                 onClicked: showInGallery()
185             }
186         ]
187     }
188
189     Rectangle {
190         opacity: toolBar.opacity
191         anchors.top: parent.top
192         anchors.topMargin: toolBar.show ? 20 : -1 * (height + 20)
193         anchors.left: parent.left
194         anchors.leftMargin: 20
195         anchors.right: parent.right
196         anchors.rightMargin: 20
197         visible: toolBar.visible
198         height: screen.isPortrait ? toolBar.height * 2 : toolBar.height
199         color: toolBar.color
200         border.color: toolBar.border.color
201         radius: toolBar.radius
202
203         Behavior on anchors.topMargin {
204             PropertyAnimation { duration: 200; }
205         }
206
207         Flow {
208             width: parent.width - 40
209             x: 20
210             height: parent.height
211
212             CameraLabel {
213                 text: view.currentItem ? view.currentItem.itemData.title : ""
214                 width: parent.width / 2
215                 height: parent.height
216                 font.bold: true
217                 verticalAlignment: Text.AlignVCenter
218                 horizontalAlignment: Text.AlignLeft
219             }
220
221             CameraLabel {
222                 text: view.currentItem ? view.currentItem.itemData.created : ""
223                 width: parent.width / 2
224                 height: parent.height
225                 font.bold: true
226                 verticalAlignment: Text.AlignVCenter
227                 horizontalAlignment: Text.AlignRight
228             }
229         }
230     }
231
232     function launchGallery() {
233         if (!gallery.launch()) {
234             showError(qsTr("Failed to launch gallery"))
235         }
236     }
237
238     function showInGallery() {
239         if (!available) {
240             return
241         }
242
243         if (!gallery.show(view.currentItem.itemUrl)) {
244             showError(qsTr("Failed to launch gallery"))
245         }
246     }
247
248     function deleteCurrentItem() {
249         if (!available) {
250             return
251         }
252
253         deleteDialog.message = view.currentItem.itemData.fileName
254         deleteDialog.open()
255     }
256
257     function shareCurrentItem() {
258         if (!available) {
259             return
260         }
261
262         if (!share.share(view.currentItem.itemData.url)) {
263             showError(qsTr("Failed to launch share service"))
264         }
265     }
266
267     function addOrRemoveFavorite() {
268         if (!available) {
269             return
270         }
271
272         if (view.currentItem.itemData.favorite) {
273             if (!trackerStore.removeFromFavorites(view.currentItem.itemData.url)) {
274                 showError(qsTr("Failed to remove favorite"))
275             } else {
276                 view.currentItem.itemData.favorite = false
277             }
278         } else {
279             if (!trackerStore.addToFavorites(view.currentItem.itemData.url)) {
280                 showError(qsTr("Failed to add favorite"))
281             } else {
282                 view.currentItem.itemData.favorite = true
283             }
284         }
285     }
286
287     function restartTimer() {
288         hideTimer.restart()
289     }
290
291     function policyLost() {
292         if (view.currentItem && view.currentItem.playing) {
293             view.currentItem.stopPlayback()
294         }
295     }
296 }