r22289 - gnucash/trunk/src - Initial code for a new register.

Geert Janssens gjanssens at code.gnucash.org
Tue Aug 7 13:24:33 EDT 2012


Author: gjanssens
Date: 2012-08-07 13:24:33 -0400 (Tue, 07 Aug 2012)
New Revision: 22289
Trac: http://svn.gnucash.org/trac/changeset/22289

Added:
   gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.c
   gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.h
   gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.c
   gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.h
   gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.c
   gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.h
   gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c
   gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.h
   gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h
   gnucash/trunk/src/gnome/gnc-plugin-page-register2.c
   gnucash/trunk/src/gnome/gnc-plugin-page-register2.h
   gnucash/trunk/src/gnome/gnc-plugin-register2.c
   gnucash/trunk/src/gnome/gnc-plugin-register2.h
   gnucash/trunk/src/gnome/ui/gnc-plugin-page-register2-ui.xml
   gnucash/trunk/src/gnome/ui/gnc-plugin-register2-ui.xml
Modified:
   gnucash/trunk/src/engine/Split.c
   gnucash/trunk/src/engine/Split.h
   gnucash/trunk/src/engine/Transaction.c
   gnucash/trunk/src/engine/Transaction.h
   gnucash/trunk/src/gnome-utils/Makefile.am
   gnucash/trunk/src/gnome-utils/gnc-tree-view.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view.h
   gnucash/trunk/src/gnome/Makefile.am
   gnucash/trunk/src/gnome/gnc-plugin-page-account-tree.c
   gnucash/trunk/src/gnome/top-level.c
   gnucash/trunk/src/gnome/ui/Makefile.am
   gnucash/trunk/src/gnome/ui/gnc-plugin-page-account-tree-ui.xml
Log:
Initial code for a new register.
This is very incomplete, but at the same time well isolated from the
rest of the code, so it is easy to disable should it not get functional
and stable before the next major release.
I decided to include it in trunk to give it more visibility and prevent
bitrot in the patch.

Modified: gnucash/trunk/src/engine/Split.c
===================================================================
--- gnucash/trunk/src/engine/Split.c	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/engine/Split.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -659,7 +659,34 @@
     return TRUE;
 }
 
+
 /********************************************************************
+ * xaccSplitListGetUniqueTransactions
+ ********************************************************************/
+static void
+add_keys_to_list(gpointer key, gpointer val, gpointer list)
+{
+    *(GList **)list = g_list_prepend(*(GList **)list, key);
+}
+
+GList *
+xaccSplitListGetUniqueTransactions(const GList *splits)
+{
+    const GList *node;
+    GList *transList = NULL;
+    GHashTable *transHash = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+    for(node = splits; node; node = node->next) {
+        Transaction *trans = xaccSplitGetParent((Split *)(node->data));
+        g_hash_table_insert(transHash, trans, trans);
+    }
+    g_hash_table_foreach(transHash, add_keys_to_list, &transList);
+    g_hash_table_destroy(transHash);
+    return transList;
+}
+
+
+/********************************************************************
  * Account funcs
  ********************************************************************/
 

Modified: gnucash/trunk/src/engine/Split.h
===================================================================
--- gnucash/trunk/src/engine/Split.h	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/engine/Split.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -343,6 +343,9 @@
 #define      xaccSplitLookupDirect(g,b) xaccSplitLookup(&(g),b)
 
 
+/* Get a GList of unique transactions containing the given list of Splits. */
+GList *xaccSplitListGetUniqueTransactions(const GList *splits);
+
 /**
  * The xaccSplitGetOtherSplit() is a convenience routine that returns
  *    the other of a pair of splits.  If there are more than two

Modified: gnucash/trunk/src/engine/Transaction.c
===================================================================
--- gnucash/trunk/src/engine/Transaction.c	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/engine/Transaction.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -954,6 +954,45 @@
     return total;
 }
 
+gboolean
+xaccTransGetRateForCommodity(const Transaction *trans,
+                             const gnc_commodity *split_com,
+                             const Split *split_to_exclude, gnc_numeric *rate)
+{
+    GList *splits;
+    gnc_commodity *trans_curr;
+
+    trans_curr = xaccTransGetCurrency(trans);
+    if (gnc_commodity_equal(trans_curr, split_com)) {
+        if (rate) 
+            *rate = gnc_numeric_create(1, 1);
+        return TRUE;
+    }
+
+    for (splits = trans->splits; splits; splits = splits->next) {
+        Split *s = splits->data;
+        gnc_commodity *comm;
+
+        if (s == split_to_exclude) continue;
+        if (!xaccTransStillHasSplit(trans, s)) continue;
+
+        comm = xaccAccountGetCommodity(xaccSplitGetAccount(s));
+        if (gnc_commodity_equal(split_com, comm)) {
+            gnc_numeric amt = xaccSplitGetAmount(s);
+            gnc_numeric val = xaccSplitGetValue(s);
+
+            if (!gnc_numeric_zero_p(xaccSplitGetValue(s)) &&
+                !gnc_numeric_zero_p(xaccSplitGetValue(s))) {
+                if (rate) 
+                    *rate = gnc_numeric_div(amt, val, GNC_DENOM_AUTO,
+                                            GNC_HOW_DENOM_REDUCE);
+                return TRUE;
+            }
+        }
+    }
+    return FALSE;
+}
+
 gnc_numeric
 xaccTransGetAccountConvRate(const Transaction *txn, const Account *acc)
 {

Modified: gnucash/trunk/src/engine/Transaction.h
===================================================================
--- gnucash/trunk/src/engine/Transaction.h	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/engine/Transaction.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -264,11 +264,12 @@
  * See #TXN_TYPE_NONE, #TXN_TYPE_INVOICE and #TXN_TYPE_PAYMENT */
 char	      xaccTransGetTxnType (const Transaction *trans);
 
-
 /** Sets the transaction Number (or ID) field*/
 void          xaccTransSetNum (Transaction *trans, const char *num);
+
 /** Sets the transaction Description */
 void          xaccTransSetDescription (Transaction *trans, const char *desc);
+
 /** Sets the transaction Notes
  *
  The Notes field is only visible in the register in double-line mode */
@@ -318,9 +319,8 @@
     this list when you are done with it. */
 /*@ dependent @*/
 SplitList *   xaccTransGetSplitList (const Transaction *trans);
-gboolean xaccTransStillHasSplit(const Transaction *trans, const Split *s);
+gboolean      xaccTransStillHasSplit(const Transaction *trans, const Split *s);
 
-
 /** Set the transaction to be ReadOnly by setting a non-NULL value as "reason".
  *
  * FIXME: If "reason" is NULL, this function does nothing, instead of removing the
@@ -410,6 +410,13 @@
 gnc_numeric xaccTransGetAccountAmount (const Transaction *trans,
                                        const Account *account);
 
+/* Gets the amt/val rate, i.e. rate from the transaction currency to
+   the 'split_com' */
+gboolean
+xaccTransGetRateForCommodity(const Transaction *trans,
+                             const gnc_commodity *split_com,
+                             const Split *split_to_exclude, gnc_numeric *rate);
+
 /* Compute the conversion rate for the transaction to this account.
  * Any "split value" (which is in the transaction currency),
  * multiplied by this conversion rate, will give you the value you

Modified: gnucash/trunk/src/gnome/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/Makefile.am	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome/Makefile.am	2012-08-07 17:24:33 UTC (rev 22289)
@@ -45,10 +45,12 @@
   gnc-plugin-basic-commands.c \
   gnc-plugin-budget.c \
   gnc-plugin-register.c \
+  gnc-plugin-register2.c \
   gnc-plugin-page-account-tree.c \
   gnc-plugin-page-budget.c \
   gnc-plugin-page-sx-list.c \
   gnc-plugin-page-register.c \
+  gnc-plugin-page-register2.c \
   gnc-split-reg.c \
   reconcile-list.c \
   top-level.c \
@@ -81,10 +83,12 @@
   gnc-plugin-basic-commands.h \
   gnc-plugin-budget.h \
   gnc-plugin-register.h \
+  gnc-plugin-register2.h \
   gnc-plugin-page-account-tree.h \
   gnc-plugin-page-budget.h \
   gnc-plugin-page-sx-list.h \
   gnc-plugin-page-register.h \
+  gnc-plugin-page-register2.h \
   gnc-split-reg.h \
   reconcile-list.h \
   top-level.h \

Modified: gnucash/trunk/src/gnome/gnc-plugin-page-account-tree.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-account-tree.c	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-account-tree.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -38,6 +38,7 @@
 #include <glib/gi18n.h>
 #include "gnc-plugin-page-account-tree.h"
 #include "gnc-plugin-page-register.h"
+#include "gnc-plugin-page-register2.h"
 
 #include "Scrub.h"
 #include "Scrub3.h"
@@ -146,6 +147,8 @@
 static void gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page);
 static void gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page);
 
+/* Command callback for new Register Test */
+static void gnc_plugin_page_account_tree_cmd_open2_account (GtkAction *action, GncPluginPageAccountTree *page);
 
 static guint plugin_page_signals[LAST_SIGNAL] = { 0 };
 
@@ -172,6 +175,11 @@
         G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_account)
     },
     {
+        "FileOpenAccount2Action", GNC_STOCK_OPEN_ACCOUNT, N_("Open New Register2 _Account"), NULL,
+        N_("Open the New Register2 selected account"),
+        G_CALLBACK (gnc_plugin_page_account_tree_cmd_open2_account)
+    },
+    {
         "FileOpenSubaccountsAction", GNC_STOCK_OPEN_ACCOUNT, N_("Open _Subaccounts"), NULL,
         N_("Open the selected account and all its subaccounts"),
         G_CALLBACK (gnc_plugin_page_account_tree_cmd_open_subaccounts)
@@ -263,6 +271,7 @@
 static const gchar *actions_requiring_account_always[] =
 {
     "FileOpenAccountAction",
+    "FileOpenAccount2Action",
     "FileOpenSubaccountsAction",
     "ActionsLotsAction",
     NULL
@@ -290,6 +299,7 @@
 static action_toolbar_labels toolbar_labels[] =
 {
     { "FileOpenAccountAction", 	    N_("Open") },
+    { "FileOpenAccount2Action", 	    N_("Open2") },
     { "EditEditAccountAction", 	    N_("Edit") },
     { "FileNewAccountAction",    	    N_("New") },
     { "EditDeleteAccountAction", 	    N_("Delete") },
@@ -775,8 +785,29 @@
     gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
 }
 
+/*#####################################################################*/
+/*                    New Register Common                              */
 static void
-gnc_plugin_page_account_tree_double_click_cb (GtkTreeView        *treeview,
+gppat_open2_account_common (GncPluginPageAccountTree *page,
+                           Account *account,
+                           gboolean include_subs)
+{
+    GncPluginPageAccountTreePrivate *priv;
+    GtkWidget *window;
+    GncPluginPage *new_page;
+
+    if (account == NULL)
+        return;
+
+    priv = GNC_PLUGIN_PAGE_ACCOUNT_TREE_GET_PRIVATE(page);
+    window = GNC_PLUGIN_PAGE (page)->window;
+    new_page = gnc_plugin_page_register2_new (account, include_subs);
+    gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
+}
+/*######################################################################*/
+
+static void
+gnc_plugin_page_account_tree_double_click_cb (GtkTreeView *treeview,
                                               GtkTreePath        *path,
                                               GtkTreeViewColumn  *col,
                                               GncPluginPageAccountTree *page)
@@ -882,7 +913,21 @@
     gppat_open_account_common (page, account, FALSE);
 }
 
+/*#####################################################################*/
+/*          Register Firing - Single Account to start with             */
 static void
+gnc_plugin_page_account_tree_cmd_open2_account (GtkAction *action,
+        GncPluginPageAccountTree *page)
+{
+    Account *account;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE (page));
+    account = gnc_plugin_page_account_tree_get_current_account (page);
+    gppat_open2_account_common (page, account, FALSE);
+}
+/*#####################################################################*/
+
+static void
 gnc_plugin_page_account_tree_cmd_open_subaccounts (GtkAction *action,
         GncPluginPageAccountTree *page)
 {

Added: gnucash/trunk/src/gnome/gnc-plugin-page-register2.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-register2.c	                        (rev 0)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-register2.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,3842 @@
+/**********************************************************************
+ * gnc-plugin-page-register2.c -- register page functions              *
+ *                                                                    *
+ * Copyright (C) 2003 Jan Arne Petersen <jpetersen at uni-bonn.de>       *
+ * Copyright (C) 2003,2005,2006 David Hampton <hampton at employees.org> *
+ * Copyright (C) 2011, Robert Fewell                                  *
+ *                                                                    *
+ * This program is free software; you can redistribute it and/or      *
+ * modify it under the terms of the GNU General Public License as     *
+ * published by the Free Software Foundation; either version 2 of     *
+ * the License, or (at your option) any later version.                *
+ *                                                                    *
+ * This program is distributed in the hope that it will be useful,    *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of     *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
+ * GNU General Public License for more details.                       *
+ *                                                                    *
+ * You should have received a copy of the GNU General Public License  *
+ * along with this program; if not, contact:                          *
+ *                                                                    *
+ * Free Software Foundation           Voice:  +1-617-542-5942         *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652         *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                     *
+ **********************************************************************/
+
+/** @addtogroup ContentPlugins
+    @{ */
+/** @addtogroup RegisterPlugin Register Page
+    @{ */
+/** @file gnc-plugin-page-register.c
+    @brief  Functions providing a register page for the GnuCash UI
+    @author Copyright (C) 2003 Jan Arne Petersen <jpetersen at uni-bonn.de>
+    @author Copyright (C) 2003,2005 David Hampton <hampton at employees.org>
+*/
+
+#include "config.h"
+
+#include <libguile.h>
+#include "guile-mappings.h"
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include "swig-runtime.h"
+
+#include "gnc-plugin-page-register2.h"
+#include "gnc-plugin-register2.h"
+#include "gnc-plugin-menu-additions.h"
+#include "gnc-plugin-page-report.h"
+
+#include "gnc-tree-view.h"
+#include "gnc-tree-view-split-reg.h"
+#include "gnc-tree-model-split-reg.h"
+
+#include "dialog-account.h"
+#include "dialog-find-transactions.h"
+/*#include "dialog-print-check.h" */
+#include "dialog-transfer.h"
+#include "dialog-utils.h"
+#include "assistant-stock-split.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-component-manager.h"
+#include "gnc-date.h"
+#include "gnc-date-edit.h"
+#include "gnc-engine.h"
+#include "gnc-event.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-gnome-utils.h"
+#include "gnc-gobject-utils.h"
+#include "gnc-gui-query.h"
+#include "gnc-icons.h"
+#include "gnc-split-reg.h"
+#include "gnc-ui-util.h"
+#include "gnc-window.h"
+#include "gnc-main-window.h"
+#include "gnc-session.h"
+#include "gnucash-sheet.h"
+#include "dialog-lot-viewer.h"
+#include "Scrub.h"
+#include "qof.h"
+#include "window-reconcile.h"
+#include "window-autoclear.h"
+#include "window-report.h"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_GUI;
+
+#define DEFAULT_LINES_AMOUNT         50
+#define GCONF_SECTION "window/pages/register2"
+
+static void gnc_plugin_page_register2_class_init (GncPluginPageRegister2Class *klass);
+static void gnc_plugin_page_register2_init (GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_finalize (GObject *object);
+
+/* static Account *gnc_plugin_page_register2_get_current_account (GncPluginPageRegister2 *page); */
+
+static GtkWidget *gnc_plugin_page_register2_create_widget (GncPluginPage *plugin_page);
+static void gnc_plugin_page_register2_destroy_widget (GncPluginPage *plugin_page);
+static void gnc_plugin_page_register2_window_changed (GncPluginPage *plugin_page, GtkWidget *window);
+static void gnc_plugin_page_register2_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
+static GncPluginPage *gnc_plugin_page_register2_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
+static void gnc_plugin_page_register2_update_edit_menu (GncPluginPage *page, gboolean hide);
+static gboolean gnc_plugin_page_register2_finish_pending (GncPluginPage *page);
+
+static gchar *gnc_plugin_page_register2_get_tab_name (GncPluginPage *plugin_page);
+static gchar *gnc_plugin_page_register2_get_tab_color (GncPluginPage *plugin_page);
+static gchar *gnc_plugin_page_register2_get_long_name (GncPluginPage *plugin_page);
+
+static void gnc_plugin_page_register2_summarybar_position_changed(GConfEntry *entry, gpointer user_data);
+
+/* Callbacks for the "Sort By" dialog */
+void gnc_plugin_page_register2_sort_button_cb(GtkToggleButton *button, GncPluginPageRegister2 *page);
+void gnc_plugin_page_register2_sort_response_cb(GtkDialog *dialog, gint response, GncPluginPageRegister2 *plugin_page);
+void gnc_plugin_page_register2_sort_order_save_cb(GtkToggleButton *button, GncPluginPageRegister2 *page);
+
+static gchar *gnc_plugin_page_register2_get_sort_order (GncPluginPage *plugin_page);
+void gnc_plugin_page_register2_set_sort_order (GncPluginPage *plugin_page, const gchar *sort_order);
+
+/* Callbacks for the "Filter By" dialog */
+void gnc_plugin_page_register2_filter_select_range_cb(GtkRadioButton *button, GncPluginPageRegister2 *page);
+void gnc_plugin_page_register2_filter_start_cb(GtkWidget *radio, GncPluginPageRegister2 *page);
+void gnc_plugin_page_register2_filter_end_cb(GtkWidget *radio, GncPluginPageRegister2 *page);
+void gnc_plugin_page_register2_filter_response_cb(GtkDialog *dialog, gint response, GncPluginPageRegister2 *plugin_page);
+void gnc_plugin_page_register2_filter_status_all_cb(GtkButton *button, GncPluginPageRegister2 *plugin_page);
+void gnc_plugin_page_register2_filter_status_one_cb(GtkToggleButton *button, GncPluginPageRegister2 *page);
+void gnc_plugin_page_register2_filter_save_cb(GtkToggleButton *button, GncPluginPageRegister2 *page);
+
+static time_t gnc_plugin_page_register2_filter_dmy2time (char *date_string);
+static gchar *gnc_plugin_page_register2_filter_time2dmy (time_t raw_time);
+static gchar *gnc_plugin_page_register2_get_filter (GncPluginPage *plugin_page);
+void gnc_plugin_page_register2_set_filter (GncPluginPage *plugin_page, const gchar *filter);
+
+static void gnc_ppr_update_status_query (GncPluginPageRegister2 *page);
+static void gnc_ppr_update_date_query (GncPluginPageRegister2 *page);
+
+/* Command callbacks */
+static void gnc_plugin_page_register2_cmd_print_check (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_cut (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_copy (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_paste (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_edit_account (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_find_transactions (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_cut_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_copy_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_paste_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_void_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_unvoid_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_reverse_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_shift_transaction_forward (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_view_sort_by (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_view_filter_by (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_style_changed (GtkAction *action, GtkRadioAction *current, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_style_double_line (GtkToggleAction *action, GncPluginPageRegister2 *plugin_page);
+
+static void gnc_plugin_page_register2_cmd_reconcile (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_autoclear (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_transfer (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_stock_split (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_lots (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_enter_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_cancel_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_delete_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_blank_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_duplicate_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_reinitialize_transaction (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_expand_transaction (GtkToggleAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_exchange_rate (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_jump (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_schedule (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_scrub_all (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_scrub_current (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_account_report (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+static void gnc_plugin_page_register2_cmd_transaction_report (GtkAction *action, GncPluginPageRegister2 *plugin_page);
+
+static void gnc_plugin_page_help_changed_cb( GNCSplitReg *gsr, GncPluginPageRegister2 *register_page );
+static void gnc_plugin_page_register2_refresh_cb (GHashTable *changes, gpointer user_data);
+static void gnc_plugin_page_register2_close_cb (gpointer user_data);
+
+static void gnc_plugin_page_register2_ui_update (gpointer various, GncPluginPageRegister2 *page);
+static void gppr_account_destroy_cb (Account *account);
+static void gnc_plugin_page_register2_event_handler (QofInstance *entity,
+        QofEventId event_type,
+        GncPluginPageRegister2 *page,
+        GncEventData *ed);
+
+/************************************************************/
+/*                          Actions                         */
+/************************************************************/
+
+static GtkActionEntry gnc_plugin_page_register2_actions [] =
+{
+    /* File menu */
+
+    {
+        "FilePrintAction", GTK_STOCK_PRINT, N_("_Print Checks..."), "<control>p", NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_print_check)
+    },
+
+    /* Edit menu */
+
+    {
+        "EditCutAction", GTK_STOCK_CUT, N_("Cu_t"), NULL,
+        N_("Cut the current selection and copy it to clipboard"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_cut)
+    },
+    {
+        "EditCopyAction", GTK_STOCK_COPY, N_("_Copy"), NULL,
+        N_("Copy the current selection to clipboard"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_copy)
+    },
+    {
+        "EditPasteAction", GTK_STOCK_PASTE, N_("_Paste"), NULL,
+        N_("Paste the clipboard content at the cursor position"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_paste)
+    },
+    {
+        "EditEditAccountAction", GNC_STOCK_EDIT_ACCOUNT, N_("Edit _Account"), "<control>e",
+        N_("Edit the selected account"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_edit_account)
+    },
+    {
+        "EditFindTransactionsAction", GTK_STOCK_FIND, N_("_Find..."), "<control>f",
+        N_("Find transactions with a search"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_find_transactions)
+    },
+
+    /* Transaction menu */
+
+    {
+        "CutTransactionAction", GTK_STOCK_CUT, N_("Cu_t Transaction"), "",
+        N_("Cut the selected transaction into clipboard"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_cut_transaction)
+    },
+    {
+        "CopyTransactionAction", GTK_STOCK_COPY, N_("_Copy Transaction"), "",
+        N_("Copy the selected transaction into clipboard"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_copy_transaction)
+    },
+    {
+        "PasteTransactionAction", GTK_STOCK_PASTE, N_("_Paste Transaction"), "",
+        N_("Paste the transaction from the clipboard"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_paste_transaction)
+    },
+    {
+        "DuplicateTransactionAction", GTK_STOCK_COPY, N_("Dup_licate Transaction"), "",
+        N_("Make a copy of the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_duplicate_transaction)
+    },
+    {
+        "DeleteTransactionAction", GTK_STOCK_DELETE, N_("_Delete Transaction"), NULL,
+        N_("Delete the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_delete_transaction)
+    },
+    {
+        "RemoveTransactionSplitsAction", GTK_STOCK_CLEAR, N_("Remo_ve Transaction Splits"), NULL,
+        N_("Remove all splits in the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_reinitialize_transaction)
+    },
+    {
+        "RecordTransactionAction", GTK_STOCK_ADD, N_("_Enter Transaction"), NULL,
+        N_("Record the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_enter_transaction)
+    },
+    {
+        "CancelTransactionAction", GTK_STOCK_CANCEL, N_("Ca_ncel Transaction"), NULL,
+        N_("Cancel the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_cancel_transaction)
+    },
+    {
+        "VoidTransactionAction", NULL, N_("_Void Transaction"), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_void_transaction)
+    },
+    {
+        "UnvoidTransactionAction", NULL, N_("_Unvoid Transaction"), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_unvoid_transaction)
+    },
+    {
+        "ReverseTransactionAction", NULL, N_("Add _Reversing Transaction"), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_reverse_transaction)
+    },
+    {
+        "ShiftTransactionForwardAction", NULL, N_("_Shift Transaction Forward"), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_shift_transaction_forward)
+    },
+
+    /* View menu */
+
+    {
+        "ViewSortByAction", NULL, N_("_Sort By..."), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_view_sort_by)
+    },
+    {
+        "ViewFilterByAction", NULL, N_("_Filter By..."), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_view_filter_by)
+    },
+
+    /* Actions menu */
+
+    {
+        "ActionsTransferAction", GNC_STOCK_TRANSFER, N_("_Transfer..."), "<control>t",
+        N_("Transfer funds from one account to another"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_transfer)
+    },
+    {
+        "ActionsReconcileAction", GTK_STOCK_INDEX, N_("_Reconcile..."), NULL,
+        N_("Reconcile the selected account"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_reconcile)
+    },
+    {
+        "ActionsAutoClearAction", GTK_STOCK_INDEX, N_("_Auto-clear..."), NULL,
+        N_("Automatically clear individual transactions, so as to reach a certain cleared amount"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_autoclear)
+    },
+    {
+        "ActionsStockSplitAction", NULL, N_("Stoc_k Split..."), NULL,
+        N_("Record a stock split or a stock merger"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_stock_split)
+    },
+    {
+        "ActionsLotsAction", NULL, N_("View _Lots..."), NULL,
+        N_("Bring up the lot viewer/editor window"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_lots)
+    },
+    {
+        "BlankTransactionAction", GTK_STOCK_GOTO_BOTTOM, N_("_Blank Transaction"), "<control>Page_Down",
+        N_("Move to the blank transaction at the bottom of the register"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_blank_transaction)
+    },
+    {
+        "EditExchangeRateAction", NULL, N_("Edit E_xchange Rate"), NULL,
+        N_("Edit the exchange rate for the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_exchange_rate)
+    },
+    {
+        "JumpTransactionAction", GNC_STOCK_JUMP_TO, N_("_Jump"), NULL,
+        N_("Jump to the corresponding transaction in the other account"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_jump)
+    },
+    {
+        "ScheduleTransactionAction", GNC_STOCK_SCHEDULE, N_("Sche_dule..."), NULL,
+        N_("Create a Scheduled Transaction with the current transaction as a template"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_schedule)
+    },
+    {
+        "ScrubAllAction", NULL, N_("_All transactions"), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_scrub_all)
+    },
+    {
+        "ScrubCurrentAction", NULL, N_("_This transaction"), NULL, NULL,
+        G_CALLBACK (gnc_plugin_page_register2_cmd_scrub_current)
+    },
+
+    /* Reports menu */
+
+    {
+        "ReportsAccountReportAction", NULL, N_("Account Report"), NULL,
+        N_("Open a register report for this Account"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_account_report)
+    },
+    {
+        "ReportsAcctTransReportAction", NULL, N_("Account Transaction Report"), NULL,
+        N_("Open a register report for the selected Transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_transaction_report)
+    },
+};
+
+static guint gnc_plugin_page_register2_n_actions = G_N_ELEMENTS (gnc_plugin_page_register2_actions);
+
+static GtkToggleActionEntry toggle_entries[] =
+{
+    {
+        "ViewStyleDoubleLineAction", NULL, N_("_Double Line"), NULL,
+        N_("Show two lines of information for each transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_style_double_line), FALSE
+    },
+
+    {
+        "SplitTransactionAction", GNC_STOCK_SPLIT_TRANS, N_("S_plit Transaction"), NULL,
+        N_("Show all splits in the current transaction"),
+        G_CALLBACK (gnc_plugin_page_register2_cmd_expand_transaction), FALSE
+    },
+};
+
+static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
+
+static GtkRadioActionEntry radio_entries_2 [] =
+{
+    /* Translators: This is a menu item in the View menu */
+    {
+        "ViewStyleBasicAction", NULL, N_("_Basic Ledger"), NULL,
+        N_("Show transactions on one or two lines"), REG_STYLE_LEDGER
+    },
+    /* Translators: This is a menu item in the View menu */
+    {
+        "ViewStyleAutoSplitAction", NULL, N_("_Auto-Split Ledger"), NULL,
+        N_("Show transactions on one or two lines and expand the current transaction"), REG_STYLE_AUTO_LEDGER
+    },
+    /* Translators: This is a menu item in the View menu */
+    {
+        "ViewStyleJournalAction", NULL, N_("Transaction _Journal"), NULL,
+        N_("Show expanded transactions with all splits"), REG_STYLE_JOURNAL
+    }
+};
+
+static guint n_radio_entries_2 = G_N_ELEMENTS (radio_entries_2);
+
+/** These are the "important" actions provided by the register page.
+ *  Their labels will appear when the toolbar is set to "Icons and
+ *  important text" (e.g. GTK_TOOLBAR_BOTH_HORIZ) mode. */
+static const gchar *important_actions[] =
+{
+    "SplitTransactionAction",
+    NULL,
+};
+
+/** Actions that require an account to be selected before they are
+ *  enabled. */
+static const gchar *actions_requiring_account[] =
+{
+    "EditEditAccountAction",
+    "ActionsReconcileAction",
+    "ActionsAutoClearAction",
+    "ActionsLotsAction",
+    NULL
+};
+
+/** View Style actions */
+static const gchar *view_style_actions[] =
+{
+    "ViewStyleBasicAction",
+    "ViewStyleAutoSplitAction",
+    "ViewStyleJournalAction",
+    NULL
+};
+
+/** Short labels for use on the toolbar buttons. */
+static action_toolbar_labels toolbar_labels[] =
+{
+    { "ActionsTransferAction", 	  N_("Transfer") },
+    { "RecordTransactionAction", 	  N_("Enter") },
+    { "CancelTransactionAction", 	  N_("Cancel") },
+    { "DeleteTransactionAction", 	  N_("Delete") },
+    { "DuplicateTransactionAction", N_("Duplicate") },
+    { "SplitTransactionAction",     N_("Split") },
+    { "ScheduleTransactionAction",  N_("Schedule") },
+    { "BlankTransactionAction",     N_("Blank") },
+    { "ActionsReconcileAction",     N_("Reconcile") },
+    { "ActionsAutoClearAction",     N_("Auto-clear") },
+    { NULL, NULL },
+};
+
+struct status_action
+{
+    const char *action_name;
+    int value;
+    GtkWidget *widget;
+};
+
+static struct status_action status_actions[] =
+{
+    { "filter_status_reconciled",   CLEARED_RECONCILED, NULL },
+    { "filter_status_cleared",      CLEARED_CLEARED, NULL },
+    { "filter_status_voided",       CLEARED_VOIDED, NULL },
+    { "filter_status_frozen",       CLEARED_FROZEN, NULL },
+    { "filter_status_unreconciled", CLEARED_NO, NULL },
+    { NULL, 0, NULL },
+};
+
+#define CLEARED_VALUE "cleared_value"
+#define DEFAULT_FILTER "0x001f"
+#define DEFAULT_SORT_ORDER "BY_STANDARD"
+
+/************************************************************/
+/*                      Data Structures                     */
+/************************************************************/
+
+typedef struct GncPluginPageRegister2Private
+{
+    GNCLedgerDisplay *ledger;
+    GNCSplitReg *gsr;
+
+    GtkWidget *widget;
+
+
+    GncTreeViewSplitReg *tv;
+
+    gint event_handler_id;
+    gint component_manager_id;
+    GncGUID key;  /* The guid of the Account we're watching */
+
+    gint lines_default;
+    gboolean read_only;
+
+    struct
+    {
+        GtkWidget *dialog;
+        SortType original_sort_type;
+        gboolean original_save_order;
+        gboolean save_order;
+    } sd;
+
+    struct
+    {
+        GtkWidget *dialog;
+        GtkWidget *table;
+        GtkWidget *start_date_choose;
+        GtkWidget *start_date_today;
+        GtkWidget *start_date;
+        GtkWidget *end_date_choose;
+        GtkWidget *end_date_today;
+        GtkWidget *end_date;
+        cleared_match_t original_cleared_match;
+        cleared_match_t cleared_match;
+        time_t original_start_time;
+        time_t original_end_time;
+        time_t start_time;
+        time_t end_time;
+        gboolean original_save_filter;
+        gboolean save_filter;
+    } fd;
+} GncPluginPageRegister2Private;
+
+#define GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2Private))
+
+static GObjectClass *parent_class = NULL;
+
+/************************************************************/
+/*                      Implementation                      */
+/************************************************************/
+
+GType
+gnc_plugin_page_register2_get_type (void)
+{
+    static GType gnc_plugin_page_register2_type = 0;
+
+    if (gnc_plugin_page_register2_type == 0)
+    {
+        static const GTypeInfo our_info =
+        {
+            sizeof (GncPluginPageRegister2Class),
+            NULL,
+            NULL,
+            (GClassInitFunc) gnc_plugin_page_register2_class_init,
+            NULL,
+            NULL,
+            sizeof (GncPluginPageRegister2),
+            0,
+            (GInstanceInitFunc) gnc_plugin_page_register2_init
+        };
+
+        gnc_plugin_page_register2_type = g_type_register_static (GNC_TYPE_PLUGIN_PAGE,
+                                        GNC_PLUGIN_PAGE_REGISTER2_NAME,
+                                        &our_info, 0);
+    }
+
+    return gnc_plugin_page_register2_type;
+}
+
+/*#################################################################################*/
+/*#################################################################################*/
+static GncPluginPage *
+gnc_plugin_page_register2_new_common (GNCLedgerDisplay *ledger)
+{
+    GncPluginPageRegister2 *register_page;
+    GncPluginPageRegister2Private *priv;
+    GncPluginPage *plugin_page;
+
+    GncTreeModelSplitReg *model; 
+    GtkTreeView *tv; 
+
+    GNCSplitReg *gsr;
+    SplitRegister *reg;
+    const GList *item;
+    GList *book_list;
+    gchar *label;
+    gchar *label_color;
+    QofQuery *q;
+    Account *account;
+
+g_print("Register New Common\n");
+
+    /* Is there an existing page? */
+    gsr = gnc_ledger_display_get_user_data (ledger);
+    if (gsr)
+    {
+        item = gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_REGISTER2_NAME);
+        for ( ; item; item = g_list_next(item))
+        {
+            register_page = (GncPluginPageRegister2 *)item->data;
+            priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(register_page);
+            if (priv->gsr == gsr)
+                return GNC_PLUGIN_PAGE(register_page);
+        }
+    }
+
+
+    register_page = g_object_new (GNC_TYPE_PLUGIN_PAGE_REGISTER2, NULL);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(register_page);
+    priv->ledger = ledger;
+    priv->key = *guid_null();
+
+    plugin_page = GNC_PLUGIN_PAGE(register_page);
+    label = gnc_plugin_page_register2_get_tab_name(plugin_page);
+    gnc_plugin_page_set_page_name(plugin_page, label);
+    g_free(label);
+
+    label_color = gnc_plugin_page_register2_get_tab_color(plugin_page);
+    gnc_plugin_page_set_page_color(plugin_page, label_color);
+    g_free(label_color);
+
+    label = gnc_plugin_page_register2_get_long_name(plugin_page);
+    gnc_plugin_page_set_page_long_name(plugin_page, label);
+    g_free(label);
+
+/*FIXME New Stuff here */
+
+    q = gnc_ledger_display_get_query (ledger);
+    book_list = qof_query_get_books (q);
+    for (item = book_list; item; item = g_list_next(item))
+        gnc_plugin_page_add_book (plugin_page, (QofBook *)item->data);
+    // Do not free the list. It is owned by the query.
+
+
+/*
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+*/
+
+    account = gnc_plugin_page_register2_get_account (register_page);
+
+    model = gnc_tree_model_split_reg_new_from_account(account);
+    priv->tv = gnc_tree_view_split_reg_new_with_model(model);
+
+
+
+/*    g_object_unref(G_OBJECT(model)); */
+
+
+
+
+
+
+    priv->component_manager_id = 0;
+    return plugin_page;
+}
+/*#################################################################################*/
+
+
+
+GncPluginPage *
+gnc_plugin_page_register2_new (Account *account, gboolean subaccounts)
+{
+    GNCLedgerDisplay *ledger;
+    GncPluginPage *page;
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("account=%p, subaccounts=%s", account,
+          subaccounts ? "TRUE" : "FALSE");
+
+    if (subaccounts)
+        ledger = gnc_ledger_display_subaccounts (account);
+    else
+        ledger = gnc_ledger_display_simple (account);
+
+    page = gnc_plugin_page_register2_new_common(ledger);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    priv->key = *xaccAccountGetGUID(account);
+
+    LEAVE("%p", page);
+    return page;
+}
+
+GncPluginPage *
+gnc_plugin_page_register2_new_gl (void)
+{
+    GNCLedgerDisplay *ledger;
+
+    ledger = gnc_ledger_display_gl ();
+    return gnc_plugin_page_register2_new_common(ledger);
+}
+
+GncPluginPage *
+gnc_plugin_page_register2_new_ledger (GNCLedgerDisplay *ledger)
+{
+    return gnc_plugin_page_register2_new_common(ledger);
+}
+
+static void
+gnc_plugin_page_register2_class_init (GncPluginPageRegister2Class *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GncPluginPageClass *gnc_plugin_class = GNC_PLUGIN_PAGE_CLASS(klass);
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    object_class->finalize = gnc_plugin_page_register2_finalize;
+
+    gnc_plugin_class->tab_icon        = GNC_STOCK_ACCOUNT;
+    gnc_plugin_class->plugin_name     = GNC_PLUGIN_PAGE_REGISTER2_NAME;
+    gnc_plugin_class->create_widget   = gnc_plugin_page_register2_create_widget;
+    gnc_plugin_class->destroy_widget  = gnc_plugin_page_register2_destroy_widget;
+    gnc_plugin_class->window_changed  = gnc_plugin_page_register2_window_changed;
+    gnc_plugin_class->save_page       = gnc_plugin_page_register2_save_page;
+    gnc_plugin_class->recreate_page   = gnc_plugin_page_register2_recreate_page;
+    gnc_plugin_class->update_edit_menu_actions = gnc_plugin_page_register2_update_edit_menu;
+    gnc_plugin_class->finish_pending  = gnc_plugin_page_register2_finish_pending;
+
+    g_type_class_add_private(klass, sizeof(GncPluginPageRegister2Private));
+
+    gnc_ui_register_account_destroy_callback (gppr_account_destroy_cb);
+}
+
+static void
+gnc_plugin_page_register2_init (GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncPluginPage *parent;
+    GtkActionGroup *action_group;
+    gboolean use_new;
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+
+    /* Init parent declared variables */
+    parent = GNC_PLUGIN_PAGE(plugin_page);
+    use_new = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, KEY_USE_NEW, NULL);
+    g_object_set(G_OBJECT(plugin_page),
+                 "page-name",      _("General Ledger"),
+                 "page-uri",       "default:",
+                 "ui-description", "gnc-plugin-page-register2-ui.xml",
+                 "use-new-window", use_new,
+                 NULL);
+
+    /* Create menu and toolbar information */
+    action_group =
+        gnc_plugin_page_create_action_group(parent,
+                                            "GncPluginPageRegister2Actions");
+    gtk_action_group_add_actions (action_group, gnc_plugin_page_register2_actions,
+                                  gnc_plugin_page_register2_n_actions, plugin_page);
+    gtk_action_group_add_toggle_actions (action_group,
+                                         toggle_entries, n_toggle_entries,
+                                         plugin_page);
+    gtk_action_group_add_radio_actions (action_group,
+                                        radio_entries_2, n_radio_entries_2,
+                                        REG_STYLE_LEDGER,
+                                        G_CALLBACK(gnc_plugin_page_register2_cmd_style_changed),
+                                        plugin_page);
+
+    gnc_plugin_init_short_names (action_group, toolbar_labels);
+    gnc_plugin_set_important_actions (action_group, important_actions);
+
+    priv->lines_default     = DEFAULT_LINES_AMOUNT;
+    priv->read_only         = FALSE;
+    priv->fd.cleared_match  = CLEARED_ALL;
+}
+
+static void
+gnc_plugin_page_register2_finalize (GObject *object)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (object));
+
+    ENTER("object %p", object);
+    page = GNC_PLUGIN_PAGE_REGISTER2 (object);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE (page);
+
+    G_OBJECT_CLASS (parent_class)->finalize (object);
+    LEAVE(" ");
+}
+
+Account *
+gnc_plugin_page_register2_get_account (GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    Account *leader;
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    ledger_type = gnc_ledger_display_type (priv->ledger);
+    leader = gnc_ledger_display_leader (priv->ledger);
+
+    if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+        return leader;
+    return NULL;
+}
+
+/* This is the list of actions which are switched inactive in a read-only book. */
+static const char* readonly_inactive_actions[] =
+{
+    "EditCutAction",
+    "EditPasteAction",
+    "CutTransactionAction",
+    "PasteTransactionAction",
+    "DuplicateTransactionAction",
+    "DeleteTransactionAction",
+    "RemoveTransactionSplitsAction",
+    "RecordTransactionAction",
+    "CancelTransactionAction",
+    "UnvoidTransactionAction",
+    "VoidTransactionAction",
+    "ReverseTransactionAction",
+    "ShiftTransactionForwardAction",
+    "ActionsTransferAction",
+    "ActionsReconcileAction",
+    "ActionsStockSplitAction",
+    "ScheduleTransactionAction",
+    "ScrubAllAction",
+    "ScrubCurrentAction",
+    NULL
+};
+
+static void
+gnc_plugin_page_register2_ui_update (gpointer various, GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    GtkAction *action;
+    gboolean expanded, voided;
+    Transaction *trans;
+
+    /* Set 'Split Transaction' */
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    expanded = gnc_split_register_current_trans_expanded(reg);
+    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
+                                         "SplitTransactionAction");
+    gtk_action_set_sensitive (action, reg->style == REG_STYLE_LEDGER);
+    g_signal_handlers_block_by_func
+    (action, gnc_plugin_page_register2_cmd_expand_transaction, page);
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), expanded);
+    g_signal_handlers_unblock_by_func
+    (action, gnc_plugin_page_register2_cmd_expand_transaction, page);
+
+    /* Set 'Void' and 'Unvoid' */
+    trans = gnc_split_register_get_current_trans(reg);
+    voided = xaccTransHasSplitsInState(trans, VREC);
+    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
+                                         "VoidTransactionAction");
+    gtk_action_set_sensitive (GTK_ACTION(action), !voided);
+
+    action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
+                                         "UnvoidTransactionAction");
+    gtk_action_set_sensitive (GTK_ACTION(action), voided);
+
+    /* If we are in a readonly book, make any modifying action inactive */
+    if (qof_book_is_readonly(gnc_get_current_book()))
+    {
+        const char **iter;
+        for (iter = readonly_inactive_actions; *iter; ++iter)
+        {
+            /* Set the action's sensitivity */
+            GtkAction *action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page), *iter);
+            gtk_action_set_sensitive(action, FALSE);
+        }
+
+    }
+}
+
+static void
+gnc_plugin_page_register2_ui_initial_state (GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv ;
+    GtkActionGroup *action_group;
+    GtkAction *action;
+    Account *account;
+    SplitRegister *reg;
+    GNCLedgerDisplayType ledger_type;
+    int i;
+    gboolean is_readwrite = !qof_book_is_readonly(gnc_get_current_book());
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    account = gnc_plugin_page_register2_get_account (page);
+    action_group = gnc_plugin_page_get_action_group(GNC_PLUGIN_PAGE(page));
+    gnc_plugin_update_actions(action_group, actions_requiring_account,
+                              "sensitive", is_readwrite && account != NULL);
+
+    /* Set "style" radio button */
+    ledger_type = gnc_ledger_display_type(priv->ledger);
+    gnc_plugin_update_actions(action_group, view_style_actions,
+                              "sensitive", ledger_type == LD_SINGLE);
+
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    for (i = n_radio_entries_2 - 1; i > 0; i--)
+    {
+        DEBUG(" index %d: comparing %x to %x", i, radio_entries_2[i].value,
+              reg->style);
+        if (radio_entries_2[i].value == reg->style)
+        {
+            DEBUG("match");
+            break;
+        }
+    }
+
+    /* Either a match was found, or fell out with i = 0 */
+    action = gtk_action_group_get_action(action_group, radio_entries_2[i].name);
+    g_signal_handlers_block_by_func(action, gnc_plugin_page_register2_cmd_style_changed, page);
+    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
+    g_signal_handlers_unblock_by_func(action, gnc_plugin_page_register2_cmd_style_changed, page);
+
+    /* Set "double line" toggle button */
+    action = gtk_action_group_get_action (action_group,
+                                          "ViewStyleDoubleLineAction");
+    g_signal_handlers_block_by_func(action, gnc_plugin_page_register2_cmd_style_double_line, page);
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION(action), reg->use_double_line);
+    g_signal_handlers_unblock_by_func(action, gnc_plugin_page_register2_cmd_style_double_line, page);
+}
+
+
+/*#################################################################################*/
+/*#################################################################################*/
+/* Virtual Functions */
+
+static GtkWidget *
+gnc_plugin_page_register2_create_widget (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GncWindow *gnc_window;
+    guint numRows;
+    GtkWidget *gsr;
+
+    GncTreeViewSplitReg *tree_view;
+    GtkWidget *scrolled_window;
+
+    SplitRegister *reg;
+    Account *acct;
+    gchar **filter;
+    gchar *order;
+    int filter_changed = 0;
+
+g_print("Register New Create\n");
+
+    ENTER("page %p", plugin_page);
+    page = GNC_PLUGIN_PAGE_REGISTER2 (plugin_page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (priv->widget != NULL)
+    {
+        LEAVE("existing widget %p", priv->widget);
+        return priv->widget;
+    }
+
+    priv->widget = gtk_vbox_new (FALSE, 0);
+    gtk_widget_show (priv->widget);
+
+    numRows = priv->lines_default;
+    numRows = MIN(numRows, DEFAULT_LINES_AMOUNT);
+
+    gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
+/*FIXME Create widget */
+
+    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled_window),
+                                   GTK_POLICY_AUTOMATIC,
+                                   GTK_POLICY_AUTOMATIC);
+    gtk_widget_show(scrolled_window);
+    gtk_box_pack_start(GTK_BOX (priv->widget), scrolled_window, TRUE, TRUE, 0);
+
+    tree_view = priv->tv;
+    g_object_set(G_OBJECT(tree_view), "gconf-section", GCONF_SECTION, 
+                 "show-column-menu", TRUE, NULL);
+
+    gnc_tree_view_configure_columns(GNC_TREE_VIEW(tree_view));
+
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE);
+    gtk_widget_show(GTK_WIDGET (tree_view));
+    gtk_container_add(GTK_CONTAINER(scrolled_window),
+                      GTK_WIDGET(tree_view));
+    gtk_widget_show(priv->widget);
+
+#ifdef SKIP
+
+    gsr = gnc_split_reg_new(priv->ledger,
+                            gnc_window_get_gtk_window(gnc_window),
+                            numRows, priv->read_only);
+    priv->gsr = (GNCSplitReg *)gsr;
+/*    gtk_widget_show (gsr); */
+/*    gtk_box_pack_start (GTK_BOX (priv->widget), gsr, TRUE, TRUE, 0); */
+
+    g_signal_connect (G_OBJECT (gsr), "help-changed",
+                      G_CALLBACK ( gnc_plugin_page_help_changed_cb ),
+                      page );
+
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+
+    gnc_split_register_config(reg, reg->type, reg->style,
+                              reg->use_double_line);
+    gnc_ledger_display_refresh(priv->ledger);
+
+#endif
+
+    gnc_plugin_page_register2_ui_initial_state (page);
+    gnc_plugin_page_register2_ui_update (NULL, page);
+
+#ifdef SKIP
+
+    ledger_type = gnc_ledger_display_type (priv->ledger);
+
+
+    if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
+    {
+        /* Set the sort order for the split register and status of save order button */
+        priv->sd.save_order = FALSE;
+        order = gnc_plugin_page_register2_get_sort_order(plugin_page);
+
+        PINFO("Loaded Sort order is %s", order);
+
+        gnc_split_reg_set_sort_type(priv->gsr, SortTypefromString(order));
+
+        if (order && (g_strcmp0 (order, DEFAULT_SORT_ORDER) != 0))
+            priv->sd.save_order = TRUE;
+
+        priv->sd.original_save_order = priv->sd.save_order;
+        g_free(order);
+
+        /* Set the filter for the split register and status of save filter button */
+        priv->fd.save_filter = FALSE;
+
+        filter = g_strsplit(gnc_plugin_page_register2_get_filter(plugin_page), ",", -1);
+
+        PINFO("Loaded Filter Status is %s", filter[0]);
+
+        priv->fd.cleared_match = (gint)g_ascii_strtoll( filter[0], NULL, 16 );
+
+        if (filter[0] && (g_strcmp0 (filter[0], DEFAULT_FILTER) != 0))
+            filter_changed = filter_changed + 1;
+
+        if (filter[1] && (g_strcmp0 (filter[1], "0") != 0 ))
+        {
+            PINFO("Loaded Filter Start Date is %s", filter[1]);
+
+            priv->fd.start_time = gnc_plugin_page_register2_filter_dmy2time( filter[1] );
+            priv->fd.start_time = gnc_timet_get_day_start(priv->fd.start_time);
+            filter_changed = filter_changed + 1;
+
+            if (filter[2] && (g_strcmp0 (filter[2], "0") != 0 ))
+            {
+                PINFO("Loaded Filter End Date is %s", filter[2]);
+
+                priv->fd.end_time = gnc_plugin_page_register2_filter_dmy2time( filter[2] );
+                priv->fd.end_time = gnc_timet_get_day_end(priv->fd.end_time);
+                filter_changed = filter_changed + 1;
+            }
+        }
+
+        if (filter_changed != 0)
+            priv->fd.save_filter = TRUE;
+
+        priv->fd.original_save_filter = priv->fd.save_filter;
+        g_strfreev(filter);
+
+        /* Update Query with Filter Status and Dates */
+        gnc_ppr_update_status_query (page);
+        gnc_ppr_update_date_query(page);
+    }
+#endif
+
+#ifdef SKIP
+    plugin_page->summarybar = gsr_create_summary_bar(priv->gsr);
+    if (plugin_page->summarybar)
+    {
+        gtk_widget_show_all(plugin_page->summarybar);
+        gtk_box_pack_start(GTK_BOX (priv->widget), plugin_page->summarybar,
+                           FALSE, FALSE, 0);
+        gnc_plugin_page_register2_summarybar_position_changed(NULL, page);
+        gnc_gconf_general_register_cb(KEY_SUMMARYBAR_POSITION,
+                                      gnc_plugin_page_register2_summarybar_position_changed, page);
+    }
+#endif
+
+    priv->event_handler_id = qof_event_register_handler
+                             ((QofEventHandler)gnc_plugin_page_register2_event_handler, page);
+    priv->component_manager_id =
+        gnc_register_gui_component(GNC_PLUGIN_PAGE_REGISTER2_NAME,
+                                   gnc_plugin_page_register2_refresh_cb,
+                                   gnc_plugin_page_register2_close_cb,
+                                   page);
+    gnc_gui_component_set_session (priv->component_manager_id,
+                                   gnc_get_current_session());
+    acct = gnc_plugin_page_register2_get_account(page);
+    if (acct)
+        gnc_gui_component_watch_entity (
+            priv->component_manager_id, xaccAccountGetGUID(acct),
+            QOF_EVENT_DESTROY | QOF_EVENT_MODIFY);
+/*
+    gnc_split_reg_set_moved_cb
+    (priv->gsr, (GFunc)gnc_plugin_page_register2_ui_update, page);
+*/
+    /* DRH - Probably lots of other stuff from regWindowLedger should end up here. */
+    LEAVE(" ");
+    return priv->widget;
+}
+/*#################################################################################*/
+
+
+
+
+
+static void
+gnc_plugin_page_register2_destroy_widget (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("page %p", plugin_page);
+    page = GNC_PLUGIN_PAGE_REGISTER2 (plugin_page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+
+    gnc_gconf_general_remove_cb(KEY_SUMMARYBAR_POSITION,
+                                gnc_plugin_page_register2_summarybar_position_changed, page);
+
+    if (priv->widget == NULL)
+        return;
+
+    if (priv->component_manager_id)
+    {
+        gnc_unregister_gui_component(priv->component_manager_id);
+        priv->component_manager_id = 0;
+    }
+
+    if (priv->event_handler_id)
+    {
+        qof_event_unregister_handler(priv->event_handler_id);
+        priv->event_handler_id = 0;
+    }
+
+    if (priv->sd.dialog)
+    {
+        gtk_widget_destroy(priv->sd.dialog);
+        memset(&priv->sd, 0, sizeof(priv->sd));
+    }
+
+    if (priv->fd.dialog)
+    {
+        gtk_widget_destroy(priv->fd.dialog);
+        memset(&priv->fd, 0, sizeof(priv->fd));
+    }
+
+    gtk_widget_hide(priv->widget);
+    gnc_ledger_display_close (priv->ledger);
+    priv->ledger = NULL;
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_window_changed (GncPluginPage *plugin_page,
+        GtkWidget *window)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page));
+
+    page = GNC_PLUGIN_PAGE_REGISTER2(plugin_page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+/*    priv->gsr->window =
+        GTK_WIDGET(gnc_window_get_gtk_window(GNC_WINDOW(window)));
+*/
+}
+
+static const gchar *style_names[] =
+{
+    "Ledger",
+    "Auto Ledger",
+    "Journal",
+    NULL
+};
+
+#define KEY_REGISTER_TYPE       "RegisterType"
+#define KEY_ACCOUNT_NAME        "AccountName"
+#define KEY_REGISTER_STYLE      "RegisterStyle"
+#define KEY_DOUBLE_LINE         "DoubleLineMode"
+
+#define LABEL_ACCOUNT		"Account"
+#define LABEL_SUBACCOUNT	"SubAccount"
+#define LABEL_GL		"GL"
+#define LABEL_SEARCH		"Search"
+
+
+/** Save enough information about this register page that it can be
+ *  recreated next time the user starts gnucash.
+ *
+ *  @param plugin_page The page to save.
+ *
+ *  @param key_file A pointer to the GKeyFile data structure where the
+ *  page information should be written.
+ *
+ *  @param group_name The group name to use when saving data. */
+static void
+gnc_plugin_page_register2_save_page (GncPluginPage *plugin_page,
+                                    GKeyFile *key_file,
+                                    const gchar *group_name)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    SplitRegister *reg;
+    Account *leader;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+    g_return_if_fail (key_file != NULL);
+    g_return_if_fail (group_name != NULL);
+
+    ENTER("page %p, key_file %p, group_name %s", plugin_page, key_file,
+          group_name);
+
+    page = GNC_PLUGIN_PAGE_REGISTER2(plugin_page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    ledger_type = gnc_ledger_display_type(priv->ledger);
+    if (ledger_type > LD_GL)
+    {
+        LEAVE("Unsupported ledger type");
+        return;
+    }
+    if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+    {
+        const gchar *label;
+        gchar* name;
+        label = (ledger_type == LD_SINGLE) ? LABEL_ACCOUNT : LABEL_SUBACCOUNT;
+        leader = gnc_ledger_display_leader(priv->ledger);
+        g_key_file_set_string(key_file, group_name, KEY_REGISTER_TYPE, label);
+        name = gnc_account_get_full_name(leader);
+        g_key_file_set_string(key_file, group_name, KEY_ACCOUNT_NAME, name);
+        g_free(name);
+    }
+    else if (reg->type == GENERAL_LEDGER)
+    {
+        g_key_file_set_string(key_file, group_name, KEY_REGISTER_TYPE,
+                              LABEL_GL);
+    }
+    else if (reg->type == SEARCH_LEDGER)
+    {
+        g_key_file_set_string(key_file, group_name, KEY_REGISTER_TYPE,
+                              LABEL_SEARCH);
+    }
+    else
+    {
+        LEAVE("Unsupported register type");
+        return;
+    }
+
+    g_key_file_set_string(key_file, group_name, KEY_REGISTER_STYLE,
+                          style_names[reg->style]);
+    g_key_file_set_boolean(key_file, group_name, KEY_DOUBLE_LINE,
+                           reg->use_double_line);
+
+    LEAVE(" ");
+}
+
+
+/** Read and restore the edit menu settings on the specified register
+ *  page.  This function will restore the register style (ledger, auto
+ *  ledger, journal) and whether or not the register is in double line
+ *  mode.  It should eventually restore the "filter by" and "sort by
+ *  settings.
+ *
+ *  @param page The register being restored.
+ *
+ *  @param key_file A pointer to the GKeyFile data structure where the
+ *  page information should be read.
+ *
+ *  @param group_name The group name to use when restoring data. */
+static void
+gnc_plugin_page_register2_restore_edit_menu (GncPluginPage *page,
+        GKeyFile *key_file,
+        const gchar *group_name)
+{
+    GncPluginPageRegister2Private *priv;
+    GtkAction *action;
+    GError *error = NULL;
+    gchar *style_name;
+    gint i;
+    gboolean use_double_line;
+
+    ENTER(" ");
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+    /* Convert the style name to an index */
+    style_name = g_key_file_get_string(key_file, group_name,
+                                       KEY_REGISTER_STYLE, &error);
+    for (i = 0 ; style_names[i]; i++)
+    {
+        if (g_ascii_strcasecmp(style_name, style_names[i]) == 0)
+        {
+            DEBUG("Found match for style name: %s", style_name);
+            break;
+        }
+    }
+    g_free(style_name);
+
+    /* Update the style menu action for this page */
+    if (i <= REG_STYLE_JOURNAL)
+    {
+        DEBUG("Setting style: %d", i);
+        action = gnc_plugin_page_get_action(page, radio_entries_2[i].name);
+        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
+    }
+
+    /* Update the  double line action on this page */
+    use_double_line =
+        g_key_file_get_boolean(key_file, group_name, KEY_DOUBLE_LINE, &error);
+    DEBUG("Setting double_line_mode: %d", use_double_line);
+    action = gnc_plugin_page_get_action(page, "ViewStyleDoubleLineAction");
+    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), use_double_line);
+
+    LEAVE(" ");
+}
+
+
+/** Create a new register page based on the information saved during a
+ *  previous instantiation of gnucash.
+ *
+ *  @param window The window where this page should be installed.
+ *
+ *  @param key_file A pointer to the GKeyFile data structure where the
+ *  page information should be read.
+ *
+ *  @param group_name The group name to use when restoring data. */
+static GncPluginPage *
+gnc_plugin_page_register2_recreate_page (GtkWidget *window,
+                                        GKeyFile *key_file,
+                                        const gchar *group_name)
+{
+    GncPluginPage *page;
+    GError *error = NULL;
+    gchar *reg_type, *acct_name;
+    Account *account;
+    QofBook *book;
+    gboolean include_subs;
+
+    g_return_val_if_fail(key_file, NULL);
+    g_return_val_if_fail(group_name, NULL);
+    ENTER("key_file %p, group_name %s", key_file, group_name);
+
+    /* Create the new page. */
+    reg_type = g_key_file_get_string(key_file, group_name,
+                                     KEY_REGISTER_TYPE, &error);
+    DEBUG("Page type: %s", reg_type);
+    if ((g_ascii_strcasecmp(reg_type, LABEL_ACCOUNT) == 0) ||
+            (g_ascii_strcasecmp(reg_type, LABEL_SUBACCOUNT) == 0))
+    {
+        include_subs = (g_ascii_strcasecmp(reg_type, LABEL_SUBACCOUNT) == 0);
+        DEBUG("Include subs: %d", include_subs);
+        acct_name = g_key_file_get_string(key_file, group_name,
+                                          KEY_ACCOUNT_NAME, &error);
+        book = qof_session_get_book(gnc_get_current_session());
+        account = gnc_account_lookup_by_full_name(gnc_book_get_root_account(book),
+                  acct_name);
+        g_free(acct_name);
+        if (account == NULL)
+        {
+            LEAVE("Bad account name");
+            g_free(reg_type);
+            return NULL;
+        }
+        page = gnc_plugin_page_register2_new (account, include_subs);
+    }
+    else if (g_ascii_strcasecmp(reg_type, LABEL_GL) == 0)
+    {
+        page = gnc_plugin_page_register2_new_gl();
+    }
+    else
+    {
+        LEAVE("Bad ledger type");
+        g_free(reg_type);
+        return NULL;
+    }
+    g_free(reg_type);
+
+    /* Recreate page in given window */
+    gnc_plugin_page_set_use_new_window(page, FALSE);
+
+    /* Install it now so we can them manipulate the created widget */
+    gnc_main_window_open_page(GNC_MAIN_WINDOW(window), page);
+
+    /* Now update the page to the last state it was in */
+    gnc_plugin_page_register2_restore_edit_menu(page, key_file, group_name);
+    LEAVE(" ");
+    return page;
+}
+
+
+/*
+ * Based on code from Epiphany (src/ephy-window.c)
+ */
+static void
+gnc_plugin_page_register2_update_edit_menu (GncPluginPage *page, gboolean hide)
+{
+    GncPluginPageRegister2Private *priv;
+    GncPluginPageRegister2 *reg_page;
+    GtkAction *action;
+    gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE;
+    gboolean has_selection;
+    gboolean is_readwrite = !qof_book_is_readonly(gnc_get_current_book());
+
+    reg_page = GNC_PLUGIN_PAGE_REGISTER2(page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(reg_page);
+    has_selection = gnucash_register_has_selection (priv->gsr->reg);
+
+    can_copy = has_selection;
+    can_cut = is_readwrite && has_selection;
+    can_paste = is_readwrite;
+
+    action = gnc_plugin_page_get_action (page, "EditCopyAction");
+    gtk_action_set_sensitive (action, can_copy);
+    gtk_action_set_visible (action, !hide || can_copy);
+    action = gnc_plugin_page_get_action (page, "EditCutAction");
+    gtk_action_set_sensitive (action, can_cut);
+    gtk_action_set_visible (action, !hide || can_cut);
+    action = gnc_plugin_page_get_action (page, "EditPasteAction");
+    gtk_action_set_sensitive (action, can_paste);
+    gtk_action_set_visible (action,  !hide || can_paste);
+}
+
+
+static gboolean
+gnc_plugin_page_register2_finish_pending (GncPluginPage *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncPluginPageRegister2 *reg_page;
+    SplitRegister *reg;
+    GtkWidget *dialog, *window;
+    const gchar *name;
+    gint response;
+
+    reg_page = GNC_PLUGIN_PAGE_REGISTER2(page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(reg_page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+
+    if (!reg || !gnc_split_register_changed(reg))
+        return TRUE;
+
+    name = gnc_plugin_page_register2_get_tab_name(page);
+    window = gnc_plugin_page_get_window(page);
+    dialog = gtk_message_dialog_new(GTK_WINDOW(window),
+                                    GTK_DIALOG_DESTROY_WITH_PARENT,
+                                    GTK_MESSAGE_WARNING,
+                                    GTK_BUTTONS_NONE,
+                                    /* Translators: %s is the name
+                                       of the tab page */
+                                    _("Save changes to %s?"), name);
+    gtk_message_dialog_format_secondary_text
+    (GTK_MESSAGE_DIALOG(dialog),
+     "%s",
+     _("This register has pending changes to a transaction.  "
+       "Would you like to save the changes to this transaction, "
+       "discard the transaction, or cancel the operation?"));
+    gnc_gtk_dialog_add_button(dialog, _("_Discard Transaction"),
+                              GTK_STOCK_DELETE, GTK_RESPONSE_REJECT);
+    gtk_dialog_add_button(GTK_DIALOG(dialog),
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+    gnc_gtk_dialog_add_button(dialog, _("_Save Transaction"),
+                              GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT);
+
+    response = gtk_dialog_run(GTK_DIALOG(dialog));
+    gtk_widget_destroy(dialog);
+
+    switch (response)
+    {
+    case GTK_RESPONSE_ACCEPT:
+        gnc_split_register_save(reg, TRUE);
+        return TRUE;
+
+    case GTK_RESPONSE_REJECT:
+        gnc_split_register_cancel_cursor_trans_changes(reg);
+        gnc_split_register_save (reg, TRUE);
+        return TRUE;
+
+    default:
+        return FALSE;
+    }
+}
+
+
+static gchar *
+gnc_plugin_page_register2_get_tab_name (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+
+    g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page), _("unknown"));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+
+    switch (ledger_type)
+    {
+    case LD_SINGLE:
+        return g_strdup(xaccAccountGetName (leader));
+
+    case LD_SUBACCOUNT:
+        return g_strdup_printf("%s+", xaccAccountGetName (leader));
+
+    case LD_GL:
+        switch (reg->type)
+        {
+        case GENERAL_LEDGER:
+        case INCOME_LEDGER:
+            return g_strdup(_("General Ledger"));
+        case PORTFOLIO_LEDGER:
+            return g_strdup(_("Portfolio"));
+        case SEARCH_LEDGER:
+            return g_strdup(_("Search Results"));
+        default:
+            break;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    return g_strdup(_("unknown"));
+}
+
+static gchar *
+gnc_plugin_page_register2_get_tab_color (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+    const char* color;
+
+    g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page), _("unknown"));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+    color = NULL;
+
+    if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+        color = xaccAccountGetColor (leader);
+
+    return g_strdup(color ? color : "Not Set");
+}
+
+static gchar *
+gnc_plugin_page_register2_get_filter (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+    const char* filter;
+
+    g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page), _("unknown"));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+    filter = NULL;
+
+    if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+        filter = xaccAccountGetFilter (leader);
+
+    return filter ? g_strdup(filter) : g_strdup_printf("%s,%s,%s", DEFAULT_FILTER, "0", "0");
+}
+
+void
+gnc_plugin_page_register2_set_filter (GncPluginPage *plugin_page, const gchar *filter )
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+    gchar *default_filter;
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+
+    if (leader != NULL)
+    {
+        default_filter = g_strdup_printf("%s,%s,%s", DEFAULT_FILTER, "0", "0");
+
+        if (!filter || (g_strcmp0 (filter, default_filter) == 0))
+            xaccAccountSetFilter (leader, NULL);
+        else
+            xaccAccountSetFilter (leader, filter);
+
+        g_free (default_filter);
+    }
+
+    return;
+}
+
+static gchar *
+gnc_plugin_page_register2_get_sort_order (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+    const char* sort_order;
+
+    g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page), _("unknown"));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+    sort_order = NULL;
+
+    if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+        sort_order = xaccAccountGetSortOrder (leader);
+
+    return g_strdup(sort_order ? sort_order : DEFAULT_SORT_ORDER);
+}
+
+void
+gnc_plugin_page_register2_set_sort_order (GncPluginPage *plugin_page, const gchar *sort_order )
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+
+    if (leader != NULL)
+    {
+        if (!sort_order || (g_strcmp0 (sort_order, DEFAULT_SORT_ORDER) == 0))
+            xaccAccountSetSortOrder (leader, NULL);
+        else
+            xaccAccountSetSortOrder (leader, sort_order);
+    }
+
+    return;
+}
+
+static gchar *
+gnc_plugin_page_register2_get_long_name (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay *ld;
+    SplitRegister *reg;
+    Account *leader;
+
+    g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER2 (plugin_page), _("unknown"));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    ld = priv->ledger;
+    reg = gnc_ledger_display_get_split_register (ld);
+    ledger_type = gnc_ledger_display_type (ld);
+    leader = gnc_ledger_display_leader (ld);
+
+    switch (ledger_type)
+    {
+    case LD_SINGLE:
+        return gnc_account_get_full_name (leader);
+
+    case LD_SUBACCOUNT:
+    {
+        gchar *account_full_name = gnc_account_get_full_name (leader);
+        gchar *return_string = g_strdup_printf("%s+", account_full_name);
+        g_free ((gpointer *) account_full_name);
+        return return_string;
+    }
+
+    default:
+        break;
+    }
+
+    return NULL;
+}
+
+static void
+gnc_plugin_page_register2_summarybar_position_changed(GConfEntry *entry,
+        gpointer user_data)
+{
+    GncPluginPage *plugin_page;
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+    GtkPositionType position = GTK_POS_BOTTOM;
+    gchar *conf_string;
+
+    g_return_if_fail(user_data != NULL);
+
+    plugin_page = GNC_PLUGIN_PAGE(user_data);
+    page = GNC_PLUGIN_PAGE_REGISTER2 (user_data);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+    conf_string = gnc_gconf_get_string (GCONF_GENERAL,
+                                        KEY_SUMMARYBAR_POSITION, NULL);
+    if (conf_string)
+    {
+        position = gnc_enum_from_nick (GTK_TYPE_POSITION_TYPE,
+                                       conf_string, GTK_POS_BOTTOM);
+        g_free (conf_string);
+    }
+
+    gtk_box_reorder_child(GTK_BOX(priv->widget),
+                          plugin_page->summarybar,
+                          (position == GTK_POS_TOP ? 0 : -1) );
+}
+
+/************************************************************/
+/*                     "Sort By" Dialog                     */
+/************************************************************/
+
+/** This function is called when the "Sort By..." dialog is closed.
+ *  If the dialog was closed by any method other than clicking the OK
+ *  button, the original sorting order will be restored.
+ *
+ *  @param dialog A pointer to the dialog box.
+ *
+ *  @param response A numerical value indicating why the dialog box was closed.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 associated with
+ *  this dialog box.
+ */
+void
+gnc_plugin_page_register2_sort_response_cb (GtkDialog *dialog,
+        gint response,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncPluginPage *plugin_page;
+    SortType type;
+    const gchar *order;
+
+    g_return_if_fail(GTK_IS_DIALOG(dialog));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER(" ");
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    plugin_page = GNC_PLUGIN_PAGE(page);
+
+    if (response != GTK_RESPONSE_OK)
+    {
+        /* Restore the original sort order */
+        gnc_split_reg_set_sort_type(priv->gsr, priv->sd.original_sort_type);
+        priv->sd.save_order = priv->sd.original_save_order;
+    }
+    else
+    {
+        priv->sd.original_save_order = priv->sd.save_order;
+
+        if (priv->sd.save_order)
+        {
+            type = gnc_split_reg_get_sort_type(priv->gsr);
+            order = SortTypeasString(type);
+            gnc_plugin_page_register2_set_sort_order (plugin_page, order);
+        }
+    }
+    priv->sd.dialog = NULL;
+    gtk_widget_destroy(GTK_WIDGET(dialog));
+    LEAVE(" ");
+}
+
+
+/** This function is called when a radio button in the "Sort By..."
+ *  dialog is clicked.
+ *
+ *  @param button The button that was toggled.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 associated with
+ *  this dialog box.
+ */
+void
+gnc_plugin_page_register2_sort_button_cb (GtkToggleButton *button,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    const gchar *name;
+    SortType type;
+
+    g_return_if_fail(GTK_IS_TOGGLE_BUTTON(button));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    name = gtk_buildable_get_name(GTK_BUILDABLE(button));
+    ENTER("button %s(%p), page %p", name, button, page);
+    type = SortTypefromString(name);
+    gnc_split_reg_set_sort_type(priv->gsr, type);
+    LEAVE(" ");
+}
+
+
+/** This function is called whenever the save sort order is checked
+ *  or unchecked which allows saving of the sort order.
+ *
+ *  @param button The toggle button that was changed.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this sort order dialog.
+ */
+void
+gnc_plugin_page_register2_sort_order_save_cb (GtkToggleButton *button,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GTK_IS_CHECK_BUTTON(button));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("Save toggle button (%p), plugin_page %p", button, page);
+
+    /* Compute the new save sort order */
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+    if (gtk_toggle_button_get_active(button))
+        priv->sd.save_order = TRUE;
+    else
+        priv->sd.save_order = FALSE;
+    LEAVE(" ");
+}
+
+
+/************************************************************/
+/*                    "Filter By" Dialog                    */
+/************************************************************/
+
+/** This function updates the "cleared match" term of the register
+ *  query.  It unconditionally removes any old "cleared match" query
+ *  term, then adds back a new query term if needed.  There seems to
+ *  be a bug in the current g2 register code such that when the number
+ *  of entries in the register doesn't fill up the window, the blank
+ *  space at the end of the window isn't correctly redrawn.  This
+ *  function works around that problem, but a root cause analysis
+ *  should probably be done.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+static void
+gnc_ppr_update_status_query (GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GSList *param_list;
+    Query *query;
+
+    ENTER(" ");
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    query = gnc_ledger_display_get_query( priv->ledger );
+    if (!query)
+    {
+        LEAVE("no query found");
+        return;
+    }
+
+    /* Remove the old status match */
+    param_list = qof_query_build_param_list (SPLIT_RECONCILE, NULL);
+    if (param_list)
+    {
+        qof_query_purge_terms (query, param_list);
+        g_slist_free(param_list);
+    }
+
+    /* Install the new status match */
+    if (priv->fd.cleared_match != CLEARED_ALL)
+        xaccQueryAddClearedMatch(query, priv->fd.cleared_match, QOF_QUERY_AND);
+
+    gnc_ledger_display_refresh (priv->ledger);
+    LEAVE(" ");
+}
+
+
+/** This function updates the "date posted" term of the register
+ *  query.  It unconditionally removes any old "date posted" query
+ *  term, then adds back a new query term if needed.  There seems to
+ *  be a bug in the current g2 register code such that when the number
+ *  of entries in the register doesn't fill up the window, the blank
+ *  space at the end of the window isn't correctly redrawn.  This
+ *  function works around that problem, but a root cause analysis
+ *  should probably be done.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+static void
+gnc_ppr_update_date_query (GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GSList *param_list;
+    Query *query;
+
+    ENTER(" ");
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (!priv->ledger)
+    {
+        LEAVE("no ledger");
+        return;
+    }
+
+    query = gnc_ledger_display_get_query( priv->ledger );
+    if (!query)
+    {
+        LEAVE("no query");
+        return;
+    }
+
+    /* Delete any existing old date spec. */
+    param_list = qof_query_build_param_list(SPLIT_TRANS, TRANS_DATE_POSTED, NULL);
+    if (param_list)
+    {
+        qof_query_purge_terms (query, param_list);
+        g_slist_free(param_list);
+    }
+
+    if (priv->fd.start_time || priv->fd.end_time)
+    {
+        /* Build a new spec */
+        xaccQueryAddDateMatchTT(query,
+                                priv->fd.start_time != 0, priv->fd.start_time,
+                                priv->fd.end_time != 0,   priv->fd.end_time,
+                                QOF_QUERY_AND);
+    }
+
+    gnc_ledger_display_refresh (priv->ledger);
+    LEAVE(" ");
+}
+
+
+/* This function converts a time_t value date to a string */
+static gchar *
+gnc_plugin_page_register2_filter_time2dmy ( time_t raw_time)
+{
+    struct tm * timeinfo;
+    gchar date_string[11];
+    gint i;
+
+    timeinfo = localtime ( &raw_time );
+    i = strftime(date_string, 11, "%d-%m-%Y", timeinfo );
+    PINFO("Date string is %s", date_string);
+
+    return g_strdup(date_string);
+}
+
+
+/* This function converts a string date to a time_t value */
+static time_t
+gnc_plugin_page_register2_filter_dmy2time ( char *date_string)
+{
+    struct tm *when;
+    gint yy = 0, mm = 0, dd = 0;
+
+    time_t raw_time;
+
+    PINFO("Date string is %s", date_string);
+
+    sscanf(date_string, "%d-%d-%d", &dd, &mm, &yy );
+
+    time(&raw_time);
+    when = localtime ( &raw_time );
+
+    when->tm_year = yy - 1900;
+    when->tm_mon = mm - 1 ;
+    when->tm_mday = dd;
+
+    return mktime(when);
+}
+
+
+/** This function is called whenever one of the status entries is
+ *  checked or unchecked.  It updates the status value maintained for
+ *  the filter dialog, and calls another function to do the work of
+ *  applying the change to the register itself.
+ *
+ *  @param button The toggle button that was changed.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+void
+gnc_plugin_page_register2_filter_status_one_cb (GtkToggleButton *button,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    const gchar *name;
+    gint i, value;
+
+    g_return_if_fail(GTK_IS_CHECK_BUTTON(button));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    name = gtk_buildable_get_name(GTK_BUILDABLE(button));
+    ENTER("toggle button %s (%p), plugin_page %p", name, button, page);
+
+    /* Determine what status bit to change */
+    value = CLEARED_NONE;
+    for (i = 0; status_actions[i].action_name; i++)
+    {
+        if (g_strcmp0(name, status_actions[i].action_name) == 0)
+        {
+            value = status_actions[i].value;
+            break;
+        }
+    }
+
+    /* Compute the new match status */
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (gtk_toggle_button_get_active(button))
+        priv->fd.cleared_match |= value;
+    else
+        priv->fd.cleared_match &= ~value;
+    gnc_ppr_update_status_query(page);
+    LEAVE(" ");
+}
+
+
+/** This function is called whenever the "select all" status button is
+ *  clicked.  It updates all of the checkbox widgets, then updates the
+ *  query on the register.
+ *
+ *  @param button The button that was clicked.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+void
+gnc_plugin_page_register2_filter_status_all_cb (GtkButton *button,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GtkWidget *widget;
+    gint i;
+
+    g_return_if_fail(GTK_IS_BUTTON(button));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(button %p, page %p)", button, page);
+
+    /* Turn on all the check menu items */
+    for (i = 0; status_actions[i].action_name; i++)
+    {
+        widget = status_actions[i].widget;
+        g_signal_handlers_block_by_func(widget, gnc_plugin_page_register2_filter_status_one_cb, page);
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), TRUE);
+        g_signal_handlers_unblock_by_func(widget, gnc_plugin_page_register2_filter_status_one_cb, page);
+    }
+
+    /* Set the requested status */
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    priv->fd.cleared_match = CLEARED_ALL;
+    gnc_ppr_update_status_query(page);
+    LEAVE(" ");
+}
+
+
+/** This function computes the starting and ending times for the
+ *  filter by examining the dialog widgets to see which ones are
+ *  selected, and will pull times out of the data entry boxes if
+ *  necessary.  This function must exist to handle the case where the
+ *  "show all" button was Selected, and the user clicks on the "select
+ *  range" button.  Since it exists, it make sense for the rest of the
+ *  callbacks to take advantage of it.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+static void
+get_filter_times(GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GtkWidget *button, *today, *gde;
+    time_t time_val;
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->fd.start_date_choose)))
+    {
+        time_val = gnc_date_edit_get_date(GNC_DATE_EDIT(priv->fd.start_date));
+        time_val = gnc_timet_get_day_start(time_val);
+        priv->fd.start_time = time_val;
+    }
+    else
+    {
+        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->fd.start_date_today)))
+        {
+            priv->fd.start_time = gnc_timet_get_today_start();
+        }
+        else
+        {
+            priv->fd.start_time = 0;
+        }
+    }
+
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->fd.end_date_choose)))
+    {
+        time_val = gnc_date_edit_get_date(GNC_DATE_EDIT(priv->fd.end_date));
+        time_val = gnc_timet_get_day_end(time_val);
+        priv->fd.end_time = time_val;
+    }
+    else
+    {
+        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->fd.start_date_today)))
+        {
+            priv->fd.end_time = gnc_timet_get_today_end();
+        }
+        else
+        {
+            priv->fd.end_time = 0;
+        }
+    }
+}
+
+
+/** This function is called when the "select range" radio button
+ *  changes state.  Since there are only two choices in this radio
+ *  group, this one signal can be used to handle all cases.  This
+ *  function is responsible for setting the sensitivity of the table
+ *  of widgets underneath the "select range" choice, and updating the
+ *  time limitation on the register query.  This is handled by a
+ *  helper function when the radio button is selected (as potentially
+ *  all the widgets in the table need to be inspected), and is trivial
+ *  for the other case.
+ *
+ *  @param button A pointer to the "select range" radio button.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+void
+gnc_plugin_page_register2_filter_select_range_cb (GtkRadioButton *button,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    gboolean active;
+
+    g_return_if_fail(GTK_IS_RADIO_BUTTON(button));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(button %p, page %p)", button, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
+    gtk_widget_set_sensitive(priv->fd.table, active);
+    if (active)
+    {
+        get_filter_times(page);
+    }
+    else
+    {
+        priv->fd.start_time = 0;
+        priv->fd.end_time = 0;
+    }
+    gnc_ppr_update_date_query(page);
+    LEAVE(" ");
+}
+
+
+/** This function is called when one of the start date entry widgets
+ *  is updated.  It simply calls common routines to determine the
+ *  start/end times and update the register query.
+ *
+ *  @param unused A pointer to a GncDateEntry widgets, but it could be
+ *  any widget.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+static void
+gnc_plugin_page_register2_filter_gde_changed_cb (GtkWidget *unused,
+        GncPluginPageRegister2 *page)
+{
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(widget %s(%p), page %p)", gtk_buildable_get_name(GTK_BUILDABLE(unused)), unused, page);
+    get_filter_times(page);
+    gnc_ppr_update_date_query(page);
+    LEAVE(" ");
+}
+
+
+/** This function is called when one of the start date radio buttons
+ *  is selected.  It updates the sensitivity of the date entry widget,
+ *  then calls a common routine to determine the start/end times and
+ *  update the register query.
+ *
+ *  *Note: This function is actually called twice for each new radio
+ *  button selection.  The first time call is to uncheck the old
+ *  button, and the second time to check the new button.  This does
+ *  make a kind of sense, as radio buttons are nothing more than
+ *  linked toggle buttons where only one can be active.
+ *
+ *  @param radio The button whose state is changing.  This will be
+ *  the previously selected button the first of the pair of calls to
+ *  this function, and will be the newly selected button the second
+ *  time.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+void
+gnc_plugin_page_register2_filter_start_cb (GtkWidget *radio,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    const gchar *name;
+    gboolean active;
+
+    g_return_if_fail(GTK_IS_RADIO_BUTTON(radio));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(radio %s(%p), page %p)", gtk_buildable_get_name(GTK_BUILDABLE(radio)), radio, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio)))
+    {
+        LEAVE("1st callback of pair. Defer to 2nd callback.");
+        return;
+    }
+
+    name = gtk_buildable_get_name(GTK_BUILDABLE(radio));
+    active = ( g_strcmp0(name, g_strdup("start_date_choose")) == 0 ? 1 : 0 );
+    gtk_widget_set_sensitive(priv->fd.start_date, active);
+    get_filter_times(page);
+    gnc_ppr_update_date_query(page);
+    LEAVE(" ");
+}
+
+
+/** This function is called when one of the end date radio buttons is
+ *  selected.  It updates the sensitivity of the date entry widget,
+ *  then calls a common routine to determine the start/end times and
+ *  update the register query.
+ *
+ *  *Note: This function is actually called twice for each new radio
+ *  button selection.  The first time call is to uncheck the old
+ *  button, and the second time to check the new button.  This does
+ *  make a kind of sense, as radio buttons are nothing more than
+ *  linked toggle buttons where only one can be active.
+ *
+ *  @param radio The button whose state is changing.  This will be
+ *  the previously selected button the first of the pair of calls to
+ *  this function, and will be the newly selected button the second
+ *  time.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+void
+gnc_plugin_page_register2_filter_end_cb (GtkWidget *radio,
+                                        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    const gchar *name;
+    gboolean active;
+
+    g_return_if_fail(GTK_IS_RADIO_BUTTON(radio));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(radio %s(%p), page %p)", gtk_buildable_get_name(GTK_BUILDABLE(radio)), radio, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio)))
+    {
+        LEAVE("1st callback of pair. Defer to 2nd callback.");
+        return;
+    }
+
+    name = gtk_buildable_get_name(GTK_BUILDABLE(radio));
+    active = ( g_strcmp0(name, g_strdup("end_date_choose")) == 0 ? 1 : 0 );
+    gtk_widget_set_sensitive(priv->fd.end_date, active);
+    get_filter_times(page);
+    gnc_ppr_update_date_query(page);
+    LEAVE(" ");
+}
+
+
+/** This function is called whenever the save status is checked
+ *  or unchecked. It will allow saving of the filter if required.
+ *
+ *  @param button The toggle button that was changed.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 that is
+ *  associated with this filter dialog.
+ */
+void
+gnc_plugin_page_register2_filter_save_cb (GtkToggleButton *button,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GTK_IS_CHECK_BUTTON(button));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("Save toggle button (%p), plugin_page %p", button, page);
+
+    /* Compute the new save filter status */
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (gtk_toggle_button_get_active(button))
+        priv->fd.save_filter = TRUE;
+    else
+        priv->fd.save_filter = FALSE;
+    LEAVE(" ");
+}
+
+
+/** This function is called when the "Filter By..." dialog is closed.
+ *  If the dialog was closed by any method other than clicking the OK
+ *  button, the original sorting order will be restored.
+ *
+ *  @param dialog A pointer to the dialog box.
+ *
+ *  @param response A numerical value indicating why the dialog box was closed.
+ *
+ *  @param page A pointer to the GncPluginPageRegister2 associated with
+ *  this dialog box.
+ */
+void
+gnc_plugin_page_register2_filter_response_cb (GtkDialog *dialog,
+        gint response,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncPluginPage *plugin_page;
+
+    g_return_if_fail(GTK_IS_DIALOG(dialog));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER(" ");
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    plugin_page = GNC_PLUGIN_PAGE(page);
+
+    if (response != GTK_RESPONSE_OK)
+    {
+        /* Remove the old status match */
+        priv->fd.cleared_match = priv->fd.original_cleared_match;
+        gnc_ppr_update_status_query(page);
+        priv->fd.start_time = priv->fd.original_start_time;
+        priv->fd.end_time = priv->fd.original_end_time;
+        priv->fd.save_filter = priv->fd.original_save_filter;
+        gnc_ppr_update_date_query(page);
+    }
+    else
+    {
+        priv->fd.original_save_filter = priv->fd.save_filter;
+
+        if (priv->fd.save_filter)
+        {
+            gchar* filter;
+            filter = g_strdup_printf("0x%04x", priv->fd.cleared_match);
+
+            if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->fd.start_date_choose)) && priv->fd.start_time != 0 )
+            {
+                gchar *timeval = gnc_plugin_page_register2_filter_time2dmy(priv->fd.start_time);
+                filter = g_strconcat ( filter, ",", timeval, NULL);
+                g_free (timeval);
+            }
+            else
+                filter = g_strconcat ( filter, ",0", NULL);
+
+            if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->fd.end_date_choose)) && priv->fd.end_time != 0 )
+            {
+                gchar *timeval = gnc_plugin_page_register2_filter_time2dmy(priv->fd.end_time);
+                filter = g_strconcat ( filter, ",", timeval, NULL);
+                g_free (timeval);
+            }
+            else
+                filter = g_strconcat ( filter, ",0", NULL);
+
+            PINFO("The filter to save is %s", filter);
+
+            gnc_plugin_page_register2_set_filter (plugin_page, filter);
+            g_free (filter);
+        }
+    }
+    priv->fd.dialog = NULL;
+    gtk_widget_destroy(GTK_WIDGET(dialog));
+    LEAVE(" ");
+}
+
+
+/************************************************************/
+/*                  Report Helper Functions                 */
+/************************************************************/
+
+static char *
+gnc_reg_get_name (GNCLedgerDisplay *ledger, gboolean for_window)
+{
+    Account *leader;
+    SplitRegister *reg;
+    gchar *account_name;
+    gchar *reg_name;
+    gchar *name;
+    GNCLedgerDisplayType ledger_type;
+
+    if (ledger == NULL)
+        return NULL;
+
+    reg = gnc_ledger_display_get_split_register (ledger);
+    ledger_type = gnc_ledger_display_type (ledger);
+
+    switch (reg->type)
+    {
+    case GENERAL_LEDGER:
+    case INCOME_LEDGER:
+        if (for_window)
+            reg_name = _("General Ledger");
+        else
+            reg_name = _("General Ledger Report");
+        break;
+    case PORTFOLIO_LEDGER:
+        if (for_window)
+            reg_name = _("Portfolio");
+        else
+            reg_name = _("Portfolio Report");
+        break;
+    case SEARCH_LEDGER:
+        if (for_window)
+            reg_name = _("Search Results");
+        else
+            reg_name = _("Search Results Report");
+        break;
+    default:
+        if (for_window)
+            reg_name = _("Register");
+        else
+            reg_name = _("Register Report");
+        break;
+    }
+
+    leader = gnc_ledger_display_leader (ledger);
+
+    if ((leader != NULL) && (ledger_type != LD_GL))
+    {
+        account_name = gnc_account_get_full_name (leader);
+
+        if (ledger_type == LD_SINGLE)
+        {
+            name = g_strconcat (account_name, " - ", reg_name, NULL);
+        }
+        else
+        {
+            name = g_strconcat (account_name, " ", _("and subaccounts"), " - ", reg_name, NULL);
+        }
+        g_free(account_name);
+    }
+    else
+        name = g_strdup (reg_name);
+
+    return name;
+}
+
+static int
+report_helper (GNCLedgerDisplay *ledger, Split *split, Query *query)
+{
+    SplitRegister *reg = gnc_ledger_display_get_split_register (ledger);
+    Account *account;
+    char *str;
+    swig_type_info * qtype;
+    SCM args;
+    SCM func;
+    SCM arg;
+
+    args = SCM_EOL;
+
+    func = scm_c_eval_string ("gnc:register-report-create");
+    g_return_val_if_fail (scm_is_procedure (func), -1);
+
+    arg = scm_makfrom0str (gnc_split_register_get_credit_string (reg));
+    args = scm_cons (arg, args);
+
+    arg = scm_makfrom0str (gnc_split_register_get_debit_string (reg));
+    args = scm_cons (arg, args);
+
+    str = gnc_reg_get_name (ledger, FALSE);
+    arg = scm_makfrom0str (str);
+    args = scm_cons (arg, args);
+    g_free (str);
+
+    arg = SCM_BOOL (reg->use_double_line);
+    args = scm_cons (arg, args);
+
+    arg = SCM_BOOL (reg->style == REG_STYLE_JOURNAL);
+    args = scm_cons (arg, args);
+
+    if (!query)
+    {
+        query = gnc_ledger_display_get_query (ledger);
+        g_return_val_if_fail (query != NULL, -1);
+    }
+
+    qtype = SWIG_TypeQuery ("_p__QofQuery");
+    g_return_val_if_fail (qtype, -1);
+
+    arg = SWIG_NewPointerObj (query, qtype, 0);
+    args = scm_cons (arg, args);
+    g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
+
+
+    if (split)
+    {
+        qtype = SWIG_TypeQuery ("_p_Split");
+        g_return_val_if_fail (qtype, -1);
+        arg = SWIG_NewPointerObj (split, qtype, 0);
+    }
+    else
+    {
+        arg = SCM_BOOL_F;
+    }
+    args = scm_cons (arg, args);
+    g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
+
+
+    qtype = SWIG_TypeQuery ("_p_Account");
+    g_return_val_if_fail (qtype, -1);
+
+    account = gnc_ledger_display_leader (ledger);
+    arg = SWIG_NewPointerObj (account, qtype, 0);
+    args = scm_cons (arg, args);
+    g_return_val_if_fail (arg != SCM_UNDEFINED, -1);
+
+
+    /* Apply the function to the args */
+    arg = scm_apply (func, args, SCM_EOL);
+    g_return_val_if_fail (scm_is_exact (arg), -1);
+
+    return scm_num2int (arg, SCM_ARG1, G_STRFUNC);
+}
+
+/************************************************************/
+/*                     Command callbacks                    */
+/************************************************************/
+
+static void
+gnc_plugin_page_register2_cmd_print_check (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister * reg;
+    Split         * split;
+    Transaction   * trans;
+    GList         * splits = NULL, *item;
+    GNCLedgerDisplayType ledger_type;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+#ifdef SKIP
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+    ledger_type = gnc_ledger_display_type(priv->ledger);
+    if (ledger_type == LD_SINGLE || ledger_type == LD_SUBACCOUNT)
+    {
+        split    = gnc_split_register_get_current_split(reg);
+        trans    = xaccSplitGetParent(split);
+
+        if (split && trans)
+        {
+            splits = g_list_append(splits, split);
+            gnc_ui_print_check_dialog_create(plugin_page, splits);
+            g_list_free(splits);
+        }
+    }
+    else if (ledger_type == LD_GL && reg->type == SEARCH_LEDGER)
+    {
+        Account *common_acct = NULL, *account;
+        splits = qof_query_run(gnc_ledger_display_get_query(priv->ledger));
+        /* Make sure each split is from the same account */
+        for (item = splits; item; item = g_list_next(item))
+        {
+            split = (Split *) item->data;
+            if (common_acct == NULL)
+            {
+                common_acct = xaccSplitGetAccount(split);
+            }
+            else
+            {
+                if (xaccSplitGetAccount(split) != common_acct)
+                {
+                    GtkWidget *dialog, *window;
+                    gint response;
+                    const gchar *title = _("Print checks from multiple accounts?");
+                    const gchar *message =
+                        _("This search result contains splits from more than one account. "
+                          "Do you want to print the checks even though they are not all "
+                          "from the same account?");
+                    window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(plugin_page));
+                    dialog = gtk_message_dialog_new(GTK_WINDOW(window),
+                                                    GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                    GTK_MESSAGE_WARNING,
+                                                    GTK_BUTTONS_CANCEL,
+                                                    "%s", title);
+                    gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+                            "%s", message);
+                    gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Print checks"),
+                                          GTK_RESPONSE_YES);
+                    response = gnc_dialog_run(GTK_DIALOG(dialog), "print_multi_acct_checks");
+                    gtk_widget_destroy(dialog);
+                    if (response != GTK_RESPONSE_YES)
+                    {
+                        LEAVE("Multiple accounts");
+                        return;
+                    }
+                    break;
+                }
+            }
+        }
+        gnc_ui_print_check_dialog_create(plugin_page, splits);
+    }
+    else
+    {
+        gnc_error_dialog(gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(plugin_page)), "%s",
+                         _("You can only print checks from a bank account register or search results."));
+        LEAVE("Unsupported ledger type");
+        return;
+    }
+#endif
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_cut (GtkAction *action,
+                                  GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    gnucash_register_cut_clipboard(priv->gsr->reg);
+    LEAVE("");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_copy (GtkAction *action,
+                                   GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    gnucash_register_copy_clipboard(priv->gsr->reg);
+    LEAVE("");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_paste (GtkAction *action,
+                                    GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    gnucash_register_paste_clipboard(priv->gsr->reg);
+    LEAVE("");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_edit_account (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    Account *account;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    account = gnc_plugin_page_register2_get_account (page);
+    if (account)
+        gnc_ui_edit_account_window (account);
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_find_transactions (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+/* This function has the original ledger type */
+/*    gnc_ui_find_transactions_dialog_create(priv->ledger); */
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_cut_transaction (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    gnc_split_register_cut_current(reg);
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_copy_transaction (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    gnc_split_register_copy_current(reg);
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_paste_transaction (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    ENTER("(action %p, page %p)", action, page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    gnc_split_register_paste_current(reg);
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_void_transaction (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GtkWidget *dialog, *entry;
+    SplitRegister *reg;
+    Transaction *trans;
+    GtkBuilder *builder;
+    const char *reason;
+    gint result;
+
+    ENTER("(action %p, page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    trans = gnc_split_register_get_current_trans(reg);
+    if (trans == NULL)
+        return;
+    if (xaccTransHasSplitsInState(trans, VREC))
+        return;
+    if (xaccTransHasReconciledSplits(trans) || xaccTransHasSplitsInState(trans, CREC))
+    {
+        gnc_error_dialog(NULL, "%s", _("You cannot void a transaction with reconciled or cleared splits."));
+        return;
+    }
+
+    if (!gnc_plugin_page_register2_finish_pending(GNC_PLUGIN_PAGE(page)))
+        return;
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder , "gnc-plugin-page-register.glade", "Void Transaction");
+    dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Void Transaction"));
+    entry = GTK_WIDGET(gtk_builder_get_object (builder, "reason"));
+
+    result = gtk_dialog_run(GTK_DIALOG(dialog));
+    if (result == GTK_RESPONSE_OK)
+    {
+        reason = gtk_entry_get_text(GTK_ENTRY(entry));
+        if (reason == NULL)
+            reason = "";
+        gnc_split_register_void_current_trans(reg, reason);
+    }
+
+    /* All done. Get rid of it. */
+    gtk_widget_destroy(dialog);
+    g_object_unref(G_OBJECT(builder));
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_unvoid_transaction (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    Transaction *trans;
+
+    ENTER("(action %p, page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    trans = gnc_split_register_get_current_trans(reg);
+    if (!xaccTransHasSplitsInState(trans, VREC))
+        return;
+    gnc_split_register_unvoid_current_trans(reg);
+    LEAVE(" ");
+}
+
+
+static void
+gnc_plugin_page_register2_cmd_reverse_transaction (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    GNCSplitReg *gsr;
+    Transaction *trans, *new_trans;
+
+    ENTER("(action %p, page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    trans = gnc_split_register_get_current_trans(reg);
+    if (trans == NULL)
+        return;
+
+    if (xaccTransGetReversedBy(trans))
+    {
+        gnc_error_dialog(gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page)), "%s",
+                         _("A reversing entry has already been created for this transaction."));
+        return;
+    }
+
+    qof_event_suspend();
+    new_trans = xaccTransReverse(trans);
+
+    /* Clear transaction level info */
+    xaccTransSetDatePostedSecs(new_trans, time(NULL));
+    xaccTransSetDateEnteredSecs(new_trans, time(NULL));
+
+    qof_event_resume();
+
+    /* Now jump to new trans */
+    gsr = gnc_plugin_page_register2_get_gsr(GNC_PLUGIN_PAGE(page));
+    gnc_split_reg_jump_to_split(gsr, xaccTransGetSplit(new_trans, 0));
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_shift_transaction_forward (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    GNCSplitReg *gsr;
+    Transaction *trans, *new_trans;
+    Timespec entered;
+
+    ENTER("(action %p, page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    trans = gnc_split_register_get_current_trans(reg);
+    if (trans == NULL)
+        return;
+
+    qof_event_suspend();
+
+    xaccTransGetDatePostedTS(trans, &entered);
+    xaccTransSetDatePostedSecs(trans, entered.tv_sec + 1);
+
+    qof_event_resume();
+
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_view_sort_by (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GtkWidget *dialog, *button;
+    GtkBuilder *builder;
+    SortType sort;
+    const gchar *name;
+    gchar *title;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+    ENTER("(action %p, page %p)", action, page);
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (priv->sd.dialog)
+    {
+        gtk_window_present(GTK_WINDOW(priv->sd.dialog));
+        LEAVE("existing dialog");
+        return;
+    }
+
+    /* Create the dialog */
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder, "gnc-plugin-page-register.glade", "Sort By");
+    dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Sort By"));
+    priv->sd.dialog = dialog;
+    gtk_window_set_transient_for(GTK_WINDOW(dialog),
+                                 gnc_window_get_gtk_window(GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window)));
+    /* Translations: The %s is the name of the plugin page */
+    title = g_strdup_printf(_("Sort %s by..."),
+                            gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(page)));
+    gtk_window_set_title(GTK_WINDOW(dialog), title);
+    g_free(title);
+
+    /* Set the button for the current sort order */
+    sort = gnc_split_reg_get_sort_type(priv->gsr);
+    name = SortTypeasString(sort);
+    button = GTK_WIDGET(gtk_builder_get_object (builder, name));
+    DEBUG("current sort %d, button %s(%p)", sort, name, button);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+    priv->sd.original_sort_type = sort;
+
+    button = GTK_WIDGET(gtk_builder_get_object (builder, "sort_save"));
+    if (priv->sd.save_order == TRUE)
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+
+    /* Wire it up */
+    gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, page);
+
+    /* Show it */
+    gtk_widget_show(dialog);
+    g_object_unref(G_OBJECT(builder));
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_view_filter_by (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    GncPluginPageRegister2Private *priv;
+    GtkWidget *dialog, *toggle, *button, *start_date, *end_date, *table, *hbox;
+    time_t start_time, end_time, time_val;
+    GtkBuilder *builder;
+    gboolean sensitive, value;
+    Query *query;
+    gchar *title;
+    int i;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+    ENTER("(action %p, page %p)", action, page);
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    if (priv->fd.dialog)
+    {
+        gtk_window_present(GTK_WINDOW(priv->fd.dialog));
+        LEAVE("existing dialog");
+        return;
+    }
+
+    /* Create the dialog */
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "gnc-plugin-page-register.glade", "Filter By");
+    dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Filter By"));
+    priv->fd.dialog = dialog;
+    gtk_window_set_transient_for(GTK_WINDOW(dialog),
+                                 gnc_window_get_gtk_window(GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window)));
+
+    /* Translators: The %s is the name of the plugin page */
+    title = g_strdup_printf(_("Filter %s by..."),
+                            gnc_plugin_page_get_page_name(GNC_PLUGIN_PAGE(page)));
+    gtk_window_set_title(GTK_WINDOW(dialog), title);
+    g_free(title);
+
+    /* Set the check buttons for the current status */
+    for (i = 0; status_actions[i].action_name; i++)
+    {
+        toggle = GTK_WIDGET(gtk_builder_get_object (builder, status_actions[i].action_name));
+        value = priv->fd.cleared_match & status_actions[i].value;
+        status_actions[i].widget = toggle;
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), value);
+    }
+    priv->fd.original_cleared_match = priv->fd.cleared_match;
+
+    button = GTK_WIDGET(gtk_builder_get_object (builder, "filter_save"));
+    if (priv->fd.save_filter == TRUE)
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+
+
+    /* Set the date info */
+    button = GTK_WIDGET(gtk_builder_get_object (builder, "filter_show_range"));
+    query = gnc_ledger_display_get_query (priv->ledger);
+    xaccQueryGetDateMatchTT(query, &start_time, &end_time);
+    priv->fd.original_start_time = start_time;
+    priv->fd.start_time = start_time;
+    priv->fd.original_end_time = end_time;
+    priv->fd.end_time = end_time;
+
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), start_time || end_time);
+    table = GTK_WIDGET(gtk_builder_get_object (builder, "select_range_table"));
+    priv->fd.table = table;
+    gtk_widget_set_sensitive(GTK_WIDGET(table), start_time || end_time);
+
+    priv->fd.start_date_choose = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_choose"));
+    priv->fd.start_date_today = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_today"));
+    priv->fd.end_date_choose = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_choose"));
+    priv->fd.end_date_today = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_today"));
+
+    {
+        /* Start date info */
+        if (start_time == 0)
+        {
+            button = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_earliest"));
+            time_val = xaccQueryGetEarliestDateFound (query);
+            sensitive = FALSE;
+        }
+        else
+        {
+            time_val = start_time;
+            if ((start_time >= gnc_timet_get_today_start()) &&
+                    (start_time <= gnc_timet_get_today_end()))
+            {
+                button = priv->fd.start_date_today;
+                sensitive = FALSE;
+            }
+            else
+            {
+                button = priv->fd.start_date_choose;
+                sensitive = TRUE;
+            }
+        }
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+        priv->fd.start_date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
+        hbox = GTK_WIDGET(gtk_builder_get_object (builder, "start_date_hbox"));
+        gtk_box_pack_start (GTK_BOX (hbox), priv->fd.start_date, TRUE, TRUE, 0);
+        gtk_widget_show (priv->fd.start_date);
+        gtk_widget_set_sensitive(GTK_WIDGET(priv->fd.start_date), sensitive);
+        gnc_date_edit_set_time(GNC_DATE_EDIT(priv->fd.start_date), time_val);
+        g_signal_connect (G_OBJECT (priv->fd.start_date), "date-changed",
+                          G_CALLBACK (gnc_plugin_page_register2_filter_gde_changed_cb),
+                          page);
+    }
+
+    {
+        /* End date info */
+        if (end_time == 0)
+        {
+            button = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_latest"));
+            time_val = xaccQueryGetLatestDateFound (query);
+            sensitive = FALSE;
+        }
+        else
+        {
+            time_val = end_time;
+            if ((end_time >= gnc_timet_get_today_start()) &&
+                    (end_time <= gnc_timet_get_today_end()))
+            {
+                button = priv->fd.end_date_today;
+                sensitive = FALSE;
+            }
+            else
+            {
+                button = priv->fd.end_date_choose;
+                sensitive = TRUE;
+            }
+        }
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+        priv->fd.end_date = gnc_date_edit_new (time (NULL), FALSE, FALSE);
+        hbox = GTK_WIDGET(gtk_builder_get_object (builder, "end_date_hbox"));
+        gtk_box_pack_start (GTK_BOX (hbox), priv->fd.end_date, TRUE, TRUE, 0);
+        gtk_widget_show (priv->fd.end_date);
+        gtk_widget_set_sensitive(GTK_WIDGET(priv->fd.end_date), sensitive);
+        gnc_date_edit_set_time(GNC_DATE_EDIT(priv->fd.end_date), time_val);
+        g_signal_connect (G_OBJECT (priv->fd.end_date), "date-changed",
+                          G_CALLBACK (gnc_plugin_page_register2_filter_gde_changed_cb),
+                          page);
+    }
+
+    /* Wire it up */
+    gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, page);
+
+    /* Show it */
+    gtk_widget_show_all(dialog);
+    g_object_unref(G_OBJECT(builder));
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_style_changed (GtkAction *action,
+        GtkRadioAction *current,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegisterStyle value;
+
+    ENTER("(action %p, radio action %p, plugin_page %p)",
+          action, current, plugin_page);
+
+    g_return_if_fail(GTK_IS_ACTION(action));
+    g_return_if_fail(GTK_IS_RADIO_ACTION(current));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    value = gtk_radio_action_get_current_value(current);
+    gnc_split_reg_change_style(priv->gsr, value);
+
+    gnc_plugin_page_register2_ui_update (NULL, plugin_page);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_style_double_line (GtkToggleAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    gboolean use_double_line;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GTK_IS_ACTION(action));
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+
+    use_double_line =  gtk_toggle_action_get_active (action);
+    if (use_double_line != reg->use_double_line)
+    {
+        gnc_split_register_config(reg, reg->type, reg->style, use_double_line);
+        gnc_ledger_display_refresh(priv->ledger);
+    }
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_transfer (GtkAction *action,
+                                       GncPluginPageRegister2 *page)
+{
+    Account *account;
+    GncWindow *gnc_window;
+    GtkWidget *window;
+
+    ENTER("(action %p, plugin_page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    account = gnc_plugin_page_register2_get_account (page);
+    gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+    window = GTK_WIDGET(gnc_window_get_gtk_window(gnc_window));
+    gnc_xfer_dialog (window, account);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_reconcile (GtkAction *action,
+                                        GncPluginPageRegister2 *page)
+{
+    Account *account;
+    GtkWindow *window;
+    RecnWindow * recnData;
+
+    ENTER("(action %p, plugin_page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    account = gnc_plugin_page_register2_get_account (page);
+
+    window = gnc_window_get_gtk_window(GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window));
+    recnData = recnWindow (GTK_WIDGET(window), account);
+    gnc_ui_reconcile_window_raise (recnData);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_autoclear (GtkAction *action,
+                                        GncPluginPageRegister2 *page)
+{
+    Account *account;
+    GtkWindow *window;
+    AutoClearWindow * autoClearData;
+
+    ENTER("(action %p, plugin_page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    account = gnc_plugin_page_register2_get_account (page);
+
+    window = gnc_window_get_gtk_window(GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window));
+    autoClearData = autoClearWindow (GTK_WIDGET(window), account);
+    gnc_ui_autoclear_window_raise (autoClearData);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_stock_split (GtkAction *action,
+        GncPluginPageRegister2 *page)
+{
+    Account *account;
+
+    ENTER("(action %p, plugin_page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    account = gnc_plugin_page_register2_get_account (page);
+    gnc_stock_split_dialog (NULL, account);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_lots (GtkAction *action,
+                                   GncPluginPageRegister2 *page)
+{
+    Account *account;
+
+    ENTER("(action %p, plugin_page %p)", action, page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+
+    account = gnc_plugin_page_register2_get_account (page);
+    gnc_lot_viewer_dialog (account);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_enter_transaction (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    gnc_split_reg_enter(priv->gsr, FALSE);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_cancel_transaction (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    gnc_split_register_cancel_cursor_trans_changes
+    (gnc_ledger_display_get_split_register(priv->ledger));
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_delete_transaction (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    gsr_default_delete_handler(priv->gsr, NULL);
+    LEAVE(" ");
+
+}
+
+static void
+gnc_plugin_page_register2_cmd_blank_transaction (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+
+    if (gnc_split_register_save (reg, TRUE))
+        gnc_split_register_redraw (reg);
+
+    gnc_split_reg_jump_to_blank (priv->gsr);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_duplicate_transaction (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    gnc_split_register_duplicate_current
+    (gnc_ledger_display_get_split_register(priv->ledger));
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_reinitialize_transaction (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    gsr_default_reinit_handler(priv->gsr, NULL);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_expand_transaction (GtkToggleAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    gboolean expand;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+    expand = gtk_toggle_action_get_active (action);
+    gnc_split_register_expand_current_trans (reg, expand);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_exchange_rate (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+
+    /* XXX Ignore the return value -- we don't care if this succeeds */
+    (void)gnc_split_register_handle_exchange (reg, TRUE);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_jump (GtkAction *action,
+                                   GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncPluginPage *new_page;
+    GncPluginPageRegister2 *new_reg_page;
+    GtkWidget *window;
+    GNCSplitReg *gsr;
+    SplitRegister *reg;
+    Account *account;
+    Account *leader;
+    Split *split;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    window = GNC_PLUGIN_PAGE (plugin_page)->window;
+    if (window == NULL)
+    {
+        LEAVE("no window");
+        return;
+    }
+
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+    split = gnc_split_register_get_current_split (reg);
+    if (split == NULL)
+    {
+        LEAVE("no split (1)");
+        return;
+    }
+
+    account = xaccSplitGetAccount (split);
+    if (account == NULL)
+    {
+        LEAVE("no account");
+        return;
+    }
+
+    leader = gnc_ledger_display_leader (priv->ledger);
+    if (account == leader)
+    {
+        split = xaccSplitGetOtherSplit (split);
+        if (split == NULL)
+        {
+            LEAVE("no split (2)");
+            return;
+        }
+
+        account = xaccSplitGetAccount (split);
+        if (account == NULL)
+        {
+            LEAVE("no account (2)");
+            return;
+        }
+
+        if (account == leader)
+        {
+            LEAVE("register open for account");
+            return;
+        }
+    }
+
+    new_page = gnc_plugin_page_register2_new (account, FALSE);
+    if (new_page == NULL)
+    {
+        LEAVE("couldn't create new page");
+        return;
+    }
+    new_reg_page = GNC_PLUGIN_PAGE_REGISTER2(new_page);
+
+    gnc_main_window_open_page (GNC_MAIN_WINDOW(window), new_page);
+    gsr = gnc_plugin_page_register2_get_gsr (new_page);
+    gnc_split_reg_jump_to_split(gsr, split);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_schedule (GtkAction *action,
+                                       GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    gsr_default_schedule_handler(priv->gsr, NULL);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_scrub_current (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    Query *query;
+    Account *root;
+    Transaction *trans;
+    SplitRegister *reg;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    query = gnc_ledger_display_get_query( priv->ledger );
+    if (query == NULL)
+    {
+        LEAVE("no query found");
+        return;
+    }
+
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    trans = gnc_split_register_get_current_trans(reg);
+    if (trans == NULL)
+    {
+        LEAVE("no trans found");
+        return;
+    }
+
+    gnc_suspend_gui_refresh();
+    root = gnc_get_current_root_account();
+    xaccTransScrubOrphans(trans);
+    xaccTransScrubImbalance(trans, root, NULL);
+    gnc_resume_gui_refresh();
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_scrub_all (GtkAction *action,
+                                        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    Query *query;
+    Account *root;
+    Transaction *trans;
+    Split *split;
+    GList *node;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    query = gnc_ledger_display_get_query( priv->ledger );
+    if (!query)
+    {
+        LEAVE("no query found");
+        return;
+    }
+
+    gnc_suspend_gui_refresh();
+    root = gnc_get_current_root_account();
+
+    for (node = qof_query_run(query); node; node = node->next)
+    {
+        split = node->data;
+        trans = xaccSplitGetParent(split);
+
+        xaccTransScrubOrphans(trans);
+        xaccTransScrubImbalance(trans, root, NULL);
+    }
+
+    gnc_resume_gui_refresh();
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_account_report (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncMainWindow *window;
+    int id;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    id = report_helper (priv->ledger, NULL, NULL);
+    if (id >= 0)
+        gnc_main_window_open_report(id, window);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register2_cmd_transaction_report (GtkAction *action,
+        GncPluginPageRegister2 *plugin_page)
+{
+    GncPluginPageRegister2Private *priv;
+    GncMainWindow *window;
+    SplitRegister *reg;
+    Split *split;
+    Query *query;
+    int id;
+
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(plugin_page);
+    reg = gnc_ledger_display_get_split_register (priv->ledger);
+
+    split = gnc_split_register_get_current_split (reg);
+    if (!split)
+        return;
+
+    query = qof_query_create_for(GNC_ID_SPLIT);
+
+    qof_query_set_book (query, gnc_get_current_book ());
+
+    xaccQueryAddGUIDMatch (query, xaccSplitGetGUID (split),
+                           GNC_ID_SPLIT, QOF_QUERY_AND);
+
+    window = GNC_MAIN_WINDOW(GNC_PLUGIN_PAGE(plugin_page)->window);
+    id = report_helper (priv->ledger, split, query);
+    if (id >= 0)
+        gnc_main_window_open_report(id, window);
+    LEAVE(" ");
+}
+
+/************************************************************/
+/*                    Auxiliary functions                   */
+/************************************************************/
+
+void
+gnc_plugin_page_register2_set_options (GncPluginPage *plugin_page,
+                                      gint lines_default,
+                                      gboolean read_only)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page));
+
+    page = GNC_PLUGIN_PAGE_REGISTER2 (plugin_page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+    priv->lines_default     = lines_default;
+    priv->read_only         = read_only;
+}
+
+GNCSplitReg *
+gnc_plugin_page_register2_get_gsr (GncPluginPage *plugin_page)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+
+    g_return_val_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(plugin_page), NULL);
+
+    page = GNC_PLUGIN_PAGE_REGISTER2 (plugin_page);
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+    return priv->gsr;
+}
+
+static void
+gnc_plugin_page_help_changed_cb (GNCSplitReg *gsr, GncPluginPageRegister2 *register_page)
+{
+    GncPluginPageRegister2Private *priv;
+    SplitRegister *reg;
+    GncWindow *window;
+    char *help;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(register_page));
+
+    window = GNC_WINDOW(GNC_PLUGIN_PAGE(register_page)->window);
+    if (!window)
+    {
+        // This routine can be called before the page is added to a
+        // window.
+        return;
+    }
+
+    /* Get the text from the ledger */
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(register_page);
+    reg = gnc_ledger_display_get_split_register(priv->ledger);
+    help = gnc_table_get_help(reg->table);
+    gnc_window_set_status(window, GNC_PLUGIN_PAGE(register_page), help);
+    g_free(help);
+}
+
+static void
+gnc_plugin_page_register2_refresh_cb (GHashTable *changes, gpointer user_data)
+{
+    GncPluginPageRegister2 *page = user_data;
+    GncPluginPageRegister2Private *priv;
+
+    g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER2(page));
+    priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+
+    if (changes)
+    {
+        const EventInfo* ei;
+        ei = gnc_gui_get_entity_events(changes, &priv->key);
+        if (ei)
+        {
+            if (ei->event_mask & QOF_EVENT_DESTROY)
+            {
+                gnc_main_window_close_page(GNC_PLUGIN_PAGE(page));
+                return;
+            }
+            if (ei->event_mask & QOF_EVENT_MODIFY)
+            {
+            }
+        }
+    }
+    else
+    {
+        /* forced updates */
+        gnucash_register_refresh_from_gconf(priv->gsr->reg);
+        gtk_widget_queue_draw(priv->widget);
+    }
+
+    gnc_plugin_page_register2_ui_update(NULL, page);
+}
+
+static void
+gnc_plugin_page_register2_close_cb (gpointer user_data)
+{
+    GncPluginPage *plugin_page = GNC_PLUGIN_PAGE(user_data);
+    gnc_main_window_close_page (plugin_page);
+}
+
+/** This function is called when an account has been edited and an
+ *  "extreme" change has been made to it.  (E.G. Changing from a
+ *  credit card account to an expense account.  This rouine is
+ *  responsible for finding all open registers containing the account
+ *  and closing them.
+ *
+ *  @param account A pointer to the account that was changed.
+ */
+static void
+gppr_account_destroy_cb (Account *account)
+{
+    GncPluginPageRegister2 *page;
+    GncPluginPageRegister2Private *priv;
+    GNCLedgerDisplayType ledger_type;
+    const GncGUID *acct_guid;
+    const GList *citem;
+    GList *item, *kill = NULL;
+
+    acct_guid = xaccAccountGetGUID(account);
+
+    /* Find all windows that need to be killed.  Don't kill them yet, as
+     * that would affect the list being walked.*/
+    citem = gnc_gobject_tracking_get_list(GNC_PLUGIN_PAGE_REGISTER2_NAME);
+    for ( ; citem; citem = g_list_next(citem))
+    {
+        page = (GncPluginPageRegister2 *)citem->data;
+        priv = GNC_PLUGIN_PAGE_REGISTER2_GET_PRIVATE(page);
+        ledger_type = gnc_ledger_display_type (priv->ledger);
+        if (ledger_type == LD_GL)
+        {
+            kill = g_list_append(kill, page);
+            /* kill it */
+        }
+        else if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+        {
+            if (guid_compare(acct_guid, &priv->key) == 0)
+            {
+                kill = g_list_append(kill, page);
+            }
+        }
+    }
+
+    /* Now kill them. */
+    for (item = kill; item; item = g_list_next(item))
+    {
+        page = (GncPluginPageRegister2 *)item->data;
+        gnc_main_window_close_page(GNC_PLUGIN_PAGE(page));
+    }
+}
+
+/** This function is the handler for all event messages from the
+ *  engine.  Its purpose is to update the register page any time
+ *  an account or transaction is changed.
+ *
+ *  @internal
+ *
+ *  @param entity A pointer to the affected item.
+ *
+ *  @param event_type The type of the affected item.
+ *
+ *  @param page A pointer to the register page.
+ *
+ *  @param ed
+ */
+static void
+gnc_plugin_page_register2_event_handler (QofInstance *entity,
+                                        QofEventId event_type,
+                                        GncPluginPageRegister2 *page,
+                                        GncEventData *ed)
+{
+    Transaction *trans;
+    QofBook *book;
+    GncPluginPage *visible_page;
+    GtkWidget *window;
+    gchar *label, *color;
+
+    g_return_if_fail(page);	/* Required */
+    if (!GNC_IS_TRANS(entity) && !GNC_IS_ACCOUNT(entity))
+        return;
+
+    ENTER("entity %p of type %d, page %p, event data %p",
+          entity, event_type, page, ed);
+
+    window = gnc_plugin_page_get_window(GNC_PLUGIN_PAGE(page));
+
+    if (GNC_IS_ACCOUNT(entity))
+    {
+        if (GNC_IS_MAIN_WINDOW(window))
+        {
+            label = gnc_plugin_page_register2_get_tab_name(GNC_PLUGIN_PAGE(page));
+            main_window_update_page_name(GNC_PLUGIN_PAGE(page), label);
+            color = gnc_plugin_page_register2_get_tab_color(GNC_PLUGIN_PAGE(page));
+            main_window_update_page_color(GNC_PLUGIN_PAGE(page), color);
+            g_free(color);
+            g_free(label);
+        }
+        LEAVE("tab name updated");
+        return;
+    }
+
+    if (!(event_type & (QOF_EVENT_MODIFY | QOF_EVENT_DESTROY)))
+    {
+        LEAVE("not a modify");
+        return;
+    }
+    trans = GNC_TRANS(entity);
+    book = qof_instance_get_book(QOF_INSTANCE(trans));
+    if (!gnc_plugin_page_has_book(GNC_PLUGIN_PAGE(page), book))
+    {
+        LEAVE("not in this book");
+        return;
+    }
+
+    if (GNC_IS_MAIN_WINDOW(window))
+    {
+        visible_page = gnc_main_window_get_current_page(GNC_MAIN_WINDOW(window));
+        if (visible_page != GNC_PLUGIN_PAGE(page))
+        {
+            LEAVE("page not visible");
+            return;
+        }
+    }
+
+    gnc_plugin_page_register2_ui_update(NULL, page);
+    LEAVE(" ");
+    return;
+}
+
+
+/** @} */
+/** @} */

Added: gnucash/trunk/src/gnome/gnc-plugin-page-register2.h
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-register2.h	                        (rev 0)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-register2.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,151 @@
+/**********************************************************************
+ * gnc-plugin-page-register2.h -- register page functions              *
+ *                                                                    *
+ * Copyright (C) 2003 Jan Arne Petersen <jpetersen at uni-bonn.de>       *
+ * Copyright (C) 2003,2005,2006 David Hampton <hampton at employees.org> *
+ *                                                                    *
+ * This program is free software; you can redistribute it and/or      *
+ * modify it under the terms of the GNU General Public License as     *
+ * published by the Free Software Foundation; either version 2 of     *
+ * the License, or (at your option) any later version.                *
+ *                                                                    *
+ * This program is distributed in the hope that it will be useful,    *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of     *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
+ * GNU General Public License for more details.                       *
+ *                                                                    *
+ * You should have received a copy of the GNU General Public License  *
+ * along with this program; if not, contact:                          *
+ *                                                                    *
+ * Free Software Foundation           Voice:  +1-617-542-5942         *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652         *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                     *
+ **********************************************************************/
+
+/** @addtogroup ContentPlugins
+    @{ */
+/** @addtogroup Register2Plugin Register2 Page
+    @{ */
+/** @file gnc-plugin-page-register.h
+    @brief  Functions providing a register page for the GnuCash UI
+    @author Copyright (C) 2003 Jan Arne Petersen <jpetersen at uni-bonn.de>
+    @author Copyright (C) 2003 David Hampton <hampton at employees.org>
+*/
+
+#ifndef __GNC_PLUGIN_PAGE_REGISTER2_H
+#define __GNC_PLUGIN_PAGE_REGISTER2_H
+
+#include <gtk/gtk.h>
+
+#include "Account.h"
+#include "gnc-ledger-display.h"
+#include "gnc-plugin-page.h"
+#include "gnc-split-reg.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_PLUGIN_PAGE_REGISTER2            (gnc_plugin_page_register2_get_type ())
+#define GNC_PLUGIN_PAGE_REGISTER2(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2))
+#define GNC_PLUGIN_PAGE_REGISTER2_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2Class))
+#define GNC_IS_PLUGIN_PAGE_REGISTER2(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_PAGE_REGISTER2))
+#define GNC_IS_PLUGIN_PAGE_REGISTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_PAGE_REGISTER2))
+#define GNC_PLUGIN_PAGE_REGISTER2_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_PAGE_REGISTER2, GncPluginPageRegister2Class))
+#define GNC_PLUGIN_PAGE_REGISTER2_NAME "GncPluginPageRegister2"
+
+/* typedefs & structures */
+typedef struct
+{
+    GncPluginPage gnc_plugin_page;
+} GncPluginPageRegister2;
+
+typedef struct
+{
+    GncPluginPageClass gnc_plugin_page;
+} GncPluginPageRegister2Class;
+
+/* function prototypes */
+
+/** Retrieve the type number for the plugin page.
+ *
+ *  @return The type number.
+ */
+GType gnc_plugin_page_register2_get_type (void);
+
+
+/** Create a new "register" plugin page, given a pointer to an
+ *  account.
+ *
+ *  @param account The pointer to the account to embed in the
+ *  register.
+ *
+ *  @param subaccounts TRUE if all the sub-accounts of the specified
+ *  account should be included in the register.
+ *
+ *  @return The newly created plugin page.
+ */
+GncPluginPage *
+gnc_plugin_page_register2_new (Account *account, gboolean subaccounts);
+
+
+/** Create a new "register" plugin page, given a pointer to an already
+ *  created ledger.  This function should be used when the ledger
+ *  already exists.  (E.G.  From the "find transaction" code, or from
+ *  the scheduled transaction code.)
+ *
+ *  @param ledger The pointer to the ledger to embed into the
+ *  register.
+ *
+ *  @return The newly created plugin page.
+ */
+GncPluginPage *
+gnc_plugin_page_register2_new_ledger (GNCLedgerDisplay *ledger);
+
+
+/** Create a new "register" plugin page containing a general ledger.
+ *
+ *  @return The newly created plugin page.
+ */
+GncPluginPage *
+gnc_plugin_page_register2_new_gl (void);
+
+
+/** Set various register options on a newly created "register" plugin page.
+ *
+ *  @param plugin_page The "register" page to modify.
+ *
+ *  @param lines_default Used to calculate the minimum preferred height of
+ *                       the plugin page.
+ *
+ *  @param read_only True if the register should be read-only.
+ */
+void
+gnc_plugin_page_register2_set_options (GncPluginPage *plugin_page,
+                                      gint lines_default,
+                                      gboolean read_only);
+
+
+/** Get the GNCSplitReg data structure associated with this register page.
+ *
+ *  @param plugin_page A "register" page.
+ */
+GNCSplitReg *
+gnc_plugin_page_register2_get_gsr (GncPluginPage *plugin_page);
+
+
+/** Get the Account associated with this register page.
+ *
+ *  @param page A "register" page.
+ *
+ *  @return The account if the register contains only a single
+ *  account, or an account and its sub-accounts.  NULL otherwise.
+ */
+Account *
+gnc_plugin_page_register2_get_account (GncPluginPageRegister2 *page);
+
+G_END_DECLS
+/** @} */
+/** @} */
+
+#endif /* __GNC_PLUGIN_PAGE_REGISTER2_H */
+

Added: gnucash/trunk/src/gnome/gnc-plugin-register2.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-register2.c	                        (rev 0)
+++ gnucash/trunk/src/gnome/gnc-plugin-register2.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,202 @@
+/*
+ * gnc-plugin-register2.c --
+ *
+ * Copyright (C) 2003 Jan Arne Petersen
+ * Author: Jan Arne Petersen <jpetersen at uni-bonn.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gnc-component-manager.h"
+#include "gnc-plugin-register2.h"
+#include "gnc-plugin-page-register2.h"
+
+
+static void gnc_plugin_register2_class_init (GncPluginRegister2Class *klass);
+static void gnc_plugin_register2_init (GncPluginRegister2 *plugin);
+static void gnc_plugin_register2_finalize (GObject *object);
+
+/* Command callbacks */
+static void gnc_plugin_register2_cmd_general_ledger (GtkAction *action, GncMainWindowActionData *data);
+
+#define PLUGIN_ACTIONS_NAME "gnc-plugin-register2-actions"
+#define PLUGIN_UI_FILENAME  "gnc-plugin-register2-ui.xml"
+#define GCONF_REGISTER2_SECTION "general/register"
+
+static GtkActionEntry gnc_plugin_actions [] =
+{
+    {
+        "ToolsGeneralLedgerAction", NULL, N_("_General Ledger"), NULL,
+        N_("Open a general ledger window"),
+        G_CALLBACK (gnc_plugin_register2_cmd_general_ledger)
+    },
+};
+static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
+
+typedef struct GncPluginRegister2Private
+{
+    gpointer dummy;
+} GncPluginRegister2Private;
+
+#define GNC_PLUGIN_REGISTER2_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2Private))
+
+static GObjectClass *parent_class = NULL;
+static QofLogModule log_module = GNC_MOD_GUI;
+
+/************************************************************
+ *                     Other Functions                      *
+ ************************************************************/
+
+/** This function is called whenever an entry in the general register
+ *  section of gconf is changed.  It does nothing more than kick off a
+ *  gui refresh which should be delivered to any open register page.
+ *  The register pages will then reread their settings from gconf and
+ *  update the screen.
+ *
+ *  @client Unused.
+ *
+ *  @cnxn_id Unused.
+ *
+ *  @entry Unused.
+ *
+ *  @user_data Unused.
+ */
+static void
+gnc_plugin_register2_gconf_changed (GConfClient *client,
+                                   guint cnxn_id,
+                                   GConfEntry *entry,
+                                   gpointer user_data)
+{
+    ENTER("");
+    gnc_gui_refresh_all ();
+    LEAVE("");
+}
+
+/************************************************************
+ *                  Object Implementation                   *
+ ************************************************************/
+
+GType
+gnc_plugin_register2_get_type (void)
+{
+    static GType gnc_plugin_register2_type = 0;
+
+    if (gnc_plugin_register2_type == 0)
+    {
+        static const GTypeInfo our_info =
+        {
+            sizeof (GncPluginRegister2Class),
+            NULL,		/* base_init */
+            NULL,		/* base_finalize */
+            (GClassInitFunc) gnc_plugin_register2_class_init,
+            NULL,		/* class_finalize */
+            NULL,		/* class_data */
+            sizeof (GncPluginRegister2),
+            0,		/* n_preallocs */
+            (GInstanceInitFunc) gnc_plugin_register2_init
+        };
+
+        gnc_plugin_register2_type = g_type_register_static (GNC_TYPE_PLUGIN,
+                                   "GncPluginRegister2",
+                                   &our_info, 0);
+    }
+
+    return gnc_plugin_register2_type;
+}
+
+GncPlugin *
+gnc_plugin_register2_new (void)
+{
+    GncPluginRegister2 *plugin;
+
+    /* Reference the register page plugin to ensure it exists in
+     * the gtk type system. */
+    GNC_TYPE_PLUGIN_PAGE_REGISTER2;
+
+    plugin = g_object_new (GNC_TYPE_PLUGIN_REGISTER2,
+                           NULL);
+
+    return GNC_PLUGIN (plugin);
+}
+
+static void
+gnc_plugin_register2_class_init (GncPluginRegister2Class *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    object_class->finalize = gnc_plugin_register2_finalize;
+
+    /* plugin info */
+    plugin_class->plugin_name  = GNC_PLUGIN_REGISTER2_NAME;
+
+    /* widget addition/removal */
+    plugin_class->actions_name = PLUGIN_ACTIONS_NAME;
+    plugin_class->actions      = gnc_plugin_actions;
+    plugin_class->n_actions    = gnc_plugin_n_actions;
+    plugin_class->ui_filename  = PLUGIN_UI_FILENAME;
+
+    plugin_class->gconf_section = GCONF_REGISTER2_SECTION;
+    plugin_class->gconf_notifications = gnc_plugin_register2_gconf_changed;
+
+    g_type_class_add_private(klass, sizeof(GncPluginRegister2Private));
+}
+
+static void
+gnc_plugin_register2_init (GncPluginRegister2 *plugin)
+{
+}
+
+static void
+gnc_plugin_register2_finalize (GObject *object)
+{
+    GncPluginRegister2 *plugin;
+    GncPluginRegister2Private *priv;
+
+    g_return_if_fail (GNC_IS_PLUGIN_REGISTER2 (object));
+
+    plugin = GNC_PLUGIN_REGISTER2 (object);
+    priv = GNC_PLUGIN_REGISTER2_GET_PRIVATE(plugin);
+
+    G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/************************************************************
+ *                    Command Callbacks                     *
+ ************************************************************/
+
+static void
+gnc_plugin_register2_cmd_general_ledger (GtkAction *action,
+                                        GncMainWindowActionData *data)
+{
+    GncPluginPage *page;
+
+    g_return_if_fail (data != NULL);
+
+    page = gnc_plugin_page_register2_new_gl ();
+    gnc_main_window_open_page (data->window, page);
+}

Added: gnucash/trunk/src/gnome/gnc-plugin-register2.h
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-register2.h	                        (rev 0)
+++ gnucash/trunk/src/gnome/gnc-plugin-register2.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,60 @@
+/*
+ * gnc-plugin-register2.h --
+ *
+ * Copyright (C) 2003 Jan Arne Petersen
+ * Author: Jan Arne Petersen <jpetersen at uni-bonn.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+#ifndef __GNC_PLUGIN_REGISTER2_H
+#define __GNC_PLUGIN_REGISTER2_H
+
+#include "gnc-plugin.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_PLUGIN_REGISTER2            (gnc_plugin_register2_get_type ())
+#define GNC_PLUGIN_REGISTER2(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2))
+#define GNC_PLUGIN_REGISTER2_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2Class))
+#define GNC_IS_PLUGIN_REGISTER2(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_REGISTER2))
+#define GNC_IS_PLUGIN_REGISTER2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_REGISTER2))
+#define GNC_PLUGIN_REGISTER2_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_REGISTER2, GncPluginRegister2Class))
+
+#define GNC_PLUGIN_REGISTER2_NAME "gnc-plugin-register2"
+
+/* typedefs & structures */
+typedef struct
+{
+    GncPlugin gnc_plugin;
+} GncPluginRegister2;
+
+typedef struct
+{
+    GncPluginClass gnc_plugin;
+} GncPluginRegister2Class;
+
+/* function prototypes */
+GType      gnc_plugin_register2_get_type (void);
+
+GncPlugin *gnc_plugin_register2_new      (void);
+
+G_END_DECLS
+
+#endif /* __GNC_PLUGIN_REGISTER2_H */

Modified: gnucash/trunk/src/gnome/top-level.c
===================================================================
--- gnucash/trunk/src/gnome/top-level.c	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome/top-level.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -51,8 +51,10 @@
 #include "gnc-plugin-basic-commands.h" /* FIXME Remove this line*/
 #include "gnc-plugin-file-history.h" /* FIXME Remove this line*/
 #include "gnc-plugin-register.h" /* FIXME Remove this line*/
+#include "gnc-plugin-register2.h" /* FIXME Remove this line*/
 #include "gnc-plugin-budget.h"
 #include "gnc-plugin-page-register.h"
+#include "gnc-plugin-page-register2.h"
 #include "gnc-plugin-manager.h" /* FIXME Remove this line*/
 #include "gnc-html.h"
 #include "gnc-gnome-utils.h"
@@ -417,6 +419,8 @@
         gnc_plugin_manager_get (), gnc_plugin_menu_additions_new ());
     gnc_plugin_manager_add_plugin (
         gnc_plugin_manager_get (), gnc_plugin_register_new ());
+    gnc_plugin_manager_add_plugin (
+        gnc_plugin_manager_get (), gnc_plugin_register2_new ());
     /* I'm not sure why the FIXME note says to remove this.  Maybe
        each module should be adding its own plugin to the manager?
        Anyway... Oh, maybe... nah */

Modified: gnucash/trunk/src/gnome/ui/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/ui/Makefile.am	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome/ui/Makefile.am	2012-08-07 17:24:33 UTC (rev 22289)
@@ -7,7 +7,9 @@
 	gnc-plugin-page-account-tree-ui.xml \
 	gnc-plugin-file-history-ui.xml \
 	gnc-plugin-register-ui.xml \
+	gnc-plugin-register2-ui.xml \
 	gnc-plugin-page-register-ui.xml \
+	gnc-plugin-page-register2-ui.xml \
         gnc-plugin-page-sx-list-ui.xml \
 	gnc-plugin-page-sxregister-ui.xml \
 	gnc-sxed-to-create-window-ui.xml \

Modified: gnucash/trunk/src/gnome/ui/gnc-plugin-page-account-tree-ui.xml
===================================================================
--- gnucash/trunk/src/gnome/ui/gnc-plugin-page-account-tree-ui.xml	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome/ui/gnc-plugin-page-account-tree-ui.xml	2012-08-07 17:24:33 UTC (rev 22289)
@@ -7,6 +7,7 @@
 	<menuitem name="EditRenumberSubaccounts" action="EditRenumberSubaccountsAction"/>
         <separator name="EditSep2"/>
         <menuitem name="FileOpenAccount" action="FileOpenAccountAction"/>
+        <menuitem name="FileOpenAccount2" action="FileOpenAccount2Action"/>
         <menuitem name="FileOpenSubaccounts" action="FileOpenSubaccountsAction"/>
       </placeholder>
     </menu>
@@ -34,6 +35,7 @@
   <popup name="MainPopup" action="FakeToplevel">
     <placeholder name="PopupPlaceholder2">
       <menuitem name="AccountOpenAccount" action="FileOpenAccountAction"/>
+      <menuitem name="AccountOpenAccount2" action="FileOpenAccount2Action"/>
       <menuitem name="AccountOpenSubaccounts" action="FileOpenSubaccountsAction"/>
       <menuitem name="AccountEditAccount" action="EditEditAccountAction"/>
       <separator name="AccountSep1"/>
@@ -60,6 +62,7 @@
     <placeholder name="DefaultToolbarPlaceholder">
       <separator name="ToolbarSep2"/>
       <toolitem name="ToolbarOpenAccount" action="FileOpenAccountAction"/>
+      <toolitem name="ToolbarOpenAccount2" action="FileOpenAccount2Action"/>
       <toolitem name="ToolbarEditAccount" action="EditEditAccountAction"/>
       <separator name="ToolbarSep3"/>
       <toolitem name="ToolbarNewAccount" action="FileNewAccountAction"/>

Added: gnucash/trunk/src/gnome/ui/gnc-plugin-page-register2-ui.xml
===================================================================
--- gnucash/trunk/src/gnome/ui/gnc-plugin-page-register2-ui.xml	                        (rev 0)
+++ gnucash/trunk/src/gnome/ui/gnc-plugin-page-register2-ui.xml	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,104 @@
+<ui>
+  <menubar>
+    <menu name="Edit" action="EditAction">
+      <placeholder name="EditAllSelectedPlaceholder">
+        <menuitem name="EditEditAccount"        action="EditEditAccountAction"/>
+      </placeholder>
+    </menu>
+
+    <menu name="Transaction" action="TransactionAction">
+      <menuitem name="CutTransaction"     	action="CutTransactionAction"/>
+      <menuitem name="CopyTransaction"    	action="CopyTransactionAction"/>
+      <menuitem name="PasteTransaction"   	action="PasteTransactionAction"/>
+      <menuitem name="DuplicateTransaction"    	action="DuplicateTransactionAction"/>
+      <menuitem name="DeleteTransaction"       	action="DeleteTransactionAction"/>
+      <menuitem name="RemoveTransactionSplits" 	action="RemoveTransactionSplitsAction"/>
+      <!--menuitem name="ShiftTransactionForward" 	action="ShiftTransactionForwardAction"/-->
+      <separator name="TransactionSep1"/>
+      <menuitem name="RecordTransaction"        action="RecordTransactionAction"/>
+      <menuitem name="CancelTransaction"        action="CancelTransactionAction"/>
+      <separator name="TransactionSep2"/>
+      <menuitem name="VoidTransaction"    	action="VoidTransactionAction"/>
+      <menuitem name="UnvoidTransaction"  	action="UnvoidTransactionAction"/>
+      <menuitem name="ReverseTransaction" 	action="ReverseTransactionAction"/>
+    </menu>
+
+    <menu name="View" action="ViewAction">
+      <placeholder name="ViewContentPlaceholder">
+        <menuitem name="ViewStyleBasic"        	action="ViewStyleBasicAction"/>
+        <menuitem name="ViewStyleAutoSplit"    	action="ViewStyleAutoSplitAction"/>
+        <menuitem name="ViewStyleJournal"      	action="ViewStyleJournalAction"/>
+        <separator name="ViewSep44"/>
+        <menuitem name="ViewStyleDoubleLine"   	action="ViewStyleDoubleLineAction"/>
+      </placeholder>
+    </menu>
+
+    <menu name="Actions" action="ActionsAction">
+      <placeholder name="ActionsPlaceholder">
+        <separator name="ActionsSep1"/>
+	<menuitem name="ActionsTransfer"         action="ActionsTransferAction"/>
+	<menuitem name="ActionsReconcile"        action="ActionsReconcileAction"/>
+	<menuitem name="ActionsStockSplit"       action="ActionsStockSplitAction"/>
+	<menuitem name="ActionLots"              action="ActionsLotsAction"/>
+        <separator name="ActionsSep4"/>
+        <menuitem name="BlankTransaction"        action="BlankTransactionAction"/>
+        <menuitem name="SplitTransaction"        action="SplitTransactionAction"/>
+        <menuitem name="EditExchangeRate"        action="EditExchangeRateAction"/>
+        <menuitem name="ScheduleTransaction"     action="ScheduleTransactionAction"/>
+        <menuitem name="JumpTransaction"         action="JumpTransactionAction"/>
+	<separator name="ActionsSep5"/>
+      </placeholder>
+      <menu name="ScrubMenu" action="ScrubMenuAction">
+	<menuitem name="ScrubAll" action="ScrubAllAction"/>
+	<menuitem name="ScrubCurrent" action="ScrubCurrentAction"/>
+      </menu>
+    </menu>
+
+    <menu name="Reports" action="ReportsAction">
+      <placeholder name="AccountReports">
+        <menuitem name="ReportsAccountReport"      action="ReportsAccountReportAction"/>
+        <menuitem name="ReportsAcctTransReport"    action="ReportsAcctTransReportAction"/>
+      </placeholder>
+    </menu>
+  </menubar>
+
+  <toolbar name="DefaultToolbar">
+    <placeholder name="DefaultToolbarPlaceholder">
+      <toolitem name="ToolbarDuplicateTransaction" action="DuplicateTransactionAction"/>
+      <toolitem name="ToolbarDeleteTransaction"    action="DeleteTransactionAction"/>
+      <separator name="ToolbarSep66"/>
+      <toolitem name="ToolbarRecordTransaction"    action="RecordTransactionAction"/>
+      <toolitem name="ToolbarCancelTransaction"    action="CancelTransactionAction"/>
+      <separator name="ToolbarSep67"/>
+      <toolitem name="ToolbarBlankTransaction"     action="BlankTransactionAction"/>
+      <toolitem name="ToolbarSplitTransaction"     action="SplitTransactionAction"/>
+      <toolitem name="ToolbarJumpTransaction"      action="JumpTransactionAction"/>
+      <toolitem name="ToolbarScheduleTransaction"  action="ScheduleTransactionAction"/>
+      <separator name="ToolbarSep68"/>
+      <toolitem name="ToolbarTransfer"             action="ActionsTransferAction"/>
+      <toolitem name="ActionsReconcile"            action="ActionsReconcileAction"/>
+    </placeholder>
+  </toolbar>
+
+  <popup name="MainPopup"                    action="FakeToplevel">
+    <placeholder name="PopupPlaceholder1">
+      <menuitem name="ViewSortBy"              action="ViewSortByAction"/>
+      <menuitem name="ViewFilterBy"            action="ViewFilterByAction"/>
+    </placeholder>
+    <placeholder name="PopupPlaceholder2">
+      <menuitem name="DuplicateTransaction"    action="DuplicateTransactionAction"/>
+      <menuitem name="DeleteTransaction"       action="DeleteTransactionAction"/>
+      <menuitem name="RemoveTransactionSplits" action="RemoveTransactionSplitsAction"/>
+      <!--menuitem name="ShiftTransactionForward" 	action="ShiftTransactionForwardAction"/-->
+      <separator name="PopupSep2"/>
+      <menuitem name="RecordTransaction"       action="RecordTransactionAction"/>
+      <menuitem name="CancelTransaction"       action="CancelTransactionAction"/>
+      <separator name="PopupSep3"/>
+      <menuitem name="BlankTransaction"        action="BlankTransactionAction"/>
+      <menuitem name="SplitTransaction"        action="SplitTransactionAction"/>
+      <menuitem name="EditExchangeRate"        action="EditExchangeRateAction"/>
+      <menuitem name="ScheduleTransaction"     action="ScheduleTransactionAction"/>
+      <menuitem name="JumpTransaction"         action="JumpTransactionAction"/>
+    </placeholder>
+  </popup>
+</ui>

Added: gnucash/trunk/src/gnome/ui/gnc-plugin-register2-ui.xml
===================================================================
--- gnucash/trunk/src/gnome/ui/gnc-plugin-register2-ui.xml	                        (rev 0)
+++ gnucash/trunk/src/gnome/ui/gnc-plugin-register2-ui.xml	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,9 @@
+<ui>
+  <menubar>
+    <menu name="Tools" action="ToolsAction">
+      <placeholder name="ToolsPlaceholder">
+        <menuitem name="ToolsGeneralLedger" action="ToolsGeneralLedgerAction"/>
+      </placeholder>
+    </menu>
+  </menubar>
+</ui>

Modified: gnucash/trunk/src/gnome-utils/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome-utils/Makefile.am	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome-utils/Makefile.am	2012-08-07 17:24:33 UTC (rev 22289)
@@ -49,6 +49,9 @@
   gnc-account-sel.c \
   gnc-amount-edit.c \
   gnc-autosave.c \
+  gnc-cell-renderer-date.c \
+  gnc-cell-renderer-popup.c \
+  gnc-cell-renderer-popup-entry.c \
   gnc-combott.c \
   gnc-commodity-edit.c \
   gnc-currency-edit.c \
@@ -87,11 +90,13 @@
   gnc-tree-model-budget.c \
   gnc-tree-model-owner.c \
   gnc-tree-model-commodity.c \
+  gnc-tree-model-split-reg.c \
   gnc-tree-model-price.c \
   gnc-tree-view-account.c \
   gnc-tree-view-commodity.c \
   gnc-tree-view-owner.c \
   gnc-tree-view-price.c \
+  gnc-tree-view-split-reg.c \
   gnc-tree-view-sx-list.c \
   gnc-tree-view.c \
   gnc-window.c \
@@ -123,6 +128,9 @@
   dialog-utils.h \
   gnc-account-sel.h \
   gnc-amount-edit.h \
+  gnc-cell-renderer-date.h \
+  gnc-cell-renderer-popup.h \
+  gnc-cell-renderer-popup-entry.h \
   gnc-combott.h \
   gnc-commodity-edit.h \
   gnc-currency-edit.h \
@@ -160,10 +168,12 @@
   gnc-tree-model-owner.h \
   gnc-tree-model-commodity.h \
   gnc-tree-model-price.h \
+  gnc-tree-model-split-reg.h \
   gnc-tree-view-account.h \
   gnc-tree-view-commodity.h \
   gnc-tree-view-owner.h \
   gnc-tree-view-price.h \
+  gnc-tree-view-split-reg.h \
   gnc-tree-view-sx-list.h \
   gnc-tree-view.h \
   gnc-ui.h \

Added: gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.c	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,525 @@
+/*************************************************************************
+ * The following code has come from Planner. This code implements a
+ * GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
+ *
+ * These files have been renamed and changed to remove code not required
+ * and to remove a dependency on libplanner.
+ *
+ * Copyright (C) 2012 Robert Fewell
+ *
+ * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.com>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ **************************************************************************/
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <string.h>
+#include <time.h>
+
+#include "gnc-cell-renderer-date.h"
+#include "gnc-cell-renderer-popup-entry.h"
+#include "gnc-date.h"
+
+enum {
+	PROP_0,
+        PROP_USE_BUTTONS,
+};
+
+static void     gcrd_init                    (GncCellRendererDate      *date);
+
+static void     gcrd_class_init              (GncCellRendererDateClass *class);
+
+static void     gcrd_set_property            (GObject                 *object,
+					      guint                    param_id,
+					      const GValue            *value,
+					      GParamSpec              *pspec);
+
+static void     gcrd_get_property            (GObject                 *object,
+					      guint                    param_id,
+					      GValue                  *value,
+					      GParamSpec              *pspec);
+
+static void     gcrd_today_clicked           (GtkWidget               *button,
+					      GncCellRendererDate *cell);
+
+static void     gcrd_selected_double_click   (GtkWidget               *calendar,
+					      GncCellRendererDate *cell);
+
+static void     gcrd_cancel_clicked          (GtkWidget               *popup_window,
+					      GncCellRendererDate      *cell);
+
+static void     gcrd_ok_clicked              (GtkWidget               *popup_window,
+					      GncCellRendererDate      *cell);
+
+static void     gcrd_day_selected            (GtkWidget               *popup_window,
+					      GncCellRendererDate      *cell);
+
+GtkCellEditable *gcrd_start_editing          (GtkCellRenderer         *cell,
+					      GdkEvent                *event,
+					      GtkWidget               *widget,
+					      const gchar             *path,
+					      GdkRectangle            *background_area,
+					      GdkRectangle            *cell_area,
+					      GtkCellRendererState     flags);
+
+static void     gcrd_show                    (GncCellRendererPopup     *cell,
+					      const gchar             *path,
+					      gint                     x1,
+					      gint                     y1,
+					      gint                     x2,
+					      gint                     y2);
+static void     gcrd_hide                    (GncCellRendererPopup     *cell);
+
+
+/* These two functions are used internally */
+gboolean gcrd_time2dmy ( time_t raw_time, gint *day, gint *month, gint *year);
+static time_t gcrd_dmy2time ( gint day, gint month, gint year);
+
+/* These two functions convert string to date to string */
+static gchar * gcrd_time2dmy_string ( time_t raw_time);
+static time_t gcrd_string_dmy2time ( char *date_string);
+
+
+static GncCellRendererPopupClass *parent_class;
+
+GType
+gnc_cell_renderer_date_get_type (void)
+{
+	static GType cell_text_type = 0;
+	
+	if (!cell_text_type) {
+		static const GTypeInfo cell_text_info = {
+			sizeof (GncCellRendererDateClass),
+			NULL,		/* base_init */
+			NULL,		/* base_finalize */
+			(GClassInitFunc) gcrd_class_init,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			sizeof (GncCellRendererDate),
+			0,              /* n_preallocs */
+			(GInstanceInitFunc) gcrd_init,
+		};
+		
+		cell_text_type = g_type_register_static (GNC_TYPE_CELL_RENDERER_POPUP,
+							 "GncCellRendererDate",
+							 &cell_text_info,
+							 0);
+	}
+	
+	return cell_text_type;
+}
+
+static void
+gcrd_init (GncCellRendererDate *date)
+{
+	GncCellRendererPopup *popup;
+	GtkWidget                *frame;
+	GtkWidget                *vbox;
+	GtkWidget                *bbox;
+	GtkWidget                *button;
+
+	popup = GNC_CELL_RENDERER_POPUP (date);
+
+	frame = gtk_frame_new (NULL);
+	gtk_container_add (GTK_CONTAINER (popup->popup_window), frame);
+	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_container_add (GTK_CONTAINER (frame), vbox);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+	
+	date->calendar = gtk_calendar_new ();
+	popup->focus_window = date->calendar;
+	gtk_box_pack_start (GTK_BOX (vbox), date->calendar, TRUE, TRUE, 0);
+
+        date->button_box = gtk_hbutton_box_new ();
+	gtk_box_set_spacing (GTK_BOX (date->button_box), 6);
+	gtk_box_pack_start (GTK_BOX (vbox), date->button_box, FALSE, FALSE, 0);
+
+	button = gtk_button_new_with_label (_("Cancel"));
+	gtk_container_add (GTK_CONTAINER (date->button_box), button);
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (gcrd_cancel_clicked),
+			  date);
+
+	date->today_button = gtk_button_new_with_label (_("Today"));
+	gtk_container_add (GTK_CONTAINER (date->button_box), date->today_button);
+	g_signal_connect (date->today_button, "clicked",
+			  G_CALLBACK (gcrd_today_clicked),
+			  date);
+
+	button = gtk_button_new_with_label (_("Select"));
+	gtk_container_add (GTK_CONTAINER (date->button_box), button);
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (gcrd_ok_clicked),
+			  date);
+
+	g_signal_connect (date->calendar, "day-selected",
+			  G_CALLBACK (gcrd_day_selected),
+			  date);
+	g_signal_connect (date->calendar, "day-selected-double-click", 
+			  G_CALLBACK (gcrd_selected_double_click),
+			  date);
+
+	//Set calendar to show current date when displayed
+	date->time = time(NULL);
+
+        gtk_widget_show_all (frame);
+}
+
+static void
+gcrd_class_init (GncCellRendererDateClass *class)
+{
+	GncCellRendererPopupClass     *popup_class;
+	GtkCellRendererClass          *cell_class;
+	GObjectClass                  *gobject_class;
+
+	popup_class = GNC_CELL_RENDERER_POPUP_CLASS (class);
+	cell_class = GTK_CELL_RENDERER_CLASS (class);	
+	parent_class = GNC_CELL_RENDERER_POPUP_CLASS (g_type_class_peek_parent (class));
+	gobject_class = G_OBJECT_CLASS (class);
+
+	gobject_class->set_property = gcrd_set_property;
+	gobject_class->get_property = gcrd_get_property;
+
+	cell_class->start_editing = gcrd_start_editing;
+		
+	popup_class->show_popup = gcrd_show;
+	popup_class->hide_popup = gcrd_hide;
+
+	g_object_class_install_property (
+		gobject_class,
+                 PROP_USE_BUTTONS,
+                 g_param_spec_boolean ("use-buttons",
+				       NULL,
+				       NULL,
+				       TRUE,
+				       G_PARAM_READWRITE));
+
+}
+
+static void
+gcrd_set_property (GObject      *object,
+		   guint         param_id,
+		   const GValue *value,
+		   GParamSpec   *pspec)
+{
+	GncCellRendererDate *date;
+
+	date = GNC_CELL_RENDERER_DATE (object);
+	
+	switch (param_id) {
+	case PROP_USE_BUTTONS:
+		date->use_buttons = g_value_get_boolean (value);
+
+		if (date->use_buttons)
+			gtk_widget_show (date->button_box);
+		else
+			gtk_widget_hide (date->button_box);
+		break;
+
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	}
+}
+
+static void
+gcrd_get_property (GObject    *object,
+		   guint       param_id,
+		   GValue     *value,
+		   GParamSpec *pspec)
+{
+	GncCellRendererDate *date;
+
+	date = GNC_CELL_RENDERER_DATE (object);
+	
+	switch (param_id) {
+	case PROP_USE_BUTTONS:
+		g_value_set_boolean (value, date->use_buttons);
+		break;
+
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	}
+}
+
+GtkCellEditable *
+gcrd_start_editing (GtkCellRenderer      *cell,
+		    GdkEvent             *event,
+		    GtkWidget            *widget,
+		    const gchar          *path,
+		    GdkRectangle         *background_area,
+		    GdkRectangle         *cell_area,
+		    GtkCellRendererState  flags)
+{
+	GNC_CELL_RENDERER_POPUP (cell)->editing_canceled = FALSE;
+	
+	if (GTK_CELL_RENDERER_CLASS (parent_class)->start_editing) {
+		return GTK_CELL_RENDERER_CLASS (parent_class)->start_editing (
+							cell,
+							event,
+							widget,
+							path,
+							background_area,
+							cell_area,
+							flags);
+	}
+
+	return NULL;
+}
+
+
+static void
+gcrd_hide (GncCellRendererPopup *cell)
+{
+	if (parent_class->hide_popup) {
+		parent_class->hide_popup (cell);
+	}
+}
+
+static void
+gcrd_show (GncCellRendererPopup *cell,
+	   const gchar              *path,
+	   gint                      x1,
+	   gint                      y1,
+	   gint                      x2,
+	   gint                      y2)
+{
+	GncCellRendererDate *date;
+	gint                     year;
+	gint                     month;
+	gint                     day;
+	gint                     index;
+	gchar                   *text;
+
+	if (parent_class->show_popup) {
+		parent_class->show_popup (cell,
+					  path,
+					  x1, y1,
+					  x2, y2);
+	}
+
+	date = GNC_CELL_RENDERER_DATE (cell);
+
+        if (!(g_strcmp0(cell->cell_text, "")))
+        {
+	    date->time = time(NULL);
+            gcrd_time2dmy ( date->time, &day, &month, &year);
+        }
+        else
+        {
+            date->time = gcrd_string_dmy2time (cell->cell_text);
+            gcrd_time2dmy ( date->time, &day, &month, &year);
+        }
+
+	gtk_calendar_clear_marks (GTK_CALENDAR (date->calendar));
+	gtk_calendar_select_month (GTK_CALENDAR (date->calendar), month - 1, year);
+
+	gtk_calendar_select_day (GTK_CALENDAR (date->calendar), day);
+	gtk_calendar_mark_day (GTK_CALENDAR (date->calendar), day);
+	
+}
+
+GtkCellRenderer *
+gnc_cell_renderer_date_new (gboolean use_buttons)
+{
+	GObject *cell;
+
+	cell = g_object_new (GNC_TYPE_CELL_RENDERER_DATE,
+			     "use-buttons", use_buttons,
+			     NULL);
+	
+	return GTK_CELL_RENDERER (cell);
+}
+
+static void
+gcrd_today_clicked (GtkWidget *button, GncCellRendererDate *cell)
+{
+	time_t  today;
+	gint    year, month, day;
+	
+	today = time(NULL);
+
+        gcrd_time2dmy ( today, &day, &month, &year);
+	
+	gtk_calendar_clear_marks (GTK_CALENDAR (cell->calendar));
+	gtk_calendar_select_month (GTK_CALENDAR (cell->calendar), month - 1, year);
+	gtk_calendar_select_day (GTK_CALENDAR (cell->calendar), day);
+	gtk_calendar_mark_day (GTK_CALENDAR (cell->calendar), day);
+}
+
+static void
+gcrd_selected_double_click (GtkWidget *calendar, GncCellRendererDate *cell)
+{
+	GncCellRendererPopup *popup;
+	
+	popup = GNC_CELL_RENDERER_POPUP (cell);
+
+	gcrd_ok_clicked (popup->popup_window, cell);
+}
+
+static void
+gcrd_cancel_clicked (GtkWidget *popup_window, GncCellRendererDate *cell)
+{
+	GncCellRendererPopup *popup;
+	
+	popup = GNC_CELL_RENDERER_POPUP (cell);
+
+	popup->editing_canceled = TRUE;
+	gnc_cell_renderer_popup_hide (popup);
+}
+
+static void
+gcrd_ok_clicked (GtkWidget *popup_window, GncCellRendererDate *cell)
+{
+	GncCellRendererPopup *popup;
+	
+	popup = GNC_CELL_RENDERER_POPUP (cell);
+
+	gcrd_day_selected (popup_window, cell);
+
+	popup->editing_canceled = FALSE;
+	gnc_cell_renderer_popup_hide (popup);
+}
+
+static void
+gcrd_day_selected (GtkWidget *popup_window, GncCellRendererDate *cell)
+{
+	guint    year;
+	guint    month;
+	guint    day;
+	time_t   t;
+	gchar   *str;
+
+	gtk_calendar_get_date (GTK_CALENDAR (cell->calendar),
+			       &year,
+			       &month,
+			       &day);
+
+        t = gcrd_dmy2time ( day, month + 1, year);
+
+	cell->time = t;
+
+	str = gcrd_time2dmy_string (t);
+
+	gnc_popup_entry_set_text (
+		GNC_POPUP_ENTRY (GNC_CELL_RENDERER_POPUP (cell)->editable), str);
+	g_free (str);
+
+}
+
+static gboolean
+gcrd_grab_on_window (GdkWindow *window,
+		     guint32    activate_time)
+{
+	if ((gdk_pointer_grab (window, TRUE,
+			       GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+			       GDK_POINTER_MOTION_MASK,
+			       NULL, NULL, activate_time) == 0)) {
+		if (gdk_keyboard_grab (window, TRUE,
+			       activate_time) == 0)
+			return TRUE;
+		else {
+			gdk_pointer_ungrab (activate_time);
+			return FALSE;
+		}
+	}
+
+	return FALSE;
+}
+
+
+/* This function converts a time_t value date to separate entities */
+gboolean
+gcrd_time2dmy ( time_t raw_time, gint *day, gint *month, gint *year)
+{
+    struct tm * timeinfo;
+  
+    timeinfo = localtime ( &raw_time );
+ 
+    *day = timeinfo->tm_mday;
+    *month = timeinfo->tm_mon + 1;
+    *year = timeinfo->tm_year + 1900;
+
+    return TRUE;
+}
+
+/* This function converts separate entities to a time_t value */
+static time_t
+gcrd_dmy2time ( gint day, gint month, gint year)
+{
+    struct tm *when;
+
+    time_t raw_time;
+
+    time(&raw_time);
+    when = localtime ( &raw_time );
+
+    when->tm_year = year - 1900;
+    when->tm_mon = month - 1 ;
+    when->tm_mday = day;
+
+    return mktime(when);
+}
+
+
+/* This function converts a time_t value date to a string */
+static gchar *
+gcrd_time2dmy_string ( time_t raw_time)
+{
+    return qof_print_date (raw_time);
+}
+
+
+/* This function converts a string date to a time_t value */
+static time_t
+gcrd_string_dmy2time ( char *date_string)
+{
+    struct tm *when;
+    gint year = 0, month = 0, day = 0;
+
+    time_t raw_time;
+
+    if(qof_scan_date (date_string, &day, &month, &year))
+    {
+        time(&raw_time);
+        when = localtime ( &raw_time );
+
+        when->tm_year = year - 1900;
+        when->tm_mon = month - 1 ;
+        when->tm_mday = day;
+
+        return mktime(when);
+    }
+    else
+    {
+ 	raw_time = time(NULL);
+        return raw_time;
+    }
+}
+
+
+
+
+

Added: gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.h	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-cell-renderer-date.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,71 @@
+/*************************************************************************
+ * The following code has come from Planner. This code implements a
+ * GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
+ *
+ * These files have been renamed and changed to remove code not required
+ * and to remove a dependency on libplanner.
+ *
+ * Copyright (C) 2012 Robert Fewell
+ *
+ * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.com>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ **************************************************************************/
+
+#ifndef __GNC_CELL_RENDERER_DATE_H__
+#define __GNC_CELL_RENDERER_DATE_H__
+
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+#include <time.h>
+#include "gnc-cell-renderer-popup.h"
+#include "gnc-cell-renderer-popup-entry.h"
+
+#define GNC_TYPE_CELL_RENDERER_DATE	       (gnc_cell_renderer_date_get_type ())
+#define GNC_CELL_RENDERER_DATE(obj)	       (GTK_CHECK_CAST ((obj), GNC_TYPE_CELL_RENDERER_DATE, GncCellRendererDate))
+#define GNC_CELL_RENDERER_DATE_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GNC_TYPE_CELL_RENDERER_DATE, GncCellRendererDateClass))
+#define GNC_IS_CELL_RENDERER_DATE(obj)	       (GTK_CHECK_TYPE ((obj), GNC_TYPE_CELL_RENDERER_DATE))
+#define GNC_IS_CELL_RENDERER_DATE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), GNC_TYPE_CELL_RENDERER_DATE))
+#define GNC_CELL_RENDERER_DATE_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GNC_TYPE_CELL_RENDERER_DATE, GncCellRendererDateClass))
+
+typedef struct _GncCellRendererDate      GncCellRendererDate;
+typedef struct _GncCellRendererDateClass GncCellRendererDateClass;
+
+struct _GncCellRendererDate
+{
+	GncCellRendererPopup      parent;
+	GtkWidget                *calendar;
+	GtkWidget                *today_button;
+
+	time_t                    time;
+        gboolean                  use_buttons;
+	GtkWidget                *button_box;
+
+};
+
+struct _GncCellRendererDateClass
+{
+	GncCellRendererPopupClass parent_class;
+};
+
+GType            gnc_cell_renderer_date_get_type (void) G_GNUC_CONST;
+GtkCellRenderer *gnc_cell_renderer_date_new      (gboolean use_buttons);
+
+
+#endif /* __GNC_CELL_RENDERER_DATE_H__ */

Added: gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.c	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,281 @@
+/*************************************************************************
+ * The following code has come from Planner. This code implements a
+ * GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
+ *
+ * These files have been renamed and changed to remove code not required
+ * and to remove a dependency on libplanner.
+ *
+ * Copyright (C) 2012 Robert Fewell
+ *
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.com>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *************************************************************************/
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <string.h>
+
+#include "gnc-cell-renderer-popup-entry.h"
+
+static void     gnc_popup_entry_init       (GncPopupEntry        *entry);
+static void     gnc_popup_entry_class_init (GncPopupEntryClass   *class);
+static void     gpw_cell_editable_init     (GtkCellEditableIface *iface);
+static gboolean gpw_key_press_event        (GtkWidget            *box,
+					    GdkEventKey          *key_event);
+
+enum {
+	ARROW_CLICKED,
+	LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_EDITING_CANCELED
+};
+
+static GtkEventBoxClass *parent_class;
+static guint signals[LAST_SIGNAL];
+
+GtkType
+gnc_popup_entry_get_type (void)
+{
+	static GtkType widget_type = 0;
+	
+	if (!widget_type) {
+		static const GTypeInfo widget_info = {
+			sizeof (GncPopupEntryClass),
+			NULL,		/* base_init */
+			NULL,		/* base_finalize */
+			(GClassInitFunc) gnc_popup_entry_class_init,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			sizeof (GncPopupEntry),
+			0,              /* n_preallocs */
+			(GInstanceInitFunc) gnc_popup_entry_init,
+		};
+
+		static const GInterfaceInfo cell_editable_info = {
+			(GInterfaceInitFunc) gpw_cell_editable_init,    /* interface_init */
+			NULL,                                           /* interface_finalize */
+			NULL                                            /* interface_data */
+		};
+      
+		widget_type = g_type_register_static (GTK_TYPE_EVENT_BOX,
+						      "GncPopupEntry",
+						      &widget_info,
+						      0);
+		
+		g_type_add_interface_static (widget_type,
+					     GTK_TYPE_CELL_EDITABLE,
+					     &cell_editable_info);
+	}
+	
+	return widget_type;
+}
+
+static void
+gnc_popup_entry_init (GncPopupEntry *widget)
+{
+	GtkWidget *arrow;
+
+	widget->hbox = gtk_hbox_new (FALSE, 0);
+	gtk_widget_show (widget->hbox);
+
+	widget->entry = g_object_new (GTK_TYPE_ENTRY, "has_frame", FALSE, NULL);
+	GTK_ENTRY (widget->entry)->is_cell_renderer = TRUE;
+	gtk_widget_show (widget->entry);
+
+	widget->button = gtk_button_new ();
+	gtk_widget_show (widget->button);
+
+	arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+	gtk_widget_show (arrow);
+
+	gtk_container_add (GTK_CONTAINER (widget->button), arrow);
+
+	gtk_box_pack_start (GTK_BOX (widget->hbox), widget->entry, TRUE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (widget->hbox), widget->button, FALSE, TRUE, 0);
+
+	gtk_container_add (GTK_CONTAINER (widget), widget->hbox);
+
+	GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+	gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_PRESS_MASK);
+	gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_RELEASE_MASK);
+}
+
+static void
+gnc_popup_entry_class_init (GncPopupEntryClass *klass)
+{
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+	widget_class->key_press_event = gpw_key_press_event;
+
+        gtk_object_add_arg_type ("GncPopupEntry::editing-canceled", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITING_CANCELED);
+	
+	parent_class = GTK_EVENT_BOX_CLASS (g_type_class_peek_parent (klass));
+
+	signals[ARROW_CLICKED] = g_signal_new
+		("arrow-clicked",
+		 G_TYPE_FROM_CLASS (klass),
+		 G_SIGNAL_RUN_LAST,
+		 0,
+		 NULL, NULL,
+		 g_cclosure_marshal_VOID__VOID,
+		 G_TYPE_NONE, 0);
+
+}
+
+static void
+gpw_arrow_clicked (GtkWidget *button, GncPopupEntry *widget)
+{
+	g_signal_emit (widget, signals[ARROW_CLICKED], 0);
+}
+	
+/* GtkCellEditable method implementations
+ */
+static void
+gtk_cell_editable_entry_activated (GtkEntry *entry, GncPopupEntry *widget)
+{
+	gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
+	gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
+}
+
+static gboolean
+gtk_cell_editable_key_press_event (GtkEntry      *entry,
+				   GdkEventKey   *key_event,
+				   GncPopupEntry *widget)
+{
+	if (key_event->keyval == GDK_Escape) {
+		widget->editing_canceled = TRUE;
+		
+		gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
+		gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
+		
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static gboolean
+gpw_key_press_event (GtkWidget   *box,
+		     GdkEventKey *key_event)
+{
+	GncPopupEntry *widget = GNC_POPUP_ENTRY (box);
+	GdkEvent       tmp_event;
+	
+	if (key_event->keyval == GDK_Escape) {
+		widget->editing_canceled = TRUE;
+
+		gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
+		gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
+		
+		return TRUE;
+	}
+
+	gtk_widget_grab_focus (widget->entry);
+
+	/* Hackish :/ Synthesize a key press event for the entry. */
+	memcpy (&tmp_event, key_event, sizeof (GdkEventKey));
+
+	tmp_event.key.window = widget->entry->window;
+	tmp_event.key.send_event = TRUE;
+	
+	gtk_widget_event (widget->entry, &tmp_event);
+
+	return GTK_WIDGET_CLASS (parent_class)->key_press_event (GTK_WIDGET (widget), 
+								 key_event);
+}
+
+static void
+gpw_start_editing (GtkCellEditable *cell_editable,
+		   GdkEvent        *event)
+{
+	GncPopupEntry *widget = GNC_POPUP_ENTRY (cell_editable);
+
+	gtk_editable_select_region (GTK_EDITABLE (widget->entry), 0, -1);
+
+	g_signal_connect (G_OBJECT (widget->entry),
+			  "activate",
+			  G_CALLBACK (gtk_cell_editable_entry_activated),
+			  widget);
+	g_signal_connect (G_OBJECT (widget->entry),
+			  "key_press_event",
+			  G_CALLBACK (gtk_cell_editable_key_press_event),
+			  widget);
+	g_signal_connect (G_OBJECT (widget->button),
+			  "clicked",
+			  (GCallback) gpw_arrow_clicked,
+			  widget);
+}
+
+static void
+gpw_cell_editable_init (GtkCellEditableIface *iface)
+{
+	iface->start_editing = gpw_start_editing;
+}
+
+void
+gnc_popup_entry_set_text (GncPopupEntry *popup, const gchar *text)
+{
+	g_return_if_fail (GNC_IS_POPUP_ENTRY (popup));
+
+	gtk_entry_set_text (GTK_ENTRY (popup->entry), text ? text : "");
+}
+
+const gchar *
+gnc_popup_entry_get_text (GncPopupEntry *popup)
+{
+	g_return_val_if_fail (GNC_IS_POPUP_ENTRY (popup), NULL);
+
+	return gtk_entry_get_text (GTK_ENTRY (popup->entry));
+}
+
+gint
+gnc_popup_get_button_width (void)
+{
+	GtkWidget *window, *button, *arrow;
+	gint       width;
+
+	GtkRequisition req;
+	
+	window = gtk_window_new (GTK_WINDOW_POPUP);
+	
+	button = gtk_button_new ();
+	gtk_widget_show (button);
+	gtk_container_add (GTK_CONTAINER (window), button);
+
+	arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+	gtk_widget_show (arrow);
+	gtk_container_add (GTK_CONTAINER (button), arrow);
+
+	gtk_window_move (GTK_WINDOW (window), -500, -500);
+	gtk_widget_show (window);
+
+	gtk_widget_size_request (window, &req);
+	
+	width = req.width;
+
+	gtk_widget_destroy (window);
+
+	return width;
+}
+

Added: gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.h	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup-entry.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,74 @@
+/*************************************************************************
+ * The following code has come from Planner. This code implements a
+ * GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
+ *
+ * These files have been renamed and changed to remove code not required
+ * and to remove a dependency on libplanner.
+ *
+ * Copyright (C) 2012 Robert Fewell
+ *
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.com>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *************************************************************************/
+
+#ifndef __GNC_POPUP_ENTRY_H__
+#define __GNC_POPUP_ENTRY_H__
+
+#include <pango/pango.h>
+#include <gtk/gtkeventbox.h>
+
+#define GNC_TYPE_POPUP_ENTRY		(gnc_popup_entry_get_type ())
+#define GNC_POPUP_ENTRY(obj)		(GTK_CHECK_CAST ((obj), GNC_TYPE_POPUP_ENTRY, GncPopupEntry))
+#define GNC_POPUP_ENTRY_CLASS(klass)	(GTK_CHECK_CLASS_CAST ((klass), GNC_TYPE_POPUP_ENTRY, GncPopupEntryClass))
+#define GNC_IS_POPUP_ENTRY(obj)		(GTK_CHECK_TYPE ((obj), GNC_TYPE_POPUP_ENTRY))
+#define GNC_IS_POPUP_ENTRY_CLASS(klass)	(GTK_CHECK_CLASS_TYPE ((obj), GNC_TYPE_POPUP_ENTRY))
+#define GNC_POPUP_ENTRY_GET_CLASS(obj)	(GTK_CHECK_GET_CLASS ((obj), GNC_TYPE_POPUP_ENTRY, GncPopupEntryClass))
+
+typedef struct _GncPopupEntry      GncPopupEntry;
+typedef struct _GncPopupEntryClass GncPopupEntryClass;
+
+struct _GncPopupEntry
+{
+	GtkEventBox  parent;
+
+	GtkWidget   *hbox;
+	GtkWidget   *button;
+	GtkWidget   *entry;
+
+	gboolean     editing_canceled;
+};
+
+struct _GncPopupEntryClass
+{
+	GtkEventBoxClass parent_class;
+};
+
+GtkType      gnc_popup_entry_get_type   (void) G_GNUC_CONST;
+
+GtkWidget   *gnc_popup_entry_new        (void);
+
+void         gnc_popup_entry_set_text   (GncPopupEntry *popup,
+					const gchar  *text);
+
+const gchar *gnc_popup_entry_get_text   (GncPopupEntry *popup);
+
+gint         gnc_popup_get_button_width (void);
+
+
+#endif /* __GNC_POPUP_ENTRY_H__ */

Added: gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.c	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,575 @@
+/*************************************************************************
+ * The following code has come from Planner. This code implements a
+ * GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
+ *
+ * These files have been renamed and changed to remove code not required
+ * and to remove a dependency on libplanner.
+ *
+ * Copyright (C) 2012 Robert Fewell
+ *
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.com>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *************************************************************************/
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gnc-cell-renderer-popup.h"
+#include "gnc-cell-renderer-popup-entry.h"
+
+enum {
+	SHOW_POPUP,
+	HIDE_POPUP,
+	LAST_SIGNAL
+};
+
+static void      gcrp_init               (GncCellRendererPopup      *popup);
+static void      gcrp_class_init         (GncCellRendererPopupClass *class);
+
+static GtkCellEditable *
+gcrp_start_editing                       (GtkCellRenderer          *cell,
+					  GdkEvent                 *event,
+					  GtkWidget                *widget,
+					  const gchar              *path,
+					  GdkRectangle             *background_area,
+					  GdkRectangle             *cell_area,
+					  GtkCellRendererState      flags);
+static void      gcrp_show_popup         (GncCellRendererPopup      *cell,
+					  const gchar              *path,
+					  gint                      x1,
+					  gint                      y1,
+					  gint                      x2,
+					  gint                      y2);
+static void      gcrp_hide_popup         (GncCellRendererPopup      *cell);
+static void      gcrp_get_size           (GtkCellRenderer          *cell,
+					  GtkWidget                *widget,
+					  GdkRectangle             *cell_area,
+					  gint                     *x_offset,
+					  gint                     *y_offset,
+					  gint                     *width,
+					  gint                     *height);
+static void      gcrp_style_set           (GtkWidget               *widget,
+					   GtkStyle                *old_style,
+					   GncCellRendererPopup     *popup);
+static gboolean  gcrp_key_press_event    (GtkWidget                *popup_window,
+					  GdkEventKey              *event,
+					  GncCellRendererPopup      *cell);
+static gboolean  gcrp_button_press_event (GtkWidget                *widget,
+					  GdkEventButton           *event,
+					  GncCellRendererPopup      *popup);
+
+
+void gnc_marshal_VOID__STRING_INT_INT_INT_INT (GClosure     *closure,
+                                               GValue       *return_value,
+                                               guint         n_param_values,
+                                               const GValue *param_values,
+                                               gpointer      invocation_hint,
+                                               gpointer      marshal_data);
+
+
+static GtkCellRendererTextClass *parent_class;
+static guint signals[LAST_SIGNAL];
+
+#define GNC_CELL_RENDERER_POPUP_PATH "gnc-cell-renderer-popup-path"
+
+GType
+gnc_cell_renderer_popup_get_type (void)
+{
+	static GType cell_text_type = 0;
+	
+	if (!cell_text_type) {
+		static const GTypeInfo cell_text_info = {
+			sizeof (GncCellRendererPopupClass),
+			NULL,		/* base_init */
+			NULL,		/* base_finalize */
+			(GClassInitFunc) gcrp_class_init,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			sizeof (GncCellRendererPopup),
+			0,              /* n_preallocs */
+			(GInstanceInitFunc) gcrp_init,
+		};
+		
+		cell_text_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT,
+							 "GncCellRendererPopup",
+							 &cell_text_info,
+							 0);
+	}
+	
+	return cell_text_type;
+}
+
+static void
+gcrp_init (GncCellRendererPopup *popup)
+{
+	popup->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
+
+	popup->button_width = -1;
+	
+	g_signal_connect (popup->popup_window,
+			  "button-press-event",
+			  G_CALLBACK (gcrp_button_press_event),
+			  popup);
+
+	g_signal_connect (popup->popup_window,
+			  "key-press-event",
+			  G_CALLBACK (gcrp_key_press_event),
+			  popup);
+
+	g_signal_connect (popup->popup_window,
+			  "style-set",
+			  G_CALLBACK (gcrp_style_set),
+			  popup);
+}
+
+static void
+gcrp_class_init (GncCellRendererPopupClass *class)
+{
+	GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+	
+	parent_class = GTK_CELL_RENDERER_TEXT_CLASS (g_type_class_peek_parent (class));
+	
+	cell_class->start_editing = gcrp_start_editing;
+	cell_class->get_size      = gcrp_get_size;
+
+	class->show_popup = gcrp_show_popup;
+	class->hide_popup = gcrp_hide_popup;
+
+	signals[SHOW_POPUP] = g_signal_new (
+		"show-popup",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (GncCellRendererPopupClass, show_popup),
+		NULL, NULL,
+		gnc_marshal_VOID__STRING_INT_INT_INT_INT,
+		G_TYPE_NONE, 5,
+		G_TYPE_STRING,
+		G_TYPE_INT,
+		G_TYPE_INT,
+		G_TYPE_INT,
+		G_TYPE_INT);
+
+	signals[HIDE_POPUP] = g_signal_new (
+		"hide-popup",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (GncCellRendererPopupClass, hide_popup),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+}
+
+static void
+gcrp_editing_done (GtkCellEditable     *editable,
+		   GncCellRendererPopup *cell)
+{
+	gchar       *path;
+	const gchar *new_text;
+
+	if (GNC_POPUP_ENTRY (editable)->editing_canceled ||
+	    cell->editing_canceled) {
+                gtk_cell_renderer_stop_editing (GTK_CELL_RENDERER (cell), TRUE);
+		return;
+	}
+	
+	path = g_object_get_data (G_OBJECT (editable),
+				  GNC_CELL_RENDERER_POPUP_PATH);
+	new_text = gnc_popup_entry_get_text (GNC_POPUP_ENTRY (editable));
+
+	g_signal_emit_by_name (cell,
+			       "edited",
+			       path,
+			       new_text);
+}
+
+static void
+gcrp_style_set (GtkWidget           *widget,
+		GtkStyle            *old_style,
+		GncCellRendererPopup *popup)
+{
+	/* Invalidate the cache. */
+	popup->button_width = -1;
+}
+	
+static gboolean
+gcrp_grab_on_window (GdkWindow *window,
+		     guint32    activate_time)
+{
+	if ((gdk_pointer_grab (window, TRUE,
+			       GDK_BUTTON_PRESS_MASK |
+			       GDK_BUTTON_RELEASE_MASK |
+			       GDK_POINTER_MOTION_MASK,
+			       NULL, NULL, activate_time) == 0)) {
+		if (gdk_keyboard_grab (window, TRUE,
+			       activate_time) == 0)
+			return TRUE;
+		else {
+			gdk_pointer_ungrab (activate_time);
+			return FALSE;
+		}
+	}
+
+	return FALSE;
+}
+
+static void
+gcrp_show_popup (GncCellRendererPopup *cell,
+		 const gchar         *path,
+		 gint                 x1,
+		 gint                 y1,
+		 gint                 x2,
+		 gint                 y2)
+{
+	GtkAllocation alloc;
+	gint          x, y;
+	gint          screen_height, screen_width;
+	gint          button_height;
+
+	cell->shown = TRUE;
+
+	gtk_widget_realize (cell->popup_window);
+
+	/* I'm not sure this is ok to do, but we need to show the window to be
+	 * able to get the allocation right.
+	 */
+	gtk_window_move (GTK_WINDOW (cell->popup_window), -500, -500);
+	gtk_widget_show (cell->popup_window);
+
+	alloc = cell->popup_window->allocation;
+
+	x = x2;
+	y = y2;
+
+	button_height = y2 - y1;
+	
+	screen_height = gdk_screen_height () - y;
+	screen_width = gdk_screen_width ();
+
+	/* Check if it fits in the available height. */
+	if (alloc.height > screen_height) {
+		/* It doesn't fit, so we see if we have the minimum space needed. */
+		if (alloc.height > screen_height && y - button_height > screen_height) {
+			/* We don't, so we show the popup above the cell
+			   instead of below it. */
+			screen_height = y - button_height;
+			y -= (alloc.height + button_height);
+			if (y < 0) {
+				y = 0;
+			}
+		}
+	}
+
+	/* We try to line it up with the right edge of the column, but we don't
+	 * want it to go off the edges of the screen.
+	 */
+	if (x > screen_width) {
+		x = screen_width;
+	}
+
+	x -= alloc.width;
+	if (x < 0) {
+		x = 0;
+	}
+
+	gtk_grab_add (cell->popup_window);
+
+	gtk_window_move (GTK_WINDOW (cell->popup_window), x, y);
+	gtk_widget_show (cell->popup_window);
+
+	gtk_widget_grab_focus (cell->focus_window);
+
+	gcrp_grab_on_window (cell->popup_window->window,
+			     gtk_get_current_event_time ());
+}
+
+static void
+gcrp_hide_popup (GncCellRendererPopup *cell)
+{
+	gtk_grab_remove (cell->popup_window);
+	gtk_widget_hide (cell->popup_window);
+
+	if (cell->editable) {
+		gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (cell->editable));
+	}
+
+	/* This may look weird (the test), but the weak pointer will actually be
+	 * nulled out for some cells, like the date cell.
+	 */
+	if (cell->editable) {
+		gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (cell->editable));
+	}
+	
+	cell->shown = FALSE;
+	cell->editing_canceled = FALSE;
+}
+
+static void
+gcrp_arrow_clicked (GtkCellEditable     *entry,
+		    GncCellRendererPopup *cell)
+{
+	GtkAllocation  alloc;
+	gint           x, y;
+	const gchar   *path;
+	
+	if (cell->shown) {
+		cell->editing_canceled = TRUE;
+		gnc_cell_renderer_popup_hide (cell);
+		return;
+	}
+	
+	path = g_object_get_data (G_OBJECT (entry),
+				  GNC_CELL_RENDERER_POPUP_PATH);
+
+	/* Temporarily grab pointer and keyboard on a window we know exists; we
+	 * do this so that the grab (with owner events == TRUE) affects
+	 * events generated when the window is mapped, such as enter
+	 * notify events on subwidgets. If the grab fails, bail out.
+	 */
+	if (!gcrp_grab_on_window (GTK_WIDGET (entry)->window,
+				  gtk_get_current_event_time ())) {
+		return;
+	}
+	
+	gtk_editable_select_region (GTK_EDITABLE (GNC_POPUP_ENTRY (entry)->entry), 0, 0);
+
+	gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y);
+	
+	alloc = GTK_WIDGET (entry)->allocation;
+
+	g_signal_emit (cell, signals[SHOW_POPUP], 0,
+		       path, 
+		       x,
+		       y,
+		       x + alloc.width,
+		       y + alloc.height);
+}
+
+static GtkCellEditable *
+gcrp_start_editing (GtkCellRenderer      *cell,
+		    GdkEvent             *event,
+		    GtkWidget            *widget,
+		    const gchar          *path,
+		    GdkRectangle         *background_area,
+		    GdkRectangle         *cell_area,
+		    GtkCellRendererState  flags)
+{
+	GncCellRendererPopup *popup;
+	GtkWidget           *editable;
+	gchar               *text;
+	
+	popup = GNC_CELL_RENDERER_POPUP (cell);
+
+	/* If the cell isn't editable we return NULL. */
+	if (GTK_CELL_RENDERER_TEXT (popup)->editable == FALSE) {
+		return NULL;
+	}
+	
+	editable = g_object_new (GNC_TYPE_POPUP_ENTRY, NULL);
+
+	text = GTK_CELL_RENDERER_TEXT (cell)->text;
+        popup->cell_text = g_strdup(text);
+
+	gnc_popup_entry_set_text (GNC_POPUP_ENTRY (editable), text ? text : "");
+	
+	g_object_set_data_full (G_OBJECT (editable),
+				GNC_CELL_RENDERER_POPUP_PATH,
+				g_strdup (path),
+				g_free);
+	
+	gtk_widget_show (editable);
+
+	g_signal_connect (editable,
+			  "editing-done",
+			  G_CALLBACK (gcrp_editing_done),
+			  popup);
+
+	g_signal_connect (editable,
+			  "arrow-clicked",
+			  G_CALLBACK (gcrp_arrow_clicked),
+			  popup);
+
+	popup->editable = editable;
+
+	g_object_add_weak_pointer (G_OBJECT (popup->editable),
+				   (gpointer) &popup->editable);
+	
+	return GTK_CELL_EDITABLE (editable);
+}
+
+GtkCellRenderer *
+gnc_cell_renderer_popup_new (void)
+{
+	return GTK_CELL_RENDERER (
+		g_object_new (gnc_cell_renderer_popup_get_type (), NULL));
+}
+
+void
+gnc_cell_renderer_popup_hide (GncCellRendererPopup *cell)
+{ 
+	g_return_if_fail (GNC_IS_CELL_RENDERER_POPUP (cell));
+	
+	g_signal_emit (cell, signals[HIDE_POPUP], 0);
+}
+
+static void
+gcrp_get_size (GtkCellRenderer *cell,
+	       GtkWidget       *widget,
+	       GdkRectangle    *cell_area,
+	       gint            *x_offset,
+	       gint            *y_offset,
+	       gint            *width,
+	       gint            *height)
+{
+	GncCellRendererPopup *popup;
+
+	popup = GNC_CELL_RENDERER_POPUP (cell);
+	
+	if (GTK_CELL_RENDERER_CLASS (parent_class)->get_size) { 
+		(* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell,
+								      widget,
+								      cell_area, 
+								      x_offset,
+								      y_offset,
+								      width,
+								      height);
+	}
+
+	/* We cache this because it takes really long to get the width. */
+	if (popup->button_width == -1) {
+		popup->button_width = gnc_popup_get_button_width ();
+	}
+	
+	*width += popup->button_width;
+}
+
+static gboolean
+gcrp_key_press_event (GtkWidget           *popup_window,
+		      GdkEventKey         *event,
+		      GncCellRendererPopup *cell)
+{
+	if (event->keyval != GDK_Escape &&
+	    event->keyval != GDK_Return &&
+	    event->keyval != GDK_KP_Enter &&
+	    event->keyval != GDK_ISO_Enter &&
+	    event->keyval != GDK_3270_Enter) {
+		return FALSE;
+	}
+	if (event->keyval == GDK_Escape) {
+		cell->editing_canceled = TRUE;
+	} else {
+		cell->editing_canceled = FALSE;
+	}		
+	gnc_cell_renderer_popup_hide (cell);
+
+	return TRUE;
+}
+
+static gboolean
+gcrp_button_press_event (GtkWidget           *widget,
+			 GdkEventButton      *event,
+			 GncCellRendererPopup *popup)
+{
+	GtkAllocation alloc;
+	gdouble       x, y;
+	gint          xoffset, yoffset;
+	gint          x1, y1;
+	gint          x2, y2;
+
+	if (event->button != 1) {
+		return FALSE;
+	}
+	
+	/* If the event happened outside the popup, cancel editing.
+	 */
+
+	/*gdk_event_get_root_coords ((GdkEvent *) event, &x, &y);*/
+	x = event->x_root;
+	y = event->y_root;
+
+	gdk_window_get_root_origin (widget->window,
+				    &xoffset,
+				    &yoffset);
+
+	xoffset += widget->allocation.x;
+	yoffset += widget->allocation.y;
+	
+	alloc = popup->popup_window->allocation;
+	x1 = alloc.x + xoffset;
+	y1 = alloc.y + yoffset;
+	x2 = x1 + alloc.width;
+	y2 = y1 + alloc.height;
+
+	if (x > x1 && x < x2 && y > y1 && y < y2) {
+		return FALSE;
+	}
+	
+	popup->editing_canceled = TRUE;
+	gnc_cell_renderer_popup_hide (popup);
+	
+	return FALSE;
+}
+
+
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+
+void
+gnc_marshal_VOID__STRING_INT_INT_INT_INT (GClosure     *closure,
+                                              GValue       *return_value G_GNUC_UNUSED,
+                                              guint         n_param_values,
+                                              const GValue *param_values,
+                                              gpointer      invocation_hint G_GNUC_UNUSED,
+                                              gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__STRING_INT_INT_INT_INT) (gpointer     data1,
+                                                             gpointer     arg_1,
+                                                             gint         arg_2,
+                                                             gint         arg_3,
+                                                             gint         arg_4,
+                                                             gint         arg_5,
+                                                             gpointer     data2);
+  register GMarshalFunc_VOID__STRING_INT_INT_INT_INT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 6);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__STRING_INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_marshal_value_peek_string (param_values + 1),
+            g_marshal_value_peek_int (param_values + 2),
+            g_marshal_value_peek_int (param_values + 3),
+            g_marshal_value_peek_int (param_values + 4),
+            g_marshal_value_peek_int (param_values + 5),
+            data2);
+}
+

Added: gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.h	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-cell-renderer-popup.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,94 @@
+/*************************************************************************
+ * The following code has come from Planner. This code implements a
+ * GtkCalendar in a custom GtkCellEditable popup from GtkCellRenderer.
+ *
+ * These files have been renamed and changed to remove code not required
+ * and to remove a dependency on libplanner.
+ *
+ * Copyright (C) 2012 Robert Fewell
+ *
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.com>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *************************************************************************/
+
+#ifndef __GNC_CELL_RENDERER_POPUP_H__
+#define __GNC_CELL_RENDERER_POPUP_H__
+
+#include <pango/pango.h>
+#include <gtk/gtkcellrenderertext.h>
+
+#define GNC_TYPE_CELL_RENDERER_POPUP		(gnc_cell_renderer_popup_get_type ())
+#define GNC_CELL_RENDERER_POPUP(obj)		(GTK_CHECK_CAST ((obj), GNC_TYPE_CELL_RENDERER_POPUP, GncCellRendererPopup))
+#define GNC_CELL_RENDERER_POPUP_CLASS(klass)	(GTK_CHECK_CLASS_CAST ((klass), GNC_TYPE_CELL_RENDERER_POPUP, GncCellRendererPopupClass))
+#define GNC_IS_CELL_RENDERER_POPUP(obj)		(GTK_CHECK_TYPE ((obj), GNC_TYPE_CELL_RENDERER_POPUP))
+#define GNC_IS_CELL_RENDERER_POPUP_CLASS(klass)	(GTK_CHECK_CLASS_TYPE ((obj), GNC_TYPE_CELL_RENDERER_POPUP))
+#define GNC_CELL_RENDERER_POPUP_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), GNC_TYPE_CELL_RENDERER_POPUP, GncCellRendererPopupClass))
+
+typedef struct _GncCellRendererPopup      GncCellRendererPopup;
+typedef struct _GncCellRendererPopupClass GncCellRendererPopupClass;
+
+struct _GncCellRendererPopup
+{
+	GtkCellRendererText  parent;
+
+	/* Cached width of the popup button. */
+	gint                 button_width;
+	
+	/* The popup window. */
+	GtkWidget           *popup_window;
+
+	/* The widget that should grab focus on popup. */
+	GtkWidget           *focus_window;
+
+	/* The editable entry. */
+	GtkWidget           *editable;
+
+	gboolean             shown;
+	gboolean             editing_canceled;
+        gchar                *cell_text;
+};
+
+struct _GncCellRendererPopupClass
+{
+	GtkCellRendererTextClass parent_class;
+	
+	void   (* show_popup) (GncCellRendererPopup *cell,
+			       const gchar         *path,
+			       gint                 x1,
+			       gint                 y1,
+			       gint                 x2,
+			       gint                 y2);
+	
+	void   (* hide_popup) (GncCellRendererPopup *cell);
+};
+
+GtkType          gnc_cell_renderer_popup_get_type (void) G_GNUC_CONST;
+
+GtkCellRenderer *gnc_cell_renderer_popup_new      (void);
+
+void             gnc_cell_renderer_popup_show     (GncCellRendererPopup *cell,
+						  const gchar         *path,
+						  gint                 x1,
+						  gint                 y1,
+						  gint                 x2,
+						  gint                 y2);
+
+void             gnc_cell_renderer_popup_hide     (GncCellRendererPopup *cell);
+
+#endif /* __GNC_CELL_RENDERER_POPUP_H__ */

Added: gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,1621 @@
+/********************************************************************\
+ * gnc-tree-model-split-reg.c -- GtkTreeView implementation to      *
+ *                     display registers   in a GtkTreeView.        *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ * Copyright (C) 2006-2007 Chris Shoemaker <c.shoemaker at cox.net>    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gnc-tree-model-split-reg.h"
+#include "gnc-component-manager.h"
+#include "gnc-commodity.h"
+#include "gnc-gconf-utils.h"
+#include "gnc-engine.h"
+#include "gnc-event.h"
+#include "gnc-gobject-utils.h"
+#include "Query.h"
+#include "Transaction.h"
+
+#include "gnc-ui-util.h"
+
+#define TREE_MODEL_SPLIT_REG_CM_CLASS "tree-model-split-reg"
+
+/** Static Globals *******************************************************/
+static QofLogModule log_module = GNC_MOD_GUI;
+
+/** Declarations *********************************************************/
+static void gnc_tree_model_split_reg_class_init (GncTreeModelSplitRegClass *klass);
+static void gnc_tree_model_split_reg_init (GncTreeModelSplitReg *model);
+static void gnc_tree_model_split_reg_finalize (GObject *object);
+static void gnc_tree_model_split_reg_dispose (GObject *object);
+
+/** Implementation of GtkTreeModel  **************************************/
+static void gnc_tree_model_split_reg_tree_model_init (GtkTreeModelIface *iface);
+
+static GtkTreeModelFlags gnc_tree_model_split_reg_get_flags (GtkTreeModel *tree_model);
+static int gnc_tree_model_split_reg_get_n_columns (GtkTreeModel *tree_model);
+static GType gnc_tree_model_split_reg_get_column_type (GtkTreeModel *tree_model, int index);
+static gboolean gnc_tree_model_split_reg_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path);
+static GtkTreePath *gnc_tree_model_split_reg_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter);
+static void gnc_tree_model_split_reg_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter, int column, GValue *value);
+static gboolean	gnc_tree_model_split_reg_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter);
+static gboolean	gnc_tree_model_split_reg_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent);
+static gboolean	gnc_tree_model_split_reg_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter);
+static int gnc_tree_model_split_reg_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter);
+static gboolean	gnc_tree_model_split_reg_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, int n);
+static gboolean	gnc_tree_model_split_reg_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child);
+
+/** Component Manager Callback ******************************************/
+static void gnc_tree_model_split_reg_event_handler (QofInstance *entity, QofEventId event_type, GncTreeModelSplitReg *model, GncEventData *ed);
+
+static void create_completion_models(GncTreeModelSplitReg *model);
+
+/** The instance private data for the split register tree model. */
+struct GncTreeModelSplitRegPrivate
+{
+    QofBook *book;
+    Account *anchor;
+    Query   *query;
+
+    GList *tlist;
+    GList *slist;
+
+    gboolean use_colors;
+    gboolean double_line;
+    gboolean alt_colors_by_txn;
+
+
+    GtkListStore *description_list;
+    GtkListStore *notes_list;
+    GtkListStore *memo_list;
+    GtkListStore *num_list;
+    GtkListStore *numact_list;
+
+    gint event_handler_id;
+};
+
+
+#define GREENROW "#BFDEB9"
+#define TANROW "#F6FFDA"
+#define SPLITROW "#EDE7D3"
+#define YELLOWROW "#FFEF98"
+
+
+#define TROW1 0x1
+#define TROW2 0x2
+#define SPLIT 0x4
+#define BLANK 0x8
+#define IS_TROW1(x) (GPOINTER_TO_INT((x)->user_data) & TROW1)
+#define IS_TROW2(x) (GPOINTER_TO_INT((x)->user_data) & TROW2)
+#define IS_BLANK(x) (GPOINTER_TO_INT((x)->user_data) & BLANK)
+#define IS_SPLIT(x) (GPOINTER_TO_INT((x)->user_data) & SPLIT)
+#define IS_BLANK_SPLIT(x) (IS_BLANK(x) && IS_SPLIT(x))
+#define IS_BLANK_TRANS(x) (IS_BLANK(x) && !IS_SPLIT(x))
+/* Meaning of user_data fields in iter struct:
+ *
+ * user_data:  a bitfield for BLANK, SPLIT, TROW1, TROW2
+ * user_data2: a pointer to a node in a GList of Transactions               
+ * user_data3: a pointer to a node in a GList of Splits.
+ *            
+ */
+
+/* FIXME ***********************
+#define VALID_ITER(model, iter) \
+    (GNC_IS_TREE_MODEL_SPLIT_REG(model) &&                            \
+     ((iter) && (iter)->user_data2) &&                                  \
+     ((iter)->stamp == (model)->stamp) &&                               \
+     (!IS_SPLIT(iter) ^ ((iter)->user_data3 != NULL)) &&                \
+     (!IS_BLANK_SPLIT(iter) ||                                          \
+      ((iter)->user_data2 == (model)->priv->bsplit_parent_node))        \
+     )
+*/
+static GtkTreeIter
+make_iter(GncTreeModelSplitReg *model, gint f, GList *tnode, GList *snode)
+{
+    GtkTreeIter iter, *iter_p;
+    iter_p = &iter;
+    iter.stamp = model->stamp;
+    iter.user_data = GINT_TO_POINTER(f);
+    iter.user_data2 = tnode;
+    iter.user_data3 = snode;
+
+/*    if (!VALID_ITER(model, &iter)) PERR("Making invalid iter"); */
+    return iter;
+}
+
+
+
+#define GNC_TREE_MODEL_SPLIT_REG_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitRegPrivate))
+
+/************************************************************/
+/*               g_object required functions                */
+/************************************************************/
+
+/** A pointer to the parent class of the split register tree model. */
+static GtkObjectClass *parent_class = NULL;
+
+GType
+gnc_tree_model_split_reg_get_type (void)
+{
+    static GType gnc_tree_model_split_reg_type = 0;
+
+    if (gnc_tree_model_split_reg_type == 0)
+    {
+        static const GTypeInfo our_info =
+        {
+            sizeof (GncTreeModelSplitRegClass),                /* class_size */
+            NULL,                                              /* base_init */
+            NULL,                                              /* base_finalize */
+            (GClassInitFunc) gnc_tree_model_split_reg_class_init,
+            NULL,                                               /* class_finalize */
+            NULL,                                               /* class_data */
+            sizeof (GncTreeModelSplitReg),                      /* */
+            0,                                                  /* n_preallocs */
+            (GInstanceInitFunc) gnc_tree_model_split_reg_init
+        };
+
+        static const GInterfaceInfo tree_model_info =
+        {
+            (GInterfaceInitFunc) gnc_tree_model_split_reg_tree_model_init,
+            NULL,
+            NULL
+        };
+
+        gnc_tree_model_split_reg_type = g_type_register_static (GNC_TYPE_TREE_MODEL,
+                                      GNC_TREE_MODEL_SPLIT_REG_NAME,
+                                      &our_info, 0);
+
+        g_type_add_interface_static (gnc_tree_model_split_reg_type,
+                                     GTK_TYPE_TREE_MODEL,
+                                     &tree_model_info);
+    }
+
+    return gnc_tree_model_split_reg_type;
+}
+
+
+
+static void
+gnc_tree_model_split_reg_class_init (GncTreeModelSplitRegClass *klass)
+{
+    GObjectClass *o_class;
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    o_class = G_OBJECT_CLASS (klass);
+
+    /* GObject signals */
+    o_class->finalize = gnc_tree_model_split_reg_finalize;
+    o_class->dispose = gnc_tree_model_split_reg_dispose;
+}
+
+
+
+static void
+gnc_tree_model_split_reg_init (GncTreeModelSplitReg *model)
+{
+    GncTreeModelSplitRegPrivate *priv;
+
+    ENTER("model %p", model);
+    while (model->stamp == 0)
+    {
+        model->stamp = g_random_int ();
+    }
+
+    model->priv = g_new0 (GncTreeModelSplitRegPrivate, 1);
+    LEAVE(" ");
+}
+
+
+
+static void
+gnc_tree_model_split_reg_finalize (GObject *object)
+{
+    GncTreeModelSplitRegPrivate *priv;
+    GncTreeModelSplitReg *model;
+
+    ENTER("model %p", object);
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (object));
+
+    model = GNC_TREE_MODEL_SPLIT_REG (object);
+    priv = model->priv;
+
+    if (priv->event_handler_id) {
+        qof_event_unregister_handler(priv->event_handler_id);
+        priv->event_handler_id = 0;
+    }
+
+    priv->book = NULL;
+    g_list_free(priv->tlist);
+    priv->tlist = NULL;
+    g_list_free(priv->slist);
+    priv->slist = NULL;
+    qof_query_destroy(priv->query);
+    priv->query = NULL;
+
+/*FIXME Other stuff here */
+
+    g_free(priv);
+
+    if (G_OBJECT_CLASS (parent_class)->finalize)
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+    LEAVE(" ");
+}
+
+
+
+static void
+gnc_tree_model_split_reg_dispose (GObject *object)
+{
+    GncTreeModelSplitRegPrivate *priv;
+    GncTreeModelSplitReg *model;
+
+/* Nor sure about this */
+
+    ENTER("model %p", object);
+    g_return_if_fail (object != NULL);
+    g_return_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (object));
+
+    model = GNC_TREE_MODEL_SPLIT_REG (object);
+    priv = model->priv;
+
+    if (priv->event_handler_id)
+    {
+        qof_event_unregister_handler (priv->event_handler_id);
+        priv->event_handler_id = 0;
+    }
+
+    if (G_OBJECT_CLASS (parent_class)->dispose)
+        G_OBJECT_CLASS (parent_class)->dispose (object);
+    LEAVE(" ");
+}
+
+
+
+/************************************************************/
+/*                   New Model Creation                     */
+/************************************************************/
+static GncTreeModelSplitReg *
+gnc_tree_model_split_reg_new (GList *slist)
+{
+    GncTreeModelSplitReg *model;
+    GncTreeModelSplitRegPrivate *priv;
+    GList *tlist;
+    const GList *item;
+
+    ENTER("Create Model");
+
+/* This needs fixing 
+    item = gnc_gobject_tracking_get_list(GNC_TREE_MODEL_SPLIT_REG_NAME);
+    for ( ; item; item = g_list_next(item))
+    {
+        model = (GncTreeModelSplitReg *)item->data;
+        priv = GNC_TREE_MODEL_SPLIT_REG_GET_PRIVATE(model);
+        if (priv->anchor == anchor)
+        {
+            g_object_ref(G_OBJECT(model));
+            LEAVE("returning existing model %p", model);
+            return model;
+        }
+    }
+*/
+
+
+    model = g_object_new (GNC_TYPE_TREE_MODEL_SPLIT_REG, NULL);
+
+    /* Get a list of Unique Transactions, upsets the list order !! */
+    tlist = xaccSplitListGetUniqueTransactions(slist);
+
+    /* Default Sort Transactions by date */
+    tlist = g_list_sort (tlist, (GCompareFunc) xaccTransOrder );
+
+    priv = model->priv;
+    priv->book = gnc_get_current_book();
+    priv->tlist = tlist;
+
+    priv->use_colors = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "use_theme_colors", NULL);
+    priv->double_line = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "double_line_mode", NULL);
+    priv->alt_colors_by_txn = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "alternate_color_by_transaction", NULL);
+
+    create_completion_models(model);
+
+/* More stuff here ? */
+
+    priv->event_handler_id = qof_event_register_handler
+                             ((QofEventHandler)gnc_tree_model_split_reg_event_handler, model);
+
+    LEAVE("model %p", model);
+    return model;
+}
+
+
+
+GncTreeModelSplitReg *
+gnc_tree_model_split_reg_new_from_query(Query *query)
+{
+    GncTreeModelSplitReg *model;
+    GList *slist;
+/*
+
+Not sure if required or what to put in here
+    slist = 
+    model = gnc_tree_model_split_reg_new(slist);
+    model->priv->query = query;
+*/
+    model = gnc_tree_model_split_reg_new(NULL);
+    return model;
+
+}
+
+
+
+GncTreeModelSplitReg *
+gnc_tree_model_split_reg_new_from_account(Account *acc)
+{
+    GncTreeModelSplitReg *model;
+    Query *q;
+    GSList  *p1, *p2;
+    QofBook *book;
+
+    GList *slist;
+
+    q = qof_query_create_for(GNC_ID_SPLIT);
+    book = gnc_get_current_book();
+    qof_query_set_book (q, book);
+
+    /* Sort by transaction date */
+    p1 = g_slist_prepend (NULL, TRANS_DATE_POSTED);
+    p1 = g_slist_prepend (p1, SPLIT_TRANS);
+    p2 = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
+    qof_query_set_sort_order (q, p1, p2, NULL);
+
+    xaccQueryAddSingleAccountMatch (q, acc, QOF_QUERY_AND);
+
+    /* Run the query */
+    slist = qof_query_run(q);
+
+    model = gnc_tree_model_split_reg_new(slist);
+    model->priv->anchor = acc;
+    model->priv->query = q;
+    return model;
+}
+
+
+
+/************************************************************/
+/*        Gnc Tree Model Debugging Utility Function         */
+/************************************************************/
+#define ITER_STRING_LEN 128
+
+static const gchar *
+iter_to_string (GtkTreeIter *iter)
+{
+#ifdef G_THREADS_ENABLED
+    static GStaticPrivate gtmits_buffer_key = G_STATIC_PRIVATE_INIT;
+    gchar *string;
+
+    string = g_static_private_get (&gtmits_buffer_key);
+    if (string == NULL)
+    {
+        string = g_malloc(ITER_STRING_LEN + 1);
+        g_static_private_set (&gtmits_buffer_key, string, g_free);
+    }
+#else
+    static char string[ITER_STRING_LEN + 1];
+#endif
+
+    if (iter)
+        snprintf(
+            string, ITER_STRING_LEN,
+            "[stamp:%x data:%d, %p (%p:%s), %p (%p:%s)]",
+            iter->stamp, GPOINTER_TO_INT(iter->user_data),
+            iter->user_data2,
+            iter->user_data2 ? ((GList *) iter->user_data2)->data : 0,
+            iter->user_data2 ?
+            (QOF_INSTANCE(((GList *) iter->user_data2)->data))->e_type : "",
+            iter->user_data3,
+            iter->user_data3 ? ((GList *) iter->user_data3)->data : 0,
+            iter->user_data3 ?
+            (QOF_INSTANCE(((GList *) iter->user_data3)->data))->e_type : "");
+    else
+        strcpy(string, "(null)");
+    return string;
+}
+
+
+
+/************************************************************/
+/*       Gtk Tree Model Required Interface Functions        */
+/************************************************************/
+static void
+gnc_tree_model_split_reg_tree_model_init (GtkTreeModelIface *iface)
+{
+    iface->get_flags       = gnc_tree_model_split_reg_get_flags;
+    iface->get_n_columns   = gnc_tree_model_split_reg_get_n_columns;
+    iface->get_column_type = gnc_tree_model_split_reg_get_column_type;
+    iface->get_iter        = gnc_tree_model_split_reg_get_iter;
+    iface->get_path        = gnc_tree_model_split_reg_get_path;
+    iface->get_value       = gnc_tree_model_split_reg_get_value;
+    iface->iter_next       = gnc_tree_model_split_reg_iter_next;
+    iface->iter_children   = gnc_tree_model_split_reg_iter_children;
+    iface->iter_has_child  = gnc_tree_model_split_reg_iter_has_child;
+    iface->iter_n_children = gnc_tree_model_split_reg_iter_n_children;
+    iface->iter_nth_child  = gnc_tree_model_split_reg_iter_nth_child;
+    iface->iter_parent     = gnc_tree_model_split_reg_iter_parent;
+}
+
+
+
+static GtkTreeModelFlags
+gnc_tree_model_split_reg_get_flags (GtkTreeModel *tree_model)
+{
+    /* Returns a set of flags supported by this interface. The flags
+       are a bitwise combination of GtkTreeModelFlags. The flags supported
+       should not change during the lifecycle of the tree_model. */
+    return 0;
+}
+
+
+
+static int
+gnc_tree_model_split_reg_get_n_columns (GtkTreeModel *tree_model)
+{
+    /* Returns the number of columns supported by tree_model. */
+    g_return_val_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(tree_model), -1);
+
+    return GNC_TREE_MODEL_SPLIT_REG_NUM_COLUMNS;
+}
+
+
+
+static GType
+gnc_tree_model_split_reg_get_column_type (GtkTreeModel *tree_model,
+                                        int index)
+{
+    /* Returns the type of the column. */
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (tree_model), G_TYPE_INVALID);
+    g_return_val_if_fail ((index < GNC_TREE_MODEL_SPLIT_REG_NUM_COLUMNS) && (index >= 0), G_TYPE_INVALID);
+
+    switch (index)
+    {
+    case GNC_TREE_MODEL_SPLIT_REG_COL_GUID:
+        return G_TYPE_POINTER;
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_DATE:
+    case GNC_TREE_MODEL_SPLIT_REG_COL_NUMACT:
+    case GNC_TREE_MODEL_SPLIT_REG_COL_DESCNOTES:
+    case GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID:
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_COLOR:
+        return G_TYPE_STRING;
+
+    default:
+        g_assert_not_reached ();
+        return G_TYPE_INVALID;
+    }
+}
+
+
+
+static gboolean
+gnc_tree_model_split_reg_get_iter (GtkTreeModel *tree_model,
+                                 GtkTreeIter *iter,
+                                 GtkTreePath *path)
+{
+    /* Sets iter to a valid iterator pointing to path. */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    GList *tnode;
+    SplitList *slist;
+    GList *snode;
+    gint depth, *indices, flags;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (tree_model), FALSE);
+
+    {
+        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_print("gnc_tree_model_split_reg_get_iter\n"); */
+
+    depth = gtk_tree_path_get_depth (path);
+/* g_print("Depth is %u\n", depth); */
+    indices = gtk_tree_path_get_indices (path);
+
+    tnode = g_list_nth(model->priv->tlist, indices[0]);
+
+    if (!tnode) {
+        DEBUG("path index off end of tlist");
+        goto fail;
+    }
+
+    slist = xaccTransGetSplitList(tnode->data);
+
+/* g_print("Num of Splits is %d\n\n", xaccTransCountSplits(tnode->data)); */
+
+    if(depth != 3 )
+        snode = g_list_nth(slist, 0);
+    else
+        snode = g_list_nth(slist, indices[2]);
+
+    if (!snode) {
+        DEBUG("path index off end of slist");
+        goto fail;
+    }
+
+    if (depth == 1)       /* Trans Row 1 */
+        flags = TROW1;
+
+    else if (depth == 2)  /* Trans Row 2 */
+        flags = TROW2;
+
+    else if (depth == 3)  /* Split */
+        flags = SPLIT;
+
+    else {
+        DEBUG("Invalid path depth");
+        goto fail;
+    }
+
+    *iter = make_iter(model, flags, tnode, snode);
+/*    g_assert(VALID_ITER(model, iter)); */
+    LEAVE("True");
+    return TRUE;
+ fail:
+    iter->stamp = 0;
+    LEAVE("False");
+    return FALSE;
+}
+
+
+
+static GtkTreePath *
+gnc_tree_model_split_reg_get_path (GtkTreeModel *tree_model,
+                                 GtkTreeIter *iter)
+{
+    /* Returns a newly-created GtkTreePath referenced by iter. 
+       This path should be freed with gtk_tree_path_free(). */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    GtkTreePath *path;
+    gint tpos, spos;
+    GList *tnode, *snode;
+    GList *slist;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (model), NULL);
+
+/* g_print("gnc_tree_model_split_reg_get_path\n"); */
+    ENTER("model %p, iter %s", model, iter_to_string(iter));
+/*    g_assert(VALID_ITER(model, iter)); */
+
+    path = gtk_tree_path_new();
+
+    tnode = iter->user_data2;
+
+    slist = xaccTransGetSplitList(tnode->data);
+    snode = iter->user_data3;
+
+    /* Level 1 */
+    tpos = g_list_position(model->priv->tlist, tnode);
+    if (tpos == -1)
+        goto fail;
+    gtk_tree_path_append_index(path, tpos);
+
+    /* Level 2 - All ways 0 */
+    if(IS_TROW2(iter))
+        gtk_tree_path_append_index(path, 0);
+
+    /* Level 3 */
+    if(IS_SPLIT(iter))
+    {
+        spos = g_list_position(slist, snode);
+
+        if (spos == -1)
+            goto fail;
+        gtk_tree_path_append_index(path, 0); /* Add the Level 2 part */
+        gtk_tree_path_append_index(path, spos);
+    }
+
+    {
+        gchar *path_string = gtk_tree_path_to_string(path);
+/* g_print("Returned get path is %s\n", gtk_tree_path_to_string(path)); */
+        LEAVE("get path  %s", path_string);
+        g_free(path_string);
+    }
+    return path;
+
+ fail:
+    LEAVE("No Valid Path");
+    return NULL;
+}
+
+
+
+static gchar*
+get_row_color(GncTreeModelSplitReg *model, gboolean is_trow1, gboolean is_trow2, gboolean is_split, gint num)
+{
+
+    gchar *cell_color = NULL;
+
+    if(!model->priv->use_colors)
+    {
+        if(model->priv->double_line)
+        {
+            if(model->priv->alt_colors_by_txn)
+            {
+                if(num % 2 == 0)
+                {
+                    if(is_trow1 || is_trow2)
+                        cell_color = (gchar*)GREENROW;
+                }
+                else 
+                {
+                    if(is_trow1 || is_trow2)
+                        cell_color = (gchar*)TANROW;
+                }
+            }
+            else
+            {
+                if(is_trow1)
+                    cell_color = (gchar*)GREENROW;
+                else if(is_trow2)
+                    cell_color = (gchar*)TANROW;
+            }
+        }
+        else
+        {
+            if(num % 2 == 0)
+            {
+                if(is_trow1)
+                    cell_color = (gchar*)GREENROW;
+                else if(is_trow2)
+                    cell_color = (gchar*)TANROW;
+            }
+            else
+            {
+                if(is_trow1)
+                    cell_color = (gchar*)TANROW;
+                else if(is_trow2)
+                    cell_color = (gchar*)GREENROW;
+            }
+        }
+        if(is_split)
+            cell_color = (gchar*)SPLITROW;
+    }
+    else
+        cell_color = (gchar*)NULL;
+
+    return cell_color;
+}
+
+
+
+static void
+gnc_tree_model_split_reg_get_value (GtkTreeModel *tree_model,
+                                  GtkTreeIter *iter,
+                                  int column,
+                                  GValue *value)
+{
+    /* Initializes and sets value to that at column. When done with value,
+       g_value_unset() needs to be called to free any allocated memory. */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    Account *account;
+    Transaction *trans;
+    Split *split;
+    const GncGUID *guid;
+    GList *tnode, *snode;
+    gint depth, *indices;
+
+    g_return_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (model));
+/* g_print("gnc_tree_model_split_reg_get_value\n"); */
+    ENTER("model %p, iter %s, col %d", tree_model, iter_to_string(iter), column);
+
+    account = model->priv->anchor;
+
+    tnode = (GList *) iter->user_data2;
+    trans = (Transaction *) tnode->data;
+
+    snode = (GList *) iter->user_data3;
+    split = (Split *) snode->data;
+
+    g_value_init(value, gnc_tree_model_split_reg_get_column_type(tree_model, column));
+
+    indices = gtk_tree_path_get_indices (gtk_tree_model_get_path (GTK_TREE_MODEL(model), iter));
+
+    switch (column)
+    {
+    case GNC_TREE_MODEL_SPLIT_REG_COL_GUID:
+        guid = qof_entity_get_guid(QOF_INSTANCE(trans));
+        g_value_set_pointer(value, (gpointer) guid);
+        break;
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_DATE:
+        break;
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_COLOR:
+            g_value_set_string (value, get_row_color(model, IS_TROW1(iter), IS_TROW2(iter), IS_SPLIT(iter), indices[0]));
+        break;
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_NUMACT:
+        break;
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_DESCNOTES:
+        break;
+
+    case GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID:
+        break;
+
+    default:
+        g_assert_not_reached ();
+    }
+
+    LEAVE(" ");
+}
+
+
+
+static gboolean
+gnc_tree_model_split_reg_iter_next (GtkTreeModel *tree_model,
+                                  GtkTreeIter *iter)
+{
+    /* Sets iter to point to the node following it at the current level.
+       If there is no next iter, FALSE is returned and iter is set to be
+       invalid */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    Transaction *trans;
+    SplitList *slist;
+    GList *tnode, *snode;
+    gint flags = TROW1;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (model), FALSE);
+/* g_print("gnc_tree_model_split_reg_iter_next\n"); */
+    ENTER("model %p, iter %s", tree_model, iter_to_string(iter));
+
+    if (IS_TROW2(iter)) {
+        LEAVE("Transaction row 2 never has a next");
+        goto fail;
+    }
+
+    if (IS_TROW1(iter)) {
+
+        tnode = iter->user_data2;
+        tnode = g_list_next(tnode);
+
+        if (!tnode) {
+           LEAVE("last trans has no next");
+           goto fail;
+        }
+
+        trans = tnode->data;
+
+        slist = xaccTransGetSplitList(trans);
+        snode = g_list_nth(slist, 0);
+
+        flags = TROW1;
+    }
+
+    if (IS_SPLIT(iter)) {
+
+        tnode = iter->user_data2;
+        snode = iter->user_data3;
+        snode = g_list_next(snode);
+
+        if (!snode) {
+           LEAVE("last split has no next");
+           goto fail;
+        }
+
+        flags = SPLIT;
+    }
+
+    *iter = make_iter(model, flags, tnode, snode);
+    LEAVE("iter %s", iter_to_string(iter));
+    return TRUE;
+ fail:
+    iter->stamp = 0;
+    return FALSE;
+}
+
+
+
+static gboolean
+gnc_tree_model_split_reg_iter_children (GtkTreeModel *tree_model,
+                                      GtkTreeIter *iter,
+                                      GtkTreeIter *parent_iter)
+{
+    /* Sets iter to point to the first child of parent. If parent has no children,
+       FALSE is returned and iter is set to be invalid. parent will remain a valid
+       node after this function has been called. */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    GList *tnode, *snode;
+    gint flags = TROW1;
+    Transaction *trans;
+    SplitList *slist;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (tree_model), FALSE);
+    ENTER("model %p, iter %p (to be filed in), parent %s",
+          tree_model, iter, (parent_iter ? iter_to_string(parent_iter) : "(null)"));
+
+/* g_print("gnc_tree_model_split_reg_iter_children\n"); */
+
+    if (!parent_iter) {
+        /* Get the very first iter */
+        tnode = model->priv->tlist;
+        if (tnode) {
+
+            slist = xaccTransGetSplitList(tnode->data);
+            snode = g_list_nth(slist, 0);
+        
+            *iter = make_iter(model, flags, tnode, snode);
+            LEAVE("iter (2) %s", iter_to_string(iter));
+            return TRUE;
+        } else {
+            PERR("We should never have a NULL trans list.");
+            goto fail;
+        }
+    }
+
+/*    g_assert(VALID_ITER(model, parent_iter)); */
+
+    if(IS_TROW1(parent_iter))
+    {
+        tnode = parent_iter->user_data2;
+        snode = parent_iter->user_data3;
+        flags = TROW2;
+    }
+
+    if(IS_TROW2(parent_iter))
+    {
+        tnode = parent_iter->user_data2;
+
+        slist = xaccTransGetSplitList(tnode->data);
+        snode = g_list_nth(slist, 0);
+        flags = SPLIT;
+    }
+
+    if(IS_SPLIT(parent_iter))
+        goto fail;
+
+    *iter = make_iter(model, flags, tnode, snode);
+    LEAVE("iter %s", iter_to_string(iter));
+    return TRUE;
+ fail:
+    LEAVE("iter has no children");
+    iter->stamp = 0;
+    return FALSE;
+}
+
+
+
+static gboolean
+gnc_tree_model_split_reg_iter_has_child (GtkTreeModel *tree_model,
+                                       GtkTreeIter *iter)
+{
+    /* Returns TRUE if iter has children, FALSE otherwise. */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    GList *tnode;
+    Transaction *trans;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (tree_model), FALSE);
+
+    ENTER("model %p, iter %s", tree_model, iter_to_string(iter));
+/* g_print("gnc_tree_model_split_reg_iter_has_child\n"); */
+
+    tnode = iter->user_data2;
+    trans = tnode->data;
+
+    if (IS_TROW1(iter))
+    {
+        LEAVE("Transaction Row 1 is yes");
+        return TRUE;
+    }
+
+    if (IS_TROW2(iter))
+    {
+        LEAVE("Transaction Row 2 is yes");
+        return TRUE;
+    }
+
+    LEAVE("We have no child");
+    return FALSE;
+}
+
+
+
+static int
+gnc_tree_model_split_reg_iter_n_children (GtkTreeModel *tree_model,
+                                        GtkTreeIter *iter)
+{
+    /* Returns the number of children that iter has. As a special case,
+       if iter is NULL, then the number of toplevel nodes is returned.  */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    Transaction *trans;
+    GList *tnode;
+    int i;
+
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (tree_model), FALSE);
+    ENTER("model %p, iter %s", tree_model, iter_to_string(iter));
+/* g_print("gnc_tree_model_split_reg_iter_n_children\n"); */
+
+    if (iter == NULL) {
+        i = g_list_length(model->priv->tlist);
+        LEAVE("toplevel count is %d", i);
+        return i;
+    }
+
+    if(IS_SPLIT(iter))
+        i = 0;
+
+    if(IS_TROW1(iter))
+        i = 1;
+
+    if(IS_TROW2(iter))
+    {
+        tnode = iter->user_data2;
+        trans = tnode->data;
+        i = xaccTransCountSplits(trans);
+    }
+
+    LEAVE("The number of children iter has is %d", i);
+    return i;
+}
+
+
+
+static gboolean
+gnc_tree_model_split_reg_iter_nth_child (GtkTreeModel *tree_model,
+                                       GtkTreeIter *iter,
+                                       GtkTreeIter *parent_iter,
+                                       int n)
+{
+    /* Sets iter to be the child of parent, using the given index. */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    Transaction *trans;
+    SplitList *slist;
+    GList *tnode, *snode;
+    gint flags = TROW1;
+
+    ENTER("model %p, iter %s, n %d", tree_model, iter_to_string(parent_iter), n);
+    g_return_val_if_fail (GNC_IS_TREE_MODEL_SPLIT_REG (tree_model), FALSE);
+
+/* g_print("gnc_tree_model_split_reg_iter_nth_child %d\n", n); */
+
+    if (parent_iter == NULL) {  /* Top-level */
+        tnode = g_list_nth(model->priv->tlist, n);
+
+        if (!tnode) {
+            PERR("Trans list should never be NULL.");
+            goto fail;
+        }
+        trans = tnode->data;
+
+        slist = xaccTransGetSplitList(trans);
+        snode = g_list_nth(slist, 0);
+
+        *iter = make_iter(model, flags, tnode, snode);
+        LEAVE("iter (2) %s", iter_to_string(iter));
+        return TRUE;
+    }
+
+    DEBUG("parent iter %s", iter_to_string(parent_iter));
+/*    g_assert(VALID_ITER(model, parent_iter)); */
+
+    if (IS_SPLIT(parent_iter))
+        goto fail;  /* Splits have no children */
+
+
+    if(IS_TROW1(parent_iter) && (n != 0))
+        goto fail;
+
+    tnode = parent_iter->user_data2;
+    trans = tnode->data;
+    snode = parent_iter->user_data3;
+    flags = TROW2;
+
+    if(IS_TROW2(parent_iter) && (n > xaccTransCountSplits(trans)))
+        goto fail;
+    else
+    {
+
+        slist = xaccTransGetSplitList(trans);
+        snode = g_list_nth(slist, n);
+        flags = SPLIT;
+    }
+
+    *iter = make_iter(model, flags, tnode, snode);
+    LEAVE("iter of child with index %u is %s", n, iter_to_string(iter));
+    return TRUE;
+ fail:
+    LEAVE("iter has no child with index %u", n);
+    iter->stamp = 0;
+    return FALSE;
+}
+
+
+
+static gboolean
+gnc_tree_model_split_reg_iter_parent (GtkTreeModel *tree_model,
+                                    GtkTreeIter *iter,
+                                    GtkTreeIter *child)
+{
+    /* Sets iter to be the parent of child. If child is at the toplevel,
+       and doesn't have a parent, then iter is set to an invalid iterator
+       and FALSE is returned. child will remain a valid node after this 
+       function has been called. */
+    GncTreeModelSplitReg *model = GNC_TREE_MODEL_SPLIT_REG (tree_model);
+    GList *tnode, *snode;
+    gint flags = TROW1;
+
+    ENTER("model %p, child %s", tree_model, iter_to_string(child));
+
+/* g_print("gnc_tree_model_split_reg_iter_parent\n"); */
+
+/*    g_assert(VALID_ITER(model, child)); */
+
+    tnode = child->user_data2;
+    snode = child->user_data3;
+
+    if(IS_TROW1(child))
+        goto fail;
+
+    if(IS_TROW2(child))
+        flags = TROW1;
+
+    if(IS_SPLIT(child))
+        flags = TROW2;
+
+    *iter = make_iter(model, flags, tnode, snode);
+    LEAVE("parent iter is %s", iter_to_string(iter));
+    return TRUE;
+ fail:
+    LEAVE("we have no parent");
+    iter->stamp = 0;
+    return FALSE;
+}
+
+
+
+
+/*###################################################################*/
+
+gboolean
+gnc_tree_model_split_reg_get_split_and_trans (
+    GncTreeModelSplitReg *model, GtkTreeIter *iter,
+    gboolean *is_trow1, gboolean *is_trow2, gboolean *is_split,
+    gboolean *is_blank, Split **split, Transaction **trans)
+{
+    GList *node;
+
+/*    g_return_val_if_fail(VALID_ITER(model, iter), FALSE); */
+    ENTER("");
+    if (is_trow1)
+        *is_trow1 = !!IS_TROW1(iter);
+    if (is_trow2)
+        *is_trow2 = !!IS_TROW2(iter);
+    if (is_split)
+        *is_split = !!IS_SPLIT(iter);
+    if (is_blank)
+        *is_blank = !!IS_BLANK(iter);
+
+    if (trans) {
+        node = iter->user_data2;
+        *trans = node ? (Transaction *) node->data : NULL;
+    }
+    if (split) {
+        node = iter->user_data3;
+        *split = node ? (Split *) node->data : NULL;
+    }
+    LEAVE("");
+    return TRUE;
+}
+
+
+/*###################################################################*/
+
+Account *
+gnc_tree_model_split_reg_get_anchor(GncTreeModelSplitReg *model)
+{
+    g_return_val_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(model), NULL);
+    return model->priv->anchor;
+}
+
+
+GtkListStore *
+gnc_tree_model_split_reg_get_description_list(GncTreeModelSplitReg *model)
+{
+    g_return_val_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(model), NULL);
+    return model->priv->description_list;
+}
+
+
+GtkListStore *
+gnc_tree_model_split_reg_get_notes_list(GncTreeModelSplitReg *model)
+{
+    g_return_val_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(model), NULL);
+    return model->priv->notes_list;
+}
+
+
+GtkListStore *
+gnc_tree_model_split_reg_get_memo_list(GncTreeModelSplitReg *model)
+{
+    g_return_val_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(model), NULL);
+    return model->priv->memo_list;
+}
+
+
+GtkListStore *
+gnc_tree_model_split_reg_get_numact_list(GncTreeModelSplitReg *model)
+{
+    g_return_val_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(model), NULL);
+    return model->priv->numact_list;
+}
+
+
+/* Return TRUE if string all ready exists in the list */
+static gboolean
+check_for_duplicates(GtkListStore *liststore, const gchar *string)
+{
+    GtkTreeIter iter;
+    gboolean valid;
+
+    valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (liststore), &iter);
+    while (valid)
+    {
+        gchar *text;
+        // Walk through the list, reading each row
+        gtk_tree_model_get (GTK_TREE_MODEL (liststore), &iter, 0, &text, -1);
+
+        if(!(g_strcmp0(text, string)))
+        {
+            g_free(text);
+            return TRUE;
+        }
+        g_free(text);
+
+        valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (liststore), &iter);
+    }
+    return FALSE;
+}
+
+
+
+/* Create the Auto Complete List Stores.... */
+static void
+create_completion_models(GncTreeModelSplitReg *model)
+{
+
+    GncTreeModelSplitRegPrivate *priv;
+    GtkListStore *description_list, *notes_list, *memo_list, *num_list;
+    GtkTreeIter d_iter, n_iter, m_iter, num_iter;
+    GList *tlist, *tnode, *slist, *snode;
+    int cnt, nSplits;
+
+    priv = model->priv;
+    tlist = priv->tlist;
+
+    description_list = gtk_list_store_new(1, G_TYPE_STRING);
+    notes_list = gtk_list_store_new(1, G_TYPE_STRING);
+    memo_list = gtk_list_store_new(1, G_TYPE_STRING);
+    num_list = gtk_list_store_new(1, G_TYPE_STRING);
+
+    for (tnode = tlist; tnode; tnode = tnode->next)
+    {
+        Transaction *trans;
+        Split       *split;
+        const gchar *string;
+
+        trans = tnode->data;
+
+        nSplits = xaccTransCountSplits(trans);
+        slist = xaccTransGetSplitList(trans);
+    
+        /* Add to the Description list */
+        string = xaccTransGetDescription(trans);
+        if(g_strcmp0(string, ""))
+        {
+            if(check_for_duplicates(description_list, string) == FALSE)
+            {
+                gtk_list_store_append(description_list, &d_iter);
+                gtk_list_store_set(description_list, &d_iter, 0, string , -1);
+            }
+        }
+
+        /* Add to the Notes list */
+        string = xaccTransGetNotes(trans);
+        if(g_strcmp0(string, ""))
+        {
+            if(check_for_duplicates(notes_list, string) == FALSE)
+            {
+                gtk_list_store_append(notes_list, &n_iter);
+                gtk_list_store_set(notes_list, &n_iter, 0, string, -1);
+            }
+        }
+
+        /* Add to the Num list */
+        string = xaccTransGetNum(trans);
+        if(g_strcmp0(string, ""))
+        {
+            if(check_for_duplicates(num_list, string) == FALSE)
+            {
+                gtk_list_store_prepend(num_list, &num_iter);
+                gtk_list_store_set(num_list, &num_iter, 0, string, -1);
+            }
+        }
+
+        /* Loop through the list of splits for each Transaction - **do not free the list** */
+        snode = slist;
+        cnt = 0;
+        while (cnt < nSplits)
+        {
+            split = snode->data;
+
+            /* Add to the Memo list */
+            string = xaccSplitGetMemo(split);
+            if(g_strcmp0(string, ""))
+            {
+                if(check_for_duplicates(memo_list, string) == FALSE)
+                {
+                    gtk_list_store_append(memo_list, &m_iter);
+                    gtk_list_store_set(memo_list, &m_iter, 0, string, -1);
+                }
+            }
+            cnt++;
+            snode = snode->next;
+         }
+    }
+
+    priv->description_list = description_list;
+    priv->notes_list = notes_list;
+    priv->memo_list = memo_list;
+    priv->num_list = num_list;
+    priv->numact_list = gtk_list_store_new(1, G_TYPE_STRING);
+}
+
+
+/* Update the model with entries for the Number field ... */
+void
+gnc_tree_model_split_reg_get_num_list(GncTreeModelSplitReg *model)
+{
+    GncTreeModelSplitRegPrivate *priv;
+    GtkListStore *store, *num_list;
+    GtkTreeIter iter, num_iter;
+    gboolean valid;
+
+    priv = model->priv;
+
+    store = priv->numact_list;
+    num_list = priv->num_list;
+
+    /* Clear the liststore */
+    gtk_list_store_clear (store);
+
+    valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (num_list), &num_iter);
+    while (valid)
+    {
+        gchar *text;
+
+        // Walk through the list, reading each row
+        gtk_tree_model_get (GTK_TREE_MODEL (num_list), &num_iter, 0, &text, -1);
+
+        gtk_list_store_append (store, &iter);
+        gtk_list_store_set (store, &iter, 0, text, -1);
+        g_free(text);
+
+        valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (num_list), &num_iter);
+    }
+    priv->numact_list = store;
+}
+
+
+/* Update the model with entries for the Action field ... */
+void
+gnc_tree_model_split_reg_get_action_list(GncTreeModelSplitReg *model)
+{
+    GncTreeModelSplitRegPrivate *priv;
+    GtkListStore *store;
+    GtkTreeIter iter;
+
+    priv = model->priv;
+    store = priv->numact_list;
+
+    /* Clear the liststore */
+    gtk_list_store_clear (store);
+
+/*FIXME This is a temp hack to give a value, this would come from ledger ? */
+    model->type = CREDIT_REGISTER2;
+
+    /* setup strings in the action pull-down */
+    switch (model->type)
+    {
+    case BANK_REGISTER2:
+        /* broken ! FIXME bg */
+    case SEARCH_LEDGER2:
+
+        /* Translators: This string has a context prefix; the translation
+        	must only contain the part after the | character. */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, Q_("Action Column|Deposit"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Withdraw"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Check"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Interest"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("ATM Deposit"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("ATM Draw"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Teller"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Charge"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Payment"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Receipt"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Increase"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Decrease"), -1);
+        /* Action: Point Of Sale */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("POS"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Phone"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Online"), -1);
+        /* Action: Automatic Deposit ?!? */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("AutoDep"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Wire"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Credit"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Direct Debit"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Transfer"), -1);
+        break;
+    case CASH_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Increase"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Decrease"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        break;
+    case ASSET_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Fee"), -1);
+        break;
+    case CREDIT_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("ATM Deposit"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("ATM Draw"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Credit"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Fee"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Interest"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Online"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        break;
+    case LIABILITY_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Loan"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Interest"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Payment"), -1);
+        break;
+    case RECEIVABLE_REGISTER2:
+    case PAYABLE_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Invoice"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Payment"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Interest"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Credit"), -1);
+        break;
+    case INCOME_LEDGER2:
+    case INCOME_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Increase"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Decrease"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Interest"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Payment"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Rebate"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Paycheck"), -1);
+        break;
+    case EXPENSE_REGISTER2:
+    case TRADING_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Increase"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Decrease"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        break;
+    case GENERAL_LEDGER2:
+    case EQUITY_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Equity"), -1);
+        break;
+    case STOCK_REGISTER2:
+    case PORTFOLIO_LEDGER2:
+    case CURRENCY_REGISTER2:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Price"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Fee"), -1);
+        /* Action: Dividend */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Dividend"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Interest"), -1);
+        /* Action: Long Term Capital Gains */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("LTCG"), -1);
+        /* Action: Short Term Capital Gains */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("STCG"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Income"), -1);
+        /* Action: Distribution */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Dist"), -1);
+        /* Translators: This string has a disambiguation prefix */
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, Q_("Action Column|Split"), -1);
+        break;
+
+    default:
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Increase"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Decrease"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Buy"), -1);
+        gtk_list_store_insert_with_values (store, &iter, 100, 0, _("Sell"), -1);
+        break;
+    }
+    priv->numact_list = store;
+}
+
+
+/* Return the GtkListstore of Accounts */
+GtkListStore *
+gnc_tree_model_split_reg_get_acct_list(GncTreeModelSplitReg *model)
+{
+    GncTreeModelSplitRegPrivate *priv;
+    Account *root;
+    Account *acc;
+    GtkListStore *store;
+    GtkTreeIter iter;
+    GList *accts, *ptr;
+    gboolean valid;
+    const gchar *name, *fname;
+    gint i;
+
+    priv = model->priv;
+
+    /* Store is short name, full name and account pointer */
+    store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER );
+
+    root = gnc_book_get_root_account( gnc_get_current_book());
+/*FIXME This does not look sorted to me, need to look at this */
+    accts = gnc_account_get_descendants_sorted( root );
+
+    for (ptr = accts, i = 0; ptr; ptr = g_list_next(ptr), i++)
+    {
+        acc = ptr->data;
+
+        if(!(acc == model->priv->anchor))
+        {
+            fname = gnc_account_get_full_name(acc);
+            name = xaccAccountGetName(acc);
+            gtk_list_store_append(store, &iter);
+            gtk_list_store_set(store, &iter, 0, name, 1, fname, 2, acc, -1);
+        }
+    }
+
+    g_list_free( accts );
+
+    return store;
+}
+
+
+/*******************************************************************/
+/*   Split Register Tree Model - Engine Event Handling Functions   */
+/*******************************************************************/
+
+/** This function is the handler for all event messages from the
+ *  engine.  Its purpose is to update the account tree model any time
+ *  an account is added to the engine or deleted from the engine.
+ *  This change to the model is then propagated to any/all overlying
+ *  filters and views.  This function listens to the ADD, REMOVE, and
+ *  DESTROY events.
+ *
+ *  @internal
+ *
+ *  @warning There is a "Catch 22" situation here.
+ *  gtk_tree_model_row_deleted() can't be called until after the item
+ *  has been deleted from the real model (which is the engine's
+ *  account tree for us), but once the account has been deleted from
+ *  the engine we have no way to determine the path to pass to
+ *  row_deleted().  This is a PITA, but the only other choice is to
+ *  have this model mirror the engine's accounts instead of
+ *  referencing them directly.
+ *
+ *  @param entity The guid of the affected item.
+ *
+ *  @param type The type of the affected item.  This function only
+ *  cares about items of type "account".
+ *
+ *  @param event type The type of the event. This function only cares
+ *  about items of type ADD, REMOVE, MODIFY, and DESTROY.
+ *
+ *  @param user_data A pointer to the split register tree model.
+ */
+static void
+gnc_tree_model_split_reg_event_handler (QofInstance *entity,
+                                      QofEventId event_type,
+                                      GncTreeModelSplitReg *model,
+                                      GncEventData *event_data)
+{
+    GncTreeModelSplitRegPrivate *priv = model->priv;
+    GncEventData *ed = event_data;
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    Transaction *trans;
+    Split *split = NULL;
+    QofIdType type;
+    const gchar *name = NULL;
+    GList *tnode;
+
+    g_return_if_fail(GNC_IS_TREE_MODEL_SPLIT_REG(model));
+
+    if (qof_instance_get_book(entity) != priv->book)
+        return;
+    type = entity->e_type;
+
+    if (safe_strcmp(type, GNC_ID_SPLIT) == 0) {
+        /* Get the split.*/
+        split = (Split *) entity;
+
+        switch (event_type) {
+        case QOF_EVENT_MODIFY:
+
+            break;
+        default:
+            DEBUG("ignored event for %p (%s)", split, name);
+        }
+    } else if (safe_strcmp(type, GNC_ID_TRANS) == 0) {
+        /* Get the trans.*/
+        trans = (Transaction *) entity;
+
+        switch (event_type) {
+        case GNC_EVENT_ITEM_ADDED:
+            split = (Split *) ed->node;
+
+
+            break;
+        case GNC_EVENT_ITEM_REMOVED:
+            split = (Split *) ed->node;
+
+
+            break;
+        case QOF_EVENT_MODIFY:
+
+
+            break;
+        case QOF_EVENT_DESTROY:
+
+
+            break;
+        default:
+            DEBUG("ignored event for %p (%s)", trans, name);
+        }
+    } else if (safe_strcmp(type, GNC_ID_ACCOUNT) == 0) {
+        switch (event_type) {
+            Account *acc;
+        case GNC_EVENT_ITEM_ADDED:
+            split = (Split *) ed;
+
+            break;
+        default:
+            ;
+        }
+    }
+}

Added: gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.h	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,196 @@
+/********************************************************************\
+ * gnc-tree-model-split-reg.h -- GtkTreeView implementation to      *
+ *                     display registers   in a GtkTreeView.        *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ * Copyright (C) 2006-2007 Chris Shoemaker <c.shoemaker at cox.net>    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+
+#ifndef __GNC_TREE_MODEL_SPLIT_REG_H
+#define __GNC_TREE_MODEL_SPLIT_REG_H
+
+#include <gtk/gtk.h>
+#include "gnc-tree-model.h"
+
+#include "Query.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_TREE_MODEL_SPLIT_REG            (gnc_tree_model_split_reg_get_type ())
+#define GNC_TREE_MODEL_SPLIT_REG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitReg))
+#define GNC_TREE_MODEL_SPLIT_REG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitRegClass))
+#define GNC_IS_TREE_MODEL_SPLIT_REG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_TREE_MODEL_SPLIT_REG))
+#define GNC_IS_TREE_MODEL_SPLIT_REG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_TREE_MODEL_SPLIT_REG))
+#define GNC_TREE_MODEL_SPLIT_REG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_TREE_MODEL_SPLIT_REG, GncTreeModelSplitRegClass))
+#define GNC_TREE_MODEL_SPLIT_REG_NAME            "GncTreeModelSplitReg"
+
+
+/** @brief Register types
+ *
+ * "registers" are single-account display windows.
+ * "ledgers" are multiple-account display windows */
+typedef enum
+{
+    BANK_REGISTER2,
+    CASH_REGISTER2,
+    ASSET_REGISTER2,
+    CREDIT_REGISTER2,
+    LIABILITY_REGISTER2,
+    INCOME_REGISTER2,
+    EXPENSE_REGISTER2,
+    EQUITY_REGISTER2,
+    STOCK_REGISTER2,
+    CURRENCY_REGISTER2,
+    RECEIVABLE_REGISTER2,
+    PAYABLE_REGISTER2,
+    TRADING_REGISTER2,
+    NUM_SINGLE_REGISTER_TYPES2,
+
+    GENERAL_LEDGER2 = NUM_SINGLE_REGISTER_TYPES2,
+    INCOME_LEDGER2,
+    PORTFOLIO_LEDGER2,
+    SEARCH_LEDGER2,
+
+    NUM_REGISTER_TYPES2
+} SplitRegisterType2;
+
+/** Register styles */
+typedef enum
+{
+    REG_STYLE_LEDGER2,
+    REG_STYLE_AUTO_LEDGER2,
+    REG_STYLE_JOURNAL2
+} SplitRegisterStyle2;
+
+
+typedef enum
+{
+    GNC_TREE_MODEL_SPLIT_REG_COL_GUID,
+    GNC_TREE_MODEL_SPLIT_REG_COL_DATE,
+    GNC_TREE_MODEL_SPLIT_REG_COL_NUMACT,
+    GNC_TREE_MODEL_SPLIT_REG_COL_DESCNOTES,
+    GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID,
+
+    GNC_TREE_MODEL_SPLIT_REG_COL_LAST_VISIBLE = GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID,
+
+    /* internal hidden columns */
+    GNC_TREE_MODEL_SPLIT_REG_COL_COLOR,
+
+    GNC_TREE_MODEL_SPLIT_REG_NUM_COLUMNS
+} GncTreeModelSplitRegColumn;
+
+/* typedefs & structures */
+typedef struct GncTreeModelSplitRegPrivate GncTreeModelSplitRegPrivate;
+
+/** The instance data structure for an account tree model. */
+typedef struct
+{
+    GncTreeModel gnc_tree_model;    /**< The parent object data. */
+    GncTreeModelSplitRegPrivate *priv;
+    int stamp;                      /**< The state of the model. Any state
+                                     *   change increments this number. */
+
+    SplitRegisterType2 type;       /* This may be the wrong place for these, may be the view ? */
+    SplitRegisterStyle2 style;
+
+
+} GncTreeModelSplitReg;
+
+
+/** The class data structure for an account tree model. */
+typedef struct
+{
+    GncTreeModelClass gnc_tree_model;   /**< The parent object data. */
+} GncTreeModelSplitRegClass;
+
+
+
+/** Get the type of split register tree plugin.
+ *
+ *  @return A GType.
+ */
+GType gnc_tree_model_split_reg_get_type (void);
+
+
+/** @name Split Register Tree Model Constructors
+ @{ */
+
+/** Create a new GtkTreeModel for manipulating gnucash splits.
+ *
+ *  @param The Query
+ */
+GncTreeModelSplitReg *gnc_tree_model_split_reg_new_from_account (Account *acc);
+/** @} */
+
+/** @name Split Register Tree Model Constructors
+ @{ */
+
+/** Create a new GtkTreeModel for manipulating gnucash splits.
+ *
+ *  @param The Query
+ */
+GncTreeModelSplitReg *gnc_tree_model_split_reg_new_from_query (Query *query);
+/** @} */
+
+/** Get the Account of GtkTreeModel.
+ *
+ *  @param The model
+ */
+Account * gnc_tree_model_split_reg_get_anchor(GncTreeModelSplitReg *model);
+/** @} */
+
+GtkListStore *
+gnc_tree_model_split_reg_get_description_list(GncTreeModelSplitReg *model);
+
+GtkListStore *
+gnc_tree_model_split_reg_get_notes_list(GncTreeModelSplitReg *model);
+
+GtkListStore *
+gnc_tree_model_split_reg_get_memo_list(GncTreeModelSplitReg *model);
+
+GtkListStore *
+gnc_tree_model_split_reg_get_numact_list(GncTreeModelSplitReg *model);
+
+GtkListStore *
+gnc_tree_model_split_reg_get_acct_list(GncTreeModelSplitReg *model);
+
+void
+gnc_tree_model_split_reg_get_num_list(GncTreeModelSplitReg *model);
+
+void
+gnc_tree_model_split_reg_get_action_list(GncTreeModelSplitReg *model);
+
+
+gboolean
+gnc_tree_model_split_reg_get_split_and_trans (
+    GncTreeModelSplitReg *model, GtkTreeIter *iter,
+    gboolean *is_trow1, gboolean *is_trow2, gboolean *is_split,
+    gboolean *is_blank, Split **split, Transaction **trans);
+
+
+G_END_DECLS
+
+#endif /* __GNC_TREE_MODEL_SPLIT_REG_H */
+
+/** @} */
+/** @} */

Added: gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,1488 @@
+/********************************************************************\
+ * gnc-tree-view-split-reg.c -- GtkTreeView implementation to       *
+ *                     display registers   in a GtkTreeView.        *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ * Copyright (C) 2006-2007 Chris Shoemaker <c.shoemaker at cox.net>    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <string.h>
+
+#include "gnc-tree-view.h"
+#include "gnc-tree-view-split-reg.h"
+#include "gnc-tree-model-split-reg.h"
+#include "gnc-gconf-utils.h"
+#include "Transaction.h"
+
+/** Static Globals *******************************************************/
+static QofLogModule log_module = GNC_MOD_GUI;
+
+static void gnc_tree_view_split_reg_class_init(GncTreeViewSplitRegClass *klass);
+static void gnc_tree_view_split_reg_init(GncTreeViewSplitReg *view);
+static void gnc_tree_view_split_reg_dispose(GObject *object);
+static void gnc_tree_view_split_reg_finalize(GObject *object);
+
+static void cdf (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model,
+                		GtkTreeIter  *iter, gpointer view);
+
+static void gtv_split_reg_edited_cb (GtkCellRendererText *cell, const gchar *path_string,
+                          	const gchar *new_text, gpointer _model);
+
+static void start_edit (GtkCellRenderer *cr, GtkCellEditable *editable,
+                       		const gchar *path, gpointer user_data);
+
+static void begin_edit(GncTreeViewSplitReg *tv, Split *split, Transaction *trans);
+
+static void get_editable_start_editing_cb (GtkCellRenderer *cr, GtkCellEditable *editable,
+   				const gchar *path, gpointer user_data);
+
+static void gtv_split_reg_editing_canceled_cb (GtkCellRenderer *cr, gpointer user_data);
+
+static void gtv_split_reg_match_selected_cb(GtkEntryCompletion *widget, GtkTreeModel *model,
+                        GtkTreeIter *iter, gpointer user_data);
+
+static void gtv_split_reg_changed_cb(GtkCellRendererCombo *widget, gchar *path_string,
+                        GtkTreeIter *iter, gpointer user_data);
+
+static gboolean gtv_split_reg_key_press_cb (GtkWidget *treeview, GdkEventKey *event, gpointer userdata);
+static void gtv_split_reg_motion_cb(GtkTreeSelection *sel, gpointer data);
+
+
+typedef enum {
+    COL_DATE,
+    COL_NUMACT,
+    COL_DESCNOTES,
+    COL_TRANSVOID,
+    COL_RECN,
+    COL_TYPE,
+    COL_VALUE,
+    COL_AMOUNT,
+    COL_RATE,
+    COL_PRICE,
+    COL_DEBIT,
+    COL_CREDIT,
+    COL_BALANCE,
+} ViewCol;
+
+
+typedef struct {
+    ViewCol viewcol;
+    gint modelcol;
+    gchar *title;
+    gchar *pref_name;
+    gchar *sizer;
+    int visibility_model_col;
+    void (*edited_cb)(GtkCellRendererText *, const gchar *,
+                      const gchar *, gpointer);
+    void (*editing_started_cb)(GtkCellRenderer *, GtkCellEditable *,
+                               const gchar *, gpointer);
+    GtkTreeIterCompareFunc sort_fn;
+} ColDef;
+
+
+static ColDef all_tree_view_split_reg_columns[] = {
+    {COL_DATE, GNC_TREE_MODEL_SPLIT_REG_COL_DATE,
+     "Date", "date", "00/00/0000xxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_NUMACT, GNC_TREE_MODEL_SPLIT_REG_COL_NUMACT,
+     "Num / Act", "numact", "0000xxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_DESCNOTES, GNC_TREE_MODEL_SPLIT_REG_COL_DESCNOTES,
+     "Description / Notes / Memo", "descnotes", "xxxxxxxxxxxxxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_TRANSVOID, GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID,
+     "Transfer / Void", "transvoid", "xxxxxxxxxxxxxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_RECN, -1,
+     "R", "recn", "x",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, NULL, NULL},
+
+    {COL_TYPE, -1,
+     "Type", "type", "x",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     NULL, NULL, NULL},
+
+    {COL_VALUE, -1,
+     "Val", "value", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     NULL, NULL, NULL},
+
+    {COL_AMOUNT, -1,
+     "Amt", "amount", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_RATE, -1,
+     "Rate", "rate", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_PRICE, -1,
+     "Price", "price", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_DEBIT, -1,
+     "Debit", "debit", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_CREDIT, -1,
+     "Credit", "credit", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     gtv_split_reg_edited_cb, get_editable_start_editing_cb, NULL},
+
+    {COL_BALANCE, -1,
+     "Balance", "balance", "xxxxxxxx",
+     GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS,
+     NULL, NULL, NULL},
+};
+
+
+struct GncTreeViewSplitRegPrivate
+{
+    GtkTreeModel *tree_model;
+    gboolean disposed;
+
+    Account *anchor;
+    gnc_commodity *reg_comm;
+
+    Split *dirty_split;
+    Transaction *dirty_trans;
+
+    gchar *acct_edit_path;    // remember which row's account we're editing
+    GtkCellRenderer *temp_cr; // Temp Cell Renderer reference
+
+    gboolean has_rate;  /* if set, the transfer dialog will never automatically pop-up */
+
+    gboolean acct_short_names;
+    gboolean double_line;
+};
+
+
+#define SPLIT_TRANS_STR _("-- Split Transaction --")
+
+/* This could be a preference setting, The minimum length of the key in order to start completing */
+#define KEY_LENGTH 2
+
+#define GNC_TREE_VIEW_SPLIT_REG_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitRegPrivate))
+
+static GObjectClass *parent_class = NULL;
+
+GType
+gnc_tree_view_split_reg_get_type(void)
+{
+    static GType gnc_tree_view_split_reg_type = 0;
+
+    if (gnc_tree_view_split_reg_type == 0)
+    {
+        static const GTypeInfo our_info =
+        {
+            sizeof (GncTreeViewSplitRegClass),
+            NULL,
+            NULL,
+            (GClassInitFunc) gnc_tree_view_split_reg_class_init,
+            NULL,
+            NULL,
+            sizeof (GncTreeViewSplitReg),
+            0,
+            (GInstanceInitFunc) gnc_tree_view_split_reg_init
+        };
+
+        gnc_tree_view_split_reg_type = g_type_register_static (GNC_TYPE_TREE_VIEW,
+                                     "GncTreeViewSplitReg",
+                                     &our_info, 0);
+    }
+
+    return gnc_tree_view_split_reg_type;
+}
+
+
+
+static void
+gnc_tree_view_split_reg_class_init(GncTreeViewSplitRegClass *klass)
+{
+    GObjectClass *o_class;
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    o_class = G_OBJECT_CLASS (klass);
+
+    o_class->dispose =  gnc_tree_view_split_reg_dispose;
+    o_class->finalize = gnc_tree_view_split_reg_finalize;
+
+    g_type_class_add_private(klass, sizeof(GncTreeViewSplitRegPrivate));
+}
+
+
+
+static void
+gnc_tree_view_split_reg_init (GncTreeViewSplitReg *view)
+{
+    view->priv = g_new0 (GncTreeViewSplitRegPrivate, 1);
+    view->priv->double_line = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "double_line_mode", NULL);
+    view->priv->acct_short_names = gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "show_leaf_account_names", NULL);
+}
+
+
+
+static void
+gnc_tree_view_split_reg_dispose(GObject *object)
+{
+    GncTreeViewSplitReg *view;
+    GncTreeViewSplitRegPrivate *priv;
+
+    gnc_leave_return_if_fail (object != NULL);
+    gnc_leave_return_if_fail (GNC_IS_TREE_VIEW_SPLIT_REG (object));
+
+    view = GNC_TREE_VIEW_SPLIT_REG (object);
+    priv = GNC_TREE_VIEW_SPLIT_REG_GET_PRIVATE(view);
+
+    if (priv->disposed)
+        return;
+    priv->disposed = TRUE;
+
+    g_object_unref(G_OBJECT(priv->tree_model));
+    priv->tree_model = NULL;
+
+    if (G_OBJECT_CLASS (parent_class)->dispose)
+        (* G_OBJECT_CLASS (parent_class)->dispose) (object);
+}
+
+
+
+static void
+gnc_tree_view_split_reg_finalize(GObject *object)
+{
+    GncTreeViewSplitReg *view;
+
+    gnc_leave_return_if_fail(object != NULL);
+    gnc_leave_return_if_fail(GNC_IS_TREE_VIEW_SPLIT_REG (object));
+
+    view = GNC_TREE_VIEW_SPLIT_REG(object);
+
+    if (G_OBJECT_CLASS(parent_class)->finalize)
+        (* G_OBJECT_CLASS(parent_class)->finalize) (object);
+}
+
+
+
+static GncTreeModelSplitReg *
+get_split_reg_model_from_view(GncTreeViewSplitReg *tv)
+{
+    GtkTreeModelSort *s_model = GTK_TREE_MODEL_SORT(
+        gtk_tree_view_get_model(GTK_TREE_VIEW(tv)));
+    return GNC_TREE_MODEL_SPLIT_REG(gtk_tree_model_sort_get_model(s_model));
+}
+
+
+
+/* Set the grid lines to be solid */
+static const gchar *rc_string =
+{
+"style \"solidTreeLines\"\n"
+"{\n"
+" GtkTreeView::grid-line-pattern = \"\1\"\n"
+" GtkTreeView::grid-line-width = 1\n" 
+"}\n"
+"\n"
+"class \"GtkTreeView\" style \"solidTreeLines\"\n"
+};
+
+static ViewCol col_list[] = {
+    COL_DATE, COL_NUMACT, COL_DESCNOTES, COL_TRANSVOID, COL_RECN,
+    COL_TYPE, COL_VALUE, COL_AMOUNT, COL_RATE, COL_PRICE, COL_DEBIT, COL_CREDIT,
+    COL_BALANCE, -1};
+
+/* Creates a treeview with the list of fields */
+static GncTreeViewSplitReg *
+gnc_tree_view_split_reg_set_cols(GncTreeViewSplitReg *tv,
+                                   const ViewCol col_list[])
+{
+    int i = 0;
+
+    GncTreeModelSplitReg *model;
+    model = get_split_reg_model_from_view(tv);
+
+    while (col_list && col_list[i] != -1) {
+        GtkCellRenderer *cr;
+        GtkTreeViewColumn *col;
+        ColDef def;
+        int j, ncol = G_N_ELEMENTS(all_tree_view_split_reg_columns);
+
+        for (j = 0; j < ncol; j++) {
+            if (col_list[i] == all_tree_view_split_reg_columns[j].viewcol) {
+                def = all_tree_view_split_reg_columns[j];
+                break;
+            }
+        }
+        if (j == ncol) {
+            PERR("Failed to find column definition.");
+            i++;
+            continue;
+        }
+
+        if (col_list[i] == COL_TRANSVOID) {
+
+            col = gnc_tree_view_add_combo_column (
+                GNC_TREE_VIEW(tv), def.title, def.pref_name, def.sizer,
+                def.modelcol, def.visibility_model_col,
+                GTK_TREE_MODEL( gnc_tree_model_split_reg_get_acct_list(model)), 0, def.sort_fn);
+
+        } else if (col_list[i] == COL_DATE) {
+            col = gnc_tree_view_add_date_column (
+                GNC_TREE_VIEW(tv), def.title, def.pref_name, NULL, def.sizer,
+                def.modelcol, def.visibility_model_col, def.sort_fn);
+
+        } else if (col_list[i] == COL_NUMACT){ 
+            col = gnc_tree_view_add_combo_column (
+                GNC_TREE_VIEW(tv), def.title, def.pref_name, def.sizer,
+                def.modelcol, def.visibility_model_col,
+                GTK_TREE_MODEL( gnc_tree_model_split_reg_get_numact_list(model)), 0, def.sort_fn);
+
+        } else { 
+            col = gnc_tree_view_add_text_column (
+                GNC_TREE_VIEW(tv), def.title, def.pref_name, NULL, def.sizer,
+                def.modelcol, def.visibility_model_col, def.sort_fn);
+        } 
+
+        g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
+        cr = gnc_tree_view_column_get_renderer(col);
+
+
+        /* Setup cell background color and default alignment */
+        g_object_set( cr, "xalign", 1.0, NULL );
+        gtk_tree_view_column_add_attribute(col, cr, "cell-background", GNC_TREE_MODEL_SPLIT_REG_COL_COLOR);
+
+        if (def.editing_started_cb) {
+            //Store the position of the column in the model
+            g_object_set_data(G_OBJECT(cr), "model_column", GINT_TO_POINTER(def.modelcol));
+            g_signal_connect(G_OBJECT(cr), "editing-started", (GCallback) def.editing_started_cb, tv);
+        }
+
+        //Connect editing-canceled signal so that edit-cancelled can be set appropriately
+        g_signal_connect(G_OBJECT(cr), "editing-canceled", G_CALLBACK(gtv_split_reg_editing_canceled_cb), tv);
+
+        // This can die when prefs are used.
+        g_object_set(G_OBJECT(col), "resizable", TRUE, NULL);
+
+        if (def.edited_cb) {
+            g_object_set(G_OBJECT(cr), "editable", TRUE, NULL);
+            g_signal_connect(G_OBJECT(cr), "edited", (GCallback) def.edited_cb, tv);
+        }
+        g_object_set_data(G_OBJECT(cr), "view_column", GINT_TO_POINTER(def.viewcol));
+        gtk_tree_view_column_set_cell_data_func( col, cr, cdf, tv, NULL);
+        i++;
+    }
+
+    gnc_tree_view_configure_columns(GNC_TREE_VIEW(tv));
+
+    g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)), "changed", G_CALLBACK(gtv_split_reg_motion_cb), tv);
+
+    //Add a data-edited property to keep track of transaction edits
+    g_object_set_data(G_OBJECT(tv), "data-edited", FALSE);
+
+    //???? gtk_tree_selection_set_mode(gtk_tree_view_get_selection(tv), GTK_SELECTION_BROWSE);
+
+/*    g_signal_connect_after(G_OBJECT(tv), "key-press-event", G_CALLBACK(gtv_split_reg_key_press_cb), NULL); */
+    return tv;
+}
+
+
+
+GncTreeViewSplitReg*
+gnc_tree_view_split_reg_new_with_model(GncTreeModelSplitReg *model)
+{
+    GtkTreeModel *s_model;
+    GncTreeViewSplitReg *tv;
+    GtkCellRenderer *cr;
+    GtkTreeViewColumn *col;
+    GtkTreeSelection    *selection;
+
+    gtk_rc_parse_string ( rc_string );
+
+    tv = g_object_new(gnc_tree_view_split_reg_get_type(), NULL);
+    g_object_set(tv, "name", "split_reg_tree", NULL);
+
+    s_model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(model));
+/*FIXME  should we  g_object_unref(G_OBJECT(model)); */
+    gnc_tree_view_set_model(GNC_TREE_VIEW(tv), s_model);
+    g_object_unref(G_OBJECT(s_model));
+
+    tv->priv->anchor = gnc_tree_model_split_reg_get_anchor(model);
+    tv->priv->reg_comm = xaccAccountGetCommodity(tv->priv->anchor);
+    tv->priv->has_rate = TRUE;  /*FIXME Not sure what this ????? */
+
+    gnc_tree_view_split_reg_set_cols(tv, col_list);
+
+    /* Set default visibilities */
+    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(tv), TRUE);
+
+    /* TreeView Grid lines */
+    if(gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "draw_horizontal_lines", NULL))
+    {
+        if(gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "draw_vertical_lines", NULL))
+            gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(tv), GTK_TREE_VIEW_GRID_LINES_BOTH);
+        else
+            gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(tv), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
+    }
+    else if(gnc_gconf_get_bool(GCONF_GENERAL_REGISTER, "draw_vertical_lines", NULL))
+            gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(tv), GTK_TREE_VIEW_GRID_LINES_VERTICAL);
+    else
+        gtk_tree_view_set_grid_lines( GTK_TREE_VIEW(tv), GTK_TREE_VIEW_GRID_LINES_NONE);
+
+
+    /* Expanders off */
+    /* gtk_tree_view_set_show_expanders (GTK_TREE_VIEW(view), FALSE); */
+
+    /* Tree Selection */
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv));
+
+    gtk_tree_selection_unselect_all( selection );
+
+/*
+
+    gnc_tree_view_configure_columns(view);
+
+    gtk_widget_show(GTK_WIDGET(view)); */
+    return tv;
+}
+
+
+
+/* Returns a value for display. */
+static gnc_numeric
+get_value_for(GncTreeViewSplitReg *tv, Transaction *trans,
+              Split *split, gboolean is_blank)
+{
+    gnc_commodity *currency = xaccTransGetCurrency(trans);
+    gnc_numeric total;
+
+    total = xaccSplitGetValue(split);
+
+    if (is_blank && gnc_numeric_zero_p(total)) {
+        gnc_numeric rate;
+        total = gnc_numeric_neg(xaccTransGetImbalanceValue(trans));
+        if (!gnc_numeric_zero_p(total)) {
+
+            if (!xaccTransGetRateForCommodity(
+                    trans, tv->priv->reg_comm, NULL, &rate))
+                return gnc_numeric_zero();
+
+            total = gnc_numeric_mul(
+                total, rate,
+                gnc_commodity_get_fraction (currency),
+                GNC_HOW_RND_ROUND);
+        }
+    } else {
+        if (!gnc_numeric_zero_p(total) &&
+            gnc_numeric_check(total) == GNC_ERROR_OK) {
+
+            /* fixme: if needs conversion? */
+            gnc_commodity *commodity = tv->priv->reg_comm;
+/*FIXME  ??          if (commodity && !gnc_commodity_equiv(commodity, currency))
+                total = xaccSplitConvertAmount(split, commodity); */
+        }
+    }
+    return total;
+}
+
+
+
+static gnc_numeric
+get_rate_for(GncTreeViewSplitReg *tv, Transaction *trans,
+              Split *split, gboolean is_blank)
+{
+    gnc_numeric num;
+
+    num = get_value_for(tv, trans, split, is_blank);
+    num = gnc_numeric_div(
+        xaccSplitGetAmount(split), num,
+        GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
+    return num;
+}
+
+
+
+/* Returns the other Split based on the current Account */
+static Split *
+get_other_split(GncTreeViewSplitReg *tv, Transaction *trans)
+{
+    int i;
+    Split *split = NULL;
+    Account *anchor = tv->priv->anchor;
+
+    for (i = 0; (split = xaccTransGetSplit(trans, i)); i++) {
+        if (anchor == xaccSplitGetAccount(split))
+            return xaccSplitGetOtherSplit(split);
+    }
+    return NULL;
+}
+
+
+
+/* Returns a Split that matches the current Account */
+static Split *
+get_this_split(GncTreeViewSplitReg *tv, Transaction *trans)
+{
+    int i;
+    Split *split = NULL;
+    Account *anchor = tv->priv->anchor;
+
+    for (i = 0; (split = xaccTransGetSplit(trans, i)); i++) {
+        if (anchor == xaccSplitGetAccount(split))
+            return split;
+    }
+    return NULL;
+}
+
+
+
+static gboolean
+get_model_iter_from_selection(GncTreeViewSplitReg *tv,
+                              GtkTreeSelection *sel, GtkTreeIter *iter)
+{
+    GtkTreeModel *s_model;
+    GtkTreeIter s_iter;
+
+    if (gtk_tree_selection_get_selected(sel, &s_model, &s_iter)) {
+        gtk_tree_model_sort_convert_iter_to_child_iter(
+            GTK_TREE_MODEL_SORT(s_model), iter, &s_iter);
+        return TRUE;
+    }
+    return FALSE;
+
+}
+
+
+
+/* Instead of setting a different cellDataFunc for each column, we just
+   collect everything here and use this one func. */
+static void
+cdf(GtkTreeViewColumn *col, GtkCellRenderer *cell, GtkTreeModel *s_model,
+    GtkTreeIter *s_iter, gpointer data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(data);
+    GncTreeModelSplitReg *model;
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    ViewCol viewcol;
+    gboolean is_split, is_blank, is_trow1, is_trow2;
+    gboolean editable, expanded;
+
+    gchar *cell_color;
+    gint depth, *indices;
+
+    Account *anchor = tv->priv->anchor;
+    Split *split;
+    Transaction *trans;
+
+    gnc_numeric num;
+    const gchar *s = "";
+
+    ENTER("");
+
+    model = get_split_reg_model_from_view(tv);
+
+    gtk_tree_model_sort_convert_iter_to_child_iter(GTK_TREE_MODEL_SORT(s_model), &iter, s_iter);
+
+    viewcol = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "view_column"));
+
+    g_return_if_fail(gnc_tree_model_split_reg_get_split_and_trans(
+                         GNC_TREE_MODEL_SPLIT_REG(model), &iter,
+                          &is_trow1, &is_trow2, &is_split, &is_blank,
+                          &split, &trans));
+
+    depth = gtk_tree_path_get_depth (gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter));
+
+/* g_print(" cdf depth is %d\n", depth); */
+
+    /* This expands to split from top level and you cannot collapse split, may be needed
+    if (depth == 2)
+        gtk_tree_view_expand_to_path (GTK_TREE_VIEW(tv), gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter));
+    */
+
+    /* This gives me double lines, you can not collapse them */
+    if ((tv->priv->double_line) && (depth == 1))
+        gtk_tree_view_expand_to_path (GTK_TREE_VIEW(tv), gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter));
+
+    indices = gtk_tree_path_get_indices (gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter));
+
+/* g_print(" cdf path is %s\n", gtk_tree_path_to_string (gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter))); */
+
+    switch (viewcol) {
+    case COL_DATE:
+        /* Column is DATE */
+        if (is_split)
+            g_object_set(cell, "cell-background", "white", (gchar*)NULL);
+
+        if (is_trow1) {
+            Timespec ts = {0,0};
+            xaccTransGetDatePostedTS (trans, &ts);
+            //If the time returned by xaccTransGetDatePostedTS is 0 then assume it
+            //is a new transaction and set the time to current time to show current
+            //date on new transactions
+            if (ts.tv_sec == 0)
+            {
+                ts.tv_sec = time(NULL);
+                //xaccTransSetDatePostedSecs(trans, ts.tv_sec);
+            }//if
+            s = gnc_print_date(ts);
+            editable = TRUE;
+        }
+        else {
+            s = "";
+            editable = FALSE;
+        }
+        /* This will remove the calander buttons if FALSE, preference may be ? */
+        g_object_set(cell, "use_buttons", TRUE, NULL ); 
+        g_object_set(cell, "text", s, "editable", editable, NULL);
+        break;
+
+    case COL_NUMACT:
+        /* Column is NUM/ACT */
+        /* Override default alignment */
+        g_object_set( cell, "xalign", 0.0, NULL );
+
+        if (is_trow1)
+           s = xaccTransGetNum(trans);
+        else if (is_trow2)
+           s = xaccSplitGetAction(get_this_split(tv, trans));
+        else if (is_split)
+           s = xaccSplitGetAction(split);
+
+        g_object_set(cell, "text", s, "editable", TRUE, NULL);
+        break;
+
+    case COL_DESCNOTES:
+        /* Column is DESCRIPTION / NOTES */
+        /* Override default alignment */
+        g_object_set( cell, "xalign", 0.0, NULL );
+        if (is_trow1)
+            s =  xaccTransGetDescription (trans);
+        else if (is_trow2)
+            s =  xaccTransGetNotes(trans);
+        else if (is_split)
+            s = xaccSplitGetMemo(split);
+
+        g_object_set(cell, "text", s, NULL);
+        break;
+
+    case COL_TRANSVOID:
+        /* Column is TRANSFER / VOID */
+
+        /* Not sure if this will stay here, this sets the combo column
+           0 for short account names, 1 for long */
+        if (tv->priv->acct_short_names)
+            g_object_set(G_OBJECT(cell), "text-column", 0, NULL );
+        else
+            g_object_set(G_OBJECT(cell), "text-column", 1, NULL );
+
+        if (is_trow1) {
+            gint count = xaccTransCountSplits(trans);
+            path = gtk_tree_model_get_path(s_model, s_iter);
+            gtk_tree_path_down (path); /* Move the path down to trow2 */
+            expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path);
+            if (count == 0 || expanded) {
+                s = ""; /* blank-out if splits are visible */
+            } else if (2 == count) {
+                Account *acct;
+                Split *osplit;
+                osplit = get_other_split(tv, trans);
+                acct = xaccSplitGetAccount(osplit);
+                if(tv->priv->acct_short_names)
+                    s = xaccAccountGetName(acct);
+                else
+                    s = gnc_account_get_full_name(acct);
+            } else {
+                s = SPLIT_TRANS_STR;
+            }
+            editable = anchor && !expanded && ((2 == count) || (0 == count));
+            gtk_tree_path_free(path);
+        }
+        if (is_trow2) {
+            s = xaccTransGetVoidReason(trans); /* This is the Void Reason */
+            editable = FALSE;
+        }
+        if (is_split) {
+            Account *acct = xaccSplitGetAccount(split);
+            if(anchor == acct)
+                editable = FALSE;
+            else
+                editable = TRUE;
+            if(tv->priv->acct_short_names)
+                s = xaccAccountGetName(acct);
+            else
+                s = gnc_account_get_full_name(acct);
+        }
+        g_object_set(cell, "text", s, "editable", editable, NULL);
+        break;
+
+    case COL_RECN:
+        /* Column is RECN */
+        if (is_trow1) {
+            static char ss[2];
+            char rec = xaccSplitGetReconcile(get_this_split(tv, trans));
+            if (rec == VREC || rec == FREC || rec == YREC)
+                editable = FALSE;
+            else
+                editable = TRUE;
+
+            ss[0] = rec;
+            ss[1] = '\0';
+            g_object_set(cell, "text", ss, "editable", editable, NULL);
+
+        } else {
+            s = "";
+            editable = FALSE;
+            g_object_set(cell, "text", s, "editable", editable, NULL);
+        }
+
+        if (is_split) {
+            static char ss[2];
+            char rec = xaccSplitGetReconcile(split);
+            if (rec == VREC || rec == FREC || rec == YREC)
+                editable = FALSE;
+            else
+                editable = TRUE;
+
+            ss[0] = rec;
+            ss[1] = '\0';
+            g_object_set(cell, "text", ss, "editable", editable, NULL);
+        }
+
+        break;
+
+    case COL_TYPE:
+        /* Column is TYPE */
+        if (is_trow1) {
+            static char ss[2];
+            char type = xaccTransGetTxnType(trans);
+            if (type == TXN_TYPE_NONE)
+                type = '?';
+
+            ss[0] = type;
+            ss[1] = '\0';
+            g_object_set(cell, "text", ss, NULL);
+        }
+        else
+        {
+            s = "";
+            g_object_set(cell, "text", s, NULL);
+        }
+        break;
+
+    case COL_AMOUNT:
+        /* Column is AMOUNT */
+       if (is_split) {
+            gnc_numeric amt = xaccSplitGetAmount(split);
+            s = xaccPrintAmount(amt, gnc_account_print_info( xaccSplitGetAccount(split), TRUE));
+            editable = TRUE;
+        } else {
+            s = "";
+            editable = FALSE;
+        }
+        g_object_set(cell, "text", s, "editable", editable, NULL);
+        break;
+
+    case COL_VALUE:
+        /* Column is VALUE */
+        if (is_split) {
+            gnc_numeric amt = xaccSplitGetValue(split);
+            s = xaccPrintAmount(amt, gnc_commodity_print_info( xaccTransGetCurrency(trans), TRUE));
+        } else {
+            s = "";
+            editable = FALSE;
+        }
+        g_object_set(cell, "text", s, NULL);
+        break;
+
+    case COL_RATE:
+        /* Column is RATE */
+        if ((is_trow1)||(is_trow2)) {
+            s = "";
+            editable = FALSE;
+        } else {
+            gnc_commodity *split_com = xaccAccountGetCommodity( xaccSplitGetAccount(split));
+            num = get_rate_for(tv, trans, split, is_blank);
+            if (gnc_numeric_check(num) == GNC_ERROR_OK) {
+                s = xaccPrintAmount(num, gnc_split_amount_print_info(split, FALSE));
+                editable = !gnc_numeric_zero_p(num) &&
+                    !gnc_commodity_equiv(split_com, tv->priv->reg_comm);
+            } else {
+                s = "";
+                editable = FALSE;
+            }
+        }
+        g_object_set(cell, "text", s, "editable", editable, NULL);
+        break;
+
+    case COL_PRICE:
+        /* Column is PRICE */
+        if ((is_trow1)||(is_trow2)) {
+            s = "";
+            editable = FALSE;
+        } else {
+            num = xaccSplitGetSharePrice(split);
+
+            if (gnc_numeric_check(num) == GNC_ERROR_OK) {
+                s = xaccPrintAmount(num, gnc_split_amount_print_info(split, FALSE));
+                editable = FALSE;
+            } else {
+                s = "";
+                editable = FALSE;
+            }
+        }
+        g_object_set(cell, "text", s, "editable", editable, NULL);
+        break;
+
+    case COL_DEBIT:
+    case COL_CREDIT:
+        /* Column is CREDIT and DEBIT */
+        if (is_split) {
+            num = get_value_for(tv, trans, split, is_blank);
+            editable = TRUE;
+        } else if (is_trow1) {
+            //comm = xaccTransGetCurrency(trans);
+            if (anchor) {
+                gint count = xaccTransCountSplits(trans);
+                path = gtk_tree_model_get_path(s_model, s_iter);
+                expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(tv), path);
+                editable = !expanded && ((2 == count) || (0 == count));
+                num = xaccTransGetAccountAmount(trans, anchor);
+            } else {
+                editable = FALSE;
+                num = gnc_numeric_zero();
+                /* CHECKME: Should trans cred/debit fields in unanchored reg
+                   show imbalances? I don't think so. */
+            }
+        } else if (is_trow2) {
+            editable = FALSE;
+            num = gnc_numeric_zero();
+        }
+
+        if ((gnc_numeric_check(num) != GNC_ERROR_OK) || gnc_numeric_zero_p(num) ||
+            (gnc_numeric_negative_p(num) && viewcol == COL_CREDIT) ||
+            (gnc_numeric_positive_p(num) && viewcol == COL_DEBIT)) {
+            s = "";
+        } else {
+            s = xaccPrintAmount(gnc_numeric_abs(num),
+                                gnc_account_print_info(anchor, TRUE)); //FIXME: TRUE just for debugging maybe
+        }
+        g_object_set(cell, "text", s, "editable", editable, NULL);
+        break;
+
+    case COL_BALANCE:
+        /* Column is BALANCE */
+        if (is_trow1 && anchor) {
+            num = xaccTransGetAccountBalance(trans, anchor);
+            if (gnc_reverse_balance(anchor))
+                num = gnc_numeric_neg(num);
+            s = xaccPrintAmount(num, gnc_account_print_info(anchor, TRUE));
+            if (gnc_numeric_negative_p(num)
+                && gnc_gconf_get_bool(GCONF_GENERAL, KEY_NEGATIVE_IN_RED, NULL))
+                g_object_set(cell, "foreground", "red", (gchar*)NULL);
+            else
+                g_object_set(cell, "foreground", NULL, (gchar*)NULL);
+        } else {
+            s = "";
+        }
+        g_object_set(cell, "text", s, NULL);
+        break;
+
+    default:
+        break;
+    }
+    LEAVE("");
+}
+
+
+
+/*####################################################################
+          vvvvv    edit function call backs      vvvvvv
+#####################################################################*/
+static void
+start_edit(GtkCellRenderer *cr, GtkCellEditable *editable,
+           const gchar *path_string, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+g_print("start_edit\n");
+/*FIXME Not sure if this is required, leave for now ? */
+    get_editable_start_editing_cb(cr, editable, path_string, user_data);
+/*    g_signal_connect(G_OBJECT(editable), "editing-done", (GCallback) editing_done_cb, tv); */
+    tv->priv->acct_edit_path = g_strdup(path_string);
+
+    return;
+}
+
+
+/* means: open trans for editing, unless we're editing a Split (split
+   != NULL) AND split doesn't belong to the trans (because it is the
+   blank split) */
+static void
+begin_edit(GncTreeViewSplitReg *tv, Split *split, Transaction *trans)
+{
+g_print("begin edit\n");
+    /* explain me -- this may need changing */
+    if (split && trans != xaccSplitGetParent(split))
+        return;
+    if (trans != tv->priv->dirty_trans) {
+        xaccTransBeginEdit(trans);
+        tv->priv->dirty_trans = trans;
+        if (!xaccTransGetCurrency(trans)) {
+            xaccTransSetCurrency(trans, tv->priv->reg_comm);
+        }
+    }
+}
+
+
+
+static void
+remove_edit_date(GtkCellEditable *ce, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+    GncPopupEntry *popup_entry;
+    const gchar *new_string; 
+    const gchar *current_string;
+
+    //These strings are used to determine if cell data was altered so
+    //that keynav works better
+g_print("remove edit date\n");
+
+    popup_entry = GNC_POPUP_ENTRY(g_object_get_data( G_OBJECT(tv->priv->temp_cr), "cell-editable"));
+
+    new_string = g_strdup(gtk_entry_get_text(GTK_ENTRY(popup_entry->entry)));
+g_print("New String is '%s'\n", new_string);	
+
+    current_string = g_object_get_data(G_OBJECT( tv->priv->temp_cr), "current-string");
+g_print("Current String is '%s'\n\n", current_string);
+
+    //If editing wasn't canceled and strings don't match then
+    //cell data was edited
+    if (!g_object_get_data(G_OBJECT(tv->priv->temp_cr), "edit-canceled") 
+             && g_ascii_strcasecmp(new_string, current_string))
+    {
+        g_object_set_data(G_OBJECT(tv), "data-edited", (gpointer)TRUE);
+    }
+
+    g_object_set_data(G_OBJECT(tv->priv->temp_cr), "cell-editable", NULL);
+    tv->priv->temp_cr = NULL;
+    g_free(tv->priv->acct_edit_path);
+    tv->priv->acct_edit_path = NULL;
+}
+
+
+
+static void
+remove_edit_combo(GtkCellEditable *ce, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+    GtkEntry *entry; 
+    const gchar *new_string; 
+    const gchar *current_string;
+
+    //These strings are used to determine if cell data was altered so
+    //that keynav works better
+g_print("remove edit combo\n");
+
+    entry = GTK_ENTRY (gtk_bin_get_child(GTK_BIN ( g_object_get_data( G_OBJECT(tv->priv->temp_cr), "cell-editable"))));
+
+    new_string = gtk_entry_get_text(GTK_ENTRY(entry));
+g_print("New String is '%s'\n", new_string);	
+
+    current_string = g_object_get_data(G_OBJECT( tv->priv->temp_cr), "current-string");
+g_print("Current String is '%s'\n\n", current_string);
+
+    //If editing wasn't canceled and strings don't match then
+    //cell data was edited
+    if (!g_object_get_data(G_OBJECT(tv->priv->temp_cr), "edit-canceled") 
+             && g_ascii_strcasecmp(new_string, current_string))
+    {
+        g_object_set_data(G_OBJECT(tv), "data-edited", (gpointer)TRUE);
+    }
+
+    g_object_set_data(G_OBJECT(tv->priv->temp_cr), "cell-editable", NULL);
+    tv->priv->temp_cr = NULL;
+    g_free(tv->priv->acct_edit_path);
+    tv->priv->acct_edit_path = NULL;
+}
+
+
+
+static void
+remove_edit_completion(GtkCellEditable *ce, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+    const gchar *new_string; 
+    const gchar *current_string; 
+
+g_print("remove edit completion\n");
+
+    //These strings are used to determine if cell data was altered so
+    //that keynav works better
+    new_string = gtk_entry_get_text(GTK_ENTRY(g_object_get_data( G_OBJECT(tv->priv->temp_cr), "cell-editable")));
+g_print("New String is '%s'\n", new_string);
+
+    current_string = g_object_get_data(G_OBJECT( tv->priv->temp_cr), "current-string");
+g_print("Current String is '%s'\n\n", current_string);
+
+    //If editing wasn't canceled and strings don't match then
+    //cell data was edited
+    if (!g_object_get_data(G_OBJECT(tv->priv->temp_cr), "edit-canceled") 
+             && g_ascii_strcasecmp(new_string, current_string))
+    {
+        g_object_set_data(G_OBJECT(tv), "data-edited", (gpointer)TRUE);
+    }
+
+    g_object_set_data(G_OBJECT(tv->priv->temp_cr), "cell-editable", NULL);
+    tv->priv->temp_cr = NULL;
+    g_free(tv->priv->acct_edit_path);
+    tv->priv->acct_edit_path = NULL;
+}
+
+
+
+/* Explain: GtkEntry has a cursor that blinks upon
+   g_timeout_dispatch().  It complains if it blinks after the GtkEntry
+   loses focus.  So, we can't pop up any dialogs while the blinking
+   cursor is around.  The solution is to force the editing to be
+   finished before raising the dialog.  That finalizes the
+   gtkcelleditable. */
+static void
+finish_edit(GtkTreeViewColumn *col)
+{
+    GtkCellRenderer *cr;
+    GtkCellEditable *ce;
+g_print("finish_edit\n");
+/*FIXME Not used yet, leave for now */
+    if (!col) return;
+    cr = gnc_tree_view_column_get_renderer(col);
+    if ((ce = GTK_CELL_EDITABLE(g_object_get_data(G_OBJECT(cr), "cell-editable")))) {
+        gtk_cell_editable_editing_done(ce);
+    }
+}
+
+
+
+/*####################################################################
+          ^^^^^    edit function call backs      ^^^^^
+          vvvvvv   gtv function call backs       vvvvv
+#####################################################################*/
+static void
+gtv_split_reg_motion_cb(GtkTreeSelection *sel, gpointer data)
+{
+
+    GtkTreeIter iter;
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(data);
+    GncTreeModelSplitReg *model; 
+    Split *split = NULL;
+    Transaction *trans = NULL;
+    gboolean is_trow1, is_trow2, is_split, is_blank;
+    GtkTreeViewColumn *numact, *descnotes, *transvoid;
+    gint depth;
+    const gchar *path_string;
+
+    model = get_split_reg_model_from_view(tv);
+
+g_print("gtv_split_reg_motion_cb\n\n");
+
+    numact = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), 1);
+    descnotes = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), 2);
+    transvoid = gtk_tree_view_get_column(GTK_TREE_VIEW(tv), 3);
+
+    if (get_model_iter_from_selection(tv, sel, &iter))
+    {
+        gnc_tree_model_split_reg_get_split_and_trans (
+            GNC_TREE_MODEL_SPLIT_REG(model), &iter, &is_trow1, &is_trow2, &is_split, &is_blank, &split, &trans);
+
+        path_string = gtk_tree_path_to_string (gtk_tree_model_get_path (GTK_TREE_MODEL(model), &iter));
+
+g_print("Path is '%s'\n", path_string);
+
+       /* Use depth to determine if it is a split or parent transaction */
+       depth = gtk_tree_path_get_depth(gtk_tree_path_new_from_string(path_string));
+
+       if (depth == 1)
+       {
+           gtk_tree_view_column_set_title(numact, _("Number"));
+           gtk_tree_view_column_set_title(descnotes, _("Description"));
+           gtk_tree_view_column_set_title(transvoid, _("Accounts"));
+       }
+       else if (depth == 2)
+       {
+           gtk_tree_view_column_set_title(numact, _("Action"));
+           gtk_tree_view_column_set_title(descnotes, _("Notes"));
+           gtk_tree_view_column_set_title(transvoid, _("Void"));
+       }     
+       else if (depth == 3)
+       {
+           gtk_tree_view_column_set_title(numact, _("Action"));
+           gtk_tree_view_column_set_title(descnotes, _("Memo"));
+           gtk_tree_view_column_set_title(transvoid, _("Accounts"));
+       }
+    }
+    else
+    {
+        /* We end up here if tree collapse and no row selected */
+        gtk_tree_view_column_set_title(numact, _("Num / Act"));
+        gtk_tree_view_column_set_title(descnotes, _("Description / Notes / Memo"));
+        gtk_tree_view_column_set_title(transvoid, _("Transfer / Void"));
+    }
+}
+
+
+
+/* Connected to "edited" from cellrenderer. For reference, see
+   split-register-model-save.c */
+static void
+gtv_split_reg_edited_cb(GtkCellRendererText *cell, const gchar *path_string,
+               const gchar *new_text, gpointer data)
+{
+    GtkTreeIter iter;
+    GtkTreeIter copy_iter;
+    GtkEntryCompletion *completion;
+    Split *split;
+    Transaction *trans;
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(data);
+    ViewCol viewcol;
+    gboolean is_trow1, is_trow2, is_split, is_blank;
+    GncTreeModelSplitReg *model;
+    char *error_loc = NULL;
+    Account *anchor = tv->priv->anchor;
+
+g_print("gtv_split_reg_edited_cb\n\n");
+
+/*    g_return_if_fail(get_model_iter_from_view_string(tv, path_string, &iter)); */
+
+    viewcol = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell), "view_column"));
+
+    model = get_split_reg_model_from_view(tv);
+    g_return_if_fail(model);
+
+    gnc_tree_model_split_reg_get_split_and_trans (
+        model, &iter, &is_trow1, &is_trow2, &is_split, &is_blank, &split, &trans);
+
+g_print("New text is '%s'\n", new_text);
+
+    switch (viewcol) {
+    case COL_DATE:
+        /* Column is DATE */
+/*FIXME        begin_edit(tv, split, trans); */
+        if (is_trow1)
+        {
+/* New_text would need to be converted to time_t */
+/*            xaccTransSetDatePostedSecs (trans, time); */
+
+        }
+        break;
+
+    case COL_NUMACT:
+        /* Column is NUM / ACT */
+/*FIXME        begin_edit(tv, split, trans); */
+
+        if (is_trow1)
+        {
+/*            xaccTransSetNum(trans, new_text); */
+
+        }
+        if (is_trow2)
+        {
+           /*FIXME Not sure if this will need to be changed */
+/*            xaccSplitSetAction(split, new_text); */
+
+        }
+
+        if (is_split)
+        {
+/*            xaccSplitSetAction(split, new_text); */
+
+        }
+        break;
+
+    case COL_DESCNOTES:
+        /* Column is DESCRIPTION / NOTES */
+/*FIXME        begin_edit(tv, split, trans); */
+        if (is_trow1)
+        {
+/*            xaccTransSetDescription(trans, new_text); */
+/*FIXME May need to add new entries to list **
+            gtk_list_store_append(GTK_LIST_STORE(g_object_get_data(G_OBJECT(tv), "desc_copy")), &copy_iter);
+            gtk_list_store_set(GTK_LIST_STORE(g_object_get_data(G_OBJECT(tv), "desc_copy")), &copy_iter, 0, new_text, -1);
+*/
+        }
+        if (is_trow2)
+        {
+/*            xaccTransSetNotes(trans, new_text); */
+/*FIXME May need to add new entries to list **
+            gtk_list_store_append(GTK_LIST_STORE(g_object_get_data(G_OBJECT(tv), "notes_copy")), &copy_iter);
+            gtk_list_store_set(GTK_LIST_STORE(g_object_get_data(G_OBJECT(tv), "notes_copy")), &copy_iter, 0, new_text, -1); 
+*/
+        }
+        if (is_split)
+        {
+/*            xaccSplitSetMemo(split, new_text); */
+/*FIXME May need to add new entries to list **
+            gtk_list_store_append(GTK_LIST_STORE(g_object_get_data(G_OBJECT(tv), "memo_copy")), &copy_iter);
+            gtk_list_store_set(GTK_LIST_STORE(g_object_get_data(G_OBJECT(tv), "memo_copy")), &copy_iter, 0, new_text, -1); 
+*/
+        }
+        break;
+
+    case COL_TRANSVOID:
+    case COL_RECN:
+    case COL_TYPE:
+    case COL_VALUE:
+    case COL_AMOUNT:
+    case COL_RATE:
+    case COL_PRICE:
+    case COL_DEBIT:
+    case COL_CREDIT:
+        break;
+
+    default:
+        //g_assert_not_reached();
+        break;
+    }
+}
+
+
+
+/* The main Start Editing Call back for the TEXT columns */
+static void
+get_editable_start_editing_cb(GtkCellRenderer *cr, GtkCellEditable *editable,
+                              const gchar *path_string, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+    GncTreeModelSplitReg *model;
+
+    GtkListStore *description_list;
+    GtkListStore *memo_list;
+    GtkListStore *notes_list;
+    GtkListStore *acct_list;
+
+    GtkEntryCompletion *completion = gtk_entry_completion_new();
+    gint depth;
+
+    ENTER(" ");
+g_print("get_editable_start_editing_cb\n\n");
+
+    model = get_split_reg_model_from_view(tv);
+
+    description_list = gnc_tree_model_split_reg_get_description_list(model);
+    notes_list = gnc_tree_model_split_reg_get_notes_list(model);
+    memo_list = gnc_tree_model_split_reg_get_memo_list(model);
+    acct_list = gnc_tree_model_split_reg_get_acct_list(model);
+
+g_print("editable Path string is '%s'\n", path_string);
+
+    //Use depth to determine if it is a split or transaction
+    depth = gtk_tree_path_get_depth(gtk_tree_path_new_from_string(path_string));
+
+g_print("editable Depth is %u\n", depth);
+
+    /* DATE COLUMN */
+    if (GNC_TREE_MODEL_SPLIT_REG_COL_DATE 
+        == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cr), "model_column")))
+    {
+        g_object_set_data(G_OBJECT(cr), "cell-editable", editable);
+        //Copy the string in the GtkEntry for later comparison
+        g_object_set_data(G_OBJECT(cr), "current-string", g_strdup(gtk_entry_get_text(GTK_ENTRY(GNC_POPUP_ENTRY(editable)->entry))));
+
+        g_signal_connect(G_OBJECT(editable), "remove-widget", (GCallback) remove_edit_date, tv);
+
+g_print("Current String is '%s'\n", g_strdup(gtk_entry_get_text(GTK_ENTRY(GNC_POPUP_ENTRY(editable)->entry))));
+
+    }
+
+    /* TRANSFER / VOID COLUMN */
+    if (GNC_TREE_MODEL_SPLIT_REG_COL_TRANSVOID 
+        == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cr), "model_column")))
+    {
+        GtkEntry *entry;
+
+        entry = GTK_ENTRY (gtk_bin_get_child(GTK_BIN (editable)));
+
+        gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+        gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (acct_list));
+
+        /* This sets which text column to use, 0 for short names, 1 for long */
+        if (tv->priv->acct_short_names)
+            gtk_entry_completion_set_text_column (completion, 0);
+        else
+            gtk_entry_completion_set_text_column (completion, 1);
+
+        gtk_entry_completion_set_popup_completion (completion, TRUE);
+        gtk_entry_completion_set_inline_selection (completion, TRUE);
+        gtk_entry_completion_set_popup_set_width (completion, FALSE);
+        gtk_entry_completion_set_minimum_key_length (completion, KEY_LENGTH);
+/*??        g_signal_connect(G_OBJECT(completion), "match-selected", (GCallback)gtv_split_reg_match_selected_cb, tv); */
+        g_object_unref (completion);
+
+        g_object_set_data(G_OBJECT(cr), "cell-editable", editable);
+        //Copy the string in the GtkEntry for later comparison
+        g_object_set_data(G_OBJECT(cr), "current-string", g_strdup(gtk_entry_get_text (entry)));
+
+        g_signal_connect(G_OBJECT(cr), "changed", (GCallback)gtv_split_reg_changed_cb, tv);
+        g_signal_connect(G_OBJECT(editable), "remove-widget", (GCallback) remove_edit_combo, tv);
+g_print("Current String is '%s'\n", g_strdup(gtk_entry_get_text(entry)));
+
+    }
+
+    /* NUMBER / ACTION COLUMN */
+    if (GNC_TREE_MODEL_SPLIT_REG_COL_NUMACT 
+        == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cr), "model_column")))
+    {
+        GtkEntry *entry;
+
+        if (depth == 1)
+            gnc_tree_model_split_reg_get_num_list(model);
+
+        else if (depth == 2)
+            gnc_tree_model_split_reg_get_action_list(model);
+
+        else if (depth == 3)
+            gnc_tree_model_split_reg_get_action_list(model);
+
+        entry = GTK_ENTRY (gtk_bin_get_child(GTK_BIN (editable)));
+
+        g_object_set_data(G_OBJECT(cr), "cell-editable", editable);
+        //Copy the string in the GtkEntry for later comparison
+        g_object_set_data(G_OBJECT(cr), "current-string", g_strdup(gtk_entry_get_text (entry)));
+
+/*??        g_signal_connect(G_OBJECT(cr), "changed", (GCallback)gtv_split_reg_changed_cb, tv); */
+        g_signal_connect(G_OBJECT(editable), "remove-widget", (GCallback) remove_edit_combo, tv);
+g_print("Current String is '%s'\n", g_strdup(gtk_entry_get_text(entry)));
+
+    }
+
+    /* DESCRIPTION / NOTES / MEMO COLUMN */
+    if (GNC_TREE_MODEL_SPLIT_REG_COL_DESCNOTES 
+        == GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cr), "model_column")))
+    {
+        //Data used for completion is set based on if editing split or not
+        if (depth == 1)
+        {
+            gtk_entry_set_completion (GTK_ENTRY (editable), completion);
+            gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (description_list));
+            gtk_entry_completion_set_text_column (completion, 0);
+        }
+        else if (depth == 2)
+        {
+            gtk_entry_set_completion (GTK_ENTRY (editable), completion);
+            gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (notes_list));
+            gtk_entry_completion_set_text_column (completion, 0);
+        }
+        else if (depth == 3)
+        {
+            gtk_entry_set_completion (GTK_ENTRY (editable), completion);
+            gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (memo_list));
+            gtk_entry_completion_set_text_column (completion, 0);
+        }
+
+        //To emit "match-selected" signal we need to have a list of matches to
+        //select from instead of using inline autocompletion
+        gtk_entry_completion_set_popup_completion (completion, TRUE);
+        gtk_entry_completion_set_inline_selection (completion, TRUE);
+        gtk_entry_completion_set_minimum_key_length (completion, KEY_LENGTH);
+/*??        g_signal_connect(G_OBJECT(completion), "match-selected", (GCallback)gtv_split_reg_match_selected_cb, tv); */
+
+        g_object_unref (completion);
+
+        g_object_set_data(G_OBJECT(cr), "cell-editable", editable);
+        //Copy the string in the GtkEntry for later comparison
+        g_object_set_data(G_OBJECT(cr), "current-string", g_strdup(gtk_entry_get_text(GTK_ENTRY(editable))));
+        g_signal_connect(G_OBJECT(editable), "remove-widget", (GCallback) remove_edit_completion, tv);
+g_print("Current String is '%s'\n", g_strdup(gtk_entry_get_text(GTK_ENTRY(editable))));
+
+    }
+
+    tv->priv->temp_cr = cr;
+    //Add edit-canceled property to cr so we can distinguish between
+    //cancelled and actual changes
+    g_object_set_data(G_OBJECT(cr), "edit-canceled", FALSE);
+
+    LEAVE(" ");
+}
+
+
+
+//Handle the "match-selected" signal
+static void
+gtv_split_reg_match_selected_cb(GtkEntryCompletion *widget, GtkTreeModel *model,
+                        GtkTreeIter *iter, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+
+    gboolean is_trow1, is_trow2, is_split, is_blank;
+
+g_print("gtv_split_reg_match_selected_cb\n\n");
+
+/* Not sure what I am going to put in here yet */
+
+}
+
+
+//Handle the "changed" signal
+static void
+gtv_split_reg_changed_cb(GtkCellRendererCombo *widget, gchar *path_string,
+                        GtkTreeIter *iter, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+
+    gboolean is_trow1, is_trow2, is_split, is_blank;
+
+g_print("gtv_split_reg_changed_cb\n\n");
+g_print("Path String is '%s'\n", path_string);
+
+/* Not sure what I am going to put in here yet */
+
+}
+
+
+//Handle the "editing-canceled" signal
+static void
+gtv_split_reg_editing_canceled_cb(GtkCellRenderer *cr, gpointer user_data)
+{
+    GncTreeViewSplitReg *tv = GNC_TREE_VIEW_SPLIT_REG(user_data);
+g_print("gtv_split_reg_editing_canceled_cb\n\n");
+
+    //Set edit-canceled property
+    g_object_set_data(G_OBJECT(cr), "edit-canceled", (gpointer)TRUE);	
+}
+
+/*####################################################################
+          ^^^^   gtv function call backs    ^^^^
+#####################################################################*/
+

Added: gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h	                        (rev 0)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -0,0 +1,69 @@
+/********************************************************************\
+ * gnc-tree-view-split-reg.c -- GtkTreeView implementation to       *
+ *                     display registers   in a GtkTreeView.        *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ * Copyright (C) 2006-2007 Chris Shoemaker <c.shoemaker at cox.net>    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+
+#ifndef __GNC_TREE_VIEW_SPLIT_REG_H
+#define __GNC_TREE_VIEW_SPLIT_REG_H
+
+#include <gtk/gtk.h>
+#include "gnc-tree-view.h"
+
+#include "gnc-tree-model-split-reg.h"
+#include "gnc-ui-util.h"
+
+G_BEGIN_DECLS
+
+#define GNC_TYPE_TREE_VIEW_SPLIT_REG            (gnc_tree_view_split_reg_get_type ())
+#define GNC_TREE_VIEW_SPLIT_REG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitReg))
+#define GNC_TREE_VIEW_SPLIT_REG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitRegClass))
+#define GNC_IS_TREE_VIEW_SPLIT_REG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_TREE_VIEW_SPLIT_REG))
+#define GNC_IS_TREE_VIEW_SPLIT_REG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_TREE_VIEW_SPLIT_REG))
+#define GNC_TREE_VIEW_SPLIT_REG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_TREE_VIEW_SPLIT_REG, GncTreeViewSplitRegClass))
+
+/* typedefs & structures */
+typedef struct GncTreeViewSplitRegPrivate GncTreeViewSplitRegPrivate;
+
+typedef struct
+{
+    GncTreeView gnc_tree_view;
+    GncTreeViewSplitRegPrivate *priv;
+    int stamp;
+
+} GncTreeViewSplitReg;
+
+typedef struct
+{
+    GncTreeViewClass gnc_tree_view;
+} GncTreeViewSplitRegClass;
+
+/* Standard g_object type */
+GType gnc_tree_view_split_reg_get_type(void);
+
+GncTreeViewSplitReg *gnc_tree_view_split_reg_new_with_model(GncTreeModelSplitReg *model);
+
+G_END_DECLS
+
+#endif /* __GNC_TREE_VIEW_SPLIT_REG_H */

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view.c	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view.c	2012-08-07 17:24:33 UTC (rev 22289)
@@ -43,6 +43,7 @@
 #include "gnc-gconf-utils.h"
 #include "gnc-gnome-utils.h"
 #include "gnc-gobject-utils.h"
+#include "gnc-cell-renderer-date.h"
 
 /* The column id refers to a specific column in the tree model.  It is
  * also attached to the side of the tree column to allow lookup of a
@@ -1987,7 +1988,74 @@
     return column;
 }
 
+
+
+/** This function adds a new date column to a GncTreeView base view.
+ *  It takes all the parameters necessary to hook a GtkTreeModel
+ *  column to a GtkTreeViewColumn.  If the tree has a gconf section
+ *  associated with it, this function also wires up the column so that
+ *  its visibility and width are remembered.
+ *
+ *  Parameters are defined in gnc-tree-view.h
+ */
 GtkTreeViewColumn *
+gnc_tree_view_add_date_column (GncTreeView *view,
+                                   const gchar *column_title,
+                                   const gchar *pref_name,
+                                   const gchar *stock_icon_name,
+                                   const gchar *sizing_text,
+                                   gint model_data_column,
+                                   gint model_visibility_column,
+                                   GtkTreeIterCompareFunc column_sort_fn)
+{
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
+  PangoLayout* layout;
+  int default_width, title_width;
+
+  g_return_val_if_fail (GNC_IS_TREE_VIEW(view), NULL);
+
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title (column, column_title);
+
+  /* Set up an icon renderer if requested */
+  if (stock_icon_name) {
+    renderer = gtk_cell_renderer_pixbuf_new ();
+    g_object_set (renderer, "stock-id", stock_icon_name, NULL);
+    gtk_tree_view_column_pack_start (column, renderer, FALSE);
+  }
+
+  /* Set up a text renderer and attributes */
+  renderer = gnc_cell_renderer_date_new(TRUE);
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+
+  /* Set renderer attributes controlled by the model */
+  if (model_data_column != GNC_TREE_VIEW_COLUMN_DATA_NONE)
+    gtk_tree_view_column_add_attribute (column, renderer,
+					"text", model_data_column);
+  if (model_visibility_column != GNC_TREE_VIEW_COLUMN_VISIBLE_ALWAYS)
+    gtk_tree_view_column_add_attribute (column, renderer,
+					"visible", model_visibility_column);
+
+  /* Default size is the larger of the column title and the sizing text */
+  layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), column_title);
+  pango_layout_get_pixel_size(layout, &title_width, NULL);
+  g_object_unref(layout);
+  layout = gtk_widget_create_pango_layout (GTK_WIDGET(view), sizing_text);
+  pango_layout_get_pixel_size(layout, &default_width, NULL);
+  g_object_unref(layout);
+  default_width = MAX(default_width, title_width);
+  if (default_width)
+    default_width += 10; /* padding on either side */
+  gnc_tree_view_column_properties (view, column, pref_name, model_data_column,
+				   default_width, TRUE, column_sort_fn);
+
+  gnc_tree_view_append_column (view, column);
+  return column;
+}
+
+
+GtkTreeViewColumn *
 gnc_tree_view_add_combo_column (GncTreeView *view,
                                 const gchar *column_title,
                                 const gchar *pref_name,

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view.h	2012-08-07 09:48:58 UTC (rev 22288)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view.h	2012-08-07 17:24:33 UTC (rev 22289)
@@ -33,6 +33,7 @@
 #define __GNC_TREE_VIEW_H
 
 #include <gtk/gtk.h>
+#include "gnc-cell-renderer-date.h"
 
 G_BEGIN_DECLS
 
@@ -208,6 +209,22 @@
                                 gint combo_model_text_column,
                                 GtkTreeIterCompareFunc column_sort_fn);
 
+
+/** This function adds a new date column to a GncTreeView base
+ *  view.  The parameters it takes in common with
+ *  gnc_tree_view_add_text_column() behave the same as there.
+ */
+GtkTreeViewColumn *
+gnc_tree_view_add_date_column (GncTreeView *view,
+                                   const gchar *column_title,
+                                   const gchar *pref_name,
+                                   const gchar *stock_icon_name,
+                                   const gchar *sizing_text,
+                                   gint model_data_column,
+                                   gint model_visibility_column,
+                                   GtkTreeIterCompareFunc column_sort_fn);
+
+
 /** This function adds a new numeric column to a GncTreeView base
  *  view.  It takes all the parameters necessary to hook a
  *  GtkTreeModel column to a GtkTreeViewColumn.  If the tree has a



More information about the gnucash-changes mailing list