from PySide6.QtCore import Qt, QThreadPool from PySide6.QtGui import QAction, QIcon, QGuiApplication from PySide6.QtWidgets import QWidget, QVBoxLayout, QMenu, QMessageBox, QTabWidget, QTableView, QProgressBar, QMdiArea from PySide6.QtWidgets import QLabel, QMainWindow from sqlalchemy import Engine from kontor_schema import KontorDB from .comic_window import ComicWindow from .media_window import MediaWindow from .meta_data_window import MetaDataWindow from .progress import ProgressUpdate from .dialogs import ExportKontorDialog, ImportKontorDialog from .model_config import KontorModelConfig from .table_model import KontorTableModel from .worker import VideoDownloader class MainWindow(QMainWindow): def __init__(self, engine: Engine, log): super().__init__() self.downloader = None self.tick = QIcon('res/tick.png') self.cross = QIcon('res/cross.png') self.import_icon = QIcon("res/application-import.png") self.export_icon = QIcon("res/application-export.png") self.circle_icon = QIcon("res/arrow-circle-double.png") self.data = [] self.filter = {} self.kontor_db = KontorDB(engine, log) self.log = log self._subwindows = {} self.media_dir = "/data/media" self.dl_tool = "yt-dlp" self._setup_ui() def _setup_ui(self): self.setWindowTitle("Kontor") self.setMinimumSize(1200, 800) self._create_actions() self.mdi_area = QMdiArea() self.setCentralWidget(self.mdi_area) self.mdi_area.setObjectName('mdi_area') self.mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self._create_menubar() self._create_toolbars() self.status_progress = QProgressBar() self.progress_update = ProgressUpdate(self.status_progress) self._create_statusbar() center_point = QGuiApplication.screens()[0].geometry().center() self.move(center_point - self.frameGeometry().center()) def _create_actions(self): self.newAction = QAction("&New", self) self.aboutAction = QAction("&Über...", self) self.aboutAction.triggered.connect(self.about) self.showComicWindow = QAction("&Comic Window", self) self.showComicWindow.triggered.connect(self.show_comic_window) self.showTyscWindow = QAction("TYSC Window", self) self.showMediaWindow = QAction("&Media Window", self) self.showMediaWindow.triggered.connect(self.show_media_window) self.showMetaDataWindow = QAction("Meta Data Window", self) self.showMetaDataWindow.triggered.connect(self.show_meta_data_window) self.importAction = QAction(self.import_icon, "&Import", self) self.importAction.triggered.connect(self.import_from_file) self.exportAction = QAction(self.export_icon, "&Export", self) self.exportAction.triggered.connect(self.export_to_file) self.refreshAction = QAction(self.circle_icon, "&Refresh", self) self.refreshAction.triggered.connect(self.refresh) self.updateTitleAction = QAction("&Update Titles", self) self.updateTitleAction.triggered.connect(self.update_title) self.downloadAction = QAction("&Download Videos", self) self.downloadAction.triggered.connect(self.start_download) self.checkFileAction = QAction("&Check files", self) self.checkFileAction.triggered.connect(self.check_files) self.exitAction = QAction("&Beenden", self) self.exitAction.setShortcut("Alt+F4") self.exitAction.triggered.connect(self.close) def _create_menubar(self): menu_bar = self.menuBar() # File menu file_menu = QMenu("&Datei") menu_bar.addMenu(file_menu) file_menu.addAction(self.exitAction) # Kontor menu kontor_menu = QMenu("&Kontor") menu_bar.addMenu(kontor_menu) kontor_menu.addAction(self.importAction) kontor_menu.addAction(self.exportAction) comic_menu = QMenu("&Comic") comic_menu.addAction(self.showComicWindow) tysc_menu = QMenu("&TradeYourSportCards") media_file_menu = QMenu("&MediaFile") media_file_menu.addAction(self.updateTitleAction) media_file_menu.addAction(self.downloadAction) media_file_menu.addAction(self.checkFileAction) kontor_menu.addMenu(comic_menu) kontor_menu.addMenu(tysc_menu) kontor_menu.addMenu(media_file_menu) window_menu = QMenu("&Window") layouts_menu = QMenu("&Layouts") window_menu.addMenu(layouts_menu) window_menu.addAction(self.showComicWindow) window_menu.addAction(self.showMediaWindow) window_menu.addAction(self.showMetaDataWindow) menu_bar.addMenu(window_menu) # Help menu help_menu = QMenu("&Hilfe") menu_bar.addMenu(help_menu) help_menu.addAction(self.aboutAction) def _create_toolbars(self): # Kontor toolbar kontor_tool_bar = self.addToolBar("Kontor") kontor_tool_bar.addAction(self.importAction) kontor_tool_bar.addAction(self.exportAction) kontor_tool_bar.addAction(self.refreshAction) def _create_statusbar(self): self.statusBar = self.statusBar() self.statusBar.showMessage("Kontor ready", 6000) self.status_label = QLabel("") self.status_progress.setEnabled(False) self.statusBar.addPermanentWidget(self.status_progress) def about(self): QMessageBox.about(self, "Über Kontor", f"Python: 3.11\nKontor: 0.1.0") def show_comic_window(self): if 'comic' not in self._subwindows: comic = ComicWindow(self) comic.closed.connect(self.sub_window_closed) self._subwindows['comic'] = comic self.mdi_area.addSubWindow(comic) comic.show() else: comic = self._subwindows.pop('comic') comic.close() self.mdi_area.removeSubWindow(comic) def show_media_window(self): if 'media' not in self._subwindows: media = MediaWindow(self) media.closed.connect(self.sub_window_closed) self._subwindows['media'] = media self.mdi_area.addSubWindow(media) media.show() else: media = self._subwindows.pop('media') media.close() self.mdi_area.removeSubWindow(media) def show_meta_data_window(self): if 'meta_data' not in self._subwindows: meta_data = MetaDataWindow(self) meta_data.closed.connect(self.sub_window_closed) self._subwindows['meta_data'] = meta_data self.mdi_area.addSubWindow(meta_data) meta_data.show() else: meta_data = self._subwindows.pop('meta_data') meta_data.close() self.mdi_area.removeSubWindow(meta_data) def remove_sub_window(self, name: str): self.log.info("remove subwindow %s", name) if name in self._subwindows: window = self._subwindows.pop(name) window.close() self.mdi_area.removeSubWindow(window) def sub_window_closed(self): self.log.info("close subwindow") def import_from_file(self): import_dlg = ImportKontorDialog(self) if import_dlg.exec(): print(f"import DB from file {import_dlg.file_name}") self.kontor_db.import_db(import_dlg.file_name, False) else: print("do nothing for import") def export_to_file(self): export_dlg = ExportKontorDialog(self, self.kontor_db) if export_dlg.exec(): self.log.info(export_dlg.get_tables_to_export()) self.log.info(f"export DB to {export_dlg.file_name}") self.statusBar.showMessage(f"export DB to {export_dlg.file_name}", 3000) self.kontor_db.export_db(export_dlg.current_export_type, export_dlg.file_name) else: self.statusBar.showMessage("Export cancelled", 3000) def update_title(self): self.log.info("update title for table MediaFile") self.statusBar.showMessage("update title for table MediaFile", 3000) self.status_progress.setEnabled(True) self.kontor_db.update_titles() self.status_progress.setEnabled(False) self.refresh() def start_download(self): self.status_progress.setEnabled(True) self.statusBar.showMessage("download videos for table MediaFile", 3000) self.downloader = VideoDownloader(self.kontor_db, self.log) self.downloader.setTotalProgress.connect(self.status_progress.setMaximum) self.downloader.setCurrentProgress.connect(self.downloadProgress) self.downloader.succeeded.connect(self.downloadSucceeded) self.downloader.finished.connect(self.downloadFinished) self.downloader.start() def downloadProgress(self, value: int): self.status_progress.setValue(value) self.refresh() def downloadSucceeded(self): self.status_progress.setValue(self.status_progress.maximum()) self.statusBar.showMessage("Download succeeded", 3000) def downloadFinished(self): self.status_progress.setEnabled(False) del self.downloader def check_files(self): self.log.info("check files") self.statusBar.showMessage("check files for table MediaFile", 3000) self.kontor_db.check_files() def refresh(self): self.log.info("refresh") for (_, window) in self._subwindows.items(): window.refresh() def update_status(self, message, timeout=3000): self.statusBar.showMessage(message, timeout=timeout)