gnucash maint: Multiple changes pushed

Geert Janssens gjanssens at code.gnucash.org
Thu Sep 27 16:00:03 EDT 2018


Updated	 via  https://github.com/Gnucash/gnucash/commit/20942827 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b6f2b111 (commit)
	from  https://github.com/Gnucash/gnucash/commit/02e3a747 (commit)



commit 2094282790818a2a09bcce6d023f9a8abcfaa7c3
Merge: 02e3a74 b6f2b11
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Thu Sep 27 21:57:39 2018 +0200

    Merge branch 'block-pref' of https://github.com/Bob-IT/gnucash into maint


commit b6f2b111bc2b9e701639eb4684bdbfe4bf4b97c9
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Sep 7 11:44:47 2018 +0100

    Block registered prefs when preference dialogue loaded
    
    When the preference dialogue is loaded and options are set, the ones
    with registered callbacks fire causing parts of Gnucash to be updated.
    This was observed with gnc_split_register_load being executed 5 times
    for each open register when the preference dialogue was loaded.
    
    To overcome this, a couple of functions have been created to block and
    unblock all registered prefs and used while the preference dialogue is
    loaded.

diff --git a/gnucash/gnome-utils/dialog-preferences.c b/gnucash/gnome-utils/dialog-preferences.c
index 2e4e779..98c0801 100644
--- a/gnucash/gnome-utils/dialog-preferences.c
+++ b/gnucash/gnome-utils/dialog-preferences.c
@@ -1153,9 +1153,8 @@ gnc_prefs_connect_one (const gchar *name,
         GList* child = gtk_container_get_children(GTK_CONTAINER(widget));
         widget_child = child->data;
         g_list_free(child);
-        DEBUG("  %s - hbox", name);
-        DEBUG("Hbox widget type is %s and name is %s", gtk_widget_get_name(GTK_WIDGET(widget_child)), name);
-
+        DEBUG("  %s - box", name);
+        DEBUG("Box widget type is %s and name is %s", gtk_widget_get_name(GTK_WIDGET(widget_child)), name);
         if (GNC_IS_CURRENCY_EDIT(widget_child))
         {
             DEBUG("  %s - currency_edit", name);
@@ -1163,7 +1162,7 @@ gnc_prefs_connect_one (const gchar *name,
         }
         else if (GNC_IS_PERIOD_SELECT(widget_child))
         {
-            DEBUG("  %s - period_Select", name);
+            DEBUG("  %s - period_select", name);
             gnc_prefs_connect_period_select(GNC_PERIOD_SELECT(widget_child), name );
         }
         else if (GNC_IS_DATE_EDIT(widget_child))
@@ -1173,7 +1172,7 @@ gnc_prefs_connect_one (const gchar *name,
         }
         else if (GTK_FILE_CHOOSER_BUTTON(widget_child))
         {
-            DEBUG("  %s - file chooser buuton", name);
+            DEBUG("  %s - file chooser button", name);
             gnc_prefs_connect_file_chooser_button(GTK_FILE_CHOOSER_BUTTON(widget_child), name );
         }
     }
@@ -1344,7 +1343,9 @@ gnc_preferences_dialog_create(GtkWindow *parent)
     gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
 
     DEBUG("We have the following interesting widgets:");
+    gnc_prefs_block_all(); // Block All Registered callbacks
     g_hash_table_foreach(prefs_table, (GHFunc)gnc_prefs_connect_one, dialog);
+    gnc_prefs_unblock_all(); // UnBlock All Registered callbacks
     DEBUG("Done with interesting widgets.");
 
     /* Other stuff */
diff --git a/libgnucash/app-utils/gnc-gsettings.c b/libgnucash/app-utils/gnc-gsettings.c
index 6e174ee..d2f0fc6 100644
--- a/libgnucash/app-utils/gnc-gsettings.c
+++ b/libgnucash/app-utils/gnc-gsettings.c
@@ -53,6 +53,8 @@ static GHashTable *schema_hash = NULL;
 static const gchar *gsettings_prefix;
 static xmlExternalEntityLoader defaultEntityLoader = NULL;
 
+static GHashTable *registered_handlers_hash = NULL;
+
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = "gnc.app-utils.gsettings";
 
@@ -131,6 +133,19 @@ static GSettings * gnc_gsettings_get_settings_ptr (const gchar *schema_str)
     return gset;
 }
 
+static void
+handlers_hash_block_helper (gpointer key, gpointer settings_ptr, gpointer pointer)
+{
+    g_signal_handler_block (settings_ptr, (gulong)key); // block signal_handler
+    PINFO("Block handler_id %ld for settings_ptr %p", (gulong)key, settings_ptr);
+}
+
+static void
+handlers_hash_unblock_helper (gpointer key, gpointer settings_ptr, gpointer pointer)
+{
+    g_signal_handler_unblock (settings_ptr, (gulong)key); // unblock signal_handler
+    PINFO("UnBlock handler_id %ld for settings_ptr %p", (gulong)key, settings_ptr);
+}
 
 /************************************************************/
 /*                      GSettings Utilities                 */
@@ -203,6 +218,17 @@ gnc_gsettings_register_cb (const gchar *schema,
 
     retval = g_signal_connect (settings_ptr, signal, G_CALLBACK (func), user_data);
 
+    if (!registered_handlers_hash)
+        registered_handlers_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+    if (retval != 0)
+    {
+        g_hash_table_insert (registered_handlers_hash,
+                             GINT_TO_POINTER(retval), settings_ptr); //key, value
+
+        PINFO("schema: %s, key: %s, settings_ptr: %p, handler_id: %ld",
+               schema, key, settings_ptr, retval);
+    }
     g_free (signal);
 
     LEAVE("");
@@ -218,6 +244,7 @@ gnc_gsettings_remove_cb_by_func (const gchar *schema,
 {
     gint matched = 0;
     GQuark quark = 0;
+    gulong handler_id = 0;
 
     GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
     g_return_if_fail (G_IS_SETTINGS (settings_ptr));
@@ -228,7 +255,7 @@ gnc_gsettings_remove_cb_by_func (const gchar *schema,
     if ((key) && (gnc_gsettings_is_valid_key(settings_ptr, key)))
         quark = g_quark_from_string (key);
 
-    matched = g_signal_handlers_disconnect_matched (
+    handler_id = g_signal_handler_find (
                   settings_ptr,
                   G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
                   g_signal_lookup ("changed", G_TYPE_SETTINGS), /* signal_id */
@@ -236,7 +263,24 @@ gnc_gsettings_remove_cb_by_func (const gchar *schema,
                   NULL, /* closure */
                   G_CALLBACK (func), /* callback function */
                   user_data);
-    LEAVE ("Schema: %s, key: %s - removed %d handlers for 'changed' signal", schema, key, matched);
+
+    while (handler_id)
+    {
+        matched ++;
+        gnc_gsettings_remove_cb_by_id (schema, handler_id);
+
+        handler_id = g_signal_handler_find (
+                      settings_ptr,
+                      G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+                      g_signal_lookup ("changed", G_TYPE_SETTINGS), /* signal_id */
+                      quark,   /* signal_detail */
+                      NULL, /* closure */
+                      G_CALLBACK (func), /* callback function */
+                      user_data);
+    }
+
+    LEAVE ("Schema: %s, key: %s, hashtable size: %d - removed %d handlers for 'changed' signal",
+            schema, key, g_hash_table_size (registered_handlers_hash), matched);
 }
 
 
@@ -247,7 +291,15 @@ gnc_gsettings_remove_cb_by_id (const gchar *schema,
     GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
     g_return_if_fail (G_IS_SETTINGS (settings_ptr));
 
+    ENTER ();
+
     g_signal_handler_disconnect (settings_ptr, handlerid);
+
+    // remove the handlerid from the registerered_handlers_hash
+    g_hash_table_remove (registered_handlers_hash, GINT_TO_POINTER(handlerid));
+
+    LEAVE ("Schema: %s, handlerid: %d, hashtable size: %d - removed for handler",
+            schema, handlerid, g_hash_table_size (registered_handlers_hash));
 }
 
 
@@ -600,6 +652,8 @@ void gnc_gsettings_load_backend (void)
     prefsbackend->set_value = gnc_gsettings_set_value;
     prefsbackend->reset = gnc_gsettings_reset;
     prefsbackend->reset_group = gnc_gsettings_reset_schema;
+    prefsbackend->block_all = gnc_gsettings_block_all;
+    prefsbackend->unblock_all = gnc_gsettings_unblock_all;
 
     LEAVE("Prefsbackend bind = %p", prefsbackend->bind);
 }
@@ -850,3 +904,21 @@ void gnc_gsettings_version_upgrade (void)
     if (cur_maj_min > old_maj_min)
         gnc_gsettings_set_int (GNC_PREFS_GROUP_GENERAL, GNC_PREF_VERSION, cur_maj_min);
 }
+
+
+void gnc_gsettings_block_all (void)
+{
+    PINFO("block registered_handlers_hash list size is %d",
+           g_hash_table_size (registered_handlers_hash));
+    g_hash_table_foreach (registered_handlers_hash,
+                          handlers_hash_block_helper, NULL);
+}
+
+
+void gnc_gsettings_unblock_all (void)
+{
+    PINFO("unblock registered_handlers_hash list size is %d",
+           g_hash_table_size (registered_handlers_hash));
+    g_hash_table_foreach (registered_handlers_hash,
+                          handlers_hash_unblock_helper, NULL);
+}
diff --git a/libgnucash/app-utils/gnc-gsettings.h b/libgnucash/app-utils/gnc-gsettings.h
index 44dcb99..7f05868 100644
--- a/libgnucash/app-utils/gnc-gsettings.h
+++ b/libgnucash/app-utils/gnc-gsettings.h
@@ -86,6 +86,16 @@ void gnc_gsettings_set_prefix (const gchar *prefix);
 const gchar *gnc_gsettings_get_prefix (void);
 
 
+/** Block all prefs callbacks, used while preference dialog is loaded.
+ */
+void gnc_gsettings_block_all (void);
+
+
+/** UnBlock all prefs callbacks, used while preference dialog is loaded.
+ */
+void gnc_gsettings_unblock_all (void);
+
+
 /** @name Listening for changes
  @{
 */
diff --git a/libgnucash/core-utils/gnc-prefs-p.h b/libgnucash/core-utils/gnc-prefs-p.h
index b780fee..a5ab855 100644
--- a/libgnucash/core-utils/gnc-prefs-p.h
+++ b/libgnucash/core-utils/gnc-prefs-p.h
@@ -104,6 +104,10 @@ typedef struct
 
     void (*reset_group) (const gchar *group);
 
+    void (*block_all) (void);
+
+    void (*unblock_all) (void);
+
 } PrefsBackend;
 
 extern PrefsBackend *prefsbackend;
diff --git a/libgnucash/core-utils/gnc-prefs.c b/libgnucash/core-utils/gnc-prefs.c
index 73eec92..d59e91f 100644
--- a/libgnucash/core-utils/gnc-prefs.c
+++ b/libgnucash/core-utils/gnc-prefs.c
@@ -368,3 +368,14 @@ gboolean gnc_prefs_is_set_up (void)
     return (prefsbackend !=NULL);
 }
 
+void gnc_prefs_block_all (void)
+{
+    if (prefsbackend && prefsbackend->block_all)
+        (prefsbackend->block_all) ();
+}
+
+void gnc_prefs_unblock_all (void)
+{
+    if (prefsbackend && prefsbackend->unblock_all)
+        (prefsbackend->unblock_all) ();
+}
diff --git a/libgnucash/core-utils/gnc-prefs.h b/libgnucash/core-utils/gnc-prefs.h
index 41c241d..c665a26 100644
--- a/libgnucash/core-utils/gnc-prefs.h
+++ b/libgnucash/core-utils/gnc-prefs.h
@@ -124,6 +124,14 @@ guint gnc_prefs_get_long_version( void );
 */
 gboolean gnc_prefs_is_set_up (void);
 
+/** Block all preference callbacks
+*/
+void gnc_prefs_block_all (void);
+
+/** Unblock all preferences callbacks
+*/
+void gnc_prefs_unblock_all (void);
+
 /** @name Listening for changes
  @{
 */



Summary of changes:
 gnucash/gnome-utils/dialog-preferences.c | 11 ++---
 libgnucash/app-utils/gnc-gsettings.c     | 76 +++++++++++++++++++++++++++++++-
 libgnucash/app-utils/gnc-gsettings.h     | 10 +++++
 libgnucash/core-utils/gnc-prefs-p.h      |  4 ++
 libgnucash/core-utils/gnc-prefs.c        | 11 +++++
 libgnucash/core-utils/gnc-prefs.h        |  8 ++++
 6 files changed, 113 insertions(+), 7 deletions(-)



More information about the gnucash-changes mailing list