r22796 - gnucash/trunk/src/gnome - Initial changes to budget view.
Phil Longstaff
plongstaff at code.gnucash.org
Wed Feb 20 20:10:22 EST 2013
Author: plongstaff
Date: 2013-02-20 20:10:21 -0500 (Wed, 20 Feb 2013)
New Revision: 22796
Trac: http://svn.gnucash.org/trac/changeset/22796
Added:
gnucash/trunk/src/gnome/gnc-budget-view.c
gnucash/trunk/src/gnome/gnc-budget-view.h
Modified:
gnucash/trunk/src/gnome/Makefile.am
gnucash/trunk/src/gnome/gnc-plugin-page-budget.c
Log:
Initial changes to budget view.
1) Splits gnc-budget-view.c/.h out from gnc-plugin-page-budget.c. gnc-plugin-page-budget.c now creates a GncBudgetView and provides the overall UI and integration for it.
2) GncBudgetView changes:
a) If an account has children but does not have a specific budget value for a period, the sum of the children's budget values will be displayed in gray
b) Totals column on the right provides total for a budget row (account)
c) At the bottom, totals lines with total income, total expenses, total transfers (assets+liabilities) and grand total (income - expenses - transfers)
Modified: gnucash/trunk/src/gnome/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/Makefile.am 2013-02-20 18:52:15 UTC (rev 22795)
+++ gnucash/trunk/src/gnome/Makefile.am 2013-02-21 01:10:21 UTC (rev 22796)
@@ -42,6 +42,7 @@
dialog-sx-from-trans.c \
dialog-sx-since-last-run.c \
dialog-tax-info.c \
+ gnc-budget-view.c \
gnc-plugin-account-tree.c \
gnc-plugin-basic-commands.c \
gnc-plugin-budget.c \
Added: gnucash/trunk/src/gnome/gnc-budget-view.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-budget-view.c (rev 0)
+++ gnucash/trunk/src/gnome/gnc-budget-view.c 2013-02-21 01:10:21 UTC (rev 22796)
@@ -0,0 +1,1086 @@
+/********************************************************************
+ * gnc-budget_view.c -- Budget display widget *
+ * *
+ * Copyright (C) 2013, Phil Longstaff <phil.longstaff at yahoo.ca> *
+ * *
+ * 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 *
+ *******************************************************************/
+
+/*
+ * TODO:
+ *
+ * *) I'd like to be able to update the budget estimates on a per cell
+ * basis, instead of a whole row (account) at one time. But, that
+ * would require some major coding.
+ *
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#ifdef __G_IR_SCANNER__
+#undef __G_IR_SCANNER__
+#endif
+#include <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+#include "gnc-date-edit.h"
+
+#include "gnc-budget-view.h"
+#include "gnc-budget.h"
+
+#include "dialog-options.h"
+#include "dialog-utils.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-gnome-utils.h"
+#include "gnc-gobject-utils.h"
+#include "gnc-icons.h"
+
+#include "gnc-session.h"
+#include "gnc-tree-view-account.h"
+#include "gnc-ui.h"
+#include "gnc-ui-util.h"
+#include "option-util.h"
+#include "gnc-main-window.h"
+#include "gnc-component-manager.h"
+
+#include "qof.h"
+
+#include "gnc-recurrence.h"
+#include "Recurrence.h"
+#include "gnc-tree-model-account-types.h"
+
+
+/* This static indicates the debugging module that this .o belongs to. */
+static QofLogModule log_module = GNC_MOD_BUDGET;
+
+#define PLUGIN_PAGE_BUDGET_CM_CLASS "budget-view"
+#define GCONF_SECTION "window/pages/budget"
+
+typedef struct GncBudgetViewPrivate GncBudgetViewPrivate;
+
+struct _GncBudgetView
+{
+ GtkVBox w;
+};
+
+struct _GncBudgetViewClass
+{
+ GtkVBoxClass w;
+};
+
+enum {
+ TOTALS_TYPE_INCOME,
+ TOTALS_TYPE_EXPENSES,
+ TOTALS_TYPE_TRANSFERS,
+ TOTALS_TYPE_TOTAL
+};
+
+/************************************************************
+ * Prototypes *
+ ************************************************************/
+/* Plugin Actions */
+static void gnc_budget_view_class_init(GncBudgetViewClass *klass);
+static void gnc_budget_view_init(GncBudgetView *budget_view);
+static void gnc_budget_view_finalize(GObject *object);
+
+static void gbv_create_widget(GncBudgetView *view);
+
+static gboolean gbv_button_press_cb(
+ GtkWidget *widget, GdkEventButton *event, GncBudgetView *view);
+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);
+#if 0
+static void gbv_selection_changed_cb(
+ GtkTreeSelection *selection, GncBudgetView *view);
+#endif
+static void gbv_treeview_resized_cb(GtkWidget* widget, GtkAllocation* allocation, GncBudgetView* view);
+static void gbv_column_resized_cb(GtkWidget* widget, GtkAllocation* allocation, GtkTreeViewColumn* col);
+static gnc_numeric gbv_get_accumulated_budget_amount(GncBudget* budget,
+ Account* account, guint period_num);
+
+struct GncBudgetViewPrivate
+{
+ GtkTreeView *tree_view;
+ GtkTreeView *totals_tree_view;
+
+ gchar* gconf_section;
+ GncBudget* budget;
+ GncGUID key;
+
+ GList *period_col_list;
+ GList *totals_col_list;
+ GtkTreeViewColumn* total_col;
+ AccountFilterDialog *fd;
+
+ Account* income;
+ Account* expenses;
+ Account* assets;
+ Account* liabilities;
+};
+
+#define GNC_BUDGET_VIEW_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((o), GNC_TYPE_BUDGET_VIEW, GncBudgetViewPrivate))
+
+G_DEFINE_TYPE(GncBudgetView, gnc_budget_view, GTK_TYPE_VBOX)
+
+GncBudgetView *
+gnc_budget_view_new(GncBudget *budget, AccountFilterDialog* fd, const gchar* gconf_section)
+{
+ GncBudgetView *budget_view;
+ GncBudgetViewPrivate *priv;
+ gchar* label;
+ const GList *item;
+
+ g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
+ ENTER(" ");
+
+ budget_view = g_object_new(GNC_TYPE_BUDGET_VIEW, NULL);
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(budget_view);
+ priv->budget = budget;
+ priv->key = *gnc_budget_get_guid(budget);
+ priv->fd = fd;
+ priv->gconf_section = g_strdup(gconf_section);
+ priv->total_col = NULL;
+ gbv_create_widget(budget_view);
+
+ LEAVE("new budget view %p", budget_view);
+ return budget_view;
+}
+
+static void
+gnc_budget_view_class_init(GncBudgetViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ gnc_budget_view_parent_class = g_type_class_peek_parent(klass);
+
+ object_class->finalize = gnc_budget_view_finalize;
+
+ g_signal_new("account-activated", GNC_TYPE_BUDGET_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 1, GNC_TYPE_ACCOUNT);
+
+ g_type_class_add_private(klass, sizeof(GncBudgetViewPrivate));
+}
+
+
+static void
+gnc_budget_view_init(GncBudgetView *budget_view)
+{
+ GncBudgetViewPrivate *priv;
+ Account* root;
+ gint num_top_accounts;
+ gint i;
+
+ ENTER("view %p", budget_view);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(budget_view);
+
+ /* Keep track of the top level asset, liability, income and expense accounts */
+ root = gnc_book_get_root_account(gnc_get_current_book());
+ num_top_accounts = gnc_account_n_children(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("");
+}
+
+
+static void
+gnc_budget_view_finalize(GObject *object)
+{
+ GncBudgetView *view;
+ GncBudgetViewPrivate *priv;
+
+ ENTER("object %p", object);
+ view = GNC_BUDGET_VIEW(object);
+ g_return_if_fail(GNC_IS_BUDGET_VIEW(view));
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ g_free(priv->gconf_section);
+
+ G_OBJECT_CLASS(gnc_budget_view_parent_class)->finalize(object);
+ LEAVE(" ");
+}
+
+
+GtkTreeSelection*
+gnc_budget_view_get_selection(GncBudgetView* view)
+{
+ GncBudgetViewPrivate *priv;
+
+ g_return_val_if_fail(GNC_IS_BUDGET_VIEW(view), NULL);
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+ return gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view));
+}
+
+Account*
+gnc_budget_view_get_account_from_path(GncBudgetView* view, GtkTreePath* path)
+{
+ GncBudgetViewPrivate *priv;
+
+ g_return_val_if_fail(GNC_IS_BUDGET_VIEW(view), NULL);
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+ return gnc_tree_view_account_get_account_from_path(GNC_TREE_VIEW_ACCOUNT(priv->tree_view), path);
+}
+
+GList*
+gnc_budget_view_get_selected_accounts(GncBudgetView* view)
+{
+ GncBudgetViewPrivate *priv;
+
+ g_return_val_if_fail(GNC_IS_BUDGET_VIEW(view), NULL);
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+ return gnc_tree_view_account_get_selected_accounts(GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
+}
+
+#if 0
+static void
+gnc_plugin_page_budget_refresh_cb(GHashTable *changes, gpointer user_data)
+{
+ GncBudgetView *view;
+ GncBudgetViewPrivate *priv;
+ const EventInfo* ei;
+
+ view = GNC_BUDGET_VIEW(user_data);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+ if (changes)
+ {
+ ei = gnc_gui_get_entity_events(changes, &priv->key);
+ if (ei)
+ {
+ if (ei->event_mask & QOF_EVENT_DESTROY)
+ {
+ gnc_plugin_page_budget_close_cb(user_data);
+ return;
+ }
+ if (ei->event_mask & QOF_EVENT_MODIFY)
+ {
+ DEBUG("refreshing budget view because budget was modified");
+ gnc_budget_view_refresh(view);
+ }
+ }
+ }
+}
+#endif
+
+
+/****************************
+ * GncPluginPage Functions *
+ ***************************/
+static void
+gbv_create_widget(GncBudgetView *view)
+{
+ GncBudgetViewPrivate* priv;
+ GtkTreeSelection *selection;
+ GtkTreeView *tree_view;
+ GtkWidget *scrolled_window;
+ const gchar *budget_guid_str;
+ GtkVBox* vbox;
+ GtkListStore* totals_tree_model;
+ GtkTreeView* totals_tree_view;
+ GtkTreeViewColumn* totals_title_col;
+ GtkTreeIter iter;
+ GtkWidget* h_separator;
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+ vbox = GTK_VBOX(view);
+
+ gtk_widget_show(GTK_WIDGET(vbox));
+ gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
+
+ scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_show(scrolled_window);
+ gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, /*expand*/TRUE, /*fill*/TRUE, 0);
+
+ tree_view = gnc_tree_view_account_new(FALSE);
+
+ g_object_set(G_OBJECT(tree_view), "gconf-section", priv->gconf_section, NULL);
+
+ gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));
+ priv->tree_view = tree_view;
+ selection = gtk_tree_view_get_selection(tree_view);
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+
+ g_signal_connect(G_OBJECT(tree_view), "row-activated",
+ G_CALLBACK(gbv_row_activated_cb), view);
+ g_signal_connect(G_OBJECT(tree_view), "size-allocate",
+ G_CALLBACK(gbv_treeview_resized_cb), view);
+
+#if 0
+ g_signal_connect(G_OBJECT(selection), "changed",
+ 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
+ gtk_tree_view_set_headers_visible(tree_view, TRUE);
+ gtk_widget_show(GTK_WIDGET(tree_view));
+ gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(tree_view));
+ priv->fd->tree_view = GNC_TREE_VIEW_ACCOUNT(priv->tree_view);
+ gnc_tree_view_account_set_filter(
+ GNC_TREE_VIEW_ACCOUNT(tree_view),
+ gnc_plugin_page_account_tree_filter_accounts,
+ priv->fd, NULL);
+
+ totals_tree_model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
+ gtk_list_store_append(totals_tree_model, &iter);
+ gtk_list_store_set(totals_tree_model, &iter, 0, "Income", 1, TOTALS_TYPE_INCOME, -1);
+ gtk_list_store_append(totals_tree_model, &iter);
+ gtk_list_store_set(totals_tree_model, &iter, 0, "Expenses", 1, TOTALS_TYPE_EXPENSES, -1);
+ gtk_list_store_append(totals_tree_model, &iter);
+ gtk_list_store_set(totals_tree_model, &iter, 0, "Transfers", 1, TOTALS_TYPE_TRANSFERS, -1);
+ gtk_list_store_append(totals_tree_model, &iter);
+ gtk_list_store_set(totals_tree_model, &iter, 0, "Total", 1, TOTALS_TYPE_TOTAL, -1);
+
+ totals_tree_view = GTK_TREE_VIEW(gtk_tree_view_new());
+ priv->totals_tree_view = totals_tree_view;
+
+ gtk_widget_show(GTK_WIDGET(totals_tree_view));
+ gtk_tree_selection_set_mode(gtk_tree_view_get_selection(totals_tree_view),
+ GTK_SELECTION_NONE);
+ gtk_tree_view_set_headers_visible(totals_tree_view, FALSE);
+ gtk_tree_view_set_model(totals_tree_view, GTK_TREE_MODEL(totals_tree_model));
+
+ totals_title_col = gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(), "text", 0, NULL);
+ gtk_tree_view_append_column(totals_tree_view, totals_title_col);
+
+ gtk_box_pack_end(GTK_BOX(vbox), GTK_WIDGET(totals_tree_view), /*expand*/FALSE, /*fill*/TRUE, 0);
+
+ h_separator = gtk_hseparator_new();
+ gtk_widget_show(h_separator);
+ gtk_box_pack_end(GTK_BOX(vbox), h_separator, /*expand*/FALSE, /*fill*/TRUE, 0);
+
+ gnc_budget_view_refresh(view);
+}
+
+
+#define BUDGET_GUID "Budget GncGUID"
+
+/***********************************************************************
+ * Save enough information about this view that it can *
+ * be recreated next time the user starts gnucash. *
+ * *
+ * @param view The view to save. *
+ * *
+ * @param key_file A pointer to the GKeyFile data structure where the *
+ * page information should be written. *
+ * *
+ * @param group_name The group name to use when saving data. *
+ **********************************************************************/
+void
+gnc_budget_view_save(GncBudgetView *view, GKeyFile *key_file, const gchar *group_name)
+{
+ GncBudgetViewPrivate *priv;
+ char guid_str[GUID_ENCODING_LENGTH+1];
+
+ g_return_if_fail(view != NULL);
+ g_return_if_fail(key_file != NULL);
+ g_return_if_fail(group_name != NULL);
+
+ ENTER("view %p, key_file %p, group_name %s", view, key_file, group_name);
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ //FIXME
+ gnc_tree_view_account_save(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
+ priv->fd, key_file, group_name);
+ LEAVE(" ");
+}
+
+
+/***********************************************************************
+ * Create a new plugin page based on the information saved
+ * during a previous instantiation of gnucash.
+ *
+ * @param view The budget view to be restored
+ *
+ * @param key_file A pointer to the GKeyFile data structure where the
+ * page information should be read.
+ *
+ * @param group_name The group name to use when restoring data.
+ *
+ * @return TRUE if successful, FALSE if unsuccessful
+ **********************************************************************/
+gboolean
+gnc_budget_view_restore(GncBudgetView* view, GKeyFile *key_file, const gchar *group_name)
+{
+ GncBudgetViewPrivate *priv;
+ GError *error = NULL;
+ char *guid_str;
+ GncGUID guid;
+ GncBudget *bgt;
+ QofBook *book;
+
+ g_return_val_if_fail(key_file, FALSE);
+ g_return_val_if_fail(group_name, FALSE);
+
+ ENTER("key_file %p, group_name %s", key_file, group_name);
+
+ guid_str = g_key_file_get_string(key_file, group_name, BUDGET_GUID,
+ &error);
+ if (error)
+ {
+ g_warning("error reading group %s key %s: %s",
+ group_name, BUDGET_GUID, error->message);
+ g_error_free(error);
+ error = NULL;
+ return FALSE;
+ }
+ if (!string_to_guid(guid_str, &guid))
+ {
+ return FALSE;
+ }
+
+ book = qof_session_get_book(gnc_get_current_session());
+ bgt = gnc_budget_lookup(&guid, book);
+ if (!bgt)
+ {
+ return FALSE;
+ }
+
+ /* Create the new view */
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ //FIXME
+ gnc_tree_view_account_restore(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
+ priv->fd, key_file, group_name);
+ LEAVE(" ");
+
+ return TRUE;
+}
+
+
+#if 0
+/***********************************************************************
+ * This button press handler calls the common button press handler
+ * for all pages. The GtkTreeView eats all button presses and
+ * doesn't pass them up the widget tree, even when it doesn't do
+ * anything with them. The only way to get access to the button
+ * presses in an account tree page is here on the tree view widget.
+ * Button presses on all other pages are caught by the signal
+ * registered in gnc-main-window.c.
+ **********************************************************************/
+static gboolean
+gbv_button_press_cb(GtkWidget *widget, GdkEventButton *event,
+ GncBudgetView *view)
+{
+ gboolean result;
+
+ g_return_val_if_fail(view != NULL, FALSE);
+
+ ENTER("widget %p, event %p, page %p", widget, event, page);
+ result = gnc_main_window_button_press_cb(widget, event, page);
+ LEAVE(" ");
+ return result;
+}
+#endif
+
+static gboolean
+gbv_key_press_cb(GtkWidget *treeview, GdkEventKey *event, gpointer userdata)
+{
+ GtkTreeView *tv = GTK_TREE_VIEW(treeview);
+ GtkTreeViewColumn *col;
+ GtkTreePath *path = NULL;
+
+ if (event->type != GDK_KEY_PRESS) return TRUE;
+
+ switch (event->keyval)
+ {
+ case GDK_Tab:
+ case GDK_ISO_Left_Tab:
+ case GDK_KP_Tab:
+ case GDK_Return:
+ case GDK_KP_Enter:
+ gtk_tree_view_get_cursor(tv, &path, &col);
+ if (!path) return TRUE;
+ //finish_edit(col);
+ break;
+ default:
+ return TRUE;
+ }
+ 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;
+}
+
+static void
+gbv_column_resized_cb(GtkWidget* widget, GtkAllocation* allocation, GtkTreeViewColumn* col)
+{
+ guint period_num;
+
+ period_num = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(col),
+ "period_num"));
+ printf("Col %d: x=%d y=%d w=%d h=%d\n", period_num, allocation->x, allocation->y, allocation->width, allocation->height);
+}
+
+static void
+gbv_treeview_resized_cb(GtkWidget* widget, GtkAllocation* allocation, GncBudgetView* view)
+{
+ guint ncols;
+ GncBudgetViewPrivate* priv;
+ guint i;
+
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ /* Num cols is number of budget periods + 1 for name. Ignore totals column. We
+ * don't want to set the width of the last column so that the user can shrink the
+ * display. */
+ ncols = gnc_budget_get_num_periods(priv->budget) + 1;
+ for (i = 0; i < ncols; ++i)
+ {
+ gint col_width;
+ GtkTreeViewColumn* tree_view_col;
+ GtkTreeViewColumn* totals_view_col;
+ gint fixed_width;
+ gint min_width;
+ gint max_width;
+
+ /* Get the width. */
+ tree_view_col = gtk_tree_view_get_column(priv->tree_view, i);
+ col_width = gtk_tree_view_column_get_width(tree_view_col);
+ fixed_width = gtk_tree_view_column_get_fixed_width(tree_view_col);
+ min_width = gtk_tree_view_column_get_min_width(tree_view_col);
+ max_width = gtk_tree_view_column_get_max_width(tree_view_col);
+
+ /* Set total view col's width the same. */
+ if (col_width != 0)
+ {
+ totals_view_col = gtk_tree_view_get_column(priv->totals_tree_view, i);
+ gtk_tree_view_column_set_min_width(totals_view_col, col_width);
+ gtk_tree_view_column_set_max_width(totals_view_col, col_width);
+ }
+ }
+}
+
+static void
+gbv_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path,
+ GtkTreeViewColumn *col, GncBudgetView *view)
+{
+ GtkWidget *window;
+ GncPluginPage *new_page;
+ Account *account;
+
+ g_return_if_fail(GNC_IS_BUDGET_VIEW(view));
+ account = gnc_tree_view_account_get_account_from_path(
+ GNC_TREE_VIEW_ACCOUNT(treeview), path);
+ if (account == NULL)
+ {
+ return;
+ }
+
+ g_signal_emit_by_name(view, "account-activated", account);
+}
+
+
+#if 0
+static void
+gbv_selection_changed_cb(GtkTreeSelection *selection, GncBudgetView *view)
+{
+ GtkTreeView *tree_view;
+ GList *acct_list;
+ gboolean sensitive;
+
+ if (!selection)
+ {
+ sensitive = FALSE;
+ }
+ else
+ {
+ g_return_if_fail(GTK_IS_TREE_SELECTION(selection));
+ tree_view = gtk_tree_selection_get_tree_view (selection);
+ acct_list = gnc_tree_view_account_get_selected_accounts(
+ GNC_TREE_VIEW_ACCOUNT(tree_view));
+
+ /* Check here for placeholder accounts, etc. */
+ sensitive = (g_list_length(acct_list) > 0);
+ g_list_free(acct_list);
+ }
+}
+#endif
+
+typedef struct
+{
+ gnc_numeric total;
+ GncBudget* budget;
+ guint period_num;
+} BudgetAccumulationInfo;
+
+static void
+budget_accum_helper(Account* account, gpointer data)
+{
+ BudgetAccumulationInfo* info = (BudgetAccumulationInfo*)data;
+ gnc_numeric numeric;
+
+ 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);
+ }
+ 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);
+ }
+}
+
+static gnc_numeric
+gbv_get_accumulated_budget_amount(GncBudget* budget, Account* account, guint period_num)
+{
+ BudgetAccumulationInfo info;
+
+ info.total = gnc_numeric_zero();
+ info.budget = budget;
+ info.period_num = period_num;
+ gnc_account_foreach_child(account, budget_accum_helper, &info);
+
+ return info.total;
+}
+
+/* Displays budget amount for a period for an account. If a budget
+ amount is set, it is displayed in black. If no budget amount is
+ set and the account has children, the total of the children's
+ budget amounts (if any) is displayed in dark grey.
+*/
+static gchar *
+budget_col_source(Account *account, GtkTreeViewColumn *col,
+ GtkCellRenderer *cell)
+{
+ GncBudget *budget;
+ guint period_num;
+ gnc_numeric numeric;
+ gchar amtbuff[100]; //FIXME: overkill, where's the #define?
+
+ budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
+ period_num = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(col),
+ "period_num"));
+
+ if (!gnc_budget_is_account_period_value_set(budget, account, period_num))
+ {
+ if (gnc_account_n_children(account) == 0)
+ {
+ amtbuff[0] = '\0';
+ }
+ else
+ {
+ numeric = gbv_get_accumulated_budget_amount(budget, account, period_num);
+ xaccSPrintAmount(amtbuff, numeric,
+ gnc_account_print_info(account, FALSE));
+ g_object_set(cell, "foreground", "dark gray", NULL);
+ }
+ }
+ else
+ {
+ numeric = gnc_budget_get_account_period_value(budget, account,
+ period_num);
+ if (gnc_numeric_check(numeric))
+ {
+ strcpy(amtbuff, "error");
+ }
+ else
+ {
+ xaccSPrintAmount(amtbuff, numeric,
+ gnc_account_print_info(account, FALSE));
+ g_object_set(cell, "foreground", "black", NULL);
+ }
+ }
+ return g_strdup(amtbuff);
+}
+
+static gnc_numeric
+bgv_get_total_for_account(Account* account, GncBudget* budget)
+{
+ guint num_periods;
+ int period_num;
+ gnc_numeric numeric;
+ gnc_numeric total = gnc_numeric_zero();
+
+ num_periods = gnc_budget_get_num_periods(budget);
+ for (period_num = 0; period_num < num_periods; ++period_num)
+ {
+ if (!gnc_budget_is_account_period_value_set(budget, account, period_num))
+ {
+ if (gnc_account_n_children(account) != 0)
+ {
+ numeric = gbv_get_accumulated_budget_amount(budget, account, period_num);
+ total = gnc_numeric_add(total, numeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ }
+ }
+ else
+ {
+ numeric = gnc_budget_get_account_period_value(budget, account, period_num);
+ if (!gnc_numeric_check(numeric))
+ {
+ total = gnc_numeric_add(total, numeric, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ }
+ }
+ }
+
+ return total;
+}
+
+static gchar *
+budget_total_col_source(Account *account, GtkTreeViewColumn *col,
+ GtkCellRenderer *cell)
+{
+ GncBudget *budget;
+ gnc_numeric total = gnc_numeric_zero();
+ 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);
+ xaccSPrintAmount(amtbuff, total,
+ gnc_account_print_info(account, FALSE));
+ return g_strdup(amtbuff);
+}
+
+static void
+budget_col_edited(Account *account, GtkTreeViewColumn *col,
+ const gchar *new_text)
+{
+ GncBudget *budget;
+ guint period_num;
+ gnc_numeric numeric = gnc_numeric_error(GNC_ERROR_ARG);
+
+ if (!xaccParseAmount(new_text, TRUE, &numeric, NULL) &&
+ !(new_text && *new_text == '\0'))
+ return;
+
+ period_num = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(col),
+ "period_num"));
+
+ budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
+
+ if (new_text && *new_text == '\0')
+ gnc_budget_unset_account_period_value(budget, account, period_num);
+ else
+ gnc_budget_set_account_period_value(budget, account, period_num,
+ numeric);
+}
+
+
+static void
+totals_col_source(GtkTreeViewColumn *col, GtkCellRenderer *cell,
+ GtkTreeModel *s_model, GtkTreeIter *s_iter,
+ gpointer user_data)
+{
+ GncBudgetView* view;
+ GncBudgetViewPrivate* priv;
+ gint row_type;
+ GncBudget *budget;
+ gint period_num;
+ gnc_numeric value;
+ gchar amtbuff[100]; //FIXME: overkill, where's the #define?
+ gint width;
+
+ view = GNC_BUDGET_VIEW(user_data);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ gtk_tree_model_get(s_model, s_iter, 1, &row_type, -1);
+ budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
+ period_num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(col),
+ "period_num"));
+
+ if (row_type == TOTALS_TYPE_INCOME)
+ {
+ if (period_num >= 0)
+ {
+ value = gbv_get_accumulated_budget_amount(budget, priv->income, period_num);
+ }
+ else
+ {
+ value = bgv_get_total_for_account(priv->income, budget);
+ }
+ xaccSPrintAmount(amtbuff, value,
+ gnc_account_print_info(priv->income, FALSE));
+ g_object_set(cell, "foreground", "black", NULL);
+ }
+ else if (row_type == TOTALS_TYPE_EXPENSES)
+ {
+ if (period_num >= 0)
+ {
+ value = gbv_get_accumulated_budget_amount(budget, priv->expenses, period_num);
+ }
+ else
+ {
+ value = bgv_get_total_for_account(priv->expenses, budget);
+ }
+ xaccSPrintAmount(amtbuff, value,
+ gnc_account_print_info(priv->expenses, FALSE));
+ g_object_set(cell, "foreground", "black", NULL);
+ }
+ else if (row_type == TOTALS_TYPE_TRANSFERS)
+ {
+ gnc_numeric assets;
+ gnc_numeric liabilities;
+
+ if (period_num >= 0)
+ {
+ assets = gbv_get_accumulated_budget_amount(budget, priv->assets, period_num);
+ liabilities = gbv_get_accumulated_budget_amount(budget, priv->liabilities, period_num);
+ }
+ else
+ {
+ assets = bgv_get_total_for_account(priv->assets, budget);
+ liabilities = bgv_get_total_for_account(priv->liabilities, budget);
+ }
+ value = gnc_numeric_sub(assets, liabilities, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ xaccSPrintAmount(amtbuff, value,
+ gnc_account_print_info(priv->assets, FALSE));
+ g_object_set(cell, "foreground", "black", NULL);
+ }
+ else if (row_type == TOTALS_TYPE_TOTAL)
+ {
+ gnc_numeric income;
+ gnc_numeric expenses;
+ gnc_numeric assets;
+ gnc_numeric liabilities;
+
+ if (period_num >= 0)
+ {
+ income = gbv_get_accumulated_budget_amount(budget, priv->income, period_num);
+ expenses = gbv_get_accumulated_budget_amount(budget, priv->expenses, period_num);
+ assets = gbv_get_accumulated_budget_amount(budget, priv->assets, period_num);
+ liabilities = gbv_get_accumulated_budget_amount(budget, priv->liabilities, period_num);
+ }
+ else
+ {
+ income = bgv_get_total_for_account(priv->income, budget);
+ expenses = bgv_get_total_for_account(priv->expenses, budget);
+ assets = bgv_get_total_for_account(priv->assets, budget);
+ liabilities = bgv_get_total_for_account(priv->liabilities, budget);
+ }
+ value = gnc_numeric_sub(income, expenses, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ value = gnc_numeric_sub(value, assets, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD);
+ value = gnc_numeric_add(value, liabilities, 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", "black", NULL);
+ }
+ }
+ else
+ {
+ g_strlcpy(amtbuff, "error", sizeof(amtbuff));
+ }
+
+ g_object_set(G_OBJECT(cell), "text", amtbuff, "xalign", 1.0, NULL);
+}
+
+static void
+gbv_refresh_col_titles(GncBudgetView *view)
+{
+ GncBudgetViewPrivate *priv;
+ const Recurrence *r;
+ GDate date, nextdate;
+ GtkTreeViewColumn *col;
+ guint titlelen;
+ gint num_periods_visible;
+ gchar title[MAX_DATE_LENGTH];
+ GList *col_list;
+ gint i;
+
+ g_return_if_fail(view != NULL);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ col_list = priv->period_col_list;
+ num_periods_visible = g_list_length(col_list);
+
+ /* Show the dates in column titles */
+ r = gnc_budget_get_recurrence(priv->budget);
+ date = r->start;
+ for (i = 0; i < num_periods_visible; i++)
+ {
+ col = GTK_TREE_VIEW_COLUMN(g_list_nth_data(col_list, i));
+ titlelen = qof_print_gdate(title, MAX_DATE_LENGTH, &date);
+ if (titlelen > 0)
+ {
+ gtk_tree_view_column_set_title(col, title);
+ }
+ recurrenceNextInstance(r, &date, &nextdate);
+ date = nextdate;
+ }
+}
+
+
+static GtkTreeViewColumn*
+gbv_create_totals_column(GncBudgetView* view, gint period_num)
+{
+ GncBudgetViewPrivate *priv;
+ GtkTreeViewColumn *col;
+ GtkCellRenderer* renderer;
+
+ g_return_val_if_fail(view != NULL, NULL);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ renderer = gtk_cell_renderer_text_new();
+ col = gtk_tree_view_column_new_with_attributes("", renderer, NULL);
+
+ gtk_tree_view_column_set_cell_data_func(col, renderer, totals_col_source, view, NULL);
+ g_object_set_data(G_OBJECT(col), "budget", priv->budget);
+ g_object_set_data(G_OBJECT(col), "period_num", GUINT_TO_POINTER(period_num));
+ if (period_num >= 0)
+ {
+ gint col_width = 86;
+ gtk_tree_view_column_set_min_width(col, col_width);
+ gtk_tree_view_column_set_max_width(col, col_width);
+ }
+
+ return col;
+}
+
+
+static void
+gbv_col_edited_cb(GtkCellRendererText* cell, gchar* path_string, gchar* new_text, gpointer user_data)
+{
+ GncBudgetView *view;
+ GncBudgetViewPrivate *priv;
+ const EventInfo* ei;
+
+ view = GNC_BUDGET_VIEW(user_data);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ gtk_widget_queue_draw(GTK_WIDGET(priv->totals_tree_view));
+}
+
+void
+gnc_budget_view_refresh(GncBudgetView *view)
+{
+ GncBudgetViewPrivate *priv;
+ gint num_periods;
+ gint num_periods_visible;
+ GtkTreeViewColumn *col;
+ GList *col_list;
+ GList *totals_col_list;
+
+ g_return_if_fail(view != NULL);
+ priv = GNC_BUDGET_VIEW_GET_PRIVATE(view);
+
+ num_periods = gnc_budget_get_num_periods(priv->budget);
+ col_list = priv->period_col_list;
+ totals_col_list = priv->totals_col_list;
+ num_periods_visible = g_list_length(col_list);
+
+ /* Hide any unneeded extra columns */
+ while (num_periods_visible > num_periods)
+ {
+ col = GTK_TREE_VIEW_COLUMN((g_list_last(col_list))->data);
+ gtk_tree_view_remove_column(GTK_TREE_VIEW(priv->tree_view), col);
+ col_list = g_list_delete_link(col_list, g_list_last(col_list));
+ num_periods_visible = g_list_length(col_list);
+
+ col = GTK_TREE_VIEW_COLUMN((g_list_last(totals_col_list))->data);
+ gtk_tree_view_remove_column(GTK_TREE_VIEW(priv->totals_tree_view), col);
+ totals_col_list = g_list_delete_link(totals_col_list, g_list_last(totals_col_list));
+ }
+
+ gnc_tree_view_configure_columns(GNC_TREE_VIEW(priv->tree_view));
+
+ /* Create any needed columns */
+ while (num_periods_visible < num_periods)
+ {
+ GList* renderer_list;
+ GList* renderer_node;
+
+ col = gnc_tree_view_account_add_custom_column(
+ GNC_TREE_VIEW_ACCOUNT(priv->tree_view), "",
+ budget_col_source, budget_col_edited);
+ g_object_set_data(G_OBJECT(col), "budget", priv->budget);
+ g_object_set_data(G_OBJECT(col), "period_num",
+ GUINT_TO_POINTER(num_periods_visible));
+ g_signal_connect(G_OBJECT(col), "size-allocate",
+ G_CALLBACK(gbv_column_resized_cb), col);
+ col_list = g_list_append(col_list, col);
+
+ renderer_list = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(col));
+ for (renderer_node = renderer_list; renderer_node != NULL; renderer_node = g_list_next(renderer_node))
+ {
+ GtkCellRenderer* renderer = GTK_CELL_RENDERER(renderer_node->data);
+ g_signal_connect(G_OBJECT(renderer), "edited", (GCallback)gbv_col_edited_cb, view);
+ }
+ g_list_free(renderer_list);
+
+ col = gbv_create_totals_column(view, num_periods_visible);
+ if (col != NULL)
+ {
+ gtk_tree_view_append_column(priv->totals_tree_view, col);
+ totals_col_list = g_list_append(totals_col_list, col);
+ }
+
+ num_periods_visible = g_list_length(col_list);
+ }
+ priv->period_col_list = col_list;
+ priv->totals_col_list = totals_col_list;
+
+ if (priv->total_col == NULL)
+ {
+ priv->total_col = gnc_tree_view_account_add_custom_column(
+ GNC_TREE_VIEW_ACCOUNT(priv->tree_view), "Total",
+ budget_total_col_source, NULL);
+ g_object_set_data(G_OBJECT(priv->total_col), "budget", priv->budget);
+
+ col = gbv_create_totals_column(view, -1);
+ if (col != NULL)
+ {
+ gtk_tree_view_append_column(priv->totals_tree_view, col);
+ }
+ }
+
+ gbv_refresh_col_titles(view);
+}
+
Added: gnucash/trunk/src/gnome/gnc-budget-view.h
===================================================================
--- gnucash/trunk/src/gnome/gnc-budget-view.h (rev 0)
+++ gnucash/trunk/src/gnome/gnc-budget-view.h 2013-02-21 01:10:21 UTC (rev 22796)
@@ -0,0 +1,75 @@
+/* Copyright (C) 2013 Phil Longstaff <phil.longstaff at yahoo.ca>
+ *
+ * gnc-budget-view.h --
+ *
+ * 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
+ */
+
+/** @addtogroup budget Budgets
+ @{ */
+/** @file gnc-budget-view.h
+ @brief
+*/
+
+#ifndef __GNC_BUDGET_VIEW_H
+#define __GNC_BUDGET_VIEW_H
+
+#include <gtk/gtk.h>
+
+#if 0
+#include "gnc-plugin-page.h"
+#endif
+#include "gnc-budget.h"
+#include "gnc-tree-view-account.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_BUDGET_VIEW (gnc_budget_view_get_type ())
+#define GNC_BUDGET_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_BUDGET_VIEW, GncBudgetView))
+#define GNC_BUDGET_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_BUDGET_VIEW, GncBudgetViewClass))
+#define GNC_IS_BUDGET_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_BUDGET_VIEW))
+#define GNC_IS_BUDGET_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_BUDGET_VIEW))
+#define GNC_BUDGET_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_BUDGET_VIEW, GncBudgetViewClass))
+
+#define GNC_BUDGET_VIEW_NAME "GncBudgetView"
+
+/* typedefs & structures */
+typedef struct _GncBudgetView GncBudgetView;
+typedef struct _GncBudgetViewClass GncBudgetViewClass;
+
+/* function prototypes */
+GType gnc_budget_view_get_type (void);
+
+/** Create a new "budget" display widget.
+ *
+ * @return The newly created widget
+ */
+GncBudgetView *gnc_budget_view_new(GncBudget *budget, AccountFilterDialog* fd,
+ const gchar* gconf_section);
+void gnc_budget_view_save(GncBudgetView* view, GKeyFile *key_file, const gchar* group_name);
+void gnc_budget_view_refresh(GncBudgetView* view);
+gboolean gnc_budget_view_restore(GncBudgetView* view, GKeyFile *key_file, const gchar* group_name);
+GtkTreeSelection* gnc_budget_view_get_selection(GncBudgetView* view);
+Account* gnc_budget_view_get_account_from_path(GncBudgetView* view, GtkTreePath* path);
+GList* gnc_budget_view_get_selected_accounts(GncBudgetView* view);
+
+G_END_DECLS
+
+#endif /* __GNC_BUDGET_VIEW_H */
+/** @} */
Modified: gnucash/trunk/src/gnome/gnc-plugin-page-budget.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-budget.c 2013-02-20 18:52:15 UTC (rev 22795)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-budget.c 2013-02-21 01:10:21 UTC (rev 22796)
@@ -53,6 +53,7 @@
#include "gnc-icons.h"
#include "gnc-plugin-page-budget.h"
#include "gnc-plugin-budget.h"
+#include "gnc-budget-view.h"
#include "gnc-session.h"
#include "gnc-tree-view-account.h"
@@ -95,15 +96,13 @@
static gboolean gppb_button_press_cb(
GtkWidget *widget, GdkEventButton *event, GncPluginPage *page);
-static gboolean gppb_key_press_cb(
- GtkWidget *treeview, GdkEventKey *event, gpointer userdata);
-static void gppb_double_click_cb(
- GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col,
- GncPluginPageBudget *page);
+static void gppb_account_activated_cb(GncBudgetView* view, Account* account,
+ GncPluginPageBudget *page);
+#if 0
static void gppb_selection_changed_cb(
GtkTreeSelection *selection, GncPluginPageBudget *page);
+#endif
-static void gnc_plugin_page_budget_view_refresh (GncPluginPageBudget *page);
static void gnc_plugin_page_budget_cmd_view_filter_by (
GtkAction *action, GncPluginPageBudget *page);
@@ -189,9 +188,10 @@
guint merge_id;
GtkUIManager *ui_merge;
- GtkWidget *widget; /* ends up being a vbox */
+ GncBudgetView* budget_view;
GtkTreeView *tree_view;
+ gchar* gconf_section;
gint component_id;
GncBudget* budget;
@@ -200,7 +200,6 @@
/* To distinguish between closing a tab and deleting a budget */
gboolean delete_budget;
- GList *period_col_list;
AccountFilterDialog fd;
/* For the estimation dialog */
@@ -272,10 +271,11 @@
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(plugin_page);
priv->budget = budget;
priv->delete_budget = FALSE;
+ priv->key = *gnc_budget_get_guid(budget);
+ priv->gconf_section = g_strjoin("/", GCONF_SECTION, guid_to_string(&priv->key), NULL);
label = g_strdup_printf("%s: %s", _("Budget"), gnc_budget_get_name(budget));
g_object_set(G_OBJECT(plugin_page), "page-name", label, NULL);
g_free(label);
- priv->key = *gnc_budget_get_guid(budget);
LEAVE("new budget page %p", plugin_page);
return GNC_PLUGIN_PAGE(plugin_page);
}
@@ -357,8 +357,9 @@
g_return_if_fail (GNC_IS_PLUGIN_PAGE_BUDGET (page));
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
- g_list_free(priv->period_col_list);
+ g_free(priv->gconf_section);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
LEAVE(" ");
}
@@ -395,7 +396,7 @@
if (ei->event_mask & QOF_EVENT_MODIFY)
{
DEBUG("refreshing budget view because budget was modified");
- gnc_plugin_page_budget_view_refresh(page);
+ gnc_budget_view_refresh(priv->budget_view);
}
}
}
@@ -413,62 +414,28 @@
GtkTreeSelection *selection;
GtkTreeView *tree_view;
GtkWidget *scrolled_window;
- gchar *priv_gconf_section;
const gchar *budget_guid_str;
ENTER("page %p", plugin_page);
page = GNC_PLUGIN_PAGE_BUDGET (plugin_page);
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
- if (priv->widget != NULL)
+ if (priv->budget_view != NULL)
{
- LEAVE("widget = %p", priv->widget);
- return priv->widget;
+ LEAVE("widget = %p", priv->budget_view);
+ return GTK_WIDGET(priv->budget_view);
}
- priv->widget = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (priv->widget);
+ priv->budget_view = gnc_budget_view_new(priv->budget, &priv->fd, priv->gconf_section);
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
- gtk_widget_show (scrolled_window);
- gtk_box_pack_start (GTK_BOX (priv->widget), scrolled_window,
- TRUE, TRUE, 0);
-
- tree_view = gnc_tree_view_account_new(FALSE);
-
- /* Have one gconf section per budget */
- budget_guid_str = guid_to_string (&priv->key);
- priv_gconf_section = g_strjoin ("/", GCONF_SECTION, budget_guid_str, NULL);
- g_object_set(G_OBJECT(tree_view), "gconf-section", priv_gconf_section, NULL);
- g_free (priv_gconf_section);
-
- gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));
- priv->tree_view = tree_view;
- selection = gtk_tree_view_get_selection(tree_view);
- gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
-
+#if 0
g_signal_connect(G_OBJECT(selection), "changed",
G_CALLBACK(gppb_selection_changed_cb), plugin_page);
- g_signal_connect(G_OBJECT(tree_view), "button-press-event",
+#endif
+ g_signal_connect(G_OBJECT(priv->budget_view), "button-press-event",
G_CALLBACK(gppb_button_press_cb), plugin_page);
- g_signal_connect(G_OBJECT(tree_view), "row-activated",
- G_CALLBACK(gppb_double_click_cb), page);
- g_signal_connect_after(G_OBJECT(tree_view), "key-press-event",
- G_CALLBACK(gppb_key_press_cb), NULL);
+ g_signal_connect(G_OBJECT(priv->budget_view), "account-activated",
+ G_CALLBACK(gppb_account_activated_cb), page);
- gppb_selection_changed_cb (NULL, page);
- gtk_tree_view_set_headers_visible(tree_view, TRUE);
- gtk_widget_show (GTK_WIDGET (tree_view));
- gtk_container_add (GTK_CONTAINER (scrolled_window),
- GTK_WIDGET(tree_view));
- priv->fd.tree_view = GNC_TREE_VIEW_ACCOUNT(priv->tree_view);
- gnc_tree_view_account_set_filter(
- GNC_TREE_VIEW_ACCOUNT(tree_view),
- gnc_plugin_page_account_tree_filter_accounts,
- &priv->fd, NULL);
-
priv->component_id =
gnc_register_gui_component(PLUGIN_PAGE_BUDGET_CM_CLASS,
gnc_plugin_page_budget_refresh_cb,
@@ -482,10 +449,8 @@
gnc_budget_get_guid(priv->budget),
QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
- gnc_plugin_page_budget_view_refresh(page);
-
- LEAVE("widget = %p", priv->widget);
- return priv->widget;
+ LEAVE("widget = %p", priv->budget_view);
+ return GTK_WIDGET(priv->budget_view);
}
@@ -493,25 +458,22 @@
gnc_plugin_page_budget_destroy_widget (GncPluginPage *plugin_page)
{
GncPluginPageBudgetPrivate *priv;
- gchar *priv_gconf_section = NULL;
ENTER("page %p", plugin_page);
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(plugin_page);
if (priv->delete_budget)
{
- g_object_get (G_OBJECT(priv->tree_view), "gconf-section", &priv_gconf_section, NULL);
- if (priv_gconf_section)
+ if (priv->gconf_section)
{
- gnc_gconf_unset_dir (priv_gconf_section, NULL);
- g_free (priv_gconf_section);
+ gnc_gconf_unset_dir (priv->gconf_section, NULL);
}
}
- if (priv->widget)
+ if (priv->budget_view)
{
- g_object_unref(G_OBJECT(priv->widget));
- priv->widget = NULL;
+ g_object_unref(G_OBJECT(priv->budget_view));
+ priv->budget_view = NULL;
}
gnc_gui_component_clear_watches (priv->component_id);
@@ -561,8 +523,8 @@
g_key_file_set_string(key_file, group_name, BUDGET_GUID, guid_str);
//FIXME
- gnc_tree_view_account_save(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
- &priv->fd, key_file, group_name);
+ gnc_budget_view_save(priv->budget_view, key_file, group_name);
+
LEAVE(" ");
}
@@ -606,12 +568,16 @@
return NULL;
}
if (!string_to_guid(guid_str, &guid))
+ {
return NULL;
+ }
book = qof_session_get_book(gnc_get_current_session());
bgt = gnc_budget_lookup(&guid, book);
if (!bgt)
+ {
return NULL;
+ }
/* Create the new page. */
page = gnc_plugin_page_budget_new(bgt);
@@ -622,8 +588,11 @@
gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
//FIXME
- gnc_tree_view_account_restore(GNC_TREE_VIEW_ACCOUNT(priv->tree_view),
- &priv->fd, key_file, group_name);
+ if (!gnc_budget_view_restore(priv->budget_view, key_file, group_name))
+ {
+ return NULL;
+ }
+
LEAVE(" ");
return page;
}
@@ -652,51 +621,14 @@
return result;
}
-
-static gboolean
-gppb_key_press_cb(GtkWidget *treeview, GdkEventKey *event, gpointer userdata)
-{
- GtkTreeView *tv = GTK_TREE_VIEW(treeview);
- GtkTreeViewColumn *col;
- GtkTreePath *path = NULL;
-
- if (event->type != GDK_KEY_PRESS) return TRUE;
-
- switch (event->keyval)
- {
- case GDK_Tab:
- case GDK_ISO_Left_Tab:
- case GDK_KP_Tab:
- case GDK_Return:
- case GDK_KP_Enter:
- gtk_tree_view_get_cursor(tv, &path, &col);
- if (!path) return TRUE;
- //finish_edit(col);
- break;
- default:
- return TRUE;
- }
- 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;
-}
-
-
static void
-gppb_double_click_cb(GtkTreeView *treeview, GtkTreePath *path,
- GtkTreeViewColumn *col, GncPluginPageBudget *page)
+gppb_account_activated_cb(GncBudgetView* view, Account* account,
+ GncPluginPageBudget *page)
{
GtkWidget *window;
GncPluginPage *new_page;
- Account *account;
g_return_if_fail(GNC_IS_PLUGIN_PAGE_BUDGET (page));
- account = gnc_tree_view_account_get_account_from_path(
- GNC_TREE_VIEW_ACCOUNT(treeview), path);
- if (account == NULL)
- return;
window = GNC_PLUGIN_PAGE(page)->window;
new_page = gnc_plugin_page_register_new(account, FALSE);
@@ -704,6 +636,7 @@
}
+#if 0
static void
gppb_selection_changed_cb(GtkTreeSelection *selection,
GncPluginPageBudget *page)
@@ -735,6 +668,7 @@
gnc_plugin_update_actions (action_group, actions_requiring_account,
"sensitive", sensitive);
}
+#endif
/*********************
@@ -752,8 +686,7 @@
g_return_if_fail (GNC_IS_PLUGIN_PAGE_BUDGET (page));
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
- acct_list = gnc_tree_view_account_get_selected_accounts(
- GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
+ acct_list = gnc_budget_view_get_selected_accounts(priv->budget_view);
window = GNC_PLUGIN_PAGE (page)->window;
for (tmp = acct_list; tmp; tmp = g_list_next(tmp))
@@ -778,8 +711,7 @@
g_return_if_fail (GNC_IS_PLUGIN_PAGE_BUDGET (page));
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
- acct_list = gnc_tree_view_account_get_selected_accounts(
- GNC_TREE_VIEW_ACCOUNT(priv->tree_view));
+ acct_list = gnc_budget_view_get_selected_accounts(priv->budget_view);
window = GNC_PLUGIN_PAGE (page)->window;
for (tmp = acct_list; tmp; tmp = g_list_next(tmp))
@@ -933,10 +865,9 @@
g_return_if_fail(GNC_IS_PLUGIN_PAGE_BUDGET(page));
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
- acct = gnc_tree_view_account_get_account_from_path(
- GNC_TREE_VIEW_ACCOUNT(priv->tree_view), path);
+ acct = gnc_budget_view_get_account_from_path(priv->budget_view, path);
- num_periods = g_list_length(priv->period_col_list);
+ num_periods = gnc_budget_get_num_periods(priv->budget);
for (i = 0; i < num_periods; i++)
{
@@ -974,7 +905,7 @@
g_return_if_fail (GNC_IS_PLUGIN_PAGE_BUDGET(page));
priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view));
+ sel = gnc_budget_view_get_selection(priv->budget_view);
if (gtk_tree_selection_count_selected_rows(sel) <= 0)
{
@@ -1034,146 +965,7 @@
}
-static gchar *
-budget_col_source(Account *account, GtkTreeViewColumn *col,
- GtkCellRenderer *cell)
-{
- GncBudget *budget;
- guint period_num;
- gnc_numeric numeric;
- gchar amtbuff[100]; //FIXME: overkill, where's the #define?
-
- budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
- period_num = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(col),
- "period_num"));
-
- if (!gnc_budget_is_account_period_value_set(budget, account, period_num))
- {
- amtbuff[0] = '\0';
- }
- else
- {
- numeric = gnc_budget_get_account_period_value(budget, account,
- period_num);
- if (gnc_numeric_check(numeric))
- {
- strcpy(amtbuff, "error");
- }
- else
- {
- xaccSPrintAmount(amtbuff, numeric,
- gnc_account_print_info(account, FALSE));
- }
- }
- return g_strdup(amtbuff);
-}
-
-
static void
-budget_col_edited(Account *account, GtkTreeViewColumn *col,
- const gchar *new_text)
-{
- GncBudget *budget;
- guint period_num;
- gnc_numeric numeric = gnc_numeric_error(GNC_ERROR_ARG);
-
- if (!xaccParseAmount (new_text, TRUE, &numeric, NULL) &&
- !(new_text && *new_text == '\0'))
- return;
-
- period_num = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(col),
- "period_num"));
-
- budget = GNC_BUDGET(g_object_get_data(G_OBJECT(col), "budget"));
-
- if (new_text && *new_text == '\0')
- gnc_budget_unset_account_period_value(budget, account, period_num);
- else
- gnc_budget_set_account_period_value(budget, account, period_num,
- numeric);
-}
-
-
-static void
-gnc_plugin_page_budget_refresh_col_titles(GncPluginPageBudget *page)
-{
- const Recurrence *r;
- GDate date, nextdate;
- GtkTreeViewColumn *col;
- guint titlelen;
- gint num_periods_visible;
- gchar title[MAX_DATE_LENGTH];
- GncPluginPageBudgetPrivate *priv;
- GList *col_list;
- gint i;
-
- g_return_if_fail(GNC_IS_PLUGIN_PAGE_BUDGET(page));
- priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
-
- col_list = priv->period_col_list;
- num_periods_visible = g_list_length(col_list);
-
- /* Show the dates in column titles */
- r = gnc_budget_get_recurrence(priv->budget);
- date = r->start;
- for (i = 0; i < num_periods_visible; i++)
- {
- col = GTK_TREE_VIEW_COLUMN(g_list_nth_data(col_list, i));
- titlelen = qof_print_gdate(title, MAX_DATE_LENGTH, &date);
- if (titlelen > 0)
- gtk_tree_view_column_set_title(col, title);
- recurrenceNextInstance(r, &date, &nextdate);
- date = nextdate;
- }
-
-}
-
-
-static void
-gnc_plugin_page_budget_view_refresh (GncPluginPageBudget *page)
-{
- GncPluginPageBudgetPrivate *priv;
- gint num_periods, num_periods_visible;
- GtkTreeViewColumn *col;
- GList *col_list;
-
- g_return_if_fail(GNC_IS_PLUGIN_PAGE_BUDGET(page));
- priv = GNC_PLUGIN_PAGE_BUDGET_GET_PRIVATE(page);
-
- num_periods = gnc_budget_get_num_periods(priv->budget);
- col_list = priv->period_col_list;
- num_periods_visible = g_list_length(col_list);
-
- /* Hide any unneeded extra columns */
- while (num_periods_visible > num_periods)
- {
- col = GTK_TREE_VIEW_COLUMN((g_list_last(col_list))->data);
- gtk_tree_view_remove_column(GTK_TREE_VIEW(priv->tree_view), col);
- col_list = g_list_delete_link(col_list, g_list_last(col_list));
- num_periods_visible = g_list_length(col_list);
- }
-
- gnc_tree_view_configure_columns(GNC_TREE_VIEW(priv->tree_view));
-
- /* Create any needed columns */
- while (num_periods_visible < num_periods)
- {
- col = gnc_tree_view_account_add_custom_column(
- GNC_TREE_VIEW_ACCOUNT(priv->tree_view), "",
- budget_col_source, budget_col_edited);
- g_object_set_data(G_OBJECT(col), "budget", priv->budget);
- g_object_set_data(G_OBJECT(col), "period_num",
- GUINT_TO_POINTER(num_periods_visible));
- col_list = g_list_append(col_list, col);
- num_periods_visible = g_list_length(col_list);
- }
- priv->period_col_list = col_list;
-
- gnc_plugin_page_budget_refresh_col_titles(page);
-}
-
-
-static void
gnc_plugin_page_budget_cmd_view_filter_by (GtkAction *action,
GncPluginPageBudget *page)
{
More information about the gnucash-changes
mailing list