diff --git a/bauh/view/qt/apps_table.py b/bauh/view/qt/apps_table.py index 24fc6302..3fe9a583 100644 --- a/bauh/view/qt/apps_table.py +++ b/bauh/view/qt/apps_table.py @@ -1,6 +1,7 @@ import operator import os from functools import reduce +from logging import Logger from threading import Lock from typing import List, Optional, Dict @@ -71,12 +72,13 @@ class PackagesTable(QTableWidget): COL_NUMBER = 9 DEFAULT_ICON_SIZE = QSize(16, 16) - def __init__(self, parent: QWidget, icon_cache: MemoryCache, download_icons: bool): + def __init__(self, parent: QWidget, icon_cache: MemoryCache, download_icons: bool, logger: Logger): super(PackagesTable, self).__init__() self.setObjectName('table_packages') self.setParent(parent) self.window = parent self.download_icons = download_icons + self.logger = logger self.setColumnCount(self.COL_NUMBER) self.setFocusPolicy(Qt.NoFocus) self.setShowGrid(False) @@ -614,9 +616,10 @@ class PackagesTable(QTableWidget): return reduce(operator.add, [self.columnWidth(i) for i in range(self.columnCount())]) def _setup_file_downloader(self, max_workers: int = 50, max_downloads: int = -1) -> None: - self.file_downloader = URLFileDownloader(parent=self, + self.file_downloader = URLFileDownloader(logger=self.logger, max_workers=max_workers, - max_downloads=max_downloads) + max_downloads=max_downloads, + parent=self) self.file_downloader.signal_downloaded.connect(self._update_pkg_icon) self.file_downloader.start() diff --git a/bauh/view/qt/thread.py b/bauh/view/qt/thread.py index 261df83f..44584418 100644 --- a/bauh/view/qt/thread.py +++ b/bauh/view/qt/thread.py @@ -1117,9 +1117,10 @@ class URLFileDownloader(QThread): signal_downloaded = pyqtSignal(str, bytes, object) - def __init__(self, max_workers: int = 50, request_timeout: int = 30, inactivity_timeout: int = 3, + def __init__(self, logger: Logger, max_workers: int = 50, request_timeout: int = 30, inactivity_timeout: int = 3, max_downloads: int = -1, parent: Optional[QWidget] = None): super().__init__(parent) + self._logger = logger self._queue = Queue() self._max_workers = max_workers self._request_timeout = request_timeout @@ -1129,6 +1130,7 @@ class URLFileDownloader(QThread): def _get(self, url_: str, id_: Optional[object]): if self._stop: + self._logger.info(f"File '{url_}' download cancelled") return try: @@ -1136,21 +1138,31 @@ class URLFileDownloader(QThread): content = res.content if res.status_code == 200 else None self.signal_downloaded.emit(url_, content, id_) except Exception as e: - sys.stderr.write(f"[ERROR] could not download file from '{url_}': " - f"{e.__class__.__name__}({str(e.args)})\n") + self._logger.error(f"[ERROR] could not download file from '{url_}': " + f"{e.__class__.__name__}({str(e.args)})\n") def run(self) -> None: download_count = 0 + futures = [] with ThreadPoolExecutor(max_workers=self._max_workers) as executor: while not self._stop and (self._max_downloads <= 0 or download_count < self._max_downloads): try: url_, id_ = self._queue.get(timeout=self._inactivity_timeout) - executor.submit(self._get, url_, id_) + futures.append(executor.submit(self._get, url_, id_)) download_count += 1 except Exception: self._stop = True - executor.shutdown(wait=False, cancel_futures=True) + cancelled_count = 0 + for f in futures: + if not f.done(): + f.cancel() + cancelled_count += 1 + + if cancelled_count > 0: + self._logger.info(f"{cancelled_count} file downloads cancelled") + + self._logger.info(f"Finished to download files (count={download_count})") def stop(self) -> None: self._stop = True diff --git a/bauh/view/qt/window.py b/bauh/view/qt/window.py index 4b9001b2..bceaa3a9 100755 --- a/bauh/view/qt/window.py +++ b/bauh/view/qt/window.py @@ -290,8 +290,10 @@ class ManageWindow(QWidget): self.table_container.setLayout(QVBoxLayout()) self.table_container.layout().setContentsMargins(0, 0, 0, 0) - self.table_apps = PackagesTable(self, self.icon_cache, - download_icons=bool(self.config['download']['icons'])) + self.table_apps = PackagesTable(parent=self, + icon_cache=self.icon_cache, + download_icons=bool(self.config['download']['icons']), + logger=logger) self.table_apps.change_headers_policy() self.table_container.layout().addWidget(self.table_apps)