Warning, /education/gcompris/src/core/DownloadDialog.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - DownloadDialog.qml
0002  *
0003  * SPDX-FileCopyrightText: 2014 Holger Kaelberer <holger.k@elberer.de>
0004  *
0005  * Authors:
0006  *   Holger Kaelberer <holger.k@elberer.de>
0007  *
0008  *   SPDX-License-Identifier: GPL-3.0-or-later
0009  */
0010 import QtQuick 2.12
0011 import GCompris 1.0
0012 import QtQuick.Layouts 1.12
0013 import QtQuick.Controls 2.12
0014 import "qrc:/gcompris/src/core/core.js" as Core
0015 
0016 /**
0017  * A QML component visualizing download progress.
0018  * @ingroup infrastructure
0019  *
0020  * A GCDialog style dialog providing visual feedback for download progress.
0021  * Uses DownloadManager for download control.
0022  *
0023  * Can be conveniently instantiated dynamically using showDownloadDialog
0024  * from core.js.
0025  *
0026  * @inherit QtQuick.Item
0027  * @sa DownloadManager, showDownloadDialog
0028  */
0029 Item {
0030     id: downloadDialog
0031     opacity: 0
0032 
0033     anchors {
0034         fill: parent
0035     }
0036 
0037     /**
0038      * type:Item
0039      * Parent object for the dialog in the qml hierarchy.
0040      */
0041     property Item main
0042 
0043     /**
0044      * type:bool
0045      * Whether to close the dialog automatically when download has finished.
0046      * Default is false.
0047      */
0048     property bool autohide: false;
0049 
0050     /**
0051      * type:bool
0052      * Whether to report download success in a Dialog.
0053      * Default is true.
0054      */
0055     property bool reportSuccess: true;
0056 
0057     /**
0058      * type:bool
0059      * Whether to report download errors in a Dialog.
0060      * Default is true.
0061      */
0062     property bool reportError: true;
0063 
0064     /**
0065      * type:bool
0066      * Whether a message has been displayed
0067      * we don't want to display several dialogs
0068      */
0069     property bool messageDisplayed: false;
0070 
0071     /**
0072      * type:GCDialog
0073      * The dialog displaying the result message
0074      */
0075     property var messageDialog: undefined;
0076 
0077     /**
0078      * type:bool
0079      * Whether the dialog has been created dynamically. If set to true, the
0080      * component takes care of destroying itself after finished.
0081      * Default is false.
0082      *
0083      * @sa Core.destroyDialog
0084      */
0085     property bool dynamic: false
0086 
0087     /**
0088      * type:bool
0089      * Whether the 'Background' button should be visible.
0090      * Default is true.
0091      */
0092     property alias backgroundButtonVisible: backgroundButton.visible
0093 
0094     /**
0095      * type:bool
0096      * Whether the 'Abort' button should be visible.
0097      * Default is true.
0098      */
0099     property alias abortButtonVisible: abortButton.visible
0100 
0101     /**
0102      * type:bool
0103      * Fixed font size used in this dialog. Note, fixed font-sizes should be
0104      * used in dialog components, to make sure they stay within bounds when
0105      * user increases font size.
0106      * Default is 14.
0107      */
0108     property int fixedFontSize: 14
0109 
0110     /// @cond INTERNAL_DOCS
0111 
0112     // start and stop trigs the animation FIXME: need to document?
0113     signal start
0114     signal stop
0115 
0116     // emitted at stop animation end
0117     signal close
0118 
0119     signal finished
0120 
0121     focus: true
0122 
0123     //We need a timer to properly get focus on this dialog and its children dialogs
0124     Timer {
0125         id: getFocusTimer
0126         interval: 250
0127         onTriggered: {
0128             if(!messageDisplayed) {
0129                 downloadDialog.forceActiveFocus();
0130                 downloadDialog.parent.Keys.enabled = false;
0131             } else {
0132                 messageDialog.forceActiveFocus();
0133                 downloadDialog.parent.Keys.enabled = false;
0134             }
0135         }
0136     }
0137 
0138     onVisibleChanged: {
0139         if(visible) {
0140             getFocusTimer.restart();
0141         }
0142     }
0143     onStart: {
0144         opacity = 1;
0145         getFocusTimer.restart();
0146     }
0147     onStop: {
0148         opacity = 0;
0149         parent.Keys.enabled = true;
0150         parent.forceActiveFocus();
0151     }
0152     onClose: {
0153         destroy();
0154         parent.Keys.enabled = true;
0155         parent.forceActiveFocus();
0156     }
0157 
0158     Behavior on opacity { NumberAnimation { duration: 200 } }
0159     onOpacityChanged: opacity === 0 ? close() : null
0160 
0161     function shutdown()
0162     {
0163         if (downloadDialog.dynamic)
0164             Core.destroyDialog(downloadDialog);
0165         else
0166             downloadDialog.close();
0167     }
0168 
0169     /// @endcond
0170 
0171     Rectangle {
0172         anchors.fill: parent
0173         opacity: 0.8
0174         color: "grey"
0175 
0176         MouseArea {
0177             // Empty mouseArea to prevent clicking "behind" the Dialog
0178             anchors.fill: parent
0179             enabled: downloadDialog.opacity != 0
0180         }
0181     }
0182 
0183     Item {
0184         id: instruction
0185         anchors {
0186             horizontalCenter: parent.horizontalCenter
0187             top: parent.top
0188             topMargin: parent.height * 0.1
0189         }
0190         width: parent.width * 0.8
0191 
0192         GCText {
0193             id: instructionTxt
0194             fontSize: mediumSize
0195             color: "black"
0196             horizontalAlignment: Text.AlignHCenter
0197             width: parent.width
0198             wrapMode: TextEdit.WordWrap
0199             z: 2
0200             height: 60 * ApplicationInfo.ratio
0201             text: qsTr("Downloading...")
0202         }
0203 
0204         Rectangle {
0205             anchors.fill: instructionTxt
0206             z: 1
0207             opacity: 0.9
0208             radius: 10
0209             border.width: 2
0210             border.color: "white"
0211             gradient: Gradient {
0212                 GradientStop { position: 0.0; color: "#fff" }
0213                 GradientStop { position: 0.9; color: "#fff" }
0214                 GradientStop { position: 1.0; color: "#ddd" }
0215             }
0216         }
0217 
0218         ProgressBar {
0219             id: downloadDialogProgress
0220             width: parent.width
0221             anchors {
0222                 horizontalCenter: parent.horizontalCenter
0223                 top: instructionTxt.bottom
0224                 topMargin: 10
0225             }
0226             visible: true
0227             Layout.alignment: Qt.AlignHCenter
0228             Layout.rowSpan: 1
0229             Layout.fillWidth: true
0230             from: 0
0231             to: 100
0232             value: 0
0233         }
0234 
0235         Rectangle {
0236             id: buttonSelector
0237             width: 0
0238             height: 0
0239             color: "#803ACAFF"
0240             scale: 1.1
0241         }
0242 
0243         GCButton {
0244             id: backgroundButton
0245             width: parent.width
0246             height: 60 * ApplicationInfo.ratio
0247             anchors {
0248                 horizontalCenter: parent.horizontalCenter
0249                 top: downloadDialogProgress.bottom
0250                 topMargin: 10
0251             }
0252             //: Run this task in background
0253             text: qsTr("Background")
0254             fixedFontSize: downloadDialog.fixedFontSize
0255             theme: "highContrast"
0256             visible: true
0257             property bool selected: false;
0258             onClicked: downloadDialog.shutdown();
0259         }
0260 
0261         GCButton {
0262             id: abortButton
0263             width: parent.width
0264             height: 60 * ApplicationInfo.ratio
0265             anchors {
0266                 horizontalCenter: parent.horizontalCenter
0267                 top: backgroundButton.bottom
0268                 topMargin: 10
0269             }
0270             text: qsTr("Abort")
0271             fixedFontSize: downloadDialog.fixedFontSize
0272             theme: "highContrast"
0273 
0274             visible: true
0275             property bool selected: false;
0276             onClicked: {
0277                 if (DownloadManager.downloadIsRunning())
0278                     DownloadManager.abortDownloads();
0279                 downloadDialog.finished();
0280                 downloadDialog.shutdown();
0281             }
0282         }
0283 
0284         states: [
0285             State {
0286                 name: "button1Selected"
0287                 when: backgroundButton.selected
0288                 PropertyChanges {
0289                     target: buttonSelector
0290                     anchors.fill: backgroundButton
0291                 }
0292             },
0293             State {
0294                 name: "button2Selected"
0295                 when: abortButton.selected
0296                 PropertyChanges {
0297                     target: buttonSelector
0298                     anchors.fill: abortButton
0299                 }
0300             }
0301         ]
0302     }
0303 
0304     Keys.onEscapePressed: {
0305         if(backgroundButtonVisible)
0306             backgroundButton.clicked();
0307         else if(abortButtonVisible)
0308             abortButton.clicked();
0309     }
0310 
0311     Keys.onPressed: {
0312         if(event.key === Qt.Key_Up || event.key === Qt.Key_Left) {
0313             if(abortButton.visible && !backgroundButton.selected && !abortButton.selected) {
0314                 abortButton.selected = true;
0315             } else if(backgroundButton.visible) {
0316                 abortButton.selected = !abortButton.selected;
0317                 backgroundButton.selected = !backgroundButton.selected;
0318             } else if(abortButton.visible) {
0319                 button1.selected = true;
0320             }
0321         }
0322         if(event.key === Qt.Key_Down || event.key === Qt.Key_Right) {
0323             if(backgroundButton.visible && !backgroundButton.selected && !abortButton.selected) {
0324                 backgroundButton.selected = true;
0325             } else if(backgroundButton.visible) {
0326                 backgroundButton.selected = !backgroundButton.selected;
0327                 abortButton.selected = !abortButton.selected;
0328             } else if(abortButton.visible) {
0329                 abortButton.selected = true;
0330             }
0331         }
0332         if(event.key === Qt.Key_Enter || event.key === Qt.Key_Return || event.key === Qt.Key_Space) {
0333             if(backgroundButton.selected) {
0334                 backgroundButton.clicked();
0335             } else if(abortButton.selected) {
0336                 abortButton.clicked();
0337             } else if(backgroundButtonVisible) {
0338                 backgroundButton.clicked();
0339             } else if(abortButtonVisible) {
0340                 abortButton.clicked();
0341             }
0342         }
0343     }
0344 
0345     Keys.onReleased: {
0346         if(event.key === Qt.Key_Back) {
0347             if(backgroundButtonVisible)
0348                 backgroundButton.clicked();
0349             else if(abortButtonVisible)
0350                 abortButton.clicked();
0351             event.accepted = true;
0352         }
0353     }
0354 
0355     Connections {
0356         target: DownloadManager
0357 
0358         onError: {
0359             //console.warn("DownloadDialog: DM reports error: " + code + ": " + msg);
0360             downloadDialog.finished();
0361             if (downloadDialog.reportError
0362                     && code != 5 && !messageDisplayed) {  // no error: OperationCanceledError
0363                 // show error message
0364                 messageDisplayed = true;
0365                 messageDialog = Core.showMessageDialog(downloadDialog.parent,
0366                                                            qsTr("Download error (code: %1): %2").arg(code).arg(msg),
0367                                                            "", null,
0368                                                            "", null,
0369                                                            function() {
0370                                                                downloadDialog.shutdown();
0371                                                            }
0372                                                            );
0373                 getFocusTimer.restart();
0374             }
0375         }
0376 
0377         onDownloadProgress: downloadDialogProgress.value = 100 * bytesReceived / bytesTotal;
0378 
0379         onDownloadStarted: {
0380             //console.log("dialog: DM reports started: " + resource);
0381             downloadDialogProgress.value = 0;
0382         }
0383 
0384         onAllDownloadsFinished: {
0385             //console.log("dialog: DM all reports finished");
0386             downloadDialog.finished();
0387             if (downloadDialog.reportSuccess
0388                     && code != 1 && !messageDisplayed) // note: errors will be reported by the onError handler
0389             {
0390                 // report success
0391                 messageDisplayed = true;
0392                 var infText = "";
0393                 if (code == 0) {  // Success
0394                     infText = qsTr("Your download finished successfully. The data files are now available.")
0395                             + '\n'
0396                             + qsTr("Restart any currently active activity.");
0397                 } else if (code == 2)  // NoChange
0398                     infText = qsTr("Your local data files are up-to-date.")
0399 
0400                 messageDialog = Core.showMessageDialog(downloadDialog.parent,
0401                                                            infText,
0402                                                            "", null,
0403                                                            "", null,
0404                                                            function() {
0405                                                                downloadDialog.shutdown();
0406                                                            }
0407                                                            );
0408                 getFocusTimer.restart();
0409             } else if (downloadDialog.autohide)
0410                 downloadDialog.shutdown();
0411         }
0412 
0413         onDownloadFinished: {
0414             //console.log("dialog: DM reports finished: " + code);
0415         }
0416     }
0417 
0418 }