Merge branch 'main' into dev/jappel
Reconciles two independent lines of work: main cherry-picked and then extended dev/jappel's build-script/config-portability/rename-tab/ COM-port fixes, additionally fixing a config-loss bug (rebuild wiped the config when it lived in the install dir -- moved to roaming %APPDATA% instead) and adding free-text notes per action plus a frameless resizable window. dev/jappel keeps its .mcp.json registration and docs/ reference tree, which main deliberately left out. Conflict resolutions favored main's versions where the two sides solved the same problem (config location, build deploy target, COM-port release, tab rename) since main's fixes were validated against a real rebuild-wipes-config incident. docs/architecture.md and docs/data-model.md updated to describe the resulting %APPDATA% config path and the note field.
This commit is contained in:
commit
189ec01e68
11 changed files with 470 additions and 125 deletions
|
|
@ -7,21 +7,35 @@ Kein Schreibzugriff auf die JSONs -- reines Lesen/Anzeigen.
|
|||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
NUM_PROFILES = 3
|
||||
|
||||
APP_NAME = "VersaPadViewer"
|
||||
|
||||
|
||||
def app_dir():
|
||||
"""Verzeichnis fuer die eigene Config-Datei (versapad_config_all.json,
|
||||
siehe versapad_combined.DEFAULT_PATH): bei der gebauten .exe (--onedir)
|
||||
das Installationsverzeichnis neben der .exe, sonst der Ordner dieses
|
||||
Moduls (Projektordner beim Start aus dem Quellcode). Kein hartkodierter
|
||||
Pfad mehr -- so laesst sich das Tool auf jede Maschine kopieren/
|
||||
installieren, ohne Pfade von Hand anzupassen."""
|
||||
if getattr(sys, "frozen", False):
|
||||
return os.path.dirname(sys.executable)
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
siehe versapad_combined.DEFAULT_PATH). Programmatisch aus der Umgebung
|
||||
abgeleitet, kein hartkodierter Pfad -- laeuft so auf jeder Maschine und
|
||||
unter jedem Benutzer.
|
||||
|
||||
Bewusst NICHT vom Startweg abhaengig (kein `sys.frozen`-Zweig): die
|
||||
gebaute .exe, der Start aus dem Quellcode und der MCP-Server muessen
|
||||
dieselbe Datei sehen, sonst laufen zwei Configs auseinander und
|
||||
Aenderungen aus dem einen Weg sind im anderen unsichtbar (genau das ist
|
||||
am 2026-08-15 passiert -- .exe zeigte ein anderes Profil 0 als der
|
||||
MCP-Server).
|
||||
|
||||
Bewusst auch NICHT das Installationsverzeichnis (%LOCALAPPDATA%\\
|
||||
VersaPadViewer, wo die .exe liegt): `build_and_deploy.ps1` raeumt das
|
||||
Zielverzeichnis vor jedem Deploy komplett ab (`Remove-Item -Recurse`) --
|
||||
laege die Config dort, wuerde JEDER Rebuild die Nutzerdaten mitloeschen
|
||||
(am 2026-08-15 genau so passiert, alle Notizen weg). Programm- und
|
||||
Datenverzeichnis bleiben deshalb getrennt: Roaming-AppData fuer die
|
||||
Config."""
|
||||
base = (os.environ.get("APPDATA") or os.environ.get("LOCALAPPDATA")
|
||||
or os.path.join(os.path.expanduser("~"), ".local", "share"))
|
||||
return os.path.join(base, APP_NAME)
|
||||
|
||||
|
||||
# CONFIG_PATHS zeigt bewusst weiterhin auf den OneDrive-Desktop -- das sind
|
||||
|
|
@ -206,15 +220,20 @@ def button_grid_position(index):
|
|||
|
||||
|
||||
def annotate_profile(cfg):
|
||||
"""Fuegt label/col/row-Felder hinzu (fuer die Anzeige) -- egal ob cfg aus
|
||||
einer Einzel-JSON oder aus dem kombinierten Programmiermodus-State kommt."""
|
||||
"""Fuegt label/note/col/row-Felder hinzu (fuer die Anzeige) -- egal ob
|
||||
cfg aus einer Einzel-JSON (kennt keine Notizen, faellt auf "" zurueck)
|
||||
oder aus dem kombinierten Programmiermodus-State kommt."""
|
||||
for b in cfg["buttons"]:
|
||||
b["label"] = action_label(b["action"])
|
||||
b["note"] = b["action"].get("note", "")
|
||||
b["col"], b["row"] = button_grid_position(b["index"])
|
||||
for e in cfg["encoders"]:
|
||||
e["sw_label"] = action_label(e["sw"])
|
||||
e["sw_note"] = e["sw"].get("note", "")
|
||||
e["cw_label"] = action_label(e["cw"])
|
||||
e["cw_note"] = e["cw"].get("note", "")
|
||||
e["ccw_label"] = action_label(e["ccw"])
|
||||
e["ccw_note"] = e["ccw"].get("note", "")
|
||||
return cfg
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue