diff --git a/constants.py b/constants.py index c8058a7..cfe9260 100644 --- a/constants.py +++ b/constants.py @@ -152,6 +152,8 @@ class Constants: APPLY = "Apply" REMOVE = "Remove" UNKNOWN = "N/A" + EXTRACTING_MSG = "Extracting..." + EXTRACTING_CODE = -1 MODULATIONS = ("8VSB", "AFSK", "AM", diff --git a/download_db_window.ui b/download_db_window.ui index 7cc90c6..2a280fe 100644 --- a/download_db_window.ui +++ b/download_db_window.ui @@ -7,14 +7,14 @@ 0 0 400 - 137 + 157 Download database - + :/icons/Artemis3.ico:/icons/Artemis3.ico @@ -33,7 +33,23 @@ Downloading database -Please wait... +Please wait... + + + + Qt::AlignCenter + + + + + + + + 12 + + + + status Qt::AlignCenter diff --git a/download_window.py b/download_window.py index 1465cc1..014d216 100644 --- a/download_window.py +++ b/download_window.py @@ -3,7 +3,7 @@ from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal from PyQt5.QtWidgets import QWidget from threads import DownloadThread, ThreadStatus from utilities import pop_up, resource_path -from constants import Messages +from constants import Constants, Messages Ui_Download_window, _ = uic.loadUiType(resource_path("download_db_window.ui")) @@ -33,8 +33,23 @@ class DownloadWindow(QWidget, Ui_Download_window): self.download_thread = DownloadThread() self.download_thread.finished.connect(self.wait_close) + self.download_thread.progress.connect(self.__display_progress) self.cancel_btn.clicked.connect(self.terminate_process) + def __downlaod_format_str(self, n, speed): + return f"Downloaded MB: {n}\nSpeed: {speed} MB/s" + + def show(self): + self.status_lbl.setText(self.__downlaod_format_str(0, 0)) + super().show() + + @pyqtSlot(int, float) + def __display_progress(self, progress, speed): + if progress != Constants.EXTRACTING_CODE: + self.status_lbl.setText(self.__downlaod_format_str(progress, speed)) + elif progress == Constants.EXTRACTING_CODE: + self.status_lbl.setText(Constants.EXTRACTING_MSG + '\n') + @pyqtSlot() def terminate_process(self): if self.download_thread.isRunning(): diff --git a/threads.py b/threads.py index fc928f3..93a56b5 100644 --- a/threads.py +++ b/threads.py @@ -1,12 +1,14 @@ import asyncio from enum import Enum, auto from io import BytesIO +from math import ceil import os.path from shutil import rmtree +from time import time from zipfile import ZipFile import aiohttp import urllib3 -from PyQt5.QtCore import QThread +from PyQt5.QtCore import QThread, pyqtSignal from constants import Constants, Database, ChecksumWhat from utilities import checksum_ok @@ -30,23 +32,56 @@ class BaseDownloadThread(QThread): class DownloadThread(BaseDownloadThread): + + progress = pyqtSignal(int, float) + CHUNK = 1024**2 + def __init__(self): super().__init__() - self.reason = 0 + + def __pretty_len(self, byte_obj): + mega = len(byte_obj) / self.CHUNK + if mega.is_integer(): + return int(mega) + else: + return ceil(mega) + + def __get_download_speed(self, data, delta): + return round( + (len(data) / self.CHUNK) / delta, + 2 + ) def run(self): self.status = ThreadStatus.UNDEFINED + raw_data = bytes(0) try: - db = urllib3.PoolManager().request('GET', Database.LINK_LOC) - except urllib3.exceptions.MaxRetryError: # No internet connection. + db = urllib3.PoolManager().request( + 'GET', + Database.LINK_LOC, + preload_content=False + ) + while True: + start = time() + data = db.read(self.CHUNK) + delta = time() - start + if not data: + break + raw_data += data + self.progress.emit( + self.__pretty_len(raw_data), + self.__get_download_speed(data, delta) + ) + db.release_conn() + except Exception: # No internet connection. + db.release_conn() self.status = ThreadStatus.NO_CONNECTION_ERR return if db.status != 200: - self.reason = db.reason self.status = ThreadStatus.BAD_DOWNLOAD_ERR return try: - is_checksum_ok = checksum_ok(db.data, ChecksumWhat.FOLDER) + is_checksum_ok = checksum_ok(raw_data, ChecksumWhat.FOLDER) except Exception: self.status = ThreadStatus.NO_CONNECTION_ERR return @@ -57,7 +92,8 @@ class DownloadThread(BaseDownloadThread): if os.path.exists(Constants.DATA_FOLDER): rmtree(Constants.DATA_FOLDER) try: - with ZipFile(BytesIO(db.data)) as zipped: + self.progress.emit(Constants.EXTRACTING_CODE, 0.0) + with ZipFile(BytesIO(raw_data)) as zipped: zipped.extractall() except Exception: self.status = ThreadStatus.UNKNOWN_ERR