[Gnucash-changes] Darin Willits' initial budget code.
Derek Atkins
warlord at cvs.gnucash.org
Thu Aug 5 17:03:31 EDT 2004
Log Message:
-----------
Darin Willits' initial budget code.
* src/engine/gnc-budget*:
* src/gnome/*budget*:
* src/gnome/glade/budget.glade:
* src/gnome-utils/gnc-budget*:
Darin Willits' initial budget code. Still not fully functional
but the basic UI is there. See the GNOME2_STATUS for additional
information.
Tags:
----
gnucash-gnome2-dev
Modified Files:
--------------
gnucash:
ChangeLog
GNOME2_STATUS
gnucash/src/engine:
Makefile.am
gnc-engine.c
gnc-engine.h
gnc-trace.c
gnucash/src/gnome:
Makefile.am
gnc-main-window.c
gnucash/src/gnome/ui:
gnc-main-window-ui.xml
gnucash/src/gnome-utils:
Makefile.am
Added Files:
-----------
gnucash/src/engine:
gnc-budget-book-p.h
gnc-budget-book.c
gnc-budget-book.h
gnc-budget-cat-p.h
gnc-budget-cat.c
gnc-budget-cat.h
gnc-budget-p.h
gnc-budget-period-p.h
gnc-budget-period-value-p.h
gnc-budget-period-value.c
gnc-budget-period-value.h
gnc-budget-period.c
gnc-budget-period.h
gnc-budget.c
gnc-budget.h
gnucash/src/gnome:
dialog-budget-category.c
dialog-budget-category.h
dialog-budget-list.c
dialog-budget-list.h
dialog-budget-workbench.c
dialog-budget-workbench.h
druid-budget-create.c
druid-budget-create.h
gnc-budget-gui.h
gnucash/src/gnome/glade:
budget.glade
gnucash/src/gnome-utils:
gnc-budget-list-tree-model.c
gnc-budget-list-tree-model.h
gnc-budget-tree-model.c
gnc-budget-tree-model.h
Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1487.2.135
retrieving revision 1.1487.2.136
diff -LChangeLog -LChangeLog -u -r1.1487.2.135 -r1.1487.2.136
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,13 @@
+2004-08-05 Derek Atkins <derek at ihtfp.com>
+
+ * src/engine/gnc-budget*:
+ * src/gnome/*budget*:
+ * src/gnome/glade/budget.glade:
+ * src/gnome-utils/gnc-budget*:
+ Darin Willits' initial budget code. Still not fully functional
+ but the basic UI is there. See the GNOME2_STATUS for additional
+ information.
+
2004-07-20 Derek Atkins <derek at ihtfp.com>
* lib/egg/eggtoolbar.c
Index: GNOME2_STATUS
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/Attic/GNOME2_STATUS,v
retrieving revision 1.1.2.25
retrieving revision 1.1.2.26
diff -LGNOME2_STATUS -LGNOME2_STATUS -u -r1.1.2.25 -r1.1.2.26
--- GNOME2_STATUS
+++ GNOME2_STATUS
@@ -121,6 +121,20 @@
HBCI - Needs new http support. [gnet]
+Budgeting
+ - Can create/modify budgets via the Budgeting workbench.
+ (Actions->Budgeting Workbench)
+ - Track budget tab still needs to be competed. Should allow you to look
+ at predicted vs actual information.
+ - No save to file functionality. Therefore budgets must currently be
+ created fresh each time gnucash is started. First thing that I want
+ to fix.
+ - Should the budgeting workbench fit into the new windowing scheme
+ better? Currently it is its own window but maybe each workbench
+ should be a tab in the new layout. How would this work with the
+ sub-tabs? Have to think about this some more.
+ - Probably more TODO but these are the main points.
+
========================================
ENHANCEMENTS
========================================
@@ -145,3 +159,4 @@
long term?)
4/ Print-preview support.
+
--- /dev/null
+++ src/gnome/glade/budget.glade
@@ -0,0 +1,2202 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkDialog" id="Budget List">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Budget List</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="has_separator">True</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="close_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-7</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="Budget List View">
+ <property name="border_width">10</property>
+ <property name="width_request">250</property>
+ <property name="height_request">200</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="new_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-new</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="edit_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button3">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-delete</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="New Budget Druid">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">New Budget</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">True</property>
+
+ <child>
+ <widget class="GnomeDruid" id="Budget Druid">
+ <property name="border_width">4</property>
+ <property name="visible">True</property>
+ <property name="show_help">False</property>
+
+ <child>
+ <widget class="GnomeDruidPageEdge" id="">
+ <property name="visible">True</property>
+ <property name="position">GNOME_EDGE_START</property>
+ <property name="title" translatable="yes">Create new Budget</property>
+ <property name="text" translatable="yes">This druid will help you create a new
+Budget.
+
+Note: This is still a *very* experimental
+feature. It will most probably crash and
+very likely spill your coffee in your lap
+causing serious burns.
+
+You have been warned.</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GnomeDruidPageStandard" id="Budget Name">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Budget Name</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="druid-vbox1">
+ <property name="border_width">16</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">0.5</property>
+
+ <child>
+ <widget class="GtkTable" id="table2">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
+
+ <child>
+ <widget class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Description: </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label36">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label37">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label39">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">46</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label41">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="name_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow10">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="description_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GnomeDruidPageStandard" id="druidpagestandard1">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Budget Setup</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="druid-vbox2">
+ <property name="border_width">16</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">0.5</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox10">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox13">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">5</property>
+
+ <child>
+ <widget class="GtkLabel" id="label77">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Budget Duration:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkSpinButton" id="length_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">0</property>
+ <property name="numeric">False</property>
+ <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+ <property name="snap_to_ticks">False</property>
+ <property name="wrap">False</property>
+ <property name="adjustment">1 0 100 1 10 10</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkOptionMenu" id="length_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="history">0</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu7">
+
+ <child>
+ <widget class="GtkMenuItem" id="months1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">months</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_months1_activate" last_modification_time="Mon, 15 Sep 2003 09:45:19 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="years1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">years</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_years1_activate" last_modification_time="Mon, 15 Sep 2003 09:45:19 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="budget_freq_box">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GnomeDruidPageStandard" id="Category Setup">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Category Setup</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="druid-vbox3">
+ <property name="border_width">16</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow11">
+ <property name="width_request">500</property>
+ <property name="height_request">400</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="budget_tree_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox2">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="new_category_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-new</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="edit_category_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="delete_category_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-delete</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GnomeDruidPageEdge" id="finish_page">
+ <property name="visible">True</property>
+ <property name="position">GNOME_EDGE_FINISH</property>
+ <property name="title" translatable="yes">Finish Budget</property>
+ <property name="text" translatable="yes">Welcome to the first step on the road
+to financial happiness!</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="Budget Workbench">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Budget Workbench</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="has_separator">True</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area3">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="helpbutton2">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-help</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-11</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="apply_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-apply</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-10</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="ok_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkNotebook" id="notebook1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">True</property>
+ <property name="show_border">True</property>
+ <property name="tab_pos">GTK_POS_TOP</property>
+ <property name="scrollable">False</property>
+ <property name="enable_popup">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox9">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame5">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox16">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkTable" id="table4">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">5</property>
+ <property name="column_spacing">10</property>
+
+ <child>
+ <widget class="GtkLabel" id="label65">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label66">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Description:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="name_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label70">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label71">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label72">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label73">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow12">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="description_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_NONE</property>
+ <property name="cursor_visible">True</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox11">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox17">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">5</property>
+
+ <child>
+ <widget class="GtkLabel" id="label78">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Budget Duration:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkSpinButton" id="length_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">0</property>
+ <property name="numeric">False</property>
+ <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+ <property name="snap_to_ticks">False</property>
+ <property name="wrap">False</property>
+ <property name="adjustment">1 0 100 1 10 10</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkOptionMenu" id="length_menu">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="history">0</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu8">
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">months</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_months1_activate" last_modification_time="Mon, 15 Sep 2003 09:45:19 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">years</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_years1_activate" last_modification_time="Mon, 15 Sep 2003 09:45:19 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="budget_freq_box">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label63">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">General Information</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame6">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox20">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow13">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="category_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox3">
+ <property name="border_width">10</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="new_category_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-new</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="edit_category_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="delete_category_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-delete</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label81">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Category Setup</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox11">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-properties</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label74">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Budget Setup</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox13">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="regenerate_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment4">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox21">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image6">
+ <property name="visible">True</property>
+ <property name="stock">gtk-refresh</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label82">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Regenerate From Defaults</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow14">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="balance_budget_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox12">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-refresh</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label75">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Balance Budget</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox14">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox22">
+ <property name="border_width">10</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox3">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_START</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="first_period_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-goto-first</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="back_period_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-go-back</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="period_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">January 1, 2004</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox2">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="next_period_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-go-forward</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="last_period_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-goto-last</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow15">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="track_view">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="track_budget_view">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="image5">
+ <property name="visible">True</property>
+ <property name="stock">gtk-zoom-100</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label76">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Track Budget</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="Modify Category Dialog">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">Modify Category</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="has_separator">True</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area4">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="helpbutton3">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-help</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-11</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="ok_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox8">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox5">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">True</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label51">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_RIGHT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label52">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Description:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_RIGHT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label59">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Value:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_RIGHT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label53">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Commodity:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_RIGHT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox6">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">True</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkEntry" id="name_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="description_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkSpinButton" id="value_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">2</property>
+ <property name="numeric">False</property>
+ <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+ <property name="snap_to_ticks">False</property>
+ <property name="wrap">False</property>
+ <property name="adjustment">1 0 1e+37 1 10 10</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="commodity_box">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label50">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Category Information</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame3">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox9">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">True</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkRadioButton" id="inflow_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">In Flow</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkRadioButton" id="outflow_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Outflow</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">inflow_button</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label55">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Category Type</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="frequency_box">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame4">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="related_accounts_scroll">
+ <property name="border_width">5</property>
+ <property name="width_request">509</property>
+ <property name="height_request">390</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label56">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Related Accounts:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
Index: gnc-main-window-ui.xml
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/ui/Attic/gnc-main-window-ui.xml,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -Lsrc/gnome/ui/gnc-main-window-ui.xml -Lsrc/gnome/ui/gnc-main-window-ui.xml -u -r1.1.2.8 -r1.1.2.9
--- src/gnome/ui/gnc-main-window-ui.xml
+++ src/gnome/ui/gnc-main-window-ui.xml
@@ -58,6 +58,7 @@
<menuitem name="ActionsSinceLastRun" action="ActionsSinceLastRunAction"/>
<menuitem name="ActionsMortgageLoan" action="ActionsMortgageLoanAction"/>
</menu>
+ <menuitem name="ActionsBudgetWorkbenchAction" action="ActionsBudgetWorkbenchAction"/>
<placeholder name="ActionsPlaceholder"/>
<menuitem name="ActionsCloseBooks" action="ActionsCloseBooksAction"/>
</menu>
Index: gnc-trace.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-trace.c,v
retrieving revision 1.2.20.7
retrieving revision 1.2.20.8
diff -Lsrc/engine/gnc-trace.c -Lsrc/engine/gnc-trace.c -u -r1.2.20.7 -r1.2.20.8
--- src/engine/gnc-trace.c
+++ src/engine/gnc-trace.c
@@ -43,7 +43,7 @@
GNC_LOG_WARNING, /* REGISTER */
GNC_LOG_WARNING, /* LEDGER */
GNC_LOG_WARNING, /* HTML */
- GNC_LOG_WARNING, /* GUI */
+ GNC_LOG_DEBUG, /* GUI */
GNC_LOG_WARNING, /* SCRUB */
GNC_LOG_WARNING, /* GTK_REG */
GNC_LOG_WARNING, /* GUILE */
--- /dev/null
+++ src/engine/gnc-budget-period-p.h
@@ -0,0 +1,49 @@
+/********************************************************************\
+ * gnc-budget-period-p.h -- Private structure definition of the *
+ * budget period structure. *
+ * Copyright (C) 16 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-period-p.h
+ * @breif Private structure definition of the budget period structure.
+ * @author Created by Darin Willits 16 sep 2003
+ * @author Copyright (c) 16 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * A budget period is simply a begin and end date right now although
+ * it may eventually have to encapsulate more information. Each budget
+ * category maintains a list of values each of which refers to a given
+ * budget period object.
+ */
+
+#ifndef __GNC_BUDGET_PERIOD_P_H__
+#define __GNC_BUDGET_PERIOD_P_H__
+
+#include "gnc-budget-period.h"
+
+struct gncp_budget_period{
+ GDate start_date;
+ GDate end_date;
+};
+
+
+#endif // __GNC_BUDGET_PERIOD_P_H__
--- /dev/null
+++ src/engine/gnc-budget-cat.c
@@ -0,0 +1,568 @@
+/********************************************************************\
+ * gnc-budget-cat.c -- Implementation of the budget category methods. *
+ * Copyright (C) 05 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget-cat.c
+ * @breif Implementation of the budget category methods.
+ * @author Created by Darin Willits 05 sep 2003
+ * @author Copyright (c) 05 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ *
+ */
+
+
+// Includes
+#include "config.h"
+#include <stdio.h>
+#include <time.h>
+
+#include "gnc-budget-cat-p.h"
+#include "qofid-p.h"
+#include "gnc-trace.h"
+#include "gnc-budget-period-value.h"
+#include "gnc-budget-period.h"
+
+static short module = MOD_GUI;
+
+GncBudgetCategory *gnc_budget_category_new(QofBook* book, GncBudget* budget)
+{
+ GncBudgetCategory* category;
+ GDate date;
+ GString* freqStr;
+
+ ENTER("book %p, budget %p", book, budget);
+ g_return_val_if_fail(book, NULL);
+
+ category = g_new0(GncBudgetCategory, 1);
+
+ qof_instance_init (&category->inst, GNC_ID_BUDGET_CATEGORY, book);
+
+ // The interface for this has been changed to the above line.
+ //category->entity_table = qof_book_get_entity_table (book);
+ //qof_entity_guid_new (category->entity_table, &category->guid);
+
+ //qof_entity_store( category->entity_table, category,
+ // &category->guid, GNC_ID_BUDGET_CATEGORY );
+
+ category->budget = budget;
+ category->value = gnc_numeric_zero();
+
+ category->freq = xaccFreqSpecMalloc(book);
+ g_date_clear(&date, 1);
+ g_date_set_time(&date, time(NULL));
+ if(g_date_valid(&date) == FALSE){
+ //printf("Invalid Date!\n");
+ }
+ xaccFreqSpecSetMonthly(category->freq, &date, 1);
+ xaccFreqSpecSetUIType(category->freq, UIFREQ_MONTHLY);
+
+ freqStr = g_string_sized_new(16);
+ xaccFreqSpecGetFreqStr(category->freq, freqStr);
+ //printf("Category Freq: %s\n", freqStr->str);
+
+
+ LEAVE("category: %p", category);
+ return category;
+}
+
+static void delete_child(gpointer data, gpointer user_data)
+{
+ GncBudgetCategory* category = (GncBudgetCategory*)data;
+ gnc_budget_category_delete(category);
+}
+
+
+void gnc_budget_category_delete(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return;
+ }
+
+ if(category->name){
+ g_free(category->name);
+ }
+ if(category->description){
+ g_free(category->description);
+ }
+
+ // Now use qof_instance_release.
+ //qof_entity_remove(category->entity_table, &category->guid);
+ g_list_free(category->accountList);
+
+ xaccFreqSpecFree(category->freq);
+
+ g_list_foreach(category->children, delete_child, NULL);
+
+
+ /* Remove us from our parents list. */
+ if(category->parent != NULL){
+ gnc_budget_category_remove_child(category->parent, category);
+ }
+
+ qof_instance_release(&category->inst);
+ g_free(category);
+}
+
+void gnc_budget_category_set_name(GncBudgetCategory* category, const gchar* name)
+{
+ g_return_if_fail( name != NULL );
+ if ( category->name != NULL ) {
+ g_free( category->name );
+ category->name = NULL;
+ }
+ category->name = g_strdup( name );
+}
+
+gchar* gnc_budget_category_get_name(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return NULL;
+ }
+ return category->name;
+}
+
+void gnc_budget_category_set_description(GncBudgetCategory* category, const gchar* description)
+{
+ g_return_if_fail(description != NULL);
+ if(category->description != NULL){
+ g_free(category->description);
+ category->description = NULL;
+ }
+ category->description = g_strdup(description);
+}
+
+gchar* gnc_budget_category_get_description(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return NULL;
+ }
+ return category->description;
+}
+
+void gnc_budget_category_set_value(GncBudgetCategory* category, gnc_numeric value)
+{
+ if(category == NULL){
+ return;
+ }
+ category->value = value;
+}
+
+gnc_numeric gnc_budget_category_get_value(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return gnc_numeric_zero();
+ }
+ return category->value;
+}
+
+void gnc_budget_category_add_account(GncBudgetCategory* category, Account* account)
+{
+ if(category == NULL){
+ return;
+ }
+ category->accountList = g_list_append(category->accountList, account);
+
+ /* If our commodity hasn't been set yet we might as well take it
+ * from the account we have just been given. */
+ if(category->commodity == NULL){
+ category->commodity = xaccAccountGetCommodity(account);
+ }
+}
+
+void gnc_budget_category_remove_account(GncBudgetCategory* category, Account* account)
+{
+ if(category == NULL){
+ return;
+ }
+ category->accountList = g_list_remove(category->accountList, account);
+}
+
+AccountList* gnc_budget_category_get_related_accounts(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return NULL;
+ }
+ return category->accountList;
+}
+
+void gnc_budget_category_set_related_accounts(GncBudgetCategory* category, AccountList* accounts)
+{
+ if(category == NULL){
+ return;
+ }
+
+ if(category->accountList != NULL){
+ g_list_free(category->accountList);
+ category->accountList = NULL;
+ }
+
+ category->accountList = accounts;
+}
+
+void gnc_budget_category_set_frequency(GncBudgetCategory* category, FreqSpec* freq)
+{
+ if(category == NULL){
+ return;
+ }
+ category->freq = freq;
+}
+
+FreqSpec* gnc_budget_category_get_frequency(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return NULL;
+ }
+ return category->freq;
+}
+
+void gnc_budget_category_set_type(GncBudgetCategory* category, GncBudgetCategoryType type)
+{
+ if(category == NULL){
+ return;
+ }
+ category->type = type;
+}
+
+GncBudgetCategoryType gnc_budget_category_get_type(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return -1;
+ }
+ return category->type;
+}
+
+void gnc_budget_category_set_commodity(GncBudgetCategory* category, gnc_commodity* commodity)
+{
+ if(category == NULL){
+ return;
+ }
+ category->commodity = commodity;
+}
+
+gnc_commodity* gnc_budget_category_get_commodity(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return NULL;
+ }
+ return category->commodity;
+}
+
+void gnc_budget_category_add_child(GncBudgetCategory* parent, GncBudgetCategory* child)
+{
+ if((parent == NULL) || (child == NULL)){
+ return;
+ }
+ if(child->parent != NULL){
+ /* Remove the child account from its previous parents list. */
+ child->parent->children = g_list_remove(child->parent->children, child);
+ }
+ parent->children = g_list_append(parent->children, child);
+ child->parent = parent;
+}
+
+void gnc_budget_category_remove_child(GncBudgetCategory* parent, GncBudgetCategory* child)
+{
+ if((parent == NULL) || (child == NULL)){
+ return;
+ }
+ parent->children = g_list_remove(parent->children, child);
+}
+
+GncBudgetCategory* gnc_budget_category_get_child(GncBudgetCategory* parent, gint index)
+{
+ if(parent == NULL){
+ return NULL;
+ }
+ return g_list_nth_data(parent->children, index);
+}
+
+GncBudgetCategoryList* gnc_budget_category_get_children(GncBudgetCategory* parent)
+{
+ if(parent == NULL){
+ return NULL;
+ }
+ return parent->children;
+}
+
+gint gnc_budget_category_get_num_children(GncBudgetCategory* parent)
+{
+ if(parent == NULL){
+ return -1;
+ }
+ return g_list_length(parent->children);
+}
+
+GncBudgetCategory* gnc_budget_category_get_parent(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return NULL;
+ }
+ return category->parent;
+}
+
+gint gnc_budget_category_get_index_in_parent_list(GncBudgetCategory* category)
+{
+ if(category == NULL){
+ return -1;
+ }
+ if(category->parent == NULL){
+ return 0;
+ }
+ return g_list_index(category->parent->children, category);
+}
+
+/*
+ * Nice idea but not necessary.
+static gint calculate_mulitplier(FreqSpec* freq, GDate* start_date, GDate* end_date)
+{
+ gint multiplier = 0;
+ gboolean done = FALSE;
+ GDate* outDate, *inDate;
+ inDate = g_date_new_dmy( g_date_get_day(start_date),
+ g_date_get_month(start_date),
+ g_date_get_year(start_date));
+ outDate = g_date_new();
+ g_date_clear(outDate, 1);
+
+
+ while(!done){
+ xaccFreqSpecGetNextInstance(freq, inDate, outDate);
+ if(!g_date_valid(outDate)){
+ break;
+ }
+
+ if(g_date_compare(outDate, end_date) < 0){
+ multiplier++;
+ g_date_set_dmy(inDate, g_date_get_day(outDate),
+ g_date_get_month(outDate),
+ g_date_get_year(outDate));
+ }
+ else{
+ done = TRUE;
+ }
+ }
+
+ g_date_free(inDate);
+ g_date_free(outDate);
+
+ return multiplier;
+}
+
+
+GncBudgetValue* budget_value_new()
+{
+ GncBudgetValue* value;
+
+ value = g_new0(GncBudgetValue, 1);
+ value->value = gnc_numeric_zero();
+ value->adjustment = gnc_numeric_zero();
+
+ return value;
+}
+*/
+
+/* Find out how many occurences of the given frequency spec fall within the
+ * given dates.
+ * TODO: This should probably be moved to the FreqSpec public interface.
+ */
+static gint find_num_occurences(FreqSpec* a, const GDate* startDate, const GDate* endDate)
+{
+ GDate outDate;
+ GDate curDate;
+
+ g_date_set_dmy(&curDate, g_date_day(startDate),
+ g_date_month(startDate),
+ g_date_year(startDate));
+
+ gint counter = 0;
+
+ do{
+ xaccFreqSpecGetNextInstance(a, &curDate, &outDate);
+ if(g_date_valid(&outDate) == FALSE){
+ break;
+ }
+
+ if(g_date_compare(&outDate, endDate) <= 0){
+ counter++;
+ g_date_set_dmy(&curDate, g_date_day(&outDate),
+ g_date_month(&outDate),
+ g_date_year(&outDate));
+ }
+ else{
+ break;
+ }
+ }while(1);
+
+ return counter;
+}
+
+/* Generate the budget value for the given period.
+ */
+static void generate_budget_value_for_period(gpointer data, gpointer user_data)
+{
+ GncBudgetCategory* category = user_data;
+ GncBudgetPeriod* period = data;
+ GDate* periodStartDate, *periodEndDate;
+ FreqSpec* periodFreq, *catFreq;
+ int compare;
+ GncBudgetPeriodValue* periodValue;
+ gint multiplier;
+ double value;
+
+ periodFreq = gnc_budget_get_period_frequency(category->budget);
+ catFreq = gnc_budget_category_get_frequency(category);
+
+ periodStartDate = gnc_budget_period_get_start_date(period);
+ periodEndDate = gnc_budget_period_get_end_date(period);
+
+ compare = gnc_freq_spec_compare(periodFreq, catFreq);
+
+ /* If the frequencies are the same we can just fill in the value
+ * from the categories value. Otherwise we have to find out how many
+ * of the categories frequencies fall within the given period and and
+ * multiply by the categories value.
+ */
+ if(compare == 0){
+ value = gnc_numeric_to_double(category->value);
+ //printf("Frequencies equal: %0.2f\n", value);
+ periodValue = gnc_budget_period_value_new();
+ gnc_budget_period_value_set_value_double(periodValue, value);
+ category->period_values = g_list_append(category->period_values, periodValue);
+ }
+ else{
+ multiplier = find_num_occurences(catFreq, periodStartDate, periodEndDate);
+ value = gnc_numeric_to_double(category->value) * multiplier;
+ //printf("Period Freq larger: %0.2f\n", value);
+ periodValue = gnc_budget_period_value_new();
+ gnc_budget_period_value_set_value_double(periodValue, value);
+ category->period_values = g_list_append(category->period_values, periodValue);
+ }
+
+}
+
+static void category_generate_values(gpointer data, gpointer user_data)
+{
+ GncBudgetCategory* category = data;
+
+ gnc_budget_category_generate_values(category);
+}
+
+static void free_budget_value(gpointer data, gpointer user_data)
+{
+ GncBudgetPeriodValue* periodValue = data;
+ gnc_budget_period_value_delete(periodValue);
+}
+
+void gnc_budget_category_generate_values(GncBudgetCategory* category)
+{
+ GList* period_list;
+ double value;
+
+ if(category == NULL){
+ return;
+ }
+
+ /* Delete all the old values if there are any cause we are going to
+ * re-evaluate them all.
+ */
+ if(category->period_values != NULL){
+ g_list_foreach(category->period_values, free_budget_value, NULL);
+ g_list_free(category->period_values);
+ category->period_values = NULL;
+ }
+
+ value = gnc_numeric_to_double(category->value);
+ //printf("Category Value: %0.2f\n", value);
+
+ period_list = gnc_budget_get_period_list(category->budget);
+
+ g_list_foreach(period_list, generate_budget_value_for_period, category);
+
+ /* Now generate the value lists for our kids.
+ * Should this really do this?? Maybe categories with children
+ * should have the sum of their kids values as their own ala the
+ * accounts. Have to think on this some more... for now the quick and
+ * dirty.
+ */
+ //printf("Doing children for category: %s\n", category->name);
+ g_list_foreach(category->children, category_generate_values, NULL);
+}
+
+gnc_numeric gnc_budget_category_get_value_by_index(GncBudgetCategory* category, gint index)
+{
+ GncBudgetPeriodValue* periodValue;
+
+ if(category == NULL){
+ return gnc_numeric_zero();
+ }
+
+ periodValue = g_list_nth_data(category->period_values, index);
+
+ if(periodValue == NULL){
+ return gnc_numeric_zero();
+ }
+
+ return gnc_budget_period_value_get_value(periodValue);
+}
+
+void gnc_budget_category_set_period_value_by_index(GncBudgetCategory* category, gint index,
+ gnc_numeric value)
+{
+ GncBudgetPeriodValue* periodValue;
+
+ if(category == NULL){
+ return;
+ }
+
+ periodValue = g_list_nth_data(category->period_values, index);
+
+ if(periodValue == NULL){
+ return;
+ }
+
+ gnc_budget_period_value_set_value(periodValue, value);
+}
+
+/* This is a cheat method right now to give meaningfull values for the
+ * display. We should probably NEVER return doubles as we could then
+ * potentially encounter rounding errors. All calculations should be done
+ * in terms of the gnc_numeric value.
+ */
+double gnc_budget_category_sum_child_values_by_index(GncBudgetCategory* category, gint index)
+{
+ double sum = 0.0;
+ GList* childList;
+
+ if(category == NULL){
+ return 0.00;
+ }
+
+ childList = category->children;
+
+ for(;childList; childList = childList->next){
+ sum += gnc_numeric_to_double(gnc_budget_category_get_value_by_index(childList->data, index));
+ }
+
+ return sum;
+}
--- /dev/null
+++ src/engine/gnc-budget-period.c
@@ -0,0 +1,87 @@
+/********************************************************************\
+ * gnc-budget-period.c -- Implementation of the budget period *
+ * interface. *
+ * Copyright (C) 16 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-period.c
+ * @breif Implementation of the budget period interface.
+ * @author Created by Darin Willits 16 sep 2003
+ * @author Copyright (c) 16 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+
+// Includes
+#include <glib.h>
+
+#include "gnc-budget-period.h"
+#include "gnc-budget-period-p.h"
+
+GncBudgetPeriod* gnc_budget_period_new(void)
+{
+ GncBudgetPeriod* period;
+
+ period = g_new0(GncBudgetPeriod, 1);
+
+ g_date_clear(&period->start_date, 1);
+ g_date_clear(&period->end_date, 1);
+
+ return period;
+}
+
+void gnc_budget_period_set_start_date(GncBudgetPeriod* period, GDate* startDate)
+{
+ if(period == NULL){
+ return;
+ }
+ period->start_date = *startDate;
+}
+
+GDate* gnc_budget_period_get_start_date(GncBudgetPeriod* period)
+{
+ if(period == NULL){
+ return NULL;
+ }
+ return &period->start_date;
+}
+
+
+
+void gnc_budget_period_set_end_date(GncBudgetPeriod* period, GDate* endDate)
+{
+ if(period == NULL){
+ return;
+ }
+ period->end_date = *endDate;
+}
+
+GDate* gnc_budget_period_get_end_date(GncBudgetPeriod* period)
+{
+ if(period == NULL){
+ return NULL;
+ }
+ return &period->end_date;
+}
+
+
--- /dev/null
+++ src/engine/gnc-budget-book-p.h
@@ -0,0 +1,53 @@
+/********************************************************************\
+ * gnc-budget-book-p.h -- Private functions for budget/book linkage*
+ * Copyright (C) 04 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget-book-p.h
+ * @breif Private functions for budget/book linkage.
+ * @author Created by Darin Willits 04 sep 2003
+ * @author Copyright (c) 04 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ *
+ */
+
+#ifndef __GNC_BUDGETBOOK_P_H__
+#define __GNC_BUDGETBOOK_P_H__
+
+#include "qofbook.h"
+#include "gnc-budget-book.h"
+
+struct xaccBudgetsDef{
+
+ QofBook *book;
+ GList *budget_list;
+ gboolean budget_notsaved;
+
+};
+
+/** Associate the given budget list to the book.*/
+void gnc_book_set_budgets( QofBook *book, GList *newList );
+
+gboolean gnc_budget_register (void);
+
+#endif // __BUDGETBOOK_P_H__
Index: gnc-engine.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-engine.h,v
retrieving revision 1.16.4.5
retrieving revision 1.16.4.6
diff -Lsrc/engine/gnc-engine.h -Lsrc/engine/gnc-engine.h -u -r1.16.4.5 -r1.16.4.6
--- src/engine/gnc-engine.h
+++ src/engine/gnc-engine.h
@@ -73,6 +73,8 @@
#define GNC_ID_PRICEDB "PriceDB"
#define GNC_ID_SPLIT "Split"
#define GNC_ID_SCHEDXACTION "SchedXaction"
+#define GNC_ID_BUDGET "Budget"
+#define GNC_ID_BUDGET_CATEGORY "BudgetCategory"
#define GNC_ID_SXTG "SXTGroup"
#define GNC_ID_SXTT "SXTTrans"
#define GNC_ID_TRANS "Trans"
--- /dev/null
+++ src/engine/gnc-budget-cat.h
@@ -0,0 +1,187 @@
+/********************************************************************\
+ * gnc-budget-cat.h -- Public interface for the budget category. *
+ * Copyright (C) 05 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget-cat.h
+ * @breif Public interface of the budget category structure.
+ * @author Created by Darin Willits 05 sep 2003
+ * @author Copyright (c) 05 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * A budget category encapsulates the concept of a single budgetable
+ * item. By default a category is linked to a single account from
+ * account tree. However a category can be linked to any number of
+ * regular accounts including none at all. Hopefully this flexibility
+ * will allow different users to utilize the budgeting engine to capture
+ * their own concept of budgeting.
+ *
+ * This is pre-alpha software. Beware.
+ */
+
+#ifndef __GNC_BUDGET_CAT_H__
+#define __GNC_BUDGET_CAT_H__
+
+#include <glib.h>
+
+/** The budget data.*/
+typedef struct gncp_budget_category GncBudgetCategory;
+typedef GList GncBudgetCategoryList;
+
+#include "Account.h"
+#include "gnc-numeric.h"
+#include "qofbook.h"
+#include "gnc-budget.h"
+#include "FreqSpec.h"
+
+
+typedef enum{
+ BUDGET_CATEGORY_INFLOW,
+ BUDGET_CATEGORY_OUTFLOW,
+} GncBudgetCategoryType;
+
+
+/**
+ * Creates and initializes a Budget Category.
+ **/
+GncBudgetCategory *gnc_budget_category_new(QofBook* book, GncBudget* budget);
+
+/** Deletes the given budget category object.*/
+void gnc_budget_category_delete(GncBudgetCategory* category);
+
+/** Set the Name of the Budget Category.
+ */
+void gnc_budget_category_set_name(GncBudgetCategory* category, const gchar* name);
+
+/** Retieve the Name of the Budget.
+ */
+gchar* gnc_budget_category_get_name(GncBudgetCategory* category);
+
+/** Set the Description of the Budget Category.
+ */
+void gnc_budget_category_set_description(GncBudgetCategory* category, const gchar* description);
+
+/** Retieve the Description of the Budget.
+ */
+gchar* gnc_budget_category_get_description(GncBudgetCategory* category);
+
+
+/** Set the value for this budget category.
+ */
+void gnc_budget_category_set_value(GncBudgetCategory* category, gnc_numeric value);
+
+/** Retrieve the value for this budget category.
+ */
+gnc_numeric gnc_budget_category_get_value(GncBudgetCategory* category);
+
+/* Add the account to the list of accounts.
+ */
+void gnc_budget_category_add_account(GncBudgetCategory* category, Account* account);
+
+/* Remove the account from the list of accounts.
+ */
+void gnc_budget_category_remove_account(GncBudgetCategory* category, Account* account);
+
+/* Return the list of related accounts.
+ */
+AccountList* gnc_budget_category_get_related_accounts(GncBudgetCategory* category);
+
+/* Set the list of related accounts to the one given.
+ * Delete the current list if it exists.
+ */
+void gnc_budget_category_set_related_accounts(GncBudgetCategory* category, AccountList* accounts);
+
+
+/* Set the frequency.
+ */
+void gnc_budget_category_set_frequency(GncBudgetCategory* category, FreqSpec* freq);
+
+/** Retrieve the frequency.
+ */
+FreqSpec* gnc_budget_category_get_frequency(GncBudgetCategory* category);
+
+
+/** Set the budget category type
+ */
+void gnc_budget_category_set_type(GncBudgetCategory* category, GncBudgetCategoryType type);
+
+/** Retrieve the category type.
+ */
+GncBudgetCategoryType gnc_budget_category_get_type(GncBudgetCategory* category);
+
+/** Set the commodity.
+ */
+void gnc_budget_category_set_commodity(GncBudgetCategory* category, gnc_commodity* commodity);
+
+/* Retrieve the commodity.
+ */
+gnc_commodity* gnc_budget_category_get_commodity(GncBudgetCategory* category);
+
+
+/* Add a category to our list of children.
+ */
+void gnc_budget_category_add_child(GncBudgetCategory* parent, GncBudgetCategory* child);
+
+/* Remove a category to our list of children.
+ */
+void gnc_budget_category_remove_child(GncBudgetCategory* parent, GncBudgetCategory* child);
+
+/* Retrieve a child category from the given index.
+ */
+GncBudgetCategory* gnc_budget_category_get_child(GncBudgetCategory* parent, gint index);
+
+/** Retrieve the entire list of our children.
+ */
+GncBudgetCategoryList* gnc_budget_category_get_children(GncBudgetCategory* parent);
+
+/** Get the number of child account we have.
+ */
+gint gnc_budget_category_get_num_children(GncBudgetCategory* parent);
+
+/* Return the parent of this category.
+ */
+GncBudgetCategory* gnc_budget_category_get_parent(GncBudgetCategory* category);
+
+/** Return the position of this category in its parents list. */
+gint gnc_budget_category_get_index_in_parent_list(GncBudgetCategory* category);
+
+
+/* Generate the budget values.
+ * This function will generate the list of budget values based on the
+ * list of periods in the associated budget object.
+ */
+void gnc_budget_category_generate_values(GncBudgetCategory* category);
+
+/* Retrieve the budget value based on an index.
+ */
+gnc_numeric gnc_budget_category_get_value_by_index(GncBudgetCategory* category, gint index);
+
+/* Set the period value at the given index.
+ */
+void gnc_budget_category_set_period_value_by_index(GncBudgetCategory* category, gint index,
+ gnc_numeric value);
+
+/** Get the sum of values for child accounts at the given period index.
+ */
+double gnc_budget_category_sum_child_values_by_index(GncBudgetCategory* category, gint index);
+
+#endif // __BUDGET_CAT_H__
--- /dev/null
+++ src/engine/gnc-budget.h
@@ -0,0 +1,187 @@
+/********************************************************************\
+ * gnc-budget.h -- Budget public handling routines. *
+ * Copyright (C) 04 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget.h
+ * @breif Public interface for budget objects.
+ * @author Created by Darin Willits 04 sep 2003
+ * @author Copyright (c) 04 Darin Willits <darin at willits.ca>
+ *
+ * This file contains the public methods to interact with a budgeting
+ * object. A budget object contains a list of budget_categories each of
+ * which define an individual budgetable item. When a budget is first
+ * created these catagories will be initialized based on the existing
+ * account hierarchy.
+ *
+ * This is pre-alpha code right now. User beware.
+ */
+
+
+#ifndef __GNC_BUDGET_H__
+#define __GNC_BUDGET_H__
+
+#include <glib.h>
+
+/** The budget data.*/
+typedef struct gncp_budget GncBudget;
+
+#include "guid.h"
+#include "qofbook.h"
+#include "gnc-budget-cat.h"
+#include "FreqSpec.h"
+
+
+/**
+ * Creates and initializes a Budget.
+ **/
+GncBudget *gnc_budget_new(QofBook *book);
+
+/** Deletes the given budget object.*/
+void gnc_budget_delete(GncBudget* budget);
+
+
+
+/** Set the Name of the Budget.
+ */
+void gnc_budget_set_name(GncBudget* budget, const gchar* name);
+
+/** Retieve the Name of the Budget.
+ */
+gchar* gnc_budget_get_name(GncBudget* budget);
+
+
+
+/** Set the Description of the Budget.
+ */
+void gnc_budget_set_description(GncBudget* budget, const gchar* description);
+
+/** Retieve the Description of the Budget.
+ */
+gchar* gnc_budget_get_description(GncBudget* budget);
+
+
+
+/** Set the period frequency.
+ */
+void gnc_budget_set_period_frequency(GncBudget* budget, FreqSpec* period);
+
+/** Get the period frequency.
+ */
+FreqSpec* gnc_budget_get_period_frequency(GncBudget* budget);
+
+
+
+/** Set the start date*/
+void gnc_budget_set_start_date(GncBudget* budget, GDate* date);
+
+/** Return the start date */
+GDate* gnc_budget_get_start_date(GncBudget* budget);
+
+
+/** Set the Length for this budget in terms of a number of months.
+ */
+void gnc_budget_set_length_months(GncBudget* budget, gint months);
+
+/** Set the Length for this budget in terms of a number of months.
+ */
+void gnc_budget_set_length_years(GncBudget* budget, gint years);
+
+/** Retrieve the Length for this budget in number of months.
+ */
+gint gnc_budget_get_length_months(GncBudget* budget);
+
+/** Retrieve the Length for this budget in number of years.
+ */
+gint gnc_budget_get_length_years(GncBudget* budget);
+
+
+
+/* Add the inflow category for this budget.
+ * This is a wrapper function to make it easier to add a category
+ * as a child of the inflow category. It's here cause I'm a lazy ass.
+ */
+void gnc_budget_add_inflow_category(GncBudget* budget, GncBudgetCategory* inflow);
+
+/* Remove the inflow category for this budget.
+ */
+void gnc_budget_remove_inflow_category(GncBudget* budget, GncBudgetCategory* category);
+
+/* Set the inflow category for this budget.
+ */
+void gnc_budget_set_inflow_category(GncBudget* budget, GncBudgetCategory* inflow);
+
+/** Retrieve the inflow category for this budget.
+ */
+GncBudgetCategory* gnc_budget_get_inflow_category(GncBudget* budget);
+
+
+
+
+/* Add the outflow category for this budget.
+ */
+void gnc_budget_add_outflow_category(GncBudget* budget, GncBudgetCategory* outflow);
+
+/* Remove the outflow category for this budget.
+ */
+void gnc_budget_remove_outflow_category(GncBudget* budget, GncBudgetCategory* inflow);
+
+/* Set the outflow category for this budget.
+ */
+void gnc_budget_set_outflow_category(GncBudget* budget, GncBudgetCategory* category);
+
+/** Retrieve the outflow category for this budget.
+ */
+GncBudgetCategory* gnc_budget_get_outflow_category(GncBudget* budget);
+
+
+
+/** Retrieve the book that this budget is associated with.*/
+QofBook* gnc_budget_get_book(GncBudget* budget);
+
+
+/** Generate the list of periods.
+ * This function will use the start date and budget length to generate a
+ * list of budget periods. The periods are represented by a list of start
+ * dates for each period.
+ * As well this function regenerates the list of values for each
+ * category.
+ * */
+void gnc_budget_generate_periods(GncBudget* budget);
+
+/** Get the number of periods.
+ */
+gint gnc_budget_get_num_periods(GncBudget* budget);
+
+/* Return the list of periods.
+ */
+GList* gnc_budget_get_period_list(GncBudget* budget);
+
+
+/** Retrieve the budget object associated with the given GUID from
+ * the given book.
+ */
+GncBudget* gnc_budget_lookup (const GUID *guid, QofBook *book);
+
+#endif // __BUDGET_H__
--- /dev/null
+++ src/engine/gnc-budget-period-value-p.h
@@ -0,0 +1,52 @@
+/********************************************************************\
+ * gnc-budget-period-value-p.h -- Private structure definition of the *
+ * budget period value objects. *
+ * Copyright (C) 16 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-period-value-p.h
+ * @breif Private structure definition of the budget period value
+ * structure.
+ * @author Created by Darin Willits 16 sep 2003
+ * @author Copyright (c) 16 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * A budget period value is the value associated with each budget period.
+ * Each category maintains a list of these values. If the budget period
+ * is changed this list needs to be regenerated.
+ * Note: We should probably add a reference here to the actual budget
+ * period we are referring to. Right now we just depend on their order
+ * in their respective lists.
+ */
+
+#ifndef __GNC_BUDGET_PERIOD_VALUE_P_H__
+#define __GNC_BUDGET_PERIOD_VALUE_P_H__
+
+#include "gnc-budget-period-value.h"
+
+struct gncp_budget_period_value{
+ gnc_numeric value;
+ gnc_numeric adjustment;
+};
+
+
+#endif // __GNC_BUDGET_PERIOD_VALUE_P_H__
--- /dev/null
+++ src/engine/gnc-budget-period-value.c
@@ -0,0 +1,85 @@
+/********************************************************************\
+ * gnc-budget-period-value.c -- Implmentation of the budget period *
+ * value structure. *
+ * Copyright (C) 16 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-period-value.c
+ * @breif Implementation of the budget-period-value structure.
+ * @author Created by Darin Willits 16 sep 2003
+ * @author Copyright (c) 16 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+// Includes
+#include "gnc-budget-period-value.h"
+#include "gnc-budget-period-value-p.h"
+#include "gnc-numeric.h"
+
+GncBudgetPeriodValue* gnc_budget_period_value_new(void)
+{
+ GncBudgetPeriodValue* periodValue;
+
+ periodValue = g_new0(GncBudgetPeriodValue, 1);
+
+ periodValue->value = gnc_numeric_zero();
+ periodValue->adjustment = gnc_numeric_zero();
+
+ return periodValue;
+}
+
+void gnc_budget_period_value_delete(GncBudgetPeriodValue* periodValue)
+{
+ g_free(periodValue);
+}
+
+
+
+void gnc_budget_period_value_set_value(GncBudgetPeriodValue* periodValue, gnc_numeric value)
+{
+ if(periodValue == NULL){
+ return;
+ }
+ periodValue->value = value;
+}
+
+void gnc_budget_period_value_set_value_double(GncBudgetPeriodValue* periodValue, double value)
+{
+ if(periodValue == NULL){
+ return;
+ }
+ periodValue->value = double_to_gnc_numeric(value, 1, GNC_RND_NEVER);
+}
+
+gnc_numeric gnc_budget_period_value_get_value(GncBudgetPeriodValue* periodValue)
+{
+ if(periodValue == NULL){
+ return gnc_numeric_zero();
+ }
+ return periodValue->value;
+}
+
+
+
+
+
--- /dev/null
+++ src/engine/gnc-budget-book.h
@@ -0,0 +1,60 @@
+/********************************************************************\
+ * gnc-budget-book.h -- Linkage between budgets and books. *
+ * Copyright (C) 04 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget-book.h
+ * @breif Linkage between budgets and books.
+ * @author Created by Darin Willits 04 sep 2003
+ * @author Copyright (c) 04 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ *
+ */
+
+#ifndef __GNC_BUDGETBOOK_H__
+#define __GNC_BUDGETBOOK_H__
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "qofbook.h"
+#include "gnc-budget.h"
+#include "gnc-engine.h"
+
+
+typedef struct xaccBudgetsDef GncBudgets;
+
+/** Retrieve the budget list structure for the given book. */
+GncBudgets* gnc_book_get_budget_list( QofBook *book );
+
+/** Retrieve the list of budgets for the given book.*/
+GList* gnc_book_get_budgets( QofBook *book );
+
+/** Add the given budget to the list of budgets for the given book. */
+void gnc_book_add_budget(QofBook* book, GncBudget* budget);
+
+/** Delete the given budget from the list of budgets for the given book. */
+void gnc_book_delete_budget(QofBook* book, GncBudget* budget);
+
+#endif // __BUDGETBOOK_H__
--- /dev/null
+++ src/engine/gnc-budget-p.h
@@ -0,0 +1,67 @@
+/********************************************************************\
+ * gnc-budget-p.h -- Private structure defintion for the budget object. *
+ * Copyright (C) 04 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget-p.h
+ * @breif Private structure definition for the budget object.
+ * @author Created by Darin Willits 04 sep 2003
+ * @author Copyright (c) 04 Darin Willits <darin at willits.ca>
+ *
+ *
+ */
+
+#ifndef __GNC_BUDGET_P_H__
+#define __GNC_BUDGET_P_H__
+
+#include <glib.h>
+#include "qofbook.h"
+#include "guid.h"
+#include "gnc-budget.h"
+#include "FreqSpec.h"
+#include "qofinstance-p.h"
+
+struct gncp_budget{
+
+ QofInstance inst;
+
+ char* name;
+ char* description;
+
+ FreqSpec* period_freq;
+ GDate start_date;
+ gint length;
+
+ GList* period_list;
+
+ GncBudgetCategory* inflow_category;
+ GncBudgetCategory* outflow_category;
+
+ /** FIXME: I think we actually have access to this value
+ * through the OofInstance member. We should probably
+ * use that one to reduce confusion and duplication. */
+ QofBook* book;
+};
+
+
+#endif // __GNC_BUDGET_P_H__
--- /dev/null
+++ src/engine/gnc-budget-period.h
@@ -0,0 +1,67 @@
+/********************************************************************\
+ * gnc-budget-period.h -- Public interface for the budget period *
+ * structure. *
+ * Copyright (C) 16 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-period.h
+ * @breif Public interface for the budget period structure.
+ * @author Created by Darin Willits 16 sep 2003
+ * @author Copyright (c) 16 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * A budget period is simply a begin and end date right now although
+ * it may eventually have to encapsulate more information. Each budget
+ * category maintains a list of values each of which refers to a given
+ * budget period object.
+ */
+
+#ifndef __GNC_BUDGET_PERIOD_H__
+#define __GNC_BUDGET_PERIOD_H__
+
+#include <glib.h>
+
+typedef struct gncp_budget_period GncBudgetPeriod;
+
+/* Create a new budget period object.
+ */
+GncBudgetPeriod* gnc_budget_period_new(void);
+
+/** Set the start date for the period.
+ */
+void gnc_budget_period_set_start_date(GncBudgetPeriod* period, GDate* startDate);
+
+/* Get the start date for the period.
+ */
+GDate* gnc_budget_period_get_start_date(GncBudgetPeriod* period);
+
+
+/** Set the end date for the period.
+ */
+void gnc_budget_period_set_end_date(GncBudgetPeriod* period, GDate* endDate);
+
+/* Get the end date for the period.
+ */
+GDate* gnc_budget_period_get_end_date(GncBudgetPeriod* period);
+
+
+#endif // __BUDGET_PERIOD_H__
--- /dev/null
+++ src/engine/gnc-budget-cat-p.h
@@ -0,0 +1,67 @@
+/********************************************************************\
+ * gnc-budget-cat-p.h -- Definition of the budget category structure. *
+ * Copyright (C) 05 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup Engine
+ * @{ */
+/** @file gnc-budget-cat-p.h
+ * @breif Definition of the private budget category structure.
+ * @author Created by Darin Willits 05 sep 2003
+ * @author Copyright (c) 05 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+#ifndef __GNC_BUDGET_CAT_P_H__
+#define __GNC_BUDGET_CAT_P_H__
+
+#include "gnc-numeric.h"
+#include "gnc-budget-cat.h"
+#include "gnc-budget.h"
+#include "Account.h"
+#include "FreqSpec.h"
+#include "qofbook.h"
+#include "gnc-engine.h"
+#include "qofinstance-p.h"
+
+struct gncp_budget_category{
+
+ QofInstance inst;
+
+ char* name;
+ char* description;
+ GncBudget* budget;
+
+ gnc_numeric value;
+ GncBudgetCategoryType type;
+ gnc_commodity* commodity;
+ GList* period_values;
+
+ GncBudgetCategory* parent;
+ GncBudgetCategoryList* children;
+
+ GList* accountList;
+
+ FreqSpec* freq;
+};
+
+
+#endif // __BUDGET_CAT_P_H__
--- /dev/null
+++ src/engine/gnc-budget-book.c
@@ -0,0 +1,200 @@
+/********************************************************************\
+ * gnc-budget-book.c -- Implementation of the budget/book linkage. *
+ * Copyright (C) 04 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @file gnc-budget-book.c
+ * @breif Implementation of the book/budget linkage.
+ * @author Created by Darin Willits 04 sep 2003
+ * @author Copyright (c) 2003 Darin Willits <darin at willits.ca>
+ *
+ *
+ */
+
+// Includes
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "gnc-engine.h"
+#include "gnc-trace.h"
+#include "gnc-engine-util.h"
+#include "gnc-event-p.h"
+
+#include "gnc-budget-book-p.h"
+#include "gnc-budget-p.h"
+
+#include "qofbook.h"
+#include "qofbook-p.h"
+#include "qofobject.h"
+
+#define GNC_BUDGETS "gnc_budgets"
+
+/* =========================================================== */
+
+/** Retrieve the budget list structure for the given book. */
+GncBudgets* gnc_book_get_budget_list( QofBook *book )
+{
+ if ( book == NULL ){
+ return NULL;
+ }
+ return qof_book_get_data (book, GNC_BUDGETS);
+}
+
+/** Retrieve the list of budgets for the given book.*/
+GList* gnc_book_get_budgets( QofBook *book )
+{
+ GncBudgets *list;
+ if ( book == NULL ){
+ return NULL;
+ }
+
+ list = qof_book_get_data (book, GNC_BUDGETS);
+ if (list){
+ return list->budget_list;
+ }
+ return NULL;
+}
+
+/** Associate the given budget list to the book.*/
+void gnc_book_set_budgets( QofBook *book, GList *newList )
+{
+ GncBudgets *old_list, *new_list;
+ if ( book == NULL ){
+ return;
+ }
+
+ old_list = qof_book_get_data (book,GNC_BUDGETS);
+ if (old_list && old_list->budget_list == newList){
+ /* Assume the worst, that any 'set' means the data has
+ * changed, and needs to be saved. */
+ old_list->budget_notsaved = TRUE;
+ return;
+ }
+
+ new_list = g_new (GncBudgets, 1);
+ new_list->book = book;
+ new_list->budget_list = newList;
+ new_list->budget_notsaved = TRUE;
+
+ if (NULL == newList){
+ new_list->budget_notsaved = FALSE;
+ }
+
+ qof_book_set_data (book, GNC_BUDGETS, new_list);
+
+ g_free (old_list);
+}
+
+/** Add the given budget to the list of budgets for the given book. */
+void gnc_book_add_budget(QofBook* book, GncBudget* budget)
+{
+ GList* budgetList;
+
+ if((budget == NULL) || (book == NULL)){
+ return;
+ }
+
+ budgetList = gnc_book_get_budgets( book );
+ budgetList = g_list_append( budgetList, budget);
+ gnc_book_set_budgets( book, budgetList );
+
+ gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_ADD);
+}
+
+/** Delete the given budget from the list of budgets for the given book. */
+void gnc_book_delete_budget(QofBook* book, GncBudget* budget)
+{
+ GList* budgetList;
+
+ if((budget == NULL) || (book == NULL)){
+ return;
+ }
+
+ budgetList = gnc_book_get_budgets( book );
+ budgetList = g_list_remove( budgetList, budget);
+ gnc_book_set_budgets( book, budgetList );
+
+ gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_REMOVE );
+}
+
+/* ============================================================ */
+
+
+
+/** ===========================================================
+ * gncObject registration functions.
+ */
+
+/* This function is called when the book is first initialized.
+ * Therefore we se the list of budgets to be NULL.
+ */
+static void budget_book_begin (QofBook *book)
+{
+ gnc_book_set_budgets (book, NULL);
+}
+
+/* This function is called when the book is being cleaned up.
+ * Therefore we se the list of budgets to be NULL.
+ */
+static void budget_book_end (QofBook *book)
+{
+ gnc_book_set_budgets(book, NULL);
+}
+
+/* ============================================================ */
+/* dirty flag stuff */
+
+static gboolean book_budget_notsaved(QofCollection *col)
+{
+ /** TODO: what is this for again??*/
+ return FALSE;
+}
+
+static void budget_mark_clean(QofCollection *col)
+{
+ /** TODO: and this one... hummm. */
+}
+
+/* Define the QofObject. */
+static QofObject budget_object_def =
+{
+ interface_version: QOF_OBJECT_VERSION,
+ e_type: GNC_ID_BUDGET,
+ type_label: "BUDGET",
+ book_begin: budget_book_begin,
+ book_end: budget_book_end,
+ is_dirty: book_budget_notsaved,
+ mark_clean: budget_mark_clean,
+ foreach: NULL,
+ printable: NULL,
+};
+
+/* Register ourselves with the engine. */
+gboolean gnc_budget_register (void)
+{
+ return qof_object_register (&budget_object_def);
+}
+
+/* ============================================================== */
Index: gnc-engine.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-engine.c,v
retrieving revision 1.17.4.2
retrieving revision 1.17.4.3
diff -Lsrc/engine/gnc-engine.c -Lsrc/engine/gnc-engine.c -u -r1.17.4.2 -r1.17.4.3
--- src/engine/gnc-engine.c
+++ src/engine/gnc-engine.c
@@ -31,6 +31,7 @@
#include "AccountP.h"
#include "GroupP.h"
#include "SX-book-p.h"
+#include "gnc-budget-book-p.h"
#include "TransactionP.h"
#include "gnc-commodity.h"
#include "gnc-lot-p.h"
@@ -95,6 +96,7 @@
xaccAccountRegister ();
xaccGroupRegister ();
gnc_sxtt_register ();
+ gnc_budget_register();
gnc_pricedb_register ();
gnc_commodity_table_register();
gnc_lot_register ();
--- /dev/null
+++ src/engine/gnc-budget.c
@@ -0,0 +1,513 @@
+/********************************************************************\
+ * gnc-budget.c -- Implementation of the top level Budgeting API's. *
+ * Copyright (C) 04 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @file gnc-budget.c
+ * @breif Implementation of the top level budgeting API's.
+ * @author Created by Darin Willits 04 sep 2003
+ * @author Copyright (c) 2003 Darin Willits <darin at willits.ca>
+ *
+ *
+ */
+
+// Includes
+#include "config.h"
+#include <stdio.h>
+
+#include "gnc-budget-p.h"
+#include "qofbook.h"
+#include "qofbook-p.h"
+#include "qofid-p.h"
+#include "gnc-engine.h"
+#include "gnc-engine-util.h"
+#include "gnc-event-p.h"
+#include "Group.h"
+#include "Account.h"
+#include "gnc-budget-period.h"
+
+
+static void budget_fill_categories(GncBudget* budget);
+
+GncBudget* gnc_budget_new(QofBook *book)
+{
+ GncBudget* budget;
+ GDate date;
+ GString* freqStr;
+
+ g_return_val_if_fail(book, NULL);
+
+ budget = g_new0(GncBudget, 1);
+
+
+ qof_instance_init (&budget->inst, GNC_ID_BUDGET, book);
+ //budget->entity_table = qof_book_get_entity_table (book);
+ //qof_entity_guid_new (budget->entity_table, &budget->guid);
+ //qof_entity_store( budget->entity_table, budget,
+ // &budget->guid, GNC_ID_BUDGET );
+
+ budget->book = book;
+
+ /* Create the default period frequency.*/
+ budget->period_freq = xaccFreqSpecMalloc(book);
+
+ g_date_clear(&date, 1);
+ g_date_set_time(&date, time(NULL));
+ xaccFreqSpecSetMonthly(budget->period_freq, &date, 1);
+ xaccFreqSpecSetUIType(budget->period_freq, UIFREQ_MONTHLY);
+
+ freqStr = g_string_sized_new(16);
+ xaccFreqSpecGetFreqStr(budget->period_freq, freqStr);
+ //printf("Category Freq: %s\n", freqStr->str);
+
+
+
+ /* fill the categories based on the current account hierarchy.
+ * FIXME: This should probably not be here but rather be a separate
+ * operation with a public interface. For now it is convienent.*/
+ budget_fill_categories(budget);
+
+
+ gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_CREATE );
+
+ return budget;
+}
+
+void gnc_budget_delete(GncBudget* budget)
+{
+ if(budget == NULL){
+ return;
+ }
+
+ /* We first send the message that this object is about to be
+ * destroyed so that any GUI elements can remove it before it is
+ * actually gone.
+ */
+ gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_DESTROY);
+
+ //qof_entity_remove(budget->entity_table, &budget->guid);
+
+ if(budget->name){
+ g_free(budget->name);
+ }
+
+ if(budget->description){
+ g_free(budget->description);
+ }
+
+ qof_instance_release (&budget->inst);
+ g_free(budget);
+}
+
+void gnc_budget_set_name(GncBudget* budget, const gchar* name)
+{
+ g_return_if_fail( name != NULL );
+ if ( budget->name != NULL ) {
+ g_free( budget->name );
+ budget->name = NULL;
+ }
+ budget->name = g_strdup( name );
+}
+
+gchar* gnc_budget_get_name(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return budget->name;
+}
+
+void gnc_budget_set_description(GncBudget* budget, const gchar* description)
+{
+ g_return_if_fail( description != NULL );
+ if ( budget->description != NULL ) {
+ g_free( budget->description);
+ budget->description = NULL;
+ }
+ budget->description = g_strdup(description);
+}
+
+gchar* gnc_budget_get_description(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return budget->description;
+}
+
+
+
+
+void gnc_budget_set_period_frequency(GncBudget* budget, FreqSpec* period)
+{
+ if(budget == NULL){
+ return;
+ }
+
+ if((budget->period_freq == period) || (period == NULL)){
+ return;
+ }
+
+ if(budget->period_freq != NULL){
+ /* Delete the existing object before setting the new one. */
+ xaccFreqSpecFree(budget->period_freq);
+ }
+
+ budget->period_freq = period;
+}
+
+FreqSpec* gnc_budget_get_period_frequency(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+
+ return budget->period_freq;
+}
+
+
+
+
+void gnc_budget_set_start_date(GncBudget* budget, GDate* date)
+{
+ if(budget == NULL){
+ return;
+ }
+ budget->start_date = *date;
+}
+
+GDate* gnc_budget_get_start_date(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return &budget->start_date;
+}
+
+
+
+
+
+
+void gnc_budget_set_length_months(GncBudget* budget, gint months)
+{
+ if(budget == NULL){
+ return;
+ }
+
+ budget->length = months;
+}
+
+void gnc_budget_set_length_years(GncBudget* budget, gint years)
+{
+ if(budget == NULL){
+ return;
+ }
+
+ budget->length = years * 12;
+}
+
+gint gnc_budget_get_length_months(GncBudget* budget)
+{
+ if(budget == NULL){
+ return 0;
+ }
+
+ return budget->length;
+}
+
+gint gnc_budget_get_length_years(GncBudget* budget)
+{
+ if(budget == NULL){
+ return 0;
+ }
+
+ return budget->length / 12;
+}
+
+
+
+
+
+
+void gnc_budget_add_inflow_category(GncBudget* budget, GncBudgetCategory* category)
+{
+ if(budget == NULL){
+ return;
+ }
+ gnc_budget_category_add_child(budget->inflow_category, category);
+}
+
+void gnc_budget_remove_inflow_category(GncBudget* budget, GncBudgetCategory* category)
+{
+ if(budget == NULL){
+ return;
+ }
+ gnc_budget_category_remove_child(budget->inflow_category, category);
+}
+
+void gnc_budget_set_inflow_category(GncBudget* budget, GncBudgetCategory* inflow)
+{
+ if(budget == NULL){
+ return;
+ }
+ budget->inflow_category = inflow;
+}
+
+GncBudgetCategory* gnc_budget_get_inflow_category(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return budget->inflow_category;
+}
+
+void gnc_budget_set_outflow_category(GncBudget* budget, GncBudgetCategory* outflow)
+{
+ if(budget == NULL){
+ return;
+ }
+ budget->outflow_category = outflow;
+}
+
+GncBudgetCategory* gnc_budget_get_outflow_category(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return budget->outflow_category;
+}
+
+void gnc_budget_add_outflow_category(GncBudget* budget, GncBudgetCategory* category)
+{
+ if(budget == NULL){
+ return;
+ }
+ gnc_budget_category_add_child(budget->outflow_category, category);
+}
+
+void gnc_budget_remove_outflow_category(GncBudget* budget, GncBudgetCategory* category)
+{
+ if(budget == NULL){
+ return;
+ }
+ gnc_budget_category_remove_child(budget->inflow_category, category);
+}
+
+QofBook* gnc_budget_get_book(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return budget->book;
+}
+
+static void free_budget_period(gpointer data, gpointer user_data)
+{
+ GncBudgetPeriod* period = data;
+ g_free(period);
+}
+
+void gnc_budget_generate_periods(GncBudget* budget)
+{
+ GDate currentPeriod, outDate;
+ GDate endDate;
+ GDate periodStartDate;
+ GncBudgetPeriod* budgetPeriod;
+
+ if(budget == NULL){
+ return;
+ }
+
+ /* TODO: Add in some error checking such that we don't regenerate
+ * the periods if they are the same as before. We may still need
+ * to recalculate the values however.
+ */
+ if(budget->period_list != NULL){
+ g_list_foreach(budget->period_list, free_budget_period, NULL);
+ g_list_free(budget->period_list);
+ budget->period_list = NULL;
+ }
+
+ /* Add the starting period. Every budget should have at least
+ * one period. */
+ g_date_set_dmy(&periodStartDate, g_date_get_day(&budget->start_date),
+ g_date_get_month(&budget->start_date),
+ g_date_get_year(&budget->start_date));
+ budgetPeriod = gnc_budget_period_new();
+ gnc_budget_period_set_start_date(budgetPeriod, &periodStartDate);
+ budget->period_list = g_list_append(budget->period_list, budgetPeriod);
+
+
+ /* Setup the end Date */
+ g_date_set_dmy(&endDate, g_date_get_day(&budget->start_date),
+ g_date_get_month(&budget->start_date),
+ g_date_get_year(&budget->start_date));
+ g_date_add_months(&endDate, budget->length);
+
+
+ g_date_set_dmy(¤tPeriod, g_date_get_day(&budget->start_date),
+ g_date_get_month(&budget->start_date),
+ g_date_get_year(&budget->start_date));
+ do{
+ xaccFreqSpecGetNextInstance(budget->period_freq, ¤tPeriod, &outDate);
+ if(g_date_valid(&outDate) == FALSE){
+ break;
+ }
+
+ if(g_date_compare(&outDate, &endDate) >= 0){
+ break;
+ }
+ else{
+ /* Set the end date of the previous period. */
+ gnc_budget_period_set_end_date(budgetPeriod, &outDate);
+
+ /* Create the new period. */
+ budgetPeriod = gnc_budget_period_new();
+ gnc_budget_period_set_start_date(budgetPeriod, &outDate);
+
+ budget->period_list = g_list_append(budget->period_list, budgetPeriod);
+ g_date_set_dmy(¤tPeriod, g_date_get_day(&outDate),
+ g_date_get_month(&outDate),
+ g_date_get_year(&outDate));
+ }
+ }while(1);
+
+ gnc_budget_period_set_end_date(budgetPeriod, &endDate);
+
+ /* Now we should generate the list of values for each category.*/
+ gnc_budget_category_generate_values(budget->inflow_category);
+ gnc_budget_category_generate_values(budget->outflow_category);
+}
+
+
+gint gnc_budget_get_num_periods(GncBudget* budget)
+{
+ if(budget == NULL){
+ return 0;
+ }
+ return g_list_length(budget->period_list);
+}
+
+GList* gnc_budget_get_period_list(GncBudget* budget)
+{
+ if(budget == NULL){
+ return NULL;
+ }
+ return budget->period_list;
+}
+
+
+
+/* ==================================================================== */
+/* Private member functions.
+ *
+ * ==================================================================== */
+
+static void add_category_from_account(gpointer data, gpointer userdata)
+{
+ GncBudget* budget;
+ Account* account;
+ AccountList* children;
+ GncBudgetCategory* category = NULL;
+ gchar* name;
+ AccountGroup* group;
+ int numChildren;
+ GNCAccountType accountType;
+
+ account = data;
+ budget = userdata;
+
+ if(account == NULL){
+ return;
+ }
+
+ //printf("Adding Category from account\n");
+ //printf("Account: %s\n", xaccAccountGetName(account));
+ group = xaccAccountGetChildren(account);
+ children = xaccGroupGetAccountList(group);
+ numChildren = xaccGroupGetNumAccounts(group);
+ //printf("NumChildren: %d\n", numChildren);
+
+ if(numChildren == 0){
+ name = xaccAccountGetFullName(account, ':');
+ accountType = xaccAccountGetType(account);
+
+ category = gnc_budget_category_new(budget->book, budget);
+ gnc_budget_category_set_name(category, name);
+ gnc_budget_category_add_account(category, account);
+
+ if(accountType == INCOME){
+ //printf("Inflow Category: %s\n", gnc_budget_category_get_name(category));
+ gnc_budget_category_set_type(category, BUDGET_CATEGORY_INFLOW);
+ gnc_budget_category_add_child(budget->inflow_category, category);
+ }
+ else{
+ //printf("Outflow Category: %s\n", gnc_budget_category_get_name(category));
+ gnc_budget_category_set_type(category, BUDGET_CATEGORY_OUTFLOW);
+ gnc_budget_category_add_child(budget->outflow_category, category);
+ }
+
+ g_free(name);
+ }
+
+}
+
+static void budget_fill_categories(GncBudget* budget)
+{
+ AccountList* children;
+ if(budget == NULL){
+ return;
+ }
+
+ //printf("Creating top level budget categories.\n");
+
+ budget->inflow_category = gnc_budget_category_new(budget->book, budget);
+ gnc_budget_category_set_name(budget->inflow_category, "Inflow");
+
+
+ budget->outflow_category = gnc_budget_category_new(budget->book, budget);
+ gnc_budget_category_set_name(budget->outflow_category, "Outflow");
+
+
+ //printf("Filing budget Categories.\n");
+ //children = xaccGroupGetAccountList(gnc_book_get_group(budget->book));
+ children = xaccGroupGetSubAccounts(gnc_book_get_group(budget->book));
+ g_list_foreach(children, add_category_from_account, budget);
+
+ //printf("Number of inflow categories: %d\n",
+ //gnc_budget_category_get_num_children(budget->inflow_category));
+ //printf("Number of outflow categories: %d\n",
+ //gnc_budget_category_get_num_children(budget->outflow_category));
+}
+
+GncBudget* gnc_budget_lookup (const GUID *guid, QofBook *book)
+{
+ QofCollection *col;
+
+ if (!guid || !book){
+ return NULL;
+ }
+
+ col = qof_book_get_collection (book, GNC_ID_BUDGET);
+ return (GncBudget*)qof_collection_lookup_entity (col, guid);
+}
+
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Makefile.am,v
retrieving revision 1.94.2.6
retrieving revision 1.94.2.7
diff -Lsrc/engine/Makefile.am -Lsrc/engine/Makefile.am -u -r1.94.2.6 -r1.94.2.7
--- src/engine/Makefile.am
+++ src/engine/Makefile.am
@@ -25,6 +25,11 @@
Transaction.c \
cap-gains.c \
gnc-associate-account.c \
+ gnc-budget-book.c \
+ gnc-budget-cat.c \
+ gnc-budget-period-value.c \
+ gnc-budget-period.c \
+ gnc-budget.c \
gnc-commodity.c \
gnc-date.c \
gnc-engine-util.c \
@@ -79,6 +84,11 @@
glib-helpers.h \
gnc-associate-account.h \
gnc-book.h \
+ gnc-budget-book.h \
+ gnc-budget-cat.h \
+ gnc-budget-period-value.h \
+ gnc-budget-period.h \
+ gnc-budget.h \
gnc-commodity.h \
gnc-date.h \
gnc-engine-util.h \
@@ -121,6 +131,11 @@
SX-book.h \
SX-ttinfo.h \
TransactionP.h \
+ gnc-budget-book-p.h \
+ gnc-budget-cat-p.h \
+ gnc-budget-period-value-p.h \
+ gnc-budget-period-p.h \
+ gnc-budget-p.h \
gnc-event-p.h \
gnc-lot.h \
gnc-lot-p.h \
--- /dev/null
+++ src/engine/gnc-budget-period-value.h
@@ -0,0 +1,65 @@
+/********************************************************************\
+ * gnc-budget-period-value.h -- Public interface for the budget period *
+ * value structure. *
+ * Copyright (C) 16 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-period-value.h
+ * @breif Public interface for the budget period value structure.
+ * @author Created by Darin Willits 16 sep 2003
+ * @author Copyright (c) 16 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * A budget period value is the value associated with each budget period.
+ * Each category maintains a list of these values. If the budget period
+ * is changed this list needs to be regenerated.
+ * Note: We should probably add a reference here to the actual budget
+ * period we are referring to. Right now we just depend on their order
+ * in their respective lists.
+ */
+
+#ifndef __GNC_BUDGET_PERIOD_VALUE_H__
+#define __GNC_BUDGET_PERIOD_VALUE_H__
+
+#include "gnc-numeric.h"
+
+typedef struct gncp_budget_period_value GncBudgetPeriodValue;
+
+/* Create a new GncBudgetPeriodValue object.
+ */
+GncBudgetPeriodValue* gnc_budget_period_value_new(void);
+
+/** Delete a GncBudgetPeriodValue object.
+ */
+void gnc_budget_period_value_delete(GncBudgetPeriodValue* periodValue);
+
+/** Set the value
+ */
+void gnc_budget_period_value_set_value(GncBudgetPeriodValue* periodValue, gnc_numeric value);
+void gnc_budget_period_value_set_value_double(GncBudgetPeriodValue* periodValue, double value);
+
+/* Get the value
+ */
+gnc_numeric gnc_budget_period_value_get_value(GncBudgetPeriodValue* periodValue);
+
+
+#endif // __BUDGET_PERIOD_VALUE_H__
--- /dev/null
+++ src/gnome/dialog-budget-list.h
@@ -0,0 +1,43 @@
+/********************************************************************\
+ * dialog-budget-list.h -- Dialog to show the list of available *
+ * budgets to the user. *
+ * Copyright (C) 08 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gui
+ * @{ */
+/** @file dialog-budget-list.h
+ * @breif Dialog to show the list of available budgets to the user.
+ * @author Created by Darin Willits 08 sep 2003
+ * @author Copyright (c) 08 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+#ifndef __DIALOG_BUDGET_LIST_H__
+#define __DIALOG_BUDGET_LIST_H__
+
+#include <glib.h>
+
+/** Launch the budget list dialog.*/
+void gnc_budget_list_dialog_create(void);
+
+void add_budget_to_model( gpointer data, gpointer user_data );
+#endif // __DIALOG_BUDGET_LIST_H__
--- /dev/null
+++ src/gnome/gnc-budget-gui.h
@@ -0,0 +1,38 @@
+/********************************************************************\
+ * gnc-budget-gui.h -- budget gui defines. *
+ * Copyright (C) 08 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gui
+ * @{ */
+/** @file gnc-budget-gui.h
+ * @breif Common defines used by the budgeting gui components.
+ * @author Created by Darin Willits 08 sep 2003
+ * @author Copyright (c) 08 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+#ifndef __GNC_BUDGET_GUI_H__
+#define __GNC_BUDGET_GUI_H__
+
+#define GNC_BUDGET_GUI_FILE "budget.glade"
+
+#endif // __GNC_BUDGET_H__
--- /dev/null
+++ src/gnome/dialog-budget-category.h
@@ -0,0 +1,47 @@
+/********************************************************************\
+ * dialog-budget-category.h -- Defintion of the public interface *
+ * for the budget category dialog. *
+ * Copyright (C) 10 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome
+ * @{ */
+/** @file dialog-budget-category.h
+ * @breif Definition of the public interface of the budget category dialog.
+ * @author Created by Darin Willits 10 sep 2003
+ * @author Copyright (c) 10 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+#ifndef __DIALOG_BUDGET_CATEGORY_H__
+#define __DIALOG_BUDGET_CATEGORY_H__
+
+#include "gnc-budget-cat.h"
+
+/* Launch the modify category dialog.
+ */
+void gnc_budget_category_dialog_create(GncBudget* budget, GncBudgetCategory* category);
+
+/* Launch the modify category dialog without an existing category.
+ * A new one will be created and inserted into the buget on success.
+ */
+void gnc_budget_category_new_dialog_create(GncBudget* budget);
+#endif // __DIALOG_BUDGET_CATEGORY_H__
--- /dev/null
+++ src/gnome/dialog-budget-category.c
@@ -0,0 +1,324 @@
+/********************************************************************\
+ * dialog-budget-category.c -- Implementation of the budget *
+ * category dialog. *
+ * Copyright (C) 10 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome
+ * @{ */
+/** @file dialog-budget-category.c
+ * @breif Implementation of the budget category dialog.
+ * @author Created by Darin Willits 10 sep 2003
+ * @author Copyright (c) 10 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+// Includes
+#include "config.h"
+
+#include <gnome.h>
+#include "dialog-utils.h"
+#include "gnc-ui-util.h"
+#include "dialog-budget-category.h"
+#include "FreqSpec.h"
+#include "gnc-tree-model-account.h"
+#include "gnc-tree-view-account.h"
+#include "gnc-general-select.h"
+#include "gnc-frequency.h"
+#include "gnc-budget-gui.h"
+#include "gnc-commodity-edit.h"
+#include "dialog-commodity.h"
+#include "gnc-ui-util.h"
+#include "Group.h"
+
+
+/* Budget Category Dialog structure definition. */
+typedef struct{
+ GtkWidget* wnd;
+ GladeXML* xml;
+
+ GtkWidget* commodityEdit;
+ dialog_commodity_mode commodityMode;
+ GtkTreeView* relatedView;
+ GNCFrequency* freqWnd;
+ GtkEntry* name_entry;
+ GtkEntry* description_entry;
+ GtkSpinButton* value_button;
+ GtkRadioButton* inflow_button;
+ GtkRadioButton* outflow_button;
+
+ gboolean new_category;
+
+ GncBudgetCategory* category;
+ GncBudget* budget;
+
+} BudgetCategoryDlg;
+
+/* Fill in the Budget Category from the values displayed in the UI. */
+static void category_from_ui(BudgetCategoryDlg* dlg)
+{
+ FreqSpec* freqSpec;
+ GDate startDate;
+ const gchar* name, *description;
+ gnc_numeric value;
+ gnc_commodity* commodity;
+ gint type;
+ AccountList* selectedAccounts;
+
+ /* Set the name and description. */
+ name = gtk_entry_get_text(dlg->name_entry);
+ description = gtk_entry_get_text(dlg->description_entry);
+
+ gnc_budget_category_set_name(dlg->category, name);
+ gnc_budget_category_set_description(dlg->category, description);
+
+ /* Set the category's value. */
+ value = double_to_gnc_numeric(
+ gtk_spin_button_get_value_as_float(dlg->value_button),
+ 1, GNC_RND_NEVER );
+ gnc_budget_category_set_value(dlg->category, value);
+
+ /* Set the frequency. */
+ freqSpec = gnc_budget_category_get_frequency(dlg->category);
+ if(freqSpec == NULL){
+ freqSpec = xaccFreqSpecMalloc(gnc_budget_get_book(dlg->budget));
+ }
+ gnc_frequency_save_state( dlg->freqWnd, freqSpec, &startDate);
+ gnc_budget_category_set_frequency(dlg->category, freqSpec);
+
+
+ /* Set the commodity. */
+ commodity = (gnc_commodity *)
+ gnc_general_select_get_selected (GNC_GENERAL_SELECT (dlg->commodityEdit));
+ gnc_budget_category_set_commodity(dlg->category, commodity);
+
+ /* Set the category's type. */
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dlg->inflow_button))){
+ type = BUDGET_CATEGORY_INFLOW;
+ }
+ else{
+ type = BUDGET_CATEGORY_OUTFLOW;
+ }
+
+ /* If this category has just been created we have to add it to either
+ * the inflow or outflow categories. We also have to check if the type
+ * has been changed and move it. */
+ if(dlg->new_category == TRUE){
+ if(type == BUDGET_CATEGORY_INFLOW){
+ gnc_budget_add_inflow_category(dlg->budget, dlg->category);
+ }
+ else{
+ gnc_budget_add_outflow_category(dlg->budget, dlg->category);
+ }
+ gnc_budget_category_set_type(dlg->category, type);
+ }
+ else if(type != gnc_budget_category_get_type(dlg->category)){
+ if(type == BUDGET_CATEGORY_INFLOW){
+ gnc_budget_remove_outflow_category(dlg->budget, dlg->category);
+ gnc_budget_add_inflow_category(dlg->budget, dlg->category);
+ }
+ else{
+ gnc_budget_remove_inflow_category(dlg->budget, dlg->category);
+ gnc_budget_add_outflow_category(dlg->budget, dlg->category);
+ }
+ gnc_budget_category_set_type(dlg->category, type);
+ }
+
+ /* Set the related accounts. */
+ selectedAccounts =
+ (AccountList*)gnc_tree_view_account_get_selected_accounts(
+ GNC_TREE_VIEW_ACCOUNT(dlg->relatedView));
+ gnc_budget_category_set_related_accounts(dlg->category, selectedAccounts);
+}
+
+/* Fill in the User Interface from the category object. */
+static void category_to_ui(BudgetCategoryDlg* dlg)
+{
+ double value;
+ gnc_commodity* commodity;
+ GncBudgetCategoryType type;
+ GList* relatedAccounts;
+
+ /* Set the name and description. */
+ gtk_entry_set_text(dlg->name_entry,
+ gnc_budget_category_get_name(dlg->category));
+ gtk_entry_set_text(dlg->description_entry,
+ gnc_budget_category_get_description(dlg->category));
+
+ /* Set the value. */
+ value = gnc_numeric_to_double(
+ gnc_budget_category_get_value(dlg->category));
+ gtk_spin_button_set_value(dlg->value_button, value);
+
+ /* Set the commodity. */
+ commodity = gnc_budget_category_get_commodity(dlg->category);
+ gnc_general_select_set_selected (GNC_GENERAL_SELECT (dlg->commodityEdit),
+ commodity);
+
+ /* Set the categories type. */
+ type = gnc_budget_category_get_type(dlg->category);
+ if(type == BUDGET_CATEGORY_INFLOW){
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dlg->inflow_button), TRUE);
+ }
+ else{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dlg->outflow_button), TRUE);
+ }
+
+ /* Set the tree view to show the related accounts. */
+ relatedAccounts = (GList*)gnc_budget_category_get_related_accounts(dlg->category);
+ printf("Related Accouts: %d\n", g_list_length(relatedAccounts));
+ gnc_tree_view_account_set_selected_accounts(
+ GNC_TREE_VIEW_ACCOUNT(dlg->relatedView), relatedAccounts, TRUE);
+}
+
+
+/* Destroy the dialog and cleanup. */
+static void category_dialog_destroy(BudgetCategoryDlg* dlg)
+{
+ gtk_widget_destroy(dlg->wnd);
+ g_free(dlg);
+}
+
+/* Ok Button event handler. */
+static void ok_clicked(GtkWidget* object, gpointer* data)
+{
+ BudgetCategoryDlg* dlg = (BudgetCategoryDlg*)data;
+ category_from_ui(dlg);
+ category_dialog_destroy(dlg);
+}
+
+/* Cancel button event handler. */
+static void cancel_clicked(GtkWidget* object, gpointer data)
+{
+ category_dialog_destroy((BudgetCategoryDlg*)data);
+}
+
+/* Create the Budget Category Dialog. */
+static void category_dialog_create(BudgetCategoryDlg* dlg)
+{
+ GladeXML *xml;
+ GtkWidget *box;
+ GtkWidget* ok_button;
+ GtkWidget* cancel_button;
+ GtkTreeModel *model;
+ GtkTreeSelection* selection;
+
+ /* Load the glade xml file and create the widget. */
+ xml = gnc_glade_xml_new (GNC_BUDGET_GUI_FILE, "Modify Category Dialog");
+ dlg->wnd = glade_xml_get_widget(xml, "Modify Category Dialog");
+ dlg->xml = xml;
+
+ /* Create the various component widgets. */
+ dlg->name_entry =
+ GTK_ENTRY(glade_xml_get_widget(dlg->xml, "name_entry"));
+ dlg->description_entry =
+ GTK_ENTRY(glade_xml_get_widget(dlg->xml, "description_entry"));
+ dlg->value_button =
+ GTK_SPIN_BUTTON(glade_xml_get_widget(dlg->xml, "value_button"));
+ dlg->inflow_button =
+ GTK_RADIO_BUTTON(glade_xml_get_widget(dlg->xml, "inflow_button"));
+ dlg->outflow_button =
+ GTK_RADIO_BUTTON(glade_xml_get_widget(dlg->xml, "outflow_button"));
+
+
+ /* Set up the commodity widget. */
+ dlg->commodityMode = DIAG_COMM_CURRENCY;
+ box = glade_xml_get_widget (dlg->xml, "commodity_box");
+ dlg->commodityEdit = gnc_general_select_new (GNC_GENERAL_SELECT_TYPE_SELECT,
+ gnc_commodity_edit_get_string,
+ gnc_commodity_edit_new_select,
+ &dlg->commodityMode);
+ gtk_box_pack_start(GTK_BOX(box), dlg->commodityEdit, TRUE, TRUE, 0);
+
+
+ /* Set up the related accounts view. */
+ model = gnc_tree_model_account_new (gnc_book_get_group (gnc_get_current_book ()));
+
+ box = glade_xml_get_widget (xml, "related_accounts_scroll");
+ dlg->relatedView = gnc_tree_view_account_new(FALSE);
+ gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(dlg->relatedView));
+ gtk_tree_view_set_model (dlg->relatedView, model);
+
+ gnc_tree_view_account_configure_columns(GNC_TREE_VIEW_ACCOUNT(dlg->relatedView), NULL);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dlg->relatedView));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+
+
+ /* Set up the frequency view. */
+ dlg->freqWnd = GNC_FREQUENCY(
+ gnc_frequency_new(gnc_budget_category_get_frequency(dlg->category), NULL));
+
+ /* Reparent to the correct location */
+ box = glade_xml_get_widget (xml, "frequency_box");
+ gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (dlg->freqWnd),TRUE, TRUE, 0);
+
+ /* Connect signals. */
+ ok_button = glade_xml_get_widget( dlg->xml, "ok_button" );
+ g_signal_connect( ok_button, "clicked",
+ G_CALLBACK(ok_clicked), dlg);
+ cancel_button = glade_xml_get_widget( dlg->xml, "cancel_button" );
+ g_signal_connect( cancel_button, "clicked",
+ G_CALLBACK(cancel_clicked), dlg);
+
+
+ /* Fill in the ui from the category. */
+ category_to_ui(dlg);
+}
+
+/* Public interface method to create the budget category dialog.
+ * This method is used to create a dialog to edit an existing category. */
+void gnc_budget_category_dialog_create(GncBudget* budget, GncBudgetCategory* category)
+{
+ BudgetCategoryDlg* dlg;
+
+ dlg = g_new0(BudgetCategoryDlg, 1);
+
+ dlg->category = category;
+ dlg->budget = budget;
+ category_dialog_create(dlg);
+
+ gtk_widget_show_all(dlg->wnd);
+}
+
+/* Public interface method to create the budget category dialog.
+ * This method is used to create a dialog to edit a newly created category.
+ * If the user clicks ok then the new category will be added to the budget,
+ * otherwise the new category will be destroyed.
+ * */
+void gnc_budget_category_new_dialog_create(GncBudget* budget)
+{
+ BudgetCategoryDlg* dlg;
+ GncBudgetCategory* category;
+
+ dlg = g_new0(BudgetCategoryDlg, 1);
+
+ category = gnc_budget_category_new(gnc_budget_get_book(budget), budget);
+
+
+ dlg->category = category;
+ dlg->budget = budget;
+
+ dlg->new_category = TRUE;
+
+ category_dialog_create(dlg);
+
+ gtk_widget_show_all(dlg->wnd);
+}
Index: gnc-main-window.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Attic/gnc-main-window.c,v
retrieving revision 1.1.2.32
retrieving revision 1.1.2.33
diff -Lsrc/gnome/gnc-main-window.c -Lsrc/gnome/gnc-main-window.c -u -r1.1.2.32 -r1.1.2.33
--- src/gnome/gnc-main-window.c
+++ src/gnome/gnc-main-window.c
@@ -35,6 +35,7 @@
#include "gnc-main-window.h"
+#include "dialog-budget-list.h"
#include "gnc-menu-extensions.h"
#include "dialog-fincalc.h"
@@ -111,6 +112,7 @@
static void gnc_main_window_cmd_view_summary (EggAction *action, GncMainWindow *window);
static void gnc_main_window_cmd_view_statusbar (EggAction *action, GncMainWindow *window);
static void gnc_main_window_cmd_actions_scheduled_transaction_editor (EggAction *action, GncMainWindow *window);
+static void gnc_main_window_cmd_actions_budget_workbench(EggAction *action, GncMainWindow *window);
static void gnc_main_window_cmd_actions_since_last_run (EggAction *action, GncMainWindow *window);
static void gnc_main_window_cmd_actions_mortgage_loan (EggAction *action, GncMainWindow *window);
static void gnc_main_window_cmd_actions_close_books (EggAction *action, GncMainWindow *window);
@@ -227,6 +229,9 @@
{ "ActionsMortgageLoanAction", N_("_Mortgage & Loan Repayment..."), NULL, "NULL",
N_("Setup scheduled transactions for repayment of a loan"),
G_CALLBACK (gnc_main_window_cmd_actions_mortgage_loan) },
+ { "ActionsBudgetWorkbenchAction", N_("_Budget Workbench (Experimental)"), NULL, NULL,
+ N_("Create, Manage, and Monitor Budgets." ),
+ G_CALLBACK(gnc_main_window_cmd_actions_budget_workbench) },
{ "ActionsCloseBooksAction", N_("Close Books"), NULL, "NULL",
N_("Archive old data using accounting periods"),
G_CALLBACK (gnc_main_window_cmd_actions_close_books) },
@@ -1142,6 +1147,12 @@
gnc_ui_sx_loan_druid_create ();
}
+static void
+gnc_main_window_cmd_actions_budget_workbench(EggAction *action, GncMainWindow *window)
+{
+ gnc_budget_list_dialog_create();
+}
+
static void
gnc_main_window_cmd_actions_close_books (EggAction *action, GncMainWindow *window)
{
--- /dev/null
+++ src/gnome/dialog-budget-workbench.c
@@ -0,0 +1,592 @@
+/********************************************************************\
+ * dialog-budget-workbench.c -- Implementation of the budget *
+ * workbench dialog. *
+ * Copyright (C) 14 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome
+ * @{ */
+/** @file dialog-budget-workbench.c
+ * @breif Implmentation of the budget workbench dialog.
+ * @author Created by Darin Willits 14 sep 2003
+ * @author Copyright (c) 14 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * The Budget Workbench is the main budgeting window. This window
+ * allows the user to configure and track their budget.
+ */
+
+// Includes
+#include <gnome.h>
+#include "dialog-utils.h"
+#include "gnc-ui-util.h"
+#include "dialog-budget-category.h"
+#include "gnc-general-select.h"
+#include "gnc-budget-gui.h"
+#include "gnc-ui-util.h"
+#include "gnc-date-edit.h"
+#include "misc-gnome-utils.h"
+#include "gnc-frequency.h"
+
+#include "dialog-budget-workbench.h"
+#include "dialog-budget-category.h"
+#include "gnc-budget-tree-model.h"
+#include "gnc-budget-period.h"
+
+
+/* The Budget Workbench dialog structure. */
+typedef struct{
+ GtkWidget* wnd;
+ GladeXML* xml;
+
+ GtkEntry* name_entry;
+ GtkTextView* description_view;
+ GNCDateEdit* start_date;
+ GNCFrequency* freqWnd;
+ GtkSpinButton* length_button;
+ GtkOptionMenu* length_menu;
+ GtkOptionMenu* period_menu;
+ GtkTreeView* category_view;
+ GtkTreeView* balance_view;
+ GtkTreeView* track_view;
+ GtkTreeModel* category_model;
+ GtkLabel* period_label;
+
+ int colNum;
+ int active_period;
+
+ GncBudget* budget;
+
+} BudgetWorkbench;
+
+/* Event handler for a cell having been edited. */
+static void cell_edited (GtkCellRendererText *cell,
+ const gchar *path_string,
+ const gchar *new_text,
+ gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ GtkTreeModel *model = bench->category_model;
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
+ GtkTreeIter iter;
+ GncBudgetCategory* category;
+
+ gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
+
+ gtk_tree_model_get_iter (model, &iter, path);
+ category = gnc_budget_tree_model_get_category(GNC_BUDGET_TREE_MODEL(model), &iter);
+
+ if(category == NULL){
+ printf("Cell_Edited: Category is NULL!\n");
+ return;
+ }
+
+ gint index = column - GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS;
+ gnc_numeric value = double_to_gnc_numeric(atof(new_text), 1, GNC_RND_NEVER);
+
+ gnc_budget_category_set_period_value_by_index(category, index, value);
+
+}
+
+/* Add a single period column to the balance view tab. */
+static void add_period_column(gpointer data, gpointer user_data)
+{
+ GncBudgetPeriod* period = data;
+ GDate* startDate, *endDate;
+ BudgetWorkbench* bench = user_data;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ char buffer[256];
+ gint colnum;
+
+ startDate = gnc_budget_period_get_start_date(period);
+ endDate = gnc_budget_period_get_end_date(period);
+
+ /* Format the period column title. */
+ sprintf(buffer, "%d/%d/%d", g_date_get_day(startDate),
+ g_date_get_month(startDate),
+ g_date_get_year(startDate));
+
+ /* column for severities */
+ colnum = GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS + bench->colNum;
+ renderer = gtk_cell_renderer_text_new ();
+ g_signal_connect (renderer, "edited",
+ G_CALLBACK (cell_edited), bench);
+ g_object_set_data (G_OBJECT (renderer), "column", (gint *)colnum);
+ column = gtk_tree_view_column_new_with_attributes (buffer,
+ renderer,
+ "text", colnum,
+ "editable", GNC_BUDGET_TREE_MODEL_COL_EDITABLE,
+ NULL);
+ gtk_tree_view_append_column (bench->balance_view, column);
+
+ bench->colNum++;
+}
+
+/* Iterates across the list of periods and adds a column for each
+ * one to the balance budget view. */
+static void add_balance_budget_columns(BudgetWorkbench* bench)
+{
+ GList* period_list;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* column for category name */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_NAME,
+ NULL);
+ gtk_tree_view_append_column (bench->balance_view, column);
+
+
+ bench->colNum = 0;
+ period_list = gnc_budget_get_period_list(bench->budget);
+
+ g_list_foreach(period_list, add_period_column, bench);
+}
+
+/* Remove a single column from the given TreeView. */
+static void remove_column(gpointer data, gpointer user_data)
+{
+ GtkTreeView* treeView = user_data;
+ GtkTreeViewColumn* column = data;
+
+ gtk_tree_view_remove_column(treeView, column);
+}
+
+/* Removes all the columns from the balance view. This is used to
+ * re-build the budget from category data. */
+static void remove_balance_view_columns(BudgetWorkbench* bench)
+{
+ GList* columns;
+ columns = gtk_tree_view_get_columns(bench->balance_view);
+
+ g_list_foreach(columns, remove_column, bench->balance_view);
+
+ g_list_free(columns);
+}
+
+/* Add the category columns to the given tree view. */
+static void add_category_columns(GtkTreeView* treeView)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* column for category name */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_NAME,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for value */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Value",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_VALUE,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for freq */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Frequency",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_FREQ,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+}
+
+/* Add the columns for the track budget view. */
+static void add_track_columns(GtkTreeView* treeView)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* column for category name */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_NAME,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for previous overflow value */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Previous Overflow",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_LAST_OVERFLOW,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for actual period value */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Actual",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_ACTUAL,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for planned period value */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Planned",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_PLANNED,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for period balance value */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Period Balance",
+ renderer,
+ "text", GNC_BUDGET_TREE_MODEL_COL_CUR_OVERFLOW,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+}
+
+/* Fill in the user interface from the budget object. */
+static void workbench_from_budget(BudgetWorkbench* bench)
+{
+ /* Set the name and description.*/
+ gtk_entry_set_text(bench->name_entry, gnc_budget_get_name(bench->budget));
+ xxxgtk_textview_set_text(bench->description_view,
+ gnc_budget_get_description(bench->budget));
+
+ /* Set the length value.
+ * FIXME: Default to showing length in months
+ * cause we have no way of knowing which they choose before.
+ * Maybe have to change this.
+ */
+ gtk_spin_button_set_value(bench->length_button,
+ gnc_budget_get_length_months(bench->budget));
+ gtk_option_menu_set_history(bench->length_menu, 0);
+}
+
+/* Fill in the budget object from the user interface. */
+static void workbench_to_budget(BudgetWorkbench* bench)
+{
+ const gchar *name, *description;
+ FreqSpec* freqSpec;
+ GDate* startDate;
+ gint length;
+
+ /* Set the name and description of the budget. */
+ name = gtk_entry_get_text(bench->name_entry);
+ description = xxxgtk_textview_get_text(bench->description_view);
+
+ gnc_budget_set_name(bench->budget, name);
+ gnc_budget_set_description(bench->budget, description);
+
+ /* Set the length of the budget. */
+ length = gtk_spin_button_get_value_as_int(bench->length_button);
+ if(gtk_option_menu_get_history(bench->length_menu) == 1){
+ gnc_budget_set_length_years(bench->budget, length);
+ }
+ else{
+ gnc_budget_set_length_months(bench->budget, length);
+ }
+
+ /* Set the budget period. */
+ freqSpec = gnc_budget_get_period_frequency(bench->budget);
+ startDate = gnc_budget_get_start_date(bench->budget);
+ if(freqSpec == NULL){
+ freqSpec = xaccFreqSpecMalloc(gnc_budget_get_book(bench->budget));
+ }
+ gnc_frequency_save_state( bench->freqWnd, freqSpec, startDate);
+ gnc_budget_set_period_frequency(bench->budget, freqSpec);
+
+}
+
+/* Destroy and cleanup the budget workbench dialog. */
+static void budget_workbench_destroy(BudgetWorkbench* bench)
+{
+ if(bench == NULL){
+ return;
+ }
+ gtk_widget_destroy(bench->wnd);
+ g_free(bench);
+}
+
+/* Event handler for the ok button. */
+static void ok_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ workbench_to_budget(bench);
+
+ budget_workbench_destroy(bench);
+}
+
+/* Event handler for the apply button. */
+static void apply_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ workbench_to_budget(bench);
+}
+
+/* Event handler for the cancel button. */
+static void cancel_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ budget_workbench_destroy(bench);
+}
+
+/* Event handler for the new category button. */
+static void new_category_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+
+ printf("Creating new Category... Budget: %p\n", bench->budget);
+ gnc_budget_category_new_dialog_create(bench->budget);
+}
+
+/* Event handler for the edit category button. */
+static void edit_category_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GncBudgetCategory *category = NULL;
+
+ printf("Editing Category... Druid: %p Budget: %p\n",bench, bench->budget);
+ selection = gtk_tree_view_get_selection (bench->category_view);
+ if (!gtk_tree_selection_get_selected (selection, &bench->category_model, &iter)){
+ printf("Nothing selected...\n");
+ return;
+ }
+
+ category = gnc_budget_tree_model_get_category(GNC_BUDGET_TREE_MODEL(bench->category_model), &iter);
+
+ gnc_budget_category_dialog_create(bench->budget, category);
+}
+
+/* Event handler for the delete category button. */
+static void delete_category_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GncBudgetCategory *category, *inflowCat, *outflowCat;
+
+ printf("Deleting Category...\n");
+ selection = gtk_tree_view_get_selection (bench->category_view);
+ if (!gtk_tree_selection_get_selected (selection, &bench->category_model, &iter)){
+ printf("Nothing selected...\n");
+ return;
+ }
+
+ category = gnc_budget_tree_model_get_category(GNC_BUDGET_TREE_MODEL(bench->category_model), &iter);
+ inflowCat = gnc_budget_get_inflow_category(bench->budget);
+ outflowCat = gnc_budget_get_outflow_category(bench->budget);
+
+ if((category != inflowCat) && (category != outflowCat)){
+ gnc_budget_category_delete(category);
+ }
+ else{
+ printf("Cannot delete this category...\n");
+ }
+}
+
+/* Event handler for the regenerate button. This will regenerate the
+ * values for each budget period from the category values. */
+static void regenerate_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+
+ remove_balance_view_columns(bench);
+ gnc_budget_generate_periods(bench->budget);
+ add_balance_budget_columns(bench);
+}
+
+/* Update the period label for the new active period on the track
+ * budget tab. */
+static void update_period_label(BudgetWorkbench* bench)
+{
+ GList* periodList;
+ periodList = gnc_budget_get_period_list(bench->budget);
+ GncBudgetPeriod* period;
+ GDate* startDate, *endDate;
+ char buffer[256];
+ gchar startBuffer[126];
+ gchar endBuffer[126];
+
+ if(bench->active_period >= g_list_length(periodList)){
+ bench->active_period = g_list_length(periodList) - 1;
+ }
+ else if(bench->active_period < 0){
+ bench->active_period = 0;
+ }
+
+ period = g_list_nth_data(periodList, bench->active_period);
+ startDate = gnc_budget_period_get_start_date(period);
+ endDate = gnc_budget_period_get_end_date(period);
+
+ g_date_strftime(startBuffer, 126, "%x", startDate);
+ g_date_strftime(endBuffer, 126, "%x", endDate);
+
+ sprintf(buffer, "%s - %s", startBuffer, endBuffer);
+ gtk_label_set_text(bench->period_label, buffer);
+}
+
+/* Roll back the active period to the first one. */
+static void first_period_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ bench->active_period = 0;
+ update_period_label(bench);
+}
+
+/* Roll back the period to the previous one. */
+static void back_period_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ if(bench->active_period > 0){
+ bench->active_period -= 1;
+ }
+ update_period_label(bench);
+}
+
+/* Advance to the next period. */
+static void next_period_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ if(bench->active_period < g_list_length(gnc_budget_get_period_list(bench->budget)) - 1){
+ bench->active_period += 1;
+ }
+ update_period_label(bench);
+}
+
+/* Advance to the last period. */
+static void last_period_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetWorkbench* bench = data;
+ bench->active_period = g_list_length(gnc_budget_get_period_list(bench->budget)) - 1;
+ update_period_label(bench);
+}
+
+/* Create the budget workbench dialog. */
+static void create_budget_workbench(BudgetWorkbench* bench)
+{
+ GtkWidget *box;
+ GDate* startDate;
+ GtkWidget* button;
+
+ /* Load the widgets from the glade xml file. */
+ bench->xml = gnc_glade_xml_new (GNC_BUDGET_GUI_FILE, "Budget Workbench");
+ bench->wnd = glade_xml_get_widget(bench->xml, "Budget Workbench");
+
+ bench->name_entry =
+ GTK_ENTRY(glade_xml_get_widget( bench->xml, "name_entry"));
+ bench->description_view =
+ GTK_TEXT_VIEW(glade_xml_get_widget( bench->xml, "description_view"));
+ bench->category_view =
+ GTK_TREE_VIEW(glade_xml_get_widget(bench->xml, "category_view"));
+ bench->balance_view =
+ GTK_TREE_VIEW(glade_xml_get_widget(bench->xml, "balance_budget_view"));
+ bench->track_view =
+ GTK_TREE_VIEW(glade_xml_get_widget(bench->xml, "track_view"));
+ bench->length_button =
+ GTK_SPIN_BUTTON(glade_xml_get_widget(bench->xml, "length_button"));
+ bench->length_menu =
+ GTK_OPTION_MENU(glade_xml_get_widget(bench->xml, "length_menu"));
+ bench->period_menu =
+ GTK_OPTION_MENU(glade_xml_get_widget(bench->xml, "period_menu"));
+ bench->period_label=
+ GTK_LABEL(glade_xml_get_widget(bench->xml, "period_label"));
+
+ /* Set up the period frequency view. */
+ startDate = gnc_budget_get_start_date(bench->budget);
+ bench->freqWnd = GNC_FREQUENCY(
+ gnc_frequency_new(gnc_budget_get_period_frequency(bench->budget), startDate));
+
+ /* Change the text so that its more mainingful for this druid*/
+ gnc_frequency_set_frequency_label_text(bench->freqWnd, _("Budget Period:"));
+ gnc_frequency_set_date_label_text(bench->freqWnd, _("Starting Date:"));
+
+ /* Reparent to the correct location */
+ box = glade_xml_get_widget (bench->xml, "budget_freq_box");
+ gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (bench->freqWnd),TRUE, TRUE, 0);
+
+ /* Create and assign the model. */
+ bench->category_model = gnc_budget_tree_model_new(bench->budget);
+ gtk_tree_view_set_model(bench->category_view, bench->category_model);
+ gtk_tree_view_set_model(bench->balance_view, bench->category_model);
+ gtk_tree_view_set_model(bench->track_view, bench->category_model);
+
+ /* Add the columns to the various tree views. */
+ add_category_columns(bench->category_view);
+ add_balance_budget_columns(bench);
+ add_track_columns(bench->track_view);
+
+ /* Connect the signal handlers. */
+ button = glade_xml_get_widget( bench->xml, "ok_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(ok_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "apply_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(apply_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "cancel_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(cancel_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "new_category_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(new_category_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "edit_category_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(edit_category_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "delete_category_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(delete_category_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "regenerate_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(regenerate_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "first_period_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(first_period_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "back_period_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(back_period_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "next_period_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(next_period_clicked), bench);
+ button = glade_xml_get_widget( bench->xml, "last_period_button" );
+ g_signal_connect( button, "clicked",
+ G_CALLBACK(last_period_clicked), bench);
+
+ /* Fill in the values based on our budget. */
+ workbench_from_budget(bench);
+ update_period_label(bench);
+}
+
+/* Public interface to create a budget workbench dialog. */
+void gnc_budget_workbench_dialog_create(GncBudget* budget)
+{
+ BudgetWorkbench* bench;
+
+ bench = g_new0(BudgetWorkbench, 1);
+ printf("Creating Workbench dialog: Budget: %p\n", budget);
+
+ bench->budget = budget;
+ bench->active_period = 0;
+ create_budget_workbench(bench);
+
+ printf("Showing Workbench dialog: Budget: %p\n", bench->budget);
+ gtk_widget_show_all(bench->wnd);
+}
--- /dev/null
+++ src/gnome/druid-budget-create.h
@@ -0,0 +1,44 @@
+/********************************************************************\
+ * druid-budget-create.h -- Public interface for the Budget *
+ * creation druid. *
+ * Copyright (C) 08 sep 2003 Darin Willits <darin at willits.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 or 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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gui
+ * @{ */
+/** @file druid-budget-create.h
+ * @breif Public interface for the budget creation druid.
+ * @author Created by Darin Willits 08 sep 2003
+ * @author Copyright (c) 08 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+#ifndef __DRUID_BUDGET_CREATE_H__
+#define __DRUID_BUDGET_CREATE_H__
+
+#include <glib.h>
+#include <gnome.h>
+
+/** Launch the Create Budget druid. */
+void gnc_budget_druid_create(GtkTreeModel* treeModel);
+
+
+#endif // __DRUID_BUDGET_CREATE_H__
--- /dev/null
+++ src/gnome/dialog-budget-list.c
@@ -0,0 +1,243 @@
+/********************************************************************\
+ * dialog-budget-list.c -- Implementation of the budget list *
+ * dialog. *
+ * Copyright (C) 08 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gui
+ * @{ */
+/** @file dialog-budget-list.c
+ * @breif Implementation of the budget list dialog.
+ * @author Created by Darin Willits 08 sep 2003
+ * @author Copyright (c) 08 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * This dialog presents the user with a list of the available budget
+ * objects. From here they can create a new budget or edit/delete
+ * an existing one.
+ */
+
+// Includes
+#include <glib.h>
+#include <gnome.h>
+
+#include "dialog-budget-list.h"
+#include "dialog-budget-workbench.h"
+#include "druid-budget-create.h"
+#include "dialog-utils.h"
+#include "gnc-ui-util.h"
+
+#include "gnc-budget-gui.h"
+#include "gnc-budget-book.h"
+#include "gnc-budget.h"
+#include "gnc-budget-list-tree-model.h"
+
+
+/* The budget list dialog structure. */
+typedef struct{
+ GtkWidget* wnd;
+ GladeXML* xml;
+
+ GtkWidget* treeView;
+ GtkTreeModel* treeModel;
+
+} BudgetListDlg;
+
+/* The budget list columns. */
+enum{
+ COLUMN_NAME,
+ COLUMN_DESCRIPTION,
+ BUDGET_LIST_NUM_COLS
+};
+
+
+/* Add the new budget object to the tree model.
+ * FIXME: This will be unnecessary once we create a tree model
+ * which directly relates to the book's list of budgets but for
+ * now we have to hack around it. This is ugly though and prone
+ * to error so it should/must be fixed.
+ */
+void add_budget_to_model( gpointer data, gpointer user_data )
+{
+ GncBudget* budget;
+ GtkTreeIter iter;
+ GtkTreeModel* treeModel;
+ /*BudgetListDlg* dlg;*/
+
+ budget = data;
+ treeModel = user_data;
+
+ if((budget == NULL) || (treeModel == NULL)){
+ return;
+ }
+
+ gtk_list_store_append (GTK_LIST_STORE(treeModel), &iter);
+ gtk_list_store_set (GTK_LIST_STORE(treeModel), &iter,
+ COLUMN_NAME, gnc_budget_get_name(budget),
+ COLUMN_DESCRIPTION, gnc_budget_get_description(budget),
+ -1);
+}
+
+/* Initialize the tree model with the list of budgets from the
+ * book.
+ */
+/*
+static void fill_model(BudgetListDlg* dlg)
+{
+ GList *budgetList;
+ GtkListStore* store;
+
+ store = gtk_list_store_new (BUDGET_LIST_NUM_COLS,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ dlg->treeModel = GTK_TREE_MODEL(store);
+
+ budgetList = gnc_book_get_budgets(gnc_get_current_book());
+ g_list_foreach( budgetList, add_budget_to_model, dlg->treeModel);
+}
+*/
+/* Add the columns to the tree view. */
+static void add_columns(GtkTreeView* treeView)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* column for name */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name",
+ renderer,
+ "text",
+ COLUMN_NAME,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for description */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Description",
+ renderer,
+ "text",
+ COLUMN_DESCRIPTION,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+}
+
+/* Destroy the budget list dialog. */
+static void budget_list_dialog_destroy(BudgetListDlg* dlg)
+{
+ if(dlg == NULL){
+ return;
+ }
+ gtk_widget_destroy(dlg->wnd);
+ g_free(dlg);
+}
+
+/* Event handler for the close button. */
+static void close_button_clicked(GtkWidget* object, gpointer data)
+{
+ budget_list_dialog_destroy(data);
+}
+
+/* Event handler for the new button. */
+static void new_button_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetListDlg* dlg = data;
+
+ gnc_budget_druid_create(dlg->treeModel);
+}
+
+/* Event handler for the edit button. Create a budget workbench
+ * dialog with the given budget object. */
+static void edit_button_clicked(GtkWidget* object, gpointer data)
+{
+ GtkTreeIter iter;
+ BudgetListDlg* dlg = data;
+ GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW(dlg->treeView));
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dlg->treeView));
+
+ /* If a budget is selected use it to create a budget workbench. */
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)){
+ gint i;
+ GtkTreePath *path;
+ GncBudget* budget;
+ GList* budgetList;
+
+ path = gtk_tree_model_get_path (model, &iter);
+ i = gtk_tree_path_get_indices (path)[0];
+
+ budgetList = gnc_book_get_budgets(gnc_get_current_book());
+ budget = g_list_nth_data(budgetList, i);
+
+ if(budget != NULL){
+ printf("Creating Workbench: Budget: %p\n", budget);
+ /* Create the workbench. */
+ gnc_budget_workbench_dialog_create(budget);
+ }
+
+ gtk_tree_path_free (path);
+ }
+}
+
+/* Create the budget list dialog. */
+static void budget_create_list_dialog(BudgetListDlg* dlg)
+{
+ GladeXML *xml;
+ GtkWidget *new_button;
+ GtkWidget *edit_button;
+ GtkWidget *close_button;
+
+ /* Load the main dialog widget. */
+ xml = gnc_glade_xml_new (GNC_BUDGET_GUI_FILE, "Budget List");
+ dlg->wnd = glade_xml_get_widget(xml, "Budget List");
+ dlg->xml = xml;
+
+ /* Create and fill the model */
+ /*fill_model(dlg);*/
+ dlg->treeModel = gnc_budget_list_tree_model_new(gnc_get_current_book());
+
+ dlg->treeView = glade_xml_get_widget(xml, "Budget List View");
+ gtk_tree_view_set_model (GTK_TREE_VIEW(dlg->treeView), dlg->treeModel);
+
+ add_columns(GTK_TREE_VIEW(dlg->treeView));
+
+
+ /* Connect signals. */
+ new_button = glade_xml_get_widget( dlg->xml, "new_button" );
+ g_signal_connect( new_button, "clicked",
+ G_CALLBACK(new_button_clicked), dlg);
+ edit_button = glade_xml_get_widget( dlg->xml, "edit_button" );
+ g_signal_connect( edit_button, "clicked",
+ G_CALLBACK(edit_button_clicked), dlg);
+ close_button = glade_xml_get_widget( dlg->xml, "close_button" );
+ g_signal_connect( close_button, "clicked",
+ G_CALLBACK(close_button_clicked), dlg);
+}
+
+/* Public interface for creating a budget list dialog. */
+void gnc_budget_list_dialog_create(void)
+{
+ BudgetListDlg* dlg;
+
+ dlg = g_new0(BudgetListDlg, 1);
+
+ budget_create_list_dialog(dlg);
+
+ gtk_widget_show_all(dlg->wnd);
+}
--- /dev/null
+++ src/gnome/dialog-budget-workbench.h
@@ -0,0 +1,43 @@
+/********************************************************************\
+ * dialog-budget-workbench.h -- Definition of the interface *
+ * for the budget workbench dialog. *
+ * Copyright (C) 14 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome
+ * @{ */
+/** @file dialog-budget-workbench.h
+ * @breif Definition of the budget workbench dialog interface.
+ * @author Created by Darin Willits 14 sep 2003
+ * @author Copyright (c) 14 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+#ifndef __DIALOG_BUDGET_WORKBENCH_H__
+#define __DIALOG_BUDGET_WORKBENCH_H__
+
+#include "gnc-budget.h"
+
+/* Create a budget workbench dialog using the given budget object.
+ */
+void gnc_budget_workbench_dialog_create(GncBudget* budget);
+
+#endif // __DIALOG_BUDGET_WORKBENCH_H__
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Makefile.am,v
retrieving revision 1.107.4.14
retrieving revision 1.107.4.15
diff -Lsrc/gnome/Makefile.am -Lsrc/gnome/Makefile.am -u -r1.107.4.14 -r1.107.4.15
--- src/gnome/Makefile.am
+++ src/gnome/Makefile.am
@@ -24,6 +24,9 @@
libgw_gnc_la_LIBADD = libgncgnome.la
libgncgnome_la_SOURCES = \
+ dialog-budget-category.c \
+ dialog-budget-list.c \
+ dialog-budget-workbench.c \
dialog-commodities.c \
dialog-fincalc.c \
dialog-find-transactions.c \
@@ -38,6 +41,7 @@
gnc-totd-dialog.c \
dialog-userpass.c \
dialog-scheduledxaction.c \
+ druid-budget-create.c \
druid-acct-period.c \
druid-hierarchy.c \
druid-loan.c \
@@ -75,6 +79,9 @@
mime_DATA = gnucash.keys gnucash.mime
noinst_HEADERS = \
+ dialog-budget-category.h \
+ dialog-budget-list.h \
+ dialog-budget-workbench.h \
dialog-fincalc.h \
dialog-find-transactions.h \
dialog-new-user.h \
@@ -84,6 +91,7 @@
dialog-sxsincelast.h \
gnc-totd-dialog.h \
dialog-scheduledxaction.h \
+ druid-budget-create.h \
druid-acct-period.h \
druid-hierarchy.h \
druid-loan.h \
--- /dev/null
+++ src/gnome/druid-budget-create.c
@@ -0,0 +1,326 @@
+/********************************************************************\
+ * druid-budget-create.c -- Implementation of the budget create *
+ * druid. *
+ * Copyright (C) 08 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gui
+ * @{ */
+/** @file druid-budget-create.c
+ * @breif Implementation of the budget create druid.
+ * @author Created by Darin Willits 08 sep 2003
+ * @author Copyright (c) 08 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ */
+
+// Includes
+#include <glib.h>
+#include <gnome.h>
+#include <libgnomeui/libgnomeui.h>
+
+#include "druid-budget-create.h"
+#include "gnc-budget.h"
+#include "dialog-budget-list.h"
+#include "gnc-budget-tree-model.h"
+#include "dialog-budget-category.h"
+#include "dialog-budget-workbench.h"
+
+#include "dialog-utils.h"
+#include "gnc-ui-util.h"
+#include "misc-gnome-utils.h"
+#include "gnc-frequency.h"
+#include "gnc-date-edit.h"
+
+#include "gnc-budget-gui.h"
+#include "gnc-budget-book.h"
+#include "gnc-budget.h"
+
+
+#define BUDGET_NAME_ENTRY "name_entry"
+#define BUDGET_DESC_VIEW "description_view"
+#define BUDGET_LENGTH_BUTTON "length_button"
+#define BUDGET_TIME_SCALE "time_scale_menu"
+#define BUDGET_TREE_VIEW "budget_tree_view"
+#define BUDGET_LENGTH_BUTTON "length_button"
+#define BUDGET_LENGTH_MENU "length_menu"
+#define BUDGET_PERIOD_MENU "period_menu"
+
+#define BUDGET_DRUID "Budget Druid"
+#define BUDGET_FINISH_PAGE "finish_page"
+
+
+
+typedef struct{
+ GtkWidget* wnd;
+ GladeXML* xml;
+ GtkTreeModel* budgetListModel;
+ GtkTreeModel* budgetCatModel;
+
+ GtkEntry* nameEntry;
+ GtkTextView* descriptionView;
+ GtkTreeView* budgetView;
+ GtkSpinButton* length_button;
+ GtkOptionMenu* length_menu;
+ GNCFrequency* freqWnd;
+
+ GncBudget* budget;
+
+} BudgetDruid;
+
+
+static void budget_druid_destroy(BudgetDruid* druid)
+{
+ if(druid == NULL){
+ return;
+ }
+ gtk_widget_destroy(druid->wnd);
+ g_free(druid);
+}
+
+static void cancel_clicked(GnomeDruid *druid, gpointer user_data)
+{
+ budget_druid_destroy(user_data);
+}
+
+static void apply_clicked(GnomeDruidPage *page, GtkWidget* arg1, gpointer data)
+{
+ QofBook* book;
+ BudgetDruid* druid = data;
+ const gchar *name, *description;
+ FreqSpec* freqSpec;
+ //time_t tmpTimeT;
+ //GDate outDate;
+ GDate* startDate;
+ gint length;//, period;
+
+ book = gnc_get_current_book();
+
+ if(druid->budget == NULL){
+ /* something terribly wrong. */
+ return;
+ }
+
+ /* Set the name and description of the budget. */
+ name = gtk_entry_get_text(druid->nameEntry);
+ description = xxxgtk_textview_get_text(druid->descriptionView);
+
+ gnc_budget_set_name(druid->budget, name);
+ gnc_budget_set_description(druid->budget, description);
+
+ /* Set the length of the budget. */
+ length = gtk_spin_button_get_value_as_int(druid->length_button);
+ if(gtk_option_menu_get_history(druid->length_menu) == 1){
+ gnc_budget_set_length_years(druid->budget, length);
+ }
+ else{
+ gnc_budget_set_length_months(druid->budget, length);
+ }
+
+ freqSpec = gnc_budget_get_period_frequency(druid->budget);
+ startDate = gnc_budget_get_start_date(druid->budget);
+ if(freqSpec == NULL){
+ freqSpec = xaccFreqSpecMalloc(gnc_budget_get_book(druid->budget));
+ }
+ gnc_frequency_save_state( druid->freqWnd, freqSpec, startDate);
+ gnc_budget_set_period_frequency(druid->budget, freqSpec);
+
+ /* Add the budget to the book. */
+ gnc_book_add_budget(book, druid->budget);
+
+ /* FIXME: This is just a temporary mesure and won't be necessary once
+ * we connect up to the gnc gui event system. We will also need to be
+ * generating the proper events from the budget engine structures so
+ * for now we will just do this.
+ */
+ /*add_budget_to_model(druid->budget, druid->budgetListModel);*/
+
+ printf("Generating periods: Druid %p Budget: %p\n", druid, druid->budget);
+ /* Generate the list of budget periods. */
+ gnc_budget_generate_periods(druid->budget);
+
+ budget_druid_destroy(druid);
+}
+
+static void add_columns(GtkTreeView* treeView)
+{
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ /* column for severities */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name",
+ renderer,
+ "text",
+ GNC_BUDGET_TREE_MODEL_COL_NAME,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for value */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Value",
+ renderer,
+ "text",
+ GNC_BUDGET_TREE_MODEL_COL_VALUE,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+
+ /* column for freq */
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Frequency",
+ renderer,
+ "text",
+ GNC_BUDGET_TREE_MODEL_COL_FREQ,
+ NULL);
+ gtk_tree_view_append_column (treeView, column);
+}
+
+static void edit_category_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetDruid* druid = data;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GncBudgetCategory *category = NULL;
+
+ printf("Editing Category... Druid: %p Budget: %p\n",druid, druid->budget);
+ selection = gtk_tree_view_get_selection (druid->budgetView);
+ if (!gtk_tree_selection_get_selected (selection, &druid->budgetCatModel, &iter)){
+ printf("Nothing selected...\n");
+ return;
+ }
+
+ category = gnc_budget_tree_model_get_category(GNC_BUDGET_TREE_MODEL(druid->budgetCatModel), &iter);
+
+ gnc_budget_category_dialog_create(druid->budget, category);
+}
+
+static void new_category_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetDruid* druid = data;
+
+ printf("Creating new Category... Budget: %p\n", druid->budget);
+ gnc_budget_category_new_dialog_create(druid->budget);
+}
+
+static void delete_category_clicked(GtkWidget* object, gpointer data)
+{
+ BudgetDruid* druid = data;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GncBudgetCategory *category, *inflowCat, *outflowCat;
+
+ printf("Deleting Category...\n");
+ selection = gtk_tree_view_get_selection (druid->budgetView);
+ if (!gtk_tree_selection_get_selected (selection, &druid->budgetCatModel, &iter)){
+ printf("Nothing selected...\n");
+ return;
+ }
+
+ category = gnc_budget_tree_model_get_category(GNC_BUDGET_TREE_MODEL(druid->budgetCatModel), &iter);
+ inflowCat = gnc_budget_get_inflow_category(druid->budget);
+ outflowCat = gnc_budget_get_outflow_category(druid->budget);
+
+ if((category != inflowCat) && (category != outflowCat)){
+ gnc_budget_category_delete(category);
+ }
+ else{
+ printf("Cannot delete this category...\n");
+ }
+
+}
+
+static void create_budget_druid(BudgetDruid* druid)
+{
+ GladeXML *xml;
+ GtkWidget *box;
+ GnomeDruid* budgetDruid;
+ GtkWidget *final_page;
+ GtkWidget* editCategoryButton;
+ GtkWidget* newCategoryButton;
+ GtkWidget* deleteCategoryButton;
+
+ druid->budget = gnc_budget_new(gnc_get_current_book());
+
+ xml = gnc_glade_xml_new (GNC_BUDGET_GUI_FILE, "New Budget Druid");
+ druid->wnd = glade_xml_get_widget(xml, "New Budget Druid");
+ druid->xml = xml;
+
+ druid->nameEntry =
+ GTK_ENTRY(glade_xml_get_widget( druid->xml, BUDGET_NAME_ENTRY));
+ druid->descriptionView =
+ GTK_TEXT_VIEW(glade_xml_get_widget( druid->xml, BUDGET_DESC_VIEW));
+ druid->budgetView =
+ GTK_TREE_VIEW(glade_xml_get_widget(druid->xml, BUDGET_TREE_VIEW));
+ druid->length_button =
+ GTK_SPIN_BUTTON(glade_xml_get_widget(druid->xml, BUDGET_LENGTH_BUTTON));
+ druid->length_menu =
+ GTK_OPTION_MENU(glade_xml_get_widget(druid->xml, BUDGET_LENGTH_MENU));
+
+ /* Set the default length to 1 year. */
+ gtk_option_menu_set_history(druid->length_menu, 1);
+
+ /* Set up the period frequency view. */
+ druid->freqWnd = GNC_FREQUENCY(
+ gnc_frequency_new(gnc_budget_get_period_frequency(druid->budget),
+ gnc_budget_get_start_date(druid->budget)));
+
+ /* Change the text so that its more mainingful for this druid*/
+ gnc_frequency_set_frequency_label_text(druid->freqWnd, _("Budget Period:"));
+ gnc_frequency_set_date_label_text(druid->freqWnd, _("Starting Date:"));
+
+ /* Reparent to the correct location */
+ box = glade_xml_get_widget (druid->xml, "budget_freq_box");
+ gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (druid->freqWnd),TRUE, TRUE, 0);
+
+ /* Create the budget Tree model. */
+ druid->budgetCatModel = gnc_budget_tree_model_new(druid->budget);
+ gtk_tree_view_set_model(druid->budgetView, druid->budgetCatModel);
+
+ add_columns(druid->budgetView);
+
+ /* Connect signals. */
+ final_page = glade_xml_get_widget( druid->xml, BUDGET_FINISH_PAGE );
+ g_signal_connect(final_page, "finish", G_CALLBACK(apply_clicked), druid);
+
+ budgetDruid = GNOME_DRUID(glade_xml_get_widget( druid->xml, BUDGET_DRUID ));
+ g_signal_connect(budgetDruid, "cancel", G_CALLBACK(cancel_clicked), druid);
+
+ editCategoryButton = glade_xml_get_widget( druid->xml, "edit_category_button" );
+ g_signal_connect(editCategoryButton, "clicked", G_CALLBACK(edit_category_clicked), druid);
+
+ newCategoryButton = glade_xml_get_widget( druid->xml, "new_category_button" );
+ g_signal_connect(newCategoryButton, "clicked", G_CALLBACK(new_category_clicked), druid);
+
+ deleteCategoryButton = glade_xml_get_widget( druid->xml, "delete_category_button" );
+ g_signal_connect(deleteCategoryButton, "clicked", G_CALLBACK(delete_category_clicked), druid);
+}
+
+void gnc_budget_druid_create(GtkTreeModel* treeModel)
+{
+ BudgetDruid* druid;
+
+ druid = g_new0(BudgetDruid, 1);
+
+ druid->budgetListModel = treeModel;
+
+ create_budget_druid(druid);
+
+ gtk_widget_show_all(druid->wnd);
+}
--- /dev/null
+++ src/gnome-utils/gnc-budget-tree-model.c
@@ -0,0 +1,726 @@
+/********************************************************************\
+ * gnc-budget-tree-model.c -- Implementation of the budget tree *
+ * model. *
+ * Copyright (C) 09 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome-util
+ * @{ */
+/** @file gnc-budget-tree-model.c
+ * @breif Implementation of the budget tree model.
+ * @author Created by Darin Willits 09 sep 2003
+ * @author Copyright (c) 09 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * This should be fun...
+ */
+
+// Includes
+#include "config.h"
+#include <string.h>
+#include "gnc-trace.h"
+
+#include "gnc-budget-tree-model.h"
+#include "gnc-budget-cat.h"
+
+static short module = MOD_GUI;
+
+/** Initialize and clean-up functions. */
+static void gnc_budget_tree_model_class_init (GncBudgetTreeModelClass *klass);
+static void gnc_budget_tree_model_init (GncBudgetTreeModel *model);
+static void gnc_budget_tree_model_finalize (GObject *object);
+static void gnc_budget_tree_model_destroy (GtkObject *object);
+static void gnc_budget_tree_model_gtk_tree_model_init (GtkTreeModelIface *iface);
+
+/* GtkTreeModel Interface functions. */
+static guint gnc_budget_tree_model_get_flags (GtkTreeModel *tree_model);
+static int gnc_budget_tree_model_get_n_columns (GtkTreeModel *tree_model);
+static GType gnc_budget_tree_model_get_column_type (GtkTreeModel *tree_model,
+ int index);
+static gboolean gnc_budget_tree_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path);
+static GtkTreePath *gnc_budget_tree_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static void gnc_budget_tree_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ int column,
+ GValue *value);
+static gboolean gnc_budget_tree_model_iter_next (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gboolean gnc_budget_tree_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent);
+static gboolean gnc_budget_tree_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static int gnc_budget_tree_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gboolean gnc_budget_tree_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ int n);
+static gboolean gnc_budget_tree_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child);
+
+/* Private internal data structure. */
+struct GncBudgetTreeModelPrivate
+{
+ GncBudget* budget;
+ GncBudgetCategory* top_category;
+ GncBudgetCategory* balance_category;
+ gint event_handler_id;
+};
+
+/************************************************************/
+/* g_object required functions */
+/************************************************************/
+
+static GtkObjectClass *parent_class = NULL;
+
+GType
+gnc_budget_tree_model_get_type (void)
+{
+ static GType gnc_budget_tree_model_type = 0;
+
+ if (gnc_budget_tree_model_type == 0) {
+ static const GTypeInfo our_info = {
+ sizeof (GncBudgetTreeModelClass), /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gnc_budget_tree_model_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GncBudgetTreeModel), /* */
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gnc_budget_tree_model_init
+ };
+
+ static const GInterfaceInfo budget_tree_model_info = {
+ (GInterfaceInitFunc) gnc_budget_tree_model_gtk_tree_model_init,
+ NULL,
+ NULL
+ };
+
+ gnc_budget_tree_model_type = g_type_register_static (GTK_TYPE_OBJECT,
+ "GncBudgetTreeModel",
+ &our_info, 0);
+
+ g_type_add_interface_static (gnc_budget_tree_model_type,
+ GTK_TYPE_TREE_MODEL,
+ &budget_tree_model_info);
+ }
+
+ return gnc_budget_tree_model_type;
+}
+
+static void
+gnc_budget_tree_model_class_init (GncBudgetTreeModelClass *klass)
+{
+ GObjectClass *o_class;
+ GtkObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ o_class = G_OBJECT_CLASS (klass);
+ object_class = GTK_OBJECT_CLASS (klass);
+
+ /* GObject signals */
+ o_class->finalize = gnc_budget_tree_model_finalize;
+
+ /* GtkObject signals */
+ object_class->destroy = gnc_budget_tree_model_destroy;
+}
+
+static void
+gnc_budget_tree_model_init (GncBudgetTreeModel *model)
+{
+ ENTER("model %p", model);
+ while (model->stamp == 0) {
+ model->stamp = g_random_int ();
+ }
+
+ model->priv = g_new0 (GncBudgetTreeModelPrivate, 1);
+ model->priv->budget = NULL;
+ LEAVE(" ");
+}
+
+static void
+gnc_budget_tree_model_finalize (GObject *object)
+{
+ GncBudgetTreeModel *model;
+
+ ENTER("model %p", object);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_BUDGET_TREE_MODEL (object));
+
+ model = GNC_BUDGET_TREE_MODEL(object);
+ g_free (model->priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+ LEAVE(" ");
+}
+
+static void
+gnc_budget_tree_model_destroy (GtkObject *object)
+{
+ GncBudgetTreeModel *model;
+
+ ENTER("model %p", object);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_BUDGET_TREE_MODEL(object));
+
+ model = GNC_BUDGET_TREE_MODEL(object);
+
+ /*active_models = g_list_remove(active_models, model);
+
+ if (model->priv->event_handler_id) {
+ gnc_engine_unregister_event_handler (model->priv->event_handler_id);
+ model->priv->event_handler_id = 0;
+ }
+ */
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ LEAVE(" ");
+}
+
+/******************************************************
+ * GtkTreeModel Interface Methods.
+ *
+ * ****************************************************/
+
+static void gnc_budget_tree_model_gtk_tree_model_init(GtkTreeModelIface *iface)
+{
+ iface->get_flags = gnc_budget_tree_model_get_flags;
+ iface->get_n_columns = gnc_budget_tree_model_get_n_columns;
+ iface->get_column_type = gnc_budget_tree_model_get_column_type;
+ iface->get_iter = gnc_budget_tree_model_get_iter;
+ iface->get_path = gnc_budget_tree_model_get_path;
+ iface->get_value = gnc_budget_tree_model_get_value;
+ iface->iter_next = gnc_budget_tree_model_iter_next;
+ iface->iter_children = gnc_budget_tree_model_iter_children;
+ iface->iter_has_child = gnc_budget_tree_model_iter_has_child;
+ iface->iter_n_children = gnc_budget_tree_model_iter_n_children;
+ iface->iter_nth_child = gnc_budget_tree_model_iter_nth_child;
+ iface->iter_parent = gnc_budget_tree_model_iter_parent;
+}
+
+static guint gnc_budget_tree_model_get_flags (GtkTreeModel *tree_model)
+{
+ return 0;
+}
+
+static int gnc_budget_tree_model_get_n_columns (GtkTreeModel *tree_model)
+{
+ GncBudgetTreeModel *model;
+ gint numCols;
+ model = GNC_BUDGET_TREE_MODEL(tree_model);
+ numCols = GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS +
+ gnc_budget_get_num_periods(model->priv->budget);
+ printf("NumCols: %d\n", numCols);
+ return numCols;
+}
+
+static GType gnc_budget_tree_model_get_column_type (GtkTreeModel *tree_model, int index)
+{
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(tree_model), G_TYPE_INVALID);
+ //g_return_val_if_fail ((index < GNC_BUDGET_TREE_MODEL_NUM_COLUMNS) && (index >= 0), G_TYPE_INVALID);
+
+ return G_TYPE_STRING;
+/*
+ switch (index) {
+ case GNC_BUDGET_TREE_MODEL_COL_NAME:
+ case GNC_BUDGET_TREE_MODEL_COL_VALUE:
+ case GNC_BUDGET_TREE_MODEL_COL_FREQ:
+ return G_TYPE_STRING;
+ default:
+ g_assert_not_reached ();
+ return G_TYPE_INVALID;
+ }
+*/
+}
+
+static gboolean gnc_budget_tree_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ GncBudgetTreeModel *model;
+ GncBudgetCategory* category;
+ gint i = 0, *indices;
+ GtkTreePath *path_copy;
+
+ {
+ gchar *path_string = gtk_tree_path_to_string(path);
+ ENTER("model %p, iter %p, path %s", tree_model, iter, path_string);
+ g_free(path_string);
+ }
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(tree_model), FALSE);
+
+ model = GNC_BUDGET_TREE_MODEL(tree_model);
+
+ path_copy = gtk_tree_path_copy(path);
+
+ if ((model->priv->budget == NULL) || (model->priv->top_category == NULL)) {
+ LEAVE("failed (2)");
+ return FALSE;
+ }
+
+ category = model->priv->top_category;
+
+ indices = gtk_tree_path_get_indices (path);
+ for(i = 0; i < gtk_tree_path_get_depth (path); i++){
+ category = gnc_budget_category_get_child(category, indices[i]);
+
+ if(category == NULL){
+ LEAVE("failed (3)");
+ return FALSE;
+ }
+ }
+
+ if(category == NULL){
+ return FALSE;
+ }
+
+ iter->stamp = model->stamp;
+ iter->user_data = category;
+
+ LEAVE("category %s", gnc_budget_category_get_name(category));
+ return TRUE;
+}
+
+static GtkTreePath *gnc_budget_tree_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GncBudgetTreeModel *model = GNC_BUDGET_TREE_MODEL(tree_model);
+ GtkTreePath *path;
+ GncBudgetCategory* category, *parent;
+
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(model), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+ g_return_val_if_fail (iter->user_data != NULL, NULL);
+ g_return_val_if_fail (iter->stamp == model->stamp, NULL);
+
+ if (model->priv->budget == NULL){
+ return NULL;
+ }
+
+ path = gtk_tree_path_new ();
+ category = iter->user_data;
+
+ if(category == model->priv->top_category){
+ gtk_tree_path_prepend_index(path, 0);
+
+ {
+ gchar* path_string = gtk_tree_path_to_string(path);
+ LEAVE("path (2) %s", path_string);
+ g_free(path_string);
+ }
+ return path;
+ }
+
+
+ do{
+ parent = gnc_budget_category_get_parent(category);
+ gtk_tree_path_prepend_index(path,
+ gnc_budget_category_get_index_in_parent_list(category));
+
+ category = gnc_budget_category_get_parent(category);
+ }while(parent != model->priv->top_category);
+
+ {
+ gchar* path_string = gtk_tree_path_to_string(path);
+ LEAVE("path (2) %s", path_string);
+ g_free(path_string);
+ }
+ return path;
+}
+
+static void gnc_budget_tree_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ int column,
+ GValue *value)
+{
+ GncBudgetTreeModel* model = GNC_BUDGET_TREE_MODEL(tree_model);
+ GncBudgetCategory* category;
+ char buffer[256];
+ gchar* tempStr;
+ double floatValue;
+ GString* freqStr;
+ int index;
+
+ g_return_if_fail (GNC_IS_BUDGET_TREE_MODEL(model));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (iter->user_data != NULL);
+ g_return_if_fail (iter->stamp == model->stamp);
+
+ category = (GncBudgetCategory*)iter->user_data;
+ ENTER("Col: %d, Category: %s", column, gnc_budget_category_get_name(category));
+ if(column == GNC_BUDGET_TREE_MODEL_COL_EDITABLE){
+ g_value_init(value, G_TYPE_BOOLEAN);
+
+ if((category == gnc_budget_get_inflow_category(model->priv->budget)) ||
+ (category == gnc_budget_get_outflow_category(model->priv->budget)) ||
+ (category == model->priv->balance_category)){
+ g_value_set_boolean(value, FALSE);
+ }
+ else{
+ g_value_set_boolean(value, TRUE);
+ }
+ return;
+ }
+
+ if((column >= GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS) &&
+ (column < (GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS +
+ gnc_budget_get_num_periods(model->priv->budget)))){
+ index = column - (GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS);
+ g_value_init (value, G_TYPE_STRING);
+
+ if(category == gnc_budget_get_inflow_category(model->priv->budget)){
+ floatValue = gnc_budget_category_sum_child_values_by_index(
+ gnc_budget_get_inflow_category(model->priv->budget), index);
+ }
+ else if(category == gnc_budget_get_outflow_category(model->priv->budget)){
+ floatValue = gnc_budget_category_sum_child_values_by_index(
+ gnc_budget_get_outflow_category(model->priv->budget), index);
+ }
+ else if(category == model->priv->balance_category){
+ floatValue = gnc_budget_category_sum_child_values_by_index(
+ gnc_budget_get_inflow_category(model->priv->budget), index);
+ floatValue += (-1) * gnc_budget_category_sum_child_values_by_index(
+ gnc_budget_get_outflow_category(model->priv->budget), index);
+ }
+ else{
+ floatValue = gnc_numeric_to_double(
+ gnc_budget_category_get_value_by_index(category, index));
+ }
+
+ sprintf(buffer, "%0.2f", floatValue);
+ tempStr = g_strdup(buffer);
+
+ g_value_set_string(value, tempStr);
+ g_free(tempStr);
+ return;
+ }
+
+ switch (column) {
+ case GNC_BUDGET_TREE_MODEL_COL_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, gnc_budget_category_get_name(category));
+ break;
+ case GNC_BUDGET_TREE_MODEL_COL_VALUE:
+ /*g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "");*/
+ g_value_init (value, G_TYPE_STRING);
+
+ floatValue = gnc_numeric_to_double(gnc_budget_category_get_value(category));
+ sprintf(buffer, "%0.2f", floatValue);
+ tempStr = g_strdup(buffer);
+ g_value_set_string(value, tempStr);
+ g_free(tempStr);
+ break;
+ case GNC_BUDGET_TREE_MODEL_COL_FREQ:
+ /*g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "");*/
+ g_value_init (value, G_TYPE_STRING);
+ freqStr = g_string_sized_new(16);
+ xaccFreqSpecGetFreqStr(gnc_budget_category_get_frequency(category), freqStr);
+ g_value_set_string (value, freqStr->str);
+ break;
+ case GNC_BUDGET_TREE_MODEL_COL_LAST_OVERFLOW:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "0.0");
+ break;
+ case GNC_BUDGET_TREE_MODEL_COL_ACTUAL:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "0.0");
+ break;
+ case GNC_BUDGET_TREE_MODEL_COL_PLANNED:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "0.0");
+ break;
+ case GNC_BUDGET_TREE_MODEL_COL_CUR_OVERFLOW:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "0.0");
+ break;
+ default:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, "0.0");
+ break;
+ }
+
+ LEAVE("category %s, column %d", gnc_budget_category_get_name(category), column);
+}
+
+static gboolean gnc_budget_tree_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ GncBudgetTreeModel *model = GNC_BUDGET_TREE_MODEL(tree_model);
+ int numChildren, index;
+ GncBudgetCategory* parent, *category;
+
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+ g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
+ ENTER("iter_next:category %s", gnc_budget_category_get_name(iter->user_data));
+
+ category = iter->user_data;
+
+ if(category == model->priv->top_category){
+ iter->stamp = 0;
+ LEAVE("failed (1)");
+ return FALSE;
+ }
+
+ parent = gnc_budget_category_get_parent(category);
+
+ numChildren = gnc_budget_category_get_num_children(parent);
+ index = gnc_budget_category_get_index_in_parent_list(category);
+
+ if(index > (numChildren - 2)){
+ iter->stamp = 0;
+ LEAVE("failed (2)");
+ return FALSE;
+ }
+
+ category = gnc_budget_category_get_child(parent, index + 1);
+
+ if(category == NULL){
+ iter->stamp = 0;
+ LEAVE("failed (3)");
+ return FALSE;
+ }
+
+ iter->user_data = category;
+
+ LEAVE("iter_next:category %s", gnc_budget_category_get_name(iter->user_data));
+ return TRUE;
+}
+
+static gboolean gnc_budget_tree_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ GncBudgetCategory* parentCat, *category;
+ GncBudgetTreeModel *model = GNC_BUDGET_TREE_MODEL(tree_model);
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ if (parent == NULL){
+ iter->user_data = model->priv->top_category;
+ iter->stamp = model->stamp;
+ return TRUE;
+ }
+ parentCat = parent->user_data;
+ category = gnc_budget_category_get_child(parentCat, 0);
+
+ if(category == NULL){
+ return FALSE;
+ }
+
+ iter->user_data = category;
+ iter->stamp = model->stamp;
+
+ LEAVE("iter_children");
+ return TRUE;
+}
+
+static gboolean gnc_budget_tree_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GncBudgetTreeModel *model;
+ GncBudgetCategory* category;
+
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(tree_model), FALSE);
+
+ model = GNC_BUDGET_TREE_MODEL(tree_model);
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+ g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
+
+ category = iter->user_data;
+
+ if(gnc_budget_category_get_num_children(category) == 0){
+ LEAVE("no");
+ return FALSE;
+ }
+
+ LEAVE("yes");
+ return TRUE;
+}
+
+static int gnc_budget_tree_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GncBudgetTreeModel *model;
+ GncBudgetCategory* category;
+
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(tree_model), FALSE);
+
+ model = GNC_BUDGET_TREE_MODEL(tree_model);
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+ g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
+
+ category = iter->user_data;
+
+ LEAVE("count is %d", gnc_budget_category_get_num_children(category));
+ return gnc_budget_category_get_num_children(category);
+}
+
+static gboolean gnc_budget_tree_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ int n)
+{
+ GncBudgetTreeModel *model;
+ GncBudgetCategory* category, *parentCat;
+
+ g_return_val_if_fail(GNC_IS_BUDGET_TREE_MODEL(tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ model = GNC_BUDGET_TREE_MODEL(tree_model);
+
+ if (parent == NULL){
+ parentCat = model->priv->top_category;
+ }
+ else{
+ parentCat = parent->user_data;
+ }
+
+ category = gnc_budget_category_get_child(parentCat, n);
+
+ iter->user_data = category;
+ iter->stamp = model->stamp;
+
+ if (iter->user_data == NULL) {
+ iter->stamp = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean gnc_budget_tree_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ GncBudgetTreeModel *model;
+ GncBudgetCategory* category, *parentCat;
+
+ model = GNC_BUDGET_TREE_MODEL(tree_model);
+
+ g_return_val_if_fail(GNC_IS_BUDGET_TREE_MODEL(tree_model), FALSE);
+ g_return_val_if_fail (child != NULL, FALSE);
+ g_return_val_if_fail (child->user_data != NULL, FALSE);
+ g_return_val_if_fail (child->stamp == model->stamp, FALSE);
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+
+ category = child->user_data;
+
+ parentCat = gnc_budget_category_get_parent(category);
+
+ iter->user_data = parentCat;
+ iter->stamp = model->stamp;
+
+ if (iter->user_data == NULL) {
+ iter->stamp = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+
+
+
+/*******************************************************
+ * Public Interface.
+ *
+ * *****************************************************/
+
+GtkTreeModel* gnc_budget_tree_model_new(GncBudget* budget)
+{
+ GncBudgetTreeModel *model;
+
+ ENTER("budget %p", budget);
+
+ /*
+ for (item = active_models; item; item = g_list_next(item)) {
+ model = (GncTreeModelAccount *)item->data;
+ if (model->priv->root == group) {
+ LEAVE("returning existing model %p", model);
+ return GTK_TREE_MODEL(model);
+ }
+ }
+ */
+
+ model = g_object_new (GNC_TYPE_BUDGET_TREE_MODEL, NULL);
+
+ model->priv->budget = budget;
+ printf("Creating dummy category. Budget %p\n", budget);
+ model->priv->top_category = gnc_budget_category_new(gnc_budget_get_book(budget), budget);
+ gnc_budget_category_set_name(model->priv->top_category, "Dummy Category");
+ printf("Adding inflow category...\n");
+ gnc_budget_category_add_child(model->priv->top_category,
+ gnc_budget_get_inflow_category(budget));
+ printf("Adding outflow category...\n");
+ gnc_budget_category_add_child(model->priv->top_category,
+ gnc_budget_get_outflow_category(budget));
+
+ model->priv->balance_category = gnc_budget_category_new(gnc_budget_get_book(budget), budget);
+ gnc_budget_category_set_name(model->priv->balance_category, "Total Budget Balance");
+ gnc_budget_category_add_child(model->priv->top_category, model->priv->balance_category);
+
+ /*
+ priv->event_handler_id =
+ gnc_engine_register_event_handler (gnc_tree_model_account_event_handler, model);
+
+ active_models = g_list_append (active_models, model);
+ */
+
+ LEAVE("model %p", model);
+ return GTK_TREE_MODEL (model);
+
+}
+
+
+GncBudgetCategory* gnc_budget_tree_model_get_category(GncBudgetTreeModel* model, GtkTreeIter* iter)
+{
+ g_return_val_if_fail (GNC_IS_BUDGET_TREE_MODEL(model), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+ g_return_val_if_fail (iter->user_data != NULL, NULL);
+ g_return_val_if_fail (iter->stamp == model->stamp, NULL);
+
+ printf("Category Selected: %s\n", gnc_budget_category_get_name(iter->user_data));
+ return (GncBudgetCategory *) iter->user_data;
+}
--- /dev/null
+++ src/gnome-utils/gnc-budget-tree-model.h
@@ -0,0 +1,91 @@
+/********************************************************************\
+ * gnc-budget-tree-model.h -- Defintion of the tree model for *
+ * budget objects. *
+ * Copyright (C) 09 sep 2003 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome-util
+ * @{ */
+/** @file gnc-budget-tree-model.h
+ * @breif Definition of the tree model for budget objects.
+ * @author Created by Darin Willits 09 sep 2003
+ * @author Copyright (c) 09 sep 2003 Darin Willits <darin at willits.ca>
+ *
+ * Lets try implementing our own GtkTreeModel shall we??
+ */
+
+#ifndef __GNC_BUDGET_TREE_MODEL_H__
+#define __GNC_BUDGET_TREE_MODEL_H__
+
+#include <gtk/gtktreemodel.h>
+#include "gnc-budget.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_BUDGET_TREE_MODEL (gnc_budget_tree_model_get_type ())
+#define GNC_BUDGET_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_BUDGET_TREE_MODEL, GncBudgetTreeModel))
+#define GNC_BUDGET_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_BUDGET_TREE_MODEL, GncBudgetTreeModelClass))
+#define GNC_IS_BUDGET_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_BUDGET_TREE_MODEL))
+#define GNC_IS_BUDGET_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_BUDGET_TREE_MODEL))
+#define GNC_BUDGET_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_BUDGET_TREE_MODEL, GncBudgetTreeModelClass))
+
+/** Column defintions */
+typedef enum{
+ GNC_BUDGET_TREE_MODEL_COL_NAME,
+ GNC_BUDGET_TREE_MODEL_COL_VALUE,
+ GNC_BUDGET_TREE_MODEL_COL_FREQ,
+ GNC_BUDGET_TREE_MODEL_COL_LAST_OVERFLOW,
+ GNC_BUDGET_TREE_MODEL_COL_ACTUAL,
+ GNC_BUDGET_TREE_MODEL_COL_PLANNED,
+ GNC_BUDGET_TREE_MODEL_COL_CUR_OVERFLOW,
+ GNC_BUDGET_TREE_MODEL_COL_EDITABLE,
+ GNC_BUDGET_TREE_MODEL_NUM_STATIC_COLUMNS
+} GncBudgetTreeModelColumns;
+
+
+/** Structure definitions */
+typedef struct GncBudgetTreeModelPrivate GncBudgetTreeModelPrivate;
+
+typedef struct{
+ GtkObject parent;
+
+ GncBudgetTreeModelPrivate *priv;
+
+ int stamp;
+} GncBudgetTreeModel;
+
+typedef struct {
+ GtkObjectClass parent;
+} GncBudgetTreeModelClass;
+
+
+
+/* Standard g_object type */
+GType gnc_budget_tree_model_get_type(void);
+
+/* Create a new GncBudgetTreeModel object. */
+GtkTreeModel* gnc_budget_tree_model_new(GncBudget* budget);
+
+GncBudgetCategory* gnc_budget_tree_model_get_category(GncBudgetTreeModel* model, GtkTreeIter* iter);
+
+G_END_DECLS
+#endif // __GNC_BUDGET_TREE_MODEL_H__
--- /dev/null
+++ src/gnome-utils/gnc-budget-list-tree-model.c
@@ -0,0 +1,572 @@
+/********************************************************************\
+ * gnc-budget-list-tree-model.c -- Implementation of the Budget List*
+ * Tree model. *
+ * Copyright (C) 09 feb 2004 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup gnome-util
+ * @{ */
+/** @file gnc-budget-list-tree-model.c
+ * @breif Implementation of the Budget List Tree model.
+ * @author Created by Darin Willits 09 feb 2004
+ * @author Copyright (c) 09 feb 2004 Darin Willits <darin at willits.ca>
+ *
+ */
+
+
+// Includes
+#include "config.h"
+#include <string.h>
+#include "gnc-trace.h"
+
+#include "gnc-budget-list-tree-model.h"
+#include "gnc-budget-book.h"
+#include "gnc-engine-util.h"
+#include "gnc-event.h"
+
+
+static short module = MOD_GUI;
+
+/** Initialize and clean-up functions. */
+static void gnc_budget_list_tree_model_class_init (GncBudgetListTreeModelClass *klass);
+static void gnc_budget_list_tree_model_init (GncBudgetListTreeModel *model);
+static void gnc_budget_list_tree_model_finalize (GObject *object);
+static void gnc_budget_list_tree_model_destroy (GtkObject *object);
+static void gnc_budget_list_tree_model_gtk_tree_model_init (GtkTreeModelIface *iface);
+
+/* GtkTreeModel Interface functions. */
+static guint gnc_budget_list_tree_model_get_flags (GtkTreeModel *tree_model);
+static int gnc_budget_list_tree_model_get_n_columns (GtkTreeModel *tree_model);
+static GType gnc_budget_list_tree_model_get_column_type (GtkTreeModel *tree_model,
+ int index);
+static gboolean gnc_budget_list_tree_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path);
+static GtkTreePath *gnc_budget_list_tree_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static void gnc_budget_list_tree_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ int column,
+ GValue *value);
+static gboolean gnc_budget_list_tree_model_iter_next (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gboolean gnc_budget_list_tree_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent);
+static gboolean gnc_budget_list_tree_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static int gnc_budget_list_tree_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter);
+static gboolean gnc_budget_list_tree_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ int n);
+static gboolean gnc_budget_list_tree_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child);
+static gboolean gnc_budget_list_tree_model_get_iter_from_budget (GncBudgetListTreeModel *model,
+ GncBudget *budget,
+ GtkTreeIter *iter);
+
+static void gnc_budget_list_tree_model_event_handler (GUID *entity, QofIdType type,
+ GNCEngineEventType event_type,
+ gpointer user_data);
+
+/* Private internal data structure. */
+struct GncBudgetListTreeModelPrivate
+{
+ QofBook* book;
+ GList* budgets;
+ gint event_handler_id;
+};
+
+/************************************************************/
+/* g_object required functions */
+/************************************************************/
+
+static GtkObjectClass *parent_class = NULL;
+
+GType
+gnc_budget_list_tree_model_get_type (void)
+{
+ static GType gnc_budget_list_tree_model_type = 0;
+
+ if (gnc_budget_list_tree_model_type == 0) {
+ static const GTypeInfo our_info = {
+ sizeof (GncBudgetListTreeModelClass), /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gnc_budget_list_tree_model_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GncBudgetListTreeModel), /* */
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) gnc_budget_list_tree_model_init
+ };
+
+ static const GInterfaceInfo budget_list_tree_model_info = {
+ (GInterfaceInitFunc) gnc_budget_list_tree_model_gtk_tree_model_init,
+ NULL,
+ NULL
+ };
+
+ gnc_budget_list_tree_model_type = g_type_register_static (GTK_TYPE_OBJECT,
+ "GncBudgetListTreeModel",
+ &our_info, 0);
+
+ g_type_add_interface_static (gnc_budget_list_tree_model_type,
+ GTK_TYPE_TREE_MODEL,
+ &budget_list_tree_model_info);
+ }
+
+ return gnc_budget_list_tree_model_type;
+}
+
+static void
+gnc_budget_list_tree_model_class_init (GncBudgetListTreeModelClass *klass)
+{
+ GObjectClass *o_class;
+ GtkObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ o_class = G_OBJECT_CLASS (klass);
+ object_class = GTK_OBJECT_CLASS (klass);
+
+ /* GObject signals */
+ o_class->finalize = gnc_budget_list_tree_model_finalize;
+
+ /* GtkObject signals */
+ object_class->destroy = gnc_budget_list_tree_model_destroy;
+}
+
+static void
+gnc_budget_list_tree_model_init (GncBudgetListTreeModel *model)
+{
+ ENTER("model %p", model);
+ while (model->stamp == 0) {
+ model->stamp = g_random_int ();
+ }
+
+ model->priv = g_new0 (GncBudgetListTreeModelPrivate, 1);
+ model->priv->book = NULL;
+ LEAVE(" ");
+}
+
+static void
+gnc_budget_list_tree_model_finalize (GObject *object)
+{
+ GncBudgetListTreeModel *model;
+
+ ENTER("model %p", object);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL (object));
+
+ model = GNC_BUDGET_LIST_TREE_MODEL(object);
+ g_free (model->priv);
+
+ if (G_OBJECT_CLASS (parent_class)->finalize)
+ (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+ LEAVE(" ");
+}
+
+static void
+gnc_budget_list_tree_model_destroy (GtkObject *object)
+{
+ GncBudgetListTreeModel *model;
+
+ ENTER("model %p", object);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(object));
+
+ model = GNC_BUDGET_LIST_TREE_MODEL(object);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ LEAVE(" ");
+}
+
+/******************************************************
+ * GtkTreeModel Interface Methods.
+ *
+ * ****************************************************/
+
+static void gnc_budget_list_tree_model_gtk_tree_model_init(GtkTreeModelIface *iface)
+{
+ iface->get_flags = gnc_budget_list_tree_model_get_flags;
+ iface->get_n_columns = gnc_budget_list_tree_model_get_n_columns;
+ iface->get_column_type = gnc_budget_list_tree_model_get_column_type;
+ iface->get_iter = gnc_budget_list_tree_model_get_iter;
+ iface->get_path = gnc_budget_list_tree_model_get_path;
+ iface->get_value = gnc_budget_list_tree_model_get_value;
+ iface->iter_next = gnc_budget_list_tree_model_iter_next;
+ iface->iter_children = gnc_budget_list_tree_model_iter_children;
+ iface->iter_has_child = gnc_budget_list_tree_model_iter_has_child;
+ iface->iter_n_children = gnc_budget_list_tree_model_iter_n_children;
+ iface->iter_nth_child = gnc_budget_list_tree_model_iter_nth_child;
+ iface->iter_parent = gnc_budget_list_tree_model_iter_parent;
+}
+
+static guint gnc_budget_list_tree_model_get_flags (GtkTreeModel *tree_model)
+{
+ return 0;
+}
+
+static int gnc_budget_list_tree_model_get_n_columns (GtkTreeModel *tree_model)
+{
+ return GNC_BUDGET_LIST_TREE_MODEL_NUM_COLUMNS;
+}
+
+static GType gnc_budget_list_tree_model_get_column_type (GtkTreeModel *tree_model, int index)
+{
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(tree_model), G_TYPE_INVALID);
+ //g_return_val_if_fail ((index < GNC_BUDGET_TREE_MODEL_NUM_COLUMNS) && (index >= 0), G_TYPE_INVALID);
+
+ return G_TYPE_STRING;
+/*
+ switch (index) {
+ case GNC_BUDGET_TREE_MODEL_COL_NAME:
+ case GNC_BUDGET_TREE_MODEL_COL_VALUE:
+ case GNC_BUDGET_TREE_MODEL_COL_FREQ:
+ return G_TYPE_STRING;
+ default:
+ g_assert_not_reached ();
+ return G_TYPE_INVALID;
+ }
+*/
+}
+
+static gboolean gnc_budget_list_tree_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ GncBudgetListTreeModel *model = GNC_BUDGET_LIST_TREE_MODEL (tree_model);
+ guint i;
+
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(model), FALSE);
+ g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
+
+ if (model->priv->budgets == NULL)
+ return FALSE;
+
+ i = gtk_tree_path_get_indices (path)[0];
+
+ g_return_val_if_fail (i >= 0 && i < g_list_length (model->priv->budgets), FALSE);
+
+ iter->stamp = model->stamp;
+ iter->user_data = g_list_nth(model->priv->budgets, i);
+
+ if (iter->user_data == NULL) {
+ iter->stamp = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GtkTreePath *gnc_budget_list_tree_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ GncBudgetListTreeModel *model = GNC_BUDGET_LIST_TREE_MODEL(tree_model);
+ GtkTreePath *path;
+
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(model), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+ g_return_val_if_fail (iter->user_data != NULL, NULL);
+ g_return_val_if_fail (iter->stamp == model->stamp, NULL);
+
+ if (model->priv->budgets== NULL)
+ return NULL;
+
+ path = gtk_tree_path_new ();
+
+ gtk_tree_path_append_index (path, g_list_position (model->priv->budgets, iter->user_data));
+
+ return path;
+
+}
+
+static void gnc_budget_list_tree_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ int column,
+ GValue *value)
+{
+ GncBudgetListTreeModel* model = GNC_BUDGET_LIST_TREE_MODEL(tree_model);
+ GncBudget* budget;
+
+ g_return_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(model));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (iter->user_data != NULL);
+ g_return_if_fail (iter->stamp == model->stamp);
+
+ budget = (GncBudget*)((GList*)iter->user_data)->data;
+
+ switch (column) {
+ case GNC_BUDGET_LIST_TREE_MODEL_COL_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, gnc_budget_get_name(budget));
+ break;
+ case GNC_BUDGET_LIST_TREE_MODEL_COL_DESCRIPTION:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string(value, gnc_budget_get_description(budget));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gboolean gnc_budget_list_tree_model_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ GncBudgetListTreeModel *model = GNC_BUDGET_LIST_TREE_MODEL(tree_model);
+
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+ g_return_val_if_fail (iter->stamp == model->stamp, FALSE);
+
+ if (g_list_next (iter->user_data) == NULL)
+ return FALSE;
+
+ iter->user_data = g_list_next(iter->user_data);
+
+ return TRUE;
+}
+
+static gboolean gnc_budget_list_tree_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ GncBudgetListTreeModel *model = GNC_BUDGET_LIST_TREE_MODEL(tree_model);
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ if (parent != NULL){
+ return FALSE;
+ }
+
+ iter->user_data = model->priv->budgets;
+ iter->stamp = model->stamp;
+
+ return TRUE;
+}
+
+static gboolean gnc_budget_list_tree_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static int gnc_budget_list_tree_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(tree_model), FALSE);
+
+ if (iter == NULL)
+ return g_list_length (GNC_BUDGET_LIST_TREE_MODEL(tree_model)->priv->budgets);
+
+ g_return_val_if_fail (GNC_BUDGET_LIST_TREE_MODEL(tree_model)->stamp == iter->stamp, -1);
+
+ return 0;
+}
+
+static gboolean gnc_budget_list_tree_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ int n)
+{
+ GncBudgetListTreeModel *model;
+
+ g_return_val_if_fail(GNC_IS_BUDGET_LIST_TREE_MODEL(tree_model), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ model = GNC_BUDGET_LIST_TREE_MODEL(tree_model);
+
+ if (parent != NULL){
+ return FALSE;
+ }
+
+ g_return_val_if_fail (n >= 0 && n < (int)g_list_length (model->priv->budgets), FALSE);
+
+ iter->stamp = model->stamp;
+ iter->user_data = g_list_nth (model->priv->budgets, n);
+
+
+ if (iter->user_data == NULL) {
+ iter->stamp = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean gnc_budget_list_tree_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+/*
+ * Convert a model/account pair into a gtk_tree_model_iter. This
+ * routine should only be called from the file
+ * gnc-tree-view-account.c.
+ */
+gboolean
+gnc_budget_list_tree_model_get_iter_from_budget (GncBudgetListTreeModel *model,
+ GncBudget *budget,
+ GtkTreeIter *iter)
+{
+
+ ENTER("model %p, budget %p, iter %p", model, budget, iter);
+ g_return_val_if_fail (GNC_IS_BUDGET_LIST_TREE_MODEL(model), FALSE);
+ g_return_val_if_fail ((budget != NULL), FALSE);
+ g_return_val_if_fail ((iter != NULL), FALSE);
+
+ if (model->priv->book != gnc_budget_get_book(budget)) {
+ LEAVE("Books don't match");
+ return FALSE;
+ }
+
+ iter->user_data = g_list_find(model->priv->budgets, budget);
+ iter->stamp = model->stamp;
+
+ return TRUE;
+}
+
+
+
+
+/*******************************************************
+ * Public Interface.
+ *
+ * *****************************************************/
+
+GtkTreeModel* gnc_budget_list_tree_model_new(QofBook* book)
+{
+ GncBudgetListTreeModel *model;
+
+ model = g_object_new (GNC_TYPE_BUDGET_LIST_TREE_MODEL, NULL);
+
+ model->priv->book = book;
+ model->priv->budgets = gnc_book_get_budgets(book);
+
+ model->priv->event_handler_id =
+ gnc_engine_register_event_handler (gnc_budget_list_tree_model_event_handler, model);
+
+ return GTK_TREE_MODEL (model);
+}
+
+
+void gnc_budget_list_tree_model_event_handler (GUID *entity, QofIdType type,
+ GNCEngineEventType event_type,
+ gpointer user_data)
+{
+ GncBudgetListTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GncBudget *budget;
+ const gchar *budget_name;
+
+ /* hard failures */
+ g_return_if_fail(GNC_IS_BUDGET_LIST_TREE_MODEL(user_data));
+
+ /* soft failures */
+ if (safe_strcmp(type, GNC_ID_BUDGET) != 0)
+ return;
+
+ ENTER("entity %p of type %s, event %d, model %p",
+ entity, type, event_type, user_data);
+ model = (GncBudgetListTreeModel*)user_data;
+
+ /* Get the account.*/
+ /* DRH - Put the book in the model private data so this code
+ * supports multiple simultaneous books. */
+ budget = gnc_budget_lookup(entity, model->priv->book);
+ budget_name = gnc_budget_get_name(budget);
+
+ switch (event_type) {
+ case GNC_EVENT_ADD:
+ /* Tell the filters/views where the new account was added. */
+ DEBUG("add budget %p (%s)", budget, budget_name);
+
+ /* We have to get the new list of budgets since it has now probably
+ * changed. */
+ model->priv->budgets = gnc_book_get_budgets(model->priv->book);
+
+ if (gnc_budget_list_tree_model_get_iter_from_budget (model, budget, &iter)) {
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL(model), path, &iter);
+ //gnc_tree_model_account_path_changed (model, path);
+ gtk_tree_path_free(path);
+ }
+ break;
+
+ case GNC_EVENT_REMOVE:
+ /* Record the path of this account for later use in destruction
+ DEBUG("remove account %p (%s)", account, account_name);
+ path = gnc_tree_model_account_get_path_from_account (model, account);
+ if (path == NULL) {
+ LEAVE("account not in model");
+ return;
+ }
+
+ data = malloc(sizeof(*data));
+ data->guid = *entity;
+ data->model = model;
+ data->path = path;
+ pending_removals = g_slist_append (pending_removals, data);
+ LEAVE(" ");
+ */
+ return;
+
+ case GNC_EVENT_MODIFY:
+ /*DEBUG("change account %p (%s)", account, account_name);
+ path = gnc_tree_model_account_get_path_from_account (model, account);
+ if (path == NULL) {
+ LEAVE("account not in model");
+ return;
+ }
+ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(model), &iter, path)) {
+ gtk_tree_path_free(path);
+ LEAVE("can't find iter for path");
+ return;
+ }
+ gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &iter);
+ gtk_tree_path_free(path);
+ LEAVE(" ");*/
+ return;
+
+ case GNC_EVENT_DESTROY:
+ /* Tell the filters/view the account has been deleted. */
+ /*DEBUG("destroy account %p (%s)", account, account_name);
+ g_slist_foreach (pending_removals,
+ (GFunc)gnc_tree_model_account_delete_event_helper,
+ entity);*/
+ break;
+
+ default:
+ LEAVE("ignored event for %p (%s)", budget, budget_name);
+ return;
+ }
+ LEAVE(" new stamp %u", model->stamp);
+
+}
+
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Makefile.am,v
retrieving revision 1.48.2.22
retrieving revision 1.48.2.23
diff -Lsrc/gnome-utils/Makefile.am -Lsrc/gnome-utils/Makefile.am -u -r1.48.2.22 -r1.48.2.23
--- src/gnome-utils/Makefile.am
+++ src/gnome-utils/Makefile.am
@@ -39,6 +39,8 @@
druid-utils.c \
gnc-account-sel.c \
gnc-amount-edit.c \
+ gnc-budget-list-tree-model.c \
+ gnc-budget-tree-model.c \
gnc-commodity-edit.c \
gnc-currency-edit.c \
gnc-date-delta.c \
@@ -90,6 +92,8 @@
dialog-utils.h \
druid-utils.h \
gnc-account-sel.h \
+ gnc-budget-list-tree-model.h \
+ gnc-budget-tree-model.h \
gnc-amount-edit.h \
gnc-commodity-edit.h \
gnc-currency-edit.h \
--- /dev/null
+++ src/gnome-utils/gnc-budget-list-tree-model.h
@@ -0,0 +1,87 @@
+/********************************************************************\
+ * gnc-budget-list-tree-model.h -- Tree Model for the internal list *
+ * of budgets. *
+ * Copyright (C) 09 feb 2004 Darin Willits <darin at willits.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 *
+ * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
+ * Boston, MA 02111-1307, USA gnu at gnu.org *
+ * *
+\********************************************************************/
+
+/** @addtogroup engine
+ * @{ */
+/** @file gnc-budget-list-tree-model.h
+ * @breif The tree model which represents the internal list of Budget
+ * objects.
+ * @author Created by Darin Willits 09 feb 2004
+ * @author Copyright (c) 09 feb 2004 Darin Willits <darin at willits.ca>
+ *
+ */
+
+
+#ifndef __GNC_BUDGET_LIST_TREE_MODEL_H__
+#define __GNC_BUDGET_LIST_TREE_MODEL_H__
+
+#include <gtk/gtktreemodel.h>
+#include "qofbook.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_BUDGET_LIST_TREE_MODEL (gnc_budget_list_tree_model_get_type ())
+#define GNC_BUDGET_LIST_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_BUDGET_LIST_TREE_MODEL, GncBudgetListTreeModel))
+#define GNC_BUDGET_LIST_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_BUDGET_LIST_TREE_MODEL, GncBudgetListTreeModelClass))
+#define GNC_IS_BUDGET_LIST_TREE_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_BUDGET_LIST_TREE_MODEL))
+#define GNC_IS_BUDGET_LIST_TREE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_BUDGET_LIST_TREE_MODEL))
+#define GNC_BUDGET_LIST_TREE_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_BUDGET_LIST_TREE_MODEL, GncBudgetListTreeModelClass))
+
+/** Column defintions */
+typedef enum{
+ GNC_BUDGET_LIST_TREE_MODEL_COL_NAME,
+ GNC_BUDGET_LIST_TREE_MODEL_COL_DESCRIPTION,
+ GNC_BUDGET_TREE_MODEL_COL_EDITABLE,
+ GNC_BUDGET_LIST_TREE_MODEL_NUM_COLUMNS,
+} GncBudgetListTreeModelColumns;
+
+
+/** Structure definitions */
+typedef struct GncBudgetListTreeModelPrivate GncBudgetListTreeModelPrivate;
+
+typedef struct{
+ GtkObject parent;
+
+ GncBudgetListTreeModelPrivate *priv;
+
+ int stamp;
+} GncBudgetListTreeModel;
+
+typedef struct {
+ GtkObjectClass parent;
+} GncBudgetListTreeModelClass;
+
+
+
+/* Standard g_object type */
+GType gnc_budget_list_tree_model_get_type(void);
+
+/* Create a new GncBudgetTreeModel object. */
+GtkTreeModel* gnc_budget_list_tree_model_new(QofBook* book);
+
+G_END_DECLS
+
+
+#endif // __GNC_BUDGET_LIST_TREE_MODEL_H__
More information about the gnucash-changes
mailing list