diff --git a/python/kontor-gui/gui/comic_window.py b/python/kontor-gui/gui/comic_window.py index 5d9b747..b9f9b9f 100644 --- a/python/kontor-gui/gui/comic_window.py +++ b/python/kontor-gui/gui/comic_window.py @@ -1,42 +1,49 @@ -from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QTabWidget, QMenu, QTableView +from PySide6.QtCore import Signal +from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QTabWidget, QMenu, QTableView, QMdiSubWindow from gui.model_config import KontorModelConfig from gui.table_model import KontorTableModel -class ComicWindow(QWidget): +class ComicWindow(QMdiSubWindow): + closed = Signal() + def __init__(self, main_window): super().__init__() - self.statusBar = main_window.statusBar - self._main_window = main_window self.data_views = list() - # self._create_menubar() + self._main_window = main_window + self.log = main_window.log self._init_gui() + self.tick = main_window.tick + self.cross = main_window.cross def _init_gui(self): - self.central_widget = QWidget() + self.setWindowTitle("Comics") + self.setWidget(QWidget()) layout = QVBoxLayout() - #self.central_widget.setLayout(parent_layout) self.tabs = QTabWidget() self.tabs.addTab(self.generate_data_tab("comic"), "Comics") self.tabs.addTab(self.generate_data_tab("publisher"), "Publisher") self.tabs.currentChanged.connect(self._tab_changed) - # label.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.addWidget(self.tabs) self.setLayout(layout) - # self.setCentralWidget(self.central_widget) + self.setWidget(self.tabs) - # def _create_menubar(self): - # menu_bar = self.menuBar() - # comic_menu = QMenu("Comic") - # menu_bar.addMenu(comic_menu) + def closeEvent(self, event): + self.closed.emit() + super().closeEvent(event) + self._main_window.remove_sub_window('comic') def refresh(self): + # self.log.info("refresh") self.data_views[self.tabs.currentIndex()].refresh() def _tab_changed(self, tab_index): self.data_views[tab_index].refresh() + def update_status(self, message): + self._main_window.update_status(message) + def generate_data_tab(self, table_name): data_tab = QWidget() diff --git a/python/kontor-gui/gui/main_window.py b/python/kontor-gui/gui/main_window.py index 751795d..384723b 100644 --- a/python/kontor-gui/gui/main_window.py +++ b/python/kontor-gui/gui/main_window.py @@ -1,5 +1,5 @@ from PySide6.QtGui import QAction, QIcon, QGuiApplication -from PySide6.QtWidgets import QWidget, QVBoxLayout, QMenu, QMessageBox, QTabWidget, QTableView, QProgressBar +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 @@ -22,32 +22,39 @@ class MainWindow(QMainWindow): 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._setup_ui() + + + #self.tabs = QTabWidget() + #self.tabs.addTab(self.generate_data_tab("comic"), "Comics") + #self.tabs.addTab(self.generate_data_tab("media_file"), "MediaFile") + #self.tabs.currentChanged.connect(self._tab_changed) + #label.setAlignment(Qt.AlignmentFlag.AlignCenter) + #parent_layout.addWidget(self.tabs) + + self.setCentralWidget(self.central_widget) + + def _setup_ui(self): self.setWindowTitle("Kontor") - self.setMinimumSize(800, 500) + self.setMinimumSize(1200, 800) self._create_actions() + self.central_widget = QWidget() + # parent_layout = QVBoxLayout() + # self.central_widget.setLayout(parent_layout) + self.mdi_area = QMdiArea(self.central_widget) + self.mdi_area.setObjectName('mdi_area') + self.setCentralWidget(self.central_widget) self._create_menubar() self._create_toolbars() self.status_progress = QProgressBar() self.progress_update = ProgressUpdate(self.status_progress) self._create_statusbar() - - self.data = [] - self.filter = {} - self.kontor_db = KontorDB(engine, log) - self.log = log - - self.comic_window = ComicWindow(self) - self.central_widget = QWidget() - parent_layout = QVBoxLayout() - self.central_widget.setLayout(parent_layout) - self.tabs = QTabWidget() - self.tabs.addTab(self.generate_data_tab("comic"), "Comics") - self.tabs.addTab(self.generate_data_tab("media_file"), "MediaFile") - self.tabs.currentChanged.connect(self._tab_changed) - #label.setAlignment(Qt.AlignmentFlag.AlignCenter) - parent_layout.addWidget(self.tabs) - - self.setCentralWidget(self.central_widget) centerPoint = QGuiApplication.screens()[0].geometry().center() self.move(centerPoint - self.frameGeometry().center()) @@ -117,10 +124,26 @@ class MainWindow(QMainWindow): QMessageBox.about(self.central_widget, "Über Kontor", f"Python: 3.11\nKontor: 0.1.0") def show_comic_window(self): - if self.comic_window.isHidden(): - self.comic_window.show() + 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: - self.comic_window.hide() + comic = self._subwindows.pop('comic') + comic.close() + self.mdi_area.removeSubWindow(comic) + + 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) @@ -162,10 +185,17 @@ class MainWindow(QMainWindow): self.kontor_db.check_files() def refresh(self): - self.data[self.tabs.currentIndex()].refresh() + self.log.info("refresh") + for (_, window) in self._subwindows.items(): + window.refresh() + # def refresh(self): + # self.data[self.tabs.currentIndex()].refresh() - def _tab_changed(self, tab_index): - self.data[tab_index].refresh() + # def _tab_changed(self, tab_index): + # self.data[tab_index].refresh() + + def update_status(self, message, timeout=3000): + self.statusBar.showMessage(message, timeout=timeout) def generate_data_tab(self, table_name): data_tab = QWidget() @@ -181,3 +211,4 @@ class MainWindow(QMainWindow): layout.addWidget(table_view) model.refresh() return data_tab + diff --git a/python/kontor-gui/gui/model_config.py b/python/kontor-gui/gui/model_config.py index e791752..7aa05cc 100644 --- a/python/kontor-gui/gui/model_config.py +++ b/python/kontor-gui/gui/model_config.py @@ -1,4 +1,4 @@ -from PySide6.QtWidgets import QHBoxLayout, QCheckBox +from PySide6.QtWidgets import QHBoxLayout, QCheckBox, QMdiSubWindow from kontor_schema import KontorDB @@ -8,15 +8,23 @@ class KontorModelConfig: self.header = {} self.filter = {} self.main_window = main_window + self.log = main_window.log self._table_name = table_name self.kontor_db = kontor_db self.get_table_config() + def __str__(self): + return f"KontorModelConfig({self._table_name})" + def get_table_config(self): + # self.log.info("get_table_config %s", self) self.header = self.kontor_db.get_column_meta_data(self._table_name) self.filter = self.kontor_db.get_filters(self._table_name) + # self.log.info("headers: %s", self.header) + # self.log.info("%s filters: %s", self, self.filter) def filters(self) -> dict: + # self.log.info("%s filters: %s", self, self.filter) _filters = {} # print(self.filter["download"].isChecked()) for column, filter_info in self.filter.items(): @@ -24,18 +32,17 @@ class KontorModelConfig: if filter_info['widget'].isChecked(): _filters[column] = True # print(f"{filter_rule=}") + # self.log.info("filters -> %s", _filters) return _filters def get_data(self) -> list: - # data = self.kontor_db.get_data(self._table_name, self.header, self.get_filter()) - # data.clear() + # self.log.info("get_data") data = self.kontor_db.data(self._table_name, self.header, self.filters()) - # print(f"KontorModelConfig.get_data: {len(data)}") - # comics = self.kontor_db.session.query(Comic).all() - # print(f'{len(comics)} Comics loaded') + # self.log.info("get_data: %d %s", len(data), data) return data def get_filter_layout(self) -> QHBoxLayout: + # self.log.info("get_filter_layout: %s", self.filter) filter_layout = QHBoxLayout() for column, filter_info in self.filter.items(): filter_checkbox = QCheckBox() @@ -44,4 +51,5 @@ class KontorModelConfig: self.filter[column]['widget'] = filter_checkbox filter_layout.addWidget(filter_checkbox) filter_layout.addStretch() + # self.log.info("get_filter_layout: %s", self.filter) return filter_layout diff --git a/python/kontor-gui/gui/table_model.py b/python/kontor-gui/gui/table_model.py index cd08ce1..6c7574b 100644 --- a/python/kontor-gui/gui/table_model.py +++ b/python/kontor-gui/gui/table_model.py @@ -13,8 +13,13 @@ class KontorTableModel(QAbstractTableModel): self._main_window = model_config.main_window self._config = model_config self._data = [] + self.log = model_config.log + + def __str__(self): + return f"KontorTableModel({self._config})" def refresh(self): + # self.log.info("refresh") data = self._config.get_data() count = 0 # print(data) @@ -27,9 +32,10 @@ class KontorTableModel(QAbstractTableModel): # print(data) # print(self._data) self.layoutChanged.emit() - self._main_window.statusBar.showMessage(f"{count} Einträge geladen", 3000) + self._main_window.update_status(f"{count} Einträge geladen") def rowCount(self, parent=QModelIndex()): + # self.log.info("rowCount %s: %d", self, len(self._data)) # The length of the outer list. if self._data is None: return 0 @@ -53,53 +59,51 @@ class KontorTableModel(QAbstractTableModel): return value if isinstance(value, bytes): if value == b'\x01': - return self._main_window.tick + return self._config.main_window.tick else: - return self._main_window.cross + return self._config.main_window.cross if isinstance(value, int): # print('{}:: {}: {}'.format(index, value, type(value))) if value == 1: - return self._main_window.tick + return self._config.main_window.tick else: - return self._main_window.cross + return self._config.main_window.cross if isinstance(value, bool): if value: - return self._main_window.tick + return self._config.main_window.tick else: - return self._main_window.cross + return self._config.main_window.cross return str(value) if role == Qt.ItemDataRole.DecorationRole: if isinstance(value, bytes): if value == b'\x01': - return self._main_window.tick + return self._config.main_window.tick else: - return self._main_window.cross + return self._config.main_window.cross if isinstance(value, int): if value == 1: - return self._main_window.tick + return self._config.main_window.tick else: - return self._main_window.cross + return self._config.main_window.cross if isinstance(value, bool): if value: - return self._main_window.tick + return self._config.main_window.tick else: - return self._main_window.cross + return self._config.main_window.cross def columnCount(self, index=QModelIndex()): - # The following takes the first sub-list, and returns - # the length (only works if all rows are an equal length) - # print(f"Header count: {len(self._config.get_header())}") + # self.log.info("rowCount %s: %d", self, len(self._config.header)) return len(self._config.header) def setData(self, index, value, role: int) -> bool: - print(index, role) + # print(index, role) if role == Qt.ItemDataRole.EditRole: self._data[index.row()][index.column()] = value - print(self._data[index.row()][index.column()]) + # print(self._data[index.row()][index.column()]) self.dataChanged.emit(index, index) return True if role == Qt.ItemDataRole.CheckStateRole: - print("role == Qt.ItemDataRole.CheckStateRole") + # print("role == Qt.ItemDataRole.CheckStateRole") checked = value == Qt.CheckState.Checked self._data[index.row()][index.column()] = checked return False diff --git a/python/kontor-schema/kontor_schema/__init__.py b/python/kontor-schema/kontor_schema/__init__.py index be7eea2..26fafd8 100644 --- a/python/kontor-schema/kontor_schema/__init__.py +++ b/python/kontor-schema/kontor_schema/__init__.py @@ -83,6 +83,7 @@ class KontorDB: filter(MetaDataTable.id == MetaDataColumn.table_id). filter(MetaDataTable.table_name == table_name). filter(MetaDataColumn.is_shown == 1).all()): + # self.log.info("get_column_meta_data: %s %s %d", column.column_name, column.column_label, column.column_order) meta_data[order] = {'column': column.column_name, 'label': column.column_label, 'order': column.column_order, 'ref_column': column.ref_column} order += 1 @@ -96,7 +97,8 @@ class KontorDB: 'ref_column': column.ref_column } order += 1 - return meta_data + # self.log.info("get_column_meta_data: %s", meta_data) + return meta_data def get_columns(self, table_name: str) -> dict: columns = {} @@ -131,6 +133,7 @@ class KontorDB: else: entries = session.scalars(select(table).filter_by(**filters)).all() for entry in entries: + # self.log.info("data: %s", entry) row = [] for order in columns.keys(): column_name = columns[order]['column'] @@ -142,6 +145,7 @@ class KontorDB: else: row.append(getattr(entry, column_name)) data.append(row) + # self.log.info("data: %s", data) return data def export_db(self, export_type: str, export_file_name: str) -> dict: @@ -259,7 +263,7 @@ class KontorDB: return existing_ids def add_entry(self, table_name: str, update_item: dict): - self.log.info("add entry to table %s with %s", table_name, update_item) + # self.log.info("add entry to table %s with %s", table_name, update_item) __session__ = sessionmaker(self.engine) with __session__() as session: add_item = self.registry[table_name]() @@ -270,7 +274,7 @@ class KontorDB: session.commit() def update_entry(self, table_name, current_id, update_item: dict) -> bool: - self.log.info("update entry to table %s", table_name) + # self.log.info("update entry to table %s", table_name) __session__ = sessionmaker(self.engine) with __session__() as session: existing_item = session.query(self.registry[table_name]).get(current_id) @@ -335,7 +339,7 @@ class KontorDB: def delete_entries(self): for (table_name, table) in self.registry.items(): - self.log.info("delete entries from table %s", table_name) + # self.log.info("delete entries from table %s", table_name) __session__ = sessionmaker(self.engine) with __session__() as session: items = session.query(table).all()