[gnome-builder] project-tree: add gbp_project_tree_reveal()
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] project-tree: add gbp_project_tree_reveal()
- Date: Mon, 26 Oct 2020 21:25:40 +0000 (UTC)
commit 8af719a31e3af77356d91585c15181d7af878840
Author: Christian Hergert <chergert redhat com>
Date: Mon Oct 26 14:15:21 2020 -0700
project-tree: add gbp_project_tree_reveal()
This helper handles the asynchronous nature of expanding the file tree to
find a given file or directory within the project. The tree will be
expanded up to that node and the node will be selected and scrolled into
view of the user.
We used ot have something like this before movin to IdeTree, and this
restores that functionality.
Related #1320
src/plugins/project-tree/gbp-project-tree.c | 171 ++++++++++++++++++++++++++++
src/plugins/project-tree/gbp-project-tree.h | 3 +
2 files changed, 174 insertions(+)
---
diff --git a/src/plugins/project-tree/gbp-project-tree.c b/src/plugins/project-tree/gbp-project-tree.c
index 5fd644118..ffa55aa2d 100644
--- a/src/plugins/project-tree/gbp-project-tree.c
+++ b/src/plugins/project-tree/gbp-project-tree.c
@@ -25,6 +25,8 @@
#include <libide-gui.h>
#include <libide-projects.h>
+#include "ide-tree-private.h"
+
#include "gbp-project-tree.h"
struct _GbpProjectTree
@@ -176,3 +178,172 @@ static void
gbp_project_tree_init (GbpProjectTree *self)
{
}
+
+static IdeTreeNode *
+gbp_project_tree_get_project_files (GbpProjectTree *self)
+{
+ IdeTreeModel *model;
+ IdeTreeNode *project_files = NULL;
+
+ g_assert (GBP_IS_PROJECT_TREE (self));
+
+ model = IDE_TREE_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (self)));
+ ide_tree_node_traverse (ide_tree_model_get_root (model),
+ G_PRE_ORDER,
+ G_TRAVERSE_ALL,
+ 1,
+ locate_project_files,
+ &project_files);
+
+ return project_files;
+}
+
+typedef struct
+{
+ GbpProjectTree *tree;
+ IdeTreeNode *node;
+ GFile *file;
+} Reveal;
+
+static void reveal_next (Reveal *r);
+
+static void
+reveal_free (Reveal *r)
+{
+ g_clear_object (&r->tree);
+ g_clear_object (&r->node);
+ g_clear_object (&r->file);
+ g_free (r);
+}
+
+static void
+reveal_next_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeTreeModel *model = (IdeTreeModel *)object;
+ Reveal *r = user_data;
+
+ g_assert (IDE_IS_TREE_MODEL (model));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (r != NULL);
+ g_assert (GBP_IS_PROJECT_TREE (r->tree));
+ g_assert (IDE_IS_TREE_NODE (r->node));
+ g_assert (G_IS_FILE (r->file));
+
+ if (!ide_tree_model_expand_finish (model, result, NULL))
+ reveal_free (r);
+ else
+ reveal_next (g_steal_pointer (&r));
+}
+
+static void
+reveal_next (Reveal *r)
+{
+ g_autoptr(GFile) file = NULL;
+ IdeProjectFile *pf;
+
+ g_assert (r != NULL);
+ g_assert (GBP_IS_PROJECT_TREE (r->tree));
+ g_assert (IDE_IS_TREE_NODE (r->node));
+ g_assert (G_IS_FILE (r->file));
+
+ if (!ide_tree_node_holds (r->node, IDE_TYPE_PROJECT_FILE) ||
+ !(pf = ide_tree_node_get_item (r->node)) ||
+ !IDE_IS_PROJECT_FILE (pf) ||
+ !(file = ide_project_file_ref_file (pf)))
+ goto failure;
+
+ if (g_file_has_prefix (r->file, file))
+ {
+ IdeTreeNode *child;
+
+ /* If this node cannot have children, then there is no way we
+ * can expect to find the child there.
+ */
+ if (!ide_tree_node_get_children_possible (r->node))
+ goto failure;
+
+ /* If this node needs to be built, then build it before we
+ * continue processing.
+ */
+ if (_ide_tree_node_get_needs_build_children (r->node))
+ {
+ IdeTreeModel *model;
+
+ if (!(model = IDE_TREE_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (r->tree)))))
+ goto failure;
+
+ ide_tree_model_expand_async (model,
+ r->node,
+ NULL,
+ reveal_next_cb,
+ r);
+ return;
+ }
+
+ /* Tree to find the first child which is equal to or is a prefix
+ * for the target file.
+ */
+ if (!(child = ide_tree_node_get_nth_child (r->node, 0)))
+ goto failure;
+
+ do
+ {
+ IdeProjectFile *cpf;
+ g_autoptr(GFile) cf = NULL;
+
+ if (!ide_tree_node_holds (child, IDE_TYPE_PROJECT_FILE) ||
+ !(cpf = ide_tree_node_get_item (child)) ||
+ !IDE_IS_PROJECT_FILE (cpf) ||
+ !(cf = ide_project_file_ref_file (cpf)) ||
+ !G_IS_FILE (cf))
+ continue;
+
+ if (g_file_has_prefix (r->file, cf) || g_file_equal (r->file, cf))
+ {
+ g_set_object (&r->node, child);
+ reveal_next (r);
+ return;
+ }
+ }
+ while ((child = ide_tree_node_get_next (child)));
+ }
+ else if (g_file_equal (r->file, file))
+ {
+ g_autoptr(GtkTreePath) path = ide_tree_node_get_path (r->node);
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (r->tree), path);
+ ide_tree_select_node (IDE_TREE (r->tree), r->node);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (r->tree),
+ path, NULL, FALSE, 0, 0);
+ }
+
+failure:
+ reveal_free (r);
+}
+
+void
+gbp_project_tree_reveal (GbpProjectTree *self,
+ GFile *file)
+{
+ IdeTreeNode *project_files;
+ Reveal *r;
+
+ g_return_if_fail (GBP_IS_PROJECT_TREE (self));
+ g_return_if_fail (!file || G_IS_FILE (file));
+
+ if (file == NULL)
+ return;
+
+ project_files = gbp_project_tree_get_project_files (self);
+
+ if (!IDE_IS_TREE_NODE (project_files))
+ return;
+
+ r = g_new0 (Reveal, 1);
+ r->tree = g_object_ref (self);
+ r->node = g_object_ref (project_files);
+ r->file = g_object_ref (file);
+
+ reveal_next (g_steal_pointer (&r));
+}
diff --git a/src/plugins/project-tree/gbp-project-tree.h b/src/plugins/project-tree/gbp-project-tree.h
index 1a1404dbe..a0ea31968 100644
--- a/src/plugins/project-tree/gbp-project-tree.h
+++ b/src/plugins/project-tree/gbp-project-tree.h
@@ -28,4 +28,7 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GbpProjectTree, gbp_project_tree, GBP, PROJECT_TREE, IdeTree)
+void gbp_project_tree_reveal (GbpProjectTree *self,
+ GFile *file);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]