From 171bc1676a1e654abfecbca4af365fcc940f7d0d Mon Sep 17 00:00:00 2001 From: Thomas Peetz Date: Thu, 6 Feb 2025 16:33:15 +0100 Subject: [PATCH] refactor project by using enums for recurring strings --- python/kontor-gui/gui/comic_window.py | 6 +- python/kontor-gui/gui/media_window.py | 2 +- python/kontor-gui/gui/meta_data_window.py | 7 +- python/kontor-gui/gui/model_config.py | 7 +- python/kontor-gui/gui/table_model.py | 96 ++++++++++--------- .../kontor-schema/kontor_schema/__init__.py | 2 +- 6 files changed, 65 insertions(+), 55 deletions(-) diff --git a/python/kontor-gui/gui/comic_window.py b/python/kontor-gui/gui/comic_window.py index 5f465d6..c4a9064 100644 --- a/python/kontor-gui/gui/comic_window.py +++ b/python/kontor-gui/gui/comic_window.py @@ -1,5 +1,6 @@ from PySide6.QtCore import Signal, QSortFilterProxyModel -from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QTabWidget, QMenu, QTableView, QMdiSubWindow +from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QTabWidget, QMenu, QTableView, QMdiSubWindow, \ + QHeaderView from gui.model_config import KontorModelConfig from gui.table_model import KontorTableModel @@ -53,10 +54,11 @@ class ComicWindow(QMdiSubWindow): self.data_views.append(model) data_tab.setLayout(layout) table_view = QTableView() + header = table_view.horizontalHeader() + header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) proxy_model = QSortFilterProxyModel() proxy_model.setSourceModel(model) table_view.setSortingEnabled(True) - #table_view.setModel(model) table_view.setModel(proxy_model) layout.addLayout(table_config.get_filter_layout()) layout.addWidget(table_view) diff --git a/python/kontor-gui/gui/media_window.py b/python/kontor-gui/gui/media_window.py index 1d9455f..a88e46c 100644 --- a/python/kontor-gui/gui/media_window.py +++ b/python/kontor-gui/gui/media_window.py @@ -57,9 +57,9 @@ class MediaWindow(QMdiSubWindow): proxy_model = QSortFilterProxyModel() proxy_model.setSourceModel(model) table_view.setSortingEnabled(True) - #table_view.setModel(model) table_view.setModel(proxy_model) layout.addLayout(table_config.get_filter_layout()) layout.addWidget(table_view) model.refresh() + table_view.resizeColumnToContents(0) return data_tab diff --git a/python/kontor-gui/gui/meta_data_window.py b/python/kontor-gui/gui/meta_data_window.py index 793fa16..e9546fd 100644 --- a/python/kontor-gui/gui/meta_data_window.py +++ b/python/kontor-gui/gui/meta_data_window.py @@ -1,5 +1,6 @@ from PySide6.QtCore import Signal, QSortFilterProxyModel -from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QTabWidget, QMenu, QTableView, QMdiSubWindow +from PySide6.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QTabWidget, QMenu, QTableView, QMdiSubWindow, \ + QHeaderView from gui.model_config import KontorModelConfig from gui.table_model import KontorTableModel @@ -57,9 +58,11 @@ class MetaDataWindow(QMdiSubWindow): proxy_model = QSortFilterProxyModel() proxy_model.setSourceModel(model) table_view.setSortingEnabled(True) - #table_view.setModel(model) + # header = table_view.horizontalHeader() + # header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) table_view.setModel(proxy_model) layout.addLayout(table_config.get_filter_layout()) layout.addWidget(table_view) model.refresh() + table_view.resizeColumnToContents(0) return data_tab diff --git a/python/kontor-gui/gui/model_config.py b/python/kontor-gui/gui/model_config.py index 990d3e4..1259fc3 100644 --- a/python/kontor-gui/gui/model_config.py +++ b/python/kontor-gui/gui/model_config.py @@ -1,6 +1,5 @@ from PySide6.QtWidgets import QHBoxLayout, QCheckBox, QMdiSubWindow -from kontor_schema import KontorDB -from kontor_schema.database import ColumnEntry +from kontor_schema import KontorDB, ColumnEntry class KontorModelConfig: @@ -30,7 +29,7 @@ class KontorModelConfig: # print(self.filter["download"].isChecked()) for column, filter_info in self.filter.items(): # print(column, filter_info) - if filter_info['widget'].isChecked(): + if filter_info[ColumnEntry.COLUMN_WIDGET].isChecked(): _filters[column] = True # print(f"{filter_rule=}") # self.log.info("filters -> %s", _filters) @@ -49,7 +48,7 @@ class KontorModelConfig: filter_checkbox = QCheckBox() filter_checkbox.setText(filter_info[ColumnEntry.COLUMN_LABEL]) filter_checkbox.checkStateChanged.connect(self.main_window.refresh) - self.filter[column]['widget'] = filter_checkbox + self.filter[column][ColumnEntry.COLUMN_WIDGET] = filter_checkbox filter_layout.addWidget(filter_checkbox) filter_layout.addStretch() # self.log.info("get_filter_layout: %s", self.filter) diff --git a/python/kontor-gui/gui/table_model.py b/python/kontor-gui/gui/table_model.py index 59340a9..ae23001 100644 --- a/python/kontor-gui/gui/table_model.py +++ b/python/kontor-gui/gui/table_model.py @@ -1,12 +1,45 @@ from datetime import datetime +from typing import Any from PySide6.QtCore import QAbstractTableModel, QModelIndex -from PySide6.QtGui import Qt +from PySide6.QtGui import Qt, QColor from kontor_schema.database import ColumnEntry from .model_config import KontorModelConfig +def get_display_value(value: Any, column_config: dict, window) -> str: + if isinstance(value, datetime): + return value.strftime("%Y-%m-%d %M:%M:%S") + if column_config[ColumnEntry.COLUMN_TYPE] == 'BOOLEAN': + if value == 1: + return window.tick + else: + return window.cross + if value is None: + return "" + # window.log.info(f"unknown type: {column_config[ColumnEntry.COLUMN_TYPE]} - {type(value)}") + return str(value) + + +def get_edit_value(value, column_config, window): + # window.log.info(f"edit value {value}") + return str(value) + + +def get_decoration_value(value: Any, column_config: dict, window): + if column_config[ColumnEntry.COLUMN_TYPE] == 'BOOLEAN': + if value == 1: + return window.tick + else: + return window.cross + + +def get_background_value(value: Any, column_config: dict, window): + if value is None: + return QColor('lightgrey') + + class KontorTableModel(QAbstractTableModel): def __init__(self, model_config: KontorModelConfig): @@ -46,68 +79,41 @@ class KontorTableModel(QAbstractTableModel): if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole: return self._config.header[col][ColumnEntry.COLUMN_LABEL] if orientation == Qt.Orientation.Vertical and role == Qt.ItemDataRole.DisplayRole: - return str(col+1) + return str(col + 1) def data(self, index, role=Qt.ItemDataRole.DisplayRole): if self._data is None: return None value = self._data[index.row()][index.column()] - # print('{}:: {}:: {}: {}'.format(index, role, value, type(value))) - if role == Qt.ItemDataRole.DisplayRole or role == Qt.ItemDataRole.EditRole: - if isinstance(value, datetime): - return value.strftime("%Y-%m-%d %M:%M:%S") - if isinstance(value, str): - return value - if isinstance(value, bytes): - if value == b'\x01': - return self._config.main_window.tick - else: - return self._config.main_window.cross - if isinstance(value, int): - # print('{}:: {}: {}'.format(index, value, type(value))) - if value == 1: - return self._config.main_window.tick - else: - return self._config.main_window.cross - if isinstance(value, bool): - if value: - return self._config.main_window.tick - else: - return self._config.main_window.cross - return str(value) - if role == Qt.ItemDataRole.DecorationRole: - if isinstance(value, bytes): - if value == b'\x01': - return self._config.main_window.tick - else: - return self._config.main_window.cross - if isinstance(value, int): - if value == 1: - return self._config.main_window.tick - else: - return self._config.main_window.cross - if isinstance(value, bool): - if value: - return self._config.main_window.tick - else: - return self._config.main_window.cross + # print('{}:: {}:: {}:: {}: {}'.format(index, role, self._config.header[index.column()][ColumnEntry.COLUMN_TYPE], value, type(value))) + match role: + case Qt.ItemDataRole.DisplayRole: + return get_display_value(value, self._config.header[index.column()], self._config.main_window) + case Qt.ItemDataRole.EditRole: + return get_edit_value(value, self._config.header[index.column()], self._config.main_window) + case Qt.ItemDataRole.DecorationRole: + return get_decoration_value(value, self._config.header[index.column()], self._config.main_window) + case Qt.ItemDataRole.BackgroundRole: + return get_background_value(value, self._config.header[index.column()], self._config.main_window) def columnCount(self, index=QModelIndex()): # 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) + def setData(self, index, value, role=Qt.ItemDataRole.EditRole) -> bool: + # self._config.log.info(f"{index}: {role}") if role == Qt.ItemDataRole.EditRole: self._data[index.row()][index.column()] = value - # print(self._data[index.row()][index.column()]) + # self._config.log.info(f"{index.row()}-{index.column()}: {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 def flags(self, index): + if self._config.header[index.column()][ColumnEntry.COLUMN_NAME] == 'id': + return Qt.ItemFlag.ItemIsEnabled return Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsUserTristate diff --git a/python/kontor-schema/kontor_schema/__init__.py b/python/kontor-schema/kontor_schema/__init__.py index 827b402..2f0718b 100644 --- a/python/kontor-schema/kontor_schema/__init__.py +++ b/python/kontor-schema/kontor_schema/__init__.py @@ -7,4 +7,4 @@ from .metadata import MetaDataTable, MetaDataColumn from .tysc import Card, CardSet, Sport, Team, FieldPosition, Rooster, Player, Vendor from .media import MediaFile, MediaArticle, MediaVideo from .base import Base -from .database import KontorDB +from .database import KontorDB, ColumnEntry