Kompletter Rewrite
This commit is contained in:
622
serien_checker/ui/main_window.py
Normal file
622
serien_checker/ui/main_window.py
Normal file
@@ -0,0 +1,622 @@
|
||||
"""
|
||||
Main window for Serien-Checker application
|
||||
"""
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QSplitter,
|
||||
QListWidget, QTableWidget, QTableWidgetItem, QLabel, QPushButton,
|
||||
QStatusBar, QMessageBox, QMenu, QAction, QHeaderView, QGroupBox
|
||||
)
|
||||
from PyQt5.QtCore import Qt, QUrl
|
||||
from PyQt5.QtGui import QDesktopServices, QColor, QIcon
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from ..database.db_manager import DatabaseManager
|
||||
from ..database.models import Series, Season, Episode, DatePreference
|
||||
from ..utils.logger import setup_logger
|
||||
from ..utils.threading import UpdateWorker
|
||||
from .options_dialog import OptionsDialog
|
||||
|
||||
logger = setup_logger()
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
"""Main application window with 3-column layout"""
|
||||
|
||||
def __init__(self, db_manager: DatabaseManager):
|
||||
super().__init__()
|
||||
self.db = db_manager
|
||||
self.current_series: Optional[Series] = None
|
||||
self.current_season: Optional[Season] = None
|
||||
self.worker = None # Keep reference to worker thread
|
||||
|
||||
self.init_ui()
|
||||
self.load_series_list()
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialize user interface"""
|
||||
self.setWindowTitle("Serien-Checker")
|
||||
self.setGeometry(100, 100, 1400, 800)
|
||||
|
||||
# Set window icon if available
|
||||
try:
|
||||
import sys
|
||||
from pathlib import Path
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Running as EXE - PyInstaller extracts to _MEIPASS
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
icon_path = Path(sys._MEIPASS) / "icon.ico"
|
||||
else:
|
||||
icon_path = Path(sys.executable).parent / "icon.ico"
|
||||
else:
|
||||
# Running as script
|
||||
icon_path = Path(__file__).parent.parent.parent / "icon.ico"
|
||||
|
||||
if icon_path.exists():
|
||||
self.setWindowIcon(QIcon(str(icon_path)))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Central widget
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
# Main layout
|
||||
main_layout = QVBoxLayout(central_widget)
|
||||
|
||||
# Create splitter for 3-column layout
|
||||
splitter = QSplitter(Qt.Horizontal)
|
||||
|
||||
# Left column: Series list
|
||||
self.series_list_widget = self._create_series_list()
|
||||
splitter.addWidget(self.series_list_widget)
|
||||
|
||||
# Middle column: Episode list
|
||||
self.episode_list_widget = self._create_episode_list()
|
||||
splitter.addWidget(self.episode_list_widget)
|
||||
|
||||
# Right column: Series info
|
||||
self.info_widget = self._create_info_panel()
|
||||
splitter.addWidget(self.info_widget)
|
||||
|
||||
# Set initial splitter sizes (30% - 40% - 30%)
|
||||
splitter.setSizes([400, 600, 400])
|
||||
|
||||
main_layout.addWidget(splitter)
|
||||
|
||||
# Status bar
|
||||
self.status_bar = QStatusBar()
|
||||
self.setStatusBar(self.status_bar)
|
||||
self.status_label = QLabel("Bereit")
|
||||
self.last_update_label = QLabel("Letztes Update: Nie")
|
||||
self.new_episodes_label = QLabel("Neue Folgen: 0")
|
||||
self.status_bar.addWidget(self.status_label)
|
||||
self.status_bar.addPermanentWidget(self.new_episodes_label)
|
||||
self.status_bar.addPermanentWidget(self.last_update_label)
|
||||
|
||||
# Menu bar
|
||||
self._create_menu_bar()
|
||||
|
||||
def _create_series_list(self) -> QWidget:
|
||||
"""Create series list widget"""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout(widget)
|
||||
|
||||
# Title
|
||||
title = QLabel("Serien")
|
||||
title.setStyleSheet("font-weight: bold; font-size: 14px;")
|
||||
layout.addWidget(title)
|
||||
|
||||
# List widget
|
||||
self.series_list = QListWidget()
|
||||
self.series_list.currentItemChanged.connect(self.on_series_selected)
|
||||
self.series_list.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.series_list.customContextMenuRequested.connect(self.show_series_context_menu)
|
||||
layout.addWidget(self.series_list)
|
||||
|
||||
# Add series button
|
||||
add_btn = QPushButton("+ Serie hinzufügen")
|
||||
add_btn.clicked.connect(self.add_series)
|
||||
layout.addWidget(add_btn)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_episode_list(self) -> QWidget:
|
||||
"""Create episode list widget"""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout(widget)
|
||||
|
||||
# Title
|
||||
title = QLabel("Folgen")
|
||||
title.setStyleSheet("font-weight: bold; font-size: 14px;")
|
||||
layout.addWidget(title)
|
||||
|
||||
# Table widget
|
||||
self.episode_table = QTableWidget()
|
||||
self.episode_table.setColumnCount(5)
|
||||
self.episode_table.setHorizontalHeaderLabels(["Nr.", "Staffel", "Folge", "Titel", "Datum"])
|
||||
self.episode_table.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch) # Titel column stretches
|
||||
self.episode_table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||
self.episode_table.setEditTriggers(QTableWidget.NoEditTriggers)
|
||||
self.episode_table.verticalHeader().setVisible(False) # Hide row numbers (1, 2, 3, 4...)
|
||||
layout.addWidget(self.episode_table)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_info_panel(self) -> QWidget:
|
||||
"""Create series info panel"""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout(widget)
|
||||
|
||||
# Title
|
||||
title = QLabel("Informationen")
|
||||
title.setStyleSheet("font-weight: bold; font-size: 14px;")
|
||||
layout.addWidget(title)
|
||||
|
||||
# Info group
|
||||
info_group = QGroupBox("Serie")
|
||||
info_layout = QVBoxLayout(info_group)
|
||||
|
||||
self.info_title = QLabel("Keine Serie ausgewählt")
|
||||
self.info_title.setWordWrap(True)
|
||||
self.info_title.setStyleSheet("font-weight: bold;")
|
||||
info_layout.addWidget(self.info_title)
|
||||
|
||||
self.info_seasons = QLabel("")
|
||||
info_layout.addWidget(self.info_seasons)
|
||||
|
||||
self.info_episodes = QLabel("")
|
||||
info_layout.addWidget(self.info_episodes)
|
||||
|
||||
self.info_link = QLabel("")
|
||||
self.info_link.setOpenExternalLinks(True)
|
||||
self.info_link.setTextFormat(Qt.RichText)
|
||||
self.info_link.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
||||
info_layout.addWidget(self.info_link)
|
||||
|
||||
info_layout.addStretch()
|
||||
layout.addWidget(info_group)
|
||||
|
||||
# Seasons group
|
||||
seasons_group = QGroupBox("Staffeln")
|
||||
seasons_layout = QVBoxLayout(seasons_group)
|
||||
|
||||
self.seasons_list = QListWidget()
|
||||
self.seasons_list.currentItemChanged.connect(self.on_season_selected)
|
||||
seasons_layout.addWidget(self.seasons_list)
|
||||
|
||||
layout.addWidget(seasons_group)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_menu_bar(self):
|
||||
"""Create menu bar"""
|
||||
menubar = self.menuBar()
|
||||
|
||||
# File menu
|
||||
file_menu = menubar.addMenu("Datei")
|
||||
|
||||
add_action = QAction("Serie hinzufügen", self)
|
||||
add_action.triggered.connect(self.add_series)
|
||||
file_menu.addAction(add_action)
|
||||
|
||||
file_menu.addSeparator()
|
||||
|
||||
exit_action = QAction("Beenden", self)
|
||||
exit_action.triggered.connect(self.close)
|
||||
file_menu.addAction(exit_action)
|
||||
|
||||
# Series menu
|
||||
series_menu = menubar.addMenu("Serien")
|
||||
|
||||
update_action = QAction("Aktualisieren", self)
|
||||
update_action.triggered.connect(self.update_current_series)
|
||||
series_menu.addAction(update_action)
|
||||
|
||||
update_all_action = QAction("Alle aktualisieren", self)
|
||||
update_all_action.triggered.connect(self.update_all_series)
|
||||
series_menu.addAction(update_all_action)
|
||||
|
||||
# Settings menu
|
||||
settings_menu = menubar.addMenu("Einstellungen")
|
||||
|
||||
options_action = QAction("Optionen", self)
|
||||
options_action.triggered.connect(self.show_options)
|
||||
settings_menu.addAction(options_action)
|
||||
|
||||
# Help menu
|
||||
help_menu = menubar.addMenu("Hilfe")
|
||||
|
||||
about_action = QAction("Über", self)
|
||||
about_action.triggered.connect(self.show_about)
|
||||
help_menu.addAction(about_action)
|
||||
|
||||
def load_series_list(self):
|
||||
"""Load all series into the list"""
|
||||
self.series_list.clear()
|
||||
series_list = self.db.get_all_series()
|
||||
|
||||
for series in series_list:
|
||||
# Check if series has future episodes
|
||||
has_new = self.db.has_future_episodes(series.id)
|
||||
title = f"⭐️ {series.title}" if has_new else series.title
|
||||
self.series_list.addItem(title)
|
||||
|
||||
self.status_label.setText(f"{len(series_list)} Serien geladen")
|
||||
|
||||
def on_series_selected(self, current, previous):
|
||||
"""Handle series selection"""
|
||||
if not current:
|
||||
return
|
||||
|
||||
series_title = current.text()
|
||||
# Remove star emoji if present
|
||||
series_title = series_title.replace("⭐️ ", "")
|
||||
|
||||
series_list = self.db.get_all_series()
|
||||
self.current_series = next((s for s in series_list if s.title == series_title), None)
|
||||
|
||||
if self.current_series:
|
||||
self.load_series_info()
|
||||
self.load_seasons_list()
|
||||
# Show recent episodes automatically
|
||||
self.load_recent_episodes()
|
||||
|
||||
def load_series_info(self):
|
||||
"""Load series information panel"""
|
||||
if not self.current_series:
|
||||
return
|
||||
|
||||
self.info_title.setText(self.current_series.title)
|
||||
|
||||
seasons = self.db.get_seasons_by_series(self.current_series.id)
|
||||
self.info_seasons.setText(f"Staffeln: {len(seasons)}")
|
||||
|
||||
episode_count = self.db.get_episode_count(self.current_series.id)
|
||||
self.info_episodes.setText(f"Folgen: {episode_count}")
|
||||
|
||||
self.info_link.setText(f'<a href="{self.current_series.url}">fernsehserien.de öffnen</a>')
|
||||
|
||||
# Update last update time
|
||||
if self.current_series.last_updated:
|
||||
last_update_str = self.current_series.last_updated.strftime("%d.%m.%Y %H:%M")
|
||||
self.last_update_label.setText(f"Letztes Update: {last_update_str}")
|
||||
|
||||
def load_seasons_list(self):
|
||||
"""Load seasons list"""
|
||||
if not self.current_series:
|
||||
return
|
||||
|
||||
self.seasons_list.clear()
|
||||
|
||||
# Add "Neuste Folgen" as first item
|
||||
self.seasons_list.addItem("Neuste Folgen")
|
||||
|
||||
# Add regular seasons
|
||||
seasons = self.db.get_seasons_by_series(self.current_series.id)
|
||||
|
||||
for season in seasons:
|
||||
self.seasons_list.addItem(season.name)
|
||||
|
||||
# Auto-select "Neuste Folgen" by default
|
||||
self.seasons_list.setCurrentRow(0)
|
||||
|
||||
def on_season_selected(self, current, previous):
|
||||
"""Handle season selection"""
|
||||
if not current or not self.current_series:
|
||||
return
|
||||
|
||||
season_name = current.text()
|
||||
|
||||
# Check if "Neuste Folgen" was selected
|
||||
if season_name == "Neuste Folgen":
|
||||
self.current_season = None # No specific season
|
||||
self.load_recent_episodes()
|
||||
return
|
||||
|
||||
# Regular season selection
|
||||
seasons = self.db.get_seasons_by_series(self.current_series.id)
|
||||
self.current_season = next((s for s in seasons if s.name == season_name), None)
|
||||
|
||||
if self.current_season:
|
||||
self.load_episodes()
|
||||
|
||||
def load_recent_episodes(self):
|
||||
"""Load 20 most recent episodes for current series"""
|
||||
if not self.current_series:
|
||||
return
|
||||
|
||||
recent_episodes = self.db.get_recent_episodes(self.current_series.id, limit=20)
|
||||
self.episode_table.setRowCount(len(recent_episodes))
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
for row, (season, episode) in enumerate(recent_episodes):
|
||||
# Nr. (fortlaufende Gesamtnummer)
|
||||
nr_text = str(episode.episode_number) if episode.episode_number else "—"
|
||||
nr_item = QTableWidgetItem(nr_text)
|
||||
self.episode_table.setItem(row, 0, nr_item)
|
||||
|
||||
# Staffel
|
||||
season_item = QTableWidgetItem(season.name)
|
||||
self.episode_table.setItem(row, 1, season_item)
|
||||
|
||||
# Folge (Episodennummer der Staffel)
|
||||
episode_item = QTableWidgetItem(episode.episode_code)
|
||||
self.episode_table.setItem(row, 2, episode_item)
|
||||
|
||||
# Title
|
||||
title_item = QTableWidgetItem(episode.title)
|
||||
self.episode_table.setItem(row, 3, title_item)
|
||||
|
||||
# Date
|
||||
date_str = episode.comparison_date.strftime("%d.%m.%Y") if episode.comparison_date else "—"
|
||||
date_item = QTableWidgetItem(date_str)
|
||||
self.episode_table.setItem(row, 4, date_item)
|
||||
|
||||
# Highlight future episodes in green
|
||||
highlight_enabled = self.db.get_setting("highlight_future", "true") == "true"
|
||||
if highlight_enabled and episode.comparison_date and episode.comparison_date > now:
|
||||
green = QColor(200, 255, 200)
|
||||
nr_item.setBackground(green)
|
||||
season_item.setBackground(green)
|
||||
episode_item.setBackground(green)
|
||||
title_item.setBackground(green)
|
||||
date_item.setBackground(green)
|
||||
|
||||
def load_episodes(self):
|
||||
"""Load episodes for current season"""
|
||||
if not self.current_season:
|
||||
return
|
||||
|
||||
episodes = self.db.get_episodes_by_season(self.current_season.id)
|
||||
self.episode_table.setRowCount(len(episodes))
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
for row, episode in enumerate(episodes):
|
||||
# Nr. (episode_number from fernsehserien.de)
|
||||
nr_text = str(episode.episode_number) if episode.episode_number else "—"
|
||||
nr_item = QTableWidgetItem(nr_text)
|
||||
self.episode_table.setItem(row, 0, nr_item)
|
||||
|
||||
# Staffel (current season name)
|
||||
season_item = QTableWidgetItem(self.current_season.name)
|
||||
self.episode_table.setItem(row, 1, season_item)
|
||||
|
||||
# Folge (episode code)
|
||||
episode_item = QTableWidgetItem(episode.episode_code)
|
||||
self.episode_table.setItem(row, 2, episode_item)
|
||||
|
||||
# Title
|
||||
title_item = QTableWidgetItem(episode.title)
|
||||
self.episode_table.setItem(row, 3, title_item)
|
||||
|
||||
# Date
|
||||
date_str = episode.comparison_date.strftime("%d.%m.%Y") if episode.comparison_date else "—"
|
||||
date_item = QTableWidgetItem(date_str)
|
||||
self.episode_table.setItem(row, 4, date_item)
|
||||
|
||||
# Highlight future episodes in green
|
||||
highlight_enabled = self.db.get_setting("highlight_future", "true") == "true"
|
||||
if highlight_enabled and episode.comparison_date and episode.comparison_date > now:
|
||||
green = QColor(200, 255, 200)
|
||||
nr_item.setBackground(green)
|
||||
season_item.setBackground(green)
|
||||
episode_item.setBackground(green)
|
||||
title_item.setBackground(green)
|
||||
date_item.setBackground(green)
|
||||
|
||||
def show_series_context_menu(self, position):
|
||||
"""Show context menu for series list"""
|
||||
menu = QMenu()
|
||||
|
||||
update_action = QAction("Aktualisieren", self)
|
||||
update_action.triggered.connect(self.update_current_series)
|
||||
menu.addAction(update_action)
|
||||
|
||||
settings_action = QAction("Einstellungen", self)
|
||||
settings_action.triggered.connect(self.show_series_settings)
|
||||
menu.addAction(settings_action)
|
||||
|
||||
remove_action = QAction("Entfernen", self)
|
||||
remove_action.triggered.connect(self.remove_current_series)
|
||||
menu.addAction(remove_action)
|
||||
|
||||
menu.exec_(self.series_list.mapToGlobal(position))
|
||||
|
||||
def add_series(self):
|
||||
"""Add a new series"""
|
||||
from .options_dialog import OptionsDialog
|
||||
dialog = OptionsDialog(self, self.db)
|
||||
if dialog.exec_():
|
||||
self.load_series_list()
|
||||
|
||||
def update_current_series(self):
|
||||
"""Update currently selected series"""
|
||||
if not self.current_series:
|
||||
QMessageBox.warning(self, "Warnung", "Bitte wählen Sie zuerst eine Serie aus")
|
||||
return
|
||||
|
||||
from ..scraper.browser_scraper import BrowserScraper, SeriesUpdater
|
||||
from ..utils.threading import UpdateWorker
|
||||
from .widgets import ProgressDialog, UpdateResultDialog
|
||||
|
||||
# Create progress dialog
|
||||
progress = ProgressDialog(self, "Serie aktualisieren")
|
||||
progress.set_determinate() # Use determinate mode for progress bar
|
||||
progress.show()
|
||||
|
||||
# Create worker
|
||||
scraper = BrowserScraper()
|
||||
|
||||
def do_update():
|
||||
# Progress callback that will be called from the worker thread
|
||||
def progress_callback(percent, message):
|
||||
self.worker.signals.progress.emit(percent, message)
|
||||
|
||||
updater = SeriesUpdater(self.db, scraper, progress_callback=progress_callback)
|
||||
return updater.update_series(self.current_series.id)
|
||||
|
||||
self.worker = UpdateWorker(do_update)
|
||||
|
||||
def on_progress(percent, message):
|
||||
progress.set_progress(percent, message)
|
||||
|
||||
def on_finished(stats):
|
||||
progress.close()
|
||||
UpdateResultDialog(self, stats).exec_()
|
||||
# Reload UI
|
||||
self.load_series_info()
|
||||
self.load_seasons_list()
|
||||
if self.current_season:
|
||||
self.load_episodes()
|
||||
self.worker = None # Clear worker reference
|
||||
|
||||
def on_error(error, traceback):
|
||||
progress.close()
|
||||
QMessageBox.critical(self, "Fehler", f"Update fehlgeschlagen:\n{error}")
|
||||
self.worker = None # Clear worker reference
|
||||
|
||||
self.worker.signals.progress.connect(on_progress)
|
||||
self.worker.signals.finished.connect(on_finished)
|
||||
self.worker.signals.error.connect(on_error)
|
||||
self.worker.start()
|
||||
|
||||
def update_all_series(self):
|
||||
"""Update all series"""
|
||||
all_series = self.db.get_all_series()
|
||||
|
||||
if not all_series:
|
||||
QMessageBox.information(self, "Info", "Keine Serien vorhanden")
|
||||
return
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Alle Serien aktualisieren",
|
||||
f"Möchten Sie alle {len(all_series)} Serien aktualisieren?\nDies kann einige Minuten dauern.",
|
||||
QMessageBox.Yes | QMessageBox.No
|
||||
)
|
||||
|
||||
if reply != QMessageBox.Yes:
|
||||
return
|
||||
|
||||
from ..scraper.browser_scraper import BrowserScraper, SeriesUpdater
|
||||
from ..utils.threading import UpdateWorker
|
||||
from .widgets import ProgressDialog, UpdateResultDialog
|
||||
|
||||
# Create progress dialog
|
||||
progress = ProgressDialog(self, "Alle Serien aktualisieren")
|
||||
progress.set_determinate()
|
||||
progress.show()
|
||||
|
||||
# Create worker
|
||||
scraper = BrowserScraper()
|
||||
|
||||
def do_update_all():
|
||||
total_stats = {
|
||||
'new_seasons': 0,
|
||||
'new_episodes': 0,
|
||||
'updated_episodes': 0,
|
||||
'unchanged': 0
|
||||
}
|
||||
|
||||
total_series = len(all_series)
|
||||
for idx, series in enumerate(all_series):
|
||||
try:
|
||||
# Progress callback for individual series
|
||||
def progress_callback(percent, message):
|
||||
# Calculate overall progress: each series gets an equal portion
|
||||
overall_percent = int((idx / total_series) * 100 + (percent / total_series))
|
||||
overall_message = f"[{idx + 1}/{total_series}] {series.title}: {message}"
|
||||
self.worker.signals.progress.emit(overall_percent, overall_message)
|
||||
|
||||
updater = SeriesUpdater(self.db, scraper, progress_callback=progress_callback)
|
||||
stats = updater.update_series(series.id)
|
||||
for key in total_stats:
|
||||
total_stats[key] += stats.get(key, 0)
|
||||
except Exception as e:
|
||||
logger.error(f"Error updating {series.title}: {e}")
|
||||
|
||||
return total_stats
|
||||
|
||||
self.worker = UpdateWorker(do_update_all)
|
||||
|
||||
def on_progress(percent, message):
|
||||
progress.set_progress(percent, message)
|
||||
|
||||
def on_finished(stats):
|
||||
progress.close()
|
||||
UpdateResultDialog(self, stats).exec_()
|
||||
# Reload UI
|
||||
self.load_series_list()
|
||||
if self.current_series:
|
||||
self.load_series_info()
|
||||
self.load_seasons_list()
|
||||
if self.current_season:
|
||||
self.load_episodes()
|
||||
self.worker = None # Clear worker reference
|
||||
|
||||
def on_error(error, traceback):
|
||||
progress.close()
|
||||
QMessageBox.critical(self, "Fehler", f"Update fehlgeschlagen:\n{error}")
|
||||
self.worker = None # Clear worker reference
|
||||
|
||||
self.worker.signals.progress.connect(on_progress)
|
||||
self.worker.signals.finished.connect(on_finished)
|
||||
self.worker.signals.error.connect(on_error)
|
||||
self.worker.start()
|
||||
|
||||
def remove_current_series(self):
|
||||
"""Remove currently selected series"""
|
||||
if not self.current_series:
|
||||
return
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Serie entfernen",
|
||||
f"Möchten Sie '{self.current_series.title}' wirklich entfernen?",
|
||||
QMessageBox.Yes | QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
self.db.delete_series(self.current_series.id)
|
||||
self.current_series = None
|
||||
self.current_season = None
|
||||
self.load_series_list()
|
||||
self.episode_table.setRowCount(0)
|
||||
self.seasons_list.clear()
|
||||
self.info_title.setText("Keine Serie ausgewählt")
|
||||
|
||||
def show_series_settings(self):
|
||||
"""Show settings for current series"""
|
||||
QMessageBox.information(self, "Hinweis", "Einstellungen werden noch implementiert")
|
||||
|
||||
def show_options(self):
|
||||
"""Show options dialog"""
|
||||
dialog = OptionsDialog(self, self.db)
|
||||
if dialog.exec_():
|
||||
self.load_series_list()
|
||||
|
||||
def show_about(self):
|
||||
"""Show about dialog"""
|
||||
QMessageBox.about(
|
||||
self,
|
||||
"Über Serien-Checker",
|
||||
"Serien-Checker v2.0\n\n"
|
||||
"TV-Serien Episode Tracker\n"
|
||||
"Datenquelle: fernsehserien.de"
|
||||
)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle window close event"""
|
||||
# Wait for worker thread to finish if running
|
||||
if self.worker and self.worker.isRunning():
|
||||
logger.info("Waiting for worker thread to finish...")
|
||||
self.worker.wait(5000) # Wait max 5 seconds
|
||||
if self.worker.isRunning():
|
||||
logger.warning("Worker thread did not finish, terminating...")
|
||||
self.worker.terminate()
|
||||
self.worker.wait()
|
||||
event.accept()
|
||||
Reference in New Issue
Block a user