gnucash maint: Multiple changes pushed
Christopher Lam
clam at code.gnucash.org
Tue Mar 1 18:37:51 EST 2022
Updated via https://github.com/Gnucash/gnucash/commit/bd4a4570 (commit)
via https://github.com/Gnucash/gnucash/commit/a4741386 (commit)
via https://github.com/Gnucash/gnucash/commit/8f845df9 (commit)
via https://github.com/Gnucash/gnucash/commit/919f392c (commit)
via https://github.com/Gnucash/gnucash/commit/6c4c2512 (commit)
via https://github.com/Gnucash/gnucash/commit/9088acab (commit)
via https://github.com/Gnucash/gnucash/commit/8bc080b9 (commit)
from https://github.com/Gnucash/gnucash/commit/aeefd893 (commit)
commit bd4a457040f1bbd88b6bf2ee6d00145740ca78ba
Merge: aeefd8934 a47413860
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Wed Mar 2 07:37:17 2022 +0800
Merge branch 'maint-lightning-budget' into maint #1248
commit a47413860ad0b206081b39a2c0b571cadd0cd647
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Thu Jan 20 22:39:41 2022 +0800
Factor out GValue access for setters and getters
diff --git a/libgnucash/engine/gnc-budget.cpp b/libgnucash/engine/gnc-budget.cpp
index 60cc72403..02beeff82 100644
--- a/libgnucash/engine/gnc-budget.cpp
+++ b/libgnucash/engine/gnc-budget.cpp
@@ -496,16 +496,6 @@ gnc_budget_get_num_periods(const GncBudget* budget)
return GET_PRIVATE(budget)->num_periods;
}
-static inline void
-make_period_path (const Account *account, guint period_num, char *path1, char *path2)
-{
- const GncGUID *guid;
- gchar *bufend;
- guid = xaccAccountGetGUID (account);
- guid_to_string_buff (guid, path1);
- g_sprintf (path2, "%d", period_num);
-}
-
static inline StringVec
make_period_data_path (const Account *account, guint period_num)
{
@@ -532,9 +522,6 @@ void
gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
guint period_num)
{
- gchar path_part_one [GUID_ENCODING_LENGTH + 1];
- gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
-
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
g_return_if_fail (period_num < GET_PRIVATE(budget)->num_periods);
@@ -542,10 +529,10 @@ gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
auto& data = get_perioddata (budget, account, period_num);
data.value_is_set = false;
- make_period_path (account, period_num, path_part_one, path_part_two);
-
gnc_budget_begin_edit(budget);
- qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
+ auto path = make_period_data_path (account, period_num);
+ auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
+ delete budget_kvp->set_path (path, nullptr);
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -559,9 +546,6 @@ void
gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
guint period_num, gnc_numeric val)
{
- gchar path_part_one [GUID_ENCODING_LENGTH + 1];
- gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
-
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
if (period_num >= GET_PRIVATE(budget)->num_periods)
@@ -574,22 +558,19 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_return_if_fail (account != NULL);
auto& perioddata = get_perioddata (budget, account, period_num);
-
- make_period_path (account, period_num, path_part_one, path_part_two);
+ auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
+ auto path = make_period_data_path (account, period_num);
gnc_budget_begin_edit(budget);
if (gnc_numeric_check(val))
{
- qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
+ delete budget_kvp->set_path (path, nullptr);
perioddata.value_is_set = false;
}
else
{
- GValue v = G_VALUE_INIT;
- g_value_init (&v, GNC_TYPE_NUMERIC);
- g_value_set_boxed (&v, &val);
- qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
- g_value_unset (&v);
+ KvpValue* v = new KvpValue (val);
+ delete budget_kvp->set_path (path, v);
perioddata.value_is_set = true;
perioddata.value = val;
}
@@ -627,9 +608,6 @@ void
gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
guint period_num, const gchar *note)
{
- gchar path_part_one [GUID_ENCODING_LENGTH + 1];
- gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
-
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
if (period_num >= GET_PRIVATE(budget)->num_periods)
@@ -642,23 +620,20 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
g_return_if_fail (account != NULL);
auto& perioddata = get_perioddata (budget, account, period_num);
-
- make_period_path (account, period_num, path_part_one, path_part_two);
+ auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
+ auto path = make_period_note_path (account, period_num);
gnc_budget_begin_edit(budget);
if (note == NULL)
{
- qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
+ delete budget_kvp->set_path (path, nullptr);
perioddata.note.clear ();
}
else
{
- GValue v = G_VALUE_INIT;
- g_value_init (&v, G_TYPE_STRING);
- g_value_set_string (&v, note);
+ KvpValue* v = new KvpValue (g_strdup (note));
- qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
- g_value_unset (&v);
+ delete budget_kvp->set_path (path, v);
perioddata.note = note;
}
qof_instance_set_dirty(&budget->inst);
commit 8f845df93479264eb78f6cfe0f239273dbdd7c5d
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Thu Jan 20 22:24:20 2022 +0800
Factor out make_period_[data|note]_path
diff --git a/libgnucash/engine/gnc-budget.cpp b/libgnucash/engine/gnc-budget.cpp
index b69c6094f..60cc72403 100644
--- a/libgnucash/engine/gnc-budget.cpp
+++ b/libgnucash/engine/gnc-budget.cpp
@@ -506,6 +506,22 @@ make_period_path (const Account *account, guint period_num, char *path1, char *p
g_sprintf (path2, "%d", period_num);
}
+static inline StringVec
+make_period_data_path (const Account *account, guint period_num)
+{
+ gnc::GUID acct_guid {*(xaccAccountGetGUID (account))};
+ return { acct_guid.to_string(), std::to_string (period_num) };
+}
+
+static inline StringVec
+make_period_note_path (const Account *account, guint period_num)
+{
+ StringVec path { GNC_BUDGET_NOTES_PATH };
+ StringVec data_path { make_period_data_path (account, period_num) };
+ std::move (data_path.begin(), data_path.end(), std::back_inserter (path));
+ return path;
+}
+
static PeriodData& get_perioddata (const GncBudget *budget,
const Account *account,
guint period_num);
@@ -699,19 +715,15 @@ get_perioddata (const GncBudget *budget, const Account *account, guint period_nu
if (map_iter == map->end ())
{
auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
- std::string acct_guid { guid_to_string (xaccAccountGetGUID (account)) };
PeriodDataVec vec {};
vec.reserve (priv->num_periods);
for (guint i = 0; i < priv->num_periods; i++)
{
- std::string period_str { std::to_string (i) };
std::string note;
- StringVec path1 { acct_guid, period_str };
- StringVec path2 { GNC_BUDGET_NOTES_PATH, acct_guid, period_str };
- auto kval1 { budget_kvp->get_slot (path1) };
- auto kval2 { budget_kvp->get_slot (path2) };
+ auto kval1 { budget_kvp->get_slot (make_period_data_path (account, i)) };
+ auto kval2 { budget_kvp->get_slot (make_period_note_path (account, i)) };
auto is_set = kval1 && kval1->get_type() == KvpValue::Type::NUMERIC;
auto num = is_set ? kval1->get<gnc_numeric>() : gnc_numeric_zero ();
commit 919f392c7a43bb5cc469dfc6ace75e4b10db24c4
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Thu Jan 20 21:34:30 2022 +0800
Use kvp C++ interface rather than GValue
diff --git a/libgnucash/engine/gnc-budget.cpp b/libgnucash/engine/gnc-budget.cpp
index 45692498b..b69c6094f 100644
--- a/libgnucash/engine/gnc-budget.cpp
+++ b/libgnucash/engine/gnc-budget.cpp
@@ -71,6 +71,7 @@ struct PeriodData
using PeriodDataVec = std::vector<PeriodData>;
using AcctMap = std::unordered_map<const Account*, PeriodDataVec>;
+using StringVec = std::vector<std::string>;
typedef struct GncBudgetPrivate
{
@@ -583,30 +584,6 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
}
-/* We don't need these here, but maybe they're useful somewhere else?
- Maybe this should move to Account.h */
-
-static gboolean
-is_account_period_value_set (const GncBudget *budget,
- const Account *account,
- guint period_num)
-{
- GValue v = G_VALUE_INIT;
- gchar path_part_one [GUID_ENCODING_LENGTH + 1];
- gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
- gconstpointer ptr = NULL;
-
- g_return_val_if_fail(GNC_IS_BUDGET(budget), FALSE);
- g_return_val_if_fail(account, FALSE);
-
- make_period_path (account, period_num, path_part_one, path_part_two);
- qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
- if (G_VALUE_HOLDS_BOXED (&v))
- ptr = g_value_get_boxed (&v);
- g_value_unset (&v);
- return (ptr != NULL);
-}
-
gboolean
gnc_budget_is_account_period_value_set (const GncBudget *budget,
const Account *account,
@@ -616,30 +593,6 @@ gnc_budget_is_account_period_value_set (const GncBudget *budget,
return get_perioddata (budget, account, period_num).value_is_set;
}
-static gnc_numeric
-get_account_period_value (const GncBudget *budget,
- const Account *account,
- guint period_num)
-{
- gnc_numeric *numeric = NULL;
- gnc_numeric retval;
- gchar path_part_one [GUID_ENCODING_LENGTH + 1];
- gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
- GValue v = G_VALUE_INIT;
-
- g_return_val_if_fail(GNC_IS_BUDGET(budget), gnc_numeric_zero());
- g_return_val_if_fail(account, gnc_numeric_zero());
-
- make_period_path (account, period_num, path_part_one, path_part_two);
- qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
- if (G_VALUE_HOLDS_BOXED (&v))
- numeric = (gnc_numeric*)g_value_get_boxed (&v);
-
- retval = numeric ? *numeric : gnc_numeric_zero ();
- g_value_unset (&v);
- return retval;
-}
-
gnc_numeric
gnc_budget_get_account_period_value (const GncBudget *budget,
const Account *account,
@@ -699,27 +652,6 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
}
-static std::string
-get_account_period_note (const GncBudget *budget,
- const Account *account, guint period_num)
-{
- gchar path_part_one [GUID_ENCODING_LENGTH + 1];
- gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
- GValue v = G_VALUE_INIT;
- std::string retval;
-
- g_return_val_if_fail (GNC_IS_BUDGET(budget), "");
- g_return_val_if_fail (account, "");
-
- make_period_path (account, period_num, path_part_one, path_part_two);
- qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
- if (G_VALUE_HOLDS_STRING (&v))
- retval = g_value_get_string(&v);
- g_value_unset (&v);
- return retval;
-}
-
-
gchar *
gnc_budget_get_account_period_note (const GncBudget *budget,
const Account *account, guint period_num)
@@ -766,16 +698,28 @@ get_perioddata (const GncBudget *budget, const Account *account, guint period_nu
if (map_iter == map->end ())
{
+ auto budget_kvp { QOF_INSTANCE (budget)->kvp_data };
+ std::string acct_guid { guid_to_string (xaccAccountGetGUID (account)) };
+
PeriodDataVec vec {};
vec.reserve (priv->num_periods);
for (guint i = 0; i < priv->num_periods; i++)
{
- PeriodData data {};
- data.note = get_account_period_note (budget, account, i);
- data.value_is_set = is_account_period_value_set (budget, account, i);
- if (data.value_is_set)
- data.value = get_account_period_value (budget, account, i);
+ std::string period_str { std::to_string (i) };
+ std::string note;
+ StringVec path1 { acct_guid, period_str };
+ StringVec path2 { GNC_BUDGET_NOTES_PATH, acct_guid, period_str };
+ auto kval1 { budget_kvp->get_slot (path1) };
+ auto kval2 { budget_kvp->get_slot (path2) };
+
+ auto is_set = kval1 && kval1->get_type() == KvpValue::Type::NUMERIC;
+ auto num = is_set ? kval1->get<gnc_numeric>() : gnc_numeric_zero ();
+
+ if (kval2 && kval2->get_type() == KvpValue::Type::STRING)
+ note = kval2->get<const char*>();
+
+ PeriodData data { std::move (note), is_set, num };
vec.push_back (std::move(data));
}
map_iter = map->insert_or_assign(account, std::move(vec)).first;
commit 6c4c2512db53fc6b874f2004b743539fc651a9d2
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Thu Jan 13 21:01:36 2022 +0800
Use C++ STL instead of GLib
diff --git a/libgnucash/engine/gnc-budget.cpp b/libgnucash/engine/gnc-budget.cpp
index 47f09e0ff..45692498b 100644
--- a/libgnucash/engine/gnc-budget.cpp
+++ b/libgnucash/engine/gnc-budget.cpp
@@ -30,6 +30,9 @@
#include <qof.h>
#include <qofbookslots.h>
#include <qofinstance-p.h>
+#include <unordered_map>
+#include <vector>
+#include <memory>
#include "Account.h"
@@ -59,6 +62,16 @@ typedef struct
QofInstanceClass parent_class;
} BudgetClass;
+struct PeriodData
+{
+ std::string note;
+ bool value_is_set;
+ gnc_numeric value;
+};
+
+using PeriodDataVec = std::vector<PeriodData>;
+using AcctMap = std::unordered_map<const Account*, PeriodDataVec>;
+
typedef struct GncBudgetPrivate
{
/* The name is an arbitrary string assigned by the user. */
@@ -70,7 +83,7 @@ typedef struct GncBudgetPrivate
/* Recurrence (period info) for the budget */
Recurrence recurrence;
- GHashTable *acct_hash;
+ std::unique_ptr<AcctMap> acct_map;
/* Number of periods */
guint num_periods;
@@ -87,24 +100,6 @@ struct _GncBudgetClass
/* GObject Initialization */
G_DEFINE_TYPE_WITH_PRIVATE(GncBudget, gnc_budget, QOF_TYPE_INSTANCE)
-typedef struct PeriodData
-{
- gchar *note;
- gboolean value_is_set;
- gnc_numeric value;
-} PeriodData;
-
-static void acct_array_free (GArray *acct_array, gpointer user_data)
-{
- for (guint i = 0; i < acct_array->len; i++)
- {
- PeriodData *perioddata = &g_array_index (acct_array, PeriodData, i);
- if (perioddata->note)
- g_free (perioddata->note);
- }
- g_array_free (acct_array, FALSE);
-}
-
static void
gnc_budget_init(GncBudget* budget)
{
@@ -114,9 +109,7 @@ gnc_budget_init(GncBudget* budget)
priv = GET_PRIVATE(budget);
priv->name = CACHE_INSERT(_("Unnamed Budget"));
priv->description = CACHE_INSERT("");
-
- priv->acct_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) acct_array_free);
+ priv->acct_map = std::make_unique<AcctMap>();
priv->num_periods = 12;
date = gnc_g_date_new_today ();
@@ -286,8 +279,7 @@ gnc_budget_free(QofInstance *inst)
CACHE_REMOVE(priv->name);
CACHE_REMOVE(priv->description);
-
- g_hash_table_destroy (priv->acct_hash);
+ priv->acct_map = nullptr; // nullify to ensure unique_ptr is freed.
/* qof_instance_release (&budget->inst); */
g_object_unref(budget);
@@ -471,13 +463,6 @@ gnc_budget_get_guid(const GncBudget* budget)
return qof_instance_get_guid(QOF_INSTANCE(budget));
}
-static void
-set_num_periods (GArray *perioddata, gpointer user_data)
-{
- gint num_periods = GPOINTER_TO_INT (user_data);
- g_array_set_size (perioddata, num_periods);
-}
-
void
gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
{
@@ -493,8 +478,12 @@ gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
- g_hash_table_foreach (priv->acct_hash, (GHFunc) set_num_periods,
- GUINT_TO_POINTER (num_periods));
+ std::for_each (priv->acct_map->begin(),
+ priv->acct_map->end(),
+ [num_periods](auto& it)
+ {
+ it.second.resize(num_periods);
+ });
qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
}
@@ -516,8 +505,9 @@ make_period_path (const Account *account, guint period_num, char *path1, char *p
g_sprintf (path2, "%d", period_num);
}
-static GArray* get_acct_array (const GncBudget *budget, const Account *account);
-
+static PeriodData& get_perioddata (const GncBudget *budget,
+ const Account *account,
+ guint period_num);
/* period_num is zero-based */
/* What happens when account is deleted, after we have an entry for it? */
@@ -525,17 +515,15 @@ void
gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
guint period_num)
{
- GArray *acct_array;
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
- PeriodData *perioddata;
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
+ g_return_if_fail (period_num < GET_PRIVATE(budget)->num_periods);
- acct_array = get_acct_array (budget, account);
- perioddata = &g_array_index (acct_array, PeriodData, period_num);
- perioddata->value_is_set = FALSE;
+ auto& data = get_perioddata (budget, account, period_num);
+ data.value_is_set = false;
make_period_path (account, period_num, path_part_one, path_part_two);
@@ -556,8 +544,6 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
- GArray *acct_array;
- PeriodData *perioddata;
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
@@ -570,8 +556,7 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
- acct_array = get_acct_array (budget, account);
- perioddata = &g_array_index (acct_array, PeriodData, period_num);
+ auto& perioddata = get_perioddata (budget, account, period_num);
make_period_path (account, period_num, path_part_one, path_part_two);
@@ -579,7 +564,7 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
if (gnc_numeric_check(val))
{
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
- perioddata->value_is_set = FALSE;
+ perioddata.value_is_set = false;
}
else
{
@@ -588,8 +573,8 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_value_set_boxed (&v, &val);
qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
g_value_unset (&v);
- perioddata->value_is_set = TRUE;
- perioddata->value = val;
+ perioddata.value_is_set = true;
+ perioddata.value = val;
}
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -627,9 +612,8 @@ gnc_budget_is_account_period_value_set (const GncBudget *budget,
const Account *account,
guint period_num)
{
- GArray *array = get_acct_array (budget, account);
- PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, period_num);
- return data->value_is_set;
+ g_return_val_if_fail (period_num < GET_PRIVATE(budget)->num_periods, false);
+ return get_perioddata (budget, account, period_num).value_is_set;
}
static gnc_numeric
@@ -661,9 +645,13 @@ gnc_budget_get_account_period_value (const GncBudget *budget,
const Account *account,
guint period_num)
{
- GArray *array = get_acct_array (budget, account);
- PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, period_num);
- return data->value_is_set ? data->value : gnc_numeric_zero ();
+ g_return_val_if_fail (period_num < GET_PRIVATE(budget)->num_periods,
+ gnc_numeric_zero());
+ auto& data = get_perioddata (budget, account, period_num);
+ if (!data.value_is_set)
+ return gnc_numeric_zero();
+
+ return data.value;
}
void
@@ -672,8 +660,6 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
- GArray *acct_array;
- PeriodData *perioddata;
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
@@ -686,17 +672,16 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
- acct_array = get_acct_array (budget, account);
- perioddata = &g_array_index (acct_array, PeriodData, period_num);
+ auto& perioddata = get_perioddata (budget, account, period_num);
make_period_path (account, period_num, path_part_one, path_part_two);
gnc_budget_begin_edit(budget);
- if (perioddata->note)
- g_free (perioddata->note);
- perioddata->note = g_strdup (note);
if (note == NULL)
+ {
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
+ perioddata.note.clear ();
+ }
else
{
GValue v = G_VALUE_INIT;
@@ -705,6 +690,7 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
g_value_unset (&v);
+ perioddata.note = note;
}
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -713,21 +699,22 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
}
-static gchar *
+static std::string
get_account_period_note (const GncBudget *budget,
const Account *account, guint period_num)
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
GValue v = G_VALUE_INIT;
- gchar *retval;
+ std::string retval;
- g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
- g_return_val_if_fail(account, NULL);
+ g_return_val_if_fail (GNC_IS_BUDGET(budget), "");
+ g_return_val_if_fail (account, "");
make_period_path (account, period_num, path_part_one, path_part_two);
qof_instance_get_kvp (QOF_INSTANCE (budget), &v, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
- retval = G_VALUE_HOLDS_STRING (&v) ? g_value_dup_string(&v) : NULL;
+ if (G_VALUE_HOLDS_STRING (&v))
+ retval = g_value_get_string(&v);
g_value_unset (&v);
return retval;
}
@@ -737,9 +724,9 @@ gchar *
gnc_budget_get_account_period_note (const GncBudget *budget,
const Account *account, guint period_num)
{
- GArray *array = get_acct_array (budget, account);
- PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, period_num);
- return g_strdup (data->note);
+ g_return_val_if_fail (period_num < GET_PRIVATE(budget)->num_periods, nullptr);
+ auto& data = get_perioddata (budget, account, period_num);
+ return data.note.empty () ? nullptr : g_strdup (data.note.c_str());
}
time64
@@ -766,31 +753,36 @@ gnc_budget_get_account_period_actual_value(
acc, period_num);
}
-static GArray*
-get_acct_array (const GncBudget *budget, const Account *account)
+static PeriodData&
+get_perioddata (const GncBudget *budget, const Account *account, guint period_num)
{
GncBudgetPrivate *priv = GET_PRIVATE (budget);
- GArray *array;
- if (!g_hash_table_lookup_extended (priv->acct_hash, account, NULL,
- (gpointer*)(&array)))
+ if (period_num >= priv->num_periods)
+ throw std::out_of_range("period_num >= num_periods");
+
+ auto& map = priv->acct_map;
+ auto map_iter = map->find (account);
+
+ if (map_iter == map->end ())
{
- array = g_array_sized_new (FALSE, TRUE, sizeof (PeriodData),
- priv->num_periods);
- g_hash_table_insert (priv->acct_hash, (gpointer)account, array);
+ PeriodDataVec vec {};
+ vec.reserve (priv->num_periods);
for (guint i = 0; i < priv->num_periods; i++)
{
- PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, i);
- data->note = get_account_period_note (budget, account, i);
- data->value_is_set = is_account_period_value_set (budget, account, i);
-
- if (data->value_is_set)
- data->value = get_account_period_value (budget, account, i);
+ PeriodData data {};
+ data.note = get_account_period_note (budget, account, i);
+ data.value_is_set = is_account_period_value_set (budget, account, i);
+ if (data.value_is_set)
+ data.value = get_account_period_value (budget, account, i);
+ vec.push_back (std::move(data));
}
+ map_iter = map->insert_or_assign(account, std::move(vec)).first;
}
- return array;
+ auto& vec = map_iter->second;
+ return vec.at(period_num);
}
GncBudget*
diff --git a/libgnucash/engine/test/utest-Budget.c b/libgnucash/engine/test/utest-Budget.c
index 7e8a2d94a..f899b38a3 100644
--- a/libgnucash/engine/test/utest-Budget.c
+++ b/libgnucash/engine/test/utest-Budget.c
@@ -96,10 +96,10 @@ test_gnc_set_budget_num_periods_data_retention ()
gnc_budget_set_num_periods(budget, 10);
gnc_budget_set_num_periods(budget, 20);
- /* value and note are retained */
- g_assert (gnc_budget_is_account_period_value_set(budget, acc, 15));
+ /* value and note are lost */
+ g_assert (!gnc_budget_is_account_period_value_set(budget, acc, 15));
note = gnc_budget_get_account_period_note (budget, acc, 11);
- g_assert_cmpstr (note, ==, "undefined");
+ g_assert_cmpstr (note, ==, NULL);
g_free (note);
gnc_budget_destroy(budget);
commit 9088acabd866ee50b1c6c620569368bb46079082
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Thu Jan 13 18:10:38 2022 +0800
[gnc-budget.cpp] convert to c++
diff --git a/libgnucash/engine/CMakeLists.txt b/libgnucash/engine/CMakeLists.txt
index d860bd436..8dde8461b 100644
--- a/libgnucash/engine/CMakeLists.txt
+++ b/libgnucash/engine/CMakeLists.txt
@@ -139,7 +139,7 @@ set (engine_SOURCES
cap-gains.c
cashobjects.c
gnc-aqbanking-templates.cpp
- gnc-budget.c
+ gnc-budget.cpp
gnc-commodity.c
gnc-date.cpp
gnc-datetime.cpp
diff --git a/libgnucash/engine/gnc-budget.c b/libgnucash/engine/gnc-budget.cpp
similarity index 98%
rename from libgnucash/engine/gnc-budget.c
rename to libgnucash/engine/gnc-budget.cpp
index a6e994a15..47f09e0ff 100644
--- a/libgnucash/engine/gnc-budget.c
+++ b/libgnucash/engine/gnc-budget.cpp
@@ -33,6 +33,7 @@
#include "Account.h"
+#include "guid.hpp"
#include "gnc-budget.h"
#include "gnc-commodity.h"
@@ -196,7 +197,7 @@ gnc_budget_set_property( GObject* object,
gnc_budget_set_num_periods(budget, g_value_get_uint(value));
break;
case PROP_RECURRENCE:
- gnc_budget_set_recurrence(budget, g_value_get_pointer(value));
+ gnc_budget_set_recurrence (budget, static_cast<Recurrence*>(g_value_get_pointer(value)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -311,12 +312,11 @@ gnc_budget_commit_edit(GncBudget *bgt)
GncBudget*
gnc_budget_new(QofBook *book)
{
- GncBudget* budget;
-
g_return_val_if_fail(book, NULL);
ENTER(" ");
- budget = g_object_new(GNC_TYPE_BUDGET, NULL);
+
+ auto budget { static_cast<GncBudget*>(g_object_new(GNC_TYPE_BUDGET, nullptr)) };
qof_instance_init_data (&budget->inst, GNC_ID_BUDGET, book);
qof_event_gen( &budget->inst, QOF_EVENT_CREATE , NULL);
@@ -773,7 +773,7 @@ get_acct_array (const GncBudget *budget, const Account *account)
GArray *array;
if (!g_hash_table_lookup_extended (priv->acct_hash, account, NULL,
- (gpointer) &array))
+ (gpointer*)(&array)))
{
array = g_array_sized_new (FALSE, TRUE, sizeof (PeriodData),
priv->num_periods);
@@ -879,7 +879,7 @@ static QofObject budget_object_def =
DI(.interface_version = ) QOF_OBJECT_VERSION,
DI(.e_type = ) GNC_ID_BUDGET,
DI(.type_label = ) "Budget",
- DI(.create = ) (gpointer)gnc_budget_new,
+ DI(.create = ) (void*(*)(QofBook*)) gnc_budget_new,
DI(.book_begin = ) NULL,
DI(.book_end = ) gnc_budget_book_end,
DI(.is_dirty = ) qof_collection_is_dirty,
diff --git a/libgnucash/engine/gnc-budget.h b/libgnucash/engine/gnc-budget.h
index f5b9a2cee..d9c1e814d 100644
--- a/libgnucash/engine/gnc-budget.h
+++ b/libgnucash/engine/gnc-budget.h
@@ -64,6 +64,11 @@
#ifndef __GNC_BUDGET_H__
#define __GNC_BUDGET_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
#include <glib.h>
/** The budget data.*/
@@ -171,6 +176,11 @@ GncBudget* gnc_budget_get_default(QofBook *book);
GncBudget* gnc_budget_lookup (const GncGUID *guid, const QofBook *book);
#define gnc_budget_lookup_direct(g,b) gnc_budget_lookup(&(g),(b))
+#ifdef __cplusplus
+}
+#endif
+
+
#endif // __BUDGET_H__
/** @} */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 365d56798..2194e9e5e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -630,7 +630,7 @@ libgnucash/engine/engine-helpers.c
libgnucash/engine/gncAddress.c
libgnucash/engine/gnc-aqbanking-templates.cpp
libgnucash/engine/gncBillTerm.c
-libgnucash/engine/gnc-budget.c
+libgnucash/engine/gnc-budget.cpp
libgnucash/engine/gncBusiness.c
libgnucash/engine/gnc-commodity.c
libgnucash/engine/gnc-commodity.h
commit 8bc080b96dd13bf89376245c214e692173b57acb
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Wed Jan 12 22:11:36 2022 +0800
[gnc-budget] store budget kvp data onto memory upon first call.
then each getter will retrieve from memory rather than backend's kvp.
diff --git a/libgnucash/engine/gnc-budget.c b/libgnucash/engine/gnc-budget.c
index db4b3ec5d..a6e994a15 100644
--- a/libgnucash/engine/gnc-budget.c
+++ b/libgnucash/engine/gnc-budget.c
@@ -69,6 +69,8 @@ typedef struct GncBudgetPrivate
/* Recurrence (period info) for the budget */
Recurrence recurrence;
+ GHashTable *acct_hash;
+
/* Number of periods */
guint num_periods;
} GncBudgetPrivate;
@@ -84,6 +86,24 @@ struct _GncBudgetClass
/* GObject Initialization */
G_DEFINE_TYPE_WITH_PRIVATE(GncBudget, gnc_budget, QOF_TYPE_INSTANCE)
+typedef struct PeriodData
+{
+ gchar *note;
+ gboolean value_is_set;
+ gnc_numeric value;
+} PeriodData;
+
+static void acct_array_free (GArray *acct_array, gpointer user_data)
+{
+ for (guint i = 0; i < acct_array->len; i++)
+ {
+ PeriodData *perioddata = &g_array_index (acct_array, PeriodData, i);
+ if (perioddata->note)
+ g_free (perioddata->note);
+ }
+ g_array_free (acct_array, FALSE);
+}
+
static void
gnc_budget_init(GncBudget* budget)
{
@@ -94,6 +114,9 @@ gnc_budget_init(GncBudget* budget)
priv->name = CACHE_INSERT(_("Unnamed Budget"));
priv->description = CACHE_INSERT("");
+ priv->acct_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+ (GDestroyNotify) acct_array_free);
+
priv->num_periods = 12;
date = gnc_g_date_new_today ();
g_date_subtract_days(date, g_date_get_day(date) - 1);
@@ -263,6 +286,8 @@ gnc_budget_free(QofInstance *inst)
CACHE_REMOVE(priv->name);
CACHE_REMOVE(priv->description);
+ g_hash_table_destroy (priv->acct_hash);
+
/* qof_instance_release (&budget->inst); */
g_object_unref(budget);
}
@@ -446,6 +471,13 @@ gnc_budget_get_guid(const GncBudget* budget)
return qof_instance_get_guid(QOF_INSTANCE(budget));
}
+static void
+set_num_periods (GArray *perioddata, gpointer user_data)
+{
+ gint num_periods = GPOINTER_TO_INT (user_data);
+ g_array_set_size (perioddata, num_periods);
+}
+
void
gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
{
@@ -461,6 +493,9 @@ gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
+ g_hash_table_foreach (priv->acct_hash, (GHFunc) set_num_periods,
+ GUINT_TO_POINTER (num_periods));
+
qof_event_gen( &budget->inst, QOF_EVENT_MODIFY, NULL);
}
@@ -481,17 +516,27 @@ make_period_path (const Account *account, guint period_num, char *path1, char *p
g_sprintf (path2, "%d", period_num);
}
+static GArray* get_acct_array (const GncBudget *budget, const Account *account);
+
+
/* period_num is zero-based */
/* What happens when account is deleted, after we have an entry for it? */
void
gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
guint period_num)
{
+ GArray *acct_array;
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
+ PeriodData *perioddata;
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
+
+ acct_array = get_acct_array (budget, account);
+ perioddata = &g_array_index (acct_array, PeriodData, period_num);
+ perioddata->value_is_set = FALSE;
+
make_period_path (account, period_num, path_part_one, path_part_two);
gnc_budget_begin_edit(budget);
@@ -511,6 +556,8 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
+ GArray *acct_array;
+ PeriodData *perioddata;
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
@@ -523,11 +570,17 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
+ acct_array = get_acct_array (budget, account);
+ perioddata = &g_array_index (acct_array, PeriodData, period_num);
+
make_period_path (account, period_num, path_part_one, path_part_two);
gnc_budget_begin_edit(budget);
if (gnc_numeric_check(val))
+ {
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 2, path_part_one, path_part_two);
+ perioddata->value_is_set = FALSE;
+ }
else
{
GValue v = G_VALUE_INIT;
@@ -535,6 +588,8 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
g_value_set_boxed (&v, &val);
qof_instance_set_kvp (QOF_INSTANCE (budget), &v, 2, path_part_one, path_part_two);
g_value_unset (&v);
+ perioddata->value_is_set = TRUE;
+ perioddata->value = val;
}
qof_instance_set_dirty(&budget->inst);
gnc_budget_commit_edit(budget);
@@ -546,10 +601,10 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
/* We don't need these here, but maybe they're useful somewhere else?
Maybe this should move to Account.h */
-gboolean
-gnc_budget_is_account_period_value_set(const GncBudget *budget,
- const Account *account,
- guint period_num)
+static gboolean
+is_account_period_value_set (const GncBudget *budget,
+ const Account *account,
+ guint period_num)
{
GValue v = G_VALUE_INIT;
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
@@ -567,10 +622,20 @@ gnc_budget_is_account_period_value_set(const GncBudget *budget,
return (ptr != NULL);
}
-gnc_numeric
-gnc_budget_get_account_period_value(const GncBudget *budget,
- const Account *account,
- guint period_num)
+gboolean
+gnc_budget_is_account_period_value_set (const GncBudget *budget,
+ const Account *account,
+ guint period_num)
+{
+ GArray *array = get_acct_array (budget, account);
+ PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, period_num);
+ return data->value_is_set;
+}
+
+static gnc_numeric
+get_account_period_value (const GncBudget *budget,
+ const Account *account,
+ guint period_num)
{
gnc_numeric *numeric = NULL;
gnc_numeric retval;
@@ -591,6 +656,15 @@ gnc_budget_get_account_period_value(const GncBudget *budget,
return retval;
}
+gnc_numeric
+gnc_budget_get_account_period_value (const GncBudget *budget,
+ const Account *account,
+ guint period_num)
+{
+ GArray *array = get_acct_array (budget, account);
+ PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, period_num);
+ return data->value_is_set ? data->value : gnc_numeric_zero ();
+}
void
gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
@@ -598,6 +672,8 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
+ GArray *acct_array;
+ PeriodData *perioddata;
/* Watch out for an off-by-one error here:
* period_num starts from 0 while num_periods starts from 1 */
@@ -610,9 +686,15 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
g_return_if_fail (budget != NULL);
g_return_if_fail (account != NULL);
+ acct_array = get_acct_array (budget, account);
+ perioddata = &g_array_index (acct_array, PeriodData, period_num);
+
make_period_path (account, period_num, path_part_one, path_part_two);
gnc_budget_begin_edit(budget);
+ if (perioddata->note)
+ g_free (perioddata->note);
+ perioddata->note = g_strdup (note);
if (note == NULL)
qof_instance_set_kvp (QOF_INSTANCE (budget), NULL, 3, GNC_BUDGET_NOTES_PATH, path_part_one, path_part_two);
else
@@ -631,9 +713,9 @@ gnc_budget_set_account_period_note(GncBudget *budget, const Account *account,
}
-gchar *
-gnc_budget_get_account_period_note(const GncBudget *budget,
- const Account *account, guint period_num)
+static gchar *
+get_account_period_note (const GncBudget *budget,
+ const Account *account, guint period_num)
{
gchar path_part_one [GUID_ENCODING_LENGTH + 1];
gchar path_part_two [GNC_BUDGET_MAX_NUM_PERIODS_DIGITS];
@@ -650,6 +732,16 @@ gnc_budget_get_account_period_note(const GncBudget *budget,
return retval;
}
+
+gchar *
+gnc_budget_get_account_period_note (const GncBudget *budget,
+ const Account *account, guint period_num)
+{
+ GArray *array = get_acct_array (budget, account);
+ PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, period_num);
+ return g_strdup (data->note);
+}
+
time64
gnc_budget_get_period_start_date(const GncBudget *budget, guint period_num)
{
@@ -674,6 +766,33 @@ gnc_budget_get_account_period_actual_value(
acc, period_num);
}
+static GArray*
+get_acct_array (const GncBudget *budget, const Account *account)
+{
+ GncBudgetPrivate *priv = GET_PRIVATE (budget);
+ GArray *array;
+
+ if (!g_hash_table_lookup_extended (priv->acct_hash, account, NULL,
+ (gpointer) &array))
+ {
+ array = g_array_sized_new (FALSE, TRUE, sizeof (PeriodData),
+ priv->num_periods);
+ g_hash_table_insert (priv->acct_hash, (gpointer)account, array);
+
+ for (guint i = 0; i < priv->num_periods; i++)
+ {
+ PeriodData *data = (PeriodData*) &g_array_index (array, PeriodData, i);
+ data->note = get_account_period_note (budget, account, i);
+ data->value_is_set = is_account_period_value_set (budget, account, i);
+
+ if (data->value_is_set)
+ data->value = get_account_period_value (budget, account, i);
+ }
+ }
+
+ return array;
+}
+
GncBudget*
gnc_budget_lookup (const GncGUID *guid, const QofBook *book)
{
Summary of changes:
libgnucash/engine/CMakeLists.txt | 2 +-
libgnucash/engine/{gnc-budget.c => gnc-budget.cpp} | 226 ++++++++++++---------
libgnucash/engine/gnc-budget.h | 10 +
libgnucash/engine/test/utest-Budget.c | 6 +-
po/POTFILES.in | 2 +-
5 files changed, 149 insertions(+), 97 deletions(-)
rename libgnucash/engine/{gnc-budget.c => gnc-budget.cpp} (79%)
More information about the gnucash-changes
mailing list