[gnome-builder] buffers: move auto-save into IdeBuffer



commit e965af7e148454f20b90eb662efe7cd9e877eb70
Author: Christian Hergert <chergert redhat com>
Date:   Sun Jun 17 22:14:37 2018 -0700

    buffers: move auto-save into IdeBuffer
    
    It's a bit easier to track this from IdeBuffer, including state
    management.

 src/libide/buffers/ide-buffer-manager.c | 178 +++-----------------------------
 src/libide/buffers/ide-buffer-private.h |   3 +
 src/libide/buffers/ide-buffer.c         |  64 ++++++++++++
 3 files changed, 84 insertions(+), 161 deletions(-)
---
diff --git a/src/libide/buffers/ide-buffer-manager.c b/src/libide/buffers/ide-buffer-manager.c
index 39a521f08..fb5cad90d 100644
--- a/src/libide/buffers/ide-buffer-manager.c
+++ b/src/libide/buffers/ide-buffer-manager.c
@@ -65,13 +65,6 @@ struct _IdeBufferManager
   guint                     auto_save : 1;
 };
 
-typedef struct
-{
-  IdeBufferManager *self;
-  IdeBuffer        *buffer;
-  guint             source_id;
-} AutoSave;
-
 typedef struct
 {
   IdeBuffer            *buffer;
@@ -131,11 +124,6 @@ enum {
   LAST_SIGNAL
 };
 
-static void register_auto_save   (IdeBufferManager *self,
-                                  IdeBuffer        *buffer);
-static void unregister_auto_save (IdeBufferManager *self,
-                                  IdeBuffer        *buffer);
-
 static GParamSpec *properties [LAST_PROP];
 static guint signals [LAST_SIGNAL];
 
@@ -237,8 +225,14 @@ ide_buffer_manager_set_auto_save_timeout (IdeBufferManager *self,
   if (self->auto_save_timeout != auto_save_timeout)
     {
       self->auto_save_timeout = auto_save_timeout;
-      g_object_notify_by_pspec (G_OBJECT (self),
-                                properties [PROP_AUTO_SAVE_TIMEOUT]);
+
+      for (guint i = 0; i < self->buffers->len; i++)
+        {
+          IdeBuffer *buffer = g_ptr_array_index (self->buffers, i);
+          _ide_buffer_set_auto_save (buffer, self->auto_save, auto_save_timeout);
+        }
+
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_AUTO_SAVE_TIMEOUT]);
     }
 }
 
@@ -282,24 +276,16 @@ ide_buffer_manager_set_auto_save (IdeBufferManager *self,
 
   if (self->auto_save != auto_save)
     {
-      gsize i;
-
       self->auto_save = auto_save;
 
-      for (i = 0; i < self->buffers->len; i++)
+      for (guint i = 0; i < self->buffers->len; i++)
         {
-          IdeBuffer *buffer;
-
-          buffer = g_ptr_array_index (self->buffers, i);
+          IdeBuffer *buffer = g_ptr_array_index (self->buffers, i);
 
-          if (auto_save)
-            register_auto_save (self, buffer);
-          else
-            unregister_auto_save (self, buffer);
+          _ide_buffer_set_auto_save (buffer, auto_save, self->auto_save_timeout);
         }
 
-      g_object_notify_by_pspec (G_OBJECT (self),
-                                properties [PROP_AUTO_SAVE]);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_AUTO_SAVE]);
     }
 }
 
@@ -346,81 +332,6 @@ ide_buffer_manager_set_focus_buffer (IdeBufferManager *self,
     }
 }
 
-static gboolean
-ide_buffer_manager_auto_save_cb (gpointer data)
-{
-  AutoSave *state = data;
-  gboolean saved = FALSE;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (state != NULL);
-  g_assert (IDE_IS_BUFFER_MANAGER (state->self));
-  g_assert (IDE_IS_BUFFER (state->buffer));
-  g_assert (state->source_id > 0);
-
-  if (!ide_buffer_get_changed_on_volume (state->buffer))
-    {
-      IdeFile *file = ide_buffer_get_file (state->buffer);
-
-      if (file != NULL)
-        {
-          ide_buffer_manager_save_file_async (state->self,
-                                              state->buffer,
-                                              file,
-                                              NULL,
-                                              NULL,
-                                              NULL,
-                                              NULL);
-          saved = TRUE;
-        }
-    }
-
-  if (!saved)
-    unregister_auto_save (state->self, state->buffer);
-
-  return G_SOURCE_REMOVE;
-}
-
-
-static void
-ide_buffer_manager_buffer_changed (IdeBufferManager *self,
-                                   IdeBuffer        *buffer)
-{
-  g_return_if_fail (IDE_IS_MAIN_THREAD ());
-  g_return_if_fail (IDE_IS_BUFFER_MANAGER (self));
-  g_return_if_fail (IDE_IS_BUFFER (buffer));
-
-  if (self->auto_save)
-    {
-      unregister_auto_save (self, buffer);
-      register_auto_save (self, buffer);
-    }
-}
-
-static void
-ide_buffer_manager_track_buffer (IdeBufferManager *self,
-                                 IdeBuffer        *buffer)
-{
-  IDE_ENTRY;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (IDE_IS_BUFFER_MANAGER (self));
-  g_assert (IDE_IS_BUFFER (buffer));
-
-  if (self->auto_save)
-    register_auto_save (self, buffer);
-
-  g_signal_connect_object (buffer,
-                           "changed",
-                           G_CALLBACK (ide_buffer_manager_buffer_changed),
-                           self,
-                           (G_CONNECT_SWAPPED | G_CONNECT_AFTER));
-
-  g_list_model_items_changed (G_LIST_MODEL (self), self->buffers->len - 1, 0, 1);
-
-  IDE_EXIT;
-}
-
 static void
 ide_buffer_manager_save_cursor_position (IdeBufferManager *self,
                                          IdeBuffer        *buffer)
@@ -491,12 +402,6 @@ found:
   /* Stealing ownership from self->buffers */
   g_ptr_array_remove_index (self->buffers, position);
 
-  unregister_auto_save (self, buffer);
-
-  g_signal_handlers_disconnect_by_func (buffer,
-                                        G_CALLBACK (ide_buffer_manager_buffer_changed),
-                                        self);
-
   /*
    * Notify anything that needs a pointer to the buffer to cleanup,
    * such as language server clients.
@@ -584,6 +489,7 @@ ide_buffer_manager_load_file__load_cb (GObject      *object,
     {
       g_ptr_array_add (self->buffers, g_object_ref (state->buffer));
       DZL_COUNTER_INC (registered);
+      g_list_model_items_changed (G_LIST_MODEL (self), self->buffers->len - 1, 0, 1);
     }
 
   if (!gtk_source_file_loader_load_finish (loader, result, &error))
@@ -606,9 +512,6 @@ ide_buffer_manager_load_file__load_cb (GObject      *object,
 
   gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (state->buffer), FALSE);
 
-  if (state->is_new)
-    ide_buffer_manager_track_buffer (self, state->buffer);
-
   /* try to restore the insertion cursor */
   if (g_settings_get_boolean (self->settings, "restore-insert-mark"))
     gtk_text_buffer_get_iter_at_line_offset (GTK_TEXT_BUFFER (state->buffer), &iter,
@@ -641,6 +544,8 @@ ide_buffer_manager_load_file__load_cb (GObject      *object,
   if (!_ide_context_is_restoring (context))
     ide_buffer_manager_set_focus_buffer (self, state->buffer);
 
+  _ide_buffer_set_auto_save (state->buffer, self->auto_save, self->auto_save_timeout);
+
   g_signal_emit (self, signals [BUFFER_LOADED], 0, state->buffer);
 
   ide_task_return_pointer (task, g_object_ref (state->buffer), g_object_unref);
@@ -1251,7 +1156,7 @@ ide_buffer_manager_save_file_async (IdeBufferManager     *self,
         }
 
       ide_task_return_boolean (task, TRUE);
-      IDE_GOTO (unmodified);
+      IDE_EXIT;
     }
 
   context = ide_object_get_context (IDE_OBJECT (self));
@@ -1279,9 +1184,6 @@ ide_buffer_manager_save_file_async (IdeBufferManager     *self,
                                 ide_buffer_manager_save_file__load_settings_cb,
                                 g_object_ref (task));
 
-unmodified:
-  unregister_auto_save (self, buffer);
-
   IDE_EXIT;
 }
 
@@ -1747,52 +1649,6 @@ ide_buffer_manager_init (IdeBufferManager *self)
   g_settings_bind (self->settings, "auto-save-timeout", self, "auto-save-timeout", G_SETTINGS_BIND_GET);
 }
 
-static void
-register_auto_save (IdeBufferManager *self,
-                    IdeBuffer        *buffer)
-{
-  g_return_if_fail (IDE_IS_MAIN_THREAD ());
-  g_return_if_fail (IDE_IS_BUFFER_MANAGER (self));
-  g_return_if_fail (IDE_IS_BUFFER (buffer));
-  g_return_if_fail (!g_hash_table_lookup (self->timeouts, buffer));
-  g_return_if_fail (self->auto_save_timeout > 0);
-
-  if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (buffer)))
-    {
-      AutoSave *state;
-
-      state = g_slice_new0 (AutoSave);
-      dzl_set_weak_pointer (&state->buffer, buffer);
-      dzl_set_weak_pointer (&state->self, self);
-      state->source_id = g_timeout_add_seconds (self->auto_save_timeout,
-                                                ide_buffer_manager_auto_save_cb,
-                                                state);
-      g_hash_table_insert (self->timeouts, buffer, state);
-    }
-}
-
-static void
-unregister_auto_save (IdeBufferManager *self,
-                      IdeBuffer        *buffer)
-{
-  AutoSave *state;
-
-  g_assert (IDE_IS_MAIN_THREAD ());
-  g_assert (IDE_IS_BUFFER_MANAGER (self));
-  g_assert (IDE_IS_BUFFER (buffer));
-
-  state = g_hash_table_lookup (self->timeouts, buffer);
-
-  if (state != NULL)
-    {
-      g_hash_table_remove (self->timeouts, buffer);
-      dzl_clear_source (&state->source_id);
-      dzl_clear_weak_pointer (&state->buffer);
-      dzl_clear_weak_pointer (&state->self);
-      g_slice_free (AutoSave, state);
-    }
-}
-
 /**
  * ide_buffer_manager_get_buffers:
  *
@@ -1974,7 +1830,7 @@ ide_buffer_manager_create_temporary_buffer (IdeBufferManager *self)
 
   g_ptr_array_add (self->buffers, g_object_ref (buffer));
   DZL_COUNTER_INC (registered);
-  ide_buffer_manager_track_buffer (self, buffer);
+  g_list_model_items_changed (G_LIST_MODEL (self), self->buffers->len - 1, 0, 1);
 
   g_signal_emit (self, signals [BUFFER_LOADED], 0, buffer);
 
diff --git a/src/libide/buffers/ide-buffer-private.h b/src/libide/buffers/ide-buffer-private.h
index 9412ad905..32d5d7475 100644
--- a/src/libide/buffers/ide-buffer-private.h
+++ b/src/libide/buffers/ide-buffer-private.h
@@ -41,6 +41,9 @@ void                _ide_buffer_set_read_only         (IdeBuffer        *buffer,
 void                _ide_buffer_set_failure           (IdeBuffer        *self,
                                                        const GError     *error);
 IdeHighlightEngine *_ide_buffer_get_highlight_engine  (IdeBuffer        *self);
+void                _ide_buffer_set_auto_save         (IdeBuffer        *self,
+                                                       gboolean          auto_save,
+                                                       guint             auto_save_timeout);
 void                _ide_buffer_manager_reclaim       (IdeBufferManager *self,
                                                        IdeBuffer        *buffer);
 IdeUnsavedFile     *_ide_unsaved_file_new             (GFile            *file,
diff --git a/src/libide/buffers/ide-buffer.c b/src/libide/buffers/ide-buffer.c
index 5448a13af..af395b3ed 100644
--- a/src/libide/buffers/ide-buffer.c
+++ b/src/libide/buffers/ide-buffer.c
@@ -107,8 +107,12 @@ typedef struct
 
   guint                   settling_handler;
 
+  guint                   auto_save_handler;
+  guint                   auto_save_timeout;
+
   gsize                   change_count;
 
+  guint                   auto_save : 1;
   guint                   cancel_cursor_restore : 1;
   guint                   changed_on_volume : 1;
   guint                   highlight_diagnostics : 1;
@@ -169,6 +173,46 @@ lookup_symbol_task_data_free (LookUpSymbolData *data)
   g_slice_free (LookUpSymbolData, data);
 }
 
+static gboolean
+ide_buffer_auto_save_cb (IdeBuffer *self)
+{
+  IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
+  IdeBufferManager *bufmgr;
+  IdeFile *file;
+
+  g_assert (IDE_IS_BUFFER (self));
+
+  priv->auto_save_handler = 0;
+
+  if (priv->context == NULL)
+    return G_SOURCE_REMOVE;
+
+  bufmgr = ide_context_get_buffer_manager (priv->context);
+  file = ide_buffer_get_file (self);
+
+  ide_buffer_manager_save_file_async (bufmgr, self, file, NULL, NULL, NULL, NULL);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+ide_buffer_queue_auto_save (IdeBuffer *self)
+{
+  IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
+
+  g_assert (IDE_IS_BUFFER (self));
+
+  dzl_clear_source (&priv->auto_save_handler);
+
+  if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (self)))
+    priv->auto_save_handler =
+      gdk_threads_add_timeout_seconds_full (G_PRIORITY_DEFAULT,
+                                            priv->auto_save_timeout,
+                                            (GSourceFunc)ide_buffer_auto_save_cb,
+                                            g_object_ref (self),
+                                            g_object_unref);
+}
+
 static void
 lookup_symbol_get_extension (IdeExtensionSetAdapter *set,
                              PeasPluginInfo         *plugin_info,
@@ -198,6 +242,8 @@ ide_buffer_settled_cb (gpointer user_data)
   priv->settling_handler = 0;
   g_signal_emit (self, signals [CHANGE_SETTLED], 0);
 
+  ide_buffer_queue_auto_save (self);
+
   return G_SOURCE_REMOVE;
 }
 
@@ -1495,6 +1541,7 @@ ide_buffer_dispose (GObject *object)
 
   ide_buffer_set_diagnostics (self, NULL);
 
+  dzl_clear_source (&priv->auto_save_handler);
   dzl_clear_source (&priv->settling_handler);
   dzl_clear_source (&priv->reclamation_handler);
   dzl_clear_source (&priv->check_modified_timeout);
@@ -1889,6 +1936,7 @@ ide_buffer_init (IdeBuffer *self)
 
   priv->loading = TRUE;
   priv->highlight_diagnostics = TRUE;
+  priv->auto_save_timeout = 60;
 
   priv->file_signals = dzl_signal_group_new (IDE_TYPE_FILE);
   dzl_signal_group_connect_object (priv->file_signals,
@@ -3354,3 +3402,19 @@ _ide_buffer_get_highlight_engine (IdeBuffer *self)
 
   return priv->highlight_engine;
 }
+
+void
+_ide_buffer_set_auto_save (IdeBuffer *self,
+                           gboolean   auto_save,
+                           guint      auto_save_timeout)
+{
+  IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_BUFFER (self));
+  g_return_if_fail (auto_save_timeout > 0);
+
+  priv->auto_save = !!auto_save;
+  priv->auto_save_timeout = auto_save_timeout;
+
+  ide_buffer_queue_auto_save (self);
+}


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