From 971bc5b709e8ec291dda44c24ef20cefe668bb6c Mon Sep 17 00:00:00 2001 From: Derek Atkins Date: Wed, 26 Dec 2007 05:17:37 +0000 Subject: [PATCH] Allow the user to permanently disable currency quotes (#499496) Patch by Daniel Harding git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16730 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/Account.c | 13 +-- src/engine/Period.c | 2 +- src/engine/gnc-commodity.c | 175 +++++++++++++++++++++++++++-- src/engine/gnc-commodity.h | 45 +++++++- src/gnome-utils/dialog-commodity.c | 4 +- 5 files changed, 218 insertions(+), 21 deletions(-) diff --git a/src/engine/Account.c b/src/engine/Account.c index 06672a24c7..74012b77a8 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -871,6 +871,7 @@ xaccCloneAccountCommon(const Account *from, QofBook *book) /* The new book should contain a commodity that matches * the one in the old book. Find it, use it. */ priv->commodity = gnc_commodity_obtain_twin(from_priv->commodity, book); + gnc_commodity_increment_usage_count(priv->commodity); priv->commodity_scu = from_priv->commodity_scu; priv->non_standard_scu = from_priv->non_standard_scu; @@ -1004,6 +1005,7 @@ xaccFreeAccount (Account *acc) priv->reconciled_balance = gnc_numeric_zero(); priv->type = ACCT_TYPE_NONE; + gnc_commodity_decrement_usage_count(priv->commodity); priv->commodity = NULL; priv->balance_dirty = FALSE; @@ -2066,7 +2068,9 @@ xaccAccountSetCommodity (Account * acc, gnc_commodity * com) return; xaccAccountBeginEdit(acc); + gnc_commodity_decrement_usage_count(priv->commodity); priv->commodity = com; + gnc_commodity_increment_usage_count(com); priv->commodity_scu = gnc_commodity_get_fraction(com); priv->non_standard_scu = FALSE; @@ -2085,15 +2089,6 @@ xaccAccountSetCommodity (Account * acc, gnc_commodity * com) priv->balance_dirty = TRUE; mark_account (acc); - if (gnc_commodity_is_iso(com)) { - /* compatability hack - Gnucash 1.8 gets currency quotes when a - non-default currency is assigned to an account. */ - gnc_commodity_begin_edit(com); - gnc_commodity_set_quote_flag(com, TRUE); - gnc_commodity_set_quote_source(com, - gnc_commodity_get_default_quote_source(com)); - gnc_commodity_commit_edit(com); - } xaccAccountCommitEdit(acc); } diff --git a/src/engine/Period.c b/src/engine/Period.c index 558d4604dc..eae54c5e70 100644 --- a/src/engine/Period.c +++ b/src/engine/Period.c @@ -538,7 +538,7 @@ gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query) /* Next, copy the commodity tables */ src_tbl = gnc_commodity_table_get_table (src_book); dst_tbl = gnc_commodity_table_get_table (dest_book); - gnc_commodity_table_copy (dst_tbl, src_tbl); + gnc_commodity_table_copy (dst_tbl, src_tbl, dest_book); /* Next, copy all of the accounts */ /* hack alert -- FIXME -- this should really be a merge, not a diff --git a/src/engine/gnc-commodity.c b/src/engine/gnc-commodity.c index dd8e321e25..87ee5efbb6 100644 --- a/src/engine/gnc-commodity.c +++ b/src/engine/gnc-commodity.c @@ -61,6 +61,10 @@ struct gnc_commodity_s gboolean quote_flag; /* user wants price quotes */ gnc_quote_source * quote_source; /* current/old source of quotes */ char * quote_tz; + + /* the number of accounts using this commodity - this field is not + * persisted */ + int usage_count; }; struct _GncCommodityClass @@ -624,6 +628,17 @@ gnc_commodity_destroy(gnc_commodity * cm) cm->mark = 0; +#if !ACCOUNTS_CLEANED_UP + /* Account objects are not actually cleaned up when a book is closed (in fact + * a memory leak), but commodities are, so in currently this warning gets hit + * quite frequently. Disable the check until cleaning up of accounts objects + * on close is implemented. */ + if(cm->usage_count != 0) { + PWARN("Destroying commodity (%p) with non-zero usage_count (%d).", cm, + cm->usage_count); + } +#endif + /* qof_instance_release (&cm->inst); */ g_object_unref(cm); } @@ -638,13 +653,15 @@ gnc_commodity_copy(gnc_commodity * dest, gnc_commodity *src) gnc_commodity_set_quote_flag (dest, src->quote_flag); gnc_commodity_set_quote_source (dest, gnc_commodity_get_quote_source (src)); gnc_commodity_set_quote_tz (dest, src->quote_tz); + kvp_frame_delete (dest->inst.kvp_data); + dest->inst.kvp_data = kvp_frame_copy (src->inst.kvp_data); } gnc_commodity * -gnc_commodity_clone(gnc_commodity *src) +gnc_commodity_clone(gnc_commodity *src, QofBook *dest_book) { gnc_commodity * dest = g_object_new(GNC_TYPE_COMMODITY, NULL); - /* qof_instance_init_data (&dest->inst, GNC_ID_COMMODITY, src->inst.book); */ + qof_instance_init_data (&dest->inst, GNC_ID_COMMODITY, dest_book); dest->fullname = CACHE_INSERT(src->fullname); dest->mnemonic = CACHE_INSERT(src->mnemonic); @@ -659,6 +676,9 @@ gnc_commodity_clone(gnc_commodity *src) gnc_commodity_set_quote_source (dest, gnc_commodity_get_quote_source (src)); + kvp_frame_delete (dest->inst.kvp_data); + dest->inst.kvp_data = kvp_frame_copy (src->inst.kvp_data); + reset_printname(dest); reset_unique_name(dest); @@ -774,6 +794,21 @@ gnc_commodity_get_mark(const gnc_commodity * cm) return cm->mark; } +/******************************************************************** + * gnc_commodity_get_auto_quote_control_flag + ********************************************************************/ + +static gboolean +gnc_commodity_get_auto_quote_control_flag(const gnc_commodity *cm) +{ + const char *str; + + if(!cm) return FALSE; + + str = kvp_frame_get_string(cm->inst.kvp_data, "auto_quote_control"); + return !str || (strcmp(str, "false") != 0); +} + /******************************************************************** * gnc_commodity_get_quote_flag ********************************************************************/ @@ -928,6 +963,60 @@ gnc_commodity_set_mark(gnc_commodity * cm, gint16 mark) cm->mark = mark; } +/******************************************************************** + * gnc_commodity_set_auto_quote_control_flag + ********************************************************************/ + +static void +gnc_commodity_set_auto_quote_control_flag(gnc_commodity *cm, + const gboolean flag) +{ + ENTER ("(cm=%p, flag=%d)", cm, flag); + + if(!cm) { + LEAVE(""); + return; + } + + gnc_commodity_begin_edit(cm); + kvp_frame_set_string(cm->inst.kvp_data, + "auto_quote_control", flag ? NULL : "false"); + mark_commodity_dirty(cm); + gnc_commodity_commit_edit(cm); + LEAVE(""); +} + +/******************************************************************** + * gnc_commodity_user_set_quote_flag + ********************************************************************/ + +void +gnc_commodity_user_set_quote_flag(gnc_commodity *cm, const gboolean flag) +{ + ENTER ("(cm=%p, flag=%d)", cm, flag); + + if(!cm) { + LEAVE(""); + return; + } + + gnc_commodity_begin_edit(cm); + gnc_commodity_set_quote_flag(cm, flag); + if(gnc_commodity_is_iso(cm)) { + /* For currencies, disable auto quote control if the quote flag is being + * changed from its default value and enable it if the quote flag is being + * reset to its default value. The defaults for the quote flag are + * disabled if no accounts are using the currency, and true otherwise. + * Thus enable auto quote control if flag is FALSE and there are not any + * accounts using this currency OR flag is TRUE and there are accounts + * using this currency; otherwise disable auto quote control */ + gnc_commodity_set_auto_quote_control_flag(cm, + (!flag && (cm->usage_count == 0)) || (flag && (cm->usage_count != 0))); + } + gnc_commodity_commit_edit(cm); + LEAVE(""); +} + /******************************************************************** * gnc_commodity_set_quote_flag ********************************************************************/ @@ -981,6 +1070,70 @@ gnc_commodity_set_quote_tz(gnc_commodity *cm, const char *tz) LEAVE(" "); } +/******************************************************************** + * gnc_commodity_increment_usage_count + ********************************************************************/ + +void +gnc_commodity_increment_usage_count(gnc_commodity *cm) +{ + const char *str; + + ENTER("(cm=%p)", cm); + + if(!cm) { + LEAVE(""); + return; + } + + if((cm->usage_count == 0) && !cm->quote_flag + && gnc_commodity_get_auto_quote_control_flag(cm) + && gnc_commodity_is_iso(cm)) { + /* compatability hack - Gnucash 1.8 gets currency quotes when a + non-default currency is assigned to an account. */ + gnc_commodity_begin_edit(cm); + gnc_commodity_set_quote_flag(cm, TRUE); + gnc_commodity_set_quote_source(cm, + gnc_commodity_get_default_quote_source(cm)); + gnc_commodity_commit_edit(cm); + } + cm->usage_count++; + LEAVE("(usage_count=%d)", cm->usage_count); +} + +/******************************************************************** + * gnc_commodity_decrement_usage_count + ********************************************************************/ + +void +gnc_commodity_decrement_usage_count(gnc_commodity *cm) +{ + const char *str; + + ENTER("(cm=%p)", cm); + + if(!cm) { + LEAVE(""); + return; + } + + if(cm->usage_count == 0) { + PWARN("usage_count already zero"); + LEAVE(""); + return; + } + + cm->usage_count--; + if((cm->usage_count == 0) && cm->quote_flag + && gnc_commodity_get_auto_quote_control_flag(cm) + && gnc_commodity_is_iso(cm)) { + /* if this is a currency with auto quote control enabled and no more + * accounts reference this currency, disable quote retrieval */ + gnc_commodity_set_quote_flag(cm, FALSE); + } + LEAVE("(usage_count=%d)", cm->usage_count); +} + /********************************************************************\ \********************************************************************/ @@ -1122,7 +1275,7 @@ gnc_commodity_obtain_twin (gnc_commodity *from, QofBook *book) twin = gnc_commodity_table_lookup_unique (comtbl, ucom); if (!twin) { - twin = gnc_commodity_clone (from); + twin = gnc_commodity_clone (from, book); twin = gnc_commodity_table_insert (comtbl, twin); } return twin; @@ -1779,19 +1932,27 @@ gnc_commodity_table_equal(gnc_commodity_table *t_1, /* =========================================================== */ +typedef struct { + gnc_commodity_table *dest; + QofBook *dest_book; +} table_copy_helper_data; + static gboolean table_copy_helper (gnc_commodity *src_cm, gpointer user_data) { - gnc_commodity_table *dest = user_data; - gnc_commodity_table_insert (dest, gnc_commodity_clone (src_cm)); + table_copy_helper_data *data = user_data; + gnc_commodity_table_insert (data->dest, + gnc_commodity_clone (src_cm, data->dest_book)); return TRUE; } void gnc_commodity_table_copy(gnc_commodity_table *dest, - gnc_commodity_table *src) + gnc_commodity_table *src, + QofBook *dest_book) { - gnc_commodity_table_foreach_commodity (src, table_copy_helper, dest); + table_copy_helper_data data = {dest, dest_book}; + gnc_commodity_table_foreach_commodity (src, table_copy_helper, &data); } /******************************************************************** diff --git a/src/engine/gnc-commodity.h b/src/engine/gnc-commodity.h index 5826c9ee2d..954d603454 100644 --- a/src/engine/gnc-commodity.h +++ b/src/engine/gnc-commodity.h @@ -312,7 +312,7 @@ void gnc_commodity_destroy(gnc_commodity * cm); void gnc_commodity_copy(gnc_commodity * dest, gnc_commodity *src); /** allocate and copy */ -gnc_commodity * gnc_commodity_clone(gnc_commodity *src); +gnc_commodity * gnc_commodity_clone(gnc_commodity *src, QofBook *dest_book); /** @} */ @@ -547,6 +547,23 @@ void gnc_commodity_set_cusip(gnc_commodity * cm, const char * cusip); */ void gnc_commodity_set_fraction(gnc_commodity * cm, int smallest_fraction); +/** Set the automatic price quote flag for the specified commodity, + * based on user input. This flag indicates whether stock quotes + * should be retrieved for the specified stock. + * + * It is necessary to have a separate function to distinguish when + * this setting is being modified by a user so that the + * auto-enabling/auto-disabling of currencies can be handled + * properly. + * + * @param cm A pointer to a commodity data structure. + * + * @param flag TRUE if quotes should be pulled for this commodity, FALSE + * otherwise. + */ +void gnc_commodity_user_set_quote_flag(gnc_commodity *cm, + const gboolean flag); + /** Set the automatic price quote flag for the specified commodity. * This flag indicates whether stock quotes should be retrieved for * the specified stock. @@ -584,6 +601,29 @@ void gnc_commodity_set_quote_tz(gnc_commodity *cm, const char *tz); /** @} */ +/** @name Commodity Usage Count Adjustment Routines +@{ +*/ + +/** Increment a commodity's internal counter that tracks how many + * accounts are using that commodity. For currencies, this may have + * the side effect of enabling the commodity's quote flag. + * + * @param cm A pointer to a commodity data structure. + */ +void +gnc_commodity_increment_usage_count(gnc_commodity *cm); + +/** Decrement a commodity's internal counter that tracks how many + * accounts are using that commodity. For currencies, this may have + * the side effect of disabling the commodity's quote flag. + * + * @param cm A pointer to a commodity data structure. + */ +void +gnc_commodity_decrement_usage_count(gnc_commodity *cm); +/** @} */ + /** @name Commodity Comparison @{ @@ -653,7 +693,8 @@ gboolean gnc_commodity_table_equal(gnc_commodity_table *t_1, /** copy all commodities from src table to dest table */ void gnc_commodity_table_copy(gnc_commodity_table *dest, - gnc_commodity_table *src); + gnc_commodity_table *src, + QofBook *dest_book); /** @} */ /* ---------------------------------------------------------- */ /** @name Commodity Table Lookup functions diff --git a/src/gnome-utils/dialog-commodity.c b/src/gnome-utils/dialog-commodity.c index ce4c4b8cf3..e5fffa94ab 100644 --- a/src/gnome-utils/dialog-commodity.c +++ b/src/gnome-utils/dialog-commodity.c @@ -1194,7 +1194,7 @@ gnc_ui_commodity_dialog_to_object(CommodityWindow * w) if (w->edit_commodity) { c = w->edit_commodity; gnc_commodity_begin_edit(c); - gnc_commodity_set_quote_flag (c, gtk_toggle_button_get_active + gnc_commodity_user_set_quote_flag (c, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w->get_quote_check))); selection = gtk_combo_box_get_active(GTK_COMBO_BOX(w->quote_tz_menu)); string = gnc_timezone_menu_position_to_string(selection); @@ -1237,7 +1237,7 @@ gnc_ui_commodity_dialog_to_object(CommodityWindow * w) gnc_commodity_set_fraction (c, fraction); } - gnc_commodity_set_quote_flag (c, gtk_toggle_button_get_active + gnc_commodity_user_set_quote_flag (c, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w->get_quote_check))); for (type = SOURCE_SINGLE; type < SOURCE_MAX; type++) {