[gnome-builder] plugins/symbol-tree: search symbol-tree from global search



commit ebb5ea9f55ea7f478aea934b84bdca4bb34137c5
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jul 19 14:43:32 2022 -0700

    plugins/symbol-tree: search symbol-tree from global search
    
    This bridges the search from the symbol-tree to the global search using
    the search popover (ctrl+enter). Handy from the standpoint of using one
    search entry for everything unless you want to browse the symbol-tree.

 po/POTFILES.in                                     |   1 +
 .../symbol-tree/gbp-symbol-search-provider.c       | 153 +++++++++++++++
 .../symbol-tree/gbp-symbol-search-provider.h       |  31 +++
 src/plugins/symbol-tree/gbp-symbol-search-result.c | 213 +++++++++++++++++++++
 src/plugins/symbol-tree/gbp-symbol-search-result.h |  36 ++++
 src/plugins/symbol-tree/meson.build                |   2 +
 src/plugins/symbol-tree/symbol-tree-plugin.c       |   5 +
 src/plugins/symbol-tree/symbol-tree.plugin         |   1 +
 8 files changed, 442 insertions(+)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 308535aa0..03a97f08a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -265,6 +265,7 @@ src/plugins/spellcheck/gbp-spell-preferences-addin.c
 src/plugins/sphinx-preview/gtk/menus.ui
 src/plugins/symbol-tree/gbp-symbol-hover-provider.c
 src/plugins/symbol-tree/gbp-symbol-popover.ui
+src/plugins/symbol-tree/gbp-symbol-search-result.c
 src/plugins/symbol-tree/gbp-symbol-workspace-addin.c
 src/plugins/sysprof/gbp-sysprof-surface.c
 src/plugins/sysprof/gbp-sysprof-workspace-addin.c
diff --git a/src/plugins/symbol-tree/gbp-symbol-search-provider.c 
b/src/plugins/symbol-tree/gbp-symbol-search-provider.c
new file mode 100644
index 000000000..8dadcfb6a
--- /dev/null
+++ b/src/plugins/symbol-tree/gbp-symbol-search-provider.c
@@ -0,0 +1,153 @@
+/* gbp-symbol-search-provider.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-symbol-search-provider"
+
+#include "config.h"
+
+#include <libide-gui.h>
+#include <libide-search.h>
+#include <libide-threading.h>
+
+#include "gbp-symbol-search-provider.h"
+#include "gbp-symbol-search-result.h"
+#include "gbp-symbol-workspace-addin.h"
+
+struct _GbpSymbolSearchProvider
+{
+  IdeObject parent_instance;
+};
+
+static gpointer
+gbp_symbol_search_provider_map_func (gpointer item,
+                                     gpointer user_data)
+{
+  g_autoptr(GtkTreeListRow) row = item;
+  g_autoptr(IdeSymbolNode) node = NULL;
+  GFile *file = user_data;
+
+  g_assert (GTK_IS_TREE_LIST_ROW (item));
+  g_assert (!file || G_IS_FILE (file));
+
+  node = gtk_tree_list_row_get_item (row);
+  g_assert (IDE_IS_SYMBOL_NODE (node));
+
+  return gbp_symbol_search_result_new (node, file);
+}
+
+static void
+gbp_symbol_search_provider_foreach_workspace_cb (IdeWorkspace *workspace,
+                                                 gpointer      user_data)
+{
+  g_autoptr(GtkMapListModel) map = NULL;
+  IdeWorkspaceAddin *addin;
+  GListStore *store = user_data;
+  GListModel *model;
+  IdeBuffer *buffer;
+  GFile *file = NULL;
+
+  g_assert (IDE_IS_WORKSPACE (workspace));
+  g_assert (G_IS_LIST_STORE (user_data));
+
+  if (!(addin = ide_workspace_addin_find_by_module_name (workspace, "symbol-tree")) ||
+      !(model = gbp_symbol_workspace_addin_get_model (GBP_SYMBOL_WORKSPACE_ADDIN (addin))))
+    return;
+
+  if ((buffer = gbp_symbol_workspace_addin_get_buffer (GBP_SYMBOL_WORKSPACE_ADDIN (addin))))
+    file = g_object_ref (ide_buffer_get_file (buffer));
+
+  map = gtk_map_list_model_new (g_object_ref (model),
+                                gbp_symbol_search_provider_map_func,
+                                file,
+                                file ? g_object_unref : NULL);
+
+  g_list_store_append (store, map);
+}
+
+static void
+gbp_symbol_search_provider_search_async (IdeSearchProvider   *provider,
+                                         const char          *query,
+                                         guint                max_results,
+                                         GCancellable        *cancellable,
+                                         GAsyncReadyCallback  callback,
+                                         gpointer             user_data)
+{
+  g_autoptr(IdeTask) task = NULL;
+  g_autoptr(GListStore) store = NULL;
+  IdeWorkbench *workbench;
+  IdeContext *context;
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (GBP_IS_SYMBOL_SEARCH_PROVIDER (provider));
+  g_assert (query != NULL);
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (provider, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, gbp_symbol_search_provider_search_async);
+
+  context = ide_object_get_context (IDE_OBJECT (provider));
+  workbench = ide_workbench_from_context (context);
+  store = g_list_store_new (G_TYPE_LIST_MODEL);
+
+  ide_workbench_foreach_workspace (workbench,
+                                   gbp_symbol_search_provider_foreach_workspace_cb,
+                                   store);
+
+  if (g_list_model_get_n_items (G_LIST_MODEL (store)) == 0)
+    ide_task_return_unsupported_error (task);
+  else
+    ide_task_return_pointer (task,
+                             g_object_new (GTK_TYPE_FLATTEN_LIST_MODEL,
+                                           "model", store,
+                                           NULL),
+                             g_object_unref);
+}
+
+static GListModel *
+gbp_symbol_search_provider_search_finish (IdeSearchProvider  *provider,
+                                          GAsyncResult       *result,
+                                          GError            **error)
+{
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (GBP_IS_SYMBOL_SEARCH_PROVIDER (provider));
+  g_assert (IDE_IS_TASK (result));
+
+  return ide_task_propagate_pointer (IDE_TASK (result), error);
+}
+
+static void
+search_provider_iface_init (IdeSearchProviderInterface *iface)
+{
+  iface->search_async = gbp_symbol_search_provider_search_async;
+  iface->search_finish = gbp_symbol_search_provider_search_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpSymbolSearchProvider, gbp_symbol_search_provider, IDE_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_SEARCH_PROVIDER, search_provider_iface_init))
+
+static void
+gbp_symbol_search_provider_class_init (GbpSymbolSearchProviderClass *klass)
+{
+}
+
+static void
+gbp_symbol_search_provider_init (GbpSymbolSearchProvider *self)
+{
+}
diff --git a/src/plugins/symbol-tree/gbp-symbol-search-provider.h 
b/src/plugins/symbol-tree/gbp-symbol-search-provider.h
new file mode 100644
index 000000000..162bcf292
--- /dev/null
+++ b/src/plugins/symbol-tree/gbp-symbol-search-provider.h
@@ -0,0 +1,31 @@
+/* gbp-symbol-search-provider.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_SYMBOL_SEARCH_PROVIDER (gbp_symbol_search_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpSymbolSearchProvider, gbp_symbol_search_provider, GBP, SYMBOL_SEARCH_PROVIDER, 
IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/symbol-tree/gbp-symbol-search-result.c 
b/src/plugins/symbol-tree/gbp-symbol-search-result.c
new file mode 100644
index 000000000..d14403913
--- /dev/null
+++ b/src/plugins/symbol-tree/gbp-symbol-search-result.c
@@ -0,0 +1,213 @@
+/* gbp-symbol-search-result.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-symbol-search-result"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-editor.h>
+#include <libide-gui.h>
+
+#include "gbp-symbol-search-result.h"
+
+struct _GbpSymbolSearchResult
+{
+  IdeSearchResult  parent_instance;
+  IdeSymbolNode   *node;
+};
+
+enum {
+  PROP_0,
+  PROP_NODE,
+  N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (GbpSymbolSearchResult, gbp_symbol_search_result, IDE_TYPE_SEARCH_RESULT)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_symbol_search_result_get_location_cb (GObject      *object,
+                                          GAsyncResult *result,
+                                          gpointer      user_data)
+{
+  IdeSymbolNode *node = (IdeSymbolNode *)object;
+  g_autoptr(IdeWorkspace) workspace = user_data;
+  g_autoptr(IdeLocation) location = NULL;
+  g_autoptr(GError) error = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (IDE_IS_SYMBOL_NODE (node));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_WORKSPACE (workspace));
+
+  if ((location = ide_symbol_node_get_location_finish (node, result, &error)))
+    ide_editor_focus_location (workspace, NULL, location);
+  else
+    ide_object_message (ide_workspace_get_context (workspace),
+                        "Failed to locate location for symbol");
+
+  IDE_EXIT;
+}
+
+static void
+gbp_symbol_search_result_activate (IdeSearchResult *result,
+                                   GtkWidget       *last_focus)
+{
+  GbpSymbolSearchResult *self = (GbpSymbolSearchResult *)result;
+  IdeWorkspace *workspace;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_SEARCH_RESULT (result));
+  g_assert (GTK_IS_WIDGET (last_focus));
+
+  workspace = ide_widget_get_workspace (last_focus);
+
+  ide_symbol_node_get_location_async (self->node,
+                                      NULL,
+                                      gbp_symbol_search_result_get_location_cb,
+                                      g_object_ref (workspace));
+
+  IDE_EXIT;
+}
+
+static void
+gbp_symbol_search_result_set_node (GbpSymbolSearchResult *self,
+                                   IdeSymbolNode         *node)
+{
+  g_assert (GBP_IS_SYMBOL_SEARCH_RESULT (self));
+  g_assert (IDE_IS_SYMBOL_NODE (node));
+
+  self->node = g_object_ref (node);
+
+  ide_search_result_set_gicon (IDE_SEARCH_RESULT (self), ide_symbol_node_get_gicon (node));
+  ide_search_result_set_title (IDE_SEARCH_RESULT (self), ide_symbol_node_get_name (node));
+  ide_search_result_set_use_markup (IDE_SEARCH_RESULT (self), ide_symbol_node_get_use_markup (node));
+}
+
+static void
+gbp_symbol_search_result_dispose (GObject *object)
+{
+  GbpSymbolSearchResult *self = (GbpSymbolSearchResult *)object;
+
+  g_clear_object (&self->node);
+
+  G_OBJECT_CLASS (gbp_symbol_search_result_parent_class)->dispose (object);
+}
+
+static void
+gbp_symbol_search_result_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  GbpSymbolSearchResult *self = GBP_SYMBOL_SEARCH_RESULT (object);
+
+  switch (prop_id)
+    {
+    case PROP_NODE:
+      g_value_set_object (value, gbp_symbol_search_result_get_node (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gbp_symbol_search_result_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  GbpSymbolSearchResult *self = GBP_SYMBOL_SEARCH_RESULT (object);
+
+  switch (prop_id)
+    {
+    case PROP_NODE:
+      gbp_symbol_search_result_set_node (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gbp_symbol_search_result_class_init (GbpSymbolSearchResultClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  IdeSearchResultClass *search_result_class = IDE_SEARCH_RESULT_CLASS (klass);
+
+  object_class->dispose = gbp_symbol_search_result_dispose;
+  object_class->get_property = gbp_symbol_search_result_get_property;
+  object_class->set_property = gbp_symbol_search_result_set_property;
+
+  search_result_class->activate = gbp_symbol_search_result_activate;
+
+  properties [PROP_NODE] =
+    g_param_spec_object ("node", NULL, NULL,
+                         IDE_TYPE_SYMBOL_NODE,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_symbol_search_result_init (GbpSymbolSearchResult *self)
+{
+}
+
+GbpSymbolSearchResult *
+gbp_symbol_search_result_new (IdeSymbolNode *node,
+                              GFile         *file)
+{
+  g_autofree char *subtitle = NULL;
+
+  g_return_val_if_fail (IDE_IS_SYMBOL_NODE (node), NULL);
+  g_return_val_if_fail (!file || G_IS_FILE (file), NULL);
+
+  if (file != NULL)
+    {
+      g_autofree char *basename = g_file_get_basename (file);
+      g_autofree char *escaped = g_markup_escape_text (basename, -1);
+
+      /* translators: "In Page" refers to the title of the page which contains the search result */
+      subtitle = g_strdup_printf ("<span fgalpha='32767'>%s</span> %s", _("In Page"), escaped);
+    }
+
+  return g_object_new (GBP_TYPE_SYMBOL_SEARCH_RESULT,
+                       "node", node,
+                       "subtitle", subtitle,
+                       NULL);
+}
+
+IdeSymbolNode *
+gbp_symbol_search_result_get_node (GbpSymbolSearchResult *self)
+{
+  g_return_val_if_fail (GBP_IS_SYMBOL_SEARCH_RESULT (self), NULL);
+
+  return self->node;
+}
diff --git a/src/plugins/symbol-tree/gbp-symbol-search-result.h 
b/src/plugins/symbol-tree/gbp-symbol-search-result.h
new file mode 100644
index 000000000..67b416a59
--- /dev/null
+++ b/src/plugins/symbol-tree/gbp-symbol-search-result.h
@@ -0,0 +1,36 @@
+/* gbp-symbol-search-result.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-code.h>
+#include <libide-search.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_SYMBOL_SEARCH_RESULT (gbp_symbol_search_result_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpSymbolSearchResult, gbp_symbol_search_result, GBP, SYMBOL_SEARCH_RESULT, 
IdeSearchResult)
+
+GbpSymbolSearchResult *gbp_symbol_search_result_new      (IdeSymbolNode         *node,
+                                                          GFile                 *file);
+IdeSymbolNode         *gbp_symbol_search_result_get_node (GbpSymbolSearchResult *self);
+
+G_END_DECLS
diff --git a/src/plugins/symbol-tree/meson.build b/src/plugins/symbol-tree/meson.build
index 94f64dc50..41b88cb59 100644
--- a/src/plugins/symbol-tree/meson.build
+++ b/src/plugins/symbol-tree/meson.build
@@ -1,6 +1,8 @@
 plugins_sources += files([
   'gbp-symbol-hover-provider.c',
   'gbp-symbol-list-model.c',
+  'gbp-symbol-search-provider.c',
+  'gbp-symbol-search-result.c',
   'gbp-symbol-popover.c',
   'gbp-symbol-util.c',
   'gbp-symbol-workspace-addin.c',
diff --git a/src/plugins/symbol-tree/symbol-tree-plugin.c b/src/plugins/symbol-tree/symbol-tree-plugin.c
index b641650a3..fbd4f4bd4 100644
--- a/src/plugins/symbol-tree/symbol-tree-plugin.c
+++ b/src/plugins/symbol-tree/symbol-tree-plugin.c
@@ -23,9 +23,11 @@
 #include <libpeas/peas.h>
 
 #include <libide-gui.h>
+#include <libide-search.h>
 #include <libide-sourceview.h>
 
 #include "gbp-symbol-hover-provider.h"
+#include "gbp-symbol-search-provider.h"
 #include "gbp-symbol-workspace-addin.h"
 
 _IDE_EXTERN void
@@ -34,6 +36,9 @@ _gbp_symbol_tree_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               GTK_SOURCE_TYPE_HOVER_PROVIDER,
                                               GBP_TYPE_SYMBOL_HOVER_PROVIDER);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_SEARCH_PROVIDER,
+                                              GBP_TYPE_SYMBOL_SEARCH_PROVIDER);
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_WORKSPACE_ADDIN,
                                               GBP_TYPE_SYMBOL_WORKSPACE_ADDIN);
diff --git a/src/plugins/symbol-tree/symbol-tree.plugin b/src/plugins/symbol-tree/symbol-tree.plugin
index 923746413..cf9fba2c6 100644
--- a/src/plugins/symbol-tree/symbol-tree.plugin
+++ b/src/plugins/symbol-tree/symbol-tree.plugin
@@ -8,3 +8,4 @@ Module=symbol-tree
 Name=Symbol Tree
 X-Category=editing
 X-Workspace-Kind=primary;editor;
+X-Search-Provider-Priority=-100


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