mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bug 647805 - Interdependent report options fail to change state after using apply for a limited number of times
On the C side an SCM guile_options object is wrapped in a GNCOptionDB. This is however a multi-to-one relationship. That is there can be several GNCOptionDBs wrapping the same SCM guile_options object. This happens for example when a report is open together with its Options dialog. Both manager their own GNCOptionDB object while both wrap the same SCM guile_options. The problem in this bug was caused by a callback function picking the wrong GNCOptionDB based on the given SCM guile_options object. Which GNCOptionDB got picked was completely dependent on how g_hash_table_foreach would cycle through the stored dbs. It appears this is dependent on the in-memory order of the hash table's values. By being more selective of which GNCOptionDB we're looking for, this could be circumvented. The GNCOptionDB we want is the one related to the open report options dialog. This GNCOptionDB is different from the one managed by the report tab in that it has callbacks set. So from now on we search for a GNCOptionDB that wraps the give SCM guile_options and has one particular callback set.
This commit is contained in:
@@ -233,35 +233,6 @@ gnc_option_db_new(SCM guile_options)
|
||||
return odb;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GNCOptionDB *odb;
|
||||
SCM guile_options;
|
||||
} ODBFindInfo;
|
||||
|
||||
static void
|
||||
option_db_finder (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
ODBFindInfo *find_info = data;
|
||||
GNCOptionDB *odb = value;
|
||||
|
||||
if (odb && (odb->guile_options == find_info->guile_options))
|
||||
find_info->odb = odb;
|
||||
}
|
||||
|
||||
static GNCOptionDB *
|
||||
gnc_option_db_find (SCM guile_options)
|
||||
{
|
||||
ODBFindInfo find_info;
|
||||
|
||||
find_info.odb = NULL;
|
||||
find_info.guile_options = guile_options;
|
||||
|
||||
g_hash_table_foreach (option_dbs, option_db_finder, &find_info);
|
||||
|
||||
return find_info.odb;
|
||||
}
|
||||
|
||||
/* Create an option DB for a particular data type */
|
||||
GNCOptionDB *
|
||||
gnc_option_db_new_for_type(QofIdType id_type)
|
||||
@@ -2634,6 +2605,27 @@ gnc_date_option_value_get_relative (SCM option_value)
|
||||
return scm_call_1 (getters.date_option_value_relative, option_value);
|
||||
}
|
||||
|
||||
static int
|
||||
find_option_db_with_selectable_pred (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
SCM guile_options = data;
|
||||
GNCOptionDB *odb = value;
|
||||
|
||||
if (odb && (odb->guile_options == guile_options)
|
||||
&& odb->set_selectable )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
static GNCOptionDB *
|
||||
find_option_db_with_selectable (SCM guile_options)
|
||||
{
|
||||
return g_hash_table_find (option_dbs, find_option_db_with_selectable_pred,
|
||||
guile_options);
|
||||
}
|
||||
|
||||
/*******************************************************************\
|
||||
* gnc_option_db_set_option_selectable_by_name *
|
||||
* set the sensitivity of the option widget *
|
||||
@@ -2645,7 +2637,7 @@ gnc_date_option_value_get_relative (SCM option_value)
|
||||
* Return: SCM value *
|
||||
\*******************************************************************/
|
||||
void
|
||||
gnc_option_db_set_option_selectable_by_name(SCM guile_option,
|
||||
gnc_option_db_set_option_selectable_by_name(SCM guile_options,
|
||||
const char *section,
|
||||
const char *name,
|
||||
gboolean selectable)
|
||||
@@ -2653,7 +2645,7 @@ gnc_option_db_set_option_selectable_by_name(SCM guile_option,
|
||||
GNCOptionDB *odb;
|
||||
GNCOption *option;
|
||||
|
||||
odb = gnc_option_db_find (guile_option);
|
||||
odb = find_option_db_with_selectable (guile_options);
|
||||
if (!odb)
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user