forked from AG_QGIS/Plugin_SN_Basis
Tests überarbeitet, Mocks und coverage eingefügt
This commit is contained in:
111
modules/qt_compat.py
Normal file
111
modules/qt_compat.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
qt_compat.py – Einheitliche Qt-Kompatibilitätsschicht für QGIS-Plugins.
|
||||
|
||||
Ziele:
|
||||
- PyQt6 bevorzugt
|
||||
- Fallback auf PyQt5
|
||||
- Mock-Modus, wenn kein Qt verfügbar ist (z. B. in Unittests)
|
||||
- OR-fähige Fake-Enums im Mock-Modus
|
||||
"""
|
||||
|
||||
QT_VERSION = 0 # 0 = Mock, 5 = PyQt5, 6 = PyQt6
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Versuch: PyQt6 importieren
|
||||
# ---------------------------------------------------------
|
||||
try:
|
||||
from PyQt6.QtWidgets import QMessageBox, QFileDialog
|
||||
from PyQt6.QtCore import Qt, QEventLoop, QUrl
|
||||
from PyQt6.QtNetwork import QNetworkRequest, QNetworkReply
|
||||
|
||||
YES = QMessageBox.StandardButton.Yes
|
||||
NO = QMessageBox.StandardButton.No
|
||||
CANCEL = QMessageBox.StandardButton.Cancel
|
||||
ICON_QUESTION = QMessageBox.Icon.Question
|
||||
|
||||
QT_VERSION = 6
|
||||
|
||||
def exec_dialog(dialog):
|
||||
"""Einheitliche Ausführung eines Dialogs."""
|
||||
return dialog.exec()
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Versuch: PyQt5 importieren
|
||||
# ---------------------------------------------------------
|
||||
except Exception:
|
||||
try:
|
||||
from PyQt5.QtWidgets import QMessageBox, QFileDialog
|
||||
from PyQt5.QtCore import Qt, QEventLoop, QUrl
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
||||
|
||||
YES = QMessageBox.Yes
|
||||
NO = QMessageBox.No
|
||||
CANCEL = QMessageBox.Cancel
|
||||
ICON_QUESTION = QMessageBox.Question
|
||||
|
||||
QT_VERSION = 5
|
||||
|
||||
def exec_dialog(dialog):
|
||||
return dialog.exec_()
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Mock-Modus (kein Qt verfügbar)
|
||||
# ---------------------------------------------------------
|
||||
except Exception:
|
||||
QT_VERSION = 0
|
||||
|
||||
class FakeEnum(int):
|
||||
"""Ein OR-fähiger Enum-Ersatz für den Mock-Modus."""
|
||||
def __or__(self, other):
|
||||
return FakeEnum(int(self) | int(other))
|
||||
|
||||
class QMessageBox:
|
||||
Yes = FakeEnum(1)
|
||||
No = FakeEnum(2)
|
||||
Cancel = FakeEnum(4)
|
||||
Question = FakeEnum(8)
|
||||
|
||||
class QFileDialog:
|
||||
"""Minimaler Mock für QFileDialog."""
|
||||
@staticmethod
|
||||
def getOpenFileName(*args, **kwargs):
|
||||
return ("", "") # kein Dateipfad
|
||||
|
||||
YES = QMessageBox.Yes
|
||||
NO = QMessageBox.No
|
||||
CANCEL = QMessageBox.Cancel
|
||||
ICON_QUESTION = QMessageBox.Question
|
||||
|
||||
def exec_dialog(dialog):
|
||||
"""Mock-Ausführung: gibt YES zurück, außer Tests patchen es."""
|
||||
return YES
|
||||
# -------------------------
|
||||
# Mock Netzwerk-Klassen
|
||||
# -------------------------
|
||||
class QEventLoop:
|
||||
def exec(self):
|
||||
return 0
|
||||
|
||||
def quit(self):
|
||||
pass
|
||||
|
||||
class QUrl(str):
|
||||
pass
|
||||
|
||||
class QNetworkRequest:
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
|
||||
class QNetworkReply:
|
||||
def __init__(self):
|
||||
self._data = b""
|
||||
|
||||
def readAll(self):
|
||||
return self._data
|
||||
|
||||
def error(self):
|
||||
return 0
|
||||
|
||||
def exec_dialog(dialog):
|
||||
return YES
|
||||
|
||||
Reference in New Issue
Block a user