Implementiere eine Download-Queue mit Funktionen zum Hinzufügen, Starten, Leeren und Verwalten von Queue-Elementen. Speichere und lade die Queue aus einer Datei.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ bin/yt-dlp.exe
|
|||||||
config.json
|
config.json
|
||||||
main.spec
|
main.spec
|
||||||
*.7z
|
*.7z
|
||||||
|
queue.json
|
||||||
|
431
main.py
431
main.py
@@ -13,10 +13,12 @@ import json
|
|||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
import uuid
|
||||||
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||||
QLabel, QLineEdit, QPushButton, QComboBox, QTextEdit,
|
QLabel, QLineEdit, QPushButton, QComboBox, QTextEdit,
|
||||||
QFileDialog, QMessageBox, QListWidget, QDialog, QFormLayout,
|
QFileDialog, QMessageBox, QListWidget, QDialog, QFormLayout,
|
||||||
QDialogButtonBox, QInputDialog, QGroupBox, QCheckBox, QTabWidget)
|
QDialogButtonBox, QInputDialog, QGroupBox, QCheckBox, QTabWidget,
|
||||||
|
QListWidgetItem, QMenu, QAction)
|
||||||
from PyQt5.QtCore import QThread, pyqtSignal, Qt
|
from PyQt5.QtCore import QThread, pyqtSignal, Qt
|
||||||
|
|
||||||
# Hilfsfunktionen für den Ressourcenpfad
|
# Hilfsfunktionen für den Ressourcenpfad
|
||||||
@@ -517,6 +519,62 @@ class OptionenDialog(QDialog):
|
|||||||
self.update_btn.setText("yt-dlp.exe updaten")
|
self.update_btn.setText("yt-dlp.exe updaten")
|
||||||
|
|
||||||
|
|
||||||
|
class QueueItem:
|
||||||
|
"""Repräsentiert einen Eintrag in der Download-Queue."""
|
||||||
|
def __init__(self, url, preset_data, output_dir=None, output_filename=None,
|
||||||
|
series_info=None, use_local_ytdlp=True, extra_args=None):
|
||||||
|
self.id = str(uuid.uuid4()) # Eindeutige ID für diesen Queue-Eintrag
|
||||||
|
self.url = url
|
||||||
|
self.preset_data = preset_data.copy() if preset_data else {}
|
||||||
|
self.output_dir = output_dir
|
||||||
|
self.output_filename = output_filename
|
||||||
|
self.series_info = series_info.copy() if series_info else {}
|
||||||
|
self.use_local_ytdlp = use_local_ytdlp
|
||||||
|
self.extra_args = extra_args or ""
|
||||||
|
self.status = "Wartend"
|
||||||
|
|
||||||
|
def get_display_name(self):
|
||||||
|
"""Gibt einen lesbaren Namen für die Queue-Anzeige zurück."""
|
||||||
|
preset_name = self.preset_data.get("name", "Unbekannt")
|
||||||
|
if self.series_info:
|
||||||
|
series = self.series_info.get("series", "")
|
||||||
|
season = self.series_info.get("season", "")
|
||||||
|
episode = self.series_info.get("episode", "")
|
||||||
|
if series and season and episode:
|
||||||
|
return f"{self.url} - {series} S{season}E{episode} ({preset_name})"
|
||||||
|
return f"{self.url} ({preset_name})"
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
"""Konvertiert das QueueItem in ein JSON-serialisierbares Dictionary."""
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"url": self.url,
|
||||||
|
"preset_data": self.preset_data,
|
||||||
|
"output_dir": self.output_dir,
|
||||||
|
"output_filename": self.output_filename,
|
||||||
|
"series_info": self.series_info,
|
||||||
|
"use_local_ytdlp": self.use_local_ytdlp,
|
||||||
|
"extra_args": self.extra_args,
|
||||||
|
"status": self.status
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_dict(cls, data):
|
||||||
|
"""Erstellt ein QueueItem aus einem Dictionary."""
|
||||||
|
item = cls(
|
||||||
|
url=data["url"],
|
||||||
|
preset_data=data["preset_data"],
|
||||||
|
output_dir=data["output_dir"],
|
||||||
|
output_filename=data["output_filename"],
|
||||||
|
series_info=data["series_info"],
|
||||||
|
use_local_ytdlp=data["use_local_ytdlp"],
|
||||||
|
extra_args=data["extra_args"]
|
||||||
|
)
|
||||||
|
item.id = data["id"]
|
||||||
|
item.status = data["status"]
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -534,9 +592,15 @@ class MainWindow(QMainWindow):
|
|||||||
self.presets = self.load_presets()
|
self.presets = self.load_presets()
|
||||||
|
|
||||||
self.download_thread = None
|
self.download_thread = None
|
||||||
|
self.download_queue = [] # Liste für die Download-Queue
|
||||||
|
self.current_queue_item = None # Aktuell laufender Download aus der Queue
|
||||||
|
|
||||||
|
# UI initialisieren
|
||||||
self.setup_ui()
|
self.setup_ui()
|
||||||
|
|
||||||
|
# Queue aus gespeicherter Datei laden (nach UI-Setup)
|
||||||
|
self.load_queue()
|
||||||
|
|
||||||
def ensure_directories(self):
|
def ensure_directories(self):
|
||||||
"""Stellt sicher, dass alle benötigten Verzeichnisse existieren."""
|
"""Stellt sicher, dass alle benötigten Verzeichnisse existieren."""
|
||||||
# Stelle sicher, dass der Presets-Ordner existiert
|
# Stelle sicher, dass der Presets-Ordner existiert
|
||||||
@@ -601,11 +665,11 @@ class MainWindow(QMainWindow):
|
|||||||
main_layout.addWidget(self.series_group)
|
main_layout.addWidget(self.series_group)
|
||||||
|
|
||||||
# Options-Button statt Felder für Standardpfad und yt-dlp-Quelle
|
# Options-Button statt Felder für Standardpfad und yt-dlp-Quelle
|
||||||
optionen_layout = QHBoxLayout()
|
options_layout = QHBoxLayout()
|
||||||
self.optionen_btn = QPushButton("Optionen...")
|
self.optionen_btn = QPushButton("Optionen...")
|
||||||
self.optionen_btn.clicked.connect(self.open_optionen_dialog)
|
self.optionen_btn.clicked.connect(self.open_optionen_dialog)
|
||||||
optionen_layout.addWidget(self.optionen_btn)
|
options_layout.addWidget(self.optionen_btn)
|
||||||
main_layout.addLayout(optionen_layout)
|
main_layout.addLayout(options_layout)
|
||||||
|
|
||||||
# Command Preview
|
# Command Preview
|
||||||
main_layout.addWidget(QLabel("Befehlsvorschau:"))
|
main_layout.addWidget(QLabel("Befehlsvorschau:"))
|
||||||
@@ -614,21 +678,60 @@ class MainWindow(QMainWindow):
|
|||||||
self.cmd_preview.setMaximumHeight(60)
|
self.cmd_preview.setMaximumHeight(60)
|
||||||
main_layout.addWidget(self.cmd_preview)
|
main_layout.addWidget(self.cmd_preview)
|
||||||
|
|
||||||
# Download Button
|
# Download Buttons
|
||||||
|
download_buttons_layout = QHBoxLayout()
|
||||||
self.download_btn = QPushButton("Download starten")
|
self.download_btn = QPushButton("Download starten")
|
||||||
self.download_btn.clicked.connect(self.start_download)
|
self.download_btn.clicked.connect(self.start_download)
|
||||||
main_layout.addWidget(self.download_btn)
|
download_buttons_layout.addWidget(self.download_btn)
|
||||||
|
|
||||||
# Log Output
|
# Neu: Queue-Button
|
||||||
main_layout.addWidget(QLabel("Ausgabe:"))
|
self.queue_btn = QPushButton("Zur Queue hinzufügen")
|
||||||
|
self.queue_btn.clicked.connect(self.add_to_queue)
|
||||||
|
download_buttons_layout.addWidget(self.queue_btn)
|
||||||
|
|
||||||
|
main_layout.addLayout(download_buttons_layout)
|
||||||
|
|
||||||
|
# Neu: Tabbed Layout für Ausgabe und Queue
|
||||||
|
self.tabs = QTabWidget()
|
||||||
|
|
||||||
|
# Log Output Tab
|
||||||
|
log_tab = QWidget()
|
||||||
|
log_layout = QVBoxLayout()
|
||||||
|
log_layout.addWidget(QLabel("Ausgabe:"))
|
||||||
self.log_output = QTextEdit()
|
self.log_output = QTextEdit()
|
||||||
self.log_output.setReadOnly(True)
|
self.log_output.setReadOnly(True)
|
||||||
main_layout.addWidget(self.log_output)
|
log_layout.addWidget(self.log_output)
|
||||||
|
log_tab.setLayout(log_layout)
|
||||||
|
self.tabs.addTab(log_tab, "Ausgabe")
|
||||||
|
|
||||||
|
# Queue Tab
|
||||||
|
queue_tab = QWidget()
|
||||||
|
queue_layout = QVBoxLayout()
|
||||||
|
queue_layout.addWidget(QLabel("Download-Queue:"))
|
||||||
|
|
||||||
|
self.queue_list = QListWidget()
|
||||||
|
self.queue_list.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
|
self.queue_list.customContextMenuRequested.connect(self.show_queue_context_menu)
|
||||||
|
queue_layout.addWidget(self.queue_list)
|
||||||
|
|
||||||
|
queue_buttons = QHBoxLayout()
|
||||||
|
self.start_queue_btn = QPushButton("Queue starten")
|
||||||
|
self.start_queue_btn.clicked.connect(self.start_queue)
|
||||||
|
queue_buttons.addWidget(self.start_queue_btn)
|
||||||
|
|
||||||
|
self.clear_queue_btn = QPushButton("Queue leeren")
|
||||||
|
self.clear_queue_btn.clicked.connect(self.clear_queue)
|
||||||
|
queue_buttons.addWidget(self.clear_queue_btn)
|
||||||
|
|
||||||
|
queue_layout.addLayout(queue_buttons)
|
||||||
|
queue_tab.setLayout(queue_layout)
|
||||||
|
self.tabs.addTab(queue_tab, "Queue")
|
||||||
|
|
||||||
|
main_layout.addWidget(self.tabs)
|
||||||
|
|
||||||
# Connect signals
|
# Connect signals
|
||||||
self.url_input.textChanged.connect(self.update_cmd_preview)
|
self.url_input.textChanged.connect(self.update_cmd_preview)
|
||||||
self.preset_combo.currentIndexChanged.connect(self.preset_changed)
|
self.preset_combo.currentIndexChanged.connect(self.preset_changed)
|
||||||
# self.optionen_btn.clicked.connect(self.open_optionen_dialog) # Entfernt, um doppeltes Öffnen zu verhindern
|
|
||||||
|
|
||||||
# Serie, Staffel, Folge Signals
|
# Serie, Staffel, Folge Signals
|
||||||
self.series_input.textChanged.connect(self.update_cmd_preview)
|
self.series_input.textChanged.connect(self.update_cmd_preview)
|
||||||
@@ -642,6 +745,7 @@ class MainWindow(QMainWindow):
|
|||||||
# Initial update
|
# Initial update
|
||||||
self.preset_changed()
|
self.preset_changed()
|
||||||
self.update_cmd_preview()
|
self.update_cmd_preview()
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
def load_config(self):
|
def load_config(self):
|
||||||
if os.path.exists(CONFIG_FILE):
|
if os.path.exists(CONFIG_FILE):
|
||||||
@@ -1115,10 +1219,317 @@ class MainWindow(QMainWindow):
|
|||||||
self.log_output.append(f"Fehler: {message}")
|
self.log_output.append(f"Fehler: {message}")
|
||||||
QMessageBox.warning(self, "Fehler", message)
|
QMessageBox.warning(self, "Fehler", message)
|
||||||
|
|
||||||
|
# Queue-Buttons nach Download aktualisieren
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
self.save_config()
|
self.save_config()
|
||||||
|
self.save_queue() # Queue beim Beenden speichern
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
|
def load_queue(self):
|
||||||
|
"""Lädt die gespeicherte Download-Queue aus einer Datei."""
|
||||||
|
queue_file = os.path.join(get_user_data_dir(), "queue.json")
|
||||||
|
if os.path.exists(queue_file):
|
||||||
|
try:
|
||||||
|
with open(queue_file, 'r', encoding='utf-8') as f:
|
||||||
|
queue_data = json.load(f)
|
||||||
|
self.download_queue = [QueueItem.from_dict(item) for item in queue_data]
|
||||||
|
# Sicherer Log-Aufruf
|
||||||
|
if hasattr(self, 'log_output'):
|
||||||
|
self.log_output.append(f"Download-Queue mit {len(self.download_queue)} Elementen geladen.")
|
||||||
|
# Queue-Liste aktualisieren
|
||||||
|
if hasattr(self, 'queue_list'):
|
||||||
|
self.update_queue_list()
|
||||||
|
except Exception as e:
|
||||||
|
if hasattr(self, 'log_output'):
|
||||||
|
self.log_output.append(f"Fehler beim Laden der Download-Queue: {str(e)}")
|
||||||
|
print(f"Fehler beim Laden der Download-Queue: {str(e)}")
|
||||||
|
self.download_queue = []
|
||||||
|
|
||||||
|
# Aktualisiere Queue-Buttons nach dem Laden
|
||||||
|
if hasattr(self, 'start_queue_btn') and hasattr(self, 'clear_queue_btn'):
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
|
def save_queue(self):
|
||||||
|
"""Speichert die Download-Queue in eine Datei."""
|
||||||
|
queue_file = os.path.join(get_user_data_dir(), "queue.json")
|
||||||
|
try:
|
||||||
|
queue_data = [item.to_dict() for item in self.download_queue]
|
||||||
|
with open(queue_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(queue_data, f, indent=4, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
if hasattr(self, 'log_output'):
|
||||||
|
self.log_output.append(f"Fehler beim Speichern der Download-Queue: {str(e)}")
|
||||||
|
print(f"Fehler beim Speichern der Download-Queue: {str(e)}")
|
||||||
|
|
||||||
|
def add_to_queue(self):
|
||||||
|
"""Fügt den aktuellen Download zur Queue hinzu."""
|
||||||
|
url = self.url_input.text()
|
||||||
|
if not url:
|
||||||
|
QMessageBox.warning(self, "Fehler", "Bitte geben Sie eine URL ein.")
|
||||||
|
return
|
||||||
|
preset = self.get_current_preset()
|
||||||
|
if not preset:
|
||||||
|
QMessageBox.warning(self, "Fehler", "Bitte wählen Sie ein Preset aus.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Wenn im Preset ein eigener Pfad definiert ist, diesen bevorzugen
|
||||||
|
custom_path = self.custom_path_input.text() or preset.get("custom_path", "")
|
||||||
|
# Wenn custom_path gesetzt ist, verwenden wir diesen anstelle des standard output_dir
|
||||||
|
output_dir = custom_path if custom_path else self.config["output_dir"]
|
||||||
|
|
||||||
|
series_info = None
|
||||||
|
output_filename = None
|
||||||
|
|
||||||
|
# Wenn es ein Serien-Preset ist, die Serien-Infos separat speichern
|
||||||
|
if preset.get("has_series_template", False):
|
||||||
|
series_info = {
|
||||||
|
"series": self.series_input.text() or preset.get("series", ""),
|
||||||
|
"season": self.season_input.text() or preset.get("season", "1"),
|
||||||
|
"episode": self.episode_input.text() or preset.get("episode", "1"),
|
||||||
|
"template": preset.get("series_template", SERIES_TEMPLATE)
|
||||||
|
}
|
||||||
|
output_filename = self.get_output_filename(preset)
|
||||||
|
|
||||||
|
# Flags und Extra-Argumente vorbereiten
|
||||||
|
flags = self.config.get("ytdlp_flags", {})
|
||||||
|
is_audio = preset.get("is_audio", False)
|
||||||
|
extra_args = []
|
||||||
|
|
||||||
|
if preset.get("username"):
|
||||||
|
extra_args.extend(["-u", preset["username"]])
|
||||||
|
if preset.get("password"):
|
||||||
|
extra_args.extend(["-p", preset["password"]])
|
||||||
|
if preset.get("referer"):
|
||||||
|
extra_args.append(f"--referer={preset['referer']}")
|
||||||
|
if preset.get("hls_ffmpeg"):
|
||||||
|
extra_args.extend(["--downloader", "ffmpeg", "--hls-use-mpegts"])
|
||||||
|
if preset.get("sublang"):
|
||||||
|
extra_args.extend(["--sub-lang", preset["sublang"]])
|
||||||
|
if preset.get("embed_subs"):
|
||||||
|
extra_args.append("--embed-subs")
|
||||||
|
if preset.get("subformat"):
|
||||||
|
extra_args.extend(["--convert-subs", preset["subformat"]])
|
||||||
|
if flags.get("ignore_config"):
|
||||||
|
extra_args.append("--ignore-config")
|
||||||
|
if flags.get("remux_mkv") and not is_audio:
|
||||||
|
extra_args.extend(["--remux-video", "mkv"])
|
||||||
|
if flags.get("embed_metadata"):
|
||||||
|
extra_args.append("--embed-metadata")
|
||||||
|
|
||||||
|
full_args = (" ".join(extra_args) + " " + preset["args"]).strip() if extra_args else preset["args"]
|
||||||
|
|
||||||
|
# Erstelle ein Queue-Element
|
||||||
|
queue_item = QueueItem(
|
||||||
|
url=url,
|
||||||
|
preset_data=preset,
|
||||||
|
output_dir=output_dir,
|
||||||
|
output_filename=output_filename,
|
||||||
|
series_info=series_info,
|
||||||
|
use_local_ytdlp=self.config["use_local_ytdlp"],
|
||||||
|
extra_args=full_args
|
||||||
|
)
|
||||||
|
|
||||||
|
# Füge das Element zur Queue hinzu
|
||||||
|
self.download_queue.append(queue_item)
|
||||||
|
|
||||||
|
# Aktualisiere die Queue-Liste
|
||||||
|
self.update_queue_list()
|
||||||
|
self.tabs.setCurrentIndex(1) # Wechsle zum Queue-Tab
|
||||||
|
|
||||||
|
# Optional: Leere die URL-Box
|
||||||
|
self.url_input.clear()
|
||||||
|
|
||||||
|
# Aktualisiere Queue-Buttons
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
|
# Queue speichern
|
||||||
|
self.save_queue()
|
||||||
|
|
||||||
|
QMessageBox.information(self, "Hinzugefügt", "Download wurde zur Queue hinzugefügt.")
|
||||||
|
|
||||||
|
def update_queue_list(self):
|
||||||
|
"""Aktualisiert die Anzeige der Queue-Liste."""
|
||||||
|
self.queue_list.clear()
|
||||||
|
for item in self.download_queue:
|
||||||
|
list_item = QListWidgetItem(f"{item.status}: {item.get_display_name()}")
|
||||||
|
list_item.setData(Qt.UserRole, item.id) # Speichere die ID als Daten
|
||||||
|
self.queue_list.addItem(list_item)
|
||||||
|
|
||||||
|
def update_queue_buttons(self):
|
||||||
|
"""Aktualisiert den Status der Queue-Buttons basierend auf dem Zustand der Queue."""
|
||||||
|
has_items = len(self.download_queue) > 0
|
||||||
|
is_downloading = self.download_thread and self.download_thread.isRunning()
|
||||||
|
|
||||||
|
self.start_queue_btn.setEnabled(has_items and not is_downloading)
|
||||||
|
self.clear_queue_btn.setEnabled(has_items and not is_downloading)
|
||||||
|
|
||||||
|
def show_queue_context_menu(self, position):
|
||||||
|
"""Zeigt das Kontextmenü für die Queue-Liste an."""
|
||||||
|
if not self.queue_list.count():
|
||||||
|
return
|
||||||
|
|
||||||
|
menu = QMenu()
|
||||||
|
|
||||||
|
# Aktionen erstellen
|
||||||
|
remove_action = QAction("Entfernen", self)
|
||||||
|
remove_action.triggered.connect(self.remove_selected_queue_item)
|
||||||
|
|
||||||
|
move_up_action = QAction("Nach oben", self)
|
||||||
|
move_up_action.triggered.connect(lambda: self.move_queue_item(-1))
|
||||||
|
|
||||||
|
move_down_action = QAction("Nach unten", self)
|
||||||
|
move_down_action.triggered.connect(lambda: self.move_queue_item(1))
|
||||||
|
|
||||||
|
# Prüfe ob ein Element ausgewählt ist
|
||||||
|
if self.queue_list.currentItem():
|
||||||
|
menu.addAction(remove_action)
|
||||||
|
menu.addAction(move_up_action)
|
||||||
|
menu.addAction(move_down_action)
|
||||||
|
|
||||||
|
# Zeige Menü
|
||||||
|
menu.exec_(self.queue_list.mapToGlobal(position))
|
||||||
|
|
||||||
|
def remove_selected_queue_item(self):
|
||||||
|
"""Entfernt das ausgewählte Element aus der Queue."""
|
||||||
|
current_item = self.queue_list.currentItem()
|
||||||
|
if not current_item:
|
||||||
|
return
|
||||||
|
|
||||||
|
item_id = current_item.data(Qt.UserRole)
|
||||||
|
self.download_queue = [item for item in self.download_queue if item.id != item_id]
|
||||||
|
self.update_queue_list()
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
|
# Queue speichern
|
||||||
|
self.save_queue()
|
||||||
|
|
||||||
|
def move_queue_item(self, direction):
|
||||||
|
"""Verschiebt ein Queue-Element nach oben oder unten."""
|
||||||
|
current_row = self.queue_list.currentRow()
|
||||||
|
if current_row < 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
new_row = current_row + direction
|
||||||
|
if new_row < 0 or new_row >= self.queue_list.count():
|
||||||
|
return
|
||||||
|
|
||||||
|
# Tausche Elemente in der Queue
|
||||||
|
self.download_queue[current_row], self.download_queue[new_row] = \
|
||||||
|
self.download_queue[new_row], self.download_queue[current_row]
|
||||||
|
|
||||||
|
# Aktualisiere UI
|
||||||
|
self.update_queue_list()
|
||||||
|
self.queue_list.setCurrentRow(new_row)
|
||||||
|
|
||||||
|
# Queue speichern
|
||||||
|
self.save_queue()
|
||||||
|
|
||||||
|
def start_queue(self):
|
||||||
|
"""Startet die Download-Queue."""
|
||||||
|
if not self.download_queue:
|
||||||
|
QMessageBox.information(self, "Queue leer", "Die Download-Queue ist leer.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.download_thread and self.download_thread.isRunning():
|
||||||
|
QMessageBox.warning(self, "Download läuft", "Es läuft bereits ein Download.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Starte den ersten Download in der Queue
|
||||||
|
self.process_next_queue_item()
|
||||||
|
|
||||||
|
def process_next_queue_item(self):
|
||||||
|
"""Verarbeitet das nächste Element in der Queue."""
|
||||||
|
if not self.download_queue:
|
||||||
|
self.log_output.append("Download-Queue abgeschlossen.")
|
||||||
|
self.current_queue_item = None
|
||||||
|
self.update_queue_buttons()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Nehme das erste Element aus der Queue
|
||||||
|
self.current_queue_item = self.download_queue[0]
|
||||||
|
self.current_queue_item.status = "Wird heruntergeladen"
|
||||||
|
self.update_queue_list()
|
||||||
|
|
||||||
|
# Starte den Download
|
||||||
|
self.tabs.setCurrentIndex(0) # Wechsle zum Ausgabe-Tab
|
||||||
|
self.log_output.clear()
|
||||||
|
self.log_output.append(f"Starte Download von: {self.current_queue_item.url}")
|
||||||
|
self.log_output.append(f"Preset: {self.current_queue_item.preset_data.get('name', 'Unbekannt')}")
|
||||||
|
self.log_output.append(f"Ausgabeverzeichnis: {self.current_queue_item.output_dir}")
|
||||||
|
|
||||||
|
# Download-Thread erstellen und starten
|
||||||
|
self.download_thread = DownloadThread(
|
||||||
|
url=self.current_queue_item.url,
|
||||||
|
output_dir=self.current_queue_item.output_dir,
|
||||||
|
cmd_args=self.current_queue_item.extra_args,
|
||||||
|
use_local_ytdlp=self.current_queue_item.use_local_ytdlp,
|
||||||
|
output_filename=self.current_queue_item.output_filename
|
||||||
|
)
|
||||||
|
|
||||||
|
self.download_thread.update_signal.connect(self.update_log)
|
||||||
|
self.download_thread.finished_signal.connect(self.queue_download_finished)
|
||||||
|
|
||||||
|
# Ändere den Button-Text und deaktiviere UI-Elemente während des Downloads
|
||||||
|
self.download_btn.setText("Download abbrechen")
|
||||||
|
self.disable_ui_during_download(True)
|
||||||
|
|
||||||
|
self.download_thread.start()
|
||||||
|
|
||||||
|
def queue_download_finished(self, success, message):
|
||||||
|
"""Callback wenn ein Download aus der Queue fertig ist."""
|
||||||
|
# UI-Elemente wieder aktivieren
|
||||||
|
self.disable_ui_during_download(False)
|
||||||
|
# Button-Text zurücksetzen
|
||||||
|
self.download_btn.setText("Download starten")
|
||||||
|
|
||||||
|
# Bearbeite das aktuelle Queue-Element
|
||||||
|
if self.current_queue_item:
|
||||||
|
self.current_queue_item.status = "Fertig" if success else "Fehler"
|
||||||
|
|
||||||
|
# Entferne das Element aus der Queue (es bleibt in der Liste, aber mit Status)
|
||||||
|
if self.download_queue and self.download_queue[0].id == self.current_queue_item.id:
|
||||||
|
self.download_queue.pop(0)
|
||||||
|
|
||||||
|
self.update_queue_list()
|
||||||
|
|
||||||
|
# Queue speichern
|
||||||
|
self.save_queue()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
self.log_output.append(message)
|
||||||
|
else:
|
||||||
|
self.log_output.append(f"Fehler: {message}")
|
||||||
|
|
||||||
|
# Wenn die Queue nicht manuell abgebrochen wurde, verarbeite das nächste Element
|
||||||
|
if not message.startswith("Download wurde abgebrochen"):
|
||||||
|
self.process_next_queue_item()
|
||||||
|
|
||||||
|
# Aktualisiere Queue-Buttons
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
|
def clear_queue(self):
|
||||||
|
"""Leert die Download-Queue."""
|
||||||
|
if not self.download_queue:
|
||||||
|
return
|
||||||
|
|
||||||
|
reply = QMessageBox.question(
|
||||||
|
self,
|
||||||
|
"Queue leeren",
|
||||||
|
"Möchten Sie wirklich die gesamte Download-Queue leeren?",
|
||||||
|
QMessageBox.Yes | QMessageBox.No,
|
||||||
|
QMessageBox.No
|
||||||
|
)
|
||||||
|
|
||||||
|
if reply == QMessageBox.Yes:
|
||||||
|
self.download_queue.clear()
|
||||||
|
self.update_queue_list()
|
||||||
|
self.update_queue_buttons()
|
||||||
|
|
||||||
|
# Queue speichern (leere Liste)
|
||||||
|
self.save_queue()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
Reference in New Issue
Block a user