2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc-commodity.c -- api for tradable commodities (incl. currency) *
|
|
|
|
* Copyright (C) 2000 Bill Gribble *
|
2003-06-10 17:22:47 -05:00
|
|
|
* Copyright (C) 2001,2003 Linas Vepstas <linas@linas.org> *
|
2006-01-23 00:38:20 -06:00
|
|
|
* Copyright (c) 2006 David Hampton <hampton@employees.org> *
|
2001-08-07 18:36:04 -05:00
|
|
|
* *
|
|
|
|
* 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 the Free Software Foundation; either version 2 of *
|
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License*
|
|
|
|
* along with this program; if not, contact: *
|
|
|
|
* *
|
|
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
2005-11-16 23:35:02 -06:00
|
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
2001-08-07 18:36:04 -05:00
|
|
|
* *
|
|
|
|
*******************************************************************/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2005-11-19 17:53:34 -06:00
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gi18n.h>
|
2003-07-01 22:35:20 -05:00
|
|
|
#include <ctype.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2003-07-26 03:08:20 -05:00
|
|
|
#include <stdlib.h>
|
2003-07-03 17:40:18 -05:00
|
|
|
#include <regex.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
#include "gnc-commodity.h"
|
2014-03-25 19:07:49 -05:00
|
|
|
#include "gnc-locale-utils.h"
|
2013-10-07 09:06:23 -05:00
|
|
|
#include "gnc-prefs.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static QofLogModule log_module = GNC_MOD_COMMODITY;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2003-06-10 17:22:47 -05:00
|
|
|
/* Parts per unit is nominal, i.e. number of 'partname' units in
|
2001-08-07 18:36:04 -05:00
|
|
|
* a 'unitname' unit. fraction is transactional, i.e. how many
|
|
|
|
* of the smallest-transactional-units of the currency are there
|
2010-03-02 15:40:28 -06:00
|
|
|
* in a 'unitname' unit. */
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
PROP_NAMESPACE,
|
|
|
|
PROP_FULL_NAME,
|
|
|
|
PROP_MNEMONIC,
|
|
|
|
PROP_PRINTNAME,
|
|
|
|
PROP_CUSIP,
|
|
|
|
PROP_FRACTION,
|
|
|
|
PROP_UNIQUE_NAME,
|
|
|
|
PROP_QUOTE_FLAG,
|
|
|
|
PROP_QUOTE_SOURCE,
|
|
|
|
PROP_QUOTE_TZ,
|
2008-08-01 11:02:07 -05:00
|
|
|
};
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
struct gnc_commodity_s
|
|
|
|
{
|
|
|
|
QofInstance inst;
|
2008-08-01 11:02:07 -05:00
|
|
|
};
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
typedef struct CommodityPrivate
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace *namespace;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
char * fullname;
|
|
|
|
char * mnemonic;
|
|
|
|
char * printname;
|
|
|
|
char * cusip; /* CUSIP or other identifying code */
|
|
|
|
int fraction;
|
|
|
|
char * unique_name;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean quote_flag; /* user wants price quotes */
|
|
|
|
gnc_quote_source * quote_source; /* current/old source of quotes */
|
|
|
|
char * quote_tz;
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* the number of accounts using this commodity - this field is not
|
|
|
|
* persisted */
|
|
|
|
int usage_count;
|
2013-11-20 22:57:30 -06:00
|
|
|
|
|
|
|
/* the default display_symbol, set in iso-4217-currencies at start-up */
|
|
|
|
const char * default_symbol;
|
2008-08-01 11:02:07 -05:00
|
|
|
} CommodityPrivate;
|
|
|
|
|
|
|
|
#define GET_PRIVATE(o) \
|
|
|
|
(G_TYPE_INSTANCE_GET_PRIVATE((o), GNC_TYPE_COMMODITY, CommodityPrivate))
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2007-04-04 19:24:18 -05:00
|
|
|
struct _GncCommodityClass
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofInstanceClass parent_class;
|
2007-04-04 19:24:18 -05:00
|
|
|
};
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
static void commodity_free(gnc_commodity * cm);
|
2013-11-20 22:57:30 -06:00
|
|
|
static void gnc_commodity_set_default_symbol(gnc_commodity *, const char *);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
struct gnc_commodity_namespace_s
|
2003-08-10 22:06:17 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofInstance inst;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gchar * name;
|
|
|
|
gboolean iso4217;
|
|
|
|
GHashTable * cm_table;
|
|
|
|
GList * cm_list;
|
2001-08-07 18:36:04 -05:00
|
|
|
};
|
|
|
|
|
2007-04-04 19:24:18 -05:00
|
|
|
struct _GncCommodityNamespaceClass
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofInstanceClass parent_class;
|
2007-04-04 19:24:18 -05:00
|
|
|
};
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
struct gnc_commodity_table_s
|
2003-08-10 22:06:17 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GHashTable * ns_table;
|
|
|
|
GList * ns_list;
|
2001-08-07 18:36:04 -05:00
|
|
|
};
|
|
|
|
|
2003-08-10 22:06:17 -05:00
|
|
|
struct gnc_new_iso_code
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *old_code;
|
|
|
|
const char *new_code;
|
|
|
|
} gnc_new_iso_codes[] =
|
|
|
|
{
|
|
|
|
{"RUR", "RUB"}, /* Russian Ruble: RUR through 1997-12, RUB from 1998-01 onwards; see bug #393185 */
|
|
|
|
{"PLZ", "PLN"}, /* Polish Zloty */
|
|
|
|
{"UAG", "UAH"}, /* Ukraine Hryvnia */
|
|
|
|
{"NIS", "ILS"}, /* New Israeli Shekel: The informal abbreviation may be "NIS", but
|
2008-10-26 16:38:10 -05:00
|
|
|
its iso-4217 is clearly ILS and only this! Incorrectly changed
|
|
|
|
due to bug#152755 (Nov 2004) and changed back again by bug#492417
|
|
|
|
(Oct 2008). */
|
2010-03-02 15:40:28 -06:00
|
|
|
{"MXP", "MXN"}, /* Mexican (Nuevo) Peso */
|
|
|
|
{"TRL", "TRY"}, /* New Turkish Lira: changed 2005 */
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Only add currencies to this table when the old currency no longer
|
|
|
|
* exists in the file iso-4217-currencies.scm */
|
2003-05-29 18:47:52 -05:00
|
|
|
};
|
|
|
|
#define GNC_NEW_ISO_CODES \
|
|
|
|
(sizeof(gnc_new_iso_codes) / sizeof(struct gnc_new_iso_code))
|
2003-07-01 22:35:20 -05:00
|
|
|
|
|
|
|
static gboolean fq_is_installed = FALSE;
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
struct gnc_quote_source_s
|
|
|
|
{
|
|
|
|
gboolean supported;
|
|
|
|
QuoteSourceType type;
|
|
|
|
gint index;
|
|
|
|
char *user_name; /* User friendly name */
|
|
|
|
char *old_internal_name; /* Name used internally (deprecated) */
|
|
|
|
char *internal_name; /* Name used internally and by finance::quote. */
|
2003-07-01 22:35:20 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static gnc_quote_source currency_quote_source =
|
2010-03-02 15:40:28 -06:00
|
|
|
{ TRUE, 0, 0, "Currency", "CURRENCY", "currency" };
|
|
|
|
|
|
|
|
static gnc_quote_source single_quote_sources[] =
|
|
|
|
{
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "Amsterdam Euronext eXchange, NL", "AEX", "aex" },
|
|
|
|
{ FALSE, 0, 0, "AEX Futures (now in AEX)", "AEX_FUTURES", "aex_futures" },
|
|
|
|
{ FALSE, 0, 0, "AEX Options (now in AEX)", "AEX_OPTIONS", "aex_options" },
|
|
|
|
{ FALSE, 0, 0, "American International Assurance, HK", "AIAHK", "aiahk" },
|
|
|
|
{ FALSE, 0, 0, "Association of Mutual Funds in India", "AMFIINDIA", "amfiindia" },
|
|
|
|
{ FALSE, 0, 0, "Athens Stock Exchange, GR", "ASEGR", "asegr" },
|
|
|
|
{ FALSE, 0, 0, "Australian Stock Exchange, AU", "ASX", "asx" },
|
|
|
|
{ FALSE, 0, 0, "BMO NesbittBurns, CA", "BMONESBITTBURNS", "bmonesbittburns" },
|
|
|
|
{ FALSE, 0, 0, "BUX/Magyar Tökepiac, HU", "BUX", "bux" },
|
|
|
|
{ FALSE, 0, 0, "Cominvest, ex-Adig, DE", "COMINVEST", "cominvest" },
|
|
|
|
{ FALSE, 0, 0, "Deka Investments, DE", "DEKA", "deka" },
|
|
|
|
{ FALSE, 0, 0, "DWS, DE", "DWS", "dwsfunds" },
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "Fidelity Direct", "FIDELITY_DIRECT", "fidelity_direct" },
|
|
|
|
{ FALSE, 0, 0, "Finance Canada", "FINANCECANADA", "financecanada" },
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "Finanzpartner, DE", "FINANZPARTNER", "finanzpartner" },
|
|
|
|
{ FALSE, 0, 0, "First Trust Portfolios, US", "FTPORTFOLIOS_DIRECT", "ftportfolios_direct" },
|
|
|
|
{ FALSE, 0, 0, "Fund Library, CA", "FUNDLIBRARY", "fundlibrary" },
|
|
|
|
{ FALSE, 0, 0, "GoldMoney spot rates, JE", "GOLDMONEY", "goldmoney" },
|
|
|
|
{ FALSE, 0, 0, "HElsinki stock eXchange, FI", "HEX", "hex" },
|
|
|
|
{ FALSE, 0, 0, "Man Investments, AU", "maninv", "maninv" },
|
|
|
|
{ FALSE, 0, 0, "Morningstar, SE", "MORNINGSTAR", "morningstar" },
|
|
|
|
{ FALSE, 0, 0, "Motley Fool, US", "FOOL", "fool" },
|
|
|
|
{ FALSE, 0, 0, "New Zealand stock eXchange, NZ", "NZX", "nzx" },
|
|
|
|
{ FALSE, 0, 0, "Paris Stock Exchange/Boursorama, FR", "BOURSO", "bourso" },
|
|
|
|
{ FALSE, 0, 0, "Paris Stock Exchange/LeRevenu, FR", "LEREVENU", "lerevenu" },
|
|
|
|
{ FALSE, 0, 0, "Platinum Asset Management, AU", "PLATINUM", "platinum" },
|
|
|
|
{ FALSE, 0, 0, "Skandinaviska Enskilda Banken, SE", "SEB_FUNDS", "seb_funds" },
|
|
|
|
{ FALSE, 0, 0, "Sharenet, ZA", "ZA", "za" },
|
|
|
|
{ FALSE, 0, 0, "StockHouse Canada", "STOCKHOUSE_FUND", "stockhousecanada_fund" },
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "TD Waterhouse Canada", "TDWATERHOUSE", "tdwaterhouse" },
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "TD Efunds, CA", "TDEFUNDS", "tdefunds" },
|
|
|
|
{ FALSE, 0, 0, "TIAA-CREF, US", "TIAACREF", "tiaacref" },
|
|
|
|
{ FALSE, 0, 0, "Toronto Stock eXchange, CA", "TSX", "tsx" },
|
|
|
|
{ FALSE, 0, 0, "T. Rowe Price, US", "TRPRICE_DIRECT", "troweprice_direct" },
|
|
|
|
{ FALSE, 0, 0, "Trustnet, GB", "TRUSTNET", "trustnet" },
|
|
|
|
{ FALSE, 0, 0, "Union Investment, DE", "UNIONFUNDS", "unionfunds" },
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "US Treasury Bonds", "usfedbonds", "usfedbonds" },
|
|
|
|
{ FALSE, 0, 0, "US Govt. Thrift Savings Plan", "TSP", "tsp" },
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "Vanguard", "VANGUARD", "vanguard" }, /* No module seen in F::Q 1.17. */
|
|
|
|
{ FALSE, 0, 0, "VWD, DE (unmaintained)", "VWD", "vwd" },
|
|
|
|
{ FALSE, 0, 0, "Yahoo USA", "YAHOO", "yahoo" },
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "Yahoo Asia", "YAHOO_ASIA", "yahoo_asia" },
|
|
|
|
{ FALSE, 0, 0, "Yahoo Australia", "YAHOO_AUSTRALIA", "yahoo_australia" },
|
|
|
|
{ FALSE, 0, 0, "Yahoo Brasil", "YAHOO_BRASIL", "yahoo_brasil" },
|
|
|
|
{ FALSE, 0, 0, "Yahoo Europe", "YAHOO_EUROPE", "yahoo_europe" },
|
|
|
|
{ FALSE, 0, 0, "Yahoo New Zealand", "YAHOO_NZ", "yahoo_nz" },
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "Zuerich Investments (outdated)", "ZIFUNDS", "zifunds" }, /* Removed from F::Q 1.11. */
|
2003-07-01 22:35:20 -05:00
|
|
|
};
|
2010-03-02 15:40:28 -06:00
|
|
|
static gnc_quote_source multiple_quote_sources[] =
|
|
|
|
{
|
|
|
|
{ FALSE, 0, 0, "Asia (Yahoo, ...)", "ASIA", "asia" },
|
|
|
|
{ FALSE, 0, 0, "Australia (ASX, Yahoo, ...)", "AUSTRALIA", "australia" },
|
|
|
|
{ FALSE, 0, 0, "Brasil (Yahoo, ...)", "BRASIL", "brasil" },
|
|
|
|
{ FALSE, 0, 0, "Canada (Yahoo, ...)", "CANADA", "canada" },
|
|
|
|
{ FALSE, 0, 0, "Canada Mutual (Fund Library, ...)", "CANADAMUTUAL", "canadamutual" },
|
|
|
|
{ FALSE, 0, 0, "Dutch (AEX, ...)", "DUTCH", "dutch" },
|
|
|
|
{ FALSE, 0, 0, "Europe (Yahoo, ...)", "EUROPE", "europe" },
|
|
|
|
{ FALSE, 0, 0, "Greece (ASE, ...)", "GREECE", "greece" },
|
|
|
|
{ FALSE, 0, 0, "India Mutual (AMFI, ...)", "INDIAMUTUAL", "indiamutual" },
|
|
|
|
{ FALSE, 0, 0, "Fidelity (Fidelity, ...)", "FIDELITY", "fidelity" },
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "Finland (HEX, ...)", "FINLAND", "finland" },
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "First Trust (First Trust, ...)", "FTPORTFOLIOS", "ftportfolios" },
|
2010-04-23 15:10:35 -05:00
|
|
|
{ FALSE, 0, 0, "France (Boursorama, ...)", "FRANCE", "france" },
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "Nasdaq (Yahoo, ...)", "NASDAQ", "nasdaq" },
|
|
|
|
{ FALSE, 0, 0, "New Zealand (Yahoo, ...)", "NZ", "nz" },
|
|
|
|
{ FALSE, 0, 0, "NYSE (Yahoo, ...)", "NYSE", "nyse" },
|
2010-06-25 13:44:40 -05:00
|
|
|
/* { FALSE, 0, 0, "South Africa (Sharenet, ...)", "ZA", "za" }, */
|
2010-03-02 15:40:28 -06:00
|
|
|
{ FALSE, 0, 0, "T. Rowe Price", "TRPRICE", "troweprice" },
|
|
|
|
{ FALSE, 0, 0, "U.K. Unit Trusts", "UKUNITTRUSTS", "uk_unit_trusts" },
|
|
|
|
{ FALSE, 0, 0, "USA (Yahoo, Fool ...)", "USA", "usa" },
|
2003-07-01 22:35:20 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static const int num_single_quote_sources =
|
2010-03-02 15:40:28 -06:00
|
|
|
sizeof(single_quote_sources) / sizeof(gnc_quote_source);
|
2003-07-01 22:35:20 -05:00
|
|
|
static const int num_multiple_quote_sources =
|
2010-03-02 15:40:28 -06:00
|
|
|
sizeof(multiple_quote_sources) / sizeof(gnc_quote_source);
|
2003-07-01 22:35:20 -05:00
|
|
|
static GList *new_quote_sources = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_fq_installed
|
|
|
|
*
|
|
|
|
* This function indicates whether or not the Finance::Quote module
|
|
|
|
* is installed on a users computer.
|
|
|
|
********************************************************************/
|
|
|
|
gboolean
|
|
|
|
gnc_quote_source_fq_installed (void)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return fq_is_installed;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_num_entries
|
|
|
|
*
|
|
|
|
* Return the number of entries for a given type of price source.
|
|
|
|
********************************************************************/
|
|
|
|
gint gnc_quote_source_num_entries(QuoteSourceType type)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (type == SOURCE_CURRENCY)
|
|
|
|
return 1;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (type == SOURCE_SINGLE)
|
|
|
|
return num_single_quote_sources;
|
|
|
|
|
|
|
|
if (type == SOURCE_MULTI)
|
|
|
|
return num_multiple_quote_sources;
|
|
|
|
|
|
|
|
return g_list_length(new_quote_sources);
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_init_tables
|
|
|
|
*
|
|
|
|
* Update the type/index values for prices sources.
|
|
|
|
********************************************************************/
|
|
|
|
static void
|
|
|
|
gnc_quote_source_init_tables (void)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gint i;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (i = 0; i < num_single_quote_sources; i++)
|
|
|
|
{
|
|
|
|
single_quote_sources[i].type = SOURCE_SINGLE;
|
|
|
|
single_quote_sources[i].index = i;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (i = 0; i < num_multiple_quote_sources; i++)
|
|
|
|
{
|
|
|
|
multiple_quote_sources[i].type = SOURCE_MULTI;
|
|
|
|
multiple_quote_sources[i].index = i;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
currency_quote_source.type = SOURCE_CURRENCY;
|
|
|
|
currency_quote_source.index = 0;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_add_new
|
|
|
|
*
|
|
|
|
* Add a new price source. Called when unknown source names are found
|
|
|
|
* either in the F::Q installation (a newly available source) or in
|
|
|
|
* the user's data file (a source that has vanished but needs to be
|
|
|
|
* tracked.)
|
|
|
|
********************************************************************/
|
|
|
|
gnc_quote_source *
|
|
|
|
gnc_quote_source_add_new (const char *source_name, gboolean supported)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_quote_source *new_source;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
DEBUG("Creating new source %s", (source_name == NULL ? "(null)" : source_name));
|
|
|
|
new_source = malloc(sizeof(gnc_quote_source));
|
|
|
|
new_source->supported = supported;
|
|
|
|
new_source->type = SOURCE_UNKNOWN;
|
|
|
|
new_source->index = g_list_length(new_quote_sources);
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* This name can be changed if/when support for this price source is
|
|
|
|
* integrated into gnucash. */
|
2010-03-03 14:46:20 -06:00
|
|
|
new_source->user_name = g_strdup(source_name);
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* This name is permanent and must be kept the same if/when support
|
|
|
|
* for this price source is integrated into gnucash (i.e. for a
|
|
|
|
* nice user name). */
|
2010-03-03 14:46:20 -06:00
|
|
|
new_source->old_internal_name = g_strdup(source_name);
|
|
|
|
new_source->internal_name = g_strdup(source_name);
|
2010-03-02 15:40:28 -06:00
|
|
|
new_quote_sources = g_list_append(new_quote_sources, new_source);
|
|
|
|
return new_source;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_lookup_by_xxx
|
|
|
|
*
|
|
|
|
* Lookup a price source data structure based upon various criteria.
|
|
|
|
********************************************************************/
|
|
|
|
gnc_quote_source *
|
|
|
|
gnc_quote_source_lookup_by_ti (QuoteSourceType type, gint index)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_quote_source *source;
|
|
|
|
GList *node;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("type/index is %d/%d", type, index);
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case SOURCE_CURRENCY:
|
|
|
|
LEAVE("found %s", currency_quote_source.user_name);
|
|
|
|
return ¤cy_quote_source;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOURCE_SINGLE:
|
|
|
|
if (index < num_single_quote_sources)
|
|
|
|
{
|
|
|
|
LEAVE("found %s", single_quote_sources[index].user_name);
|
|
|
|
return &single_quote_sources[index];
|
|
|
|
}
|
|
|
|
break;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
case SOURCE_MULTI:
|
|
|
|
if (index < num_multiple_quote_sources)
|
|
|
|
{
|
|
|
|
LEAVE("found %s", multiple_quote_sources[index].user_name);
|
|
|
|
return &multiple_quote_sources[index];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SOURCE_UNKNOWN:
|
|
|
|
default:
|
|
|
|
node = g_list_nth(new_quote_sources, index);
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
source = node->data;
|
|
|
|
LEAVE("found %s", source->user_name);
|
|
|
|
return source;
|
|
|
|
}
|
2012-12-15 04:30:35 -06:00
|
|
|
break;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE("not found");
|
|
|
|
return NULL;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gnc_quote_source *
|
|
|
|
gnc_quote_source_lookup_by_internal(const char * name)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_quote_source *source;
|
|
|
|
GList *node;
|
|
|
|
gint i;
|
|
|
|
|
2012-08-07 12:24:55 -05:00
|
|
|
if ((name == NULL) || (g_strcmp0(name, "") == 0))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, currency_quote_source.internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return ¤cy_quote_source;
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, currency_quote_source.old_internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return ¤cy_quote_source;
|
|
|
|
|
|
|
|
for (i = 0; i < num_single_quote_sources; i++)
|
|
|
|
{
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, single_quote_sources[i].internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return &single_quote_sources[i];
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, single_quote_sources[i].old_internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return &single_quote_sources[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < num_multiple_quote_sources; i++)
|
|
|
|
{
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, multiple_quote_sources[i].internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return &multiple_quote_sources[i];
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, multiple_quote_sources[i].old_internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return &multiple_quote_sources[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, node = new_quote_sources; node; node = node->next, i++)
|
|
|
|
{
|
|
|
|
source = node->data;
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, source->internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return source;
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(name, source->old_internal_name) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return source;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
DEBUG("gnc_quote_source_lookup_by_internal: Unknown source %s", name);
|
2003-07-01 22:35:20 -05:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_get_xxx
|
|
|
|
*
|
|
|
|
* Accessor functions - get functions only. There are no set functions.
|
|
|
|
********************************************************************/
|
|
|
|
QuoteSourceType
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_quote_source_get_type (const gnc_quote_source *source)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("%p", source);
|
|
|
|
if (!source)
|
|
|
|
{
|
|
|
|
LEAVE("bad source");
|
|
|
|
return SOURCE_SINGLE;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE("type is %d", source->type);
|
|
|
|
return source->type;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_quote_source_get_index (const gnc_quote_source *source)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("%p", source);
|
|
|
|
if (!source)
|
|
|
|
{
|
|
|
|
LEAVE("bad source");
|
|
|
|
return 0;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE("index is %d", source->index);
|
|
|
|
return source->index;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_quote_source_get_supported (const gnc_quote_source *source)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("%p", source);
|
|
|
|
if (!source)
|
|
|
|
{
|
|
|
|
LEAVE("bad source");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE("%ssupported", source && source->supported ? "" : "not ");
|
|
|
|
return source->supported;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_quote_source_get_user_name (const gnc_quote_source *source)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("%p", source);
|
|
|
|
if (!source)
|
|
|
|
{
|
|
|
|
LEAVE("bad source");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
LEAVE("user name %s", source->user_name);
|
|
|
|
return source->user_name;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_quote_source_get_internal_name (const gnc_quote_source *source)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("%p", source);
|
|
|
|
if (!source)
|
|
|
|
{
|
|
|
|
LEAVE("bad source");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
LEAVE("internal name %s", source->internal_name);
|
|
|
|
return source->internal_name;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_set_fq_installed
|
|
|
|
*
|
|
|
|
* Update gnucash internal tables on what Finance::Quote sources are
|
|
|
|
* installed.
|
|
|
|
********************************************************************/
|
|
|
|
void
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_quote_source_set_fq_installed (const GList *sources_list)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_quote_source *source;
|
|
|
|
char *source_name;
|
|
|
|
const GList *node;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER(" ");
|
|
|
|
fq_is_installed = TRUE;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!sources_list)
|
|
|
|
return;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (node = sources_list; node; node = node->next)
|
|
|
|
{
|
|
|
|
source_name = node->data;
|
|
|
|
|
|
|
|
source = gnc_quote_source_lookup_by_internal(source_name);
|
|
|
|
if (source != NULL)
|
|
|
|
{
|
|
|
|
DEBUG("Found source %s: %s", source_name, source->user_name);
|
|
|
|
source->supported = TRUE;
|
|
|
|
continue;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_quote_source_add_new(source_name, TRUE);
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE(" ");
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
2006-05-06 01:14:21 -05:00
|
|
|
/********************************************************************
|
|
|
|
* QoF Helpers
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_begin_edit (gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_begin_edit(&cm->inst);
|
2006-05-06 01:14:21 -05:00
|
|
|
}
|
|
|
|
|
2006-11-29 09:13:02 -06:00
|
|
|
static void commit_err (QofInstance *inst, QofBackendError errcode)
|
2006-05-06 01:14:21 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
PERR ("Failed to commit: %d", errcode);
|
|
|
|
gnc_engine_signal_commit_error( errcode );
|
2006-05-06 01:14:21 -05:00
|
|
|
}
|
|
|
|
|
2006-11-29 09:13:02 -06:00
|
|
|
static void noop (QofInstance *inst) {}
|
2006-05-06 01:14:21 -05:00
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
static void
|
|
|
|
comm_free(QofInstance* inst)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
commodity_free( GNC_COMMODITY(inst) );
|
2008-08-01 11:02:07 -05:00
|
|
|
}
|
|
|
|
|
2006-05-06 01:14:21 -05:00
|
|
|
void
|
|
|
|
gnc_commodity_commit_edit (gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!qof_commit_edit (QOF_INSTANCE(cm))) return;
|
|
|
|
qof_commit_edit_part2 (&cm->inst, commit_err, noop, comm_free);
|
2006-05-06 01:14:21 -05:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_new
|
|
|
|
********************************************************************/
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
static void
|
|
|
|
mark_commodity_dirty (gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_set_dirty(&cm->inst);
|
|
|
|
qof_event_gen (&cm->inst, QOF_EVENT_MODIFY, NULL);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
2003-08-17 02:13:02 -05:00
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
static void
|
2008-08-01 11:02:07 -05:00
|
|
|
reset_printname(CommodityPrivate *priv)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2008-08-01 11:02:07 -05:00
|
|
|
g_free(priv->printname);
|
|
|
|
priv->printname = g_strdup_printf("%s (%s)",
|
2010-03-02 15:40:28 -06:00
|
|
|
priv->mnemonic ? priv->mnemonic : "",
|
|
|
|
priv->fullname ? priv->fullname : "");
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2008-08-01 11:02:07 -05:00
|
|
|
reset_unique_name(CommodityPrivate *priv)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2005-11-01 21:32:36 -06:00
|
|
|
gnc_commodity_namespace *ns;
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
g_free(priv->unique_name);
|
|
|
|
ns = priv->namespace;
|
|
|
|
priv->unique_name = g_strdup_printf("%s::%s",
|
2010-03-02 15:40:28 -06:00
|
|
|
ns ? ns->name : "",
|
|
|
|
priv->mnemonic ? priv->mnemonic : "");
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2007-04-04 19:24:18 -05:00
|
|
|
/* GObject Initialization */
|
2008-08-01 11:02:07 -05:00
|
|
|
G_DEFINE_TYPE(gnc_commodity, gnc_commodity, QOF_TYPE_INSTANCE);
|
2007-04-04 19:24:18 -05:00
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_commodity_init(gnc_commodity* com)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(com);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv->namespace = NULL;
|
|
|
|
priv->fullname = CACHE_INSERT("");
|
|
|
|
priv->mnemonic = CACHE_INSERT("");
|
|
|
|
priv->cusip = CACHE_INSERT("");
|
|
|
|
priv->fraction = 10000;
|
|
|
|
priv->quote_flag = 0;
|
|
|
|
priv->quote_source = NULL;
|
|
|
|
priv->quote_tz = CACHE_INSERT("");
|
|
|
|
|
|
|
|
reset_printname(priv);
|
|
|
|
reset_unique_name(priv);
|
2007-04-04 19:24:18 -05:00
|
|
|
}
|
|
|
|
|
2007-04-04 22:10:26 -05:00
|
|
|
static void
|
2008-08-01 11:02:07 -05:00
|
|
|
gnc_commodity_dispose(GObject *comp)
|
2007-04-04 22:10:26 -05:00
|
|
|
{
|
2008-08-01 11:02:07 -05:00
|
|
|
G_OBJECT_CLASS(gnc_commodity_parent_class)->dispose(comp);
|
2007-04-04 22:10:26 -05:00
|
|
|
}
|
|
|
|
|
2007-04-04 19:24:18 -05:00
|
|
|
static void
|
2008-08-01 11:02:07 -05:00
|
|
|
gnc_commodity_finalize(GObject* comp)
|
2007-04-04 19:24:18 -05:00
|
|
|
{
|
2008-08-01 11:02:07 -05:00
|
|
|
G_OBJECT_CLASS(gnc_commodity_parent_class)->finalize(comp);
|
|
|
|
}
|
2013-09-24 15:11:24 -05:00
|
|
|
/* Note that g_value_set_object() refs the object, as does
|
|
|
|
* g_object_get(). But g_object_get() only unrefs once when it disgorges
|
|
|
|
* the object, leaving an unbalanced ref, which leaks. So instead of
|
|
|
|
* using g_value_set_object(), use g_value_take_object() which doesn't
|
|
|
|
* ref the object when used in get_property().
|
|
|
|
*/
|
2008-08-01 11:02:07 -05:00
|
|
|
static void
|
|
|
|
gnc_commodity_get_property (GObject *object,
|
2010-03-02 15:40:28 -06:00
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2008-08-01 11:02:07 -05:00
|
|
|
{
|
|
|
|
gnc_commodity *commodity;
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
|
|
|
g_return_if_fail(GNC_IS_COMMODITY(object));
|
|
|
|
|
|
|
|
commodity = GNC_COMMODITY(object);
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(commodity);
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_NAMESPACE:
|
2013-09-24 15:11:24 -05:00
|
|
|
g_value_take_object(value, priv->namespace);
|
2010-03-02 15:40:28 -06:00
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_FULL_NAME:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_string(value, priv->fullname);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_MNEMONIC:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_string(value, priv->mnemonic);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_PRINTNAME:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_string(value, priv->printname);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_CUSIP:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_string(value, priv->cusip);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_FRACTION:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_int(value, priv->fraction);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_UNIQUE_NAME:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_string(value, priv->unique_name);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_QUOTE_FLAG:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_boolean(value, priv->quote_flag);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_QUOTE_SOURCE:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_pointer(value, priv->quote_source);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_QUOTE_TZ:
|
2010-03-02 15:40:28 -06:00
|
|
|
g_value_set_string(value, priv->quote_tz);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_commodity_set_property (GObject *object,
|
2010-03-02 15:40:28 -06:00
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2008-08-01 11:02:07 -05:00
|
|
|
{
|
|
|
|
gnc_commodity *commodity;
|
|
|
|
|
|
|
|
g_return_if_fail(GNC_IS_COMMODITY(object));
|
|
|
|
|
|
|
|
commodity = GNC_COMMODITY(object);
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_NAMESPACE:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_namespace(commodity, g_value_get_object(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_FULL_NAME:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_fullname(commodity, g_value_get_string(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_MNEMONIC:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_mnemonic(commodity, g_value_get_string(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_CUSIP:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_cusip(commodity, g_value_get_string(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_FRACTION:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_fraction(commodity, g_value_get_int(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_QUOTE_FLAG:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_quote_flag(commodity, g_value_get_boolean(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_QUOTE_SOURCE:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_quote_source(commodity, g_value_get_pointer(value));
|
|
|
|
break;
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_QUOTE_TZ:
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_quote_tz(commodity, g_value_get_string(value));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
2008-08-01 11:02:07 -05:00
|
|
|
}
|
|
|
|
static void
|
|
|
|
gnc_commodity_class_init(struct _GncCommodityClass* klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
|
|
|
|
|
|
|
|
gobject_class->dispose = gnc_commodity_dispose;
|
|
|
|
gobject_class->finalize = gnc_commodity_finalize;
|
|
|
|
gobject_class->set_property = gnc_commodity_set_property;
|
|
|
|
gobject_class->get_property = gnc_commodity_get_property;
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_type_class_add_private(klass, sizeof(CommodityPrivate));
|
2008-08-01 11:02:07 -05:00
|
|
|
|
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_NAMESPACE,
|
|
|
|
g_param_spec_object ("namespace",
|
|
|
|
"Namespace",
|
|
|
|
"The namespace field denotes the "
|
|
|
|
"namespace for this commodity, either "
|
|
|
|
"a currency or symbol from a quote source.",
|
|
|
|
GNC_TYPE_COMMODITY_NAMESPACE,
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_FULL_NAME,
|
|
|
|
g_param_spec_string ("fullname",
|
|
|
|
"Full Commodity Name",
|
|
|
|
"The fullname is the official full name of"
|
|
|
|
"the currency.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_MNEMONIC,
|
|
|
|
g_param_spec_string ("mnemonic",
|
|
|
|
"Commodity Mnemonic",
|
|
|
|
"The mnemonic is the official abbreviated"
|
|
|
|
"designation for the currency.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_PRINTNAME,
|
|
|
|
g_param_spec_string ("printname",
|
|
|
|
"Commodity Print Name",
|
|
|
|
"Printable form of the commodity name.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READABLE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_CUSIP,
|
|
|
|
g_param_spec_string ("cusip",
|
|
|
|
"Commodity CUSIP Code",
|
|
|
|
"?????",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_FRACTION,
|
|
|
|
g_param_spec_int ("fraction",
|
|
|
|
"Fraction",
|
|
|
|
"The fraction is the number of sub-units that "
|
|
|
|
"the basic commodity can be divided into.",
|
|
|
|
1,
|
|
|
|
1000000,
|
|
|
|
1,
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_UNIQUE_NAME,
|
|
|
|
g_param_spec_string ("unique-name",
|
|
|
|
"Commodity Unique Name",
|
|
|
|
"Unique form of the commodity name which combines "
|
|
|
|
"the namespace name and the commodity name.",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READABLE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_QUOTE_FLAG,
|
|
|
|
g_param_spec_boolean ("quote_flag",
|
|
|
|
"Quote Flag",
|
|
|
|
"TRUE if prices are to be downloaded for this "
|
|
|
|
"commodity from a quote source.",
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_QUOTE_SOURCE,
|
|
|
|
g_param_spec_pointer("quote-source",
|
|
|
|
"Quote Source",
|
|
|
|
"The quote source from which prices are downloaded.",
|
|
|
|
G_PARAM_READWRITE));
|
2008-08-01 11:02:07 -05:00
|
|
|
g_object_class_install_property(gobject_class,
|
2010-03-02 15:40:28 -06:00
|
|
|
PROP_QUOTE_TZ,
|
|
|
|
g_param_spec_string ("quote-tz",
|
|
|
|
"Commodity Quote Timezone",
|
|
|
|
"?????",
|
|
|
|
NULL,
|
|
|
|
G_PARAM_READWRITE));
|
2007-04-04 19:24:18 -05:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_commodity *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_new(QofBook *book, const char * fullname,
|
|
|
|
const char * namespace, const char * mnemonic,
|
2006-02-11 14:00:52 -06:00
|
|
|
const char * cusip, int fraction)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity * retval = g_object_new(GNC_TYPE_COMMODITY, NULL);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_init_data (&retval->inst, GNC_ID_COMMODITY, book);
|
|
|
|
gnc_commodity_begin_edit(retval);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if ( namespace != NULL )
|
|
|
|
{
|
2014-01-16 16:52:03 -06:00
|
|
|
/* Prevent setting anything except template in namespace template. */
|
|
|
|
if (g_strcmp0 (namespace, "template") == 0 &&
|
|
|
|
g_strcmp0 (mnemonic, "template") != 0)
|
|
|
|
{
|
|
|
|
PWARN("Converting commodity %s from namespace template to "
|
|
|
|
"namespace User", mnemonic);
|
|
|
|
namespace = "User";
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_namespace(retval, namespace);
|
|
|
|
if (gnc_commodity_namespace_is_iso(namespace))
|
|
|
|
{
|
|
|
|
gnc_commodity_set_quote_source(retval,
|
|
|
|
gnc_quote_source_lookup_by_internal("currency") );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gnc_commodity_set_fullname(retval, fullname);
|
|
|
|
gnc_commodity_set_mnemonic(retval, mnemonic);
|
|
|
|
gnc_commodity_set_cusip(retval, cusip);
|
|
|
|
gnc_commodity_set_fraction(retval, fraction);
|
|
|
|
gnc_commodity_commit_edit(retval);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&retval->inst, QOF_EVENT_CREATE, NULL);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return retval;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_destroy
|
|
|
|
********************************************************************/
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
static void
|
|
|
|
commodity_free(gnc_commodity * cm)
|
2001-10-03 05:07:45 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofBook *book;
|
|
|
|
gnc_commodity_table *table;
|
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
2001-10-03 05:07:45 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
book = qof_instance_get_book(&cm->inst);
|
|
|
|
table = gnc_commodity_table_get_table(book);
|
|
|
|
gnc_commodity_table_remove(table, cm);
|
|
|
|
priv = GET_PRIVATE(cm);
|
2006-04-05 12:59:14 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&cm->inst, QOF_EVENT_DESTROY, NULL);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Set at creation */
|
|
|
|
CACHE_REMOVE (priv->fullname);
|
|
|
|
CACHE_REMOVE (priv->cusip);
|
|
|
|
CACHE_REMOVE (priv->mnemonic);
|
|
|
|
CACHE_REMOVE (priv->quote_tz);
|
|
|
|
priv->namespace = NULL;
|
2001-10-03 05:07:45 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Set through accessor functions */
|
|
|
|
priv->quote_source = NULL;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Automatically generated */
|
|
|
|
g_free(priv->printname);
|
|
|
|
priv->printname = NULL;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free(priv->unique_name);
|
|
|
|
priv->unique_name = NULL;
|
2001-10-03 05:07:45 -05:00
|
|
|
|
2007-12-27 08:02:06 -06:00
|
|
|
#ifdef ACCOUNTS_CLEANED_UP
|
2010-03-02 15:40:28 -06:00
|
|
|
/* 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 (priv->usage_count != 0)
|
|
|
|
{
|
|
|
|
PWARN("Destroying commodity (%p) with non-zero usage_count (%d).", cm,
|
2008-08-01 11:02:07 -05:00
|
|
|
priv->usage_count);
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2007-12-25 23:17:37 -06:00
|
|
|
#endif
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* qof_instance_release (&cm->inst); */
|
|
|
|
g_object_unref(cm);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
void
|
|
|
|
gnc_commodity_destroy(gnc_commodity * cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
qof_instance_set_destroying(cm, TRUE);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2008-08-01 11:02:07 -05:00
|
|
|
}
|
|
|
|
|
2003-08-16 23:20:25 -05:00
|
|
|
void
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_commodity_copy(gnc_commodity * dest, const gnc_commodity *src)
|
2003-08-16 23:20:25 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* src_priv = GET_PRIVATE(src);
|
|
|
|
CommodityPrivate* dest_priv = GET_PRIVATE(dest);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_fullname (dest, src_priv->fullname);
|
|
|
|
gnc_commodity_set_mnemonic (dest, src_priv->mnemonic);
|
|
|
|
dest_priv->namespace = src_priv->namespace;
|
|
|
|
gnc_commodity_set_fraction (dest, src_priv->fraction);
|
|
|
|
gnc_commodity_set_cusip (dest, src_priv->cusip);
|
|
|
|
gnc_commodity_set_quote_flag (dest, src_priv->quote_flag);
|
|
|
|
gnc_commodity_set_quote_source (dest, gnc_commodity_get_quote_source (src));
|
|
|
|
gnc_commodity_set_quote_tz (dest, src_priv->quote_tz);
|
|
|
|
kvp_frame_delete (dest->inst.kvp_data);
|
|
|
|
dest->inst.kvp_data = kvp_frame_copy (src->inst.kvp_data);
|
2003-08-16 23:20:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gnc_commodity *
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_commodity_clone(const gnc_commodity *src, QofBook *dest_book)
|
2003-08-16 23:20:25 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* src_priv;
|
|
|
|
CommodityPrivate* dest_priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity * dest = g_object_new(GNC_TYPE_COMMODITY, NULL);
|
|
|
|
qof_instance_init_data (&dest->inst, GNC_ID_COMMODITY, dest_book);
|
|
|
|
src_priv = GET_PRIVATE(src);
|
|
|
|
dest_priv = GET_PRIVATE(dest);
|
2003-08-16 23:20:25 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
dest_priv->fullname = CACHE_INSERT(src_priv->fullname);
|
|
|
|
dest_priv->mnemonic = CACHE_INSERT(src_priv->mnemonic);
|
|
|
|
dest_priv->cusip = CACHE_INSERT(src_priv->cusip);
|
|
|
|
dest_priv->quote_tz = CACHE_INSERT(src_priv->quote_tz);
|
2006-01-10 20:58:59 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
dest_priv->namespace = src_priv->namespace;
|
2003-08-16 23:20:25 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
dest_priv->fraction = src_priv->fraction;
|
|
|
|
dest_priv->quote_flag = src_priv->quote_flag;
|
2003-08-17 01:37:24 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_quote_source (dest, gnc_commodity_get_quote_source (src));
|
2003-08-16 23:20:25 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
kvp_frame_delete (dest->inst.kvp_data);
|
|
|
|
dest->inst.kvp_data = kvp_frame_copy (src->inst.kvp_data);
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
reset_printname(dest_priv);
|
|
|
|
reset_unique_name(dest_priv);
|
2003-08-16 23:20:25 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return dest;
|
2003-08-16 23:20:25 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_mnemonic
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
const char *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_mnemonic(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->mnemonic;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_printname
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
const char *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_printname(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->printname;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_namespace
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
const char *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_namespace(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return gnc_commodity_namespace_get_name(GET_PRIVATE(cm)->namespace);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2006-04-03 16:39:25 -05:00
|
|
|
const char *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_namespace_compat(const gnc_commodity * cm)
|
2006-04-03 16:39:25 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if (!priv->namespace) return NULL;
|
|
|
|
if (priv->namespace->iso4217)
|
|
|
|
{
|
|
|
|
/* Data files are still written with ISO4217. */
|
|
|
|
return GNC_COMMODITY_NS_ISO;
|
|
|
|
}
|
|
|
|
return gnc_commodity_namespace_get_name(priv->namespace);
|
2006-04-03 16:39:25 -05:00
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
gnc_commodity_namespace *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_namespace_ds(const gnc_commodity * cm)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->namespace;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_fullname
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
const char *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_fullname(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->fullname;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_unique_name
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
const char *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_unique_name(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->unique_name;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
2006-02-11 14:00:52 -06:00
|
|
|
* gnc_commodity_get_cusip
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *
|
|
|
|
gnc_commodity_get_cusip(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->cusip;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_fraction
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
int
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_fraction(const gnc_commodity * cm)
|
2002-01-01 22:28:32 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return 0;
|
|
|
|
return GET_PRIVATE(cm)->fraction;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2007-12-25 23:17:37 -06:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_auto_quote_control_flag
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gnc_commodity_get_auto_quote_control_flag(const gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
const char *str;
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return FALSE;
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
str = kvp_frame_get_string(cm->inst.kvp_data, "auto_quote_control");
|
|
|
|
return !str || (strcmp(str, "false") != 0);
|
2007-12-25 23:17:37 -06:00
|
|
|
}
|
|
|
|
|
2003-05-10 19:45:03 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_quote_flag
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gnc_commodity_get_quote_flag(const gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return FALSE;
|
|
|
|
return (GET_PRIVATE(cm)->quote_flag);
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_quote_source
|
|
|
|
********************************************************************/
|
|
|
|
|
2003-07-01 22:35:20 -05:00
|
|
|
gnc_quote_source*
|
2003-05-10 19:45:03 -05:00
|
|
|
gnc_commodity_get_quote_source(const gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if (!priv->quote_source && gnc_commodity_is_iso(cm))
|
|
|
|
return ¤cy_quote_source;
|
|
|
|
return priv->quote_source;
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
2003-07-01 22:35:20 -05:00
|
|
|
gnc_quote_source*
|
|
|
|
gnc_commodity_get_default_quote_source(const gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (cm && gnc_commodity_is_iso(cm))
|
|
|
|
return ¤cy_quote_source;
|
|
|
|
/* Should make this a user option at some point. */
|
|
|
|
return gnc_quote_source_lookup_by_internal("yahoo");
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
2003-05-10 19:45:03 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_quote_tz
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
const char*
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_get_quote_tz(const gnc_commodity *cm)
|
2003-05-10 19:45:03 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return NULL;
|
|
|
|
return GET_PRIVATE(cm)->quote_tz;
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
2013-10-24 07:27:37 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_user_symbol
|
|
|
|
********************************************************************/
|
|
|
|
const char*
|
|
|
|
gnc_commodity_get_user_symbol(const gnc_commodity *cm)
|
|
|
|
{
|
|
|
|
const char *str;
|
|
|
|
if (!cm) return NULL;
|
2014-03-25 19:07:49 -05:00
|
|
|
return kvp_frame_get_string(cm->inst.kvp_data, "user_symbol");
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_default_symbol
|
|
|
|
*******************************************************************/
|
|
|
|
const char*
|
|
|
|
gnc_commodity_get_default_symbol(const gnc_commodity *cm)
|
|
|
|
{
|
|
|
|
const char *str;
|
|
|
|
if (!cm) return NULL;
|
2013-11-20 22:57:30 -06:00
|
|
|
return GET_PRIVATE(cm)->default_symbol;
|
2013-10-24 07:27:37 -05:00
|
|
|
}
|
|
|
|
|
2014-03-25 19:07:49 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_nice_symbol
|
|
|
|
*******************************************************************/
|
|
|
|
const char*
|
|
|
|
gnc_commodity_get_nice_symbol (const gnc_commodity *cm)
|
|
|
|
{
|
|
|
|
const char *nice_symbol;
|
|
|
|
struct lconv *lc;
|
|
|
|
if (!cm) return NULL;
|
|
|
|
|
|
|
|
nice_symbol = gnc_commodity_get_user_symbol(cm);
|
|
|
|
if (nice_symbol && *nice_symbol)
|
|
|
|
return nice_symbol;
|
|
|
|
|
|
|
|
lc = gnc_localeconv();
|
|
|
|
nice_symbol = lc->currency_symbol;
|
|
|
|
if (!g_strcmp0(gnc_commodity_get_mnemonic(cm), lc->int_curr_symbol))
|
|
|
|
return nice_symbol;
|
|
|
|
|
|
|
|
nice_symbol = gnc_commodity_get_default_symbol(cm);
|
|
|
|
if (nice_symbol && *nice_symbol)
|
|
|
|
return nice_symbol;
|
|
|
|
|
|
|
|
return gnc_commodity_get_mnemonic(cm);
|
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_mnemonic
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_mnemonic(gnc_commodity * cm, const char * mnemonic)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if (priv->mnemonic == mnemonic) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
CACHE_REMOVE (priv->mnemonic);
|
|
|
|
priv->mnemonic = CACHE_INSERT(mnemonic);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
mark_commodity_dirty (cm);
|
|
|
|
reset_printname(priv);
|
|
|
|
reset_unique_name(priv);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_namespace
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_namespace(gnc_commodity * cm, const char * namespace)
|
|
|
|
{
|
|
|
|
QofBook *book;
|
|
|
|
gnc_commodity_table *table;
|
|
|
|
gnc_commodity_namespace *nsp;
|
|
|
|
CommodityPrivate* priv;
|
|
|
|
|
|
|
|
if (!cm) return;
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
book = qof_instance_get_book (&cm->inst);
|
|
|
|
table = gnc_commodity_table_get_table(book);
|
|
|
|
nsp = gnc_commodity_table_add_namespace(table, namespace, book);
|
|
|
|
if (priv->namespace == nsp)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
priv->namespace = nsp;
|
|
|
|
if (nsp->iso4217)
|
|
|
|
priv->quote_source = gnc_quote_source_lookup_by_internal("currency");
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
reset_printname(priv);
|
|
|
|
reset_unique_name(priv);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_fullname
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_fullname(gnc_commodity * cm, const char * fullname)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if (priv->fullname == fullname) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
CACHE_REMOVE (priv->fullname);
|
|
|
|
priv->fullname = CACHE_INSERT (fullname);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
reset_printname(priv);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
2006-02-11 14:00:52 -06:00
|
|
|
* gnc_commodity_set_cusip
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_cusip(gnc_commodity * cm,
|
|
|
|
const char * cusip)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if (priv->cusip == cusip) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
CACHE_REMOVE (priv->cusip);
|
|
|
|
priv->cusip = CACHE_INSERT (cusip);
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_fraction
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_fraction(gnc_commodity * cm, int fraction)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
GET_PRIVATE(cm)->fraction = fraction;
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2007-12-25 23:17:37 -06:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_auto_quote_control_flag
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_commodity_set_auto_quote_control_flag(gnc_commodity *cm,
|
2010-03-02 15:40:28 -06:00
|
|
|
const gboolean flag)
|
2007-12-25 23:17:37 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("(cm=%p, flag=%d)", cm, flag);
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm)
|
|
|
|
{
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
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("");
|
2007-12-25 23:17:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_user_set_quote_flag
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_user_set_quote_flag(gnc_commodity *cm, const gboolean flag)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("(cm=%p, flag=%d)", cm, flag);
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm)
|
|
|
|
{
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
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 && (priv->usage_count == 0)) || (flag && (priv->usage_count != 0)));
|
|
|
|
}
|
|
|
|
gnc_commodity_commit_edit(cm);
|
2007-12-25 23:17:37 -06:00
|
|
|
LEAVE("");
|
|
|
|
}
|
|
|
|
|
2003-05-10 19:45:03 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_quote_flag
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_set_quote_flag(gnc_commodity *cm, const gboolean flag)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("(cm=%p, flag=%d)", cm, flag);
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
GET_PRIVATE(cm)->quote_flag = flag;
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
|
|
|
LEAVE(" ");
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_quote_source
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2003-07-01 22:35:20 -05:00
|
|
|
gnc_commodity_set_quote_source(gnc_commodity *cm, gnc_quote_source *src)
|
2003-05-10 19:45:03 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("(cm=%p, src=%p(%s))", cm, src, src ? src->internal_name : "unknown");
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return;
|
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
GET_PRIVATE(cm)->quote_source = src;
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
|
|
|
LEAVE(" ");
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_quote_tz
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_set_quote_tz(gnc_commodity *cm, const char *tz)
|
2003-05-10 19:45:03 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
|
|
|
|
|
|
|
if (!cm) return;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2011-01-18 22:18:00 -06:00
|
|
|
ENTER ("(cm=%p, tz=%s)", cm, tz ? tz : "(null)");
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(cm);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2011-01-24 08:10:09 -06:00
|
|
|
if (tz == priv->quote_tz)
|
2011-01-18 22:18:00 -06:00
|
|
|
{
|
2011-01-24 08:10:09 -06:00
|
|
|
LEAVE("Already correct TZ");
|
|
|
|
return;
|
2011-01-18 22:18:00 -06:00
|
|
|
}
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_begin_edit(cm);
|
|
|
|
CACHE_REMOVE (priv->quote_tz);
|
|
|
|
priv->quote_tz = CACHE_INSERT (tz);
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
|
|
|
LEAVE(" ");
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
2013-10-24 07:27:37 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_user_symbol
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_set_user_symbol(gnc_commodity * cm, const char * user_symbol)
|
|
|
|
{
|
2014-03-25 19:07:49 -05:00
|
|
|
struct lconv *lc;
|
|
|
|
|
2013-10-24 07:27:37 -05:00
|
|
|
if (!cm) return;
|
|
|
|
|
|
|
|
ENTER ("(cm=%p, symbol=%s)", cm, user_symbol ? user_symbol : "(null)");
|
|
|
|
|
|
|
|
gnc_commodity_begin_edit(cm);
|
2014-03-25 19:07:49 -05:00
|
|
|
|
|
|
|
lc = gnc_localeconv();
|
|
|
|
if (!user_symbol || !*user_symbol)
|
|
|
|
user_symbol = NULL;
|
|
|
|
else if (!g_strcmp0(lc->int_curr_symbol, gnc_commodity_get_mnemonic(cm)) &&
|
|
|
|
!g_strcmp0(lc->currency_symbol, user_symbol))
|
|
|
|
/* if the user gives the ISO symbol for the locale currency or the
|
|
|
|
* default symbol, actually remove the user symbol */
|
|
|
|
user_symbol = NULL;
|
|
|
|
else if (!g_strcmp0(user_symbol, gnc_commodity_get_default_symbol(cm)))
|
|
|
|
user_symbol = NULL;
|
|
|
|
|
2013-10-24 07:27:37 -05:00
|
|
|
kvp_frame_set_string(cm->inst.kvp_data, "user_symbol", user_symbol);
|
|
|
|
mark_commodity_dirty(cm);
|
|
|
|
gnc_commodity_commit_edit(cm);
|
|
|
|
|
|
|
|
LEAVE(" ");
|
|
|
|
}
|
|
|
|
|
2013-11-20 22:57:30 -06:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_set_default_symbol
|
|
|
|
* Not made visible in gnc-commodity.h, it is only called from
|
|
|
|
* iso-4217-currencies.c at startup.
|
|
|
|
********************************************************************/
|
|
|
|
void
|
|
|
|
gnc_commodity_set_default_symbol(gnc_commodity * cm,
|
|
|
|
const char * default_symbol)
|
|
|
|
{
|
|
|
|
GET_PRIVATE(cm)->default_symbol = default_symbol;
|
|
|
|
}
|
|
|
|
|
2007-12-25 23:17:37 -06:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_increment_usage_count
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_increment_usage_count(gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("(cm=%p)", cm);
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm)
|
|
|
|
{
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(cm);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if ((priv->usage_count == 0) && !priv->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);
|
|
|
|
}
|
|
|
|
priv->usage_count++;
|
|
|
|
LEAVE("(usage_count=%d)", priv->usage_count);
|
2007-12-25 23:17:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_decrement_usage_count
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_decrement_usage_count(gnc_commodity *cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("(cm=%p)", cm);
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm)
|
|
|
|
{
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(cm);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (priv->usage_count == 0)
|
|
|
|
{
|
|
|
|
PWARN("usage_count already zero");
|
|
|
|
LEAVE("");
|
|
|
|
return;
|
|
|
|
}
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv->usage_count--;
|
|
|
|
if ((priv->usage_count == 0) && priv->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)", priv->usage_count);
|
2007-12-25 23:17:37 -06:00
|
|
|
}
|
|
|
|
|
2003-05-10 19:45:03 -05:00
|
|
|
/********************************************************************\
|
|
|
|
\********************************************************************/
|
|
|
|
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_equiv
|
2010-03-02 15:40:28 -06:00
|
|
|
* are two commodities the same?
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gboolean
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_equiv(const gnc_commodity * a, const gnc_commodity * b)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv_a;
|
|
|
|
CommodityPrivate* priv_b;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (a == b) return TRUE;
|
|
|
|
if (!a || !b) return FALSE;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv_a = GET_PRIVATE(a);
|
|
|
|
priv_b = GET_PRIVATE(b);
|
|
|
|
if (priv_a->namespace != priv_b->namespace) return FALSE;
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(priv_a->mnemonic, priv_b->mnemonic) != 0) return FALSE;
|
2010-03-02 15:40:28 -06:00
|
|
|
return TRUE;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2001-10-12 05:50:35 -05:00
|
|
|
gboolean
|
|
|
|
gnc_commodity_equal(const gnc_commodity * a, const gnc_commodity * b)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv_a;
|
|
|
|
CommodityPrivate* priv_b;
|
2010-03-25 13:32:40 -05:00
|
|
|
gboolean same_book;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (a == b) return TRUE;
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!a || !b)
|
|
|
|
{
|
|
|
|
DEBUG ("one is NULL");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv_a = GET_PRIVATE(a);
|
|
|
|
priv_b = GET_PRIVATE(b);
|
2010-03-25 13:32:40 -05:00
|
|
|
same_book = qof_instance_get_book(QOF_INSTANCE(a)) == qof_instance_get_book(QOF_INSTANCE(b));
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-25 13:32:40 -05:00
|
|
|
if ((same_book && priv_a->namespace != priv_b->namespace)
|
2012-08-07 12:24:55 -05:00
|
|
|
|| (!same_book && g_strcmp0( gnc_commodity_namespace_get_name(priv_a->namespace),
|
2010-03-25 13:32:40 -05:00
|
|
|
gnc_commodity_namespace_get_name(priv_b->namespace)) != 0))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
DEBUG ("namespaces differ: %p(%s) vs %p(%s)",
|
|
|
|
priv_a->namespace, gnc_commodity_namespace_get_name(priv_a->namespace),
|
|
|
|
priv_b->namespace, gnc_commodity_namespace_get_name(priv_b->namespace));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(priv_a->mnemonic, priv_b->mnemonic) != 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
DEBUG ("mnemonics differ: %s vs %s", priv_a->mnemonic, priv_b->mnemonic);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(priv_a->fullname, priv_b->fullname) != 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
DEBUG ("fullnames differ: %s vs %s", priv_a->fullname, priv_b->fullname);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(priv_a->cusip, priv_b->cusip) != 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
DEBUG ("cusips differ: %s vs %s", priv_a->cusip, priv_b->cusip);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (priv_a->fraction != priv_b->fraction)
|
|
|
|
{
|
|
|
|
DEBUG ("fractions differ: %d vs %d", priv_a->fraction, priv_b->fraction);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-10-12 05:50:35 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return TRUE;
|
2001-10-12 05:50:35 -05:00
|
|
|
}
|
|
|
|
|
2008-11-20 11:00:37 -06:00
|
|
|
int gnc_commodity_compare(const gnc_commodity * a, const gnc_commodity * b)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (gnc_commodity_equal(a, b))
|
2008-11-20 11:00:37 -06:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2008-11-20 11:11:47 -06:00
|
|
|
int gnc_commodity_compare_void(const void * a, const void * b)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
return gnc_commodity_compare(a, b);
|
2008-11-20 11:11:47 -06:00
|
|
|
}
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/************************************************************
|
|
|
|
* Namespace functions *
|
|
|
|
************************************************************/
|
|
|
|
const char *
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_commodity_namespace_get_name (const gnc_commodity_namespace *ns)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (ns == NULL)
|
|
|
|
return NULL;
|
|
|
|
return ns->name;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *
|
|
|
|
gnc_commodity_namespace_get_commodity_list(const gnc_commodity_namespace *namespace)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!namespace)
|
|
|
|
return NULL;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return namespace->cm_list;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gnc_commodity_namespace_is_iso(const char *namespace)
|
|
|
|
{
|
2012-08-07 12:24:55 -05:00
|
|
|
return ((g_strcmp0(namespace, GNC_COMMODITY_NS_ISO) == 0) ||
|
|
|
|
(g_strcmp0(namespace, GNC_COMMODITY_NS_CURRENCY) == 0));
|
2006-04-03 16:39:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
gnc_commodity_table_map_namespace(const char * namespace)
|
|
|
|
{
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(namespace, GNC_COMMODITY_NS_ISO) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return GNC_COMMODITY_NS_CURRENCY;
|
|
|
|
return namespace;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_new
|
2010-03-02 15:40:28 -06:00
|
|
|
* make a new commodity table
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gnc_commodity_table *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table_new(void)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table * retval = g_new0(gnc_commodity_table, 1);
|
|
|
|
retval->ns_table = g_hash_table_new(&g_str_hash, &g_str_equal);
|
|
|
|
retval->ns_list = NULL;
|
|
|
|
return retval;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-06-09 22:33:06 -05:00
|
|
|
/********************************************************************
|
|
|
|
* book anchor functons
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gnc_commodity_table *
|
2003-06-24 19:52:46 -05:00
|
|
|
gnc_commodity_table_get_table(QofBook *book)
|
2003-06-09 22:33:06 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!book) return NULL;
|
|
|
|
return qof_book_get_data (book, GNC_COMMODITY_TABLE);
|
2003-06-09 22:33:06 -05:00
|
|
|
}
|
|
|
|
|
2003-10-21 00:00:30 -05:00
|
|
|
gnc_commodity *
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_commodity_obtain_twin (const gnc_commodity *from, QofBook *book)
|
2003-10-21 00:00:30 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *twin;
|
|
|
|
const char * ucom;
|
|
|
|
gnc_commodity_table * comtbl;
|
2003-10-21 00:00:30 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!from) return NULL;
|
|
|
|
comtbl = gnc_commodity_table_get_table (book);
|
|
|
|
if (!comtbl) return NULL;
|
2003-10-21 00:00:30 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ucom = gnc_commodity_get_unique_name (from);
|
|
|
|
twin = gnc_commodity_table_lookup_unique (comtbl, ucom);
|
|
|
|
if (!twin)
|
|
|
|
{
|
|
|
|
twin = gnc_commodity_clone (from, book);
|
|
|
|
twin = gnc_commodity_table_insert (comtbl, twin);
|
|
|
|
}
|
|
|
|
return twin;
|
2003-10-21 00:00:30 -05:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
2005-11-01 21:32:36 -06:00
|
|
|
* gnc_commodity_table_get_size
|
2001-08-07 18:36:04 -05:00
|
|
|
* get the size of the commodity table
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
static void
|
|
|
|
count_coms(gpointer key, gpointer value, gpointer user_data)
|
|
|
|
{
|
2005-11-01 21:32:36 -06:00
|
|
|
GHashTable *tbl = ((gnc_commodity_namespace*)value)->cm_table;
|
2001-08-07 18:36:04 -05:00
|
|
|
guint *count = (guint*)user_data;
|
|
|
|
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0((char*)key, GNC_COMMODITY_NS_CURRENCY) == 0)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
|
|
|
/* don't count default commodities */
|
|
|
|
return;
|
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
if (!value) return;
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
*count += g_hash_table_size(tbl);
|
|
|
|
}
|
|
|
|
|
|
|
|
guint
|
2007-12-27 20:27:57 -06:00
|
|
|
gnc_commodity_table_get_size(const gnc_commodity_table* tbl)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
|
|
|
guint count = 0;
|
|
|
|
g_return_val_if_fail(tbl, 0);
|
2005-11-01 21:32:36 -06:00
|
|
|
g_return_val_if_fail(tbl->ns_table, 0);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
g_hash_table_foreach(tbl->ns_table, count_coms, (gpointer)&count);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_lookup
|
2010-03-02 15:40:28 -06:00
|
|
|
* locate a commodity by namespace and mnemonic.
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gnc_commodity *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table_lookup(const gnc_commodity_table * table,
|
2003-05-29 18:47:52 -05:00
|
|
|
const char * namespace, const char * mnemonic)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * nsp = NULL;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (!table || !namespace || !mnemonic) return NULL;
|
|
|
|
|
|
|
|
nsp = gnc_commodity_table_find_namespace(table, namespace);
|
|
|
|
|
|
|
|
if (nsp)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Backward compatability support for currencies that have
|
|
|
|
* recently changed.
|
|
|
|
*/
|
|
|
|
if (nsp->iso4217)
|
|
|
|
{
|
|
|
|
for (i = 0; i < GNC_NEW_ISO_CODES; i++)
|
|
|
|
{
|
|
|
|
if (strcmp(mnemonic, gnc_new_iso_codes[i].old_code) == 0)
|
|
|
|
{
|
|
|
|
mnemonic = gnc_new_iso_codes[i].new_code;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return g_hash_table_lookup(nsp->cm_table, (gpointer)mnemonic);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
2003-05-29 18:47:52 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_lookup
|
|
|
|
* locate a commodity by unique name.
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gnc_commodity *
|
|
|
|
gnc_commodity_table_lookup_unique(const gnc_commodity_table *table,
|
|
|
|
const char * unique_name)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
char *namespace;
|
|
|
|
char *mnemonic;
|
|
|
|
gnc_commodity *commodity;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table || !unique_name) return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
namespace = g_strdup (unique_name);
|
|
|
|
mnemonic = strstr (namespace, "::");
|
|
|
|
if (!mnemonic)
|
|
|
|
{
|
|
|
|
g_free (namespace);
|
|
|
|
return NULL;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
*mnemonic = '\0';
|
|
|
|
mnemonic += 2;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
commodity = gnc_commodity_table_lookup (table, namespace, mnemonic);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free (namespace);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return commodity;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_find_full
|
2010-03-02 15:40:28 -06:00
|
|
|
* locate a commodity by namespace and printable name
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gnc_commodity *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table_find_full(const gnc_commodity_table * table,
|
|
|
|
const char * namespace,
|
|
|
|
const char * fullname)
|
|
|
|
{
|
|
|
|
gnc_commodity * retval = NULL;
|
|
|
|
GList * all;
|
|
|
|
GList * iterator;
|
|
|
|
|
|
|
|
if (!fullname || (fullname[0] == '\0'))
|
|
|
|
return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
all = gnc_commodity_table_get_commodities(table, namespace);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (iterator = all; iterator; iterator = iterator->next)
|
|
|
|
{
|
|
|
|
if (!strcmp(fullname,
|
|
|
|
gnc_commodity_get_printname(iterator->data)))
|
|
|
|
{
|
|
|
|
retval = iterator->data;
|
|
|
|
break;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_list_free (all);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return retval;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_insert
|
2010-03-02 15:40:28 -06:00
|
|
|
* add a commodity to the table.
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
gnc_commodity *
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table_insert(gnc_commodity_table * table,
|
|
|
|
gnc_commodity * comm)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * nsp = NULL;
|
|
|
|
gnc_commodity *c;
|
|
|
|
const char *ns_name;
|
|
|
|
CommodityPrivate* priv;
|
|
|
|
QofBook *book;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table) return NULL;
|
|
|
|
if (!comm) return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(comm);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER ("(table=%p, comm=%p) %s %s", table, comm,
|
|
|
|
(priv->mnemonic == NULL ? "(null)" : priv->mnemonic),
|
|
|
|
(priv->fullname == NULL ? "(null)" : priv->fullname));
|
|
|
|
ns_name = gnc_commodity_namespace_get_name(priv->namespace);
|
|
|
|
c = gnc_commodity_table_lookup (table, ns_name, priv->mnemonic);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (c)
|
2003-08-10 22:06:17 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (c == comm)
|
|
|
|
{
|
|
|
|
LEAVE("already in table");
|
|
|
|
return c;
|
|
|
|
}
|
2009-01-11 15:00:54 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Backward compatability support for currencies that have
|
|
|
|
* recently changed. */
|
|
|
|
if (priv->namespace->iso4217)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
for (i = 0; i < GNC_NEW_ISO_CODES; i++)
|
|
|
|
{
|
|
|
|
if (!priv->mnemonic
|
|
|
|
|| !strcmp(priv->mnemonic, gnc_new_iso_codes[i].old_code))
|
|
|
|
{
|
|
|
|
gnc_commodity_set_mnemonic(comm, gnc_new_iso_codes[i].new_code);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-01-11 15:00:54 -06:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_copy (c, comm);
|
|
|
|
gnc_commodity_destroy (comm);
|
|
|
|
LEAVE("found at %p", c);
|
|
|
|
return c;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2014-01-16 16:52:03 -06:00
|
|
|
/* Prevent setting anything except template in namespace template. */
|
|
|
|
if (g_strcmp0 (ns_name, "template") == 0 &&
|
|
|
|
g_strcmp0 (priv->mnemonic, "template") != 0)
|
|
|
|
{
|
|
|
|
PWARN("Converting commodity %s from namespace template to "
|
|
|
|
"namespace User", priv->mnemonic);
|
|
|
|
gnc_commodity_set_namespace (comm, "User");
|
|
|
|
ns_name = "User";
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
book = qof_instance_get_book (&comm->inst);
|
|
|
|
nsp = gnc_commodity_table_add_namespace(table, ns_name, book);
|
2006-01-02 15:11:26 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
PINFO ("insert %p %s into nsp=%p %s", priv->mnemonic, priv->mnemonic,
|
|
|
|
nsp->cm_table, nsp->name);
|
|
|
|
g_hash_table_insert(nsp->cm_table,
|
|
|
|
CACHE_INSERT(priv->mnemonic),
|
|
|
|
(gpointer)comm);
|
|
|
|
nsp->cm_list = g_list_append(nsp->cm_list, comm);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&comm->inst, QOF_EVENT_ADD, NULL);
|
|
|
|
LEAVE ("(table=%p, comm=%p)", table, comm);
|
|
|
|
return comm;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_remove
|
2010-03-02 15:40:28 -06:00
|
|
|
* remove a commodity from the table.
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_commodity_table_remove(gnc_commodity_table * table,
|
|
|
|
gnc_commodity * comm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * nsp;
|
|
|
|
gnc_commodity *c;
|
|
|
|
CommodityPrivate* priv;
|
|
|
|
const char *ns_name;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table) return;
|
|
|
|
if (!comm) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(comm);
|
|
|
|
ns_name = gnc_commodity_namespace_get_name(priv->namespace);
|
|
|
|
c = gnc_commodity_table_lookup (table, ns_name, priv->mnemonic);
|
|
|
|
if (c != comm) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&comm->inst, QOF_EVENT_REMOVE, NULL);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
nsp = gnc_commodity_table_find_namespace(table, ns_name);
|
|
|
|
if (!nsp) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
nsp->cm_list = g_list_remove(nsp->cm_list, comm);
|
|
|
|
g_hash_table_remove (nsp->cm_table, priv->mnemonic);
|
|
|
|
/* XXX minor mem leak, should remove the key as well */
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_has_namespace
|
2003-05-10 19:45:03 -05:00
|
|
|
* see if the commodities namespace exists. May have zero commodities.
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
int
|
|
|
|
gnc_commodity_table_has_namespace(const gnc_commodity_table * table,
|
2010-03-02 15:40:28 -06:00
|
|
|
const char * namespace)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * nsp = NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table || !namespace)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsp = gnc_commodity_table_find_namespace(table, namespace);
|
|
|
|
if (nsp)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static void
|
|
|
|
hash_keys_helper(gpointer key, gpointer value, gpointer data)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList ** l = data;
|
|
|
|
*l = g_list_prepend(*l, key);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
2010-03-02 15:40:28 -06:00
|
|
|
g_hash_table_keys(GHashTable * table)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList * l = NULL;
|
|
|
|
g_hash_table_foreach(table, &hash_keys_helper, (gpointer) &l);
|
|
|
|
return l;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static void
|
|
|
|
hash_values_helper(gpointer key, gpointer value, gpointer data)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList ** l = data;
|
|
|
|
*l = g_list_prepend(*l, value);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static GList *
|
2010-03-02 15:40:28 -06:00
|
|
|
g_hash_table_values(GHashTable * table)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList * l = NULL;
|
|
|
|
g_hash_table_foreach(table, &hash_values_helper, (gpointer) &l);
|
|
|
|
return l;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_get_namespaces
|
2010-03-02 15:40:28 -06:00
|
|
|
* see if any commodities in the namespace exist
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *
|
|
|
|
gnc_commodity_table_get_namespaces(const gnc_commodity_table * table)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table)
|
|
|
|
return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return g_hash_table_keys(table->ns_table);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *
|
|
|
|
gnc_commodity_table_get_namespaces_list(const gnc_commodity_table * table)
|
2003-04-29 01:15:34 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table)
|
|
|
|
return NULL;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return table->ns_list;
|
2003-04-29 01:15:34 -05:00
|
|
|
}
|
|
|
|
|
2009-12-17 02:03:23 -06:00
|
|
|
/* Because gnc_commodity_table_add_namespace maps GNC_COMMODITY_NS_ISO to
|
|
|
|
GNC_COMMODITY_NS_CURRENCY and then sets iso4217 if the namespace is
|
|
|
|
either of these, the net result is that the iso4217 bit is set only
|
|
|
|
for GNC_COMMODITY_NS_CURRENCY. This means that gnc_commodity_is_iso is
|
2010-03-02 15:40:28 -06:00
|
|
|
a subset of gnc_commodity_is_currency. Most callers seem to use
|
2009-12-17 02:03:23 -06:00
|
|
|
gnc_commodity_is_iso. */
|
2003-04-29 01:15:34 -05:00
|
|
|
gboolean
|
|
|
|
gnc_commodity_is_iso(const gnc_commodity * cm)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
CommodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return FALSE;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if ( !priv->namespace) return FALSE;
|
|
|
|
return priv->namespace->iso4217;
|
2003-04-29 01:15:34 -05:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2006-03-06 20:42:12 -06:00
|
|
|
gboolean
|
|
|
|
gnc_commodity_is_currency(const gnc_commodity *cm)
|
|
|
|
{
|
|
|
|
const char *ns_name;
|
|
|
|
if (!cm) return FALSE;
|
|
|
|
|
2008-08-01 11:02:07 -05:00
|
|
|
ns_name = gnc_commodity_namespace_get_name(GET_PRIVATE(cm)->namespace);
|
2012-08-07 12:24:55 -05:00
|
|
|
return (!g_strcmp0(ns_name, GNC_COMMODITY_NS_LEGACY) ||
|
|
|
|
!g_strcmp0(ns_name, GNC_COMMODITY_NS_CURRENCY));
|
2006-03-06 20:42:12 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_get_commodities
|
2010-03-02 15:40:28 -06:00
|
|
|
* list commodities in a give namespace
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
2006-10-15 14:02:05 -05:00
|
|
|
CommodityList *
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_commodity_table_get_commodities(const gnc_commodity_table * table,
|
2010-03-02 15:40:28 -06:00
|
|
|
const char * namespace)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * ns = NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table)
|
|
|
|
return NULL;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ns = gnc_commodity_table_find_namespace(table, namespace);
|
|
|
|
if (!ns)
|
|
|
|
return NULL;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return g_hash_table_values(ns->cm_table);
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_get_quotable_commodities
|
|
|
|
* list commodities in a given namespace that get price quotes
|
|
|
|
********************************************************************/
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static void
|
|
|
|
get_quotables_helper1(gpointer key, gpointer value, gpointer data)
|
2003-05-10 19:45:03 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *comm = value;
|
|
|
|
CommodityPrivate* priv = GET_PRIVATE(comm);
|
|
|
|
GList ** l = data;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!priv->quote_flag ||
|
|
|
|
!priv->quote_source || !priv->quote_source->supported)
|
|
|
|
return;
|
|
|
|
*l = g_list_prepend(*l, value);
|
2003-05-10 19:45:03 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static gboolean
|
2003-05-10 19:45:03 -05:00
|
|
|
get_quotables_helper2 (gnc_commodity *comm, gpointer data)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GList ** l = data;
|
|
|
|
CommodityPrivate* priv = GET_PRIVATE(comm);
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!priv->quote_flag ||
|
|
|
|
!priv->quote_source || !priv->quote_source->supported)
|
|
|
|
return TRUE;
|
|
|
|
*l = g_list_prepend(*l, comm);
|
2003-05-10 19:45:03 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2006-10-15 14:02:05 -05:00
|
|
|
CommodityList *
|
2006-01-20 21:50:25 -06:00
|
|
|
gnc_commodity_table_get_quotable_commodities(const gnc_commodity_table * table)
|
2003-05-10 19:45:03 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * ns = NULL;
|
|
|
|
const char *namespace;
|
|
|
|
GList * nslist, * tmp;
|
|
|
|
GList * l = NULL;
|
|
|
|
regex_t pattern;
|
2013-10-07 09:06:23 -05:00
|
|
|
const char *expression = gnc_prefs_get_namespace_regexp();
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER("table=%p, expression=%s", table, expression);
|
|
|
|
if (!table)
|
|
|
|
return NULL;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (expression && *expression)
|
|
|
|
{
|
|
|
|
if (regcomp(&pattern, expression, REG_EXTENDED | REG_ICASE) != 0)
|
|
|
|
{
|
|
|
|
LEAVE("Cannot compile regex");
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-07-03 17:40:18 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
nslist = gnc_commodity_table_get_namespaces(table);
|
|
|
|
for (tmp = nslist; tmp; tmp = tmp->next)
|
|
|
|
{
|
|
|
|
namespace = tmp->data;
|
|
|
|
if (regexec(&pattern, namespace, 0, NULL, 0) == 0)
|
|
|
|
{
|
|
|
|
DEBUG("Running list of %s commodities", namespace);
|
|
|
|
ns = gnc_commodity_table_find_namespace(table, namespace);
|
|
|
|
if (ns)
|
|
|
|
{
|
|
|
|
g_hash_table_foreach(ns->cm_table, &get_quotables_helper1, (gpointer) &l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_list_free(nslist);
|
|
|
|
regfree(&pattern);
|
2003-07-03 17:40:18 -05:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
gnc_commodity_table_foreach_commodity(table, get_quotables_helper2,
|
|
|
|
(gpointer) &l);
|
|
|
|
}
|
|
|
|
LEAVE("list head %p", l);
|
|
|
|
return l;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_add_namespace
|
2010-03-02 15:40:28 -06:00
|
|
|
* add an empty namespace if it does not exist
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
2007-04-04 21:44:47 -05:00
|
|
|
/* GObject Initialization */
|
|
|
|
QOF_GOBJECT_IMPL(gnc_commodity_namespace, gnc_commodity_namespace, QOF_TYPE_INSTANCE);
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_commodity_namespace_init(gnc_commodity_namespace* ns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-04-04 22:10:26 -05:00
|
|
|
static void
|
|
|
|
gnc_commodity_namespace_dispose_real (GObject *nsp)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-04-04 21:44:47 -05:00
|
|
|
static void
|
|
|
|
gnc_commodity_namespace_finalize_real(GObject* nsp)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace *
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_commodity_table_add_namespace(gnc_commodity_table * table,
|
2006-01-02 15:11:26 -06:00
|
|
|
const char * namespace,
|
2010-03-02 15:40:28 -06:00
|
|
|
QofBook *book)
|
|
|
|
{
|
|
|
|
gnc_commodity_namespace * ns = NULL;
|
|
|
|
|
|
|
|
if (!table) return NULL;
|
|
|
|
|
|
|
|
namespace = gnc_commodity_table_map_namespace(namespace);
|
|
|
|
ns = gnc_commodity_table_find_namespace(table, namespace);
|
|
|
|
if (!ns)
|
|
|
|
{
|
|
|
|
ns = g_object_new(GNC_TYPE_COMMODITY_NAMESPACE, NULL);
|
|
|
|
ns->cm_table = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
ns->name = CACHE_INSERT((gpointer)namespace);
|
|
|
|
ns->iso4217 = gnc_commodity_namespace_is_iso(namespace);
|
|
|
|
qof_instance_init_data (&ns->inst, GNC_ID_COMMODITY_NAMESPACE, book);
|
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_CREATE, NULL);
|
|
|
|
|
|
|
|
g_hash_table_insert(table->ns_table,
|
|
|
|
(gpointer) ns->name,
|
|
|
|
(gpointer) ns);
|
|
|
|
table->ns_list = g_list_append(table->ns_list, ns);
|
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_ADD, NULL);
|
|
|
|
}
|
|
|
|
return ns;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gnc_commodity_namespace *
|
2005-11-01 21:32:36 -06:00
|
|
|
gnc_commodity_table_find_namespace(const gnc_commodity_table * table,
|
2010-03-02 15:40:28 -06:00
|
|
|
const char * namespace)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table || !namespace)
|
|
|
|
return NULL;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
namespace = gnc_commodity_table_map_namespace(namespace);
|
|
|
|
return g_hash_table_lookup(table->ns_table, (gpointer)namespace);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gnc_commodity *
|
2010-03-27 16:01:21 -05:00
|
|
|
gnc_commodity_find_commodity_by_guid(const GncGUID *guid, QofBook *book)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofCollection *col;
|
|
|
|
if (!guid || !book) return NULL;
|
|
|
|
col = qof_book_get_collection (book, GNC_ID_COMMODITY);
|
|
|
|
return (gnc_commodity *) qof_collection_lookup_entity (col, guid);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_delete_namespace
|
2010-03-02 15:40:28 -06:00
|
|
|
* delete a namespace
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
static int
|
2010-03-02 15:40:28 -06:00
|
|
|
ns_helper(gpointer key, gpointer value, gpointer user_data)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity * c = value;
|
|
|
|
gnc_commodity_destroy(c);
|
|
|
|
CACHE_REMOVE(key); /* key is commodity mnemonic */
|
|
|
|
return TRUE;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
void
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_commodity_table_delete_namespace(gnc_commodity_table * table,
|
2010-03-02 15:40:28 -06:00
|
|
|
const char * namespace)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * ns;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ns = gnc_commodity_table_find_namespace(table, namespace);
|
|
|
|
if (!ns)
|
|
|
|
return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_REMOVE, NULL);
|
|
|
|
g_hash_table_remove(table->ns_table, namespace);
|
|
|
|
table->ns_list = g_list_remove(table->ns_list, ns);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_list_free(ns->cm_list);
|
|
|
|
ns->cm_list = NULL;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_hash_table_foreach_remove(ns->cm_table, ns_helper, NULL);
|
|
|
|
g_hash_table_destroy(ns->cm_table);
|
|
|
|
CACHE_REMOVE(ns->name);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_DESTROY, NULL);
|
|
|
|
/* qof_instance_release(&ns->inst); */
|
|
|
|
g_object_unref(ns);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_foreach_commodity
|
|
|
|
* call user-defined function once for every commodity in every
|
2010-03-02 15:40:28 -06:00
|
|
|
* namespace
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gboolean ok;
|
|
|
|
gboolean (*func)(gnc_commodity *, gpointer);
|
|
|
|
gpointer user_data;
|
2001-08-07 18:36:04 -05:00
|
|
|
} IterData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
iter_commodity (gpointer key, gpointer value, gpointer user_data)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
IterData *iter_data = (IterData *) user_data;
|
|
|
|
gnc_commodity *cm = (gnc_commodity *) value;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (iter_data->ok)
|
|
|
|
{
|
|
|
|
iter_data->ok = (iter_data->func)(cm, iter_data->user_data);
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
iter_namespace (gpointer key, gpointer value, gpointer user_data)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
GHashTable *namespace_hash = ((gnc_commodity_namespace *) value)->cm_table;
|
|
|
|
g_hash_table_foreach (namespace_hash, iter_commodity, user_data);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean
|
2003-05-10 19:45:03 -05:00
|
|
|
gnc_commodity_table_foreach_commodity (const gnc_commodity_table * tbl,
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean (*f)(gnc_commodity *, gpointer),
|
|
|
|
gpointer user_data)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
IterData iter_data;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!tbl || !f) return FALSE;
|
2001-12-31 15:14:28 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
iter_data.ok = TRUE;
|
|
|
|
iter_data.func = f;
|
|
|
|
iter_data.user_data = user_data;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_hash_table_foreach(tbl->ns_table, iter_namespace, (gpointer)&iter_data);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
return iter_data.ok;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_destroy
|
2010-03-02 15:40:28 -06:00
|
|
|
* cleanup and free.
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table_destroy(gnc_commodity_table * t)
|
2001-12-31 15:14:28 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_namespace * ns;
|
|
|
|
GList *item, *next;
|
|
|
|
|
|
|
|
if (!t) return;
|
|
|
|
ENTER ("table=%p", t);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (item = t->ns_list; item; item = next)
|
|
|
|
{
|
|
|
|
next = g_list_next(item);
|
|
|
|
ns = item->data;
|
|
|
|
gnc_commodity_table_delete_namespace(t, ns->name);
|
|
|
|
}
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_list_free(t->ns_list);
|
|
|
|
t->ns_list = NULL;
|
|
|
|
g_hash_table_destroy(t->ns_table);
|
|
|
|
t->ns_table = NULL;
|
|
|
|
g_free(t);
|
|
|
|
LEAVE ("table=%p", t);
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-08-16 23:20:25 -05:00
|
|
|
/* =========================================================== */
|
|
|
|
|
2001-12-11 10:15:08 -06:00
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_table_add_default_data
|
|
|
|
********************************************************************/
|
|
|
|
|
2010-04-23 15:07:24 -05:00
|
|
|
#define CUR_I18N(String) dgettext ("iso_4217", String)
|
|
|
|
|
2001-12-11 10:15:08 -06:00
|
|
|
gboolean
|
2005-11-01 21:32:36 -06:00
|
|
|
gnc_commodity_table_add_default_data(gnc_commodity_table *table, QofBook *book)
|
2001-12-11 10:15:08 -06:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
QofCollection *col;
|
|
|
|
gnc_commodity* c;
|
|
|
|
|
|
|
|
ENTER ("table=%p", table);
|
|
|
|
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_AMEX, book);
|
|
|
|
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_NYSE, book);
|
|
|
|
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_NASDAQ, book);
|
|
|
|
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_EUREX, book);
|
|
|
|
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_MUTUAL, book);
|
|
|
|
gnc_commodity_table_add_namespace(table, "template", book);
|
|
|
|
c = gnc_commodity_new(book, "template", "template", "template", "template", 1);
|
|
|
|
gnc_commodity_table_insert(table, c);
|
|
|
|
|
|
|
|
#include "iso-4217-currencies.c"
|
|
|
|
|
|
|
|
/* We've just created the default namespaces and currencies. Mark
|
|
|
|
* these collections as clean because there is no USER entered data
|
|
|
|
* in these collections as of yet. */
|
|
|
|
col = qof_book_get_collection(book, GNC_ID_COMMODITY);
|
|
|
|
qof_collection_mark_clean(col);
|
|
|
|
col = qof_book_get_collection(book, GNC_ID_COMMODITY_NAMESPACE);
|
|
|
|
qof_collection_mark_clean(col);
|
|
|
|
|
|
|
|
LEAVE ("table=%p", table);
|
|
|
|
return TRUE;
|
2001-12-11 10:15:08 -06:00
|
|
|
}
|
|
|
|
|
2003-06-10 17:22:47 -05:00
|
|
|
/********************************************************************
|
|
|
|
********************************************************************/
|
2005-11-01 21:32:36 -06:00
|
|
|
/* QofObject function implementation and registration */
|
|
|
|
|
2010-02-27 12:41:49 -06:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
/* MSVC compiler doesn't have C99 "designated initializers"
|
|
|
|
* so we wrap them in a macro that is empty on MSVC. */
|
|
|
|
# define DI(x) /* */
|
|
|
|
#else
|
|
|
|
# define DI(x) x
|
|
|
|
#endif
|
2010-03-02 15:40:28 -06:00
|
|
|
static QofObject commodity_object_def =
|
|
|
|
{
|
|
|
|
DI(.interface_version = ) QOF_OBJECT_VERSION,
|
|
|
|
DI(.e_type = ) GNC_ID_COMMODITY,
|
|
|
|
DI(.type_label = ) "Commodity",
|
2010-03-22 16:14:38 -05:00
|
|
|
DI(.create = ) NULL,
|
2010-03-02 15:40:28 -06:00
|
|
|
DI(.book_begin = ) NULL,
|
|
|
|
DI(.book_end = ) NULL,
|
|
|
|
DI(.is_dirty = ) qof_collection_is_dirty,
|
|
|
|
DI(.mark_clean = ) qof_collection_mark_clean,
|
|
|
|
DI(.foreach = ) qof_collection_foreach,
|
|
|
|
DI(.printable = ) (const char * (*)(gpointer)) gnc_commodity_get_fullname,
|
2005-11-01 21:32:36 -06:00
|
|
|
};
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static QofObject namespace_object_def =
|
|
|
|
{
|
|
|
|
DI(.interface_version = ) QOF_OBJECT_VERSION,
|
|
|
|
DI(.e_type = ) GNC_ID_COMMODITY_NAMESPACE,
|
|
|
|
DI(.type_label = ) "Namespace",
|
2010-03-22 16:14:38 -05:00
|
|
|
DI(.create = ) NULL,
|
2010-03-02 15:40:28 -06:00
|
|
|
DI(.book_begin = ) NULL,
|
|
|
|
DI(.book_end = ) NULL,
|
|
|
|
DI(.is_dirty = ) NULL,
|
|
|
|
DI(.mark_clean = ) NULL,
|
|
|
|
DI(.foreach = ) NULL,
|
|
|
|
DI(.printable = ) NULL,
|
2005-11-01 21:32:36 -06:00
|
|
|
};
|
2003-06-10 17:22:47 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static void
|
2003-06-24 19:52:46 -05:00
|
|
|
commodity_table_book_begin (QofBook *book)
|
2003-06-10 17:22:47 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table *ct;
|
|
|
|
ENTER ("book=%p", book);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (gnc_commodity_table_get_table(book))
|
|
|
|
return;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ct = gnc_commodity_table_new ();
|
|
|
|
qof_book_set_data (book, GNC_COMMODITY_TABLE, ct);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!gnc_commodity_table_add_default_data(ct, book))
|
|
|
|
{
|
|
|
|
PWARN("unable to initialize book's commodity_table");
|
|
|
|
}
|
|
|
|
|
|
|
|
LEAVE ("book=%p", book);
|
2003-06-10 17:22:47 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static void
|
2003-06-24 19:52:46 -05:00
|
|
|
commodity_table_book_end (QofBook *book)
|
2003-06-10 17:22:47 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_table *ct;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
ct = gnc_commodity_table_get_table (book);
|
|
|
|
qof_book_set_data (book, GNC_COMMODITY_TABLE, NULL);
|
|
|
|
gnc_commodity_table_destroy (ct);
|
2003-06-10 17:22:47 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
static QofObject commodity_table_object_def =
|
2003-06-10 17:22:47 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
DI(.interface_version = ) QOF_OBJECT_VERSION,
|
|
|
|
DI(.e_type = ) GNC_ID_COMMODITY_TABLE,
|
|
|
|
DI(.type_label = ) "CommodityTable",
|
|
|
|
DI(.create = ) NULL,
|
|
|
|
DI(.book_begin = ) commodity_table_book_begin,
|
|
|
|
DI(.book_end = ) commodity_table_book_end,
|
|
|
|
DI(.is_dirty = ) qof_collection_is_dirty,
|
|
|
|
DI(.mark_clean = ) qof_collection_mark_clean,
|
|
|
|
DI(.foreach = ) NULL,
|
|
|
|
DI(.printable = ) NULL,
|
|
|
|
DI(.version_cmp = ) NULL,
|
2003-06-10 17:22:47 -05:00
|
|
|
};
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
gboolean
|
2003-06-10 17:22:47 -05:00
|
|
|
gnc_commodity_table_register (void)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_quote_source_init_tables();
|
|
|
|
|
|
|
|
if (!qof_object_register (&commodity_object_def))
|
|
|
|
return FALSE;
|
|
|
|
if (!qof_object_register (&namespace_object_def))
|
|
|
|
return FALSE;
|
|
|
|
return qof_object_register (&commodity_table_object_def);
|
2003-06-10 17:22:47 -05:00
|
|
|
}
|
|
|
|
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
/* *******************************************************************
|
|
|
|
* gnc_monetary methods
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
/** Add a gnc_monetary to the list */
|
|
|
|
MonetaryList *
|
|
|
|
gnc_monetary_list_add_monetary(MonetaryList *list, gnc_monetary add_mon)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
MonetaryList *l = list, *tmp;
|
|
|
|
for (tmp = list; tmp; tmp = tmp->next)
|
|
|
|
{
|
|
|
|
gnc_monetary *list_mon = tmp->data;
|
|
|
|
if (gnc_commodity_equiv(list_mon->commodity, add_mon.commodity))
|
|
|
|
{
|
|
|
|
list_mon->value = gnc_numeric_add(list_mon->value, add_mon.value,
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
|
|
|
|
break;
|
|
|
|
}
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
/* See if we found an entry, and add one if not */
|
|
|
|
if (tmp == NULL)
|
|
|
|
{
|
|
|
|
gnc_monetary *new_mon = g_new0(gnc_monetary, 1);
|
|
|
|
*new_mon = add_mon;
|
|
|
|
l = g_list_prepend(l, new_mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
return l;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Delete all entries in the list that have zero value. Return list
|
|
|
|
pointer will be a null pointer if there are no non-zero entries **/
|
|
|
|
MonetaryList *
|
|
|
|
gnc_monetary_list_delete_zeros(MonetaryList *list)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
MonetaryList *node, *next;
|
|
|
|
for (node = list; node; node = next)
|
|
|
|
{
|
|
|
|
gnc_monetary *mon = node->data;
|
|
|
|
next = node->next;
|
|
|
|
if (gnc_numeric_zero_p(mon->value))
|
|
|
|
{
|
|
|
|
g_free(mon);
|
|
|
|
list = g_list_delete_link(list, node);
|
|
|
|
}
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
2010-03-02 15:40:28 -06:00
|
|
|
return list;
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Free a MonetaryList and all the monetaries it points to */
|
|
|
|
void
|
|
|
|
gnc_monetary_list_free(MonetaryList *list)
|
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
MonetaryList *tmp;
|
|
|
|
for (tmp = list; tmp; tmp = tmp->next)
|
|
|
|
{
|
|
|
|
g_free(tmp->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free(list);
|
Bug #537476: Implement currency trading accounts optionally, to be enabled per-book.
Patch by Mike Alexander:
This patch implements trading accounts somewhat as described in Peter
Selinger's document at
<http://www.mathstat.dal.ca/~selinger/accounting/gnucash.html>. Although he
describes it as a multiple currency problem, it really applies to any
transactions involving multiple commodities (for example buying or selling a
stock) Hence I've called the trading accounts "commodity exchange accounts"
which seems more descriptive.
In summary these patches add an option to use commodity exchange accounts and
if it is on a transaction must be balanced both in value (in the transaction
currency) and in each commodity or currency used in any split in the
transaction. If a transaction only contains splits in the transaction currency
then this is the same rule as Gnucash has always enforced.
In this patch, the option to use trading accounts has been moved from
Edit->Preferences to File->Properties and is now associated with the active
book instead of being a global option. If you have set the global value on in
a previous version you will need to set it on again in each file for which you
want trading accounts, the previous global setting will be ignored.
A more detailed list of changes follows:
1. Added a "Use commodity exchange accounts" per-book option.
2. Added gnc_monetary and MonetaryList data types.
3. Renamed xaccTransGetImbalance to xaccTransGetImbalanceValue and added a new
xaccTransGetImbalance that returns a MonetaryList. Also added
xaccTransIsBalanced to see if the transaction is balanced without returning a
GList that needs to be freed. It calls both xaccTransGetImbalance and
xaccTransGetImbalanceValue since a transaction may be unbalanced with regard to
either without being unbalanced with regard to the other.
4. Changed gnc_split_register_get_debcred_bg_color to use xaccTransIsBalanced.
5. Changed gnc_split_register_balance_trans to not offer to adjust an existing
split if there imbalances in multiple currencies. Because of bugs in the
register code this is rarely called.
6. Changed importers to use xaccTransGetImbalanceValue to check for imbalance,
assuming that they won't create multiple currency trasactions.
7. Changed xaccTransScrubImbalance to create a balancing split for each
imbalanced commodity in the transaction. Also balances the transaction value.
The commodity balancing splits go into accounts in the hierarchy
Trading:NAMESPACE:COMMODITY. The value balancing splits go into
Imbalance-CURRENCY as before.
8. Changed xaccSplitConvertAmount to use xaccTransIsBalanced instead of
xaccTransGetImbalance.
9. Changed gnc_split_register_get_debcred_entry to sometimes use the split
amount instead of value if using currency accounts.
If the register is a stock register (i.e., shows shares and prices), it uses
the value if the split is in the register commodity (i.e. is for the stock) and
the amount otherwise. It shows the currency symbol unless the commodity is the
default currency.
If the register is not a stock register it always uses the amount and shows the
currency symbol if the split is not in the register commodity.
Also changed it to not return a value for a null split unless the transaction
is unbalanced in exactly one currency. This is what goes in a blank split as
the proposed value.
10. Changed refresh_model_row to use xaccTransGetImbalanceValue to get the
imbalance, assuming that importers don't create transactions in multiple
currencies. Also same change in gnc_import_process_trans_item,
downloaded_transaction_append, and gnc_import_TransInfo_is_balanced.
11. Changed the TRANS_IMBALANCE accessor method in xaccTransRegister to use
xaccTransGetImbalanceValue. As far as I can tell this is only used by the
"pd-balance" query type in gnc_scm2query_term_query_v1() defined in
engine-helpers.c. This query type only tests the result for zero/non-zero.
12. Changed xaccTransGetAccountConvRate to accept any split into the correct
commodity instead of insisting on one into the provided account. Then can use
it in xaccTransScrubImbalance to set the value of the imbalance split from its
amount, however later changed xaccTransScrubImbalance to not use it. Instead
it sets the value for the new split correctly to keep the value of the whole
transaction balanced.
13. Changed the balance sheet report to include a new option to not compute
unrealized gains and losses.
14. Related to 9 above, changed gnc_split_register_auto_calc to not do anything
if given a stock register where the value cell doesn't contain the value.
15. Also related to 9, changed gnc_split_register_save_amount_values to set the
amount and value fields in the split correctly when using trading accounts.
16. Changed the new account and edit account dialogs to allow any commodity or
currency for an income account if using trading accounts. It would be better
to add a new account type for trading accounts, but that's a big deal and I'll
leave that for later after we see whether this set of changes is going to be
accepted or rejected.
17. Change gnc_xfer_dialog_run_exchange_dialog to understand that the new value
is really the split's amount if using trading accounts.
18. Changed xaccSplitGetOtherSplit to ignore trading splits if using commodity
exchange accounts.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18429 57a11ea4-9604-0410-9ed3-97b8803252fd
2009-11-20 14:11:03 -06:00
|
|
|
}
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
/* ========================= END OF FILE ============================== */
|