~jonas-drange/ubuntu-system-settings/harden-clickclient-test

« back to all changes in this revision

Viewing changes to plugins/system-update/PageComponent.qml

  • Committer: Bileto Bot
  • Author(s): jonas-drange
  • Date: 2016-08-17 11:18:05 UTC
  • mfrom: (1631.6.245 updates-rewrite)
  • Revision ID: ci-train-bot@canonical.com-20160817111805-moyvik9wloy79ul3
rewrite the system update panel

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * This file is part of system-settings
3
3
 *
4
 
 * Copyright (C) 2013-2014 Canonical Ltd.
 
4
 * Copyright (C) 2013-2016 Canonical Ltd.
5
5
 *
6
6
 * Contact: Didier Roche <didier.roches@canonical.com>
7
 
 * Contact: Diego Sarmentero <diego.sarmentero@canonical.com>
 
7
 *          Diego Sarmentero <diego.sarmentero@canonical.com>
 
8
 *          Jonas G. Drange <jonas.drange@canonical.com>
8
9
 *
9
10
 * This program is free software: you can redistribute it and/or modify it
10
11
 * under the terms of the GNU General Public License version 3, as published
29
30
import Ubuntu.SystemSettings.Update 1.0
30
31
import Ubuntu.Connectivity 1.0
31
32
 
32
 
 
33
33
ItemPage {
34
34
    id: root
35
35
    objectName: "systemUpdatesPage"
36
36
 
37
 
    title: installingImageUpdate.visible ? "" : i18n.tr("Updates")
38
 
    flickable: installingImageUpdate.visible ? null : scrollWidget
39
 
 
40
 
    property bool installAll: false
41
 
    property bool includeSystemUpdate: false
42
 
    property bool systemUpdateInProgress: false
43
 
    property int updatesAvailable: 0
44
 
    property bool isCharging: indicatorPower.deviceState === "charging"
45
 
    property bool batterySafeForUpdate: isCharging || chargeLevel > 25
46
 
    property var chargeLevel: indicatorPower.batteryLevel || 0
47
 
    property var notificationAction;
48
 
    property string errorDialogText: ""
49
 
 
50
 
    onUpdatesAvailableChanged: {
51
 
        if (updatesAvailable < 1 && root.state != "SEARCHING")
52
 
            root.state = "NOUPDATES";
 
37
    header: PageHeader {
 
38
        title: i18n.tr("Updates")
 
39
        flickable: scrollWidget
 
40
    }
 
41
 
 
42
 
 
43
    property bool batchMode: false
 
44
    property bool havePower: (indicatorPower.deviceState === "charging") ||
 
45
                             (indicatorPower.batteryLevel > 25)
 
46
    property bool online: NetworkingStatus.online
 
47
    property bool authenticated: UpdateManager.authenticated
 
48
    property bool forceCheck: false
 
49
 
 
50
    property int updatesCount: {
 
51
        var count = 0;
 
52
        if (authenticated) {
 
53
            count += clickRepeater.count;
 
54
        }
 
55
        count += imageRepeater.count;
 
56
        return count;
 
57
    }
 
58
 
 
59
    function check(force) {
 
60
        if (force === true) {
 
61
            UpdateManager.check(UpdateManager.CheckAll);
 
62
        } else {
 
63
            if (imageRepeater.count === 0 && clickRepeater.count === 0) {
 
64
                UpdateManager.check(UpdateManager.CheckAll);
 
65
            } else {
 
66
                // Only check 30 minutes after last successful check.
 
67
                UpdateManager.check(UpdateManager.CheckIfNecessary);
 
68
            }
 
69
        }
53
70
    }
54
71
 
55
72
    QDBusActionGroup {
57
74
        busType: 1
58
75
        busName: "com.canonical.indicator.power"
59
76
        objectPath: "/com/canonical/indicator/power"
60
 
        property variant batteryLevel: action("battery-level").state
61
 
        property variant deviceState: action("device-state").state
 
77
        property var batteryLevel: action("battery-level").state || 0
 
78
        property var deviceState: action("device-state").state
62
79
        Component.onCompleted: start()
63
80
    }
64
81
 
65
 
    Connections {
66
 
        id: networkingStatus
67
 
        target: NetworkingStatus
68
 
        onOnlineChanged: {
69
 
            if (NetworkingStatus.online) {
70
 
                activity.running = true;
71
 
                root.state = "SEARCHING";
72
 
                UpdateManager.checkUpdates();
73
 
            } else {
74
 
                activity.running = false;
75
 
            }
76
 
        }
77
 
    }
78
 
 
79
82
    Setup {
80
83
        id: uoaConfig
 
84
        objectName: "uoaConfig"
81
85
        applicationId: "ubuntu-system-settings"
82
86
        providerId: "ubuntuone"
83
87
 
84
88
        onFinished: {
85
 
            credentialsNotification.visible = false;
86
 
            root.state = "SEARCHING";
87
 
            if (NetworkingStatus.online)
88
 
                UpdateManager.checkUpdates();
89
 
        }
90
 
    }
91
 
 
92
 
    Component {
93
 
         id: dialogInstallComponent
94
 
         Dialog {
95
 
             id: dialogueInstall
96
 
             title: i18n.tr("Update System")
97
 
             text: root.batterySafeForUpdate ? i18n.tr("The device needs to restart to install the system update.") : i18n.tr("Connect the device to power before installing the system update.")
98
 
 
99
 
             Button {
100
 
                 text: i18n.tr("Restart & Install")
101
 
                 visible: root.batterySafeForUpdate ? true : false
102
 
                 color: theme.palette.normal.positive
103
 
                 onClicked: {
104
 
                     installingImageUpdate.visible = true;
105
 
                     UpdateManager.applySystemUpdate();
106
 
                     PopupUtils.close(dialogueInstall);
107
 
                 }
108
 
             }
109
 
             Button {
110
 
                 text: i18n.tr("Cancel")
111
 
                 onClicked: {
112
 
                     updateList.currentIndex = 0;
113
 
                     var item = updateList.currentItem;
114
 
                     var modelItem = UpdateManager.model[0];
115
 
                     item.actionButton.text = i18n.tr("Install");
116
 
                     item.progressBar.opacity = 0;
117
 
                     modelItem.updateReady = true;
118
 
                     modelItem.selected = false;
119
 
                     root.systemUpdateInProgress = false;
120
 
                     PopupUtils.close(dialogueInstall);
121
 
                 }
122
 
             }
123
 
         }
124
 
    }
125
 
 
126
 
    Component {
127
 
         id: dialogErrorComponent
128
 
         Dialog {
129
 
             id: dialogueError
130
 
             title: i18n.tr("Installation failed")
131
 
             text: root.errorDialogText
132
 
 
133
 
             Button {
134
 
                 text: i18n.tr("OK")
135
 
                 color: theme.palette.normal.positive
136
 
                 onClicked: {
137
 
                     PopupUtils.close(dialogueError);
138
 
                 }
139
 
             }
140
 
         }
141
 
    }
142
 
 
143
 
    //states
144
 
    states: [
145
 
        State {
146
 
            name: "SEARCHING"
147
 
            PropertyChanges { target: installAllButton; visible: false}
148
 
            PropertyChanges { target: checkForUpdatesArea; visible: true}
149
 
            PropertyChanges { target: updateNotification; visible: false}
150
 
            PropertyChanges { target: activity; running: NetworkingStatus.online}
151
 
        },
152
 
        State {
153
 
            name: "NOUPDATES"
154
 
            PropertyChanges { target: updateNotification; text: i18n.tr("Software is up to date")}
155
 
            PropertyChanges { target: updateNotification; visible: true}
156
 
            PropertyChanges { target: updateList; visible: false}
157
 
            PropertyChanges { target: installAllButton; visible: false}
158
 
        },
159
 
        State {
160
 
            name: "SYSTEMUPDATEFAILED"
161
 
            PropertyChanges { target: installingImageUpdate; visible: false}
162
 
            PropertyChanges { target: installAllButton; visible: false}
163
 
            PropertyChanges { target: checkForUpdatesArea; visible: false}
164
 
            PropertyChanges { target: updateNotification; visible: false}
165
 
        },
166
 
        State {
167
 
            name: "UPDATE"
168
 
            PropertyChanges { target: updateList; visible: true}
169
 
            PropertyChanges { target: installAllButton; visible: root.updatesAvailable > 1}
170
 
            PropertyChanges { target: updateNotification; visible: false}
171
 
        }
172
 
    ]
173
 
 
174
 
    Connections {
175
 
        id: updateManager
176
 
        target: UpdateManager
177
 
        objectName: "updateManager"
178
 
 
179
 
        Component.onCompleted: {
180
 
            credentialsNotification.visible = false;
181
 
            root.state = "SEARCHING";
182
 
            if (NetworkingStatus.online)
183
 
                UpdateManager.checkUpdates();
184
 
        }
185
 
 
186
 
        onUpdateAvailableFound: {
187
 
            root.updatesAvailable = UpdateManager.model.length;
188
 
            if (root.updatesAvailable > 0)
189
 
                root.includeSystemUpdate = UpdateManager.model[0].systemUpdate
190
 
            root.state = "UPDATE";
191
 
            root.installAll = downloading;
192
 
        }
193
 
 
194
 
        onUpdatesNotFound: {
195
 
            if (!credentialsNotification.visible) {
196
 
                root.state = "NOUPDATES";
 
89
            if (reply.errorName) {
 
90
                console.warn('Online Accounts failed:', reply.errorName);
197
91
            }
198
 
        }
199
 
 
200
 
        onCheckFinished: {
201
 
            checkForUpdatesArea.visible = false;
202
 
        }
203
 
 
204
 
        onCredentialsNotFound: {
205
 
            credentialsNotification.visible = true;
206
 
        }
207
 
 
208
 
        onCredentialsDeleted: {
209
 
            credentialsNotification.visible = true;
210
 
        }
211
 
 
212
 
        onSystemUpdateDownloaded: {
213
 
            root.installAll = false;
214
 
            if (root.includeSystemUpdate)
215
 
                UpdateManager.model[0].status = Update.Downloaded;
216
 
        }
217
 
 
218
 
        onSystemUpdateFailed: {
219
 
            root.state = "SYSTEMUPDATEFAILED";
220
 
            root.errorDialogText = i18n.tr("Sorry, the system update failed.");
221
 
            PopupUtils.open(dialogErrorComponent);
222
 
        }
223
 
 
224
 
        onUpdateProcessFailed: {
225
 
            root.state = "SYSTEMUPDATEFAILED";
226
 
            root.errorDialogText = i18n.tr("Sorry, the system update failed.");
227
 
            PopupUtils.open(dialogErrorComponent);
228
 
        }
229
 
 
230
 
        onServerError: {
231
 
            activity.running = false;
232
 
        }
233
 
 
234
 
        onNetworkError: {
235
 
            activity.running = false;
236
 
        }
237
 
 
238
 
        onRebooting: {
239
 
            installingImageUpdate.message = i18n.tr("Restarting…");
240
 
        }
241
 
    }
 
92
            UpdateManager.check(UpdateManager.CheckClick);
 
93
            notauthNotification.enabled = true;
 
94
        }
 
95
    }
 
96
 
 
97
    DownloadHandler {
 
98
        id: downloadHandler
 
99
        updateModel: UpdateManager.model
 
100
    }
 
101
 
242
102
    Flickable {
243
103
        id: scrollWidget
244
 
 
245
 
        anchors.top: parent.top
246
 
        anchors.left: parent.left
247
 
        anchors.right: parent.right
248
 
        anchors.bottom: configuration.top
249
 
 
250
 
        contentHeight: contentItem.childrenRect.height
251
 
        boundsBehavior: (contentHeight > root.height) ? Flickable.DragAndOvershootBounds : Flickable.StopAtBounds
 
104
        anchors {
 
105
            top: parent.top
 
106
            left: parent.left
 
107
            right: parent.right
 
108
            bottom: configuration.top
 
109
        }
252
110
        clip: true
253
 
        /* Set the direction to workaround https://bugreports.qt-project.org/browse/QTBUG-31905
254
 
           otherwise the UI might end up in a situation where scrolling doesn't work */
 
111
        contentHeight: content.height
 
112
        boundsBehavior: (contentHeight > parent.height) ?
 
113
                        Flickable.DragAndOvershootBounds :
 
114
                        Flickable.StopAtBounds
255
115
        flickableDirection: Flickable.VerticalFlick
256
116
 
257
117
        Column {
258
 
            id: columnId
259
 
            anchors {
260
 
                left: parent.left
261
 
                right: parent.right
 
118
            id: content
 
119
            anchors { left: parent.left; right: parent.right }
 
120
 
 
121
            Global {
 
122
                id: glob
 
123
                objectName: "global"
 
124
                anchors { left: parent.left; right: parent.right }
 
125
 
 
126
                height: hidden ? 0 : units.gu(8)
 
127
                clip: true
 
128
                status: UpdateManager.status
 
129
                batchMode: root.batchMode
 
130
                requireRestart: imageRepeater.count > 0
 
131
                updatesCount: root.updatesCount
 
132
                online: root.online
 
133
                onStop: UpdateManager.cancel()
 
134
 
 
135
                onRequestInstall: {
 
136
                    if (requireRestart) {
 
137
                        var popup = PopupUtils.open(
 
138
                            Qt.resolvedUrl("ImageUpdatePrompt.qml"), null, {
 
139
                                havePowerForUpdate: root.havePower
 
140
                            }
 
141
                        );
 
142
                        popup.requestSystemUpdate.connect(function () {
 
143
                            install();
 
144
                        });
 
145
                    } else {
 
146
                        install();
 
147
                    }
 
148
                }
 
149
                onInstall: {
 
150
                    root.batchMode = true
 
151
                    if (requireRestart) {
 
152
                        postAllBatchHandler.target = root;
 
153
                    } else {
 
154
                        postClickBatchHandler.target = root;
 
155
                    }
 
156
                }
262
157
            }
263
 
            height: childrenRect.height
264
 
 
265
 
            ListItem.Base {
266
 
                id: checkForUpdatesArea
267
 
                objectName: "checkForUpdatesArea"
268
 
                showDivider: false
269
 
                visible: false
270
 
 
271
 
                ActivityIndicator {
272
 
                    id: activity
273
 
                    running: checkForUpdatesArea.visible
274
 
                    visible: activity.running
275
 
                    anchors {
276
 
                        left: parent.left
277
 
                        top: parent.top
278
 
                    }
279
 
                    height: parent.height
 
158
 
 
159
            Rectangle {
 
160
                id: overlay
 
161
                objectName: "overlay"
 
162
                anchors {
 
163
                    left: parent.left
 
164
                    leftMargin: units.gu(2)
 
165
                    right: parent.right
 
166
                    rightMargin: units.gu(2)
280
167
                }
 
168
                visible: placeholder.text
 
169
                color: theme.palette.normal.background
 
170
                height: units.gu(10)
281
171
 
282
172
                Label {
283
 
                    text: activity.running ? i18n.tr("Checking for updates…") : i18n.tr("Connect to the Internet to check for updates")
 
173
                    id: placeholder
 
174
                    objectName: "overlayText"
 
175
                    anchors.fill: parent
284
176
                    verticalAlignment: Text.AlignVCenter
285
 
                    wrapMode: Text.Wrap
286
 
                    anchors {
287
 
                        left: activity.running ? activity.right : parent.left
288
 
                        top: parent.top
289
 
                        right: parent.right
290
 
                        rightMargin: units.gu(2)
291
 
                        leftMargin: units.gu(2)
292
 
                    }
293
 
                    height: parent.height
294
 
                }
295
 
            }
296
 
 
297
 
            ListItem.SingleControl {
298
 
                height: installAllButton.visible ? units.gu(8) : units.gu(2)
299
 
                highlightWhenPressed: false
300
 
                control: Button {
301
 
                    id: installAllButton
302
 
                    objectName: "installAllButton"
303
 
                    property string primaryText: includeSystemUpdate ?
304
 
                                                     i18n.tr("Install %1 update…", "Install %1 updates…", root.updatesAvailable).arg(root.updatesAvailable) :
305
 
                                                     i18n.tr("Install %1 update", "Install %1 updates", root.updatesAvailable).arg(root.updatesAvailable)
306
 
                    property string secondaryText: i18n.tr("Pause All")
307
 
                    color: theme.palette.normal.positive
308
 
                    text: root.installAll ? secondaryText : primaryText
309
 
                    width: parent.width - units.gu(4)
310
 
 
311
 
                    onClicked: {
312
 
                        for (var i=0; i < updateList.count; i++) {
313
 
                            updateList.currentIndex = i;
314
 
                            var item = updateList.currentItem;
315
 
                            var modelItem = UpdateManager.model[i];
316
 
                            if (item.installing || item.installed)
317
 
                                continue;
318
 
                            console.warn("AllClicked: " + modelItem.updateState + " " + modelItem.updateReady + " " +  modelItem.selected);
319
 
                            if (item.retry) {
320
 
                                item.retry = false;
321
 
                                UpdateManager.retryDownload(modelItem.packageName);
322
 
                                continue;
323
 
                            }
324
 
                            if (root.installAll && !modelItem.updateReady && modelItem.selected) {
325
 
                                item.pause();
326
 
                                continue;
327
 
                            }
328
 
                            console.warn("Past pause");
329
 
                            if (!root.installAll && !modelItem.updateReady && modelItem.selected) {
330
 
                                item.resume();
331
 
                                continue;
332
 
                            }
333
 
                            console.warn("Past resume");
334
 
                            if (!root.installAll && !modelItem.updateState && !modelItem.updateReady && !modelItem.selected) {
335
 
                                item.start();
336
 
                                continue;
337
 
                            }
338
 
                            console.warn("Past start");
339
 
                        }
340
 
                        root.installAll = !root.installAll;
341
 
                    }
342
 
                }
343
 
                showDivider: false
344
 
            }
345
 
 
346
 
            ListView {
347
 
                id: updateList
348
 
                objectName: "updateList"
349
 
                anchors {
350
 
                    left: parent.left
351
 
                    right: parent.right
352
 
                }
353
 
                model: UpdateManager.model
354
 
                height: childrenRect.height
355
 
                interactive: false
356
 
                spacing: 0
357
 
 
358
 
                delegate: ListItem.Subtitled {
359
 
                    id: listItem
360
 
                    anchors {
361
 
                        left: parent.left
362
 
                        right: parent.right
363
 
                        topMargin: units.gu(1)
364
 
                        bottomMargin: units.gu(1)
365
 
                    }
366
 
                    iconSource: Qt.resolvedUrl(modelData.iconUrl)
367
 
                    iconFrame: modelData.systemUpdate ? false : true
368
 
                    height: visible ? textArea.height + units.gu(2) : 0
369
 
                    highlightWhenPressed: false
370
 
                    showDivider: false
371
 
                    visible: opacity > 0
372
 
                    opacity: installed ? 0 : 1
373
 
                    Behavior on opacity { PropertyAnimation { duration: UbuntuAnimation.SleepyDuration } }
374
 
 
375
 
                    property alias actionButton: buttonAppUpdate
376
 
                    property alias progressBar: progress
377
 
                    property bool installing: !modelData.systemUpdate && (modelData.updateReady || (progressBar.value === progressBar.maximumValue))
378
 
                    property bool installed: false
379
 
                    property bool retry: false
380
 
 
381
 
                    function pause () {
382
 
                        console.warn("PAUSE: " + modelData.packageName);
383
 
                        if (modelData.systemUpdate)
384
 
                            return UpdateManager.pauseDownload(modelData.packageName);
385
 
                        modelData.updateState = false;
386
 
                        tracker.pause();
387
 
                    }
388
 
 
389
 
                    function resume () {
390
 
                        console.warn("RESUME: " + modelData.packageName);
391
 
                        if (modelData.systemUpdate)
392
 
                            return UpdateManager.startDownload(modelData.packageName);
393
 
                        modelData.updateState = true;
394
 
                        tracker.resume();
395
 
                    }
396
 
 
397
 
                    function start () {
398
 
                        console.warn("START: " + modelData.packageName);
399
 
                        modelData.selected = true;
400
 
                        modelData.updateState = true;
401
 
                        UpdateManager.startDownload(modelData.packageName);
402
 
                    }
403
 
 
404
 
                    function forceDownload () {
405
 
                        console.warn("FORCE DOWNLOAD: " + modelData.packageName);
406
 
                        modelData.selected = true;
407
 
                        modelData.updateState = true;
408
 
                        UpdateManager.forceAllowGSMDownload(modelData.packageName);
409
 
                    }
410
 
 
411
 
                    Column {
412
 
                        id: textArea
413
 
                        objectName: "textArea"
414
 
                        anchors {
415
 
                            left: parent.left
416
 
                            right: parent.right
417
 
                        }
418
 
                        spacing: units.gu(0.5)
419
 
 
420
 
                        Item {
421
 
                            anchors {
422
 
                                left: parent.left
423
 
                                right: parent.right
424
 
                            }
425
 
                            height: buttonAppUpdate.height
426
 
 
427
 
                            Label {
428
 
                                id: labelTitle
429
 
                                objectName: "labelTitle"
430
 
                                anchors {
431
 
                                    left: parent.left
432
 
                                    right: buttonAppUpdate.visible ? buttonAppUpdate.left : parent.right
433
 
                                    verticalCenter: parent.verticalCenter
434
 
                                }
435
 
                                text: modelData.title
436
 
                                font.bold: true
437
 
                                elide: Text.ElideMiddle
438
 
                            }
439
 
 
440
 
                            Button {
441
 
                                id: buttonAppUpdate
442
 
                                objectName: "buttonAppUpdate"
443
 
                                anchors.right: parent.right
444
 
                                height: labelTitle.height + units.gu(1)
445
 
                                enabled: !installing
446
 
                                text: {
447
 
                                    if (retry)
448
 
                                        return i18n.tr("Retry");
449
 
                                    if (modelData.systemUpdate) {
450
 
                                        if (modelData.updateReady) {
451
 
                                            return i18n.tr("Install…");
452
 
                                        } else if ((!modelData.updateState && !modelData.selected) || modelData.status === Update.NotStarted) {
453
 
                                            return i18n.tr("Download");
454
 
                                        }
455
 
                                    }
456
 
                                    if (modelData.updateState || modelData.status === Update.Downloading) {
457
 
                                        return i18n.tr("Pause");
458
 
                                    } else if (modelData.selected) {
459
 
                                        return i18n.tr("Resume");
460
 
                                    }
461
 
                                    return i18n.tr("Update");
462
 
                                }
463
 
 
464
 
                                onClicked: {
465
 
                                    if (retry) {
466
 
                                        retry = false;
467
 
                                        return UpdateManager.retryDownload(modelData.packageName);
468
 
                                    }
469
 
                                    if (modelData.updateState)
470
 
                                        return pause();
471
 
                                    if (!modelData.updateState && modelData.selected)
472
 
                                        return resume();
473
 
                                    if (!modelData.updateState && !modelData.selected && !modelData.updateReady)
474
 
                                        return start();
475
 
                                    if (modelData.systemUpdate && modelData.status === Update.NotStarted)
476
 
                                        return forceDownload();
477
 
                                    if (modelData.updateReady)
478
 
                                        PopupUtils.open(dialogInstallComponent);
479
 
                                }
480
 
                            }
481
 
                        }
482
 
 
483
 
                        Item {
484
 
                            id: labelUpdateStatus
485
 
                            anchors {
486
 
                                left: parent.left
487
 
                                right: parent.right
488
 
                            }
489
 
                            height: childrenRect.height
490
 
                            visible: opacity > 0
491
 
                            opacity: (modelData.updateState && modelData.selected && !modelData.updateReady) || (installing || installed) ? 1 : 0
492
 
                            Behavior on opacity { PropertyAnimation { duration: UbuntuAnimation.SleepyDuration } }
493
 
                            Label {
494
 
                                objectName: "labelUpdateStatus"
495
 
                                anchors.left: parent.left
496
 
                                anchors.right: updateStatusLabel.left
497
 
                                elide: Text.ElideMiddle
498
 
                                fontSize: "small"
499
 
                                text: {
500
 
                                    if (retry)
501
 
                                        return modelData.error;
502
 
                                    if (installing)
503
 
                                        return i18n.tr("Installing");
504
 
                                    if (installed)
505
 
                                        return i18n.tr("Installed");
506
 
                                    return i18n.tr("Downloading");
507
 
                                }
508
 
                            }
509
 
                            Label {
510
 
                                id: updateStatusLabel
511
 
                                anchors.right: parent.right
512
 
                                visible: !labelSize.visible && !installing && !installed
513
 
                                fontSize: "small"
514
 
                                text: {
515
 
                                    if (!labelUpdateStatus.visible)
516
 
                                        return Utilities.formatSize(modelData.binaryFilesize);
517
 
 
518
 
                                    return i18n.tr("%1 of %2").arg(
519
 
                                        Utilities.formatSize(modelData.binaryFilesize * (progress.value * 0.01))).arg(
520
 
                                        Utilities.formatSize(modelData.binaryFilesize)
521
 
                                    );
522
 
                                }
523
 
                            }
524
 
                        }
525
 
 
526
 
                        ProgressBar {
527
 
                            id: progress
528
 
                            objectName: "progress"
529
 
                            height: units.gu(2)
530
 
                            anchors {
531
 
                                left: parent.left
532
 
                                right: parent.right
533
 
                            }
534
 
                            visible: opacity > 0
535
 
                            opacity: modelData.selected && !modelData.updateReady && !installed ? 1 : 0
536
 
                            value: modelData.systemUpdate ? modelData.downloadProgress : tracker.progress
537
 
                            minimumValue: 0
538
 
                            maximumValue: 100
539
 
 
540
 
                            DownloadTracker {
541
 
                                id: tracker
542
 
                                objectName: "tracker"
543
 
                                packageName: modelData.packageName
544
 
                                title: modelData.title
545
 
                                showInIndicator: false
546
 
                                clickToken: modelData.clickToken
547
 
                                download: modelData.downloadUrl
548
 
                                downloadSha512: modelData.downloadSha512
549
 
 
550
 
                                onFinished: {
551
 
                                    progress.visible = false;
552
 
                                    buttonAppUpdate.visible = false;
553
 
                                    installed = true;
554
 
                                    installing = false;
555
 
                                    root.updatesAvailable -= 1;
556
 
                                    modelData.updateRequired = false;
557
 
                                    UpdateManager.updateClickScope();
558
 
                                }
559
 
 
560
 
                                onProcessing: {
561
 
                                    console.warn("onProcessing: " + modelData.packageName + " " + path);
562
 
                                    buttonAppUpdate.enabled = false;
563
 
                                    installing = true;
564
 
                                    modelData.updateState = false;
565
 
                                }
566
 
 
567
 
                                onStarted: {
568
 
                                    console.warn("onStarted: " + modelData.packageName + " " + success);
569
 
                                    if (success)
570
 
                                        modelData.updateState = true;
571
 
                                    else
572
 
                                        modelData.updateState = false;
573
 
                                }
574
 
 
575
 
                                onPaused: {
576
 
                                    console.warn("onPaused: " + modelData.packageName + " " + success);
577
 
                                    if (success)
578
 
                                        modelData.updateState = false;
579
 
                                    else
580
 
                                        modelData.updateState = true;
581
 
                                }
582
 
 
583
 
                                onResumed: {
584
 
                                    console.warn("onResumed: " + modelData.packageName + " " + success);
585
 
                                    if (success)
586
 
                                        modelData.updateState = true;
587
 
                                    else
588
 
                                        modelData.updateState = false;
589
 
                                }
590
 
 
591
 
                                onCanceled: {
592
 
                                    console.warn("onCanceled: " + modelData.packageName + " " + success);
593
 
                                    if (success) {
594
 
                                        modelData.updateState = false;
595
 
                                        modelData.selected = false;
596
 
                                    }
597
 
                                }
598
 
 
599
 
                                onErrorFound: {
600
 
                                    console.warn("onErrorFound: " + modelData.packageName + " " + error);
601
 
                                    modelData.updateState = false;
602
 
                                    retry = true;
603
 
                                    installing = false;
604
 
                                }
605
 
                            }
606
 
 
607
 
                            Behavior on opacity { PropertyAnimation { duration: UbuntuAnimation.SleepyDuration } }
608
 
                        }
609
 
 
610
 
                        Item {
611
 
                            anchors {
612
 
                                left: parent.left
613
 
                                right: parent.right
614
 
                            }
615
 
                            height: childrenRect.height
616
 
                            Label {
617
 
                                id: labelVersion
618
 
                                objectName: "labelVersion"
619
 
                                anchors.left: parent.left
620
 
                                text: modelData.remoteVersion ? i18n.tr("Version: ") + modelData.remoteVersion : ""
621
 
                                elide: Text.ElideRight
622
 
                                fontSize: "small"
623
 
                            }
624
 
 
625
 
                            Label {
626
 
                                id: labelSize
627
 
                                objectName: "labelSize"
628
 
                                anchors.right: parent.right
629
 
                                text: Utilities.formatSize(modelData.binaryFilesize)
630
 
                                fontSize: "small"
631
 
                                visible: !labelUpdateStatus.visible && !installing && !installed
632
 
                            }
633
 
                        }
634
 
                    }
635
 
                }
636
 
            }
637
 
 
638
 
            Column {
639
 
                id: credentialsNotification
640
 
                objectName: "credentialsNotification"
641
 
 
642
 
                visible: false
643
 
 
644
 
                spacing: units.gu(2)
645
 
                anchors {
646
 
                    left: parent.left
647
 
                    right: parent.right
648
 
                }
649
 
                ListItem.ThinDivider {}
650
 
 
651
 
                Label {
652
 
                    text: i18n.tr("Sign in to Ubuntu One to receive updates for apps.")
653
177
                    horizontalAlignment: Text.AlignHCenter
654
 
                    wrapMode: Text.Wrap
655
 
                    anchors {
656
 
                        left: parent.left
657
 
                        right: parent.right
658
 
                    }
659
 
                }
660
 
                Button {
661
 
                    text: i18n.tr("Sign In…")
662
 
                    anchors {
663
 
                        left: parent.left
664
 
                        right: parent.right
665
 
                        leftMargin: units.gu(2)
666
 
                        rightMargin: units.gu(2)
667
 
                    }
668
 
                    onClicked: uoaConfig.exec()
669
 
                }
670
 
 
671
 
            }
672
 
        }
673
 
    }
674
 
 
675
 
    Rectangle {
676
 
        id: updateNotification
677
 
        objectName: "updateNotification"
678
 
        anchors {
679
 
            bottom: configuration.top
680
 
            left: parent.left
681
 
            right: parent.right
682
 
            top: parent.top
683
 
        }
684
 
        visible: false
685
 
        property string text: ""
686
 
 
687
 
        color: "transparent"
688
 
 
689
 
        Label {
690
 
            anchors.centerIn: updateNotification
691
 
            text: updateNotification.text
692
 
            width: updateNotification.width
693
 
            horizontalAlignment: Text.AlignHCenter
694
 
            wrapMode: Text.Wrap
695
 
        }
696
 
    }
697
 
 
698
 
    Rectangle {
699
 
        id: installingImageUpdate
700
 
        objectName: "installingImageUpdate"
701
 
        anchors.fill: root
702
 
        visible: false
703
 
        z: 10
704
 
        color: "#221e1c"
705
 
        property string message: i18n.tr("Installing update…")
706
 
 
707
 
        Column {
708
 
            anchors.centerIn: parent
709
 
            spacing: units.gu(2)
710
 
 
711
 
            Image {
712
 
                source: Qt.resolvedUrl("file:///usr/share/icons/suru/places/scalable/distributor-logo.svg")
713
 
                anchors.horizontalCenter: parent.horizontalCenter
714
 
                height: width
715
 
                width: 96
716
 
                NumberAnimation on rotation {
717
 
                    from: 0
718
 
                    to: 360
719
 
                    running: installingImageUpdate.visible == true
720
 
                    loops: Animation.Infinite
721
 
                    duration: 2000
722
 
                }
723
 
            }
724
 
 
725
 
            ProgressBar {
726
 
                indeterminate: true
727
 
                anchors.horizontalCenter: parent.horizontalCenter
728
 
            }
729
 
 
730
 
            Label {
731
 
                text: installingImageUpdate.message
732
 
                anchors.horizontalCenter: parent.horizontalCenter
733
 
            }
734
 
        }
735
 
    }
 
178
                    wrapMode: Text.WordWrap
 
179
                    text: {
 
180
                        var s = UpdateManager.status;
 
181
                        if (!root.online) {
 
182
                            return i18n.tr("Connect to the Internet to check for updates.");
 
183
                        } else if (s === UpdateManager.StatusIdle && updatesCount === 0) {
 
184
                            return i18n.tr("Software is up to date");
 
185
                        } else if (s === UpdateManager.StatusServerError ||
 
186
                                   s === UpdateManager.StatusNetworkError) {
 
187
                            return i18n.tr("The update server is not responding. Try again later.");
 
188
                        }
 
189
                        return "";
 
190
                    }
 
191
                }
 
192
            }
 
193
 
 
194
            SettingsItemTitle {
 
195
                id: updatesAvailableHeader
 
196
                text: i18n.tr("Updates Available")
 
197
                visible: imageUpdateCol.visible || clickUpdatesCol.visible
 
198
            }
 
199
 
 
200
            Column {
 
201
                id: imageUpdateCol
 
202
                objectName: "imageUpdates"
 
203
                anchors { left: parent.left; right: parent.right }
 
204
                visible: {
 
205
                    var s = UpdateManager.status;
 
206
                    var haveUpdates = imageRepeater.count > 0;
 
207
                    switch (s) {
 
208
                    case UpdateManager.StatusCheckingClickUpdates:
 
209
                    case UpdateManager.StatusIdle:
 
210
                        return haveUpdates && online;
 
211
                    }
 
212
                    return false;
 
213
                }
 
214
 
 
215
                Repeater {
 
216
                    id: imageRepeater
 
217
                    model: UpdateManager.imageUpdates
 
218
 
 
219
                    delegate: UpdateDelegate {
 
220
                        objectName: "imageUpdatesDelegate-" + index
 
221
                        width: imageUpdateCol.width
 
222
                        updateState: model.updateState
 
223
                        progress: model.progress
 
224
                        version: SystemImage.versionTag ?
 
225
                                 SystemImage.versionTag : remoteVersion
 
226
                        size: model.size
 
227
                        changelog: model.changelog
 
228
                        error: model.error
 
229
                        kind: model.kind
 
230
                        iconUrl: model.iconUrl
 
231
                        name: title
 
232
 
 
233
                        onResume: download()
 
234
                        onRetry: download()
 
235
                        onDownload: {
 
236
                            if (SystemImage.downloadMode < 2) {
 
237
                                SystemImage.downloadUpdate();
 
238
                                SystemImage.forceAllowGSMDownload();
 
239
                            } else {
 
240
                                SystemImage.downloadUpdate();
 
241
                            }
 
242
                        }
 
243
                        onPause: SystemImage.pauseDownload();
 
244
                        onInstall: {
 
245
                            var popup = PopupUtils.open(
 
246
                                Qt.resolvedUrl("ImageUpdatePrompt.qml"), null, {
 
247
                                    havePowerForUpdate: root.havePower
 
248
                                }
 
249
                            );
 
250
                            popup.requestSystemUpdate.connect(SystemImage.applyUpdate);
 
251
                        }
 
252
                    }
 
253
                }
 
254
            }
 
255
 
 
256
            Column {
 
257
                id: clickUpdatesCol
 
258
                objectName: "clickUpdates"
 
259
                anchors { left: parent.left; right: parent.right }
 
260
                visible: {
 
261
                    var s = UpdateManager.status;
 
262
                    var haveUpdates = clickRepeater.count > 0;
 
263
                    switch (s) {
 
264
                    case UpdateManager.StatusCheckingImageUpdates:
 
265
                    case UpdateManager.StatusIdle:
 
266
                        return haveUpdates && online && authenticated;
 
267
                    }
 
268
                    return false;
 
269
                }
 
270
 
 
271
                Repeater {
 
272
                    id: clickRepeater
 
273
                    model: UpdateManager.clickUpdates
 
274
 
 
275
                    delegate: ClickUpdateDelegate {
 
276
                        objectName: "clickUpdatesDelegate" + index
 
277
                        width: clickUpdatesCol.width
 
278
                        updateState: model.updateState
 
279
                        progress: model.progress
 
280
                        version: remoteVersion
 
281
                        size: model.size
 
282
                        name: title
 
283
                        iconUrl: model.iconUrl
 
284
                        kind: model.kind
 
285
                        changelog: model.changelog
 
286
                        error: model.error
 
287
                        signedUrl: signedDownloadUrl
 
288
 
 
289
                        onInstall: downloadHandler.createDownload(model);
 
290
                        onPause: downloadHandler.pauseDownload(model)
 
291
                        onResume: downloadHandler.resumeDownload(model)
 
292
                        onRetry: {
 
293
                            /* This creates a new signed URL with which we can
 
294
                            retry the download. See onSignedUrlChanged. */
 
295
                            UpdateManager.retry(model.identifier,
 
296
                                               model.revision);
 
297
                        }
 
298
 
 
299
                        onSignedUrlChanged: {
 
300
                            // If we have a signedUrl, user intend to retry.
 
301
                            if (signedUrl) {
 
302
                                downloadHandler.retryDownload(model);
 
303
                            }
 
304
                        }
 
305
 
 
306
                        Connections {
 
307
                            target: glob
 
308
                            onInstall: install()
 
309
                        }
 
310
 
 
311
                        /* If we a downloadId, we expect UDM to restore it
 
312
                        after some time. Workaround for lp:1603770. */
 
313
                        Timer {
 
314
                            id: downloadTimeout
 
315
                            interval: 30000
 
316
                            running: true
 
317
                            onTriggered: {
 
318
                                var s = updateState;
 
319
                                if (model.downloadId
 
320
                                    || s === Update.StateQueuedForDownload
 
321
                                    || s === Update.StateDownloading) {
 
322
                                    downloadHandler.assertDownloadExist(model);
 
323
                                }
 
324
                            }
 
325
                        }
 
326
                    }
 
327
                }
 
328
            }
 
329
 
 
330
            NotAuthenticatedNotification {
 
331
                id: notauthNotification
 
332
                objectName: "noAuthenticationNotification"
 
333
                visible: {
 
334
                    var s = UpdateManager.status;
 
335
                    switch (s) {
 
336
                    case UpdateManager.StatusCheckingImageUpdates:
 
337
                    case UpdateManager.StatusIdle:
 
338
                        return !authenticated && online;
 
339
                    }
 
340
                    return false;
 
341
                }
 
342
                anchors {
 
343
                    left: parent.left
 
344
                    right: parent.right
 
345
                }
 
346
                onRequestAuthentication: uoaConfig.exec()
 
347
            }
 
348
 
 
349
            SettingsItemTitle {
 
350
                text: i18n.tr("Recent updates")
 
351
                visible: installedCol.visible
 
352
            }
 
353
 
 
354
            Column {
 
355
                id: installedCol
 
356
                objectName: "installedUpdates"
 
357
                anchors { left: parent.left; right: parent.right }
 
358
                visible: installedRepeater.count > 0
 
359
 
 
360
                Repeater {
 
361
                    id: installedRepeater
 
362
                    model: UpdateManager.installedUpdates
 
363
 
 
364
                    delegate: UpdateDelegate {
 
365
                        objectName: "installedUpdateDelegate-" + index
 
366
                        width: installedCol.width
 
367
                        version: remoteVersion
 
368
                        size: model.size
 
369
                        name: title
 
370
                        kind: model.kind
 
371
                        iconUrl: model.iconUrl
 
372
                        changelog: model.changelog
 
373
                        updateState: Update.StateInstalled
 
374
                        updatedAt: model.updatedAt
 
375
 
 
376
                        leadingActions: ListItemActions {
 
377
                           actions: [
 
378
                               Action {
 
379
                                    iconName: "delete"
 
380
                                    onTriggered: UpdateManager.remove(
 
381
                                        model.identifier, model.revision
 
382
                                    )
 
383
                               }
 
384
                           ]
 
385
                        }
 
386
 
 
387
                        // Launchable if there's a package name on a click.
 
388
                        launchable: (!!packageName &&
 
389
                                     model.kind === Update.KindClick)
 
390
 
 
391
                        onLaunch: UpdateManager.launch(identifier, revision);
 
392
                    }
 
393
                }
 
394
            }
 
395
        } // Column inside flickable.
 
396
    } // Flickable
736
397
 
737
398
    Column {
738
399
        id: configuration
739
400
 
740
 
        anchors.bottom: parent.bottom
741
 
        anchors.left: parent.left
742
 
        anchors.right: parent.right
 
401
        height: childrenRect.height
 
402
 
 
403
        anchors {
 
404
            bottom: parent.bottom
 
405
            left: parent.left
 
406
            right: parent.right
 
407
        }
 
408
 
743
409
        ListItem.ThinDivider {}
 
410
 
744
411
        ListItem.SingleValue {
745
412
            objectName: "configuration"
746
413
            text: i18n.tr("Auto download")
747
414
            value: {
748
 
                if (UpdateManager.downloadMode === 0)
 
415
                if (SystemImage.downloadMode === 0)
749
416
                    return i18n.tr("Never")
750
 
                else if (UpdateManager.downloadMode === 1)
 
417
                else if (SystemImage.downloadMode === 1)
751
418
                    return i18n.tr("On wi-fi")
752
 
                else if (UpdateManager.downloadMode === 2)
 
419
                else if (SystemImage.downloadMode === 2)
753
420
                    return i18n.tr("Always")
 
421
                else
 
422
                    return i18n.tr("Unknown")
754
423
            }
755
424
            progression: true
756
425
            onClicked: pageStack.push(Qt.resolvedUrl("Configuration.qml"))
757
426
        }
758
427
    }
 
428
 
 
429
    Connections {
 
430
        id: postClickBatchHandler
 
431
        ignoreUnknownSignals: true
 
432
        target: null
 
433
        onUpdatesCountChanged: {
 
434
            if (target.updatesCount === 0) {
 
435
                root.batchMode = false;
 
436
                target = null;
 
437
            }
 
438
        }
 
439
    }
 
440
 
 
441
    Connections {
 
442
        id: postAllBatchHandler
 
443
        ignoreUnknownSignals: true
 
444
        target: null
 
445
        onUpdatesCountChanged: {
 
446
            if (target.updatesCount === 1) {
 
447
                SystemImage.updateDownloaded.connect(function () {
 
448
                    SystemImage.applyUpdate();
 
449
                });
 
450
                SystemImage.downloadUpdate();
 
451
            }
 
452
        }
 
453
    }
 
454
 
 
455
    Connections {
 
456
        target: NetworkingStatus
 
457
        onOnlineChanged: {
 
458
            if (!online) {
 
459
                UpdateManager.cancel();
 
460
            } else {
 
461
                UpdateManager.check(UpdateManager.CheckAll);
 
462
            }
 
463
        }
 
464
    }
 
465
 
 
466
    Connections {
 
467
        target: SystemImage
 
468
        onUpdateFailed: {
 
469
            if (consecutiveFailureCount > SystemImage.failuresBeforeWarning) {
 
470
                var popup = PopupUtils.open(
 
471
                    Qt.resolvedUrl("InstallationFailed.qml"), null, {
 
472
                        text: lastReason
 
473
                    }
 
474
                );
 
475
            }
 
476
        }
 
477
    }
 
478
 
 
479
    Component.onCompleted: check()
759
480
}