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
|
|
|
* *
|
|
|
|
*******************************************************************/
|
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
#include <config.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
|
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>
|
2014-05-07 08:37:14 -05:00
|
|
|
#include <qofinstance-p.h>
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-02-11 20:40:11 -06:00
|
|
|
#include "gnc-commodity.hpp"
|
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"
|
2023-01-24 11:46:48 -06:00
|
|
|
#include "guid.h"
|
|
|
|
#include "qofinstance.h"
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-05-09 01:43:54 -05:00
|
|
|
#include <list>
|
2024-02-18 19:19:44 -06:00
|
|
|
#include <unordered_map>
|
|
|
|
|
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,
|
2014-05-07 08:37:14 -05:00
|
|
|
PROP_NAMESPACE, /* Table */
|
|
|
|
PROP_FULL_NAME, /* Table */
|
|
|
|
PROP_MNEMONIC, /* Table */
|
|
|
|
PROP_PRINTNAME, /* Constructed */
|
|
|
|
PROP_CUSIP, /* Table */
|
|
|
|
PROP_FRACTION, /* Table */
|
|
|
|
PROP_UNIQUE_NAME, /* Constructed */
|
|
|
|
PROP_QUOTE_FLAG, /* Table */
|
|
|
|
PROP_QUOTE_SOURCE, /* Table */
|
|
|
|
PROP_QUOTE_TZ, /* Table */
|
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
|
|
|
|
2018-12-05 14:50:15 -06:00
|
|
|
typedef struct gnc_commodityPrivate
|
2008-08-01 11:02:07 -05:00
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
gnc_commodity_namespace *name_space;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2021-07-08 14:42:03 -05:00
|
|
|
const char *fullname;
|
|
|
|
const char *mnemonic;
|
|
|
|
char *printname;
|
|
|
|
const char *cusip; /* CUSIP or other identifying code */
|
|
|
|
int fraction;
|
|
|
|
char *unique_name;
|
2021-08-21 22:17:28 -05:00
|
|
|
char *user_symbol;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2021-07-08 14:42:03 -05:00
|
|
|
gboolean quote_flag; /* user wants price quotes */
|
|
|
|
gnc_quote_source *quote_source; /* current/old source of quotes */
|
|
|
|
const 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 */
|
2021-07-08 14:42:03 -05:00
|
|
|
int usage_count;
|
2013-11-20 22:57:30 -06:00
|
|
|
|
|
|
|
/* the default display_symbol, set in iso-4217-currencies at start-up */
|
2021-07-08 14:42:03 -05:00
|
|
|
const char *default_symbol;
|
2018-12-05 14:50:15 -06:00
|
|
|
} gnc_commodityPrivate;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
|
|
|
#define GET_PRIVATE(o) \
|
2022-07-30 18:45:13 -05:00
|
|
|
((gnc_commodityPrivate*)gnc_commodity_get_instance_private((gnc_commodity*)o))
|
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
|
|
|
|
2021-07-08 14:42:03 -05:00
|
|
|
const gchar *name;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
};
|
|
|
|
|
2024-02-18 19:19:44 -06:00
|
|
|
static const std::unordered_map<std::string,std::string> gnc_new_iso_codes =
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
{"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
|
2019-10-05 13:06:58 -05:00
|
|
|
* exists in the file iso-4217-currencies.xml */
|
2003-05-29 18:47:52 -05:00
|
|
|
};
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2024-02-11 09:07:53 -06:00
|
|
|
static std::string fq_version;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
struct gnc_quote_source_s
|
|
|
|
{
|
2024-02-12 05:00:41 -06:00
|
|
|
private:
|
|
|
|
gboolean m_supported;
|
|
|
|
QuoteSourceType m_type;
|
|
|
|
std::string m_user_name; /* User friendly name incl. region code*/
|
|
|
|
std::string m_internal_name; /* Name used internally and by finance::quote. */
|
|
|
|
public:
|
|
|
|
bool get_supported () const { return m_supported; }
|
|
|
|
void set_supported (bool supported) { m_supported = supported; }
|
|
|
|
QuoteSourceType get_type () const { return m_type; }
|
|
|
|
const char* get_user_name () const { return m_user_name.c_str(); }
|
|
|
|
const char* get_internal_name () const { return m_internal_name.c_str(); }
|
2024-02-14 10:36:44 -06:00
|
|
|
gnc_quote_source_s (gboolean supported, QuoteSourceType type,
|
2024-02-12 05:00:41 -06:00
|
|
|
const char* username, const char* int_name)
|
|
|
|
: m_supported{supported}
|
|
|
|
, m_type{type}
|
2024-05-03 19:26:11 -05:00
|
|
|
, m_user_name{username ? username : ""}
|
|
|
|
, m_internal_name{int_name ? int_name: ""} { };
|
2003-07-01 22:35:20 -05:00
|
|
|
};
|
|
|
|
|
2024-05-09 01:43:54 -05:00
|
|
|
using QuoteSourceList = std::list<gnc_quote_source>;
|
2024-02-18 03:20:09 -06:00
|
|
|
|
2018-03-15 12:09:08 -05:00
|
|
|
/* To update the following lists scan
|
|
|
|
* from github.com/finance-quote/finance-quote
|
|
|
|
* in lib/Finance/Quote/ all *.pm for "methods"
|
|
|
|
* because many of them have more than one -
|
|
|
|
* ideally after each release of them.
|
|
|
|
*
|
|
|
|
* Apply changes here also to the FQ appendix of help.
|
2018-03-10 03:20:26 -06:00
|
|
|
*/
|
2024-05-09 01:43:54 -05:00
|
|
|
static QuoteSourceList currency_quote_sources =
|
2024-02-18 03:20:09 -06:00
|
|
|
{
|
|
|
|
{ true, SOURCE_CURRENCY, "Currency", "currency" }
|
|
|
|
};
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2018-03-15 12:09:08 -05:00
|
|
|
/* The single quote method is usually the module name, but
|
2021-02-05 13:52:33 -06:00
|
|
|
* sometimes it gets the suffix "_direct"
|
2018-03-15 12:09:08 -05:00
|
|
|
* and the failover method is without suffix.
|
|
|
|
*/
|
2024-05-09 01:43:54 -05:00
|
|
|
static QuoteSourceList single_quote_sources =
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-14 10:36:44 -06:00
|
|
|
{ false, SOURCE_SINGLE, "Alphavantage, US", "alphavantage" },
|
|
|
|
{ false, SOURCE_SINGLE, "Amsterdam Euronext eXchange, NL", "aex" },
|
|
|
|
{ false, SOURCE_SINGLE, "Association of Mutual Funds in India", "amfiindia" },
|
|
|
|
{ false, SOURCE_SINGLE, "Australian Stock Exchange, AU", "asx" },
|
|
|
|
{ false, SOURCE_SINGLE, "Canada Mutual", "canadamutual" },
|
|
|
|
{ false, SOURCE_SINGLE, "Deka Investments, DE", "deka" },
|
|
|
|
{ false, SOURCE_SINGLE, "Dutch", "dutch" },
|
|
|
|
{ false, SOURCE_SINGLE, "DWS, DE", "dwsfunds" },
|
|
|
|
{ false, SOURCE_SINGLE, "Financial Times Funds service, GB", "ftfunds" },
|
|
|
|
{ false, SOURCE_SINGLE, "Finanzpartner, DE", "finanzpartner" },
|
|
|
|
{ false, SOURCE_SINGLE, "GoldMoney spot rates, JE", "goldmoney" },
|
2024-04-06 20:23:35 -05:00
|
|
|
{ false, SOURCE_SINGLE, "Google Web, US Stocks", "googleweb" },
|
2024-02-14 10:36:44 -06:00
|
|
|
{ false, SOURCE_SINGLE, "India Mutual", "indiamutual" },
|
2024-04-06 20:23:35 -05:00
|
|
|
{ false, SOURCE_SINGLE, "Morningstar, GB", "morningstaruk" },
|
2024-02-14 10:36:44 -06:00
|
|
|
{ false, SOURCE_SINGLE, "Morningstar, JP", "morningstarjp" },
|
|
|
|
{ false, SOURCE_SINGLE, "New Zealand stock eXchange, NZ", "nzx" },
|
|
|
|
{ false, SOURCE_SINGLE, "Paris Stock Exchange/Boursorama, FR", "bourso" },
|
|
|
|
{ false, SOURCE_SINGLE, "Romania", "romania" },
|
2024-04-06 20:23:35 -05:00
|
|
|
{ false, SOURCE_SINGLE, "SIX Swiss Exchange shares, CH", "six" },
|
2024-02-14 10:36:44 -06:00
|
|
|
{ false, SOURCE_SINGLE, "Skandinaviska Enskilda Banken, SE", "seb_funds" },
|
|
|
|
{ false, SOURCE_SINGLE, "Sharenet, ZA", "za" },
|
|
|
|
{ false, SOURCE_SINGLE, "TIAA-CREF, US", "tiaacref" },
|
|
|
|
{ false, SOURCE_SINGLE, "Toronto Stock eXchange, CA", "tsx" },
|
|
|
|
{ false, SOURCE_SINGLE, "T. Rowe Price", "troweprice" },
|
|
|
|
{ false, SOURCE_SINGLE, "T. Rowe Price, US", "troweprice_direct" },
|
|
|
|
{ false, SOURCE_SINGLE, "Union Investment, DE", "unionfunds" },
|
|
|
|
{ false, SOURCE_SINGLE, "US Govt. Thrift Savings Plan", "tsp" },
|
|
|
|
{ false, SOURCE_SINGLE, "Yahoo as JSON", "yahoo_json" },
|
2024-04-06 20:23:35 -05:00
|
|
|
{ false, SOURCE_SINGLE, "Yahoo Web", "yahooweb" },
|
2024-09-19 15:00:33 -05:00
|
|
|
{ false, SOURCE_SINGLE, "YH Finance (FinanceAPI)", "financeapi" },
|
2003-07-01 22:35:20 -05:00
|
|
|
};
|
2018-03-15 12:09:08 -05:00
|
|
|
|
2024-05-09 01:43:54 -05:00
|
|
|
static QuoteSourceList multiple_quote_sources =
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-14 10:36:44 -06:00
|
|
|
{ false, SOURCE_MULTI, "Australia (ASX, ...)", "australia" },
|
|
|
|
{ false, SOURCE_MULTI, "Canada (Alphavantage, TSX, ...)", "canada" },
|
|
|
|
{ false, SOURCE_MULTI, "Canada Mutual (Fund Library, StockHouse, ...)", "canadamutual" },
|
|
|
|
{ false, SOURCE_MULTI, "Dutch (AEX, ...)", "dutch" },
|
|
|
|
{ false, SOURCE_MULTI, "Europe (asegr,.bsero, hex ...)", "europe" },
|
|
|
|
{ false, SOURCE_MULTI, "India Mutual (AMFI, ...)", "indiamutual" },
|
|
|
|
{ false, SOURCE_MULTI, "France (bourso, ĺerevenu, ...)", "france" },
|
2024-04-07 19:36:23 -05:00
|
|
|
{ false, SOURCE_MULTI, "Nasdaq (alphavantage, yahoo_json, ...)", "nasdaq" },
|
|
|
|
{ false, SOURCE_MULTI, "NYSE (alphavantage, yahoo_json, ...)", "nyse" },
|
2024-02-14 10:36:44 -06:00
|
|
|
{ false, SOURCE_MULTI, "South Africa (Sharenet, ...)", "za" },
|
|
|
|
{ false, SOURCE_MULTI, "Romania (BSE-RO, ...)", "romania" },
|
|
|
|
{ false, SOURCE_MULTI, "T. Rowe Price", "troweprice" },
|
|
|
|
{ false, SOURCE_MULTI, "U.K. Funds (citywire, FTfunds, MStar, tnetuk, ...)", "ukfunds" },
|
2024-04-07 19:36:23 -05:00
|
|
|
{ false, SOURCE_MULTI, "USA (alphavantage, yahoo_json, ...)", "usa" },
|
2003-07-01 22:35:20 -05:00
|
|
|
};
|
|
|
|
|
2024-05-09 01:43:54 -05:00
|
|
|
static QuoteSourceList new_quote_sources;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2024-02-18 03:20:09 -06:00
|
|
|
// cannot use map or unordered_map because order must be preserved
|
2024-05-09 01:43:54 -05:00
|
|
|
static const std::vector<std::pair<QuoteSourceType,QuoteSourceList&>> quote_sources_map =
|
2024-02-18 03:20:09 -06:00
|
|
|
{
|
|
|
|
{ SOURCE_CURRENCY, currency_quote_sources },
|
|
|
|
{ SOURCE_SINGLE, single_quote_sources },
|
|
|
|
{ SOURCE_MULTI, multiple_quote_sources },
|
|
|
|
{ SOURCE_UNKNOWN, new_quote_sources }
|
|
|
|
};
|
2003-07-01 22:35:20 -05:00
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* 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)
|
|
|
|
{
|
2024-02-11 09:07:53 -06:00
|
|
|
return (!fq_version.empty());
|
2018-01-25 03:09:50 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_quote_source_fq_version
|
|
|
|
*
|
|
|
|
* This function the version of the Finance::Quote module installed
|
2024-03-17 17:11:48 -05:00
|
|
|
* on a user's computer or nullptr if no installation is found.
|
2018-01-25 03:09:50 -06:00
|
|
|
********************************************************************/
|
|
|
|
const char*
|
|
|
|
gnc_quote_source_fq_version (void)
|
|
|
|
{
|
2024-02-11 09:07:53 -06:00
|
|
|
return fq_version.c_str();
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
2024-05-09 01:43:54 -05:00
|
|
|
static QuoteSourceList&
|
2024-02-18 03:20:09 -06:00
|
|
|
get_quote_source_from_type (QuoteSourceType type)
|
|
|
|
{
|
2024-02-16 03:47:03 -06:00
|
|
|
auto quote_sources_it = std::find_if (quote_sources_map.begin(), quote_sources_map.end(),
|
|
|
|
[type] (const auto& qs) { return type == qs.first; });
|
2024-02-18 03:20:09 -06:00
|
|
|
|
2024-02-16 03:47:03 -06:00
|
|
|
if (quote_sources_it != quote_sources_map.end())
|
|
|
|
return quote_sources_it->second;
|
|
|
|
|
|
|
|
PWARN ("Invalid Quote Source %d, returning new_quote_sources", type);
|
2024-02-18 03:20:09 -06:00
|
|
|
return new_quote_sources;
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2024-05-09 01:43:54 -05:00
|
|
|
auto source{get_quote_source_from_type(type)};
|
|
|
|
return std::distance(source.begin(), source.end());
|
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)
|
|
|
|
{
|
2024-02-16 03:46:21 -06:00
|
|
|
DEBUG("Creating new source %s", (!source_name ? "(null)" : source_name));
|
2010-03-02 15:40:28 -06:00
|
|
|
/* This name can be changed if/when support for this price source is
|
|
|
|
* integrated into gnucash. */
|
|
|
|
/* 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). */
|
2024-02-14 10:36:44 -06:00
|
|
|
return &new_quote_sources.emplace_back (supported, SOURCE_UNKNOWN, source_name, source_name);
|
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
|
|
|
ENTER("type/index is %d/%d", type, index);
|
2024-02-18 03:20:09 -06:00
|
|
|
auto& sources = get_quote_source_from_type (type);
|
|
|
|
if ((size_t) index < sources.size())
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-05-09 01:43:54 -05:00
|
|
|
auto it = std::next(sources.begin(), index);
|
|
|
|
LEAVE("found %s", it->get_user_name());
|
|
|
|
return &*it;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE("not found");
|
2024-02-16 03:46:21 -06:00
|
|
|
return nullptr;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
gnc_quote_source *
|
|
|
|
gnc_quote_source_lookup_by_internal(const char * name)
|
|
|
|
{
|
2024-02-16 03:46:21 -06:00
|
|
|
if (!name || !*name)
|
|
|
|
return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2024-02-18 03:20:09 -06:00
|
|
|
for (const auto& [_, sources] : quote_sources_map)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-16 03:47:03 -06:00
|
|
|
auto source_it = std::find_if (sources.begin(), sources.end(),
|
|
|
|
[name] (const auto& qs)
|
|
|
|
{ return (g_strcmp0(name, qs.get_internal_name()) == 0); });
|
|
|
|
if (source_it != sources.end())
|
|
|
|
return &(*source_it);
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
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);
|
2024-02-16 03:46:21 -06:00
|
|
|
return nullptr;
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* 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
|
|
|
|
2024-02-12 05:00:41 -06:00
|
|
|
LEAVE("type is %d", source->get_type());
|
|
|
|
return source->get_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
|
|
|
if (!source)
|
|
|
|
{
|
2024-02-14 10:36:44 -06:00
|
|
|
PWARN ("bad source");
|
2010-03-02 15:40:28 -06:00
|
|
|
return 0;
|
|
|
|
}
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2024-02-18 03:20:09 -06:00
|
|
|
auto& sources = get_quote_source_from_type (source->get_type());
|
|
|
|
auto is_source = [&source](const auto& findif_source)
|
|
|
|
{ return &findif_source == source; };
|
|
|
|
|
|
|
|
auto iter = std::find_if (sources.begin(), sources.end(), is_source);
|
|
|
|
if (iter != sources.end())
|
|
|
|
return std::distance (sources.begin(), iter);
|
|
|
|
|
2024-02-14 10:36:44 -06:00
|
|
|
PWARN ("couldn't locate source");
|
|
|
|
return 0;
|
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
|
|
|
|
2024-02-16 03:46:21 -06:00
|
|
|
LEAVE("%s supported", source && source->get_supported() ? "" : "not ");
|
2024-02-12 05:00:41 -06:00
|
|
|
return source->get_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");
|
2024-02-16 03:46:21 -06:00
|
|
|
return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2024-02-12 05:00:41 -06:00
|
|
|
LEAVE("user name %s", source->get_user_name());
|
|
|
|
return source->get_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");
|
2024-02-16 03:46:21 -06:00
|
|
|
return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2024-02-12 05:00:41 -06:00
|
|
|
LEAVE("internal name %s", source->get_internal_name());
|
|
|
|
return source->get_internal_name();
|
2003-07-01 22:35:20 -05:00
|
|
|
}
|
|
|
|
|
2018-01-25 03:09:50 -06:00
|
|
|
|
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
|
2018-01-25 03:09:50 -06:00
|
|
|
gnc_quote_source_set_fq_installed (const char* version_string,
|
2024-02-11 20:40:11 -06:00
|
|
|
const std::vector<std::string>& sources_list)
|
2003-07-01 22:35:20 -05:00
|
|
|
{
|
2010-03-02 15:40:28 -06:00
|
|
|
ENTER(" ");
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2024-02-11 20:40:11 -06:00
|
|
|
if (sources_list.empty())
|
2010-03-02 15:40:28 -06:00
|
|
|
return;
|
2003-07-01 22:35:20 -05:00
|
|
|
|
2018-01-25 03:09:50 -06:00
|
|
|
if (version_string)
|
2024-02-11 09:07:53 -06:00
|
|
|
fq_version = version_string;
|
|
|
|
else
|
|
|
|
fq_version.clear();
|
2018-01-25 03:09:50 -06:00
|
|
|
|
2024-02-11 20:40:11 -06:00
|
|
|
for (const auto& source_name_str : sources_list)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-11 20:40:11 -06:00
|
|
|
auto source_name = source_name_str.c_str();
|
|
|
|
auto source = gnc_quote_source_lookup_by_internal(source_name);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2024-02-16 03:46:21 -06:00
|
|
|
if (source)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-12 05:00:41 -06:00
|
|
|
DEBUG("Found source %s: %s", source_name, source->get_user_name());
|
|
|
|
source->set_supported (true);
|
2010-03-02 15:40:28 -06:00
|
|
|
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);
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&cm->inst, QOF_EVENT_MODIFY, nullptr);
|
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
|
2018-12-05 14:50:15 -06:00
|
|
|
reset_printname(gnc_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
|
2018-12-05 14:50:15 -06:00
|
|
|
reset_unique_name(gnc_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);
|
2014-08-12 12:56:53 -05:00
|
|
|
ns = priv->name_space;
|
2008-08-01 11:02:07 -05:00
|
|
|
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 */
|
2023-01-24 07:22:18 -06:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE(gnc_commodity, gnc_commodity, QOF_TYPE_INSTANCE)
|
2007-04-04 19:24:18 -05:00
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_commodity_init(gnc_commodity* com)
|
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
priv->name_space = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
priv->fullname = CACHE_INSERT("");
|
|
|
|
priv->mnemonic = CACHE_INSERT("");
|
|
|
|
priv->cusip = CACHE_INSERT("");
|
|
|
|
priv->fraction = 10000;
|
|
|
|
priv->quote_flag = 0;
|
2024-03-17 17:11:48 -05:00
|
|
|
priv->quote_source = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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;
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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:
|
2014-08-12 12:56:53 -05:00
|
|
|
g_value_take_object(value, priv->name_space);
|
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);
|
2014-05-07 08:37:14 -05:00
|
|
|
g_assert (qof_instance_get_editlevel(commodity));
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
switch (prop_id)
|
|
|
|
{
|
2008-08-01 11:02:07 -05:00
|
|
|
case PROP_NAMESPACE:
|
2024-02-09 22:14:40 -06:00
|
|
|
gnc_commodity_set_namespace(commodity, static_cast<const char*>(g_value_get_object(value)));
|
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
|
|
|
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:
|
2024-02-09 22:14:40 -06:00
|
|
|
gnc_commodity_set_quote_source(commodity, static_cast<gnc_quote_source*>(g_value_get_pointer(value)));
|
2010-03-02 15:40:28 -06:00
|
|
|
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;
|
|
|
|
|
|
|
|
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.",
|
2024-03-17 17:11:48 -05:00
|
|
|
nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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.",
|
2024-03-17 17:11:48 -05:00
|
|
|
nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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.",
|
2024-03-17 17:11:48 -05:00
|
|
|
nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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",
|
|
|
|
"?????",
|
2024-03-17 17:11:48 -05:00
|
|
|
nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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,
|
2018-09-21 14:29:56 -05:00
|
|
|
GNC_COMMODITY_MAX_FRACTION,
|
2010-03-02 15:40:28 -06:00
|
|
|
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.",
|
2024-03-17 17:11:48 -05:00
|
|
|
nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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",
|
|
|
|
"?????",
|
2024-03-17 17:11:48 -05:00
|
|
|
nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space, const char * mnemonic,
|
2006-02-11 14:00:52 -06:00
|
|
|
const char * cusip, int fraction)
|
2001-08-07 18:36:04 -05:00
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
auto retval = GNC_COMMODITY(g_object_new(GNC_TYPE_COMMODITY, nullptr));
|
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
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if ( name_space != nullptr )
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2014-01-16 16:52:03 -06:00
|
|
|
/* Prevent setting anything except template in namespace template. */
|
2017-06-20 05:06:14 -05:00
|
|
|
if (g_strcmp0 (name_space, GNC_COMMODITY_NS_TEMPLATE) == 0 &&
|
2014-01-16 16:52:03 -06:00
|
|
|
g_strcmp0 (mnemonic, "template") != 0)
|
|
|
|
{
|
|
|
|
PWARN("Converting commodity %s from namespace template to "
|
|
|
|
"namespace User", mnemonic);
|
2014-08-12 12:56:53 -05:00
|
|
|
name_space = "User";
|
2014-01-16 16:52:03 -06:00
|
|
|
}
|
2014-08-12 12:56:53 -05:00
|
|
|
gnc_commodity_set_namespace(retval, name_space);
|
|
|
|
if (gnc_commodity_namespace_is_iso(name_space))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
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);
|
2014-09-04 18:26:32 -05:00
|
|
|
mark_commodity_dirty (retval);
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_commit_edit(retval);
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&retval->inst, QOF_EVENT_CREATE, nullptr);
|
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;
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&cm->inst, QOF_EVENT_DESTROY, nullptr);
|
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);
|
2024-03-17 17:11:48 -05:00
|
|
|
priv->name_space = nullptr;
|
2001-10-03 05:07:45 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Set through accessor functions */
|
2024-03-17 17:11:48 -05:00
|
|
|
priv->quote_source = nullptr;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Automatically generated */
|
|
|
|
g_free(priv->printname);
|
2024-03-17 17:11:48 -05:00
|
|
|
priv->printname = nullptr;
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
g_free(priv->unique_name);
|
2024-03-17 17:11:48 -05:00
|
|
|
priv->unique_name = nullptr;
|
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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* src_priv = GET_PRIVATE(src);
|
|
|
|
gnc_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);
|
2014-08-12 12:56:53 -05:00
|
|
|
dest_priv->name_space = src_priv->name_space;
|
2010-03-02 15:40:28 -06:00
|
|
|
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);
|
2015-06-09 18:19:41 -05:00
|
|
|
qof_instance_copy_kvp (QOF_INSTANCE (dest), QOF_INSTANCE (src));
|
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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* src_priv;
|
|
|
|
gnc_commodityPrivate* dest_priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
auto dest = GNC_COMMODITY (g_object_new(GNC_TYPE_COMMODITY, nullptr));
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
dest_priv->name_space = src_priv->name_space;
|
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
|
|
|
|
2015-06-09 18:19:41 -05:00
|
|
|
qof_instance_copy_kvp (QOF_INSTANCE (dest), QOF_INSTANCE (src));
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2014-08-12 12:56:53 -05:00
|
|
|
return gnc_commodity_namespace_get_name(GET_PRIVATE(cm)->name_space);
|
2001-08-07 18:36:04 -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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2014-08-12 12:56:53 -05:00
|
|
|
return GET_PRIVATE(cm)->name_space;
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
|
|
|
{
|
2015-06-09 18:19:41 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2021-06-01 09:45:49 -05:00
|
|
|
gboolean retval = TRUE;
|
2007-12-25 23:17:37 -06:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!cm) return FALSE;
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_get_kvp (QOF_INSTANCE (cm), &v, 1, "auto_quote_control");
|
2015-06-09 18:19:41 -05:00
|
|
|
if (G_VALUE_HOLDS_STRING (&v) &&
|
|
|
|
strcmp(g_value_get_string (&v), "false") == 0)
|
2021-06-01 09:45:49 -05:00
|
|
|
retval = FALSE;
|
|
|
|
g_value_unset (&v);
|
|
|
|
return retval;
|
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)
|
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv;
|
2008-08-01 11:02:07 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
if (!priv->quote_source && gnc_commodity_is_iso(cm))
|
2024-05-09 01:43:54 -05:00
|
|
|
return ¤cy_quote_sources.front();
|
2010-03-02 15:40:28 -06:00
|
|
|
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))
|
2024-05-09 01:43:54 -05:00
|
|
|
return ¤cy_quote_sources.front();
|
2010-03-02 15:40:28 -06:00
|
|
|
/* Should make this a user option at some point. */
|
2018-01-02 12:43:49 -06:00
|
|
|
return gnc_quote_source_lookup_by_internal("alphavantage");
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
g_return_val_if_fail (GNC_IS_COMMODITY (cm), nullptr);
|
2023-03-01 05:49:20 -06:00
|
|
|
|
|
|
|
GValue v = G_VALUE_INIT;
|
|
|
|
qof_instance_get_kvp (QOF_INSTANCE(cm), &v, 1, "user_symbol");
|
2024-03-17 17:11:48 -05:00
|
|
|
const char *rv = G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : nullptr;
|
2023-03-01 05:49:20 -06:00
|
|
|
g_value_unset (&v);
|
|
|
|
return rv;
|
2014-03-25 19:07:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************
|
|
|
|
* gnc_commodity_get_default_symbol
|
|
|
|
*******************************************************************/
|
|
|
|
const char*
|
|
|
|
gnc_commodity_get_default_symbol(const gnc_commodity *cm)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
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;
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!cm) return nullptr;
|
2014-03-25 19:07:49 -05:00
|
|
|
|
|
|
|
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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
2014-08-12 12:56:53 -05:00
|
|
|
gnc_commodity_set_namespace(gnc_commodity * cm, const char * name_space)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
QofBook *book;
|
|
|
|
gnc_commodity_table *table;
|
|
|
|
gnc_commodity_namespace *nsp;
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
if (!cm) return;
|
|
|
|
priv = GET_PRIVATE(cm);
|
|
|
|
book = qof_instance_get_book (&cm->inst);
|
|
|
|
table = gnc_commodity_table_get_table(book);
|
2014-08-12 12:56:53 -05:00
|
|
|
nsp = gnc_commodity_table_add_namespace(table, name_space, book);
|
|
|
|
if (priv->name_space == nsp)
|
2010-03-02 15:40:28 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
gnc_commodity_begin_edit(cm);
|
2014-08-12 12:56:53 -05:00
|
|
|
priv->name_space = nsp;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
|
|
{
|
2015-06-09 18:19:41 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
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;
|
|
|
|
}
|
|
|
|
gnc_commodity_begin_edit(cm);
|
2015-06-09 18:19:41 -05:00
|
|
|
if (flag)
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (cm), nullptr, 1, "auto_quote_control");
|
2015-06-09 18:19:41 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
|
|
|
g_value_set_string (&v, "false");
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE (cm), &v, 1, "auto_quote_control");
|
2015-06-09 18:19:41 -05:00
|
|
|
}
|
2021-06-01 09:45:49 -05:00
|
|
|
g_value_unset (&v);
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
|
|
{
|
2024-02-12 05:00:41 -06:00
|
|
|
ENTER ("(cm=%p, src=%p(%s))", cm, src, src ? src->get_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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
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;
|
2021-08-21 22:17:28 -05:00
|
|
|
|
2013-10-24 07:27:37 -05:00
|
|
|
if (!cm) return;
|
|
|
|
|
|
|
|
ENTER ("(cm=%p, symbol=%s)", cm, user_symbol ? user_symbol : "(null)");
|
|
|
|
|
2014-03-25 19:07:49 -05:00
|
|
|
lc = gnc_localeconv();
|
|
|
|
if (!user_symbol || !*user_symbol)
|
2024-03-17 17:11:48 -05:00
|
|
|
user_symbol = nullptr;
|
2014-03-25 19:07:49 -05:00
|
|
|
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 */
|
2024-03-17 17:11:48 -05:00
|
|
|
user_symbol = nullptr;
|
2014-03-25 19:07:49 -05:00
|
|
|
else if (!g_strcmp0(user_symbol, gnc_commodity_get_default_symbol(cm)))
|
2024-03-17 17:11:48 -05:00
|
|
|
user_symbol = nullptr;
|
2021-08-21 22:17:28 -05:00
|
|
|
|
|
|
|
gnc_commodity_begin_edit (cm);
|
|
|
|
|
2015-06-09 18:19:41 -05:00
|
|
|
if (user_symbol)
|
|
|
|
{
|
2021-08-21 22:17:28 -05:00
|
|
|
GValue v = G_VALUE_INIT;
|
2015-06-09 18:19:41 -05:00
|
|
|
g_value_init (&v, G_TYPE_STRING);
|
2023-03-01 05:49:20 -06:00
|
|
|
g_value_set_static_string (&v, user_symbol);
|
2017-12-10 07:42:08 -06:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE(cm), &v, 1, "user_symbol");
|
2021-06-01 09:45:49 -05:00
|
|
|
g_value_unset (&v);
|
2015-06-09 18:19:41 -05:00
|
|
|
}
|
|
|
|
else
|
2021-08-21 22:17:28 -05:00
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_instance_set_kvp (QOF_INSTANCE(cm), nullptr, 1, "user_symbol");
|
2021-08-21 22:17:28 -05:00
|
|
|
}
|
2014-03-25 19:07:49 -05:00
|
|
|
|
2013-10-24 07:27:37 -05:00
|
|
|
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)
|
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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))
|
|
|
|
{
|
2017-01-16 16:03:50 -06:00
|
|
|
/* compatibility hack - Gnucash 1.8 gets currency quotes when a
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv_a;
|
|
|
|
gnc_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);
|
2014-08-12 12:56:53 -05:00
|
|
|
if (priv_a->name_space != priv_b->name_space) return FALSE;
|
2012-08-07 12:24:55 -05:00
|
|
|
if (g_strcmp0(priv_a->mnemonic, priv_b->mnemonic) != 0) return FALSE;
|
2023-01-24 11:46:48 -06:00
|
|
|
|
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)
|
|
|
|
{
|
2023-01-24 11:46:48 -06:00
|
|
|
return gnc_commodity_compare(a, b) == 0;
|
2001-10-12 05:50:35 -05:00
|
|
|
}
|
|
|
|
|
2023-01-24 11:46:48 -06:00
|
|
|
// Used as a sorting callback for deleting old prices, so it needs to be
|
|
|
|
// stable but doesn't need to be in any particular order sensible to humans.
|
2008-11-20 11:00:37 -06:00
|
|
|
int gnc_commodity_compare(const gnc_commodity * a, const gnc_commodity * b)
|
|
|
|
{
|
2023-01-24 11:46:48 -06:00
|
|
|
if (a == b) return 0;
|
|
|
|
if (a && !b) return 1;
|
|
|
|
if (b && !a) return -1;
|
|
|
|
return qof_instance_guid_compare(a, b);
|
2008-11-20 11:00:37 -06:00
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2023-01-24 11:46:48 -06:00
|
|
|
// Used as a callback to g_list_find_custom, it should return 0
|
|
|
|
// when the commodities match.
|
2008-11-20 11:11:47 -06:00
|
|
|
int gnc_commodity_compare_void(const void * a, const void * b)
|
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
return gnc_commodity_compare(GNC_COMMODITY (a), GNC_COMMODITY (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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (ns == nullptr)
|
|
|
|
return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
return ns->name;
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
2017-06-16 13:30:33 -05:00
|
|
|
const char *
|
|
|
|
gnc_commodity_namespace_get_gui_name (const gnc_commodity_namespace *ns)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (ns == nullptr)
|
|
|
|
return nullptr;
|
2017-06-16 13:30:33 -05:00
|
|
|
if (g_strcmp0 (ns->name, GNC_COMMODITY_NS_CURRENCY) == 0)
|
|
|
|
return GNC_COMMODITY_NS_ISO_GUI;
|
|
|
|
return ns->name;
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
GList *
|
2014-08-12 12:56:53 -05:00
|
|
|
gnc_commodity_namespace_get_commodity_list(const gnc_commodity_namespace *name_space)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
if (!name_space)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2024-08-24 00:55:11 -05:00
|
|
|
return g_list_copy (name_space->cm_list);
|
2005-11-01 21:32:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2014-08-12 12:56:53 -05:00
|
|
|
gnc_commodity_namespace_is_iso(const char *name_space)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
return ((g_strcmp0(name_space, GNC_COMMODITY_NS_ISO) == 0) ||
|
|
|
|
(g_strcmp0(name_space, GNC_COMMODITY_NS_CURRENCY) == 0));
|
2006-04-03 16:39:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
2014-08-12 12:56:53 -05:00
|
|
|
gnc_commodity_table_map_namespace(const char * name_space)
|
2006-04-03 16:39:25 -05:00
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
if (g_strcmp0(name_space, GNC_COMMODITY_NS_ISO) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
return GNC_COMMODITY_NS_CURRENCY;
|
2014-08-12 12:56:53 -05:00
|
|
|
return name_space;
|
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);
|
2024-03-17 17:11:48 -05:00
|
|
|
retval->ns_list = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
return retval;
|
2001-08-07 18:36:04 -05:00
|
|
|
}
|
|
|
|
|
2003-06-09 22:33:06 -05:00
|
|
|
/********************************************************************
|
2021-02-05 13:52:33 -06:00
|
|
|
* book anchor functions
|
2003-06-09 22:33:06 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!book) return nullptr;
|
2024-02-09 22:14:40 -06:00
|
|
|
return static_cast<gnc_commodity_table*>(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
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!from) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
comtbl = gnc_commodity_table_get_table (book);
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!comtbl) return nullptr;
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space, const char * mnemonic)
|
2003-05-29 18:47:52 -05:00
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace * nsp = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!table || !name_space || !mnemonic) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
nsp = gnc_commodity_table_find_namespace(table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
if (nsp)
|
|
|
|
{
|
|
|
|
/*
|
2017-01-16 16:03:50 -06:00
|
|
|
* Backward compatibility support for currencies that have
|
2010-03-02 15:40:28 -06:00
|
|
|
* recently changed.
|
|
|
|
*/
|
|
|
|
if (nsp->iso4217)
|
|
|
|
{
|
2024-02-18 19:19:44 -06:00
|
|
|
auto it = gnc_new_iso_codes.find (mnemonic);
|
|
|
|
if (it != gnc_new_iso_codes.end())
|
|
|
|
mnemonic = it->second.c_str();
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
2024-02-09 22:14:40 -06:00
|
|
|
return GNC_COMMODITY(g_hash_table_lookup(nsp->cm_table, (gpointer)mnemonic));
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
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)
|
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
char *name_space;
|
2010-03-02 15:40:28 -06:00
|
|
|
char *mnemonic;
|
|
|
|
gnc_commodity *commodity;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!table || !unique_name) return nullptr;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
name_space = g_strdup (unique_name);
|
|
|
|
mnemonic = strstr (name_space, "::");
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!mnemonic)
|
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
g_free (name_space);
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
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
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
commodity = gnc_commodity_table_lookup (table, name_space, mnemonic);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
g_free (name_space);
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space,
|
2010-03-02 15:40:28 -06:00
|
|
|
const char * fullname)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity * retval = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
GList * all;
|
|
|
|
GList * iterator;
|
|
|
|
|
|
|
|
if (!fullname || (fullname[0] == '\0'))
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
all = gnc_commodity_table_get_commodities(table, name_space);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
for (iterator = all; iterator; iterator = iterator->next)
|
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto commodity = GNC_COMMODITY (iterator->data);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!strcmp(fullname,
|
2024-02-09 22:14:40 -06:00
|
|
|
gnc_commodity_get_printname(commodity)))
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
retval = commodity;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace * nsp = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity *c;
|
|
|
|
const char *ns_name;
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv;
|
2010-03-02 15:40:28 -06:00
|
|
|
QofBook *book;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!table) return nullptr;
|
|
|
|
if (!comm) return nullptr;
|
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,
|
2024-03-17 17:11:48 -05:00
|
|
|
(priv->mnemonic == nullptr ? "(null)" : priv->mnemonic),
|
|
|
|
(priv->fullname == nullptr ? "(null)" : priv->fullname));
|
2014-08-12 12:56:53 -05:00
|
|
|
ns_name = gnc_commodity_namespace_get_name(priv->name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
|
2017-01-16 16:03:50 -06:00
|
|
|
/* Backward compatibility support for currencies that have
|
2010-03-02 15:40:28 -06:00
|
|
|
* recently changed. */
|
2014-08-12 12:56:53 -05:00
|
|
|
if (priv->name_space->iso4217)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-18 19:19:44 -06:00
|
|
|
auto it = gnc_new_iso_codes.find (priv->mnemonic);
|
|
|
|
if (it != gnc_new_iso_codes.end())
|
|
|
|
gnc_commodity_set_mnemonic(comm, it->second.c_str());
|
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. */
|
2017-06-20 05:06:14 -05:00
|
|
|
if (g_strcmp0 (ns_name, GNC_COMMODITY_NS_TEMPLATE) == 0 &&
|
2014-01-16 16:52:03 -06:00
|
|
|
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";
|
2014-09-04 18:26:32 -05:00
|
|
|
mark_commodity_dirty (comm);
|
2014-01-16 16:52:03 -06:00
|
|
|
}
|
|
|
|
|
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,
|
2021-07-08 14:42:03 -05:00
|
|
|
(gpointer)CACHE_INSERT(priv->mnemonic),
|
2010-03-02 15:40:28 -06:00
|
|
|
(gpointer)comm);
|
|
|
|
nsp->cm_list = g_list_append(nsp->cm_list, comm);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&comm->inst, QOF_EVENT_ADD, nullptr);
|
2010-03-02 15:40:28 -06:00
|
|
|
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;
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv;
|
2010-03-02 15:40:28 -06:00
|
|
|
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);
|
2014-08-12 12:56:53 -05:00
|
|
|
ns_name = gnc_commodity_namespace_get_name(priv->name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
c = gnc_commodity_table_lookup (table, ns_name, priv->mnemonic);
|
|
|
|
if (c != comm) return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&comm->inst, QOF_EVENT_REMOVE, nullptr);
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace * nsp = nullptr;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
if (!table || !name_space)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
nsp = gnc_commodity_table_find_namespace(table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto l = (GList**)data;
|
2010-03-02 15:40:28 -06:00
|
|
|
*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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
GList * l = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto l = (GList**)data;
|
2010-03-02 15:40:28 -06:00
|
|
|
*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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
GList * l = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
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)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2024-08-24 00:55:11 -05:00
|
|
|
return g_list_copy (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)
|
|
|
|
{
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_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);
|
2014-08-12 12:56:53 -05:00
|
|
|
if ( !priv->name_space) return FALSE;
|
|
|
|
return priv->name_space->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;
|
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
ns_name = gnc_commodity_namespace_get_name(GET_PRIVATE(cm)->name_space);
|
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
|
2017-01-10 09:21:47 -06:00
|
|
|
* list commodities in a given namespace
|
2001-08-07 18:36:04 -05:00
|
|
|
********************************************************************/
|
|
|
|
|
2016-12-15 15:39:09 -06:00
|
|
|
static CommodityList*
|
|
|
|
commodity_table_get_all_noncurrency_commodities(const gnc_commodity_table* table)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
GList *node = nullptr, *nslist = gnc_commodity_table_get_namespaces(table);
|
|
|
|
CommodityList *retval = nullptr;
|
2016-12-15 15:39:09 -06:00
|
|
|
for (node = nslist; node; node=g_list_next(node))
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace *ns = nullptr;
|
2016-12-15 15:39:09 -06:00
|
|
|
if (g_strcmp0((char*)(node->data), GNC_COMMODITY_NS_CURRENCY) == 0
|
2017-06-20 05:06:14 -05:00
|
|
|
|| g_strcmp0((char*)(node->data), GNC_COMMODITY_NS_TEMPLATE) == 0)
|
2016-12-15 15:39:09 -06:00
|
|
|
continue;
|
|
|
|
ns = gnc_commodity_table_find_namespace(table, (char*)(node->data));
|
|
|
|
if (!ns)
|
|
|
|
continue;
|
2017-01-10 09:21:47 -06:00
|
|
|
retval = g_list_concat(g_hash_table_values(ns->cm_table), retval);
|
2016-12-15 15:39:09 -06:00
|
|
|
}
|
|
|
|
g_list_free(nslist);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space)
|
2002-01-02 04:08:17 -06:00
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace * ns = nullptr;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!table)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2022-03-24 19:37:47 -05:00
|
|
|
if (g_strcmp0(name_space, GNC_COMMODITY_NS_NONISO_GUI) == 0)
|
2016-12-15 15:39:09 -06:00
|
|
|
return commodity_table_get_all_noncurrency_commodities(table);
|
2014-08-12 12:56:53 -05:00
|
|
|
ns = gnc_commodity_table_find_namespace(table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!ns)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
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
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto comm = GNC_COMMODITY(value);
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv = GET_PRIVATE(comm);
|
2024-02-09 22:14:40 -06:00
|
|
|
auto l = static_cast<GList**>(data);
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2024-02-12 05:00:41 -06:00
|
|
|
if (!priv->quote_flag || !priv->quote_source || !priv->quote_source->get_supported())
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto l = static_cast<GList**>(data);
|
2018-12-05 14:50:15 -06:00
|
|
|
gnc_commodityPrivate* priv = GET_PRIVATE(comm);
|
2003-05-10 19:45:03 -05:00
|
|
|
|
2024-02-12 05:00:41 -06:00
|
|
|
if (!priv->quote_flag || priv->quote_source || !priv->quote_source->get_supported())
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace * ns = nullptr;
|
2014-08-12 12:56:53 -05:00
|
|
|
const char *name_space;
|
2010-03-02 15:40:28 -06:00
|
|
|
GList * nslist, * tmp;
|
2024-03-17 17:11:48 -05:00
|
|
|
GList * l = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
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");
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
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)
|
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
name_space = static_cast<const char*>(tmp->data);
|
2024-03-17 17:11:48 -05:00
|
|
|
if (regexec(&pattern, name_space, 0, nullptr, 0) == 0)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
DEBUG("Running list of %s commodities", name_space);
|
|
|
|
ns = gnc_commodity_table_find_namespace(table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
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 */
|
2023-01-24 07:22:18 -06:00
|
|
|
QOF_GOBJECT_IMPL(gnc_commodity_namespace, gnc_commodity_namespace, QOF_TYPE_INSTANCE)
|
2007-04-04 21:44:47 -05:00
|
|
|
|
|
|
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space,
|
2010-03-02 15:40:28 -06:00
|
|
|
QofBook *book)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
gnc_commodity_namespace * ns = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!table) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
name_space = gnc_commodity_table_map_namespace(name_space);
|
|
|
|
ns = gnc_commodity_table_find_namespace(table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!ns)
|
|
|
|
{
|
2024-03-17 17:11:48 -05:00
|
|
|
ns = static_cast<gnc_commodity_namespace*>(g_object_new(GNC_TYPE_COMMODITY_NAMESPACE, nullptr));
|
2010-03-02 15:40:28 -06:00
|
|
|
ns->cm_table = g_hash_table_new(g_str_hash, g_str_equal);
|
2024-02-09 22:14:40 -06:00
|
|
|
ns->name = CACHE_INSERT(static_cast<const char*>(name_space));
|
2014-08-12 12:56:53 -05:00
|
|
|
ns->iso4217 = gnc_commodity_namespace_is_iso(name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
qof_instance_init_data (&ns->inst, GNC_ID_COMMODITY_NAMESPACE, book);
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_CREATE, nullptr);
|
2010-03-02 15:40:28 -06:00
|
|
|
|
|
|
|
g_hash_table_insert(table->ns_table,
|
|
|
|
(gpointer) ns->name,
|
|
|
|
(gpointer) ns);
|
|
|
|
table->ns_list = g_list_append(table->ns_list, ns);
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_ADD, nullptr);
|
2010-03-02 15:40:28 -06:00
|
|
|
}
|
|
|
|
return ns;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gnc_commodity_namespace *
|
2005-11-01 21:32:36 -06:00
|
|
|
gnc_commodity_table_find_namespace(const gnc_commodity_table * table,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space)
|
2005-11-01 21:32:36 -06:00
|
|
|
{
|
2014-08-12 12:56:53 -05:00
|
|
|
if (!table || !name_space)
|
2024-03-17 17:11:48 -05:00
|
|
|
return nullptr;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
name_space = gnc_commodity_table_map_namespace(name_space);
|
2024-02-09 22:14:40 -06:00
|
|
|
return static_cast<gnc_commodity_namespace*>(g_hash_table_lookup(table->ns_table, (gpointer)name_space));
|
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;
|
2024-03-17 17:11:48 -05:00
|
|
|
if (!guid || !book) return nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
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
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto c = GNC_COMMODITY(value);
|
2010-03-02 15:40:28 -06:00
|
|
|
gnc_commodity_destroy(c);
|
2024-02-09 22:14:40 -06:00
|
|
|
CACHE_REMOVE(static_cast<char*>(key)); /* key is commodity mnemonic */
|
2010-03-02 15:40:28 -06:00
|
|
|
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,
|
2014-08-12 12:56:53 -05:00
|
|
|
const char * name_space)
|
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
|
|
|
|
2014-08-12 12:56:53 -05:00
|
|
|
ns = gnc_commodity_table_find_namespace(table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
if (!ns)
|
|
|
|
return;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_REMOVE, nullptr);
|
2014-08-12 12:56:53 -05:00
|
|
|
g_hash_table_remove(table->ns_table, name_space);
|
2010-03-02 15:40:28 -06:00
|
|
|
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);
|
2024-03-17 17:11:48 -05:00
|
|
|
ns->cm_list = nullptr;
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
g_hash_table_foreach_remove(ns->cm_table, ns_helper, nullptr);
|
2010-03-02 15:40:28 -06:00
|
|
|
g_hash_table_destroy(ns->cm_table);
|
|
|
|
CACHE_REMOVE(ns->name);
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_event_gen (&ns->inst, QOF_EVENT_DESTROY, nullptr);
|
2010-03-02 15:40:28 -06:00
|
|
|
/* 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);
|
2024-02-09 22:14:40 -06:00
|
|
|
ns = static_cast<gnc_commodity_namespace*>(item->data);
|
2010-03-02 15:40:28 -06:00
|
|
|
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);
|
2024-03-17 17:11:48 -05:00
|
|
|
t->ns_list = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
g_hash_table_destroy(t->ns_table);
|
2024-03-17 17:11:48 -05:00
|
|
|
t->ns_table = nullptr;
|
2010-03-02 15:40:28 -06:00
|
|
|
LEAVE ("table=%p", t);
|
2018-11-27 23:48:42 -06:00
|
|
|
g_free(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);
|
2017-06-20 05:06:14 -05:00
|
|
|
gnc_commodity_table_add_namespace(table, GNC_COMMODITY_NS_TEMPLATE, book);
|
|
|
|
c = gnc_commodity_new(book, "template", GNC_COMMODITY_NS_TEMPLATE, "template", "template", 1);
|
2010-03-02 15:40:28 -06:00
|
|
|
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",
|
2024-03-17 17:11:48 -05:00
|
|
|
DI(.create = ) nullptr,
|
|
|
|
DI(.book_begin = ) nullptr,
|
|
|
|
DI(.book_end = ) nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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",
|
2024-03-17 17:11:48 -05:00
|
|
|
DI(.create = ) nullptr,
|
|
|
|
DI(.book_begin = ) nullptr,
|
|
|
|
DI(.book_end = ) nullptr,
|
|
|
|
DI(.is_dirty = ) nullptr,
|
|
|
|
DI(.mark_clean = ) nullptr,
|
|
|
|
DI(.foreach = ) nullptr,
|
|
|
|
DI(.printable = ) nullptr,
|
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);
|
2024-03-17 17:11:48 -05:00
|
|
|
qof_book_set_data (book, GNC_COMMODITY_TABLE, nullptr);
|
2010-03-02 15:40:28 -06:00
|
|
|
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",
|
2024-03-17 17:11:48 -05:00
|
|
|
DI(.create = ) nullptr,
|
2010-03-02 15:40:28 -06:00
|
|
|
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,
|
2024-03-17 17:11:48 -05:00
|
|
|
DI(.foreach = ) nullptr,
|
|
|
|
DI(.printable = ) nullptr,
|
|
|
|
DI(.version_cmp = ) nullptr,
|
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
|
|
|
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)
|
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto list_mon = static_cast<gnc_monetary*>(tmp->data);
|
2010-03-02 15:40:28 -06:00
|
|
|
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 */
|
2024-03-17 17:11:48 -05:00
|
|
|
if (tmp == nullptr)
|
2010-03-02 15:40:28 -06:00
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto new_mon = static_cast<gnc_monetary*>(g_new0(gnc_monetary, 1));
|
2010-03-02 15:40:28 -06:00
|
|
|
*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)
|
|
|
|
{
|
2024-02-09 22:14:40 -06:00
|
|
|
auto mon = static_cast<gnc_monetary*>(node->data);
|
2010-03-02 15:40:28 -06:00
|
|
|
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 ============================== */
|