[gedit/wip/loader-saver: 2/2] Port GeditTab and GeditDocument to GtkSourceFile (not finished)



commit 3e70458d08c0977ff570f63981c07ee6bdbb3395
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Thu Jun 12 23:11:04 2014 +0200

    Port GeditTab and GeditDocument to GtkSourceFile (not finished)

 gedit/gedit-document.c |  288 ++++++++++++++++++++++++++++++++++++++++++++++++
 gedit/gedit-document.h |   17 +++
 gedit/gedit-tab.c      |  127 +++++++++++++---------
 3 files changed, 382 insertions(+), 50 deletions(-)
---
diff --git a/gedit/gedit-document.c b/gedit/gedit-document.c
index 1630871..f822d82 100644
--- a/gedit/gedit-document.c
+++ b/gedit/gedit-document.c
@@ -134,6 +134,13 @@ struct _GeditDocumentPrivate
        guint empty_search : 1;
 };
 
+typedef struct
+{
+       gint line_pos;
+       gint column_pos;
+       guint create : 1;
+} TaskData;
+
 enum {
        PROP_0,
 
@@ -2621,4 +2628,285 @@ gedit_document_get_file (GeditDocument *doc)
        return doc->priv->file;
 }
 
+static TaskData *
+task_data_new (void)
+{
+       return g_slice_new (TaskData);
+}
+
+static void
+task_data_free (TaskData *data)
+{
+       if (data != NULL)
+       {
+               g_slice_free (TaskData, data);
+       }
+}
+
+static void
+load_succeeded (GTask *task)
+{
+       GeditDocument *doc = g_task_get_source_object (task);
+       TaskData *data = g_task_get_task_data (task);
+
+       g_get_current_time (&doc->priv->time_of_last_save_or_load);
+
+       doc->priv->externally_modified = FALSE;
+       doc->priv->deleted = FALSE;
+
+       /* move the cursor at the requested line if any */
+       if (data->line_pos > 0)
+       {
+               gedit_document_goto_line_offset (doc,
+                                                data->line_pos - 1,
+                                                data->column_pos < 1 ? 0 : data->column_pos - 1);
+       }
+       else
+       {
+               GtkTextIter iter;
+
+               /* if enabled, move to the position stored in the metadata */
+               if (g_settings_get_boolean (doc->priv->editor_settings, 
GEDIT_SETTINGS_RESTORE_CURSOR_POSITION))
+               {
+                       gchar *pos;
+                       gint offset;
+
+                       pos = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_POSITION);
+
+                       offset = pos ? atoi (pos) : 0;
+                       g_free (pos);
+
+                       gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc),
+                                                           &iter,
+                                                           MAX (offset, 0));
+
+                       /* make sure it's a valid position, if the file
+                        * changed we may have ended up in the middle of
+                        * a utf8 character cluster */
+                       if (!gtk_text_iter_is_cursor_position (&iter))
+                       {
+                               gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc),
+                                                               &iter);
+                       }
+               }
+
+               /* otherwise to the top */
+               else
+               {
+                       gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (doc),
+                                                       &iter);
+               }
+
+               gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc), &iter);
+       }
+
+       if (!doc->priv->language_set_by_user)
+       {
+               GtkSourceLanguage *language = guess_language (doc, doc->priv->content_type);
+
+               gedit_debug_message (DEBUG_DOCUMENT, "Language: %s",
+                                    language != NULL ? gtk_source_language_get_name (language) : "None");
+
+               set_language (doc, language, FALSE);
+       }
+
+       g_task_return_boolean (task, TRUE);
+       g_object_unref (task);
+}
+
+static void
+query_info_cb (GFile        *location,
+              GAsyncResult *result,
+              GTask        *task)
+{
+       GFileInfo *info;
+       GeditDocument *doc = g_task_get_source_object (task);
+       const gchar *content_type = NULL;
+       gboolean read_only = FALSE;
+       GError *error = NULL;
+
+       info = g_file_query_info_finish (location, result, &error);
+
+       if (error != NULL)
+       {
+               g_warning ("Query file info error: %s", error->message);
+               g_error_free (error);
+               error = NULL;
+       }
+
+       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_ACCESS_CAN_WRITE))
+               {
+                       read_only = !g_file_info_get_attribute_boolean (info, 
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE);
+               }
+
+               g_object_unref (info);
+       }
+
+       set_content_type (doc, content_type);
+       set_readonly (doc, read_only);
+
+       load_succeeded (task);
+}
+
+static void
+load_cb (GtkSourceFileLoader *loader,
+        GAsyncResult        *result,
+        GTask               *task)
+{
+       TaskData *data = g_task_get_task_data (task);
+       GError *error = NULL;
+
+       gtk_source_file_loader_load_finish (loader, result, &error);
+       g_object_unref (loader);
+
+       /* load was successful */
+       if (error == NULL ||
+           (error->domain == GTK_SOURCE_FILE_LOADER_ERROR &&
+            error->code == GTK_SOURCE_FILE_LOADER_ERROR_CONVERSION_FALLBACK))
+       {
+               GeditDocument *doc = g_task_get_source_object (task);
+               GFile *location = gtk_source_file_get_location (doc->priv->file);
+
+               if (location != NULL)
+               {
+                       g_file_query_info_async (location,
+                                                G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+                                                G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
+                                                G_FILE_QUERY_INFO_NONE,
+                                                g_task_get_priority (task),
+                                                g_task_get_cancellable (task),
+                                                (GAsyncReadyCallback)query_info_cb,
+                                                task);
+               }
+
+               /* loaded from stream */
+               else
+               {
+                       set_content_type (doc, NULL);
+                       set_readonly (doc, FALSE);
+
+                       load_succeeded (task);
+               }
+
+               if (error != NULL)
+               {
+                       g_error_free (error);
+               }
+       }
+
+       /* special case creating a named new doc */
+       else if (data->create &&
+                error->domain == G_IO_ERROR &&
+                error->code == G_IO_ERROR_NOT_FOUND &&
+                g_file_has_uri_scheme (location, "file"))
+       {
+               g_task_return_boolean (task, TRUE);
+               g_object_unref (task);
+       }
+
+       else
+       {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+       }
+}
+
+void
+_gedit_document_load_async (GeditDocument           *doc,
+                           GFile                   *location,
+                           GInputStream            *stream,
+                           const GtkSourceEncoding *encoding,
+                           gint                     line_pos,
+                           gint                     column_pos,
+                           gboolean                 create,
+                           GCancellable            *cancellable,
+                           GFileProgressCallback    progress_callback,
+                           gpointer                 progress_callback_data,
+                           GAsyncReadyCallback      callback,
+                           gpointer                 user_data)
+{
+       GTask *task;
+       TaskData *data;
+       GtkSourceFileLoader *loader;
+
+       g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
+       g_return_if_fail (location != NULL || stream != NULL);
+       g_return_if_fail (location == NULL || G_IS_FILE (location));
+       g_return_if_fail (stream == NULL || G_IS_INPUT_STREAM (stream));
+       g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+
+       task = g_task_new (doc, cancellable, callback, user_data);
+       g_task_set_priority (task, G_PRIORITY_HIGH);
+
+       data = task_data_new ();
+       data->line_pos = line_pos;
+       data->column_pos = column_pos;
+       data->create = create != FALSE;
+
+       g_task_set_task_data (task, data, (GDestroyNotify)task_data_free);
+
+       if (location != NULL)
+       {
+               loader = gtk_source_file_loader_new (doc->priv->file, location);
+       }
+       else
+       {
+               loader = gtk_source_file_loader_new_from_stream (doc->priv->file, stream);
+       }
+
+       if (encoding != NULL)
+       {
+               GSList *list = g_slist_append (NULL, (gpointer)encoding);
+               gtk_source_file_loader_set_candidate_encodings (loader, list);
+               g_slist_free (list);
+       }
+       else
+       {
+               /* TODO */
+       }
+
+       gtk_source_file_loader_load_async (loader,
+                                          g_task_get_priority (task),
+                                          g_task_get_cancellable (task),
+                                          progress_callback,
+                                          progress_callback_data,
+                                          NULL,
+                                          (GAsyncReadyCallback)load_cb,
+                                          task);
+}
+
+gboolean
+_gedit_document_load_finish (GeditDocument  *doc,
+                            GAsyncResult   *result,
+                            GError        **error)
+{
+       gboolean ok;
+
+       g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+       g_return_val_if_fail (g_task_is_valid (result, doc), FALSE);
+
+       ok = g_task_propagate_boolean (G_TASK (result), error);
+
+       /* Emit signal only on success. Normally plugins don't need the error,
+        * it is already handled by GeditTab.
+        */
+       if (ok)
+       {
+               g_signal_emit (doc,
+                              document_signals[LOADED],
+                              0,
+                              NULL);
+       }
+
+       return ok;
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gedit/gedit-document.h b/gedit/gedit-document.h
index be122c4..4fdbd76 100644
--- a/gedit/gedit-document.h
+++ b/gedit/gedit-document.h
@@ -304,6 +304,23 @@ gboolean            _gedit_document_get_empty_search       (GeditDocument          *doc);
 
 GtkSourceFile          *gedit_document_get_file                (GeditDocument *doc);
 
+void                    _gedit_document_load_async             (GeditDocument           *doc,
+                                                                GFile                   *location,
+                                                                GInputStream            *stream,
+                                                                const GtkSourceEncoding *encoding,
+                                                                gint                     line_pos,
+                                                                gint                     column_pos,
+                                                                gboolean                 create,
+                                                                GCancellable            *cancellable,
+                                                                GFileProgressCallback    progress_callback,
+                                                                gpointer                 
progress_callback_data,
+                                                                GAsyncReadyCallback      callback,
+                                                                gpointer                 user_data);
+
+gboolean                _gedit_document_load_finish            (GeditDocument  *doc,
+                                                                GAsyncResult   *result,
+                                                                GError        **error);
+
 G_END_DECLS
 
 #endif /* __GEDIT_DOCUMENT_H__ */
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index ba57a04..cdab4e3 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -58,9 +58,10 @@ struct _GeditTabPrivate
        GFile                  *tmp_save_location;
 
        /* tmp data for loading */
+       GCancellable           *cancellable;
        gint                    tmp_line_pos;
        gint                    tmp_column_pos;
-       const GtkSourceEncoding *tmp_encoding;
+       const GtkSourceEncoding *tmp_encoding; /* TODO remove */
 
        GTimer                 *timer;
 
@@ -71,7 +72,6 @@ struct _GeditTabPrivate
 
        gint                    not_editable : 1;
        gint                    auto_save : 1;
-
        gint                    ask_if_externally_modified : 1;
 };
 
@@ -933,38 +933,6 @@ info_bar_set_progress (GeditTab *tab,
        }
 }
 
-static void
-document_loading (GeditDocument *document,
-                 goffset        size,
-                 goffset        total_size,
-                 GeditTab      *tab)
-{
-       gdouble et;
-       gdouble total_time;
-
-       g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_LOADING) ||
-                         (tab->priv->state == GEDIT_TAB_STATE_REVERTING));
-
-       gedit_debug_message (DEBUG_TAB, "%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, size, total_size);
-
-       if (tab->priv->timer == NULL)
-       {
-               tab->priv->timer = g_timer_new ();
-       }
-
-       et = g_timer_elapsed (tab->priv->timer, NULL);
-
-       /* et : total_time = size : total_size */
-       total_time = (et * total_size) / size;
-
-       if ((total_time - et) > 3.0)
-       {
-               show_loading_info_bar (tab);
-       }
-
-       info_bar_set_progress (tab, size, total_size);
-}
-
 static gboolean
 remove_tab_idle (GeditTab *tab)
 {
@@ -1712,10 +1680,6 @@ gedit_tab_init (GeditTab *tab)
                          G_CALLBACK (document_modified_changed),
                          tab);
        g_signal_connect (doc,
-                         "loading",
-                         G_CALLBACK (document_loading),
-                         tab);
-       g_signal_connect (doc,
                          "loaded",
                          G_CALLBACK (document_loaded),
                          tab);
@@ -2031,6 +1995,60 @@ gedit_tab_get_from_document (GeditDocument *doc)
        return (res != NULL) ? GEDIT_TAB (res) : NULL;
 }
 
+static void
+progress_cb (goffset   current_num_bytes,
+            goffset   total_num_bytes,
+            GeditTab *tab)
+{
+       gdouble elapsed_time;
+       gdouble total_time;
+       gdouble remaining_time;
+
+       g_return_if_fail ((tab->priv->state == GEDIT_TAB_STATE_LOADING) ||
+                         (tab->priv->state == GEDIT_TAB_STATE_REVERTING));
+
+       gedit_debug_message (DEBUG_TAB, "%" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT,
+                            current_num_bytes,
+                            total_num_bytes);
+
+       if (tab->priv->timer == NULL)
+       {
+               tab->priv->timer = g_timer_new ();
+       }
+
+       elapsed_time = g_timer_elapsed (tab->priv->timer, NULL);
+
+       /* elapsed_time / total_time = current_num_bytes / total_num_bytes */
+       total_time = (elapsed_time * total_num_bytes) / current_num_bytes;
+
+       remaining_time = total_time - elapsed_time;
+
+       /* Approximately more than 3 seconds remaining. */
+       if (remaining_time > 3.0)
+       {
+               show_loading_info_bar (tab);
+       }
+
+       info_bar_set_progress (tab, current_num_bytes, total_num_bytes);
+}
+
+static void
+load_cb (GeditDocument *doc,
+        GAsyncResult  *result,
+        GeditTab      *tab)
+{
+       GError *error = NULL;
+
+       _gedit_document_load_finish (doc, result, &error);
+
+       if (error != NULL)
+       {
+       }
+
+       /* Async operation finished. */
+       g_object_unref (tab);
+}
+
 void
 _gedit_tab_load (GeditTab                *tab,
                 GFile                   *location,
@@ -2044,24 +2062,33 @@ _gedit_tab_load (GeditTab                *tab,
        g_return_if_fail (GEDIT_IS_TAB (tab));
        g_return_if_fail (G_IS_FILE (location));
        g_return_if_fail (tab->priv->state == GEDIT_TAB_STATE_NORMAL);
-
-       doc = gedit_view_frame_get_document (tab->priv->frame);
+       g_return_if_fail (tab->priv->cancellable == NULL);
 
        gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
 
-       tab->priv->tmp_line_pos = line_pos;
-       tab->priv->tmp_column_pos = column_pos;
-       tab->priv->tmp_encoding = encoding;
-
        if (tab->priv->auto_save_timeout > 0)
+       {
                remove_auto_save_timeout (tab);
+       }
 
-       gedit_document_load (doc,
-                            location,
-                            encoding,
-                            line_pos,
-                            column_pos,
-                            create);
+       doc = gedit_view_frame_get_document (tab->priv->frame);
+       tab->priv->cancellable = g_cancellable_new ();
+
+       /* Keep tab alive during the async operation. */
+       g_object_ref (tab);
+
+       _gedit_document_load_async (doc,
+                                   location,
+                                   NULL,
+                                   encoding,
+                                   line_pos,
+                                   column_pos,
+                                   create,
+                                   tab->priv->cancellable,
+                                   (GFileProgressCallback)progress_cb,
+                                   tab,
+                                   (GAsyncReadyCallback)load_cb,
+                                   tab);
 }
 
 void


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