Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7755e3e8cb | ||
|
|
bc9bb20597 | ||
|
|
113fda7d04 | ||
|
|
8545152317 | ||
|
|
8cea9022f0 | ||
|
|
1b5a715c70 | ||
|
|
749d6d6f52 |
@@ -1,3 +1,10 @@
|
||||
- Landkreis-Dropdown (statt Freitext) in den Projekteigenschaften ergänzt, inkl. Landkreiskennzahl als eigene Projektvariable
|
||||
- Landkreisliste liegt jetzt als JSON (sn_basis/data/landkreise.json) statt hartcodiert vor, damit auch andere Module und Nicht-Entwickler sie pflegen können
|
||||
- Auswahldialog für mehrere BauRaumOderBodenordnungsrecht-Treffer auf Mehrfachauswahl umgestellt (mehrere Objekte gemeinsam laden/verschmelzen)
|
||||
- Landkreisweiter Objekt-Auswahldialog jetzt als Tabelle (Spalten "Nummer"/"Name", per Spaltenkopf sortierbar, Standard aufsteigend nach Nummer) mit Suchfeld (Filter nach Nummer/Name); "Alle auswählen" berücksichtigt die Filterung; Checkbox-Text zu "Nur Objekte laden (ohne weitere Prüfungen)" geändert
|
||||
- Dialoge: Titel, Wappen-Icon, kompaktere Größe, Scrollbar-Fix und größenveränderbare Liste ergänzt
|
||||
- Die drei Verfahrensgebiet-spezifischen ALKIS-Dialoge (BROR-Auswahl, Landkreis-Objektauswahl, Landkreis-Auswahl) sind aus sn_basis nach sn_verfahrensgebiet verschoben (functions/verfahrensgebiet_dialoge.py), da sie fachlich dorthin gehören
|
||||
---
|
||||
Version 26.8.1-unstable:
|
||||
-Vergleich einer CSV aus dem BI-Server mit den Beteiligten Flurstücken lt. ALKIS
|
||||
---
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
[
|
||||
{"kennzahl": "11", "name": "Chemnitz, Stadt"},
|
||||
{"kennzahl": "12", "name": "Dresden, Stadt"},
|
||||
{"kennzahl": "13", "name": "Leipzig, Stadt"},
|
||||
{"kennzahl": "21", "name": "Erzgebirgskreis"},
|
||||
{"kennzahl": "22", "name": "Mittelsachsen"},
|
||||
{"kennzahl": "23", "name": "Vogtlandkreis"},
|
||||
{"kennzahl": "24", "name": "Zwickau"},
|
||||
{"kennzahl": "25", "name": "Bautzen"},
|
||||
{"kennzahl": "26", "name": "Görlitz"},
|
||||
{"kennzahl": "27", "name": "Meißen"},
|
||||
{"kennzahl": "28", "name": "Sächsische Schweiz-Osterzgebirge"},
|
||||
{"kennzahl": "29", "name": "Leipzig"},
|
||||
{"kennzahl": "30", "name": "Nordsachsen"}
|
||||
]
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -390,53 +390,3 @@ class ProgressDialog:
|
||||
def create_progress_dialog(total: int, title: str = "Fortschritt", label: str = "Verarbeite...") -> ProgressDialog:
|
||||
return ProgressDialog(total, title, label)
|
||||
|
||||
|
||||
def ask_bror_kombination(
|
||||
parent: Any,
|
||||
kombinationen: list[tuple[str, str]],
|
||||
) -> Optional[tuple[str, str]]:
|
||||
"""Zeigt Dialog zur Auswahl einer BROR-Kombination (adv_name + bezeichnung).
|
||||
|
||||
Wird aufgerufen, wenn der WFS mehrere verschiedene Kombinationen aus
|
||||
``adv_name`` und ``bezeichnung`` zurückliefert, sodass der Nutzer
|
||||
entscheiden muss, welche Objekte in die Pipeline einfließen sollen.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
parent :
|
||||
Eltern-Widget oder None.
|
||||
kombinationen :
|
||||
Sortierte Liste von ``(adv_name, bezeichnung)``-Tupeln.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Optional[tuple[str, str]]
|
||||
Das gewählte ``(adv_name, bezeichnung)``-Tupel oder ``None`` bei
|
||||
Abbruch bzw. leerer Eingabe.
|
||||
"""
|
||||
if not kombinationen:
|
||||
return None
|
||||
|
||||
if QT_VERSION == 0: # Mock-Modus
|
||||
print(f"Mock-Modus: ask_bror_kombination → {kombinationen[0]}")
|
||||
return kombinationen[0]
|
||||
|
||||
items = [f"{adv} | {bez}" for adv, bez in kombinationen]
|
||||
item, ok = QInputDialog.getItem(
|
||||
parent,
|
||||
"BROR-Objekt auswählen",
|
||||
"Mehrere BauRaumOderBodenordnungsrecht-Objekte gefunden.\n"
|
||||
"Bitte wählen Sie die gewünschte Kombination\n"
|
||||
"aus ADV-Name und Bezeichnung:",
|
||||
items,
|
||||
0,
|
||||
False,
|
||||
)
|
||||
if not ok:
|
||||
return None
|
||||
try:
|
||||
idx = items.index(item)
|
||||
return kombinationen[idx]
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
"""sn_basis/functions/landkreise.py – Sächsische Landkreise/Helfer mit Kennzahl.
|
||||
|
||||
Daten liegen in sn_basis/data/landkreise.json (auch von anderen sn_*-Modulen
|
||||
lesbar, z.B. per ``from sn_basis.functions.landkreise import LANDKREISE``).
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
try:
|
||||
from qgis.core import Qgis, QgsMessageLog
|
||||
except Exception: # Mock-Modus / außerhalb QGIS
|
||||
Qgis = None
|
||||
QgsMessageLog = None
|
||||
|
||||
# .../sn_basis/data/landkreise.json (eine Ebene über dieser Datei, dann data/)
|
||||
_DATA_DATEI = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "landkreise.json")
|
||||
|
||||
|
||||
def _lade_landkreise() -> "list[tuple[str, str]]":
|
||||
try:
|
||||
with open(_DATA_DATEI, "r", encoding="utf-8") as f:
|
||||
rohdaten = json.load(f)
|
||||
return [(eintrag["kennzahl"], eintrag["name"]) for eintrag in rohdaten]
|
||||
except Exception as exc:
|
||||
if QgsMessageLog is not None:
|
||||
QgsMessageLog.logMessage(
|
||||
f"landkreise.json konnte nicht geladen werden ({_DATA_DATEI}): {exc}",
|
||||
"sn_basis",
|
||||
Qgis.Warning,
|
||||
)
|
||||
else:
|
||||
print(f"⚠️ landkreise.json konnte nicht geladen werden ({_DATA_DATEI}): {exc}")
|
||||
return []
|
||||
|
||||
|
||||
#: Liste von (Landkreiskennzahl, Landkreis/Helfer)-Tupeln, in Datei-Reihenfolge.
|
||||
LANDKREISE: "list[tuple[str, str]]" = _lade_landkreise()
|
||||
|
||||
#: Kennzahl -> Name
|
||||
KENNZAHL_ZU_NAME: "dict[str, str]" = dict(LANDKREISE)
|
||||
|
||||
#: Name -> Kennzahl
|
||||
NAME_ZU_KENNZAHL: "dict[str, str]" = {name: kennzahl for kennzahl, name in LANDKREISE}
|
||||
|
||||
#: Sentinel-"Kennzahl" für die Auswahl "Alle Landkreise" (kein Landkreis-Filter).
|
||||
ALLE_LANDKREISE = "ALLE"
|
||||
+193
-10
@@ -46,6 +46,15 @@ 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:
|
||||
@@ -92,8 +101,16 @@ try:
|
||||
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
|
||||
from qgis.PyQt.QtGui import QFont as _QFont, QIcon as _QIcon
|
||||
from qgis.PyQt.QtCore import (
|
||||
QEventLoop as _QEventLoop,
|
||||
QTimer as _QTimer,
|
||||
@@ -143,6 +160,15 @@ try:
|
||||
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
|
||||
@@ -163,7 +189,12 @@ try:
|
||||
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()
|
||||
|
||||
@@ -194,8 +225,16 @@ except (ImportError, AttributeError):
|
||||
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
|
||||
from PyQt5.QtGui import QFont as _QFont, QIcon as _QIcon
|
||||
from PyQt5.QtCore import (
|
||||
QEventLoop as _QEventLoop,
|
||||
QTimer as _QTimer,
|
||||
@@ -243,7 +282,16 @@ except (ImportError, AttributeError):
|
||||
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
|
||||
@@ -265,7 +313,12 @@ except (ImportError, AttributeError):
|
||||
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_()
|
||||
|
||||
@@ -319,6 +372,10 @@ except (ImportError, AttributeError):
|
||||
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:
|
||||
@@ -482,13 +539,19 @@ except (ImportError, AttributeError):
|
||||
|
||||
class _MockComboBox:
|
||||
def __init__(self, parent=None):
|
||||
self._items = []
|
||||
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) -> None: self._items.append(text)
|
||||
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:
|
||||
return self._items.index(text) if text in self._items else -1
|
||||
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
|
||||
@@ -497,7 +560,11 @@ except (ImportError, AttributeError):
|
||||
idx = self.findText(text)
|
||||
if idx >= 0: self.setCurrentIndex(idx)
|
||||
def currentText(self) -> str:
|
||||
return self._items[self._index] if 0 <= self._index < len(self._items) else ""
|
||||
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
|
||||
|
||||
@@ -605,6 +672,122 @@ except (ImportError, AttributeError):
|
||||
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 ---------------------------
|
||||
|
||||
@@ -20,6 +20,7 @@ class SettingsLogic:
|
||||
"amt",
|
||||
"behoerde",
|
||||
"landkreis_user",
|
||||
"landkreis_kennzahl",
|
||||
"sachgebiet",
|
||||
"bezeichnung",
|
||||
"name",
|
||||
|
||||
+13
-2
@@ -30,7 +30,6 @@ from sn_basis.modules.linkpruefer import Linkpruefer
|
||||
from sn_basis.modules.layerpruefer import Layerpruefer
|
||||
from sn_basis.modules.stilpruefer import Stilpruefer
|
||||
from sn_basis.modules.excel_importer import ExcelImporter
|
||||
from sn_plan41.modules.listenauswerter import Listenauswerter
|
||||
|
||||
|
||||
SourceType = Literal["service", "database", "excel", "unknown"]
|
||||
@@ -286,7 +285,19 @@ class DataGrabber:
|
||||
}
|
||||
source_dict["rows"].append(result_row)
|
||||
|
||||
# Validierung über Listenauswerter
|
||||
# Validierung über Listenauswerter – Import erst hier (statt am Modul-
|
||||
# anfang), da DataGrabber generisch für alle sn_*-Plugins nutzbar sein
|
||||
# soll und nicht bei jedem Aufruf zwingend sn_plan41 installiert ist;
|
||||
# nur die Excel-Quellenverarbeitung braucht Listenauswerter.
|
||||
try:
|
||||
from sn_plan41.modules.listenauswerter import Listenauswerter
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Die Verarbeitung von Excel-Quellen benötigt das Plugin "
|
||||
"sn_plan41 (sn_plan41.modules.listenauswerter.Listenauswerter), "
|
||||
"das hier nicht installiert ist."
|
||||
) from exc
|
||||
|
||||
listenauswerter = Listenauswerter(self.pruefmanager, self.stil_pruefer or Stilpruefer())
|
||||
validated, validation_results = listenauswerter.validate_rows(source_dict)
|
||||
results.extend(validation_results)
|
||||
|
||||
+42
-11
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
sn_basis/ui/tabs/settings_tab.py – Einstellungen-Tab für Projekteinformationen.
|
||||
sn_basis/ui/tabs/settings_tab.py – Einstellungen-Tab für Projektinformationen.
|
||||
Verwaltet benutzerspezifische und projektspezifische Einstellungen.
|
||||
"""
|
||||
|
||||
@@ -8,28 +8,33 @@ from sn_basis.functions.qt_wrapper import (
|
||||
QGridLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QComboBox,
|
||||
QGroupBox,
|
||||
QVBoxLayout,
|
||||
QPushButton,
|
||||
)
|
||||
from sn_basis.functions.settings_logic import SettingsLogic
|
||||
from sn_basis.functions.landkreise import LANDKREISE
|
||||
|
||||
#: Feldschlüssel, die als Landkreis-Dropdown (statt Freitext) dargestellt werden.
|
||||
_LANDKREIS_DROPDOWN_FELDER = {"landkreis_user"}
|
||||
|
||||
|
||||
class SettingsTab(QWidget):
|
||||
"""
|
||||
Tab-Widget für die Verwaltung von Projekt- und Benutzereinstellungen.
|
||||
|
||||
|
||||
Attributes:
|
||||
tab_title: Anzeigetitel des Tabs ("Projekteigenschaften")
|
||||
logic: SettingsLogic-Instanz für persistente Einstellungen
|
||||
"""
|
||||
|
||||
|
||||
tab_title = "Projekteigenschaften"
|
||||
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Initialisiert den Settings-Tab mit Eingabefeldern.
|
||||
|
||||
|
||||
Args:
|
||||
parent: Übergeordnetes Widget (Standard: None)
|
||||
"""
|
||||
@@ -64,7 +69,7 @@ class SettingsTab(QWidget):
|
||||
self.user_inputs = {}
|
||||
|
||||
for row, (key, label) in enumerate(self.user_fields.items()):
|
||||
input_widget = QLineEdit()
|
||||
input_widget = self._build_input(key)
|
||||
self.user_inputs[key] = input_widget
|
||||
|
||||
user_layout.addWidget(QLabel(label), row, 0)
|
||||
@@ -80,7 +85,7 @@ class SettingsTab(QWidget):
|
||||
self.project_inputs = {}
|
||||
|
||||
for row, (key, label) in enumerate(self.project_fields.items()):
|
||||
input_widget = QLineEdit()
|
||||
input_widget = self._build_input(key)
|
||||
self.project_inputs[key] = input_widget
|
||||
|
||||
project_layout.addWidget(QLabel(label), row, 0)
|
||||
@@ -107,14 +112,35 @@ class SettingsTab(QWidget):
|
||||
# Daten laden
|
||||
self.load_data()
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Eingabewidget je Feld erzeugen
|
||||
# ---------------------------------------------------------
|
||||
def _build_input(self, key: str):
|
||||
if key in _LANDKREIS_DROPDOWN_FELDER:
|
||||
combo = QComboBox()
|
||||
combo.addItem("", None) # Platzhalter: keine Vorbelegung bei leerem Projekt
|
||||
for kennzahl, name in LANDKREISE:
|
||||
combo.addItem(name, kennzahl)
|
||||
return combo
|
||||
return QLineEdit()
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# Speichern
|
||||
# ---------------------------------------------------------
|
||||
def save_data(self):
|
||||
fields = {
|
||||
key: widget.text()
|
||||
for key, widget in {**self.user_inputs, **self.project_inputs}.items()
|
||||
}
|
||||
fields = {}
|
||||
for key, widget in {**self.user_inputs, **self.project_inputs}.items():
|
||||
if isinstance(widget, QComboBox):
|
||||
fields[key] = widget.currentText()
|
||||
else:
|
||||
fields[key] = widget.text()
|
||||
|
||||
# Landkreiskennzahl aus der Dropdown-Auswahl zusätzlich als eigene
|
||||
# Variable bereitstellen (siehe landkreise.py).
|
||||
landkreis_widget = self.user_inputs.get("landkreis_user")
|
||||
if isinstance(landkreis_widget, QComboBox):
|
||||
fields["landkreis_kennzahl"] = landkreis_widget.currentData() or ""
|
||||
|
||||
self.logic.save(fields)
|
||||
|
||||
# ---------------------------------------------------------
|
||||
@@ -123,4 +149,9 @@ class SettingsTab(QWidget):
|
||||
def load_data(self):
|
||||
data = self.logic.load()
|
||||
for key, widget in {**self.user_inputs, **self.project_inputs}.items():
|
||||
widget.setText(data.get(key, ""))
|
||||
if isinstance(widget, QComboBox):
|
||||
gespeicherter_name = data.get(key, "")
|
||||
index = widget.findText(gespeicherter_name)
|
||||
widget.setCurrentIndex(index if index >= 0 else 0)
|
||||
else:
|
||||
widget.setText(data.get(key, ""))
|
||||
|
||||
Reference in New Issue
Block a user