""" sn_basis/functions/qt_wrapper.py – zentrale Qt-Abstraktion (PyQt6 primär / PyQt5 Fallback / Mock) """ from typing import Optional, Type, Any, Callable # Globale Qt-Symbole (werden dynamisch gesetzt) QT_VERSION = 0 # 0 = Mock, 5 = PyQt5, 6 = PyQt6 YES: Optional[Any] = None NO: Optional[Any] = None CANCEL: Optional[Any] = None ICON_QUESTION: Optional[Any] = None QVariant: Type[Any] = object # Qt-Klassen (werden dynamisch gesetzt) QDockWidget: Type[Any] = object QMessageBox: Type[Any] = object QFileDialog: Type[Any] = object QProgressDialog: Type[Any] = object QEventLoop: Type[Any] = object QTimer: Type[Any] = object QUrl: Type[Any] = object QNetworkRequest: Type[Any] = object QNetworkReply: Type[Any] = object QCoreApplication: Type[Any] = object QWidget: Type[Any] = object QGridLayout: Type[Any] = object QLabel: Type[Any] = object QLineEdit: Type[Any] = object QInputDialog: Type[Any] = object QGroupBox: Type[Any] = object QVBoxLayout: Type[Any] = object QPushButton: Type[Any] = object QAction: Type[Any] = object QMenu: Type[Any] = object QToolBar: Type[Any] = object QActionGroup: Type[Any] = object QTabWidget: Type[Any] = object QToolButton: Type[Any] = object QSizePolicy: Type[Any] = object Qt: Type[Any] = object QComboBox: Type[Any] = object QCheckBox: Type[Any] = object QHBoxLayout: Type[Any] = object QFont: Type[Any] = object QSettings: Type[Any] = object QDialog: Type[Any] = object QDialogButtonBox: Type[Any] = object QListWidget: Type[Any] = object QListWidgetItem: Type[Any] = object QAbstractItemView: Type[Any] = object QTableWidget: Type[Any] = object QTableWidgetItem: Type[Any] = object QTableWidgetSelectionRange: Type[Any] = object QIcon: Type[Any] = object def exec_dialog(dialog: Any) -> Any: """Führt Dialog modal aus (Qt6: exec(), Qt5: exec_(), Mock: YES)""" raise NotImplementedError("Qt nicht initialisiert") def debug_qt_status() -> None: """Debug: Zeigt Qt-Status für Troubleshooting.""" print(f"🔍 QT_VERSION: {QT_VERSION}") print(f"🔍 QMessageBox Typ: {getattr(QMessageBox, '__name__', type(QMessageBox).__name__)}") print(f"🔍 YES Wert: {YES} (Typ: {type(YES) if YES is not None else 'None'})") if QT_VERSION == 0: print("❌ MOCK-MODUS AKTIV! Keine Dialoge möglich!") elif QT_VERSION == 5: print("✅ PyQt5 geladen (Fallback) – Dialoge sollten funktionieren!") elif QT_VERSION == 6: print("✅ PyQt6 geladen (primär) – Dialoge sollten funktionieren!") else: print("❓ Unbekannte Qt-Version!") # --------------------------- PYQT6 PRIMÄR --------------------------- try: from qgis.PyQt.QtWidgets import ( QMessageBox as _QMessageBox, QFileDialog as _QFileDialog, QProgressDialog as _QProgressDialog, QWidget as _QWidget, QGridLayout as _QGridLayout, QLabel as _QLabel, QLineEdit as _QLineEdit, QInputDialog as _QInputDialog, QGroupBox as _QGroupBox, QVBoxLayout as _QVBoxLayout, QPushButton as _QPushButton, QAction as _QAction, QMenu as _QMenu, QToolBar as _QToolBar, QActionGroup as _QActionGroup, QDockWidget as _QDockWidget, QTabWidget as _QTabWidget, QToolButton as _QToolButton, QSizePolicy as _QSizePolicy, QComboBox as _QComboBox, QCheckBox as _QCheckBox, QHBoxLayout as _QHBoxLayout, QDialog as _QDialog, QDialogButtonBox as _QDialogButtonBox, QListWidget as _QListWidget, QListWidgetItem as _QListWidgetItem, QAbstractItemView as _QAbstractItemView, QTableWidget as _QTableWidget, QTableWidgetItem as _QTableWidgetItem, QTableWidgetSelectionRange as _QTableWidgetSelectionRange, ) from qgis.PyQt.QtGui import QFont as _QFont, QIcon as _QIcon from qgis.PyQt.QtCore import ( QEventLoop as _QEventLoop, QTimer as _QTimer, QUrl as _QUrl, QCoreApplication as _QCoreApplication, Qt as _Qt, QVariant as _QVariant, QSettings as _QSettings, ) from qgis.PyQt.QtNetwork import ( QNetworkRequest as _QNetworkRequest, QNetworkReply as _QNetworkReply, ) # ✅ ALLE GLOBALS ZUWEISEN QT_VERSION = 6 QMessageBox = _QMessageBox QFileDialog = _QFileDialog QProgressDialog = _QProgressDialog QProgressDialog = _QProgressDialog QEventLoop = _QEventLoop QTimer = _QTimer QUrl = _QUrl QNetworkRequest = _QNetworkRequest QNetworkReply = _QNetworkReply QCoreApplication = _QCoreApplication Qt = _Qt QDockWidget = _QDockWidget QWidget = _QWidget QGridLayout = _QGridLayout QLabel = _QLabel QLineEdit = _QLineEdit QInputDialog = _QInputDialog QGroupBox = _QGroupBox QVBoxLayout = _QVBoxLayout QPushButton = _QPushButton QAction = _QAction QMenu = _QMenu QToolBar = _QToolBar QActionGroup = _QActionGroup QTabWidget = _QTabWidget QToolButton = _QToolButton QSizePolicy = _QSizePolicy QComboBox = _QComboBox QCheckBox = _QCheckBox QVariant = _QVariant QHBoxLayout = _QHBoxLayout QFont = _QFont QSettings = _QSettings QDialog = _QDialog QDialogButtonBox = _QDialogButtonBox QListWidget = _QListWidget QListWidgetItem = _QListWidgetItem QAbstractItemView = _QAbstractItemView QTableWidget = _QTableWidget QTableWidgetItem = _QTableWidgetItem QTableWidgetSelectionRange = _QTableWidgetSelectionRange QIcon = _QIcon # ✅ QT6 ENUMS YES = QMessageBox.StandardButton.Yes NO = QMessageBox.StandardButton.No CANCEL = QMessageBox.StandardButton.Cancel ICON_QUESTION = QMessageBox.Icon.Question AcceptRole = QMessageBox.ButtonRole.AcceptRole ActionRole = QMessageBox.ButtonRole.ActionRole RejectRole = QMessageBox.ButtonRole.RejectRole # Qt6 Enum-Aliase ToolButtonTextBesideIcon = Qt.ToolButtonStyle.ToolButtonTextBesideIcon ArrowDown = Qt.ArrowType.DownArrow ArrowRight = Qt.ArrowType.RightArrow SizePolicyPreferred = QSizePolicy.Policy.Preferred SizePolicyMaximum = QSizePolicy.Policy.Maximum DockWidgetMovable = QDockWidget.DockWidgetFeature.DockWidgetMovable DockWidgetFloatable = QDockWidget.DockWidgetFeature.DockWidgetFloatable DockWidgetClosable = QDockWidget.DockWidgetFeature.DockWidgetClosable DockAreaLeft = Qt.DockWidgetArea.LeftDockWidgetArea DockAreaRight = Qt.DockWidgetArea.RightDockWidgetArea DialogAccepted = QDialog.DialogCode.Accepted ExtendedSelection = QAbstractItemView.SelectionMode.ExtendedSelection SelectRows = QAbstractItemView.SelectionBehavior.SelectRows NoEditTriggers = QAbstractItemView.EditTrigger.NoEditTriggers AscendingOrder = Qt.SortOrder.AscendingOrder def exec_dialog(dialog: Any) -> Any: return dialog.exec() print(f"✅ qt_wrapper: PyQt6 geladen (QT_VERSION={QT_VERSION})") # --------------------------- PYQT5 FALLBACK --------------------------- except (ImportError, AttributeError): try: from PyQt5.QtWidgets import ( QMessageBox as _QMessageBox, QFileDialog as _QFileDialog, QWidget as _QWidget, QGridLayout as _QGridLayout, QLabel as _QLabel, QLineEdit as _QLineEdit, QInputDialog as _QInputDialog, QGroupBox as _QGroupBox, QVBoxLayout as _QVBoxLayout, QPushButton as _QPushButton, QAction as _QAction, QMenu as _QMenu, QToolBar as _QToolBar, QActionGroup as _QActionGroup, QDockWidget as _QDockWidget, QTabWidget as _QTabWidget, QToolButton as _QToolButton, QSizePolicy as _QSizePolicy, QComboBox as _QComboBox, QCheckBox as _QCheckBox, QHBoxLayout as _QHBoxLayout, QDialog as _QDialog, QDialogButtonBox as _QDialogButtonBox, QListWidget as _QListWidget, QListWidgetItem as _QListWidgetItem, QAbstractItemView as _QAbstractItemView, QTableWidget as _QTableWidget, QTableWidgetItem as _QTableWidgetItem, QTableWidgetSelectionRange as _QTableWidgetSelectionRange, ) from PyQt5.QtGui import QFont as _QFont, QIcon as _QIcon from PyQt5.QtCore import ( QEventLoop as _QEventLoop, QTimer as _QTimer, QUrl as _QUrl, QCoreApplication as _QCoreApplication, Qt as _Qt, QVariant as _QVariant, QSettings as _QSettings, ) from PyQt5.QtNetwork import ( QNetworkRequest as _QNetworkRequest, QNetworkReply as _QNetworkReply, ) # ✅ ALLE GLOBALS ZUWEISEN QT_VERSION = 5 QMessageBox = _QMessageBox QFileDialog = _QFileDialog QEventLoop = _QEventLoop QTimer = _QTimer QUrl = _QUrl QNetworkRequest = _QNetworkRequest QNetworkReply = _QNetworkReply QCoreApplication = _QCoreApplication Qt = _Qt QDockWidget = _QDockWidget QWidget = _QWidget QGridLayout = _QGridLayout QLabel = _QLabel QLineEdit = _QLineEdit QInputDialog = _QInputDialog QGroupBox = _QGroupBox QVBoxLayout = _QVBoxLayout QPushButton = _QPushButton QAction = _QAction QMenu = _QMenu QToolBar = _QToolBar QActionGroup = _QActionGroup QTabWidget = _QTabWidget QToolButton = _QToolButton QSizePolicy = _QSizePolicy QComboBox = _QComboBox QCheckBox = _QCheckBox QVariant = _QVariant QHBoxLayout= _QHBoxLayout QFont = _QFont QSettings = _QSettings QDialog = _QDialog QDialogButtonBox = _QDialogButtonBox QListWidget = _QListWidget QListWidgetItem = _QListWidgetItem QAbstractItemView = _QAbstractItemView QTableWidget = _QTableWidget QTableWidgetItem = _QTableWidgetItem QTableWidgetSelectionRange = _QTableWidgetSelectionRange QIcon = _QIcon # ✅ PYQT5 ENUMS YES = QMessageBox.Yes NO = QMessageBox.No CANCEL = QMessageBox.Cancel ICON_QUESTION = QMessageBox.Question AcceptRole = QMessageBox.AcceptRole ActionRole = QMessageBox.ActionRole RejectRole = QMessageBox.RejectRole # PyQt5 Enum-Aliase ToolButtonTextBesideIcon = Qt.ToolButtonTextBesideIcon ArrowDown = Qt.DownArrow ArrowRight = Qt.RightArrow SizePolicyPreferred = QSizePolicy.Preferred SizePolicyMaximum = QSizePolicy.Maximum DockWidgetMovable = QDockWidget.DockWidgetMovable DockWidgetFloatable = QDockWidget.DockWidgetFloatable DockWidgetClosable = QDockWidget.DockWidgetClosable DockAreaLeft = Qt.LeftDockWidgetArea DockAreaRight = Qt.RightDockWidgetArea DialogAccepted = QDialog.Accepted ExtendedSelection = QAbstractItemView.ExtendedSelection SelectRows = QAbstractItemView.SelectRows NoEditTriggers = QAbstractItemView.NoEditTriggers AscendingOrder = Qt.AscendingOrder def exec_dialog(dialog: Any) -> Any: return dialog.exec_() print(f"✅ qt_wrapper: PyQt5 Fallback geladen (QT_VERSION={QT_VERSION})") # --------------------------- MOCK-MODUS --------------------------- except Exception: QT_VERSION = 0 print("⚠️ qt_wrapper: Mock-Modus aktiviert (QT_VERSION=0)") # Fake Enum für Bit-Operationen class FakeEnum(int): def __or__(self, other: Any) -> "FakeEnum": return FakeEnum(int(self) | int(other)) YES = FakeEnum(1) NO = FakeEnum(2) CANCEL = FakeEnum(4) ICON_QUESTION = FakeEnum(8) # Im Mock-Block von qt_wrapper.py: class _MockQMessageBox: Yes = YES No = NO Cancel = CANCEL Question = ICON_QUESTION AcceptRole = 0 ActionRole = 3 RejectRole = 1 @classmethod def question(cls, parent, title, message, buttons, default_button): """Mock: Gibt immer default_button zurück""" print(f"🔍 Mock QMessageBox.question: '{title}' → {default_button}") return default_button QMessageBox = _MockQMessageBox class _MockQFileDialog: @staticmethod def getOpenFileName(*args, **kwargs): return ("", "") @staticmethod def getSaveFileName(*args, **kwargs): return ("", "") QFileDialog = _MockQFileDialog class _MockQInputDialog: @staticmethod def getText(parent, title, label, mode=None, text=""): return text, True @staticmethod def getItem(parent, title, label, items, current=0, editable=False): return (items[current] if items else ""), True QInputDialog = _MockQInputDialog class _MockQEventLoop: def exec(self) -> int: return 0 def quit(self) -> None: pass QEventLoop = _MockQEventLoop class _MockQTimer: def __init__(self, *args, **kwargs): self.timeout = type('Signal', (), { 'connect': lambda s, cb: None, })() def setSingleShot(self, v: bool) -> None: pass def start(self, ms: int) -> None: pass def stop(self) -> None: pass QTimer = _MockQTimer class _MockQUrl(str): def isValid(self) -> bool: return True QUrl = _MockQUrl class _MockQNetworkRequest: def __init__(self, url: Any): self.url = url QNetworkRequest = _MockQNetworkRequest class _MockQNetworkReply: def error(self) -> int: return 0 def errorString(self) -> str: return "" def readAll(self) -> bytes: return b"" def deleteLater(self) -> None: pass QNetworkReply = _MockQNetworkReply class _MockWidget: pass class _MockLayout: def __init__(self, *args, **kwargs): self._widgets = [] def addWidget(self, widget): self._widgets.append(widget) def addLayout(self, layout): pass def addStretch(self, *args, **kwargs): pass def setSpacing(self, *args, **kwargs): pass def setContentsMargins(self, *args, **kwargs): pass class _MockLabel: def __init__(self, text: str = ""): self._text = text class _MockLineEdit: Normal = 0 def __init__(self, *args, **kwargs): self._text = "" def text(self) -> str: return self._text def setText(self, value: str) -> None: self._text = value class _MockFont: def __init__(self, family: str = "", pointSize: int = 10): self.family = family self.pointSize = pointSize class _MockButton: def __init__(self, *args, **kwargs): self.clicked = lambda *a, **k: None QWidget = _MockWidget QGridLayout = _MockLayout QLabel = _MockLabel QLineEdit = _MockLineEdit QGroupBox = _MockWidget QVBoxLayout = _MockLayout QPushButton = _MockButton QFont = _MockFont QCoreApplication = object() class _MockQt: ToolButtonTextBesideIcon = 0 ArrowDown = 1 ArrowRight = 2 LeftDockWidgetArea = 1 RightDockWidgetArea = 2 Qt = _MockQt() ToolButtonTextBesideIcon = Qt.ToolButtonTextBesideIcon ArrowDown = Qt.ArrowDown ArrowRight = Qt.ArrowRight DockAreaLeft = Qt.LeftDockWidgetArea DockAreaRight = Qt.RightDockWidgetArea class _MockQDockWidget(_MockWidget): def __init__(self, *args, **kwargs): self._object_name = "" def setObjectName(self, name: str) -> None: self._object_name = name def objectName(self) -> str: return self._object_name def show(self) -> None: pass def deleteLater(self) -> None: pass QDockWidget = _MockQDockWidget class _MockAction: def __init__(self, *args, **kwargs): self._checked = False self.triggered = lambda *a, **k: None def setToolTip(self, text: str) -> None: pass def setCheckable(self, value: bool) -> None: pass def setChecked(self, value: bool) -> None: self._checked = value class _MockMenu: def __init__(self, *args, **kwargs): self._actions = [] def addAction(self, action): self._actions.append(action) def removeAction(self, action): if action in self._actions: self._actions.remove(action) def clear(self): self._actions.clear() def menuAction(self): return self class _MockToolBar: def __init__(self, *args, **kwargs): self._actions = [] def setObjectName(self, name: str) -> None: pass def addAction(self, action): self._actions.append(action) def removeAction(self, action): if action in self._actions: self._actions.remove(action) def clear(self): self._actions.clear() class _MockActionGroup: def __init__(self, *args, **kwargs): self._actions = [] def setExclusive(self, value: bool) -> None: pass def addAction(self, action): self._actions.append(action) QAction = _MockAction QMenu = _MockMenu QToolBar = _MockToolBar QActionGroup = _MockActionGroup class _MockToolButton(_MockWidget): def __init__(self, *args, **kwargs): self._checked = False self.toggled = lambda *a, **k: None def setText(self, text: str) -> None: pass def setCheckable(self, value: bool) -> None: pass def setChecked(self, value: bool) -> None: self._checked = value def setToolButtonStyle(self, *args, **kwargs): pass def setArrowType(self, *args, **kwargs): pass def setStyleSheet(self, *args, **kwargs): pass QToolButton = _MockToolButton class _MockQSizePolicy: Preferred = 3 Maximum = 2 QSizePolicy = _MockQSizePolicy SizePolicyPreferred = QSizePolicy.Preferred SizePolicyMaximum = QSizePolicy.Maximum DockWidgetMovable = 1 DockWidgetFloatable = 2 DockWidgetClosable = 4 class _MockTabWidget: def __init__(self, *args, **kwargs): self._tabs = [] def addTab(self, widget, title: str): self._tabs.append((widget, title)) QTabWidget = _MockTabWidget class _MockComboBox: def __init__(self, parent=None): self._items = [] # Liste von (text, userData) self._index = -1 self.currentTextChanged = type('Signal', (), {'connect': lambda s, cb: None, 'emit': lambda s, v: None})() def addItem(self, text: str, userData=None) -> None: self._items.append((text, userData)) if self._index < 0: self._index = 0 def addItems(self, items): [self.addItem(it) for it in items] def findText(self, text: str) -> int: for i, (t, _) in enumerate(self._items): if t == text: return i return -1 def setCurrentIndex(self, idx: int) -> None: if 0 <= idx < len(self._items): self._index = idx self.currentTextChanged.emit(self.currentText()) def setCurrentText(self, text: str) -> None: idx = self.findText(text) if idx >= 0: self.setCurrentIndex(idx) def currentText(self) -> str: return self._items[self._index][0] if 0 <= self._index < len(self._items) else "" def currentData(self): return self._items[self._index][1] if 0 <= self._index < len(self._items) else None def count(self) -> int: return len(self._items) QComboBox = _MockComboBox # --------------------------- # Mock für QVariant # --------------------------- class _MockQVariant: """ Minimaler Ersatz für QtCore.QVariant. Ziel: - Werte transparent durchreichen - Typ-Konstanten bereitstellen - Keine Qt-Abhängigkeiten """ # Typ-Konstanten (symbolisch, Werte egal) Invalid = 0 Int = 1 Double = 2 String = 3 Bool = 4 Date = 5 DateTime = 6 def __init__(self, value: Any = None): self._value = value def value(self) -> Any: return self._value def __repr__(self) -> str: return f"QVariant({self._value!r})" # Optional: automatische Entpackung def __int__(self): return int(self._value) def __float__(self): return float(self._value) def __str__(self): return str(self._value) QVariant = _MockQVariant class _MockQHBoxLayout: def __init__(self, *args, **kwargs): self._widgets = [] def addWidget(self, widget): self._widgets.append(widget) def addLayout(self, layout): pass def addStretch(self, *args, **kwargs): pass def setSpacing(self, *args, **kwargs): pass def setContentsMargins(self, *args, **kwargs): pass QHBoxLayout = _MockQHBoxLayout class _MockQSettings: def __init__(self, *args, **kwargs): self._data: dict = {} self._group = "" def beginGroup(self, group: str) -> None: self._group = group def endGroup(self) -> None: self._group = "" def setValue(self, key: str, value: Any) -> None: full = "%s/%s" % (self._group, key) if self._group else key self._data[full] = value def value(self, key: str, default: Any = "") -> Any: full = "%s/%s" % (self._group, key) if self._group else key return self._data.get(full, default) def remove(self, key: str) -> None: full = "%s/%s" % (self._group, key) if self._group else key self._data.pop(full, None) QSettings = _MockQSettings class _MockQCheckBox: def __init__(self, text: str = "", *args, **kwargs): self._text = text self._checked = False def setText(self, text: str) -> None: self._text = text def isChecked(self) -> bool: return self._checked def setChecked(self, checked: bool) -> None: self._checked = checked QCheckBox = _MockQCheckBox DialogAccepted = 1 ExtendedSelection = 3 SelectRows = 1 NoEditTriggers = 0 AscendingOrder = 0 class _MockQDialog(_MockWidget): DialogCode = type("DialogCode", (), {"Accepted": DialogAccepted, "Rejected": 0}) def __init__(self, *args, **kwargs): self._layout = None def setWindowTitle(self, title: str) -> None: pass def setWindowIcon(self, icon) -> None: pass def exec(self) -> int: return DialogAccepted def exec_(self) -> int: return DialogAccepted def accept(self) -> None: pass def reject(self) -> None: pass def resize(self, *args, **kwargs) -> None: pass def adjustSize(self) -> None: pass def sizeHint(self): return type("Size", (), {"width": lambda self=None: 200, "height": lambda self=None: 100})() QDialog = _MockQDialog class _MockQDialogButtonBox(_MockWidget): StandardButton = type("StandardButton", (), {"Ok": 1, "Cancel": 2}) Ok = 1 Cancel = 2 def __init__(self, *args, **kwargs): self.accepted = type('Signal', (), {'connect': lambda s, cb: None})() self.rejected = type('Signal', (), {'connect': lambda s, cb: None})() QDialogButtonBox = _MockQDialogButtonBox class _MockQListWidgetItem: def __init__(self, text: str = ""): self._text = text self._selected = False def setSelected(self, value: bool) -> None: self._selected = value def isSelected(self) -> bool: return self._selected QListWidgetItem = _MockQListWidgetItem class _MockQListWidget(_MockWidget): def __init__(self, *args, **kwargs): self._items = [] def addItem(self, item) -> None: self._items.append(item) def item(self, index: int): return self._items[index] if 0 <= index < len(self._items) else None def count(self) -> int: return len(self._items) def row(self, item) -> int: return self._items.index(item) if item in self._items else -1 def selectedItems(self): return [i for i in self._items if i.isSelected()] def setSelectionMode(self, *args, **kwargs) -> None: pass def sizeHintForRow(self, index: int) -> int: return 20 def setFixedHeight(self, height: int) -> None: pass def frameWidth(self) -> int: return 1 QListWidget = _MockQListWidget class _MockQAbstractItemView: SelectionMode = type("SelectionMode", (), {"ExtendedSelection": ExtendedSelection}) QAbstractItemView = _MockQAbstractItemView class _MockQTableWidgetItem: def __init__(self, text: str = ""): self._text = text def text(self) -> str: return self._text def setText(self, text: str) -> None: self._text = text QTableWidgetItem = _MockQTableWidgetItem class _MockQTableWidget(_MockWidget): def __init__(self, rows: int = 0, cols: int = 0, *args, **kwargs): self._items = {} self._row_count = rows self._col_count = cols self._hidden_rows = set() def setItem(self, row: int, col: int, item) -> None: self._items[(row, col)] = item def item(self, row: int, col: int): return self._items.get((row, col)) def rowCount(self) -> int: return self._row_count def setRowCount(self, rows: int) -> None: self._row_count = rows def setHorizontalHeaderLabels(self, labels) -> None: pass def setSelectionMode(self, *args, **kwargs) -> None: pass def setSelectionBehavior(self, *args, **kwargs) -> None: pass def setEditTriggers(self, *args, **kwargs) -> None: pass def setSortingEnabled(self, *args, **kwargs) -> None: pass def setRowHidden(self, row: int, hidden: bool) -> None: if hidden: self._hidden_rows.add(row) else: self._hidden_rows.discard(row) def isRowHidden(self, row: int) -> bool: return row in self._hidden_rows def selectRow(self, row: int) -> None: pass def selectedItems(self): return [] def setRangeSelected(self, *args, **kwargs) -> None: pass def sortByColumn(self, *args, **kwargs) -> None: pass def resizeColumnToContents(self, col: int) -> None: pass def setColumnWidth(self, col: int, width: int) -> None: pass def columnWidth(self, col: int) -> int: return 100 def columnCount(self) -> int: return self._col_count def verticalHeader(self): return _MockWidget() def horizontalHeader(self): return _MockWidget() def frameWidth(self) -> int: return 1 QTableWidget = _MockQTableWidget class _MockQTableWidgetSelectionRange: def __init__(self, *args, **kwargs): pass QTableWidgetSelectionRange = _MockQTableWidgetSelectionRange class _MockQIcon: def __init__(self, *args, **kwargs): pass QIcon = _MockQIcon def exec_dialog(dialog: Any) -> Any: return YES # --------------------------- TEST --------------------------- if __name__ == "__main__": debug_qt_status()