[gedit/wip/loader-saver] Port to GtkSourceFileSaver (not finished)



commit 5e69aae1db40e4592e44a8e953b4599151aaa6cf
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Thu Jun 26 15:24:56 2014 +0200

    Port to GtkSourceFileSaver (not finished)

 gedit/gedit-document.c |  183 +++++--------------
 gedit/gedit-document.h |    4 -
 gedit/gedit-tab.c      |  479 +++++++++++++++++++++++++-----------------------
 3 files changed, 300 insertions(+), 366 deletions(-)
---
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 17aa310..0e0b256 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -49,12 +49,8 @@
 static void    gedit_document_loaded_real      (GeditDocument *doc,
                                                 const GError  *error);
 
-static void    gedit_document_save_real        (GeditDocument                *doc,
-                                                GFile                        *location,
-                                                const GeditEncoding          *encoding,
-                                                GeditDocumentNewlineType      newline_type,
-                                                GeditDocumentCompressionType  compression_type,
-                                                GeditDocumentSaveFlags        flags);
+static void    gedit_document_saved_real       (GeditDocument *doc,
+                                                const GError  *error);
 
 struct _GeditDocumentPrivate
 {
@@ -130,7 +126,6 @@ enum
        LOAD,
        LOADED,
        SAVE,
-       SAVING,
        SAVED,
        LAST_SIGNAL
 };
@@ -435,7 +430,7 @@ gedit_document_class_init (GeditDocumentClass *klass)
        buf_class->changed = gedit_document_changed;
 
        klass->loaded = gedit_document_loaded_real;
-       klass->save = gedit_document_save_real;
+       klass->saved = gedit_document_saved_real;
 
        g_object_class_install_property (object_class, PROP_LOCATION,
                                         g_param_spec_object ("location",
@@ -622,18 +617,6 @@ gedit_document_class_init (GeditDocumentClass *klass)
                              GEDIT_TYPE_DOCUMENT_COMPRESSION_TYPE,
                              GEDIT_TYPE_DOCUMENT_SAVE_FLAGS);
 
-       document_signals[SAVING] =
-               g_signal_new ("saving",
-                             G_OBJECT_CLASS_TYPE (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (GeditDocumentClass, saving),
-                             NULL, NULL,
-                             gedit_marshal_VOID__UINT64_UINT64,
-                             G_TYPE_NONE,
-                             2,
-                             G_TYPE_UINT64,
-                             G_TYPE_UINT64);
-
        document_signals[SAVED] =
                g_signal_new ("saved",
                              G_OBJECT_CLASS_TYPE (object_class),
@@ -1231,9 +1214,9 @@ gedit_document_get_readonly (GeditDocument *doc)
 }
 
 static void
-query_info_cb (GFile         *location,
-              GAsyncResult  *result,
-              GeditDocument *doc)
+loaded_query_info_cb (GFile         *location,
+                     GAsyncResult  *result,
+                     GeditDocument *doc)
 {
        GFileInfo *info;
        const gchar *content_type = NULL;
@@ -1302,7 +1285,7 @@ gedit_document_loaded_real (GeditDocument *doc,
                                 G_FILE_QUERY_INFO_NONE,
                                 G_PRIORITY_DEFAULT,
                                 NULL,
-                                (GAsyncReadyCallback) query_info_cb,
+                                (GAsyncReadyCallback) loaded_query_info_cb,
                                 doc);
 }
 
@@ -1335,133 +1318,63 @@ has_invalid_chars (GeditDocument *doc)
 }
 
 static void
-document_saver_saving (GeditDocumentSaver *saver,
-                      gboolean            completed,
-                      const GError       *error,
-                      GeditDocument      *doc)
+saved_query_info_cb (GFile         *location,
+                    GAsyncResult  *result,
+                    GeditDocument *doc)
 {
-       gedit_debug (DEBUG_DOCUMENT);
-
-       if (completed)
-       {
-               /* save was successful */
-               if (error == NULL)
-               {
-                       GFile *location;
-                       const gchar *content_type = NULL;
-                       GTimeVal mtime = {0, 0};
-                       GFileInfo *info;
-
-                       location = gedit_document_saver_get_location (saver);
-                       set_location (doc, location);
-                       g_object_unref (location);
-
-                       info = gedit_document_saver_get_info (saver);
-
-                       if (info != NULL)
-                       {
-                               if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
-                                       content_type = g_file_info_get_attribute_string (info,
-                                                                                        
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
-
-                               if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
-                                       g_file_info_get_modification_time (info, &mtime);
-                       }
-
-                       gedit_document_set_content_type (doc, content_type);
-                       doc->priv->mtime = mtime;
-
-                       g_get_current_time (&doc->priv->time_of_last_save_or_load);
+       GFileInfo *info;
+       const gchar *content_type = NULL;
+       GError *error = NULL;
 
-                       doc->priv->externally_modified = FALSE;
-                       doc->priv->deleted = FALSE;
-                       doc->priv->create = FALSE;
+       info = g_file_query_info_finish (location, result, &error);
 
-                       _gedit_document_set_readonly (doc, FALSE);
+       if (error != NULL)
+       {
+               g_warning ("Document saving: query info error: %s", error->message);
+               g_error_free (error);
+               error = NULL;
+       }
 
-                       gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc),
-                                                     FALSE);
+       if (info != NULL &&
+           g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
+       {
+               content_type = g_file_info_get_attribute_string (info, 
G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
+       }
 
-                       set_encoding (doc,
-                                     doc->priv->requested_encoding,
-                                     TRUE);
-               }
+       gedit_document_set_content_type (doc, content_type);
 
-               g_signal_emit (doc,
-                              document_signals[SAVED],
-                              0,
-                              error);
+       g_get_current_time (&doc->priv->time_of_last_save_or_load);
 
-               /* the saver has been used, throw it away */
-               g_object_unref (doc->priv->saver);
-               doc->priv->saver = NULL;
-       }
-       else
-       {
-               goffset size = 0;
-               goffset written = 0;
+       doc->priv->externally_modified = FALSE;
+       doc->priv->deleted = FALSE;
+       doc->priv->create = FALSE;
 
-               size = gedit_document_saver_get_file_size (saver);
-               written = gedit_document_saver_get_bytes_written (saver);
+       _gedit_document_set_readonly (doc, FALSE);
 
-               gedit_debug_message (DEBUG_DOCUMENT, "save progress: %" G_GINT64_FORMAT " of %" 
G_GINT64_FORMAT, written, size);
+       set_encoding (doc,
+                     gtk_source_file_get_encoding (doc->priv->file),
+                     TRUE);
 
-               g_signal_emit (doc,
-                              document_signals[SAVING],
-                              0,
-                              written,
-                              size);
-       }
+       /* Async operation finished. */
+       g_object_unref (doc);
 }
 
 static void
-gedit_document_save_real (GeditDocument                *doc,
-                         GFile                        *location,
-                         const GeditEncoding          *encoding,
-                         GeditDocumentNewlineType      newline_type,
-                         GeditDocumentCompressionType  compression_type,
-                         GeditDocumentSaveFlags        flags)
+gedit_document_saved_real (GeditDocument *doc,
+                          const GError  *error)
 {
-       g_return_if_fail (doc->priv->saver == NULL);
-
-       if (!(flags & GEDIT_DOCUMENT_SAVE_IGNORE_INVALID_CHARS) && has_invalid_chars (doc))
-       {
-               GError *error = NULL;
-
-               g_set_error_literal (&error,
-                                    GEDIT_DOCUMENT_ERROR,
-                                    GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
-                                    "The document contains invalid characters");
-
-               g_signal_emit (doc,
-                              document_signals[SAVED],
-                              0,
-                              error);
-
-               g_error_free (error);
-       }
-       else
-       {
-               /* create a saver, it will be destroyed once saving is complete */
-               doc->priv->saver = gedit_document_saver_new (doc,
-                                                            location,
-                                                            encoding,
-                                                            newline_type,
-                                                            compression_type,
-                                                            flags);
-
-               g_signal_connect (doc->priv->saver,
-                                 "saving",
-                                 G_CALLBACK (document_saver_saving),
-                                 doc);
+       GFile *location = gtk_source_file_get_location (doc->priv->file);
 
-               doc->priv->requested_encoding = encoding;
-               doc->priv->newline_type = newline_type;
-               doc->priv->compression_type = compression_type;
+       /* Keep the doc alive during the async operation. */
+       g_object_ref (doc);
 
-               gedit_document_saver_save (doc->priv->saver,
-                                          &doc->priv->mtime);
-       }
+       g_file_query_info_async (location,
+                                G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                                G_FILE_QUERY_INFO_NONE,
+                                G_PRIORITY_DEFAULT,
+                                NULL,
+                                (GAsyncReadyCallback) saved_query_info_cb,
+                                doc);
 }
 
 /*
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index 3566577..b88ec9b 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -128,10 +128,6 @@ struct _GeditDocumentClass
                                         GeditDocumentCompressionType  compression_type,
                                         GeditDocumentSaveFlags        flags);
 
-       void (* saving)                 (GeditDocument    *document,
-                                        goffset           size,
-                                        goffset           total_size);
-
        void (* saved)                  (GeditDocument    *document,
                                         const GError     *error);
 };
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index 8e65f73..a9d4f54 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -55,7 +55,8 @@ struct _GeditTabPrivate
        GeditPrintJob          *print_job;
 
        /* tmp data for saving */
-       GFile                  *tmp_save_location;
+       GtkSourceFileSaver     *saver;
+       GFile                  *tmp_save_location; /* TODO remove */
 
        /* tmp data for loading */
        GtkSourceFileLoader    *loader;
@@ -67,7 +68,8 @@ struct _GeditTabPrivate
 
        GTimer                 *timer;
 
-       GeditDocumentSaveFlags  save_flags;
+       GeditDocumentSaveFlags  save_flags; /* TODO remove */
+       GtkSourceFileSaverFlags new_save_flags;
 
        gint                    auto_save_interval;
        guint                   auto_save_timeout;
@@ -229,6 +231,12 @@ clear_loading (GeditTab *tab)
 }
 
 static void
+clear_saving (GeditTab *tab)
+{
+       g_clear_object (&tab->priv->saver);
+}
+
+static void
 gedit_tab_dispose (GObject *object)
 {
        GeditTab *tab = GEDIT_TAB (object);
@@ -244,6 +252,7 @@ gedit_tab_dispose (GObject *object)
        g_clear_object (&tab->priv->editor);
 
        clear_loading (tab);
+       clear_saving (tab);
 
        G_OBJECT_CLASS (gedit_tab_parent_class)->dispose (object);
 }
@@ -809,7 +818,7 @@ show_saving_info_bar (GeditTab *tab)
        gchar *msg = NULL;
        gint len;
 
-       g_return_if_fail (tab->priv->tmp_save_location != NULL);
+       g_return_if_fail (tab->priv->saver != NULL);
 
        if (tab->priv->info_bar != NULL)
        {
@@ -829,18 +838,17 @@ show_saving_info_bar (GeditTab *tab)
         */
        if (len > MAX_MSG_LENGTH)
        {
-               from = gedit_utils_str_middle_truncate (short_name,
-                                                       MAX_MSG_LENGTH);
+               from = gedit_utils_str_middle_truncate (short_name, MAX_MSG_LENGTH);
                g_free (short_name);
        }
        else
        {
                gchar *str;
+               GFile *location = gtk_source_file_saver_get_location (tab->priv->saver);
 
                from = short_name;
-               to = g_file_get_parse_name (tab->priv->tmp_save_location);
-               str = gedit_utils_str_middle_truncate (to,
-                                                      MAX (20, MAX_MSG_LENGTH - len));
+               to = g_file_get_parse_name (location);
+               str = gedit_utils_str_middle_truncate (to, MAX (20, MAX_MSG_LENGTH - len));
                g_free (to);
 
                to = str;
@@ -854,9 +862,7 @@ show_saving_info_bar (GeditTab *tab)
 
                /* Translators: the first %s is a file name (e.g. test.txt) the second one
                   is a directory (e.g. ssh://master.gnome.org/home/users/paolo) */
-               msg = g_strdup_printf (_("Saving %s to %s"),
-                                      from_markup,
-                                      to_markup);
+               msg = g_strdup_printf (_("Saving %s to %s"), from_markup, to_markup);
                g_free (to_markup);
        }
        else
@@ -864,9 +870,7 @@ show_saving_info_bar (GeditTab *tab)
                msg = g_strdup_printf (_("Saving %s"), from_markup);
        }
 
-       bar = gedit_progress_info_bar_new ("document-save",
-                                          msg,
-                                          FALSE);
+       bar = gedit_progress_info_bar_new ("document-save", msg, FALSE);
 
        set_info_bar (tab, bar, GTK_RESPONSE_NONE);
 
@@ -931,48 +935,6 @@ scroll_to_cursor (GeditTab *tab)
 }
 
 static void
-document_saving (GeditDocument *document,
-                goffset        size,
-                goffset        total_size,
-                GeditTab      *tab)
-{
-       gdouble elapsed_time;
-       gdouble total_time;
-       gdouble remaining_time;
-
-       g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_SAVING);
-
-       if (tab->priv->timer == NULL)
-       {
-               tab->priv->timer = g_timer_new ();
-       }
-
-       elapsed_time = g_timer_elapsed (tab->priv->timer, NULL);
-
-       /* elapsed_time / total_time = size / total_size */
-       total_time = (elapsed_time * total_size) / size;
-
-       remaining_time = total_time - elapsed_time;
-
-       /* Approximately more than 3 seconds remaining. */
-       if (remaining_time > 3.0)
-       {
-               show_saving_info_bar (tab);
-       }
-
-       info_bar_set_progress (tab, size, total_size);
-}
-
-static void
-end_saving (GeditTab *tab)
-{
-       /* Reset tmp data for saving */
-       g_clear_object (&tab->priv->tmp_save_location);
-
-       tab->priv->tmp_encoding = NULL;
-}
-
-static void
 unrecoverable_saving_error_info_bar_response (GtkWidget *info_bar,
                                              gint       response_id,
                                              GeditTab  *tab)
@@ -988,7 +950,7 @@ unrecoverable_saving_error_info_bar_response (GtkWidget *info_bar,
                gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
        }
 
-       end_saving (tab);
+       clear_saving (tab);
 
        set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
@@ -1122,124 +1084,6 @@ recoverable_saving_error_info_bar_response (GtkWidget *info_bar,
 }
 
 static void
-document_saved (GeditDocument *document,
-               const GError  *error,
-               GeditTab      *tab)
-{
-       g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_SAVING);
-
-       g_return_if_fail (tab->priv->tmp_save_location != NULL);
-       g_return_if_fail (tab->priv->tmp_encoding != NULL);
-
-       if (tab->priv->timer != NULL)
-       {
-               g_timer_destroy (tab->priv->timer);
-               tab->priv->timer = NULL;
-       }
-
-       set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
-
-       if (error != NULL)
-       {
-               GtkWidget *info_bar;
-
-               gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING_ERROR);
-
-               if (error->domain == GEDIT_DOCUMENT_ERROR &&
-                   error->code == GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED)
-               {
-                       /* This error is recoverable */
-                       info_bar = gedit_externally_modified_saving_error_info_bar_new 
(tab->priv->tmp_save_location,
-                                                                                       error);
-                       g_return_if_fail (info_bar != NULL);
-
-                       g_signal_connect (info_bar,
-                                         "response",
-                                         G_CALLBACK (externally_modified_error_info_bar_response),
-                                         tab);
-               }
-               else if (error->domain == G_IO_ERROR &&
-                        error->code == G_IO_ERROR_CANT_CREATE_BACKUP)
-               {
-                       /* This error is recoverable */
-                       info_bar = gedit_no_backup_saving_error_info_bar_new (tab->priv->tmp_save_location,
-                                                                             error);
-                       g_return_if_fail (info_bar != NULL);
-
-                       g_signal_connect (info_bar,
-                                         "response",
-                                         G_CALLBACK (no_backup_error_info_bar_response),
-                                         tab);
-               }
-               else if (error->domain == GEDIT_DOCUMENT_ERROR &&
-                        error->code == GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK)
-               {
-                       /* If we have any invalid char in the document we must warn the user
-                          as it can make the document useless if it is saved */
-                       info_bar = gedit_invalid_character_info_bar_new (tab->priv->tmp_save_location);
-                       g_return_if_fail (info_bar != NULL);
-
-                       g_signal_connect (info_bar,
-                                         "response",
-                                         G_CALLBACK (invalid_character_info_bar_response),
-                                         tab);
-               }
-               else if (error->domain == GEDIT_DOCUMENT_ERROR ||
-                        (error->domain == G_IO_ERROR &&
-                         error->code != G_IO_ERROR_INVALID_DATA &&
-                         error->code != G_IO_ERROR_PARTIAL_INPUT))
-               {
-                       /* These errors are _NOT_ recoverable */
-                       gedit_recent_remove_if_local (tab->priv->tmp_save_location);
-
-                       info_bar = gedit_unrecoverable_saving_error_info_bar_new 
(tab->priv->tmp_save_location,
-                                                                                 error);
-                       g_return_if_fail (info_bar != NULL);
-
-                       g_signal_connect (info_bar,
-                                         "response",
-                                         G_CALLBACK (unrecoverable_saving_error_info_bar_response),
-                                         tab);
-               }
-               else
-               {
-                       /* This error is recoverable */
-                       g_return_if_fail (error->domain == G_CONVERT_ERROR ||
-                                         error->domain == G_IO_ERROR);
-
-                       info_bar = gedit_conversion_error_while_saving_info_bar_new 
(tab->priv->tmp_save_location,
-                                                                                    tab->priv->tmp_encoding,
-                                                                                    error);
-                       g_return_if_fail (info_bar != NULL);
-
-                       g_signal_connect (info_bar,
-                                         "response",
-                                         G_CALLBACK (recoverable_saving_error_info_bar_response),
-                                         tab);
-               }
-
-               set_info_bar (tab, info_bar, GTK_RESPONSE_CANCEL);
-       }
-       else
-       {
-               gedit_recent_add_document (document);
-
-               if (tab->priv->print_preview != NULL)
-               {
-                       gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
-               }
-               else
-               {
-                       gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
-               }
-
-               tab->priv->ask_if_externally_modified = TRUE;
-
-               end_saving (tab);
-       }
-}
-
-static void
 externally_modified_notification_info_bar_response (GtkWidget *info_bar,
                                                    gint       response_id,
                                                    GeditTab  *tab)
@@ -1447,16 +1291,6 @@ gedit_tab_init (GeditTab *tab)
                          G_CALLBACK (document_modified_changed),
                          tab);
 
-       g_signal_connect (doc,
-                         "saving",
-                         G_CALLBACK (document_saving),
-                         tab);
-
-       g_signal_connect (doc,
-                         "saved",
-                         G_CALLBACK (document_saved),
-                         tab);
-
        view = gedit_tab_get_view (tab);
 
        g_signal_connect_after (view,
@@ -1758,9 +1592,9 @@ gedit_tab_get_from_document (GeditDocument *doc)
 }
 
 static void
-progress_cb (goffset   size,
-            goffset   total_size,
-            GeditTab *tab)
+loader_progress_cb (goffset   size,
+                   goffset   total_size,
+                   GeditTab *tab)
 {
        gdouble elapsed_time;
        gdouble total_time;
@@ -1854,6 +1688,7 @@ load_cb (GtkSourceFileLoader *loader,
 
        if (error != NULL)
        {
+               /* TODO remove when no longer needed. */
                g_warning ("File loading error: %s", error->message);
        }
 
@@ -2106,7 +1941,7 @@ load (GeditTab                *tab,
        gtk_source_file_loader_load_async (tab->priv->loader,
                                           G_PRIORITY_DEFAULT,
                                           tab->priv->cancellable,
-                                          (GFileProgressCallback) progress_cb,
+                                          (GFileProgressCallback) loader_progress_cb,
                                           tab,
                                           NULL,
                                           (GAsyncReadyCallback) load_cb,
@@ -2210,43 +2045,233 @@ _gedit_tab_revert (GeditTab *tab)
        load (tab, NULL, 0, 0);
 }
 
+static void
+saver_progress_cb (goffset   size,
+                  goffset   total_size,
+                  GeditTab *tab)
+{
+       gdouble elapsed_time;
+       gdouble total_time;
+       gdouble remaining_time;
+
+       g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_SAVING);
+
+       if (tab->priv->timer == NULL)
+       {
+               tab->priv->timer = g_timer_new ();
+       }
+
+       elapsed_time = g_timer_elapsed (tab->priv->timer, NULL);
+
+       /* elapsed_time / total_time = size / total_size */
+       total_time = (elapsed_time * total_size) / size;
+
+       remaining_time = total_time - elapsed_time;
+
+       /* Approximately more than 3 seconds remaining. */
+       if (remaining_time > 3.0)
+       {
+               show_saving_info_bar (tab);
+       }
+
+       info_bar_set_progress (tab, size, total_size);
+}
+
+static void
+save_cb (GtkSourceFileSaver *saver,
+        GAsyncResult       *result,
+        GeditTab           *tab)
+{
+       GeditDocument *doc = gedit_tab_get_document (tab);
+       GFile *location = gtk_source_file_saver_get_location (saver);
+       GError *error = NULL;
+
+       g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_SAVING);
+
+       gtk_source_file_saver_save_finish (saver, result, &error);
+
+       if (error != NULL)
+       {
+               /* TODO remove when no longer needed. */
+               g_warning ("File saving error: %s", error->message);
+       }
+
+       if (tab->priv->timer != NULL)
+       {
+               g_timer_destroy (tab->priv->timer);
+               tab->priv->timer = NULL;
+       }
+
+       set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
+
+       if (error != NULL)
+       {
+               GtkWidget *info_bar;
+
+               gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING_ERROR);
+
+               if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
+                   error->code == GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED)
+               {
+                       /* This error is recoverable */
+                       info_bar = gedit_externally_modified_saving_error_info_bar_new (location, error);
+                       g_return_if_fail (info_bar != NULL);
+
+                       g_signal_connect (info_bar,
+                                         "response",
+                                         G_CALLBACK (externally_modified_error_info_bar_response),
+                                         tab);
+               }
+               else if (error->domain == G_IO_ERROR &&
+                        error->code == G_IO_ERROR_CANT_CREATE_BACKUP)
+               {
+                       /* This error is recoverable */
+                       info_bar = gedit_no_backup_saving_error_info_bar_new (location, error);
+                       g_return_if_fail (info_bar != NULL);
+
+                       g_signal_connect (info_bar,
+                                         "response",
+                                         G_CALLBACK (no_backup_error_info_bar_response),
+                                         tab);
+               }
+               else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR &&
+                        error->code == GTK_SOURCE_FILE_SAVER_ERROR_INVALID_CHARS)
+               {
+                       /* If we have any invalid char in the document we must warn the user
+                        * as it can make the document useless if it is saved.
+                        */
+                       info_bar = gedit_invalid_character_info_bar_new (location);
+                       g_return_if_fail (info_bar != NULL);
+
+                       g_signal_connect (info_bar,
+                                         "response",
+                                         G_CALLBACK (invalid_character_info_bar_response),
+                                         tab);
+               }
+               else if (error->domain == GTK_SOURCE_FILE_SAVER_ERROR ||
+                        (error->domain == G_IO_ERROR &&
+                         error->code != G_IO_ERROR_INVALID_DATA &&
+                         error->code != G_IO_ERROR_PARTIAL_INPUT))
+               {
+                       /* These errors are _NOT_ recoverable */
+                       gedit_recent_remove_if_local (location);
+
+                       info_bar = gedit_unrecoverable_saving_error_info_bar_new (location, error);
+                       g_return_if_fail (info_bar != NULL);
+
+                       g_signal_connect (info_bar,
+                                         "response",
+                                         G_CALLBACK (unrecoverable_saving_error_info_bar_response),
+                                         tab);
+               }
+               else
+               {
+                       const GtkSourceEncoding *encoding;
+
+                       /* This error is recoverable */
+                       g_return_if_fail (error->domain == G_CONVERT_ERROR ||
+                                         error->domain == G_IO_ERROR);
+
+                       encoding = gtk_source_file_saver_get_encoding (saver);
+
+                       info_bar = gedit_conversion_error_while_saving_info_bar_new (location, encoding, 
error);
+                       g_return_if_fail (info_bar != NULL);
+
+                       g_signal_connect (info_bar,
+                                         "response",
+                                         G_CALLBACK (recoverable_saving_error_info_bar_response),
+                                         tab);
+               }
+
+               set_info_bar (tab, info_bar, GTK_RESPONSE_CANCEL);
+       }
+       else
+       {
+               gedit_recent_add_document (doc);
+
+               if (tab->priv->print_preview != NULL)
+               {
+                       gedit_tab_set_state (tab, GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
+               }
+               else
+               {
+                       gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
+               }
+
+               tab->priv->ask_if_externally_modified = TRUE;
+
+               clear_saving (tab);
+
+               g_signal_emit_by_name (doc, "saved", NULL);
+       }
+
+       /* Async operation finished. */
+       g_object_unref (tab);
+
+       if (error != NULL)
+       {
+               g_error_free (error);
+       }
+}
+
+static void
+save (GeditTab *tab)
+{
+       g_return_if_fail (GTK_SOURCE_IS_FILE_SAVER (tab->priv->saver));
+
+       gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
+
+       /* Keep the tab alive during the async operation. */
+       g_object_ref (tab);
+
+       gtk_source_file_saver_save_async (tab->priv->saver,
+                                         G_PRIORITY_DEFAULT,
+                                         NULL, /* TODO add a cancellable */
+                                         (GFileProgressCallback) saver_progress_cb,
+                                         tab,
+                                         NULL,
+                                         (GAsyncReadyCallback) save_cb,
+                                         tab);
+}
+
 void
 _gedit_tab_save (GeditTab *tab)
 {
        GeditDocument *doc;
-       GeditDocumentSaveFlags save_flags;
+       GtkSourceFile *file;
+       GFile *location;
+       GtkSourceFileSaverFlags save_flags = tab->priv->new_save_flags;
 
        g_return_if_fail (GEDIT_IS_TAB (tab));
        g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL ||
                          tab->priv->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION ||
                          tab->priv->state == GEDIT_TAB_STATE_SHOWING_PRINT_PREVIEW);
-       g_return_if_fail (tab->priv->tmp_save_location == NULL);
-       g_return_if_fail (tab->priv->tmp_encoding == NULL);
 
        doc = gedit_tab_get_document (tab);
        g_return_if_fail (!gedit_document_is_untitled (doc));
 
        if (tab->priv->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
        {
-               /* We already told the user about the external
-                * modification: hide the message bar and set
-                * the save flag.
+               /* We already told the user about the external modification:
+                * hide the message bar and set the save flag.
                 */
                set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
-               save_flags = tab->priv->save_flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME;
+               save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
        }
-       else
+
+       file = gedit_document_get_file (doc);
+       location = gtk_source_file_get_location (file);
+
+       if (tab->priv->saver != NULL)
        {
-               save_flags = tab->priv->save_flags;
+               g_warning ("GeditTab: file saver already exists.");
+               g_object_unref (tab->priv->saver);
        }
 
-       gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
-
-       /* location used in error messages, will be freed in document_saved */
-       tab->priv->tmp_save_location = gedit_document_get_location (doc);
-       tab->priv->tmp_encoding = gedit_document_get_encoding (doc);
+       tab->priv->saver = gtk_source_file_saver_new (file, location);
+       gtk_source_file_saver_set_flags (tab->priv->saver, save_flags);
 
-       _gedit_document_save (doc, save_flags);
+       save (tab);
 }
 
 static gboolean
@@ -2303,6 +2328,7 @@ gedit_tab_auto_save (GeditTab *tab)
        return G_SOURCE_REMOVE;
 }
 
+/* TODO port to GtkSourceNewlineType and GtkSourceCompressionType */
 void
 _gedit_tab_save_as (GeditTab                     *tab,
                    GFile                        *location,
@@ -2311,7 +2337,8 @@ _gedit_tab_save_as (GeditTab                     *tab,
                    GeditDocumentCompressionType  compression_type)
 {
        GeditDocument *doc;
-       GeditDocumentSaveFlags save_flags;
+       GtkSourceFile *file;
+       GtkSourceFileSaverFlags save_flags;
 
        g_return_if_fail (GEDIT_IS_TAB (tab));
        g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL ||
@@ -2320,41 +2347,39 @@ _gedit_tab_save_as (GeditTab                     *tab,
        g_return_if_fail (G_IS_FILE (location));
        g_return_if_fail (encoding != NULL);
 
-       g_return_if_fail (tab->priv->tmp_save_location == NULL);
-       g_return_if_fail (tab->priv->tmp_encoding == NULL);
-
        doc = gedit_tab_get_document (tab);
 
        /* reset the save flags, when saving as */
-       tab->priv->save_flags = 0;
+       tab->priv->new_save_flags = GTK_SOURCE_FILE_SAVER_FLAGS_NONE;
+       save_flags = tab->priv->new_save_flags;
 
        if (tab->priv->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)
        {
-               /* We already told the user about the external
-                * modification: hide the message bar and set
-                * the save flag.
+               /* We already told the user about the external modification:
+                * hide the message bar and set the save flag.
                 */
                set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
-               save_flags = tab->priv->save_flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME;
+               save_flags |= GTK_SOURCE_FILE_SAVER_FLAGS_IGNORE_MODIFICATION_TIME;
        }
-       else
+
+       gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
+
+       file = gedit_document_get_file (doc);
+
+       if (tab->priv->saver != NULL)
        {
-               save_flags = tab->priv->save_flags;
+               g_warning ("GeditTab: file saver already exists.");
+               g_object_unref (tab->priv->saver);
        }
 
-       gedit_tab_set_state (tab, GEDIT_TAB_STATE_SAVING);
+       tab->priv->saver = gtk_source_file_saver_new (file, location);
+
+       gtk_source_file_saver_set_encoding (tab->priv->saver, encoding);
+       gtk_source_file_saver_set_newline_type (tab->priv->saver, newline_type);
+       gtk_source_file_saver_set_compression_type (tab->priv->saver, compression_type);
+       gtk_source_file_saver_set_flags (tab->priv->saver, save_flags);
 
-       /* location used in error messages... dup because errors are async
-        * and the location can go away. Will be freed in document_saved. */
-       tab->priv->tmp_save_location = g_file_dup (location);
-       tab->priv->tmp_encoding = encoding;
-
-       _gedit_document_save_as (doc,
-                                location,
-                                encoding,
-                                newline_type,
-                                compression_type,
-                                save_flags);
+       save (tab);
 }
 
 #define GEDIT_PAGE_SETUP_KEY "gedit-page-setup-key"


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