mirror of
https://github.com/KeksPirates/SoftwareManager.git
synced 2026-08-04 01:49:42 +02:00
274 lines
9.9 KiB
Python
274 lines
9.9 KiB
Python
from PySide6.QtCore import Qt, QPoint, Signal, QThread
|
|
from network.direct_download.handle import DirectDownloadHandle
|
|
from utils.logging.logs import consoleLog, remove_download_log
|
|
from utils.network.download import download_selected
|
|
from utils.data.tracker import get_magnet_link
|
|
from utils.general.wrappers import run_thread
|
|
from PySide6.QtWidgets import QMessageBox
|
|
from utils.data.state import state
|
|
from send2trash import send2trash
|
|
from PySide6 import QtWidgets
|
|
import threading
|
|
import webbrowser
|
|
import subprocess
|
|
import platform
|
|
import os
|
|
|
|
|
|
class MagnetWorker(QThread):
|
|
finished = Signal(str)
|
|
|
|
def __init__(self, url, parent=None):
|
|
super().__init__(parent)
|
|
self.url = url
|
|
|
|
def run(self):
|
|
magnet = get_magnet_link(self.url)
|
|
if magnet:
|
|
self.finished.emit(magnet)
|
|
|
|
class ContextMenu_Downloads:
|
|
def __init__(self, main_window):
|
|
self.main_window = main_window
|
|
self.context_menu = QtWidgets.QMenu(main_window)
|
|
self.context_menu.addAction("Open Containing Folder", self.openFolderAction)
|
|
self.context_menu.addAction("Copy Download Link", self.copyMagnetURIAction)
|
|
self.context_menu.addAction("Remove from list", self.cancelDownloadAction)
|
|
self.context_menu.addAction("Delete File", self.deleteFileAction)
|
|
|
|
main_window.downloadList.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
|
main_window.downloadList.customContextMenuRequested.connect(self._show_context_menu)
|
|
|
|
@property
|
|
def downloadList(self):
|
|
return self.main_window.downloadList
|
|
|
|
def _show_context_menu(self, pos: QPoint):
|
|
index = self.downloadList.indexAt(pos)
|
|
if index.isValid():
|
|
self._context_menu_row = index.row()
|
|
self.context_menu.exec(self.downloadList.viewport().mapToGlobal(pos))
|
|
|
|
def openFolderAction(self):
|
|
if not hasattr(self, '_context_menu_row'):
|
|
return
|
|
row = self._context_menu_row
|
|
with state.downloads_lock:
|
|
if row < 0 or row >= len(state.active_downloads):
|
|
return
|
|
keys = list(state.active_downloads.keys())
|
|
magnet_link = keys[row]
|
|
magnetdl = state.active_downloads[magnet_link]
|
|
download_path = magnetdl.save_path()
|
|
if download_path and os.path.exists(download_path):
|
|
if platform.system() == "Windows":
|
|
os.startfile(os.path.normpath(download_path))
|
|
elif platform.system() == "Linux":
|
|
subprocess.Popen(["xdg-open", download_path])
|
|
elif platform.system() == "Darwin":
|
|
subprocess.Popen(["open", download_path])
|
|
|
|
def copyMagnetURIAction(self):
|
|
if not hasattr(self, '_context_menu_row'):
|
|
return
|
|
row = self._context_menu_row
|
|
with state.downloads_lock:
|
|
if row < 0 or row >= len(state.active_downloads):
|
|
return
|
|
keys = list(state.active_downloads.keys())
|
|
magnet_link = keys[row]
|
|
clipboard = QtWidgets.QApplication.clipboard()
|
|
clipboard.setText(magnet_link)
|
|
|
|
def cancelDownloadAction(self):
|
|
selected_rows = sorted(set(index.row() for index in self.downloadList.selectedIndexes()), reverse=True)
|
|
|
|
if not selected_rows:
|
|
return
|
|
|
|
names = []
|
|
items_to_remove = []
|
|
|
|
with state.downloads_lock:
|
|
keys = list(state.active_downloads.keys())
|
|
|
|
for row in selected_rows:
|
|
if 0 <= row < len(keys):
|
|
magnet_link = keys[row]
|
|
magnetdl = state.active_downloads[magnet_link]
|
|
|
|
try:
|
|
name = magnetdl.status().name
|
|
except RuntimeError:
|
|
name = "Unknown"
|
|
|
|
names.append(name)
|
|
items_to_remove.append((magnet_link, magnetdl, name))
|
|
|
|
confirm = QMessageBox.question(
|
|
self.main_window,
|
|
"Cancel Downloads",
|
|
f"Are you sure you want to cancel {len(names)} download(s)?\n\n" + "\n".join(names),
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if confirm != QMessageBox.StandardButton.Yes:
|
|
return
|
|
|
|
for magnet_link, magnetdl, name in items_to_remove:
|
|
with state.downloads_lock:
|
|
state.active_downloads.pop(magnet_link, None)
|
|
|
|
remove_download_log(magnet_link)
|
|
|
|
if isinstance(magnetdl, DirectDownloadHandle):
|
|
try:
|
|
magnetdl.stop()
|
|
except Exception as e:
|
|
consoleLog(f"Exception while stopping direct download: {e}")
|
|
elif state.dl_session:
|
|
try:
|
|
state.dl_session.remove_torrent(magnetdl)
|
|
except Exception as e:
|
|
consoleLog(f"Exception while removing download from LibTorrent: {e}")
|
|
|
|
consoleLog(f"Cancelled download: {name}", True)
|
|
|
|
|
|
def deleteFileAction(self):
|
|
selected_rows = sorted(set(index.row() for index in self.downloadList.selectedIndexes()), reverse=True)
|
|
|
|
if not selected_rows:
|
|
return
|
|
|
|
items_to_remove = []
|
|
|
|
with state.downloads_lock:
|
|
keys = list(state.active_downloads.keys())
|
|
|
|
for row in selected_rows:
|
|
if 0 <= row < len(keys):
|
|
magnet_link = keys[row]
|
|
magnetdl = state.active_downloads[magnet_link]
|
|
|
|
try:
|
|
status = magnetdl.status()
|
|
save_path = status.save_path
|
|
torrent_name = status.name
|
|
except RuntimeError:
|
|
consoleLog("Error: torrent handle already invalid", True)
|
|
continue
|
|
|
|
download_path = os.path.join(save_path, torrent_name)
|
|
|
|
items_to_remove.append((magnet_link, magnetdl, torrent_name, download_path))
|
|
|
|
if not items_to_remove:
|
|
return
|
|
|
|
names = [item[2] for item in items_to_remove]
|
|
|
|
confirm = QMessageBox.question(
|
|
self.main_window,
|
|
"Delete Files",
|
|
f"Are you sure you want to delete {len(names)} download(s)?\n\n" + "\n".join(names),
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if confirm != QMessageBox.StandardButton.Yes:
|
|
return
|
|
|
|
for magnet_link, magnetdl, torrent_name, download_path in items_to_remove:
|
|
with state.downloads_lock:
|
|
state.active_downloads.pop(magnet_link, None)
|
|
|
|
remove_download_log(magnet_link)
|
|
|
|
if isinstance(magnetdl, DirectDownloadHandle):
|
|
try:
|
|
magnetdl.stop()
|
|
except Exception as e:
|
|
consoleLog(f"Exception while stopping direct download: {e}")
|
|
elif state.dl_session:
|
|
try:
|
|
state.dl_session.remove_torrent(magnetdl)
|
|
except Exception as e:
|
|
consoleLog(f"Exception while removing download from LibTorrent: {e}")
|
|
|
|
if download_path and os.path.exists(download_path):
|
|
try:
|
|
if os.path.isfile(download_path) or os.path.isdir(download_path):
|
|
send2trash(download_path)
|
|
consoleLog(f"Deleted files for: {torrent_name}", True)
|
|
except Exception as e:
|
|
consoleLog(f"Error deleting files: {e}", True)
|
|
else:
|
|
consoleLog(f"Removed entry (files not found): {torrent_name}", True)
|
|
|
|
class ContextMenu_TrackerTable:
|
|
def __init__(self, main_window):
|
|
self.main_window = main_window
|
|
self.context_menu = QtWidgets.QMenu(main_window)
|
|
self.context_menu.addAction("Copy Download Link", self.copyMagnetURIAction)
|
|
self.context_menu.addAction("Open in Browser", self.openInBrowserAction)
|
|
self.context_menu.addAction("Download", self.downloadItemAction)
|
|
|
|
state.trackertable.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
|
state.trackertable.customContextMenuRequested.connect(self._show_context_menu)
|
|
|
|
@property
|
|
def TrackerTable(self):
|
|
return state.trackertable
|
|
|
|
def _show_context_menu(self, pos: QPoint):
|
|
index = self.TrackerTable.indexAt(pos)
|
|
if index.isValid():
|
|
self._context_menu_row = index.row()
|
|
self.context_menu.exec(self.TrackerTable.viewport().mapToGlobal(pos))
|
|
|
|
def copyMagnetURIAction(self):
|
|
if not hasattr(self, '_context_menu_row'):
|
|
return
|
|
row = self._context_menu_row
|
|
|
|
if not state.posts or row < 0 or row >= len(state.posts):
|
|
return
|
|
|
|
post = state.posts[row]
|
|
url = post.get("url")
|
|
if not url:
|
|
return
|
|
|
|
worker = MagnetWorker(url, parent=self.main_window)
|
|
worker.finished.connect(self._on_magnet_fetched)
|
|
worker.finished.connect(worker.deleteLater)
|
|
worker.start()
|
|
|
|
def _on_magnet_fetched(self, magnet):
|
|
clipboard = QtWidgets.QApplication.clipboard()
|
|
clipboard.setText(magnet)
|
|
consoleLog("Magnet URI copied to clipboard!", True)
|
|
|
|
def openInBrowserAction(self):
|
|
if not hasattr(self, '_context_menu_row'):
|
|
return
|
|
row = self._context_menu_row
|
|
|
|
if not state.posts or row < 0 or row >= len(state.posts):
|
|
return
|
|
|
|
post = state.posts[row]
|
|
url = post.get("url")
|
|
if url:
|
|
try: webbrowser.open(url)
|
|
except Exception as e: consoleLog(f"Failed to open URL: {e}", True)
|
|
|
|
def downloadItemAction(self):
|
|
if not hasattr(self, '_context_menu_row'):
|
|
return
|
|
row = self._context_menu_row
|
|
if not state.posts or row < 0 or row >= len(state.posts):
|
|
return
|
|
|
|
run_thread(threading.Thread(target=download_selected, args=(state.trackertable.selectedItems(),)))
|