From d924e3f6248ba5f46b638f00845ae97757e23751 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sat, 3 Jun 2023 21:18:54 +0100 Subject: [PATCH] Register preference "Jump action for multiple splits" Make the behaviour when the "Jump" operation encounters a transaction with more than two splits configurable. This can be configured as: * Do nothing (this is the default) * Use the split with the largest value * Use the split with the smallest value This makes it much easier to jump between accounts for stock transactions that include splits for fees and taxes, or dividend transactions that have a zero value split for the stock account. --- gnucash/gnome/gnc-plugin-page-register.cpp | 84 +++++++++++- .../org.gnucash.GnuCash.gschema.xml.in | 13 +- gnucash/gtkbuilder/dialog-preferences.glade | 126 +++++++++++++++--- libgnucash/core-utils/gnc-prefs.h | 1 + 4 files changed, 199 insertions(+), 25 deletions(-) diff --git a/gnucash/gnome/gnc-plugin-page-register.cpp b/gnucash/gnome/gnc-plugin-page-register.cpp index 2069b40fc6..970d8f45b7 100644 --- a/gnucash/gnome/gnc-plugin-page-register.cpp +++ b/gnucash/gnome/gnc-plugin-page-register.cpp @@ -91,6 +91,14 @@ #include "qofbookslots.h" #include "gnc-gtk-utils.h" +/* gschema: org.gnucash.GnuCash.general.register.JumpMultipleSplits */ +typedef enum : gint +{ + JUMP_DEFAULT = 0, /* Do nothing */ + JUMP_LARGEST_VALUE_FIRST_SPLIT = 1, + JUMP_SMALLEST_VALUE_FIRST_SPLIT = 2, +} GncPrefJumpMultSplits; + /* This static indicates the debugging module that this .o belongs to. */ static QofLogModule log_module = GNC_MOD_GUI; @@ -4854,6 +4862,68 @@ gnc_plugin_page_register_cmd_exchange_rate (GSimpleAction *simple, LEAVE (" "); } +static Split* +jump_multiple_splits_by_value (Account *account, Split *split, gboolean largest) +{ + Transaction *trans; + SplitList *splits; + Split *other_split = NULL; + gnc_numeric best; + int cmp = largest ? 1 : -1; + + trans = xaccSplitGetParent(split); + if (!trans) + return NULL; + + for (splits = xaccTransGetSplitList(trans); splits; splits = splits->next) + { + Split *s = (Split*)splits->data; + gnc_numeric value; + + if (!xaccTransStillHasSplit(trans, s)) + continue; + + if (xaccSplitGetAccount(s) == account) + continue; + + value = gnc_numeric_abs(xaccSplitGetValue(s)); + if (gnc_numeric_check(value)) + continue; + + /* For splits with the same value as the best, the first split + * encountered is used. + */ + if (other_split && gnc_numeric_compare(value, best) != cmp) + continue; + + best = value; + other_split = s; + } + + return other_split; +} + +static Split* +jump_multiple_splits (Account* account, Split *split) +{ + GncPrefJumpMultSplits mode = (GncPrefJumpMultSplits)gnc_prefs_get_enum(GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_JUMP_MULT_SPLITS); + + switch (mode) + { + case JUMP_LARGEST_VALUE_FIRST_SPLIT: + return jump_multiple_splits_by_value (account, split, TRUE); + + case JUMP_SMALLEST_VALUE_FIRST_SPLIT: + return jump_multiple_splits_by_value (account, split, FALSE); + + case JUMP_DEFAULT: + default: + break; + } + + return NULL; +} + static void gnc_plugin_page_register_cmd_jump (GSimpleAction *simple, GVariant *paramter, @@ -4911,7 +4981,9 @@ gnc_plugin_page_register_cmd_jump (GSimpleAction *simple, * * If you've selected a split for this account, for consistency with * selecting the split of another account we should do nothing. - * You're already on the account for the split you selected. + * You're already on the account for the split you selected. Jumping + * to the "other" account now would make the "multiple split" + * options confusing. * * We could jump to a different anchoring split but that'll be very * subtle and only cause problems because it'll have to save any @@ -4921,13 +4993,19 @@ gnc_plugin_page_register_cmd_jump (GSimpleAction *simple, return; } - split = xaccSplitGetOtherSplit (split); - if (split == NULL) + Split* other_split = xaccSplitGetOtherSplit (split); + if (other_split == NULL) + { + other_split = jump_multiple_splits (account, split); + } + if (other_split == NULL) { LEAVE ("no split (2)"); return; } + split = other_split; + account = xaccSplitGetAccount (split); if (account == NULL) { diff --git a/gnucash/gschemas/org.gnucash.GnuCash.gschema.xml.in b/gnucash/gschemas/org.gnucash.GnuCash.gschema.xml.in index 933a6507c0..3d32c99b5a 100644 --- a/gnucash/gschemas/org.gnucash.GnuCash.gschema.xml.in +++ b/gnucash/gschemas/org.gnucash.GnuCash.gschema.xml.in @@ -235,6 +235,12 @@ + + + + + + true @@ -256,6 +262,11 @@ Move to Transfer field when memorised transaction auto filled If active then after a memorised transaction is automatically filled in the cursor will move to the Transfer field. If not active then it skips to the value field. + + 'default' + "Jump" behaviour when there are multiple splits + Select how the "Jump" operation should behave when a transaction has multiple splits. + false Create a new window for each new register @@ -337,7 +348,7 @@ This sets the number of characters before auto complete starts for description, notes and memo fields. - + false diff --git a/gnucash/gtkbuilder/dialog-preferences.glade b/gnucash/gtkbuilder/dialog-preferences.glade index ee6977bf9f..0545d7c32a 100644 --- a/gnucash/gtkbuilder/dialog-preferences.glade +++ b/gnucash/gtkbuilder/dialog-preferences.glade @@ -2578,7 +2578,9 @@ many months before the current month True False start - <b>Reconciling</b> + <b>Jump action for multiple splits</b> + Transaction jump action when there are more than two splits. + Transaction jump action when there are more than two splits. True @@ -2587,16 +2589,17 @@ many months before the current month - - Check cleared _transactions + + Do _nothing True True False True - Pre-check cleared transactions when creating a reconcile dialog. - Pre-check cleared transactions when creating a reconcile dialog. + Do nothing. + Do nothing. start True + True True @@ -2605,17 +2608,19 @@ many months before the current month - - Automatic credit card _payment + + Go to the first split with the _largest value True True False True - After reconciling a credit card statement, prompt the user to enter a credit card payment. - After reconciling a credit card statement, prompt the user to enter a credit card payment. + Use the first split with the largest value to determine the other account. + Use the first split with the largest value to determine the other account. start True + True True + pref/general.register/jump-multiple-splits=default 0 @@ -2623,17 +2628,19 @@ many months before the current month - - Always reconcile to t_oday + + Go to the first split with the _smallest value True True False True - Always open the reconcile dialog using today's date for the statement date, regardless of previous reconciliations. - Always open the reconcile dialog using today's date for the statement date, regardless of previous reconciliations. + Use the first split with the smallest value to determine the other account. + Use the first split with the smallest value to determine the other account. start True + True True + pref/general.register/jump-multiple-splits=default 0 @@ -2655,7 +2662,7 @@ many months before the current month True False start - <b>Graphics</b> + <b>Reconciling</b> True @@ -2663,6 +2670,83 @@ many months before the current month 10 + + + Check cleared _transactions + True + True + False + True + Pre-check cleared transactions when creating a reconcile dialog. + Pre-check cleared transactions when creating a reconcile dialog. + start + True + True + + + 0 + 11 + + + + + Automatic credit card _payment + True + True + False + True + After reconciling a credit card statement, prompt the user to enter a credit card payment. + After reconciling a credit card statement, prompt the user to enter a credit card payment. + start + True + True + + + 0 + 12 + + + + + Always reconcile to t_oday + True + True + False + True + Always open the reconcile dialog using today's date for the statement date, regardless of previous reconciliations. + Always open the reconcile dialog using today's date for the statement date, regardless of previous reconciliations. + start + True + True + + + 0 + 13 + + + + + True + False + + + 0 + 14 + + + + + True + False + start + <b>Graphics</b> + True + + + 0 + 15 + + _Use GnuCash built-in color theme @@ -2678,7 +2762,7 @@ many months before the current month 0 - 11 + 16 @@ -2696,7 +2780,7 @@ many months before the current month 0 - 12 + 17 @@ -2714,7 +2798,7 @@ many months before the current month 0 - 13 + 18 @@ -2732,7 +2816,7 @@ many months before the current month 0 - 14 + 19 @@ -2742,7 +2826,7 @@ many months before the current month 0 - 15 + 20 @@ -2757,7 +2841,7 @@ many months before the current month 0 - 16 + 21 @@ -2775,7 +2859,7 @@ many months before the current month 0 - 17 + 22 diff --git a/libgnucash/core-utils/gnc-prefs.h b/libgnucash/core-utils/gnc-prefs.h index 6e6a9f30f6..00549dd2e8 100644 --- a/libgnucash/core-utils/gnc-prefs.h +++ b/libgnucash/core-utils/gnc-prefs.h @@ -79,6 +79,7 @@ #define GNC_PREF_USE_GNUCASH_COLOR_THEME "use-gnucash-color-theme" #define GNC_PREF_TAB_TRANS_MEMORISED "tab-to-transfer-on-memorised" #define GNC_PREF_FUTURE_AFTER_BLANK "future-after-blank-transaction" +#define GNC_PREF_JUMP_MULT_SPLITS "jump-multiple-splits" /* Date preferences */ #define GNC_PREF_START_CHOICE_ABS "start-choice-absolute" #define GNC_PREF_START_CHOICE_REL "start-choice-relative"