~abreu-alexandre/webbrowser-app/theme-color-meta-detection

« back to all changes in this revision

Viewing changes to src/app/webbrowser/DownloadsPage.qml

  • Committer: CI Train Bot
  • Author(s): Michael Sheldon
  • Date: 2015-12-21 20:39:33 UTC
  • mfrom: (1106.3.119 implement-download-folder)
  • Revision ID: ci-train-bot@canonical.com-20151221203933-o2ijlcmhhyoi62wk
Add support for handling downloads internally within the browser. Fixes: #1354391
Approved by: Olivier Tilloy

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2015 Canonical Ltd.
 
3
 *
 
4
 * This file is part of webbrowser-app.
 
5
 *
 
6
 * webbrowser-app is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; version 3.
 
9
 *
 
10
 * webbrowser-app is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
import QtQuick 2.0
 
20
import Qt.labs.settings 1.0
 
21
import Ubuntu.Components 1.3
 
22
import Ubuntu.Components.Popups 1.0
 
23
import Ubuntu.Thumbnailer 0.1
 
24
import Ubuntu.Content 1.3
 
25
import Ubuntu.Web 0.2
 
26
import webbrowserapp.private 0.1
 
27
import webbrowsercommon.private 0.1
 
28
 
 
29
import "../MimeTypeMapper.js" as MimeTypeMapper
 
30
 
 
31
Item {
 
32
    id: downloadsItem
 
33
 
 
34
    property QtObject downloadsModel
 
35
 
 
36
    // We can get file picking requests either via content-hub (activeTransfer)
 
37
    // Or via the internal oxide file picker (internalFilePicker) in the case
 
38
    // where the user wishes to upload a file from their previous downloads.
 
39
    property var activeTransfer
 
40
    property var internalFilePicker
 
41
 
 
42
    property bool selectMode
 
43
    property bool pickingMode
 
44
    property bool multiSelect
 
45
    property alias mimetypeFilter: downloadModelFilter.pattern
 
46
 
 
47
    signal done()
 
48
 
 
49
    Rectangle {
 
50
        anchors.fill: parent
 
51
        color: "#fbfbfb"
 
52
    }
 
53
 
 
54
    BrowserPageHeader {
 
55
        id: title
 
56
        text: i18n.tr("Downloads")
 
57
        color: "#f7f7f7"
 
58
        actions: [
 
59
            Action {
 
60
                text: i18n.tr("Confirm selection")
 
61
                iconName: "tick"
 
62
                visible: pickingMode
 
63
                enabled: downloadsListView.ViewItems.selectedIndices.length > 0
 
64
                onTriggered: {
 
65
                    var results = []
 
66
                    if (internalFilePicker) {
 
67
                        for (var i = 0; i < downloadsListView.ViewItems.selectedIndices.length; i++) {
 
68
                            var selectedDownload = downloadsListView.model.get(downloadsListView.ViewItems.selectedIndices[i])
 
69
                            results.push(selectedDownload.path)
 
70
                        }
 
71
                        internalFilePicker.accept(results)
 
72
                    } else {
 
73
                        for (var i = 0; i < downloadsListView.ViewItems.selectedIndices.length; i++) {
 
74
                            var selectedDownload = downloadsListView.model.get(downloadsListView.ViewItems.selectedIndices[i])
 
75
                            results.push(resultComponent.createObject(downloadsItem, {"url": "file://" + selectedDownload.path}))
 
76
                        }
 
77
                        activeTransfer.items = results
 
78
                        activeTransfer.state = ContentTransfer.Charged
 
79
                    }
 
80
                    downloadsItem.done()
 
81
                }
 
82
            },
 
83
            Action {
 
84
                text: i18n.tr("Select all")
 
85
                iconName: "select"
 
86
                visible: selectMode
 
87
                onTriggered: {
 
88
                    if (downloadsListView.ViewItems.selectedIndices.length === downloadsListView.count) {
 
89
                        downloadsListView.ViewItems.selectedIndices = []
 
90
                    } else {
 
91
                        var indices = []
 
92
                        for (var i = 0; i < downloadsListView.count; ++i) {
 
93
                            indices.push(i)
 
94
                        }
 
95
                        downloadsListView.ViewItems.selectedIndices = indices
 
96
                    }
 
97
                }
 
98
            },
 
99
            Action {
 
100
                text: i18n.tr("Delete")
 
101
                iconName: "delete"
 
102
                visible: selectMode
 
103
                onTriggered: {
 
104
                    var toDelete = []
 
105
                    for (var i = 0; i < downloadsListView.ViewItems.selectedIndices.length; i++) {
 
106
                        var selectedDownload = downloadsListView.model.get(downloadsListView.ViewItems.selectedIndices[i])
 
107
                        toDelete.push(selectedDownload.path)
 
108
                    }
 
109
                    for (var i = 0; i < toDelete.length; i++) {
 
110
                        downloadsModel.deleteDownload(toDelete[i])
 
111
                    }
 
112
                    downloadsListView.ViewItems.selectedIndices = []
 
113
                    downloadsItem.selectMode = false
 
114
                }
 
115
            },
 
116
            Action {
 
117
                iconName: "edit" 
 
118
                visible: !selectMode && !pickingMode
 
119
                onTriggered: {
 
120
                    selectMode = true
 
121
                    multiSelect = true
 
122
                }
 
123
            }
 
124
        ]
 
125
        onBack: {
 
126
            if (selectMode) {
 
127
                selectMode = false
 
128
            } else {
 
129
                if (activeTransfer) {
 
130
                    activeTransfer.state = ContentTransfer.Aborted
 
131
                }
 
132
                if (internalFilePicker) {
 
133
                    internalFilePicker.reject()
 
134
                }
 
135
                downloadsItem.done()
 
136
            }
 
137
        }
 
138
    }
 
139
 
 
140
    Component {
 
141
        id: resultComponent
 
142
        ContentItem { }
 
143
    }
 
144
 
 
145
    ListView {
 
146
        id: downloadsListView
 
147
        clip: true
 
148
 
 
149
        anchors {
 
150
            top: title.bottom
 
151
            left: parent.left
 
152
            right: parent.right
 
153
            bottom: parent.bottom
 
154
            rightMargin: units.gu(2)
 
155
        }
 
156
 
 
157
        model: SortFilterModel {
 
158
            model: downloadsModel
 
159
            filter { 
 
160
                id: downloadModelFilter
 
161
                property: "mimetype"
 
162
            }
 
163
        }
 
164
 
 
165
        delegate: DownloadDelegate {
 
166
            downloadId: model.downloadId
 
167
            title: model.filename ? model.filename : model.url.toString().split('/').pop().split('?').shift()
 
168
            url: model.url
 
169
            image: model.complete && (model.mimetype.indexOf("image") === 0 || model.mimetype.indexOf("video") === 0) ? "image://thumbnailer/file://" + model.path : ""
 
170
            icon: MimeDatabase.iconForMimetype(model.mimetype)
 
171
            incomplete: !model.complete
 
172
            selectMode: downloadsItem.selectMode || downloadsItem.pickingMode
 
173
            visible: !(selectMode && incomplete)
 
174
            errorMessage: model.error
 
175
            paused: model.paused
 
176
            // Work around bug #1493880
 
177
            property bool lastSelected
 
178
 
 
179
            onSelectedChanged: {
 
180
                if (!multiSelect && selected && lastSelected != selected) {
 
181
                    downloadsListView.ViewItems.selectedIndices = [index]
 
182
                }
 
183
                lastSelected = selected
 
184
            }
 
185
 
 
186
            onClicked: {
 
187
                if (model.complete) {
 
188
                    if (selectMode) {
 
189
                        selected = !selected
 
190
                    } else {
 
191
                        exportPeerPicker.contentType = MimeTypeMapper.mimeTypeToContentType(model.mimetype)
 
192
                        exportPeerPicker.visible = true
 
193
                        exportPeerPicker.path = model.path
 
194
                    }
 
195
                }
 
196
            }
 
197
 
 
198
            onPressAndHold: {
 
199
                downloadsItem.selectMode = true
 
200
                downloadsItem.multiSelect = true
 
201
                if (downloadsItem.selectMode) {
 
202
                    downloadsListView.ViewItems.selectedIndices = [index]
 
203
                }
 
204
            }
 
205
 
 
206
            onRemoved: {
 
207
                if (model.complete) {
 
208
                    downloadsModel.deleteDownload(model.path)
 
209
                }
 
210
            }
 
211
 
 
212
            onCancelled: {
 
213
                downloadsModel.cancelDownload(model.downloadId)
 
214
            }
 
215
        }
 
216
 
 
217
    }
 
218
 
 
219
    Label {
 
220
        id: emptyLabel
 
221
        anchors.centerIn: parent
 
222
        visible: downloadsListView.count == 0
 
223
        wrapMode: Text.Wrap
 
224
        width: parent.width
 
225
        horizontalAlignment: Text.AlignHCenter
 
226
        text: i18n.tr("No downloads available")
 
227
    }
 
228
 
 
229
    Component {
 
230
        id: contentItemComponent
 
231
        ContentItem {}
 
232
    }
 
233
 
 
234
    ContentPeerPicker {
 
235
        id: exportPeerPicker
 
236
        visible: false
 
237
        anchors.fill: parent
 
238
        handler: ContentHandler.Destination
 
239
        property string path
 
240
        onPeerSelected: {
 
241
            var transfer = peer.request()
 
242
            if (transfer.state === ContentTransfer.InProgress) {
 
243
                transfer.items = [contentItemComponent.createObject(downloadsItem, {"url": path})]
 
244
                transfer.state = ContentTransfer.Charged
 
245
            }
 
246
            visible = false
 
247
        }
 
248
        onCancelPressed: {
 
249
            visible = false
 
250
        }
 
251
    }
 
252
 
 
253
}