[gedit/wip/loader-saver: 4/4] Adapter between GtkSourceFile and file saving gedit API



commit ea8205e060d606adaacfdad5f48ffbfdd6062fa7
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sat Apr 5 19:11:44 2014 +0200

    Adapter between GtkSourceFile and file saving gedit API

 gedit/gedit-document.c   |  326 +++++++++++++++++++++++++++++++---------------
 gedit/gedit-document.h   |   14 +--
 gedit/gedit-settings.h   |    1 +
 gedit/gedit-view-frame.c |    3 +-
 4 files changed, 228 insertions(+), 116 deletions(-)
---
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 8d230c2..14d98f7 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -5,6 +5,7 @@
  * Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
  * Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
  * Copyright (C) 2002-2005 Paolo Maggi
+ * Copyright (C) 2014 Sébastien Wilmet
  *
  * 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
@@ -35,7 +36,6 @@
 #include "gedit-debug.h"
 #include "gedit-utils.h"
 #include "gedit-document-loader.h"
-#include "gedit-document-saver.h"
 #include "gedit-marshal.h"
 #include "gedit-enum-types.h"
 
@@ -69,6 +69,7 @@ static void   gedit_document_load_real        (GeditDocument                *doc,
                                                 gint                          line_pos,
                                                 gint                          column_pos,
                                                 gboolean                      create);
+
 static void    gedit_document_save_real        (GeditDocument                *doc,
                                                 GFile                        *location,
                                                 const GeditEncoding          *encoding,
@@ -111,13 +112,13 @@ struct _GeditDocumentPrivate
        gint                 requested_column_pos;
 
        /* Saving stuff */
-       GeditDocumentSaver *saver;
+       GtkSourceFile *source_file;
 
        GtkTextTag *error_tag;
 
        /* Mount operation factory */
-       GeditMountOperationFactory  mount_operation_factory;
-       gpointer                    mount_operation_userdata;
+       GtkSourceMountOperationFactory mount_operation_factory;
+       gpointer                       mount_operation_userdata;
 
        guint readonly : 1;
        guint externally_modified : 1;
@@ -1328,8 +1329,8 @@ document_loader_loaded (GeditDocumentLoader *loader,
 
                g_get_current_time (&doc->priv->time_of_last_save_or_load);
 
-               doc->priv->externally_modified = FALSE;
-               doc->priv->deleted = FALSE;
+               doc->priv->externally_modified = FALSE;
+               doc->priv->deleted = FALSE;
 
                set_encoding (doc,
                              gedit_document_loader_get_encoding (loader),
@@ -1601,84 +1602,197 @@ has_invalid_chars (GeditDocument *doc)
        return FALSE;
 }
 
-static void
-document_saver_saving (GeditDocumentSaver *saver,
-                      gboolean            completed,
-                      const GError       *error,
-                      GeditDocument      *doc)
+static GtkSourceNewlineType
+convert_newline_type (GeditDocumentNewlineType gedit_newline_type)
 {
-       gedit_debug (DEBUG_DOCUMENT);
+       switch (gedit_newline_type)
+       {
+               case GEDIT_DOCUMENT_NEWLINE_TYPE_LF:
+                       return GTK_SOURCE_NEWLINE_TYPE_LF;
 
-       if (completed)
+               case GEDIT_DOCUMENT_NEWLINE_TYPE_CR:
+                       return GTK_SOURCE_NEWLINE_TYPE_CR;
+
+               case GEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
+                       return GTK_SOURCE_NEWLINE_TYPE_CR_LF;
+       }
+
+       g_return_val_if_reached (GTK_SOURCE_NEWLINE_TYPE_LF);
+}
+
+static GtkSourceCompressionType
+convert_compression_type (GeditDocumentCompressionType gedit_compression_type)
+{
+       switch (gedit_compression_type)
+       {
+               case GEDIT_DOCUMENT_COMPRESSION_TYPE_NONE:
+                       return GTK_SOURCE_COMPRESSION_TYPE_NONE;
+
+               case GEDIT_DOCUMENT_COMPRESSION_TYPE_GZIP:
+                       return GTK_SOURCE_COMPRESSION_TYPE_GZIP;
+       }
+
+       g_return_val_if_reached (GTK_SOURCE_COMPRESSION_TYPE_NONE);
+}
+
+static GtkSourceFileSaveFlags
+convert_save_flags (GeditDocumentSaveFlags gedit_flags)
+{
+       GtkSourceFileSaveFlags source_flags = 0;
+
+       if (gedit_flags & GEDIT_DOCUMENT_SAVE_IGNORE_MTIME)
+       {
+               source_flags |= GTK_SOURCE_FILE_SAVE_IGNORE_MTIME;
+       }
+
+       if (gedit_flags & GEDIT_DOCUMENT_SAVE_IGNORE_INVALID_CHARS)
        {
-               /* save was successful */
-               if (error == NULL)
+               source_flags |= GTK_SOURCE_FILE_SAVE_IGNORE_INVALID_CHARS;
+       }
+
+       if ((gedit_flags & GEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP) == 0 &&
+           (gedit_flags & GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP) == 0)
+       {
+               source_flags |= GTK_SOURCE_FILE_SAVE_CREATE_BACKUP;
+       }
+
+       return source_flags;
+}
+
+static GError *
+convert_error (GError *error)
+{
+       GError *new_error = NULL;
+
+       if (error == NULL)
+       {
+               return NULL;
+       }
+
+       new_error = g_error_copy (error);
+
+       if (error->domain == GTK_SOURCE_FILE_ERROR)
+       {
+               switch (error->code)
                {
-                       GFile *location;
-                       const gchar *content_type = NULL;
-                       GTimeVal mtime = {0, 0};
-                       GFileInfo *info;
+                       case GTK_SOURCE_FILE_ERROR_EXTERNALLY_MODIFIED:
+                               new_error->code = GEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED;
+                               break;
 
-                       location = gedit_document_saver_get_location (saver);
-                       set_location (doc, location);
-                       g_object_unref (location);
+                       case GTK_SOURCE_FILE_ERROR_TOO_BIG:
+                               new_error->code = GEDIT_DOCUMENT_ERROR_TOO_BIG;
+                               break;
 
-                       info = gedit_document_saver_get_info (saver);
+                       case GTK_SOURCE_FILE_ERROR_ENCODING_AUTO_DETECTION_FAILED:
+                               new_error->code = GEDIT_DOCUMENT_ERROR_ENCODING_AUTO_DETECTION_FAILED;
+                               break;
 
-                       if (info != NULL)
+                       case GTK_SOURCE_FILE_ERROR_CONVERSION_FALLBACK:
+                               new_error->code = GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK;
+                               break;
+
+                       default:
+                               g_return_val_if_reached (new_error);
+                               break;
+               }
+
+               new_error->domain = GEDIT_DOCUMENT_ERROR;
+       }
+
+       return new_error;
+}
+
+static void
+save_progress_cb (goffset        current_position,
+                 goffset        total_size,
+                 GeditDocument *doc)
+{
+       g_signal_emit (doc,
+                      document_signals[SAVING],
+                      0,
+                      current_position,
+                      total_size);
+}
+
+static void
+saved_cb (GtkSourceFile *source_file,
+         GAsyncResult  *result,
+         GeditDocument *doc)
+{
+       GError *error = NULL;
+       GError *converted_error = NULL;
+
+       gtk_source_file_save_finish (source_file, result, &error);
+
+       /* save was successful */
+       if (error == NULL)
+       {
+               GFile *location;
+               const gchar *content_type = NULL;
+               GTimeVal mtime = {0, 0};
+               GFileInfo *info;
+
+               location = gtk_source_file_get_location (source_file);
+               set_location (doc, location);
+
+               /* Use sync function as a temporary solution. Ideally this code
+                * should be placed in GtkSourceView (and use async version).
+                */
+               info = g_file_query_info (location,
+                                         G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+                                         G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                                         G_FILE_QUERY_INFO_NONE,
+                                         NULL,
+                                         NULL);
+
+               if (info != NULL)
+               {
+                       if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE))
                        {
-                               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);
+                               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);
+                       if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+                       {
+                               g_file_info_get_modification_time (info, &mtime);
                        }
 
-                       set_content_type (doc, content_type);
-                       doc->priv->mtime = mtime;
+                       g_object_unref (info);
+               }
 
-                       g_get_current_time (&doc->priv->time_of_last_save_or_load);
+               set_content_type (doc, content_type);
+               doc->priv->mtime = mtime;
 
-                       doc->priv->externally_modified = FALSE;
-                       doc->priv->deleted = FALSE;
-                       doc->priv->create = FALSE;
+               g_get_current_time (&doc->priv->time_of_last_save_or_load);
 
-                       _gedit_document_set_readonly (doc, FALSE);
+               doc->priv->externally_modified = FALSE;
+               doc->priv->deleted = FALSE;
 
-                       gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc),
-                                                     FALSE);
+               _gedit_document_set_readonly (doc, FALSE);
 
-                       set_encoding (doc,
-                                     doc->priv->requested_encoding,
-                                     TRUE);
-               }
+               gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc), FALSE);
 
-               g_signal_emit (doc,
-                              document_signals[SAVED],
-                              0,
-                              error);
+               set_encoding (doc,
+                             gtk_source_file_get_encoding (source_file),
+                             TRUE);
 
-               /* the saver has been used, throw it away */
-               g_object_unref (doc->priv->saver);
-               doc->priv->saver = NULL;
+               g_object_unref (location);
        }
-       else
-       {
-               goffset size = 0;
-               goffset written = 0;
-
-               size = gedit_document_saver_get_file_size (saver);
-               written = gedit_document_saver_get_bytes_written (saver);
 
-               gedit_debug_message (DEBUG_DOCUMENT, "save progress: %" G_GINT64_FORMAT " of %" 
G_GINT64_FORMAT, written, size);
+       converted_error = convert_error (error);
 
-               g_signal_emit (doc,
-                              document_signals[SAVING],
-                              0,
-                              written,
-                              size);
+       if (error != NULL)
+       {
+               g_error_free (error);
        }
+
+       g_signal_emit (doc,
+                      document_signals[SAVED],
+                      0,
+                      converted_error);
+
+       /* the saver has been used, throw it away */
+       g_clear_object (&doc->priv->source_file);
 }
 
 static void
@@ -1689,7 +1803,9 @@ gedit_document_save_real (GeditDocument                *doc,
                          GeditDocumentCompressionType  compression_type,
                          GeditDocumentSaveFlags        flags)
 {
-       g_return_if_fail (doc->priv->saver == NULL);
+       gboolean ensure_trailing_newline;
+
+       g_return_if_fail (doc->priv->source_file == NULL);
 
        if (!(flags & GEDIT_DOCUMENT_SAVE_IGNORE_INVALID_CHARS) && has_invalid_chars (doc))
        {
@@ -1706,29 +1822,50 @@ gedit_document_save_real (GeditDocument                *doc,
                               error);
 
                g_error_free (error);
+               return;
        }
-       else
+
+       /* Do not make backups for remote files so they do not clutter
+        * remote systems. */
+       if (!gedit_document_is_local (doc) ||
+           !g_settings_get_boolean (doc->priv->editor_settings,
+                                    GEDIT_SETTINGS_CREATE_BACKUP_COPY))
        {
-               /* 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);
+               flags |= GEDIT_DOCUMENT_SAVE_IGNORE_BACKUP;
+       }
 
-               g_signal_connect (doc->priv->saver,
-                                 "saving",
-                                 G_CALLBACK (document_saver_saving),
-                                 doc);
+       doc->priv->newline_type = newline_type;
+       doc->priv->compression_type = compression_type;
 
-               doc->priv->requested_encoding = encoding;
-               doc->priv->newline_type = newline_type;
-               doc->priv->compression_type = compression_type;
+       /* Create source file, it will be destroyed when the saving is finished. */
+       doc->priv->source_file = gtk_source_file_new (location, GTK_SOURCE_BUFFER (doc));
 
-               gedit_document_saver_save (doc->priv->saver,
-                                          &doc->priv->mtime);
-       }
+       gtk_source_file_set_encoding (doc->priv->source_file,
+                                     (const GtkSourceEncoding *)encoding);
+
+       gtk_source_file_set_newline_type (doc->priv->source_file,
+                                         convert_newline_type (newline_type));
+
+       gtk_source_file_set_compression_type (doc->priv->source_file,
+                                             convert_compression_type (compression_type));
+
+       ensure_trailing_newline = g_settings_get_boolean (doc->priv->editor_settings,
+                                                         GEDIT_SETTINGS_ENSURE_TRAILING_NEWLINE);
+
+       gtk_source_file_set_ensure_trailing_newline (doc->priv->source_file, ensure_trailing_newline);
+
+       gtk_source_file_set_mount_operation_factory (doc->priv->source_file,
+                                                    doc->priv->mount_operation_factory,
+                                                    doc->priv->mount_operation_userdata);
+
+       gtk_source_file_save_async (doc->priv->source_file,
+                                   convert_save_flags (flags),
+                                   G_PRIORITY_HIGH,
+                                   NULL,
+                                   (GFileProgressCallback) save_progress_cb,
+                                   doc,
+                                   (GAsyncReadyCallback) saved_cb,
+                                   doc);
 }
 
 /**
@@ -1776,20 +1913,10 @@ gedit_document_save_as (GeditDocument                *doc,
                        GeditDocumentCompressionType  compression_type,
                        GeditDocumentSaveFlags        flags)
 {
-       GError *error = NULL;
-
        g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
        g_return_if_fail (G_IS_FILE (location));
        g_return_if_fail (encoding != NULL);
 
-       if (has_invalid_chars (doc))
-       {
-               g_set_error_literal (&error,
-                                    GEDIT_DOCUMENT_ERROR,
-                                    GEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
-                                    "The document contains invalid chars");
-       }
-
        /* priv->mtime refers to the the old location (if any). Thus, it should be
         * ignored when saving as. */
        g_signal_emit (doc,
@@ -1799,13 +1926,7 @@ gedit_document_save_as (GeditDocument                *doc,
                       encoding,
                       newline_type,
                       compression_type,
-                      flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME,
-                      error);
-
-       if (error != NULL)
-       {
-               g_error_free (error);
-       }
+                      flags | GEDIT_DOCUMENT_SAVE_IGNORE_MTIME);
 }
 
 gboolean
@@ -2232,9 +2353,9 @@ gedit_document_get_compression_type (GeditDocument *doc)
 }
 
 void
-_gedit_document_set_mount_operation_factory (GeditDocument            *doc,
-                                           GeditMountOperationFactory  callback,
-                                           gpointer                    userdata)
+_gedit_document_set_mount_operation_factory (GeditDocument                  *doc,
+                                            GtkSourceMountOperationFactory  callback,
+                                            gpointer                        userdata)
 {
        g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
 
@@ -2253,8 +2374,7 @@ _gedit_document_create_mount_operation (GeditDocument *doc)
        }
        else
        {
-               return doc->priv->mount_operation_factory (doc,
-                                                          doc->priv->mount_operation_userdata);
+               return doc->priv->mount_operation_factory (doc->priv->mount_operation_userdata);
        }
 }
 
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index 1a0bef6..d41698d 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -279,18 +279,10 @@ gboolean  _gedit_document_check_externally_modified
 
 gboolean        _gedit_document_needs_saving   (GeditDocument       *doc);
 
-/**
- * GeditMountOperationFactory: (skip)
- * @doc:
- * @userdata:
- */
-typedef GMountOperation *(*GeditMountOperationFactory)(GeditDocument *doc,
-                                                      gpointer       userdata);
-
 void            _gedit_document_set_mount_operation_factory
-                                               (GeditDocument              *doc,
-                                                GeditMountOperationFactory  callback,
-                                                gpointer                    userdata);
+                                               (GeditDocument                  *doc,
+                                                GtkSourceMountOperationFactory  callback,
+                                                gpointer                        userdata);
 GMountOperation
                *_gedit_document_create_mount_operation
                                                (GeditDocument       *doc);
diff --git a/gedit/gedit-settings.h b/gedit/gedit-settings.h
index cb9bedc..39ee82e 100644
--- a/gedit/gedit-settings.h
+++ b/gedit/gedit-settings.h
@@ -109,6 +109,7 @@ void                         gedit_settings_set_list                        (GSettings    
 *settings,
 #define GEDIT_SETTINGS_ENCODING_AUTO_DETECTED          "auto-detected"
 #define GEDIT_SETTINGS_ENCODING_SHOWN_IN_MENU          "shown-in-menu"
 #define GEDIT_SETTINGS_ACTIVE_PLUGINS                  "active-plugins"
+#define GEDIT_SETTINGS_ENSURE_TRAILING_NEWLINE         "ensure-trailing-newline"
 
 /* window state keys */
 #define GEDIT_SETTINGS_WINDOW_STATE                    "state"
diff --git a/gedit/gedit-view-frame.c b/gedit/gedit-view-frame.c
index 02f3b41..075302e 100644
--- a/gedit/gedit-view-frame.c
+++ b/gedit/gedit-view-frame.c
@@ -1449,8 +1449,7 @@ gedit_view_frame_class_init (GeditViewFrameClass *klass)
 }
 
 static GMountOperation *
-view_frame_mount_operation_factory (GeditDocument *doc,
-                                   gpointer       user_data)
+view_frame_mount_operation_factory (gpointer user_data)
 {
        GtkWidget *frame = user_data;
        GtkWidget *window = gtk_widget_get_toplevel (frame);


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