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 }