Eigentümersuche mit Trefferliste im Tab „Eigentümer“ (#56)
Eigentümerdatei (CSV-Layer mit Nachname/Vorname) wählen, Name und/oder Vorname eingeben: Eine nicht modale Trefferliste zeigt Name, Anschrift, E-Mail und die Kennzeichen „verstorben“/„Rechtsperson“. Gleiche Personen mit gleicher Anschrift werden zusammengefasst; Groß-/Kleinschreibung und Umlautschreibweise spielen keine Rolle. Von QGIS als Zahl gelesene PLZ bekommen ihre führende Null zurück. Meldungen enthalten keine Namen. Die Auswahltabelle aus „Verfahrensgebiete aus Landkreis laden“ ist als baue_auswahltabelle herausgelöst und wird von der Trefferliste mitgenutzt. Zweiter Schritt von #56; Anzeigefenster und Korrekturen folgen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
"""sn_verfahrensgebiet/functions/verfahrensgebiet_dialoge.py – Dialoge zum
|
||||
Laden eines Verfahrensgebiets aus ALKIS (Qt5/6/Mock-kompatibel).
|
||||
|
||||
Enthält außerdem die gemeinsame Auswahltabelle (:func:`baue_auswahltabelle`),
|
||||
die auch die Eigentümer-Trefferliste (#56) nutzt.
|
||||
"""
|
||||
from typing import Any, Optional
|
||||
from sn_basis.functions.qt_wrapper import (
|
||||
@@ -8,6 +11,7 @@ from sn_basis.functions.qt_wrapper import (
|
||||
QTableWidget, QTableWidgetItem, QTableWidgetSelectionRange,
|
||||
QIcon, QVBoxLayout, QHBoxLayout, QLabel, QCheckBox,
|
||||
DialogAccepted, ExtendedSelection, SelectRows, NoEditTriggers, AscendingOrder,
|
||||
UserRole,
|
||||
)
|
||||
from sn_basis.functions.landkreise import ALLE_LANDKREISE
|
||||
import os
|
||||
@@ -17,6 +21,98 @@ _PLUGINS_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
_WAPPEN_ICON = os.path.join(_PLUGINS_DIR, "sn_basis", "favicon.ico")
|
||||
|
||||
|
||||
def zeilen_sichtbar(zeilen_texte: list[list[str]], suchtext: str) -> list[bool]:
|
||||
"""Ob jede Tabellenzeile zum Suchtext passt: Teilstring in irgendeiner Spalte,
|
||||
ohne Groß-/Kleinschreibung. Ein leerer Suchtext zeigt alle Zeilen."""
|
||||
such = (suchtext or "").strip().lower()
|
||||
return [not such or any(such in (t or "").lower() for t in texte) for texte in zeilen_texte]
|
||||
|
||||
|
||||
def baue_auswahltabelle(
|
||||
layout: Any,
|
||||
spaltenkoepfe: list[str],
|
||||
zeilen: list[tuple[str, ...]],
|
||||
platzhalter: str = "Suche …",
|
||||
alle_auswaehlen: bool = True,
|
||||
) -> Any:
|
||||
"""Fügt Suchfeld, „Alle auswählen“, Auswahltabelle und Mehrfachauswahl-Hinweis
|
||||
in ``layout`` ein und gibt die Tabelle zurück.
|
||||
|
||||
Gemeinsamer Baustein von :func:`ask_landkreis_objekte` und der
|
||||
Eigentümer-Trefferliste (#56). Die Tabelle ist nach Spalte 0 aufsteigend
|
||||
sortiert, per Klick auf den Spaltenkopf umsortierbar und erlaubt die
|
||||
Mehrfachauswahl ganzer Zeilen. Spalte 0 trägt den Index der Zeile in
|
||||
``zeilen`` (``UserRole``), damit die Auswahl auch nach dem Umsortieren
|
||||
zugeordnet werden kann (:func:`ausgewaehlte_indizes`).
|
||||
"""
|
||||
suche_zeile = QHBoxLayout()
|
||||
suche_zeile.addWidget(QLabel("Suche:"))
|
||||
suche_feld = QLineEdit()
|
||||
suche_feld.setPlaceholderText(platzhalter)
|
||||
suche_zeile.addWidget(suche_feld)
|
||||
layout.addLayout(suche_zeile)
|
||||
|
||||
alle_checkbox = None
|
||||
if alle_auswaehlen:
|
||||
alle_checkbox = QCheckBox("Alle auswählen")
|
||||
layout.addWidget(alle_checkbox)
|
||||
|
||||
table = QTableWidget(len(zeilen), len(spaltenkoepfe))
|
||||
table.setHorizontalHeaderLabels(spaltenkoepfe)
|
||||
table.setSelectionMode(ExtendedSelection)
|
||||
table.setSelectionBehavior(SelectRows)
|
||||
table.setEditTriggers(NoEditTriggers)
|
||||
table.verticalHeader().setVisible(False)
|
||||
table.verticalHeader().setDefaultSectionSize(22) # flachere Zeilen
|
||||
table.horizontalHeader().setStretchLastSection(True)
|
||||
# Sortierung erst nach dem Befüllen einschalten, sonst wandern Zeilen beim setItem
|
||||
table.setSortingEnabled(False)
|
||||
for row, texte in enumerate(zeilen):
|
||||
for col, text in enumerate(texte):
|
||||
item = QTableWidgetItem(text)
|
||||
if col == 0:
|
||||
item.setData(UserRole, row)
|
||||
table.setItem(row, col, item)
|
||||
table.setSortingEnabled(True)
|
||||
table.sortByColumn(0, AscendingOrder)
|
||||
layout.addWidget(table, 1) # Stretch-Faktor: wächst mit Fenstergröße
|
||||
|
||||
def _suche_geaendert(text):
|
||||
texte = [
|
||||
[table.item(row, col).text() for col in range(table.columnCount())]
|
||||
for row in range(table.rowCount())
|
||||
]
|
||||
for row, sichtbar in enumerate(zeilen_sichtbar(texte, text)):
|
||||
table.setRowHidden(row, not sichtbar)
|
||||
|
||||
suche_feld.textChanged.connect(_suche_geaendert)
|
||||
|
||||
def _alle_auswaehlen_umschalten(checked):
|
||||
table.clearSelection()
|
||||
if checked:
|
||||
letzte_spalte = table.columnCount() - 1
|
||||
for row in range(table.rowCount()):
|
||||
if not table.isRowHidden(row):
|
||||
# setRangeSelected (statt selectRow) fügt der Selektion
|
||||
# hinzu, ohne vorherige Zeilen wieder abzuwählen.
|
||||
table.setRangeSelected(
|
||||
QTableWidgetSelectionRange(row, 0, row, letzte_spalte), True
|
||||
)
|
||||
|
||||
if alle_checkbox is not None:
|
||||
alle_checkbox.stateChanged.connect(_alle_auswaehlen_umschalten)
|
||||
|
||||
layout.addWidget(QLabel("<small>Mehrfachauswahl mit Strg + Umschalt</small>"))
|
||||
return table
|
||||
|
||||
|
||||
def ausgewaehlte_indizes(table: Any) -> list[int]:
|
||||
"""Indizes der ausgewählten Zeilen, bezogen auf ``zeilen`` aus
|
||||
:func:`baue_auswahltabelle`, aufsteigend."""
|
||||
zeilen = {item.row() for item in table.selectedItems()}
|
||||
return sorted(int(table.item(row, 0).data(UserRole)) for row in zeilen)
|
||||
|
||||
|
||||
def ask_bror_kombinationen(
|
||||
parent: Any,
|
||||
kombinationen: list[tuple[str, str]],
|
||||
@@ -144,65 +240,17 @@ def ask_landkreis_objekte(
|
||||
hinweis.setWordWrap(True)
|
||||
layout.addWidget(hinweis)
|
||||
|
||||
suche_zeile = QHBoxLayout()
|
||||
suche_zeile.addWidget(QLabel("Suche:"))
|
||||
suche_feld = QLineEdit()
|
||||
suche_feld.setPlaceholderText("Nummer oder Name …")
|
||||
suche_zeile.addWidget(suche_feld)
|
||||
layout.addLayout(suche_zeile)
|
||||
|
||||
alle_auswaehlen = QCheckBox("Alle auswählen")
|
||||
layout.addWidget(alle_auswaehlen)
|
||||
|
||||
# Standardsortierung nach Bezeichnung; per Klick auf Spaltenkopf änderbar
|
||||
# (setSortingEnabled aktiviert die eingebaute Tabellensortierung).
|
||||
# Standardsortierung nach Bezeichnung; per Klick auf Spaltenkopf änderbar.
|
||||
sortierte_kombinationen = sorted(kombinationen, key=lambda kb: kb[1])
|
||||
|
||||
table = QTableWidget(len(sortierte_kombinationen), 2)
|
||||
table.setHorizontalHeaderLabels(["Nummer", "Name"])
|
||||
table.setSelectionMode(ExtendedSelection)
|
||||
table.setSelectionBehavior(SelectRows)
|
||||
table.setEditTriggers(NoEditTriggers)
|
||||
table.verticalHeader().setVisible(False)
|
||||
table.verticalHeader().setDefaultSectionSize(22) # flachere Zeilen
|
||||
table.horizontalHeader().setStretchLastSection(True)
|
||||
table.setSortingEnabled(False)
|
||||
for row, (adv, bez) in enumerate(sortierte_kombinationen):
|
||||
table.setItem(row, 0, QTableWidgetItem(bez))
|
||||
table.setItem(row, 1, QTableWidgetItem(adv))
|
||||
table.setSortingEnabled(True)
|
||||
table.sortByColumn(0, AscendingOrder) # Standard: aufsteigend nach Nummer
|
||||
table = baue_auswahltabelle(
|
||||
layout,
|
||||
["Nummer", "Name"],
|
||||
[(bez, adv) for adv, bez in sortierte_kombinationen],
|
||||
platzhalter="Nummer oder Name …",
|
||||
)
|
||||
table.resizeColumnToContents(0)
|
||||
table.setColumnWidth(0, max(110, table.columnWidth(0)))
|
||||
table.selectRow(0)
|
||||
layout.addWidget(table, 1) # Stretch-Faktor: wächst mit Fenstergröße
|
||||
|
||||
def _suche_geaendert(text):
|
||||
text_lower = text.strip().lower()
|
||||
for row in range(table.rowCount()):
|
||||
bez_text = table.item(row, 0).text().lower()
|
||||
adv_text = table.item(row, 1).text().lower()
|
||||
treffer = not text_lower or text_lower in bez_text or text_lower in adv_text
|
||||
table.setRowHidden(row, not treffer)
|
||||
|
||||
suche_feld.textChanged.connect(_suche_geaendert)
|
||||
|
||||
def _alle_auswaehlen_umschalten(checked):
|
||||
table.clearSelection()
|
||||
if checked:
|
||||
letzte_spalte = table.columnCount() - 1
|
||||
for row in range(table.rowCount()):
|
||||
if not table.isRowHidden(row):
|
||||
# setRangeSelected (statt selectRow) fügt der Selektion
|
||||
# hinzu, ohne vorherige Zeilen wieder abzuwählen.
|
||||
table.setRangeSelected(
|
||||
QTableWidgetSelectionRange(row, 0, row, letzte_spalte), True
|
||||
)
|
||||
|
||||
alle_auswaehlen.stateChanged.connect(_alle_auswaehlen_umschalten)
|
||||
|
||||
mehrfachauswahl_hinweis = QLabel("<small>Mehrfachauswahl mit Strg + Umschalt</small>")
|
||||
layout.addWidget(mehrfachauswahl_hinweis)
|
||||
|
||||
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
||||
buttons.accepted.connect(dialog.accept)
|
||||
|
||||
Reference in New Issue
Block a user