Overrides-Fenster aufgeräumt + Rule-Templates

UX-Cleanup:
- Globaler AN/AUS-Toggle entfernt — den gibt's bereits in der
  Oberleiste, doppelt war redundant.
- Reload/Refresh-Button entfernt — Backend re-applied automatisch
  bei jeder Regel-Aenderung, manuelles Reload nicht noetig.
- + (Neue Regel) wurde aus dem Header in eine neue Sektion
  UNTER der Kombinationen-Card verschoben.

Neues Feature: Rule-Templates (einzelne wiederverwendbare Regeln)
- Storage: ~/Library/.../override_rule_templates.json (cross-doc,
  parallel zu den Kombinationen-Presets)
- API in overrides.py: list/save/load/delete_rule_template
- Bridge-Messages: SAVE_RULE_TEMPLATE, DELETE_RULE_TEMPLATE,
  ADD_FROM_TEMPLATE
- State enthaelt jetzt ruleTemplates: [{name, rule}]

UI:
- Neuer Bereich "Neue Regel" unter Kombinationen: [+ leer] +
  [+ Aus Vorlage ▼ dropdown]
- Vorlage waehlen → insert auf hoechste Prio (gleich wie addRule)
- Im Dropdown unten: "🗑 <name> loeschen" zum Entfernen einer Vorlage
- Im Rule-Kontextmenue: neuer Eintrag "Als Vorlage speichern…"
  fragt nach Name, speichert die Regel cross-doc

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-19 02:10:31 +02:00
parent 42d9c1e27b
commit e3918cb155
4 changed files with 172 additions and 35 deletions
+38 -7
View File
@@ -67,13 +67,14 @@ def _list_hatch_patterns(doc):
def _payload(doc):
cfg = overrides.load_config(doc)
return {
"enabled": bool(cfg.get("enabled")),
"rules": cfg.get("rules") or [],
"layers": _list_layer_names(doc),
"linetypes": _list_linetypes(doc),
"hatchPatterns": _list_hatch_patterns(doc),
"presets": overrides.list_presets(),
"activePreset": cfg.get("activePreset"),
"enabled": bool(cfg.get("enabled")),
"rules": cfg.get("rules") or [],
"layers": _list_layer_names(doc),
"linetypes": _list_linetypes(doc),
"hatchPatterns": _list_hatch_patterns(doc),
"presets": overrides.list_presets(),
"activePreset": cfg.get("activePreset"),
"ruleTemplates": overrides.list_rule_templates(),
}
@@ -210,6 +211,36 @@ class OverridesBridge(panel_base.BaseBridge):
overrides.delete_preset(name)
self._send_state()
# --- Rule-Templates (cross-doc, einzelne Regeln) ----------------
elif t == "SAVE_RULE_TEMPLATE":
name = (p.get("name") or "").strip()
rule = p.get("rule") or {}
if name and isinstance(rule, dict):
# ID/Name aus dem Template-Rule herausschneiden (template hat
# eigenen Namen, ID wird beim Insert neu generiert)
clean = {k: v for k, v in rule.items() if k not in ("id",)}
overrides.save_rule_template(name, clean)
self._send_state()
elif t == "DELETE_RULE_TEMPLATE":
name = (p.get("name") or "").strip()
if name:
overrides.delete_rule_template(name)
self._send_state()
elif t == "ADD_FROM_TEMPLATE":
name = (p.get("name") or "").strip()
if not name: return
tpl = overrides.load_rule_template(name)
if not tpl: return
cfg = overrides.load_config(doc)
new_rule = dict(tpl)
new_rule["id"] = "rule_" + uuid.uuid4().hex[:8]
new_rule.setdefault("enabled", True)
new_rule.setdefault("name", name)
rules = cfg.get("rules") or []
rules.insert(0, new_rule)
overrides.update_rules(doc, rules, cfg.get("enabled"))
self._send_state()
def _ensure_listeners_once():
"""Overrides-Listener nur EINMAL global installieren (statt bei jedem