Close the popover when 'Add X' opens a dialog or arms map placement

Every menu popover (Units/Spotters/Reference Points/Targets/Scout
Flights) stayed open on top of the modal dialog or map-click placement
its own 'Add <thing>' button just triggered, holding onto focus that
should have gone to the new dialog or the map instead. _add_row() now
takes a close() callback (threaded through from _make_menu_button,
which already owns the Gtk.Popover) and pops the popover down right
before calling on_click().

Verified end to end with a GTK smoke test: opens the real 'Scout
Flights' popover, clicks its real 'Add scout flight' button, confirms
the popover is no longer visible afterward.
This commit is contained in:
Dominik Moritz Roth 2026-08-09 20:32:06 +02:00
parent 77fe6a2948
commit 68d312934b

View File

@ -130,18 +130,23 @@ def _row(
return box
def _add_row(label: str, on_click) -> Gtk.Widget:
def _add_row(label: str, on_click, close) -> Gtk.Widget:
"""The trailing 'Add <thing>' row in a popover: just one button, not
the full _row() layout (which always pairs a manual-input action
with a per-item screenshot action). There's nothing to screenshot
*into* yet for something that doesn't exist, and the universal
clipboard button in the header already covers 'load everything from
a screenshot' for every category, a second, category-specific
version of that here was redundant."""
version of that here was redundant.
Closes the popover before calling on_click(): every on_click here
either opens its own modal dialog or arms map-click placement, and
the popover staying open on top of that just holds onto focus the
dialog/map should have instead."""
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6,
margin_top=4, margin_bottom=4, margin_start=8, margin_end=8)
btn = Gtk.Button(label=label, hexpand=True)
btn.connect("clicked", lambda _b: on_click())
btn.connect("clicked", lambda _b: (close(), on_click()))
box.append(btn)
return box
@ -341,17 +346,21 @@ class MainWindow(Adw.ApplicationWindow):
# -- generic helpers -----------------------------------------------------
def _make_menu_button(self, label: str, build_popover) -> Gtk.MenuButton:
"""build_popover(rebuild) returns the popover's content widget;
rebuild() lets a row's own callback refresh the popover in place
(e.g. after toggling hidden, or removing an item) instead of only
refreshing next time it's reopened."""
"""build_popover(rebuild, close) returns the popover's content
widget; rebuild() lets a row's own callback refresh the popover
in place (e.g. after toggling hidden, or removing an item)
instead of only refreshing next time it's reopened. close()
closes the popover outright, for an action that opens its own
modal dialog or arms map-click placement, where the popover
staying open on top just holds onto focus that dialog/the map
should have instead (see _add_row's use of it)."""
button = Gtk.MenuButton(label=label)
popover = Gtk.Popover()
popover.set_size_request(280, -1)
button.set_popover(popover)
def rebuild():
popover.set_child(build_popover(rebuild))
popover.set_child(build_popover(rebuild, popover.popdown))
popover.connect("show", lambda _p: rebuild())
return button
@ -716,7 +725,7 @@ class MainWindow(Adw.ApplicationWindow):
self.cursor_label.set_label(coord.label())
# -- Spotters --------------------------------------------------------------
def _build_spotters_popover(self, rebuild) -> Gtk.Widget:
def _build_spotters_popover(self, rebuild, close) -> Gtk.Widget:
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
box.set_margin_top(6)
box.set_margin_bottom(6)
@ -742,7 +751,7 @@ class MainWindow(Adw.ApplicationWindow):
on_submit=lambda loc, id_, _t: self._add_spotter(loc, id_),
show_id=True,
id_placeholder=f"ID (blank = auto, next: {self.board.next_spotter_id()})",
)))
), close))
return box
def _add_spotter(self, location: Location, id_text: str | None) -> None:
@ -762,7 +771,7 @@ class MainWindow(Adw.ApplicationWindow):
rebuild()
# -- Reference Points --------------------------------------------------------
def _build_rp_popover(self, rebuild) -> Gtk.Widget:
def _build_rp_popover(self, rebuild, close) -> Gtk.Widget:
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
box.set_margin_top(6)
box.set_margin_bottom(6)
@ -787,7 +796,7 @@ class MainWindow(Adw.ApplicationWindow):
box.append(_add_row("Add RP", lambda: self._open_coord_dialog(
title="Add reference point",
on_submit=lambda loc, _id, _t: self._add_rp(loc),
)))
), close))
return box
def _add_rp(self, location: Location) -> None:
@ -815,7 +824,7 @@ class MainWindow(Adw.ApplicationWindow):
self.toast(f"{rp.name} converted to {new_target.name}.")
# -- Targets -----------------------------------------------------------------
def _build_targets_popover(self, rebuild) -> Gtk.Widget:
def _build_targets_popover(self, rebuild, close) -> Gtk.Widget:
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
box.set_margin_top(6)
box.set_margin_bottom(6)
@ -844,7 +853,7 @@ class MainWindow(Adw.ApplicationWindow):
on_submit=lambda loc, id_, type_: self._add_target(loc, id_, type_),
show_id=True,
show_type=True,
)))
), close))
return box
def _add_target(self, location: Location, id_, type_) -> None:
@ -866,7 +875,7 @@ class MainWindow(Adw.ApplicationWindow):
self.toast(f"{target.name} converted to {new_rp.name}.")
# -- Units (Nest + Allies) -------------------------------------------------
def _build_units_popover(self, rebuild) -> Gtk.Widget:
def _build_units_popover(self, rebuild, close) -> Gtk.Widget:
"""Your own side of the map: the Nest (always first, there's
only ever one) plus every friendly contact ('FriendlyTank#1:',
tracked entirely separately from Targets, see models.py's
@ -913,7 +922,7 @@ class MainWindow(Adw.ApplicationWindow):
on_submit=lambda loc, id_, type_: self._add_ally(loc, id_, type_),
show_id=True,
show_type=True,
)))
), close))
return box
def _add_ally(self, location: Location, id_, type_) -> None:
@ -926,7 +935,7 @@ class MainWindow(Adw.ApplicationWindow):
rebuild()
# -- Scout Flights ------------------------------------------------------------
def _build_scout_flights_popover(self, rebuild) -> Gtk.Widget:
def _build_scout_flights_popover(self, rebuild, close) -> Gtk.Widget:
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
box.set_margin_top(6)
box.set_margin_bottom(6)
@ -940,7 +949,7 @@ class MainWindow(Adw.ApplicationWindow):
))
box.append(Gtk.Separator())
box.append(_add_row("Add scout flight", self._add_scout_flight))
box.append(_add_row("Add scout flight", self._add_scout_flight, close))
return box
def _add_scout_flight(self) -> None: