[gnome-builder/wip/gtk4-port: 985/1774] libide/projects: add similar file locator interface
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 985/1774] libide/projects: add similar file locator interface
- Date: Mon, 11 Jul 2022 22:31:30 +0000 (UTC)
commit e927460c2bbe32593799c2b78958028293dc0271
Author: Christian Hergert <chergert redhat com>
Date: Wed May 11 15:44:42 2022 -0700
libide/projects: add similar file locator interface
This will be used to implement "find other files" in a more extensible way.
The find-other-files plugin will be able to reuse this from the project
object and then attach it to various widgetry when necessary.
src/libide/projects/ide-project.c | 176 ++++++++++++++++++++++++-
src/libide/projects/ide-project.h | 54 ++++----
src/libide/projects/ide-similar-file-locator.c | 89 +++++++++++++
src/libide/projects/ide-similar-file-locator.h | 59 +++++++++
src/libide/projects/libide-projects.h | 1 +
src/libide/projects/meson.build | 2 +
6 files changed, 358 insertions(+), 23 deletions(-)
---
diff --git a/src/libide/projects/ide-project.c b/src/libide/projects/ide-project.c
index e3fb7cd78..54f720619 100644
--- a/src/libide/projects/ide-project.c
+++ b/src/libide/projects/ide-project.c
@@ -23,15 +23,20 @@
#include "config.h"
#include <glib/gi18n.h>
+#include <libpeas/peas.h>
+
#include <libide-code.h>
+#include <libide-plugins.h>
#include "ide-buffer-private.h"
#include "ide-project.h"
+#include "ide-similar-file-locator.h"
struct _IdeProject
{
- IdeObject parent_instance;
+ IdeObject parent_instance;
+ IdeExtensionSetAdapter *similar_file_locators;
};
typedef struct
@@ -51,9 +56,23 @@ G_DEFINE_FINAL_TYPE (IdeProject, ide_project, IDE_TYPE_OBJECT)
static guint signals [N_SIGNALS];
+static void
+ide_project_dispose (GObject *object)
+{
+ IdeProject *self = (IdeProject *)object;
+
+ ide_clear_and_destroy_object (&self->similar_file_locators);
+
+ G_OBJECT_CLASS (ide_project_parent_class)->dispose (object);
+}
+
static void
ide_project_class_init (IdeProjectClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = ide_project_dispose;
+
signals [FILE_RENAMED] =
g_signal_new ("file-renamed",
G_TYPE_FROM_CLASS (klass),
@@ -484,3 +503,158 @@ ide_project_trash_file_finish (IdeProject *self,
IDE_RETURN (ret);
}
+
+typedef struct
+{
+ GFile *file;
+ GListStore *models;
+ guint n_active;
+} ListSimilar;
+
+static void
+list_similar_free (ListSimilar *state)
+{
+ g_assert (state->n_active == 0);
+
+ g_clear_object (&state->file);
+ g_clear_object (&state->models);
+ g_slice_free (ListSimilar, state);
+}
+
+static void
+ide_project_list_similar_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeSimilarFileLocator *locator = (IdeSimilarFileLocator *)object;
+ g_autoptr(GListModel) model = NULL;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ ListSimilar *state;
+ IdeProject *self;
+
+ g_assert (IDE_IS_SIMILAR_FILE_LOCATOR (locator));
+ 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);
+
+ g_assert (IDE_IS_PROJECT (self));
+ g_assert (state != NULL);
+ g_assert (G_IS_FILE (state->file));
+ g_assert (G_IS_LIST_STORE (state->models));
+
+ if ((model = ide_similar_file_locator_list_finish (locator, result, &error)))
+ g_list_store_append (state->models, model);
+ else if (!ide_error_ignore (error))
+ ide_object_warning (IDE_OBJECT (self), "%s", error->message);
+
+ state->n_active--;
+
+ if (state->n_active == 0)
+ ide_task_return_object (task,
+ gtk_flatten_list_model_new (g_object_ref (G_LIST_MODEL (state->models))));
+}
+
+static void
+ide_project_list_similar_foreach_cb (IdeExtensionSetAdapter *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *exten,
+ gpointer user_data)
+{
+ IdeSimilarFileLocator *locator = (IdeSimilarFileLocator *)exten;
+ IdeTask *task = user_data;
+ ListSimilar *state;
+
+ g_assert (IDE_IS_EXTENSION_SET_ADAPTER (set));
+ g_assert (plugin_info != NULL);
+ g_assert (IDE_IS_SIMILAR_FILE_LOCATOR (locator));
+ g_assert (IDE_IS_TASK (task));
+
+ state = ide_task_get_task_data (task);
+
+ g_assert (state != NULL);
+ g_assert (G_IS_FILE (state->file));
+ g_assert (G_IS_LIST_STORE (state->models));
+
+ state->n_active++;
+
+ ide_similar_file_locator_list_async (locator,
+ state->file,
+ ide_task_get_cancellable (task),
+ ide_project_list_similar_cb,
+ g_object_ref (task));
+}
+
+void
+ide_project_list_similar_async (IdeProject *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ ListSimilar *state;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_MAIN_THREAD ());
+ g_return_if_fail (IDE_IS_PROJECT (self));
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, ide_project_list_similar_async);
+
+ if (self->similar_file_locators == NULL)
+ self->similar_file_locators = ide_extension_set_adapter_new (IDE_OBJECT (self),
+ peas_engine_get_default (),
+ IDE_TYPE_SIMILAR_FILE_LOCATOR,
+ NULL, NULL);
+
+ state = g_slice_new0 (ListSimilar);
+ state->file = g_object_ref (file);
+ state->models = g_list_store_new (G_TYPE_LIST_MODEL);
+ ide_task_set_task_data (task, state, list_similar_free);
+
+ ide_extension_set_adapter_foreach (self->similar_file_locators,
+ ide_project_list_similar_foreach_cb,
+ task);
+
+ if (state->n_active == 0)
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Not supported");
+
+ IDE_EXIT;
+}
+
+/**
+ * ide_project_list_similar_finish:
+ * @self: a #IdeProject
+ * @result: a #GAsyncResult
+ * @error: location for a #GError
+ *
+ * Completes asynchronous request to locate similar files.
+ *
+ * Returns: (transfer full): a #GListModel of #GFile or %NULL
+ */
+GListModel *
+ide_project_list_similar_finish (IdeProject *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL);
+ g_return_val_if_fail (IDE_IS_PROJECT (self), NULL);
+ g_return_val_if_fail (IDE_IS_TASK (result), NULL);
+
+ ret = ide_task_propagate_object (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
+}
diff --git a/src/libide/projects/ide-project.h b/src/libide/projects/ide-project.h
index 156a04250..f5f480416 100644
--- a/src/libide/projects/ide-project.h
+++ b/src/libide/projects/ide-project.h
@@ -30,27 +30,37 @@ IDE_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (IdeProject, ide_project, IDE, PROJECT, IdeObject)
IDE_AVAILABLE_IN_ALL
-IdeProject *ide_project_from_context (IdeContext *context);
-IDE_AVAILABLE_IN_ALL
-void ide_project_rename_file_async (IdeProject *self,
- GFile *orig_file,
- GFile *new_file,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-IDE_AVAILABLE_IN_ALL
-gboolean ide_project_rename_file_finish (IdeProject *self,
- GAsyncResult *result,
- GError **error);
-IDE_AVAILABLE_IN_ALL
-void ide_project_trash_file_async (IdeProject *self,
- GFile *file,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-IDE_AVAILABLE_IN_ALL
-gboolean ide_project_trash_file_finish (IdeProject *self,
- GAsyncResult *result,
- GError **error);
+IdeProject *ide_project_from_context (IdeContext *context);
+IDE_AVAILABLE_IN_ALL
+void ide_project_rename_file_async (IdeProject *self,
+ GFile *orig_file,
+ GFile *new_file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_ALL
+gboolean ide_project_rename_file_finish (IdeProject *self,
+ GAsyncResult *result,
+ GError **error);
+IDE_AVAILABLE_IN_ALL
+void ide_project_trash_file_async (IdeProject *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_ALL
+gboolean ide_project_trash_file_finish (IdeProject *self,
+ GAsyncResult *result,
+ GError **error);
+IDE_AVAILABLE_IN_ALL
+void ide_project_list_similar_async (IdeProject *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_ALL
+GListModel *ide_project_list_similar_finish (IdeProject *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/libide/projects/ide-similar-file-locator.c b/src/libide/projects/ide-similar-file-locator.c
new file mode 100644
index 000000000..35dca9969
--- /dev/null
+++ b/src/libide/projects/ide-similar-file-locator.c
@@ -0,0 +1,89 @@
+/* ide-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 "ide-similar-file-locator"
+
+#include "config.h"
+
+#include "ide-similar-file-locator.h"
+
+G_DEFINE_INTERFACE (IdeSimilarFileLocator, ide_similar_file_locator, G_TYPE_OBJECT)
+
+static void
+ide_similar_file_locator_default_init (IdeSimilarFileLocatorInterface *iface)
+{
+}
+
+/**
+ * ide_similar_file_locator_list_async:
+ * @self: a #IdeSimilarFileLocator
+ * @file: a #GFile to find similar files for
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: callback to use to complete operation
+ * @user_data: closure data for @callback
+ *
+ * Asynchronously requests locating similar files.
+ *
+ * A similar file may be found such as those with similar file suffixes
+ * or perhaps a designer file associated with a source file.
+ */
+void
+ide_similar_file_locator_list_async (IdeSimilarFileLocator *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_SIMILAR_FILE_LOCATOR (self));
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ IDE_SIMILAR_FILE_LOCATOR_GET_IFACE (self)->list_async (self, file, cancellable, callback, user_data);
+
+ IDE_EXIT;
+}
+
+/**
+ * ide_similar_file_locator_list_finish:
+ * @self: a #IdeSimilarFileLocator
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
+ *
+ * Completes asynchronous request to list similar files.
+ *
+ * Returns: (transfer full): a #GListModel of #GFile or %NULL
+ */
+GListModel *
+ide_similar_file_locator_list_finish (IdeSimilarFileLocator *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GListModel *ret;
+
+ IDE_ENTRY;
+
+ g_return_val_if_fail (IDE_IS_SIMILAR_FILE_LOCATOR (self), NULL);
+
+ ret = IDE_SIMILAR_FILE_LOCATOR_GET_IFACE (self)->list_finish (self, result, error);
+
+ IDE_RETURN (ret);
+}
diff --git a/src/libide/projects/ide-similar-file-locator.h b/src/libide/projects/ide-similar-file-locator.h
new file mode 100644
index 000000000..6b955b0fc
--- /dev/null
+++ b/src/libide/projects/ide-similar-file-locator.h
@@ -0,0 +1,59 @@
+/* ide-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
+
+#if !defined (IDE_PROJECTS_INSIDE) && !defined (IDE_PROJECTS_COMPILATION)
+# error "Only <libide-projects.h> can be included directly."
+#endif
+
+#include <libide-core.h>
+
+#define IDE_TYPE_SIMILAR_FILE_LOCATOR (ide_similar_file_locator_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_INTERFACE (IdeSimilarFileLocator, ide_similar_file_locator, IDE, SIMILAR_FILE_LOCATOR, GObject)
+
+struct _IdeSimilarFileLocatorInterface
+{
+ GTypeInterface parent_iface;
+
+ void (*list_async) (IdeSimilarFileLocator *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ GListModel *(*list_finish) (IdeSimilarFileLocator *self,
+ GAsyncResult *result,
+ GError **error);
+};
+
+IDE_AVAILABLE_IN_ALL
+void ide_similar_file_locator_list_async (IdeSimilarFileLocator *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_ALL
+GListModel *ide_similar_file_locator_list_finish (IdeSimilarFileLocator *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
diff --git a/src/libide/projects/libide-projects.h b/src/libide/projects/libide-projects.h
index f1f7db00d..62e1cfc75 100644
--- a/src/libide/projects/libide-projects.h
+++ b/src/libide/projects/libide-projects.h
@@ -34,6 +34,7 @@
#include "ide-project-tree-addin.h"
#include "ide-projects-global.h"
#include "ide-recent-projects.h"
+#include "ide-similar-file-locator.h"
#include "ide-template-base.h"
#include "ide-template-provider.h"
diff --git a/src/libide/projects/meson.build b/src/libide/projects/meson.build
index 0916891d1..e4c36399d 100644
--- a/src/libide/projects/meson.build
+++ b/src/libide/projects/meson.build
@@ -15,6 +15,7 @@ libide_projects_public_headers = [
'ide-project-template.h',
'ide-project-tree-addin.h',
'ide-recent-projects.h',
+ 'ide-similar-file-locator.h',
'ide-template-base.h',
'ide-template-provider.h',
'libide-projects.h',
@@ -43,6 +44,7 @@ libide_projects_public_sources = [
'ide-project-template.c',
'ide-project-tree-addin.c',
'ide-recent-projects.c',
+ 'ide-similar-file-locator.c',
'ide-template-base.c',
'ide-template-provider.c',
]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]