From 002b391836a211756f92a9baef0a69ee97596dfc Mon Sep 17 00:00:00 2001 From: TianXing-Yi Date: Sat, 10 Jul 2021 20:02:32 +0800 Subject: [PATCH 01/29] In find customer dialog, add a column for "Shipping Contact" parameter --- gnucash/gnome/dialog-customer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gnucash/gnome/dialog-customer.c b/gnucash/gnome/dialog-customer.c index f356bfa172..560b54060c 100644 --- a/gnucash/gnome/dialog-customer.c +++ b/gnucash/gnome/dialog-customer.c @@ -930,6 +930,8 @@ gnc_customer_search (GtkWindow *parent, GncCustomer *start, QofBook *book) /* Build the column list in reverse order */ if (columns == NULL) { + columns = gnc_search_param_prepend (columns, _("Shipping Contact"), NULL, type, + CUSTOMER_SHIPADDR, ADDRESS_NAME, NULL); columns = gnc_search_param_prepend (columns, _("Contact"), NULL, type, CUSTOMER_ADDR, ADDRESS_NAME, NULL); columns = gnc_search_param_prepend (columns, _("Company"), NULL, type, From e4619fdae6eeb481faf2385a94a7ba8e21183a0d Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Tue, 24 Aug 2021 08:54:06 +0100 Subject: [PATCH 02/29] xml-backend: Don't try to close m_lockfd if it's not open m_lockfd is not initialised. If the file is locked then it will not be set before session_end and close() will be called on an uninitialised int. Initialise it to -1 in the class definition. Consistently use -1 instead of "< 0" or "< 1" as the definition of invalid. Always set it to -1 after closing it. --- libgnucash/backend/xml/gnc-xml-backend.cpp | 10 ++++++++-- libgnucash/backend/xml/gnc-xml-backend.hpp | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libgnucash/backend/xml/gnc-xml-backend.cpp b/libgnucash/backend/xml/gnc-xml-backend.cpp index 236afa80b4..d9e3c9d3da 100644 --- a/libgnucash/backend/xml/gnc-xml-backend.cpp +++ b/libgnucash/backend/xml/gnc-xml-backend.cpp @@ -171,8 +171,11 @@ GncXmlBackend::session_end() if (!m_linkfile.empty()) g_unlink (m_linkfile.c_str()); - if (m_lockfd > 0) + if (m_lockfd != -1) + { close (m_lockfd); + m_lockfd = -1; + } if (!m_lockfile.empty()) { @@ -643,7 +646,7 @@ GncXmlBackend::get_file_lock () m_lockfd = g_open (m_lockfile.c_str(), O_RDWR | O_CREAT | O_EXCL , S_IRUSR | S_IWUSR); - if (m_lockfd < 0) + if (m_lockfd == -1) { /* oops .. we can't create the lockfile .. */ switch (errno) @@ -708,6 +711,7 @@ GncXmlBackend::get_file_lock () set_error(ERR_BACKEND_LOCKED); g_unlink (linkfile.str().c_str()); close (m_lockfd); + m_lockfd = -1; g_unlink (m_lockfile.c_str()); return false; } @@ -721,6 +725,7 @@ GncXmlBackend::get_file_lock () set_message(msg + m_lockfile); g_unlink (linkfile.str().c_str()); close (m_lockfd); + m_lockfd = -1; g_unlink (m_lockfile.c_str()); return false; } @@ -730,6 +735,7 @@ GncXmlBackend::get_file_lock () set_error(ERR_BACKEND_LOCKED); g_unlink (linkfile.str().c_str()); close (m_lockfd); + m_lockfd = -1; g_unlink (m_lockfile.c_str()); return false; } diff --git a/libgnucash/backend/xml/gnc-xml-backend.hpp b/libgnucash/backend/xml/gnc-xml-backend.hpp index 1e6ff76e81..ab98a7b612 100644 --- a/libgnucash/backend/xml/gnc-xml-backend.hpp +++ b/libgnucash/backend/xml/gnc-xml-backend.hpp @@ -60,7 +60,7 @@ private: std::string m_dirname; std::string m_lockfile; std::string m_linkfile; - int m_lockfd; + int m_lockfd = -1; QofBook* m_book = nullptr; /* The primary, main open book */ }; From 066520829970fd14c45f953884e6aeeb7d4e1202 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Tue, 24 Aug 2021 09:01:16 +0100 Subject: [PATCH 03/29] xml-backend: Lock file is deleted even if the lock is not acquired The lock file is set in m_lockfile and then unlinked in session_end even if the lock was not acquired. Clear m_lockfile if locking was not successful. --- libgnucash/backend/xml/gnc-xml-backend.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libgnucash/backend/xml/gnc-xml-backend.cpp b/libgnucash/backend/xml/gnc-xml-backend.cpp index d9e3c9d3da..f6cb55a785 100644 --- a/libgnucash/backend/xml/gnc-xml-backend.cpp +++ b/libgnucash/backend/xml/gnc-xml-backend.cpp @@ -641,6 +641,7 @@ GncXmlBackend::get_file_lock () { /* oops .. file is locked by another user .. */ set_error(ERR_BACKEND_LOCKED); + m_lockfile.clear(); return false; } @@ -664,6 +665,7 @@ GncXmlBackend::get_file_lock () PWARN ("Unable to create the lockfile %s: %s", m_lockfile.c_str(), strerror(errno)); set_error(be_err); + m_lockfile.clear(); return false; } @@ -713,6 +715,7 @@ GncXmlBackend::get_file_lock () close (m_lockfd); m_lockfd = -1; g_unlink (m_lockfile.c_str()); + m_lockfile.clear(); return false; } @@ -727,6 +730,7 @@ GncXmlBackend::get_file_lock () close (m_lockfd); m_lockfd = -1; g_unlink (m_lockfile.c_str()); + m_lockfile.clear(); return false; } @@ -737,6 +741,7 @@ GncXmlBackend::get_file_lock () close (m_lockfd); m_lockfd = -1; g_unlink (m_lockfile.c_str()); + m_lockfile.clear(); return false; } From 047673a493690134eefa44b35e8b9317a2a75b12 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Thu, 2 Sep 2021 16:35:15 +0200 Subject: [PATCH 04/29] Small refactoring of scm config loading. - Remove and cleanup duplicate code - C++-ify - Run code in gnucash-cli commands related to reports. Users may want to load modified report code via config-user.scm which they want to access while executing cli commands --- gnucash/gnucash-commands.cpp | 6 ++- gnucash/gnucash-commands.hpp | 4 ++ gnucash/gnucash-core-app.cpp | 79 ++++++++---------------------------- gnucash/gnucash-core-app.hpp | 1 + gnucash/gnucash.cpp | 55 +------------------------ 5 files changed, 29 insertions(+), 116 deletions(-) diff --git a/gnucash/gnucash-commands.cpp b/gnucash/gnucash-commands.cpp index 488a93cb99..3a5edb8f36 100644 --- a/gnucash/gnucash-commands.cpp +++ b/gnucash/gnucash-commands.cpp @@ -30,6 +30,7 @@ #endif #include "gnucash-commands.hpp" +#include "gnucash-core-app.hpp" extern "C" { #include @@ -173,8 +174,7 @@ scm_run_report (void *data, scm_c_use_module ("gnucash reports"); gnc_report_init (); - // load_system_config(); - // load_user_config(); + Gnucash::gnc_load_scm_config(); gnc_prefs_init (); qof_event_suspend (); @@ -303,6 +303,7 @@ scm_report_show (void *data, scm_c_use_module ("gnucash app-utils"); scm_c_use_module ("gnucash reports"); gnc_report_init (); + Gnucash::gnc_load_scm_config(); if (!args->file_to_load.empty()) { @@ -334,6 +335,7 @@ scm_report_list ([[maybe_unused]] void *data, scm_c_use_module ("gnucash app-utils"); scm_c_use_module ("gnucash reports"); gnc_report_init (); + Gnucash::gnc_load_scm_config(); scm_call_1 (scm_c_eval_string ("gnc:cmdline-report-list"), scm_current_output_port ()); diff --git a/gnucash/gnucash-commands.hpp b/gnucash/gnucash-commands.hpp index 01511d5847..ae3607147b 100644 --- a/gnucash/gnucash-commands.hpp +++ b/gnucash/gnucash-commands.hpp @@ -40,5 +40,9 @@ namespace Gnucash { int report_list (void); int report_show (const bo_str& file_to_load, const bo_str& run_report); + + // A helper function to load scm config files (SYSCONFIGDIR/config + // and USERCONFIGDIR/config-user.scm) on demand + void gnc_load_scm_config(void); } #endif diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp index 8207d85bf3..4ecde0f7c7 100644 --- a/gnucash/gnucash-core-app.cpp +++ b/gnucash/gnucash-core-app.cpp @@ -86,25 +86,6 @@ gnc_print_unstable_message(void) << bl::format (bl::translate ("To find the last stable version, please refer to {1}")) % PACKAGE_URL << "\n"; } -static gboolean -try_load_config_array(const gchar *fns[]) -{ - gchar *filename; - int i; - - for (i = 0; fns[i]; i++) - { - filename = gnc_build_userdata_path(fns[i]); - if (gfec_try_load(filename)) - { - g_free(filename); - return TRUE; - } - g_free(filename); - } - return FALSE; -} - static void update_message(const gchar *msg) { @@ -112,52 +93,28 @@ update_message(const gchar *msg) g_message("%s", msg); } -static void -load_system_config(void) +void +Gnucash::gnc_load_scm_config (void) { - static int is_system_config_loaded = FALSE; - gchar *system_config_dir; - gchar *system_config; - - if (is_system_config_loaded) return; - - update_message("loading system configuration"); - system_config_dir = gnc_path_get_pkgsysconfdir(); - system_config = g_build_filename(system_config_dir, "config", nullptr); - is_system_config_loaded = gfec_try_load(system_config); - g_free(system_config_dir); - g_free(system_config); -} - -static void -load_user_config(void) -{ - /* Don't continue adding to this list. When 3.0 rolls around bump - the 2.4 files off the list. */ - static const gchar *saved_report_files[] = + static auto is_system_config_loaded = false; + if (!is_system_config_loaded) { - SAVED_REPORTS_FILE, SAVED_REPORTS_FILE_OLD_REV, NULL - }; - static const gchar *stylesheet_files[] = { "stylesheets-2.0", NULL}; - static int is_user_config_loaded = FALSE; - - if (is_user_config_loaded) - return; - else is_user_config_loaded = TRUE; - - update_message("loading user configuration"); - { - gchar *config_filename; - config_filename = g_build_filename (gnc_userconfig_dir (), - "config-user.scm", (char *)NULL); - gfec_try_load(config_filename); - g_free(config_filename); + update_message ("loading system scm configuration"); + auto system_config_dir = gnc_path_get_pkgsysconfdir (); + auto system_config = g_build_filename (system_config_dir, "config", nullptr); + is_system_config_loaded = gfec_try_load (system_config); + g_free (system_config_dir); + g_free (system_config); } - update_message("loading saved reports"); - try_load_config_array(saved_report_files); - update_message("loading stylesheets"); - try_load_config_array(stylesheet_files); + static auto is_user_config_loaded = false; + if (!is_user_config_loaded) + { + update_message("loading user scm configuration"); + auto config_filename = g_build_filename (gnc_userconfig_dir (), "config-user.scm", nullptr); + is_user_config_loaded = gfec_try_load (config_filename); + g_free (config_filename); + } } static void diff --git a/gnucash/gnucash-core-app.hpp b/gnucash/gnucash-core-app.hpp index ed61af1f28..9ff91af336 100644 --- a/gnucash/gnucash-core-app.hpp +++ b/gnucash/gnucash-core-app.hpp @@ -70,5 +70,6 @@ private: char *sys_locale = nullptr; }; +void gnc_load_scm_config(void); } #endif diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp index d7a76466a0..2ab37cb00f 100644 --- a/gnucash/gnucash.cpp +++ b/gnucash/gnucash.cpp @@ -73,56 +73,6 @@ namespace bl = boost::locale; static QofLogModule log_module = GNC_MOD_GUI; static gchar *userdata_migration_msg = NULL; -static void -update_message(const gchar *msg) -{ - gnc_update_splash_screen(msg, GNC_SPLASH_PERCENTAGE_UNKNOWN); - g_message("%s", msg); -} - -static void -load_system_config(void) -{ - static int is_system_config_loaded = FALSE; - gchar *system_config_dir; - gchar *system_config; - - if (is_system_config_loaded) return; - - update_message("loading system configuration"); - system_config_dir = gnc_path_get_pkgsysconfdir(); - system_config = g_build_filename(system_config_dir, "config", nullptr); - is_system_config_loaded = gfec_try_load(system_config); - g_free(system_config_dir); - g_free(system_config); -} - -static void -load_user_config(void) -{ - /* Don't continue adding to this list. When 3.0 rolls around bump - the 2.4 files off the list. */ - static const gchar *saved_report_files[] = - { - SAVED_REPORTS_FILE, SAVED_REPORTS_FILE_OLD_REV, NULL - }; - static const gchar *stylesheet_files[] = { "stylesheets-2.0", NULL}; - static int is_user_config_loaded = FALSE; - - if (is_user_config_loaded) - return; - else is_user_config_loaded = TRUE; - - update_message("loading user configuration"); - { - gchar *config_filename; - config_filename = g_build_filename (gnc_userconfig_dir (), - "config-user.scm", (char *)NULL); - gfec_try_load(config_filename); - g_free(config_filename); - } -} - static void load_gnucash_plugins() { @@ -207,11 +157,10 @@ scm_run_gnucash (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char ** load_gnucash_plugins(); load_gnucash_modules(); - /* Load the config before starting up the gui. This insures that + /* Load the scm config files before starting up the gui. This ensures that * custom reports have been read into memory before the Reports * menu is created. */ - load_system_config(); - load_user_config(); + Gnucash::gnc_load_scm_config(); /* Setting-up the report menu must come after the module loading but before the gui initializat*ion. */ From 849fdd59bcf8d829095a4b84e950122d0e4b08a5 Mon Sep 17 00:00:00 2001 From: TianXing_Yi Date: Thu, 2 Sep 2021 22:34:01 +0200 Subject: [PATCH 05/29] Translation update by TianXing_Yi using Weblate po/zh_CN.po: 99.7% (5353 of 5364 strings; 0 fuzzy) 0 failing checks (0.0%) Translation: GnuCash/Program (Chinese (Simplified)) Translate-URL: https://hosted.weblate.org/projects/gnucash/gnucash/zh_Hans/ Co-authored-by: TianXing_Yi --- po/zh_CN.po | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index e3f477f3c1..20ab90b99b 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -23,7 +23,7 @@ msgstr "" "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "cgi?product=GnuCash&component=Translations\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n" -"PO-Revision-Date: 2021-08-31 14:33+0000\n" +"PO-Revision-Date: 2021-09-02 06:33+0000\n" "Last-Translator: TianXing_Yi \n" "Language-Team: Chinese (Simplified) \n" @@ -9239,7 +9239,7 @@ msgstr "重新计算(_R)" #: gnucash/report/trep-engine.scm:168 gnucash/report/trep-engine.scm:956 #: gnucash/report/trep-engine.scm:1045 msgid "Account Name" -msgstr "科目名称" +msgstr "名称" #: gnucash/gnome-utils/gnc-tree-view-account.c:816 #: gnucash/gnome-utils/gnc-tree-view-split-reg.c:2919 @@ -11330,7 +11330,7 @@ msgstr "最大的几个月又回到过去。" msgid "" "Dates will be completed so that they are close to the current date. Enter " "the maximum number of months to go backwards in time when completing dates." -msgstr "录入月份和本月差值在限额内(小于等于),即本年;超出(大于)为明年。" +msgstr "相隔月数小于等于设定值为本年,大于设定值为明年。" #: gnucash/gschemas/org.gnucash.gschema.xml.in:180 msgid "Show Horizontal Grid Lines" @@ -15973,7 +15973,7 @@ msgstr "日期补全" #: gnucash/gtkbuilder/dialog-preferences.glade:1112 msgid "When a date is entered without year, it should be taken" -msgstr "输入的日期没有年份时,其应属于" +msgstr "没有年份的日期,其应属于" #: gnucash/gtkbuilder/dialog-preferences.glade:1128 msgid "" @@ -15984,9 +15984,7 @@ msgstr "日期年份补全为本年。" msgid "" "In a sliding 12-month window starting this\n" "many months before the current month" -msgstr "" -"从现在开始这个次数,它追溯到过去,\n" -"它被认为是那个月的12个月内的日期" +msgstr "相隔月数定年份" #: gnucash/gtkbuilder/dialog-preferences.glade:1165 msgid "Enter number of months." @@ -17356,7 +17354,7 @@ msgstr "GnuCash 每日提示" #: gnucash/gtkbuilder/dialog-totd.glade:26 msgid "_Previous" -msgstr "去年末(_P)" +msgstr "上一个(_P)" #: gnucash/gtkbuilder/dialog-totd.glade:41 msgid "_Next" From 82f70ffe00698c57034de421e5541c0b330eba4a Mon Sep 17 00:00:00 2001 From: Christian Wehling Date: Thu, 2 Sep 2021 22:34:01 +0200 Subject: [PATCH 06/29] Translation update by Christian Wehling using Weblate po/de.po: 99.8% (5357 of 5364 strings; 7 fuzzy) 250 failing checks (4.6%) Translation: GnuCash/Program (German) Translate-URL: https://hosted.weblate.org/projects/gnucash/gnucash/de/ Co-authored-by: Christian Wehling --- po/de.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/po/de.po b/po/de.po index a06d46b216..c47d41628d 100644 --- a/po/de.po +++ b/po/de.po @@ -36,7 +36,7 @@ msgstr "" "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "cgi?product=GnuCash&component=Translations\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n" -"PO-Revision-Date: 2021-08-16 20:35+0000\n" +"PO-Revision-Date: 2021-09-02 20:33+0000\n" "Last-Translator: Christian Wehling \n" "Language-Team: German \n" @@ -45,7 +45,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.8-dev\n" +"X-Generator: Weblate 4.8.1-dev\n" #: bindings/guile/commodity-table.scm:44 msgid "ALL NON-CURRENCY" @@ -17134,7 +17134,7 @@ msgstr "Zahl, Datum, Zeit" # erreichbar. Können wir das vereinheitlichen? #: gnucash/gtkbuilder/dialog-preferences.glade:1417 msgid "Perform account list _setup on new file" -msgstr "Bei neuer Datei erstellen: Konten_einrichtung anzeigen" +msgstr "Bei neuer Datei erstellen: Konten_einrichtung starten" #: gnucash/gtkbuilder/dialog-preferences.glade:1423 msgid "Present the new account list dialog when you choose File->New File." From 429a08069978f4c61df024f3b2dd5e1b680a3322 Mon Sep 17 00:00:00 2001 From: jean <27791933+jeanlaroche@users.noreply.github.com> Date: Sat, 4 Sep 2021 11:00:42 -0700 Subject: [PATCH 07/29] Revert be6fb1abe2b7fac27c4aefc4b32415bd1c73ab92 --- gnucash/import-export/import-backend.c | 100 ++++++++++++++++++++ gnucash/import-export/import-backend.h | 9 ++ gnucash/import-export/import-main-matcher.c | 30 +++++- gnucash/import-export/import-utilities.c | 23 +++++ gnucash/import-export/import-utilities.h | 11 +++ 5 files changed, 168 insertions(+), 5 deletions(-) diff --git a/gnucash/import-export/import-backend.c b/gnucash/import-export/import-backend.c index 60b01459bc..8e409e6fb1 100644 --- a/gnucash/import-export/import-backend.c +++ b/gnucash/import-export/import-backend.c @@ -1048,6 +1048,106 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap, return FALSE; } +/********************************************************************\ + * check_trans_online_id() Callback function used by + * gnc_import_exists_online_id. Takes pointers to transaction and split, + * returns 0 if their online_ids do NOT match, or if the split + * belongs to the transaction +\********************************************************************/ +static gint check_trans_online_id(Transaction *trans1, void *user_data) +{ + Account *account; + Split *split1; + Split *split2 = user_data; + const gchar *online_id1; + const gchar *online_id2; + + account = xaccSplitGetAccount(split2); + split1 = xaccTransFindSplitByAccount(trans1, account); + if (split1 == split2) + return 0; + + /* hack - we really want to iterate over the _splits_ of the account + instead of the transactions */ + g_assert(split1 != NULL); + + if (gnc_import_split_has_online_id(split1)) + online_id1 = gnc_import_get_split_online_id(split1); + else + online_id1 = gnc_import_get_trans_online_id(trans1); + + online_id2 = gnc_import_get_split_online_id(split2); + + if ((online_id1 == NULL) || + (online_id2 == NULL) || + (strcmp(online_id1, online_id2) != 0)) + { + return 0; + } + else + { + /*printf("test_trans_online_id(): Duplicate found\n");*/ + return 1; + } +} + +static gint collect_trans_online_id(Transaction *trans, void *user_data) +{ + Split *split; + GHashTable *id_hash = user_data; + int i=0; + + const gchar* online_id = gnc_import_get_trans_online_id (trans); + if (online_id) + g_hash_table_add (id_hash, (void*) online_id); + + for (GList *splits = xaccTransGetSplitList (trans); splits; splits = splits->next) + { + if (gnc_import_split_has_online_id (splits->data)) + g_hash_table_add(id_hash, (void*) gnc_import_get_split_online_id (splits->data)); + } + return 0; +} + +/** Checks whether the given transaction's online_id already exists in + its parent account. */ +gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_hash) +{ + gboolean online_id_exists = FALSE; + Account *dest_acct; + Split *source_split; + + /* Look for an online_id in the first split */ + source_split = xaccTransGetSplit(trans, 0); + g_assert(source_split); + + // No online id, no point in continuing. We'd crash if we tried. + if (!gnc_import_get_split_online_id (source_split)) + return FALSE; + // Create a hash per account of a hash of all transactions IDs. Then the test below will be fast if + // we have many transactions to import. + dest_acct = xaccSplitGetAccount (source_split); + if (!g_hash_table_contains (acct_id_hash, dest_acct)) + { + GHashTable* new_hash = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (acct_id_hash, dest_acct, new_hash); + xaccAccountForEachTransaction (dest_acct, collect_trans_online_id, new_hash); + } + online_id_exists = g_hash_table_contains (g_hash_table_lookup (acct_id_hash, dest_acct), + gnc_import_get_split_online_id (source_split)); + + /* If it does, abort the process for this transaction, since it is + already in the system. */ + if (online_id_exists == TRUE) + { + DEBUG("%s", "Transaction with same online ID exists, destroying current transaction"); + xaccTransDestroy(trans); + xaccTransCommitEdit(trans); + } + return online_id_exists; +} + + /* ****************************************************************** */ diff --git a/gnucash/import-export/import-backend.h b/gnucash/import-export/import-backend.h index 69cd2bc995..b524d18359 100644 --- a/gnucash/import-export/import-backend.h +++ b/gnucash/import-export/import-backend.h @@ -57,6 +57,15 @@ typedef enum _action /** @name Non-GUI Functions */ /*@{*/ +/** Checks whether the given transaction's online_id already exists in + * its parent account. The given transaction has to be open for + * editing. If a matching online_id exists, the transaction is + * destroyed (!) and TRUE is returned, otherwise FALSE is returned. + * + * @param trans The transaction for which to check for an existing + * online_id. */ +gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_hash); + /** Evaluates the match between trans_info and split using the provided parameters. * * @param trans_info The TransInfo for the imported transaction diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c index ff779eeaee..e6c9df3611 100644 --- a/gnucash/import-export/import-main-matcher.c +++ b/gnucash/import-export/import-main-matcher.c @@ -76,6 +76,7 @@ struct _main_matcher_info gboolean add_toggled; // flag to indicate that add has been toggled to stop selection gint id; GSList* temp_trans_list; // Temporary list of imported transactions + GHashTable* acct_id_hash; // Hash table, per account, of list of transaction IDs. GSList* edited_accounts; // List of accounts currently edited. }; @@ -143,6 +144,14 @@ static gboolean query_tooltip_tree_view_cb (GtkWidget *widget, gint x, gint y, gpointer user_data); /* end local prototypes */ +static +gboolean delete_hash (gpointer key, gpointer value, gpointer user_data) +{ + // Value is a hash table that needs to be destroyed. + g_hash_table_destroy (value); + return TRUE; +} + static void update_all_balances (GNCImportMainMatcher *info) { @@ -209,6 +218,8 @@ gnc_gen_trans_list_delete (GNCImportMainMatcher *info) // We've deferred balance computations on many accounts. Let's do it now that we're done. update_all_balances (info); + g_hash_table_foreach_remove (info->acct_id_hash, delete_hash, NULL); + info->acct_id_hash = NULL; g_free (info); } @@ -1133,6 +1144,8 @@ gnc_gen_trans_init_view (GNCImportMainMatcher *info, G_CALLBACK(gnc_gen_trans_onButtonPressed_cb), info); g_signal_connect (view, "popup-menu", G_CALLBACK(gnc_gen_trans_onPopupMenu_cb), info); + + info->acct_id_hash = g_hash_table_new (g_direct_hash, g_direct_equal); } static void @@ -1713,11 +1726,16 @@ gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transaction g_assert (gui); g_assert (trans); - transaction_info = gnc_import_TransInfo_new (trans, NULL); - gnc_import_TransInfo_set_ref_id (transaction_info, ref_id); - // It's much faster to gather the imported transactions into a GSList than directly into the - // treeview. - gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info); + if (gnc_import_exists_online_id (trans, gui->acct_id_hash)) + return; + else + { + transaction_info = gnc_import_TransInfo_new (trans, NULL); + gnc_import_TransInfo_set_ref_id (transaction_info, ref_id); + // It's much faster to gather the imported transactions into a GSList than directly into the + // treeview. + gui->temp_trans_list = g_slist_prepend (gui->temp_trans_list, transaction_info); + } return; } @@ -1781,6 +1799,8 @@ create_hash_of_potential_matches (GList *candidate_txns, { Account* split_account; GSList* split_list; + if (gnc_import_split_has_online_id (candidate->data)) + continue; split_account = xaccSplitGetAccount (candidate->data); /* g_hash_table_steal_extended would do the two calls in one shot but is * not available until GLib 2.58. diff --git a/gnucash/import-export/import-utilities.c b/gnucash/import-export/import-utilities.c index 4be49b323f..8d672d4e0e 100644 --- a/gnucash/import-export/import-utilities.c +++ b/gnucash/import-export/import-utilities.c @@ -57,6 +57,29 @@ void gnc_import_set_acc_online_id (Account *account, const gchar *id) xaccAccountCommitEdit (account); } +const gchar * gnc_import_get_trans_online_id (Transaction * transaction) +{ + gchar *id = NULL; + qof_instance_get (QOF_INSTANCE (transaction), "online-id", &id, NULL); + return id; +} +/* Not actually used */ +void gnc_import_set_trans_online_id (Transaction *transaction, + const gchar *id) +{ + g_return_if_fail (transaction != NULL); + xaccTransBeginEdit (transaction); + qof_instance_set (QOF_INSTANCE (transaction), "online-id", id, NULL); + xaccTransCommitEdit (transaction); +} + +gboolean gnc_import_trans_has_online_id(Transaction * transaction) +{ + const gchar * online_id; + online_id = gnc_import_get_trans_online_id(transaction); + return (online_id != NULL && strlen(online_id) > 0); +} + const gchar * gnc_import_get_split_online_id (Split * split) { gchar *id = NULL; diff --git a/gnucash/import-export/import-utilities.h b/gnucash/import-export/import-utilities.h index a39d641571..1ef733d8b5 100644 --- a/gnucash/import-export/import-utilities.h +++ b/gnucash/import-export/import-utilities.h @@ -49,6 +49,17 @@ const gchar * gnc_import_get_acc_online_id(Account * account); void gnc_import_set_acc_online_id(Account * account, const gchar * string_value); /** @} */ +/** @name Setter-getters + Setter and getter functions for the online_id field for + Transactions. + @{ +*/ +const gchar * gnc_import_get_trans_online_id(Transaction * transaction); +void gnc_import_set_trans_online_id(Transaction * transaction, + const gchar * string_value); +/** @} */ + +gboolean gnc_import_trans_has_online_id(Transaction * transaction); /** @name Setter-getters Setter and getter functions for the online_id field for From d3a056d1ca4fd64a26f19b0313cfae3810af3b7a Mon Sep 17 00:00:00 2001 From: jean <27791933+jeanlaroche@users.noreply.github.com> Date: Sat, 4 Sep 2021 15:25:11 -0700 Subject: [PATCH 08/29] During transaction import, ignore splits whose account is not the destination account --- gnucash/import-export/import-backend.c | 27 +++++++------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/gnucash/import-export/import-backend.c b/gnucash/import-export/import-backend.c index 8e409e6fb1..d9f86f6cce 100644 --- a/gnucash/import-export/import-backend.c +++ b/gnucash/import-export/import-backend.c @@ -1091,24 +1091,6 @@ static gint check_trans_online_id(Transaction *trans1, void *user_data) } } -static gint collect_trans_online_id(Transaction *trans, void *user_data) -{ - Split *split; - GHashTable *id_hash = user_data; - int i=0; - - const gchar* online_id = gnc_import_get_trans_online_id (trans); - if (online_id) - g_hash_table_add (id_hash, (void*) online_id); - - for (GList *splits = xaccTransGetSplitList (trans); splits; splits = splits->next) - { - if (gnc_import_split_has_online_id (splits->data)) - g_hash_table_add(id_hash, (void*) gnc_import_get_split_online_id (splits->data)); - } - return 0; -} - /** Checks whether the given transaction's online_id already exists in its parent account. */ gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_hash) @@ -1124,14 +1106,19 @@ gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_ha // No online id, no point in continuing. We'd crash if we tried. if (!gnc_import_get_split_online_id (source_split)) return FALSE; - // Create a hash per account of a hash of all transactions IDs. Then the test below will be fast if + // Create a hash per account of a hash of all split IDs. Then the test below will be fast if // we have many transactions to import. dest_acct = xaccSplitGetAccount (source_split); if (!g_hash_table_contains (acct_id_hash, dest_acct)) { GHashTable* new_hash = g_hash_table_new (g_str_hash, g_str_equal); + GList* split_list = xaccAccountGetSplitList(dest_acct); g_hash_table_insert (acct_id_hash, dest_acct, new_hash); - xaccAccountForEachTransaction (dest_acct, collect_trans_online_id, new_hash); + for (;split_list;split_list=split_list->next) + { + if (gnc_import_split_has_online_id (split_list->data)) + g_hash_table_add (new_hash, (void*) gnc_import_get_split_online_id (split_list->data)); + } } online_id_exists = g_hash_table_contains (g_hash_table_lookup (acct_id_hash, dest_acct), gnc_import_get_split_online_id (source_split)); From 4afe5d83cfb1c495cc6f21f2d6f36d646eb78278 Mon Sep 17 00:00:00 2001 From: Christian Wehling Date: Sun, 5 Sep 2021 23:35:18 +0200 Subject: [PATCH 09/29] Translation update by Christian Wehling using Weblate po/de.po: 99.8% (5358 of 5364 strings; 6 fuzzy) 250 failing checks (4.6%) Translation: GnuCash/Program (German) Translate-URL: https://hosted.weblate.org/projects/gnucash/gnucash/de/ Co-authored-by: Christian Wehling --- po/de.po | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/po/de.po b/po/de.po index c47d41628d..42e40c6b67 100644 --- a/po/de.po +++ b/po/de.po @@ -36,7 +36,7 @@ msgstr "" "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "cgi?product=GnuCash&component=Translations\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n" -"PO-Revision-Date: 2021-09-02 20:33+0000\n" +"PO-Revision-Date: 2021-09-05 21:35+0000\n" "Last-Translator: Christian Wehling \n" "Language-Team: German \n" @@ -18328,7 +18328,7 @@ msgstr "Voreinstellungen Buchungseditor" #: gnucash/gtkbuilder/dialog-sx.glade:545 msgid "_Run when data file opened" -msgstr "Seit-Letztem-Aufruf Fenster starten, wenn eine _Datei geöffnet wird" +msgstr "Ausführen, wenn eine _Datei geöffnet wird" #: gnucash/gtkbuilder/dialog-sx.glade:549 msgid "Run the \"since last run\" process when a file is opened." @@ -18388,10 +18388,8 @@ msgid "R_emind in advance" msgstr "Im Voraus er_innern" #: gnucash/gtkbuilder/dialog-sx.glade:724 -#, fuzzy -#| msgid "_Review created transactions" msgid "Set 'Re_view Created Transactions' as default" -msgstr "Erzeugte Buchungen _durchsehen" +msgstr "'Erstellte _Buchungen durchsehen' als Standard festlegen" #: gnucash/gtkbuilder/dialog-sx.glade:728 msgid "" From 4e9fe0a4d1a611e9e4b3e68de02316e231070d28 Mon Sep 17 00:00:00 2001 From: jean <27791933+jeanlaroche@users.noreply.github.com> Date: Sun, 5 Sep 2021 17:52:34 -0700 Subject: [PATCH 10/29] Add missing function to mock account --- libgnucash/engine/mocks/gmock-Account.cpp | 9 +++++++++ libgnucash/engine/mocks/gmock-Account.h | 1 + 2 files changed, 10 insertions(+) diff --git a/libgnucash/engine/mocks/gmock-Account.cpp b/libgnucash/engine/mocks/gmock-Account.cpp index b4dd7d28fc..aea26ed818 100644 --- a/libgnucash/engine/mocks/gmock-Account.cpp +++ b/libgnucash/engine/mocks/gmock-Account.cpp @@ -60,6 +60,15 @@ xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, return mockaccount ? mockaccount->for_each_transaction(proc, data) : 0; } +SplitList * +xaccAccountGetSplitList (const Account *account) +{ + SCOPED_TRACE(""); + auto mockaccount = gnc_mockaccount(account); + return mockaccount ? mockaccount->xaccAccountGetSplitList() : nullptr; +} + + GncImportMatchMap * gnc_account_imap_create_imap (Account *acc) { diff --git a/libgnucash/engine/mocks/gmock-Account.h b/libgnucash/engine/mocks/gmock-Account.h index 6b7bbaefa3..07a249b1e2 100644 --- a/libgnucash/engine/mocks/gmock-Account.h +++ b/libgnucash/engine/mocks/gmock-Account.h @@ -43,6 +43,7 @@ public: MOCK_METHOD0(commit_edit, void()); MOCK_CONST_METHOD0(get_book, QofBook*()); MOCK_CONST_METHOD2(for_each_transaction, gint(TransactionCallback, void*)); + MOCK_CONST_METHOD0(xaccAccountGetSplitList, SplitList*()); MOCK_METHOD0(create_imap, GncImportMatchMap*()); protected: From 068a5d2fa8f2a9658b4b5ffb0a8821adf58d09f3 Mon Sep 17 00:00:00 2001 From: Mike Alexander Date: Mon, 6 Sep 2021 02:45:37 -0400 Subject: [PATCH 11/29] Fix xaccSplitGetOtherSplit which was broken by 028bf9826, don't count splits that aren't really in the transaction. The rewrite left out one test. This was most obvious in the dummy transaction used to enter a new transaction into an account. xaccSplitGetOtherSplit never returned an "other split" for this transaction. It turns out the old code was broken too, but it worked for this case by coincidence. --- libgnucash/engine/Split.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libgnucash/engine/Split.c b/libgnucash/engine/Split.c index d771e1f8bf..31ede94c61 100644 --- a/libgnucash/engine/Split.c +++ b/libgnucash/engine/Split.c @@ -2107,6 +2107,7 @@ xaccSplitGetOtherSplit (const Split *split) { Split *s = n->data; if ((s == split) || + (!xaccTransStillHasSplit(trans, s)) || (xaccAccountGetType (xaccSplitGetAccount (s)) == ACCT_TYPE_TRADING) || (qof_instance_has_slot (QOF_INSTANCE (s), "lot-split"))) continue; From 38cd06e54a016f6d039ff97ecffaf4c0f8eb7191 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Mon, 6 Sep 2021 15:18:34 -0700 Subject: [PATCH 12/29] Remove the lock-file-link-count test from the XML backend. This was an effort of somewhat dubious value to detect if a process on another ocmputer had a hsrd-link to a lockfile on an NFS share. NFS is rarely used now and SMB doesn't support hard links so this check adds complexity with no real value. --- libgnucash/backend/xml/gnc-xml-backend.cpp | 83 ---------------------- 1 file changed, 83 deletions(-) diff --git a/libgnucash/backend/xml/gnc-xml-backend.cpp b/libgnucash/backend/xml/gnc-xml-backend.cpp index f6cb55a785..8b8a3059f1 100644 --- a/libgnucash/backend/xml/gnc-xml-backend.cpp +++ b/libgnucash/backend/xml/gnc-xml-backend.cpp @@ -669,90 +669,7 @@ GncXmlBackend::get_file_lock () return false; } - /* OK, now work around some NFS atomic lock race condition - * mumbo-jumbo. We do this by linking a unique file, and - * then examining the link count. At least that's what the - * NFS programmers guide suggests. - * Note: the "unique filename" must be unique for the - * triplet filename-host-process, otherwise accidental - * aliases can occur. - */ - - /* apparently, even this code may not work for some NFS - * implementations. In the long run, I am told that - * ftp.debian.org - * /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz - * provides a better long-term solution. - */ - -#ifndef G_OS_WIN32 - auto path = m_lockfile.find_last_of('.'); - std::stringstream linkfile; - if (path != std::string::npos) - linkfile << m_lockfile.substr(0, path); - else - linkfile << m_lockfile; - linkfile << "." << gethostid() << "." << getpid() << ".LNK"; - rc = link (m_lockfile.c_str(), linkfile.str().c_str()); - if (rc) - { - /* If hard links aren't supported, just allow the lock. */ - if (errno == EPERM || errno == ENOSYS -# ifdef EOPNOTSUPP - || errno == EOPNOTSUPP -# endif -# ifdef ENOTSUP - || errno == ENOTSUP -# endif - ) - { - return true; - } - - /* Otherwise, something else is wrong. */ - set_error(ERR_BACKEND_LOCKED); - g_unlink (linkfile.str().c_str()); - close (m_lockfd); - m_lockfd = -1; - g_unlink (m_lockfile.c_str()); - m_lockfile.clear(); - return false; - } - - rc = g_stat (m_lockfile.c_str(), &statbuf); - if (rc) - { - /* oops .. stat failed! This can't happen! */ - set_error(ERR_BACKEND_LOCKED); - std::string msg{"Failed to stat lockfile "}; - set_message(msg + m_lockfile); - g_unlink (linkfile.str().c_str()); - close (m_lockfd); - m_lockfd = -1; - g_unlink (m_lockfile.c_str()); - m_lockfile.clear(); - return false; - } - - if (statbuf.st_nlink != 2) - { - set_error(ERR_BACKEND_LOCKED); - g_unlink (linkfile.str().c_str()); - close (m_lockfd); - m_lockfd = -1; - g_unlink (m_lockfile.c_str()); - m_lockfile.clear(); - return false; - } - - m_linkfile = linkfile.str(); return true; - -#else /* ifndef G_OS_WIN32 */ - /* On windows, there is no NFS and the open(,O_CREAT | O_EXCL) - is sufficient for locking. */ - return true; -#endif /* ifndef G_OS_WIN32 */ } bool From 4488568b45e6516929af57d506ec0ef344ffcaca Mon Sep 17 00:00:00 2001 From: Robert Fewell <14uBobIT@gmail.com> Date: Tue, 7 Sep 2021 10:34:10 +0100 Subject: [PATCH 13/29] Change text for SX preference option Change the text of 'Review created transactions' to better align with existing SX text so use "since last run". --- gnucash/gtkbuilder/dialog-sx.glade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnucash/gtkbuilder/dialog-sx.glade b/gnucash/gtkbuilder/dialog-sx.glade index 7f14ca0bb9..796a20b291 100644 --- a/gnucash/gtkbuilder/dialog-sx.glade +++ b/gnucash/gtkbuilder/dialog-sx.glade @@ -721,11 +721,11 @@ - Set 'Re_view Created Transactions' as default + Re_view created transactions True True False - Set 'Review Created Transactions' as the default in the 'Since Last Run' dialog. + Set 'Review created transactions' as the default in the "since last run" dialog. start True True From ae559089d39e1e2aca04ccfc47b5544f1f1549f0 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Tue, 7 Sep 2021 12:02:46 +0200 Subject: [PATCH 14/29] Prep early splash screen messages for translation --- gnucash/gnucash-core-app.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp index 4ecde0f7c7..3269fbf17c 100644 --- a/gnucash/gnucash-core-app.cpp +++ b/gnucash/gnucash-core-app.cpp @@ -99,7 +99,8 @@ Gnucash::gnc_load_scm_config (void) static auto is_system_config_loaded = false; if (!is_system_config_loaded) { - update_message ("loading system scm configuration"); + auto msg = bl::translate ("Loading system scm configuration...").str (gnc_get_boost_locale()); + update_message (msg.c_str()); auto system_config_dir = gnc_path_get_pkgsysconfdir (); auto system_config = g_build_filename (system_config_dir, "config", nullptr); is_system_config_loaded = gfec_try_load (system_config); @@ -110,7 +111,8 @@ Gnucash::gnc_load_scm_config (void) static auto is_user_config_loaded = false; if (!is_user_config_loaded) { - update_message("loading user scm configuration"); + auto msg = bl::translate ("Loading user scm configuration...").str (gnc_get_boost_locale()); + update_message (msg.c_str()); auto config_filename = g_build_filename (gnc_userconfig_dir (), "config-user.scm", nullptr); is_user_config_loaded = gfec_try_load (config_filename); g_free (config_filename); From 4a8acf3fb2417c82e8b4dbf0ae4655535ec5a0af Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sun, 11 Jul 2021 15:58:34 +0100 Subject: [PATCH 15/29] Free template root accounts on book end The template root should be unset so that it's destroyed when the book is ending. This is required to free all the template accounts and referenced strings. The scheduled transactions themselves need to be freed first so reverse the order that SXRegister and gnc_sxtt_register are called in cashobjects_register: The list resulting from that function is traversed from the bottom up. --- libgnucash/engine/SX-book.c | 2 +- libgnucash/engine/cashobjects.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libgnucash/engine/SX-book.c b/libgnucash/engine/SX-book.c index e15cb57f0b..d8d8c27db6 100644 --- a/libgnucash/engine/SX-book.c +++ b/libgnucash/engine/SX-book.c @@ -127,7 +127,7 @@ sxtg_book_begin (QofBook *book) static void sxtg_book_end (QofBook *book) { -// gnc_book_set_template_root (book, NULL); + gnc_book_set_template_root (book, NULL); } static gboolean diff --git a/libgnucash/engine/cashobjects.c b/libgnucash/engine/cashobjects.c index 903705d342..fd3ae34260 100644 --- a/libgnucash/engine/cashobjects.c +++ b/libgnucash/engine/cashobjects.c @@ -73,8 +73,8 @@ cashobjects_register(void) g_return_val_if_fail(xaccAccountRegister(), FALSE); g_return_val_if_fail ( xaccTransRegister(), FALSE); g_return_val_if_fail ( xaccSplitRegister(), FALSE); - g_return_val_if_fail ( SXRegister (), FALSE); g_return_val_if_fail ( gnc_sxtt_register(), FALSE); + g_return_val_if_fail ( SXRegister (), FALSE); g_return_val_if_fail(gnc_pricedb_register(), FALSE); g_return_val_if_fail (gnc_budget_register(), FALSE); g_return_val_if_fail ( gnc_lot_register (), FALSE); From d398a359caf7b60b4879984cf56be7a64e1fc2f3 Mon Sep 17 00:00:00 2001 From: cjh Date: Tue, 7 Sep 2021 12:34:55 +0200 Subject: [PATCH 16/29] Translation update by cjh using Weblate po/zh_CN.po: 99.9% (5361 of 5364 strings; 0 fuzzy) 0 failing checks (0.0%) Translation: GnuCash/Program (Chinese (Simplified)) Translate-URL: https://hosted.weblate.org/projects/gnucash/gnucash/zh_Hans/ Co-authored-by: cjh --- po/zh_CN.po | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index 20ab90b99b..90cedb8186 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -23,8 +23,8 @@ msgstr "" "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "cgi?product=GnuCash&component=Translations\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n" -"PO-Revision-Date: 2021-09-02 06:33+0000\n" -"Last-Translator: TianXing_Yi \n" +"PO-Revision-Date: 2021-09-07 10:34+0000\n" +"Last-Translator: cjh \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" @@ -10877,13 +10877,13 @@ msgstr "" msgid "" "Set \"Review Created Transactions\" as the default for the \"since last run" "\" dialog." -msgstr "" +msgstr "将 \"审查创建的交易 \"设为 \"自上次运行以来 \"对话框的默认值。" #: gnucash/gschemas/org.gnucash.dialogs.sxs.gschema.xml.in:28 msgid "" "This setting controls whether as default the \"review created transactions\" " "is set for the \"since last run\" dialog." -msgstr "" +msgstr "此设置控制 \"自上次运行以来 \"对话框是否默认设置 \"审查已创建的交易\"。" #: gnucash/gschemas/org.gnucash.dialogs.sxs.gschema.xml.in:35 msgid "Set the \"auto create\" flag by default" @@ -11238,7 +11238,7 @@ msgstr "新打开的标签页前置,而非最后" msgid "" "If active, new tabs are opened adjacent to current tab. If inactive, the new " "tabs are opened instead at the end." -msgstr "" +msgstr "如果激活,新标签会在当前标签的旁边打开。如果不激活,新标签将在最后打开。" #: gnucash/gschemas/org.gnucash.gschema.xml.in:140 #: gnucash/gtkbuilder/dialog-preferences.glade:940 @@ -16255,13 +16255,13 @@ msgstr "不可能的匹配日阈值 (_U)" msgid "" "A transaction whose date is within the threshold is likely to be a match. " "Default is 4 days." -msgstr "" +msgstr "日期在阈值内的交易可能是匹配的。默认为4天。" #: gnucash/gtkbuilder/dialog-preferences.glade:2340 msgid "" "A transaction whose date is outside the threshold is unlikely to be a match. " "Default is 14 days." -msgstr "" +msgstr "日期在阈值之外的交易不太可能是匹配的。默认为14天。" #: gnucash/gtkbuilder/dialog-preferences.glade:2385 msgid "Checks" @@ -17201,7 +17201,7 @@ msgstr "默认复核已创建交易(_R)" msgid "" "Set 'Review Created Transactions' as the default in the 'Since Last Run' " "dialog." -msgstr "" +msgstr "在 \"自上次运行 \"对话框中,将 \"审查创建的交易 \"设置为默认值。" #: gnucash/gtkbuilder/dialog-sx.glade:765 msgid "Edit Scheduled Transaction" @@ -21966,7 +21966,7 @@ msgstr "价格信息的来源。" #: gnucash/report/options-utilities.scm:144 msgid "Average cost of purchases weighted by volume" -msgstr "" +msgstr "按数量加权的平均采购成本" #: gnucash/report/options-utilities.scm:145 msgid "Weighted average of all transactions in the past" @@ -24535,7 +24535,7 @@ msgstr "以逐条求和计算么?" #: gnucash/report/reports/standard/budget-barchart.scm:142 msgid "Select which chart type to use." -msgstr "" +msgstr "选择要使用的图表类型。" #: gnucash/report/reports/standard/budget-barchart.scm:144 #: gnucash/report/reports/standard/category-barchart.scm:156 From 140922a37e451461e07c615f603fd3807fd4f724 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Wed, 8 Sep 2021 23:59:24 +0800 Subject: [PATCH 17/29] QofQuery args must be destroyed after qof_query_merge qof_query_merge returns a new QofQuery; the two merged QofQueries are not explicitly destroyed. --- bindings/guile/gnc-engine-guile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bindings/guile/gnc-engine-guile.c b/bindings/guile/gnc-engine-guile.c index 36915cd64c..45a69ec243 100644 --- a/bindings/guile/gnc-engine-guile.c +++ b/bindings/guile/gnc-engine-guile.c @@ -1116,6 +1116,7 @@ gnc_scm2query_and_terms (SCM and_terms, query_version_t vers) if (q_and) { q_new = qof_query_merge (q, q_and, QOF_QUERY_AND); + qof_query_destroy (q_and); if (q_new) { @@ -1158,6 +1159,7 @@ gnc_scm2query_or_terms (SCM or_terms, query_version_t vers) if (q_or) { q_new = qof_query_merge (q, q_or, QOF_QUERY_OR); + qof_query_destroy (q_or); if (q_new) { From d4bd60059614cbe980bef100476fa8d044ee805d Mon Sep 17 00:00:00 2001 From: John Ralls Date: Thu, 9 Sep 2021 15:58:19 -0700 Subject: [PATCH 18/29] Fix free-of-unallocated-address crash due to uninitialized ptr. --- gnucash/gnome/gnc-plugin-report-system.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gnucash/gnome/gnc-plugin-report-system.c b/gnucash/gnome/gnc-plugin-report-system.c index 3016f99373..621f001317 100644 --- a/gnucash/gnome/gnc-plugin-report-system.c +++ b/gnucash/gnome/gnc-plugin-report-system.c @@ -136,10 +136,10 @@ gnc_report_system_file_stream_cb (const char *location, char ** data, int *len) static gboolean gnc_report_system_report_stream_cb (const char *location, char ** data, int *len) { - gboolean ok; - gchar *captured_str; - - ok = gnc_run_report_id_string_with_error_handling (location, data, &captured_str); + gchar *captured_str = NULL; + gboolean ok = + gnc_run_report_id_string_with_error_handling (location, data, + &captured_str); if (!ok) { From 1387d5f960255feeeb7a2a63ce3f7119385e69cc Mon Sep 17 00:00:00 2001 From: John Ralls Date: Thu, 9 Sep 2021 15:58:47 -0700 Subject: [PATCH 19/29] Fix unchecked ptr dereference. First crash in Bug 798225. --- libgnucash/engine/gncTaxTable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgnucash/engine/gncTaxTable.c b/libgnucash/engine/gncTaxTable.c index 3cd689db5c..2e0cbfa907 100644 --- a/libgnucash/engine/gncTaxTable.c +++ b/libgnucash/engine/gncTaxTable.c @@ -704,7 +704,7 @@ GncTaxTableList * gncTaxTableGetTables (QofBook *book) if (!book) return NULL; bi = qof_book_get_data (book, _GNC_MOD_NAME); - return bi->tables; + return bi ? bi->tables : NULL; } const char *gncTaxTableGetName (const GncTaxTable *table) From 8ab8642e76466e1af2c381dfa64b5bb3409f2a9e Mon Sep 17 00:00:00 2001 From: John Ralls Date: Thu, 9 Sep 2021 16:02:00 -0700 Subject: [PATCH 20/29] Fix leak of trading_splits list in xaccTransClearTradingSplits --- libgnucash/engine/Scrub.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libgnucash/engine/Scrub.c b/libgnucash/engine/Scrub.c index 888378cdee..de14940e4c 100644 --- a/libgnucash/engine/Scrub.c +++ b/libgnucash/engine/Scrub.c @@ -612,7 +612,7 @@ gnc_transaction_get_commodity_imbalance (Transaction *trans, /* GFunc wrapper for xaccSplitDestroy */ static void -destroy_split (void* ptr, void* data) +destroy_split (void* ptr) { Split *split = GNC_SPLIT (ptr); if (split) @@ -642,7 +642,10 @@ xaccTransClearTradingSplits (Transaction *trans) return; xaccTransBeginEdit (trans); - g_list_foreach (trading_splits, destroy_split, NULL); + /* destroy_splits doesn't actually free the splits but this gets + * the list ifself freed. + */ + g_list_free_full (trading_splits, destroy_split); xaccTransCommitEdit (trans); } From ff26b71a91ab50f6a4db465b4bde0c42fc072f97 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Thu, 9 Sep 2021 18:03:18 -0700 Subject: [PATCH 21/29] Bug 798256 - Crash in recnFinishCB Make the action_group not sensitive in the recn_destroy_cb so that the action callbacks won't be called after the recnData is freed. --- gnucash/gnome/window-reconcile.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gnucash/gnome/window-reconcile.c b/gnucash/gnome/window-reconcile.c index 4177072281..9ed645d1b1 100644 --- a/gnucash/gnome/window-reconcile.c +++ b/gnucash/gnome/window-reconcile.c @@ -2120,6 +2120,9 @@ recn_destroy_cb (GtkWidget *w, gpointer data) if (recnData->delete_refresh) gnc_resume_gui_refresh (); + //Disable the actions, the handlers try to access recnData + gtk_action_group_set_sensitive(recnData->action_group, FALSE); + g_free (recnData); } From cd0d50aac135d74aac6ee5e2297da258b71ebbae Mon Sep 17 00:00:00 2001 From: John Ralls Date: Fri, 10 Sep 2021 12:21:46 -0700 Subject: [PATCH 22/29] Deprecate date options with a time of day setting. Removing the only use, an example in hello-world.scm. GnuCash doesn't use this value in any of its own report options and the feature will be removed in GnuCash 5. Related to bug 798297 Pref "Use 24-hour clock" obsolete?. --- gnucash/report/reports/example/hello-world.scm | 17 ----------------- libgnucash/app-utils/options.scm | 8 ++++++-- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/gnucash/report/reports/example/hello-world.scm b/gnucash/report/reports/example/hello-world.scm index 77f8d55525..2313fbb637 100644 --- a/gnucash/report/reports/example/hello-world.scm +++ b/gnucash/report/reports/example/hello-world.scm @@ -94,15 +94,6 @@ (lambda () (cons 'absolute (current-time))) #f 'absolute #f )) - ;; This is another date option, but the user can also select - ;; the time. - (add-option - (gnc:make-date-option - (N_ "Hello, World!") (N_ "Time and Date Option") - "e" (N_ "This is a date option with time.") - (lambda () (cons 'absolute (current-time))) - #t 'absolute #f )) - (add-option (gnc:make-date-option (N_ "Hello, World!") (N_ "Combo Date Option") @@ -234,8 +225,6 @@ option like this.") (string-val (op-value "Hello, World!" "String Option")) (date-val (gnc:date-option-absolute-time (op-value "Hello, World!" "Just a Date Option"))) - (date2-val (gnc:date-option-absolute-time - (op-value "Hello, World!" "Time and Date Option"))) (rel-date-val (gnc:date-option-absolute-time (op-value "Hello, World!" "Relative Date Option"))) (combo-date-val (gnc:date-option-absolute-time @@ -258,7 +247,6 @@ option like this.") ;; qof-print-date (let ((time-string (gnc-print-time64 (current-time) "%X")) (date-string (gnc-print-time64 date-val "%x")) - (date-string2 (gnc-print-time64 date2-val "%x %X")) (rel-date-string (gnc-print-time64 rel-date-val "%x")) (combo-date-string (gnc-print-time64 combo-date-val "%x"))) @@ -369,11 +357,6 @@ new, totally cool report, consult the mailing list ~a.") (G_ "The date option is ~a.") (gnc:html-markup-b date-string))) - (gnc:html-markup-p - (gnc:html-markup/format - (G_ "The date and time option is ~a.") - (gnc:html-markup-b date-string2))) - (gnc:html-markup-p (gnc:html-markup/format (G_ "The relative date option is ~a.") diff --git a/libgnucash/app-utils/options.scm b/libgnucash/app-utils/options.scm index 5befd47437..8481572cbb 100644 --- a/libgnucash/app-utils/options.scm +++ b/libgnucash/app-utils/options.scm @@ -719,10 +719,14 @@ the option '~a'.")) (begin (rpterror-earlier "date" item (car full-list)) 0))) - (let* ((value (default-getter)) + (if show-time + (issue-deprecation-warning + (format #f "Date options with time of day values are deprecated and will be removed in GnuCash 5."))) + + (let* ((value (default-getter)) (value->string (lambda () (string-append "'" (gnc:value->string value))))) - (gnc:make-option + (gnc:make-option section name sort-tag 'date documentation-string (lambda () value) (lambda (date) From fcab298245f39318cc7151ee86ef985ec9d39489 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Fri, 10 Sep 2021 13:26:59 -0700 Subject: [PATCH 23/29] Add test for Transaction GetDate() in python bindings. Pursuant to Bug 798284. --- bindings/python/tests/test_transaction.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bindings/python/tests/test_transaction.py b/bindings/python/tests/test_transaction.py index 78e792156d..529390f311 100644 --- a/bindings/python/tests/test_transaction.py +++ b/bindings/python/tests/test_transaction.py @@ -2,6 +2,7 @@ from unittest import main from gnucash import Transaction, Book, Account, Split from unittest_support import * +from datetime import datetime, timezone from test_book import BookSession @@ -138,5 +139,12 @@ class TestTransaction(TransactionSession): self.trans.SetNotes(NOTE) self.assertEqual( NOTE, self.trans.GetNotes() ) + def test_date(self): + ZERODATE=datetime.fromisoformat('1970-01-01 00:00:00 +00:00') + DATE=datetime.fromisoformat('2020-02-20 10:59:00 +00:00') + self.assertEqual(ZERODATE, self.trans.GetDate().astimezone(timezone.utc)) + self.trans.SetDate(DATE.day, DATE.month, DATE.year) + self.assertEqual(DATE, self.trans.GetDate().astimezone(timezone.utc)) + if __name__ == '__main__': main() From a310b72b37c58958dd50301153e20eecfdd365f1 Mon Sep 17 00:00:00 2001 From: TianXing_Yi Date: Fri, 10 Sep 2021 18:33:34 +0200 Subject: [PATCH 24/29] Translation update by TianXing_Yi using Weblate po/zh_CN.po: 99.9% (5361 of 5364 strings; 0 fuzzy) 0 failing checks (0.0%) Translation: GnuCash/Program (Chinese (Simplified)) Translate-URL: https://hosted.weblate.org/projects/gnucash/gnucash/zh_Hans/ Co-authored-by: TianXing_Yi --- po/zh_CN.po | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index 90cedb8186..6674dc8e9f 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -23,8 +23,8 @@ msgstr "" "Report-Msgid-Bugs-To: https://bugs.gnucash.org/enter_bug." "cgi?product=GnuCash&component=Translations\n" "POT-Creation-Date: 2021-06-30 07:34+0200\n" -"PO-Revision-Date: 2021-09-07 10:34+0000\n" -"Last-Translator: cjh \n" +"PO-Revision-Date: 2021-09-10 16:33+0000\n" +"Last-Translator: TianXing_Yi \n" "Language-Team: Chinese (Simplified) \n" "Language: zh_CN\n" @@ -32,7 +32,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.8.1-dev\n" +"X-Generator: Weblate 4.9-dev\n" "X-Bugs: Report translation errors to the Language-Team address.\n" #: bindings/guile/commodity-table.scm:44 @@ -2162,7 +2162,7 @@ msgstr "入账日期" #: gnucash/gnome/dialog-invoice.c:872 msgid "Post to Account" -msgstr "入账到科目" +msgstr "入账科目" #: gnucash/gnome/dialog-invoice.c:873 msgid "Accumulate Splits?" @@ -3643,7 +3643,7 @@ msgstr "打开查找项目对话框" #: gnucash/gnome/gnc-plugin-business.c:238 #: gnucash/gnome/gnc-plugin-business.c:271 msgid "_Process Payment..." -msgstr "处理收付(_P)..." +msgstr "收付(_P)..." #: gnucash/gnome/gnc-plugin-business.c:196 #: gnucash/gnome/gnc-plugin-business.c:239 @@ -4946,7 +4946,7 @@ msgstr "显示员工报表" #: gnucash/gnome/gnc-plugin-page-owner-tree.c:293 msgid "New Voucher" -msgstr "新建支出凭证" +msgstr "新建报销" #: gnucash/gnome/gnc-plugin-page-owner-tree.c:446 msgid "Owners" @@ -21347,7 +21347,7 @@ msgstr "小计" #: gnucash/report/reports/standard/owner-report.scm:56 #: libgnucash/app-utils/business-options.scm:78 msgid "Tax" -msgstr "税务" +msgstr "税额" #: gnucash/register/ledger-core/gncEntryLedgerModel.c:127 msgid "Billable?" @@ -22101,7 +22101,7 @@ msgstr "收入支出(_I)" #: gnucash/report/report-core.scm:154 msgid "_Taxes" -msgstr "税务(_U)" +msgstr "税额(_U)" #: gnucash/report/report-core.scm:155 msgid "E_xamples" From b8552a8070325e6815fd9086eb3cacbb3f57612a Mon Sep 17 00:00:00 2001 From: John Ralls Date: Fri, 10 Sep 2021 17:01:38 -0700 Subject: [PATCH 25/29] Fix python transaction test_date on Ubuntu-81.04. Python3 there is too old for fromisoformat, use direct construction instead. --- bindings/python/tests/test_transaction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/tests/test_transaction.py b/bindings/python/tests/test_transaction.py index 529390f311..446a7b8e41 100644 --- a/bindings/python/tests/test_transaction.py +++ b/bindings/python/tests/test_transaction.py @@ -140,8 +140,8 @@ class TestTransaction(TransactionSession): self.assertEqual( NOTE, self.trans.GetNotes() ) def test_date(self): - ZERODATE=datetime.fromisoformat('1970-01-01 00:00:00 +00:00') - DATE=datetime.fromisoformat('2020-02-20 10:59:00 +00:00') + ZERODATE=datetime(1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc) + DATE=datetime(2020, 2, 20, 10, 59, 0, tzinfo=timezone.utc) self.assertEqual(ZERODATE, self.trans.GetDate().astimezone(timezone.utc)) self.trans.SetDate(DATE.day, DATE.month, DATE.year) self.assertEqual(DATE, self.trans.GetDate().astimezone(timezone.utc)) From 72a3ebbba330635325ba657a8e4935c510dd5047 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Sat, 11 Sep 2021 14:57:57 +0800 Subject: [PATCH 26/29] [engine.i] QofQueryParamList * args must be freed --- bindings/engine.i | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/engine.i b/bindings/engine.i index a8fe5827d2..a2bdf0289a 100644 --- a/bindings/engine.i +++ b/bindings/engine.i @@ -211,6 +211,7 @@ SplitList * qof_query_last_run (QofQuery *q); SplitList * qof_query_run_subquery (QofQuery *q, const QofQuery *q); %typemap(in) QofQueryParamList * "$1 = gnc_query_scm2path($input);" +%typemap(freearg) QofQueryParamList * "g_slist_free_full ($1, g_free);" %include %include From d0f7daf4cfd02db17c03e3946e145a13760cd3d0 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Sat, 11 Sep 2021 15:45:32 +0800 Subject: [PATCH 27/29] Revert "[engine.i] QofQueryParamList * args must be freed" This reverts commit 72a3ebbba330635325ba657a8e4935c510dd5047. Freeing does not apply to all qof_query_* calls. --- bindings/engine.i | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/engine.i b/bindings/engine.i index a2bdf0289a..a8fe5827d2 100644 --- a/bindings/engine.i +++ b/bindings/engine.i @@ -211,7 +211,6 @@ SplitList * qof_query_last_run (QofQuery *q); SplitList * qof_query_run_subquery (QofQuery *q, const QofQuery *q); %typemap(in) QofQueryParamList * "$1 = gnc_query_scm2path($input);" -%typemap(freearg) QofQueryParamList * "g_slist_free_full ($1, g_free);" %include %include From b9deb5ea2a870f1568c8342b60a6df9c44772344 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Sat, 11 Sep 2021 10:11:36 -0700 Subject: [PATCH 28/29] Bug 798303 - account list is sorted wrong by amount Use balances converted to the default currency when sorting columns on the accounts page. --- gnucash/gnome-utils/gnc-tree-view-account.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gnucash/gnome-utils/gnc-tree-view-account.c b/gnucash/gnome-utils/gnc-tree-view-account.c index 35c33f2e85..03425bf056 100644 --- a/gnucash/gnome-utils/gnc-tree-view-account.c +++ b/gnucash/gnome-utils/gnc-tree-view-account.c @@ -372,6 +372,7 @@ sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn, gpointer user_data) { const Account *account_a, *account_b; + const gnc_commodity *cur = gnc_default_currency(); gnc_numeric balance_a, balance_b; gint result; @@ -379,8 +380,8 @@ sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn, sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b); /* Get balances */ - balance_a = gnc_ui_account_get_balance_full(fn, account_a, recurse, NULL, NULL); - balance_b = gnc_ui_account_get_balance_full(fn, account_b, recurse, NULL, NULL); + balance_a = gnc_ui_account_get_balance_full(fn, account_a, recurse, NULL, cur); + balance_b = gnc_ui_account_get_balance_full(fn, account_b, recurse, NULL, cur); result = gnc_numeric_compare(balance_a, balance_b); if (result != 0) From edad194389d91421e80bfc78f067b002a7e6d9e6 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Sat, 11 Sep 2021 16:09:55 -0700 Subject: [PATCH 29/29] Bug 798180 - Update to macOS Big Sur 11.3 breaks Finance Quote Added new dependency Test2 to gnc-fq-update. This is a second-order dependency of Finanance::Quote that CPAN doesn't seem to recognize on its own. --- libgnucash/quotes/gnc-fq-update.in | 1 + 1 file changed, 1 insertion(+) diff --git a/libgnucash/quotes/gnc-fq-update.in b/libgnucash/quotes/gnc-fq-update.in index 797a6d1894..dbbcf675a0 100755 --- a/libgnucash/quotes/gnc-fq-update.in +++ b/libgnucash/quotes/gnc-fq-update.in @@ -36,6 +36,7 @@ if ($( != 0) { exit 0 if ($input ne "y"); } +CPAN::Shell->install('Test2'); #Required by an F::Q dependency but cpan doesn't notice. CPAN::Shell->install('Date::Manip'); #Required by gnc-fq-helper CPAN::Shell->install('Finance::Quote');