[gnome-builder] libide-gui: use single selection for search results



commit 8b28a19c589703848e55c67636cb12c3f1a5f97a
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jul 12 22:37:06 2022 -0700

    libide-gui: use single selection for search results
    
    This also allows us to use the signal callbacks for movements from the
    search entry (for ctrl+g/ctrl+shift+g).

 src/libide/gui/ide-search-popover.c  | 61 ++++++++++++++++++++++++++++--------
 src/libide/gui/ide-search-popover.ui |  5 ++-
 2 files changed, 52 insertions(+), 14 deletions(-)
---
diff --git a/src/libide/gui/ide-search-popover.c b/src/libide/gui/ide-search-popover.c
index ba71fb2ed..922413c13 100644
--- a/src/libide/gui/ide-search-popover.c
+++ b/src/libide/gui/ide-search-popover.c
@@ -31,18 +31,18 @@
 
 struct _IdeSearchPopover
 {
-  GtkPopover       parent_instance;
+  GtkPopover          parent_instance;
 
-  GCancellable    *cancellable;
-  IdeSearchEngine *search_engine;
+  GCancellable       *cancellable;
+  IdeSearchEngine    *search_engine;
 
-  GtkSearchEntry  *entry;
-  GtkNoSelection  *selection;
-  GtkListView     *list_view;
+  GtkSearchEntry     *entry;
+  GtkSingleSelection *selection;
+  GtkListView        *list_view;
 
-  guint            queued_search;
+  guint               queued_search;
 
-  guint            activate_after_search : 1;
+  guint               activate_after_search : 1;
 };
 
 enum {
@@ -132,7 +132,7 @@ ide_search_popover_search_cb (GObject      *object,
   if (error != NULL)
     g_debug ("Search failed: %s", error->message);
 
-  gtk_no_selection_set_model (self->selection, results);
+  gtk_single_selection_set_model (self->selection, results);
 
   if (self->activate_after_search)
     {
@@ -140,9 +140,12 @@ ide_search_popover_search_cb (GObject      *object,
 
       if (results != NULL && g_list_model_get_n_items (results) > 0)
         {
-          g_autoptr(IdeSearchResult) first = g_list_model_get_item (results, 0);
-          g_assert (IDE_IS_SEARCH_RESULT (first));
-          ide_search_popover_activate (self, first);
+          IdeSearchResult *selected = gtk_single_selection_get_selected_item (self->selection);
+
+          g_assert (!selected || IDE_IS_SEARCH_RESULT (selected));
+
+          if (selected != NULL)
+            ide_search_popover_activate (self, selected);
         }
     }
 
@@ -183,7 +186,7 @@ ide_search_popover_search_source_func (gpointer data)
 
 failure:
   self->activate_after_search = FALSE;
-  gtk_no_selection_set_model (self->selection, NULL);
+  gtk_single_selection_set_model (self->selection, NULL);
 
   IDE_RETURN (G_SOURCE_REMOVE);
 }
@@ -254,6 +257,36 @@ ide_search_popover_entry_activate_cb (IdeSearchPopover *self,
   ide_search_popover_queue_search (self);
 }
 
+static void
+ide_search_popover_next_match_cb (IdeSearchPopover *self,
+                                  GtkSearchEntry   *entry)
+{
+  guint selected;
+
+  g_assert (IDE_IS_SEARCH_POPOVER (self));
+  g_assert (GTK_IS_SEARCH_ENTRY (entry));
+
+  selected = gtk_single_selection_get_selected (self->selection);
+
+  if (selected + 1 < g_list_model_get_n_items (G_LIST_MODEL (self->selection)))
+    gtk_single_selection_set_selected (self->selection, selected + 1);
+}
+
+static void
+ide_search_popover_previous_match_cb (IdeSearchPopover *self,
+                                      GtkSearchEntry   *entry)
+{
+  guint selected;
+
+  g_assert (IDE_IS_SEARCH_POPOVER (self));
+  g_assert (GTK_IS_SEARCH_ENTRY (entry));
+
+  selected = gtk_single_selection_get_selected (self->selection);
+
+  if (selected > 0)
+    gtk_single_selection_set_selected (self->selection, selected - 1);
+}
+
 static void
 ide_search_popover_show (GtkWidget *widget)
 {
@@ -358,6 +391,8 @@ ide_search_popover_class_init (IdeSearchPopoverClass *klass)
   gtk_widget_class_bind_template_callback (widget_class, ide_search_popover_activate_cb);
   gtk_widget_class_bind_template_callback (widget_class, ide_search_popover_entry_activate_cb);
   gtk_widget_class_bind_template_callback (widget_class, ide_search_popover_search_changed_cb);
+  gtk_widget_class_bind_template_callback (widget_class, ide_search_popover_next_match_cb);
+  gtk_widget_class_bind_template_callback (widget_class, ide_search_popover_previous_match_cb);
 
   gtk_widget_class_install_action (widget_class, "search.hide", NULL, ide_search_popover_hide_action);
 }
diff --git a/src/libide/gui/ide-search-popover.ui b/src/libide/gui/ide-search-popover.ui
index 668aa6cab..63f8fc138 100644
--- a/src/libide/gui/ide-search-popover.ui
+++ b/src/libide/gui/ide-search-popover.ui
@@ -21,6 +21,8 @@
                 <property name="width-chars">40</property>
                 <signal name="activate" handler="ide_search_popover_entry_activate_cb" swapped="true" 
object="IdeSearchPopover"/>
                 <signal name="changed" handler="ide_search_popover_search_changed_cb" swapped="true" 
object="IdeSearchPopover"/>
+                <signal name="next-match" handler="ide_search_popover_next_match_cb" swapped="true" 
object="IdeSearchPopover"/>
+                <signal name="previous-match" handler="ide_search_popover_previous_match_cb" swapped="true" 
object="IdeSearchPopover"/>
               </object>
             </child>
           </object>
@@ -36,7 +38,8 @@
                 <property name="single-click-activate">True</property>
                 <property name="orientation">vertical</property>
                 <property name="model">
-                  <object class="GtkNoSelection" id="selection">
+                  <object class="GtkSingleSelection" id="selection">
+                    <property name="autoselect">true</property>
                   </object>
                 </property>
                 <property name="factory">


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]