gnucash maint: Multiple changes pushed
John Ralls
jralls at code.gnucash.org
Thu May 23 12:54:48 EDT 2019
Updated via https://github.com/Gnucash/gnucash/commit/2d4f771b (commit)
via https://github.com/Gnucash/gnucash/commit/f6df367f (commit)
via https://github.com/Gnucash/gnucash/commit/51dda770 (commit)
via https://github.com/Gnucash/gnucash/commit/91aceaa7 (commit)
via https://github.com/Gnucash/gnucash/commit/d16a236e (commit)
via https://github.com/Gnucash/gnucash/commit/0319144b (commit)
via https://github.com/Gnucash/gnucash/commit/5bb54d07 (commit)
via https://github.com/Gnucash/gnucash/commit/df1cc590 (commit)
via https://github.com/Gnucash/gnucash/commit/52895eab (commit)
via https://github.com/Gnucash/gnucash/commit/93bf1a0f (commit)
from https://github.com/Gnucash/gnucash/commit/311f7d26 (commit)
commit 2d4f771bedf13ef9a2de4bd45d25d9afc860a8ec
Merge: 311f7d26e f6df367f5
Author: John Ralls <jralls at ceridwen.us>
Date: Thu May 23 09:50:20 2019 -0700
Merge Adrién Panella's 'budget' into maint.
commit f6df367f50506aef8ae6f18cffbbbad6db2b945f
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Sat May 18 14:14:27 2019 -0500
[budget] Remove unused code
Remove some priv attributes and code that were never used
diff --git a/gnucash/gnome/gnc-budget-view.c b/gnucash/gnome/gnc-budget-view.c
index 697701fce..3710196b3 100644
--- a/gnucash/gnome/gnc-budget-view.c
+++ b/gnucash/gnome/gnc-budget-view.c
@@ -161,10 +161,6 @@ struct GncBudgetViewPrivate
GtkTreeViewColumn* total_col;
AccountFilterDialog *fd;
- Account* income;
- Account* expenses;
- Account* assets;
- Account* liabilities;
Account* rootAcct;
GtkCellRenderer *temp_cr;
@@ -235,29 +231,6 @@ gnc_budget_view_init(GncBudgetView *budget_view)
priv->rootAcct = root;
- for (i = 0; i < num_top_accounts; ++i)
- {
- Account* acc = gnc_account_nth_child(root, i);
- GNCAccountType type = xaccAccountGetType(acc);
-
- if (type == ACCT_TYPE_ASSET)
- {
- priv->assets = acc;
- }
- else if (type == ACCT_TYPE_LIABILITY)
- {
- priv->liabilities = acc;
- }
- else if (type == ACCT_TYPE_INCOME)
- {
- priv->income = acc;
- }
- else if (type == ACCT_TYPE_EXPENSE)
- {
- priv->expenses = acc;
- }
- }
-
LEAVE("");
}
commit 51dda770579efa666ea516a96de7a8f4639e1473
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Fri May 17 23:10:25 2019 -0500
Bug 577968 - Values are not stored by pressing <TAB> in budget page
Also fix duplicates: 760194
diff --git a/gnucash/gnome/gnc-budget-view.c b/gnucash/gnome/gnc-budget-view.c
index e6b06aea2..697701fce 100644
--- a/gnucash/gnome/gnc-budget-view.c
+++ b/gnucash/gnome/gnc-budget-view.c
@@ -118,10 +118,8 @@ static void gbv_create_widget(GncBudgetView *view);
static gboolean gbv_button_press_cb(
GtkWidget *widget, GdkEventButton *event, GncBudgetView *view);
#endif
-#if 0
-static gboolean gbv_key_press_cb(
- GtkWidget *treeview, GdkEventKey *event, gpointer userdata);
-#endif
+static gboolean gbv_key_press_cb(GtkWidget *treeview, GdkEventKey *event,
+ gpointer userdata);
static void gbv_row_activated_cb(
GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col,
GncBudgetView *view);
@@ -168,6 +166,9 @@ struct GncBudgetViewPrivate
Account* assets;
Account* liabilities;
Account* rootAcct;
+
+ GtkCellRenderer *temp_cr;
+ GtkCellEditable *temp_ce;
};
G_DEFINE_TYPE_WITH_PRIVATE(GncBudgetView, gnc_budget_view, GTK_TYPE_BOX)
@@ -427,9 +428,6 @@ gbv_create_widget(GncBudgetView *view)
G_CALLBACK(gbv_selection_changed_cb), view);
g_signal_connect(G_OBJECT(tree_view), "button-press-event",
G_CALLBACK(gbv_button_press_cb), view);
- g_signal_connect_after(G_OBJECT(tree_view), "key-press-event",
- G_CALLBACK(gbv_key_press_cb), NULL);
-
gbv_selection_changed_cb(NULL, view);
#endif
@@ -669,39 +667,103 @@ gbv_button_press_cb(GtkWidget *widget, GdkEventButton *event,
}
#endif
-#if 0
-/** \brief Key press action for gnc budget view.
+/** \brief Key press action for gnc budget view when in editing mode.
+ * Used for navigating with tab while editing.
+ * The handler is for the cell-editable, not for the treeview
*/
static gboolean
-gbv_key_press_cb(GtkWidget *treeview, GdkEventKey *event, gpointer userdata)
+gbv_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer userdata)
{
- GtkTreeView *tv = GTK_TREE_VIEW(treeview);
GtkTreeViewColumn *col;
- GtkTreePath *path = NULL;
-
- if (event->type != GDK_KEY_PRESS) return TRUE;
+ GtkTreePath *path = NULL;
+ GncBudgetViewPrivate *priv = GNC_BUDGET_VIEW_GET_PRIVATE(userdata);
+ GtkTreeView *tv = priv->tree_view;
+ gboolean shifted;
+ gint period_num, num_periods;
+ gpointer data;
+
+ if (event->type != GDK_KEY_PRESS || !priv->temp_cr)
+ return FALSE;
switch (event->keyval)
{
case GDK_KEY_Tab:
case GDK_KEY_ISO_Left_Tab:
case GDK_KEY_KP_Tab:
- case GDK_KEY_Return:
- case GDK_KEY_KP_Enter:
+ shifted = event->state & GDK_SHIFT_MASK;
gtk_tree_view_get_cursor(tv, &path, &col);
- if (!path) return TRUE;
- //finish_edit(col);
+ if (!path)
+ return TRUE;
+ data = g_object_get_data(G_OBJECT(col), "period_num");
+ period_num = GPOINTER_TO_UINT(data);
+ num_periods = gnc_budget_get_num_periods(priv->budget);
+
+ if (period_num >= num_periods)
+ period_num = num_periods - 1;
+
+ if (shifted)
+ period_num--;
+ else
+ period_num++;
+
+ if (period_num >= num_periods)
+ {
+ period_num = 0;
+ if (gtk_tree_view_row_expanded(tv, path))
+ {
+ gtk_tree_path_down(path);
+ }
+ else
+ {
+ gtk_tree_path_next(path);
+ while (!gnc_tree_view_path_is_valid(GNC_TREE_VIEW(tv), path) &&
+ gtk_tree_path_get_depth(path) > 1)
+ {
+ gtk_tree_path_up(path);
+ gtk_tree_path_next(path);
+ }
+ }
+ }
+ else if (period_num < 0)
+ {
+ period_num = num_periods - 1;
+ if (!gtk_tree_path_prev(path))
+ gtk_tree_path_up(path);
+ else
+ while (gtk_tree_view_row_expanded(tv, path))
+ {
+ gtk_tree_path_down(path);
+ do
+ {
+ gtk_tree_path_next(path);
+ } while (
+ gnc_tree_view_path_is_valid(GNC_TREE_VIEW(tv), path));
+ gtk_tree_path_prev(path);
+ }
+ }
+
+ col = g_list_nth_data(priv->period_col_list, period_num);
+
+ // finish editing
+ if (priv->temp_ce)
+ {
+ gtk_cell_editable_editing_done(priv->temp_ce);
+ gtk_cell_editable_remove_widget(priv->temp_ce);
+
+ while (gtk_events_pending())
+ gtk_main_iteration();
+ }
+
+ if (gnc_tree_view_path_is_valid(GNC_TREE_VIEW(tv), path))
+ gtk_tree_view_set_cursor(tv, path, col, TRUE);
+ gtk_tree_path_free(path);
break;
default:
- return TRUE;
+ return FALSE;
}
- gnc_tree_view_keynav(GNC_TREE_VIEW(tv), &col, path, event);
- if (path && gnc_tree_view_path_is_valid(GNC_TREE_VIEW(tv), path))
- gtk_tree_view_set_cursor(tv, path, col, TRUE);
return TRUE;
}
-#endif
/** \brief gnc budget view actions for resize of treeview.
*/
@@ -1270,6 +1332,30 @@ gbv_col_edited_cb(GtkCellRendererText* cell, gchar* path_string, gchar* new_text
gtk_widget_queue_draw(GTK_WIDGET(priv->totals_tree_view));
}
+/* The main Start Editing Call back for the budget columns, for key navigation
+ */
+static void
+gdv_editing_started_cb(GtkCellRenderer *cr, GtkCellEditable *editable,
+ const gchar *path_string, gpointer user_data)
+{
+ GncBudgetViewPrivate *priv = GNC_BUDGET_VIEW_GET_PRIVATE(user_data);
+
+ priv->temp_cr = cr;
+ priv->temp_ce = editable;
+
+ g_signal_connect(G_OBJECT(editable), "key-press-event",
+ G_CALLBACK(gbv_key_press_cb), user_data);
+}
+
+static void
+gdv_editing_canceled_cb(GtkCellRenderer *cr, gpointer user_data)
+{
+ GncBudgetViewPrivate *priv = GNC_BUDGET_VIEW_GET_PRIVATE(user_data);
+
+ priv->temp_cr = NULL;
+ priv->temp_ce = NULL;
+}
+
/** \brief refreshes the current budget view
The function will step through to only display the columns that are set
@@ -1343,7 +1429,10 @@ gnc_budget_view_refresh(GncBudgetView *view)
gbv_renderer_add_padding (renderer);
g_signal_connect(G_OBJECT(renderer), "edited", (GCallback)gbv_col_edited_cb, view);
-
+ g_signal_connect(G_OBJECT(renderer), "editing-started",
+ (GCallback)gdv_editing_started_cb, view);
+ g_signal_connect(G_OBJECT(renderer), "editing-canceled",
+ (GCallback)gdv_editing_canceled_cb, view);
col = gbv_create_totals_column(view, num_periods_visible);
if (col != NULL)
{
commit 91aceaa71ba4a162d246b60fcdc09b14b6545d62
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Fri May 17 23:04:35 2019 -0500
Bug 781345 - Equity disregarded by budget totals
diff --git a/gnucash/gnome/gnc-budget-view.c b/gnucash/gnome/gnc-budget-view.c
index 3c6013ccc..e6b06aea2 100644
--- a/gnucash/gnome/gnc-budget-view.c
+++ b/gnucash/gnome/gnc-budget-view.c
@@ -1125,6 +1125,7 @@ totals_col_source(GtkTreeViewColumn *col, GtkCellRenderer *cell,
continue;
break;
case ACCT_TYPE_LIABILITY:
+ case ACCT_TYPE_EQUITY:
if (row_type != TOTALS_TYPE_TRANSFERS &&
row_type != TOTALS_TYPE_TOTAL)
continue;
commit d16a236eceaaf7dd322996fbbdcafdc42da23789
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Fri May 17 23:03:14 2019 -0500
[Budget] Fix negative Numbers Not Colored Red
diff --git a/gnucash/gnome/gnc-budget-view.c b/gnucash/gnome/gnc-budget-view.c
index 92d603177..3c6013ccc 100644
--- a/gnucash/gnome/gnc-budget-view.c
+++ b/gnucash/gnome/gnc-budget-view.c
@@ -869,6 +869,19 @@ gbv_get_accumulated_budget_amount(GncBudget* budget, Account* account, guint per
return info.total;
}
+static gchar*
+get_negative_color (void)
+{
+ GdkRGBA color;
+ GtkWidget *label = gtk_label_new ("Color");
+ GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET(label));
+ gtk_style_context_add_class (context, "negative-numbers");
+ gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
+ gtk_widget_destroy(label);
+
+ return gdk_rgba_to_string(&color);
+}
+
/** \brief Calculates and displays budget amount for a period in a defined account.
Displays budget amount for a period for an account. If a budget
@@ -885,6 +898,7 @@ budget_col_source(Account *account, GtkTreeViewColumn *col,
guint period_num;
gnc_numeric numeric;
gchar amtbuff[100]; //FIXME: overkill, where's the #define?
+ gboolean red = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_NEGATIVE_IN_RED);
budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
bview = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(col), "budget_view"));
@@ -906,10 +920,18 @@ budget_col_source(Account *account, GtkTreeViewColumn *col,
numeric = gbv_get_accumulated_budget_amount(budget, account, period_num);
xaccSPrintAmount(amtbuff, numeric,
gnc_account_print_info(account, FALSE));
- if (gnc_is_dark_theme (&color))
- g_object_set(cell, "foreground", "darkgray", NULL);
+ if (gnc_is_dark_theme(&color))
+ g_object_set(cell, "foreground",
+ red && gnc_numeric_negative_p(numeric)
+ ? "darkred"
+ : "darkgray",
+ NULL);
else
- g_object_set(cell, "foreground", "dimgray", NULL);
+ g_object_set(cell, "foreground",
+ red && gnc_numeric_negative_p(numeric)
+ ? "PaleVioletRed"
+ : "dimgray",
+ NULL);
}
}
else
@@ -924,7 +946,11 @@ budget_col_source(Account *account, GtkTreeViewColumn *col,
{
xaccSPrintAmount(amtbuff, numeric,
gnc_account_print_info(account, FALSE));
- g_object_set(cell, "foreground", NULL, NULL);
+ g_object_set(cell, "foreground",
+ red && gnc_numeric_negative_p(numeric)
+ ? get_negative_color()
+ : NULL,
+ NULL);
}
}
return g_strdup(amtbuff);
@@ -994,11 +1020,14 @@ budget_total_col_source(Account *account, GtkTreeViewColumn *col,
GncBudget *budget;
gnc_numeric total;
gchar amtbuff[100]; //FIXME: overkill, where's the #define?
+ gboolean red = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_NEGATIVE_IN_RED);
budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
total = bgv_get_total_for_account(account, budget, NULL);
xaccSPrintAmount(amtbuff, total,
gnc_account_print_info(account, TRUE));
+ g_object_set(cell, "foreground",
+ red && gnc_numeric_negative_p(total) ? get_negative_color () : NULL, NULL);
return g_strdup(amtbuff);
}
@@ -1060,14 +1089,16 @@ totals_col_source(GtkTreeViewColumn *col, GtkCellRenderer *cell,
gchar amtbuff[100]; //FIXME: overkill, where's the #define?
gint i;
gint num_top_accounts;
- gboolean neg;
+ gboolean neg, red;
GNCPriceDB *pdb;
gnc_commodity *total_currency, *currency;
+
gnc_numeric total = gnc_numeric_zero();
view = GNC_BUDGET_VIEW(user_data);
priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+ red = gnc_prefs_get_bool(GNC_PREFS_GROUP_GENERAL, GNC_PREF_NEGATIVE_IN_RED);
gtk_tree_model_get(s_model, s_iter, 1, &row_type, -1);
budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
@@ -1141,7 +1172,7 @@ totals_col_source(GtkTreeViewColumn *col, GtkCellRenderer *cell,
gnc_commodity_print_info(total_currency,
period_num < 0 ? TRUE : FALSE));
g_object_set(cell, "foreground",
- gnc_numeric_negative_p(total) ? "red" : NULL, NULL);
+ red && gnc_numeric_negative_p(total) ? get_negative_color () : NULL, NULL);
g_object_set(G_OBJECT(cell), "text", amtbuff, "xalign", 1.0, NULL);
}
commit 0319144ba6d04e94d84bbae190952beccee93f63
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Mon May 13 22:57:51 2019 -0500
Bug 788157 - Open Budget Menu Item Doesn't Select Default Budget
diff --git a/gnucash/gnome/gnc-plugin-budget.c b/gnucash/gnome/gnc-plugin-budget.c
index c1afd95f7..358567303 100644
--- a/gnucash/gnome/gnc-plugin-budget.c
+++ b/gnucash/gnome/gnc-plugin-budget.c
@@ -312,6 +312,13 @@ gnc_budget_gui_select_budget(GtkWindow *parent, QofBook *book)
gtk_container_add(GTK_CONTAINER (gtk_dialog_get_content_area (dlg)), GTK_WIDGET(tv));
gtk_widget_show_all(GTK_WIDGET(dlg));
+ // Preselect the default budget
+ bgt = gnc_budget_get_default(book);
+ if (bgt && gnc_tree_model_budget_get_iter_for_budget(tm, &iter, bgt))
+ {
+ gtk_tree_view_set_cursor(tv, gtk_tree_model_get_path(tm, &iter), NULL,
+ FALSE);
+ }
bgt = NULL;
response = gtk_dialog_run(dlg);
switch (response)
commit 5bb54d073c2fc936ff5cc129110844b18096c599
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Mon May 13 22:56:04 2019 -0500
[budget] Fix error in qof_book property path
The "Default budget" property had an erroneus path
and was not returning any value.
diff --git a/libgnucash/engine/qofbook.cpp b/libgnucash/engine/qofbook.cpp
index 3991e96d6..8e7dc93cf 100644
--- a/libgnucash/engine/qofbook.cpp
+++ b/libgnucash/engine/qofbook.cpp
@@ -163,6 +163,8 @@ qof_book_init (QofBook *book)
static const std::string str_KVP_OPTION_PATH(KVP_OPTION_PATH);
static const std::string str_OPTION_SECTION_ACCOUNTS(OPTION_SECTION_ACCOUNTS);
+static const std::string str_OPTION_SECTION_BUDGETING(OPTION_SECTION_BUDGETING);
+static const std::string str_OPTION_NAME_DEFAULT_BUDGET(OPTION_NAME_DEFAULT_BUDGET);
static const std::string str_OPTION_NAME_TRADING_ACCOUNTS(OPTION_NAME_TRADING_ACCOUNTS);
static const std::string str_OPTION_NAME_AUTO_READONLY_DAYS(OPTION_NAME_AUTO_READONLY_DAYS);
static const std::string str_OPTION_NAME_NUM_FIELD_SOURCE(OPTION_NAME_NUM_FIELD_SOURCE);
@@ -206,7 +208,7 @@ qof_book_get_property (GObject* object,
break;
case PROP_OPT_DEFAULT_BUDGET:
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {str_KVP_OPTION_PATH,
- str_OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_BUDGET});
+ str_OPTION_SECTION_BUDGETING, str_OPTION_NAME_DEFAULT_BUDGET});
break;
case PROP_OPT_FY_END:
qof_instance_get_path_kvp (QOF_INSTANCE (book), value, {"fy_end"});
@@ -261,7 +263,7 @@ qof_book_set_property (GObject *object,
break;
case PROP_OPT_DEFAULT_BUDGET:
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {str_KVP_OPTION_PATH,
- str_OPTION_SECTION_ACCOUNTS, OPTION_NAME_DEFAULT_BUDGET});
+ str_OPTION_SECTION_BUDGETING, OPTION_NAME_DEFAULT_BUDGET});
break;
case PROP_OPT_FY_END:
qof_instance_set_path_kvp (QOF_INSTANCE (book), value, {"fy_end"});
commit df1cc5902b17916f8da7da9866e9371bfadcb8d0
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Thu May 9 08:07:34 2019 -0500
Bug 676810 - Wrong accounting in multi-currency budget report
Adds multicurrency support in budget page
Convert currencies before summing up to parent and totals.
diff --git a/gnucash/gnome/gnc-budget-view.c b/gnucash/gnome/gnc-budget-view.c
index 6fe4d9eda..92d603177 100644
--- a/gnucash/gnome/gnc-budget-view.c
+++ b/gnucash/gnome/gnc-budget-view.c
@@ -804,6 +804,8 @@ typedef struct
gnc_numeric total;
GncBudget* budget;
guint period_num;
+ GNCPriceDB *pdb;
+ gnc_commodity *total_currency;
} BudgetAccumulationInfo;
/** \brief Function to assist in the calculation of sub-account totals.
@@ -815,16 +817,29 @@ budget_accum_helper(Account* account, gpointer data)
{
BudgetAccumulationInfo* info = (BudgetAccumulationInfo*)data;
gnc_numeric numeric;
+ gnc_commodity *currency;
+
+ currency = gnc_account_get_currency_or_parent(account);
if (gnc_budget_is_account_period_value_set(info->budget, account, info->period_num))
{
- numeric = gnc_budget_get_account_period_value(info->budget, account, info->period_num);
- info->total = gnc_numeric_add(info->total, numeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ numeric = gnc_budget_get_account_period_value(info->budget, account,
+ info->period_num);
+ numeric = gnc_pricedb_convert_balance_nearest_price_t64(
+ info->pdb, numeric, currency, info->total_currency,
+ gnc_budget_get_period_start_date(info->budget, info->period_num));
+ info->total = gnc_numeric_add(info->total, numeric, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_LCD);
}
else if (gnc_account_n_children(account) != 0)
{
- numeric = gbv_get_accumulated_budget_amount(info->budget, account, info->period_num);
- info->total = gnc_numeric_add(info->total, numeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ numeric = gbv_get_accumulated_budget_amount(info->budget, account,
+ info->period_num);
+ numeric = gnc_pricedb_convert_balance_nearest_price_t64(
+ info->pdb, numeric, currency, info->total_currency,
+ gnc_budget_get_period_start_date(info->budget, info->period_num));
+ info->total = gnc_numeric_add(info->total, numeric, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_LCD);
}
}
@@ -840,6 +855,8 @@ gbv_get_accumulated_budget_amount(GncBudget* budget, Account* account, guint per
info.total = gnc_numeric_zero();
info.budget = budget;
info.period_num = period_num;
+ info.pdb = gnc_pricedb_get_db (gnc_account_get_book (account));
+ info.total_currency = gnc_account_get_currency_or_parent(account);
if (!gnc_budget_is_account_period_value_set(budget, account, period_num))
{
@@ -917,12 +934,20 @@ budget_col_source(Account *account, GtkTreeViewColumn *col,
totals column to the right.
*/
static gnc_numeric
-bgv_get_total_for_account(Account* account, GncBudget* budget)
+bgv_get_total_for_account(Account* account, GncBudget* budget, gnc_commodity *new_currency)
{
guint num_periods;
int period_num;
gnc_numeric numeric;
gnc_numeric total = gnc_numeric_zero();
+ GNCPriceDB *pdb;
+ gnc_commodity *currency;
+
+ if (new_currency)
+ {
+ pdb = gnc_pricedb_get_db(gnc_get_current_book());
+ currency = gnc_account_get_currency_or_parent(account);
+ }
num_periods = gnc_budget_get_num_periods(budget);
for (period_num = 0; period_num < num_periods; ++period_num)
@@ -932,6 +957,13 @@ bgv_get_total_for_account(Account* account, GncBudget* budget)
if (gnc_account_n_children(account) != 0)
{
numeric = gbv_get_accumulated_budget_amount(budget, account, period_num);
+
+ if (new_currency)
+ {
+ numeric = gnc_pricedb_convert_balance_nearest_price_t64(
+ pdb, numeric, currency, new_currency,
+ gnc_budget_get_period_start_date(budget, period_num));
+ }
total = gnc_numeric_add(total, numeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
}
}
@@ -940,6 +972,12 @@ bgv_get_total_for_account(Account* account, GncBudget* budget)
numeric = gnc_budget_get_account_period_value(budget, account, period_num);
if (!gnc_numeric_check(numeric))
{
+ if (new_currency)
+ {
+ numeric = gnc_pricedb_convert_balance_nearest_price_t64(
+ pdb, numeric, currency, new_currency,
+ gnc_budget_get_period_start_date(budget, period_num));
+ }
total = gnc_numeric_add(total, numeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
}
}
@@ -958,9 +996,9 @@ budget_total_col_source(Account *account, GtkTreeViewColumn *col,
gchar amtbuff[100]; //FIXME: overkill, where's the #define?
budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
- total = bgv_get_total_for_account(account, budget);
+ total = bgv_get_total_for_account(account, budget, NULL);
xaccSPrintAmount(amtbuff, total,
- gnc_account_print_info(account, FALSE));
+ gnc_account_print_info(account, TRUE));
return g_strdup(amtbuff);
}
@@ -1022,11 +1060,11 @@ totals_col_source(GtkTreeViewColumn *col, GtkCellRenderer *cell,
gchar amtbuff[100]; //FIXME: overkill, where's the #define?
gint i;
gint num_top_accounts;
+ gboolean neg;
+ GNCPriceDB *pdb;
+ gnc_commodity *total_currency, *currency;
- gnc_numeric totalincome = gnc_numeric_zero();
- gnc_numeric totalexpenses = gnc_numeric_zero();
- gnc_numeric totalassets = gnc_numeric_zero();
- gnc_numeric totalliabilities = gnc_numeric_zero();
+ gnc_numeric total = gnc_numeric_zero();
view = GNC_BUDGET_VIEW(user_data);
priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
@@ -1036,93 +1074,75 @@ totals_col_source(GtkTreeViewColumn *col, GtkCellRenderer *cell,
period_num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(col),
"period_num"));
+ pdb = gnc_pricedb_get_db (gnc_get_current_book());
+ total_currency = gnc_default_currency();
num_top_accounts = gnc_account_n_children(priv->rootAcct);
// step through each child account of the root, find the total income, expenses, liabilities, and assets.
for (i = 0; i < num_top_accounts; ++i)
{
- account = gnc_account_nth_child(priv->rootAcct, i);
+ account = gnc_account_nth_child(priv->rootAcct, i);
+ currency = gnc_account_get_currency_or_parent(account);
+ neg = FALSE;
+ switch (xaccAccountGetType(account))
+ {
+ case ACCT_TYPE_INCOME:
+ if (row_type != TOTALS_TYPE_INCOME &&
+ row_type != TOTALS_TYPE_TOTAL)
+ continue;
+ break;
+ case ACCT_TYPE_LIABILITY:
+ if (row_type != TOTALS_TYPE_TRANSFERS &&
+ row_type != TOTALS_TYPE_TOTAL)
+ continue;
+ break;
+ case ACCT_TYPE_EXPENSE:
+ if (row_type == TOTALS_TYPE_TOTAL)
+ neg = TRUE;
+ else if (row_type != TOTALS_TYPE_EXPENSES)
+ continue;
+ break;
+ case ACCT_TYPE_ASSET:
+ if (row_type != TOTALS_TYPE_TRANSFERS &&
+ row_type != TOTALS_TYPE_TOTAL)
+ continue;
+ neg = TRUE;
+ break;
+ default:
+ continue;
+ }
// find the total for this account
if (period_num < 0)
{
- value = bgv_get_total_for_account(account, budget);
+ value = bgv_get_total_for_account(account, budget, total_currency);
}
else
{
- value = gbv_get_accumulated_budget_amount(budget, account, period_num);
- }
-
- // test for what account type, and add 'value' to the appopriate total
+ value =
+ gbv_get_accumulated_budget_amount(budget, account, period_num);
- if (xaccAccountGetType(account) == ACCT_TYPE_INCOME)
- {
- totalincome = gnc_numeric_add(totalincome, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
- }
- else if (xaccAccountGetType(account) == ACCT_TYPE_EXPENSE)
- {
- totalexpenses = gnc_numeric_add(totalexpenses, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
- }
- else if (xaccAccountGetType(account) == ACCT_TYPE_ASSET)
- {
- totalassets = gnc_numeric_add(totalassets, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
- }
- else if (xaccAccountGetType(account) == ACCT_TYPE_LIABILITY)
- {
- totalliabilities = gnc_numeric_add(totalliabilities, value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ value = gnc_pricedb_convert_balance_nearest_price_t64(
+ pdb, value, currency, total_currency,
+ gnc_budget_get_period_start_date(budget, period_num));
}
+
+ if (neg)
+ total = gnc_numeric_sub(total, value, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_LCD);
else
- {
- // Do nothing because this account is not of interest
- }
+ total = gnc_numeric_add(total, value, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_LCD);
}
- // at this point we should have variables holding the values for assets, liabilities, expenses and incomes.
-
- // Set the text to display, depending on which of the totals rows we are currently looking at
+ xaccSPrintAmount(amtbuff, total,
+ gnc_commodity_print_info(total_currency,
+ period_num < 0 ? TRUE : FALSE));
+ g_object_set(cell, "foreground",
+ gnc_numeric_negative_p(total) ? "red" : NULL, NULL);
- if (row_type == TOTALS_TYPE_INCOME)
- {
- // FIXME: There must be a better way to get the GncAccountPrintInfo object than this. Would prefer to depreciate the tracking of top level accounts.
- xaccSPrintAmount(amtbuff, totalincome,
- gnc_account_print_info(priv->income, FALSE));
- g_object_set(cell, "foreground", NULL, NULL);
- }
- else if (row_type == TOTALS_TYPE_EXPENSES)
- {
- xaccSPrintAmount(amtbuff, totalexpenses,
- gnc_account_print_info(priv->expenses, FALSE));
- g_object_set(cell, "foreground", NULL, NULL);
- }
- else if (row_type == TOTALS_TYPE_TRANSFERS)
- {
- xaccSPrintAmount(amtbuff, gnc_numeric_sub(totalassets, totalliabilities, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD),
- gnc_account_print_info(priv->assets, FALSE));
- g_object_set(cell, "foreground", NULL, NULL);
- }
- else if (row_type == TOTALS_TYPE_TOTAL)
- {
- value = gnc_numeric_sub(totalincome, totalexpenses, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
- value = gnc_numeric_sub(value, totalassets, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
- value = gnc_numeric_add(value, totalliabilities, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
- xaccSPrintAmount(amtbuff, value,
- gnc_account_print_info(priv->assets, FALSE));
- if (gnc_numeric_negative_p(value))
- {
- g_object_set(cell, "foreground", "red", NULL);
- }
- else
- {
- g_object_set(cell, "foreground", NULL, NULL);
- }
- }
- else
- {
- // if it reaches here then the row type was not set correctly
- g_strlcpy(amtbuff, "error", sizeof(amtbuff));
- }
g_object_set(G_OBJECT(cell), "text", amtbuff, "xalign", 1.0, NULL);
}
commit 52895eabd1996f9cf3693a813889dcb29a3e0ccd
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Wed May 15 21:50:36 2019 -0500
Bug 679800 - Shortcut to allow population of all budgeting periods
Add functionality to change at once the budget for all
periods of selected accounts.
It can :
replace with a new value
unset the budget
add a value to current budget
multiply current budget with value
Solvese issue #679800 and a duplicates (#639404, #760634)
diff --git a/gnucash/gnome/gnc-plugin-page-budget.c b/gnucash/gnome/gnc-plugin-page-budget.c
index 8bb2283f9..d47ae121c 100644
--- a/gnucash/gnome/gnc-plugin-page-budget.c
+++ b/gnucash/gnome/gnc-plugin-page-budget.c
@@ -115,6 +115,8 @@ static void gnc_plugin_page_budget_cmd_view_options(
GtkAction *action, GncPluginPageBudget *page);
static void gnc_plugin_page_budget_cmd_estimate_budget(
GtkAction *action, GncPluginPageBudget *page);
+static void gnc_plugin_page_budget_cmd_allperiods_budget(
+ GtkAction *action, GncPluginPageBudget *page);
static GtkActionEntry gnc_plugin_page_budget_actions [] =
{
@@ -151,6 +153,12 @@ static GtkActionEntry gnc_plugin_page_budget_actions [] =
N_("Estimate a budget value for the selected accounts from past transactions"),
G_CALLBACK (gnc_plugin_page_budget_cmd_estimate_budget)
},
+ {
+ "AllPeriodsBudgetAction", "system-run", N_("All Periods"),
+ NULL,
+ N_("Edit budget for all periods for the selected accounts"),
+ G_CALLBACK (gnc_plugin_page_budget_cmd_allperiods_budget)
+ },
/* View menu */
{
@@ -179,9 +187,18 @@ static action_toolbar_labels toolbar_labels[] =
{ "DeleteBudgetAction", N_("Delete") },
{ "OptionsBudgetAction", N_("Options") },
{ "EstimateBudgetAction", N_("Estimate") },
+ { "AllPeriodsBudgetAction", N_("All Periods") },
{ NULL, NULL },
};
+typedef enum allperiods_action
+{
+ REPLACE,
+ ADD,
+ MULTIPLY,
+ UNSET
+} allperiods_action;
+
typedef struct GncPluginPageBudgetPrivate
{
GtkActionGroup *action_group;
@@ -205,6 +222,11 @@ typedef struct GncPluginPageBudgetPrivate
Recurrence r;
gint sigFigs;
gboolean useAvg;
+
+ /* For the allPeriods value dialog */
+ gnc_numeric allValue;
+ allperiods_action action;
+
} GncPluginPageBudgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageBudget, gnc_plugin_page_budget, GNC_TYPE_PLUGIN_PAGE)
@@ -864,11 +886,13 @@ estimate_budget_helper(GtkTreeModel *model, GtkTreePath *path,
if (priv->useAvg && num_periods)
{
num = xaccAccountGetBalanceChangeForPeriod(acct,
- recurrenceGetPeriodTime(&priv->r, 0, FALSE),
- recurrenceGetPeriodTime(&priv->r, num_periods - 1, TRUE), TRUE);
+ recurrenceGetPeriodTime(&priv->r, 0, FALSE),
+ recurrenceGetPeriodTime(&priv->r, num_periods - 1, TRUE), TRUE);
num = gnc_numeric_div(num,
- gnc_numeric_create(num_periods, 1), GNC_DENOM_AUTO,
- GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) | GNC_HOW_RND_ROUND_HALF_UP);
+ gnc_numeric_create(num_periods, 1),
+ GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) |
+ GNC_HOW_RND_ROUND_HALF_UP);
if (gnc_reverse_balance(acct))
num = gnc_numeric_neg(num);
@@ -979,6 +1003,133 @@ gnc_plugin_page_budget_cmd_estimate_budget(GtkAction *action,
g_object_unref(G_OBJECT(builder));
}
+static void
+allperiods_budget_helper(GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gpointer data)
+{
+ Account *acct;
+ guint num_periods, i;
+ gnc_numeric num;
+ GncPluginPageBudgetPrivate *priv;
+ GncPluginPageBudget *page = data;
+
+ g_return_if_fail(GNC_IS_PLUGIN_PAGE_BUDGET(page));
+ priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
+ acct = gnc_budget_view_get_account_from_path(priv->budget_view, path);
+ num_periods = gnc_budget_get_num_periods(priv->budget);
+ num = priv->allValue;
+
+ for (i = 0; i < num_periods; i++)
+ {
+ switch (priv->action)
+ {
+ case ADD:
+ num = gnc_budget_get_account_period_value(priv->budget, acct, i);
+ num = gnc_numeric_add(num, priv->allValue, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) |
+ GNC_HOW_RND_ROUND_HALF_UP);
+ gnc_budget_set_account_period_value(priv->budget, acct, i, num);
+ break;
+ case MULTIPLY:
+ num = gnc_budget_get_account_period_value(priv->budget, acct, i);
+ num = gnc_numeric_mul(num, priv->allValue, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) |
+ GNC_HOW_RND_ROUND_HALF_UP);
+ gnc_budget_set_account_period_value(priv->budget, acct, i, num);
+ break;
+ case UNSET:
+ gnc_budget_unset_account_period_value(priv->budget, acct, i);
+ break;
+ default:
+ gnc_budget_set_account_period_value(priv->budget, acct, i,
+ priv->allValue);
+ break;
+ }
+ }
+}
+
+/*******************************/
+/* All Periods Value Dialog */
+/*******************************/
+static void
+gnc_plugin_page_budget_cmd_allperiods_budget(GtkAction *action,
+ GncPluginPageBudget *page)
+{
+ GncPluginPageBudgetPrivate *priv;
+ GtkTreeSelection *sel;
+ GtkWidget *dialog, *gde, *val, *dtr, *add, *mult;
+ gint result;
+ GtkBuilder *builder;
+ const gchar *txt;
+
+ g_return_if_fail(GNC_IS_PLUGIN_PAGE_BUDGET(page));
+ priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
+ sel = gnc_budget_view_get_selection(priv->budget_view);
+
+ if (gtk_tree_selection_count_selected_rows(sel) <= 0)
+ {
+ dialog = gtk_message_dialog_new(
+ GTK_WINDOW(gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page))),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
+ GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "%s",
+ _("You must select at least one account to edit."));
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ return;
+ }
+
+ builder = gtk_builder_new();
+ gnc_builder_add_from_file(builder, "gnc-plugin-page-budget.glade",
+ "DigitsToRound_Adj");
+ gnc_builder_add_from_file(builder, "gnc-plugin-page-budget.glade",
+ "budget_allperiods_dialog");
+
+ dialog = GTK_WIDGET(
+ gtk_builder_get_object(builder, "budget_allperiods_dialog"));
+
+ gtk_window_set_transient_for(
+ GTK_WINDOW(dialog),
+ GTK_WINDOW(gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page))));
+
+ val = GTK_WIDGET(gtk_builder_get_object(builder, "Value"));
+ gtk_entry_set_text(GTK_ENTRY(val), "");
+
+ dtr = GTK_WIDGET(gtk_builder_get_object(builder, "DigitsToRound1"));
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(dtr), (gdouble)priv->sigFigs);
+
+ add = GTK_WIDGET(gtk_builder_get_object(builder, "RB_Add"));
+ mult = GTK_WIDGET(gtk_builder_get_object(builder, "RB_Multiply"));
+
+ gtk_widget_show_all(dialog);
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+ switch (result)
+ {
+ case GTK_RESPONSE_OK:
+
+ priv->sigFigs = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dtr));
+ priv->action = REPLACE;
+ txt = gtk_entry_get_text(GTK_ENTRY(val));
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(add)))
+ priv->action = ADD;
+ else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mult)))
+ priv->action = MULTIPLY;
+
+ if (priv->action == REPLACE &&
+ !gtk_entry_get_text_length(GTK_ENTRY(val)))
+ priv->action = UNSET;
+
+ if (xaccParseAmount(txt, TRUE, &priv->allValue, NULL) ||
+ priv->action == UNSET)
+ gtk_tree_selection_selected_foreach(sel, allperiods_budget_helper,
+ page);
+ break;
+ default:
+ break;
+ }
+ gtk_widget_destroy(dialog);
+ g_object_unref(G_OBJECT(builder));
+}
static void
gnc_plugin_page_budget_cmd_view_filter_by (GtkAction *action,
diff --git a/gnucash/gtkbuilder/gnc-plugin-page-budget.glade b/gnucash/gtkbuilder/gnc-plugin-page-budget.glade
index 088d8b504..7f102b3dd 100644
--- a/gnucash/gtkbuilder/gnc-plugin-page-budget.glade
+++ b/gnucash/gtkbuilder/gnc-plugin-page-budget.glade
@@ -9,6 +9,244 @@
<property name="step_increment">1</property>
<property name="page_increment">1</property>
</object>
+ <object class="GtkDialog" id="budget_allperiods_dialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Edit budget for all periods</property>
+ <property name="modal">True</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancelbutton3">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="okbutton3">
+ <property name="label" translatable="yes">_OK</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes">
+ Use a fixed value or apply transformation for all periods.
+ </property>
+ <property name="wrap">True</property>
+ <property name="width_chars">40</property>
+ <property name="max_width_chars">40</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="table1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Value:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="Value">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="input_purpose">number</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Action</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkRadioButton" id="RB_Replace">
+ <property name="label" translatable="yes">Replace</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">
+ Replace the budget for all periods with new 'value'. Use empty value to unset budget for the accounts.
+ </property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_Add">
+ <property name="label" translatable="yes">Add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">
+ Add 'value' to current budget for each period
+ </property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_Replace</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="RB_Multiply">
+ <property name="label" translatable="yes">Multiply</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">
+ Multiply current budget for each period by 'value'
+ </property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">RB_Replace</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="DigitsToRound1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip_text" translatable="yes">The number of leading digits to keep when rounding</property>
+ <property name="hexpand">True</property>
+ <property name="text" translatable="yes">1</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="adjustment">DigitsToRound_Adj</property>
+ <property name="climb_rate">1</property>
+ <property name="numeric">True</property>
+ <property name="value">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Significant Digits:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">cancelbutton3</action-widget>
+ <action-widget response="-5">okbutton3</action-widget>
+ </action-widgets>
+ </object>
<object class="GtkDialog" id="budget_estimate_dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
diff --git a/gnucash/ui/gnc-plugin-page-budget-ui.xml b/gnucash/ui/gnc-plugin-page-budget-ui.xml
index 87fcceb11..9f45fe45a 100644
--- a/gnucash/ui/gnc-plugin-page-budget-ui.xml
+++ b/gnucash/ui/gnc-plugin-page-budget-ui.xml
@@ -3,6 +3,7 @@
<menu name="Edit" action="EditAction">
<placeholder name="EditSelectedPlaceholder">
<menuitem name="Estimate" action="EstimateBudgetAction"/>
+ <menuitem name="AllPeriods" action="AllPeriodsBudgetAction"/>
<menuitem name="Delete" action="DeleteBudgetAction"/>
</placeholder>
<menuitem name="Options" action="OptionsBudgetAction"/>
@@ -22,6 +23,7 @@
<toolitem name="Options" action="OptionsBudgetAction"/>
<separator name="ToolbarSep4"/>
<toolitem name="Estimate" action="EstimateBudgetAction"/>
+ <toolitem name="AllPeriods" action="AllPeriodsBudgetAction"/>
<toolitem name="Delete" action="DeleteBudgetAction"/>
</placeholder>
</toolbar>
commit 93bf1a0f23913fb9c88e29470c782e3aac4de92b
Author: Adrian Panella <ianchi74 at outlook.com>
Date: Sat May 4 20:47:52 2019 -0500
Bug 646361 - Estimate budget option to have same amount in each budget period
If set, all periods get the same budget, from the average
of the reference period.
diff --git a/gnucash/gnome/gnc-plugin-page-budget.c b/gnucash/gnome/gnc-plugin-page-budget.c
index ccddfd306..8bb2283f9 100644
--- a/gnucash/gnome/gnc-plugin-page-budget.c
+++ b/gnucash/gnome/gnc-plugin-page-budget.c
@@ -204,6 +204,7 @@ typedef struct GncPluginPageBudgetPrivate
/* For the estimation dialog */
Recurrence r;
gint sigFigs;
+ gboolean useAvg;
} GncPluginPageBudgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageBudget, gnc_plugin_page_budget, GNC_TYPE_PLUGIN_PAGE)
@@ -309,6 +310,7 @@ gnc_plugin_page_budget_init (GncPluginPageBudget *plugin_page)
priv->fd.filter_override = g_hash_table_new (g_direct_hash, g_direct_equal);
priv->sigFigs = 1;
+ priv->useAvg = FALSE;
recurrenceSet(&priv->r, 1, PERIOD_MONTH, NULL, WEEKEND_ADJ_NONE);
LEAVE("page %p, priv %p, action group %p",
@@ -859,19 +861,38 @@ estimate_budget_helper(GtkTreeModel *model, GtkTreePath *path,
num_periods = gnc_budget_get_num_periods(priv->budget);
- for (i = 0; i < num_periods; i++)
+ if (priv->useAvg && num_periods)
{
- num = recurrenceGetAccountPeriodValue(&priv->r, acct, i);
- if (!gnc_numeric_check(num))
- {
- if (gnc_reverse_balance (acct))
- num = gnc_numeric_neg (num);
+ num = xaccAccountGetBalanceChangeForPeriod(acct,
+ recurrenceGetPeriodTime(&priv->r, 0, FALSE),
+ recurrenceGetPeriodTime(&priv->r, num_periods - 1, TRUE), TRUE);
+ num = gnc_numeric_div(num,
+ gnc_numeric_create(num_periods, 1), GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) | GNC_HOW_RND_ROUND_HALF_UP);
+ if (gnc_reverse_balance(acct))
+ num = gnc_numeric_neg(num);
- num = gnc_numeric_convert(num, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) | GNC_HOW_RND_ROUND_HALF_UP);
- gnc_budget_set_account_period_value(
- priv->budget, acct, i, num);
+ for (i = 0; i < num_periods; i++)
+ {
+ gnc_budget_set_account_period_value(priv->budget, acct, i, num);
+ }
+ }
+ else
+ {
+ for (i = 0; i < num_periods; i++)
+ {
+ num = recurrenceGetAccountPeriodValue(&priv->r, acct, i);
+ if (!gnc_numeric_check(num))
+ {
+ if (gnc_reverse_balance(acct))
+ num = gnc_numeric_neg(num);
+
+ num = gnc_numeric_convert(num, GNC_DENOM_AUTO,
+ GNC_HOW_DENOM_SIGFIGS(priv->sigFigs) |
+ GNC_HOW_RND_ROUND_HALF_UP);
+ gnc_budget_set_account_period_value(priv->budget, acct, i, num);
+ }
}
}
}
@@ -886,7 +907,7 @@ gnc_plugin_page_budget_cmd_estimate_budget(GtkAction *action,
{
GncPluginPageBudgetPrivate *priv;
GtkTreeSelection *sel;
- GtkWidget *dialog, *gde, *dtr, *hb;
+ GtkWidget *dialog, *gde, *dtr, *hb, *avg;
gint result;
GDate date;
const Recurrence *r;
@@ -930,6 +951,9 @@ gnc_plugin_page_budget_cmd_estimate_budget(GtkAction *action,
gtk_spin_button_set_value(GTK_SPIN_BUTTON(dtr),
(gdouble)priv->sigFigs);
+ avg = GTK_WIDGET(gtk_builder_get_object(builder, "UseAverage"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(avg), priv->useAvg);
+
gtk_widget_show_all (dialog);
result = gtk_dialog_run(GTK_DIALOG(dialog));
switch (result)
@@ -944,6 +968,8 @@ gnc_plugin_page_budget_cmd_estimate_budget(GtkAction *action,
priv->sigFigs =
gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(dtr));
+ priv->useAvg = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(avg));
+
gtk_tree_selection_selected_foreach(sel, estimate_budget_helper, page);
break;
default:
diff --git a/gnucash/gtkbuilder/gnc-plugin-page-budget.glade b/gnucash/gtkbuilder/gnc-plugin-page-budget.glade
index da3c11e75..088d8b504 100644
--- a/gnucash/gtkbuilder/gnc-plugin-page-budget.glade
+++ b/gnucash/gtkbuilder/gnc-plugin-page-budget.glade
@@ -151,6 +151,22 @@
<property name="top_attach">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="UseAverage">
+ <property name="label" translatable="yes">Use Average</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">
+ Use the average value over all actual periods for all projected periods
+ </property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
Summary of changes:
gnucash/gnome/gnc-budget-view.c | 380 +++++++++++++++---------
gnucash/gnome/gnc-plugin-budget.c | 7 +
gnucash/gnome/gnc-plugin-page-budget.c | 199 ++++++++++++-
gnucash/gtkbuilder/gnc-plugin-page-budget.glade | 254 ++++++++++++++++
gnucash/ui/gnc-plugin-page-budget-ui.xml | 2 +
libgnucash/engine/qofbook.cpp | 6 +-
6 files changed, 702 insertions(+), 146 deletions(-)
More information about the gnucash-changes
mailing list