[gedit/wip/tab-gtask: 4/4] tab: use a GTask for the file loading and reverting



commit 1958f1ece7b6ed0103275b5111d07be9c9c3c3ae
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sat Jun 20 18:11:04 2015 +0200

    tab: use a GTask for the file loading and reverting
    
    So that there are less object attributes in the GeditTab struct.
    
    The change is only internal to GeditTab. Later commits will use the
    async/finish functions externally.

 gedit/gedit-tab.c |  383 +++++++++++++++++++++++++++++++++--------------------
 1 files changed, 242 insertions(+), 141 deletions(-)
---
diff --git a/gedit/gedit-tab.c b/gedit/gedit-tab.c
index c819557..e27b1d4 100644
--- a/gedit/gedit-tab.c
+++ b/gedit/gedit-tab.c
@@ -63,11 +63,6 @@ struct _GeditTab
 
        GtkSourceFileSaverFlags save_flags;
 
-       /* tmp data for loading */
-       GtkSourceFileLoader *loader;
-       GCancellable *cancellable;
-       gint tmp_line_pos;
-       gint tmp_column_pos;
        guint idle_scroll;
 
        GTimer *timer;
@@ -79,12 +74,10 @@ struct _GeditTab
        guint auto_save : 1;
 
        guint ask_if_externally_modified : 1;
-
-       /* tmp data for loading */
-       guint user_requested_encoding : 1;
 };
 
 typedef struct _SaverData SaverData;
+typedef struct _LoaderData LoaderData;
 
 struct _SaverData
 {
@@ -111,6 +104,14 @@ struct _SaverData
        guint force_no_backup : 1;
 };
 
+struct _LoaderData
+{
+       GtkSourceFileLoader *loader;
+       gint line_pos;
+       gint column_pos;
+       guint user_requested_encoding : 1;
+};
+
 G_DEFINE_TYPE (GeditTab, gedit_tab, GTK_TYPE_BOX)
 
 enum
@@ -133,10 +134,8 @@ static guint signals[LAST_SIGNAL] = { 0 };
 
 static gboolean gedit_tab_auto_save (GeditTab *tab);
 
-static void launch_loader (GeditTab                *tab,
-                          const GtkSourceEncoding *encoding,
-                          gint                     line_pos,
-                          gint                     column_pos);
+static void launch_loader (GTask                   *loading_task,
+                          const GtkSourceEncoding *encoding);
 
 static void launch_saver (GTask *saving_task);
 
@@ -160,6 +159,26 @@ saver_data_free (SaverData *data)
        }
 }
 
+static LoaderData *
+loader_data_new (void)
+{
+       return g_slice_new0 (LoaderData);
+}
+
+static void
+loader_data_free (LoaderData *data)
+{
+       if (data != NULL)
+       {
+               if (data->loader != NULL)
+               {
+                       g_object_unref (data->loader);
+               }
+
+               g_slice_free (LoaderData, data);
+       }
+}
+
 static void
 set_editable (GeditTab *tab,
              gboolean  editable)
@@ -287,13 +306,6 @@ gedit_tab_set_property (GObject      *object,
 }
 
 static void
-clear_loading (GeditTab *tab)
-{
-       g_clear_object (&tab->loader);
-       g_clear_object (&tab->cancellable);
-}
-
-static void
 gedit_tab_dispose (GObject *object)
 {
        GeditTab *tab = GEDIT_TAB (object);
@@ -302,8 +314,6 @@ gedit_tab_dispose (GObject *object)
        g_clear_object (&tab->print_job);
        g_clear_object (&tab->print_preview);
 
-       clear_loading (tab);
-
        G_OBJECT_CLASS (gedit_tab_parent_class)->dispose (object);
 }
 
@@ -652,14 +662,14 @@ remove_tab (GeditTab *tab)
 static void
 io_loading_error_info_bar_response (GtkWidget *info_bar,
                                    gint       response_id,
-                                   GeditTab  *tab)
+                                   GTask     *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
+       LoaderData *data = g_task_get_task_data (loading_task);
        GFile *location;
        const GtkSourceEncoding *encoding;
 
-       g_return_if_fail (tab->loader != NULL);
-
-       location = gtk_source_file_loader_get_location (tab->loader);
+       location = gtk_source_file_loader_get_location (data->loader);
 
        switch (response_id)
        {
@@ -669,10 +679,7 @@ io_loading_error_info_bar_response (GtkWidget *info_bar,
                        set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
                        gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
 
-                       launch_loader (tab,
-                                      encoding,
-                                      tab->tmp_line_pos,
-                                      tab->tmp_column_pos);
+                       launch_loader (loading_task, encoding);
                        break;
 
                case GTK_RESPONSE_YES:
@@ -680,7 +687,9 @@ io_loading_error_info_bar_response (GtkWidget *info_bar,
                        set_editable (tab, TRUE);
                        set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
                        gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
-                       clear_loading (tab);
+
+                       g_task_return_boolean (loading_task, TRUE);
+                       g_object_unref (loading_task);
                        break;
 
                default:
@@ -689,6 +698,9 @@ io_loading_error_info_bar_response (GtkWidget *info_bar,
                                gedit_recent_remove_if_local (location);
                        }
 
+                       g_task_return_boolean (loading_task, FALSE);
+                       g_object_unref (loading_task);
+
                        remove_tab (tab);
                        break;
        }
@@ -714,36 +726,40 @@ file_already_open_warning_info_bar_response (GtkWidget *info_bar,
 static void
 load_cancelled (GtkWidget *bar,
                gint       response_id,
-               GeditTab  *tab)
+               GTask     *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
+
        g_return_if_fail (GEDIT_IS_PROGRESS_INFO_BAR (tab->info_bar));
-       g_return_if_fail (G_IS_CANCELLABLE (tab->cancellable));
 
-       g_cancellable_cancel (tab->cancellable);
+       g_cancellable_cancel (g_task_get_cancellable (loading_task));
 }
 
 static void
 unrecoverable_reverting_error_info_bar_response (GtkWidget *info_bar,
                                                 gint       response_id,
-                                                GeditTab  *tab)
+                                                GTask     *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
        GeditView *view;
 
        gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
 
        set_info_bar (tab, NULL, GTK_RESPONSE_NONE);
 
-       clear_loading (tab);
-
        view = gedit_tab_get_view (tab);
        gtk_widget_grab_focus (GTK_WIDGET (view));
+
+       g_task_return_boolean (loading_task, FALSE);
+       g_object_unref (loading_task);
 }
 
 #define MAX_MSG_LENGTH 100
 
 static void
-show_loading_info_bar (GeditTab *tab)
+show_loading_info_bar (GTask *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
        GtkWidget *bar;
        GeditDocument *doc;
        gchar *name;
@@ -840,10 +856,11 @@ show_loading_info_bar (GeditTab *tab)
                bar = gedit_progress_info_bar_new ("document-open", msg, TRUE);
        }
 
-       g_signal_connect (bar,
-                         "response",
-                         G_CALLBACK (load_cancelled),
-                         tab);
+       g_signal_connect_object (bar,
+                                "response",
+                                G_CALLBACK (load_cancelled),
+                                loading_task,
+                                0);
 
        set_info_bar (tab, bar, GTK_RESPONSE_NONE);
 
@@ -1685,32 +1702,36 @@ gedit_tab_get_from_document (GeditDocument *doc)
 }
 
 static void
-loader_progress_cb (goffset   size,
-                   goffset   total_size,
-                   GeditTab *tab)
+loader_progress_cb (goffset  size,
+                   goffset  total_size,
+                   GTask   *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
+
        g_return_if_fail (tab->state == GEDIT_TAB_STATE_LOADING ||
                          tab->state == GEDIT_TAB_STATE_REVERTING);
 
        if (should_show_progress_info (tab, size, total_size))
        {
-               show_loading_info_bar (tab);
+               show_loading_info_bar (loading_task);
                info_bar_set_progress (tab, size, total_size);
        }
 }
 
 static void
-goto_line (GeditTab *tab)
+goto_line (GTask *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
+       LoaderData *data = g_task_get_task_data (loading_task);
        GeditDocument *doc = gedit_tab_get_document (tab);
        GtkTextIter iter;
 
        /* Move the cursor at the requested line if any. */
-       if (tab->tmp_line_pos > 0)
+       if (data->line_pos > 0)
        {
                gedit_document_goto_line_offset (doc,
-                                                tab->tmp_line_pos - 1,
-                                                MAX (0, tab->tmp_column_pos - 1));
+                                                data->line_pos - 1,
+                                                MAX (0, data->column_pos - 1));
                return;
        }
 
@@ -1790,18 +1811,17 @@ file_already_opened (GeditDocument *doc,
 }
 
 static void
-successful_load (GeditTab *tab)
+successful_load (GTask *loading_task)
 {
-       GeditDocument *doc;
-       GtkSourceFile *file;
+       GeditTab *tab = g_task_get_source_object (loading_task);
+       LoaderData *data = g_task_get_task_data (loading_task);
+       GeditDocument *doc = gedit_tab_get_document (tab);
+       GtkSourceFile *file = gedit_document_get_file (doc);
        GFile *location;
 
-       doc = gedit_tab_get_document (tab);
-       file = gedit_document_get_file (doc);
-
-       if (tab->user_requested_encoding)
+       if (data->user_requested_encoding)
        {
-               const GtkSourceEncoding *encoding = gtk_source_file_loader_get_encoding (tab->loader);
+               const GtkSourceEncoding *encoding = gtk_source_file_loader_get_encoding (data->loader);
                const gchar *charset = gtk_source_encoding_get_charset (encoding);
 
                gedit_document_set_metadata (doc,
@@ -1809,7 +1829,7 @@ successful_load (GeditTab *tab)
                                             NULL);
        }
 
-       goto_line (tab);
+       goto_line (loading_task);
 
        /* Scroll to the cursor when the document is loaded, we need to do it in
         * an idle as after the document is loaded the textview is still
@@ -1820,7 +1840,7 @@ successful_load (GeditTab *tab)
                tab->idle_scroll = g_idle_add ((GSourceFunc)scroll_to_cursor, tab);
        }
 
-       location = gtk_source_file_loader_get_location (tab->loader);
+       location = gtk_source_file_loader_get_location (data->loader);
 
        /* If the document is readonly we don't care how many times the file
         * is opened.
@@ -1858,8 +1878,9 @@ successful_load (GeditTab *tab)
 static void
 load_cb (GtkSourceFileLoader *loader,
         GAsyncResult        *result,
-        GeditTab            *tab)
+        GTask               *loading_task)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
        GeditDocument *doc = gedit_tab_get_document (tab);
        GFile *location = gtk_source_file_loader_get_location (loader);
        gboolean create_named_new_doc;
@@ -1896,8 +1917,13 @@ load_cb (GtkSourceFileLoader *loader,
 
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
        {
+               g_task_return_boolean (loading_task, FALSE);
+               g_object_unref (loading_task);
+
                remove_tab (tab);
-               goto end;
+
+               g_error_free (error);
+               return;
        }
 
        if (g_error_matches (error,
@@ -1919,7 +1945,7 @@ load_cb (GtkSourceFileLoader *loader,
                g_signal_connect (info_bar,
                                  "response",
                                  G_CALLBACK (io_loading_error_info_bar_response),
-                                 tab);
+                                 loading_task);
 
                set_info_bar (tab, info_bar, GTK_RESPONSE_CANCEL);
 
@@ -1933,12 +1959,12 @@ load_cb (GtkSourceFileLoader *loader,
                        gedit_tab_set_state (tab, GEDIT_TAB_STATE_REVERTING_ERROR);
                }
 
-               /* The loading was successful, despite some invalid characters.
-                * The document can be edited.
-                */
-               successful_load (tab);
+               /* The loading was successful, despite some invalid characters. */
+               successful_load (loading_task);
                gedit_recent_add_document (doc);
-               goto end;
+
+               g_error_free (error);
+               return;
        }
 
        if (error != NULL)
@@ -1971,7 +1997,7 @@ load_cb (GtkSourceFileLoader *loader,
                        g_signal_connect (info_bar,
                                          "response",
                                          G_CALLBACK (io_loading_error_info_bar_response),
-                                         tab);
+                                         loading_task);
                }
                else
                {
@@ -1982,33 +2008,27 @@ load_cb (GtkSourceFileLoader *loader,
                        g_signal_connect (info_bar,
                                          "response",
                                          G_CALLBACK (unrecoverable_reverting_error_info_bar_response),
-                                         tab);
+                                         loading_task);
                }
 
                set_info_bar (tab, info_bar, GTK_RESPONSE_CANCEL);
-               goto end;
+
+               g_error_free (error);
+               return;
        }
 
        g_assert (error == NULL);
 
        gedit_tab_set_state (tab, GEDIT_TAB_STATE_NORMAL);
-       successful_load (tab);
+       successful_load (loading_task);
 
        if (!create_named_new_doc)
        {
                gedit_recent_add_document (doc);
        }
 
-       clear_loading (tab);
-
-end:
-       /* Async operation finished. */
-       g_object_unref (tab);
-
-       if (error != NULL)
-       {
-               g_error_free (error);
-       }
+       g_task_return_boolean (loading_task, TRUE);
+       g_object_unref (loading_task);
 }
 
 /* The returned list may contain duplicated encodings. Only the first occurrence
@@ -2058,36 +2078,28 @@ get_candidate_encodings (GeditTab *tab)
 }
 
 static void
-launch_loader (GeditTab                *tab,
-              const GtkSourceEncoding *encoding,
-              gint                     line_pos,
-              gint                     column_pos)
+launch_loader (GTask                   *loading_task,
+              const GtkSourceEncoding *encoding)
 {
+       GeditTab *tab = g_task_get_source_object (loading_task);
+       LoaderData *data = g_task_get_task_data (loading_task);
        GSList *candidate_encodings = NULL;
        GeditDocument *doc;
 
-       g_return_if_fail (GTK_SOURCE_IS_FILE_LOADER (tab->loader));
-
        if (encoding != NULL)
        {
-               tab->user_requested_encoding = TRUE;
+               data->user_requested_encoding = TRUE;
                candidate_encodings = g_slist_append (NULL, (gpointer) encoding);
        }
        else
        {
-               tab->user_requested_encoding = FALSE;
+               data->user_requested_encoding = FALSE;
                candidate_encodings = get_candidate_encodings (tab);
        }
 
-       gtk_source_file_loader_set_candidate_encodings (tab->loader, candidate_encodings);
+       gtk_source_file_loader_set_candidate_encodings (data->loader, candidate_encodings);
        g_slist_free (candidate_encodings);
 
-       tab->tmp_line_pos = line_pos;
-       tab->tmp_column_pos = column_pos;
-
-       g_clear_object (&tab->cancellable);
-       tab->cancellable = g_cancellable_new ();
-
        doc = gedit_tab_get_document (tab);
        g_signal_emit_by_name (doc, "load");
 
@@ -2098,66 +2110,109 @@ launch_loader (GeditTab                *tab,
 
        tab->timer = g_timer_new ();
 
-       /* Keep the tab alive during the async operation. */
-       g_object_ref (tab);
-
-       gtk_source_file_loader_load_async (tab->loader,
+       gtk_source_file_loader_load_async (data->loader,
                                           G_PRIORITY_DEFAULT,
-                                          tab->cancellable,
+                                          g_task_get_cancellable (loading_task),
                                           (GFileProgressCallback) loader_progress_cb,
-                                          tab,
+                                          loading_task,
                                           NULL,
                                           (GAsyncReadyCallback) load_cb,
-                                          tab);
+                                          loading_task);
 }
 
-void
-_gedit_tab_load (GeditTab                *tab,
-                GFile                   *location,
-                const GtkSourceEncoding *encoding,
-                gint                     line_pos,
-                gint                     column_pos,
-                gboolean                 create)
+static void
+_gedit_tab_load_async (GeditTab                *tab,
+                      GFile                   *location,
+                      const GtkSourceEncoding *encoding,
+                      gint                     line_pos,
+                      gint                     column_pos,
+                      gboolean                 create,
+                      GCancellable            *cancellable,
+                      GAsyncReadyCallback      callback,
+                      gpointer                 user_data)
 {
        GeditDocument *doc;
        GtkSourceFile *file;
+       GTask *loading_task;
+       LoaderData *data;
 
        g_return_if_fail (GEDIT_IS_TAB (tab));
        g_return_if_fail (G_IS_FILE (location));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
        g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
 
        gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
 
        doc = gedit_tab_get_document (tab);
        file = gedit_document_get_file (doc);
+       gtk_source_file_set_location (file, location);
 
-       if (tab->loader != NULL)
-       {
-               g_warning ("GeditTab: file loader already exists.");
-               g_object_unref (tab->loader);
-       }
+       loading_task = g_task_new (tab, cancellable, callback, user_data);
 
-       gtk_source_file_set_location (file, location);
+       data = loader_data_new ();
+       g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
 
-       tab->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
+       data->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
+       data->line_pos = line_pos;
+       data->column_pos = column_pos;
 
        _gedit_document_set_create (doc, create);
 
-       launch_loader (tab, encoding, line_pos, column_pos);
+       launch_loader (loading_task, encoding);
+}
+
+static gboolean
+_gedit_tab_load_finish (GeditTab     *tab,
+                       GAsyncResult *result)
+{
+       g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
+
+       return g_task_propagate_boolean (G_TASK (result), NULL);
 }
 
 void
-_gedit_tab_load_stream (GeditTab                *tab,
-                       GInputStream            *stream,
-                       const GtkSourceEncoding *encoding,
-                       gint                     line_pos,
-                       gint                     column_pos)
+_gedit_tab_load (GeditTab                *tab,
+                GFile                   *location,
+                const GtkSourceEncoding *encoding,
+                gint                     line_pos,
+                gint                     column_pos,
+                gboolean                 create)
+{
+       GCancellable *cancellable;
+
+       cancellable = g_cancellable_new ();
+
+       _gedit_tab_load_async (tab,
+                              location,
+                              encoding,
+                              line_pos,
+                              column_pos,
+                              create,
+                              cancellable,
+                              (GAsyncReadyCallback) _gedit_tab_load_finish,
+                              NULL);
+
+       g_object_unref (cancellable);
+}
+
+static void
+_gedit_tab_load_stream_async (GeditTab                *tab,
+                             GInputStream            *stream,
+                             const GtkSourceEncoding *encoding,
+                             gint                     line_pos,
+                             gint                     column_pos,
+                             GCancellable            *cancellable,
+                             GAsyncReadyCallback      callback,
+                             gpointer                 user_data)
 {
        GeditDocument *doc;
        GtkSourceFile *file;
+       GTask *loading_task;
+       LoaderData *data;
 
        g_return_if_fail (GEDIT_IS_TAB (tab));
        g_return_if_fail (G_IS_INPUT_STREAM (stream));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
        g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL);
 
        gedit_tab_set_state (tab, GEDIT_TAB_STATE_LOADING);
@@ -2165,31 +2220,61 @@ _gedit_tab_load_stream (GeditTab                *tab,
        doc = gedit_tab_get_document (tab);
        file = gedit_document_get_file (doc);
 
-       if (tab->loader != NULL)
-       {
-               g_warning ("GeditTab: file loader already exists.");
-               g_object_unref (tab->loader);
-       }
-
        gtk_source_file_set_location (file, NULL);
 
-       tab->loader = gtk_source_file_loader_new_from_stream (GTK_SOURCE_BUFFER (doc),
-                                                                   file,
-                                                                   stream);
+       loading_task = g_task_new (tab, cancellable, callback, user_data);
+
+       data = loader_data_new ();
+       g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
+
+       data->loader = gtk_source_file_loader_new_from_stream (GTK_SOURCE_BUFFER (doc),
+                                                              file,
+                                                              stream);
+       data->line_pos = line_pos;
+       data->column_pos = column_pos;
 
        _gedit_document_set_create (doc, FALSE);
 
-       launch_loader (tab, encoding, line_pos, column_pos);
+       launch_loader (loading_task, encoding);
 }
 
 void
-_gedit_tab_revert (GeditTab *tab)
+_gedit_tab_load_stream (GeditTab                *tab,
+                       GInputStream            *stream,
+                       const GtkSourceEncoding *encoding,
+                       gint                     line_pos,
+                       gint                     column_pos)
+{
+       GCancellable *cancellable;
+
+       cancellable = g_cancellable_new ();
+
+       _gedit_tab_load_stream_async (tab,
+                                     stream,
+                                     encoding,
+                                     line_pos,
+                                     column_pos,
+                                     cancellable,
+                                     (GAsyncReadyCallback) _gedit_tab_load_finish,
+                                     NULL);
+
+       g_object_unref (cancellable);
+}
+
+static void
+_gedit_tab_revert_async (GeditTab            *tab,
+                        GCancellable        *cancellable,
+                        GAsyncReadyCallback  callback,
+                        gpointer             user_data)
 {
        GeditDocument *doc;
        GtkSourceFile *file;
        GFile *location;
+       GTask *loading_task;
+       LoaderData *data;
 
        g_return_if_fail (GEDIT_IS_TAB (tab));
+       g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
        g_return_if_fail (tab->state == GEDIT_TAB_STATE_NORMAL ||
                          tab->state == GEDIT_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
 
@@ -2205,15 +2290,31 @@ _gedit_tab_revert (GeditTab *tab)
 
        gedit_tab_set_state (tab, GEDIT_TAB_STATE_REVERTING);
 
-       if (tab->loader != NULL)
-       {
-               g_warning ("GeditTab: file loader already exists.");
-               g_object_unref (tab->loader);
-       }
+       loading_task = g_task_new (tab, cancellable, callback, user_data);
+
+       data = loader_data_new ();
+       g_task_set_task_data (loading_task, data, (GDestroyNotify) loader_data_free);
+
+       data->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
+       data->line_pos = 0;
+       data->column_pos = 0;
+
+       launch_loader (loading_task, NULL);
+}
+
+void
+_gedit_tab_revert (GeditTab *tab)
+{
+       GCancellable *cancellable;
+
+       cancellable = g_cancellable_new ();
 
-       tab->loader = gtk_source_file_loader_new (GTK_SOURCE_BUFFER (doc), file);
+       _gedit_tab_revert_async (tab,
+                                cancellable,
+                                (GAsyncReadyCallback) _gedit_tab_load_finish,
+                                NULL);
 
-       launch_loader (tab, NULL, 0, 0);
+       g_object_unref (cancellable);
 }
 
 static void


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