Projektdaten in Project-Settings + Swisstopo-Adress-Prefill
Schema-Erweiterung: - _PROJECT_SETTINGS_DEFAULTS hat jetzt 'project'-Block mit name / number / address / bauherr / architekt / notes / projectZeroMum - _normalize_project_meta stripped Strings + clampt mum als float - load/save_project_settings handeln das 'project'-feld - save_project_settings spiegelt projectZeroMum auch in den Legacy-Key dossier_project_zero_mum (fuer Geschoss-Settings-Dialog) - load_project_settings liest Legacy-Key als Fallback wenn neuer Wert noch nicht gesetzt UI: - InlineTextField + TextareaField Helpers (Pill-Stil) - Projektdaten-Section in Voreinstellungen-Tab: Name, Projekt-Nr., Adresse, Bauherrschaft, Architekt:in, EG-Nullpunkt m.ü.M (mit Hinweis auf Swisstopo-Nutzung), Notizen Swisstopo: - _cmd_open_swisstopo_dialog laedt Projekt-Adresse + sendet projectAddress im SWISSTOPO_STATE - SwisstopoApp: vorbelegt searchText mit projectAddress wenn Feld leer ist (User-Input wird nicht ueberschrieben) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -8217,6 +8217,14 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
e_raw = doc.Strings.GetValue("dossier_ebenen") if doc else None
|
||||
ebenen = json.loads(e_raw) if e_raw else []
|
||||
except Exception: ebenen = []
|
||||
# Projekt-Adresse als Vorschlag fuer die Adress-Suche
|
||||
project_address = ""
|
||||
try:
|
||||
import rhinopanel
|
||||
ps = rhinopanel.load_project_settings(doc) if doc else None
|
||||
if isinstance(ps, dict):
|
||||
project_address = (ps.get("project", {}) or {}).get("address") or ""
|
||||
except Exception: pass
|
||||
|
||||
class _SwisstopoBridge(panel_base.BaseBridge):
|
||||
def __init__(self):
|
||||
@@ -8225,6 +8233,7 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
self.send("SWISSTOPO_STATE", {
|
||||
"ebenen": ebenen,
|
||||
"cacheDir": __import__("swisstopo").CACHE_DIR,
|
||||
"projectAddress": project_address,
|
||||
})
|
||||
def _push_log(self, msg):
|
||||
try: self.send("SWISSTOPO_LOG", {"msg": str(msg)})
|
||||
|
||||
+74
-20
@@ -283,11 +283,39 @@ _PROJECT_SETTINGS_DEFAULTS = {
|
||||
"schnittHeightMin": -1.0,
|
||||
"schnittHeightMax": 12.0,
|
||||
},
|
||||
"materials": [], # User-erweiterte Materialien (zusaetzlich zur
|
||||
# hardcoded _MATERIAL_LIBRARY in elemente.py)
|
||||
"materials": [],
|
||||
"project": {
|
||||
"name": "",
|
||||
"number": "",
|
||||
"address": "",
|
||||
"bauherr": "",
|
||||
"architekt": "",
|
||||
"notes": "",
|
||||
# m.ü.M (Meter ueber Meer) des Rhino-z=0 (= EG-Nullpunkt). Wird
|
||||
# von Swisstopo/Terrain-Import zur Hoehen-Kalibrierung genutzt.
|
||||
"projectZeroMum": 0.0,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _normalize_project_meta(p):
|
||||
"""Garantiert das project-Schema. Strings werden gestripped, mum als
|
||||
float (default 0.0 wenn nicht parsebar)."""
|
||||
if not isinstance(p, dict): p = {}
|
||||
try: mum = float(p.get("projectZeroMum", 0.0) or 0.0)
|
||||
except Exception: mum = 0.0
|
||||
def _s(k): return str(p.get(k) or "")
|
||||
return {
|
||||
"name": _s("name"),
|
||||
"number": _s("number"),
|
||||
"address": _s("address"),
|
||||
"bauherr": _s("bauherr"),
|
||||
"architekt": _s("architekt"),
|
||||
"notes": _s("notes"),
|
||||
"projectZeroMum": mum,
|
||||
}
|
||||
|
||||
|
||||
def _normalize_material(m):
|
||||
"""Garantiert Material-Schema. Material ist REIN 3D — Section-Hatch
|
||||
(2D-Schnitt) wird via Ebenen-Settings am Layer konfiguriert.
|
||||
@@ -343,39 +371,64 @@ def _clamp(v, lo, hi):
|
||||
|
||||
def load_project_settings(doc):
|
||||
"""Liefert die Project-Settings als dict — mit Defaults-Merge wenn
|
||||
Felder fehlen. Garantiert dass `defaults` und `materials` immer da
|
||||
sind, und Materialien normalisiert (source + libraryId)."""
|
||||
Felder fehlen. Garantiert dass `defaults`, `materials` und `project`
|
||||
immer da sind."""
|
||||
raw = None
|
||||
try: raw = doc.Strings.GetValue(_PROJECT_SETTINGS_KEY) if doc else None
|
||||
except Exception: raw = None
|
||||
out = {
|
||||
"defaults": dict(_PROJECT_SETTINGS_DEFAULTS["defaults"]),
|
||||
"materials": list(_PROJECT_SETTINGS_DEFAULTS["materials"]),
|
||||
"project": dict(_PROJECT_SETTINGS_DEFAULTS["project"]),
|
||||
}
|
||||
if not raw: return out
|
||||
if raw:
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
if isinstance(data, dict):
|
||||
d = data.get("defaults")
|
||||
if isinstance(d, dict):
|
||||
for k, v in d.items():
|
||||
out["defaults"][k] = v
|
||||
m = data.get("materials")
|
||||
if isinstance(m, list):
|
||||
out["materials"] = [
|
||||
_normalize_material(x) for x in m
|
||||
if _normalize_material(x) is not None
|
||||
]
|
||||
pr = data.get("project")
|
||||
if isinstance(pr, dict):
|
||||
out["project"] = _normalize_project_meta(pr)
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] load:", ex)
|
||||
# Legacy-Sync: alter dossier_project_zero_mum-Wert in project.projectZeroMum
|
||||
# spiegeln wenn Project-Settings noch keinen hat. Geschoss-Settings-Dialog
|
||||
# schreibt diesen Key separat — wir lesen ihn als fallback.
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
if isinstance(data, dict):
|
||||
d = data.get("defaults")
|
||||
if isinstance(d, dict):
|
||||
for k, v in d.items():
|
||||
out["defaults"][k] = v
|
||||
m = data.get("materials")
|
||||
if isinstance(m, list):
|
||||
out["materials"] = [
|
||||
_normalize_material(x) for x in m
|
||||
if _normalize_material(x) is not None
|
||||
]
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] load:", ex)
|
||||
if doc and out["project"]["projectZeroMum"] == 0.0:
|
||||
legacy = doc.Strings.GetValue("dossier_project_zero_mum")
|
||||
if legacy:
|
||||
out["project"]["projectZeroMum"] = float(legacy)
|
||||
except Exception: pass
|
||||
return out
|
||||
|
||||
|
||||
def save_project_settings(doc, settings):
|
||||
"""Persistiert Settings in doc.Strings. settings: dict mit
|
||||
'defaults' + 'materials'. Caller broadcastet ggf. selbst."""
|
||||
'defaults' + 'materials' + 'project'. Schreibt auch
|
||||
`dossier_project_zero_mum` separat (legacy-key fuer Geschoss-Settings)."""
|
||||
if doc is None or not isinstance(settings, dict): return False
|
||||
try:
|
||||
# project-Block normalisieren bevor wir speichern
|
||||
if "project" in settings:
|
||||
settings = dict(settings)
|
||||
settings["project"] = _normalize_project_meta(settings["project"])
|
||||
# Legacy-Key spiegeln
|
||||
try:
|
||||
mum = settings["project"].get("projectZeroMum", 0.0)
|
||||
doc.Strings.SetString("dossier_project_zero_mum",
|
||||
"{:.6f}".format(float(mum)))
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] mum sync:", ex)
|
||||
doc.Strings.SetString(_PROJECT_SETTINGS_KEY,
|
||||
json.dumps(settings, ensure_ascii=False))
|
||||
return True
|
||||
@@ -849,6 +902,7 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
new_settings = {
|
||||
"defaults": updated.get("defaults", {}),
|
||||
"materials": updated.get("materials", []),
|
||||
"project": updated.get("project", {}),
|
||||
}
|
||||
save_project_settings(doc2, new_settings)
|
||||
_broadcast_state(doc2)
|
||||
|
||||
Reference in New Issue
Block a user