gnucash master: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Mon Oct 26 15:35:38 EDT 2015
Updated via https://github.com/Gnucash/gnucash/commit/5537a7ed (commit)
via https://github.com/Gnucash/gnucash/commit/50e3bf21 (commit)
via https://github.com/Gnucash/gnucash/commit/f5cf2ba5 (commit)
via https://github.com/Gnucash/gnucash/commit/362b9e3d (commit)
via https://github.com/Gnucash/gnucash/commit/ae35dbb4 (commit)
via https://github.com/Gnucash/gnucash/commit/dfc0b28b (commit)
via https://github.com/Gnucash/gnucash/commit/4bfe29ac (commit)
via https://github.com/Gnucash/gnucash/commit/9a53cc8f (commit)
via https://github.com/Gnucash/gnucash/commit/7298a469 (commit)
via https://github.com/Gnucash/gnucash/commit/811a30db (commit)
via https://github.com/Gnucash/gnucash/commit/70493537 (commit)
via https://github.com/Gnucash/gnucash/commit/ab15ca8f (commit)
via https://github.com/Gnucash/gnucash/commit/76c1259f (commit)
via https://github.com/Gnucash/gnucash/commit/348fe45b (commit)
via https://github.com/Gnucash/gnucash/commit/a40bc92d (commit)
via https://github.com/Gnucash/gnucash/commit/6e141377 (commit)
via https://github.com/Gnucash/gnucash/commit/f30b38b5 (commit)
via https://github.com/Gnucash/gnucash/commit/a8d4eaae (commit)
via https://github.com/Gnucash/gnucash/commit/f79a3af4 (commit)
via https://github.com/Gnucash/gnucash/commit/be5b9f2b (commit)
via https://github.com/Gnucash/gnucash/commit/9c2813ac (commit)
via https://github.com/Gnucash/gnucash/commit/96678937 (commit)
via https://github.com/Gnucash/gnucash/commit/5e609dac (commit)
via https://github.com/Gnucash/gnucash/commit/c4082524 (commit)
via https://github.com/Gnucash/gnucash/commit/ca447fc0 (commit)
via https://github.com/Gnucash/gnucash/commit/85148cd2 (commit)
via https://github.com/Gnucash/gnucash/commit/e94622c9 (commit)
via https://github.com/Gnucash/gnucash/commit/ab535fb1 (commit)
from https://github.com/Gnucash/gnucash/commit/de264c58 (commit)
commit 5537a7ed35a597f68701fd97d3bc4670b92a9bf5
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Oct 23 14:14:20 2015 -0700
Implement gnc_numeric_invert via GncRational::invert.
diff --git a/src/libqof/qof/gnc-numeric.cpp b/src/libqof/qof/gnc-numeric.cpp
index 547b619..f9adbdf 100644
--- a/src/libqof/qof/gnc-numeric.cpp
+++ b/src/libqof/qof/gnc-numeric.cpp
@@ -487,20 +487,7 @@ gnc_numeric_invert(gnc_numeric num)
{
if (num.num == 0)
return gnc_numeric_zero();
- if (num.denom > 0)
- {
- if (num.num < 0)
- return gnc_numeric_create (-num.denom, -num.num);
- return gnc_numeric_create (num.denom, num.num);
- }
- else /* Negative denominator means multiply instead of divide. */
- {
- int64_t mult = (num.num < 0 ? INT64_C(-1) : INT64_C(1));
- qofint128 denom = mult128(-num.denom, mult * num.num);
- if (denom.hi)
- return gnc_numeric_error(GNC_ERROR_OVERFLOW);
- return gnc_numeric_create (mult, denom.lo);
- }
+ return static_cast<gnc_numeric>(GncNumeric(num).inv());
}
/* *******************************************************************
* double_to_gnc_numeric
diff --git a/src/libqof/qof/gnc-rational.cpp b/src/libqof/qof/gnc-rational.cpp
index 35e7e6f..a3db422 100644
--- a/src/libqof/qof/gnc-rational.cpp
+++ b/src/libqof/qof/gnc-rational.cpp
@@ -80,9 +80,7 @@ GncRational::operator-() const noexcept
GncRational&
GncRational::inv () noexcept
{
- auto tmp = m_num;
- m_num = m_den;
- m_den = tmp;
+ std::swap(m_num, m_den);
GncRational b {1, 1};
GncDenom d {*this, b, INT64_C(0), GNC_HOW_RND_NEVER };
diff --git a/src/libqof/qof/gnc-rational.hpp b/src/libqof/qof/gnc-rational.hpp
index dd25789..1c4edc6 100644
--- a/src/libqof/qof/gnc-rational.hpp
+++ b/src/libqof/qof/gnc-rational.hpp
@@ -44,6 +44,7 @@ public:
GncRational& div(GncRational b, GncDenom& d) noexcept;
GncRational& add(const GncRational& b, GncDenom& d) noexcept;
GncRational& sub(const GncRational& b, GncDenom& d) noexcept;
+
/** Inverts the number, equivalent of /= {1, 1} */
GncRational& inv() noexcept;
commit 50e3bf21db44661ac4273a1b52a596a2d957c792
Merge: de264c5 f5cf2ba
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Oct 24 14:55:56 2015 -0700
Merge branch 'maint'
commit f5cf2ba54264006aed462e9680b7a36e4a911ecc
Merge: e3da1c4 362b9e3
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Oct 24 14:52:49 2015 -0700
Merge branch 'single-price' into maint
commit 362b9e3d7c4dfff0e11656d6d983866e7d15b980
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Oct 24 13:28:55 2015 -0700
Fix leaking QofBook in most of the engine unit tests.
The problem is that QofBook is not a well-formed GObject and doesn't clean
itself up properly when its ref count goes to zero. qof_book_destroy() must
be explicitly called on it. An interesting side effect is that QofObject
keeps a list of all of the books ever opened and not properly destroyed and
registering a class (in this case GNCPriceDB) tries to create that class's
instance in all of those leaked books. Since they already have one, the
instantiation code raises a critical error and the test program fails.
diff --git a/src/engine/test/utest-Account.c b/src/engine/test/utest-Account.c
index c027d8b..0f23dfc 100644
--- a/src/engine/test/utest-Account.c
+++ b/src/engine/test/utest-Account.c
@@ -694,8 +694,7 @@ test_gnc_book_set_get_root_account (Fixture *fixture, gconstpointer pData)
/* acc1 gets freed by setting the root accout to acc2
g_object_unref (acc1);
*/
- g_object_unref (book1);
- g_object_unref (acc2);
+ qof_book_destroy (book1);
}
/* xaccMallocAccount
@@ -711,8 +710,8 @@ test_xaccMallocAccount (void)
g_assert (acc != NULL);
test_signal_assert_hits (signal, 1);
test_signal_free (signal);
- g_object_unref (book);
g_object_unref (acc);
+ qof_book_destroy (book);
}
/* gnc_account_create_root
@@ -734,8 +733,8 @@ test_gnc_account_create_root (void)
g_object_get (acc, "name", &name, NULL);
g_assert_cmpstr (name, == , "Root Account");
g_assert (gnc_book_get_root_account (book) == acc);
- g_object_unref (book);
g_object_unref (acc);
+ qof_book_destroy (book);
g_free (func);
g_free (name);
}
@@ -1403,7 +1402,7 @@ test_xaccAccountOrder ( )
xaccAccountDestroy (aa);
xaccAccountBeginEdit (ab);
xaccAccountDestroy (ab);
- g_object_unref (book);
+ qof_book_destroy (book);
}
/* qof_xaccAccountOrder
static int
@@ -1544,7 +1543,7 @@ test_gnc_account_append_remove_child (Fixture *fixture, gconstpointer pData)
xaccAccountDestroy (account);
xaccAccountBeginEdit (froot);
xaccAccountDestroy (froot);
- g_object_unref (fbook);
+ qof_book_destroy (fbook);
}
/* Simple Getters or passthroughs, no tests:
diff --git a/src/engine/test/utest-Budget.c b/src/engine/test/utest-Budget.c
index 0509cfd..fdb624a 100644
--- a/src/engine/test/utest-Budget.c
+++ b/src/engine/test/utest-Budget.c
@@ -675,11 +675,7 @@ test_gnc_book_set_get_root_account (Fixture *fixture, gconstpointer pData)
g_assert (gnc_book_get_root_account (book1) != acc1);
g_assert (gnc_book_get_root_account (book1) == acc2);
/* Clean up */
- /* acc1 gets freed by setting the root accout to acc2
- g_object_unref (acc1);
- */
- g_object_unref (book1);
- g_object_unref (acc2);
+ qof_book_destroy (book1);
}
/* xaccMallocAccount
@@ -695,8 +691,7 @@ test_xaccMallocAccount (void)
g_assert (acc != NULL);
test_signal_assert_hits (signal, 1);
test_signal_free (signal);
- g_object_unref (book);
- g_object_unref (acc);
+ qof_book_destroy (book);
}
/* gnc_account_create_root
@@ -718,8 +713,7 @@ test_gnc_account_create_root (void)
g_object_get (acc, "name", &name, NULL);
g_assert_cmpstr (name, == , "Root Account");
g_assert (gnc_book_get_root_account (book) == acc);
- g_object_unref (book);
- g_object_unref (acc);
+ qof_book_destroy (book);
g_free (func);
g_free (name);
}
@@ -1363,7 +1357,7 @@ test_xaccAccountOrder ( )
xaccAccountDestroy (aa);
xaccAccountBeginEdit (ab);
xaccAccountDestroy (ab);
- g_object_unref (book);
+ qof_book_destroy (book);
}
/* qof_xaccAccountOrder
static int
@@ -1504,7 +1498,7 @@ test_gnc_account_append_remove_child (Fixture *fixture, gconstpointer pData)
xaccAccountDestroy (account);
xaccAccountBeginEdit (froot);
xaccAccountDestroy (froot);
- g_object_unref (fbook);
+ qof_book_destroy (fbook);
}
/* Simple Getters or passthroughs, no tests:
@@ -2494,6 +2488,7 @@ test_gnc_set_budget_num_periods()
g_assert_cmpint(gnc_budget_get_num_periods(budget), ==, 20);
gnc_budget_destroy(budget);
+ qof_book_destroy(book);
}
static void
@@ -2544,6 +2539,7 @@ test_gnc_set_budget_recurrence()
}
gnc_budget_destroy(budget);
+ qof_book_destroy(book);
}
static void
@@ -2577,9 +2573,8 @@ test_gnc_set_budget_account_period_value()
g_assert_cmpint (check.hits, ==, 1);
g_log_set_default_handler (oldlogger, NULL);
- g_object_unref(book);
- g_object_unref(acc);
gnc_budget_destroy(budget);
+ qof_book_destroy(book);
}
void
diff --git a/src/engine/test/utest-Split.c b/src/engine/test/utest-Split.c
index 0064a8b..6d0446c 100644
--- a/src/engine/test/utest-Split.c
+++ b/src/engine/test/utest-Split.c
@@ -110,7 +110,7 @@ teardown (Fixture *fixture, gconstpointer pData)
test_destroy (fixture->split);
test_destroy (fixture->curr);
test_destroy (fixture->comm);
- test_destroy (book);
+ qof_book_destroy (book);
g_free (fixture->func);
g_slist_free_full (fixture->hdlrs, test_free_log_handler);
test_clear_error_list();
@@ -171,7 +171,7 @@ test_gnc_split_dispose ()
g_assert (instance->e_type == NULL);
g_object_unref (split);
- g_object_unref (book);
+ qof_book_destroy (book);
}
/* gnc_split_finalize
static void
@@ -251,7 +251,7 @@ test_gnc_split_set_get_property ()
g_object_unref (lot);
gnc_commodity_destroy (curr);
g_object_unref (split);
- g_object_unref (book);
+ qof_book_destroy (book);
}
/* xaccInitSplit
@@ -1094,7 +1094,7 @@ test_xaccSplitDestroy ()
test_destroy (txn);
test_destroy (acc);
test_destroy (gnaira);
- test_destroy (book);
+ qof_book_destroy (book);
}
/* xaccSplitOrder
gint
diff --git a/src/engine/test/utest-Transaction.c b/src/engine/test/utest-Transaction.c
index e81a9a4..77569f0 100644
--- a/src/engine/test/utest-Transaction.c
+++ b/src/engine/test/utest-Transaction.c
@@ -215,7 +215,7 @@ teardown (Fixture *fixture, gconstpointer pData)
test_destroy (fixture->curr);
test_destroy (fixture->comm);
g_free (mbe);
- test_destroy (book);
+ qof_book_destroy(book);
g_slist_free_full (fixture->hdlrs, test_free_log_handler);
test_clear_error_list();
}
@@ -387,7 +387,7 @@ test_gnc_transaction_dispose ()
test_destroy (curr);
test_destroy (txn);
- test_destroy (book);
+ qof_book_destroy (book);
}
/* gnc_transaction_finalize
static void
@@ -473,7 +473,7 @@ test_gnc_transaction_set_get_property (Fixture *fixture, gconstpointer pData)
xaccTransRollbackEdit (txn);
test_destroy (txn);
test_destroy (curr);
- test_destroy (book);
+ qof_book_destroy (book);
g_free (t_entered);
}
/* gnc_transaction_class_init
@@ -511,7 +511,7 @@ test_xaccMallocTransaction (Fixture *fixture, gconstpointer pData)
test_signal_assert_hits (sig1, 1);
test_destroy (txn);
- test_destroy (book);
+ qof_book_destroy (book);
test_signal_free (sig1);
}
/* xaccTransSortSplits
@@ -1420,7 +1420,7 @@ test_xaccTransDestroy ()
test_destroy (txn);
test_destroy (dupe);
- test_destroy (book);
+ qof_book_destroy (book);
}
/* destroy_gains
static void
@@ -1674,7 +1674,7 @@ test_xaccTransCommitEdit (void)
test_destroy (acc2);
test_destroy (curr);
test_destroy (comm);
- test_destroy (book);
+ qof_book_destroy (book);
}
/* xaccTransRollbackEdit
void
commit ae35dbb46407762c925346975588cd58fdb60ca3
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Oct 18 11:44:51 2015 -0700
Use gnc_pricedb_has_prices instead of testing the return value of get_prices.
diff --git a/src/gnome/dialog-commodities.c b/src/gnome/dialog-commodities.c
index 1a0e385..3f29a29 100644
--- a/src/gnome/dialog-commodities.c
+++ b/src/gnome/dialog-commodities.c
@@ -164,8 +164,7 @@ remove_clicked (CommoditiesDialog *cd)
g_list_free (accounts);
pdb = gnc_pricedb_get_db (cd->book);
- prices = gnc_pricedb_get_prices(pdb, commodity, NULL);
- if (prices)
+ if (gnc_pricedb_has_prices(pdb, commodity, NULL))
{
message = _("This commodity has price quotes. Are "
"you sure you want to delete the selected "
commit dfc0b28bedc3d4bc0f9d9afc9d638898cf08e6a3
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Oct 16 12:40:32 2015 -0700
Remove be->price_lookup conditional clauses.
No backend implements price_lookup, and the struct member is removed from
master. Even if it had existed these clauses wouldn't actually do anything.
diff --git a/src/engine/gnc-pricedb-p.h b/src/engine/gnc-pricedb-p.h
index 8d867da..091cd64 100644
--- a/src/engine/gnc-pricedb-p.h
+++ b/src/engine/gnc-pricedb-p.h
@@ -78,17 +78,6 @@ typedef enum
LOOKUP_EARLIEST_AFTER
} PriceLookupType;
-
-struct gnc_price_lookup_s
-{
- PriceLookupType type;
- GNCPriceDB *prdb;
- const gnc_commodity *commodity;
- const gnc_commodity *currency;
- Timespec date;
-};
-
-
typedef struct gnc_price_lookup_helper_s
{
GList **return_list;
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index bdc8e41..123c520 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -1364,24 +1364,9 @@ gnc_pricedb_lookup_latest(GNCPriceDB *db,
GList *price_list;
GNCPrice *result;
GHashTable *currency_hash;
- QofBook *book;
- QofBackend *be;
if (!db || !commodity || !currency) return NULL;
ENTER ("db=%p commodity=%p currency=%p", db, commodity, currency);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_LATEST;
- pl.prdb = db;
- pl.commodity = commodity;
- pl.currency = currency;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
if (!currency_hash)
@@ -1426,26 +1411,11 @@ gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db,
{
GList *result;
GHashTable *currency_hash;
- QofBook *book;
- QofBackend *be;
result = NULL;
if (!db || !commodity) return NULL;
ENTER ("db=%p commodity=%p", db, commodity);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_LATEST;
- pl.prdb = db;
- pl.commodity = commodity;
- pl.currency = NULL; /* can the backend handle this??? */
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
if (!currency_hash)
{
@@ -1483,24 +1453,9 @@ gnc_pricedb_has_prices(GNCPriceDB *db,
GList *price_list;
GHashTable *currency_hash;
gint size;
- QofBook *book;
- QofBackend *be;
if (!db || !commodity) return FALSE;
ENTER ("db=%p commodity=%p currency=%p", db, commodity, currency);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (book && be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_ALL;
- pl.prdb = db;
- pl.commodity = commodity;
- pl.currency = currency;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
if (!currency_hash)
{
@@ -1535,27 +1490,13 @@ gnc_pricedb_get_prices(GNCPriceDB *db,
GList *result;
GList *node;
GHashTable *currency_hash;
- QofBook *book;
- QofBackend *be;
if (!db || !commodity) return NULL;
ENTER ("db=%p commodity=%p currency=%p", db, commodity, currency);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_ALL;
- pl.prdb = db;
- pl.commodity = commodity;
- pl.currency = currency;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
if (!currency_hash)
{
+ currency_hash = g_hash_table_lookup(db->commodity_hash, commodity);
LEAVE (" no currency hash");
return NULL;
}
@@ -1602,25 +1543,9 @@ gnc_pricedb_lookup_at_time(GNCPriceDB *db,
GList *result = NULL;
GList *item = NULL;
GHashTable *currency_hash;
- QofBook *book;
- QofBackend *be;
if (!db || !c || !currency) return NULL;
ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_AT_TIME;
- pl.prdb = db;
- pl.commodity = c;
- pl.currency = currency;
- pl.date = t;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
if (!currency_hash)
{
@@ -1664,25 +1589,9 @@ lookup_nearest_in_time(GNCPriceDB *db,
GNCPrice *result = NULL;
GList *item = NULL;
GHashTable *currency_hash;
- QofBook *book;
- QofBackend *be;
if (!db || !c || !currency) return NULL;
ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_NEAREST_IN_TIME;
- pl.prdb = db;
- pl.commodity = c;
- pl.currency = currency;
- pl.date = t;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
if (!currency_hash)
{
@@ -1812,26 +1721,10 @@ gnc_pricedb_lookup_latest_before (GNCPriceDB *db,
GNCPrice *result = NULL;*/
GList *item = NULL;
GHashTable *currency_hash;
- QofBook *book;
- QofBackend *be;
Timespec price_time;
if (!db || !c || !currency) return NULL;
ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_LATEST_BEFORE;
- pl.prdb = db;
- pl.commodity = c;
- pl.currency = currency;
- pl.date = t;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
if (!currency_hash)
{
@@ -1963,25 +1856,9 @@ gnc_pricedb_lookup_nearest_in_time_any_currency(GNCPriceDB *db,
GList *result = NULL;
GHashTable *currency_hash;
GNCPriceLookupHelper lookup_helper;
- QofBook *book;
- QofBackend *be;
if (!db || !c) return NULL;
ENTER ("db=%p commodity=%p", db, c);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_NEAREST_IN_TIME;
- pl.prdb = db;
- pl.commodity = c;
- pl.currency = NULL; /* can the backend handle this??? */
- pl.date = t;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
if (!currency_hash)
{
@@ -2014,25 +1891,9 @@ gnc_pricedb_lookup_latest_before_any_currency(GNCPriceDB *db,
GList *result = NULL;
GHashTable *currency_hash;
GNCPriceLookupHelper lookup_helper;
- QofBook *book;
- QofBackend *be;
if (!db || !c) return NULL;
ENTER ("db=%p commodity=%p", db, c);
- book = qof_instance_get_book(&db->inst);
- be = qof_book_get_backend(book);
-#ifdef GNUCASH_MAJOR_VERSION
- if (be && be->price_lookup)
- {
- GNCPriceLookup pl;
- pl.type = LOOKUP_LATEST_BEFORE;
- pl.prdb = db;
- pl.commodity = c;
- pl.currency = NULL; /* can the backend handle this??? */
- pl.date = t;
- (be->price_lookup) (be, &pl);
- }
-#endif
currency_hash = g_hash_table_lookup(db->commodity_hash, c);
if (!currency_hash)
{
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index e3966b3..5c3a625 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -153,7 +153,6 @@ GType gnc_pricedb_get_type(void);
@{ */
/** */
-typedef struct gnc_price_lookup_s GNCPriceLookup;
typedef GList PriceList;
/** Price source enum. Be sure to keep in sync with the source_name array in
commit 4bfe29aca3beeac18d0abcf0fabee1ecc716d4e8
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 15 12:03:39 2015 -0700
Prevent F::Q from updating PRICE_SOURCE_EDIT_DLG prices.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 8e1e79e..a17b7f3 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1324,7 +1324,7 @@ gnc_xfer_dialog_set_fetch_sensitive (GtkWidget *fetch)
if (gnc_quote_source_fq_installed ())
{
gtk_widget_set_sensitive (fetch, TRUE);
- gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote"));
+ gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote. This will fail if there is a manually-created price for today."));
return;
}
gtk_widget_set_sensitive (fetch, FALSE);
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index b597a94..f3d97e0 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -412,14 +412,16 @@
commodity currency
gnc-time))
(if (not (null? saved-price))
- (begin
- (gnc-price-begin-edit saved-price)
- (gnc-price-set-time saved-price gnc-time)
+ (if (> (gnc-price-get-source saved-price) PRICE-SOURCE-FQ)
+ (begin
+ (gnc-price-begin-edit saved-price)
+ (gnc-price-set-time saved-price gnc-time)
(gnc-price-set-source saved-price PRICE-SOURCE-FQ)
- (gnc-price-set-typestr saved-price price-type)
- (gnc-price-set-value saved-price price)
- (gnc-price-commit-edit saved-price)
- #f)
+ (gnc-price-set-typestr saved-price price-type)
+ (gnc-price-set-value saved-price price)
+ (gnc-price-commit-edit saved-price)
+ #f)
+ #f)
(let ((gnc-price (gnc-price-create book)))
(if (not gnc-price)
(string-append
commit 9a53cc8f58ad2dba4ea60b5720c5a6c890c2c15a
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Sep 12 12:09:46 2015 -0700
Remove unnecessary and harmful price rounding.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 926af38..8e1e79e 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -331,10 +331,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
/* grab the price from the pricedb */
price_value = gnc_price_get_value (pr.price);
if (pr.reverse)
- {
price_value = gnc_numeric_invert (price_value);
- price_value = round_price(pr.from, pr.to, price_value);
- }
gnc_price_unref(pr.price);
/* and set the price entry */
@@ -1087,8 +1084,6 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
price_value = gnc_xfer_dialog_compute_price_value(xferData);
- price_value = round_price(xferData->from_commodity, xferData->to_commodity,
- price_value);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
xferData->price_source = PRICE_SOURCE_XFER_DLG_VAL;
@@ -1594,7 +1589,6 @@ swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
*to = *from;
*from = tmp;
value = gnc_numeric_invert(value);
- value = round_price(*from, *to, value);
return value;
}
@@ -1880,8 +1874,7 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
{
gnc_numeric price_value = gnc_price_get_value(pr.price);
if (pr.reverse)
- price_value = round_price(pr.from, pr.to,
- gnc_numeric_invert(price_value));
+ price_value = gnc_numeric_invert(price_value);
gnc_xfer_dialog_set_price_edit(xferData, price_value);
gnc_price_unref (pr.price);
}
@@ -2498,10 +2491,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
- {
dialog_rate = gnc_numeric_invert(*exch_rate);
- dialog_rate = round_price(xfer_com, txn_cur, *exch_rate);
- }
amount = gnc_numeric_neg(amount);
}
else
commit 7298a469994c23a4e0526556ab31bf9940b9c7e1
Author: John Ralls <jralls at ceridwen.us>
Date: Wed Sep 9 15:06:56 2015 -0700
Implement user-entered-price preference.
Add user:price as a source and prefer values with lower PriceSource enum
values over higher ones: In other words a price with a lower PriceSource
value (e.g. user:price-editor) will overwrite one with a higher value (e.g.
user:split-register) and not the other way around.
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 8cb841b..bdc8e41 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -71,8 +71,12 @@ gnc_price_init(GNCPrice* price)
*/
static const char* source_names[] =
{
- "user:price-editor", //sync with price_to_gui in dialog-price-editor.c
- "Finance::Quote", //sync with
+ /* sync with price_to_gui in dialog-price-editor.c */
+ "user:price-editor",
+ /* sync with commidity-tz-quote->price in price-quotes.scm */
+ "Finance::Quote",
+ "user:price",
+ /* String retained for backwards compatibility. */
"user:xfer-dialog",
"user:split-register",
"user:stock-split",
@@ -1004,7 +1008,7 @@ insert_or_replace_price(GNCPriceDB *db, GNCPrice *p)
p->currency, p->tmspec);
if (old_price == NULL)
return TRUE;
- if (p->source != PRICE_SOURCE_FQ)
+ if (p->source < old_price->source)
return TRUE;
return FALSE;
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index 00a4126..e3966b3 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -165,7 +165,8 @@ typedef enum
{
PRICE_SOURCE_EDIT_DLG, // "user:price-editor"
PRICE_SOURCE_FQ, // "Finance::Quote"
- PRICE_SOURCE_XFER_DLG, // "user:xfer-dialog"
+ PRICE_SOURCE_USER_PRICE, // "user:price"
+ PRICE_SOURCE_XFER_DLG_VAL, // "user:xfer-dialog"
PRICE_SOURCE_SPLIT_REG, // "user:split-register"
PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
PRICE_SOURCE_INVOICE, // "user:invoice-post"
@@ -174,7 +175,7 @@ typedef enum
#define PRICE_TYPE_LAST "last"
#define PRICE_TYPE_UNK "unknown"
-
+#define PRICE_TYPE_TRN "transaction"
/* ------------------ */
/** @name Constructors
@{ */
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index a07a8ba..926af38 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -121,6 +121,8 @@ struct _xferDialog
* creating a transaction)
*/
gnc_numeric *exch_rate;
+ PriceSource price_source;
+ const char *price_type;
/* Callback function to notify of the newly created Transaction */
gnc_xfer_dialog_cb transaction_cb;
@@ -1057,6 +1059,9 @@ gnc_xfer_price_update_cb(GtkWidget *widget, GdkEventFocus *event,
XferDialog *xferData = data;
gnc_xfer_update_to_amount (xferData);
+ xferData->price_source = PRICE_SOURCE_USER_PRICE;
+ xferData->price_type = PRICE_TYPE_TRN;
+
return FALSE;
}
@@ -1086,6 +1091,8 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
price_value);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
+ xferData->price_source = PRICE_SOURCE_XFER_DLG_VAL;
+ xferData->price_type = PRICE_TYPE_TRN;
gnc_xfer_dialog_update_conv_info(xferData);
return FALSE;
@@ -1634,9 +1641,9 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (pr.price);
return;
}
- if (gnc_price_get_source(pr.price) == PRICE_SOURCE_FQ)
+ if (gnc_price_get_source(pr.price) < xferData->price_source)
{
- PINFO("Existing price is from Finance::Quote, so won't supersede.");
+ PINFO("Existing price is preferred, so won't supersede.");
gnc_price_unref (pr.price);
return;
}
@@ -1649,7 +1656,8 @@ create_price(XferDialog *xferData, Timespec ts)
value = round_price(pr.from, pr.to, value);
gnc_price_begin_edit (pr.price);
gnc_price_set_time (pr.price, ts);
- gnc_price_set_source (pr.price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_source (pr.price, xferData->price_source);
+ gnc_price_set_typestr(pr.price, xferData->price_type);
gnc_price_set_value (pr.price, value);
gnc_price_commit_edit (pr.price);
PINFO("Modified price: 1 %s = %f %s",
@@ -1682,7 +1690,8 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_set_commodity (price, from);
gnc_price_set_currency (price, to);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_source (price, xferData->price_source);
+ gnc_price_set_typestr (price, xferData->price_type);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (xferData->pricedb, price);
gnc_price_commit_edit (price);
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 1332bf1..3e4eb74 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2044,7 +2044,8 @@ recalculate_value (Split *split, SplitRegister *reg,
}
static void
-record_price (SplitRegister *reg, Account *account, gnc_numeric value)
+record_price (SplitRegister *reg, Account *account, gnc_numeric value,
+ PriceSource source)
{
Transaction *trans = gnc_split_register_get_current_trans (reg);
QofBook *book = qof_instance_get_book (QOF_INSTANCE (account));
@@ -2084,8 +2085,9 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_unref (price);
return;
}
- if (gnc_price_get_source(price) == PRICE_SOURCE_FQ)
+ if (gnc_price_get_source(price) < PRICE_SOURCE_XFER_DLG_VAL)
{
+ /* Existing price is preferred over this one. */
gnc_price_unref(price);
return;
}
@@ -2098,7 +2100,8 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
GNC_HOW_RND_ROUND_HALF_UP);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
+ gnc_price_set_source (price, source);
+ gnc_price_set_typestr (price, PRICE_TYPE_TRN);
gnc_price_set_value (price, value);
gnc_price_commit_edit (price);
gnc_price_unref (price);
@@ -2112,7 +2115,8 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_set_commodity (price, comm);
gnc_price_set_currency (price, curr);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
+ gnc_price_set_source (price, source);
+ gnc_price_set_typestr (price, PRICE_TYPE_TRN);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (pricedb, price);
gnc_price_commit_edit (price);
@@ -2135,6 +2139,7 @@ gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
Account *account;
int denom;
int choice;
+ PriceSource source = PRICE_SOURCE_USER_PRICE;
if (STOCK_REGISTER != reg->type &&
CURRENCY_REGISTER != reg->type &&
@@ -2283,6 +2288,7 @@ gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
{
recalculate_price (split, reg, value, amount);
price_changed = TRUE;
+ source = PRICE_SOURCE_SPLIT_REG;
}
if (recalc_value)
recalculate_value (split, reg, price, amount, shares_changed);
@@ -2293,7 +2299,7 @@ gnc_split_register_auto_calc (SplitRegister *reg, Split *split)
PRIC_CELL);
price = gnc_price_cell_get_value (cell);
if (gnc_numeric_positive_p(price))
- record_price (reg, account, price);
+ record_price (reg, account, price, source);
}
return TRUE;
}
commit 811a30db4a28bb8b62a945c744ef791cb1674e3b
Author: John Ralls <jralls at ceridwen.us>
Date: Wed Sep 9 11:22:52 2015 -0700
Fold separate call of gnc_pricedb_lookup_latest() into lookup_price.
Requires a 3-state enum instead of a boolean for the second arg to lookup_price.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index bf3de11..a07a8ba 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -215,6 +215,13 @@ round_price(gnc_commodity *from, gnc_commodity *to, gnc_numeric value)
return value;
}
+typedef enum
+{
+ SAME_DAY,
+ NEAREST,
+ LATEST
+} PriceDate;
+
typedef struct
{
GNCPrice *price;
@@ -239,7 +246,7 @@ price_request_from_xferData(PriceReq *pr, XferDialog *xd)
}
static gboolean
-lookup_price(PriceReq *pr, gboolean day_only)
+lookup_price(PriceReq *pr, PriceDate pd)
{
GNCPrice *prc = NULL;
g_return_val_if_fail (pr != NULL, FALSE);
@@ -248,26 +255,37 @@ lookup_price(PriceReq *pr, gboolean day_only)
g_return_val_if_fail (pr->to != NULL, FALSE);
pr->reverse = FALSE;
- if (day_only)
- {
- prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from, pr->to, pr->ts);
- if (!prc)
- {
- prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
- pr->from, pr->ts);
- pr->reverse = TRUE;
- }
- }
- else
+ switch (pd)
{
- prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
- pr->to, pr->ts);
- if (!prc)
- {
- prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
- pr->from, pr->ts);
- pr->reverse = TRUE;
- }
+ default:
+ case SAME_DAY:
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from,
+ pr->to, pr->ts);
+ if (!prc)
+ {
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
+ }
+ break;
+ case NEAREST:
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
+ pr->to, pr->ts);
+ if (!prc)
+ {
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
+ }
+ break;
+ case LATEST:
+ prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->from, pr->to);
+ if (!prc)
+ {
+ prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->to, pr->from);
+ pr->reverse = TRUE;
+ }
+ break;
}
if (pr->reverse)
{
@@ -304,8 +322,8 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
if (!xferData->pricedb) return;
price_request_from_xferData(&pr, xferData);
- if (!lookup_price(&pr, TRUE))
- if (!lookup_price(&pr, FALSE))
+ if (!lookup_price(&pr, SAME_DAY))
+ if (!lookup_price(&pr, NEAREST))
return;
/* grab the price from the pricedb */
@@ -1604,7 +1622,7 @@ create_price(XferDialog *xferData, Timespec ts)
* shifts to be < 1. */
price_request_from_xferData(&pr, xferData);
- if (lookup_price(&pr, TRUE))
+ if (lookup_price(&pr, SAME_DAY))
{
price_value = gnc_price_get_value(pr.price);
if (gnc_numeric_equal(pr.reverse ? gnc_numeric_invert(value) : value,
@@ -1809,14 +1827,11 @@ gnc_xfer_dialog_close_cb(GtkDialog *dialog, gpointer data)
void
gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
{
- gnc_numeric rate;
GNCPrice *prc;
- gnc_commodity *from = xferData->from_commodity;
- gnc_commodity *to = xferData->to_commodity;
+ PriceReq pr;
SCM quotes_func;
SCM book_scm;
SCM scm_window;
- gboolean have_price = FALSE;
g_return_if_fail (xferData);
@@ -1851,29 +1866,15 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
gnc_unset_busy_cursor (NULL);
/*the results should be in the price db now, but don't crash if not. */
-
- prc = gnc_pricedb_lookup_latest(xferData->pricedb, from, to);
- if (prc)
- {
- rate = gnc_price_get_value (prc);
- gnc_xfer_dialog_set_price_edit(xferData, rate);
- gnc_price_unref (prc);
- have_price = TRUE;
- }
-
- /* Lets try reversing the commodities */
- if(!have_price)
+ price_request_from_xferData(&pr, xferData);
+ if (lookup_price(&pr, LATEST))
{
- prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
- if (prc)
- {
-/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
- rate = gnc_numeric_invert(gnc_price_get_value (prc));
- rate = round_price(from, to, rate);
- gnc_xfer_dialog_set_price_edit(xferData, rate);
- gnc_price_unref (prc);
- have_price = TRUE;
- }
+ gnc_numeric price_value = gnc_price_get_value(pr.price);
+ if (pr.reverse)
+ price_value = round_price(pr.from, pr.to,
+ gnc_numeric_invert(price_value));
+ gnc_xfer_dialog_set_price_edit(xferData, price_value);
+ gnc_price_unref (pr.price);
}
LEAVE("quote retrieved");
commit 70493537e9a5cc92f7ff1611b9846c8776891ea2
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Sep 3 16:22:14 2015 -0700
Use an enum for internal representation of Price Sources.
Strings are still used for storage and display.
Purpose is to make multiple comparisons and conditional setting more
convenient.
diff --git a/src/backend/sql/gnc-price-sql.c b/src/backend/sql/gnc-price-sql.c
index 8729c91..83c5f3d 100644
--- a/src/backend/sql/gnc-price-sql.c
+++ b/src/backend/sql/gnc-price-sql.c
@@ -203,7 +203,7 @@ write_price( GNCPrice* p, gpointer data )
g_return_val_if_fail( p != NULL, FALSE );
g_return_val_if_fail( data != NULL, FALSE );
- if ( s->is_ok && strcmp(gnc_price_get_source(p), PRICE_SOURCE_INVOICE) != 0)
+ if ( s->is_ok && gnc_price_get_source(p) != PRICE_SOURCE_INVOICE)
{
s->is_ok = save_price( s->be, QOF_INSTANCE(p) );
}
diff --git a/src/backend/xml/gnc-pricedb-xml-v2.c b/src/backend/xml/gnc-pricedb-xml-v2.c
index fad3ff4..710fa01 100644
--- a/src/backend/xml/gnc-pricedb-xml-v2.c
+++ b/src/backend/xml/gnc-pricedb-xml-v2.c
@@ -120,7 +120,7 @@ price_parse_xml_sub_node(GNCPrice *p, xmlNodePtr sub_node, QofBook *book)
{
char *text = dom_tree_to_text(sub_node);
if (!text) return FALSE;
- gnc_price_set_source(p, text);
+ gnc_price_set_source_string(p, text);
g_free(text);
}
else if (g_strcmp0("price:type", (char*)sub_node->name) == 0)
@@ -440,7 +440,7 @@ gnc_price_to_dom_tree(const xmlChar *tag, GNCPrice *price)
tmpnode = timespec_to_dom_tree("price:time", ×p);
if (!add_child_or_kill_parent(price_xml, tmpnode)) return NULL;
- sourcestr = gnc_price_get_source(price);
+ sourcestr = gnc_price_get_source_string(price);
if (sourcestr && (strlen(sourcestr) != 0))
{
tmpnode = text_to_dom_tree("price:source", sourcestr);
diff --git a/src/backend/xml/io-gncxml-v1.c b/src/backend/xml/io-gncxml-v1.c
index 099ccd6..2dff2d0 100644
--- a/src/backend/xml/io-gncxml-v1.c
+++ b/src/backend/xml/io-gncxml-v1.c
@@ -3112,7 +3112,7 @@ price_parse_xml_sub_node(GNCPrice *p, xmlNodePtr sub_node, QofBook *book)
{
char *text = dom_tree_to_text(sub_node);
if (!text) return FALSE;
- gnc_price_set_source(p, text);
+ gnc_price_set_source_string(p, text);
g_free(text);
}
else if (g_strcmp0("price:type", (char*)sub_node->name) == 0)
diff --git a/src/engine/engine.i b/src/engine/engine.i
index bed289b..f11d309 100644
--- a/src/engine/engine.i
+++ b/src/engine/engine.i
@@ -354,7 +354,7 @@ KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, GSList *key_path);
SET_ENUM("TRANS-DATE-POSTED");
SET_ENUM("TRANS-DESCRIPTION");
SET_ENUM("TRANS-NUM");
-
+
SET_ENUM("KVP-OPTION-PATH");
SET_ENUM("OPTION-SECTION-ACCOUNTS");
@@ -375,6 +375,15 @@ KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, GSList *key_path);
SET_ENUM("GNC-HOW-RND-ROUND");
SET_ENUM("GNC-HOW-RND-NEVER");
+ SET_ENUM("PRICE-SOURCE-EDIT-DLG");
+ SET_ENUM("PRICE-SOURCE-FQ");
+ SET_ENUM("PRICE-SOURCE-USER-PRICE");
+ SET_ENUM("PRICE-SOURCE-XFER-DLG-VAL");
+ SET_ENUM("PRICE-SOURCE-SPLIT-REG");
+ SET_ENUM("PRICE-SOURCE-STOCK-SPLIT");
+ SET_ENUM("PRICE-SOURCE-INVOICE");
+ SET_ENUM("PRICE-SOURCE-INVALID");
+
#undef SET_ENUM
}
diff --git a/src/engine/gnc-pricedb-p.h b/src/engine/gnc-pricedb-p.h
index d93747b..8d867da 100644
--- a/src/engine/gnc-pricedb-p.h
+++ b/src/engine/gnc-pricedb-p.h
@@ -39,7 +39,7 @@ struct gnc_price_s
gnc_commodity *commodity;
gnc_commodity *currency;
Timespec tmspec;
- char *source;
+ PriceSource source;
char *type;
gnc_numeric value;
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 81febf1..8cb841b 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -58,9 +58,28 @@ gnc_price_init(GNCPrice* price)
price->refcount = 1;
price->value = gnc_numeric_zero();
price->type = NULL;
- price->source = NULL;
+ price->source = PRICE_SOURCE_INVALID;
}
+/* Array of char constants for converting price-source enums. Be sure to keep in
+ * sync with the enum values in gnc-pricedb.h The string user:price-editor is
+ * explicitly used by price_to_gui() in dialog-price-editor.c and the string
+ * Finance::Quote is explicitly used by fq-results->commod-tz-quote-triples in
+ * price-quotes.scm. Take care to keep them in sync if you make changes. Beware
+ * that the strings are used to store the enum values in the backends so any
+ * changes will affect backward data compatibility.
+ */
+static const char* source_names[] =
+{
+ "user:price-editor", //sync with price_to_gui in dialog-price-editor.c
+ "Finance::Quote", //sync with
+ "user:xfer-dialog",
+ "user:split-register",
+ "user:stock-split",
+ "user:invoice-post",
+ "invalid"
+};
+
static void
gnc_price_dispose(GObject *pricep)
{
@@ -90,7 +109,7 @@ gnc_price_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec
switch (prop_id)
{
case PROP_SOURCE:
- g_value_set_string(value, price->source);
+ g_value_set_string(value, gnc_price_get_source_string(price));
break;
case PROP_TYPE:
g_value_set_string(value, price->type);
@@ -126,7 +145,7 @@ gnc_price_set_property(GObject* object, guint prop_id, const GValue* value, GPar
switch (prop_id)
{
case PROP_SOURCE:
- gnc_price_set_source(price, g_value_get_string(value));
+ gnc_price_set_source_string(price, g_value_get_string(value));
break;
case PROP_TYPE:
gnc_price_set_typestr(price, g_value_get_string(value));
@@ -188,10 +207,10 @@ gnc_price_class_init(GNCPriceClass *klass)
PROP_SOURCE,
g_param_spec_string ("source",
"Price source",
- "The price source is a string describing the "
- "source of a price quote. It will be something "
- "like this: 'Finance::Quote', 'user:misc', "
- "'user:foo', etc.",
+ "The price source is PriceSource enum describing how"
+ " the price was created. This property works on the"
+ " string values in source_names for SQL database"
+ " compatibility.",
NULL,
G_PARAM_READWRITE));
@@ -252,7 +271,6 @@ gnc_price_destroy (GNCPrice *p)
qof_event_gen (&p->inst, QOF_EVENT_DESTROY, NULL);
if (p->type) CACHE_REMOVE(p->type);
- if (p->source) CACHE_REMOVE(p->source);
/* qof_instance_release (&p->inst); */
g_object_unref(p);
@@ -439,23 +457,30 @@ gnc_price_set_time(GNCPrice *p, Timespec t)
}
void
-gnc_price_set_source(GNCPrice *p, const char *s)
+gnc_price_set_source(GNCPrice *p, PriceSource s)
{
if (!p) return;
- if (g_strcmp0(p->source, s) != 0)
- {
- char *tmp;
-
- gnc_price_begin_edit (p);
- tmp = CACHE_INSERT((gpointer) s);
- if (p->source) CACHE_REMOVE(p->source);
- p->source = tmp;
- gnc_price_set_dirty(p);
- gnc_price_commit_edit (p);
- }
+ gnc_price_begin_edit (p);
+ p->source = s;
+ gnc_price_set_dirty(p);
+ gnc_price_commit_edit(p);
}
void
+gnc_price_set_source_string(GNCPrice *p, const char* str)
+{
+ if (!p) return;
+ for (PriceSource s = PRICE_SOURCE_EDIT_DLG;
+ s < PRICE_SOURCE_INVALID; ++s)
+ if (strcmp(source_names[s], str) == 0)
+ {
+ gnc_price_set_source(p, s);
+ return;
+ }
+
+
+}
+void
gnc_price_set_typestr(GNCPrice *p, const char* type)
{
if (!p) return;
@@ -518,13 +543,20 @@ gnc_price_get_time(const GNCPrice *p)
return p->tmspec;
}
-const char *
+PriceSource
gnc_price_get_source(const GNCPrice *p)
{
- if (!p) return NULL;
+ if (!p) return PRICE_SOURCE_INVALID;
return p->source;
}
+const char*
+gnc_price_get_source_string(const GNCPrice *p)
+{
+ if (!p) return NULL;
+ return source_names[p->source];
+}
+
const char *
gnc_price_get_typestr(const GNCPrice *p)
{
@@ -573,8 +605,7 @@ gnc_price_equal (const GNCPrice *p1, const GNCPrice *p2)
if (!timespec_equal (&ts1, &ts2))
return FALSE;
- if (g_strcmp0 (gnc_price_get_source (p1),
- gnc_price_get_source (p2)) != 0)
+ if (gnc_price_get_source (p1) != gnc_price_get_source (p2))
return FALSE;
if (g_strcmp0 (gnc_price_get_typestr (p1),
@@ -973,11 +1004,11 @@ insert_or_replace_price(GNCPriceDB *db, GNCPrice *p)
p->currency, p->tmspec);
if (old_price == NULL)
return TRUE;
- if (strcmp(p->source, "PRICE_SOURCE_FQ"))
+ if (p->source != PRICE_SOURCE_FQ)
return TRUE;
return FALSE;
-}
+}
/* ==================================================================== */
/* The add_price() function is a utility that only manages the
* dual hash table instertion */
@@ -1210,7 +1241,7 @@ static gboolean
check_one_price_date (GNCPrice *price, gpointer user_data)
{
remove_info *data = user_data;
- const gchar *source;
+ PriceSource source;
Timespec pt;
ENTER("price %p (%s), data %p", price,
@@ -1219,7 +1250,7 @@ check_one_price_date (GNCPrice *price, gpointer user_data)
if (!data->delete_user)
{
source = gnc_price_get_source (price);
- if (g_strcmp0(source, "Finance::Quote") != 0)
+ if (source != PRICE_SOURCE_FQ)
{
LEAVE("Not an automatic quote");
return TRUE;
@@ -2472,8 +2503,8 @@ gnc_price_print(GNCPrice *p, FILE *f, int indent)
str = str ? str : "(null)";
fprintf(f, "%s <cmdty:ref-id>%s</cmdty:ref-id>\n", istr, str);
fprintf(f, "%s </pdb:currency>\n", istr);
- str = gnc_price_get_source(p);
- str = str ? str : "(null)";
+ str = source_names[gnc_price_get_source(p)];
+ str = str ? str : "invalid";
fprintf(f, "%s %s\n", istr, str);
str = gnc_price_get_typestr(p);
str = str ? str : "(null)";
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index ae65748..00a4126 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -156,6 +156,25 @@ GType gnc_pricedb_get_type(void);
typedef struct gnc_price_lookup_s GNCPriceLookup;
typedef GList PriceList;
+/** Price source enum. Be sure to keep in sync with the source_name array in
+ * gnc-pricedb.c. These are in preference order, so for example a quote with
+ * PRICE_SOURCE_EDIT_DLG will overwrite one with PRICE_SOURCE_FQ but not the
+ * other way around.
+ */
+typedef enum
+{
+ PRICE_SOURCE_EDIT_DLG, // "user:price-editor"
+ PRICE_SOURCE_FQ, // "Finance::Quote"
+ PRICE_SOURCE_XFER_DLG, // "user:xfer-dialog"
+ PRICE_SOURCE_SPLIT_REG, // "user:split-register"
+ PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
+ PRICE_SOURCE_INVOICE, // "user:invoice-post"
+ PRICE_SOURCE_INVALID,
+} PriceSource;
+
+#define PRICE_TYPE_LAST "last"
+#define PRICE_TYPE_UNK "unknown"
+
/* ------------------ */
/** @name Constructors
@{ */
@@ -202,33 +221,26 @@ void gnc_price_commit_edit (GNCPrice *p);
void gnc_price_set_commodity(GNCPrice *p, gnc_commodity *c);
void gnc_price_set_currency(GNCPrice *p, gnc_commodity *c);
void gnc_price_set_time(GNCPrice *p, Timespec t);
-void gnc_price_set_source(GNCPrice *p, const char *source);
+void gnc_price_set_source(GNCPrice *p, PriceSource source);
+void gnc_price_set_source_string(GNCPrice *p, const char* s);
void gnc_price_set_typestr(GNCPrice *p, const char* type);
void gnc_price_set_value(GNCPrice *p, gnc_numeric value);
/** @} */
-#define PRICE_SOURCE_FQ "Finance::Quote"
-#define PRICE_SOURCE_INVOICE "user:invoice-post"
-#define PRICE_SOURCE_STOCK_SPLIT "user:stock-split"
-#define PRICE_SOURCE_XFER_DLG "user:xfer-dialog"
-#define PRICE_SOURCE_SPLIT_REG "user:split-register"
-#define PRICE_SOURCE_EDIT_DLG "user:price-editor"
-#define PRICE_TYPE_LAST "last"
-#define PRICE_TYPE_UNK "unknown"
-
/* ------------------ */
/** @name Getters
All of the getters return data that's internal
to the GNCPrice, not copies, so don't free these values.
@{ */
-GNCPrice * gnc_price_lookup (const GncGUID *guid, QofBook *book);
+ GNCPrice * gnc_price_lookup (const GncGUID *guid, QofBook *book);
/*@ dependent @*/
gnc_commodity * gnc_price_get_commodity(const GNCPrice *p);
/*@ dependent @*/
gnc_commodity * gnc_price_get_currency(const GNCPrice *p);
Timespec gnc_price_get_time(const GNCPrice *p);
-const char * gnc_price_get_source(const GNCPrice *p);
+PriceSource gnc_price_get_source(const GNCPrice *p);
+const char * gnc_price_get_source_string(const GNCPrice *p);
const char * gnc_price_get_typestr(const GNCPrice *p);
gnc_numeric gnc_price_get_value(const GNCPrice *p);
gboolean gnc_price_equal(const GNCPrice *p1, const GNCPrice *p2);
diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c
index fa63449..1415b6b 100644
--- a/src/engine/test-core/test-engine-stuff.c
+++ b/src/engine/test-core/test-engine-stuff.c
@@ -676,6 +676,7 @@ void
make_random_changes_to_price (QofBook *book, GNCPrice *p)
{
Timespec *ts;
+ PriceSource ps;
char *string;
gnc_commodity *c;
@@ -693,9 +694,9 @@ make_random_changes_to_price (QofBook *book, GNCPrice *p)
gnc_price_set_time (p, *ts);
g_free (ts);
- string = get_random_string ();
- gnc_price_set_source (p, string);
- g_free (string);
+ ps = (PriceSource)get_random_int_in_range((int)PRICE_SOURCE_EDIT_DLG,
+ (int)PRICE_SOURCE_INVALID);
+ gnc_price_set_source (p, ps);
string = get_random_string ();
gnc_price_set_typestr (p, string);
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 58b2c63..bf3de11 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1616,7 +1616,7 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (pr.price);
return;
}
- if (strcmp (gnc_price_get_source(pr.price), PRICE_SOURCE_FQ) == 0)
+ if (gnc_price_get_source(pr.price) == PRICE_SOURCE_FQ)
{
PINFO("Existing price is from Finance::Quote, so won't supersede.");
gnc_price_unref (pr.price);
diff --git a/src/gnome-utils/gnc-tree-model-price.c b/src/gnome-utils/gnc-tree-model-price.c
index c62b749..20a4409 100644
--- a/src/gnome-utils/gnc-tree-model-price.c
+++ b/src/gnome-utils/gnc-tree-model-price.c
@@ -786,7 +786,7 @@ gnc_tree_model_price_get_value (GtkTreeModel *tree_model,
break;
case GNC_TREE_MODEL_PRICE_COL_SOURCE:
g_value_init (value, G_TYPE_STRING);
- g_value_set_string (value, gettext (gnc_price_get_source (price)));
+ g_value_set_string (value, gettext (gnc_price_get_source_string (price)));
break;
case GNC_TREE_MODEL_PRICE_COL_TYPE:
g_value_init (value, G_TYPE_STRING);
diff --git a/src/gnome-utils/gnc-tree-view-price.c b/src/gnome-utils/gnc-tree-view-price.c
index 7f3113d..b0dc599 100644
--- a/src/gnome-utils/gnc-tree-view-price.c
+++ b/src/gnome-utils/gnc-tree-view-price.c
@@ -300,8 +300,7 @@ sort_by_source (GtkTreeModel *f_model,
return sort_ns_or_cm (f_model, f_iter_a, f_iter_b);
/* sort by source first */
- result = safe_utf8_collate (gnc_price_get_source (price_a),
- gnc_price_get_source (price_b));
+ result = gnc_price_get_source (price_a) < gnc_price_get_source (price_b);
if (result != 0)
return result;
diff --git a/src/gnome/dialog-price-editor.c b/src/gnome/dialog-price-editor.c
index c7c5b9e..d395903 100644
--- a/src/gnome/dialog-price-editor.c
+++ b/src/gnome/dialog-price-editor.c
@@ -161,7 +161,7 @@ price_to_gui (PriceEditDialog *pedit_dialog)
currency = gnc_price_get_currency (pedit_dialog->price);
date = gnc_price_get_time (pedit_dialog->price);
- source = gnc_price_get_source (pedit_dialog->price);
+ source = gnc_price_get_source_string (pedit_dialog->price);
type = gnc_price_get_typestr (pedit_dialog->price);
value = gnc_price_get_value (pedit_dialog->price);
}
@@ -170,7 +170,7 @@ price_to_gui (PriceEditDialog *pedit_dialog)
currency = gnc_default_currency ();
date.tv_sec = gnc_time (NULL);
date.tv_nsec = 0;
- source = PRICE_SOURCE_EDIT_DLG;
+ source = "user:price-editor"; //Sync with source_names in gnc-pricedb.c
type = "";
value = gnc_numeric_zero ();
}
@@ -237,7 +237,7 @@ gui_to_price (PriceEditDialog *pedit_dialog)
gnc_price_set_commodity (pedit_dialog->price, commodity);
gnc_price_set_currency (pedit_dialog->price, currency);
gnc_price_set_time (pedit_dialog->price, date);
- gnc_price_set_source (pedit_dialog->price, source);
+ gnc_price_set_source_string (pedit_dialog->price, source);
gnc_price_set_typestr (pedit_dialog->price, type);
gnc_price_set_value (pedit_dialog->price, value);
gnc_price_commit_edit (pedit_dialog->price);
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 1b5dd47..1332bf1 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2084,7 +2084,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_unref (price);
return;
}
- if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ if (gnc_price_get_source(price) == PRICE_SOURCE_FQ)
{
gnc_price_unref(price);
return;
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index c6a2405..b597a94 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -415,7 +415,7 @@
(begin
(gnc-price-begin-edit saved-price)
(gnc-price-set-time saved-price gnc-time)
- (gnc-price-set-source saved-price "Finance::Quote")
+ (gnc-price-set-source saved-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr saved-price price-type)
(gnc-price-set-value saved-price price)
(gnc-price-commit-edit saved-price)
@@ -429,7 +429,7 @@
(gnc-price-set-commodity gnc-price commodity)
(gnc-price-set-currency gnc-price currency)
(gnc-price-set-time gnc-price gnc-time)
- (gnc-price-set-source gnc-price "Finance::Quote")
+ (gnc-price-set-source gnc-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr gnc-price price-type)
(gnc-price-set-value gnc-price price)
(gnc-price-commit-edit gnc-price)
commit ab15ca8f8458480ebbc8d68f73eeb335ed959c25
Author: John Ralls <jralls at ceridwen.us>
Date: Thu Sep 3 11:22:51 2015 -0700
Extract function lookup_price in dialog_transfer.c
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index b36fdc0..58b2c63 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -215,73 +215,107 @@ round_price(gnc_commodity *from, gnc_commodity *to, gnc_numeric value)
return value;
}
-/* (maybe) update the price from the pricedb. */
-static void
-gnc_xfer_dialog_update_price (XferDialog *xferData)
+typedef struct
{
- GNCPrice *prc;
- gnc_numeric price_value;
- Timespec date;
- gnc_commodity *from = xferData->from_commodity;
- gnc_commodity *to = xferData->to_commodity;
+ GNCPrice *price;
+ GNCPriceDB *pricedb;
+ gnc_commodity *from;
+ gnc_commodity *to;
+ Timespec ts;
gboolean reverse;
+} PriceReq;
- if (!xferData) return;
- if (!xferData->from_commodity || ! xferData->to_commodity) return;
- if (gnc_commodity_equal (xferData->from_commodity, xferData->to_commodity))
- return;
- if (!xferData->pricedb) return;
-
- /* when do we update, and when do we NOT update? */
-
- /* XXX: I'm ALWAYS going to update whenever we get called */
-
- /* grab the price on the same day or nearest to the DATE out of the pricedb */
- date = gnc_date_edit_get_date_ts (GNC_DATE_EDIT (xferData->date_entry));
+static void
+price_request_from_xferData(PriceReq *pr, XferDialog *xd)
+{
+ g_return_if_fail (pr != NULL);
+ g_return_if_fail (xd != NULL);
+ pr->price = NULL;
+ pr->pricedb = xd->pricedb;
+ pr->from = xd->from_commodity;
+ pr->to = xd->to_commodity;
+ pr->ts = gnc_date_edit_get_date_ts (GNC_DATE_EDIT (xd->date_entry));
+ pr->reverse = FALSE;
+}
- /* Look for a price on the same day or, failing that, closest in time. */
- prc = gnc_pricedb_lookup_day (xferData->pricedb, from, to, date);
- reverse = FALSE;
+static gboolean
+lookup_price(PriceReq *pr, gboolean day_only)
+{
+ GNCPrice *prc = NULL;
+ g_return_val_if_fail (pr != NULL, FALSE);
+ g_return_val_if_fail (pr->pricedb != NULL, FALSE);
+ g_return_val_if_fail (pr->from != NULL, FALSE);
+ g_return_val_if_fail (pr->to != NULL, FALSE);
+ pr->reverse = FALSE;
+ if (day_only)
+ {
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from, pr->to, pr->ts);
if (!prc)
{
- /* Look for reverse price on same day */
- prc = gnc_pricedb_lookup_day (xferData->pricedb, to, from, date);
- reverse = TRUE;
+ prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
}
-
+ }
+ else
+ {
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
+ pr->to, pr->ts);
if (!prc)
{
- /* Didn't find one on the same day, look for nearest in time */
- prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, from,
- to, date);
- reverse = FALSE;
+ prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
+ pr->from, pr->ts);
+ pr->reverse = TRUE;
}
+ }
+ if (pr->reverse)
+ {
+ PINFO("Found reverse price: 1 %s = %f %s",
+ gnc_commodity_get_mnemonic(pr->to),
+ gnc_numeric_to_double(gnc_price_get_value(prc)),
+ gnc_commodity_get_mnemonic(pr->from));
- if (!prc)
+ }
+ else
{
- prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, to,
- from, date);
- reverse = TRUE;
+ PINFO("Found price: 1 %s = %f %s",
+ gnc_commodity_get_mnemonic(pr->from),
+ gnc_numeric_to_double(gnc_price_get_value(prc)),
+ gnc_commodity_get_mnemonic(pr->to));
}
-
if (!prc)
+ return FALSE;
+ pr->price = prc;
+ return TRUE;
+}
+
+/* (maybe) update the price from the pricedb. */
+static void
+gnc_xfer_dialog_update_price (XferDialog *xferData)
+{
+ PriceReq pr;
+ gnc_numeric price_value;
+
+ if (!xferData) return;
+ if (!xferData->from_commodity || ! xferData->to_commodity) return;
+ if (gnc_commodity_equal (xferData->from_commodity, xferData->to_commodity))
+ return;
+ if (!xferData->pricedb) return;
+
+ price_request_from_xferData(&pr, xferData);
+ if (!lookup_price(&pr, TRUE))
+ if (!lookup_price(&pr, FALSE))
return;
/* grab the price from the pricedb */
- price_value = gnc_price_get_value (prc);
- if (reverse)
+ price_value = gnc_price_get_value (pr.price);
+ if (pr.reverse)
{
- PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
- gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
price_value = gnc_numeric_invert (price_value);
- price_value = round_price(from, to, price_value);
- }
- else
- {
- PINFO("Found price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(to));
+ price_value = round_price(pr.from, pr.to, price_value);
}
+ gnc_price_unref(pr.price);
/* and set the price entry */
gnc_xfer_dialog_set_price_edit(xferData, price_value);
@@ -1542,9 +1576,10 @@ swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
static void
create_price(XferDialog *xferData, Timespec ts)
{
+ PriceReq pr;
+ GNCPrice *price = NULL;
gnc_commodity *from = xferData->from_commodity;
gnc_commodity *to = xferData->to_commodity;
- GNCPrice *price;
gnc_numeric price_value;
gnc_numeric value;
gnc_numeric from_amt, to_amt;
@@ -1561,52 +1596,49 @@ create_price(XferDialog *xferData, Timespec ts)
(strcmp (gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to)) < 0)))
swap_amount (&from, &to, &value, &from_amt, &to_amt);
- /* First see if the closest entry on the same day has an equivalent rate */
- price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
- if (!price)
- {
- price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
- if (price)
- swap = TRUE;
- }
+
/* Normally we want to store currency rates such that the rate > 1 and commodity
* prices in terms of a currency regardless of value. However, if we already
* have a price in either direction we want to continue using that direction for
* the rest of the day so that we don't wind up with two prices if the rate
* shifts to be < 1. */
- if (price)
+ price_request_from_xferData(&pr, xferData);
+ if (lookup_price(&pr, TRUE))
{
- price_value = gnc_price_get_value(price);
- if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
+ price_value = gnc_price_get_value(pr.price);
+ if (gnc_numeric_equal(pr.reverse ? gnc_numeric_invert(value) : value,
price_value))
{
- PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to));
- gnc_price_unref (price);
+ PINFO("Found price for %s in %s",
+ gnc_commodity_get_mnemonic(pr.from),
+ gnc_commodity_get_mnemonic(pr.to));
+ gnc_price_unref (pr.price);
return;
}
- if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ if (strcmp (gnc_price_get_source(pr.price), PRICE_SOURCE_FQ) == 0)
{
PINFO("Existing price is from Finance::Quote, so won't supersede.");
- gnc_price_unref (price);
+ gnc_price_unref (pr.price);
return;
}
- if (swap)
+ if (pr.reverse)
{
value = swap_commodities(&from, &to, value);
xferData->from_commodity = from;
xferData->to_commodity = to;
}
- value = round_price(from, to, value);
- gnc_price_begin_edit (price);
- gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
- gnc_price_set_value (price, value);
- gnc_price_commit_edit (price);
- PINFO("Modified price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
- gnc_price_unref (price);
+ value = round_price(pr.from, pr.to, value);
+ gnc_price_begin_edit (pr.price);
+ gnc_price_set_time (pr.price, ts);
+ gnc_price_set_source (pr.price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_value (pr.price, value);
+ gnc_price_commit_edit (pr.price);
+ PINFO("Modified price: 1 %s = %f %s",
+ gnc_commodity_get_mnemonic(from),
+ gnc_numeric_to_double(value),
+ gnc_commodity_get_mnemonic(to));
+ gnc_price_unref (pr.price);
return;
}
if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
commit 76c1259f1b3b22320df931f6a1d4abe850579f5a
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:44:25 2015 -0700
Adjust split_register to match transfer dialog checking inverted prices.
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 3cf90cc..1b5dd47 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2056,6 +2056,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
int scu = gnc_commodity_get_fraction(curr);
Timespec ts;
BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
+ gboolean swap = FALSE;
/* Only record the price for account types that don't have a
* "rate" cell. They'll get handled later by
@@ -2065,24 +2066,20 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
return;
gnc_date_cell_get_date ((DateCell*)cell, &ts);
price = gnc_pricedb_lookup_day (pricedb, comm, curr, ts);
- if (price)
- {
- price_value = gnc_price_get_value(price);
- }
- else
+ if (!price)
{
price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
if (price)
- {
/* It might be better to raise an error here: We shouldn't be creating
* currency->commodity prices.
*/
- price_value = gnc_numeric_invert(gnc_price_get_value(price));
- }
+ swap = TRUE;
}
if (price)
{
- if (gnc_numeric_equal(value, price_value))
+ price_value = gnc_price_get_value(price);
+ if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
+ price_value))
{
gnc_price_unref (price);
return;
@@ -2092,16 +2089,13 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_unref(price);
return;
}
- if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ if (swap)
{
value = gnc_numeric_invert(value);
scu = gnc_commodity_get_fraction(comm);
- value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
}
- else
- value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
commit 348fe45b76ad4527a82726a287f0a76186f1b80a
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:39:12 2015 -0700
Fix missing initialization of price_value.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 15afccb..b36fdc0 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1577,6 +1577,7 @@ create_price(XferDialog *xferData, Timespec ts)
if (price)
{
+ price_value = gnc_price_get_value(price);
if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
price_value))
{
commit a40bc92d3410409470ae281c4cf013818c295f54
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:17:12 2015 -0700
Change CURRENCY_DENOM to 10000, matching what F::Q returns.
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index c7fe6d0..ae65748 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -250,7 +250,7 @@ void gnc_price_print(GNCPrice *db, FILE *f, int indent);
* of the commodity with a fixed denominator of the pricing currency's
* SCU * 10000.
*/
-#define CURRENCY_DENOM 1000
+#define CURRENCY_DENOM 10000
#define COMMODITY_DENOM_MULT 10000
/* ================================================================ */
commit 6e1413771032ee2ad14244042edf320e0ad94d44
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Sep 1 12:16:09 2015 -0700
Extract function round_price(), consistently apply it.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index c43d868..15afccb 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -189,6 +189,32 @@ gnc_xfer_dialog_compute_price_value (XferDialog *xferData)
return(gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE));
}
+/* Round a price value according to this policy:
+ * If both commodities are currencies, round to a fixed denominator.
+ * If only one is a currency, round to the currency's scu * a fixed factor.
+ * The fixed values are defined in gnc-pricedb.h
+ */
+static gnc_numeric
+round_price(gnc_commodity *from, gnc_commodity *to, gnc_numeric value)
+{
+ if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
+ value = gnc_numeric_convert(value, CURRENCY_DENOM,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ else if (gnc_commodity_is_currency(to))
+ {
+ int scu = gnc_commodity_get_fraction (to);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ else if (gnc_commodity_is_currency(from))
+ {
+ int scu = gnc_commodity_get_fraction (from);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ return value;
+}
+
/* (maybe) update the price from the pricedb. */
static void
gnc_xfer_dialog_update_price (XferDialog *xferData)
@@ -248,7 +274,8 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
- price_value = gnc_numeric_invert(price_value);
+ price_value = gnc_numeric_invert (price_value);
+ price_value = round_price(from, to, price_value);
}
else
{
@@ -1000,17 +1027,11 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
XferDialog *xferData = data;
gnc_numeric price_value;
Account *account;
- int scu;
- account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
- if (account == NULL)
- account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_FROM);
- scu = xaccAccountGetCommoditySCU(account);
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
-
price_value = gnc_xfer_dialog_compute_price_value(xferData);
- price_value = gnc_numeric_convert (price_value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
+ price_value = round_price(xferData->from_commodity, xferData->to_commodity,
+ price_value);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
gnc_xfer_dialog_update_conv_info(xferData);
@@ -1496,24 +1517,26 @@ static void
swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
gnc_numeric *from_amt, gnc_numeric *to_amt)
{
- gnc_commodity *tmp;
- gnc_numeric *tmp_amt;
- tmp = *from;
+ gnc_commodity *tmp = *from;
+ gnc_numeric *tmp_amt = from_amt;
*from = *to;
*to = tmp;
- tmp_amt = from_amt;
from_amt = to_amt;
to_amt = tmp_amt;
*value = gnc_numeric_invert (*value);
+ *value = round_price(*from, *to, *value);
}
static gnc_numeric
swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
{
gnc_commodity *tmp = *to;
+
*to = *from;
*from = tmp;
- return gnc_numeric_invert(value);
+ value = gnc_numeric_invert(value);
+ value = round_price(*from, *to, value);
+ return value;
}
static void
@@ -1546,6 +1569,11 @@ create_price(XferDialog *xferData, Timespec ts)
if (price)
swap = TRUE;
}
+/* Normally we want to store currency rates such that the rate > 1 and commodity
+ * prices in terms of a currency regardless of value. However, if we already
+ * have a price in either direction we want to continue using that direction for
+ * the rest of the day so that we don't wind up with two prices if the rate
+ * shifts to be < 1. */
if (price)
{
@@ -1566,16 +1594,10 @@ create_price(XferDialog *xferData, Timespec ts)
if (swap)
{
value = swap_commodities(&from, &to, value);
+ xferData->from_commodity = from;
+ xferData->to_commodity = to;
}
- if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
- value = gnc_numeric_convert(value, CURRENCY_DENOM,
- GNC_HOW_RND_ROUND_HALF_UP);
- else if (gnc_commodity_is_currency(to))
- {
- int scu = gnc_commodity_get_fraction (to);
- value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
- GNC_HOW_RND_ROUND_HALF_UP);
- }
+ value = round_price(from, to, value);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
@@ -1814,6 +1836,7 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
{
/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
rate = gnc_numeric_invert(gnc_price_get_value (prc));
+ rate = round_price(from, to, rate);
gnc_xfer_dialog_set_price_edit(xferData, rate);
gnc_price_unref (prc);
have_price = TRUE;
@@ -2370,6 +2393,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gboolean swap_amounts = FALSE;
gnc_commodity *txn_cur = xaccTransGetCurrency(txn);
gnc_commodity *reg_com = xaccAccountGetCommodity(reg_acc);
+ gnc_numeric dialog_rate = *exch_rate;
g_return_val_if_fail(txn_cur, TRUE);
@@ -2431,7 +2455,10 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
- *exch_rate = gnc_numeric_invert(*exch_rate);
+ {
+ dialog_rate = gnc_numeric_invert(*exch_rate);
+ dialog_rate = round_price(xfer_com, txn_cur, *exch_rate);
+ }
amount = gnc_numeric_neg(amount);
}
else
@@ -2461,10 +2488,5 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
if (gnc_xfer_dialog_run_until_done(xfer) == FALSE)
return TRUE;
- /* If we swapped the amounts for the dialog, then make sure we swap
- * it back now...
- */
- if (swap_amounts)
- *exch_rate = gnc_numeric_invert(*exch_rate);
return FALSE;
}
commit f30b38b5c3496e1e3846c9a1e1ee20841de15a2e
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 21:20:51 2015 +0100
Create a rounding policy for prices in the pricedb.
Currency-currency prices will be priced in the smaller currency so that
the price > 1 and will be rounded to 3 digits after the decimal.
Commodity-currency prices will be priced in the currency and rounded to
the currency's scu * 10000.
This affects only prices stored in the pricedb. Prices in splits will
continue to be computed from value/amount.
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index befff2d..c7fe6d0 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -243,6 +243,15 @@ gboolean gnc_price_equal(const GNCPrice *p1, const GNCPrice *p2);
/** This simple function can be useful for debugging the price code */
void gnc_price_print(GNCPrice *db, FILE *f, int indent);
/** @} */
+/** @name Denominator Constants Price policy: In order to avoid rounding
+ * problems, currency prices (often called exchange rates) are saved in terms of
+ * the smaller currency, so that price > 1, with a fixed denominator of
+ * 1/1000. Commodity prices in currency are always expressed as value per unit
+ * of the commodity with a fixed denominator of the pricing currency's
+ * SCU * 10000.
+ */
+#define CURRENCY_DENOM 1000
+#define COMMODITY_DENOM_MULT 10000
/* ================================================================ */
/** @name GNCPrice lists
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 6233581..c43d868 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -55,8 +55,6 @@
#define DIALOG_TRANSFER_CM_CLASS "dialog-transfer"
#define GNC_PREFS_GROUP "dialogs.transfer"
-#define PRECISION 1000000
-
typedef enum
{
XFER_DIALOG_FROM,
@@ -1002,15 +1000,16 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
XferDialog *xferData = data;
gnc_numeric price_value;
Account *account;
+ int scu;
account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
if (account == NULL)
account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_FROM);
-
+ scu = xaccAccountGetCommoditySCU(account);
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
price_value = gnc_xfer_dialog_compute_price_value(xferData);
- price_value = gnc_numeric_convert (price_value, PRECISION,
+ price_value = gnc_numeric_convert (price_value, scu * COMMODITY_DENOM_MULT,
GNC_HOW_RND_ROUND_HALF_UP);
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
price_value);
@@ -1507,6 +1506,16 @@ swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
to_amt = tmp_amt;
*value = gnc_numeric_invert (*value);
}
+
+static gnc_numeric
+swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
+{
+ gnc_commodity *tmp = *to;
+ *to = *from;
+ *from = tmp;
+ return gnc_numeric_invert(value);
+}
+
static void
create_price(XferDialog *xferData, Timespec ts)
{
@@ -1516,6 +1525,7 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_numeric price_value;
gnc_numeric value;
gnc_numeric from_amt, to_amt;
+ gboolean swap = FALSE;
/* Bail in the unlikely event that both currencies have joined the Euro. */
if (gnc_is_euro_currency (from) && gnc_is_euro_currency (to))
@@ -1530,21 +1540,17 @@ create_price(XferDialog *xferData, Timespec ts)
swap_amount (&from, &to, &value, &from_amt, &to_amt);
/* First see if the closest entry on the same day has an equivalent rate */
price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
- if (price)
- {
- price_value = gnc_price_get_value(price);
- }
- else
+ if (!price)
{
price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
if (price)
-
- price_value = gnc_numeric_invert(gnc_price_get_value(price));
+ swap = TRUE;
}
if (price)
{
- if (gnc_numeric_equal(value, price_value))
+ if (gnc_numeric_equal(swap ? gnc_numeric_invert(value) : value,
+ price_value))
{
PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to));
@@ -1557,10 +1563,18 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (price);
return;
}
- if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ if (swap)
{
- value = gnc_numeric_invert(value);
- value = gnc_numeric_convert(value, PRECISION, GNC_HOW_DENOM_REDUCE);
+ value = swap_commodities(&from, &to, value);
+ }
+ if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
+ value = gnc_numeric_convert(value, CURRENCY_DENOM,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ else if (gnc_commodity_is_currency(to))
+ {
+ int scu = gnc_commodity_get_fraction (to);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
}
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
@@ -1572,6 +1586,24 @@ create_price(XferDialog *xferData, Timespec ts)
gnc_price_unref (price);
return;
}
+ if (gnc_commodity_is_currency(from) && gnc_commodity_is_currency(to))
+ {
+ if (value.num < value.denom)
+ {
+ value = swap_commodities(&from, &to, value);
+ }
+ value = gnc_numeric_convert(value, CURRENCY_DENOM,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ else if (gnc_commodity_is_currency(from) || gnc_commodity_is_currency(to))
+ {
+ int scu;
+ if (gnc_commodity_is_currency(from))
+ value = swap_commodities(&from, &to, value);
+ scu = gnc_commodity_get_fraction (to);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
price = gnc_price_create (xferData->book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, from);
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index aef5c6f..3cf90cc 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -64,9 +64,9 @@ static QofLogModule log_module = GNC_MOD_LEDGER;
static CursorClass copied_class = CURSOR_CLASS_NONE;
static SCM copied_item = SCM_UNDEFINED;
static GncGUID copied_leader_guid;
-static const int PRECISION = 1000000;
-
-
+/* A denominator representing number of digits to the right of the decimal point
+ * displayed in a price cell. */
+static int PRICE_CELL_DENOM = 1000000;
/** static prototypes *****************************************************/
static gboolean gnc_split_register_save_to_scm (SplitRegister *reg,
@@ -2053,6 +2053,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_commodity *curr = xaccTransGetCurrency (trans);
GNCPrice *price;
gnc_numeric price_value;
+ int scu = gnc_commodity_get_fraction(curr);
Timespec ts;
BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
@@ -2073,10 +2074,10 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
if (price)
{
- price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
- gnc_price_get_value(price),
- GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
+/* It might be better to raise an error here: We shouldn't be creating
+ * currency->commodity prices.
+ */
+ price_value = gnc_numeric_invert(gnc_price_get_value(price));
}
}
if (price)
@@ -2092,9 +2093,15 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
return;
}
if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
- value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
- PRECISION, GNC_HOW_DENOM_REDUCE);
-
+ {
+ value = gnc_numeric_invert(value);
+ scu = gnc_commodity_get_fraction(comm);
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+ else
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
@@ -2104,6 +2111,8 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
return;
}
+ value = gnc_numeric_convert(value, scu * COMMODITY_DENOM_MULT,
+ GNC_HOW_RND_ROUND_HALF_UP);
price = gnc_price_create (book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, comm);
@@ -2589,7 +2598,8 @@ gnc_split_register_config_cells (SplitRegister *reg)
/* Use 6 decimal places for prices and "exchange rates" */
gnc_price_cell_set_fraction
((PriceCell *)
- gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL), PRECISION);
+ gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL),
+ PRICE_CELL_DENOM);
/* Initialize shares and share balance cells */
gnc_price_cell_set_print_info
commit a8d4eaae5ecf663d550687b2cebf4a02dc5c8f56
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 19:25:35 2015 +0100
Rename _gnc_xfer_dialog_set_exchange_rate and use it consistently.
gnc_xfer_dialog_set_price_edit says what we're actually setting.
diff --git a/src/business/business-gnome/dialog-invoice.c b/src/business/business-gnome/dialog-invoice.c
index 10c4d75..0a24b69 100644
--- a/src/business/business-gnome/dialog-invoice.c
+++ b/src/business/business-gnome/dialog-invoice.c
@@ -878,7 +878,7 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
{
exch_rate = gnc_numeric_div ((gnc_numeric){1, 1}, exch_rate,
GNC_DENOM_AUTO, GNC_HOW_RND_ROUND_HALF_UP);
- gnc_xfer_dialog_set_exchange_rate (xfer, exch_rate);
+ gnc_xfer_dialog_set_price_edit (xfer, exch_rate);
}
}
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 0a97be7..6233581 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -259,7 +259,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
}
/* and set the price entry */
- gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit), price_value);
+ gnc_xfer_dialog_set_price_edit(xferData, price_value);
/* And then update the to_amount */
gnc_xfer_update_to_amount (xferData);
@@ -313,9 +313,7 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
if (!currency_active)
{
GtkEntry *entry;
-
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
- gnc_numeric_zero ());
+ gnc_xfer_dialog_set_price_edit(xferData, gnc_numeric_zero());
entry = GTK_ENTRY(gnc_amount_edit_gtk_entry
(GNC_AMOUNT_EDIT(xferData->price_edit)));
gtk_entry_set_text(entry, "");
@@ -1338,16 +1336,16 @@ void gnc_xfer_dialog_set_date_sensitive(XferDialog *xferData,
}
void
-gnc_xfer_dialog_set_exchange_rate(XferDialog *xferData, gnc_numeric exchange_rate)
+gnc_xfer_dialog_set_price_edit(XferDialog *xferData, gnc_numeric price_value)
{
if (xferData == NULL)
return;
- if (gnc_numeric_zero_p (exchange_rate))
+ if (gnc_numeric_zero_p (price_value))
return;
gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit),
- exchange_rate);
+ price_value);
gnc_xfer_update_to_amount (xferData);
}
@@ -1771,7 +1769,7 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
if (prc)
{
rate = gnc_price_get_value (prc);
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
+ gnc_xfer_dialog_set_price_edit(xferData, rate);
gnc_price_unref (prc);
have_price = TRUE;
}
@@ -1782,9 +1780,9 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
if (prc)
{
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
rate = gnc_numeric_invert(gnc_price_get_value (prc));
+ gnc_xfer_dialog_set_price_edit(xferData, rate);
gnc_price_unref (prc);
have_price = TRUE;
}
@@ -2425,7 +2423,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
*/
/* Set the exchange rate */
- gnc_xfer_dialog_set_exchange_rate(xfer, *exch_rate);
+ gnc_xfer_dialog_set_price_edit(xfer, *exch_rate);
/* and run it... */
if (gnc_xfer_dialog_run_until_done(xfer) == FALSE)
@@ -2435,7 +2433,6 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
* it back now...
*/
if (swap_amounts)
- *exch_rate = gnc_numeric_div(gnc_numeric_create(1, 1), *exch_rate,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ *exch_rate = gnc_numeric_invert(*exch_rate);
return FALSE;
}
diff --git a/src/gnome-utils/dialog-transfer.h b/src/gnome-utils/dialog-transfer.h
index 7a8d6b3..4b4bc84 100644
--- a/src/gnome-utils/dialog-transfer.h
+++ b/src/gnome-utils/dialog-transfer.h
@@ -141,9 +141,11 @@ void gnc_xfer_dialog_set_date(XferDialog *xferData, time64 set_time);
/** Set the "sensitive" state of the date field to the given value */
void gnc_xfer_dialog_set_date_sensitive(XferDialog *xferData, gboolean is_sensitive);
-/** Set the exchange rate. If exchange-rate is 0, then do nothing */
-void gnc_xfer_dialog_set_exchange_rate(XferDialog *xferData,
- gnc_numeric exchange_rate);
+/** Set the dialog's exchange rate edit. If price_value is 0, then do
+ * nothing.
+ */
+void gnc_xfer_dialog_set_price_edit(XferDialog *xferData,
+ gnc_numeric price_value);
/** Indicate whether the dialog should quickfill based on the "To" account,
* rather than the default which is the "From" account.
commit f79a3af4a2168f11f03d85c1295c050bfd931932
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 19:21:37 2015 +0100
Provide gnc_numeric_invert() convenience function.
Clearer and faster than dividing into 1/1.
diff --git a/src/app-utils/gnc-sx-instance-model.c b/src/app-utils/gnc-sx-instance-model.c
index 560fe79..cc7dbbf 100644
--- a/src/app-utils/gnc-sx-instance-model.c
+++ b/src/app-utils/gnc-sx-instance-model.c
@@ -1170,9 +1170,9 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
}
else
{
- exchange = gnc_numeric_div(gnc_numeric_create(1,1),
- gnc_price_get_value(price),
- 1000, GNC_HOW_RND_ROUND_HALF_UP);
+ exchange = gnc_numeric_invert(gnc_price_get_value(price));
+ exchange = gnc_numeric_convert(exchange, 1000,
+ GNC_HOW_RND_ROUND_HALF_UP);
}
}
else
@@ -1779,4 +1779,3 @@ GHashTable* gnc_sx_all_instantiate_cashflow_all(GDate range_start, GDate range_e
result_map, NULL);
return result_map;
}
-
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 174ff7a..0a97be7 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -250,8 +250,7 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
- price_value = gnc_numeric_div (gnc_numeric_create (1, 1), price_value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ price_value = gnc_numeric_invert(price_value);
}
else
{
@@ -910,8 +909,7 @@ gnc_xfer_dialog_update_conv_info (XferDialog *xferData)
gtk_label_set_text(GTK_LABEL(xferData->conv_forward), string);
g_free(string);
- rate = gnc_numeric_div(gnc_numeric_create (1, 1), rate,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ rate = gnc_numeric_invert(rate);
string = g_strdup_printf("1 %s = %f %s", to_mnemonic,
gnc_numeric_to_double(rate), from_mnemonic);
gtk_label_set_text(GTK_LABEL(xferData->conv_reverse), string);
@@ -1509,8 +1507,7 @@ swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
tmp_amt = from_amt;
from_amt = to_amt;
to_amt = tmp_amt;
- *value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ *value = gnc_numeric_invert (*value);
}
static void
create_price(XferDialog *xferData, Timespec ts)
@@ -1543,12 +1540,8 @@ create_price(XferDialog *xferData, Timespec ts)
{
price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
if (price)
- {
- price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
- gnc_price_get_value(price),
- GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- }
+
+ price_value = gnc_numeric_invert(gnc_price_get_value(price));
}
if (price)
@@ -1567,9 +1560,10 @@ create_price(XferDialog *xferData, Timespec ts)
return;
}
if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
- value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
- PRECISION, GNC_HOW_DENOM_REDUCE);
-
+ {
+ value = gnc_numeric_invert(value);
+ value = gnc_numeric_convert(value, PRECISION, GNC_HOW_DENOM_REDUCE);
+ }
gnc_price_begin_edit (price);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
@@ -1788,10 +1782,9 @@ gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData)
prc = gnc_pricedb_lookup_latest (xferData->pricedb, to, from);
if (prc)
{
- rate = gnc_numeric_div (gnc_numeric_create (1, 1), gnc_price_get_value (prc),
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
-
gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), rate);
+/* FIXME: We probably want to swap the result price's to and from, not invert the price. */
+ rate = gnc_numeric_invert(gnc_price_get_value (prc));
gnc_price_unref (prc);
have_price = TRUE;
}
@@ -2397,9 +2390,9 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_numeric rate = xaccTransGetAccountConvRate(txn, reg_acc);
/* XXX: should we tell the user we've done the conversion? */
- amount = gnc_numeric_div(
- amount, rate,
- gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
+ amount = gnc_numeric_div(amount, rate,
+ gnc_commodity_get_fraction(txn_cur),
+ GNC_HOW_DENOM_REDUCE);
}
/* enter the accounts */
@@ -2408,8 +2401,7 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
gnc_xfer_dialog_select_to_currency(xfer, txn_cur);
gnc_xfer_dialog_select_from_currency(xfer, xfer_com);
if (!gnc_numeric_zero_p(*exch_rate))
- *exch_rate = gnc_numeric_div(gnc_numeric_create(1, 1), *exch_rate,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ *exch_rate = gnc_numeric_invert(*exch_rate);
amount = gnc_numeric_neg(amount);
}
else
diff --git a/src/libqof/qof/gnc-numeric.c b/src/libqof/qof/gnc-numeric.c
index 693fdf9..44c6400 100644
--- a/src/libqof/qof/gnc-numeric.c
+++ b/src/libqof/qof/gnc-numeric.c
@@ -1149,7 +1149,26 @@ gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
return TRUE;
}
-
+gnc_numeric
+gnc_numeric_invert(gnc_numeric num)
+{
+ if (num.num == 0)
+ return gnc_numeric_zero();
+ if (num.denom > 0)
+ {
+ if (num.num < 0)
+ return gnc_numeric_create (-num.denom, -num.num);
+ return gnc_numeric_create (num.denom, num.num);
+ }
+ else /* Negative denominator means multiply instead of divide. */
+ {
+ int64_t mult = (num.num < 0 ? INT64_C(-1) : INT64_C(1));
+ qofint128 denom = mult128(-num.denom, mult * num.num);
+ if (denom.hi)
+ return gnc_numeric_error(GNC_ERROR_OVERFLOW);
+ return gnc_numeric_create (mult, denom.lo);
+ }
+}
/* *******************************************************************
* double_to_gnc_numeric
********************************************************************/
diff --git a/src/libqof/qof/gnc-numeric.h b/src/libqof/qof/gnc-numeric.h
index bcb70f1..89933c8 100644
--- a/src/libqof/qof/gnc-numeric.h
+++ b/src/libqof/qof/gnc-numeric.h
@@ -504,6 +504,13 @@ gnc_numeric gnc_numeric_reduce(gnc_numeric n);
********************************************************************/
gboolean gnc_numeric_to_decimal(gnc_numeric * a,
guint8 * max_decimal_places);
+
+/** Invert a gnc_numeric.
+ * Much faster than dividing 1 by it.
+ * @param num The number to be inverted
+ * @return a gnc_numeric that is the inverse of num
+ */
+gnc_numeric gnc_numeric_invert (gnc_numeric num);
/** @} */
/** @name GValue
commit be5b9f2b84a1ba51e8501e6aea2f0451ca833bb9
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 28 18:40:01 2015 +0100
Use price_value when referring to a gnc_numeric.
Price and prc are for gnc_price*.
For clarity.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index dbe76b4..174ff7a 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -180,7 +180,7 @@ void gnc_xfer_dialog_close_cb(GtkDialog *dialog, gpointer data);
/** Implementations **********************************************/
static gnc_numeric
-gnc_xfer_dialog_compute_price (XferDialog *xferData)
+gnc_xfer_dialog_compute_price_value (XferDialog *xferData)
{
gnc_numeric from_amt, to_amt;
g_return_val_if_fail (xferData != NULL, gnc_numeric_error (GNC_ERROR_ARG));
@@ -196,7 +196,7 @@ static void
gnc_xfer_dialog_update_price (XferDialog *xferData)
{
GNCPrice *prc;
- gnc_numeric price;
+ gnc_numeric price_value;
Timespec date;
gnc_commodity *from = xferData->from_commodity;
gnc_commodity *to = xferData->to_commodity;
@@ -245,22 +245,22 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
return;
/* grab the price from the pricedb */
- price = gnc_price_get_value (prc);
+ price_value = gnc_price_get_value (prc);
if (reverse)
{
PINFO("Found reverse price: 1 %s = %f %s", gnc_commodity_get_mnemonic(to),
- gnc_numeric_to_double(price), gnc_commodity_get_mnemonic(from));
- price = gnc_numeric_div (gnc_numeric_create (1, 1), price,
+ gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(from));
+ price_value = gnc_numeric_div (gnc_numeric_create (1, 1), price_value,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
}
else
{
PINFO("Found price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(price), gnc_commodity_get_mnemonic(to));
+ gnc_numeric_to_double(price_value), gnc_commodity_get_mnemonic(to));
}
/* and set the price entry */
- gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit), price);
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->price_edit), price_value);
/* And then update the to_amount */
gnc_xfer_update_to_amount (xferData);
@@ -309,7 +309,7 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
{
gnc_numeric from_rate;
gnc_numeric to_rate;
- gnc_numeric price;
+ gnc_numeric price_value;
if (!currency_active)
{
@@ -339,9 +339,9 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
if (gnc_numeric_zero_p (from_rate) || gnc_numeric_zero_p (to_rate))
gnc_xfer_dialog_update_price (xferData);
- price = gnc_numeric_div (to_rate, from_rate, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ price_value = gnc_numeric_div (to_rate, from_rate, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(xferData->price_edit), price);
+ gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(xferData->price_edit), price_value);
gnc_xfer_update_to_amount (xferData);
}
@@ -938,7 +938,7 @@ static void
gnc_xfer_update_to_amount (XferDialog *xferData)
{
GNCAmountEdit *amount_edit, *price_edit, *to_amount_edit;
- gnc_numeric price, to_amount;
+ gnc_numeric price_value, to_amount;
Account *account;
int scu = 0;
@@ -961,11 +961,11 @@ gnc_xfer_update_to_amount (XferDialog *xferData)
/* Determine the amount to transfer. */
if (!gnc_amount_edit_evaluate(price_edit) ||
- gnc_numeric_zero_p(price = gnc_amount_edit_get_amount(price_edit)))
+ gnc_numeric_zero_p(price_value = gnc_amount_edit_get_amount(price_edit)))
to_amount = gnc_numeric_zero();
else
to_amount = gnc_numeric_mul(gnc_amount_edit_get_amount(amount_edit),
- price, scu, GNC_HOW_RND_ROUND_HALF_UP);
+ price_value, scu, GNC_HOW_RND_ROUND_HALF_UP);
/* Update the dialog. */
gnc_amount_edit_set_amount(to_amount_edit, to_amount);
@@ -1004,7 +1004,7 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
gpointer data)
{
XferDialog *xferData = data;
- gnc_numeric price;
+ gnc_numeric price_value;
Account *account;
account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
@@ -1013,9 +1013,11 @@ gnc_xfer_to_amount_update_cb(GtkWidget *widget, GdkEventFocus *event,
gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit));
- price = gnc_xfer_dialog_compute_price(xferData);
- price = gnc_numeric_convert (price, PRECISION, GNC_HOW_RND_ROUND_HALF_UP);
- gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit), price);
+ price_value = gnc_xfer_dialog_compute_price_value(xferData);
+ price_value = gnc_numeric_convert (price_value, PRECISION,
+ GNC_HOW_RND_ROUND_HALF_UP);
+ gnc_amount_edit_set_amount(GNC_AMOUNT_EDIT(xferData->price_edit),
+ price_value);
gnc_xfer_dialog_update_conv_info(xferData);
return FALSE;
@@ -1657,7 +1659,7 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
if (xferData->exch_rate)
{
- gnc_numeric price;
+ gnc_numeric price_value;
/* If we've got the price-button set, then make sure we update the
* to-amount before we use it.
@@ -1665,8 +1667,8 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xferData->price_radio)))
gnc_xfer_update_to_amount(xferData);
- price = gnc_xfer_dialog_compute_price(xferData);
- *(xferData->exch_rate) = gnc_numeric_abs(price);
+ price_value = gnc_xfer_dialog_compute_price_value(xferData);
+ *(xferData->exch_rate) = gnc_numeric_abs(price_value);
}
else
create_transaction (xferData, &ts, from_account, to_account,
commit 9c2813acb66a2070e026d6e4d710aafcb2822adc
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Aug 25 11:17:07 2015 +0100
Price-quotes: Modify quotes on same day instead of creating new ones.
We can use only one per day so no point in keeping a bunch of them.
Finance::Quote prices always overwrite user prices.
diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm
index 7daacd0..c6a2405 100644
--- a/src/scm/price-quotes.scm
+++ b/src/scm/price-quotes.scm
@@ -370,7 +370,11 @@
(string? currency-str)
(gnc-commodity-table-lookup commodity-table
"ISO4217"
- (string-upcase currency-str)))))
+ (string-upcase currency-str))))
+ (pricedb (gnc-pricedb-get-db book))
+ (saved-price #f)
+ (commodity-str (gnc-commodity-get-printname commodity))
+ )
(or-map (lambda (price-sym)
(let ((p (assq-ref quote-data price-sym)))
@@ -403,27 +407,44 @@
(if (not (and commodity currency gnc-time price price-type))
(string-append
currency-str ":" (gnc-commodity-get-mnemonic commodity))
- (let ((gnc-price (gnc-price-create book)))
- (if (not gnc-price)
- (string-append
- currency-str ":" (gnc-commodity-get-mnemonic commodity))
- (begin
- (gnc-price-begin-edit gnc-price)
- (gnc-price-set-commodity gnc-price commodity)
- (gnc-price-set-currency gnc-price currency)
- (gnc-price-set-time gnc-price gnc-time)
- (gnc-price-set-source gnc-price "Finance::Quote")
- (gnc-price-set-typestr gnc-price price-type)
- (gnc-price-set-value gnc-price price)
- (gnc-price-commit-edit gnc-price)
- gnc-price))))))
+ (begin
+ (set! saved-price (gnc-pricedb-lookup-day pricedb
+ commodity currency
+ gnc-time))
+ (if (not (null? saved-price))
+ (begin
+ (gnc-price-begin-edit saved-price)
+ (gnc-price-set-time saved-price gnc-time)
+ (gnc-price-set-source saved-price "Finance::Quote")
+ (gnc-price-set-typestr saved-price price-type)
+ (gnc-price-set-value saved-price price)
+ (gnc-price-commit-edit saved-price)
+ #f)
+ (let ((gnc-price (gnc-price-create book)))
+ (if (not gnc-price)
+ (string-append
+ currency-str ":" (gnc-commodity-get-mnemonic commodity))
+ (begin
+ (gnc-price-begin-edit gnc-price)
+ (gnc-price-set-commodity gnc-price commodity)
+ (gnc-price-set-currency gnc-price currency)
+ (gnc-price-set-time gnc-price gnc-time)
+ (gnc-price-set-source gnc-price "Finance::Quote")
+ (gnc-price-set-typestr gnc-price price-type)
+ (gnc-price-set-value gnc-price price)
+ (gnc-price-commit-edit gnc-price)
+ gnc-price)))))
+ )))
(define (book-add-prices! book prices)
(let ((pricedb (gnc-pricedb-get-db book)))
(for-each
(lambda (price)
- (gnc-pricedb-add-price pricedb price)
- (gnc-price-unref price))
+ (if price
+ (begin
+ (gnc-pricedb-add-price pricedb price)
+ (gnc-price-unref price)
+ #f)))
prices)))
;; FIXME: uses of gnc:warn in here need to be cleaned up. Right
commit 966789374d15838820a60de36d3d7b18f33828ce
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 23 12:17:23 2015 +0100
Edit split-based prices instead of adding.
For split-register and xfer-dialog generated prices if there's an existing
non-FQ price for the day, change it. If there's an F::Q quote for the day,
do nothing. Only add a price if there isn't one for the from/to
combination.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index bacbeba..dbe76b4 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -86,7 +86,7 @@ struct _xferDialog
gnc_commodity *to_commodity;
QuickFill *qf; /* Quickfill on transfer descriptions,
- defaults to matching on the "From" account. */
+ defaults to matching on the "From" account. */
XferDirection quickfill; /* direction match on the account instead. */
@@ -1549,26 +1549,46 @@ create_price(XferDialog *xferData, Timespec ts)
}
}
- if (price && gnc_numeric_equal(value, price_value))
- {
- PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to));
- }
- else
+ if (price)
{
- price = gnc_price_create (xferData->book);
+ if (gnc_numeric_equal(value, price_value))
+ {
+ PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
+ gnc_commodity_get_mnemonic(to));
+ gnc_price_unref (price);
+ return;
+ }
+ if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ {
+ PINFO("Existing price is from Finance::Quote, so won't supersede.");
+ gnc_price_unref (price);
+ return;
+ }
+ if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
+ PRECISION, GNC_HOW_DENOM_REDUCE);
+
gnc_price_begin_edit (price);
- gnc_price_set_commodity (price, from);
- gnc_price_set_currency (price, to);
gnc_price_set_time (price, ts);
gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
gnc_price_set_value (price, value);
- gnc_pricedb_add_price (xferData->pricedb, price);
gnc_price_commit_edit (price);
- PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
+ PINFO("Modified price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
+ gnc_price_unref (price);
+ return;
}
-
+ price = gnc_price_create (xferData->book);
+ gnc_price_begin_edit (price);
+ gnc_price_set_commodity (price, from);
+ gnc_price_set_currency (price, to);
+ gnc_price_set_time (price, ts);
+ gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_value (price, value);
+ gnc_pricedb_add_price (xferData->pricedb, price);
+ gnc_price_commit_edit (price);
+ PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
+ gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
gnc_price_unref (price);
}
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 119a459..aef5c6f 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -64,6 +64,7 @@ static QofLogModule log_module = GNC_MOD_LEDGER;
static CursorClass copied_class = CURSOR_CLASS_NONE;
static SCM copied_item = SCM_UNDEFINED;
static GncGUID copied_leader_guid;
+static const int PRECISION = 1000000;
/** static prototypes *****************************************************/
@@ -2078,9 +2079,31 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
GNC_HOW_DENOM_REDUCE);
}
}
-
- if (price && gnc_numeric_equal(value, price_value))
+ if (price)
+ {
+ if (gnc_numeric_equal(value, price_value))
+ {
+ gnc_price_unref (price);
+ return;
+ }
+ if (strcmp (gnc_price_get_source(price), PRICE_SOURCE_FQ) == 0)
+ {
+ gnc_price_unref(price);
+ return;
+ }
+ if (!gnc_numeric_eq(price_value, gnc_price_get_value(price)))
+ value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
+ PRECISION, GNC_HOW_DENOM_REDUCE);
+
+ gnc_price_begin_edit (price);
+ gnc_price_set_time (price, ts);
+ gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
+ gnc_price_set_value (price, value);
+ gnc_price_commit_edit (price);
+ gnc_price_unref (price);
return;
+ }
+
price = gnc_price_create (book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, comm);
@@ -2566,7 +2589,7 @@ gnc_split_register_config_cells (SplitRegister *reg)
/* Use 6 decimal places for prices and "exchange rates" */
gnc_price_cell_set_fraction
((PriceCell *)
- gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL), 1000000);
+ gnc_table_layout_get_cell (reg->table->layout, PRIC_CELL), PRECISION);
/* Initialize shares and share balance cells */
gnc_price_cell_set_print_info
commit 5e609dac0d2b4c1a7ec59dfff675c620fb734a95
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 23 11:44:24 2015 +0100
Check for an existing price before adding one in split_reg.
To make the behavior the same as in xfer_dialog.
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index fc4f587..119a459 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2051,8 +2051,9 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_commodity *comm = xaccAccountGetCommodity (account);
gnc_commodity *curr = xaccTransGetCurrency (trans);
GNCPrice *price;
+ gnc_numeric price_value;
Timespec ts;
- BasicCell *cell;
+ BasicCell *cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
/* Only record the price for account types that don't have a
* "rate" cell. They'll get handled later by
@@ -2060,8 +2061,26 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
*/
if (gnc_split_reg_has_rate_cell (reg->type))
return;
- cell = gnc_table_layout_get_cell (reg->table->layout, DATE_CELL);
gnc_date_cell_get_date ((DateCell*)cell, &ts);
+ price = gnc_pricedb_lookup_day (pricedb, comm, curr, ts);
+ if (price)
+ {
+ price_value = gnc_price_get_value(price);
+ }
+ else
+ {
+ price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
+ if (price)
+ {
+ price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
+ gnc_price_get_value(price),
+ GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ }
+ }
+
+ if (price && gnc_numeric_equal(value, price_value))
+ return;
price = gnc_price_create (book);
gnc_price_begin_edit (price);
gnc_price_set_commodity (price, comm);
commit c4082524cbc943562d37145cd5b9b142f0bb2f9c
Author: John Ralls <jralls at ceridwen.us>
Date: Sun Aug 23 11:06:14 2015 +0100
In the transfer dialog use the price_edit value for the saved price.
Instead of computing it separately and differently from to_amt and from_amt.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 087b2dd..bacbeba 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1524,16 +1524,7 @@ create_price(XferDialog *xferData, Timespec ts)
if (gnc_is_euro_currency (from) && gnc_is_euro_currency (to))
return;
- from_amt =
- gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
- to_amt =
- gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
-
- /* compute the price -- maybe we need to swap? */
- value = gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- value = gnc_numeric_abs (value);
-
+ value = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->price_edit));
/* Try to be consistent about how quotes are installed. */
if (from == gnc_default_currency() ||
((to != gnc_default_currency()) &&
@@ -1558,20 +1549,7 @@ create_price(XferDialog *xferData, Timespec ts)
}
}
- /* See if we found a good enough price */
- if (price)
- {
- int scu = gnc_commodity_get_fraction (to);
- if (!gnc_numeric_equal (gnc_numeric_mul (from_amt, price_value,
- scu, GNC_HOW_RND_ROUND_HALF_UP),
- to_amt))
- {
- gnc_price_unref (price);
- price = NULL;
- }
- }
-
- if (price)
+ if (price && gnc_numeric_equal(value, price_value))
{
PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to));
commit ca447fc0473269fa5f54c13c817d290ea0de275d
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 22 10:48:24 2015 +0100
Fix up whitespace in dialog-transfer.c.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index 50c1367..087b2dd 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -69,61 +69,60 @@ static QofLogModule log_module = GNC_MOD_GUI;
struct _xferDialog
{
- GtkWidget * dialog;
-
- GtkWidget * amount_edit;
- GtkWidget * date_entry;
- GtkWidget * num_entry;
- GtkWidget * description_entry;
- GtkWidget * memo_entry;
- GtkWidget * conv_forward;
- GtkWidget * conv_reverse;
-
- GtkWidget * from_window;
+ GtkWidget *dialog;
+ GtkWidget *amount_edit;
+ GtkWidget *date_entry;
+ GtkWidget *num_entry;
+ GtkWidget *description_entry;
+ GtkWidget *memo_entry;
+ GtkWidget *conv_forward;
+ GtkWidget *conv_reverse;
+
+ GtkWidget *from_window;
GtkTreeView * from_tree_view;
- gnc_commodity * from_commodity;
- GtkWidget * to_window;
- GtkTreeView * to_tree_view;
- gnc_commodity * to_commodity;
+ gnc_commodity *from_commodity;
+ GtkWidget *to_window;
+ GtkTreeView *to_tree_view;
+ gnc_commodity *to_commodity;
- QuickFill * qf; /* Quickfill on transfer descriptions,
- defaults to matching on the "From" account. */
+ QuickFill *qf; /* Quickfill on transfer descriptions,
+ defaults to matching on the "From" account. */
- XferDirection quickfill; /* direction match on the account instead. */
+ XferDirection quickfill; /* direction match on the account instead. */
/* stored data for the description quickfill selection function */
gint desc_start_selection;
gint desc_end_selection;
guint desc_selection_source_id;
- GtkWidget * transferinfo_label;
+ GtkWidget *transferinfo_label;
- GtkWidget * from_transfer_label;
- GtkWidget * to_transfer_label;
+ GtkWidget *from_transfer_label;
+ GtkWidget *to_transfer_label;
- GtkWidget * from_currency_label;
- GtkWidget * to_currency_label;
+ GtkWidget *from_currency_label;
+ GtkWidget *to_currency_label;
- GtkWidget * from_show_button;
- GtkWidget * to_show_button;
+ GtkWidget *from_show_button;
+ GtkWidget *to_show_button;
- GtkWidget * curr_xfer_table;
+ GtkWidget *curr_xfer_table;
- GtkWidget * price_edit;
- GtkWidget * to_amount_edit;
+ GtkWidget *price_edit;
+ GtkWidget *to_amount_edit;
- GtkWidget * price_radio;
- GtkWidget * amount_radio;
+ GtkWidget *price_radio;
+ GtkWidget *amount_radio;
- GtkWidget * fetch_button;
+ GtkWidget *fetch_button;
- QofBook * book;
- GNCPriceDB * pricedb;
+ QofBook *book;
+ GNCPriceDB *pricedb;
/* Where to store the "exchange_rate" at exit (in lieu of
* creating a transaction)
*/
- gnc_numeric * exch_rate;
+ gnc_numeric *exch_rate;
/* Callback function to notify of the newly created Transaction */
gnc_xfer_dialog_cb transaction_cb;
@@ -157,10 +156,10 @@ static void gnc_xfer_update_to_amount (XferDialog *xferData);
static void gnc_xfer_dialog_update_conv_info(XferDialog *xferData);
static Account *gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
- XferDirection direction);
+ XferDirection direction);
static void gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
- Account *account,
- XferDirection direction);
+ Account *account,
+ XferDirection direction);
void gnc_xfer_description_insert_cb(GtkEditable *editable,
const gchar *insert_text,
@@ -168,11 +167,11 @@ void gnc_xfer_description_insert_cb(GtkEditable *editable,
gint *start_pos,
XferDialog *xferData);
gboolean gnc_xfer_description_key_press_cb( GtkEntry *entry,
- GdkEventKey *event,
- XferDialog *xferData );
+ GdkEventKey *event,
+ XferDialog *xferData );
void gnc_xfer_dialog_fetch (GtkButton *button, XferDialog *xferData);
gboolean gnc_xfer_dialog_inc_exp_filter_func (Account *account,
- gpointer data);
+ gpointer data);
void price_amount_radio_toggled_cb(GtkToggleButton *togglebutton, gpointer data);
void gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data);
@@ -231,14 +230,14 @@ gnc_xfer_dialog_update_price (XferDialog *xferData)
{
/* Didn't find one on the same day, look for nearest in time */
prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, from,
- to, date);
+ to, date);
reverse = FALSE;
}
if (!prc)
{
prc = gnc_pricedb_lookup_nearest_in_time (xferData->pricedb, to,
- from, date);
+ from, date);
reverse = TRUE;
}
@@ -328,7 +327,7 @@ gnc_xfer_dialog_set_price_auto (XferDialog *xferData,
}
if (!gnc_is_euro_currency (from_currency) ||
- !gnc_is_euro_currency (to_currency))
+ !gnc_is_euro_currency (to_currency))
{
gnc_xfer_dialog_update_price (xferData);
return;
@@ -363,8 +362,8 @@ gnc_xfer_dialog_curr_acct_activate(XferDialog *xferData)
curr_active = (xferData->exch_rate ||
((from_account != NULL) && (to_account != NULL)))
- && !gnc_commodity_equiv(xferData->from_commodity,
- xferData->to_commodity);
+ && !gnc_commodity_equiv(xferData->from_commodity,
+ xferData->to_commodity);
gtk_widget_set_sensitive(xferData->curr_xfer_table, curr_active);
gtk_widget_set_sensitive(xferData->price_edit,
@@ -441,7 +440,7 @@ gnc_xfer_dialog_reload_quickfill( XferDialog *xferData )
static void
gnc_xfer_dialog_from_tree_selection_changed_cb (GtkTreeSelection *selection,
- gpointer data)
+ gpointer data)
{
XferDialog *xferData = data;
GNCPrintAmountInfo print_info;
@@ -541,7 +540,7 @@ gnc_xfer_dialog_fill_tree_view(XferDialog *xferData,
g_return_if_fail (xferData != NULL);
use_accounting_labels = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL,
- GNC_PREF_ACCOUNTING_LABELS);
+ GNC_PREF_ACCOUNTING_LABELS);
/* In "normal" mode (non accounting terms) the account where the
* money comes from is displayed on the left side and the account
@@ -557,20 +556,20 @@ gnc_xfer_dialog_fill_tree_view(XferDialog *xferData,
if (use_accounting_labels)
{
button = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "left_show_button" : "right_show_button"));
+ (direction == XFER_DIALOG_TO) ?
+ "left_show_button" : "right_show_button"));
scroll_win = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "left_trans_window" : "right_trans_window"));
+ (direction == XFER_DIALOG_TO) ?
+ "left_trans_window" : "right_trans_window"));
}
else
{
button = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "right_show_button" : "left_show_button"));
+ (direction == XFER_DIALOG_TO) ?
+ "right_show_button" : "left_show_button"));
scroll_win = GTK_WIDGET(gtk_builder_get_object (builder,
- (direction == XFER_DIALOG_TO) ?
- "right_trans_window" : "left_trans_window"));
+ (direction == XFER_DIALOG_TO) ?
+ "right_trans_window" : "left_trans_window"));
}
@@ -686,7 +685,7 @@ gnc_xfer_dialog_quickfill( XferDialog *xferData )
*/
if ( gnc_numeric_zero_p(
- gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit))))
+ gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit))))
{
gnc_numeric amt;
DEBUG("updating amount");
@@ -718,7 +717,7 @@ gnc_xfer_dialog_quickfill( XferDialog *xferData )
* and select that account in the appropriate account tree.
*/
if ( ( other = xaccSplitGetOtherSplit( split ) ) &&
- ( other_acct = xaccSplitGetAccount( other ) ) )
+ ( other_acct = xaccSplitGetAccount( other ) ) )
{
GNCAccountType other_type;
GtkWidget *other_button;
@@ -804,8 +803,8 @@ gnc_xfer_description_insert_cb(GtkEditable *editable,
g_free(prefix);
if ((match = gnc_quickfill_get_string_match(xferData->qf, new_text))
- && (match_str = gnc_quickfill_string(match))
- && ((match_str_len = strlen(match_str)) > new_text_len))
+ && (match_str = gnc_quickfill_string(match))
+ && ((match_str_len = strlen(match_str)) > new_text_len))
{
g_signal_handlers_block_matched (G_OBJECT (editable),
G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, xferData);
@@ -829,7 +828,7 @@ gnc_xfer_description_insert_cb(GtkEditable *editable,
xferData->desc_start_selection = *start_pos;
xferData->desc_end_selection = -1;
xferData->desc_selection_source_id = g_idle_add(idle_select_region,
- xferData);
+ xferData);
}
g_free(new_text);
}
@@ -954,7 +953,7 @@ gnc_xfer_update_to_amount (XferDialog *xferData)
account = gnc_transfer_dialog_get_selected_account(xferData, XFER_DIALOG_TO);
if (account == NULL)
account = gnc_transfer_dialog_get_selected_account(xferData,
- XFER_DIALOG_FROM);
+ XFER_DIALOG_FROM);
if (account != NULL)
scu = xaccAccountGetCommoditySCU(account);
else if (xferData->to_commodity != NULL)
@@ -962,7 +961,7 @@ gnc_xfer_update_to_amount (XferDialog *xferData)
/* Determine the amount to transfer. */
if (!gnc_amount_edit_evaluate(price_edit) ||
- gnc_numeric_zero_p(price = gnc_amount_edit_get_amount(price_edit)))
+ gnc_numeric_zero_p(price = gnc_amount_edit_get_amount(price_edit)))
to_amount = gnc_numeric_zero();
else
to_amount = gnc_numeric_mul(gnc_amount_edit_get_amount(amount_edit),
@@ -1099,18 +1098,18 @@ gnc_xfer_dialog_lock_account_tree(XferDialog *xferData,
switch (direction)
{
- case XFER_DIALOG_FROM:
- tree_view = xferData->from_tree_view;
- scroll_win = xferData->from_window;
- show_button = xferData->from_show_button;
- break;
- case XFER_DIALOG_TO:
- tree_view = xferData->to_tree_view;
- scroll_win = xferData->to_window;
- show_button = xferData->to_show_button;
- break;
- default:
- return;
+ case XFER_DIALOG_FROM:
+ tree_view = xferData->from_tree_view;
+ scroll_win = xferData->from_window;
+ show_button = xferData->from_show_button;
+ break;
+ case XFER_DIALOG_TO:
+ tree_view = xferData->to_tree_view;
+ scroll_win = xferData->to_window;
+ show_button = xferData->to_show_button;
+ break;
+ default:
+ return;
}
gtk_widget_set_sensitive( GTK_WIDGET(tree_view), FALSE );
@@ -1199,7 +1198,7 @@ gnc_xfer_dialog_is_exchange_dialog (XferDialog *xferData,
g_return_if_fail(xferData);
ENTER("xferData=%p, exch_rate=%p (%s)", xferData, exch_rate,
exch_rate == NULL ? "NULL" : xaccPrintAmount(*exch_rate,
- gnc_default_print_info(FALSE)));
+ gnc_default_print_info(FALSE)));
gtk_widget_set_sensitive (xferData->amount_edit, FALSE);
gtk_widget_set_sensitive (xferData->date_entry, FALSE);
@@ -1233,15 +1232,15 @@ gnc_xfer_dialog_set_amount(XferDialog *xferData, gnc_numeric amount)
return;
account = gnc_transfer_dialog_get_selected_account (xferData,
- XFER_DIALOG_FROM);
+ XFER_DIALOG_FROM);
if (account == NULL)
account = gnc_transfer_dialog_get_selected_account (xferData,
- XFER_DIALOG_TO);
+ XFER_DIALOG_TO);
gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (xferData->amount_edit), amount);
}
void gnc_xfer_dialog_set_amount_sensitive(XferDialog *xferData,
- gboolean is_sensitive)
+ gboolean is_sensitive)
{
g_assert(xferData);
gtk_widget_set_sensitive(gnc_amount_edit_gtk_entry(GNC_AMOUNT_EDIT (xferData->amount_edit)), is_sensitive);
@@ -1252,9 +1251,9 @@ gnc_xfer_dialog_set_fetch_sensitive (GtkWidget *fetch)
{
if (gnc_quote_source_fq_installed ())
{
- gtk_widget_set_sensitive (fetch, TRUE);
- gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote"));
- return;
+ gtk_widget_set_sensitive (fetch, TRUE);
+ gtk_widget_set_tooltip_text (fetch, _("Retrieve the current online quote"));
+ return;
}
gtk_widget_set_sensitive (fetch, FALSE);
gtk_widget_set_tooltip_text (fetch, _("Finance::Quote must be installed to enable this button."));
@@ -1509,7 +1508,7 @@ swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
from_amt = to_amt;
to_amt = tmp_amt;
*value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
}
static void
create_price(XferDialog *xferData, Timespec ts)
@@ -1809,7 +1808,7 @@ gnc_xfer_dialog_create(GtkWidget *parent, XferDialog *xferData)
gboolean use_accounting_labels;
use_accounting_labels = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL,
- GNC_PREF_ACCOUNTING_LABELS);
+ GNC_PREF_ACCOUNTING_LABELS);
ENTER(" ");
builder = gtk_builder_new();
@@ -2130,7 +2129,7 @@ gnc_xfer_dialog_set_to_account_label( XferDialog *xferData,
void
gnc_xfer_dialog_set_from_show_button_active( XferDialog *xferData,
- gboolean set_value )
+ gboolean set_value )
{
if ( xferData && xferData->from_show_button )
{
@@ -2141,7 +2140,7 @@ gnc_xfer_dialog_set_from_show_button_active( XferDialog *xferData,
void
gnc_xfer_dialog_set_to_show_button_active( XferDialog *xferData,
- gboolean set_value )
+ gboolean set_value )
{
if ( xferData && xferData->to_show_button )
{
@@ -2152,16 +2151,16 @@ gnc_xfer_dialog_set_to_show_button_active( XferDialog *xferData,
/* Add a button with a user-specified label and "clicked" callback */
void gnc_xfer_dialog_add_user_specified_button( XferDialog *xferData,
- const gchar *label,
- GCallback callback,
- gpointer user_data )
+ const gchar *label,
+ GCallback callback,
+ gpointer user_data )
{
if ( xferData && label && callback )
{
GtkBuilder *builder = g_object_get_data (G_OBJECT (xferData->dialog), "builder");
GtkWidget *button = gtk_button_new_with_label( label );
GtkWidget *box = GTK_WIDGET(gtk_builder_get_object (builder,
- "transfermain-vbox" ));
+ "transfermain-vbox" ));
gtk_box_pack_end( GTK_BOX(box), button, FALSE, FALSE, 0 );
g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (callback), user_data);
gtk_widget_show( button );
@@ -2169,7 +2168,7 @@ void gnc_xfer_dialog_add_user_specified_button( XferDialog *xferData,
}
void gnc_xfer_dialog_toggle_currency_table( XferDialog *xferData,
- gboolean show_table )
+ gboolean show_table )
{
if (xferData && xferData->curr_xfer_table)
{
@@ -2212,8 +2211,8 @@ gboolean gnc_xfer_dialog_run_until_done( XferDialog *xferData )
* that's bad mojo whole gtk_dialog_run is still in control.
*/
count = g_signal_handlers_disconnect_by_func(dialog,
- gnc_xfer_dialog_response_cb,
- xferData);
+ gnc_xfer_dialog_response_cb,
+ xferData);
g_assert(count == 1);
while ( TRUE )
@@ -2270,22 +2269,22 @@ gnc_xfer_dialog_quickfill_to_account(XferDialog *xferData,
static Account *
gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
- XferDirection direction)
+ XferDirection direction)
{
GtkTreeView *tree_view;
Account *account;
switch (direction)
{
- case XFER_DIALOG_FROM:
- tree_view = dialog->from_tree_view;
- break;
- case XFER_DIALOG_TO:
- tree_view = dialog->to_tree_view;
- break;
- default:
- g_assert_not_reached ();
- return NULL;
+ case XFER_DIALOG_FROM:
+ tree_view = dialog->from_tree_view;
+ break;
+ case XFER_DIALOG_TO:
+ tree_view = dialog->to_tree_view;
+ break;
+ default:
+ g_assert_not_reached ();
+ return NULL;
}
account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (tree_view));
@@ -2294,8 +2293,8 @@ gnc_transfer_dialog_get_selected_account (XferDialog *dialog,
static void
gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
- Account *account,
- XferDirection direction)
+ Account *account,
+ XferDirection direction)
{
GtkTreeView *tree_view;
GtkCheckButton *show_button;
@@ -2306,17 +2305,17 @@ gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
switch (direction)
{
- case XFER_DIALOG_FROM:
- tree_view = dialog->from_tree_view;
- show_button = GTK_CHECK_BUTTON (dialog->from_show_button);
- break;
- case XFER_DIALOG_TO:
- tree_view = dialog->to_tree_view;
- show_button = GTK_CHECK_BUTTON (dialog->to_show_button);
- break;
- default:
- g_assert_not_reached ();
- return;
+ case XFER_DIALOG_FROM:
+ tree_view = dialog->from_tree_view;
+ show_button = GTK_CHECK_BUTTON (dialog->from_show_button);
+ break;
+ case XFER_DIALOG_TO:
+ tree_view = dialog->to_tree_view;
+ show_button = GTK_CHECK_BUTTON (dialog->to_show_button);
+ break;
+ default:
+ g_assert_not_reached ();
+ return;
}
type = xaccAccountGetType (account);
@@ -2325,7 +2324,7 @@ gnc_transfer_dialog_set_selected_account (XferDialog *dialog,
(type == ACCT_TYPE_INCOME));
gnc_tree_view_account_set_selected_account (GNC_TREE_VIEW_ACCOUNT (tree_view),
- account);
+ account);
}
@@ -2399,8 +2398,8 @@ gboolean gnc_xfer_dialog_run_exchange_dialog(
/* XXX: should we tell the user we've done the conversion? */
amount = gnc_numeric_div(
- amount, rate,
- gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
+ amount, rate,
+ gnc_commodity_get_fraction(txn_cur), GNC_HOW_DENOM_REDUCE);
}
/* enter the accounts */
commit 85148cd23bf27ac12e4add9b3cdf59cb443c5889
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 22 10:44:00 2015 +0100
Refactor gnc_xfer_dialog_response_cb with several extract-functions.
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index aaa7a24..50c1367 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1353,24 +1353,257 @@ gnc_xfer_dialog_set_exchange_rate(XferDialog *xferData, gnc_numeric exchange_rat
gnc_xfer_update_to_amount (xferData);
}
+static gboolean
+check_accounts (XferDialog* xferData, Account* from_account,
+ Account* to_account)
+{
+ if ((from_account == NULL) || (to_account == NULL))
+ {
+ const char *message = _("You must specify an account to transfer from, "
+ "or to, or both, for this transaction. "
+ "Otherwise, it will not be recorded.");
+ gnc_error_dialog(xferData->dialog, "%s", message);
+ LEAVE("bad account");
+ return FALSE;
+ }
+
+ if (from_account == to_account)
+ {
+ const char *message = _("You can't transfer from and to the same "
+ "account!");
+ gnc_error_dialog(xferData->dialog, "%s", message);
+ LEAVE("same account");
+ return FALSE;
+ }
+
+ if (xaccAccountGetPlaceholder(from_account) ||
+ xaccAccountGetPlaceholder(to_account))
+ {
+ const char *placeholder_format =
+ _("The account %s does not allow transactions.");
+ char *name;
+
+ if (xaccAccountGetPlaceholder(from_account))
+ name = gnc_account_get_full_name(from_account);
+ else
+ name = gnc_account_get_full_name(to_account);
+ gnc_error_dialog(xferData->dialog, placeholder_format, name);
+ g_free(name);
+ LEAVE("placeholder");
+ return TRUE;
+ }
+
+ if (!gnc_commodity_is_iso (xferData->from_commodity))
+ {
+ const char *message =
+ _("You can't transfer from a non-currency account. "
+ "Try reversing the \"from\" and \"to\" accounts "
+ "and making the \"amount\" negative.");
+ gnc_error_dialog(xferData->dialog, "%s", message);
+ LEAVE("non-currency");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+check_edit(XferDialog *xferData)
+{
+ if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->price_edit)))
+ {
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(xferData->price_radio)))
+ {
+ gnc_parse_error_dialog (xferData, _("You must enter a valid price."));
+ LEAVE("invalid price");
+ return FALSE;
+ }
+ }
+
+ if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit)))
+ {
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(xferData->amount_radio)))
+ {
+ gnc_parse_error_dialog (xferData,
+ _("You must enter a valid `to' amount."));
+ LEAVE("invalid to amount");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void
+create_transaction(XferDialog *xferData, Timespec *ts,
+ Account *from_account, Account* to_account,
+ gnc_numeric amount, gnc_numeric to_amount)
+{
+ Transaction *trans;
+ Split *from_split;
+ Split *to_split;
+ const char *string;
+ /* Create the transaction */
+ trans = xaccMallocTransaction(xferData->book);
+
+ xaccTransBeginEdit(trans);
+
+ xaccTransSetCurrency(trans, xferData->from_commodity);
+ xaccTransSetDatePostedTS(trans, ts);
+
+ /* Trans-Num or Split-Action set with gnc_set_num_action below per book
+ * option */
+
+ string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
+ xaccTransSetDescription(trans, string);
+
+ /* create from split */
+ from_split = xaccMallocSplit(xferData->book);
+ xaccTransAppendSplit(trans, from_split);
+
+ /* create to split */
+ to_split = xaccMallocSplit(xferData->book);
+ xaccTransAppendSplit(trans, to_split);
+
+ xaccAccountBeginEdit(from_account);
+ xaccAccountInsertSplit(from_account, from_split);
+
+ xaccAccountBeginEdit(to_account);
+ xaccAccountInsertSplit(to_account, to_split);
+
+ xaccSplitSetBaseValue(from_split, gnc_numeric_neg (amount),
+ xferData->from_commodity);
+ xaccSplitSetBaseValue(to_split, amount, xferData->from_commodity);
+ xaccSplitSetBaseValue(to_split, to_amount, xferData->to_commodity);
+
+ /* Set the transaction number or split action field based on book option*/
+ string = gtk_entry_get_text(GTK_ENTRY(xferData->num_entry));
+ gnc_set_num_action (trans, from_split, string, NULL);
+
+ /* Set the memo fields */
+ string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
+ xaccSplitSetMemo(from_split, string);
+ xaccSplitSetMemo(to_split, string);
+
+ /* finish transaction */
+ xaccTransCommitEdit(trans);
+ xaccAccountCommitEdit(from_account);
+ xaccAccountCommitEdit(to_account);
+
+ /* If there is a registered callback handler that should be
+ notified of the newly created Transaction, call it now. */
+ if (xferData->transaction_cb)
+ xferData->transaction_cb(trans, xferData->transaction_user_data);
+}
+
+static void
+swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
+ gnc_numeric *from_amt, gnc_numeric *to_amt)
+{
+ gnc_commodity *tmp;
+ gnc_numeric *tmp_amt;
+ tmp = *from;
+ *from = *to;
+ *to = tmp;
+ tmp_amt = from_amt;
+ from_amt = to_amt;
+ to_amt = tmp_amt;
+ *value = gnc_numeric_div (gnc_numeric_create(1, 1), *value,
+ GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+}
+static void
+create_price(XferDialog *xferData, Timespec ts)
+{
+ gnc_commodity *from = xferData->from_commodity;
+ gnc_commodity *to = xferData->to_commodity;
+ GNCPrice *price;
+ gnc_numeric price_value;
+ gnc_numeric value;
+ gnc_numeric from_amt, to_amt;
+
+/* Bail in the unlikely event that both currencies have joined the Euro. */
+ if (gnc_is_euro_currency (from) && gnc_is_euro_currency (to))
+ return;
+
+ from_amt =
+ gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
+ to_amt =
+ gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
+
+ /* compute the price -- maybe we need to swap? */
+ value = gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ value = gnc_numeric_abs (value);
+
+ /* Try to be consistent about how quotes are installed. */
+ if (from == gnc_default_currency() ||
+ ((to != gnc_default_currency()) &&
+ (strcmp (gnc_commodity_get_mnemonic(from),
+ gnc_commodity_get_mnemonic(to)) < 0)))
+ swap_amount (&from, &to, &value, &from_amt, &to_amt);
+ /* First see if the closest entry on the same day has an equivalent rate */
+ price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
+ if (price)
+ {
+ price_value = gnc_price_get_value(price);
+ }
+ else
+ {
+ price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
+ if (price)
+ {
+ price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
+ gnc_price_get_value(price),
+ GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ }
+ }
+
+ /* See if we found a good enough price */
+ if (price)
+ {
+ int scu = gnc_commodity_get_fraction (to);
+ if (!gnc_numeric_equal (gnc_numeric_mul (from_amt, price_value,
+ scu, GNC_HOW_RND_ROUND_HALF_UP),
+ to_amt))
+ {
+ gnc_price_unref (price);
+ price = NULL;
+ }
+ }
+
+ if (price)
+ {
+ PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
+ gnc_commodity_get_mnemonic(to));
+ }
+ else
+ {
+ price = gnc_price_create (xferData->book);
+ gnc_price_begin_edit (price);
+ gnc_price_set_commodity (price, from);
+ gnc_price_set_currency (price, to);
+ gnc_price_set_time (price, ts);
+ gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
+ gnc_price_set_value (price, value);
+ gnc_pricedb_add_price (xferData->pricedb, price);
+ gnc_price_commit_edit (price);
+ PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
+ gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
+ }
+
+ gnc_price_unref (price);
+}
+
void
gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
{
XferDialog *xferData = data;
Account *to_account;
Account *from_account;
- gnc_commodity *from_commodity;
- gnc_commodity *to_commodity;
gnc_numeric amount, to_amount;
- const char *string;
Timespec ts;
- gboolean curr_trans;
-
- Transaction *trans;
- Split *from_split;
- Split *to_split;
-
g_return_if_fail (xferData != NULL);
ENTER(" ");
@@ -1390,54 +1623,9 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
from_account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_FROM);
to_account = gnc_transfer_dialog_get_selected_account (xferData, XFER_DIALOG_TO);
- if (xferData->exch_rate == NULL)
- {
- if ((from_account == NULL) || (to_account == NULL))
- {
- const char *message = _("You must specify an account to transfer from, "
- "or to, or both, for this transaction. "
- "Otherwise, it will not be recorded.");
- gnc_error_dialog(xferData->dialog, "%s", message);
- LEAVE("bad account");
- return;
- }
-
- if (from_account == to_account)
- {
- const char *message = _("You can't transfer from and to the same "
- "account!");
- gnc_error_dialog(xferData->dialog, "%s", message);
- LEAVE("same account");
- return;
- }
-
- if (xaccAccountGetPlaceholder(from_account) ||
- xaccAccountGetPlaceholder(to_account))
- {
- const char *placeholder_format =
- _("The account %s does not allow transactions.");
- char *name;
-
- if (xaccAccountGetPlaceholder(from_account))
- name = gnc_account_get_full_name(from_account);
- else
- name = gnc_account_get_full_name(to_account);
- gnc_error_dialog(xferData->dialog, placeholder_format, name);
- g_free(name);
- LEAVE("placeholder");
- return;
- }
-
- if (!gnc_commodity_is_iso (xferData->from_commodity))
- {
- const char *message = _("You can't transfer from a non-currency account. "
- "Try reversing the \"from\" and \"to\" accounts "
- "and making the \"amount\" negative.");
- gnc_error_dialog(xferData->dialog, "%s", message);
- LEAVE("non-currency");
- return;
- }
- }
+ if (xferData->exch_rate == NULL &&
+ !check_accounts(xferData, from_account, to_account))
+ return;
if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->amount_edit)))
{
@@ -1446,11 +1634,6 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
return;
}
- from_commodity = xferData->from_commodity;
- to_commodity = xferData->to_commodity;
-
- curr_trans = !gnc_commodity_equiv(from_commodity, to_commodity);
-
amount = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
if (gnc_numeric_zero_p (amount))
@@ -1463,33 +1646,12 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
ts = gnc_date_edit_get_date_ts(GNC_DATE_EDIT(xferData->date_entry));
- if (curr_trans)
+ if (!gnc_commodity_equiv(xferData->from_commodity, xferData->to_commodity))
{
- if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->price_edit)))
- {
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(xferData->price_radio)))
- {
- gnc_parse_error_dialog (xferData, _("You must enter a valid price."));
- LEAVE("invalid price");
- return;
- }
- }
-
- if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (xferData->to_amount_edit)))
- {
- if (gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(xferData->amount_radio)))
- {
- gnc_parse_error_dialog (xferData,
- _("You must enter a valid `to' amount."));
- LEAVE("invalid to amount");
- return;
- }
- }
-
+ if (!check_edit(xferData))
+ return;
to_amount = gnc_amount_edit_get_amount
- (GNC_AMOUNT_EDIT(xferData->to_amount_edit));
+ (GNC_AMOUNT_EDIT(xferData->to_amount_edit));
}
else
to_amount = amount;
@@ -1510,156 +1672,12 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
*(xferData->exch_rate) = gnc_numeric_abs(price);
}
else
- {
- /* Create the transaction */
- trans = xaccMallocTransaction(xferData->book);
-
- xaccTransBeginEdit(trans);
-
- xaccTransSetCurrency(trans, from_commodity);
- xaccTransSetDatePostedTS(trans, &ts);
-
- /* Trans-Num or Split-Action set with gnc_set_num_action below per book
- * option */
-
- string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
- xaccTransSetDescription(trans, string);
-
- /* create from split */
- from_split = xaccMallocSplit(xferData->book);
- xaccTransAppendSplit(trans, from_split);
-
- /* create to split */
- to_split = xaccMallocSplit(xferData->book);
- xaccTransAppendSplit(trans, to_split);
-
- xaccAccountBeginEdit(from_account);
- xaccAccountInsertSplit(from_account, from_split);
-
- xaccAccountBeginEdit(to_account);
- xaccAccountInsertSplit(to_account, to_split);
-
- xaccSplitSetBaseValue(from_split, gnc_numeric_neg (amount), from_commodity);
- xaccSplitSetBaseValue(to_split, amount, from_commodity);
- xaccSplitSetBaseValue(to_split, to_amount, to_commodity);
-
- /* Set the transaction number or split action field based on book option*/
- string = gtk_entry_get_text(GTK_ENTRY(xferData->num_entry));
- gnc_set_num_action (trans, from_split, string, NULL);
-
- /* Set the memo fields */
- string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
- xaccSplitSetMemo(from_split, string);
- xaccSplitSetMemo(to_split, string);
-
- /* finish transaction */
- xaccTransCommitEdit(trans);
- xaccAccountCommitEdit(from_account);
- xaccAccountCommitEdit(to_account);
-
- /* If there is a registered callback handler that should be
- notified of the newly created Transaction, call it now. */
- if (xferData->transaction_cb)
- xferData->transaction_cb(trans, xferData->transaction_user_data);
- }
-
+ create_transaction (xferData, &ts, from_account, to_account,
+ amount, to_amount);
/* try to save this to the pricedb */
- if (xferData->pricedb)
- {
- gnc_commodity *from = xferData->from_commodity;
- gnc_commodity *to = xferData->to_commodity;
-
- /* only continue if the currencies are DIFFERENT and are
- * not both euroland currencies
- */
- if (!gnc_commodity_equal (from, to) &&
- !(gnc_is_euro_currency (from) && gnc_is_euro_currency (to)))
- {
- GNCPrice *price;
- gnc_numeric price_value;
- gnc_numeric value;
- gnc_commodity *tmp;
- gnc_numeric from_amt, to_amt;
- gnc_numeric tmp_amt;
-
- from_amt = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->amount_edit));
- to_amt = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->to_amount_edit));
-
- /* compute the price -- maybe we need to swap? */
-
- value = gnc_numeric_div(to_amt, from_amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- value = gnc_numeric_abs (value);
-
- /* Try to be consistent about how quotes are installed. */
- if (from == gnc_default_currency() ||
- ((to != gnc_default_currency()) &&
- (strcmp (gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to)) < 0)))
- {
- tmp = from;
- from = to;
- to = tmp;
- tmp_amt = from_amt;
- from_amt = to_amt;
- to_amt = tmp_amt;
- value = gnc_numeric_div (gnc_numeric_create(1, 1), value,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- }
-
- /* First see if the closest entry on the same day has an equivalent rate */
- price = gnc_pricedb_lookup_day (xferData->pricedb, from, to, ts);
- if (price)
- {
- price_value = gnc_price_get_value(price);
- }
- else
- {
- price = gnc_pricedb_lookup_day (xferData->pricedb, to, from, ts);
- if (price)
- {
- price_value = gnc_numeric_div (gnc_numeric_create(1, 1),
- gnc_price_get_value(price),
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- }
- }
-
- /* See if we found a good enough price */
- if (price)
- {
- int scu = gnc_commodity_get_fraction (to);
- if (!gnc_numeric_equal (gnc_numeric_mul (from_amt, price_value,
- scu, GNC_HOW_RND_ROUND_HALF_UP),
- to_amt))
- {
- gnc_price_unref (price);
- price = NULL;
- }
- }
-
- if (price)
- {
- PINFO("Found price for %s in %s", gnc_commodity_get_mnemonic(from),
- gnc_commodity_get_mnemonic(to));
- }
- else
- {
- price = gnc_price_create (xferData->book);
- gnc_price_begin_edit (price);
- gnc_price_set_commodity (price, from);
- gnc_price_set_currency (price, to);
- gnc_price_set_time (price, ts);
- gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
- gnc_price_set_value (price, value);
- gnc_pricedb_add_price (xferData->pricedb, price);
- gnc_price_commit_edit (price);
- PINFO("Created price: 1 %s = %f %s", gnc_commodity_get_mnemonic(from),
- gnc_numeric_to_double(value), gnc_commodity_get_mnemonic(to));
- }
-
- gnc_price_unref (price);
- }
- }
-
+ if (xferData->pricedb && !gnc_commodity_equal (xferData->from_commodity,
+ xferData->to_commodity))
+ create_price(xferData, ts);
/* Refresh everything */
gnc_resume_gui_refresh ();
commit e94622c9e32071598723862d989f76765e79c4cc
Author: John Ralls <jralls at ceridwen.us>
Date: Sat Aug 22 09:17:49 2015 +0100
Don't store prices of source invoice.
They're intended to be temporary, for creating splits. They're also already
stored from the transfer dialog.
diff --git a/src/backend/sql/gnc-price-sql.c b/src/backend/sql/gnc-price-sql.c
index d7e6b70..8729c91 100644
--- a/src/backend/sql/gnc-price-sql.c
+++ b/src/backend/sql/gnc-price-sql.c
@@ -203,7 +203,7 @@ write_price( GNCPrice* p, gpointer data )
g_return_val_if_fail( p != NULL, FALSE );
g_return_val_if_fail( data != NULL, FALSE );
- if ( s->is_ok )
+ if ( s->is_ok && strcmp(gnc_price_get_source(p), PRICE_SOURCE_INVOICE) != 0)
{
s->is_ok = save_price( s->be, QOF_INSTANCE(p) );
}
commit ab535fb1005cbda85585cbd91a272e370a82d112
Author: John Ralls <jralls at ceridwen.us>
Date: Fri Aug 21 15:54:58 2015 +0100
Replace the price source and type strings with defines.
diff --git a/src/business/business-gnome/dialog-invoice.c b/src/business/business-gnome/dialog-invoice.c
index e840742..10c4d75 100644
--- a/src/business/business-gnome/dialog-invoice.c
+++ b/src/business/business-gnome/dialog-invoice.c
@@ -901,11 +901,8 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
gnc_price_set_commodity (convprice, account_currency);
gnc_price_set_currency (convprice, gncInvoiceGetCurrency (invoice));
gnc_price_set_time (convprice, postdate);
- gnc_price_set_source (convprice, "user:invoice-post");
-
- /* Yes, magic strings are evil but I can't find any defined constants
- for this..*/
- gnc_price_set_typestr (convprice, "last");
+ gnc_price_set_source (convprice, PRICE_SOURCE_INVOICE);
+ gnc_price_set_typestr (convprice, PRICE_TYPE_LAST);
gnc_price_set_value (convprice, exch_rate);
gncInvoiceAddPrice(invoice, convprice);
gnc_price_commit_edit (convprice);
@@ -1702,7 +1699,7 @@ gnc_invoice_update_window (InvoiceWindow *iw, GtkWidget *widget)
}
/* Set the type label */
- gtk_label_set_text (GTK_LABEL(iw->type_label), iw->is_credit_note ? _("Credit Note")
+ gtk_label_set_text (GTK_LABEL(iw->type_label), iw->is_credit_note ? _("Credit Note")
: gtk_label_get_text (GTK_LABEL(iw->type_label)));
if (iw->owner_choice)
@@ -1820,14 +1817,14 @@ gnc_invoice_update_window (InvoiceWindow *iw, GtkWidget *widget)
gtk_widget_hide (hide);
hide = GTK_WIDGET (gtk_builder_get_object (iw->builder, "hide4"));
gtk_widget_hide (hide);
-
+
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "posted_label"));
gtk_widget_show (show);
gtk_widget_show (iw->posted_date_hbox);
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "acct_label"));
gtk_widget_show (show);
gtk_widget_show (acct_entry);
-
+
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "hide1"));
gtk_widget_show (show);
show = GTK_WIDGET (gtk_builder_get_object (iw->builder, "hide2"));
@@ -2347,17 +2344,17 @@ gnc_invoice_create_page (InvoiceWindow *iw, gpointer page)
{
case GNC_OWNER_VENDOR:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Bill Information"));
- gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
- gtk_label_set_text (GTK_LABEL(iw->id_label), _("Bill ID"));
+ gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
+ gtk_label_set_text (GTK_LABEL(iw->id_label), _("Bill ID"));
break;
case GNC_OWNER_EMPLOYEE:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Voucher Information"));
gtk_label_set_text (GTK_LABEL(iw->type_label), _("Voucher"));
- gtk_label_set_text (GTK_LABEL(iw->id_label), _("Voucher ID"));
+ gtk_label_set_text (GTK_LABEL(iw->id_label), _("Voucher ID"));
default:
break;
}
-
+
entry_ledger = gnc_entry_ledger_new (iw->book, ledger_type);
/* Save the ledger... */
@@ -2430,7 +2427,7 @@ gnc_invoice_window_new_invoice (InvoiceDialogType dialog_type, QofBook *bookp,
const GncOwner *start_owner;
GncBillTerm *owner_terms = NULL;
GncOwnerType owner_type;
-
+
g_assert (dialog_type == NEW_INVOICE || dialog_type == MOD_INVOICE || dialog_type == DUP_INVOICE);
if (invoice)
@@ -2513,20 +2510,20 @@ gnc_invoice_window_new_invoice (InvoiceDialogType dialog_type, QofBook *bookp,
iw->id_label = GTK_WIDGET (gtk_builder_get_object (builder, "label14"));
iw->info_label = GTK_WIDGET (gtk_builder_get_object (builder, "label1"));
invoice_radio = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_invoice_type"));
-
+
iw->type_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_type_choice_hbox"));
iw->type_choice = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_type_invoice"));
-
+
/* The default GUI lables are for invoices, so change them if it isn't. */
owner_type = gncOwnerGetType (&iw->owner);
switch(owner_type)
{
case GNC_OWNER_VENDOR:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Bill Information"));
- gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
+ gtk_label_set_text (GTK_LABEL(iw->type_label), _("Bill"));
gtk_button_set_label (GTK_BUTTON(invoice_radio), _("Bill"));
gtk_label_set_text (GTK_LABEL(iw->id_label), _("Bill ID"));
-
+
break;
case GNC_OWNER_EMPLOYEE:
gtk_label_set_text (GTK_LABEL(iw->info_label), _("Voucher Information"));
@@ -2536,7 +2533,7 @@ gnc_invoice_window_new_invoice (InvoiceDialogType dialog_type, QofBook *bookp,
default:
break;
}
-
+
/* configure the type related widgets based on dialog type and invoice type */
switch (dialog_type)
{
@@ -3306,4 +3303,3 @@ gnc_invoice_remind_bills_due_cb (void)
gnc_invoice_remind_bills_due();
}
-
diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 54b7385..81febf1 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -966,6 +966,18 @@ gnc_pricedb_equal (GNCPriceDB *db1, GNCPriceDB *db2)
return equal_data.equal;
}
+static gboolean
+insert_or_replace_price(GNCPriceDB *db, GNCPrice *p)
+{
+ GNCPrice *old_price = gnc_pricedb_lookup_day (db, p->commodity,
+ p->currency, p->tmspec);
+ if (old_price == NULL)
+ return TRUE;
+ if (strcmp(p->source, "PRICE_SOURCE_FQ"))
+ return TRUE;
+ return FALSE;
+}
+
/* ==================================================================== */
/* The add_price() function is a utility that only manages the
* dual hash table instertion */
@@ -1030,6 +1042,12 @@ add_price(GNCPriceDB *db, GNCPrice *p)
LEAVE (" no price list");
return FALSE;
}
+
+ if (!insert_or_replace_price(db, p))
+ {
+ LEAVE("A better price already exists");
+ return FALSE;
+ }
g_hash_table_insert(currency_hash, currency, price_list);
p->db = db;
qof_event_gen (&p->inst, QOF_EVENT_ADD, NULL);
diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h
index ce077a5..befff2d 100644
--- a/src/engine/gnc-pricedb.h
+++ b/src/engine/gnc-pricedb.h
@@ -207,6 +207,15 @@ void gnc_price_set_typestr(GNCPrice *p, const char* type);
void gnc_price_set_value(GNCPrice *p, gnc_numeric value);
/** @} */
+#define PRICE_SOURCE_FQ "Finance::Quote"
+#define PRICE_SOURCE_INVOICE "user:invoice-post"
+#define PRICE_SOURCE_STOCK_SPLIT "user:stock-split"
+#define PRICE_SOURCE_XFER_DLG "user:xfer-dialog"
+#define PRICE_SOURCE_SPLIT_REG "user:split-register"
+#define PRICE_SOURCE_EDIT_DLG "user:price-editor"
+#define PRICE_TYPE_LAST "last"
+#define PRICE_TYPE_UNK "unknown"
+
/* ------------------ */
/** @name Getters
All of the getters return data that's internal
diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c
index cd87d46..aaa7a24 100644
--- a/src/gnome-utils/dialog-transfer.c
+++ b/src/gnome-utils/dialog-transfer.c
@@ -1648,7 +1648,7 @@ gnc_xfer_dialog_response_cb (GtkDialog *dialog, gint response, gpointer data)
gnc_price_set_commodity (price, from);
gnc_price_set_currency (price, to);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, "user:xfer-dialog");
+ gnc_price_set_source (price, PRICE_SOURCE_XFER_DLG);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (xferData->pricedb, price);
gnc_price_commit_edit (price);
diff --git a/src/gnome/assistant-stock-split.c b/src/gnome/assistant-stock-split.c
index 7c19634..262df75 100644
--- a/src/gnome/assistant-stock-split.c
+++ b/src/gnome/assistant-stock-split.c
@@ -398,8 +398,8 @@ gnc_stock_split_assistant_finish (GtkAssistant *assistant,
gnc_price_set_commodity (price, xaccAccountGetCommodity (account));
gnc_price_set_currency (price, gnc_currency_edit_get_currency (ce));
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, "user:stock-split");
- gnc_price_set_typestr (price, "unknown");
+ gnc_price_set_source (price, PRICE_SOURCE_STOCK_SPLIT);
+ gnc_price_set_typestr (price, PRICE_TYPE_UNK);
gnc_price_set_value (price, amount);
gnc_price_commit_edit (price);
diff --git a/src/gnome/dialog-price-editor.c b/src/gnome/dialog-price-editor.c
index ac980dc..c7c5b9e 100644
--- a/src/gnome/dialog-price-editor.c
+++ b/src/gnome/dialog-price-editor.c
@@ -50,8 +50,6 @@
#define DIALOG_PRICE_EDIT_CM_CLASS "dialog-price-edit"
#define GNC_PREFS_GROUP "dialogs.price-editor"
-#define DIALOG_PRICE_EDIT_SOURCE "user:price-editor"
-
/* This static indicates the debugging module that this .o belongs to. */
G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_GUI;
@@ -172,7 +170,7 @@ price_to_gui (PriceEditDialog *pedit_dialog)
currency = gnc_default_currency ();
date.tv_sec = gnc_time (NULL);
date.tv_nsec = 0;
- source = DIALOG_PRICE_EDIT_SOURCE;
+ source = PRICE_SOURCE_EDIT_DLG;
type = "";
value = gnc_numeric_zero ();
}
@@ -553,7 +551,7 @@ gnc_price_edit_dialog (GtkWidget * parent,
price = gnc_price_clone(price, pedit_dialog->book);
// } else {
// price = gnc_price_create (pedit_dialog->book);
- gnc_price_set_source (price, DIALOG_PRICE_EDIT_SOURCE);
+ gnc_price_set_source (price, PRICE_SOURCE_EDIT_DLG);
}
pedit_dialog->is_new = TRUE;
diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c
index 3531633..fc4f587 100644
--- a/src/register/ledger-core/split-register.c
+++ b/src/register/ledger-core/split-register.c
@@ -2067,7 +2067,7 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value)
gnc_price_set_commodity (price, comm);
gnc_price_set_currency (price, curr);
gnc_price_set_time (price, ts);
- gnc_price_set_source (price, "user:split-register");
+ gnc_price_set_source (price, PRICE_SOURCE_SPLIT_REG);
gnc_price_set_value (price, value);
gnc_pricedb_add_price (pricedb, price);
gnc_price_commit_edit (price);
Summary of changes:
src/app-utils/gnc-sx-instance-model.c | 7 +-
src/backend/sql/gnc-price-sql.c | 2 +-
src/backend/xml/gnc-pricedb-xml-v2.c | 4 +-
src/backend/xml/io-gncxml-v1.cpp | 2 +-
src/business/business-gnome/dialog-invoice.c | 36 +-
src/engine/engine.i | 11 +-
src/engine/gnc-pricedb-p.h | 13 +-
src/engine/gnc-pricedb.c | 250 ++-----
src/engine/gnc-pricedb.h | 38 +-
src/engine/test-core/test-engine-stuff.cpp | 7 +-
src/engine/test/utest-Account.cpp | 11 +-
src/engine/test/utest-Budget.c | 21 +-
src/engine/test/utest-Split.cpp | 8 +-
src/engine/test/utest-Transaction.cpp | 10 +-
src/gnome-utils/dialog-transfer.c | 1031 ++++++++++++++------------
src/gnome-utils/dialog-transfer.h | 8 +-
src/gnome-utils/gnc-tree-model-price.c | 2 +-
src/gnome-utils/gnc-tree-view-price.c | 3 +-
src/gnome/assistant-stock-split.c | 4 +-
src/gnome/dialog-commodities.c | 3 +-
src/gnome/dialog-price-editor.c | 10 +-
src/libqof/qof/gnc-numeric.cpp | 7 +
src/libqof/qof/gnc-numeric.h | 7 +
src/libqof/qof/gnc-rational.cpp | 4 +-
src/libqof/qof/gnc-rational.hpp | 1 +
src/register/ledger-core/split-register.c | 68 +-
src/scm/price-quotes.scm | 57 +-
27 files changed, 868 insertions(+), 757 deletions(-)
More information about the gnucash-changes
mailing list