gnucash stable: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Tue Jul 14 17:29:23 EDT 2026
Updated via https://github.com/Gnucash/gnucash/commit/b766c126 (commit)
via https://github.com/Gnucash/gnucash/commit/80211df8 (commit)
via https://github.com/Gnucash/gnucash/commit/4d6f19a0 (commit)
via https://github.com/Gnucash/gnucash/commit/748ccca7 (commit)
via https://github.com/Gnucash/gnucash/commit/b1efe076 (commit)
via https://github.com/Gnucash/gnucash/commit/0aac4438 (commit)
via https://github.com/Gnucash/gnucash/commit/3a0bce9a (commit)
via https://github.com/Gnucash/gnucash/commit/3395ff0a (commit)
via https://github.com/Gnucash/gnucash/commit/02ff19e1 (commit)
via https://github.com/Gnucash/gnucash/commit/bae02599 (commit)
via https://github.com/Gnucash/gnucash/commit/adb25886 (commit)
via https://github.com/Gnucash/gnucash/commit/fa38cb35 (commit)
via https://github.com/Gnucash/gnucash/commit/31978c1b (commit)
via https://github.com/Gnucash/gnucash/commit/ff30f443 (commit)
via https://github.com/Gnucash/gnucash/commit/75411913 (commit)
via https://github.com/Gnucash/gnucash/commit/28c892b8 (commit)
via https://github.com/Gnucash/gnucash/commit/28cdb77a (commit)
via https://github.com/Gnucash/gnucash/commit/1e654412 (commit)
via https://github.com/Gnucash/gnucash/commit/b1eb12f5 (commit)
via https://github.com/Gnucash/gnucash/commit/254ec4b4 (commit)
via https://github.com/Gnucash/gnucash/commit/0d5c74b8 (commit)
from https://github.com/Gnucash/gnucash/commit/d37f4b49 (commit)
commit b766c126eefb022a271ee6e15daf831c2062ec7e
Merge: d37f4b49a5 80211df860
Author: John Ralls <jralls at ceridwen.us>
Date: Tue Jul 14 14:24:53 2026 -0700
Merge Sherlock's 'stock-splits' into stable.
commit 80211df86081c6cc22cf030ec5e61e3ac650de40
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Thu Jul 9 00:08:08 2026 -0700
Miscellaneous cleanup
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index f336381e1f..4fa86b9471 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -505,11 +505,12 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gnc_commodity *currency;
Transaction *trans = xaccSplitGetParent (split);
time64 date = xaccTransGetDate (trans);
- gnc_numeric amnt, value, gain;
+ gnc_numeric amnt = xaccSplitGetAdjustedAmount (split);
+ gnc_numeric value, gain;
GtkTreeIter iter;
/* Do not show gains splits, however do show empty business splits */
- if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount (split))) continue;
+ if (!is_business_lot && gnc_numeric_zero_p (amnt)) continue;
if (xaccSplitIsStockSplit (split)) continue;
@@ -526,7 +527,6 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gtk_list_store_set (store, &iter, SPLIT_COL_DESCRIPTION, xaccTransGetDescription (trans), -1);
/* Amount */
- amnt = xaccSplitGetAdjustedAmount (split);
xaccSPrintAmount (amtbuff, show_adjusted_amounts ? amnt : xaccSplitGetAmount (split),
gnc_account_print_info (lv->account, is_business_lot));
gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT, amtbuff, -1);
@@ -977,7 +977,7 @@ lv_init_lot_view (GNCLotViewer *lv)
/* Set up signals */
selection = gtk_tree_view_get_selection (view);
g_signal_connect (selection, "changed",
- G_CALLBACK(lv_selection_changed_cb), lv);
+ G_CALLBACK(lv_selection_changed_cb), lv);
}
/* ======================================================================== */
diff --git a/gnucash/register/ledger-core/split-register-copy-ops.c b/gnucash/register/ledger-core/split-register-copy-ops.c
index a4af7ebbf9..25c40e4eec 100644
--- a/gnucash/register/ledger-core/split-register-copy-ops.c
+++ b/gnucash/register/ledger-core/split-register-copy-ops.c
@@ -135,14 +135,12 @@ void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_dat
void gnc_float_split_set_amount (FloatingSplit *fs, const gnc_numeric amount)
{
g_return_if_fail (fs);
-
fs->m_amount = amount;
}
void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value)
{
g_return_if_fail (fs);
-
fs->m_value = value;
}
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 2f83f1cabc..612fbd7832 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -3961,7 +3961,8 @@ xaccAccountGetSplitsSize (const Account *account)
return GNC_IS_ACCOUNT(account) ? GET_PRIVATE(account)->splits.size() : 0;
}
-gboolean gnc_account_and_descendants_empty (Account *acc)
+gboolean
+gnc_account_and_descendants_empty (Account *acc)
{
g_return_val_if_fail (GNC_IS_ACCOUNT (acc), FALSE);
auto priv = GET_PRIVATE (acc);
diff --git a/libgnucash/engine/Scrub2.cpp b/libgnucash/engine/Scrub2.cpp
index ccdb9174c3..9862c761f6 100644
--- a/libgnucash/engine/Scrub2.cpp
+++ b/libgnucash/engine/Scrub2.cpp
@@ -107,16 +107,16 @@ xaccLotFill (GNCLot *lot)
/* If balance already zero, we have nothing to do. */
if (gnc_lot_is_closed (lot))
{
- LEAVE ("Lot Closed (lot=%s, acc=%s)", gnc_lot_get_title(lot),
- xaccAccountGetName(acc));
- return;
+ LEAVE ("Lot Closed (lot=%s, acc=%s)", gnc_lot_get_title(lot),
+ xaccAccountGetName(acc));
+ return;
}
split = pcy->PolicyGetSplit (pcy, lot);
if (!split)
{
- LEAVE ("No Split (lot=%s, acc=%s)", gnc_lot_get_title(lot),
- xaccAccountGetName(acc));
- return; /* Handle the common case */
+ LEAVE ("No Split (lot=%s, acc=%s)", gnc_lot_get_title(lot),
+ xaccAccountGetName(acc));
+ return; /* Handle the common case */
}
/* Reject stock split transactions */
@@ -131,9 +131,9 @@ xaccLotFill (GNCLot *lot)
if (gnc_numeric_zero_p(split->amount) &&
xaccTransGetVoidStatus(split->parent))
{
- LEAVE ("Voided transaction (lot=%s, acc=%s)",
- gnc_lot_get_title(lot), xaccAccountGetName(acc));
- return;
+ LEAVE ("Voided transaction (lot=%s, acc=%s)",
+ gnc_lot_get_title(lot), xaccAccountGetName(acc));
+ return;
}
xaccAccountBeginEdit (acc);
@@ -189,8 +189,8 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
/* We double-check only closed lots */
if (FALSE == gnc_lot_is_closed (lot))
{
- LEAVE ("lot=%s is closed", gnc_lot_get_title(lot));
- return;
+ LEAVE ("lot=%s is closed", gnc_lot_get_title(lot));
+ return;
}
for (snode = gnc_lot_get_split_list(lot); snode; snode = snode->next)
diff --git a/libgnucash/engine/Split.cpp b/libgnucash/engine/Split.cpp
index 368aeb1337..7347fbee86 100644
--- a/libgnucash/engine/Split.cpp
+++ b/libgnucash/engine/Split.cpp
@@ -759,6 +759,10 @@ xaccFreeSplit (Split *split)
split->acc = nullptr;
split->orig_acc = nullptr;
+ split->balance = gnc_numeric_zero();
+ split->cleared_balance = gnc_numeric_zero();
+ split->reconciled_balance = gnc_numeric_zero();
+ split->noclosing_balance = gnc_numeric_zero();
split->adjusted_amount = gnc_numeric_zero();
split->split_type = nullptr;
@@ -779,12 +783,11 @@ xaccFreeSplit (Split *split)
void mark_split (Split *s)
{
if (s->acc)
- {
g_object_set(s->acc, "sort-dirty", TRUE, "balance-dirty", TRUE, nullptr);
- }
/* set dirty flag on lot too. */
- if (s->lot) gnc_lot_set_closed_unknown(s->lot);
+ if (s->lot)
+ gnc_lot_set_closed_unknown(s->lot);
}
/*
diff --git a/libgnucash/engine/cap-gains.cpp b/libgnucash/engine/cap-gains.cpp
index 269780a484..6c3a4d1e7e 100644
--- a/libgnucash/engine/cap-gains.cpp
+++ b/libgnucash/engine/cap-gains.cpp
@@ -748,7 +748,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
/* Are the cap gains zero? If not, add a balancing transaction.
* As per design doc lots.txt: the transaction has two splits,
- * with equal & opposite values. The amt of one iz zero (so as
+ * with equal & opposite values. The amt of one is zero (so as
* not to upset the lot balance), the amt of the other is the same
* as its value (its the realized gain/loss).
*/
commit 4d6f19a0f9815c14e5d1eeacd3ca718f2b538411
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 23:55:39 2026 -0700
Bug: Missing account event
An account event should be generated for the original account if a lot is moved to a different account in xaccAccountInsertLot() as it is, if the lot is removed in xaccAccountRemoveLot().
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 52af5b45de..2f83f1cabc 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -2139,30 +2139,26 @@ xaccAccountRemoveLot (Account *acc, GNCLot *lot)
void
xaccAccountInsertLot (Account *acc, GNCLot *lot)
{
- AccountPrivate *priv, *opriv;
- Account * old_acc = nullptr;
- Account* lot_account;
-
/* errors */
g_return_if_fail(GNC_IS_ACCOUNT(acc));
g_return_if_fail(GNC_IS_LOT(lot));
/* optimizations */
- lot_account = gnc_lot_get_account(lot);
- if (lot_account == acc)
+ auto lot_acc = gnc_lot_get_account(lot);
+ if (lot_acc == acc)
return;
ENTER ("(acc=%p, lot=%p)", acc, lot);
/* pull it out of the old account */
- if (lot_account)
+ if (lot_acc)
{
- old_acc = lot_account;
- opriv = GET_PRIVATE(old_acc);
- opriv->lots = g_list_remove(opriv->lots, lot);
+ auto priv = GET_PRIVATE(lot_acc);
+ priv->lots = g_list_remove(priv->lots, lot);
+ qof_event_gen (&lot_acc->inst, QOF_EVENT_MODIFY, nullptr);
}
- priv = GET_PRIVATE(acc);
+ auto priv = GET_PRIVATE(acc);
priv->lots = g_list_prepend(priv->lots, lot);
gnc_lot_set_account(lot, acc);
diff --git a/libgnucash/engine/test/utest-Account.cpp b/libgnucash/engine/test/utest-Account.cpp
index fc52032ba1..fcffccf780 100644
--- a/libgnucash/engine/test/utest-Account.cpp
+++ b/libgnucash/engine/test/utest-Account.cpp
@@ -1565,7 +1565,7 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData)
g_assert_cmpuint (g_list_length (p_priv->lots), == , 1);
test_signal_assert_hits (sig1, 2);
test_signal_assert_hits (sig4, 1);
- test_signal_assert_hits (sig2, 1);
+ test_signal_assert_hits (sig2, 2);
/* Check that removing the lot works */
xaccAccountRemoveLot (parent, lot);
/* The following test should fail, but it doesn't because of an
@@ -1576,7 +1576,7 @@ test_xaccAccountInsertRemoveLot (Fixture *fixture, gconstpointer pData)
g_assert_cmpuint (g_list_length (p_priv->lots), == , 0);
test_signal_assert_hits (sig3, 1);
test_signal_assert_hits (sig4, 2);
- test_signal_assert_hits (sig2, 1);
+ test_signal_assert_hits (sig2, 2);
/* Check that destroying the lot removes its reference */
/* Because the lot's account pointer doesn't get nulled when the lot
* is removed, we have to do that for the next test to work: */
@@ -1635,7 +1635,7 @@ test_xaccAccountRecomputeBalance (Fixture *fixture, gconstpointer pData)
rec_bal = gnc_numeric_add_fixed (rec_bal, p.amount);
}
g_assert_true (gnc_numeric_zero_p (priv->starting_balance));
- g_assert_true (gnc_numeric_zero_p (priv->balance));
+ priv->cleared_balance = gnc_numeric_zero ();
priv->balance_dirty = TRUE;
xaccAccountRecomputeBalance (fixture->acct);
g_assert_true (gnc_numeric_zero_p (priv->starting_balance));
@@ -2375,6 +2375,7 @@ test_xaccAccountFindOpenLots (Fixture *fixture, gconstpointer pData)
LotList* lots;
g_assert_true (acct);
+ xaccAccountRecomputeBalance (acct);
lots = xaccAccountFindOpenLots (acct, NULL, NULL, NULL);
g_assert_true (g_list_length (lots) == 2);
if (lots) g_list_free (lots);
diff --git a/libgnucash/engine/test/utest-Split.cpp b/libgnucash/engine/test/utest-Split.cpp
index b9b177b6b0..a35cf7e98c 100644
--- a/libgnucash/engine/test/utest-Split.cpp
+++ b/libgnucash/engine/test/utest-Split.cpp
@@ -91,6 +91,7 @@ setup (Fixture *fixture, gconstpointer pData)
fixture->split->balance = amount;
fixture->split->cleared_balance = amount;
fixture->split->reconciled_balance = amount;
+ fixture->split->adjusted_amount = amount;
qof_instance_mark_clean (QOF_INSTANCE (fixture->split));
qof_instance_mark_clean (QOF_INSTANCE (acc));
qof_instance_mark_clean (QOF_INSTANCE (txn));
commit 748ccca7dbb4f2c948aaa3b347b7815ff6413a0d
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 23:40:46 2026 -0700
Bug: Split type field is not being maintained appropriately
Pasted, duplicated, or reversed stock split transactions and pasted or duplicated stock split splits do not maintain the "stock-split" type. They become "normal" split types.
As we only have two split types, "normal" and "stock-split", added a flag to FloatingSplit for a stock split.
diff --git a/gnucash/register/ledger-core/split-register-copy-ops.c b/gnucash/register/ledger-core/split-register-copy-ops.c
index 7c88c84c2a..a4af7ebbf9 100644
--- a/gnucash/register/ledger-core/split-register-copy-ops.c
+++ b/gnucash/register/ledger-core/split-register-copy-ops.c
@@ -82,6 +82,12 @@ gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs)
return fs->m_value;
}
+gboolean gnc_float_split_get_stock_split (const FloatingSplit *fs)
+{
+ g_return_val_if_fail (fs, FALSE);
+ return fs->m_stock_split;
+}
+
/* modifiers */
void gnc_float_split_set_split(FloatingSplit *fs, Split *split)
@@ -140,6 +146,12 @@ void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value)
fs->m_value = value;
}
+void gnc_float_split_set_stock_split (FloatingSplit *fs, gboolean stock_split)
+{
+ g_return_if_fail (fs);
+ fs->m_stock_split = stock_split;
+}
+
static void
gnc_float_template_sx_data_free (FloatingTemplateSxData *ftsd)
{
@@ -247,6 +259,7 @@ FloatingSplit *gnc_split_to_float_split (Split *split, gboolean is_template)
fs->m_reconcile_date = xaccSplitGetDateReconciled (split);
fs->m_amount = xaccSplitGetAmount (split);
fs->m_value = xaccSplitGetValue (split);
+ fs->m_stock_split = xaccSplitIsStockSplit (split);
if (is_template)
fs->m_template_sx_data = gnc_split_to_float_template_sx_data (split);
@@ -336,6 +349,8 @@ gnc_float_split_to_split (const FloatingSplit *fs, Split *split, Account *templa
{
xaccSplitSetAmount (split, fs->m_amount);
xaccSplitSetValue (split, fs->m_value);
+ if (fs->m_stock_split)
+ xaccSplitMakeStockSplit(split);
}
if (split_account)
diff --git a/gnucash/register/ledger-core/split-register-copy-ops.h b/gnucash/register/ledger-core/split-register-copy-ops.h
index a3cae8ca79..d372f78038 100644
--- a/gnucash/register/ledger-core/split-register-copy-ops.h
+++ b/gnucash/register/ledger-core/split-register-copy-ops.h
@@ -55,6 +55,7 @@ typedef struct
char m_reconcile_state;
gnc_numeric m_value;
gnc_numeric m_amount;
+ gboolean m_stock_split;
FloatingTemplateSxData *m_template_sx_data;
@@ -83,6 +84,7 @@ char gnc_float_split_get_reconcile_state (const FloatingSplit *fs);
time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs);
gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs);
gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs);
+gboolean gnc_float_split_get_stock_split (const FloatingSplit *fs);
/* modifiers */
void gnc_float_split_set_split (FloatingSplit *fs, Split *split);
@@ -94,6 +96,7 @@ void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_stat
void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date);
void gnc_float_split_set_amount (FloatingSplit *fs, gnc_numeric amount);
void gnc_float_split_set_value (FloatingSplit *fs, gnc_numeric value);
+void gnc_float_split_set_stock_split (FloatingSplit *fs, gboolean stock_split);
FloatingSplit *gnc_split_to_float_split (Split *split, gboolean is_template);
void gnc_float_split_to_split (const FloatingSplit *fs, Split *split, Account *template_account);
commit b1efe0763c82699ab9edcd8c735a8d55b1d1b7fb
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 23:20:03 2026 -0700
The lot scrubber should exclude stock-split splits.
diff --git a/libgnucash/engine/Scrub2.cpp b/libgnucash/engine/Scrub2.cpp
index 7c78bca4d7..ccdb9174c3 100644
--- a/libgnucash/engine/Scrub2.cpp
+++ b/libgnucash/engine/Scrub2.cpp
@@ -68,6 +68,9 @@ restart_loop:
{
/* If already in lot, then no-op */
if (split->lot) continue;
+
+ /* Skip stock splits */
+ if (xaccSplitIsStockSplit(split)) continue;
/* Skip voided transactions */
if (gnc_numeric_zero_p (split->amount) &&
@@ -116,6 +119,14 @@ xaccLotFill (GNCLot *lot)
return; /* Handle the common case */
}
+ /* Reject stock split transactions */
+ if (xaccSplitIsStockSplit(split))
+ {
+ LEAVE ("Stock split transaction (lot=%s, acc=%s)",
+ gnc_lot_get_title(lot), xaccAccountGetName(acc));
+ return;
+ }
+
/* Reject voided transactions */
if (gnc_numeric_zero_p(split->amount) &&
xaccTransGetVoidStatus(split->parent))
commit 0aac4438e7f4e7a593107a6037fd3a0aa7fbd46e
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 23:07:45 2026 -0700
Bug: Gain/Loss displayed in "Splits free" is not correct
The gain/loss displayed for splits in the "Splits free" is historical. It may or may not be correct. Instead, the gain should be calculated against the selected lot for appropriate splits.
Implements xaccSplitLotCapGain() to obtain the gain for the selected lot.
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index be9c425e57..f336381e1f 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -200,15 +200,6 @@ lv_show_splits_in_lot (GNCLotViewer *lv)
gnc_split_viewer_fill (lv, lv->split_in_lot_store, split_list);
}
-/* ======================================================================== */
-/* Remove all splits from the split list view */
-
-static void
-lv_clear_splits_in_lot (GNCLotViewer *lv)
-{
- gtk_list_store_clear (lv->split_in_lot_store);
-}
-
/* ======================================================================== */
/* Populate the free split list view */
@@ -218,9 +209,6 @@ lv_show_splits_free (GNCLotViewer *lv)
SplitList *split_list, *node;
SplitList *filtered_list = NULL;
- /* cleanup */
- gtk_list_store_clear (lv->split_free_store);
-
/* get splits */
split_list = xaccAccountGetSplitList (lv->account);
@@ -286,7 +274,7 @@ lv_unset_lot (GNCLotViewer *lv)
gtk_text_view_set_editable (lv->lot_notes, FALSE);
/* Erase the mini-view area */
- lv_clear_splits_in_lot (lv);
+ gtk_list_store_clear (lv->split_in_lot_store);
#ifdef LOTS_READY_FOR_SHOWTIME
gtk_widget_set_sensitive (GTK_WIDGET(lv->regview_button), FALSE);
@@ -505,7 +493,8 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gboolean show_adjusted_amounts = gtk_toggle_button_get_active (lv->show_adjusted_amounts_checkbutton);
gnc_numeric baln = gnc_numeric_zero ();
- gtk_list_store_clear (lv->split_in_lot_store);
+ gtk_list_store_clear (store);
+
for (SplitList *node = split_list; node; node = node->next)
{
Split *split = node->data;
@@ -516,7 +505,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gnc_commodity *currency;
Transaction *trans = xaccSplitGetParent (split);
time64 date = xaccTransGetDate (trans);
- gnc_numeric amnt, value, gains;
+ gnc_numeric amnt, value, gain;
GtkTreeIter iter;
/* Do not show gains splits, however do show empty business splits */
@@ -556,20 +545,21 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gtk_list_store_set (store, &iter, SPLIT_COL_VALUE_DOUBLE, gnc_numeric_to_double (value), -1);
/* Gains. Blank if none. */
- gains = xaccSplitGetCapGains (split);
- if (gnc_numeric_zero_p (gains))
+ gain = (store == lv->split_in_lot_store) ?
+ xaccSplitGetCapGains (split) : xaccLotFreeSplitCapGain (split, lv->selected_lot);
+ if (gnc_numeric_zero_p (gain))
{
gainbuff[0] = 0;
}
else
{
- xaccSPrintAmount (gainbuff, gains,
+ xaccSPrintAmount (gainbuff, gain,
gnc_commodity_print_info (currency, TRUE));
}
gtk_list_store_set (store, &iter, SPLIT_COL_GAIN_LOSS, gainbuff, -1);
- gtk_list_store_set (store, &iter, SPLIT_COL_GAIN_LOSS_DOUBLE, gnc_numeric_to_double (gains), -1);
+ gtk_list_store_set (store, &iter, SPLIT_COL_GAIN_LOSS_DOUBLE, gnc_numeric_to_double (gain), -1);
- /* Balance of Gains */
+ /* Balance of Amounts */
baln = gnc_numeric_add_fixed (baln, amnt);
if (gnc_numeric_zero_p (baln))
{
diff --git a/libgnucash/engine/Split.h b/libgnucash/engine/Split.h
index f6d4733f6d..63fb1ac370 100644
--- a/libgnucash/engine/Split.h
+++ b/libgnucash/engine/Split.h
@@ -345,14 +345,14 @@ gnc_numeric xaccSplitGetClearedBalance (const Split *split);
*/
gnc_numeric xaccSplitGetReconciledBalance (const Split *split);
-/** Returns the stock-split adjusted amount of the split in the account's commodity.
+/** Sets the stock split adjusted amount of a split.
+ * @note The adjusted amount will be reset when the account is rebalanced.
*/
-gnc_numeric xaccSplitGetAdjustedAmount (const Split *split);
+void xaccSplitSetAdjustedAmount (Split *split, gnc_numeric amount);
-/** Sets the stock split adjusted amount of a split. Note: The adjusted amount
- * will be reset when the account is rebalanced.
+/** Returns the stock-split adjusted amount of the split in the account's commodity.
*/
-void xaccSplitSetAdjustedAmount (Split *split, gnc_numeric amount);
+gnc_numeric xaccSplitGetAdjustedAmount (const Split *split);
/** @} */
@@ -420,14 +420,8 @@ void xaccSplitMergePeerSplits (Split *split, const Split *other_split);
*/
Split * xaccSplitGetOtherSplit (const Split *split);
-/** The xaccIsPeerSplit() is a convenience routine that returns TRUE
- * (a non-zero value) if the two splits share a common parent
- * transaction, else it returns FALSE (zero).
- *
-gboolean xaccIsPeerSplit (const Split *split_1, const Split *split_2);
-*/
/** Returns the split type, which is either the string "normal", or
- * "stock-split" for a split from a stock split (pun intended? :-). */
+ * "stock-split" for a split from a stock split. */
const char *xaccSplitGetType(Split *s);
/** Mark a split to be of type stock split - after this, you shouldn't
diff --git a/libgnucash/engine/cap-gains.cpp b/libgnucash/engine/cap-gains.cpp
index 1b1241af40..269780a484 100644
--- a/libgnucash/engine/cap-gains.cpp
+++ b/libgnucash/engine/cap-gains.cpp
@@ -892,6 +892,148 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
/* ============================================================== */
+gnc_numeric
+xaccLotFreeSplitCapGain(Split *split, GNCLot *lot)
+{
+ g_return_val_if_fail (split && lot && !split->lot, gnc_numeric_zero());
+
+ ENTER ("(split=%p lot=%s)", split, gnc_lot_get_title(lot));
+
+ auto pcy = gnc_account_get_policy (gnc_lot_get_account (lot));
+ auto currency = split->parent->common_currency;
+
+ /* Not possible to have gains if the transaction currency and
+ * account commodity are identical. */
+ if (gnc_commodity_equal (currency,
+ xaccAccountGetCommodity(split->acc)))
+ {
+ LEAVE ("Currency transfer, gains not possible, returning.");
+ return gnc_numeric_zero();
+ }
+
+ auto *esplit = gnc_lot_get_earliest_split (lot);
+ if (!esplit)
+ {
+ LEAVE ("Lot is empty, returning.");
+ return gnc_numeric_zero();
+ }
+
+ if (xaccTransGetDate (xaccSplitGetParent (esplit)) >= xaccTransGetDate (xaccSplitGetParent (split)))
+ {
+ LEAVE ("Split is too early, returning.");
+ return gnc_numeric_zero();
+ }
+
+ if (xaccSplitIsStockSplit (split))
+ {
+ LEAVE ("Stock split split, returning.");
+ return gnc_numeric_zero();
+ }
+
+ /* If amount is zero, there's nothing to do! Amount-zero splits
+ * may exist if users attempted to manually record gains. */
+ if (gnc_numeric_zero_p (split->amount)) return gnc_numeric_zero();
+
+ /* If we got to here, then the gains really do need to be recomputed.
+ * So start working things. */
+
+ /* Get the amount and value in this lot at the time of this transaction. */
+ gnc_numeric lot_amount, lot_value;
+ gnc_lot_get_balance_before (lot, split, &lot_amount, &lot_value);
+
+ gnc_numeric opening_amount, opening_value;
+ gnc_commodity *opening_currency;
+ pcy->PolicyGetLotOpening (pcy, lot, &opening_amount, &opening_value,
+ &opening_currency);
+
+ /* Check to make sure the lot-opening currency and this split
+ * use the same currency */
+ if (FALSE == gnc_commodity_equiv (currency, opening_currency))
+ {
+ /* OK, the purchase and the sale were made in different currencies.
+ * I don't know how to compute cap gains for that. This is not
+ * an error. Just punt, silently.
+ */
+ LEAVE ("Can't compute gains, mismatched commodities!");
+ return gnc_numeric_zero();
+ }
+
+ /* Opening amount should be larger (or equal) to current split,
+ * and it should be of the opposite sign.
+ * XXX This should really be a part of a scrub routine that
+ * cleans up the lot, before we get at it!
+ */
+ if (0 > gnc_numeric_compare (gnc_numeric_abs(lot_amount),
+ gnc_numeric_abs(xaccSplitGetAdjustedAmount (split))))
+ {
+ for (auto *n = gnc_lot_get_split_list(lot); n; n = n->next)
+ {
+ auto *s = GNC_SPLIT(n->data);
+ PINFO ("split adj amt=%s", gnc_num_dbg_to_string(xaccSplitGetAdjustedAmount (s)));
+ }
+ return gnc_numeric_zero();
+ }
+ if ( (gnc_numeric_negative_p(lot_amount) ||
+ gnc_numeric_positive_p(xaccSplitGetAdjustedAmount (split))) &&
+ (gnc_numeric_positive_p(lot_amount) ||
+ gnc_numeric_negative_p(xaccSplitGetAdjustedAmount (split))))
+ {
+ for (auto *n = gnc_lot_get_split_list(lot); n; n = n->next)
+ {
+ auto *s = GNC_SPLIT(n->data);
+ PINFO ("split adj amt=%s", gnc_num_dbg_to_string(xaccSplitGetAdjustedAmount (s)));
+ }
+ return gnc_numeric_zero();
+ }
+
+ /* The cap gains is the difference between the basis prior to the
+ * current split, and the current split, pro-rated for an equal
+ * amount of shares.
+ * i.e. purchase_price = lot_value / lot_amount
+ * cost_basis = purchase_price * current_split_amount
+ * cap_gain = current_split_value - cost_basis
+ */
+ /* Fraction of the lot that this split represents: */
+ auto frac = gnc_numeric_div (xaccSplitGetAdjustedAmount (split), lot_amount,
+ GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ /* Basis for this split: */
+ auto value = gnc_numeric_mul (frac, lot_value,
+ gnc_numeric_denom(opening_value),
+ GNC_HOW_DENOM_EXACT | GNC_HOW_RND_ROUND_HALF_UP);
+ /* Capital gain for this split: */
+ value = gnc_numeric_sub (value, split->value,
+ GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
+
+ PINFO ("Open amt=%s val=%s; split adj amt=%s val=%s; gains=%s\n",
+ gnc_num_dbg_to_string (lot_amount),
+ gnc_num_dbg_to_string (lot_value),
+ gnc_num_dbg_to_string (xaccSplitGetAdjustedAmount (split)),
+ gnc_num_dbg_to_string (split->value),
+ gnc_num_dbg_to_string (value));
+
+ if (gnc_numeric_check (value))
+ {
+ PERR ("Numeric overflow during gains calculation\n"
+ "Acct=%s Txn=%s\n"
+ "\tOpen amt=%s val=%s\n\tsplit amt=%s val=%s\n\tgains=%s\n",
+ xaccAccountGetName(split->acc),
+ xaccTransGetDescription(split->parent),
+ gnc_num_dbg_to_string (lot_amount),
+ gnc_num_dbg_to_string (lot_value),
+ gnc_num_dbg_to_string (xaccSplitGetAdjustedAmount (split)),
+ gnc_num_dbg_to_string (split->value),
+ gnc_num_dbg_to_string (value));
+ return gnc_numeric_zero();
+ }
+
+ LEAVE ("(lot=%s)", gnc_lot_get_title(lot));
+
+ return value;
+}
+
+/* ============================================================== */
+
gnc_numeric
xaccSplitGetCapGains(Split * split)
{
diff --git a/libgnucash/engine/cap-gains.h b/libgnucash/engine/cap-gains.h
index c8ced0be1c..9b6b7606f9 100644
--- a/libgnucash/engine/cap-gains.h
+++ b/libgnucash/engine/cap-gains.h
@@ -187,6 +187,20 @@ gboolean xaccSplitAssign (Split *split);
*/
Split * xaccSplitAssignToLot (Split *split, GNCLot *lot);
+/** The xaccLotFreeSplitCapGain() method returns the value of capital gain
+ * (if any) associated with the indicated split against the indicated
+ * lot. In order for there to be any capital gain, a few things must
+ * hold true about this split:
+ * (1) It must have been involved in trading (for example,
+ * by belonging to a stock or trading account)
+ * (2) It must not be assigned to a lot.
+ * (3) It cannot be the opening split of a lot; that
+ * is, it must be a matching sale of an earlier purchase
+ * (or vice versa).
+ */
+gnc_numeric xaccLotFreeSplitCapGain(Split *split, GNCLot *lot);
+
+
/** The xaccSplitComputeCapGains() routine computes the cap gains
* or losses for the indicated split. The gains are placed into
* the 'gains_acct'. If the gains_acct is NULL, then the appropriate
commit 3a0bce9ab95cf0c34543cdca76a73a2061c0e5fb
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 22:49:50 2026 -0700
Partial cleanup of Lot Viewer's lot and split list populate functions
Much more to be done...
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 58e91797e6..be9c425e57 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -344,25 +344,23 @@ lv_unselect_row (GNCLotViewer *lv)
static void
gnc_lot_viewer_fill (GNCLotViewer *lv)
{
- LotList *lot_list, *node;
+ LotList *lot_list = xaccAccountGetLotList (lv->account);
GNCLot *this_lot, *selected_lot = NULL;
GtkListStore *store;
GtkTreeModel *model;
GtkTreeIter iter;
- GtkTreeSelection *selection;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (lv->lot_view);
gboolean found = FALSE;
gboolean is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (lv->account));
+ gboolean show_only_open_lots = gtk_toggle_button_get_active (lv->only_show_open_lots_checkbutton);
- lot_list = xaccAccountGetLotList (lv->account);
-
- selection = gtk_tree_view_get_selection (lv->lot_view);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
gtk_tree_model_get (model, &iter, LOT_COL_PNTR, &selected_lot, -1);
/* Crazy. Should update in place if possible. */
gtk_list_store_clear (lv->lot_store);
- for (node = lot_list; node; node = node->next)
+ for (LotList *node = lot_list; node; node = node->next)
{
char type_buff[200];
char baln_buff[200];
@@ -374,7 +372,7 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
gnc_numeric gains_baln = get_realized_gains (lot, currency);
/* Skip closed lots when only open should be shown */
- if (TRUE == gtk_toggle_button_get_active (lv->only_show_open_lots_checkbutton) && gnc_lot_is_closed (lot))
+ if (show_only_open_lots && gnc_lot_is_closed (lot))
{
continue;
}
@@ -503,14 +501,12 @@ lv_can_remove_split_from_lot (Split * split, GNCLot * lot)
static void
gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_list)
{
- SplitList *node;
- GtkTreeIter iter;
gboolean is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (lv->account));
gboolean show_adjusted_amounts = gtk_toggle_button_get_active (lv->show_adjusted_amounts_checkbutton);
gnc_numeric baln = gnc_numeric_zero ();
gtk_list_store_clear (lv->split_in_lot_store);
- for (node = split_list; node; node = node->next)
+ for (SplitList *node = split_list; node; node = node->next)
{
Split *split = node->data;
char amtbuff[200];
@@ -521,6 +517,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
Transaction *trans = xaccSplitGetParent (split);
time64 date = xaccTransGetDate (trans);
gnc_numeric amnt, value, gains;
+ GtkTreeIter iter;
/* Do not show gains splits, however do show empty business splits */
if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount (split))) continue;
commit 3395ff0a60750ec8f57e57a70538adb193a65a53
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 21:22:08 2026 -0700
Lot viewer should display the current name of the account in the window title.
Added to lv_refresh().
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 9f3d0806c4..58e91797e6 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -613,6 +613,12 @@ lv_update_split_buttons (GNCLotViewer *lv)
}
}
+static void set_window_title (GNCLotViewer *lv)
+{
+ gchar *win_title = g_strdup_printf (_("Lots in Account %s"), xaccAccountGetName (lv->account));
+ gtk_window_set_title (GTK_WINDOW (lv->window), win_title);
+ g_free (win_title);
+}
static void set_adjusted_ammounts_checkbutton_visibility (GNCLotViewer *lv)
{
@@ -628,7 +634,8 @@ static void lv_refresh (GNCLotViewer *lv)
gnc_lot_viewer_fill (lv);
lv_show_splits_free (lv);
lv_show_splits_in_lot (lv);
- set_adjusted_ammounts_checkbutton_visibility (lv);
+ set_window_title (lv);
+ set_adjusted_ammounts_checkbutton_visibility (lv);
}
/* ======================================================================== */
@@ -1103,7 +1110,6 @@ window_realize_set_split_paned_position_cb (GtkWidget *widget, gpointer user_dat
static void
lv_create (GNCLotViewer *lv, GtkWindow *parent)
{
- gchar *win_title;
GtkBuilder *builder;
builder = gtk_builder_new ();
@@ -1116,11 +1122,6 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
// Set the name for this dialog so it can be easily manipulated with css
gtk_widget_set_name (GTK_WIDGET(lv->window), "gnc-id-lot-viewer");
- win_title = g_strdup_printf (_("Lots in Account %s"),
- xaccAccountGetName (lv->account));
- gtk_window_set_title (GTK_WINDOW (lv->window), win_title);
- g_free (win_title);
-
#ifdef LOTS_READY_FOR_SHOWTIME
lv->regview_button = GTK_BUTTON(glade_xml_get_widget (builder, "regview_button"));
#endif
commit 02ff19e1b364f80e852e295524aa90aa25716888
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 21:13:50 2026 -0700
Bug: Lot Viewer should watch and handle the account's events
Splits that appear on "Splits free" list are obviously iffy.
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index f2a780b374..9f3d0806c4 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -46,8 +46,10 @@
#include "dialog-utils.h"
#include "dialog-lot-viewer.h"
#include "gnc-component-manager.h"
+#include "gnc-event.h"
#include "gnc-prefs.h"
#include "gnc-ui-util.h"
+#include "gnc-session.h"
#include "gnc-window.h"
#include "misc-gnome-utils.h"
#include "tree-view-utils.h"
@@ -120,6 +122,8 @@ struct _GNCLotViewer
Account * account;
GNCLot * selected_lot;
+ gint component_id;
+ GncGUID account_id;
};
static void gnc_lot_viewer_fill (GNCLotViewer *lv);
@@ -633,6 +637,17 @@ static void
lv_refresh_handler (GHashTable *changes, gpointer user_data)
{
GNCLotViewer *lv = user_data;
+
+ if (changes)
+ {
+ const EventInfo *info = gnc_gui_get_entity_events (changes, &lv->account_id);
+ if (info && (info->event_mask & QOF_EVENT_DESTROY))
+ {
+ gnc_close_gui_component (lv->component_id);
+ return;
+ }
+ }
+
lv_refresh (lv);
}
@@ -698,7 +713,9 @@ void
lv_window_destroy_cb (GtkWidget *object, gpointer user_data)
{
GNCLotViewer *lv = user_data;
- gnc_unregister_gui_component_by_data (LOT_VIEWER_CM_CLASS, lv);
+
+ gnc_unregister_gui_component (lv->component_id);
+
g_free (lv);
}
@@ -1175,7 +1192,6 @@ GNCLotViewer *
gnc_lot_viewer_dialog (GtkWindow *parent, Account *account)
{
GNCLotViewer *lv;
- gint component_id;
if (!account) return NULL;
@@ -1184,14 +1200,14 @@ gnc_lot_viewer_dialog (GtkWindow *parent, Account *account)
lv_create (lv, parent);
lv_refresh (lv);
- component_id = gnc_register_gui_component (LOT_VIEWER_CM_CLASS,
- lv_refresh_handler,
- lv_close_handler,
- lv);
+ lv->component_id = gnc_register_gui_component (LOT_VIEWER_CM_CLASS, lv_refresh_handler, lv_close_handler, lv);
+ lv->account_id = *xaccAccountGetGUID (account);
- gnc_gui_component_watch_entity_type (component_id,
- GNC_ID_LOT,
- QOF_EVENT_CREATE | QOF_EVENT_ADD | QOF_EVENT_REMOVE | QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
+ gnc_gui_component_set_session (lv->component_id, gnc_get_current_session ());
+ gnc_gui_component_watch_entity_type (lv->component_id, GNC_ID_LOT,
+ QOF_EVENT_CREATE | QOF_EVENT_ADD | QOF_EVENT_REMOVE | QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
+ gnc_gui_component_watch_entity (lv->component_id, &lv->account_id,
+ QOF_EVENT_MODIFY | QOF_EVENT_DESTROY | GNC_EVENT_ITEM_CHANGED);
return lv;
commit bae025995d04c07f97da817d58584582eae6abe1
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:58:20 2026 -0700
Reuse lv_refresh()
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 107a5a7e1a..f2a780b374 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -811,9 +811,7 @@ lv_response_cb (GtkDialog *dialog, gint response, gpointer data)
else
xaccAccountScrubLots (lv->account);
gnc_resume_gui_refresh ();
- gnc_lot_viewer_fill (lv);
- lv_show_splits_free (lv);
- lv_show_splits_in_lot (lv);
+ lv_refresh (lv);
break;
case RESPONSE_NEW_LOT:
@@ -1184,8 +1182,7 @@ gnc_lot_viewer_dialog (GtkWindow *parent, Account *account)
lv = g_new0 (GNCLotViewer, 1);
lv->account = account;
lv_create (lv, parent);
- gnc_lot_viewer_fill (lv);
- lv_show_splits_free (lv);
+ lv_refresh (lv);
component_id = gnc_register_gui_component (LOT_VIEWER_CM_CLASS,
lv_refresh_handler,
commit adb2588633ce72b25d1806cc57df5ef11ff3512b
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:52:41 2026 -0700
Lot Viewer "Amount" and "Balance" columns should not display the currency symbol.
For now, weâll only display the currency in these columns if the account is of a business type.
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 1b02cc29f3..107a5a7e1a 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -347,6 +347,7 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
GtkTreeIter iter;
GtkTreeSelection *selection;
gboolean found = FALSE;
+ gboolean is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (lv->account));
lot_list = xaccAccountGetLotList (lv->account);
@@ -414,7 +415,7 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
/* Amount */
xaccSPrintAmount (baln_buff, amt_baln,
- gnc_account_print_info (lv->account, TRUE));
+ gnc_account_print_info (lv->account, is_business_lot));
gtk_list_store_set (store, &iter, LOT_COL_BALN, baln_buff, -1);
gtk_list_store_set (store, &iter, LOT_COL_BALN_DOUBLE, gnc_numeric_to_double (amt_baln), -1);
@@ -500,13 +501,10 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
{
SplitList *node;
GtkTreeIter iter;
- gboolean is_business_lot = FALSE;
+ gboolean is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (lv->account));
gboolean show_adjusted_amounts = gtk_toggle_button_get_active (lv->show_adjusted_amounts_checkbutton);
gnc_numeric baln = gnc_numeric_zero ();
- if (lv->selected_lot)
- is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (gnc_lot_get_account (lv->selected_lot)));
-
gtk_list_store_clear (lv->split_in_lot_store);
for (node = split_list; node; node = node->next)
{
@@ -540,7 +538,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
/* Amount */
amnt = xaccSplitGetAdjustedAmount (split);
xaccSPrintAmount (amtbuff, show_adjusted_amounts ? amnt : xaccSplitGetAmount (split),
- gnc_account_print_info (lv->account, TRUE));
+ gnc_account_print_info (lv->account, is_business_lot));
gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT, amtbuff, -1);
gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT_DOUBLE, gnc_numeric_to_double (amnt), -1);
@@ -579,7 +577,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
else
{
xaccSPrintAmount (balnbuff, baln,
- gnc_account_print_info (lv->account, TRUE));
+ gnc_account_print_info (lv->account, is_business_lot));
}
gtk_list_store_set (store, &iter, SPLIT_COL_BALANCE, balnbuff, -1);
gtk_list_store_set (store, &iter, SPLIT_COL_BALANCE_DOUBLE, gnc_numeric_to_double (baln), -1);
commit fa38cb352111fc1ab2aaf8941f48f93038e8e896
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:40:47 2026 -0700
Remove unused declaration
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index dc31c170ca..1b02cc29f3 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -131,9 +131,6 @@ static void gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitL
void lv_title_entry_changed_cb (GtkEntry *ent, gpointer user_data);
void lv_response_cb (GtkDialog *dialog, gint response, gpointer data);
void lv_window_destroy_cb (GtkWidget *object, gpointer user_data);
-void lv_paned_notify_cb (GObject *gobject,
- GParamSpec *pspec,
- gpointer user_data);
/* ======================================================================== */
/* Get the realized gains for this lot. This routine or a variant of it
commit 31978c1b4d3c6a61df0f09e2a2b59be93b5326fb
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:35:44 2026 -0700
Only show the âShow stock split adjusted amountsâ checkbox when there are stock splits
Added has_stock_split field to Account private. This flag is set to true when xaccAccountRecomputeBalance() detects a stock-split split otherwise it is false. Defined and declared xaccAccountHasStockSplit() for use by the Lot Viewer to whether to display the check box.
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 02a81193e6..dc31c170ca 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -116,6 +116,7 @@ struct _GNCLotViewer
GtkButton * add_split_to_lot_button;
GtkButton * remove_split_from_lot_button;
GtkToggleButton * only_show_open_lots_checkbutton;
+ GtkToggleButton * show_adjusted_amounts_checkbutton;
Account * account;
GNCLot * selected_lot;
@@ -503,6 +504,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
SplitList *node;
GtkTreeIter iter;
gboolean is_business_lot = FALSE;
+ gboolean show_adjusted_amounts = gtk_toggle_button_get_active (lv->show_adjusted_amounts_checkbutton);
gnc_numeric baln = gnc_numeric_zero ();
if (lv->selected_lot)
@@ -612,11 +614,22 @@ lv_update_split_buttons (GNCLotViewer *lv)
}
}
-static void lv_refresh (GNCLotViewer * lv)
+
+static void set_adjusted_ammounts_checkbutton_visibility (GNCLotViewer *lv)
+{
+ GtkWidget *widget = GTK_WIDGET(lv->show_adjusted_amounts_checkbutton);
+ gboolean has_stock_split = xaccAccountHasStockSplit (lv->account);
+
+ gtk_widget_set_visible (widget, has_stock_split);
+ gtk_widget_set_no_show_all (widget, !has_stock_split);
+}
+
+static void lv_refresh (GNCLotViewer *lv)
{
gnc_lot_viewer_fill (lv);
lv_show_splits_free (lv);
lv_show_splits_in_lot (lv);
+ set_adjusted_ammounts_checkbutton_visibility (lv);
}
/* ======================================================================== */
@@ -1110,6 +1123,7 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
lv->show_adjusted_amounts_checkbutton = GTK_TOGGLE_BUTTON(gtk_builder_get_object (builder, "show_adjusted_amounts_checkbutton"));
g_signal_connect (lv->show_adjusted_amounts_checkbutton, "toggled", G_CALLBACK(lv_show_adjusted_amounts_changed_cb), lv);
+ set_adjusted_ammounts_checkbutton_visibility (lv);
lv->lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "lot_view"));
lv_init_lot_view (lv);
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 134f468efb..52af5b45de 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -328,6 +328,7 @@ gnc_account_init(Account* acc)
priv->starting_cleared_balance = gnc_numeric_zero();
priv->starting_reconciled_balance = gnc_numeric_zero();
priv->balance_dirty = FALSE;
+ priv->has_stock_split = false;
new (&priv->children) AccountVec ();
new (&priv->splits) SplitsVec ();
@@ -1456,6 +1457,7 @@ xaccFreeAccount (Account *acc)
priv->commodity = nullptr;
priv->balance_dirty = FALSE;
+ priv->has_stock_split = false;
priv->sort_dirty = FALSE;
priv->splits.~SplitsVec();
priv->children.~AccountVec();
@@ -2288,6 +2290,7 @@ xaccAccountRecomputeBalance (Account * acc)
auto noclosing_balance = priv->starting_noclosing_balance;
auto cleared_balance = priv->starting_cleared_balance;
auto reconciled_balance = priv->starting_reconciled_balance;
+ auto has_stock_split = false;
PINFO ("acct=%s starting baln=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT,
priv->accountName, balance.num, balance.denom);
@@ -2314,6 +2317,7 @@ xaccAccountRecomputeBalance (Account * acc)
GNC_HOW_RND_ROUND_HALF_UP));
}
balance = new_balance;
+ has_stock_split = true;
}
else
{
@@ -2348,6 +2352,7 @@ xaccAccountRecomputeBalance (Account * acc)
priv->cleared_balance = cleared_balance;
priv->reconciled_balance = reconciled_balance;
priv->balance_dirty = FALSE;
+ priv->has_stock_split = has_stock_split;
}
/********************************************************************\
@@ -3502,6 +3507,13 @@ xaccAccountGetProjectedMinimumBalance (const Account *acc)
return minimum ? *minimum : gnc_numeric_zero();
}
+gboolean
+xaccAccountHasStockSplit (const Account *acc)
+{
+ g_return_val_if_fail(GNC_IS_ACCOUNT(acc), false);
+ return GET_PRIVATE(acc)->has_stock_split;
+}
+
/********************************************************************\
\********************************************************************/
diff --git a/libgnucash/engine/Account.h b/libgnucash/engine/Account.h
index d8e7dd406b..510b326ae3 100644
--- a/libgnucash/engine/Account.h
+++ b/libgnucash/engine/Account.h
@@ -648,6 +648,10 @@ typedef enum
gnc_numeric xaccAccountGetBalanceChangeForPeriod (
Account *acc, time64 date1, time64 date2, gboolean recurse);
+ /** Returns true if the account has a stock split,
+ * otherwise false. */
+ gboolean xaccAccountHasStockSplit (const Account *acc);
+
/** @} */
/** @name Account Children and Parents.
diff --git a/libgnucash/engine/AccountP.hpp b/libgnucash/engine/AccountP.hpp
index ea617fe011..58faf542df 100644
--- a/libgnucash/engine/AccountP.hpp
+++ b/libgnucash/engine/AccountP.hpp
@@ -114,6 +114,7 @@ typedef struct AccountPrivate
gnc_numeric reconciled_balance;
gboolean balance_dirty; /* balances in splits incorrect */
+ gboolean has_stock_split; /* account includes a stock split */
std::vector<Split*> splits; /* list of split pointers */
GHashTable* splits_hash;
commit ff30f4438b7ade6e6fc22410a714e46e7fa443e4
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:21:18 2026 -0700
Add "Show stock split adjusted amounts" check box
With the lot now displaying the split adjusted balance, it's useful to be able to view the split's adjusted amounts.
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index fa80e6fab4..02a81193e6 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -539,8 +539,8 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gtk_list_store_set (store, &iter, SPLIT_COL_DESCRIPTION, xaccTransGetDescription (trans), -1);
/* Amount */
- amnt = xaccSplitGetAmount (split);
- xaccSPrintAmount (amtbuff, amnt,
+ amnt = xaccSplitGetAdjustedAmount (split);
+ xaccSPrintAmount (amtbuff, show_adjusted_amounts ? amnt : xaccSplitGetAmount (split),
gnc_account_print_info (lv->account, TRUE));
gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT, amtbuff, -1);
gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT_DOUBLE, gnc_numeric_to_double (amnt), -1);
@@ -746,6 +746,12 @@ lv_only_show_open_lots_changed_cb (GtkWidget *widget, GNCLotViewer * lv)
lv_refresh (lv);
}
+static void
+lv_show_adjusted_amounts_changed_cb (GtkWidget *widget, GNCLotViewer * lv)
+{
+ lv_refresh (lv);
+}
+
/* ======================================================================== */
/* Any button was pressed */
@@ -954,10 +960,7 @@ lv_init_lot_view (GNCLotViewer *lv)
/* Set up signals */
selection = gtk_tree_view_get_selection (view);
g_signal_connect (selection, "changed",
- G_CALLBACK(lv_selection_changed_cb), lv);
- g_signal_connect (lv->only_show_open_lots_checkbutton, "toggled",
- G_CALLBACK(lv_only_show_open_lots_changed_cb), lv);
-
+ G_CALLBACK(lv_selection_changed_cb), lv);
}
/* ======================================================================== */
@@ -1102,8 +1105,13 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
lv->scrub_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "scrub_lot_button"));
lv->new_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "new_lot_button"));
- lv->lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "lot_view"));
lv->only_show_open_lots_checkbutton = GTK_TOGGLE_BUTTON(gtk_builder_get_object (builder, "only_show_open_lots_checkbutton"));
+ g_signal_connect (lv->only_show_open_lots_checkbutton, "toggled", G_CALLBACK(lv_only_show_open_lots_changed_cb), lv);
+
+ lv->show_adjusted_amounts_checkbutton = GTK_TOGGLE_BUTTON(gtk_builder_get_object (builder, "show_adjusted_amounts_checkbutton"));
+ g_signal_connect (lv->show_adjusted_amounts_checkbutton, "toggled", G_CALLBACK(lv_show_adjusted_amounts_changed_cb), lv);
+
+ lv->lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "lot_view"));
lv_init_lot_view (lv);
lv->lot_notes = GTK_TEXT_VIEW(gtk_builder_get_object (builder, "lot_notes_text"));
lv->title_entry = GTK_ENTRY (gtk_builder_get_object (builder, "lot_title_entry"));
@@ -1150,6 +1158,8 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
lv_update_split_buttons (lv);
gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(lv->window), parent);
+ gtk_widget_show_all (lv->window);
+ gnc_window_adjust_for_screen (GTK_WINDOW(lv->window));
}
/* ======================================================================== */
@@ -1177,8 +1187,6 @@ gnc_lot_viewer_dialog (GtkWindow *parent, Account *account)
GNC_ID_LOT,
QOF_EVENT_CREATE | QOF_EVENT_ADD | QOF_EVENT_REMOVE | QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
- gtk_widget_show_all (lv->window);
- gnc_window_adjust_for_screen (GTK_WINDOW(lv->window));
return lv;
}
diff --git a/gnucash/gtkbuilder/dialog-lot-viewer.glade b/gnucash/gtkbuilder/dialog-lot-viewer.glade
index a24d50f3b8..6ffb030822 100644
--- a/gnucash/gtkbuilder/dialog-lot-viewer.glade
+++ b/gnucash/gtkbuilder/dialog-lot-viewer.glade
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 -->
+<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkDialog" id="lot_viewer_dialog">
@@ -107,6 +107,22 @@
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="show_adjusted_amounts_checkbutton">
+ <property name="label" translatable="yes">Show stock split adjusted amounts</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="draw-indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
<child>
<object class="GtkPaned" id="lot_vpaned">
<property name="visible">True</property>
@@ -191,13 +207,13 @@
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">_Title</property>
- <style>
- <class name="gnc-class-strong"/>
- </style>
<property name="use-markup">True</property>
<property name="use-underline">True</property>
<property name="justify">center</property>
<property name="mnemonic-widget">lot_title_entry</property>
+ <style>
+ <class name="gnc-class-strong"/>
+ </style>
</object>
<packing>
<property name="left-attach">0</property>
@@ -224,12 +240,12 @@
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">_Lots in This Account</property>
- <style>
- <class name="gnc-class-strong"/>
- </style>
<property name="use-markup">True</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">lot_view</property>
+ <style>
+ <class name="gnc-class-strong"/>
+ </style>
</object>
<packing>
<property name="left-attach">0</property>
@@ -242,8 +258,6 @@
<property name="can-focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
- <property name="hscrollbar-policy">always</property>
- <property name="vscrollbar-policy">always</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="lot_view">
@@ -308,12 +322,12 @@
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Splits _free</property>
- <style>
- <class name="gnc-class-strong"/>
- </style>
<property name="use-markup">True</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">split_free_view</property>
+ <style>
+ <class name="gnc-class-strong"/>
+ </style>
</object>
<packing>
<property name="left-attach">0</property>
@@ -366,12 +380,12 @@
<property name="can-focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Splits _in lot</property>
- <style>
- <class name="gnc-class-strong"/>
- </style>
<property name="use-markup">True</property>
<property name="use-underline">True</property>
<property name="mnemonic-widget">split_in_lot_view</property>
+ <style>
+ <class name="gnc-class-strong"/>
+ </style>
</object>
<packing>
<property name="left-attach">1</property>
commit 75411913818bbad8370706fe8ae7ca3dac6ec945
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:09:46 2026 -0700
Exclude stock-splits from Split views in Lot Viewer
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 11ca5c9f23..fa80e6fab4 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -524,6 +524,8 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
/* Do not show gains splits, however do show empty business splits */
if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount (split))) continue;
+ if (xaccSplitIsStockSplit (split)) continue;
+
gtk_list_store_append (store, &iter);
/* Date */
commit 28c892b8a725e18589d49314a7607a2980e34a43
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 20:04:44 2026 -0700
Improve readability of dialog-lot-viewer
Cosmetic white-space changes.
diff --git a/gnucash/gnome/dialog-lot-viewer.c b/gnucash/gnome/dialog-lot-viewer.c
index 061617a9ab..11ca5c9f23 100644
--- a/gnucash/gnome/dialog-lot-viewer.c
+++ b/gnucash/gnome/dialog-lot-viewer.c
@@ -97,28 +97,28 @@ enum split_cols
struct _GNCLotViewer
{
- GtkWidget * window;
+ GtkWidget * window;
#ifdef LOTS_READY_FOR_SHOWTIME
- GtkButton * regview_button;
+ GtkButton * regview_button;
#endif
- GtkButton * delete_button;
- GtkButton * scrub_lot_button;
- GtkButton * new_lot_button;
- GtkTreeView * lot_view;
- GtkListStore * lot_store;
- GtkTextView * lot_notes;
- GtkEntry * title_entry;
- GtkTreeView * split_in_lot_view;
- GtkListStore * split_in_lot_store;
- GtkTreeView * split_free_view;
- GtkListStore * split_free_store;
- GtkWidget * split_hpaned;
- GtkButton * add_split_to_lot_button;
- GtkButton * remove_split_from_lot_button;
+ GtkButton * delete_button;
+ GtkButton * scrub_lot_button;
+ GtkButton * new_lot_button;
+ GtkTreeView * lot_view;
+ GtkListStore * lot_store;
+ GtkTextView * lot_notes;
+ GtkEntry * title_entry;
+ GtkTreeView * split_in_lot_view;
+ GtkListStore * split_in_lot_store;
+ GtkTreeView * split_free_view;
+ GtkListStore * split_free_store;
+ GtkWidget * split_hpaned;
+ GtkButton * add_split_to_lot_button;
+ GtkButton * remove_split_from_lot_button;
GtkToggleButton * only_show_open_lots_checkbutton;
- Account * account;
- GNCLot * selected_lot;
+ Account * account;
+ GNCLot * selected_lot;
};
static void gnc_lot_viewer_fill (GNCLotViewer *lv);
@@ -146,12 +146,12 @@ find_first_currency (GNCLot *lot)
{
SplitList *split_list, *node;
- split_list = gnc_lot_get_split_list(lot);
+ split_list = gnc_lot_get_split_list (lot);
for (node = split_list; node; node = node->next)
{
Split *s = node->data;
Transaction *trans;
- if (FALSE == gnc_numeric_zero_p(xaccSplitGetAmount(s))) continue;
+ if (FALSE == gnc_numeric_zero_p (xaccSplitGetAmount (s))) continue;
trans = xaccSplitGetParent (s);
return xaccTransGetCurrency (trans);
}
@@ -161,21 +161,21 @@ find_first_currency (GNCLot *lot)
static gnc_numeric
get_realized_gains (GNCLot *lot, gnc_commodity *currency)
{
- gnc_numeric zero = gnc_numeric_zero();
+ gnc_numeric zero = gnc_numeric_zero ();
gnc_numeric gains = zero;
SplitList *split_list, *node;
if (!currency) return zero;
- split_list = gnc_lot_get_split_list(lot);
+ split_list = gnc_lot_get_split_list (lot);
for (node = split_list; node; node = node->next)
{
Split *s = node->data;
Transaction *trans;
- if (FALSE == gnc_numeric_zero_p(xaccSplitGetAmount(s))) continue;
+ if (FALSE == gnc_numeric_zero_p (xaccSplitGetAmount (s))) continue;
trans = xaccSplitGetParent (s);
- if (FALSE == gnc_commodity_equal (xaccTransGetCurrency(trans), currency)) continue;
+ if (FALSE == gnc_commodity_equal (xaccTransGetCurrency (trans), currency)) continue;
gains = gnc_numeric_add (gains, xaccSplitGetValue (s), GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
}
@@ -195,7 +195,7 @@ lv_show_splits_in_lot (GNCLotViewer *lv)
if (NULL == lot) return;
split_list = gnc_lot_get_split_list (lot);
- gnc_split_viewer_fill(lv, lv->split_in_lot_store, split_list);
+ gnc_split_viewer_fill (lv, lv->split_in_lot_store, split_list);
}
/* ======================================================================== */
@@ -220,13 +220,13 @@ lv_show_splits_free (GNCLotViewer *lv)
gtk_list_store_clear (lv->split_free_store);
/* get splits */
- split_list = xaccAccountGetSplitList(lv->account);
+ split_list = xaccAccountGetSplitList (lv->account);
/* filter splits */
for (node = split_list; node; node = node->next)
{
Split *split = node->data;
- if (NULL == xaccSplitGetLot(split))
+ if (NULL == xaccSplitGetLot (split))
{
filtered_list = g_list_prepend (filtered_list, split);
}
@@ -234,7 +234,7 @@ lv_show_splits_free (GNCLotViewer *lv)
filtered_list = g_list_reverse (filtered_list);
/* display list */
- gnc_split_viewer_fill(lv, lv->split_free_store, filtered_list);
+ gnc_split_viewer_fill (lv, lv->split_free_store, filtered_list);
g_list_free (filtered_list);
g_list_free (split_list);
}
@@ -251,7 +251,7 @@ lv_save_current_lot (GNCLotViewer *lv)
if (lot)
{
- gnc_lot_begin_edit(lot);
+ gnc_lot_begin_edit (lot);
/* Get the title, save_the_title */
str = gtk_entry_get_text (lv->title_entry);
@@ -260,9 +260,9 @@ lv_save_current_lot (GNCLotViewer *lv)
/* Get the notes, save the notes */
notes = xxxgtk_textview_get_text (lv->lot_notes);
gnc_lot_set_notes (lot, notes);
- g_free(notes);
+ g_free (notes);
- gnc_lot_commit_edit(lot);
+ gnc_lot_commit_edit (lot);
}
}
@@ -287,10 +287,10 @@ lv_unset_lot (GNCLotViewer *lv)
lv_clear_splits_in_lot (lv);
#ifdef LOTS_READY_FOR_SHOWTIME
- gtk_widget_set_sensitive(GTK_WIDGET(lv->regview_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->regview_button), FALSE);
#endif
- gtk_widget_set_sensitive(GTK_WIDGET(lv->delete_button), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(lv->scrub_lot_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->delete_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->scrub_lot_button), FALSE);
}
/* ======================================================================== */
@@ -320,10 +320,10 @@ lv_select_row (GNCLotViewer *lv,
lv_show_splits_in_lot (lv);
#ifdef LOTS_READY_FOR_SHOWTIME
- gtk_widget_set_sensitive(GTK_WIDGET(lv->regview_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->regview_button), TRUE);
#endif
- gtk_widget_set_sensitive(GTK_WIDGET(lv->delete_button), TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(lv->scrub_lot_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->delete_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->scrub_lot_button), TRUE);
}
/* ======================================================================== */
@@ -352,9 +352,9 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
lot_list = xaccAccountGetLotList (lv->account);
- selection = gtk_tree_view_get_selection(lv->lot_view);
+ selection = gtk_tree_view_get_selection (lv->lot_view);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
- gtk_tree_model_get(model, &iter, LOT_COL_PNTR, &selected_lot, -1);
+ gtk_tree_model_get (model, &iter, LOT_COL_PNTR, &selected_lot, -1);
/* Crazy. Should update in place if possible. */
gtk_list_store_clear (lv->lot_store);
@@ -371,31 +371,31 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
gnc_numeric gains_baln = get_realized_gains (lot, currency);
/* Skip closed lots when only open should be shown */
- if (TRUE == gtk_toggle_button_get_active(lv->only_show_open_lots_checkbutton) && gnc_lot_is_closed (lot))
+ if (TRUE == gtk_toggle_button_get_active (lv->only_show_open_lots_checkbutton) && gnc_lot_is_closed (lot))
{
continue;
}
store = lv->lot_store;
- gtk_list_store_append(store, &iter);
+ gtk_list_store_append (store, &iter);
/* Part of invoice */
type_buff[0] = '\0';
- if ( NULL != gncInvoiceGetInvoiceFromLot(lot) )
+ if ( NULL != gncInvoiceGetInvoiceFromLot (lot) )
{
- snprintf(type_buff, 200, "I");
+ snprintf (type_buff, 200, "I");
}
- gtk_list_store_set(store, &iter, LOT_COL_TYPE, type_buff, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_TYPE, type_buff, -1);
/* Opening date */
if (esplit)
{
Transaction *etrans = xaccSplitGetParent (esplit);
time64 open_date = xaccTransGetDate (etrans);
- gtk_list_store_set(store, &iter, LOT_COL_OPEN, open_date, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_OPEN, open_date, -1);
}
else
- gtk_list_store_set(store, &iter, LOT_COL_OPEN, G_MININT64, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_OPEN, G_MININT64, -1);
/* Closing date */
if (gnc_lot_is_closed (lot))
@@ -404,56 +404,56 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
Transaction *ftrans = xaccSplitGetParent (fsplit);
time64 close_date = xaccTransGetDate (ftrans);
- gtk_list_store_set(store, &iter, LOT_COL_CLOSE, close_date, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_CLOSE, close_date, -1);
}
else
{
- gtk_list_store_set(store, &iter, LOT_COL_CLOSE, G_MAXINT64, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_CLOSE, G_MAXINT64, -1);
}
/* Title */
- gtk_list_store_set(store, &iter, LOT_COL_TITLE, gnc_lot_get_title(lot), -1);
+ gtk_list_store_set (store, &iter, LOT_COL_TITLE, gnc_lot_get_title (lot), -1);
/* Amount */
xaccSPrintAmount (baln_buff, amt_baln,
gnc_account_print_info (lv->account, TRUE));
- gtk_list_store_set(store, &iter, LOT_COL_BALN, baln_buff, -1);
- gtk_list_store_set(store, &iter, LOT_COL_BALN_DOUBLE, gnc_numeric_to_double (amt_baln), -1);
+ gtk_list_store_set (store, &iter, LOT_COL_BALN, baln_buff, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_BALN_DOUBLE, gnc_numeric_to_double (amt_baln), -1);
/* Capital Gains/Losses Appreciation/Depreciation */
xaccSPrintAmount (gain_buff, gains_baln,
gnc_commodity_print_info (currency, TRUE));
- gtk_list_store_set(store, &iter, LOT_COL_GAINS, gain_buff, -1);
- gtk_list_store_set(store, &iter, LOT_COL_GAINS_DOUBLE, gnc_numeric_to_double (gains_baln), -1);
+ gtk_list_store_set (store, &iter, LOT_COL_GAINS, gain_buff, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_GAINS_DOUBLE, gnc_numeric_to_double (gains_baln), -1);
/* Self-reference */
- gtk_list_store_set(store, &iter, LOT_COL_PNTR, lot, -1);
+ gtk_list_store_set (store, &iter, LOT_COL_PNTR, lot, -1);
}
- g_list_free(lot_list);
+ g_list_free (lot_list);
/* re-select the row that the user had previously selected,
* if possible. */
if (selected_lot)
{
- model = GTK_TREE_MODEL(lv->lot_store);
- if (gtk_tree_model_get_iter_first(model, &iter))
+ model = GTK_TREE_MODEL (lv->lot_store);
+ if (gtk_tree_model_get_iter_first (model, &iter))
{
do
{
- gtk_tree_model_get(model, &iter, LOT_COL_PNTR, &this_lot, -1);
+ gtk_tree_model_get (model, &iter, LOT_COL_PNTR, &this_lot, -1);
if (this_lot == selected_lot)
{
- gtk_tree_selection_select_iter(selection, &iter);
+ gtk_tree_selection_select_iter (selection, &iter);
found = TRUE;
break;
}
}
- while (gtk_tree_model_iter_next(model, &iter));
+ while (gtk_tree_model_iter_next (model, &iter));
}
}
if (!found)
- gtk_tree_selection_unselect_all(selection);
+ gtk_tree_selection_unselect_all (selection);
}
/* ======================================================================== */
@@ -467,10 +467,10 @@ lv_get_selected_split (GNCLotViewer *lv, GtkTreeView *view)
GtkTreeSelection *selection;
GtkTreeIter iter;
- selection = gtk_tree_view_get_selection(view);
+ selection = gtk_tree_view_get_selection (view);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
- gtk_tree_model_get(model, &iter, SPLIT_COL_PNTR, &split, -1);
+ gtk_tree_model_get (model, &iter, SPLIT_COL_PNTR, &split, -1);
}
return split;
@@ -480,14 +480,14 @@ lv_get_selected_split (GNCLotViewer *lv, GtkTreeView *view)
/* Check if split is main invoice split in lot */
static gboolean
-lv_can_remove_split_from_lot(Split * split, GNCLot * lot)
+lv_can_remove_split_from_lot (Split * split, GNCLot * lot)
{
GncInvoice *lot_invoice, *txn_invoice;
Transaction *txn;
- lot_invoice = gncInvoiceGetInvoiceFromLot(lot);
- txn = xaccSplitGetParent(split);
- txn_invoice = gncInvoiceGetInvoiceFromTxn(txn);
+ lot_invoice = gncInvoiceGetInvoiceFromLot (lot);
+ txn = xaccSplitGetParent (split);
+ txn_invoice = gncInvoiceGetInvoiceFromTxn (txn);
if ( lot_invoice != NULL && lot_invoice == txn_invoice )
return FALSE;
@@ -503,7 +503,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
SplitList *node;
GtkTreeIter iter;
gboolean is_business_lot = FALSE;
- gnc_numeric baln = gnc_numeric_zero();
+ gnc_numeric baln = gnc_numeric_zero ();
if (lv->selected_lot)
is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (gnc_lot_get_account (lv->selected_lot)));
@@ -522,9 +522,9 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gnc_numeric amnt, value, gains;
/* Do not show gains splits, however do show empty business splits */
- if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount(split))) continue;
+ if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount (split))) continue;
- gtk_list_store_append(store, &iter);
+ gtk_list_store_append (store, &iter);
/* Date */
gtk_list_store_set (store, &iter, SPLIT_COL_DATE, date, -1);
@@ -557,7 +557,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
/* Gains. Blank if none. */
gains = xaccSplitGetCapGains (split);
- if (gnc_numeric_zero_p(gains))
+ if (gnc_numeric_zero_p (gains))
{
gainbuff[0] = 0;
}
@@ -571,7 +571,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
/* Balance of Gains */
baln = gnc_numeric_add_fixed (baln, amnt);
- if (gnc_numeric_zero_p(baln))
+ if (gnc_numeric_zero_p (baln))
{
balnbuff[0] = 0;
}
@@ -584,33 +584,33 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gtk_list_store_set (store, &iter, SPLIT_COL_BALANCE_DOUBLE, gnc_numeric_to_double (baln), -1);
/* Self-reference */
- gtk_list_store_set(store, &iter, SPLIT_COL_PNTR, split, -1);
+ gtk_list_store_set (store, &iter, SPLIT_COL_PNTR, split, -1);
}
}
/* ======================================================================== */
static void
-lv_update_split_buttons(GNCLotViewer *lv)
+lv_update_split_buttons (GNCLotViewer *lv)
{
- Split * split;
- gtk_widget_set_sensitive(GTK_WIDGET(lv->add_split_to_lot_button), FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(lv->remove_split_from_lot_button), FALSE);
+ Split *split;
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->add_split_to_lot_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->remove_split_from_lot_button), FALSE);
if (NULL != lv->selected_lot)
{
- if (NULL != lv_get_selected_split(lv, lv->split_free_view) )
+ if (NULL != lv_get_selected_split (lv, lv->split_free_view) )
{
- gtk_widget_set_sensitive(GTK_WIDGET(lv->add_split_to_lot_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->add_split_to_lot_button), TRUE);
}
- split = lv_get_selected_split(lv, lv->split_in_lot_view);
- if (NULL != split && TRUE == lv_can_remove_split_from_lot(split, lv->selected_lot))
+ split = lv_get_selected_split (lv, lv->split_in_lot_view);
+ if (NULL != split && TRUE == lv_can_remove_split_from_lot (split, lv->selected_lot))
{
- gtk_widget_set_sensitive(GTK_WIDGET(lv->remove_split_from_lot_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET(lv->remove_split_from_lot_button), TRUE);
}
}
}
-static void lv_refresh(GNCLotViewer * lv)
+static void lv_refresh (GNCLotViewer * lv)
{
gnc_lot_viewer_fill (lv);
lv_show_splits_free (lv);
@@ -633,7 +633,7 @@ lv_close_handler (gpointer user_data)
lv_save_current_lot (lv);
- gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(lv->window));
+ gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(lv->window));
gtk_widget_destroy (lv->window);
}
@@ -651,10 +651,10 @@ lv_title_entry_changed_cb (GtkEntry *ent, gpointer user_data)
const char * title;
title = gtk_entry_get_text (lv->title_entry);
- selection = gtk_tree_view_get_selection(lv->lot_view);
+ selection = gtk_tree_view_get_selection (lv->lot_view);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
- gtk_list_store_set(GTK_LIST_STORE(model), &iter, LOT_COL_TITLE, title, -1);
+ gtk_list_store_set (GTK_LIST_STORE(model), &iter, LOT_COL_TITLE, title, -1);
}
}
@@ -671,14 +671,14 @@ lv_selection_changed_cb (GtkTreeSelection *selection,
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
- gtk_tree_model_get(model, &iter, LOT_COL_PNTR, &lot, -1);
- lv_select_row(lv, lot);
+ gtk_tree_model_get (model, &iter, LOT_COL_PNTR, &lot, -1);
+ lv_select_row (lv, lot);
}
else
{
- lv_unselect_row(lv);
+ lv_unselect_row (lv);
}
- lv_update_split_buttons(lv);
+ lv_update_split_buttons (lv);
}
/* ======================================================================== */
@@ -696,7 +696,7 @@ static void
lv_split_selection_changed_cb (GtkTreeSelection *selection,
GNCLotViewer *lv)
{
- lv_update_split_buttons(lv);
+ lv_update_split_buttons (lv);
}
static void
@@ -705,16 +705,16 @@ lv_add_split_to_lot_cb (GtkWidget *widget, GNCLotViewer * lv)
Split *split;
if ( NULL == lv->selected_lot ) return;
- split = lv_get_selected_split(lv, lv->split_free_view);
+ split = lv_get_selected_split (lv, lv->split_free_view);
if ( NULL == split ) return;
- gnc_suspend_gui_refresh();
- xaccAccountBeginEdit(lv->account);
- gnc_lot_add_split(lv->selected_lot, split);
- xaccAccountCommitEdit(lv->account);
- gnc_resume_gui_refresh();
+ gnc_suspend_gui_refresh ();
+ xaccAccountBeginEdit (lv->account);
+ gnc_lot_add_split (lv->selected_lot, split);
+ xaccAccountCommitEdit (lv->account);
+ gnc_resume_gui_refresh ();
- lv_refresh(lv);
+ lv_refresh (lv);
}
static void
@@ -723,25 +723,25 @@ lv_remove_split_from_lot_cb (GtkWidget *widget, GNCLotViewer * lv)
Split *split;
if ( NULL == lv->selected_lot ) return;
- split = lv_get_selected_split(lv, lv->split_in_lot_view);
+ split = lv_get_selected_split (lv, lv->split_in_lot_view);
if ( NULL == split ) return;
- if ( FALSE == lv_can_remove_split_from_lot(split, lv->selected_lot) )
+ if ( FALSE == lv_can_remove_split_from_lot (split, lv->selected_lot) )
return;
- gnc_suspend_gui_refresh();
- xaccAccountBeginEdit(lv->account);
- gnc_lot_remove_split(lv->selected_lot, split);
- xaccAccountCommitEdit(lv->account);
- gnc_resume_gui_refresh();
+ gnc_suspend_gui_refresh ();
+ xaccAccountBeginEdit (lv->account);
+ gnc_lot_remove_split (lv->selected_lot, split);
+ xaccAccountCommitEdit (lv->account);
+ gnc_resume_gui_refresh ();
- lv_refresh(lv);
+ lv_refresh (lv);
}
static void
lv_only_show_open_lots_changed_cb (GtkWidget *widget, GNCLotViewer * lv)
{
- lv_refresh(lv);
+ lv_refresh (lv);
}
/* ======================================================================== */
@@ -769,9 +769,9 @@ lv_response_cb (GtkDialog *dialog, gint response, gpointer data)
if (NULL == lot)
return;
/* Prevent broken invoices */
- if (NULL != gncInvoiceGetInvoiceFromLot(lot))
+ if (NULL != gncInvoiceGetInvoiceFromLot (lot))
return;
- xaccAccountRemoveLot (gnc_lot_get_account(lot), lot);
+ xaccAccountRemoveLot (gnc_lot_get_account (lot), lot);
gnc_lot_destroy (lot);
lv_unset_lot (lv);
gnc_lot_viewer_fill (lv);
@@ -780,7 +780,7 @@ lv_response_cb (GtkDialog *dialog, gint response, gpointer data)
case RESPONSE_SCRUB_LOT:
if (NULL == lot)
return;
- if (xaccAccountIsAPARType (xaccAccountGetType(lv->account)))
+ if (xaccAccountIsAPARType (xaccAccountGetType (lv->account)))
gncScrubBusinessLot (lot);
else
xaccScrubLot (lot);
@@ -790,7 +790,7 @@ lv_response_cb (GtkDialog *dialog, gint response, gpointer data)
case RESPONSE_SCRUB_ACCOUNT:
gnc_suspend_gui_refresh ();
- if (xaccAccountIsAPARType (xaccAccountGetType(lv->account)))
+ if (xaccAccountIsAPARType (xaccAccountGetType (lv->account)))
gncScrubBusinessAccountLots (lv->account, gnc_window_show_progress);
else
xaccAccountScrubLots (lv->account);
@@ -891,70 +891,70 @@ lv_init_lot_view (GNCLotViewer *lv)
GtkTreeSelection *selection;
GtkCellRenderer *renderer;
- g_return_if_fail(GTK_IS_TREE_VIEW(lv->lot_view));
+ g_return_if_fail (GTK_IS_TREE_VIEW(lv->lot_view));
view = lv->lot_view;
- store = gtk_list_store_new(NUM_LOT_COLS, G_TYPE_STRING, G_TYPE_INT64,
- G_TYPE_INT64, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_DOUBLE,
- G_TYPE_STRING,G_TYPE_DOUBLE,
- G_TYPE_POINTER);
- gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
- g_object_unref(store);
+ store = gtk_list_store_new (NUM_LOT_COLS, G_TYPE_STRING, G_TYPE_INT64,
+ G_TYPE_INT64, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_DOUBLE,
+ G_TYPE_STRING,G_TYPE_DOUBLE,
+ G_TYPE_POINTER);
+ gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
+ g_object_unref (store);
lv->lot_store = store;
/* Set up the columns */
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Type"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Type"), renderer,
"text", LOT_COL_TYPE, NULL);
- gtk_tree_view_column_set_sort_column_id(column, LOT_COL_TYPE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_sort_column_id (column, LOT_COL_TYPE);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Opened"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Opened"), renderer,
"text", LOT_COL_OPEN, NULL);
- gtk_tree_view_column_set_sort_column_id(column, LOT_COL_OPEN);
+ gtk_tree_view_column_set_sort_column_id (column, LOT_COL_OPEN);
tree_view_column_set_default_width (view, column, "31-12-2013");
gtk_tree_view_column_set_cell_data_func (column, renderer,
(GtkTreeCellDataFunc) lot_print_date,
lot_get_open_date, NULL);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Closed"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Closed"), renderer,
"text", LOT_COL_CLOSE, NULL);
- gtk_tree_view_column_set_sort_column_id(column, LOT_COL_CLOSE);
+ gtk_tree_view_column_set_sort_column_id (column, LOT_COL_CLOSE);
tree_view_column_set_default_width (view, column, "31-12-2013");
gtk_tree_view_column_set_cell_data_func (column, renderer,
(GtkTreeCellDataFunc) lot_print_date,
lot_get_closing_date, NULL);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Title"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Title"), renderer,
"text", LOT_COL_TITLE, NULL);
- gtk_tree_view_column_set_sort_column_id(column, LOT_COL_TITLE);
+ gtk_tree_view_column_set_sort_column_id (column, LOT_COL_TITLE);
gtk_tree_view_column_set_expand (column, TRUE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Balance"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Balance"), renderer,
"text", LOT_COL_BALN, NULL);
configure_number_columns (column, renderer, LOT_COL_BALN_DOUBLE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Gains"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Gains"), renderer,
"text", LOT_COL_GAINS, NULL);
configure_number_columns (column, renderer, LOT_COL_GAINS_DOUBLE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
/* Set up signals */
- selection = gtk_tree_view_get_selection(view);
- g_signal_connect(selection, "changed",
- G_CALLBACK(lv_selection_changed_cb), lv);
- g_signal_connect(lv->only_show_open_lots_checkbutton, "toggled",
- G_CALLBACK(lv_only_show_open_lots_changed_cb), lv);
+ selection = gtk_tree_view_get_selection (view);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK(lv_selection_changed_cb), lv);
+ g_signal_connect (lv->only_show_open_lots_checkbutton, "toggled",
+ G_CALLBACK(lv_only_show_open_lots_changed_cb), lv);
}
@@ -968,37 +968,37 @@ lv_init_split_view (GNCLotViewer *lv, GtkTreeView *view)
GtkTreeSelection *selection;
GtkCellRenderer *renderer;
- g_return_val_if_fail(GTK_IS_TREE_VIEW(view), NULL);
+ g_return_val_if_fail (GTK_IS_TREE_VIEW(view), NULL);
- store = gtk_list_store_new(NUM_SPLIT_COLS, G_TYPE_INT64,
- G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_DOUBLE,
- G_TYPE_STRING, G_TYPE_DOUBLE,
- G_TYPE_STRING, G_TYPE_DOUBLE,
- G_TYPE_STRING, G_TYPE_DOUBLE,
- G_TYPE_POINTER);
- gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
- g_object_unref(store);
+ store = gtk_list_store_new (NUM_SPLIT_COLS, G_TYPE_INT64,
+ G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_DOUBLE,
+ G_TYPE_STRING, G_TYPE_DOUBLE,
+ G_TYPE_STRING, G_TYPE_DOUBLE,
+ G_TYPE_STRING, G_TYPE_DOUBLE,
+ G_TYPE_POINTER);
+ gtk_tree_view_set_model (view, GTK_TREE_MODEL(store));
+ g_object_unref (store);
/* Set up the columns */
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Date"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Date"), renderer,
"text", SPLIT_COL_DATE, NULL);
- gtk_tree_view_column_set_sort_column_id(column, SPLIT_COL_DATE);
+ gtk_tree_view_column_set_sort_column_id (column, SPLIT_COL_DATE);
tree_view_column_set_default_width (view, column, "31-12-2013");
gtk_tree_view_column_set_cell_data_func (column, renderer,
(GtkTreeCellDataFunc) print_date,
GINT_TO_POINTER (SPLIT_COL_DATE), NULL);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Num"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Num"), renderer,
"text", SPLIT_COL_NUM, NULL);
- gtk_tree_view_column_set_sort_column_id(column, SPLIT_COL_NUM);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_column_set_sort_column_id (column, SPLIT_COL_NUM);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Description"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Description"), renderer,
"text", SPLIT_COL_DESCRIPTION, NULL);
g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
@@ -1006,39 +1006,39 @@ lv_init_split_view (GNCLotViewer *lv, GtkTreeView *view)
width would be small, so set a minimum width */
gtk_tree_view_column_set_min_width (column, 200);
- gtk_tree_view_column_set_sort_column_id(column, SPLIT_COL_DESCRIPTION);
+ gtk_tree_view_column_set_sort_column_id (column, SPLIT_COL_DESCRIPTION);
gtk_tree_view_column_set_expand (column, TRUE);
gtk_tree_view_column_set_resizable (column, TRUE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Amount"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Amount"), renderer,
"text", SPLIT_COL_AMOUNT, NULL);
configure_number_columns (column, renderer, SPLIT_COL_AMOUNT_DOUBLE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Value"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Value"), renderer,
"text", SPLIT_COL_VALUE, NULL);
configure_number_columns (column, renderer, SPLIT_COL_VALUE_DOUBLE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Gain/Loss"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Gain/Loss"), renderer,
"text", SPLIT_COL_GAIN_LOSS, NULL);
configure_number_columns (column, renderer, SPLIT_COL_GAIN_LOSS_DOUBLE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Balance"), renderer,
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes (_("Balance"), renderer,
"text", SPLIT_COL_BALANCE, NULL);
configure_number_columns (column, renderer, SPLIT_COL_BALANCE_DOUBLE);
- gtk_tree_view_append_column(view, column);
+ gtk_tree_view_append_column (view, column);
/* Set up the selection callbacks */
- selection = gtk_tree_view_get_selection(view);
- g_signal_connect(selection, "changed",
- G_CALLBACK(lv_split_selection_changed_cb), lv);
+ selection = gtk_tree_view_get_selection (view);
+ g_signal_connect (selection, "changed",
+ G_CALLBACK(lv_split_selection_changed_cb), lv);
return store;
}
@@ -1054,10 +1054,10 @@ static void
lv_init_split_buttons (GNCLotViewer *lv)
{
/* Set up the add/remove callbacks */
- g_signal_connect(G_OBJECT(lv->add_split_to_lot_button), "clicked",
- G_CALLBACK(lv_add_split_to_lot_cb), lv);
- g_signal_connect(G_OBJECT(lv->remove_split_from_lot_button), "clicked",
- G_CALLBACK(lv_remove_split_from_lot_cb), lv);
+ g_signal_connect (G_OBJECT(lv->add_split_to_lot_button), "clicked",
+ G_CALLBACK(lv_add_split_to_lot_cb), lv);
+ g_signal_connect (G_OBJECT(lv->remove_split_from_lot_button), "clicked",
+ G_CALLBACK(lv_remove_split_from_lot_cb), lv);
}
/* ======================================================================== */
@@ -1078,7 +1078,7 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
gchar *win_title;
GtkBuilder *builder;
- builder = gtk_builder_new();
+ builder = gtk_builder_new ();
gnc_builder_add_from_file (builder, "dialog-lot-viewer.glade", "lot_viewer_dialog");
lv->window = GTK_WIDGET(gtk_builder_get_object (builder, "lot_viewer_dialog"));
@@ -1089,7 +1089,7 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
gtk_widget_set_name (GTK_WIDGET(lv->window), "gnc-id-lot-viewer");
win_title = g_strdup_printf (_("Lots in Account %s"),
- xaccAccountGetName(lv->account));
+ xaccAccountGetName (lv->account));
gtk_window_set_title (GTK_WINDOW (lv->window), win_title);
g_free (win_title);
@@ -1102,18 +1102,18 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
lv->lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "lot_view"));
lv->only_show_open_lots_checkbutton = GTK_TOGGLE_BUTTON(gtk_builder_get_object (builder, "only_show_open_lots_checkbutton"));
- lv_init_lot_view(lv);
+ lv_init_lot_view (lv);
lv->lot_notes = GTK_TEXT_VIEW(gtk_builder_get_object (builder, "lot_notes_text"));
lv->title_entry = GTK_ENTRY (gtk_builder_get_object (builder, "lot_title_entry"));
lv->split_in_lot_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "split_in_lot_view"));
lv->split_free_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "split_free_view"));
lv->split_hpaned = GTK_WIDGET(gtk_builder_get_object (builder, "split_hpaned"));
- lv_init_split_views(lv);
+ lv_init_split_views (lv);
lv->add_split_to_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "add_split_to_lot_button"));
lv->remove_split_from_lot_button = GTK_BUTTON(gtk_builder_get_object (builder, "remove_split_from_lot_button"));
- lv_init_split_buttons(lv);
+ lv_init_split_buttons (lv);
// Set grid lines option to preference
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(lv->lot_view), gnc_tree_view_get_grid_lines_pref ());
@@ -1125,7 +1125,7 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(lv->split_free_view), gnc_tree_view_get_grid_lines_pref ());
- if (gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_SAVE_GEOMETRY))
+ if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_SAVE_GEOMETRY))
{
GObject *object;
object = gtk_builder_get_object (builder, "lot_vpaned");
@@ -1142,12 +1142,12 @@ lv_create (GNCLotViewer *lv, GtkWindow *parent)
G_CALLBACK(window_realize_set_split_paned_position_cb), lv);
/* Setup signals */
- gtk_builder_connect_signals(builder, lv);
- g_object_unref(G_OBJECT(builder));
+ gtk_builder_connect_signals (builder, lv);
+ g_object_unref (G_OBJECT(builder));
- lv_update_split_buttons(lv);
+ lv_update_split_buttons (lv);
- gnc_restore_window_size(GNC_PREFS_GROUP, GTK_WINDOW(lv->window), parent);
+ gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(lv->window), parent);
}
/* ======================================================================== */
commit 28cdb77a0b6bcdbabaedf9e5d029ab67edff6fbb
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 19:28:59 2026 -0700
Improve code reuse
diff --git a/libgnucash/engine/cap-gains.cpp b/libgnucash/engine/cap-gains.cpp
index dea5e3c265..1b1241af40 100644
--- a/libgnucash/engine/cap-gains.cpp
+++ b/libgnucash/engine/cap-gains.cpp
@@ -486,48 +486,34 @@ xaccSplitAssign (Split *split)
/* ============================================================== */
-Split *
-xaccSplitGetCapGainsSplit (const Split *split)
+static Split *
+find_split_by_type (const gchar *type, const Split *split)
{
- GncGUID *gains_guid;
- Split *gains_split;
+ GncGUID *type_guid = nullptr;
if (!split) return nullptr;
- qof_instance_get (QOF_INSTANCE (split),
- "gains-split", &gains_guid,
- nullptr);
- if (!gains_guid) return nullptr;
+ qof_instance_get (QOF_INSTANCE (split), type, &type_guid, nullptr);
+ if (!type_guid) return nullptr;
/* Both splits will be in the same collection, so search there. */
- gains_split = (Split*) qof_collection_lookup_entity (
- qof_instance_get_collection(split), gains_guid);
- PINFO ("split=%p has gains-split=%p", split, gains_split);
- guid_free (gains_guid);
- return gains_split;
+ auto *guid_split = (Split *) qof_collection_lookup_entity (qof_instance_get_collection (split), type_guid);
+ PINFO ("split=%p has %s=%p", split, type, guid_split);
+ guid_free (type_guid);
+ return guid_split;
}
-/* ============================================================== */
Split *
-xaccSplitGetGainsSourceSplit (const Split *split)
+xaccSplitGetCapGainsSplit (const Split *split)
{
- GncGUID *source_guid;
- Split *source_split;
-
- if (!split) return nullptr;
-
- qof_instance_get (QOF_INSTANCE (split),
- "gains-source", &source_guid,
- nullptr);
- if (!source_guid) return nullptr;
+ return find_split_by_type ("gains-split", split);
+}
- /* Both splits will be in the same collection, so search there. */
- source_split = (Split*) qof_collection_lookup_entity(
- qof_instance_get_collection(split), source_guid);
- PINFO ("split=%p has source-split=%p", split, source_split);
- guid_free (source_guid);
- return source_split;
+Split *
+xaccSplitGetGainsSourceSplit (const Split *split)
+{
+ return find_split_by_type ("gains-source", split);
}
/* ============================================================== */
commit 1e654412abb64518a94c95002ea724e8af68096c
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 19:25:07 2026 -0700
use adjusted_amount in place of amount
impacts gains, lots, and policy
diff --git a/libgnucash/engine/cap-gains.cpp b/libgnucash/engine/cap-gains.cpp
index 92c493dcc6..dea5e3c265 100644
--- a/libgnucash/engine/cap-gains.cpp
+++ b/libgnucash/engine/cap-gains.cpp
@@ -298,7 +298,7 @@ xaccSplitAssignToLot (Split *split, GNCLot *lot)
* then we split the split into two pieces: one piece that will
* bring the lot balance to zero, and another to be dealt with
* later. */
- cmp = gnc_numeric_compare (gnc_numeric_abs(split->amount),
+ cmp = gnc_numeric_compare (gnc_numeric_abs(xaccSplitGetAdjustedAmount (split)),
gnc_numeric_abs(baln));
PINFO ("found open lot with baln=%s (%s)", gnc_num_dbg_to_string (baln),
@@ -331,6 +331,16 @@ xaccSplitAssignToLot (Split *split, GNCLot *lot)
trans = split->parent;
xaccTransBeginEdit (trans);
+ /* Adjust split's view of the lot balance for stock splits */
+ if (!gnc_numeric_equal (split->amount, xaccSplitGetAdjustedAmount (split)))
+ {
+ frac = gnc_numeric_div (split->amount, xaccSplitGetAdjustedAmount (split),
+ GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
+ baln = gnc_numeric_mul (baln, frac,
+ xaccAccountGetCommoditySCU(acc),
+ GNC_HOW_RND_ROUND_HALF_UP);
+ }
+
amt_tot = split->amount;
amt_a = gnc_numeric_neg (baln);
amt_b = gnc_numeric_sub_fixed (amt_tot, amt_a);
@@ -675,38 +685,38 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
* cleans up the lot, before we get at it!
*/
if (0 > gnc_numeric_compare (gnc_numeric_abs(lot_amount),
- gnc_numeric_abs(split->amount)))
+ gnc_numeric_abs(xaccSplitGetAdjustedAmount (split))))
{
GList *n;
for (n = gnc_lot_get_split_list(lot); n; n = n->next)
{
Split *s = GNC_SPLIT(n->data);
- PINFO ("split amt=%s", gnc_num_dbg_to_string(s->amount));
+ PINFO ("split adj amt=%s", gnc_num_dbg_to_string(xaccSplitGetAdjustedAmount (s)));
}
PERR ("Malformed Lot \"%s\"! (too thin!) "
- "opening amt=%s split amt=%s baln=%s",
+ "opening amt=%s split adj amt=%s baln=%s",
gnc_lot_get_title (lot),
gnc_num_dbg_to_string (lot_amount),
- gnc_num_dbg_to_string (split->amount),
+ gnc_num_dbg_to_string (xaccSplitGetAdjustedAmount (split)),
gnc_num_dbg_to_string (gnc_lot_get_balance(lot)));
return;
}
if ( (gnc_numeric_negative_p(lot_amount) ||
- gnc_numeric_positive_p(split->amount)) &&
+ gnc_numeric_positive_p(xaccSplitGetAdjustedAmount (split))) &&
(gnc_numeric_positive_p(lot_amount) ||
- gnc_numeric_negative_p(split->amount)))
+ gnc_numeric_negative_p(xaccSplitGetAdjustedAmount (split))))
{
GList *n;
for (n = gnc_lot_get_split_list(lot); n; n = n->next)
{
Split *s = GNC_SPLIT(n->data);
- PINFO ("split amt=%s", gnc_num_dbg_to_string(s->amount));
+ PINFO ("split adj amt=%s", gnc_num_dbg_to_string(xaccSplitGetAdjustedAmount (s)));
}
PERR ("Malformed Lot \"%s\"! (too fat!) "
- "opening amt=%s split amt=%s baln=%s",
+ "opening adj amt=%s split adj amt=%s baln=%s",
gnc_lot_get_title (lot),
gnc_num_dbg_to_string (lot_amount),
- gnc_num_dbg_to_string (split->amount),
+ gnc_num_dbg_to_string (xaccSplitGetAdjustedAmount (split)),
gnc_num_dbg_to_string (gnc_lot_get_balance(lot)));
return;
}
@@ -719,7 +729,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
* cap_gain = current_split_value - cost_basis
*/
/* Fraction of the lot that this split represents: */
- frac = gnc_numeric_div (split->amount, lot_amount,
+ frac = gnc_numeric_div (xaccSplitGetAdjustedAmount (split), lot_amount,
GNC_DENOM_AUTO,
GNC_HOW_DENOM_REDUCE);
/* Basis for this split: */
@@ -729,10 +739,10 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
/* Capital gain for this split: */
value = gnc_numeric_sub (value, split->value,
GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
- PINFO ("Open amt=%s val=%s; split amt=%s val=%s; gains=%s\n",
+ PINFO ("Open amt=%s val=%s; split adj amt=%s val=%s; gains=%s\n",
gnc_num_dbg_to_string (lot_amount),
gnc_num_dbg_to_string (lot_value),
- gnc_num_dbg_to_string (split->amount),
+ gnc_num_dbg_to_string (xaccSplitGetAdjustedAmount (split)),
gnc_num_dbg_to_string (split->value),
gnc_num_dbg_to_string (value));
if (gnc_numeric_check (value))
@@ -744,7 +754,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
xaccTransGetDescription(split->parent),
gnc_num_dbg_to_string (lot_amount),
gnc_num_dbg_to_string (lot_value),
- gnc_num_dbg_to_string (split->amount),
+ gnc_num_dbg_to_string (xaccSplitGetAdjustedAmount (split)),
gnc_num_dbg_to_string (split->value),
gnc_num_dbg_to_string (value));
return;
diff --git a/libgnucash/engine/gnc-lot.cpp b/libgnucash/engine/gnc-lot.cpp
index 8b83efbbac..b6269bd34c 100644
--- a/libgnucash/engine/gnc-lot.cpp
+++ b/libgnucash/engine/gnc-lot.cpp
@@ -505,7 +505,7 @@ gnc_lot_get_balance (GNCLot *lot)
for (node = priv->splits; node; node = node->next)
{
Split *s = GNC_SPLIT(node->data);
- gnc_numeric amt = xaccSplitGetAmount (s);
+ gnc_numeric amt = xaccSplitGetAdjustedAmount (s);
baln = gnc_numeric_add_fixed (baln, amt);
g_assert (gnc_numeric_check (baln) == GNC_ERROR_OK);
}
@@ -561,7 +561,7 @@ gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
if ((ta == tb && source != target) ||
xaccTransOrder (ta, tb) < 0)
{
- gnc_numeric tmpval = xaccSplitGetAmount (s);
+ gnc_numeric tmpval = xaccSplitGetAdjustedAmount (s);
amt = gnc_numeric_add_fixed (amt, tmpval);
tmpval = xaccSplitGetValue (s);
val = gnc_numeric_add_fixed (val, tmpval);
diff --git a/libgnucash/engine/policy.cpp b/libgnucash/engine/policy.cpp
index f67cc9d822..33346ef86e 100644
--- a/libgnucash/engine/policy.cpp
+++ b/libgnucash/engine/policy.cpp
@@ -119,7 +119,7 @@ static GNCLot *
FIFOPolicyGetLot (GNCPolicy *pcy, Split *split)
{
if (!split) return nullptr;
- return xaccAccountFindEarliestOpenLot (split->acc, split->amount,
+ return xaccAccountFindEarliestOpenLot (split->acc, xaccSplitGetAdjustedAmount (split),
split->parent->common_currency);
}
@@ -138,7 +138,7 @@ FIFOPolicyGetLotOpening (GNCPolicy *pcy,
Split *opening_split;
opening_split = gnc_lot_get_earliest_split(lot);
- if (ret_amount) *ret_amount = opening_split->amount;
+ if (ret_amount) *ret_amount = xaccSplitGetAdjustedAmount (opening_split);
if (ret_value) *ret_value = opening_split->value;
if (ret_currency) *ret_currency = opening_split->parent->common_currency;
}
commit b1eb12f558d8cbb1055e323667bcde3cbe3bb0d8
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 19:08:38 2026 -0700
Determine the adjusted_amount for each split in an account
The algorithm to determine the current adjusted_amount is implemented in xaccAccountRecomputeBalance().
If the balance or new balance is nil, the stock-split split is ignored as it isn't possible to calculate the stock-split ratio. This means the prior split adjusted amounts will not reflect the true current adjusted amounts. These are conditions that should be raised appropriately to the user with sufficient details for resolution.
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index 852d5ac674..134f468efb 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -2276,32 +2276,50 @@ xaccAccountMoveAllSplits (Account *accfrom, Account *accto)
void
xaccAccountRecomputeBalance (Account * acc)
{
- AccountPrivate *priv;
- gnc_numeric balance;
- gnc_numeric noclosing_balance;
- gnc_numeric cleared_balance;
- gnc_numeric reconciled_balance;
-
if (nullptr == acc) return;
- priv = GET_PRIVATE(acc);
+ auto priv = GET_PRIVATE(acc);
if (qof_instance_get_editlevel(acc) > 0) return;
if (!priv->balance_dirty || priv->defer_bal_computation) return;
if (qof_instance_get_destroying(acc)) return;
if (qof_book_shutting_down(qof_instance_get_book(acc))) return;
- balance = priv->starting_balance;
- noclosing_balance = priv->starting_noclosing_balance;
- cleared_balance = priv->starting_cleared_balance;
- reconciled_balance = priv->starting_reconciled_balance;
+ auto balance = priv->starting_balance;
+ auto noclosing_balance = priv->starting_noclosing_balance;
+ auto cleared_balance = priv->starting_cleared_balance;
+ auto reconciled_balance = priv->starting_reconciled_balance;
PINFO ("acct=%s starting baln=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT,
priv->accountName, balance.num, balance.denom);
for (auto split : priv->splits)
{
- gnc_numeric amt = xaccSplitGetAmount (split);
+ auto amt = xaccSplitGetAmount (split);
- balance = gnc_numeric_add_fixed(balance, amt);
+ if (xaccSplitIsStockSplit(split))
+ {
+ if (gnc_numeric_zero_p(balance))
+ continue;
+ auto new_balance = gnc_numeric_add_fixed(balance, amt);
+ if (gnc_numeric_zero_p(new_balance))
+ continue;
+ auto ratio = gnc_numeric_div(new_balance, balance, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_REDUCE);
+ auto denom = xaccAccountGetCommoditySCU(acc);
+ for (auto psplit : priv->splits)
+ {
+ if (psplit == split)
+ break;
+ xaccSplitSetAdjustedAmount(psplit,
+ gnc_numeric_mul(xaccSplitGetAdjustedAmount(psplit), ratio, denom,
+ GNC_HOW_RND_ROUND_HALF_UP));
+ }
+ balance = new_balance;
+ }
+ else
+ {
+ split->adjusted_amount = amt;
+ balance = gnc_numeric_add_fixed(balance, amt);
+ }
if (NREC != split->reconciled)
{
commit 254ec4b4d0268bce92bee13b8e6bb157ee7e5238
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Wed Jul 8 16:00:15 2026 -0700
Improve stock-split type detection
Noted split_type field in Split exists but is not used...
Reset split_type field's data type to hold the type of the getter.
Implemented xaccSplitIsStockSplit() abstraction to limit the split type string reference to Split.cpp and propagated it's use.
diff --git a/gnucash/register/ledger-core/split-register-model.c b/gnucash/register/ledger-core/split-register-model.c
index 34ed7d5a1f..e62e280b82 100644
--- a/gnucash/register/ledger-core/split-register-model.c
+++ b/gnucash/register/ledger-core/split-register-model.c
@@ -1546,7 +1546,7 @@ gnc_split_register_get_mxfrm_entry (VirtualLocation virt_loc,
if (s)
name = g_strdup (SPLIT_TRANS_STR);
- else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
+ else if (xaccSplitIsStockSplit (split))
name = g_strdup (STOCK_SPLIT_STR);
else
name = g_strdup ("");
@@ -1588,7 +1588,7 @@ gnc_split_register_get_mxfrm_help (VirtualLocation virt_loc,
if (s)
help = _ ("This transaction has multiple splits; "
"press the Split button to see them all");
- else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
+ else if (xaccSplitIsStockSplit (split))
help = _ ("This transaction is a stock split; "
"press the Split button to see details");
else
@@ -2080,7 +2080,7 @@ gnc_split_register_get_debcred_io_flags (VirtualLocation virt_loc,
split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
- if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
+ if (xaccSplitIsStockSplit (split))
return XACC_CELL_ALLOW_NONE;
return XACC_CELL_ALLOW_ALL;
diff --git a/libgnucash/engine/Split.cpp b/libgnucash/engine/Split.cpp
index f176e58722..368aeb1337 100644
--- a/libgnucash/engine/Split.cpp
+++ b/libgnucash/engine/Split.cpp
@@ -129,6 +129,7 @@ gnc_split_init(Split* split)
split->noclosing_balance = gnc_numeric_zero();
split->adjusted_amount = gnc_numeric_zero();
+ split->split_type = nullptr;
split->gains = GAINS_STATUS_UNKNOWN;
split->gains_split = nullptr;
@@ -523,6 +524,7 @@ xaccSplitReinit(Split * split)
split->noclosing_balance = gnc_numeric_zero();
split->adjusted_amount = gnc_numeric_zero();
+ split->split_type = nullptr;
qof_instance_set_idata(split, 0);
@@ -609,6 +611,7 @@ xaccSplitCloneNoKvp (const Split *s)
split->reconciled_balance = s->reconciled_balance;
split->noclosing_balance = s->noclosing_balance;
split->adjusted_amount = s->adjusted_amount;
+ split->split_type = s->split_type;
split->gains = GAINS_STATUS_UNKNOWN;
split->gains_split = nullptr;
@@ -695,6 +698,7 @@ xaccSplitDump (const Split *split, const char *tag)
gnc_numeric_to_string(split->reconciled_balance));
printf(" NoClose: %s\n", gnc_numeric_to_string(split->noclosing_balance));
printf(" AdjAmt: %s\n", gnc_numeric_to_string(split->adjusted_amount));
+ printf(" Type: %s\n", split->split_type ? split->split_type : "(null)");
printf(" idata: %x\n", qof_instance_get_idata(split));
}
#endif
@@ -756,6 +760,7 @@ xaccFreeSplit (Split *split)
split->orig_acc = nullptr;
split->adjusted_amount = gnc_numeric_zero();
+ split->split_type = nullptr;
split->date_reconciled = 0;
G_OBJECT_CLASS (QOF_INSTANCE_GET_CLASS (&split->inst))->dispose(G_OBJECT (split));
@@ -2028,20 +2033,25 @@ xaccSplitGetBook (const Split *split)
}
const char *
-xaccSplitGetType(const Split *s)
+xaccSplitGetType(Split *s)
{
if (!s) return nullptr;
- auto type{qof_instance_get_path_kvp<const char*> (QOF_INSTANCE(s), {"split-type"})};
-
- if (!type || !g_strcmp0 (*type, split_type_normal))
- return split_type_normal;
-
- if (!g_strcmp0 (*type, split_type_stock_split))
- return split_type_stock_split;
+ if (!s->split_type)
+ {
+ auto type{qof_instance_get_path_kvp<const char*> (QOF_INSTANCE(s), {"split-type"})};
- PERR ("unexpected split-type %s, reset to normal.", *type);
- return split_type_normal;
+ if (!type || !g_strcmp0 (*type, split_type_normal))
+ s->split_type = split_type_normal;
+ else if (!g_strcmp0 (*type, split_type_stock_split))
+ s->split_type = split_type_stock_split;
+ else
+ {
+ PERR ("unexpected split-type %s, reset to normal.", *type);
+ s->split_type = split_type_normal;
+ }
+ }
+ return s->split_type;
}
/* reconfigure a split to be a stock split - after this, you shouldn't
@@ -2052,6 +2062,7 @@ xaccSplitMakeStockSplit(Split *s)
xaccTransBeginEdit (s->parent);
s->value = gnc_numeric_zero();
+ s->split_type = split_type_stock_split;
qof_instance_set_path_kvp<const char*> (QOF_INSTANCE(s), g_strdup(split_type_stock_split),
{"split-type"});
SET_GAINS_VDIRTY(s);
@@ -2060,6 +2071,12 @@ xaccSplitMakeStockSplit(Split *s)
xaccTransCommitEdit(s->parent);
}
+gboolean
+xaccSplitIsStockSplit (Split *s)
+{
+ return g_strcmp0(split_type_stock_split, xaccSplitGetType(s)) == 0;
+}
+
void
xaccSplitAddPeerSplit (Split *split, const Split *other_split,
time64 timestamp)
diff --git a/libgnucash/engine/Split.h b/libgnucash/engine/Split.h
index a554874314..f6d4733f6d 100644
--- a/libgnucash/engine/Split.h
+++ b/libgnucash/engine/Split.h
@@ -428,12 +428,16 @@ gboolean xaccIsPeerSplit (const Split *split_1, const Split *split_2);
*/
/** Returns the split type, which is either the string "normal", or
* "stock-split" for a split from a stock split (pun intended? :-). */
-const char *xaccSplitGetType(const Split *s);
+const char *xaccSplitGetType(Split *s);
/** Mark a split to be of type stock split - after this, you shouldn't
modify the value anymore, just the amount. */
void xaccSplitMakeStockSplit(Split *s);
+/** Returns true if the split is of type stock split
+ */
+gboolean xaccSplitIsStockSplit(Split *s);
+
/**
* The xaccSplitOrder(sa,sb) method is useful for sorting.
* if sa and sb have different transactions, return their xaccTransOrder
diff --git a/libgnucash/engine/SplitP.hpp b/libgnucash/engine/SplitP.hpp
index 821775f736..cda33cc5f6 100644
--- a/libgnucash/engine/SplitP.hpp
+++ b/libgnucash/engine/SplitP.hpp
@@ -115,7 +115,7 @@ struct split_s
gnc_numeric value;
gnc_numeric amount;
- const gchar * split_type;
+ const char *split_type;
/* -------------------------------------------------------------- */
/* Below follow some 'temporary' fields */
diff --git a/libgnucash/engine/cap-gains.cpp b/libgnucash/engine/cap-gains.cpp
index e9b677ee7c..92c493dcc6 100644
--- a/libgnucash/engine/cap-gains.cpp
+++ b/libgnucash/engine/cap-gains.cpp
@@ -581,7 +581,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
return;
}
- if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
+ if (xaccSplitIsStockSplit (split))
{
LEAVE ("Stock split split, returning.");
return;
commit 0d5c74b868691ffd3e72bfae807e214eceb8c1db
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date: Sat Jul 4 09:58:50 2026 -0700
Add adjusted_amount field to split
The adjusted_amount field of a split will hold the stock split adjusted amount. The adjusted amount is initially the same as the original amount. When the account balances are recomputed and a stock-split split type is encountered, the ratio of the stock split will be applied to the preceding splits adjusted_amounts. If there are no stock splits in the split's account, the adjusted amount remains the original amount.
diff --git a/libgnucash/engine/Split.cpp b/libgnucash/engine/Split.cpp
index 1c042cac3e..f176e58722 100644
--- a/libgnucash/engine/Split.cpp
+++ b/libgnucash/engine/Split.cpp
@@ -128,6 +128,8 @@ gnc_split_init(Split* split)
split->reconciled_balance = gnc_numeric_zero();
split->noclosing_balance = gnc_numeric_zero();
+ split->adjusted_amount = gnc_numeric_zero();
+
split->gains = GAINS_STATUS_UNKNOWN;
split->gains_split = nullptr;
}
@@ -520,6 +522,8 @@ xaccSplitReinit(Split * split)
split->reconciled_balance = gnc_numeric_zero();
split->noclosing_balance = gnc_numeric_zero();
+ split->adjusted_amount = gnc_numeric_zero();
+
qof_instance_set_idata(split, 0);
split->gains = GAINS_STATUS_UNKNOWN;
@@ -604,6 +608,7 @@ xaccSplitCloneNoKvp (const Split *s)
split->cleared_balance = s->cleared_balance;
split->reconciled_balance = s->reconciled_balance;
split->noclosing_balance = s->noclosing_balance;
+ split->adjusted_amount = s->adjusted_amount;
split->gains = GAINS_STATUS_UNKNOWN;
split->gains_split = nullptr;
@@ -689,6 +694,7 @@ xaccSplitDump (const Split *split, const char *tag)
printf(" RBalance: %s\n",
gnc_numeric_to_string(split->reconciled_balance));
printf(" NoClose: %s\n", gnc_numeric_to_string(split->noclosing_balance));
+ printf(" AdjAmt: %s\n", gnc_numeric_to_string(split->adjusted_amount));
printf(" idata: %x\n", qof_instance_get_idata(split));
}
#endif
@@ -749,6 +755,8 @@ xaccFreeSplit (Split *split)
split->acc = nullptr;
split->orig_acc = nullptr;
+ split->adjusted_amount = gnc_numeric_zero();
+
split->date_reconciled = 0;
G_OBJECT_CLASS (QOF_INSTANCE_GET_CLASS (&split->inst))->dispose(G_OBJECT (split));
@@ -915,6 +923,9 @@ xaccSplitEqual(const Split *sa, const Split *sb,
if (!xaccSplitEqualCheckBal ("noclosing ", sa->noclosing_balance,
sb->noclosing_balance))
return FALSE;
+ if (!xaccSplitEqualCheckBal ("adjusted ", sa->adjusted_amount,
+ sb->adjusted_amount))
+ return FALSE;
}
if (!xaccTransEqual(sa->parent, sb->parent, check_guids, check_txn_splits,
@@ -1238,6 +1249,7 @@ xaccSplitSetAmount (Split *s, gnc_numeric amt)
}
else
s->amount = amt;
+ s->adjusted_amount = s->amount;
SET_GAINS_ADIRTY(s);
mark_split (s);
@@ -1316,6 +1328,21 @@ xaccSplitGetReconciledBalance (const Split *s)
return s ? s->reconciled_balance : gnc_numeric_zero();
}
+gnc_numeric
+xaccSplitGetAdjustedAmount (const Split *s)
+{
+ return s ? s->adjusted_amount : gnc_numeric_zero();
+}
+
+void
+xaccSplitSetAdjustedAmount (Split *s, gnc_numeric amt)
+{
+ if (!s) return;
+ if (gnc_numeric_check (amt)) return;
+
+ s->adjusted_amount = amt;
+}
+
void
xaccSplitSetBaseValue (Split *s, gnc_numeric value,
const gnc_commodity * base_currency)
diff --git a/libgnucash/engine/Split.h b/libgnucash/engine/Split.h
index 26fd6b01c3..a554874314 100644
--- a/libgnucash/engine/Split.h
+++ b/libgnucash/engine/Split.h
@@ -345,6 +345,16 @@ gnc_numeric xaccSplitGetClearedBalance (const Split *split);
*/
gnc_numeric xaccSplitGetReconciledBalance (const Split *split);
+/** Returns the stock-split adjusted amount of the split in the account's commodity.
+ */
+gnc_numeric xaccSplitGetAdjustedAmount (const Split *split);
+
+/** Sets the stock split adjusted amount of a split. Note: The adjusted amount
+ * will be reset when the account is rebalanced.
+ */
+void xaccSplitSetAdjustedAmount (Split *split, gnc_numeric amount);
+
+
/** @} */
/** @name Split utility functions
diff --git a/libgnucash/engine/SplitP.hpp b/libgnucash/engine/SplitP.hpp
index d13c2ffa1b..821775f736 100644
--- a/libgnucash/engine/SplitP.hpp
+++ b/libgnucash/engine/SplitP.hpp
@@ -128,6 +128,9 @@ struct split_s
gnc_numeric noclosing_balance;
gnc_numeric cleared_balance;
gnc_numeric reconciled_balance;
+
+ /* The stock-split adjusted amount */
+ gnc_numeric adjusted_amount;
};
struct _SplitClass
Summary of changes:
gnucash/gnome/dialog-lot-viewer.c | 536 +++++++++++----------
gnucash/gtkbuilder/dialog-lot-viewer.glade | 44 +-
.../register/ledger-core/split-register-copy-ops.c | 17 +-
.../register/ledger-core/split-register-copy-ops.h | 3 +
.../register/ledger-core/split-register-model.c | 6 +-
libgnucash/engine/Account.cpp | 77 ++-
libgnucash/engine/Account.h | 4 +
libgnucash/engine/AccountP.hpp | 1 +
libgnucash/engine/Scrub2.cpp | 33 +-
libgnucash/engine/Split.cpp | 73 ++-
libgnucash/engine/Split.h | 24 +-
libgnucash/engine/SplitP.hpp | 5 +-
libgnucash/engine/cap-gains.cpp | 230 +++++++--
libgnucash/engine/cap-gains.h | 14 +
libgnucash/engine/gnc-lot.cpp | 4 +-
libgnucash/engine/policy.cpp | 4 +-
libgnucash/engine/test/utest-Account.cpp | 7 +-
libgnucash/engine/test/utest-Split.cpp | 1 +
18 files changed, 694 insertions(+), 389 deletions(-)
More information about the gnucash-changes
mailing list