[gtksourceview/wip/loader-saver] Refactor the FileSaver to fit GtkSourceFile API



commit 1199263dab1614b152d6ffd553f239884e1bdfa9
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Dec 13 21:48:13 2013 +0100

    Refactor the FileSaver to fit GtkSourceFile API
    
    Not finished, not compilable.

 gtksourceview/gtksourcefilesaver.c |  254 ++++++++++++++----------------------
 gtksourceview/gtksourcefilesaver.h |   14 --
 2 files changed, 98 insertions(+), 170 deletions(-)
---
diff --git a/gtksourceview/gtksourcefilesaver.c b/gtksourceview/gtksourcefilesaver.c
index fe96dac..07dc732 100644
--- a/gtksourceview/gtksourcefilesaver.c
+++ b/gtksourceview/gtksourcefilesaver.c
@@ -77,15 +77,20 @@ typedef struct
 
 struct _GtkSourceFileSaverPrivate
 {
-       GFileInfo *info;
        GtkTextBuffer *buffer;
 
        GFile *location;
+       GFileInfo *info;
        const GtkSourceEncoding *encoding;
        GtkSourceNewlineType newline_type;
        GtkSourceCompressionType compression_type;
        GtkSourceFileSaveFlags flags;
 
+       GTask *task;
+
+       GFileProgressCallback progress_cb;
+       gpointer progress_cb_data;
+
        GTimeVal old_mtime;
 
        goffset size;
@@ -102,6 +107,7 @@ struct _GtkSourceFileSaverPrivate
 
        guint used : 1;
        guint ensure_trailing_newline : 1;
+       guint tried_mount : 1;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceFileSaver, gtk_source_file_saver, G_TYPE_OBJECT)
@@ -110,7 +116,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceFileSaver, gtk_source_file_saver, G_TYPE_OB
 static void read_file_chunk (AsyncData *async);
 static void write_file_chunk (AsyncData *async);
 
-static void check_modified_async (AsyncData *async);
+static void check_externally_modified (GtkSourceFileSaver *saver);
 
 static void
 gtk_source_file_saver_set_property (GObject      *object,
@@ -756,7 +762,7 @@ async_replace_ready_callback (GFile        *source,
        file_stream = g_file_replace_finish (source, res, &error);
 
        /* handle any error that might occur */
-       if (!file_stream)
+       if (file_stream == NULL)
        {
                DEBUG ({
                       g_print ("Opening file failed: %s\n", error->message);
@@ -853,34 +859,26 @@ begin_write (AsyncData *async)
 }
 
 static void
-mount_ready_callback (GFile        *file,
-                     GAsyncResult *res,
-                     AsyncData    *async)
+mount_cb (GFile              *location,
+         GAsyncResult       *result,
+         GtkSourceFileSaver *saver)
 {
        GError *error = NULL;
-       gboolean mounted;
 
        DEBUG ({
               g_print ("%s\n", G_STRFUNC);
        });
 
-       /* manual check for cancelled state */
-       if (g_cancellable_is_cancelled (async->cancellable))
-       {
-               async_data_free (async);
-               return;
-       }
-
-       mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
+       g_file_mount_enclosing_volume_finish (location, result, &error);
 
-       if (!mounted)
+       if (error != NULL)
        {
-               async_failed (async, error);
+               g_task_return_error (saver->priv->task, error);
        }
        else
        {
-               /* try again to get the modified state */
-               check_modified_async (async);
+               /* Try again to get the modified state. */
+               check_externally_modified (saver);
        }
 }
 
@@ -893,31 +891,30 @@ create_mount_operation (GtkSourceFileSaver *saver)
 }
 
 static void
-recover_not_mounted (AsyncData *async)
+recover_not_mounted (GtkSourceFileSaver *saver)
 {
-       GMountOperation *mount_operation = create_mount_operation (async->saver);
+       GMountOperation *mount_operation = create_mount_operation (saver);
 
        DEBUG ({
               g_print ("%s\n", G_STRFUNC);
        });
 
-       async->tried_mount = TRUE;
-       g_file_mount_enclosing_volume (async->saver->priv->location,
+       saver->priv->tried_mount = TRUE;
+       g_file_mount_enclosing_volume (saver->priv->location,
                                       G_MOUNT_MOUNT_NONE,
                                       mount_operation,
-                                      async->cancellable,
-                                      (GAsyncReadyCallback) mount_ready_callback,
-                                      async);
+                                      g_task_get_cancellable (saver->priv->task),
+                                      (GAsyncReadyCallback) mount_cb,
+                                      saver);
 
        g_object_unref (mount_operation);
 }
 
 static void
-check_modification_callback (GFile        *source,
-                            GAsyncResult *res,
-                            AsyncData    *async)
+check_externally_modified_cb (GFile              *location,
+                             GAsyncResult       *result,
+                             GtkSourceFileSaver *saver)
 {
-       GtkSourceFileSaver *saver;
        GError *error = NULL;
        GFileInfo *info;
 
@@ -925,37 +922,35 @@ check_modification_callback (GFile        *source,
               g_print ("%s\n", G_STRFUNC);
        });
 
-       /* manually check cancelled state */
-       if (g_cancellable_is_cancelled (async->cancellable))
+       if (saver->priv->flags & GTK_SOURCE_FILE_SAVE_IGNORE_MTIME)
        {
-               async_data_free (async);
-               return;
+               g_warning ("Useless check for externally modified file.");
        }
 
-       saver = async->saver;
-       info = g_file_query_info_finish (source, res, &error);
-       if (info == NULL)
+       info = g_file_query_info_finish (location, result, &error);
+
+       if (error != NULL)
        {
-               if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
+               if (error->code == G_IO_ERROR_NOT_MOUNTED && !saver->priv->tried_mount)
                {
-                       recover_not_mounted (async);
+                       recover_not_mounted (saver);
                        g_error_free (error);
                        return;
                }
 
-               /* it's perfectly fine if the file doesn't exist yet */
+               /* It's perfectly fine if the file doesn't exist yet. */
                if (error->code != G_IO_ERROR_NOT_FOUND)
                {
                        DEBUG ({
                               g_print ("Error getting modification: %s\n", error->message);
                        });
 
-                       async_failed (async, error);
+                       g_task_return_error (saver->priv->task, error);
                        return;
                }
        }
 
-       /* check if the mtime is > what we know about it (if we have it) */
+       /* Check if the mtime is greater from what we know about it (if we have it). */
        if (info != NULL && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
        {
                GTimeVal mtime;
@@ -972,14 +967,12 @@ check_modification_callback (GFile        *source,
                               g_print ("File is externally modified\n");
                        });
 
-                       g_set_error (&saver->priv->error,
-                                    GTK_SOURCE_FILE_ERROR,
-                                    GTK_SOURCE_FILE_ERROR_EXTERNALLY_MODIFIED,
-                                    "Externally modified");
-
-                       remote_save_completed_or_failed (saver, async);
                        g_object_unref (info);
 
+                       g_task_return_new_error (saver->priv->task,
+                                                GTK_SOURCE_FILE_ERROR,
+                                                GTK_SOURCE_FILE_ERROR_EXTERNALLY_MODIFIED,
+                                                "Externally modified");
                        return;
                }
        }
@@ -989,150 +982,99 @@ check_modification_callback (GFile        *source,
                g_object_unref (info);
        }
 
-       /* modification check passed, start write */
-       begin_write (async);
+       /* Externally modified check passed, start write. */
+       begin_write (saver);
 }
 
 static void
-check_modified_async (AsyncData *async)
+check_externally_modified (GtkSourceFileSaver *saver)
 {
        DEBUG ({
               g_print ("Check externally modified\n");
        });
 
-       g_file_query_info_async (async->saver->priv->location,
+       g_file_query_info_async (saver->priv->location,
                                 G_FILE_ATTRIBUTE_TIME_MODIFIED,
                                 G_FILE_QUERY_INFO_NONE,
-                                G_PRIORITY_HIGH,
-                                async->cancellable,
-                                (GAsyncReadyCallback) check_modification_callback,
-                                async);
+                                g_task_get_priority (saver->priv->task),
+                                g_task_get_cancellable (saver->priv->task),
+                                (GAsyncReadyCallback)check_externally_modified_cb,
+                                saver);
 }
 
-static gboolean
-save_remote_file_real (GtkSourceFileSaver *saver)
+GFile *
+gtk_source_file_saver_get_location (GtkSourceFileSaver *saver)
 {
-       AsyncData *async;
-
-       DEBUG ({
-              g_print ("Starting  save\n");
-       });
+       g_return_val_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver), NULL);
 
-       /* First find out if the file is modified externally. This requires
-        * a stat, but I don't think we can do this any other way
-        */
-       async = async_data_new (saver);
+       return g_file_dup (saver->priv->location);
+}
 
-       check_modified_async (async);
+void
+gtk_source_file_saver_set_mount_operation_factory (GtkSourceFileSaver             *saver,
+                                                  GtkSourceMountOperationFactory  callback,
+                                                  gpointer                        user_data)
+{
+       g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver));
 
-       /* return false to stop timeout */
-       return FALSE;
+       saver->priv->mount_operation_factory = callback;
+       saver->priv->mount_operation_userdata = user_data;
 }
 
 void
-gtk_source_file_saver_save (GtkSourceFileSaver *saver,
-                           GTimeVal           *old_mtime)
+gtk_source_file_saver_save_async (GtkSourceFileSaver     *saver,
+                                 gint                    io_priority,
+                                 GTimeVal               *old_mtime,
+                                 GCancellable           *cancellable,
+                                 GFileProgressCallback   progress_callback,
+                                 gpointer                progress_callback_data,
+                                 GAsyncReadyCallback     callback,
+                                 gpointer                user_data)
 {
-       DEBUG ({
-              g_print ("%s\n", G_STRFUNC);
-       });
-
        g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver));
+       g_return_if_fail (saver->priv->task == NULL);
        g_return_if_fail (saver->priv->location != NULL);
+       g_return_if_fail (!saver->priv->used);
 
-       g_return_if_fail (saver->priv->used == FALSE);
        saver->priv->used = TRUE;
 
-       /* CHECK:
-        report async (in an idle handler) or sync (bool ret)
-        async is extra work here, sync is special casing in the caller */
+       saver->priv->task = g_task_new (saver, cancellable, callback, user_data);
+       g_task_set_priority (task, io_priority);
 
        saver->priv->old_mtime = *old_mtime;
+       saver->priv->progress_cb = progress_callback;
+       saver->priv->progress_cb_data = progress_callback_data;
 
-       /* saving start */
-       gtk_source_file_saver_saving (saver, FALSE, NULL);
-
-       g_timeout_add_full (G_PRIORITY_HIGH,
-                           0,
-                           (GSourceFunc) save_remote_file_real,
-                           saver,
-                           NULL);
-}
+       DEBUG ({
+              g_print ("Starting  save\n");
+       });
 
-void
-gtk_source_file_saver_saving (GtkSourceFileSaver *saver,
-                            gboolean            completed,
-                            GError             *error)
-{
-       /* the object will be unrefed in the callback of the saving
-        * signal, so we need to prevent finalization.
+       /* TODO create a thread and use sync GIO functions for the first steps.
+        * Destroy the thread for the main step, reading the buffer and writing
+        * the file. Because the buffer must be read in the main thread.
         */
-       if (completed)
+
+       if (saver->priv->flags & GTK_SOURCE_FILE_SAVE_IGNORE_MTIME)
        {
-               g_object_ref (saver);
+               begin_write (saver);
        }
-
-       g_signal_emit (saver, signals[SAVING], 0, completed, error);
-
-       if (completed)
+       else
        {
-               if (error == NULL)
-               {
-                       DEBUG ({
-                              g_print ("save completed\n");
-                       });
-               }
-               else
-               {
-                       DEBUG ({
-                              g_print ("save failed\n");
-                       });
-               }
-
-               g_object_unref (saver);
+               /* TODO install a FileMonitor in GtkSourceFile, with an
+                * externally-modified property, or a signal.
+                */
+               check_externally_modified (saver);
        }
 }
 
-GFile *
-gtk_source_file_saver_get_location (GtkSourceFileSaver *saver)
-{
-       g_return_val_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver), NULL);
-
-       return g_file_dup (saver->priv->location);
-}
-
-/* Returns 0 if file size is unknown */
-goffset
-gtk_source_file_saver_get_file_size (GtkSourceFileSaver *saver)
-{
-       g_return_val_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver), 0);
-
-       return saver->priv->size;
-}
-
-goffset
-gtk_source_file_saver_get_bytes_written (GtkSourceFileSaver *saver)
-{
-       g_return_val_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver), 0);
-
-       return saver->priv->bytes_written;
-}
-
-GFileInfo *
-gtk_source_file_saver_get_info (GtkSourceFileSaver *saver)
+gboolean
+gtk_source_file_saver_save_finish (GtkSourceFileSaver  *saver,
+                                  GAsyncResult        *result,
+                                  GError             **error)
 {
-       g_return_val_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver), NULL);
+       g_return_val_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver), FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+       g_return_val_if_fail (g_task_is_valid (result, saver), FALSE);
 
-       return saver->priv->info;
-}
-
-void
-gtk_source_file_saver_set_mount_operation_factory (GtkSourceFileSaver             *saver,
-                                                  GtkSourceMountOperationFactory  callback,
-                                                  gpointer                        user_data)
-{
-       g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (saver));
-
-       saver->priv->mount_operation_factory = callback;
-       saver->priv->mount_operation_userdata = user_data;
+       return g_task_propagate_boolean (G_TASK (result), error);
 }
diff --git a/gtksourceview/gtksourcefilesaver.h b/gtksourceview/gtksourcefilesaver.h
index 4f69c01..0964e4d 100644
--- a/gtksourceview/gtksourcefilesaver.h
+++ b/gtksourceview/gtksourcefilesaver.h
@@ -84,22 +84,8 @@ void                  gtk_source_file_saver_saving           (GtkSourceFileSaver  *saver,
                                                                 GError              *error);
 
 G_GNUC_INTERNAL
-void                    gtk_source_file_saver_save             (GtkSourceFileSaver  *saver,
-                                                                GTimeVal            *old_mtime);
-
-G_GNUC_INTERNAL
 GFile                  *gtk_source_file_saver_get_location     (GtkSourceFileSaver  *saver);
 
-/* Returns 0 if file size is unknown */
-G_GNUC_INTERNAL
-goffset                         gtk_source_file_saver_get_file_size    (GtkSourceFileSaver  *saver);
-
-G_GNUC_INTERNAL
-goffset                         gtk_source_file_saver_get_bytes_written (GtkSourceFileSaver *saver);
-
-G_GNUC_INTERNAL
-GFileInfo              *gtk_source_file_saver_get_info         (GtkSourceFileSaver  *saver);
-
 G_GNUC_INTERNAL
 void                    gtk_source_file_saver_set_mount_operation_factory
                                                                (GtkSourceFileSaver             *saver,


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