[gnome-builder] plugins/find-other-file: port to C
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] plugins/find-other-file: port to C
- Date: Tue, 12 Jul 2022 06:39:16 +0000 (UTC)
commit c8c38d64a43a02df432f472a5f65a72e90dfe13a
Author: Christian Hergert <chergert redhat com>
Date: Mon Jul 11 22:41:48 2022 -0700
plugins/find-other-file: port to C
This both ports the plugin to C and improves how we integrate the feature
into the application so that the command-bar/global-search is not needed
to be used. Instead a button is placed in the statusbar.
.../find-other-file/find-other-file-plugin.c | 42 ++++
.../find-other-file/find-other-file.gresource.xml | 8 +
src/plugins/find-other-file/find-other-file.plugin | 11 +-
src/plugins/find-other-file/find_other_file.py | 169 -------------
.../find-other-file/gbp-find-other-file-browser.c | 234 ++++++++++++++++++
.../find-other-file/gbp-find-other-file-browser.h | 37 +++
.../find-other-file/gbp-find-other-file-popover.c | 195 +++++++++++++++
.../find-other-file/gbp-find-other-file-popover.h | 34 +++
.../find-other-file/gbp-find-other-file-popover.ui | 80 ++++++
.../gbp-find-other-file-workspace-addin.c | 270 +++++++++++++++++++++
.../gbp-find-other-file-workspace-addin.h | 31 +++
src/plugins/find-other-file/gbp-found-file.c | 244 +++++++++++++++++++
src/plugins/find-other-file/gbp-found-file.h | 36 +++
.../gbp-simple-similar-file-locator.c | 171 +++++++++++++
.../gbp-simple-similar-file-locator.h | 31 +++
src/plugins/find-other-file/gtk/keybindings.json | 1 +
src/plugins/find-other-file/meson.build | 21 +-
17 files changed, 1432 insertions(+), 183 deletions(-)
---
diff --git a/src/plugins/find-other-file/find-other-file-plugin.c
b/src/plugins/find-other-file/find-other-file-plugin.c
new file mode 100644
index 000000000..a0c02bf1d
--- /dev/null
+++ b/src/plugins/find-other-file/find-other-file-plugin.c
@@ -0,0 +1,42 @@
+/* find-other-file-plugin.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 "find-other-file-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-gui.h>
+#include <libide-projects.h>
+
+#include "gbp-simple-similar-file-locator.h"
+#include "gbp-find-other-file-workspace-addin.h"
+
+_IDE_EXTERN void
+_gbp_find_other_file_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_SIMILAR_FILE_LOCATOR,
+ GBP_TYPE_SIMPLE_SIMILAR_FILE_LOCATOR);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKSPACE_ADDIN,
+ GBP_TYPE_FIND_OTHER_FILE_WORKSPACE_ADDIN);
+}
diff --git a/src/plugins/find-other-file/find-other-file.gresource.xml
b/src/plugins/find-other-file/find-other-file.gresource.xml
new file mode 100644
index 000000000..e0108f7c9
--- /dev/null
+++ b/src/plugins/find-other-file/find-other-file.gresource.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/plugins/find-other-file">
+ <file>find-other-file.plugin</file>
+ <file>gtk/keybindings.json</file>
+ <file preprocess="xml-stripblanks">gbp-find-other-file-popover.ui</file>
+ </gresource>
+</gresources>
diff --git a/src/plugins/find-other-file/find-other-file.plugin
b/src/plugins/find-other-file/find-other-file.plugin
index bb9e3c7ad..366bb39b4 100644
--- a/src/plugins/find-other-file/find-other-file.plugin
+++ b/src/plugins/find-other-file/find-other-file.plugin
@@ -1,12 +1,9 @@
[Plugin]
Authors=Christian Hergert <christian hergert me>
Builtin=true
-Copyright=Copyright © 2017 Christian Hergert
-Depends=editor;
+Copyright=Copyright © 2017-2022 Christian Hergert
Description=Allows the user to rotate through other files similarly named to the open document.
-Hidden=true
-Loader=python3
-Module=find_other_file
-Name=Find other files
-X-Builder-ABI=@PACKAGE_ABI@
+Embedded=_gbp_find_other_file_register_types
+Module=find-other-file
+Name=Find Similar Files
X-Workspace-Kind=primary;editor;
diff --git a/src/plugins/find-other-file/gbp-find-other-file-browser.c
b/src/plugins/find-other-file/gbp-find-other-file-browser.c
new file mode 100644
index 000000000..21cee9d69
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-browser.c
@@ -0,0 +1,234 @@
+/* gbp-find-other-file-browser.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-find-other-file-browser"
+
+#include "config.h"
+
+#include "gbp-find-other-file-browser.h"
+#include "gbp-found-file.h"
+
+struct _GbpFindOtherFileBrowser
+{
+ GObject parent_instance;
+ GPtrArray *items;
+ GFile *file;
+ GFile *root;
+};
+
+enum {
+ PROP_0,
+ PROP_ROOT,
+ PROP_FILE,
+ N_PROPS
+};
+
+static GType
+gbp_find_other_file_browser_get_item_type (GListModel *model)
+{
+ return G_TYPE_FILE;
+}
+
+static guint
+gbp_find_other_file_browser_get_n_items (GListModel *model)
+{
+ return GBP_FIND_OTHER_FILE_BROWSER (model)->items->len;
+}
+
+static gpointer
+gbp_find_other_file_browser_get_item (GListModel *model,
+ guint position)
+{
+ GbpFindOtherFileBrowser *self = GBP_FIND_OTHER_FILE_BROWSER (model);
+
+ if (position < self->items->len)
+ return g_object_ref (g_ptr_array_index (self->items, position));
+
+ return NULL;
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gbp_find_other_file_browser_get_item_type;
+ iface->get_n_items = gbp_find_other_file_browser_get_n_items;
+ iface->get_item = gbp_find_other_file_browser_get_item;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpFindOtherFileBrowser, gbp_find_other_file_browser, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_find_other_file_browser_reload (GbpFindOtherFileBrowser *self)
+{
+ guint old_len = 0;
+ guint new_len = 0;
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_BROWSER (self));
+
+ old_len = self->items->len;
+
+ if (old_len)
+ g_ptr_array_remove_range (self->items, 0, old_len);
+
+ if (self->root != NULL &&
+ self->file != NULL &&
+ g_file_has_prefix (self->file, self->root))
+ {
+ GFile *parent = g_file_get_parent (self->file);
+
+ while (parent != NULL &&
+ (g_file_has_prefix (parent, self->root) ||
+ g_file_equal (parent, self->root)))
+ {
+ g_ptr_array_insert (self->items, 0, parent);
+ parent = g_file_get_parent (parent);
+ }
+
+ g_clear_object (&parent);
+ }
+
+ new_len = self->items->len;
+
+ if (old_len || new_len)
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, old_len, new_len);
+}
+
+static void
+gbp_find_other_file_browser_dispose (GObject *object)
+{
+ GbpFindOtherFileBrowser *self = (GbpFindOtherFileBrowser *)object;
+
+ g_clear_object (&self->file);
+ g_clear_object (&self->root);
+ g_clear_pointer (&self->items, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (gbp_find_other_file_browser_parent_class)->dispose (object);
+}
+
+static void
+gbp_find_other_file_browser_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpFindOtherFileBrowser *self = GBP_FIND_OTHER_FILE_BROWSER (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+
+ case PROP_ROOT:
+ g_value_set_object (value, self->root);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_find_other_file_browser_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpFindOtherFileBrowser *self = GBP_FIND_OTHER_FILE_BROWSER (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ gbp_find_other_file_browser_set_file (self, g_value_get_object (value));
+ break;
+
+ case PROP_ROOT:
+ gbp_find_other_file_browser_set_root (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_find_other_file_browser_class_init (GbpFindOtherFileBrowserClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gbp_find_other_file_browser_dispose;
+ object_class->get_property = gbp_find_other_file_browser_get_property;
+ object_class->set_property = gbp_find_other_file_browser_set_property;
+
+ properties [PROP_FILE] =
+ g_param_spec_object ("file", NULL, NULL,
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_ROOT] =
+ g_param_spec_object ("root", NULL, NULL,
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_find_other_file_browser_init (GbpFindOtherFileBrowser *self)
+{
+ self->items = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+void
+gbp_find_other_file_browser_set_file (GbpFindOtherFileBrowser *self,
+ GFile *file)
+{
+ g_return_if_fail (GBP_IS_FIND_OTHER_FILE_BROWSER (self));
+ g_return_if_fail (!file || G_IS_FILE (file));
+
+ if (g_set_object (&self->file, file))
+ {
+ gbp_find_other_file_browser_reload (self);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE]);
+ }
+}
+
+void
+gbp_find_other_file_browser_set_root (GbpFindOtherFileBrowser *self,
+ GFile *root)
+{
+ g_return_if_fail (GBP_IS_FIND_OTHER_FILE_BROWSER (self));
+ g_return_if_fail (!root || G_IS_FILE (root));
+
+ if (g_set_object (&self->root, root))
+ {
+ gbp_find_other_file_browser_reload (self);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ROOT]);
+ }
+}
+
+GbpFindOtherFileBrowser *
+gbp_find_other_file_browser_new (void)
+{
+ return g_object_new (GBP_TYPE_FIND_OTHER_FILE_BROWSER, NULL);
+}
diff --git a/src/plugins/find-other-file/gbp-find-other-file-browser.h
b/src/plugins/find-other-file/gbp-find-other-file-browser.h
new file mode 100644
index 000000000..f93adb1cd
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-browser.h
@@ -0,0 +1,37 @@
+/* gbp-find-other-file-browser.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 <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_FIND_OTHER_FILE_BROWSER (gbp_find_other_file_browser_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpFindOtherFileBrowser, gbp_find_other_file_browser, GBP, FIND_OTHER_FILE_BROWSER,
GObject)
+
+GbpFindOtherFileBrowser *gbp_find_other_file_browser_new (void);
+void gbp_find_other_file_browser_set_root (GbpFindOtherFileBrowser *self,
+ GFile *root);
+void gbp_find_other_file_browser_set_file (GbpFindOtherFileBrowser *self,
+ GFile *file);
+
+G_END_DECLS
diff --git a/src/plugins/find-other-file/gbp-find-other-file-popover.c
b/src/plugins/find-other-file/gbp-find-other-file-popover.c
new file mode 100644
index 000000000..33b4e57c4
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-popover.c
@@ -0,0 +1,195 @@
+/* gbp-find-other-file-popover.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-find-other-file-popover"
+
+#include "config.h"
+
+#include <libide-gui.h>
+#include <libide-projects.h>
+
+#include "gbp-find-other-file-popover.h"
+#include "gbp-found-file.h"
+
+struct _GbpFindOtherFilePopover
+{
+ GtkPopover parent_instance;
+ GListModel *model;
+ GtkListView *list_view;
+};
+
+G_DEFINE_FINAL_TYPE (GbpFindOtherFilePopover, gbp_find_other_file_popover, GTK_TYPE_POPOVER)
+
+enum {
+ PROP_0,
+ PROP_MODEL,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_find_other_file_popover_activate_cb (GbpFindOtherFilePopover *self,
+ guint position,
+ GtkListView *list_view)
+{
+ IdeWorkspace *workspace;
+ GbpFoundFile *file;
+ GListModel *model;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_POPOVER (self));
+ g_assert (GTK_IS_LIST_VIEW (list_view));
+
+ g_debug ("Activating file row at position %u", position);
+
+ model = G_LIST_MODEL (gtk_list_view_get_model (list_view));
+ file = g_list_model_get_item (model, position);
+ workspace = ide_widget_get_workspace (GTK_WIDGET (self));
+
+ gtk_popover_popdown (GTK_POPOVER (self));
+ gbp_found_file_open (file, workspace);
+
+ IDE_EXIT;
+}
+
+static gpointer
+file_to_found_file (gpointer item,
+ gpointer user_data)
+{
+ GFile *workdir = user_data;
+ g_autoptr(GFile) file = item;
+
+ g_assert (G_IS_FILE (workdir));
+ g_assert (G_IS_FILE (file));
+
+ return gbp_found_file_new (workdir, file);
+}
+
+void
+gbp_find_other_file_popover_set_model (GbpFindOtherFilePopover *self,
+ GListModel *model)
+{
+ g_assert (GBP_IS_FIND_OTHER_FILE_POPOVER (self));
+ g_assert (!model || G_IS_LIST_MODEL (model));
+
+ if (g_set_object (&self->model, model))
+ {
+ g_autoptr(GtkNoSelection) selection = NULL;
+
+ if (model != NULL)
+ {
+ IdeContext *context = ide_widget_get_context (GTK_WIDGET (self));
+ GtkMapListModel *map;
+
+ map = gtk_map_list_model_new (g_object_ref (model),
+ file_to_found_file,
+ ide_context_ref_workdir (context),
+ g_object_unref);
+ selection = gtk_no_selection_new (G_LIST_MODEL (map));
+ }
+ else
+ {
+ selection = gtk_no_selection_new (G_LIST_MODEL (g_list_store_new (GBP_TYPE_FOUND_FILE)));
+ }
+
+ gtk_list_view_set_model (self->list_view, GTK_SELECTION_MODEL (selection));
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MODEL]);
+ }
+}
+
+static void
+gbp_find_other_file_popover_dispose (GObject *object)
+{
+ GbpFindOtherFilePopover *self = (GbpFindOtherFilePopover *)object;
+
+ g_clear_object (&self->model);
+
+ G_OBJECT_CLASS (gbp_find_other_file_popover_parent_class)->dispose (object);
+}
+
+static void
+gbp_find_other_file_popover_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpFindOtherFilePopover *self = GBP_FIND_OTHER_FILE_POPOVER (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ g_value_set_object (value, self->model);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_find_other_file_popover_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpFindOtherFilePopover *self = GBP_FIND_OTHER_FILE_POPOVER (object);
+
+ switch (prop_id)
+ {
+ case PROP_MODEL:
+ gbp_find_other_file_popover_set_model (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_find_other_file_popover_class_init (GbpFindOtherFilePopoverClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gbp_find_other_file_popover_dispose;
+ object_class->get_property = gbp_find_other_file_popover_get_property;
+ object_class->set_property = gbp_find_other_file_popover_set_property;
+
+ properties [PROP_MODEL] =
+ g_param_spec_object ("model", NULL, NULL,
+ G_TYPE_LIST_MODEL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/plugins/find-other-file/gbp-find-other-file-popover.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpFindOtherFilePopover, list_view);
+ gtk_widget_class_bind_template_callback (widget_class, gbp_find_other_file_popover_activate_cb);
+
+ g_type_ensure (GBP_TYPE_FOUND_FILE);
+}
+
+static void
+gbp_find_other_file_popover_init (GbpFindOtherFilePopover *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/src/plugins/find-other-file/gbp-find-other-file-popover.h
b/src/plugins/find-other-file/gbp-find-other-file-popover.h
new file mode 100644
index 000000000..9ec8a6c9c
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-popover.h
@@ -0,0 +1,34 @@
+/* gbp-find-other-file-popover.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 <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_FIND_OTHER_FILE_POPOVER (gbp_find_other_file_popover_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpFindOtherFilePopover, gbp_find_other_file_popover, GBP, FIND_OTHER_FILE_POPOVER,
GtkPopover)
+
+void gbp_find_other_file_popover_set_model (GbpFindOtherFilePopover *self,
+ GListModel *model);
+
+G_END_DECLS
diff --git a/src/plugins/find-other-file/gbp-find-other-file-popover.ui
b/src/plugins/find-other-file/gbp-find-other-file-popover.ui
new file mode 100644
index 000000000..96aa995cc
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-popover.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpFindOtherFilePopover" parent="GtkPopover">
+ <style>
+ <class name="menu"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="scroller">
+ <property name="propagate-natural-height">true</property>
+ <property name="propagate-natural-width">true</property>
+ <property name="min-content-height">100</property>
+ <property name="max-content-height">600</property>
+ <property name="min-content-width">300</property>
+ <property name="max-content-width">300</property>
+ <child>
+ <object class="GtkListView" id="list_view">
+ <signal name="activate" handler="gbp_find_other_file_popover_activate_cb" swapped="true"
object="GbpFindOtherFilePopover"/>
+ <property name="orientation">vertical</property>
+ <property name="single-click-activate">True</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage">
+ <property name="pixel-size">16</property>
+ <binding name="gicon">
+ <lookup name="gicon" type="GbpFoundFile">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="hexpand">true</property>
+ <property name="ellipsize">start</property>
+ <binding name="label">
+ <lookup name="display-name" type="GbpFoundFile">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <binding name="visible">
+ <lookup name="is-directory" type="GbpFoundFile">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
+]]>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/plugins/find-other-file/gbp-find-other-file-workspace-addin.c
b/src/plugins/find-other-file/gbp-find-other-file-workspace-addin.c
new file mode 100644
index 000000000..8d0c4d933
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-workspace-addin.c
@@ -0,0 +1,270 @@
+/* gbp-find-other-file-workspace-addin.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-find-other-file-workspace-addin"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-gui.h>
+#include <libide-editor.h>
+#include <libide-projects.h>
+
+#include "gbp-find-other-file-browser.h"
+#include "gbp-find-other-file-popover.h"
+#include "gbp-find-other-file-workspace-addin.h"
+
+struct _GbpFindOtherFileWorkspaceAddin
+{
+ GObject parent_instance;
+ IdeWorkspace *workspace;
+ GtkMenuButton *menu_button;
+ GtkLabel *label;
+ GtkImage *image;
+ GbpFindOtherFileBrowser *browser;
+ GbpFindOtherFilePopover *popover;
+};
+
+static void
+find_other_file_action (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpFindOtherFileWorkspaceAddin *self = user_data;
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_WORKSPACE_ADDIN (self));
+
+ if (self->menu_button != NULL &&
+ gtk_widget_get_visible (GTK_WIDGET (self->menu_button)))
+ gtk_menu_button_popup (self->menu_button);
+}
+
+static GActionEntry actions[] = {
+ { "find-other-file", find_other_file_action },
+};
+
+static void
+gbp_find_other_file_workspace_addin_clear (GbpFindOtherFileWorkspaceAddin *self)
+{
+ g_assert (GBP_IS_FIND_OTHER_FILE_WORKSPACE_ADDIN (self));
+
+ gtk_widget_hide (GTK_WIDGET (self->menu_button));
+ gbp_find_other_file_popover_set_model (self->popover, NULL);
+ gbp_find_other_file_browser_set_file (self->browser, NULL);
+}
+
+static GListModel *
+join_models (GListModel *a,
+ GListModel *b)
+{
+ GListStore *joined = g_list_store_new (G_TYPE_LIST_MODEL);
+
+ g_assert (G_IS_LIST_MODEL (a));
+ g_assert (G_IS_LIST_MODEL (b));
+
+ g_list_store_append (joined, a);
+ g_list_store_append (joined, b);
+
+ return G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (joined)));
+}
+
+static void
+gbp_find_other_file_workspace_addin_list_similar_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeProject *project = (IdeProject *)object;
+ g_autoptr(GbpFindOtherFileWorkspaceAddin) self = user_data;
+ g_autoptr(GListModel) model = NULL;
+ g_autoptr(GListModel) joined = NULL;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_PROJECT (project));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_FIND_OTHER_FILE_WORKSPACE_ADDIN (self));
+
+ /* Maybe we were disposed already */
+ if (self->workspace == NULL)
+ IDE_EXIT;
+
+ if (!(model = ide_project_list_similar_finish (project, result, &error)))
+ {
+ if (!ide_error_ignore (error))
+ g_warning ("%s", error->message);
+ gbp_find_other_file_workspace_addin_clear (self);
+ IDE_EXIT;
+ }
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_BROWSER (self->browser));
+ g_assert (G_IS_LIST_MODEL (model));
+
+ joined = join_models (G_LIST_MODEL (self->browser), model);
+ gbp_find_other_file_popover_set_model (self->popover, joined);
+ gtk_widget_show (GTK_WIDGET (self->menu_button));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_find_other_file_workspace_addin_page_changed (IdeWorkspaceAddin *addin,
+ IdePage *page)
+{
+ GbpFindOtherFileWorkspaceAddin *self = (GbpFindOtherFileWorkspaceAddin *)addin;
+ IdeProject *project;
+ IdeContext *context;
+ GFile *file;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_WORKSPACE_ADDIN (self));
+ g_assert (!page || IDE_IS_PAGE (page));
+
+ gbp_find_other_file_workspace_addin_clear (self);
+
+ if (!IDE_IS_EDITOR_PAGE (page))
+ IDE_EXIT;
+
+ context = ide_workspace_get_context (self->workspace);
+ project = ide_project_from_context (context);
+ file = ide_editor_page_get_file (IDE_EDITOR_PAGE (page));
+
+ gbp_find_other_file_browser_set_file (self->browser, file);
+
+ ide_project_list_similar_async (project,
+ file,
+ NULL,
+ gbp_find_other_file_workspace_addin_list_similar_cb,
+ g_object_ref (self));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_find_other_file_workspace_addin_load (IdeWorkspaceAddin *addin,
+ IdeWorkspace *workspace)
+{
+ GbpFindOtherFileWorkspaceAddin *self = (GbpFindOtherFileWorkspaceAddin *)addin;
+ g_autoptr(GFile) workdir = NULL;
+ PanelStatusbar *statusbar;
+ IdeContext *context;
+ GtkBox *box;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_WORKSPACE_ADDIN (self));
+ g_assert (IDE_IS_WORKSPACE (workspace));
+
+ self->workspace = workspace;
+
+ context = ide_workspace_get_context (workspace);
+ workdir = ide_context_ref_workdir (context);
+
+ self->browser = gbp_find_other_file_browser_new ();
+ gbp_find_other_file_browser_set_root (self->browser, workdir);
+
+ self->popover = g_object_new (GBP_TYPE_FIND_OTHER_FILE_POPOVER,
+ NULL);
+ box = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "spacing", 6,
+ NULL);
+ self->image = g_object_new (GTK_TYPE_IMAGE,
+ "icon-name", "folder-symbolic",
+ "pixel-size", 16,
+ NULL);
+ gtk_box_append (box, GTK_WIDGET (self->image));
+#if 0
+ self->label = g_object_new (GTK_TYPE_LABEL,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+ gtk_box_append (box, GTK_WIDGET (self->label));
+#endif
+ self->menu_button = g_object_new (GTK_TYPE_MENU_BUTTON,
+ "focus-on-click", FALSE,
+ "popover", self->popover,
+ "direction", GTK_ARROW_UP,
+ "child", box,
+ "visible", FALSE,
+ "tooltip-text", _("Similar Files"),
+ NULL);
+
+ statusbar = ide_workspace_get_statusbar (workspace);
+ panel_statusbar_add_suffix (statusbar, 10000, GTK_WIDGET (self->menu_button));
+
+ g_action_map_add_action_entries (G_ACTION_MAP (workspace),
+ actions,
+ G_N_ELEMENTS (actions),
+ self);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_find_other_file_workspace_addin_unload (IdeWorkspaceAddin *addin,
+ IdeWorkspace *workspace)
+{
+ GbpFindOtherFileWorkspaceAddin *self = (GbpFindOtherFileWorkspaceAddin *)addin;
+ PanelStatusbar *statusbar;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_FIND_OTHER_FILE_WORKSPACE_ADDIN (self));
+ g_assert (IDE_IS_WORKSPACE (workspace));
+
+ g_clear_object (&self->browser);
+
+ for (guint i = 0; i < G_N_ELEMENTS (actions); i++)
+ g_action_map_remove_action (G_ACTION_MAP (workspace), actions[i].name);
+
+ statusbar = ide_workspace_get_statusbar (workspace);
+ panel_statusbar_remove (statusbar, GTK_WIDGET (self->menu_button));
+ self->menu_button = NULL;
+ self->popover = NULL;
+ self->label = NULL;
+ self->image = NULL;
+
+ self->workspace = NULL;
+
+ IDE_EXIT;
+}
+
+static void
+workspace_addin_iface_init (IdeWorkspaceAddinInterface *iface)
+{
+ iface->load = gbp_find_other_file_workspace_addin_load;
+ iface->unload = gbp_find_other_file_workspace_addin_unload;
+ iface->page_changed = gbp_find_other_file_workspace_addin_page_changed;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpFindOtherFileWorkspaceAddin, gbp_find_other_file_workspace_addin,
G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKSPACE_ADDIN, workspace_addin_iface_init))
+
+static void
+gbp_find_other_file_workspace_addin_class_init (GbpFindOtherFileWorkspaceAddinClass *klass)
+{
+}
+
+static void
+gbp_find_other_file_workspace_addin_init (GbpFindOtherFileWorkspaceAddin *self)
+{
+}
diff --git a/src/plugins/find-other-file/gbp-find-other-file-workspace-addin.h
b/src/plugins/find-other-file/gbp-find-other-file-workspace-addin.h
new file mode 100644
index 000000000..a069b6f60
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-find-other-file-workspace-addin.h
@@ -0,0 +1,31 @@
+/* gbp-find-other-file-workspace-addin.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 <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_FIND_OTHER_FILE_WORKSPACE_ADDIN (gbp_find_other_file_workspace_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpFindOtherFileWorkspaceAddin, gbp_find_other_file_workspace_addin, GBP,
FIND_OTHER_FILE_WORKSPACE_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/find-other-file/gbp-found-file.c b/src/plugins/find-other-file/gbp-found-file.c
new file mode 100644
index 000000000..d3ae24da8
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-found-file.c
@@ -0,0 +1,244 @@
+/* gbp-found-file.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-found-file"
+
+#include "config.h"
+
+#include "gbp-found-file.h"
+
+struct _GbpFoundFile
+{
+ GObject parent_instance;
+ GFile *file;
+ GFileInfo *info;
+ char *relative;
+};
+
+enum {
+ PROP_0,
+ PROP_DISPLAY_NAME,
+ PROP_FILE,
+ PROP_GICON,
+ PROP_IS_DIRECTORY,
+ N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (GbpFoundFile, gbp_found_file, G_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+
+static gboolean
+gbp_found_file_get_is_directory (GbpFoundFile *self)
+{
+ g_assert (GBP_IS_FOUND_FILE (self));
+
+ return self->info != NULL ?
+ g_file_info_get_file_type (self->info) == G_FILE_TYPE_DIRECTORY :
+ FALSE;
+}
+
+static void
+gbp_found_file_query_info_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = (GFile *)object;
+ g_autoptr(GbpFoundFile) self = user_data;
+
+ g_assert (G_IS_FILE (file));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_FOUND_FILE (self));
+
+ if (!(self->info = g_file_query_info_finish (file, result, NULL)))
+ return;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPLAY_NAME]);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_GICON]);
+
+ if (gbp_found_file_get_is_directory (self))
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IS_DIRECTORY]);
+}
+
+static void
+gbp_found_file_constructed (GObject *object)
+{
+ GbpFoundFile *self = (GbpFoundFile *)object;
+
+ G_OBJECT_CLASS (gbp_found_file_parent_class)->constructed (object);
+
+ if (self->file == NULL)
+ return;
+
+ g_file_query_info_async (self->file,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_LOW,
+ NULL,
+ gbp_found_file_query_info_cb,
+ g_object_ref (self));
+}
+
+static void
+gbp_found_file_dispose (GObject *object)
+{
+ GbpFoundFile *self = (GbpFoundFile *)object;
+
+ g_clear_object (&self->file);
+ g_clear_object (&self->info);
+ g_clear_pointer (&self->relative, g_free);
+
+ G_OBJECT_CLASS (gbp_found_file_parent_class)->dispose (object);
+}
+
+static void
+gbp_found_file_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpFoundFile *self = GBP_FOUND_FILE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY_NAME:
+ if (self->relative != NULL)
+ g_value_set_string (value, self->relative);
+ else if (self->info != NULL)
+ g_value_set_string (value, g_file_info_get_attribute_string (self->info,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME));
+ break;
+
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+
+ case PROP_GICON:
+ if (self->info != NULL)
+ g_value_set_object (value, g_file_info_get_attribute_object (self->info,
G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON));
+ break;
+
+ case PROP_IS_DIRECTORY:
+ g_value_set_boolean (value, gbp_found_file_get_is_directory (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_found_file_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpFoundFile *self = GBP_FOUND_FILE (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ self->file = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_found_file_class_init (GbpFoundFileClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gbp_found_file_constructed;
+ object_class->dispose = gbp_found_file_dispose;
+ object_class->get_property = gbp_found_file_get_property;
+ object_class->set_property = gbp_found_file_set_property;
+
+ properties [PROP_FILE] =
+ g_param_spec_object ("file", NULL, NULL,
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_DISPLAY_NAME] =
+ g_param_spec_string ("display-name", NULL, NULL,
+ NULL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_GICON] =
+ g_param_spec_object ("gicon", NULL, NULL,
+ G_TYPE_ICON,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_IS_DIRECTORY] =
+ g_param_spec_boolean ("is-directory", NULL, NULL,
+ FALSE,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_found_file_init (GbpFoundFile *self)
+{
+}
+
+GbpFoundFile *
+gbp_found_file_new (GFile *workdir,
+ GFile *file)
+{
+ GbpFoundFile *ret;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+ ret = g_object_new (GBP_TYPE_FOUND_FILE,
+ "file", file,
+ NULL);
+ ret->relative = g_file_get_relative_path (workdir, file);
+
+ return ret;
+}
+
+void
+gbp_found_file_open (GbpFoundFile *self,
+ IdeWorkspace *workspace)
+{
+ g_autoptr(IdePanelPosition) position = NULL;
+ IdeWorkbench *workbench;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (GBP_IS_FOUND_FILE (self));
+ g_return_if_fail (IDE_IS_WORKSPACE (workspace));
+
+ workbench = ide_workspace_get_workbench (workspace);
+ position = ide_panel_position_new ();
+
+ ide_workbench_open_async (workbench,
+ self->file,
+ NULL,
+ IDE_BUFFER_OPEN_FLAGS_NONE,
+ position,
+ NULL, NULL, NULL);
+
+ IDE_EXIT;
+}
diff --git a/src/plugins/find-other-file/gbp-found-file.h b/src/plugins/find-other-file/gbp-found-file.h
new file mode 100644
index 000000000..f5476e4d2
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-found-file.h
@@ -0,0 +1,36 @@
+/* gbp-found-file.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-gui.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_FOUND_FILE (gbp_found_file_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpFoundFile, gbp_found_file, GBP, FOUND_FILE, GObject)
+
+GbpFoundFile *gbp_found_file_new (GFile *workdir,
+ GFile *file);
+void gbp_found_file_open (GbpFoundFile *self,
+ IdeWorkspace *workspace);
+
+G_END_DECLS
diff --git a/src/plugins/find-other-file/gbp-simple-similar-file-locator.c
b/src/plugins/find-other-file/gbp-simple-similar-file-locator.c
new file mode 100644
index 000000000..6ec8ced66
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-simple-similar-file-locator.c
@@ -0,0 +1,171 @@
+/* gbp-simple-similar-file-locator.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-simple-similar-file-locator"
+
+#include "config.h"
+
+#include <libide-projects.h>
+#include <libide-threading.h>
+#include <libide-vcs.h>
+
+#include "gbp-simple-similar-file-locator.h"
+
+struct _GbpSimpleSimilarFileLocator
+{
+ IdeObject parent_instance;
+};
+
+static void
+gbp_simple_similar_file_locator_list_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = (GFile *)object;
+ g_autoptr(GListStore) store = NULL;
+ g_autoptr(GPtrArray) ar = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ IdeVcs *vcs;
+
+ IDE_ENTRY;
+
+ g_assert (G_IS_FILE (file));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!(ar = ide_g_file_find_finish (file, result, &error)))
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ IDE_EXIT;
+ }
+
+ vcs = ide_task_get_task_data (task);
+ store = g_list_store_new (G_TYPE_FILE);
+
+ for (guint i = 0; i < ar->len; i++)
+ {
+ GFile *item = g_ptr_array_index (ar, i);
+
+ if (!ide_vcs_is_ignored (vcs, item, NULL))
+ g_list_store_append (store, item);
+ }
+
+ ide_task_return_object (task, g_steal_pointer (&store));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_simple_similar_file_locator_list_async (IdeSimilarFileLocator *locator,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpSimpleSimilarFileLocator *self = (GbpSimpleSimilarFileLocator *)locator;
+ g_autofree char *name = NULL;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GFile) parent = NULL;
+ g_autofree char *pattern = NULL;
+ IdeContext *context;
+ IdeVcs *vcs;
+ char *ptr;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_SIMPLE_SIMILAR_FILE_LOCATOR (self));
+ g_assert (G_IS_FILE (file));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ vcs = ide_vcs_from_context (context);
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_simple_similar_file_locator_list_async);
+ ide_task_set_task_data (task, g_object_ref (vcs), g_object_unref);
+
+ if (!(parent = g_file_get_parent (file)) ||
+ !(name = g_file_get_basename (file)))
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Unexpected GFile");
+ IDE_EXIT;
+ }
+
+ /* Strip off file suffix */
+ if ((ptr = strrchr (name, '.')))
+ *ptr = 0;
+
+ /* remove -private or private suffix */
+ if (g_str_has_suffix (name, "-private"))
+ name[strlen (name) - strlen ("-private") - 1] = 0;
+
+ /* Simple glob pattern */
+ pattern = g_strdup_printf ("%s*", name);
+
+ ide_g_file_find_with_depth_async (parent,
+ pattern,
+ 2,
+ cancellable,
+ gbp_simple_similar_file_locator_list_cb,
+ g_steal_pointer (&task));
+
+ IDE_EXIT;
+}
+
+static GListModel *
+gbp_simple_similar_file_locator_list_finish (IdeSimilarFileLocator *locator,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_SIMPLE_SIMILAR_FILE_LOCATOR (locator));
+ g_assert (IDE_IS_TASK (result));
+
+ ret = ide_task_propagate_object (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
+
+static void
+similar_file_locator_iface_init (IdeSimilarFileLocatorInterface *iface)
+{
+ iface->list_async = gbp_simple_similar_file_locator_list_async;
+ iface->list_finish = gbp_simple_similar_file_locator_list_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpSimpleSimilarFileLocator, gbp_simple_similar_file_locator, IDE_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_SIMILAR_FILE_LOCATOR,
similar_file_locator_iface_init))
+
+static void
+gbp_simple_similar_file_locator_class_init (GbpSimpleSimilarFileLocatorClass *klass)
+{
+}
+
+static void
+gbp_simple_similar_file_locator_init (GbpSimpleSimilarFileLocator *self)
+{
+}
diff --git a/src/plugins/find-other-file/gbp-simple-similar-file-locator.h
b/src/plugins/find-other-file/gbp-simple-similar-file-locator.h
new file mode 100644
index 000000000..1d1d9dc38
--- /dev/null
+++ b/src/plugins/find-other-file/gbp-simple-similar-file-locator.h
@@ -0,0 +1,31 @@
+/* gbp-simple-similar-file-locator.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_SIMPLE_SIMILAR_FILE_LOCATOR (gbp_simple_similar_file_locator_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpSimpleSimilarFileLocator, gbp_simple_similar_file_locator, GBP,
SIMPLE_SIMILAR_FILE_LOCATOR, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/find-other-file/gtk/keybindings.json
b/src/plugins/find-other-file/gtk/keybindings.json
new file mode 100644
index 000000000..15c99196c
--- /dev/null
+++ b/src/plugins/find-other-file/gtk/keybindings.json
@@ -0,0 +1 @@
+{ "trigger" : "<Control><Shift>o", "action" : "win.find-other-file", "when" : "canEdit()", "phase" :
"capture" },
diff --git a/src/plugins/find-other-file/meson.build b/src/plugins/find-other-file/meson.build
index 4df9128b6..7c527d822 100644
--- a/src/plugins/find-other-file/meson.build
+++ b/src/plugins/find-other-file/meson.build
@@ -1,9 +1,16 @@
-install_data('find_other_file.py', install_dir: plugindir)
+plugins_sources += files([
+ 'find-other-file-plugin.c',
+ 'gbp-simple-similar-file-locator.c',
+ 'gbp-find-other-file-browser.c',
+ 'gbp-find-other-file-popover.c',
+ 'gbp-find-other-file-workspace-addin.c',
+ 'gbp-found-file.c',
+])
-configure_file(
- input: 'find-other-file.plugin',
- output: 'find-other-file.plugin',
- configuration: config_h,
- install: true,
- install_dir: plugindir,
+plugin_find_other_file_resources = gnome.compile_resources(
+ 'find-other-file-resources',
+ 'find-other-file.gresource.xml',
+ c_name: 'gbp_find_other_file',
)
+
+plugins_sources += plugin_find_other_file_resources
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]