[gedit/wip/spell-checking] spell-plugin: improve memory management for the auto-spell



commit fb6f9bf1f08191c15c33dbad7a0fcde37e9a289b
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sun Jul 19 11:31:52 2015 +0200

    spell-plugin: improve memory management for the auto-spell
    
    Create a ViewData struct and attach it to the view. The struct is freed
    when the view is destroyed, which unrefs the auto_spell.
    
    In ViewData, the GeditSpellPlugin instance is needed, to access the
    "auto-spell" GAction of the window. If it was not needed, then
    implementing GeditViewActivatable would have been easier.

 plugins/spell/gedit-spell-plugin.c |  124 ++++++++++++++++++++++++++----------
 1 files changed, 90 insertions(+), 34 deletions(-)
---
diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c
index eb1b61e..f21b476 100644
--- a/plugins/spell/gedit-spell-plugin.c
+++ b/plugins/spell/gedit-spell-plugin.c
@@ -2,6 +2,7 @@
  * gedit-spell-plugin.c
  *
  * Copyright (C) 2002-2005 Paolo Maggi
+ * Copyright (C) 2015 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
@@ -45,6 +46,7 @@
 #define SPELL_ENABLED_STR "1"
 
 #define GEDIT_AUTOMATIC_SPELL_VIEW "GeditAutomaticSpellView"
+#define AUTO_SPELL_DATA_KEY "GeditSpellPlugin-AutoSpellData"
 
 static void gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface);
 
@@ -70,6 +72,20 @@ struct _CheckRange
        GtkTextMark *current_mark;
 };
 
+typedef struct _ViewData ViewData;
+
+struct _ViewData
+{
+       GeditSpellPlugin *plugin;
+       GeditView *view;
+       GeditAutomaticSpellChecker *auto_spell;
+
+       /* The doc is also needed, to be sure that the signals are disconnected
+        * on the same doc.
+        */
+       GeditDocument *doc;
+};
+
 enum
 {
        PROP_0,
@@ -89,6 +105,9 @@ static void  set_language_cb                 (GSimpleAction *action, GVariant *parameter, 
gpoin
 static void    auto_spell_activate_cb          (GSimpleAction *action, GVariant *parameter, gpointer data);
 static void    auto_spell_change_state_cb      (GSimpleAction *action, GVariant *state, gpointer data);
 
+static void    on_document_loaded              (GeditDocument *doc, ViewData *data);
+static void    on_document_saved               (GeditDocument *doc, ViewData *data);
+
 static GActionEntry action_entries[] =
 {
        { "check-spell", spell_cb },
@@ -99,6 +118,56 @@ static GActionEntry action_entries[] =
 static GQuark spell_checker_id = 0;
 static GQuark check_range_id = 0;
 
+static ViewData *
+view_data_new (GeditSpellPlugin *plugin,
+              GeditView        *view)
+{
+       ViewData *data;
+
+       data = g_slice_new (ViewData);
+       data->plugin = g_object_ref (plugin);
+       data->view = g_object_ref (view);
+       data->auto_spell = NULL;
+
+       data->doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+       g_object_ref (data->doc);
+
+       g_signal_connect (data->doc,
+                         "loaded",
+                         G_CALLBACK (on_document_loaded),
+                         data);
+
+       g_signal_connect (data->doc,
+                         "saved",
+                         G_CALLBACK (on_document_saved),
+                         data);
+
+       return data;
+}
+
+static void
+view_data_free (ViewData *data)
+{
+       if (data == NULL)
+       {
+               return;
+       }
+
+       if (data->doc != NULL)
+       {
+               g_signal_handlers_disconnect_by_func (data->doc, on_document_loaded, data);
+               g_signal_handlers_disconnect_by_func (data->doc, on_document_saved, data);
+
+               g_object_unref (data->doc);
+       }
+
+       g_clear_object (&data->plugin);
+       g_clear_object (&data->view);
+       g_clear_object (&data->auto_spell);
+
+       g_slice_free (ViewData, data);
+}
+
 static void
 gedit_spell_plugin_init (GeditSpellPlugin *plugin)
 {
@@ -1074,11 +1143,10 @@ set_auto_spell_from_metadata (GeditSpellPlugin *plugin,
 }
 
 static void
-on_document_loaded (GeditDocument    *doc,
-                   GeditSpellPlugin *plugin)
+on_document_loaded (GeditDocument *doc,
+                   ViewData      *data)
 {
        GeditSpellChecker *checker;
-       GeditView *view;
 
        checker = GEDIT_SPELL_CHECKER (g_object_get_qdata (G_OBJECT (doc),
                                                           spell_checker_id));
@@ -1087,21 +1155,18 @@ on_document_loaded (GeditDocument    *doc,
                set_language_from_metadata (checker, doc);
        }
 
-       view = GEDIT_VIEW (g_object_get_data (G_OBJECT (doc), GEDIT_AUTOMATIC_SPELL_VIEW));
-
-       set_auto_spell_from_metadata (plugin, view);
+       set_auto_spell_from_metadata (data->plugin, data->view);
 }
 
 static void
-on_document_saved (GeditDocument    *doc,
-                  GeditSpellPlugin *plugin)
+on_document_saved (GeditDocument *doc,
+                  ViewData      *data)
 {
-       GeditAutomaticSpellChecker *autospell;
        GeditSpellChecker *checker;
        const gchar *key;
 
        /* Make sure to save the metadata here too */
-       autospell = gedit_automatic_spell_checker_get_from_buffer (GTK_SOURCE_BUFFER (doc));
+
        checker = GEDIT_SPELL_CHECKER (g_object_get_qdata (G_OBJECT (doc), spell_checker_id));
 
        if (checker != NULL)
@@ -1115,7 +1180,7 @@ on_document_saved (GeditDocument    *doc,
 
        gedit_document_set_metadata (doc,
                                     GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED,
-                                    autospell != NULL ? SPELL_ENABLED_STR : NULL,
+                                    data->auto_spell != NULL ? SPELL_ENABLED_STR : NULL,
                                     GEDIT_METADATA_ATTRIBUTE_SPELL_LANGUAGE,
                                     key,
                                     NULL);
@@ -1127,25 +1192,15 @@ tab_added_cb (GeditWindow      *window,
              GeditSpellPlugin *plugin)
 {
        GeditView *view;
-       GeditDocument *doc;
+       ViewData *data;
 
        view = gedit_tab_get_view (tab);
-       doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
-
-       /* We need to pass the view with the document as there is no way to
-        * attach the view to the automatic spell checker.
-        */
-       g_object_set_data (G_OBJECT (doc), GEDIT_AUTOMATIC_SPELL_VIEW, view);
-
-       g_signal_connect (doc,
-                         "loaded",
-                         G_CALLBACK (on_document_loaded),
-                         plugin);
 
-       g_signal_connect (doc,
-                         "saved",
-                         G_CALLBACK (on_document_saved),
-                         plugin);
+       data = view_data_new (plugin, view);
+       g_object_set_data_full (G_OBJECT (view),
+                               AUTO_SPELL_DATA_KEY,
+                               data,
+                               (GDestroyNotify) view_data_free);
 }
 
 static void
@@ -1153,13 +1208,8 @@ tab_removed_cb (GeditWindow      *window,
                GeditTab         *tab,
                GeditSpellPlugin *plugin)
 {
-       GeditDocument *doc;
-
-       doc = gedit_tab_get_document (tab);
-       g_object_set_data (G_OBJECT (doc), GEDIT_AUTOMATIC_SPELL_VIEW, NULL);
-
-       g_signal_handlers_disconnect_by_func (doc, on_document_loaded, plugin);
-       g_signal_handlers_disconnect_by_func (doc, on_document_saved, plugin);
+       GeditView *view = gedit_tab_get_view (tab);
+       g_object_set_data (G_OBJECT (view), AUTO_SPELL_DATA_KEY, NULL);
 }
 
 static void
@@ -1188,6 +1238,12 @@ gedit_spell_plugin_activate (GeditWindowActivatable *activatable)
        for (l = views; l != NULL; l = g_list_next (l))
        {
                GeditView *view = GEDIT_VIEW (l->data);
+               ViewData *data = view_data_new (plugin, view);
+
+               g_object_set_data_full (G_OBJECT (view),
+                                       AUTO_SPELL_DATA_KEY,
+                                       data,
+                                       (GDestroyNotify) view_data_free);
 
                set_auto_spell_from_metadata (plugin, view);
        }


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