[gnome-builder/wip/chergert/perspective] libide: migrate IdeBackForwardItem to use IdeUri
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/perspective] libide: migrate IdeBackForwardItem to use IdeUri
- Date: Mon, 16 Nov 2015 05:02:38 +0000 (UTC)
commit 954d2079101b04e92718ce6b6f12c109dbc6c3b0
Author: Christian Hergert <chergert redhat com>
Date: Sun Nov 15 21:02:12 2015 -0800
libide: migrate IdeBackForwardItem to use IdeUri
Previously we used IdeSourceLocation which made it basically impossible
to use the navigation list for anything but source code. We really want
to be able to navigate back/forward from anything in the view.
libide/Makefile.am | 3 +
libide/ide-back-forward-item.c | 106 +++++++-----
libide/ide-back-forward-item.h | 11 +-
libide/ide-back-forward-list-load.c | 154 ++++++++++++++++
libide/ide-back-forward-list-private.h | 52 ++++++
libide/ide-back-forward-list-save.c | 137 ++++++++++++++
libide/ide-back-forward-list.c | 307 ++------------------------------
libide/ide-buffer-manager.c | 42 +++--
libide/ide-context.c | 1 +
libide/ide-internal.h | 18 --
libide/ide-source-view.c | 19 ++-
11 files changed, 463 insertions(+), 387 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index c4e62f1..6271cb0 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -26,6 +26,8 @@ libide_1_0_la_public_sources = \
ide-back-forward-item.c \
ide-back-forward-item.h \
ide-back-forward-list.c \
+ ide-back-forward-list-load.c \
+ ide-back-forward-list-save.c \
ide-back-forward-list.h \
ide-buffer-change-monitor.c \
ide-buffer-change-monitor.h \
@@ -242,6 +244,7 @@ libide_1_0_la_SOURCES = \
ide-application-private.h \
ide-async-helper.c \
ide-async-helper.h \
+ ide-back-forward-list-private.h \
ide-battery-monitor.c \
ide-battery-monitor.h \
ide-css-provider.c \
diff --git a/libide/ide-back-forward-item.c b/libide/ide-back-forward-item.c
index 74beb98..fb29438 100644
--- a/libide/ide-back-forward-item.c
+++ b/libide/ide-back-forward-item.c
@@ -26,49 +26,50 @@
struct _IdeBackForwardItem
{
- IdeObject parent_instance;
- IdeSourceLocation *location;
+ IdeObject parent_instance;
+ IdeUri *uri;
};
G_DEFINE_TYPE (IdeBackForwardItem, ide_back_forward_item, IDE_TYPE_OBJECT)
enum {
PROP_0,
- PROP_LOCATION,
+ PROP_URI,
LAST_PROP
};
static GParamSpec *properties [LAST_PROP];
IdeBackForwardItem *
-ide_back_forward_item_new (IdeContext *context,
- IdeSourceLocation *location)
+ide_back_forward_item_new (IdeContext *context,
+ IdeUri *uri)
{
return g_object_new (IDE_TYPE_BACK_FORWARD_ITEM,
"context", context,
- "location", location,
+ "uri", uri,
NULL);
}
-IdeSourceLocation *
-ide_back_forward_item_get_location (IdeBackForwardItem *self)
+IdeUri *
+ide_back_forward_item_get_uri (IdeBackForwardItem *self)
{
g_return_val_if_fail (IDE_IS_BACK_FORWARD_ITEM (self), NULL);
- return self->location;
+ return self->uri;
}
static void
-ide_back_forward_item_set_location (IdeBackForwardItem *self,
- IdeSourceLocation *location)
+ide_back_forward_item_set_uri (IdeBackForwardItem *self,
+ IdeUri *uri)
{
g_return_if_fail (IDE_IS_BACK_FORWARD_ITEM (self));
- g_return_if_fail (location);
+ g_return_if_fail (uri != NULL);
- if (location != self->location)
+ if (uri != self->uri)
{
- g_clear_pointer (&self->location, ide_source_location_unref);
- self->location = ide_source_location_ref (location);
+ g_clear_pointer (&self->uri, ide_uri_unref);
+ self->uri = ide_uri_ref (uri);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_URI]);
}
}
@@ -77,7 +78,7 @@ ide_back_forward_item_finalize (GObject *object)
{
IdeBackForwardItem *self = (IdeBackForwardItem *)object;
- g_clear_pointer (&self->location, ide_source_location_unref);
+ g_clear_pointer (&self->uri, ide_uri_unref);
G_OBJECT_CLASS (ide_back_forward_item_parent_class)->finalize (object);
}
@@ -92,8 +93,8 @@ ide_back_forward_item_get_property (GObject *object,
switch (prop_id)
{
- case PROP_LOCATION:
- g_value_set_boxed (value, ide_back_forward_item_get_location (self));
+ case PROP_URI:
+ g_value_set_boxed (value, ide_back_forward_item_get_uri (self));
break;
default:
@@ -111,8 +112,8 @@ ide_back_forward_item_set_property (GObject *object,
switch (prop_id)
{
- case PROP_LOCATION:
- ide_back_forward_item_set_location (self, g_value_get_boxed (value));
+ case PROP_URI:
+ ide_back_forward_item_set_uri (self, g_value_get_boxed (value));
break;
default:
@@ -130,16 +131,21 @@ ide_back_forward_item_class_init (IdeBackForwardItemClass *klass)
object_class->set_property = ide_back_forward_item_set_property;
/**
- * IdeBackForwardItem:location:
+ * IdeBackForwardItem:uri:
*
- * The #IdeBackForwardItem:location property contains the location within
- * a source file to navigate to.
+ * The #IdeBackForwardItem:uri property contains the location for the
+ * back/forward item.
+ *
+ * This might be a uri to a file, including a line number.
+ *
+ * #IdeWorkbenchAddin can hook how these are loaded, by implementing the
+ * IdeWorkbenchAddin::can_open() vfunc and associated functions.
*/
- properties [PROP_LOCATION] =
- g_param_spec_boxed ("location",
- "Location",
+ properties [PROP_URI] =
+ g_param_spec_boxed ("uri",
+ "Uri",
"The location of the navigation item.",
- IDE_TYPE_SOURCE_LOCATION,
+ IDE_TYPE_URI,
(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
@@ -156,33 +162,43 @@ gboolean
ide_back_forward_item_chain (IdeBackForwardItem *self,
IdeBackForwardItem *other)
{
- IdeSourceLocation *loc1;
- IdeSourceLocation *loc2;
- IdeFile *file1;
- IdeFile *file2;
- gint line1;
- gint line2;
+ const gchar *tmp1;
+ const gchar *tmp2;
+ gint line1 = 0;
+ gint line2 = 0;
g_return_val_if_fail (IDE_IS_BACK_FORWARD_ITEM (self), FALSE);
g_return_val_if_fail (IDE_IS_BACK_FORWARD_ITEM (other), FALSE);
- loc1 = ide_back_forward_item_get_location (self);
- loc2 = ide_back_forward_item_get_location (other);
+ tmp1 = ide_uri_get_scheme (self->uri);
+ tmp2 = ide_uri_get_scheme (other->uri);
+ if (!ide_str_equal0 (tmp1, tmp2))
+ return FALSE;
- file1 = ide_source_location_get_file (loc1);
- file2 = ide_source_location_get_file (loc2);
+ tmp1 = ide_uri_get_host (self->uri);
+ tmp2 = ide_uri_get_host (other->uri);
+ if (!ide_str_equal0 (tmp1, tmp2))
+ return FALSE;
- if (!ide_file_equal (file1, file2))
+ tmp1 = ide_uri_get_path (self->uri);
+ tmp2 = ide_uri_get_path (other->uri);
+ if (!ide_str_equal0 (tmp1, tmp2))
return FALSE;
- line1 = ide_source_location_get_line (loc1);
- line2 = ide_source_location_get_line (loc2);
+ tmp1 = ide_uri_get_fragment (self->uri);
+ tmp2 = ide_uri_get_fragment (other->uri);
+ if ((tmp1 == NULL) || (tmp2 == NULL))
+ return FALSE;
- if (ABS (line1 - line2) <= NUM_LINES_CHAIN_MAX)
- {
- ide_back_forward_item_set_location (self, other->location);
- return TRUE;
- }
+ if ((1 != sscanf (tmp1, "L%u_", &line1)) ||
+ (1 != sscanf (tmp2, "L%u_", &line2)))
+ return FALSE;
+
+ if (line1 >= G_MAXINT || line2 >= G_MAXINT)
+ return FALSE;
+
+ if (ABS (line1 - line2) < 10)
+ return TRUE;
return FALSE;
}
diff --git a/libide/ide-back-forward-item.h b/libide/ide-back-forward-item.h
index e635f5a..4837fe3 100644
--- a/libide/ide-back-forward-item.h
+++ b/libide/ide-back-forward-item.h
@@ -20,6 +20,7 @@
#define IDE_BACK_FORWARD_ITEM_H
#include "ide-object.h"
+#include "ide-uri.h"
G_BEGIN_DECLS
@@ -27,11 +28,11 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeBackForwardItem, ide_back_forward_item, IDE, BACK_FORWARD_ITEM, IdeObject)
-IdeBackForwardItem *ide_back_forward_item_new (IdeContext *context,
- IdeSourceLocation *location);
-IdeSourceLocation *ide_back_forward_item_get_location (IdeBackForwardItem *self);
-gboolean ide_back_forward_item_chain (IdeBackForwardItem *self,
- IdeBackForwardItem *other);
+IdeBackForwardItem *ide_back_forward_item_new (IdeContext *context,
+ IdeUri *uri);
+IdeUri *ide_back_forward_item_get_uri (IdeBackForwardItem *self);
+gboolean ide_back_forward_item_chain (IdeBackForwardItem *self,
+ IdeBackForwardItem *other);
G_END_DECLS
diff --git a/libide/ide-back-forward-list-load.c b/libide/ide-back-forward-list-load.c
new file mode 100644
index 0000000..7249f97
--- /dev/null
+++ b/libide/ide-back-forward-list-load.c
@@ -0,0 +1,154 @@
+/* ide-back-forward-list-load.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ide-back-forward-item.h"
+#include "ide-back-forward-list.h"
+#include "ide-back-forward-list-private.h"
+#include "ide-context.h"
+#include "ide-debug.h"
+
+static void
+ide_back_forward_list_load_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ g_autofree gchar *contents = NULL;
+ g_auto(GStrv) lines = NULL;
+ IdeBackForwardList *self;
+ IdeContext *context;
+ GError *error = NULL;
+ GFile *file = (GFile *)object;
+ gsize length = 0;
+ gsize n_lines;
+ gint i;
+
+ g_assert (G_IS_FILE (file));
+ g_assert (G_IS_TASK (task));
+
+ self = g_task_get_source_object (task);
+ g_assert (IDE_IS_BACK_FORWARD_LIST (self));
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ g_assert (IDE_IS_CONTEXT (context));
+
+ if (!g_file_load_contents_finish (file, result, &contents, &length, NULL, &error))
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ if (length > (10 * 1024 * 1024))
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Implausible file size discovered");
+ return;
+ }
+
+ if (!g_utf8_validate (contents, length, NULL))
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "The content was not UTF-8 formatted");
+ return;
+ }
+
+ lines = g_strsplit (contents, "\n", 0);
+ n_lines = g_strv_length (lines);
+
+ for (i = n_lines; i > 0; i--)
+ {
+ const gchar *line = lines [i - 1];
+ g_autoptr(IdeUri) uri = NULL;
+ g_autoptr(IdeBackForwardItem) item = NULL;
+ g_autofree gchar *new_style_uri = NULL;
+ char *old_style_uri = NULL;
+ guint lineno = 0;
+ guint line_offset = 0;
+
+ if (ide_str_empty0 (line))
+ continue;
+
+ /* Convert from old style "LINE OFFSET URI" to new-style "URI". */
+ if (3 == sscanf (line, "%u %u %ms", &lineno, &line_offset, &old_style_uri))
+ {
+ line = new_style_uri = g_strdup_printf ("%s#L%u_%u", old_style_uri, lineno, line_offset);
+ free (old_style_uri);
+ }
+
+ uri = ide_uri_new (line, 0, &error);
+
+ if (uri == NULL)
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+
+ item = ide_back_forward_item_new (context, uri);
+ ide_back_forward_list_push (self, item);
+ }
+
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+_ide_back_forward_list_load_async (IdeBackForwardList *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_assert (IDE_IS_BACK_FORWARD_LIST (self));
+ g_assert (G_IS_FILE (file));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+#ifdef IDE_ENABLE_TRACE
+ {
+ g_autofree gchar *path = NULL;
+
+ path = g_file_get_path (file);
+ IDE_TRACE_MSG ("Loading %s", path);
+ }
+#endif
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ g_file_load_contents_async (file,
+ cancellable,
+ ide_back_forward_list_load_cb,
+ g_object_ref (task));
+}
+
+gboolean
+_ide_back_forward_list_load_finish (IdeBackForwardList *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_BACK_FORWARD_LIST (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/libide/ide-back-forward-list-private.h b/libide/ide-back-forward-list-private.h
new file mode 100644
index 0000000..0031b89
--- /dev/null
+++ b/libide/ide-back-forward-list-private.h
@@ -0,0 +1,52 @@
+/* ide-back-forward-list-private.h
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#ifndef IDE_BACK_FORWARD_LIST_PRIVATE_H
+#define IDE_BACK_FORWARD_LIST_PRIVATE_H
+
+#include <gio/gio.h>
+
+#include "ide-back-forward-list.h"
+
+G_BEGIN_DECLS
+
+void _ide_back_forward_list_foreach (IdeBackForwardList *self,
+ GFunc callback,
+ gpointer user_data);
+void _ide_back_forward_list_load_async (IdeBackForwardList *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean _ide_back_forward_list_load_finish (IdeBackForwardList *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_back_forward_list_save_async (IdeBackForwardList *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean _ide_back_forward_list_save_finish (IdeBackForwardList *self,
+ GAsyncResult *result,
+ GError **error);
+IdeBackForwardItem *_ide_back_forward_list_find (IdeBackForwardList *self,
+ IdeFile *file);
+
+G_END_DECLS
+
+#endif /* IDE_BACK_FORWARD_LIST_PRIVATE_H */
diff --git a/libide/ide-back-forward-list-save.c b/libide/ide-back-forward-list-save.c
new file mode 100644
index 0000000..476abe0
--- /dev/null
+++ b/libide/ide-back-forward-list-save.c
@@ -0,0 +1,137 @@
+/* ide-back-forward-list-save.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include "ide-back-forward-item.h"
+#include "ide-back-forward-list.h"
+#include "ide-back-forward-list-private.h"
+#include "ide-debug.h"
+
+#define MAX_ITEMS_PER_FILE 5
+
+typedef struct
+{
+ GHashTable *counter;
+ GString *content;
+} IdeBackForwardListSave;
+
+static void
+ide_back_forward_list_save_collect (gpointer data,
+ gpointer user_data)
+{
+ IdeBackForwardListSave *state = user_data;
+ IdeBackForwardItem *item = data;
+ g_autofree gchar *hash_key = NULL;
+ g_autofree gchar *str = NULL;
+ IdeUri *uri;
+ gsize count;
+
+ g_assert (IDE_IS_BACK_FORWARD_ITEM (item));
+ g_assert (state != NULL);
+ g_assert (state->content != NULL);
+ g_assert (state->counter != NULL);
+
+ uri = ide_back_forward_item_get_uri (item);
+
+ hash_key = g_strdup_printf ("%s://%s%s",
+ ide_uri_get_scheme (uri) ?: "",
+ ide_uri_get_host (uri) ?: "",
+ ide_uri_get_path (uri) ?: "");
+
+ count = GPOINTER_TO_SIZE (g_hash_table_lookup (state->counter, hash_key));
+
+ if (count == MAX_ITEMS_PER_FILE)
+ {
+ g_free (hash_key);
+ return;
+ }
+
+ g_hash_table_insert (state->counter, hash_key, GSIZE_TO_POINTER (count + 1));
+
+ str = ide_uri_to_string (uri, 0);
+ g_string_append_printf (state->content, "%s\n", str);
+}
+
+static void
+ide_back_forward_list_save_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ GFile *file = (GFile *)object;
+ GError *error = NULL;
+
+ g_assert (G_IS_FILE (file));
+ g_assert (G_IS_TASK (task));
+
+ if (!g_file_replace_contents_finish (file, result, NULL, &error))
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+_ide_back_forward_list_save_async (IdeBackForwardList *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ GString *content;
+ GBytes *bytes;
+
+ g_return_if_fail (IDE_IS_BACK_FORWARD_LIST (self));
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+#ifdef IDE_ENABLE_TRACE
+ {
+ g_autofree gchar *path = NULL;
+
+ path = g_file_get_path (file);
+ IDE_TRACE_MSG ("Saving %s", path);
+ }
+#endif
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ content = g_string_new (NULL);
+ _ide_back_forward_list_foreach (self, ide_back_forward_list_save_collect, content);
+ bytes = g_bytes_new_take (content->str, content->len + 1);
+ g_string_free (content, FALSE);
+
+ g_file_replace_contents_bytes_async (file,
+ bytes,
+ NULL,
+ FALSE,
+ G_FILE_CREATE_NONE,
+ cancellable,
+ ide_back_forward_list_save_cb,
+ g_object_ref (task));
+}
+
+gboolean
+_ide_back_forward_list_save_finish (IdeBackForwardList *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_BACK_FORWARD_LIST (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/libide/ide-back-forward-list.c b/libide/ide-back-forward-list.c
index 92ab663..94bb15b 100644
--- a/libide/ide-back-forward-list.c
+++ b/libide/ide-back-forward-list.c
@@ -33,8 +33,7 @@
#include "ide-project.h"
#include "ide-source-location.h"
-#define MAX_ITEMS_PER_FILE 5
-#define MAX_ITEMS_TOTAL 100
+#define MAX_ITEMS_TOTAL 100
struct _IdeBackForwardList
{
@@ -462,7 +461,7 @@ ide_back_forward_list_init (IdeBackForwardList *self)
self->forward = g_queue_new ();
}
-static void
+void
_ide_back_forward_list_foreach (IdeBackForwardList *self,
GFunc callback,
gpointer user_data)
@@ -487,10 +486,9 @@ find_by_file (gpointer data,
gpointer user_data)
{
IdeBackForwardItem *item = data;
- IdeSourceLocation *item_loc;
- IdeFile *item_file;
+ IdeUri *uri;
struct {
- IdeFile *file;
+ GFile *file;
IdeBackForwardItem *result;
} *lookup = user_data;
@@ -501,10 +499,11 @@ find_by_file (gpointer data,
if (lookup->result)
return;
- item_loc = ide_back_forward_item_get_location (item);
- item_file = ide_source_location_get_file (item_loc);
+ uri = ide_back_forward_item_get_uri (item);
+ if (uri == NULL)
+ return;
- if (ide_file_equal (item_file, lookup->file))
+ if (ide_uri_is_file (uri, lookup->file))
lookup->result = item;
}
@@ -526,297 +525,17 @@ _ide_back_forward_list_find (IdeBackForwardList *self,
IdeFile *file)
{
struct {
- IdeFile *file;
+ GFile *file;
IdeBackForwardItem *result;
- } lookup = { file, NULL };
+ } lookup;
g_return_val_if_fail (IDE_IS_BACK_FORWARD_LIST (self), NULL);
g_return_val_if_fail (IDE_IS_FILE (file), NULL);
+ lookup.file = ide_file_get_file (file);
+ lookup.result = NULL;
+
_ide_back_forward_list_foreach (self, find_by_file, &lookup);
return lookup.result;
}
-
-static void
-add_item_string (gpointer data,
- gpointer user_data)
-{
- IdeBackForwardItem *item = data;
- IdeSourceLocation *item_loc;
- g_autofree gchar *uri = NULL;
- IdeFile *file;
- GFile *gfile;
- struct {
- GHashTable *counts;
- GString *str;
- guint count;
- } *save_state = user_data;
- guint count;
- guint line;
- guint line_offset;
-
- g_assert (IDE_IS_BACK_FORWARD_ITEM (item));
- g_assert (save_state);
- g_assert (save_state->str);
- g_assert (save_state->counts);
-
- item_loc = ide_back_forward_item_get_location (item);
- file = ide_source_location_get_file (item_loc);
-
- count = GPOINTER_TO_INT (g_hash_table_lookup (save_state->counts, file));
- if (count >= MAX_ITEMS_PER_FILE)
- return;
-
- if (save_state->count == MAX_ITEMS_TOTAL)
- return;
-
- save_state->count++;
-
- g_hash_table_replace (save_state->counts, file, GINT_TO_POINTER (++count));
-
- line = ide_source_location_get_line (item_loc);
- line_offset = ide_source_location_get_line_offset (item_loc);
-
- gfile = ide_file_get_file (file);
- uri = g_file_get_uri (gfile);
-
- g_string_append_printf (save_state->str, "%u %u %s\n", line, line_offset, uri);
-}
-
-static void
-ide_back_forward_list__replace_contents_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GFile *file = (GFile *)object;
- g_autoptr(GTask) task = user_data;
- GError *error = NULL;
-
- g_assert (G_IS_FILE (file));
- g_assert (G_IS_TASK (task));
-
- if (!g_file_replace_contents_finish (file, result, NULL, &error))
- g_task_return_error (task, error);
- else
- g_task_return_boolean (task, TRUE);
-}
-
-void
-_ide_back_forward_list_save_async (IdeBackForwardList *self,
- GFile *file,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- g_autoptr(GTask) task = NULL;
- g_autoptr(GBytes) contents = NULL;
- struct {
- GHashTable *counts;
- GString *str;
- guint count;
- } save_state = { 0 };
- gsize len;
-
- g_assert (IDE_IS_BACK_FORWARD_LIST (self));
- g_assert (G_IS_FILE (file));
- g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-#ifdef IDE_ENABLE_TRACE
- {
- g_autofree gchar *path = NULL;
-
- path = g_file_get_path (file);
- IDE_TRACE_MSG ("Saving %s", path);
- }
-#endif
-
- task = g_task_new (self, cancellable, callback, user_data);
-
- save_state.counts = g_hash_table_new ((GHashFunc)ide_file_hash,
- (GEqualFunc)ide_file_equal);
- save_state.str = g_string_new (NULL);
- _ide_back_forward_list_foreach (self, add_item_string, &save_state);
- len = save_state.str->len;
- contents = g_bytes_new_take (g_string_free (save_state.str, FALSE), len);
- g_hash_table_destroy (save_state.counts);
-
- g_file_replace_contents_bytes_async (file, contents, NULL, FALSE,
- G_FILE_CREATE_REPLACE_DESTINATION,
- cancellable,
- ide_back_forward_list__replace_contents_cb,
- g_object_ref (task));
-}
-
-gboolean
-_ide_back_forward_list_save_finish (IdeBackForwardList *self,
- GAsyncResult *result,
- GError **error)
-{
- GTask *task = (GTask *)result;
-
- g_return_val_if_fail (IDE_IS_BACK_FORWARD_LIST (self), FALSE);
- g_return_val_if_fail (G_IS_TASK (task), FALSE);
-
- return g_task_propagate_boolean (task, error);
-}
-
-static IdeSourceLocation *
-create_source_location (IdeBackForwardList *self,
- GFile *gfile,
- guint line,
- guint line_offset)
-{
- IdeContext *context;
- IdeProject *project;
- g_autoptr(IdeFile) file = NULL;
- IdeSourceLocation *ret;
-
- g_assert (IDE_IS_BACK_FORWARD_LIST (self));
- g_assert (G_IS_FILE (gfile));
-
- context = ide_object_get_context (IDE_OBJECT (self));
- project = ide_context_get_project (context);
- file = ide_project_get_project_file (project, gfile);
-
- ret = ide_source_location_new (file, line, line_offset, 0);
-
- return ret;
-}
-
-static void
-ide_back_forward_list__load_contents_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GFile *file = (GFile *)object;
- IdeBackForwardList *self;
- g_autoptr(GTask) task = user_data;
- g_autofree gchar *contents = NULL;
- IdeContext *context;
- GError *error = NULL;
- gsize length = 0;
- gchar **lines = NULL;
- gssize line_count;
- gssize i;
-
- IDE_ENTRY;
-
- g_assert (G_IS_FILE (file));
- g_assert (G_IS_TASK (task));
-
- self = g_task_get_source_object (task);
- context = ide_object_get_context (IDE_OBJECT (self));
-
- if (!g_file_load_contents_finish (file, result, &contents, &length, NULL, &error))
- {
- g_task_return_error (task, error);
- IDE_EXIT;
- }
-
- if (!g_utf8_validate (contents, length, NULL))
- {
- g_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_INVALID_DATA,
- _("File contained invalid UTF-8"));
- IDE_EXIT;
- }
-
- lines = g_strsplit (contents, "\n", 0);
- line_count = g_strv_length (lines);
-
- for (i = line_count - 1; i >= 0; i--)
- {
- gchar **parts;
-
- g_strstrip (lines [i]);
-
- if (!lines [i][0])
- continue;
-
- parts = g_strsplit (lines [i], " ", 3);
-
- if (g_strv_length (parts) == 3)
- {
- if (g_str_is_ascii (parts [0]) && g_str_is_ascii (parts [1]))
- {
- gint64 line;
- gint64 line_offset;
-
- line = g_ascii_strtoll (parts [0], NULL, 10);
- line_offset = g_ascii_strtoll (parts [1], NULL, 10);
-
- /*
- * g_ascii_strtoll() will return G_MAXINT64/G_MININT64 and set errno to ERANGE. We
- * don't really care about anything other than it being out of range.
- */
- if ((line >= 0) && (line <= G_MAXUINT) &&
- (line_offset >= 0) && (line_offset <= G_MAXUINT))
- {
- g_autoptr(IdeSourceLocation) srcloc = NULL;
- g_autoptr(IdeBackForwardItem) item = NULL;
- g_autoptr(GFile) jump_file = NULL;
-
- jump_file = g_file_new_for_uri (parts [2]);
- srcloc = create_source_location (self, jump_file, line, line_offset);
- item = ide_back_forward_item_new (context, srcloc);
-
- ide_back_forward_list_push (self, item);
- }
- }
- }
-
- g_strfreev (parts);
- }
-
- g_strfreev (lines);
-
- g_task_return_boolean (task, TRUE);
-
- IDE_EXIT;
-}
-
-
-void
-_ide_back_forward_list_load_async (IdeBackForwardList *self,
- GFile *file,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- g_autoptr(GTask) task = NULL;
-
- g_assert (IDE_IS_BACK_FORWARD_LIST (self));
- g_assert (G_IS_FILE (file));
- g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
-
-#ifdef IDE_ENABLE_TRACE
- {
- g_autofree gchar *path = NULL;
-
- path = g_file_get_path (file);
- IDE_TRACE_MSG ("Loading %s", path);
- }
-#endif
-
- task = g_task_new (self, cancellable, callback, user_data);
-
- g_file_load_contents_async (file,
- cancellable,
- ide_back_forward_list__load_contents_cb,
- g_object_ref (task));
-}
-
-gboolean
-_ide_back_forward_list_load_finish (IdeBackForwardList *self,
- GAsyncResult *result,
- GError **error)
-{
- GTask *task = (GTask *)result;
-
- g_return_val_if_fail (IDE_IS_BACK_FORWARD_LIST (self), FALSE);
- g_return_val_if_fail (G_IS_TASK (task), FALSE);
-
- return g_task_propagate_boolean (task, error);
-}
diff --git a/libide/ide-buffer-manager.c b/libide/ide-buffer-manager.c
index 2b7d699..dafe943 100644
--- a/libide/ide-buffer-manager.c
+++ b/libide/ide-buffer-manager.c
@@ -25,6 +25,7 @@
#include "ide-back-forward-item.h"
#include "ide-back-forward-list.h"
+#include "ide-back-forward-list-private.h"
#include "ide-buffer.h"
#include "ide-buffer-manager.h"
#include "ide-context.h"
@@ -50,6 +51,7 @@ struct _IdeBufferManager
GHashTable *timeouts;
IdeBuffer *focus_buffer;
GtkSourceCompletionWords *word_completion;
+ GSettings *settings;
gsize max_file_size;
@@ -505,27 +507,31 @@ ide_buffer_manager_load_file__load_cb (GObject *object,
back_forward_list = ide_context_get_back_forward_list (context);
item = _ide_back_forward_list_find (back_forward_list, state->file);
- if (item != NULL)
+ gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (state->buffer), &iter);
+
+ if (item != NULL && g_settings_get_boolean (self->settings, "restore-insert-mark"))
{
- IdeSourceLocation *item_loc;
- guint line;
- guint line_offset;
+ const gchar *fragment;
+ IdeUri *uri;
- item_loc = ide_back_forward_item_get_location (item);
- line = ide_source_location_get_line (item_loc);
- line_offset = ide_source_location_get_line_offset (item_loc);
+ uri = ide_back_forward_item_get_uri (item);
+ fragment = ide_uri_get_fragment (uri);
- IDE_TRACE_MSG ("Restoring insert mark to %u:%u", line, line_offset);
+ if (fragment != NULL)
+ {
+ guint line = 0;
+ guint line_offset = 0;
- gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (state->buffer), &iter, line);
- for (; line_offset; line_offset--)
- if (gtk_text_iter_ends_line (&iter) || !gtk_text_iter_forward_char (&iter))
- break;
- }
- else
- {
- IDE_TRACE_MSG ("Restoring insert mark to 0:0");
- gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (state->buffer), &iter);
+ if (1 == sscanf (fragment, "L%u_%u", &line, &line_offset))
+ {
+ IDE_TRACE_MSG ("Restoring insert mark to %u:%u", line, line_offset);
+
+ gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (state->buffer), &iter, line);
+ for (; line_offset; line_offset--)
+ if (gtk_text_iter_ends_line (&iter) || !gtk_text_iter_forward_char (&iter))
+ break;
+ }
+ }
}
gtk_text_buffer_select_range (GTK_TEXT_BUFFER (state->buffer), &iter, &iter);
@@ -1192,6 +1198,7 @@ ide_buffer_manager_finalize (GObject *object)
g_clear_pointer (&self->buffers, g_ptr_array_unref);
g_clear_pointer (&self->timeouts, g_hash_table_unref);
+ g_clear_object (&self->settings);
G_OBJECT_CLASS (ide_buffer_manager_parent_class)->finalize (object);
}
@@ -1423,6 +1430,7 @@ ide_buffer_manager_init (IdeBufferManager *self)
self->max_file_size = MAX_FILE_SIZE_BYTES_DEFAULT;
self->timeouts = g_hash_table_new (g_direct_hash, g_direct_equal);
self->word_completion = gtk_source_completion_words_new (_("Words"), NULL);
+ self->settings = g_settings_new ("org.gnome.builder.editor");
}
static void
diff --git a/libide/ide-context.c b/libide/ide-context.c
index 6cb2fbe..1aef8b9 100644
--- a/libide/ide-context.c
+++ b/libide/ide-context.c
@@ -23,6 +23,7 @@
#include "ide-async-helper.h"
#include "ide-back-forward-list.h"
+#include "ide-back-forward-list-private.h"
#include "ide-buffer-manager.h"
#include "ide-buffer.h"
#include "ide-build-system.h"
diff --git a/libide/ide-internal.h b/libide/ide-internal.h
index 460ac33..432c2e0 100644
--- a/libide/ide-internal.h
+++ b/libide/ide-internal.h
@@ -33,24 +33,6 @@
G_BEGIN_DECLS
-void _ide_back_forward_list_load_async (IdeBackForwardList *self,
- GFile *file,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean _ide_back_forward_list_load_finish (IdeBackForwardList *self,
- GAsyncResult *result,
- GError **error);
-void _ide_back_forward_list_save_async (IdeBackForwardList *self,
- GFile *file,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean _ide_back_forward_list_save_finish (IdeBackForwardList *self,
- GAsyncResult *result,
- GError **error);
-IdeBackForwardItem *_ide_back_forward_list_find (IdeBackForwardList *self,
- IdeFile *file);
void _ide_battery_monitor_init (void);
void _ide_battery_monitor_shutdown (void);
void _ide_buffer_set_changed_on_volume (IdeBuffer *self,
diff --git a/libide/ide-source-view.c b/libide/ide-source-view.c
index 680e69c..50b83dd 100644
--- a/libide/ide-source-view.c
+++ b/libide/ide-source-view.c
@@ -2666,13 +2666,13 @@ ide_source_view_real_jump (IdeSourceView *self,
const GtkTextIter *location)
{
IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
- g_autoptr(IdeSourceLocation) srcloc = NULL;
- g_autoptr(IdeBackForwardItem) item = NULL;
+ IdeBackForwardItem *item;
IdeContext *context;
IdeFile *file;
+ IdeUri *uri;
+ gchar *fragment;
guint line;
guint line_offset;
- guint offset;
IDE_ENTRY;
@@ -2693,15 +2693,18 @@ ide_source_view_real_jump (IdeSourceView *self,
if (file == NULL)
IDE_EXIT;
+ uri = ide_uri_new_from_file (ide_file_get_file (file));
line = gtk_text_iter_get_line (location);
line_offset = gtk_text_iter_get_line_offset (location);
- offset = gtk_text_iter_get_offset (location);
-
- srcloc = ide_source_location_new (file, line, line_offset, offset);
- item = ide_back_forward_item_new (context, srcloc);
-
+ fragment = g_strdup_printf ("L%u_%u", line, line_offset);
+ ide_uri_set_fragment (uri, fragment);
+ item = ide_back_forward_item_new (context, uri);
ide_back_forward_list_push (priv->back_forward_list, item);
+ g_object_unref (item);
+ ide_uri_unref (uri);
+ g_free (fragment);
+
IDE_EXIT;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]