From fa3a43887a4f379af1468fc754449651e6d679d8 Mon Sep 17 00:00:00 2001 From: Vxrtrauter <101264710+Vxrtrauter@users.noreply.github.com> Date: Sat, 31 Jan 2026 02:20:26 +0100 Subject: [PATCH] integrate downloads in downloads tab --- core/interface/gui.py | 107 +++++++++++++++++++++++---------- core/network/libtorrent_int.py | 30 ++++----- core/utils/data/state.py | 3 +- 3 files changed, 86 insertions(+), 54 deletions(-) diff --git a/core/interface/gui.py b/core/interface/gui.py index c596253..18f5093 100644 --- a/core/interface/gui.py +++ b/core/interface/gui.py @@ -29,6 +29,7 @@ import platform import requests as r import os import subprocess +import libtorrent as lt import time import sys import json @@ -183,7 +184,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): self.headers = ["Action", "Name", "Status", "Progress", "Speed", "Size", "Total Size"] def rowCount(self, parent=QModelIndex()): - return len(state.downloads) + return len(state.active_downloads) def columnCount(self, parent=QModelIndex()): return len(self.headers) @@ -194,36 +195,79 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): return None def data(self, index, role=Qt.DisplayRole): - col = index.column() - download = state.downloads[index.row()] if role == Qt.DisplayRole: col = index.column() - + + magnet_link = list(state.active_downloads.keys())[index.row()] + magnetdl = state.active_downloads[magnet_link] + + status = magnetdl.status() + if col == 0: - return "▶︎" if download.is_paused else "⏸︎" + is_paused = magnetdl.status().paused + return "▶︎" if is_paused else "⏸︎" elif col == 1: - return download.name + return status.name if status.has_metadata else "Fetching metadata..." elif col == 2: - return getattr(download, 'status', 'Downloading') + if status.state == lt.torrent_status.downloading: + return "Downloading" + elif status.state == lt.torrent_status.seeding: + return "Seeding" + elif status.paused: + return "Paused" + else: + return "Queued" elif col == 3: - return f"{int(download.progress)}%" + return f"{status.progress * 100:.1f}%" elif col == 4: - return f"{download.download_speed_string()}" + speed_kbs = status.download_rate / 1024 + if speed_kbs > 1024: + return f"{speed_kbs / 1024:.1f} MB/s" + else: + return f"{speed_kbs:.1f} kB/s" elif col == 5: - return f"{download.completed_length_string()}" + downloaded_mb = status.total_wanted_done / (1024 * 1024) + if downloaded_mb > 1024: + return f"{downloaded_mb / 1024:.2f} GB" + else: + return f"{downloaded_mb:.1f} MB" elif col == 6: - return f"{download.total_length_string()}" + total_mb = status.total_wanted / (1024 * 1024) + if total_mb > 1024: + return f"{total_mb / 1024:.2f} GB" + else: + return f"{total_mb:.1f} MB" elif col == 7: - return f"{download.eta_string()}" + if status.download_rate > 0: + bytes_left = status.total_wanted - status.total_wanted_done + eta_seconds = bytes_left / status.download_rate + + if eta_seconds < 60: + return f"{int(eta_seconds)}s" + elif eta_seconds < 3600: + minutes = int(eta_seconds / 60) + seconds = int(eta_seconds % 60) + return f"{minutes}m {seconds}s" + else: + hours = int(eta_seconds / 3600) + minutes = int((eta_seconds % 3600) / 60) + return f"{hours}h {minutes}m" + else: + return "∞" if status.paused else "Stalled" + + if role == Qt.UserRole and index.column() == 0: + magnet_link = list(state.active_downloads.keys())[index.row()] + magnetdl = state.active_downloads[magnet_link] + return magnetdl.status().paused - if role == Qt.UserRole and col == 0: - return download.is_paused - return None def toggle_pause_resume(self, row): - download = state.downloads[row] - if download.progress == 100: + magnet_link = list(state.active_downloads.keys())[row] + magnetdl = state.active_downloads[magnet_link] + status = magnetdl.status() + + if status.state == lt.torrent_status.seeding: if state.download_path is not None and os.path.exists(state.download_path): if platform.system() == "Windows": os.startfile(os.path.normpath(state.download_path)) @@ -231,21 +275,15 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): subprocess.Popen(["xdg-open", state.download_path]) elif platform.system() == "Darwin": subprocess.Popen(["open", state.download_path]) - else: - if platform.system() == "Windows": - os.startfile(os.path.normpath(os.getcwd())) - elif platform.system() == "Linux": - subprocess.Popen(["xdg-open", os.getcwd()]) - elif platform.system() == "Darwin": - subprocess.Popen(["open", os.getcwd()]) return - - if download.is_paused: - download.resume() - consoleLog(f"Resumed download: {download.name}", True) + + if status.paused: + magnetdl.resume() + consoleLog(f"Resumed download: {status.name}", True) else: - download.pause() - consoleLog(f"Paused download: {download.name}", True) + magnetdl.pause() + consoleLog(f"Paused download: {status.name}", True) + idx = self.index(row, 0) self.dataChanged.emit(idx, idx, [Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.UserRole]) @@ -258,12 +296,15 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): return paused = index.data(Qt.UserRole) - download = state.downloads[index.row()] + + magnet_link = list(state.active_downloads.keys())[index.row()] + magnetdl = state.active_downloads[magnet_link] + status = magnetdl.status() button = QStyleOptionButton() button.rect = option.rect - if download.progress == 100: + if status.state == lt.torrent_status.seeding: button.text = "📁" else: button.text = "▶︎" if paused else "⏸︎" @@ -415,7 +456,7 @@ class MainWindow(QtWidgets.QMainWindow, QWidget): self.emptyResults.hide() def show_empty_downloads(self): - if len(state.downloads) > 0: + if len(state.active_downloads) > 0: self.emptyDownload.hide() self.downloadList.show() else: diff --git a/core/network/libtorrent_int.py b/core/network/libtorrent_int.py index ee6d84d..4f7d847 100644 --- a/core/network/libtorrent_int.py +++ b/core/network/libtorrent_int.py @@ -45,16 +45,13 @@ def add_download(magnet_uri, dl_path=state.download_path): consoleLog("Skipping, download already running...") return - consoleLog(f"Adding {magnet_uri} to downloads...") magnetdl = lt.parse_magnet_uri(magnet_uri) magnetdl.save_path = dl_path - consoleLog(f"Download Path: {dl_path}") - download = state.dl_session.add_torrent(magnetdl) state.active_downloads[magnet_uri] = download - consoleLog("added download") + consoleLog(f"Added {magnet_uri} to downloads") run_thread(threading.Thread(target=dl_status_loop)) @@ -62,38 +59,33 @@ def add_download(magnet_uri, dl_path=state.download_path): def dl_status_loop(): global loop_running - if loop_running == True: return loop_running = True - completed = [] - + completed_set = set() + if not state.active_downloads: consoleLog("No active downloads") + loop_running = False return - + while state.active_downloads: - completed.clear() - for magnet_uri, magnetdl in list(state.active_downloads.items()): status = magnetdl.status() - if status.state == lt.torrent_status.seeding: - completed.append(magnet_uri) + if status.state == lt.torrent_status.seeding and magnet_uri not in completed_set: consoleLog(f"Download completed: {status.name}") - continue + + completed_set.add(magnet_uri) - for magnet_uri in completed: - magnetdl = state.active_downloads[magnet_uri] - state.dl_session.remove_torrent(magnetdl) - del state.active_downloads[magnet_uri] - if not state.active_downloads: loop_running = False break - + time.sleep(1) + + loop_running = False diff --git a/core/utils/data/state.py b/core/utils/data/state.py index b8e8f3d..cf6d33f 100644 --- a/core/utils/data/state.py +++ b/core/utils/data/state.py @@ -11,7 +11,6 @@ class AppState(QObject): self.post_titles: List[str] = [] self.post_urls: List[str] = [] self.post_author: List[str] = [] - self.downloads: List[str] = [] self.version: str = "dev" self._image_path: str = "" self.ignore_updates: bool = False @@ -27,7 +26,7 @@ class AppState(QObject): self.aria2_threads: int = 4 self.settings_path: str = None self.dl_session: Any = None - self.active_downloads: Any = None + self.active_downloads: List[str] = {} @property def image_path(self) -> str: