[gnome-builder] plugins/codeui: add dialog to find references
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] plugins/codeui: add dialog to find references
- Date: Wed, 21 Sep 2022 06:00:17 +0000 (UTC)
commit 4fb2294685628b98f6ec32803660898feb5949fd
Author: Christian Hergert <chergert redhat com>
Date: Tue Sep 20 22:56:17 2022 -0700
plugins/codeui: add dialog to find references
This was missing from the GTK 4 port of IdeSourceView still.
po/POTFILES.in | 2 +
src/plugins/codeui/codeui.gresource.xml | 1 +
src/plugins/codeui/gbp-codeui-editor-page-addin.c | 131 ++++++++++++++++
src/plugins/codeui/gbp-codeui-range-dialog.c | 177 ++++++++++++++++++++++
src/plugins/codeui/gbp-codeui-range-dialog.h | 33 ++++
src/plugins/codeui/gbp-codeui-range-dialog.ui | 35 +++++
src/plugins/codeui/gtk/menus.ui | 2 +-
src/plugins/codeui/meson.build | 1 +
8 files changed, 381 insertions(+), 1 deletion(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f27d85066..89412ef66 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -131,6 +131,8 @@ src/plugins/code-index/ide-code-index-index.c
src/plugins/codespell/ide-codespell-diagnostic-provider.c
src/plugins/codeui/gbp-codeui-editor-page-addin.c
src/plugins/codeui/gbp-codeui-hover-provider.c
+src/plugins/codeui/gbp-codeui-range-dialog.c
+src/plugins/codeui/gbp-codeui-range-dialog.ui
src/plugins/codeui/gbp-codeui-rename-dialog.c
src/plugins/codeui/gbp-codeui-rename-dialog.ui
src/plugins/codeui/gtk/menus.ui
diff --git a/src/plugins/codeui/codeui.gresource.xml b/src/plugins/codeui/codeui.gresource.xml
index 32f4c9aac..1eb2d12e7 100644
--- a/src/plugins/codeui/codeui.gresource.xml
+++ b/src/plugins/codeui/codeui.gresource.xml
@@ -2,6 +2,7 @@
<gresources>
<gresource prefix="/plugins/codeui">
<file>codeui.plugin</file>
+ <file preprocess="xml-stripblanks">gbp-codeui-range-dialog.ui</file>
<file preprocess="xml-stripblanks">gbp-codeui-rename-dialog.ui</file>
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
</gresource>
diff --git a/src/plugins/codeui/gbp-codeui-editor-page-addin.c
b/src/plugins/codeui/gbp-codeui-editor-page-addin.c
index 0bc7f604e..d49e32825 100644
--- a/src/plugins/codeui/gbp-codeui-editor-page-addin.c
+++ b/src/plugins/codeui/gbp-codeui-editor-page-addin.c
@@ -27,6 +27,7 @@
#include <libide-editor.h>
#include "gbp-codeui-editor-page-addin.h"
+#include "gbp-codeui-range-dialog.h"
#include "gbp-codeui-rename-dialog.h"
struct _GbpCodeuiEditorPageAddin
@@ -40,6 +41,8 @@ struct _GbpCodeuiEditorPageAddin
gulong notify_has_selection;
};
+static void find_references_action (GbpCodeuiEditorPageAddin *self,
+ GVariant *params);
static void goto_declaration_action (GbpCodeuiEditorPageAddin *self,
GVariant *params);
static void goto_definition_action (GbpCodeuiEditorPageAddin *self,
@@ -51,6 +54,7 @@ IDE_DEFINE_ACTION_GROUP (GbpCodeuiEditorPageAddin, gbp_codeui_editor_page_addin,
{ "rename-symbol", rename_symbol_action },
{ "goto-declaration", goto_declaration_action },
{ "goto-definition", goto_definition_action },
+ { "find-references", find_references_action },
})
static void
@@ -73,6 +77,7 @@ gbp_codeui_editor_page_addin_update_state (GbpCodeuiEditorPageAddin *self)
gbp_codeui_editor_page_addin_set_action_enabled (self, "rename-symbol", has_selection && provider);
gbp_codeui_editor_page_addin_set_action_enabled (self, "goto-declaration", has_resolvers);
gbp_codeui_editor_page_addin_set_action_enabled (self, "goto-definition", has_resolvers);
+ gbp_codeui_editor_page_addin_set_action_enabled (self, "find-references", has_resolvers);
IDE_EXIT;
}
@@ -337,6 +342,132 @@ goto_definition_action (GbpCodeuiEditorPageAddin *self,
IDE_EXIT;
}
+typedef struct
+{
+ IdeLocation *location;
+ GPtrArray *active;
+ GListStore *references;
+ GbpCodeuiRangeDialog *dialog;
+} FindReferences;
+
+static void
+find_references_free (FindReferences *state)
+{
+ g_clear_object (&state->location);
+ g_clear_object (&state->references);
+ g_clear_object (&state->dialog);
+ g_clear_pointer (&state->active, g_ptr_array_unref);
+ g_slice_free (FindReferences, state);
+}
+
+static void
+find_references_append (FindReferences *state,
+ GPtrArray *ranges)
+{
+ g_assert (state != NULL);
+ g_assert (G_IS_LIST_STORE (state->references));
+ g_assert (ranges != NULL);
+
+ for (guint i = 0; i < ranges->len; i++)
+ g_list_store_append (state->references, g_ptr_array_index (ranges, i));
+}
+
+static void
+find_references_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeSymbolResolver *resolver = (IdeSymbolResolver *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GPtrArray) references = NULL;
+ g_autoptr(GError) error = NULL;
+ GbpCodeuiEditorPageAddin *self;
+ FindReferences *state;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_SYMBOL_RESOLVER (resolver));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ self = ide_task_get_source_object (task);
+ state = ide_task_get_task_data (task);
+
+ if (!(references = ide_symbol_resolver_find_references_finish (resolver, result, &error)))
+ gbp_codeui_editor_page_addin_error (self, error);
+ else
+ find_references_append (state, references);
+
+ g_ptr_array_remove (state->active, resolver);
+
+ if (state->active->len == 0)
+ {
+ adw_message_dialog_set_response_label (ADW_MESSAGE_DIALOG (state->dialog),
+ "close", _("Close"));
+ gbp_codeui_range_dialog_done (state->dialog);
+ ide_task_return_boolean (task, TRUE);
+ }
+}
+
+static void
+find_references_action (GbpCodeuiEditorPageAddin *self,
+ GVariant *params)
+{
+ g_autoptr(GPtrArray) resolvers = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ FindReferences *state;
+ const char *language_id;
+ GtkWidget *dialog;
+ GtkRoot *toplevel;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_CODEUI_EDITOR_PAGE_ADDIN (self));
+
+ resolvers = ide_buffer_get_symbol_resolvers (self->buffer);
+ IDE_PTR_ARRAY_SET_FREE_FUNC (resolvers, g_object_unref);
+
+ if (resolvers == NULL || resolvers->len == 0)
+ return;
+
+ task = ide_task_new (self, NULL, NULL, NULL);
+ ide_task_set_source_tag (task, find_references_action);
+
+ state = g_slice_new0 (FindReferences);
+ state->location = ide_buffer_get_insert_location (self->buffer);
+ state->active = g_ptr_array_ref (resolvers);
+ state->references = g_list_store_new (IDE_TYPE_RANGE);
+ ide_task_set_task_data (task, state, find_references_free);
+
+ language_id = ide_buffer_get_language_id (self->buffer);
+
+ for (guint i = 0; i < resolvers->len; i++)
+ {
+ IdeSymbolResolver *resolver = g_ptr_array_index (resolvers, i);
+
+ ide_symbol_resolver_find_references_async (resolver,
+ state->location,
+ language_id,
+ NULL,
+ find_references_cb,
+ g_object_ref (task));
+ }
+
+ toplevel = gtk_widget_get_root (GTK_WIDGET (self->page));
+ dialog = g_object_new (GBP_TYPE_CODEUI_RANGE_DIALOG,
+ "transient-for", toplevel,
+ "modal", FALSE,
+ "model", state->references,
+ "heading", _("Find References"),
+ NULL);
+
+ state->dialog = g_object_ref_sink (GBP_CODEUI_RANGE_DIALOG (dialog));
+
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ IDE_EXIT;
+}
+
G_DEFINE_FINAL_TYPE_WITH_CODE (GbpCodeuiEditorPageAddin, gbp_codeui_editor_page_addin, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP,
gbp_codeui_editor_page_addin_init_action_group)
G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_PAGE_ADDIN,
editor_page_addin_iface_init))
diff --git a/src/plugins/codeui/gbp-codeui-range-dialog.c b/src/plugins/codeui/gbp-codeui-range-dialog.c
new file mode 100644
index 000000000..d9dcff21a
--- /dev/null
+++ b/src/plugins/codeui/gbp-codeui-range-dialog.c
@@ -0,0 +1,177 @@
+/* gbp-codeui-range-dialog.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-codeui-range-dialog"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libpanel.h>
+
+#include <libide-editor.h>
+#include <libide-code.h>
+
+#include "gbp-codeui-range-dialog.h"
+
+struct _GbpCodeuiRangeDialog
+{
+ AdwMessageDialog parent_instance;
+ GtkListBox *list_box;
+ AdwActionRow *loading;
+ AdwPreferencesGroup *group;
+ guint count;
+};
+
+G_DEFINE_FINAL_TYPE (GbpCodeuiRangeDialog, gbp_codeui_range_dialog, ADW_TYPE_MESSAGE_DIALOG)
+
+enum {
+ PROP_0,
+ PROP_MODEL,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static GtkWidget *
+create_widget_cb (gpointer item,
+ gpointer user_data)
+{
+ GbpCodeuiRangeDialog *self = user_data;
+ IdeRange *range = item;
+ IdeLocation *begin = ide_range_get_begin (range);
+ GFile *file = ide_location_get_file (begin);
+ g_autofree char *name = g_file_get_basename (file);
+ g_autoptr(GFile) parent = g_file_get_parent (file);
+ g_autofree char *dir = g_file_is_native (parent) ? g_file_get_path (parent) : g_file_get_uri (parent);
+ guint line = ide_location_get_line (begin) + 1;
+ guint line_offset = ide_location_get_line_offset (begin) + 1;
+ g_autofree char *title = g_strdup_printf ("%s:%u:%u", name, line, line_offset);
+ GtkWidget *image = gtk_image_new_from_icon_name ("go-next-symbolic");
+ AdwActionRow *row;
+
+ self->count++;
+
+ row = g_object_new (ADW_TYPE_ACTION_ROW,
+ "activatable", TRUE,
+ "title", title,
+ "subtitle", dir,
+ NULL);
+
+ g_object_set_data_full (G_OBJECT (row),
+ "IDE_LOCATION",
+ g_object_ref (begin),
+ g_object_unref);
+
+ adw_action_row_add_suffix (row, image);
+
+ gtk_widget_show (GTK_WIDGET (self->list_box));
+
+ return GTK_WIDGET (row);
+}
+
+static void
+gbp_codeui_range_dialog_activate_row_cb (GbpCodeuiRangeDialog *self,
+ GtkListBoxRow *row,
+ GtkListBox *list_box)
+{
+ g_autoptr(PanelPosition) position = NULL;
+ IdeWorkspace *workspace;
+ IdeLocation *location;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_CODEUI_RANGE_DIALOG (self));
+ g_assert (GTK_IS_LIST_BOX_ROW (row));
+ g_assert (GTK_IS_LIST_BOX (list_box));
+
+ workspace = ide_widget_get_workspace (GTK_WIDGET (self));
+ location = g_object_get_data (G_OBJECT (row), "IDE_LOCATION");
+ position = panel_position_new ();
+
+ ide_editor_focus_location (workspace, position, location);
+}
+
+static void
+gbp_codeui_range_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpCodeuiRangeDialog *self = GBP_CODEUI_RANGE_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ gtk_list_box_bind_model (self->list_box,
+ g_value_get_object (value),
+ create_widget_cb, self, NULL);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_codeui_range_dialog_class_init (GbpCodeuiRangeDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->set_property = gbp_codeui_range_dialog_set_property;
+
+ properties[PROP_MODEL] =
+ g_param_spec_object ("model", NULL, NULL,
+ G_TYPE_LIST_MODEL,
+ (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/plugins/codeui/gbp-codeui-range-dialog.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpCodeuiRangeDialog, group);
+ gtk_widget_class_bind_template_child (widget_class, GbpCodeuiRangeDialog, list_box);
+ gtk_widget_class_bind_template_child (widget_class, GbpCodeuiRangeDialog, loading);
+ gtk_widget_class_bind_template_callback (widget_class, gbp_codeui_range_dialog_activate_row_cb);
+}
+
+static void
+gbp_codeui_range_dialog_init (GbpCodeuiRangeDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+gbp_codeui_range_dialog_done (GbpCodeuiRangeDialog *self)
+{
+ g_return_if_fail (GBP_IS_CODEUI_RANGE_DIALOG (self));
+
+ if (self->count == 0)
+ {
+ g_object_set (self->loading,
+ "title", _("No references found"),
+ "subtitle", _("The programming language tooling may not support finding references"),
+ NULL);
+ gtk_widget_hide (GTK_WIDGET (self->list_box));
+ return;
+ }
+
+ adw_preferences_group_remove (self->group, GTK_WIDGET (self->loading));
+ self->loading = NULL;
+}
diff --git a/src/plugins/codeui/gbp-codeui-range-dialog.h b/src/plugins/codeui/gbp-codeui-range-dialog.h
new file mode 100644
index 000000000..a5fcd9687
--- /dev/null
+++ b/src/plugins/codeui/gbp-codeui-range-dialog.h
@@ -0,0 +1,33 @@
+/* gbp-codeui-range-dialog.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 <adwaita.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_CODEUI_RANGE_DIALOG (gbp_codeui_range_dialog_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpCodeuiRangeDialog, gbp_codeui_range_dialog, GBP, CODEUI_RANGE_DIALOG,
AdwMessageDialog)
+
+void gbp_codeui_range_dialog_done (GbpCodeuiRangeDialog *self);
+
+G_END_DECLS
diff --git a/src/plugins/codeui/gbp-codeui-range-dialog.ui b/src/plugins/codeui/gbp-codeui-range-dialog.ui
new file mode 100644
index 000000000..ed5252f56
--- /dev/null
+++ b/src/plugins/codeui/gbp-codeui-range-dialog.ui
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpCodeuiRangeDialog" parent="AdwMessageDialog">
+ <property name="heading" translatable="yes">Find References</property>
+ <property name="close-response">close</property>
+ <responses>
+ <response id="close" translatable="yes">_Cancel</response>
+ </responses>
+ <property name="extra-child">
+ <object class="AdwPreferencesPage">
+ <child>
+ <object class="AdwPreferencesGroup" id="group">
+ <property name="width-request">375</property>
+ <property name="height-request">75</property>
+ <child>
+ <object class="AdwActionRow" id="loading">
+ <property name="title" translatable="yes">Loading…</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBox" id="list_box">
+ <property name="margin-top">18</property>
+ <property name="visible">false</property>
+ <signal name="row-activated" handler="gbp_codeui_range_dialog_activate_row_cb"
swapped="true" object="GbpCodeuiRangeDialog"/>
+ <style>
+ <class name="boxed-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
diff --git a/src/plugins/codeui/gtk/menus.ui b/src/plugins/codeui/gtk/menus.ui
index afbedbaf2..d22d52921 100644
--- a/src/plugins/codeui/gtk/menus.ui
+++ b/src/plugins/codeui/gtk/menus.ui
@@ -22,7 +22,7 @@
<item>
<attribute name="id">source-view-find-references</attribute>
<attribute name="label" translatable="yes">_Find References</attribute>
- <attribute name="action">sourceview.find-references</attribute>
+ <attribute name="action">page.codeui.find-references</attribute>
</item>
</section>
</menu>
diff --git a/src/plugins/codeui/meson.build b/src/plugins/codeui/meson.build
index 13b9c353d..7eeafc8bf 100644
--- a/src/plugins/codeui/meson.build
+++ b/src/plugins/codeui/meson.build
@@ -3,6 +3,7 @@ plugins_sources += files([
'gbp-codeui-buffer-addin.c',
'gbp-codeui-editor-page-addin.c',
'gbp-codeui-hover-provider.c',
+ 'gbp-codeui-range-dialog.c',
'gbp-codeui-rename-dialog.c',
'gbp-codeui-tree-addin.c',
])
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]