r14852 - gnucash/branches/sx-cleanup - New, simplified implementation of the SinceLastRun dialog. Extensions of GncSxInstanceModel to support (variable parsing, single/flat upcoming-instance list).

Joshua Sled jsled at cvs.gnucash.org
Sat Sep 16 14:56:47 EDT 2006


Author: jsled
Date: 2006-09-16 14:56:44 -0400 (Sat, 16 Sep 2006)
New Revision: 14852
Trac: http://svn.gnucash.org/trac/changeset/14852

Added:
   gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.c
   gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.h
Modified:
   gnucash/branches/sx-cleanup/ChangeLog
   gnucash/branches/sx-cleanup/src/doc/sx.rst
   gnucash/branches/sx-cleanup/src/engine/SchedXaction.h
   gnucash/branches/sx-cleanup/src/gnome/Makefile.am
   gnucash/branches/sx-cleanup/src/gnome/dialog-sx-editor.c
   gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.c
   gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.h
   gnucash/branches/sx-cleanup/src/gnome/glade/sched-xact.glade
   gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-basic-commands.c
   gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.c
   gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.h
Log:
New, simplified implementation of the SinceLastRun dialog.  Extensions of GncSxInstanceModel to support (variable parsing, single/flat upcoming-instance list).

2006-09-16  Joshua Sled  <jsled at asynchronous.org>

	* src/gnome/gnc-plugin-page-sx-list.c (sxsl_get_sx_vars): Add
	variable extraction to instance-model creation.  The
	GncSxInstances now has a hashtable of variables parsed from the
	formula, and the GncSxInstance has a copy of that variables hash.
	Not finished, but mostly in place.

	* src/gnome/dialog-sx-since-last-run.c: New, simplified version of
	the since-last-run dialog.  GncSxSlrTreeModelAdapter.


Modified: gnucash/branches/sx-cleanup/ChangeLog
===================================================================
--- gnucash/branches/sx-cleanup/ChangeLog	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/ChangeLog	2006-09-16 18:56:44 UTC (rev 14852)
@@ -1,3 +1,14 @@
+2006-09-16  Joshua Sled  <jsled at asynchronous.org>
+
+	* src/gnome/gnc-plugin-page-sx-list.c (sxsl_get_sx_vars): Add
+	variable extraction to instance-model creation.  The
+	GncSxInstances now has a hashtable of variables parsed from the
+	formula, and the GncSxInstance has a copy of that variables hash.
+	Not finished, but mostly in place.
+
+	* src/gnome/dialog-sx-since-last-run.c: New, simplified version of
+	the since-last-run dialog.  GncSxSlrTreeModelAdapter.
+
 2006-07-27  Joshua Sled  <jsled at asynchronous.org>
 
 	* src/gnome-utils/gnc-dense-cal.c

Modified: gnucash/branches/sx-cleanup/src/doc/sx.rst
===================================================================
--- gnucash/branches/sx-cleanup/src/doc/sx.rst	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/doc/sx.rst	2006-09-16 18:56:44 UTC (rev 14852)
@@ -1,8 +1,8 @@
 Scheduled Transactions
-======================
+===============================================================
 
 Overview
---------
+--------------
 
 - SX List
   - CRUD operations on SXes
@@ -16,15 +16,22 @@
     - gnc_sx_get_instances(now)
 
 TODO
-----
+----------
 
-- [x] sx list -> qof collection
-- [ ] sx engine events
-  - [x] sx list collection add/remove -- sx-list GNC_EVENT_ITEM_ADDED, _REMOVED
-  - [ ] sx modified -- QOF_EVENT_MODIFY
+- meta
+  - [ ] move files around
+  - [ ] GncSxListTreeModelAdapter: s/real/adapted/
 
+- core
+  - [x] sx list -> qof collection
+  - [ ] sx engine events
+    - [x] sx list collection add/remove -- sx-list GNC_EVENT_ITEM_ADDED, _REMOVED
+    - [ ] sx modified -- QOF_EVENT_MODIFY
+  - [ ] sx upcoming instance model
+    - [ ] implement sort model
+
 - gnc_dense_cal
-  - change number-month properties to display (width, length)
+  - [ ] change number-of-month properties to display-named properties (width, length)
   - [x] set_model(GncTemporalInstancesModel *mdl)
     - [x] new interface creation.
     - [x] register callbacks for signals
@@ -32,32 +39,118 @@
 - sx-from-trans
   - [ ] convert to GObject, hookup destroy/finalize
 
-- transaction creation
-  - verification routine
-    - variable binding/requirements.
-  - actual creation
-    - error handling
+- use Recurrence instead of Freq Spec
+  - [ ] XML migration, handling
 
-- stateful editing of instances in since-last-run dialog
-  - postponed/ignored/to-create constraints
-    - processed_valid_reminders_list, contiguous-date logic
-  - postponed/ignored/to-create transitions [?]
-  - "allowed to finish" decision.
+- since-last-run
+  - [ ] add reminders, postponed to SxInstanceModel
+  - [ ] add obsolete flag to SxInstanceModel
+  - [ ] add mutation support to sx instance model
+    - [ ] state machine
+  - [ ] add variable state to sx instance model
+  - [ ] add sx_upcoming_instance_model()
+      - [ ] add effect_auto_create()
+  - [ ] add some sort of "ready to go" flag and api
+    - [ ] variable setting, primarily
+  - [ ] some sort of commit_changes()
+    - ??? does effect_auto_create() imply or need commit_changes()?
+  - [/] add variable table to instances
 
 Pedantic Todo
-----------------
+----------------------
 
 - s/SchedXaction/Scheduled/
 - s/temporal_state/instance_sequence_context/
+- change instance variable from 'i' to '__i' or something
 
-GtkTreeModelIface
------------------
 
-- signals
-  - row_changed : sx_updated
-  - row_inserted : sx_created
-  - row_has_child_toggled : are there any children, here?
-  - row_deleted : sx_deleted
-  - rows_reordered : ???
+============================================================
 
-- GtkTreeSortableIface
+(eventually real documentation... (?))
+
+Since Last Run
+----------------------
+
++------------------+------------------+------------------+
+|      Thing       |      State       |      Value       |
++------------------+------------------+------------------+
+| - Foo            |                  |                  |
++------------------+------------------+------------------+
+|   - 2006-08-27   |  [Postponed|v]   |                  |
++------------------+------------------+------------------+
+|     - variable-a |                  |        42        |
++------------------+------------------+------------------+
+|     - variable-b |                  |        75        |
++------------------+------------------+------------------+
+|   - 2006-08-27   |  [To-Create|v]   |                  |
++------------------+------------------+------------------+
+|     - variable-a |                  |        31        |
++------------------+------------------+------------------+
+|     - variable-b |                  |  (value needed)  |
++------------------+------------------+------------------+
+
+
+The since-last-run dialog is a key user interface.  More frequently than the
+SX list or editor, the user will be in the process of creating transaction
+instances through this interface.
+
+The old SLR dialog has the following stages:
+
+- Reminders
+  - can be promoted to "to-create"
+- Auto-created, with notification
+- To-Create
+  - postponed, to-create
+  - ignore state.
+- Created review
+- Obsolete SX cleanup
+
+The new SLR dialog will have the following:
+
+- Creation
+  (treemodel consisting of)
+  - auto-created
+  - reminder
+  - postponed
+  - to-create
+  - [obsolete SX]?
+
+There is no seperate to-review page.
+
+Upcoming instance states
+---------------------------------------
+
+    reminder -> to-create
+    postponed -> to-create
+    to-create -> postponed  (with constraints)
+    to-create -> ignore
+
+Definitions:
+
+    reminder: a transient upcoming transaction that will not be created.
+    postponed: a historical to-create transaction that the user has
+        explicitly deferred.
+    to-create: an upcoming SX instance that should be created.
+    ignore: a scheduled instance the user has explicitly prevented the
+        instantiation of.
+
+What does the SX need to store?
+- postponed instance list.
+- last state of created instance.
+
+    void gnc_sx_instance_model_change_state(sx_id, instance_id, new_state, **gerror)
+    boolean gnc_sx_instance_model_get_readiness(sx_id, instance_id)
+    boolean gnc_sx_instance_model_set_variables(sx_id, instance_id, variable_name:string, value:string, **gerrror)
+
+Formula Parsing
+------------------------
+
+A SXes formula is parsed in the context of:
+- the template transaction
+  - the accounts of the splits
+- the sequence number
+- the date of the transaction
+- a variable-binding table.
+
+
+

Modified: gnucash/branches/sx-cleanup/src/engine/SchedXaction.h
===================================================================
--- gnucash/branches/sx-cleanup/src/engine/SchedXaction.h	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/engine/SchedXaction.h	2006-09-16 18:56:44 UTC (rev 14852)
@@ -199,7 +199,7 @@
 
  This is a date-sorted state-data instance list.
  The list should not be modified by the caller; use the
- gnc_sx_{add,remove}_defer_instance() functions to modifiy the list.
+ gnc_sx_{add,remove}_defer_instance() functions to modify the list.
 */
 GList *gnc_sx_get_defer_instances( SchedXaction *sx );
 

Modified: gnucash/branches/sx-cleanup/src/gnome/Makefile.am
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/Makefile.am	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/Makefile.am	2006-09-16 18:56:44 UTC (rev 14852)
@@ -43,6 +43,7 @@
   dialog-sx-editor.c \
   dialog-sx-from-trans.c \
   dialog-sxsincelast.c \
+  dialog-sx-since-last-run.c \
   dialog-tax-info.c \
   dialog-userpass.c \
   druid-acct-period.c \
@@ -82,6 +83,7 @@
   dialog-sx-editor.h \
   dialog-sx-from-trans.h \
   dialog-sxsincelast.h \
+  dialog-sx-since-last-run.h \
   druid-acct-period.h \
   druid-hierarchy.h \
   druid-merge.h \

Modified: gnucash/branches/sx-cleanup/src/gnome/dialog-sx-editor.c
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/dialog-sx-editor.c	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/dialog-sx-editor.c	2006-09-16 18:56:44 UTC (rev 14852)
@@ -58,6 +58,7 @@
 
 /* FIXME: temp until variable-related-stuff settled. */
 #include "dialog-sxsincelast.h"
+#include "dialog-sx-since-last-run.h"
 
 #ifdef HAVE_LANGINFO_D_FMT
 #include <langinfo.h>

Added: gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.c
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.c	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.c	2006-09-16 18:56:44 UTC (rev 14852)
@@ -0,0 +1,502 @@
+/********************************************************************\
+ * dialog-sx-since-last-run.c : dialog for scheduled transaction    *
+ * since-last-run processing.                                       *
+ * Copyright (C) 2006 Joshua Sled <jsled at asynchronous.org>          *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of version 2 of the GNU General Public *
+ * License as published by the Free Software Foundation.            *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#include "config.h"
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <glade/glade-xml.h>
+
+#include "dialog-utils.h"
+#include "gnc-plugin-page-sx-list.h"
+#include "dialog-sx-since-last-run.h"
+
+typedef struct _GncSxSlrTreeModelAdapter GncSxSlrTreeModelAdapter;
+
+struct _GncSxSinceLastRunDialog
+{
+     GtkWidget *dialog;
+     GncSxInstanceModel *instances;
+     GncSxSlrTreeModelAdapter *editing_model;
+     GtkTreeView *instance_view;
+};
+
+/* ------------------------------------------------------------ */
+
+struct _GncSxSlrTreeModelAdapter
+{
+     GObject parent;
+
+     /* protected */
+     GncSxInstanceModel *instances;
+     GtkTreeStore *real;
+};
+
+typedef struct _GncSxSlrTreeModelAdapterClass
+{
+     GObjectClass parent;
+} GncSxSlrTreeModelAdapterClass;
+
+GType gnc_sx_slr_tree_model_adapter_get_type(void);
+static void gnc_sx_slr_tree_model_adapter_class_init(GncSxSlrTreeModelAdapterClass *klass);
+static void gnc_sx_slr_tree_model_adapter_interface_init(gpointer g_iface, gpointer iface_data);
+static void gnc_sx_slr_tree_model_adapter_init(GTypeInstance *instance, gpointer klass);
+GncSxSlrTreeModelAdapter* gnc_sx_slr_tree_model_adapter_new(GncSxInstanceModel *instances);
+
+GncSxInstances* gnc_sx_slr_tree_model_adapter_get_sx_instances(GncSxSlrTreeModelAdapter *model, GtkTreeIter *iter);
+
+#define GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER	      (gnc_sx_slr_tree_model_adapter_get_type ())
+#define GNC_SX_SLR_TREE_MODEL_ADAPTER(obj)	      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapter))
+#define GNC_SX_SLR_TREE_MODEL_ADAPTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapterClass))
+#define GNC_IS_SX_SLR_TREE_MODEL_ADAPTER(obj)	      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER))
+#define GNC_IS_SX_SLR_TREE_MODEL_ADAPTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER))
+#define GNC_SX_SLR_TREE_MODEL_ADAPTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, GncSxSlrTreeModelAdapterClass))
+
+/* ------------------------------------------------------------ */
+
+static void _cell_visibility_func(GtkTreeViewColumn *tree_column,
+                                  GtkCellRenderer *cell,
+                                  GtkTreeModel *tree_model,
+                                  GtkTreeIter *iter,
+                                  gpointer data);
+
+GType
+gnc_sx_slr_tree_model_adapter_get_type(void)
+{
+     static GType type = 0;
+     if (type == 0) {
+          static const GTypeInfo info = {
+               sizeof (GncSxSlrTreeModelAdapterClass),
+               NULL,   /* base_init */
+               NULL,   /* base_finalize */
+               (GClassInitFunc)gnc_sx_slr_tree_model_adapter_class_init,   /* class_init */
+               NULL,   /* class_finalize */
+               NULL,   /* class_data */
+               sizeof (GncSxSlrTreeModelAdapter),
+               0,      /* n_preallocs */
+               (GInstanceInitFunc)gnc_sx_slr_tree_model_adapter_init    /* instance_init */
+          };
+          static const GInterfaceInfo itreeModel_info = {
+               (GInterfaceInitFunc) gnc_sx_slr_tree_model_adapter_interface_init,    /* interface_init */
+               NULL,               /* interface_finalize */
+               NULL                /* interface_data */
+          };
+
+          type = g_type_register_static (G_TYPE_OBJECT,
+                                         "GncSxSlrTreeModelAdapterType",
+                                         &info, 0);
+          g_type_add_interface_static(type,
+                                      GTK_TYPE_TREE_MODEL,
+                                      &itreeModel_info);
+     }
+     return type;
+}
+
+static void
+gnc_sx_slr_tree_model_adapter_class_init(GncSxSlrTreeModelAdapterClass *klass)
+{
+     ; /* nop */
+}
+
+static GtkTreeModelFlags
+gsslrtma_get_flags(GtkTreeModel *tree_model)
+{
+     return gtk_tree_model_get_flags(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real));
+}
+
+static gint
+gsslrtma_get_n_columns(GtkTreeModel *tree_model)
+{
+     return gtk_tree_model_get_n_columns(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real));
+}
+
+static GType
+gsslrtma_get_column_type(GtkTreeModel *tree_model, gint index)
+{
+     return gtk_tree_model_get_column_type(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), index);
+}
+
+static gboolean
+gsslrtma_get_iter(GtkTreeModel *tree_model,
+                GtkTreeIter *iter,
+                GtkTreePath *path)
+{
+     return gtk_tree_model_get_iter(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, path);
+}
+
+static GtkTreePath*
+gsslrtma_get_path(GtkTreeModel *tree_model,
+                GtkTreeIter *iter)
+{
+     return gtk_tree_model_get_path(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
+}
+
+static void
+gsslrtma_get_value(GtkTreeModel *tree_model,
+                 GtkTreeIter *iter,
+                 gint column,
+                 GValue *value)
+{
+     gtk_tree_model_get_value(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, column, value);
+}
+
+static gboolean
+gsslrtma_iter_next(GtkTreeModel *tree_model,
+                 GtkTreeIter *iter)
+{
+     return gtk_tree_model_iter_next(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
+}
+
+static gboolean
+gsslrtma_iter_children(GtkTreeModel *tree_model,
+                     GtkTreeIter *iter,
+                     GtkTreeIter *parent)
+{
+     return gtk_tree_model_iter_children(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, parent);
+}
+
+static gboolean
+gsslrtma_iter_has_child(GtkTreeModel *tree_model,
+                      GtkTreeIter *iter)
+{
+     return gtk_tree_model_iter_has_child(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
+}
+
+static gint
+gsslrtma_iter_n_children(GtkTreeModel *tree_model,
+                       GtkTreeIter *iter)
+{
+     return gtk_tree_model_iter_n_children(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
+}
+
+static gboolean
+gsslrtma_iter_nth_child(GtkTreeModel *tree_model,
+                      GtkTreeIter *iter,
+                      GtkTreeIter *parent,
+                      gint n)
+{
+     return gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, parent, n);
+}
+
+static gboolean
+gsslrtma_iter_parent(GtkTreeModel *tree_model,
+                   GtkTreeIter *iter,
+                   GtkTreeIter *child)
+{
+     return gtk_tree_model_iter_parent(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter, child);
+}
+
+static void
+gsslrtma_ref_node(GtkTreeModel *tree_model,
+                GtkTreeIter *iter)
+{
+     gtk_tree_model_ref_node(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
+}
+
+static void
+gsslrtma_unref_node(GtkTreeModel *tree_model,
+                  GtkTreeIter *iter)
+{
+     gtk_tree_model_unref_node(GTK_TREE_MODEL(GNC_SX_SLR_TREE_MODEL_ADAPTER(tree_model)->real), iter);
+}
+
+static void
+gnc_sx_slr_tree_model_adapter_interface_init(gpointer g_iface, gpointer iface_data)
+{
+     GtkTreeModelIface *tree_model = (GtkTreeModelIface*)g_iface;
+     tree_model->get_flags = gsslrtma_get_flags;
+     tree_model->get_n_columns = gsslrtma_get_n_columns;
+     tree_model->get_column_type = gsslrtma_get_column_type;
+     tree_model->get_iter = gsslrtma_get_iter;
+     tree_model->get_path = gsslrtma_get_path;
+     tree_model->get_value = gsslrtma_get_value;
+     tree_model->iter_next = gsslrtma_iter_next;
+     tree_model->iter_children = gsslrtma_iter_children;
+     tree_model->iter_has_child = gsslrtma_iter_has_child;
+     tree_model->iter_n_children = gsslrtma_iter_n_children;
+     tree_model->iter_nth_child = gsslrtma_iter_nth_child;
+     tree_model->iter_parent = gsslrtma_iter_parent;
+     tree_model->ref_node = gsslrtma_ref_node;
+     tree_model->unref_node = gsslrtma_unref_node;
+}
+
+static void
+gsslrtma_proxy_row_changed(GtkTreeModel *treemodel,
+                         GtkTreePath *arg1,
+                         GtkTreeIter *arg2,
+                         gpointer user_data)
+{
+     g_signal_emit_by_name(user_data, "row-changed", arg1, arg2);
+}
+
+static void
+gsslrtma_proxy_row_deleted(GtkTreeModel *treemodel,
+                         GtkTreePath *arg1,
+                         gpointer user_data)
+{
+     g_signal_emit_by_name(user_data, "row-deleted", arg1);
+}
+
+static void
+gsslrtma_proxy_row_has_child_toggled(GtkTreeModel *treemodel,
+                                   GtkTreePath *arg1,
+                                   GtkTreeIter *arg2,
+                                   gpointer user_data)
+{
+     g_signal_emit_by_name(user_data, "row-has-child-toggled", arg1, arg2);
+}
+
+static void
+gsslrtma_proxy_row_inserted(GtkTreeModel *treemodel,
+                          GtkTreePath *arg1,
+                          GtkTreeIter *arg2,
+                          gpointer user_data)
+{
+     g_signal_emit_by_name(user_data, "row-inserted", arg1, arg2);
+}
+
+static void
+gsslrtma_proxy_rows_reordered(GtkTreeModel *treemodel,
+                            GtkTreePath *arg1,
+                            GtkTreeIter *arg2,
+                            gpointer arg3,
+                            gpointer user_data)
+{
+     g_signal_emit_by_name(user_data, "rows-reordered", arg1, arg2, arg3);
+}
+
+static void
+gnc_sx_slr_tree_model_adapter_init(GTypeInstance *instance, gpointer klass)
+{
+     GncSxSlrTreeModelAdapter *adapter = GNC_SX_SLR_TREE_MODEL_ADAPTER(instance);
+     // columns:    thing-name, instance-state, variable-value
+     // at depth=0: <sx>,       N/A,            N/A
+     // at depth=1: <instance>, <state>,        N/A
+     // at depth=2: <variable>, N/A,            <value>
+     adapter->real = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+     g_signal_connect(adapter->real, "row-changed", G_CALLBACK(gsslrtma_proxy_row_changed), adapter);
+     g_signal_connect(adapter->real, "row-deleted", G_CALLBACK(gsslrtma_proxy_row_deleted), adapter);
+     g_signal_connect(adapter->real, "row-has-child-toggled", G_CALLBACK(gsslrtma_proxy_row_has_child_toggled), adapter);
+     g_signal_connect(adapter->real, "row-inserted", G_CALLBACK(gsslrtma_proxy_row_inserted), adapter);
+     g_signal_connect(adapter->real, "rows-reordered", G_CALLBACK(gsslrtma_proxy_rows_reordered), adapter);
+}
+
+static void
+_build_variable_name_list(gpointer key, gpointer value, gpointer user_data)
+{
+     GList **name_list = (GList**)user_data;
+     *name_list = g_list_append(*name_list, key);
+}
+
+/* @@fixme: i18n. **/
+/* @@fixme: non-staticize. **/
+static char* gnc_sx_instance_type_names[] = {
+     ("Ignored"),
+     ("Postponed"),
+     ("To-Create"),
+     ("Reminder"),
+     NULL
+};
+
+static void
+gsslrtma_populate_tree_store(GncSxSlrTreeModelAdapter *model)
+{
+     GtkTreeIter sx_iter;
+     GList *list;
+
+     for (list = model->instances->sx_instance_list; list != NULL; list = list->next)
+     {
+          GncSxInstances *instances = (GncSxInstances*)list->data;
+          FreqSpec *fs;
+          GString *frequency_str;
+          char last_occur_date_buf[MAX_DATE_LENGTH+1];
+          char next_occur_date_buf[MAX_DATE_LENGTH+1];
+
+          frequency_str = g_string_sized_new(32);
+          fs = xaccSchedXactionGetFreqSpec(instances->sx);
+          xaccFreqSpecGetFreqStr(fs, frequency_str);
+
+          {
+               GDate *last_occur = xaccSchedXactionGetLastOccurDate(instances->sx);
+               if (last_occur == NULL || !g_date_valid(last_occur))
+               {
+                    g_stpcpy(last_occur_date_buf, "never");
+               }
+               else
+               {
+                    qof_print_gdate(last_occur_date_buf,
+                                    MAX_DATE_LENGTH,
+                                    last_occur);
+               }
+          }
+
+          qof_print_gdate(next_occur_date_buf, MAX_DATE_LENGTH, &instances->next_instance_date);
+
+          gtk_tree_store_append(model->real, &sx_iter, NULL);
+          gtk_tree_store_set(model->real, &sx_iter,
+                             0, xaccSchedXactionGetName(instances->sx),
+                             1, NULL,
+                             2, NULL,
+                             -1);
+          g_string_free(frequency_str, TRUE);
+
+          // Insert instance information
+          {
+               GList *inst_iter;
+               GtkTreeIter inst_tree_iter;
+               char instance_date_buf[MAX_DATE_LENGTH+1];
+
+               for (inst_iter = instances->list; inst_iter != NULL; inst_iter = inst_iter->next)
+               {
+                    GncSxInstance *inst = (GncSxInstance*)inst_iter->data;
+                    qof_print_gdate(instance_date_buf, MAX_DATE_LENGTH, &inst->date);
+                    gtk_tree_store_append(model->real, &inst_tree_iter, &sx_iter);
+                    gtk_tree_store_set(model->real, &inst_tree_iter,
+                                       0, instance_date_buf,
+                                       1, gnc_sx_instance_type_names[inst->type],
+                                       2, NULL,
+                                       -1);
+
+                    // Insert variable information
+                    {
+                         GList *names = NULL, *names_iter;
+                         GtkTreeIter var_iter;
+
+                         g_hash_table_foreach(inst->variable_bindings, _build_variable_name_list, &names);
+                         for (names_iter = names; names_iter != NULL; names_iter = names_iter->next)
+                         {
+                              gtk_tree_store_append(model->real, &var_iter, &inst_tree_iter);
+                              gtk_tree_store_set(model->real, &var_iter,
+                                                 0, (gchar*)names_iter->data,
+                                                 1, NULL,
+                                                 2, "(@fixme - value)"
+                                                 -1);
+                         }
+                    }
+               }
+          }
+     }
+}
+
+static void
+gsslrtma_updated_cb(GncSxInstanceModel *instances, gpointer user_data)
+{
+     GncSxSlrTreeModelAdapter *model = GNC_SX_SLR_TREE_MODEL_ADAPTER(user_data);
+     printf("update\n");
+     gtk_tree_store_clear(model->real);
+     gsslrtma_populate_tree_store(model);
+}
+
+GncSxSlrTreeModelAdapter*
+gnc_sx_slr_tree_model_adapter_new(GncSxInstanceModel *instances)
+{
+     GncSxSlrTreeModelAdapter *rtn;
+     rtn = GNC_SX_SLR_TREE_MODEL_ADAPTER(g_object_new(GNC_TYPE_SX_SLR_TREE_MODEL_ADAPTER, NULL));
+     rtn->instances = instances;
+     gsslrtma_populate_tree_store(rtn);
+     g_signal_connect(G_OBJECT(rtn->instances), "updated", (GCallback)gsslrtma_updated_cb, (gpointer)rtn);
+     return rtn;
+}
+
+
+void
+gnc_sx_sxsincelast_book_opened(void)
+{
+     // Get the instance model
+     // check for mumble and futz
+     // maybe create dialog.
+     printf("not ready\n");
+     //gnc_ui_sxsincelast_dialog_create();
+}
+
+gint
+gnc_ui_sxsincelast_dialog_create(void)
+{
+     GDate now;
+     GncSxInstanceModel *model;
+     g_date_clear(&now, 1);
+     g_date_set_time_t(&now, time(NULL));
+     model = gnc_sx_get_instances(&now);
+     gnc_ui_sx_since_last_run_dialog(model);
+     return 1;
+}
+
+GncSxSinceLastRunDialog*
+gnc_ui_sx_since_last_run_dialog(GncSxInstanceModel *model)
+{
+     GncSxSinceLastRunDialog *dialog;
+     GladeXML *glade;
+
+     dialog = g_new0(GncSxSinceLastRunDialog, 1);
+     dialog->instances = model;
+
+     glade = gnc_glade_xml_new("sched-xact.glade", "since-last-run-dialog");
+     dialog->dialog = glade_xml_get_widget(glade, "since-last-run-dialog");
+
+     dialog->editing_model = gnc_sx_slr_tree_model_adapter_new(model);
+
+     {
+          GtkCellRenderer *renderer;
+          GtkTreeViewColumn *col;
+          int position = -1;
+          
+          dialog->instance_view = GTK_TREE_VIEW(glade_xml_get_widget(glade, "instance_view"));
+          gtk_tree_view_set_model(dialog->instance_view, GTK_TREE_MODEL(dialog->editing_model));
+
+          renderer = gtk_cell_renderer_text_new();
+          col = gtk_tree_view_column_new_with_attributes("SX, Instance, Variable", renderer, "text", ++position, NULL);
+          gtk_tree_view_append_column(dialog->instance_view, col);
+
+          renderer = gtk_cell_renderer_text_new();
+          col = gtk_tree_view_column_new_with_attributes("Instance State", renderer, "text", ++position, NULL);
+          gtk_tree_view_column_set_cell_data_func(col, renderer, _cell_visibility_func, GINT_TO_POINTER(position), NULL);
+          gtk_tree_view_append_column(dialog->instance_view, col);
+
+          renderer = gtk_cell_renderer_text_new();
+          col = gtk_tree_view_column_new_with_attributes("Variable Value", renderer, "text", ++position, NULL);
+          gtk_tree_view_column_set_cell_data_func(col, renderer, _cell_visibility_func, GINT_TO_POINTER(position), NULL);
+          gtk_tree_view_append_column(dialog->instance_view, col);
+     }
+
+     gtk_widget_show_all(dialog->dialog);
+
+     return dialog;
+}
+
+
+static void
+_cell_visibility_func(GtkTreeViewColumn *tree_column,
+                      GtkCellRenderer *cell,
+                      GtkTreeModel *tree_model,
+                      GtkTreeIter *iter,
+                      gpointer data)
+{
+     GtkTreePath *path;
+     int select_depth, path_depth;
+
+     select_depth = GPOINTER_TO_INT(data);
+     path = gtk_tree_model_get_path(tree_model, iter);
+     path_depth = gtk_tree_path_get_depth(path);
+     // printf("item depth: %d\n", path_depth);
+     g_object_set(G_OBJECT(cell), "visible", path_depth == select_depth ? TRUE : FALSE, NULL);
+}
+

Added: gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.h
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.h	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/dialog-sx-since-last-run.h	2006-09-16 18:56:44 UTC (rev 14852)
@@ -0,0 +1,50 @@
+/********************************************************************\
+ * dialog-sx-since-last-run.h : dialog for scheduled transaction    *
+ * since-last-run processing.                                       *
+ * Copyright (C) 2006 Joshua Sled <jsled at asynchronous.org>          *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of version 2 of the GNU General Public *
+ * License as published by the Free Software Foundation.            *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#ifndef DIALOG_SX_SINCE_LAST_RUN_H
+#define DIALOG_SX_SINCE_LAST_RUN_H
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "SchedXaction.h"
+#include "gnc-plugin-page-sx-list.h"
+
+typedef struct _GncSxSinceLastRunDialog GncSxSinceLastRunDialog;
+
+/**
+ * This encapsulates the "run when file opened" application logic.  As such,
+ * it should probably move to a non-ui file.
+ **/
+void gnc_sx_sxsincelast_book_opened(void);
+
+/**
+ * Create the since-last-run dialog from the given instance-model.
+ **/
+GncSxSinceLastRunDialog*  gnc_ui_sx_since_last_run_dialog(GncSxInstanceModel *model);
+
+// @@fixme: resurect, fix return type.
+gint gnc_ui_sxsincelast_dialog_create( void );
+
+
+#endif

Modified: gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.c
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.c	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.c	2006-09-16 18:56:44 UTC (rev 14852)
@@ -406,6 +406,7 @@
 /**
  * Used to wrap for the book-open hook, where the book filename is given.
  **/
+#if 0
 void
 gnc_sx_sxsincelast_book_opened (void)
 {
@@ -427,8 +428,8 @@
        -(ret));
   }
 }
+#endif // 0 
 
-
 static gboolean
 show_handler (const char *class, gint component_id,
               gpointer user_data, gpointer iter_data)
@@ -455,6 +456,7 @@
  * [e.g., for book-open-hook: do nothing; for menu-selection: display an info
  *  dialog stating there's nothing to do.]
  **/
+#if 0
 gint
 gnc_ui_sxsincelast_dialog_create()
 {
@@ -488,6 +490,7 @@
         sxsincelast_init( sxsld );
         return autoCreateCount;
 }
+#endif //0
 
 static void 
 clist_set_all_cols_autoresize( GtkCList *cl, guint n_cols )
@@ -1698,6 +1701,10 @@
         reminderInstanceTuple *rit;
         void *seqStateData;
 
+        void *foo = sxsincelast_init;
+        foo = sxsincelast_populate;
+        foo = show_handler;
+
         g_assert( g_date_valid(end) );
         g_assert( g_date_valid(reminderEnd) );
 

Modified: gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.h
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.h	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/dialog-sxsincelast.h	2006-09-16 18:56:44 UTC (rev 14852)
@@ -37,8 +37,8 @@
  * [e.g., for book-open-hook: do nothing; for menu-selection: display an info
  *  dialog stating there's nothing to do.]
  **/
-gint gnc_ui_sxsincelast_dialog_create( void );
-void gnc_sx_sxsincelast_book_opened (void);
+//gint gnc_ui_sxsincelast_dialog_create( void );
+//void gnc_sx_sxsincelast_book_opened (void);
 
 /**
  * Returns the varaibles from the Splits of the given SchedXaction as the

Modified: gnucash/branches/sx-cleanup/src/gnome/glade/sched-xact.glade
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/glade/sched-xact.glade	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/glade/sched-xact.glade	2006-09-16 18:56:44 UTC (rev 14852)
@@ -8480,4 +8480,114 @@
   </child>
 </widget>
 
+<widget class="GtkDialog" id="since-last-run-dialog">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Since Last Run...</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+  <property name="modal">False</property>
+  <property name="default_width">640</property>
+  <property name="default_height">480</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">True</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox25">
+      <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_area25">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="cancelbutton1">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="has_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="focus_on_click">True</property>
+	      <property name="response_id">-6</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="okbutton2">
+	      <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="focus_on_click">True</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="GtkVPaned" id="vpaned1">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="position">0</property>
+
+	  <child>
+	    <widget class="GtkScrolledWindow" id="scrolledwindow21">
+	      <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="instance_view">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="has_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="shrink">True</property>
+	      <property name="resize">False</property>
+	    </packing>
+	  </child>
+
+	  <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>
+
 </glade-interface>

Modified: gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-basic-commands.c
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-basic-commands.c	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-basic-commands.c	2006-09-16 18:56:44 UTC (rev 14852)
@@ -42,6 +42,7 @@
 #include "dialog-fincalc.h"
 #include "dialog-find-transactions.h"
 #include "dialog-sxsincelast.h"
+#include "dialog-sx-since-last-run.h"
 #include "dialog-totd.h"
 #include "druid-acct-period.h"
 #include "druid-loan.h"

Modified: gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.c
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.c	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.c	2006-09-16 18:56:44 UTC (rev 14852)
@@ -42,7 +42,11 @@
 #ifndef HAVE_GLIB26
 #include "gkeyfile.h"
 #endif
+#include "gnc-exp-parser.h"
 #include "gnc-engine.h"
+#include "Transaction.h"
+#include "Split.h"
+#include "gnc-commodity.h"
 #include "gnc-event.h"
 #include "gnc-dense-cal.h"
 #include "gnc-icons.h"
@@ -61,10 +65,6 @@
 #define PLUGIN_PAGE_SX_LIST_CM_CLASS "plugin-page-sx-list"
 #define GCONF_SECTION "window/pages/sx_list"
 
-typedef struct _GncSxInstanceDenseCalAdapter GncSxInstanceDenseCalAdapter;
-typedef struct _GncSxInstanceModel GncSxInstanceModel;
-typedef struct _GncSxListTreeModelAdapter GncSxListTreeModelAdapter;
-
 typedef struct GncPluginPageSxListPrivate
 {
      GtkWidget* widget;
@@ -88,62 +88,20 @@
 
 /* ------------------------------------------------------------ */
 
-struct _GncSxInstanceModel
-{
-     GObject parent;
+GType gnc_sx_instance_model_get_type(void);
+static void gnc_sx_instance_model_class_init (GncSxInstanceModelClass *klass);
+static void gnc_sx_instance_model_init(GTypeInstance *instance, gpointer klass);
+static GncSxInstanceModel* gnc_sx_instance_model_new(void);
 
-     /* private */
-     gint qof_event_handler_id;
+static GncSxInstance* gnc_sx_instance_new(GncSxInstances *parent, GncSxInstanceType type, GDate *date, gint sequence_num);
 
-     /* signals */
-     /* void (*added)(GncSxInstance *sx); // gpointer user_data */
-     /* void (*removed)(GncSxInstance *sx); // gpointer user_data */
-     /* void (*changed)(GncSxInstance *inst); // gpointer user_data */
+static void sxsl_get_sx_vars(SchedXaction *sx, GHashTable *var_hash);
+static gint _get_vars_helper(Transaction *txn, void *var_hash_data);
+static void clear_variable_numerics(gpointer key, gpointer value, gpointer data);
+static int parse_vars_from_formula(const char *formula, GHashTable *varHash, gnc_numeric *result);
 
-     /* public */
-     GDate range_end;
-     GList *sx_instance_list; /* <GncSxInstances*> */
-};
+static void gnc_util_copy_hash_table(GHashTable *from, GHashTable *to);
 
-typedef struct _GncSxInstanceModelClass
-{
-     GObjectClass parent;
-
-     guint removing_signal_id;
-     guint updated_signal_id;
-     guint added_signal_id;
-} GncSxInstanceModelClass;
-
-typedef struct _GncSxInstances
-{
-     SchedXaction *sx;
-
-     GDate next_instance_date;
-
-     /** all: <GncSxInstance*> **/
-     GList *ignored;
-     GList *postponed;
-     GList *upcoming;
-     GList *remind;
-} GncSxInstances;
-
-typedef enum 
-{
-     IGNORED, POSTPONED, TO_CREATE, REMINDER, MAX_STATE
-} GncSxInstanceType;
-
-typedef struct _GncSxInstance
-{
-     GncSxInstances *parent;
-     GncSxInstanceType type;
-     GDate date;
-} GncSxInstance;
-
-GType gnc_sx_instance_model_get_type(void);
-static void gnc_sx_instance_model_class_init (GncSxInstanceModelClass *klass);
-static void gnc_sx_instance_model_init(GTypeInstance *instance, gpointer klass);
-GncSxInstanceModel* gnc_sx_instance_model_new(void);
-
 static void _gnc_sx_instance_event_handler(QofEntity *ent, QofEventId event_type, gpointer user_data, gpointer evt_data);
 
 #define GNC_TYPE_SX_INSTANCE_MODEL	      (gnc_sx_instance_model_get_type ())
@@ -246,7 +204,6 @@
 
 static void gppsl_row_activated_cb(GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data);
 
-
 /* Callbacks */
 static void gnc_plugin_page_sx_list_cmd_new(GtkAction *action, GncPluginPageSxList *page);
 static void gnc_plugin_page_sx_list_cmd_edit(GtkAction *action, GncPluginPageSxList *page);
@@ -806,6 +763,169 @@
 
 /* ------------------------------------------------------------ */
 
+static int
+parse_vars_from_formula(const char *formula,
+                        GHashTable *varHash,
+                        gnc_numeric *result)
+{
+     gnc_numeric num;
+     char *errLoc;
+     int toRet = 0;
+
+     if (!gnc_exp_parser_parse_separate_vars(formula, &num, &errLoc, varHash))
+     {
+          toRet = -1;
+     }
+
+     if (result != NULL)
+     {
+          *result = num;
+     }
+
+     return toRet;
+}
+
+static void
+clear_variable_numerics(gpointer key, gpointer value, gpointer data)
+{
+     g_free((gnc_numeric*)value);
+     g_hash_table_insert((GHashTable*)data, key, NULL);
+}
+
+static gint
+_get_vars_helper(Transaction *txn, void *var_hash_data)
+{
+     GHashTable *var_hash = (GHashTable*)var_hash_data;
+     GList *split_list;
+     kvp_frame *kvpf;
+     kvp_value *kvp_val;
+     Split *s;
+     char *str;
+     gnc_commodity *first_cmdty = NULL;
+
+     split_list = xaccTransGetSplitList(txn);
+     if (split_list == NULL)
+     {
+          return 1;
+     }
+
+     for ( ; split_list; split_list = split_list->next)
+     {
+          gnc_commodity *split_cmdty = NULL;
+          GUID *acct_guid;
+          Account *acct;
+
+          s = (Split*)split_list->data;
+          kvpf = xaccSplitGetSlots(s);
+          kvp_val = kvp_frame_get_slot_path(kvpf,
+                                            GNC_SX_ID,
+                                            GNC_SX_ACCOUNT,
+                                            NULL);
+          acct_guid = kvp_value_get_guid(kvp_val);
+          acct = xaccAccountLookup(acct_guid, gnc_get_current_book());
+          split_cmdty = xaccAccountGetCommodity(acct);
+          if (first_cmdty == NULL)
+          {
+               first_cmdty = split_cmdty;
+          }
+                
+          if (! gnc_commodity_equal(split_cmdty, first_cmdty))
+          {
+               gnc_numeric *tmp_num;
+               GString *var_name = g_string_sized_new(16);
+               g_string_printf(var_name, "%s -> %s",
+                               gnc_commodity_get_mnemonic(split_cmdty),
+                               gnc_commodity_get_mnemonic(first_cmdty));
+               tmp_num = g_new0(gnc_numeric, 1);
+               *tmp_num = gnc_numeric_create(0, 1);
+               g_hash_table_insert(var_hash, g_strdup(var_name->str), tmp_num);
+               g_string_free(var_name, TRUE);
+          }
+
+          // existing... ------------------------------------------
+          kvp_val = kvp_frame_get_slot_path(kvpf,
+                                            GNC_SX_ID,
+                                            GNC_SX_CREDIT_FORMULA,
+                                            NULL);
+          if (kvp_val != NULL)
+          {
+               str = kvp_value_get_string(kvp_val);
+               if (str && strlen(str) != 0)
+               {
+                    parse_vars_from_formula(str, var_hash, NULL);
+               }
+          }
+
+          kvp_val = kvp_frame_get_slot_path(kvpf,
+                                            GNC_SX_ID,
+                                            GNC_SX_DEBIT_FORMULA,
+                                            NULL);
+          if (kvp_val != NULL)
+          {
+               str = kvp_value_get_string(kvp_val);
+               if (str && strlen(str) != 0)
+               {
+                    parse_vars_from_formula(str, var_hash, NULL);
+               }
+          }
+     }
+
+     return 0;
+}
+
+static void
+sxsl_get_sx_vars(SchedXaction *sx, GHashTable *var_hash)
+{
+     AccountGroup *template_group;
+     Account *sx_template_acct;
+     const char *sx_guid_str;
+
+     template_group = gnc_book_get_template_group(gnc_get_current_book());
+     sx_guid_str = guid_to_string(xaccSchedXactionGetGUID(sx));
+     /* Get account named after guid string. */
+     sx_template_acct = xaccGetAccountFromName(template_group, sx_guid_str);
+     xaccAccountForEachTransaction(sx_template_acct, _get_vars_helper, var_hash);
+
+     // @@fixme - This should actually create GncSxVariable structures.
+     g_hash_table_foreach(var_hash, clear_variable_numerics, (gpointer)var_hash);
+}
+
+static void
+_clone_hash_entry(gpointer key, gpointer value, gpointer user_data)
+{
+     GHashTable *to = (GHashTable*)user_data;
+     g_hash_table_insert(to, key, value);
+}
+
+static void
+gnc_util_copy_hash_table(GHashTable *from, GHashTable *to)
+{
+     g_hash_table_foreach(from, _clone_hash_entry, (gpointer)to);
+}
+
+static GncSxInstance*
+gnc_sx_instance_new(GncSxInstances *parent, GncSxInstanceType type, GDate *date, gint sequence_num)
+{
+     GncSxInstance *rtn = g_new0(GncSxInstance, 1);
+     rtn->parent = parent;
+     rtn->type = type;
+     g_date_clear(&rtn->date, 1);
+     rtn->date = *date;
+
+     if (! parent->variable_names_parsed)
+     {
+          parent->variable_names = g_hash_table_new(g_str_hash, g_str_equal);
+          sxsl_get_sx_vars(parent->sx, parent->variable_names);
+          parent->variable_names_parsed = TRUE;
+
+          // @@fixme: add sequence_num as `i`, non-editable
+     }
+
+     rtn->variable_bindings = g_hash_table_new(g_str_hash, g_str_equal);
+     gnc_util_copy_hash_table(parent->variable_names, rtn->variable_bindings);
+     return rtn;
+}
+
 static GncSxInstances*
 _gnc_sx_gen_instances(gpointer *data, gpointer user_data)
 {
@@ -825,7 +945,18 @@
 
      /* postponed */
      {
-          /* @@fixme - defer list. */
+          GList *postponed = gnc_sx_get_defer_instances(sx);
+          for ( ; postponed != NULL; postponed = g_list_next(postponed))
+          {
+               GDate inst_date;
+               int seq_num;
+               GncSxInstance *inst;
+
+               inst_date = xaccSchedXactionGetNextInstance(sx, postponed->data);
+               seq_num = gnc_sx_get_instance_count(sx, postponed->data);
+               inst = gnc_sx_instance_new(instances, POSTPONED, &inst_date, seq_num);
+               instances->list = g_list_append(instances->list, inst);
+          }
      }
 
      /* to-create */
@@ -833,19 +964,13 @@
      sequence_ctx = gnc_sx_create_temporal_state(sx);
      cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx);
      instances->next_instance_date = cur_date;
-
-     while (g_date_valid(&cur_date)
-            && (g_date_compare(&cur_date, &creation_end) <= 0))
+     while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &creation_end) <= 0)
      {
           GncSxInstance *inst;
-          inst = g_new0(GncSxInstance, 1);
-          inst->parent = instances;
-          inst->type = TO_CREATE;
-          g_date_clear(&inst->date, 1);
-          inst->date = cur_date;
-
-          instances->upcoming = g_list_append(instances->upcoming, inst);
-
+          int seq_num;
+          seq_num = gnc_sx_get_instance_count(sx, sequence_ctx);
+          inst = gnc_sx_instance_new(instances, TO_CREATE, &cur_date, seq_num);
+          instances->list = g_list_append(instances->list, inst);
           gnc_sx_incr_temporal_state(sx, sequence_ctx);
           cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx);
      }
@@ -854,14 +979,10 @@
      while (g_date_valid(&cur_date) && g_date_compare(&cur_date, &remind_end) <= 0)
      {
           GncSxInstance *inst;
-          inst = g_new0(GncSxInstance, 1);
-          inst->parent = instances;
-          inst->type = REMINDER;
-          g_date_clear(&inst->date, 1);
-          inst->date = cur_date;
-
-          instances->remind = g_list_append(instances->remind, inst);
-
+          int seq_num;
+          seq_num = gnc_sx_get_instance_count(sx, sequence_ctx);
+          inst = gnc_sx_instance_new(instances, REMINDER, &cur_date, seq_num);
+          instances->list = g_list_append(instances->list, inst);
           gnc_sx_incr_temporal_state(sx, sequence_ctx);
           cur_date = xaccSchedXactionGetInstanceAfter(sx, &cur_date, sequence_ctx);
      }
@@ -886,7 +1007,7 @@
      return instances;
 }
 
-GncSxInstanceModel*
+static GncSxInstanceModel*
 gnc_sx_instance_model_new(void)
 {
      return GNC_SX_INSTANCE_MODEL(g_object_new(GNC_TYPE_SX_INSTANCE_MODEL, NULL));
@@ -1204,7 +1325,7 @@
           = (GncSxInstances*)g_list_find_custom(adapter->instances->sx_instance_list, GUINT_TO_POINTER(tag), gsidca_find_sx_with_tag)->data;
      if (insts == NULL)
           return 0;
-     return g_list_length(insts->upcoming);
+     return g_list_length(insts->list);
 }
 
 static void
@@ -1216,7 +1337,7 @@
           = (GncSxInstances*)g_list_find_custom(adapter->instances->sx_instance_list, GUINT_TO_POINTER(tag), gsidca_find_sx_with_tag)->data;
      if (insts == NULL)
           return;
-     inst = (GncSxInstance*)g_list_nth_data(insts->upcoming, instance_index);
+     inst = (GncSxInstance*)g_list_nth_data(insts->list, instance_index);
      g_date_valid(&inst->date);
      *date = inst->date;
      g_date_valid(date);

Modified: gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.h
===================================================================
--- gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.h	2006-09-15 21:11:56 UTC (rev 14851)
+++ gnucash/branches/sx-cleanup/src/gnome/gnc-plugin-page-sx-list.h	2006-09-16 18:56:44 UTC (rev 14852)
@@ -32,6 +32,8 @@
 #ifndef __GNC_PLUGIN_PAGE_SX_LIST_H
 #define __GNC_PLUGIN_PAGE_SX_LIST_H
 
+#include "config.h"
+#include <glib/gi18n.h>
 #include <gtk/gtkwindow.h>
 #include "SchedXaction.h"
 #include "gnc-plugin-page.h"
@@ -72,6 +74,73 @@
  **/
 GncPluginPage *gnc_plugin_page_sx_list_new  (void);
 
+
+/** ------------------------------------------------------------ **/
+typedef struct _GncSxInstanceDenseCalAdapter GncSxInstanceDenseCalAdapter;
+typedef struct _GncSxInstanceModel GncSxInstanceModel;
+typedef struct _GncSxListTreeModelAdapter GncSxListTreeModelAdapter;
+
+struct _GncSxInstanceModel
+{
+     GObject parent;
+
+     /* private */
+     gint qof_event_handler_id;
+
+     /* signals */
+     /* void (*added)(GncSxInstance *sx); // gpointer user_data */
+     /* void (*removed)(GncSxInstance *sx); // gpointer user_data */
+     /* void (*changed)(GncSxInstance *inst); // gpointer user_data */
+
+     /* public */
+     GDate range_end;
+     GList *sx_instance_list; /* <GncSxInstances*> */
+};
+
+typedef struct _GncSxInstanceModelClass
+{
+     GObjectClass parent;
+
+     guint removing_signal_id;
+     guint updated_signal_id;
+     guint added_signal_id;
+} GncSxInstanceModelClass;
+
+typedef struct _GncSxInstances
+{
+     SchedXaction *sx;
+     GHashTable /** <char*,NULL> **/ *variable_names;
+     gboolean variable_names_parsed;
+     
+     GDate next_instance_date;
+     
+     /** GList<GncSxInstance*> **/
+     GList *list;
+} GncSxInstances;
+
+typedef enum 
+{
+     IGNORED, POSTPONED, TO_CREATE, REMINDER, MAX_STATE
+} GncSxInstanceType;
+
+typedef struct _GncSxVariable
+{
+     GString *name;
+     GString *value;
+     gboolean editable;
+} GncSxVariable;
+
+typedef struct _GncSxInstance
+{
+     GncSxInstances *parent;
+     GncSxInstanceType type;
+     GDate date;
+     GHashTable *variable_bindings;
+} GncSxInstance;
+
+GncSxInstanceModel* gnc_sx_get_instances(GDate *range_end);
+/** ------------------------------------------------------------ **/
+
 G_END_DECLS
 
 #endif /* __GNC_PLUGIN_PAGE_SX_LIST_H */



More information about the gnucash-changes mailing list