forked from AG_QGIS/Plugin_SN_Plan41
309 lines
9.6 KiB
Python
309 lines
9.6 KiB
Python
"""
|
||
sn_plan41/ui/tab_a_ui.py – UI für Tab A (Daten)
|
||
"""
|
||
|
||
from typing import Optional
|
||
|
||
from sn_basis.functions.qt_wrapper import ( # type: ignore
|
||
QWidget,
|
||
QVBoxLayout,
|
||
QLabel,
|
||
QPushButton,
|
||
QToolButton,
|
||
QFileDialog,
|
||
QMessageBox,
|
||
QTabWidget,
|
||
ToolButtonTextBesideIcon,
|
||
ArrowDown,
|
||
ArrowRight,
|
||
SizePolicyPreferred,
|
||
SizePolicyMaximum,
|
||
|
||
)
|
||
from sn_basis.functions.qgisui_wrapper import ( # type: ignore
|
||
QgsFileWidget,
|
||
QgsMapLayerComboBox,
|
||
add_dock_widget,
|
||
)
|
||
from sn_basis.functions.qgiscore_wrapper import ( # type: ignore
|
||
QgsProject,
|
||
QgsMapLayerProxyModel,
|
||
)
|
||
from sn_basis.functions.message_wrapper import ( # type: ignore
|
||
info,
|
||
warning,
|
||
error,
|
||
)
|
||
from sn_basis.functions.dialog_wrapper import ask_yes_no # type: ignore
|
||
from sn_basis.functions.sys_wrapper import file_exists # type: ignore
|
||
|
||
from sn_plan41.ui.tab_a_logic import TabALogic # type: ignore
|
||
|
||
|
||
class TabA(QWidget):
|
||
"""
|
||
UI-Klasse für Tab A (Daten).
|
||
Enthält ausschließlich UI-Code und delegiert Logik an TabALogic.
|
||
"""
|
||
|
||
|
||
|
||
def __init__(self, parent=None, build_ui: bool=True):
|
||
super().__init__(parent)
|
||
self.parent=parent
|
||
self.tab_title="Daten"
|
||
|
||
self.logic = TabALogic()
|
||
|
||
self.verfahrens_db: Optional[str] = None
|
||
self.lokale_linkliste: Optional[str] = None
|
||
|
||
if build_ui:
|
||
self._build_ui()
|
||
self._restore_state()
|
||
|
||
# ---------------------------------------------------------
|
||
# UI-Aufbau
|
||
# ---------------------------------------------------------
|
||
|
||
def _build_ui(self) -> None:
|
||
main_layout = QVBoxLayout()
|
||
main_layout.setSpacing(4)
|
||
main_layout.setContentsMargins(4, 4, 4, 4)
|
||
|
||
# -------------------------------
|
||
# Verfahrens-Datenbank
|
||
# -------------------------------
|
||
|
||
self.group_button = QToolButton()
|
||
self.group_button.setText("Verfahrens-Datenbank")
|
||
self.group_button.setCheckable(True)
|
||
self.group_button.setChecked(True)
|
||
self.group_button.setToolButtonStyle(ToolButtonTextBesideIcon)
|
||
self.group_button.setArrowType(ArrowDown)
|
||
|
||
self.group_button.setStyleSheet("font-weight: bold;")
|
||
self.group_button.toggled.connect(self._toggle_group)
|
||
main_layout.addWidget(self.group_button)
|
||
|
||
self.group_content = QWidget()
|
||
self.group_content.setSizePolicy(SizePolicyPreferred, SizePolicyMaximum)
|
||
|
||
|
||
group_layout = QVBoxLayout()
|
||
group_layout.setSpacing(2)
|
||
group_layout.setContentsMargins(10, 4, 4, 4)
|
||
|
||
group_layout.addWidget(QLabel("bestehende Datei auswählen"))
|
||
|
||
self.file_widget = QgsFileWidget()
|
||
self.file_widget.setStorageMode(QgsFileWidget.GetFile)
|
||
self.file_widget.setFilter("Geopackage (*.gpkg)")
|
||
self.file_widget.fileChanged.connect(self._on_verfahrens_db_changed)
|
||
group_layout.addWidget(self.file_widget)
|
||
|
||
group_layout.addWidget(QLabel("-oder-"))
|
||
|
||
self.btn_new = QPushButton("Neue Verfahrens-DB anlegen")
|
||
self.btn_new.clicked.connect(self._create_new_gpkg)
|
||
group_layout.addWidget(self.btn_new)
|
||
|
||
self.group_content.setLayout(group_layout)
|
||
main_layout.addWidget(self.group_content)
|
||
|
||
# -------------------------------
|
||
# Optionale Linkliste
|
||
# -------------------------------
|
||
|
||
self.optional_button = QToolButton()
|
||
self.optional_button.setText("Optional: Lokale Linkliste")
|
||
self.optional_button.setCheckable(True)
|
||
self.optional_button.setChecked(False)
|
||
self.optional_button.setToolButtonStyle(ToolButtonTextBesideIcon)
|
||
self.optional_button.setArrowType(ArrowRight)
|
||
|
||
self.optional_button.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
||
self.optional_button.toggled.connect(self._toggle_optional)
|
||
main_layout.addWidget(self.optional_button)
|
||
|
||
self.optional_content = QWidget()
|
||
self.optional_content.setSizePolicy(SizePolicyPreferred, SizePolicyMaximum)
|
||
|
||
optional_layout = QVBoxLayout()
|
||
optional_layout.setSpacing(2)
|
||
optional_layout.setContentsMargins(10, 4, 4, 20)
|
||
|
||
optional_layout.addWidget(QLabel("(frei lassen für globale Linkliste)"))
|
||
|
||
self.linkliste_widget = QgsFileWidget()
|
||
self.linkliste_widget.setStorageMode(QgsFileWidget.GetFile)
|
||
self.linkliste_widget.setFilter("Excelliste (*.xlsx)")
|
||
self.linkliste_widget.fileChanged.connect(self._on_linkliste_changed)
|
||
optional_layout.addWidget(self.linkliste_widget)
|
||
|
||
self.optional_content.setLayout(optional_layout)
|
||
self.optional_content.setVisible(False)
|
||
main_layout.addWidget(self.optional_content)
|
||
|
||
# -------------------------------
|
||
# Layer-Auswahl
|
||
# -------------------------------
|
||
|
||
layer_label = QLabel("Verfahrensgebiet-Layer auswählen")
|
||
layer_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
||
main_layout.addWidget(layer_label)
|
||
|
||
self.layer_combo = QgsMapLayerComboBox()
|
||
self.layer_combo.setSizePolicy(SizePolicyPreferred, SizePolicyMaximum)
|
||
self.layer_combo.setFilters(QgsMapLayerProxyModel.VectorLayer)
|
||
self.layer_combo.layerChanged.connect(self._on_layer_changed)
|
||
main_layout.addWidget(self.layer_combo)
|
||
|
||
main_layout.addStretch(1)
|
||
self.setLayout(main_layout)
|
||
|
||
# ---------------------------------------------------------
|
||
# State Restore
|
||
# ---------------------------------------------------------
|
||
|
||
def _restore_state(self) -> None:
|
||
db = self.logic.load_verfahrens_db()
|
||
if db:
|
||
self.verfahrens_db = db
|
||
self.file_widget.setFilePath(db)
|
||
self._update_group_color()
|
||
|
||
link = self.logic.load_linkliste()
|
||
if link:
|
||
self.lokale_linkliste = link
|
||
self.linkliste_widget.setFilePath(link)
|
||
|
||
layer_id = self.logic.load_verfahrensgebiet_layer_id()
|
||
if layer_id:
|
||
layer = QgsProject.instance().mapLayer(layer_id)
|
||
if layer:
|
||
self.layer_combo.setLayer(layer)
|
||
|
||
# ---------------------------------------------------------
|
||
# UI-Callbacks
|
||
# ---------------------------------------------------------
|
||
|
||
def _toggle_group(self, checked: bool):
|
||
"""
|
||
Klappt den Gruppenbereich ein oder aus.
|
||
"""
|
||
if not hasattr(self, "group_button"):
|
||
return
|
||
|
||
self.group_button.setArrowType(
|
||
ArrowDown if checked else ArrowRight
|
||
)
|
||
|
||
self.group_content.setVisible(checked)
|
||
|
||
|
||
def _toggle_optional(self, checked: bool):
|
||
"""
|
||
Klappt den optionalen Bereich ein oder aus.
|
||
"""
|
||
if not hasattr(self, "optional_button"):
|
||
return
|
||
|
||
self.group_button.setArrowType(
|
||
ArrowDown if checked else ArrowRight
|
||
)
|
||
|
||
self.optional_content.setVisible(checked)
|
||
|
||
|
||
def _on_verfahrens_db_changed(self, path: str) -> None:
|
||
if not path:
|
||
self.verfahrens_db = None
|
||
self.logic.set_verfahrens_db(None)
|
||
self._update_group_color()
|
||
return
|
||
|
||
if not path.lower().endswith(".gpkg"):
|
||
path += ".gpkg"
|
||
self.file_widget.setFilePath(path)
|
||
|
||
if not file_exists(path):
|
||
warning("Datei nicht gefunden", f"Die Datei existiert nicht:\n{path}")
|
||
self.file_widget.setFilePath("")
|
||
return
|
||
|
||
self.verfahrens_db = path
|
||
self.logic.set_verfahrens_db(path)
|
||
self._update_group_color()
|
||
|
||
def _on_linkliste_changed(self, path: str) -> None:
|
||
if not path:
|
||
self.lokale_linkliste = None
|
||
self.logic.set_linkliste(None)
|
||
return
|
||
|
||
if not path.lower().endswith(".xlsx"):
|
||
path += ".xlsx"
|
||
self.linkliste_widget.setFilePath(path)
|
||
|
||
if not file_exists(path):
|
||
warning("Datei nicht gefunden", f"Die Datei existiert nicht:\n{path}")
|
||
self.linkliste_widget.setFilePath("")
|
||
return
|
||
|
||
self.lokale_linkliste = path
|
||
self.logic.set_linkliste(path)
|
||
|
||
def _on_layer_changed(self, layer) -> None:
|
||
self.logic.save_verfahrensgebiet_layer(layer)
|
||
|
||
def _create_new_gpkg(self) -> None:
|
||
file_path, _ = QFileDialog.getSaveFileName(
|
||
self,
|
||
"Neue Verfahrens-Datenbank anlegen",
|
||
"",
|
||
"Geopackage (*.gpkg)",
|
||
)
|
||
|
||
if not file_path:
|
||
return
|
||
|
||
if not file_path.lower().endswith(".gpkg"):
|
||
file_path += ".gpkg"
|
||
|
||
if file_exists(file_path):
|
||
overwrite = ask_yes_no(
|
||
"Datei existiert bereits",
|
||
f"Die Datei existiert bereits:\n\n{file_path}\n\nSoll sie überschrieben werden?",
|
||
default=False,
|
||
parent=self,
|
||
)
|
||
if not overwrite:
|
||
return
|
||
|
||
if not self.logic.create_new_verfahrens_db(file_path):
|
||
error("Fehler", "Die Datei konnte nicht angelegt werden.")
|
||
return
|
||
|
||
self.verfahrens_db = file_path
|
||
self.file_widget.setFilePath(file_path)
|
||
self._update_group_color()
|
||
info("Projekt-DB angelegt", f"Neue Projekt-Datenbank wurde angelegt:\n{file_path}")
|
||
|
||
# ---------------------------------------------------------
|
||
# UI-Helfer
|
||
# ---------------------------------------------------------
|
||
|
||
def _update_group_color(self):
|
||
"""
|
||
Aktualisiert die Darstellung der Gruppenüberschrift.
|
||
"""
|
||
if not hasattr(self, "group_button"):
|
||
return
|
||
|
||
if self.verfahrens_db:
|
||
self.group_button.setStyleSheet("font-weight: bold;")
|
||
else:
|
||
self.group_button.setStyleSheet("")
|
||
|