diff --git a/artemis/resources.py b/artemis/resources.py index fcdb427..33fd87b 100644 --- a/artemis/resources.py +++ b/artemis/resources.py @@ -6635,7 +6635,7 @@ G@\x11\x10HG\x93Hp\xec\x0au\xe3\xcd\x1e\xf4\ >k\xd0\xd3b\x1eG\xb5_d\xde\xb6{\x8f\x95\xc5\ U\xaf\xbc\xfd\xe9\xb5\x9f\xe5\xe3}r\xba?\xbbI\x06\ \xfe\xfc\x0f\xf4\xcd*2\ -\x00\x00\x06\x95\ +\x00\x00\x070\ i\ mport QtQuick\x0d\x0ai\ mport QtQuick.Wi\ @@ -6674,75 +6674,84 @@ ceived\x0d\x0a \ progressBar.to =\ bytesTotal\x0d\x0a \ }\x0d\x0a\x0d\x0a functi\ -on updateStatus(\ -arg) {\x0d\x0a \ -progressLabel.te\ -xt = arg\x0d\x0a }\x0d\ -\x0a\x0d\x0a Page {\x0d\x0a \ - id: page\x0d\ -\x0a anchors\ -.fill: parent\x0d\x0a\x0d\ -\x0a ColumnL\ -ayout {\x0d\x0a \ - id: columnL\ -ayout\x0d\x0a \ - anchors.fill:\ - parent\x0d\x0a\x0d\x0a \ - Label {\x0d\x0a\ - \ -text: qsTr(\x22Down\ -loading in progr\ -ess...\x22)\x0d\x0a \ - Layout\ -.alignment: Qt.A\ -lignHCenter | Qt\ -.AlignVCenter\x0d\x0a \ - }\x0d\x0a\x0d\x0a\ - Prog\ -ressBar {\x0d\x0a \ - id: p\ -rogressBar\x0d\x0a \ - Layo\ -ut.rightMargin: \ -20\x0d\x0a \ - Layout.leftM\ -argin: 20\x0d\x0a \ - Layou\ -t.fillWidth: tru\ -e\x0d\x0a \ - value: 0\x0d\x0a \ - to:\ - 0\x0d\x0a \ -}\x0d\x0a\x0d\x0a \ - Label {\x0d\x0a \ - id: pr\ -ogressLabel\x0d\x0a \ - Lay\ -out.alignment: Q\ -t.AlignHCenter |\ - Qt.AlignVCenter\ -\x0d\x0a }\x0d\ -\x0a\x0d\x0a B\ -utton {\x0d\x0a \ +on setIndetermin\ +ateBar() {\x0d\x0a \ + progressBar.\ +indeterminate = \ +true\x0d\x0a }\x0d\x0a\x0d\x0a \ + function upda\ +teStatus(arg) {\x0d\ +\x0a progres\ +sLabel.text = ar\ +g\x0d\x0a }\x0d\x0a\x0d\x0a \ +Page {\x0d\x0a \ +id: page\x0d\x0a \ + anchors.fill: \ +parent\x0d\x0a\x0d\x0a \ + ColumnLayout {\ +\x0d\x0a id\ +: columnLayout\x0d\x0a\ + anch\ +ors.fill: parent\ +\x0d\x0a\x0d\x0a \ +Label {\x0d\x0a \ text: q\ -sTr(\x22Abort\x22)\x0d\x0a \ - ic\ -on.source: \x22qrc:\ -/images/icons/ab\ -ort.svg\x22\x0d\x0a \ - displa\ -y: AbstractButto\ -n.TextBesideIcon\ +sTr(\x22Downloading\ + in progress...\x22\ +)\x0d\x0a \ + Layout.alignm\ +ent: Qt.AlignHCe\ +nter | Qt.AlignV\ +Center\x0d\x0a \ + }\x0d\x0a\x0d\x0a \ + ProgressBar\ + {\x0d\x0a \ + id: progress\ +Bar\x0d\x0a \ + Layout.righ\ +tMargin: 20\x0d\x0a \ + Lay\ +out.leftMargin: \ +20\x0d\x0a \ + Layout.fillW\ +idth: true\x0d\x0a \ + inde\ +terminate: false\ \x0d\x0a \ - Layout.alignme\ -nt: Qt.AlignHCen\ -ter | Qt.AlignBo\ -ttom\x0d\x0a \ - onClicked:\ - { onAbort() }\x0d\x0a\ - }\x0d\x0a \ - }\x0d\x0a }\x0d\ -\x0a}\x0d\x0a\ + value: 0\x0d\x0a \ + to: \ +0\x0d\x0a }\ +\x0d\x0a\x0d\x0a \ +Label {\x0d\x0a \ + id: pro\ +gressLabel\x0d\x0a \ + Layo\ +ut.alignment: Qt\ +.AlignHCenter | \ +Qt.AlignVCenter\x0d\ +\x0a }\x0d\x0a\ +\x0d\x0a Bu\ +tton {\x0d\x0a \ + Layout.a\ +lignment: Qt.Ali\ +gnHCenter | Qt.A\ +lignBottom\x0d\x0a \ + text\ +: qsTr(\x22Abort\x22)\x0d\ +\x0a \ + icon.source: \x22q\ +rc:/images/icons\ +/abort.svg\x22\x0d\x0a \ + dis\ +play: AbstractBu\ +tton.TextBesideI\ +con\x0d\x0a \ + flat: true\x0d\ +\x0a \ + onClicked: { on\ +Abort() }\x0d\x0a \ + }\x0d\x0a \ + }\x0d\x0a }\x0d\x0a}\x0d\x0a\ \x00\x00\x05\xac\ i\ mport QtQuick\x0d\x0ai\ @@ -7293,12 +7302,12 @@ qt_resource_struct = b"\ \x00\x00\x01\x8f\xff^8P\ \x00\x00\x03<\x00\x01\x00\x00\x00\x01\x00\x01>\xe2\ \x00\x00\x01\x8f\xff^8P\ -\x00\x00\x05\xa8\x00\x00\x00\x00\x00\x01\x00\x01\x9f\xdf\ +\x00\x00\x05\xa8\x00\x00\x00\x00\x00\x01\x00\x01\xa0z\ \x00\x00\x01\x8f\xff^8P\ \x00\x00\x03r\x00\x01\x00\x00\x00\x01\x00\x01I\x0c\ \x00\x00\x01\x8f\xff^8_\ \x00\x00\x05\x86\x00\x00\x00\x00\x00\x01\x00\x01\x99F\ -\x00\x00\x01\x90\x03\xb0\x82B\ +\x00\x00\x01\x90\x0e\xde\xeeO\ \x00\x00\x03X\x00\x02\x00\x00\x00\x04\x00\x00\x00+\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x04\xc4\x00\x01\x00\x00\x00\x01\x00\x01v\x14\ @@ -7317,13 +7326,13 @@ qt_resource_struct = b"\ \x00\x00\x01\x8f\xff^8P\ \x00\x00\x05\x06\x00\x00\x00\x00\x00\x01\x00\x01\x85\xad\ \x00\x00\x01\x8f\xff^8P\ -\x00\x00\x05\xdc\x00\x01\x00\x00\x00\x01\x00\x01\xa8\x92\ +\x00\x00\x05\xdc\x00\x01\x00\x00\x00\x01\x00\x01\xa9-\ \x00\x00\x01\x8f\xff^8_\ -\x00\x00\x06$\x00\x01\x00\x00\x00\x01\x00\x01\xae\xd7\ +\x00\x00\x06$\x00\x01\x00\x00\x00\x01\x00\x01\xafr\ \x00\x00\x01\x8f\xff^8_\ -\x00\x00\x05\xc0\x00\x01\x00\x00\x00\x01\x00\x01\xa5\x8f\ +\x00\x00\x05\xc0\x00\x01\x00\x00\x00\x01\x00\x01\xa6*\ \x00\x00\x01\x8f\xff^8_\ -\x00\x00\x06\x00\x00\x01\x00\x00\x00\x01\x00\x01\xabU\ +\x00\x00\x06\x00\x00\x01\x00\x00\x00\x01\x00\x01\xab\xf0\ \x00\x00\x01\x8f\xff^8_\ " diff --git a/artemis/ui/artemis.py b/artemis/ui/artemis.py index f55fe3d..7506138 100644 --- a/artemis/ui/artemis.py +++ b/artemis/ui/artemis.py @@ -226,7 +226,6 @@ class UIArtemis(QObject): self.downloader.finished.connect(self.update_manager.post_download_db) self.downloader.on_start( self.update_manager.remote_db_url, - self.update_manager.remote_db_size, DATA_DIR ) diff --git a/artemis/ui/downloader.py b/artemis/ui/downloader.py index 99f42ad..c2f9e7e 100644 --- a/artemis/ui/downloader.py +++ b/artemis/ui/downloader.py @@ -1,3 +1,5 @@ +import requests + from PySide6.QtQml import QQmlApplicationEngine from PySide6.QtCore import QObject, Slot, Signal, QUrl, QSaveFile, QDir, QIODevice from PySide6.QtNetwork import QNetworkReply, QNetworkRequest, QNetworkAccessManager @@ -7,11 +9,12 @@ from artemis.utils.constants import Messages class UIDownloader(QObject): # Python > QML Signals - finished = Signal() show_ui = Signal() close_ui = Signal() update_progress_bar = Signal(int, int) + set_indeterminate_bar = Signal() update_status = Signal(str) + finished = Signal() def __init__(self, parent): @@ -25,6 +28,10 @@ class UIDownloader(QObject): self.file_url = None self.file_size = None + self.dest_file = None + self.file = None + self.manager = None + self.reply = None self._connect() @@ -37,17 +44,22 @@ class UIDownloader(QObject): self.show_ui.connect(self._window.show) self.close_ui.connect(self._window.close) self.update_progress_bar.connect(self._window.updateProgressBar) + self.set_indeterminate_bar.connect(self._window.setIndeterminateBar) self.update_status.connect(self._window.updateStatus) - def on_start(self, url, filesize, save_path): - """ Start the download of the DB taking the needed url and size from - the attributes of the UpdatesController class + def on_start(self, url, save_path): + """ Start the download process using the specified URL + + Args: + url (str): url from where download the file + save_path (str): path where to save the downloaded file """ + self.show_ui.emit() self.file_url = QUrl(url) - self.file_size = filesize + self.file_size = self._get_filesize(url) dest_path = QDir(save_path) self.dest_file = dest_path.filePath(self.file_url.fileName()) self.file = QSaveFile(self.dest_file) @@ -69,7 +81,8 @@ class UIDownloader(QObject): @Slot() def on_abort(self): - """ Stop the download when user press abort button """ + """ Stop the download when user presses the abort button + """ if self.reply: self.reply.abort() self.update_progress_bar.emit(0, 0) @@ -80,7 +93,8 @@ class UIDownloader(QObject): @Slot() def on_ready_read(self): - """ Get available bytes and store them into the file """ + """ Write available bytes to the file + """ if self.reply: if self.reply.error() == QNetworkReply.NoError: self.file.write(self.reply.readAll()) @@ -88,8 +102,9 @@ class UIDownloader(QObject): @Slot() def on_finished(self): - """ Delete reply, close the file, check the hash for integrity, - extract the database and delete the downloaded zip + """ Finalize the download process and if no errors + occurrs emits the finished signal usefulle for + a callback """ if self.reply: self.reply.deleteLater() @@ -105,10 +120,13 @@ class UIDownloader(QObject): @Slot(int, int) def on_progress(self, bytesReceived: int): - """ Update progress bar and label + """ Update progress bar and status label """ - self.update_status.emit("{:.1f} Mb / {:.1f} Mb".format(bytesReceived/10**6, self.file_size/10**6)) - self.update_progress_bar.emit(bytesReceived, self.file_size) + if self.file_size is not None: + self.update_status.emit("{:.1f} Mb / {:.1f} Mb".format(bytesReceived/10**6, self.file_size/10**6)) + self.update_progress_bar.emit(bytesReceived, self.file_size) + else: + self.update_status.emit("{:.1f} Mb".format(bytesReceived/10**6)) @Slot(QNetworkReply.NetworkError) @@ -122,6 +140,22 @@ class UIDownloader(QObject): ) + def _get_filesize(self, url): + """ Get the file size by sending a HEAD request to the URL. + If the Content-Length in HTTP headers is missing, returns None + + Args: + url (str): URL to check the file size + """ + try: + response = requests.get(url, stream=True) + size = int(response.headers.get('content-length')) + return size + except: + self.set_indeterminate_bar.emit() + return None + + def show_popup_error(self, error_msg): self._parent.dialog_popup( Messages.DIALOG_TYPE_ERROR, diff --git a/ui/Downloader.qml b/ui/Downloader.qml index 1fa57fe..039b574 100644 --- a/ui/Downloader.qml +++ b/ui/Downloader.qml @@ -29,6 +29,10 @@ Window { progressBar.to = bytesTotal } + function setIndeterminateBar() { + progressBar.indeterminate = true + } + function updateStatus(arg) { progressLabel.text = arg } @@ -51,6 +55,7 @@ Window { Layout.rightMargin: 20 Layout.leftMargin: 20 Layout.fillWidth: true + indeterminate: false value: 0 to: 0 } @@ -61,10 +66,11 @@ Window { } Button { + Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom text: qsTr("Abort") icon.source: "qrc:/images/icons/abort.svg" display: AbstractButton.TextBesideIcon - Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + flat: true onClicked: { onAbort() } } }