gnucash master: Multiple changes pushed
Geert Janssens
gjanssens at code.gnucash.org
Mon Mar 13 15:02:29 EDT 2023
Updated via https://github.com/Gnucash/gnucash/commit/16cc2180 (commit)
via https://github.com/Gnucash/gnucash/commit/0ed0be4e (commit)
via https://github.com/Gnucash/gnucash/commit/4ae15e67 (commit)
via https://github.com/Gnucash/gnucash/commit/37e0f407 (commit)
via https://github.com/Gnucash/gnucash/commit/d75ab275 (commit)
via https://github.com/Gnucash/gnucash/commit/13ec4bb5 (commit)
via https://github.com/Gnucash/gnucash/commit/8010d964 (commit)
from https://github.com/Gnucash/gnucash/commit/427c1b96 (commit)
commit 16cc21809743337494178f5ab46eacba086dca13
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Dec 30 19:28:00 2022 +0100
C++ - use more expressive std::any_of rather than std::find
What's looked for is encapsulated in a lambda function
named is_req_column_type. This compares values in the vector
with a value captured from the main context, which is updated
for each call of std::any.
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 0a8b3e359c..1e3093ede4 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -1683,11 +1683,13 @@ void CsvImpPriceAssist::preview_refresh_table ()
preview_style_column (i, combostore);
auto column_types = price_imp->column_types_price();
+ GncPricePropType req_column_type;
+ auto is_req_column_type = [&req_column_type] (GncPricePropType column_type)->bool
+ { return column_type == req_column_type; };
// look for a namespace column, clear the commodity combo
- auto col_type_name = std::find (column_types.begin(),
- column_types.end(), GncPricePropType::FROM_NAMESPACE);
- if (col_type_name != column_types.end())
+ req_column_type = GncPricePropType::FROM_NAMESPACE; // Used by is_column_type()
+ if (std::any_of (column_types.begin(), column_types.end(), is_req_column_type))
{
g_signal_handlers_block_by_func (commodity_selector, (gpointer) csv_price_imp_preview_commodity_sel_cb, this);
set_commodity_for_combo (GTK_COMBO_BOX(commodity_selector), nullptr);
@@ -1695,9 +1697,8 @@ void CsvImpPriceAssist::preview_refresh_table ()
}
// look for a symbol column, clear the commodity combo
- auto col_type_sym = std::find (column_types.begin(),
- column_types.end(), GncPricePropType::FROM_SYMBOL);
- if (col_type_sym != column_types.end())
+ req_column_type = GncPricePropType::FROM_SYMBOL; // Used by is_column_type()
+ if (std::any_of (column_types.begin(), column_types.end(), is_req_column_type))
{
g_signal_handlers_block_by_func (commodity_selector, (gpointer) csv_price_imp_preview_commodity_sel_cb, this);
set_commodity_for_combo (GTK_COMBO_BOX(commodity_selector), nullptr);
@@ -1705,9 +1706,8 @@ void CsvImpPriceAssist::preview_refresh_table ()
}
// look for a currency column, clear the currency combo
- auto col_type_curr = std::find (column_types.begin(),
- column_types.end(), GncPricePropType::TO_CURRENCY);
- if (col_type_curr != column_types.end())
+ req_column_type = GncPricePropType::TO_CURRENCY; // Used by is_column_type()
+ if (std::any_of (column_types.begin(), column_types.end(), is_req_column_type))
{
g_signal_handlers_block_by_func (currency_selector, (gpointer) csv_price_imp_preview_currency_sel_cb, this);
set_commodity_for_combo (GTK_COMBO_BOX(currency_selector), nullptr);
commit 0ed0be4ef233368ff21bcf8976a25bcd59b607a5
Author: Geert Janssens <geert at kobaltwit.be>
Date: Fri Dec 30 19:20:43 2022 +0100
C++ - use more expressive std::accumulate algo rather than std::for_each
It encapsulates the custom string concatenation bits into a
lambda called "add_bullet_item" and streamlines the logic
of when to add what to the summary.
diff --git a/gnucash/gnome/assistant-stock-transaction.cpp b/gnucash/gnome/assistant-stock-transaction.cpp
index 27fc521c72..f2418e1d0b 100644
--- a/gnucash/gnome/assistant-stock-transaction.cpp
+++ b/gnucash/gnome/assistant-stock-transaction.cpp
@@ -899,20 +899,24 @@ to ensure proper recording."), new_date_str, last_split_date_str);
// generate final summary message. Collates a header, the errors
// and warnings. Then allow completion if errors is empty.
- auto header = errors.empty() ?
- N_("No errors found. Click Apply to create transaction.") :
- N_("The following errors must be fixed:");
- auto summary = std::string { _(header) };
- auto summary_add = [&summary](auto a) { summary += "\n• "; summary += a; };
- std::for_each (errors.begin(), errors.end(), summary_add);
+ auto add_bullet_item = [](std::string& a, std::string& b)->std::string { return std::move(a) + "\n• " + b; };
+ auto summary = std::string{};
if (errors.empty())
- std::for_each (infos.begin(), infos.end(), summary_add);
+ {
+ summary = _("No errors found. Click Apply to create transaction.");
+ summary = std::accumulate (infos.begin(), infos.end(), std::move (summary), add_bullet_item);
+ }
+ else
+ {
+ summary = _("The following errors must be fixed:");
+ summary = std::accumulate (errors.begin(), errors.end(), std::move (summary), add_bullet_item);
+ }
+
if (!warnings.empty())
{
- auto warnings_header = N_ ("The following warnings exist:");
summary += "\n\n";
- summary += _(warnings_header);
- std::for_each (warnings.begin(), warnings.end(), summary_add);
+ summary += _("The following warnings exist:");
+ summary = std::accumulate (warnings.begin(), warnings.end(), std::move (summary), add_bullet_item);
}
gtk_label_set_text (GTK_LABEL (info->finish_summary), summary.c_str());
gtk_assistant_set_page_complete (GTK_ASSISTANT (info->window),
commit 4ae15e675c46131632ca4228323a67c8a4982746
Author: Geert Janssens <geert at kobaltwit.be>
Date: Tue Feb 28 22:25:19 2023 +0100
CsvImport - actually do as the warning indicates
If an invalid column is found in a preset, replace it
with a NONE column, rather than not inserting a column
at all.
diff --git a/gnucash/import-export/csv-imp/gnc-imp-settings-csv-price.cpp b/gnucash/import-export/csv-imp/gnc-imp-settings-csv-price.cpp
index c1ebcff745..c2bcd29004 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-settings-csv-price.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-settings-csv-price.cpp
@@ -152,14 +152,14 @@ CsvPriceImpSettings::load (void)
{
auto col_types_it = std::find_if (gnc_price_col_type_strs.begin(),
gnc_price_col_type_strs.end(), test_price_prop_type_str (col_types_str_price[i]));
+ auto prop = GncPricePropType::NONE;
if (col_types_it != gnc_price_col_type_strs.end())
- {
// Found a valid column type
- m_column_types_price.push_back(col_types_it->first);
- }
+ prop = col_types_it->first;
else
PWARN("Found invalid column type '%s' in group '%s'. Inserting column type 'NONE' instead'.",
col_types_str_price[i], group.c_str());
+ m_column_types_price.push_back(prop);
}
if (col_types_str_price)
g_strfreev (col_types_str_price);
diff --git a/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp
index 151ce91166..a4904e808b 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-settings-csv-tx.cpp
@@ -261,12 +261,12 @@ CsvTransImpSettings::load (void)
col_type_str = gnc_csv_col_type_strs[GncTransPropType::NUM];
auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
gnc_csv_col_type_strs.end(), test_prop_type_str (col_type_str));
+ auto prop = GncTransPropType::NONE;
if (col_types_it != gnc_csv_col_type_strs.end())
{
/* Found a valid column type. Now check whether it is allowed
* in the selected mode (two-split vs multi-split) */
- auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
- m_column_types.push_back(prop);
+ prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
if (prop != col_types_it->first)
PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
"Inserting column type 'NONE' instead'.",
@@ -274,7 +274,8 @@ CsvTransImpSettings::load (void)
}
else
PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
- col_types_str[i]);
+ col_types_str[i]);
+ m_column_types.push_back(prop);
}
if (col_types_str)
g_strfreev (col_types_str);
commit 37e0f407e94ea947ad0343b89fab8fc5933f6884
Author: Geert Janssens <geert at kobaltwit.be>
Date: Tue Feb 28 15:50:48 2023 +0100
First test for gnc-trans-props-tx
Start with test for parse_monetary
- a few basic tests
- extra tests for recent bug fixes, like
- allow blank as thousands separator
- double minus sign equals positive number
diff --git a/gnucash/import-export/csv-imp/test/CMakeLists.txt b/gnucash/import-export/csv-imp/test/CMakeLists.txt
index d2afce6a65..0472b93305 100644
--- a/gnucash/import-export/csv-imp/test/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/test/CMakeLists.txt
@@ -28,6 +28,26 @@ if (NOT WIN32)
# gtest_csv_imp_INCLUDES gtest_csv_imp_LIBS)
endif()
+set(GNC_IMP_PROPS_TX_TEST_INCLUDE_DIRS
+ ${CMAKE_BINARY_DIR}/common # for config.h
+ ${CMAKE_SOURCE_DIR}/gnucash/import-export/csv-imp
+ ${GTEST_INCLUDE_DIR}
+)
+
+set(GNC_IMP_PROPS_TX_TEST_LIBS
+ gnc-engine
+ test-core
+ gnc-generic-import
+ gtest)
+
+set(GNC_IMP_PROPS_TX_TEST_SOURCES
+ ../gnc-imp-props-tx.cpp
+ gtest-gnc-imp-props-tx.cpp
+)
+
+gnc_add_test(test-gnc-imp-props-tx "${GNC_IMP_PROPS_TX_TEST_SOURCES}"
+ GNC_IMP_PROPS_TX_TEST_INCLUDE_DIRS GNC_IMP_PROPS_TX_TEST_LIBS)
+
set_dist_list(test_csv_import_DIST CMakeLists.txt
- test-tx-import.cpp test-tokenizer.cpp
+ test-tx-import.cpp test-tokenizer.cpp gtest-gnc-imp-props-tx.cpp
sample1.csv ${test_csv_imp_SOURCES})
diff --git a/gnucash/import-export/csv-imp/test/gtest-gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/test/gtest-gnc-imp-props-tx.cpp
new file mode 100644
index 0000000000..7981453eec
--- /dev/null
+++ b/gnucash/import-export/csv-imp/test/gtest-gnc-imp-props-tx.cpp
@@ -0,0 +1,74 @@
+#include <gtest/gtest.h>
+
+#include <config.h>
+
+#include <gnc-datetime.hpp>
+
+#include <gnc-imp-props-tx.hpp>
+#include <qofbook.h>
+#include <engine-helpers.h>
+#include <gnc-ui-util.h>
+
+// Test fixture for tests without bayesian matching
+class GncImpPropsTxTest : public testing::Test
+{
+protected:
+ void SetUp()
+ {
+ }
+
+ void TearDown()
+ {
+ }
+
+};
+
+
+
+/* Tests using fixture GncImpPropsTxTest */
+
+extern GncNumeric parse_monetary (const std::string &str, int currency_format);
+
+//! Test for function parse_monetary (const std::string &str, int currency_format)
+TEST_F(GncImpPropsTxTest, ParseMonetary)
+{
+
+ using namespace testing;
+
+ /* Empty string */
+ auto value = parse_monetary ("", 1);
+ EXPECT_EQ (value, (GncNumeric {0, 1}));
+
+ /* No digits in string */
+ EXPECT_THROW (parse_monetary ("abc", 1), std::invalid_argument);
+
+ /* Tests using currency_format "Period" (1) */
+ value = parse_monetary ("1,000.00", 1);
+ EXPECT_EQ (value, (GncNumeric {100000, 100}));
+ value = parse_monetary ("-1,001.00", 1);
+ EXPECT_EQ (value, (GncNumeric {-100100, 100}));
+ value = parse_monetary ("-1,002.00$", 1);
+ EXPECT_EQ (value, (GncNumeric {-100200, 100}));
+ // 798334 - Importing transactions from CSV with space as thousand separator
+ value = parse_monetary ("1 000 003.00", 1);
+ EXPECT_EQ (value, (GncNumeric {100000300, 100}));
+ auto input = "1\u202F000\u202F004.00"; // Using Polish thousand separator
+ value = parse_monetary (input, 1);
+ EXPECT_EQ (value, (GncNumeric {100000400, 100}));
+ // Bug 798572 - Parse numbers with two minus signs as a positive numbers
+ value = parse_monetary ("--1,005.00", 1);
+ EXPECT_EQ (value, (GncNumeric {100500, 100}));
+
+ /* Tests using currency_format "Comma" (2) */
+ value = parse_monetary ("2.000,00", 2);
+ EXPECT_EQ (value, (GncNumeric {200000, 100}));
+ // 798334 - Importing transactions from CSV with space as thousand separator
+ value = parse_monetary ("2 000 001,00", 2);
+ EXPECT_EQ (value, (GncNumeric {200000100, 100}));
+ input = "2\u202F000\u202F002,00"; // Using Polish thousand separator
+ value = parse_monetary (input, 2);
+ EXPECT_EQ (value, (GncNumeric {200000200, 100}));
+
+ /* Things that will throw */
+ EXPECT_THROW (parse_monetary ("3000.00.01", 1), std::invalid_argument);
+};
commit d75ab275f1c481014107ba8b66bca3daccb8c6ac
Author: Geert Janssens <geert at kobaltwit.be>
Date: Tue Feb 28 15:49:10 2023 +0100
Eliminate gnc-csv-account-map.[ch]
The code is was only used by the csv import assistant and forced
gtk as a dependency on gnc-imp-props-tx
Part has been moved to Account, other bits have
been moved to the importer code where they were
used.
diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index e7bb7ecb28..5347cfdec2 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -12,7 +12,6 @@ set(csv_import_SOURCES
assistant-csv-trans-import.cpp
gnc-plugin-csv-import.c
csv-account-import.c
- gnc-csv-account-map.c
gnc-csv-gnumeric-popup.c
gnc-imp-props-price.cpp
gnc-imp-props-tx.cpp
@@ -42,7 +41,6 @@ set(csv_import_noinst_HEADERS
assistant-csv-trans-import.h
gnc-plugin-csv-import.h
csv-account-import.h
- gnc-csv-account-map.h
gnc-csv-gnumeric-popup.h
gnc-imp-props-price.hpp
gnc-imp-props-tx.hpp
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index 71fe41c775..55823b93b1 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -51,7 +51,6 @@
#include "import-account-matcher.h"
#include "import-main-matcher.h"
#include "import-backend.h"
-#include "gnc-csv-account-map.h"
#include "gnc-account-sel.h"
#include "gnc-csv-gnumeric-popup.h"
@@ -82,6 +81,11 @@ namespace bl = boost::locale;
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_ASSISTANT;
+enum GncImportColumn {
+ MAPPING_STRING,
+ MAPPING_FULLPATH,
+ MAPPING_ACCOUNT
+};
/* A note on memory management
*
@@ -1772,6 +1776,39 @@ void CsvImpTransAssist::acct_match_set_accounts ()
}
}
+static void
+csv_tximp_acct_match_load_mappings (GtkTreeModel *mappings_store)
+{
+ // Set iter to first entry of store
+ GtkTreeIter iter;
+ auto valid = gtk_tree_model_get_iter_first (mappings_store, &iter);
+
+ // Walk through the store trying to match to a map
+ while (valid)
+ {
+ // Walk through the list, reading each row
+ Account *account = nullptr;
+ gchar *map_string;
+ gtk_tree_model_get (GTK_TREE_MODEL(mappings_store), &iter, MAPPING_STRING, &map_string, MAPPING_ACCOUNT, &account, -1);
+
+ // Look for an account matching the map_string
+ // It may already be set in the tree model. If not we try to match the map_string with
+ // - an entry in our saved account maps
+ // - a full name of any of our existing accounts
+ if (account ||
+ (account = gnc_account_imap_find_any (gnc_get_current_book(), IMAP_CAT_CSV, map_string)) ||
+ (account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), map_string)))
+ {
+ auto fullpath = gnc_account_get_full_name (account);
+ gtk_list_store_set (GTK_LIST_STORE(mappings_store), &iter, MAPPING_FULLPATH, fullpath, -1);
+ gtk_list_store_set (GTK_LIST_STORE(mappings_store), &iter, MAPPING_ACCOUNT, account, -1);
+ g_free (fullpath);
+ }
+
+ g_free (map_string);
+ valid = gtk_tree_model_iter_next (mappings_store, &iter);
+ }
+}
static bool
csv_tximp_acct_match_check_all (GtkTreeModel *model)
@@ -1853,7 +1890,11 @@ CsvImpTransAssist::acct_match_select(GtkTreeModel *model, GtkTreeIter* iter)
MAPPING_FULLPATH, fullpath, -1);
// Update the account kvp mappings
- gnc_csv_account_map_change_mappings (account, gnc_acc, text);
+ if (text && *text)
+ {
+ gnc_account_imap_delete_account (account, IMAP_CAT_CSV, text);
+ gnc_account_imap_add_account (gnc_acc, IMAP_CAT_CSV, text, gnc_acc);
+ }
// Force reparsing of account columns - may impact multi-currency mode
auto col_types = tx_imp->column_types();
@@ -2001,7 +2042,6 @@ CsvImpTransAssist::assist_preview_page_prepare ()
g_idle_add ((GSourceFunc)csv_imp_preview_queue_rebuild_table, this);
}
}
-
void
CsvImpTransAssist::assist_account_match_page_prepare ()
{
@@ -2011,7 +2051,7 @@ CsvImpTransAssist::assist_account_match_page_prepare ()
// Match the account strings to account maps from previous imports
auto store = gtk_tree_view_get_model (GTK_TREE_VIEW(account_match_view));
- gnc_csv_account_map_load_mappings (store);
+ csv_tximp_acct_match_load_mappings (store);
// Enable the view, possibly after an error
gtk_widget_set_sensitive (account_match_view, true);
diff --git a/gnucash/import-export/csv-imp/gnc-csv-account-map.c b/gnucash/import-export/csv-imp/gnc-csv-account-map.c
deleted file mode 100644
index aeb942b6e6..0000000000
--- a/gnucash/import-export/csv-imp/gnc-csv-account-map.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*******************************************************************\
- * gnc-csv-account-map.c -- Load and Update Mappings *
- * *
- * Copyright (C) 2015 Robert Fewell *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
-\********************************************************************/
-/** @file gnc-csv-account-map.c
- @brief Save and Load Mappings
- @author Copyright (c) 2015 Robert Fewell
-*/
-#include <config.h>
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include "qof.h"
-#include "gnc-ui-util.h"
-#include "gnc-csv-account-map.h"
-
-#define CSV_CATEGORY "csv-account-map"
-
-#define IMPORT_STRING "String"
-#define IMPORT_FULL_PATH "FullPath"
-#define IMPORT_ACCOUNT "Account"
-
-#define UNUSED_VAR __attribute__ ((unused))
-
-/* This static indicates the debugging module that this .o belongs to. */
-static QofLogModule UNUSED_VAR log_module = G_LOG_DOMAIN;
-
-/**************************************************
- * gnc_csv_account_map_search
- *
- * search the existing mappings for the account
- * linked to the import string.
- **************************************************/
-Account * gnc_csv_account_map_search (const gchar *map_string)
-{
- Account *root, *account = NULL;
- GList *accts, *ptr;
-
- /* Get list of Accounts */
- root = gnc_book_get_root_account (gnc_get_current_book());
- accts = gnc_account_get_descendants_sorted (root);
-
- /* Go through list of accounts */
- for (ptr = accts; ptr; ptr = g_list_next (ptr))
- {
- Account *tmp_acc = ptr->data;
-
- if (gnc_account_imap_find_account (tmp_acc, CSV_CATEGORY, map_string))
- {
- account = tmp_acc;
- break;
- }
- }
- g_list_free (accts);
-
- return account;
-}
-
-
-/**************************************************
- * gnc_csv_account_map_load_mappings
- *
- * load the existing mappings
- **************************************************/
-void
-gnc_csv_account_map_load_mappings (GtkTreeModel *mappings_store)
-{
- GtkTreeIter iter;
- gboolean valid;
-
- // Set iter to first entry of store
- valid = gtk_tree_model_get_iter_first (mappings_store, &iter);
-
- // Walk through the store trying to match to a map
- while (valid)
- {
- Account *account = NULL;
- gchar *map_string;
- gchar *fullpath;
-
- // Walk through the list, reading each row
- gtk_tree_model_get (GTK_TREE_MODEL(mappings_store), &iter, MAPPING_STRING, &map_string, MAPPING_ACCOUNT, &account, -1);
-
- // Look for an account matching the map_string
- // It may already be set in the tree model. If not we try to match the map_string with
- // - an entry in our saved account maps
- // - a full name of any of our existing accounts
- if (account ||
- (account = gnc_csv_account_map_search (map_string)) ||
- (account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), map_string)))
- {
- fullpath = gnc_account_get_full_name (account);
- gtk_list_store_set (GTK_LIST_STORE(mappings_store), &iter, MAPPING_FULLPATH, fullpath, -1);
- gtk_list_store_set (GTK_LIST_STORE(mappings_store), &iter, MAPPING_ACCOUNT, account, -1);
- g_free (fullpath);
- }
-
- g_free (map_string);
- valid = gtk_tree_model_iter_next (mappings_store, &iter);
- }
-}
-
-
-/**************************************************
- * gnc_csv_account_map_change_mappings
- *
- * change the existing mappings
- **************************************************/
-void
-gnc_csv_account_map_change_mappings (Account *old_account, Account *new_account, const gchar *map_string)
-{
- if (strlen (map_string) == 0)
- return;
-
- if (old_account)
- gnc_account_imap_delete_account (old_account, CSV_CATEGORY, map_string);
-
- if (new_account)
- gnc_account_imap_add_account (new_account, CSV_CATEGORY, map_string, new_account);
-}
diff --git a/gnucash/import-export/csv-imp/gnc-csv-account-map.h b/gnucash/import-export/csv-imp/gnc-csv-account-map.h
deleted file mode 100644
index c6391e4af7..0000000000
--- a/gnucash/import-export/csv-imp/gnc-csv-account-map.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*******************************************************************\
- * gnc-csv-account-map.h -- Load and Update Mappings *
- * *
- * Copyright (C) 2015 Robert Fewell *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
-\********************************************************************/
-/** @file gnc-csv-account-map.h
- @brief Save and Load Mappings
- @author Copyright (c) 2015 Robert Fewell
-*/
-#ifndef GNC_CSV_ACCOUNT_MAP_H
-#define GNC_CSV_ACCOUNT_MAP_H
-
-#include <gtk/gtk.h>
-#include "Account.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Enumeration for the mappings liststore */
-enum GncImportColumn {MAPPING_STRING, MAPPING_FULLPATH, MAPPING_ACCOUNT};
-
-/** Load the import mappings.
- *
- * For each mapping string in the tree model, try to find a
- * corresponding account and account full path.
- *
- * - if the account was already set, just update the full path
- * - if the mapping string matches an account in the account maps,
- * use that account and its corresponding full name
- * - otherwise search for an existing account whose full name matches the
- * mapping string
- *
- */
-void gnc_csv_account_map_load_mappings (GtkTreeModel *mappings_store);
-
-/** Update the import mappings.
- *
- */
-void gnc_csv_account_map_change_mappings (Account *old_account, Account *new_account, const gchar *map_string);
-
-/** Returns a pointer to the account that matches the import string.
- *
- * @return A pointer to an account.
- */
-Account * gnc_csv_account_map_search (const gchar *map_string);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
index 6298f8707d..a2a3615124 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp
@@ -29,7 +29,6 @@
#endif
#include "engine-helpers.h"
-#include "gnc-csv-account-map.h"
#include "gnc-ui-util.h"
#include "Account.h"
#include "Transaction.h"
@@ -446,7 +445,7 @@ void GncPreSplit::set (GncTransPropType prop_type, const std::string& value)
m_account.reset();
if (value.empty())
throw std::invalid_argument (_("Account value can't be empty."));
- if ((acct = gnc_csv_account_map_search (value.c_str())) ||
+ if ((acct = gnc_account_imap_find_any (gnc_get_current_book(), IMAP_CAT_CSV, value.c_str())) ||
(acct = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), value.c_str())))
m_account = acct;
else
@@ -458,7 +457,7 @@ void GncPreSplit::set (GncTransPropType prop_type, const std::string& value)
if (value.empty())
throw std::invalid_argument (_("Transfer account value can't be empty."));
- if ((acct = gnc_csv_account_map_search (value.c_str())) ||
+ if ((acct = gnc_account_imap_find_any (gnc_get_current_book(), IMAP_CAT_CSV,value.c_str())) ||
(acct = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), value.c_str())))
m_taccount = acct;
else
diff --git a/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp b/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp
index f9d094e0c0..967950e755 100644
--- a/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp
+++ b/gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp
@@ -77,6 +77,8 @@ enum class GncTransPropType {
SPLIT_PROPS = TREC_DATE
};
+#define IMAP_CAT_CSV "csv-account-map"
+
using StrVec = std::vector<std::string>;
using ErrMap = std::map<GncTransPropType, std::string>;
using ErrPair = std::pair<GncTransPropType, std::string>;
diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp
index a599f158ea..005a896699 100644
--- a/libgnucash/engine/Account.cpp
+++ b/libgnucash/engine/Account.cpp
@@ -5646,6 +5646,31 @@ gnc_account_imap_find_account (Account *acc,
return retval;
}
+Account*
+gnc_account_imap_find_any (QofBook *book, const char* category, const char *key)
+{
+ Account *account = NULL;
+
+ /* Get list of Accounts */
+ auto root = gnc_book_get_root_account (book);
+ auto accts = gnc_account_get_descendants_sorted (root);
+
+ /* Go through list of accounts */
+ for (auto ptr = accts; ptr; ptr = g_list_next (ptr))
+ {
+ auto tmp_acc = static_cast<Account*> (ptr->data);
+
+ if (gnc_account_imap_find_account (tmp_acc, category, key))
+ {
+ account = tmp_acc;
+ break;
+ }
+ }
+ g_list_free (accts);
+
+return account;
+}
+
/* Store an Account in the map */
void
gnc_account_imap_add_account (Account *acc,
diff --git a/libgnucash/engine/Account.h b/libgnucash/engine/Account.h
index 5a2f2c45d1..499ffbe0e8 100644
--- a/libgnucash/engine/Account.h
+++ b/libgnucash/engine/Account.h
@@ -1575,6 +1575,11 @@ typedef enum
Account* gnc_account_imap_find_account (Account* acc, const char* category,
const char *key);
+ /* Look up an Account in the map non-Baysian, searching through the
+ * import map data of all accounts. Returns first match.
+ */
+ Account* gnc_account_imap_find_any (QofBook *book, const char* category, const char *key);
+
/* Store an Account in the map non Baysian
*/
void gnc_account_imap_add_account (Account* acc, const char *category,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 81f99711c5..2e8342a4d6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -333,7 +333,6 @@ gnucash/import-export/csv-imp/assistant-csv-account-import.c
gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
gnucash/import-export/csv-imp/csv-account-import.c
-gnucash/import-export/csv-imp/gnc-csv-account-map.c
gnucash/import-export/csv-imp/gnc-csv-gnumeric-popup.c
gnucash/import-export/csv-imp/gnc-import-price.cpp
gnucash/import-export/csv-imp/gnc-import-tx.cpp
commit 13ec4bb5941945a5e1796e3260aabc610a543e2a
Author: Geert Janssens <geert at kobaltwit.be>
Date: Sun Feb 26 20:04:48 2023 +0100
xaccParseAmount... - some code cleanups
- declare at first use
- compact tests
- reduce use of {}
diff --git a/libgnucash/app-utils/gnc-ui-util.c b/libgnucash/app-utils/gnc-ui-util.c
index b32973ee45..fa460f5469 100644
--- a/libgnucash/app-utils/gnc-ui-util.c
+++ b/libgnucash/app-utils/gnc-ui-util.c
@@ -1766,27 +1766,14 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
gboolean use_auto_decimal,
gnc_numeric *result, char **endstr)
{
- gboolean is_negative;
- gboolean got_decimal;
- gboolean need_paren;
- long long int numer;
- long long int denom;
- int count;
-
- ParseState state;
-
- const gchar *in;
- gunichar uc;
- gchar *out_str;
- gchar *out;
-
/* Initialize *endstr to in_str */
- if (endstr != NULL)
+ if (endstr)
*endstr = (char *) in_str;
- if (in_str == NULL)
+ if (!in_str)
return FALSE;
+ const gchar *in;
if (!g_utf8_validate(in_str, -1, &in))
{
printf("Invalid utf8 string '%s'. Bad character at position %ld.\n",
@@ -1796,29 +1783,29 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
/* 'out_str' will be used to store digits for numeric conversion.
* 'out' will be used to traverse out_str. */
- out = out_str = g_new(gchar, strlen(in_str) + 128);
+ gchar *out_str = g_new(gchar, strlen(in_str) + 128);
+ gchar *out = out_str;
/* 'in' is used to traverse 'in_str'. */
in = in_str;
- is_negative = FALSE;
- got_decimal = FALSE;
- need_paren = FALSE;
- numer = 0;
- denom = 1;
+ gboolean is_negative = FALSE;
+ gboolean got_decimal = FALSE;
+ gboolean need_paren = FALSE;
+ long long int numer = 0;
+ long long int denom = 1;
/* Initialize the state machine */
- state = START_ST;
+ ParseState state = START_ST;
/* This while loop implements a state machine for parsing numbers. */
while (TRUE)
{
ParseState next_state = state;
-
- uc = g_utf8_get_char(in);
+ gunichar uc = g_utf8_get_char(in);
/* Ignore anything in the 'ignore list' */
- if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc) != NULL)
+ if (ignore_list && uc && g_utf8_strchr(ignore_list, -1, uc))
{
in = g_utf8_next_char(in);
continue;
@@ -1832,18 +1819,15 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
case START_ST:
if (g_unichar_isdigit(uc))
{
- count = g_unichar_to_utf8(uc, out);
+ int count = g_unichar_to_utf8(uc, out);
out += count; /* we record the digits themselves in out_str
* for later conversion by libc routines */
next_state = NUMER_ST;
}
else if (uc == decimal_point)
- {
next_state = FRAC_ST;
- }
else if (g_unichar_isspace(uc))
- {
- }
+ ;
else if (uc == negative_sign)
{
is_negative = TRUE;
@@ -1856,9 +1840,7 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
next_state = NEG_ST;
}
else
- {
next_state = NO_NUM_ST;
- }
break;
@@ -1867,21 +1849,16 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
case NEG_ST:
if (g_unichar_isdigit(uc))
{
- count = g_unichar_to_utf8(uc, out);
+ int count = g_unichar_to_utf8(uc, out);
out += count;
next_state = NUMER_ST;
}
else if (uc == decimal_point)
- {
next_state = FRAC_ST;
- }
else if (g_unichar_isspace(uc))
- {
- }
+ ;
else
- {
next_state = NO_NUM_ST;
- }
break;
@@ -1890,26 +1867,20 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
case NUMER_ST:
if (g_unichar_isdigit(uc))
{
- count = g_unichar_to_utf8(uc, out);
+ int count = g_unichar_to_utf8(uc, out);
out += count;
}
else if (uc == decimal_point)
- {
next_state = FRAC_ST;
- }
else if (uc == group_separator)
- {
; //ignore it
- }
else if (uc == ')' && need_paren)
{
next_state = DONE_ST;
need_paren = FALSE;
}
else
- {
next_state = DONE_ST;
- }
break;
@@ -1917,7 +1888,7 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
case FRAC_ST:
if (g_unichar_isdigit(uc))
{
- count = g_unichar_to_utf8(uc, out);
+ int count = g_unichar_to_utf8(uc, out);
out += count;
}
else if (uc == decimal_point)
@@ -1944,9 +1915,7 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
need_paren = FALSE;
}
else
- {
next_state = DONE_ST;
- }
break;
@@ -1963,10 +1932,8 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
{
*out = '\0';
- if (*out_str != '\0' && sscanf(out_str, QOF_SCANF_LLD, &numer) < 1)
- {
+ if (*out_str && sscanf(out_str, QOF_SCANF_LLD, &numer) < 1)
next_state = NO_NUM_ST;
- }
else if (next_state == FRAC_ST)
{
/* reset the out pointer to record the fraction */
@@ -1995,12 +1962,10 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
*out = '\0';
/* Add in fractional value */
- if (got_decimal && (*out_str != '\0'))
+ if (got_decimal && *out_str)
{
- size_t len;
- long long int fraction;
- len = strlen(out_str);
+ size_t len = strlen(out_str);
if (len > 12)
{
@@ -2008,6 +1973,7 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
len = 12;
}
+ long long int fraction;
if (sscanf (out_str, QOF_SCANF_LLD, &fraction) < 1)
{
g_free(out_str);
@@ -2032,14 +1998,14 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
}
}
- if (result != NULL)
+ if (result)
{
*result = gnc_numeric_create (numer, denom);
if (is_negative)
*result = gnc_numeric_neg (*result);
}
- if (endstr != NULL)
+ if (endstr)
*endstr = (char *) in;
g_free (out_str);
@@ -2054,14 +2020,10 @@ xaccParseAmountBasicInternal (const char * in_str, gboolean monetary,
char **endstr, gboolean skip)
{
struct lconv *lc = gnc_localeconv();
+ gunichar negative_sign = g_utf8_get_char(lc->negative_sign);
- gunichar negative_sign;
gunichar decimal_point;
gunichar group_separator;
- gchar *ignore = NULL;
- char *plus_sign = "+";
-
- negative_sign = g_utf8_get_char(lc->negative_sign);
if (monetary)
{
group_separator = g_utf8_get_char(lc->mon_thousands_sep);
@@ -2073,6 +2035,7 @@ xaccParseAmountBasicInternal (const char * in_str, gboolean monetary,
decimal_point = g_utf8_get_char(lc->decimal_point);
}
+ gchar *ignore = NULL;
if (skip)
{
/* We want the locale's positive sign to be ignored.
@@ -2080,7 +2043,7 @@ xaccParseAmountBasicInternal (const char * in_str, gboolean monetary,
* an optional positive sign and ignore that */
ignore = lc->positive_sign;
if (!ignore || !*ignore)
- ignore = plus_sign;
+ ignore = "+";
}
return xaccParseAmountInternal(in_str, monetary, negative_sign,
commit 8010d9646c003e5056a063c817515e421255011b
Author: Geert Janssens <geert at kobaltwit.be>
Date: Sun Feb 26 19:39:12 2023 +0100
Restore proper indentation
It got mixed up while refactoring the various xaccParseAmountXYZ functions
diff --git a/libgnucash/app-utils/gnc-ui-util.c b/libgnucash/app-utils/gnc-ui-util.c
index fdcb45910e..b32973ee45 100644
--- a/libgnucash/app-utils/gnc-ui-util.c
+++ b/libgnucash/app-utils/gnc-ui-util.c
@@ -1862,98 +1862,98 @@ xaccParseAmountInternal (const char * in_str, gboolean monetary,
break;
- /* NEG_ST means we have just parsed a negative sign. For now,
- * we only recognize formats where the negative sign comes first. */
- case NEG_ST:
- if (g_unichar_isdigit(uc))
- {
- count = g_unichar_to_utf8(uc, out);
- out += count;
- next_state = NUMER_ST;
- }
- else if (uc == decimal_point)
- {
- next_state = FRAC_ST;
- }
- else if (g_unichar_isspace(uc))
- {
- }
+ /* NEG_ST means we have just parsed a negative sign. For now,
+ * we only recognize formats where the negative sign comes first. */
+ case NEG_ST:
+ if (g_unichar_isdigit(uc))
+ {
+ count = g_unichar_to_utf8(uc, out);
+ out += count;
+ next_state = NUMER_ST;
+ }
+ else if (uc == decimal_point)
+ {
+ next_state = FRAC_ST;
+ }
+ else if (g_unichar_isspace(uc))
+ {
+ }
+ else
+ {
+ next_state = NO_NUM_ST;
+ }
+
+ break;
+
+ /* NUMER_ST means we have started parsing the number, but
+ * have not encountered a decimal separator. */
+ case NUMER_ST:
+ if (g_unichar_isdigit(uc))
+ {
+ count = g_unichar_to_utf8(uc, out);
+ out += count;
+ }
+ else if (uc == decimal_point)
+ {
+ next_state = FRAC_ST;
+ }
+ else if (uc == group_separator)
+ {
+ ; //ignore it
+ }
+ else if (uc == ')' && need_paren)
+ {
+ next_state = DONE_ST;
+ need_paren = FALSE;
+ }
+ else
+ {
+ next_state = DONE_ST;
+ }
+
+ break;
+
+ /* FRAC_ST means we are now parsing fractional digits. */
+ case FRAC_ST:
+ if (g_unichar_isdigit(uc))
+ {
+ count = g_unichar_to_utf8(uc, out);
+ out += count;
+ }
+ else if (uc == decimal_point)
+ {
+ /* If a subsequent decimal point is also whitespace,
+ * assume it was intended as such and stop parsing.
+ * Otherwise, there is a problem. */
+ if (g_unichar_isspace(decimal_point))
+ next_state = DONE_ST;
else
- {
next_state = NO_NUM_ST;
- }
-
- break;
-
- /* NUMER_ST means we have started parsing the number, but
- * have not encountered a decimal separator. */
- case NUMER_ST:
- if (g_unichar_isdigit(uc))
- {
- count = g_unichar_to_utf8(uc, out);
- out += count;
- }
- else if (uc == decimal_point)
- {
- next_state = FRAC_ST;
- }
- else if (uc == group_separator)
- {
- ; //ignore it
- }
- else if (uc == ')' && need_paren)
- {
- next_state = DONE_ST;
- need_paren = FALSE;
- }
- else
- {
- next_state = DONE_ST;
- }
+ }
+ else if (uc == group_separator)
+ {
+ /* If a subsequent group separator is also whitespace,
+ * assume it was intended as such and stop parsing.
+ * Otherwise ignore it. */
+ if (g_unichar_isspace(group_separator))
+ next_state = DONE_ST;
+ }
+ else if (uc == ')' && need_paren)
+ {
+ next_state = DONE_ST;
+ need_paren = FALSE;
+ }
+ else
+ {
+ next_state = DONE_ST;
+ }
- break;
+ break;
- /* FRAC_ST means we are now parsing fractional digits. */
- case FRAC_ST:
- if (g_unichar_isdigit(uc))
- {
- count = g_unichar_to_utf8(uc, out);
- out += count;
- }
- else if (uc == decimal_point)
- {
- /* If a subsequent decimal point is also whitespace,
- * assume it was intended as such and stop parsing.
- * Otherwise, there is a problem. */
- if (g_unichar_isspace(decimal_point))
- next_state = DONE_ST;
- else
- next_state = NO_NUM_ST;
- }
- else if (uc == group_separator)
- {
- /* If a subsequent group separator is also whitespace,
- * assume it was intended as such and stop parsing.
- * Otherwise ignore it. */
- if (g_unichar_isspace(group_separator))
- next_state = DONE_ST;
- }
- else if (uc == ')' && need_paren)
- {
- next_state = DONE_ST;
- need_paren = FALSE;
- }
- else
- {
- next_state = DONE_ST;
- }
-
- break;
-
- default:
- PERR("bad state");
- g_assert_not_reached();
- break;
+ default:
+ PERR("bad state");
+ g_assert_not_reached();
+ break;
}
/* If we're moving into the FRAC_ST or out of the machine
Summary of changes:
gnucash/gnome/assistant-stock-transaction.cpp | 24 ++-
gnucash/import-export/csv-imp/CMakeLists.txt | 2 -
.../csv-imp/assistant-csv-price-import.cpp | 18 +-
.../csv-imp/assistant-csv-trans-import.cpp | 48 ++++-
.../import-export/csv-imp/gnc-csv-account-map.c | 139 -------------
.../import-export/csv-imp/gnc-csv-account-map.h | 69 ------
gnucash/import-export/csv-imp/gnc-imp-props-tx.cpp | 5 +-
gnucash/import-export/csv-imp/gnc-imp-props-tx.hpp | 2 +
.../csv-imp/gnc-imp-settings-csv-price.cpp | 6 +-
.../csv-imp/gnc-imp-settings-csv-tx.cpp | 7 +-
gnucash/import-export/csv-imp/test/CMakeLists.txt | 22 +-
.../csv-imp/test/gtest-gnc-imp-props-tx.cpp | 74 +++++++
libgnucash/app-utils/gnc-ui-util.c | 231 +++++++++------------
libgnucash/engine/Account.cpp | 25 +++
libgnucash/engine/Account.h | 5 +
po/POTFILES.in | 1 -
16 files changed, 300 insertions(+), 378 deletions(-)
delete mode 100644 gnucash/import-export/csv-imp/gnc-csv-account-map.c
delete mode 100644 gnucash/import-export/csv-imp/gnc-csv-account-map.h
create mode 100644 gnucash/import-export/csv-imp/test/gtest-gnc-imp-props-tx.cpp
More information about the gnucash-changes
mailing list