Fix expansion state detection and rewrite hover-reveal with EventControllerMotion

This commit is contained in:
Pavel Baksy 2026-06-02 17:18:04 +02:00
parent 71f01edde0
commit bea3fe1b74
2 changed files with 31 additions and 18 deletions

View File

@ -62,11 +62,17 @@ class RequestItem(Gtk.Box):
self._setup_menu() self._setup_menu()
# Click gesture for loading (on the whole row, but not on the menu button) # Click gesture for loading
gesture = Gtk.GestureClick.new() gesture = Gtk.GestureClick.new()
gesture.connect('released', self._on_clicked) gesture.connect('released', self._on_clicked)
self.add_controller(gesture) self.add_controller(gesture)
# Show/hide menu button on hover
motion = Gtk.EventControllerMotion.new()
motion.connect('enter', self._on_hover_enter)
motion.connect('leave', self._on_hover_leave)
self.add_controller(motion)
def _setup_menu(self): def _setup_menu(self):
actions = Gio.SimpleActionGroup.new() actions = Gio.SimpleActionGroup.new()
@ -107,17 +113,31 @@ class RequestItem(Gtk.Box):
self.menu_button.set_menu_model(menu) self.menu_button.set_menu_model(menu)
# Hidden by default; shown on hover via EventControllerMotion.
# When the popover closes, hide the button again.
self.menu_button.set_opacity(0.0)
popover = self.menu_button.get_popover()
if popover:
popover.connect('closed', lambda p: self.menu_button.set_opacity(0.0))
def _on_move_to_project_activated(self, action, param): def _on_move_to_project_activated(self, action, param):
self.emit('move-to-project-requested', param.get_string()) self.emit('move-to-project-requested', param.get_string())
def _on_clicked(self, gesture, n_press, x, y): def _on_clicked(self, gesture, n_press, x, y):
"""Load request on row click (but not if the menu button was clicked).""" """Load request on row click (but not if the menu button was clicked)."""
# Check if the click was on the menu button — if so, ignore
alloc = self.menu_button.get_allocation() alloc = self.menu_button.get_allocation()
if alloc.x <= x <= alloc.x + alloc.width and alloc.y <= y <= alloc.y + alloc.height: if alloc.x <= x <= alloc.x + alloc.width and alloc.y <= y <= alloc.y + alloc.height:
return return
self.emit('load-requested') self.emit('load-requested')
def _on_hover_enter(self, controller, x, y):
self.menu_button.set_opacity(1.0)
def _on_hover_leave(self, controller):
popover = self.menu_button.get_popover()
if not (popover and popover.get_visible()):
self.menu_button.set_opacity(0.0)
def set_can_move_up(self, can: bool): def set_can_move_up(self, can: bool):
self._move_up_action.set_enabled(can) self._move_up_action.set_enabled(can)

View File

@ -224,16 +224,6 @@ class RosterWindow(Adw.ApplicationWindow):
min-width: 0; min-width: 0;
} }
/* Request menu button: hidden by default, visible on row hover or when open */
.request-menu-button {
opacity: 0;
transition: opacity 150ms ease;
}
row:hover .request-menu-button,
.request-menu-button:checked {
opacity: 1;
}
/* Method chips in sidebar request list */ /* Method chips in sidebar request list */
.method-chip { .method-chip {
border-radius: 4px; border-radius: 4px;
@ -971,13 +961,16 @@ class RosterWindow(Adw.ApplicationWindow):
def _load_projects(self) -> None: def _load_projects(self) -> None:
"""Load and display projects.""" """Load and display projects."""
# Remember which projects are currently expanded # Remember which projects are currently expanded.
# GtkListBox wraps each child in a GtkListBoxRow, so we call get_child()
# on the row to reach the actual ProjectItem widget.
expanded_ids = set() expanded_ids = set()
child = self.projects_listbox.get_first_child() row = self.projects_listbox.get_first_child()
while child: while row:
if isinstance(child, ProjectItem) and child.expanded: project_item = row.get_child()
expanded_ids.add(child.project.id) if isinstance(project_item, ProjectItem) and project_item.expanded:
child = child.get_next_sibling() expanded_ids.add(project_item.project.id)
row = row.get_next_sibling()
# Clear existing # Clear existing
while child := self.projects_listbox.get_first_child(): while child := self.projects_listbox.get_first_child():