Warning, /system/plasma-pk-updates/src/plasma/contents/ui/Full.qml is written in an unsupported language. File is not indexed.

0001 /***************************************************************************
0002  *   Copyright (C) 2013 by Aleix Pol Gonzalez <aleixpol@blue-systems.com>  *
0003  *   Copyright (C) 2015 by Lukáš Tinkl <lukas@kde.org>                     *
0004  *   Copyright (C) 2015 by Jan Grulich <jgrulich@redhat.com>               *
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  *   This program is distributed in the hope that it will be useful,       *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0014  *   GNU General Public License for more details.                          *
0015  *                                                                         *
0016  *   You should have received a copy of the GNU General Public License     *
0017  *   along with this program; if not, write to the                         *
0018  *   Free Software Foundation, Inc.,                                       *
0019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0020  ***************************************************************************/
0021 
0022 import QtQuick 2.15
0023 import QtQuick.Layouts 1.1
0024 import QtQuick.Controls 2.5 as QQC2
0025 import QtQuick.Dialogs 1.2
0026 import org.kde.plasma.components 3.0 as PlasmaComponents3
0027 import org.kde.plasma.extras 2.0 as PlasmaExtras
0028 import org.kde.plasma.core 2.0 as PlasmaCore
0029 import org.kde.plasma.PackageKit 1.0
0030 
0031 Item {
0032     id: fullRepresentation
0033 
0034     property bool anySelected: false
0035     property bool allSelected: false
0036     property bool populatePreSelected: true
0037 
0038     width: units.gridUnit * 20
0039     height: units.gridUnit * 20
0040 
0041     Binding {
0042         target: timestampLabel
0043         property: "text"
0044         value: PkUpdates.timestamp
0045         when: !plasmoid.expanded
0046     }
0047 
0048     Connections {
0049         target: PkUpdates
0050         onUpdatesChanged: populateModel()
0051         onUpdateDetail: updateDetails(packageID, updateText, urls)
0052         onUpdatesInstalled: plasmoid.expanded = false
0053         onEulaRequired: eulaDialog.showPrompt(eulaID, packageID, vendor, licenseAgreement)
0054     }
0055 
0056     Component.onCompleted: populateModel()
0057 
0058     Dialog {
0059         property string eulaID: ""
0060         property string packageName: ""
0061         property string vendor: ""
0062         property string licenseText: ""
0063 
0064         property bool buttonClicked: false
0065 
0066         id: eulaDialog
0067         title: i18n("License Agreement for %1").arg(packageName)
0068         standardButtons: StandardButton.Yes | StandardButton.No
0069 
0070         ColumnLayout {
0071             anchors.fill: parent
0072 
0073             QQC2.Label {
0074                 text: i18n("License agreement required for %1 (from %2):").arg(eulaDialog.packageName).arg(eulaDialog.vendor)
0075             }
0076 
0077             QQC2.ScrollView {
0078                 Layout.fillWidth: true
0079                 Layout.fillHeight: true
0080                 // The Dialog uses the implicit size as minimum,
0081                 // so this doesn't have much effect...
0082                 Layout.minimumWidth: 400
0083                 Layout.minimumHeight: 200
0084 
0085                 Layout.preferredWidth: 600
0086                 Layout.preferredHeight: 500
0087 
0088                 // Work around that TextArea does not redraw
0089                 // when the visible area changes after resizing.
0090                 onHeightChanged: licenseArea.update()
0091                 onWidthChanged: licenseArea.update()
0092 
0093                 QQC2.TextArea {
0094                     id: licenseArea
0095                     text: eulaDialog.licenseText
0096                     readOnly: true
0097                 }
0098             }
0099 
0100             QQC2.Label {
0101                 text: i18n("Do you accept?")
0102             }
0103         }
0104 
0105         onVisibleChanged: {
0106             // onRejected does not fire on dialog closing, so implement that ourselves
0107             if(!visible && !buttonClicked)
0108                 onNo();
0109         }
0110         onNo: {
0111             buttonClicked = true;
0112             PkUpdates.eulaAgreementResult(this.eulaID, false);
0113         }
0114         onYes: {
0115             buttonClicked = true;
0116             PkUpdates.eulaAgreementResult(this.eulaID, true);
0117         }
0118 
0119         function showPrompt(eulaID, packageID, vendor, licenseAgreement) {
0120             this.eulaID = eulaID;
0121             this.packageName = PkUpdates.packageName(packageID);
0122             this.vendor = vendor;
0123             this.licenseText = licenseAgreement;
0124 
0125             this.visible = true;
0126         }
0127     }
0128 
0129     ListModel {
0130         id: updatesModel
0131     }
0132 
0133 
0134     ColumnLayout {
0135         id: statusbar
0136 
0137         anchors.fill: parent
0138 
0139         spacing: units.smallSpacing
0140 
0141         PlasmaExtras.Heading {
0142             Layout.fillWidth: true
0143             level: 4
0144             wrapMode: Text.WordWrap
0145             text: !PkUpdates.isNetworkOnline ? i18n("Network is offline") : PkUpdates.message
0146         }
0147 
0148         PlasmaComponents3.Label {
0149             visible: PkUpdates.isActive || PkUpdates.count === 0
0150             font.pointSize: theme.smallestFont.pointSize;
0151             opacity: 0.6;
0152             text: {
0153                 if (PkUpdates.isActive)
0154                     return PkUpdates.statusMessage
0155                 else if (PkUpdates.isNetworkOnline)
0156                     return i18n("Updates are automatically checked %1.",
0157                                 updateInterval(plasmoid.configuration.daily,
0158                                                plasmoid.configuration.weekly,
0159                                                plasmoid.configuration.monthly));
0160                 return ""
0161             }
0162             Layout.fillWidth: true
0163             wrapMode: Text.WordWrap
0164         }
0165 
0166         PlasmaComponents3.Label {
0167             id: timestampLabel
0168             Layout.fillWidth: true
0169             visible: !PkUpdates.isActive
0170             wrapMode: Text.WordWrap
0171             font.italic: true
0172             font.pointSize: theme.smallestFont.pointSize;
0173             opacity: 0.6;
0174             text: PkUpdates.timestamp
0175         }
0176 
0177         PlasmaComponents3.ProgressBar {
0178             Layout.fillWidth: true
0179             visible: PkUpdates.isActive
0180             from: 0
0181             to: 101 // BUG workaround a bug in ProgressBar! if the value is > max, it's set to max and never changes below
0182             value: PkUpdates.percentage
0183             indeterminate: PkUpdates.percentage > 100
0184         }
0185 
0186         PlasmaExtras.ScrollArea {
0187             id: listViewScrollArea
0188 
0189             Layout.fillWidth: true
0190             Layout.fillHeight: true
0191 
0192             visible: PkUpdates.count && PkUpdates.isNetworkOnline && !PkUpdates.isActive
0193 
0194             ListView {
0195                 id: updatesView
0196 
0197                 reuseItems: true
0198                 clip: true
0199                 model: PlasmaCore.SortFilterModel {
0200                     sourceModel: updatesModel
0201                     filterRole: "name"
0202                 }
0203                 anchors.fill: parent
0204                 currentIndex: -1
0205                 property int lastIndex: -1
0206                 boundsBehavior: Flickable.StopAtBounds
0207                 delegate: PackageDelegate {
0208                     onClicked: {
0209                         if (updatesView.lastIndex == updatesView.currentIndex) {
0210                             // Unselect as current
0211                             updatesView.currentIndex = -1
0212                         } else {
0213                             // Expand, load details
0214                             PkUpdates.getUpdateDetails(id)
0215                         }
0216                         updatesView.lastIndex = updatesView.currentIndex
0217                     }
0218                     onCheckStateChanged: updateSelectionState();
0219                 }
0220             }
0221         }
0222 
0223         // Container for other items that can be shown when the main scroll
0224         // view is not visible
0225         Item {
0226             Layout.fillWidth: true
0227             Layout.fillHeight: true
0228 
0229             visible: !listViewScrollArea.visible
0230 
0231             PlasmaComponents3.BusyIndicator {
0232                 running: PkUpdates.isActive && PkUpdates.count == 0
0233                 visible: running
0234                 anchors.centerIn: parent
0235             }
0236 
0237             PlasmaExtras.PlaceholderMessage {
0238                 anchors.centerIn: parent
0239                 width: parent.width - (units.largeSpacing * 4)
0240 
0241                 visible: PkUpdates.count === 0 && PkUpdates.isNetworkOnline && !PkUpdates.isActive
0242 
0243                 text: PkUpdates.lastCheckSuccessful ? i18n("No updates available") : ""
0244 
0245                 helpfulAction: QQC2.Action {
0246                     icon.name: "view-refresh"
0247                     text: i18n("Check for Updates")
0248                     onTriggered: {
0249                         PkUpdates.checkUpdates(true /* manual */) // circumvent the checks, the user knows what they're doing ;)
0250                     }
0251                 }
0252             }
0253         }
0254 
0255         PlasmaComponents3.CheckBox {
0256             Layout.fillWidth: true
0257             Layout.leftMargin: units.smallSpacing
0258 
0259             visible: PkUpdates.count !== 0 && PkUpdates.isNetworkOnline && !PkUpdates.isActive
0260 
0261             tristate: true
0262 
0263             checkState: fullRepresentation.allSelected ? Qt.Checked :
0264                         (fullRepresentation.anySelected ? Qt.PartiallyChecked
0265                                                         : Qt.Unchecked)
0266 
0267             text: i18n("Select all packages")
0268 
0269             onClicked: {
0270                 populatePreSelected = !fullRepresentation.anySelected;
0271                 populateModel();
0272             }
0273         }
0274 
0275         PlasmaComponents3.Button {
0276             visible: PkUpdates.count !== 0 && PkUpdates.isNetworkOnline && !PkUpdates.isActive
0277             icon.name: "install"
0278             enabled: fullRepresentation.anySelected
0279             Layout.alignment: Qt.AlignHCenter
0280             text: i18n("Install Updates")
0281             onClicked: PkUpdates.installUpdates(selectedPackages())
0282 
0283             PlasmaComponents3.ToolTip {
0284                 text: i18n("Performs the software update")
0285             }
0286         }
0287     }
0288 
0289     function updateSelectionState() {
0290         console.log("Updating state of selection");
0291         var anySelected = false;
0292         var allSelected = true;
0293         for (var i = 0; i < updatesModel.count; i++) {
0294             var pkg = updatesModel.get(i)
0295             if (pkg.selected)
0296                 anySelected = true;
0297             else
0298                 allSelected = false;
0299 
0300             if (anySelected && !allSelected)
0301                 break; // Can't change anymore
0302         }
0303         fullRepresentation.anySelected = anySelected;
0304         fullRepresentation.allSelected = allSelected;
0305     }
0306 
0307     function selectedPackages() {
0308         var result = []
0309         for (var i = 0; i < updatesModel.count; i++) {
0310             var pkg = updatesModel.get(i)
0311             if (pkg.selected) {
0312                 print("Package " + pkg.id + " selected for update")
0313                 result.push(pkg.id)
0314             }
0315         }
0316         return result
0317     }
0318 
0319     function populateModel() {
0320         print("Populating model")
0321         updatesModel.clear()
0322         var packages = PkUpdates.packages
0323         for (var id in packages) {
0324             if (packages.hasOwnProperty(id)) {
0325                 var desc = packages[id]
0326                 updatesModel.append({"selected": populatePreSelected, "id": id, "name": PkUpdates.packageName(id), "desc": desc, "version": PkUpdates.packageVersion(id)})
0327             }
0328         }
0329         updateSelectionState();
0330     }
0331 
0332     function updateDetails(packageID, updateText, urls) {
0333         //print("Got update details for: " + packageID)
0334         print("Update text: " + updateText)
0335         print("URLs: " + urls)
0336         updatesView.currentItem.updateText = updateText
0337         updatesView.currentItem.updateUrls = urls
0338     }
0339 
0340     function updateInterval(daily, weekly, monthly) {
0341         if (weekly)
0342             return i18n("weekly");
0343         else if (monthly)
0344             return i18n("monthly");
0345 
0346         return i18n("daily");
0347     }
0348 }