[gnome-builder] libide: restore previously loaded files when loading context



commit 9ea4b3bbb9e596888db0bc1f2c6b2842fda64c4e
Author: Christian Hergert <christian hergert me>
Date:   Fri Apr 24 15:52:21 2015 -0700

    libide: restore previously loaded files when loading context
    
    This will restore any of the previously loaded files when restoring the
    context.
    
       ** I'm sorry if this causes a bunch of files to open on you **
       ** initially, since we failed to prune them in the past.    **
    
    Once you close them (and wait a few seconds for the reclamation to
    happen), they shouldn't come back.
    
    If it gets really annoying, and you want to have a clean slate, just
    remove everything in ~/.local/share/gnome-builder/drafts/

 libide/ide-buffer-manager.c  |   15 ++++-
 libide/ide-buffer-manager.h  |    1 +
 libide/ide-buffer.c          |    2 +-
 libide/ide-context.c         |  130 +++++++++++++++++++++++++++++++++++++++++-
 libide/ide-context.h         |    7 ++
 libide/ide-internal.h        |    1 +
 src/app/gb-application.c     |    3 -
 src/workbench/gb-workbench.c |   30 ++++++++++
 8 files changed, 180 insertions(+), 9 deletions(-)
---
diff --git a/libide/ide-buffer-manager.c b/libide/ide-buffer-manager.c
index a2fc2e5..81e3cf0 100644
--- a/libide/ide-buffer-manager.c
+++ b/libide/ide-buffer-manager.c
@@ -430,6 +430,8 @@ ide_buffer_manager_load_file__load_cb (GObject      *object,
   g_assert (IDE_IS_BUFFER (state->buffer));
   g_assert (IDE_IS_PROGRESS (state->progress));
 
+  context = ide_object_get_context (IDE_OBJECT (self));
+
   if (!gtk_source_file_loader_load_finish (loader, result, &error))
     {
       /*
@@ -462,7 +464,6 @@ ide_buffer_manager_load_file__load_cb (GObject      *object,
    * If we have a navigation item for this buffer, restore the insert mark to
    * the most recent navigation point.
    */
-  context = ide_object_get_context (IDE_OBJECT (self));
   back_forward_list = ide_context_get_back_forward_list (context);
   item = _ide_back_forward_list_find (back_forward_list, state->file);
 
@@ -508,7 +509,9 @@ ide_buffer_manager_load_file__load_cb (GObject      *object,
 emit_signal:
   _ide_buffer_set_loading (state->buffer, FALSE);
 
-  ide_buffer_manager_set_focus_buffer (self, state->buffer);
+  if (!_ide_context_is_restoring (context))
+    ide_buffer_manager_set_focus_buffer (self, state->buffer);
+
   g_signal_emit (self, gSignals [BUFFER_LOADED], 0, state->buffer);
 
   g_task_return_pointer (task, g_object_ref (state->buffer), g_object_unref);
@@ -1595,3 +1598,11 @@ _ide_buffer_manager_reclaim (IdeBufferManager *self,
 
   IDE_EXIT;
 }
+
+guint
+ide_buffer_manager_get_n_buffers (IdeBufferManager *self)
+{
+  g_return_val_if_fail (IDE_IS_BUFFER_MANAGER (self), 0);
+
+  return self->buffers->len;
+}
diff --git a/libide/ide-buffer-manager.h b/libide/ide-buffer-manager.h
index a309e78..1393f04 100644
--- a/libide/ide-buffer-manager.h
+++ b/libide/ide-buffer-manager.h
@@ -56,6 +56,7 @@ void                      ide_buffer_manager_set_focus_buffer    (IdeBufferManag
                                                                   IdeBuffer            *buffer);
 GPtrArray                *ide_buffer_manager_get_buffers         (IdeBufferManager     *self);
 GtkSourceCompletionWords *ide_buffer_manager_get_word_completion (IdeBufferManager     *self);
+guint                     ide_buffer_manager_get_n_buffers       (IdeBufferManager     *self);
 gboolean                  ide_buffer_manager_has_file            (IdeBufferManager     *self,
                                                                   IdeFile              *file);
 IdeBuffer                *ide_buffer_manager_find_buffer         (IdeBufferManager     *self,
diff --git a/libide/ide-buffer.c b/libide/ide-buffer.c
index 51b8b25..037fafb 100644
--- a/libide/ide-buffer.c
+++ b/libide/ide-buffer.c
@@ -43,7 +43,7 @@
 
 #define DEFAULT_DIAGNOSE_TIMEOUT_MSEC          333
 #define DEFAULT_DIAGNOSE_CONSERVE_TIMEOUT_MSEC 5000
-#define RECLAIMATION_TIMEOUT_SECS              5
+#define RECLAIMATION_TIMEOUT_SECS              1
 
 #define TAG_ERROR   "diagnostician::error"
 #define TAG_WARNING "diagnostician::warning"
diff --git a/libide/ide-context.c b/libide/ide-context.c
index ea02650..3470062 100644
--- a/libide/ide-context.c
+++ b/libide/ide-context.c
@@ -39,6 +39,7 @@
 #include "ide-search-provider.h"
 #include "ide-service.h"
 #include "ide-source-snippets-manager.h"
+#include "ide-unsaved-file.h"
 #include "ide-unsaved-files.h"
 #include "ide-vcs.h"
 
@@ -62,6 +63,8 @@ struct _IdeContext
   IdeVcs                   *vcs;
 
   guint                     services_started : 1;
+  guint                     restored : 1;
+  guint                     restoring : 1;
 };
 
 static void async_initable_init (GAsyncInitableIface *);
@@ -1333,14 +1336,12 @@ ide_context_init_async (GAsyncInitable      *initable,
                         ide_context_init_files,
                         ide_context_init_project_name,
                         ide_context_init_back_forward_list,
-                        ide_context_init_unsaved_files,
                         ide_context_init_search_engine,
                         ide_context_init_snippets,
                         ide_context_init_scripts,
+                        ide_context_init_unsaved_files,
                         ide_context_init_add_recent,
                         NULL);
-
-  /* TODO: Restore buffer state? */
 }
 
 static gboolean
@@ -1590,3 +1591,126 @@ ide_context_unload_finish (IdeContext    *self,
 
   IDE_RETURN (ret);
 }
+
+static gboolean restore_in_idle (gpointer user_data);
+
+static void
+ide_context_restore__load_file_cb (GObject      *object,
+                                   GAsyncResult *result,
+                                   gpointer      user_data)
+{
+  IdeBufferManager *buffer_manager = (IdeBufferManager *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
+  g_assert (G_IS_TASK (task));
+
+  if (!ide_buffer_manager_load_file_finish (buffer_manager, result, &error))
+    {
+      g_warning ("%s", error->message);
+      /* TODO: add error into grouped error */
+    }
+
+  g_idle_add (restore_in_idle, g_object_ref (task));
+}
+
+static gboolean
+restore_in_idle (gpointer user_data)
+{
+  g_autoptr(IdeFile) ifile = NULL;
+  g_autoptr(GTask) task = user_data;
+  IdeUnsavedFile *uf;
+  IdeContext *self;
+  GPtrArray *ar;
+  GFile *file;
+
+  g_assert (G_IS_TASK (task));
+
+  self = g_task_get_source_object (task);
+  ar = g_task_get_task_data (task);
+
+  if (ar == NULL || ar->len == 0)
+    {
+      self->restoring = FALSE;
+      g_task_return_boolean (task, TRUE);
+      return G_SOURCE_REMOVE;
+    }
+
+  g_assert (ar != NULL);
+  g_assert_cmpint (ar->len, >, 0);
+
+  uf = g_ptr_array_index (ar, ar->len - 1);
+  file = ide_unsaved_file_get_file (uf);
+  ifile = ide_project_get_project_file (self->project, file);
+  g_ptr_array_remove_index (ar, ar->len - 1);
+
+  ide_buffer_manager_load_file_async (self->buffer_manager,
+                                      ifile,
+                                      FALSE,
+                                      NULL,
+                                      g_task_get_cancellable (task),
+                                      ide_context_restore__load_file_cb,
+                                      g_object_ref (task));
+
+  return G_SOURCE_REMOVE;
+}
+
+void
+ide_context_restore_async (IdeContext          *self,
+                           GCancellable        *cancellable,
+                           GAsyncReadyCallback  callback,
+                           gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(GPtrArray) ar = NULL;
+
+  g_return_if_fail (IDE_IS_CONTEXT (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  if (self->restored)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_FAILED,
+                               _("Context has already been restored."));
+      return;
+    }
+
+  self->restored = TRUE;
+
+  ar = ide_unsaved_files_to_array (self->unsaved_files);
+
+  if (ar->len == 0)
+    {
+      g_task_return_boolean (task, TRUE);
+      return;
+    }
+
+  self->restoring = TRUE;
+
+  g_task_set_task_data (task, g_ptr_array_ref (ar), (GDestroyNotify)g_ptr_array_unref);
+
+  g_idle_add (restore_in_idle, g_object_ref (task));
+}
+
+gboolean
+ide_context_restore_finish (IdeContext    *self,
+                            GAsyncResult  *result,
+                            GError       **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_CONTEXT (self), FALSE);
+  g_return_val_if_fail (G_IS_TASK (task), FALSE);
+
+  return g_task_propagate_boolean (task, error);
+}
+
+gboolean
+_ide_context_is_restoring (IdeContext *self)
+{
+  return self->restoring;
+}
diff --git a/libide/ide-context.h b/libide/ide-context.h
index 0e5d3be..3988347 100644
--- a/libide/ide-context.h
+++ b/libide/ide-context.h
@@ -60,6 +60,13 @@ IdeContext               *ide_context_new_finish            (GAsyncResult
                                                              GError              **error);
 void                      ide_context_set_root_build_dir    (IdeContext           *self,
                                                              const gchar          *root_build_dir);
+void                      ide_context_restore_async         (IdeContext           *self,
+                                                             GCancellable         *cancellable,
+                                                             GAsyncReadyCallback   callback,
+                                                             gpointer              user_data);
+gboolean                  ide_context_restore_finish        (IdeContext           *self,
+                                                             GAsyncResult         *result,
+                                                             GError              **error);
 
 G_END_DECLS
 
diff --git a/libide/ide-internal.h b/libide/ide-internal.h
index dbff757..5f82588 100644
--- a/libide/ide-internal.h
+++ b/libide/ide-internal.h
@@ -64,6 +64,7 @@ void                _ide_buffer_manager_reclaim        (IdeBufferManager      *s
                                                         IdeBuffer             *buffer);
 void                _ide_build_system_set_project_file (IdeBuildSystem        *self,
                                                         GFile                 *project_file);
+gboolean            _ide_context_is_restoring          (IdeContext            *self);
 void                _ide_diagnostic_add_range          (IdeDiagnostic         *self,
                                                         IdeSourceRange        *range);
 IdeDiagnostic      *_ide_diagnostic_new                (IdeDiagnosticSeverity  severity,
diff --git a/src/app/gb-application.c b/src/app/gb-application.c
index abce31f..8f85aae 100644
--- a/src/app/gb-application.c
+++ b/src/app/gb-application.c
@@ -280,9 +280,6 @@ gb_application__context_new_cb (GObject      *object,
                             "context", context,
                             NULL);
 
-  if (ar->len == 0)
-    gb_workbench_add_temporary_buffer (workbench);
-
   for (i = 0; i < ar->len; i++)
     {
       GFile *file;
diff --git a/src/workbench/gb-workbench.c b/src/workbench/gb-workbench.c
index 71782b8..53a5a5a 100644
--- a/src/workbench/gb-workbench.c
+++ b/src/workbench/gb-workbench.c
@@ -79,6 +79,31 @@ gb_workbench__project_notify_name_cb (GbWorkbench *self,
 }
 
 static void
+gb_workbench__context_restore_cb (GObject      *object,
+                                  GAsyncResult *result,
+                                  gpointer      user_data)
+{
+  IdeContext *context = (IdeContext *)object;
+  g_autoptr(GbWorkbench) self = user_data;
+  g_autoptr(GError) error = NULL;
+  IdeBufferManager *buffer_manager;
+
+  g_assert (GB_IS_WORKBENCH (self));
+  g_assert (IDE_IS_CONTEXT (context));
+
+  if (!ide_context_restore_finish (context, result, &error))
+    {
+      g_warning ("%s", error->message);
+    }
+
+  buffer_manager = ide_context_get_buffer_manager (context);
+  if (ide_buffer_manager_get_n_buffers (buffer_manager) == 0)
+    gb_workbench_add_temporary_buffer (self);
+
+  gtk_widget_grab_focus (GTK_WIDGET (self->editor_workspace));
+}
+
+static void
 gb_workbench_connect_context (GbWorkbench *self,
                               IdeContext  *context)
 {
@@ -96,6 +121,11 @@ gb_workbench_connect_context (GbWorkbench *self,
                              self,
                              G_CONNECT_SWAPPED);
   gb_workbench__project_notify_name_cb (self, NULL, project);
+
+  ide_context_restore_async (context,
+                             NULL,
+                             gb_workbench__context_restore_cb,
+                             g_object_ref (self));
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]