[evolution/webkit-composer: 101/185] Optimize e_spell_checker_list_available_dicts()



commit 78f0b4a3005a0c598f132399ec4784095e8c390b
Author: Dan Vrátil <dvratil redhat com>
Date:   Sun Dec 9 21:48:00 2012 +0100

    Optimize e_spell_checker_list_available_dicts()
    
    Use a static cache to store all listed dictionaries to minimize number
    of enchant_broker_list_dicts() calls.
    
    Possibly fixes bug #689626

 e-util/e-editor-actions.c        |  3 --
 e-util/e-spell-checker.c         | 77 ++++++++++++++++++++--------------------
 e-util/e-spell-checker.h         |  2 +-
 modules/mail/em-composer-prefs.c |  3 +-
 4 files changed, 41 insertions(+), 44 deletions(-)
---
diff --git a/e-util/e-editor-actions.c b/e-util/e-editor-actions.c
index 6fb61f5..7dc3e31 100644
--- a/e-util/e-editor-actions.c
+++ b/e-util/e-editor-actions.c
@@ -1699,8 +1699,6 @@ editor_actions_setup_languages_menu (EEditor *editor)
                        e_spell_dictionary_get_code (dictionary),
                        e_spell_dictionary_get_code (dictionary),
                        GTK_UI_MANAGER_AUTO, FALSE);
-
-               g_object_unref (dictionary);
        }
 
        g_list_free (available_dicts);
@@ -1776,7 +1774,6 @@ editor_actions_setup_spell_check_menu (EEditor *editor)
                        action_name, action_name,
                        GTK_UI_MANAGER_AUTO, FALSE);
 
-               g_object_unref (dictionary);
                g_free (action_label);
                g_free (action_name);
        }
diff --git a/e-util/e-spell-checker.c b/e-util/e-spell-checker.c
index f10438b..de4317b 100644
--- a/e-util/e-spell-checker.c
+++ b/e-util/e-spell-checker.c
@@ -38,9 +38,12 @@ G_DEFINE_TYPE_EXTENDED (
                WEBKIT_TYPE_SPELL_CHECKER,
                e_spell_checker_init_webkit_checker))
 
+
+static ESpellChecker *s_instance = NULL;
+
 struct _ESpellCheckerPrivate {
        GList *active;
-
+       GHashTable *dictionaries_cache;
        EnchantBroker *broker;
 };
 
@@ -248,7 +251,7 @@ wksc_update_languages (WebKitSpellChecker *webkit_checker,
        }
 
        e_spell_checker_set_active_dictionaries (checker, dictionaries);
-       g_list_free_full (dictionaries, g_object_unref);
+       g_list_free (dictionaries);
 }
 
 
@@ -344,19 +347,18 @@ e_spell_checker_init (ESpellChecker *checker)
                checker, E_TYPE_SPELL_CHECKER, ESpellCheckerPrivate);
 
        checker->priv->broker = enchant_broker_init ();
+       checker->priv->dictionaries_cache = NULL;
 }
 
 ESpellChecker *
-e_spell_checker_new (void)
+e_spell_checker_instance (void)
 {
-       return g_object_new (E_TYPE_SPELL_CHECKER, NULL);
-}
-
+       if (s_instance == NULL) {
+               s_instance = g_object_new (E_TYPE_SPELL_CHECKER, NULL);
+       }
 
-typedef struct  {
-       ESpellChecker *checker;
-       GList *dicts;
-} ListAvailDictsData;
+       return s_instance;
+}
 
 static void
 list_enchant_dicts (const char * const lang_tag,
@@ -365,16 +367,18 @@ list_enchant_dicts (const char * const lang_tag,
                    const char * const provider_file,
                    void * user_data)
 {
-       ListAvailDictsData *data = user_data;
+       ESpellChecker *checker = user_data;
        EnchantDict *dict;
 
-       dict = enchant_broker_request_dict (data->checker->priv->broker, lang_tag);
+       dict = enchant_broker_request_dict (checker->priv->broker, lang_tag);
        if (dict) {
                ESpellDictionary *e_dict;
 
-               e_dict = e_spell_dictionary_new (data->checker, dict);
+               e_dict = e_spell_dictionary_new (checker, dict);
 
-               data->dicts = g_list_prepend (data->dicts, e_dict);
+               g_hash_table_insert (
+                       checker->priv->dictionaries_cache,
+                       (gpointer) e_spell_dictionary_get_code (e_dict), e_dict);
        }
 }
 
@@ -386,24 +390,24 @@ list_enchant_dicts (const char * const lang_tag,
  * Returns list of all dictionaries available to the actual
  * spell-checking backend.
  *
- * Return value: a #GList of #ESpellDictionary. Free the list using g_list_free()
- *             when not needed anymore.
+ * Return value: new copy of #GList of #ESpellDictionary. The dictionaries are
+ * owned by the @checker and should not be free'd. The list should be free'd
+ * using g_list_free() when not neede anymore. [transfer-list]
  */
 GList *
 e_spell_checker_list_available_dicts (ESpellChecker *checker)
 {
-       ESpellChecker *e_checker;
-       ListAvailDictsData data = { 0 };
-
        g_return_val_if_fail (E_IS_SPELL_CHECKER (checker), NULL);
 
-       e_checker = E_SPELL_CHECKER (checker);
+       if (checker->priv->dictionaries_cache == NULL) {
 
-       data.checker = e_checker;
-       enchant_broker_list_dicts (
-               e_checker->priv->broker, list_enchant_dicts, &data);
+               checker->priv->dictionaries_cache = g_hash_table_new_full (
+                       g_str_hash, g_str_equal, NULL, g_object_unref);
+               enchant_broker_list_dicts (
+                       checker->priv->broker, list_enchant_dicts, checker);
+       }
 
-       return g_list_reverse (data.dicts);
+       return g_hash_table_get_values (checker->priv->dictionaries_cache);
 }
 
 /**
@@ -420,32 +424,29 @@ ESpellDictionary *
 e_spell_checker_lookup_dictionary (ESpellChecker *checker,
                                   const gchar *language_code)
 {
-       ESpellChecker *e_checker;
-       ESpellDictionary *e_dict;
+       ESpellDictionary *e_dict = NULL;
+       GList *dicts;
 
        g_return_val_if_fail (E_IS_SPELL_CHECKER (checker), NULL);
 
-       e_checker = E_SPELL_CHECKER (checker);
-
-       e_dict = NULL;
+       /* If the cache has not yet been initialized, do so - we will need
+        * it anyway, Otherwise is this call very cheap */
+       dicts = e_spell_checker_list_available_dicts (checker);
 
        if (!language_code) {
-               GList *dicts = e_spell_checker_list_available_dicts (checker);
-
                if (dicts) {
                        e_dict = g_object_ref (dicts->data);
-                       g_list_free_full (dicts, g_object_unref);
                }
        } else {
-               EnchantDict *dict;
-               dict = enchant_broker_request_dict (
-                       e_checker->priv->broker, language_code);
-               if (dict) {
-                       e_dict = e_spell_dictionary_new (checker, dict);
+               e_dict = g_hash_table_lookup (
+                       checker->priv->dictionaries_cache, language_code);
+               if (e_dict) {
+                       g_object_ref (e_dict);
                }
        }
 
-       return e_dict;
+       g_list_free (dicts);
+       return NULL;
 }
 
 /**
diff --git a/e-util/e-spell-checker.h b/e-util/e-spell-checker.h
index 3a38048..ff3b6eb 100644
--- a/e-util/e-spell-checker.h
+++ b/e-util/e-spell-checker.h
@@ -60,7 +60,7 @@ struct _ESpellCheckerClass {
 
 GType                  e_spell_checker_get_type        (void);
 
-ESpellChecker *                e_spell_checker_new             (void);
+ESpellChecker *                e_spell_checker_instance        (void);
 
 GList *                        e_spell_checker_list_available_dicts
                                                        (ESpellChecker *checker);
diff --git a/modules/mail/em-composer-prefs.c b/modules/mail/em-composer-prefs.c
index 346dbb9..3b2e661 100644
--- a/modules/mail/em-composer-prefs.c
+++ b/modules/mail/em-composer-prefs.c
@@ -54,7 +54,6 @@ composer_prefs_dispose (GObject *object)
        EMComposerPrefs *prefs = (EMComposerPrefs *) object;
 
        g_clear_object (&prefs->builder);
-       g_clear_object (&prefs->spell_checker);
 
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (em_composer_prefs_parent_class)->dispose (object);
@@ -261,7 +260,7 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
        e_load_ui_builder_definition (prefs->builder, "mail-config.ui");
 
 
-       prefs->spell_checker = e_spell_checker_new ();
+       prefs->spell_checker = e_spell_checker_instance();
 
        /** @HookPoint-EMConfig: Mail Composer Preferences
         * @Id: org.gnome.evolution.mail.composerPrefs


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