[gedit: 9/9] spell-plugin: improve memory management for the auto-spell
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit: 9/9] spell-plugin: improve memory management for the auto-spell
- Date: Sun, 19 Jul 2015 11:18:44 +0000 (UTC)
commit a659dd2e96ce18395c968003237447abbbc83c27
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-automatic-spell-checker.c | 5 +-
plugins/spell/gedit-spell-plugin.c | 191 ++++++++++++++++---------
2 files changed, 126 insertions(+), 70 deletions(-)
---
diff --git a/plugins/spell/gedit-automatic-spell-checker.c b/plugins/spell/gedit-automatic-spell-checker.c
index 9fdb01d..29a9f0d 100644
--- a/plugins/spell/gedit-automatic-spell-checker.c
+++ b/plugins/spell/gedit-automatic-spell-checker.c
@@ -970,7 +970,10 @@ gedit_automatic_spell_checker_new (GtkSourceBuffer *buffer,
g_return_val_if_fail (GEDIT_IS_SPELL_CHECKER (checker), NULL);
spell = gedit_automatic_spell_checker_get_from_buffer (buffer);
- g_return_val_if_fail (spell == NULL, spell);
+ if (spell != NULL)
+ {
+ return spell;
+ }
return g_object_new (GEDIT_TYPE_AUTOMATIC_SPELL_CHECKER,
"buffer", buffer,
diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c
index eb1b61e..03fd4ed 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 VIEW_DATA_KEY "GeditSpellPlugin-ViewData"
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)
{
@@ -885,33 +954,27 @@ spell_cb (GSimpleAction *action,
}
static void
-set_auto_spell (GeditWindow *window,
- GeditView *view,
- gboolean active)
+set_auto_spell (ViewData *data,
+ gboolean active)
{
- GeditAutomaticSpellChecker *autospell;
- GeditSpellChecker *checker;
- GeditDocument *doc;
+ if (!active)
+ {
+ g_clear_object (&data->auto_spell);
+ }
+ else if (data->auto_spell == NULL)
+ {
+ GeditSpellChecker *checker;
- doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
+ checker = get_spell_checker_from_document (data->doc);
+ g_return_if_fail (checker != NULL);
- checker = get_spell_checker_from_document (doc);
- g_return_if_fail (checker != NULL);
+ data->auto_spell = gedit_automatic_spell_checker_new (GTK_SOURCE_BUFFER (data->doc),
+ checker);
- autospell = gedit_automatic_spell_checker_get_from_buffer (GTK_SOURCE_BUFFER (doc));
+ gedit_automatic_spell_checker_attach_view (data->auto_spell,
+ GTK_TEXT_VIEW (data->view));
- if (active)
- {
- if (autospell == NULL)
- {
- autospell = gedit_automatic_spell_checker_new (GTK_SOURCE_BUFFER (doc), checker);
- gedit_automatic_spell_checker_attach_view (autospell, GTK_TEXT_VIEW (view));
- gedit_automatic_spell_checker_recheck_all (autospell);
- }
- }
- else if (autospell != NULL)
- {
- g_object_unref (autospell);
+ gedit_automatic_spell_checker_recheck_all (data->auto_spell);
}
}
@@ -977,7 +1040,13 @@ auto_spell_change_state_cb (GSimpleAction *action,
view = gedit_window_get_active_view (priv->window);
if (view != NULL)
{
- set_auto_spell (priv->window, view, active);
+ ViewData *data = g_object_get_data (G_OBJECT (view), VIEW_DATA_KEY);
+
+ if (data != NULL)
+ {
+ set_auto_spell (data, active);
+ }
+
g_simple_action_set_state (action, g_variant_new_boolean (active));
}
}
@@ -1041,29 +1110,26 @@ update_ui (GeditSpellPlugin *plugin)
}
static void
-set_auto_spell_from_metadata (GeditSpellPlugin *plugin,
- GeditView *view)
+set_auto_spell_from_metadata (ViewData *data)
{
+ GeditSpellPlugin *plugin = data->plugin;
gboolean active = FALSE;
gchar *active_str;
- GeditDocument *doc;
- GeditDocument *active_doc;
+ GeditView *active_view;
- doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
-
- active_str = gedit_document_get_metadata (doc, GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED);
+ active_str = gedit_document_get_metadata (data->doc, GEDIT_METADATA_ATTRIBUTE_SPELL_ENABLED);
if (active_str != NULL)
{
active = g_str_equal (active_str, SPELL_ENABLED_STR);
g_free (active_str);
}
- set_auto_spell (plugin->priv->window, view, active);
+ set_auto_spell (data, active);
- /* In case that the doc is the active one we mark the spell action */
- active_doc = gedit_window_get_active_document (plugin->priv->window);
+ /* In case that the view is the active one we mark the spell action */
+ active_view = gedit_window_get_active_view (plugin->priv->window);
- if (active_doc == doc)
+ if (active_view == data->view)
{
GAction *action;
@@ -1074,11 +1140,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 +1152,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);
}
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 +1177,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 +1189,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),
+ VIEW_DATA_KEY,
+ data,
+ (GDestroyNotify) view_data_free);
}
static void
@@ -1153,13 +1205,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), VIEW_DATA_KEY, NULL);
}
static void
@@ -1188,8 +1235,14 @@ 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),
+ VIEW_DATA_KEY,
+ data,
+ (GDestroyNotify) view_data_free);
- set_auto_spell_from_metadata (plugin, view);
+ set_auto_spell_from_metadata (data);
}
priv->tab_added_id = g_signal_connect (priv->window,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]