From 6e18d60eb52d9e5fd9429c433abaca73451a96f4 Mon Sep 17 00:00:00 2001 From: Dominik Roth Date: Thu, 13 Aug 2026 19:42:52 +0200 Subject: [PATCH] Fix Change ID dialog still enforcing the old shared-per-group id rule The manual "Change ID" popover's collision check was never updated when Board.add_target/add_ally's auto-id scheme changed to per-type (commit d2f7067): it still rejected a rename if ANY target/ally in the whole group had that id, regardless of type, so e.g. renaming an Infantry to id "4" failed with "Another target already has id '4'" just because an unrelated Mechanized already used it. Now scopes the collision check to siblings of the SAME type, matching add_target/ add_ally exactly. Verified directly against the same expression run on real Board/Target objects (a full GTK popover popup cycle needs a real window surface, not available headlessly). Co-Authored-By: Claude Sonnet 5 --- src/fenigma/app.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fenigma/app.py b/src/fenigma/app.py index ea2d83f..ef0fd87 100644 --- a/src/fenigma/app.py +++ b/src/fenigma/app.py @@ -1721,16 +1721,18 @@ class MainWindow(Adw.ApplicationWindow): return elif field == "id" and isinstance(obj, (Target, Ally)): # Same invariant as Board.add_target/add_ally's auto-id - # (see their comments): one shared id namespace per group, - # targets vs allies, never split further by type. A manual - # rename has to keep that too, or you get two entities - # that both read as e.g. "...#A" with only the type prefix - # telling them apart. + # (see their comments): id namespace is targets-vs-allies, + # AND scoped per type within that -- a Tank#1 and an + # Infantry#1 are not a collision, only two entities of the + # SAME type sharing an id are. A manual rename has to keep + # that too, or you get two entities that both read as + # e.g. "Infantry#1" with nothing telling them apart. value = text - siblings = self.board.targets if isinstance(obj, Target) else self.board.allies + group = self.board.targets if isinstance(obj, Target) else self.board.allies + siblings = [o for o in group if o.type == obj.type] if any(o is not obj and o.id == value for o in siblings): kind = "target" if isinstance(obj, Target) else "ally" - self.toast(f"Another {kind} already has id {value!r}.") + self.toast(f"Another {obj.type.short} {kind} already has id {value!r}.") return else: value = text