r22883 - gnucash/trunk/src - Register rewrite Update, fixes for duplicate and reversing transaction. This update fixes duplicate transaction and reversing transaction. Also included is a minor change to the model, added the test for unbalanced transaction along with some other dialogs. Tab key navigation has been revised but still further work. Account key seperator works along with new account creation. Author: Robert Fewell

John Ralls jralls at code.gnucash.org
Sun Apr 7 18:14:09 EDT 2013


Author: jralls
Date: 2013-04-07 18:14:09 -0400 (Sun, 07 Apr 2013)
New Revision: 22883
Trac: http://svn.gnucash.org/trac/changeset/22883

Modified:
   gnucash/trunk/src/gnome-utils/dialog-dup-trans.c
   gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c
   gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h
   gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c
   gnucash/trunk/src/gnome/gnc-plugin-page-register2.c
Log:
Register rewrite Update, fixes for duplicate and reversing transaction. This update fixes duplicate transaction and reversing transaction. Also included is a minor change to the model, added the test for unbalanced transaction along with some other dialogs. Tab key navigation has been revised but still further work. Account key seperator works along with new account creation. Author: Robert Fewell

Modified: gnucash/trunk/src/gnome/gnc-plugin-page-register2.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-register2.c	2013-04-07 20:54:35 UTC (rev 22882)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-register2.c	2013-04-07 22:14:09 UTC (rev 22883)
@@ -3130,8 +3130,12 @@
     split = gnc_tree_view_split_reg_get_current_split (view);
     if (split == NULL)
     {
-        LEAVE("split is NULL");
-        return;
+        split = gnc_tree_control_split_reg_get_current_trans_split (view);
+        if (split == NULL)
+        {
+            LEAVE("split is NULL");
+            return;
+        }
     }
 
     if (!gnc_tree_view_split_reg_trans_expanded (view, NULL))

Modified: gnucash/trunk/src/gnome-utils/dialog-dup-trans.c
===================================================================
--- gnucash/trunk/src/gnome-utils/dialog-dup-trans.c	2013-04-07 20:54:35 UTC (rev 22882)
+++ gnucash/trunk/src/gnome-utils/dialog-dup-trans.c	2013-04-07 22:14:09 UTC (rev 22883)
@@ -132,7 +132,9 @@
     }
     else
     {
-        dt_dialog->date_edit = NULL;
+        GtkWidget *date_edit;
+        date_edit = gnc_date_edit_new (date, FALSE, FALSE);
+        dt_dialog->date_edit = date_edit;
     }
 
     dt_dialog->duplicate_title_label = GTK_WIDGET(gtk_builder_get_object (builder, "duplicate_title_label"));
@@ -246,7 +248,7 @@
         if (date_p)
             *date_p = gnc_date_edit_get_date (GNC_DATE_EDIT (dt_dialog->date_edit));
         if (gdate_p)
-            gnc_date_edit_get_gdate(GNC_DATE_EDIT (dt_dialog->date_edit), gdate_p);
+            gnc_date_edit_get_gdate (GNC_DATE_EDIT (dt_dialog->date_edit), gdate_p);
         if (out_num)
             *out_num = g_strdup (gtk_entry_get_text (GTK_ENTRY (dt_dialog->num_edit)));
         if (tnum)

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c	2013-04-07 20:54:35 UTC (rev 22882)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.c	2013-04-07 22:14:09 UTC (rev 22883)
@@ -41,9 +41,12 @@
 #include "dialog-utils.h"
 #include "guile-util.h"
 #include "dialog-dup-trans.h"
+#include "dialog-account.h"
 
 #include "Transaction.h"
 #include "engine-helpers.h"
+#include "gnc-event.h"
+#include "Scrub.h"
 
 /** Static Globals *******************************************************/
 static QofLogModule log_module = GNC_MOD_LEDGER;
@@ -88,25 +91,29 @@
                                   gnc_get_current_book ());
 }
 
+/*****************************************************************************/
+/*****************************************************************************/
 
-/*************************************************************************/
-
-
-/* Read only dialoue */
+/* Read only dialog */
 static gboolean
-gtc_is_trans_readonly_and_warn (const Transaction *trans)
+gtc_is_trans_readonly_and_warn (GncTreeViewSplitReg *view, Transaction *trans)
 {
+    GncTreeModelSplitReg *model;
+    GtkWidget *window;
     GtkWidget *dialog;
     const gchar *reason;
     const gchar *title = _("Cannot modify or delete this transaction.");
-    const gchar *message =
+    const gchar *message_reason =
         _("This transaction is marked read-only with the comment: '%s'");
 
     if (!trans) return FALSE;
 
+    window = gnc_tree_view_split_reg_get_parent (view);
+    model = gnc_tree_view_split_reg_get_model_from_view (view);
+
     if (xaccTransIsReadonlyByPostedDate (trans))
     {
-        dialog = gtk_message_dialog_new (NULL,
+        dialog = gtk_message_dialog_new (GTK_WINDOW (window),
                                         0,
                                         GTK_MESSAGE_ERROR,
                                         GTK_BUTTONS_OK,
@@ -122,21 +129,257 @@
     reason = xaccTransGetReadOnly (trans);
     if (reason)
     {
-        dialog = gtk_message_dialog_new (NULL,
+        dialog = gtk_message_dialog_new (GTK_WINDOW (window),
                                         0,
                                         GTK_MESSAGE_ERROR,
                                         GTK_BUTTONS_OK,
                                         "%s", title);
         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                message, reason);
+                message_reason, reason);
         gtk_dialog_run (GTK_DIALOG (dialog));
         gtk_widget_destroy (dialog);
         return TRUE;
     }
+
+    if (gnc_tree_model_split_reg_get_read_only (model, trans))
+    {
+        dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                        0,
+                                        GTK_MESSAGE_ERROR,
+                                        GTK_BUTTONS_OK,
+                                        "%s", title);
+        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                "%s", _("You can not change this transaction, the Book or Register is set to Read Only."));
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+        return TRUE;
+    }
     return FALSE;
 }
 
 
+/* Transaction is being edited dialog */
+static gboolean
+gtc_trans_open_and_warn (GncTreeViewSplitReg *view, Transaction *trans)
+{
+    Transaction *dirty_trans;
+    GtkWidget *window;
+    GtkWidget *dialog;
+    gint response;
+    const char *title = _("Save Transaction before proceding?");
+    const char *message =
+            _("The current transaction has been changed. Would you like to "
+              "record the changes before proceding, or cancel?");
+
+    window = gnc_tree_view_split_reg_get_parent (view);
+    dirty_trans = gnc_tree_view_split_reg_get_dirty_trans (view);
+
+    if (trans == dirty_trans)
+    {
+        dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                        GTK_DIALOG_DESTROY_WITH_PARENT,
+                                        GTK_MESSAGE_QUESTION,
+                                        GTK_BUTTONS_CANCEL,
+                                        "%s", title);
+        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                "%s", message);
+        gtk_dialog_add_button (GTK_DIALOG (dialog),
+                              _("_Record"), GTK_RESPONSE_ACCEPT);
+        response = gnc_dialog_run (GTK_DIALOG (dialog), "transaction_being_edited");
+        gtk_widget_destroy (dialog);
+
+        if (response != GTK_RESPONSE_ACCEPT)
+            return TRUE;
+
+        xaccTransCommitEdit (trans);
+        gnc_tree_view_split_reg_set_dirty_trans (view, NULL);
+
+        return FALSE;
+    }
+    else
+        return FALSE;
+}
+
+
+static gboolean
+gtc_trans_test_for_edit (GncTreeViewSplitReg *view, Transaction *trans)
+{
+    GtkWidget *window;
+    Transaction *dirty_trans;
+
+    /* Make sure we have stopped editing */
+    gnc_tree_view_split_reg_finish_edit (view);
+
+    window = gnc_tree_view_split_reg_get_parent (view);
+
+    /* Get dirty_trans */
+    dirty_trans = gnc_tree_view_split_reg_get_dirty_trans (view);
+
+    /* We are being edited in a different register */
+    if (xaccTransIsOpen (trans) && (dirty_trans != trans))
+    {
+        gnc_error_dialog (window, "%s",
+                         _("This transaction is being edited in a different register."));
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+
+
+gboolean
+gnc_tree_control_split_reg_balance_trans (GncTreeViewSplitReg *view, Transaction *trans)
+{
+    GncTreeModelSplitReg *model;
+    GtkWidget *window;
+    int choice;
+    int default_value;
+    Account *default_account;
+    Account *other_account;
+    Account *root;
+    GList *radio_list = NULL;
+    const char *title   = _("Rebalance Transaction");
+    const char *message = _("The current transaction is not balanced.");
+    Split *split;
+    Split *other_split;
+    gboolean two_accounts;
+    gboolean multi_currency;
+
+
+    if (xaccTransIsBalanced (trans))
+        return FALSE;
+
+    window = gnc_tree_view_split_reg_get_parent (view);
+    model = gnc_tree_view_split_reg_get_model_from_view (view);
+
+//FIXME ## Trading ## Copied from split-register-control, needs testing
+
+    if (xaccTransUseTradingAccounts (trans))
+    {
+        MonetaryList *imbal_list;
+        gnc_monetary *imbal_mon;
+        imbal_list = xaccTransGetImbalance (trans);
+
+        /* See if the imbalance is only in the transaction's currency */
+        if (!imbal_list)
+            /* Value imbalance, but not commodity imbalance.  This shouldn't
+               be something that scrubbing can cause to happen.  Perhaps someone
+               entered invalid splits.  */
+            multi_currency = TRUE;
+        else
+        {
+            imbal_mon = imbal_list->data;
+            if (!imbal_list->next &&
+                    gnc_commodity_equiv(gnc_monetary_commodity(*imbal_mon),
+                                        xaccTransGetCurrency(trans)))
+                multi_currency = FALSE;
+            else
+                multi_currency = TRUE;
+        }
+
+        /* We're done with the imbalance list, the real work will be done
+           by xaccTransScrubImbalance which will get it again. */
+        gnc_monetary_list_free(imbal_list);
+    }
+    else
+        multi_currency = FALSE;
+//FIXME
+
+    split = xaccTransGetSplit (trans, 0);
+    other_split = xaccSplitGetOtherSplit (split);
+
+    if (other_split == NULL)
+    {
+        /* Attempt to handle the inverted many-to-one mapping */
+        split = xaccTransGetSplit (trans, 1);
+        if (split) other_split = xaccSplitGetOtherSplit (split);
+        else split = xaccTransGetSplit (trans, 0);
+    }
+    if (other_split == NULL || multi_currency)
+    {
+        two_accounts = FALSE;
+        other_account = NULL;
+    }
+    else
+    {
+        two_accounts = TRUE;
+        other_account = xaccSplitGetAccount (other_split);
+    }
+
+    default_account = gnc_tree_model_split_reg_get_anchor (model);
+
+    /* If the two pointers are the same, the account from other_split
+     * is actually the default account. We must make other_account
+     * the account from split instead.   */
+
+    if (default_account == other_account)
+        other_account = xaccSplitGetAccount (split);
+
+    /*  If the two pointers are still the same, we have two splits, but
+     *  they both refer to the same account. While non-sensical, we don't
+     *  object.   */
+
+    if (default_account == other_account)
+        two_accounts = FALSE;
+
+    radio_list = g_list_append (radio_list,
+                                _("Balance it _manually"));
+    radio_list = g_list_append (radio_list,
+                                _("Let GnuCash _add an adjusting split"));
+
+    if (model->type < NUM_SINGLE_REGISTER_TYPES2 && !multi_currency)
+    {
+        radio_list = g_list_append (radio_list,
+                                    _("Adjust current account _split total"));
+
+        default_value = 2;
+        if (two_accounts)
+        {
+            radio_list = g_list_append (radio_list,
+                                        _("Adjust _other account split total"));
+            default_value = 3;
+        }
+    }
+    else
+        default_value = 0;
+
+    choice = gnc_choose_radio_option_dialog
+             (window,
+              title,
+              message,
+              _("_Rebalance"),
+              default_value,
+              radio_list);
+
+    g_list_free (radio_list);
+
+    root = gnc_account_get_root(default_account);
+    switch (choice)
+    {
+    default:
+    case 0:
+        return TRUE;
+        break;
+
+    case 1:
+        xaccTransScrubImbalance (trans, root, NULL);
+        break;
+
+    case 2:
+        xaccTransScrubImbalance (trans, root, default_account);
+        break;
+
+    case 3:
+        xaccTransScrubImbalance (trans, root, other_account);
+        break;
+    }
+    return FALSE;
+}
+
+
 /* Cancel the edit and Rollback */
 void
 gnc_tree_control_split_reg_cancel_edit (GncTreeViewSplitReg *view, gboolean reg_closing)
@@ -174,9 +417,25 @@
     anchor = gnc_tree_model_split_reg_get_anchor (model);
     txn_com = xaccTransGetCurrency (trans);
 
-    if (gtc_is_trans_readonly_and_warn (trans))
+    if (trans == NULL)
         return;
 
+    /* See if we were asked to change a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+        return;
+
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+        return;
+
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
+        return;
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gtc_trans_open_and_warn (view, trans))
+        return;
+
     if (num_splits < 2)
         return;
 
@@ -206,8 +465,8 @@
 
         value = xaccSplitGetValue (split);
 
+        gnc_tree_view_split_reg_set_dirty_trans (view, trans);
         xaccTransBeginEdit (trans);
-        gnc_tree_view_split_reg_set_dirty_trans (view, trans);
 
         if (txn_com == xaccAccountGetCommodity (xaccSplitGetAccount(split)))
            gnc_tree_view_split_reg_set_value_for (view, trans, osplit, gnc_numeric_neg (value), TRUE);
@@ -256,7 +515,7 @@
 
     blank_split = gnc_tree_control_split_reg_get_blank_split (view);
 
-    /* get the current split based on cursor position */
+    /* get the current split */
     split = gnc_tree_view_split_reg_get_current_split (view);
     if (split == NULL)
         return;
@@ -271,6 +530,25 @@
 
     trans = xaccSplitGetParent (split);
 
+    if (trans == NULL)
+        return;
+
+    /* See if we were asked to change a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+        return;
+
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+        return;
+
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
+        return;
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gtc_trans_open_and_warn (view, trans))
+        return;
+
     gnc_tree_view_split_reg_set_dirty_trans (view, trans);
 
     xaccTransVoid (trans, reason);
@@ -311,6 +589,13 @@
 
     trans = xaccSplitGetParent (split);
 
+    if (trans == NULL)
+        return;
+
+    /* See if we were asked to change a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+        return;
+
     gnc_tree_view_split_reg_set_dirty_trans (view, trans);
 
     xaccTransUnvoid (trans);
@@ -334,6 +619,9 @@
 
     gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), spath);
 
+    /* Set cursor to new spath */
+    gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), spath, NULL, FALSE);
+
     gtk_tree_path_free (spath);
     gtk_tree_path_free (mpath);
 
@@ -361,6 +649,9 @@
 
     gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), spath);
 
+    /* Set cursor to new spath */
+    gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), spath, NULL, FALSE);
+
     gtk_tree_path_free (spath);
     gtk_tree_path_free (mpath);
 
@@ -454,6 +745,9 @@
     gnc_tree_view_split_reg_block_selection (view, FALSE);
     gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)), new_spath);
 
+    /* Set cursor to new spath */
+    gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), new_spath, NULL, FALSE);
+
     LEAVE("new_spath is %s", gtk_tree_path_to_string (new_spath));
 
     gtk_tree_path_free (new_spath);
@@ -471,6 +765,8 @@
 
     ENTER("view=%p, next_transaction=%s", view, next_transaction ? "TRUE" : "FALSE");
 
+//FIXME Might need more...
+
     model = gnc_tree_view_split_reg_get_model_from_view (view);
 
     goto_blank = gnc_gconf_get_bool (GCONF_GENERAL_REGISTER,
@@ -508,7 +804,7 @@
             gnc_tree_view_split_reg_collapse_trans (view, NULL);
 
         /* Now move. */
-        if (goto_blank)
+        if (goto_blank) //FIXME What do we want to do here...
             gnc_tree_control_split_reg_jump_to_blank (view);
         else if (next_transaction)
             gnc_tree_control_split_reg_goto_rel_trans_row (view, 1);
@@ -533,9 +829,26 @@
                               "cause your reconciled balance to be off.");
 
     trans = gnc_tree_view_split_reg_get_current_trans (view);
-    if (gtc_is_trans_readonly_and_warn (trans))
+
+    if (trans == NULL)
         return;
 
+    /* See if we were asked to change a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+        return;
+
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+        return;
+
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
+        return;
+
+    /* Make sure we ask to commit any changes before we procede */
+    if (gtc_trans_open_and_warn (view, trans))
+        return;
+
     window = gnc_tree_view_split_reg_get_parent (view);
 
     dialog = gtk_message_dialog_new (GTK_WINDOW (window),
@@ -543,6 +856,7 @@
                                     GTK_MESSAGE_WARNING,
                                     GTK_BUTTONS_NONE,
                                     "%s", title);
+
     if (xaccTransHasReconciledSplits (trans))
     {
         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
@@ -582,10 +896,27 @@
     split = gnc_tree_view_split_reg_get_current_split (view);
     if (split == NULL)
     {
-        return;
+        split = gnc_tree_control_split_reg_get_current_trans_split (view);
+        if (split == NULL)
+        {
+            LEAVE("split is NULL");
+            return;
+        }
     }
 
     trans = xaccSplitGetParent (split);
+
+    if (trans == NULL)
+        return;
+
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+        return;
+
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
+        return;
+
     depth = gnc_tree_view_reg_get_selected_row_depth (view);
 
     /* Deleting the blank split just cancels */
@@ -593,14 +924,9 @@
         Split *blank_split = gnc_tree_control_split_reg_get_blank_split (view);
 
         if (split == blank_split)
-        {
             return;
-        }
     }
 
-    if (gtc_is_trans_readonly_and_warn (trans))
-        return;
-
     window = gnc_tree_view_split_reg_get_parent (view);
 
     /* On a split cursor, just delete the one split. */
@@ -726,41 +1052,58 @@
 {
     GtkWidget *window;
     Transaction *trans = NULL, *new_trans = NULL;
+    GList *snode = NULL;
+    gboolean changed = FALSE;
 
+    ENTER(" ");
+
     trans = gnc_tree_view_split_reg_get_current_trans (view);
 
     if (trans == NULL)
+    {
+        LEAVE("Trans is Null");
         return;
+    }
 
-//FIXME Need same tests as duplicate ?????
-
-    window = gnc_tree_view_split_reg_get_parent (view);
-
-    /* Make sure we have stopped editing */
-    gnc_tree_view_split_reg_finish_edit (view);
-
     /* See if we were asked to reverse a blank trans. */
     if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
     {
-        LEAVE("skip blank trans");
+        LEAVE("Skip blank trans");
         return;
     }
 
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+    {
+        LEAVE("Read only");
+        return;
+    }
+
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
+    {
+        LEAVE("Open in different register");
+        return;
+    }
+
+    window = gnc_tree_view_split_reg_get_parent (view);
+
     if (xaccTransGetReversedBy (trans))
     {
         gnc_error_dialog (window, "%s",
                          _("A reversing entry has already been created for this transaction."));
+        LEAVE("Already have reversing transaction");
         return;
     }
 
-#ifdef skip
+    /* Make sure we ask to commit any changes before we add reverse transaction */
+    if (gtc_trans_open_and_warn (view, trans))
+    {
+        LEAVE("save cancelled");
+        return;
+    }
 
-//FIXME Test for trans in edit....
-
-    gnc_tree_view_split_reg_set_dirty_trans (view, trans);
-
-    xaccTransBeginEdit (trans);
-
+    /* Create reverse transaction */
     new_trans = xaccTransReverse (trans);
 
     xaccTransBeginEdit (new_trans);
@@ -770,14 +1113,25 @@
     xaccTransSetDateEnteredSecs (new_trans, gnc_time (NULL));
 
     xaccTransCommitEdit (new_trans);
-    xaccTransCommitEdit (trans);
 
-    gnc_tree_view_split_reg_set_dirty_trans (view, NULL);
+    // We need to loop through the splits and send an event to update the register.
+    for (snode = xaccTransGetSplitList (new_trans); snode; snode = snode->next)
+    {
+        if (xaccTransStillHasSplit (new_trans, snode->data))
+        {
+           /* Send an event based on the split account */
+           qof_event_gen (QOF_INSTANCE (xaccSplitGetAccount(snode->data)), GNC_EVENT_ITEM_ADDED, snode->data);
+        }
+    }
 
+    /* give gtk+ a chance to handle pending events */
+    while (gtk_events_pending ())
+        gtk_main_iteration ();
+
     /* Now jump to new trans */
-//    gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (new_trans, 0));
+    gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (new_trans, 0));
 
-#endif
+    LEAVE("Reverse transaction created");
 }
 
 
@@ -792,6 +1146,7 @@
     Split *blank_split;
     Split *split, *trans_split;
     gboolean changed = FALSE;
+    gboolean use_split_action_for_num_field = FALSE;
 
     ENTER("");
 
@@ -800,99 +1155,119 @@
     blank_split = gnc_tree_control_split_reg_get_blank_split (view);
     split = gnc_tree_view_split_reg_get_current_split (view);
     trans_split = gnc_tree_control_split_reg_get_current_trans_split (view);
+    depth = gnc_tree_view_reg_get_selected_row_depth (view);
+
+    use_split_action_for_num_field = qof_book_use_split_action_for_num_field (gnc_get_current_book());
+
     trans = gnc_tree_view_split_reg_get_current_trans (view);
-    depth = gnc_tree_view_reg_get_selected_row_depth (view);
-#ifdef skip
+
     /* This shouldn't happen, but be paranoid. */
     if (trans == NULL)
+        return FALSE;
+
+    /* See if we were asked to change a blank trans. */
+    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
     {
-        LEAVE("no transaction");
+        LEAVE("Skip blank trans");
         return FALSE;
     }
 
-    if (gtc_is_trans_readonly_and_warn (trans))
+    /* See if we were asked to change a blank split. */
+    if (split == blank_split)
     {
-        LEAVE("read only transaction");
+        LEAVE("Skip blank split");
         return FALSE;
     }
 
-    /* Make sure we have stopped editing */
-    gnc_tree_view_split_reg_finish_edit (view);
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, trans))
+    {
+        LEAVE("Read only");
+        return FALSE;
+    }
 
-    /* See if we are editing this transcation all ready */
-    if (trans == gnc_tree_view_split_reg_get_dirty_trans (view))
-        changed = TRUE;
-
-    /* See if we were asked to duplicate a blank split. */
-    if (split == gnc_tree_control_split_reg_get_blank_split (view))
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, trans))
     {
-        LEAVE("skip blank split");
+        LEAVE("Open in different register");
         return FALSE;
     }
 
-    /* See if we were asked to duplicate a blank trans. */
-    if (trans == gnc_tree_control_split_reg_get_blank_trans (view))
+    /* Make sure we ask to commit any changes before we procede */
+    if (gtc_trans_open_and_warn (view, trans))
     {
-        LEAVE("skip blank trans");
+        LEAVE("save cancelled");
         return FALSE;
     }
 
-    gnc_suspend_gui_refresh ();
-
     window = gnc_tree_view_split_reg_get_parent (view);
 
-    /* If the cursor has been edited, we are going to have to commit
-     * it before we can duplicate. Make sure the user wants to do that. */
-    if (changed)
-    {
-        GtkWidget *dialog;
-        gint response;
-        const char *title = _("Save transaction before duplicating?");
-        const char *message =
-            _("The current transaction has been changed. Would you like to "
-              "record the changes before duplicating the transaction, or "
-              "cancel the duplication?");
-
-        dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                        GTK_DIALOG_DESTROY_WITH_PARENT,
-                                        GTK_MESSAGE_QUESTION,
-                                        GTK_BUTTONS_CANCEL,
-                                        "%s", title);
-        gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                "%s", message);
-        gtk_dialog_add_button (GTK_DIALOG (dialog),
-                              _("_Record"), GTK_RESPONSE_ACCEPT);
-        response = gnc_dialog_run (GTK_DIALOG (dialog), "transaction_duplicated");
-        gtk_widget_destroy (dialog);
-
-        if (response != GTK_RESPONSE_ACCEPT)
-        {
-            gnc_resume_gui_refresh ();
-            LEAVE("save cancelled");
-            return FALSE;
-        }
-
-        xaccTransCommitEdit (trans);
-        gnc_tree_view_split_reg_set_dirty_trans (view, NULL);
-    }
-
     /* Ok, we are now ready to make the copy. */
 
     if (depth == SPLIT3)
     {
         Split *new_split;
+        gboolean new_act_num = FALSE;
+        char *out_num;
+        time64 date;
 
         /* We are on a split in an expanded transaction.
-         * Just copy the split and add it to the transaction. */
+         * Just copy the split and add it to the transaction.
+         * However, if the split-action field is being used as the register 
+         * number, and the action field is a number, request a new value or
+         * cancel. Need to get next number and update account last num from
+         * split account not register account, which may be the same or not */
 
         if (split != trans_split)
         {
+            if (use_split_action_for_num_field && gnc_strisnum (gnc_get_num_action (NULL, split)))
+            {
+                Account *account = xaccSplitGetAccount (split);
+                const char* title = _("New Split Information");
+                const char *in_num = NULL;
+                date = time (0);
+
+                if (account)
+                    in_num = xaccAccountGetLastNum (account);
+                else
+                    in_num = gnc_get_num_action (NULL, split);
+
+                if (!gnc_dup_trans_dialog (window, title, FALSE,
+                                           &date, in_num, &out_num, NULL, NULL))
+                {
+                    LEAVE("dup cancelled");
+                    return FALSE;
+                }
+                new_act_num = TRUE;
+            }
+
             new_split = xaccMallocSplit (gnc_get_current_book ());
 
+            // Remove the blank split
+            gnc_tree_model_split_reg_set_blank_split_parent (model, trans, TRUE);
+
             xaccTransBeginEdit (trans);
+            gnc_tree_view_split_reg_set_dirty_trans (view, trans);
+
             xaccSplitSetParent (new_split, trans);
             gtc_copy_split_onto_split (split, new_split, FALSE);
-            xaccTransCommitEdit (trans);
+
+            // Add the blank split
+            gnc_tree_model_split_reg_set_blank_split_parent (model, trans, FALSE);
+
+            if (new_act_num) /* if new number supplied by user dialog */
+                gnc_set_num_action (NULL, new_split, out_num, NULL);
+
+            if (new_act_num && gnc_strisnum (out_num))
+            {
+                Account *account = xaccSplitGetAccount (new_split);
+
+                /* If current register is for account, set last num */
+                if (account == gnc_tree_model_split_reg_get_anchor (model))
+                    xaccAccountSetLastNum (account, out_num);
+            }
+            if (new_act_num)
+                g_free (out_num);
         }
         else
         {
@@ -906,14 +1281,14 @@
     else
     {
         Transaction *new_trans;
+        int trans_split_index;
+        int split_index;
         const char *in_num = NULL;
         const char *in_tnum = NULL;
         char *out_num;
         char *out_tnum;
         time64 date;
         gboolean use_autoreadonly = qof_book_uses_autoreadonly (gnc_get_current_book());
-        gboolean use_split_action_for_num_field = qof_book_use_split_action_for_num_field
-                           (gnc_get_current_book());
 
         /* We are on a transaction row. Copy the whole transaction. */
 
@@ -924,16 +1299,16 @@
             if (account)
                 in_num = xaccAccountGetLastNum (account);
             else
-                in_num = xaccTransGetNum (trans);
-            in_tnum = (use_split_action_for_num_field
+                in_num = gnc_get_num_action (trans, trans_split);
+
+            in_tnum = (!use_split_action_for_num_field
                                         ? NULL
-                                        : gnc_get_num_action (trans, NULL)); //FIXME is this right way round ?
+                                        : gnc_get_num_action (trans, NULL));
         }
 
         if (!gnc_dup_trans_dialog (window, NULL, TRUE,
                                    &date, in_num, &out_num, in_tnum, &out_tnum))
         {
-            gnc_resume_gui_refresh ();
             LEAVE("dup cancelled");
             return FALSE;
         }
@@ -963,19 +1338,35 @@
             g_date_free (readonly_threshold);
         }
 
+        split_index = xaccTransGetSplitIndex (trans, split);
+        trans_split_index = xaccTransGetSplitIndex (trans, trans_split);
+
         new_trans = xaccMallocTransaction (gnc_get_current_book ());
 
         xaccTransBeginEdit (new_trans);
         gtc_copy_trans_onto_trans (trans, new_trans, FALSE, FALSE);
         xaccTransSetDatePostedSecs (new_trans, date);
-        xaccTransSetNum (new_trans, out_num);
+
+        /* set per book option */
+        gnc_set_num_action (new_trans, NULL, out_num, out_tnum);
+        if (!use_split_action_for_num_field)
+        {
+            /* find split in new_trans that equals trans_split and set
+             * split_action to out_num */
+            gnc_set_num_action (NULL,
+                                xaccTransGetSplit (new_trans, trans_split_index),
+                                out_num, NULL);
+            /* note that if the transaction has multiple splits to the register
+             * account, only the anchor split will be set with user input. The
+             * user will have to adjust other splits manually. */
+        }
         xaccTransCommitEdit (new_trans);
-    }
 
+        g_free (out_num);
 
-    /* Refresh the GUI. */
-    gnc_resume_gui_refresh ();
-#endif
+        if (!use_split_action_for_num_field)
+            g_free (out_tnum);
+    }
     LEAVE(" ");
     return TRUE;
 }
@@ -987,7 +1378,7 @@
 {
     GncTreeModelSplitReg *model;
     RowDepth depth;
-    Transaction *pending_trans;
+    Transaction *dirty_trans;
     Transaction *blank_trans;
     Transaction *trans;
     Account *account;
@@ -1013,7 +1404,7 @@
     model = gnc_tree_view_split_reg_get_model_from_view (view);
 
     blank_split = gnc_tree_control_split_reg_get_blank_split (view);
-    pending_trans = gnc_tree_view_split_reg_get_dirty_trans (view);
+    dirty_trans = gnc_tree_view_split_reg_get_dirty_trans (view);
     blank_trans = gnc_tree_control_split_reg_get_blank_trans (view);
 
     /* get the handle to the current split and transaction */
@@ -1034,7 +1425,7 @@
         return FALSE;
     }
 
-    if (trans == pending_trans )
+    if (trans == dirty_trans )
     {
         if (trans != blank_trans)
         {
@@ -1250,6 +1641,52 @@
 }
 
 
+/* Return the account for name given or create it */ 
+Account *
+gnc_tree_control_split_reg_get_account_by_name (GncTreeViewSplitReg *view, const char *name)
+{
+    GtkWidget *window;
+    const char *placeholder = _("The account %s does not allow transactions.");
+    const char *missing = _("The account %s does not exist. "
+                            "Would you like to create it?");
+    char *account_name;
+    Account *account;
+
+    if (!name || (strlen(name) == 0))
+        return NULL;
+
+    /* Find the account */
+    if (gnc_gconf_get_bool (GCONF_GENERAL_REGISTER, "show_leaf_account_names", NULL))
+        account = gnc_account_lookup_by_name (gnc_get_current_root_account(), name);
+    else
+        account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), name);
+
+    if (!account)
+        account = gnc_account_lookup_by_code (gnc_get_current_root_account(), name);
+
+    window = gnc_tree_view_split_reg_get_parent (view);
+
+    if (!account)
+    {
+        /* Ask if they want to create a new one. */
+        if (!gnc_verify_dialog (window, TRUE, missing, name))
+            return NULL;
+
+        /* User said yes, they want to create a new account. */
+        account = gnc_ui_new_accounts_from_name_window (name);
+        if (!account)
+            return NULL;
+    }
+    /* Now have the account. */
+
+    /* See if the account (either old or new) is a placeholder. */
+    if (xaccAccountGetPlaceholder (account))
+        gnc_error_dialog (window, placeholder, name);
+
+    /* Be seeing you. */
+    return account;
+}
+
 /*****************************************************************************
  *                         ClipBoard Functions                               *
  *****************************************************************************/
@@ -1272,15 +1709,9 @@
     if (!from_trans)
         return;
 
-    if (gnc_tree_model_split_reg_get_read_only (model, from_trans))
-    {
-        GtkWidget *window;
-
-        window = gnc_tree_view_split_reg_get_parent (view);
-        gnc_error_dialog (window, "%s",
-                         _("You can not cut from a read only transaction or register."));
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, from_trans))
         return;
-    }
 
     xaccTransBeginEdit (clipboard_trans);
     if (clipboard_trans)
@@ -1354,15 +1785,13 @@
     if (!to_trans || !clipboard_trans)
         return;
 
-    if (gnc_tree_model_split_reg_get_read_only (model, to_trans))
-    {
-        GtkWidget *window;
+    /* See if we are being edited in another register */
+    if (gtc_trans_test_for_edit (view, to_trans))
+        return;
 
-        window = gnc_tree_view_split_reg_get_parent (view);
-        gnc_error_dialog (window, "%s",
-                         _("You can not paste to a read only transaction or register."));
+    /* Test for read only */
+    if (gtc_is_trans_readonly_and_warn (view, to_trans))
         return;
-    }
 
     //FIXME You can not paste from gl to a register, is this too simplistic
     if (clipboard_acct == NULL && anchor_acct != NULL)

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h	2013-04-07 20:54:35 UTC (rev 22882)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-control-split-reg.h	2013-04-07 22:14:09 UTC (rev 22883)
@@ -71,6 +71,10 @@
 
 gboolean gnc_tree_control_split_reg_recn_test (GncTreeViewSplitReg *view);
 
+gboolean gnc_tree_control_split_reg_balance_trans (GncTreeViewSplitReg *view, Transaction *trans);
+
+Account * gnc_tree_control_split_reg_get_account_by_name (GncTreeViewSplitReg *view, const char *name);
+
 /*****************************************************************************/
 
 /* Cut transaction and copy to clipboard */

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c	2013-04-07 20:54:35 UTC (rev 22882)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-model-split-reg.c	2013-04-07 22:14:09 UTC (rev 22883)
@@ -345,18 +345,14 @@
 
     if (model == NULL)
         return;
-//g_print("gnc_tree_model_split_reg_gconf_changed\n");
 
     if (g_str_has_suffix (entry->key, KEY_ACCOUNTING_LABELS))
     {
-        // FIXME This only works on create, dynamic ? 
         model->use_accounting_labels = gnc_gconf_get_bool (GCONF_GENERAL, KEY_ACCOUNTING_LABELS, NULL);
-
-//g_print("model->use_accounting_labels changed %d\n", model->use_accounting_labels);
     }
     else if (g_str_has_suffix (entry->key, KEY_ACCOUNT_SEPARATOR))
     {
-        model->separator_changed = TRUE; // FIXME Not dealt with this
+        model->separator_changed = TRUE;
     }
     else
     {
@@ -804,45 +800,68 @@
     if (depth == 1) {      /* Trans Row 1 */
         flags = TROW1;
         /* Check if this is the blank trans */
-        if (tnode->data == model->priv->btrans) {
+        if (tnode->data == model->priv->btrans)
+        {
             flags |= BLANK;
-            snode = NULL;
+
+            if (xaccTransCountSplits (tnode->data) == 0)
+            {
+                if (model->priv->bsplit_parent_node == tnode)
+                    snode = model->priv->bsplit_node; // blank split
+                else
+                    snode = NULL; // blank trans - not selected
+            }
+            else
+            {
+                split = xaccTransGetSplit (tnode->data, 0);
+                snode = g_list_find (slist, split); // else first split
+            }
         }
         else
         {
-            split = xaccTransGetSplit (tnode->data, 0); // else first split
-            snode = g_list_find (slist, split);
+            split = xaccTransGetSplit (tnode->data, 0);
+            snode = g_list_find (slist, split); // else first split
         }
-
-
     }
     else if (depth == 2) { /* Trans Row 2 */
         flags = TROW2;
         /* Check if this is the blank trans */
-        if (tnode->data == model->priv->btrans) {
+        if (tnode->data == model->priv->btrans)
+        {
             flags |= BLANK;
-            snode = NULL;
+
+            if (xaccTransCountSplits (tnode->data) == 0)
+            {
+                if (model->priv->bsplit_parent_node == tnode)
+                    snode = model->priv->bsplit_node; // blank split
+                else
+                    snode = NULL; // blank trans - not selected
+            }
+            else
+            {
+                split = xaccTransGetSplit (tnode->data, 0);
+                snode = g_list_find (slist, split); // else first split
+            }
         }
         else
         {
-            split = xaccTransGetSplit (tnode->data, 0); // else first split
-            snode = g_list_find (slist, split);
+            split = xaccTransGetSplit (tnode->data, 0);
+            snode = g_list_find (slist, split); // else first split
         }
     }
-    else if (depth == 3) /* Split */
-    {        
+    else if (depth == 3) { /* Split */       
         flags = SPLIT;
 
         /* Check if this is the blank split */
         if ((tnode == model->priv->bsplit_parent_node) && (xaccTransCountSplits (tnode->data) == indices[2]))
         {
             flags |= BLANK;
-            snode = model->priv->bsplit_node;
+            snode = model->priv->bsplit_node; // blank split = number of splits in list
         }
         else
         {
             split = xaccTransGetSplit (tnode->data, indices[2]);
-            snode = g_list_find (slist, split);
+            snode = g_list_find (slist, split); // split = position in list
         }
 
         if (!snode) {
@@ -1228,14 +1247,27 @@
         slist = xaccTransGetSplitList (tnode->data);
 
         /* Check if this is the blank trans */
-        if (tnode->data == model->priv->btrans) {
+        if (tnode->data == model->priv->btrans)
+        {
             flags |= BLANK;
-            snode = NULL;
+
+            if (xaccTransCountSplits (tnode->data) == 0)
+            {
+                if (model->priv->bsplit_parent_node == tnode)
+                    snode = model->priv->bsplit_node; // blank split
+                else
+                    snode = NULL; // blank trans with no splits
+            }
+            else
+            {
+                split = xaccTransGetSplit (tnode->data, 0);
+                snode = g_list_find (slist, split); // else first split
+            }
         }
         else
         {
             split = xaccTransGetSplit (tnode->data, 0);
-            snode = g_list_find (slist, split);
+            snode = g_list_find (slist, split); // else first split
         }
     }
 
@@ -1291,7 +1323,7 @@
     ENTER("model %p, iter %p , parent %s",
           tree_model, iter, (parent_iter ? iter_to_string (parent_iter) : "(null)"));
 
-    if (!parent_iter)
+    if (!parent_iter) // special parent iter is NULL
     {
         /* Get the very first iter */
         tnode = g_list_first (model->priv->tlist);
@@ -1302,12 +1334,24 @@
             if (tnode->data == model->priv->btrans)
             {
                 flags |= BLANK;
-                snode = NULL;
+
+                if (xaccTransCountSplits (tnode->data) == 0)
+                {
+                    if (model->priv->bsplit_parent_node == tnode)
+                        snode = model->priv->bsplit_node; // blank split
+                    else
+                        snode = NULL; // blank trans with no splits
+                }
+                else
+                {
+                     split = xaccTransGetSplit (tnode->data, 0);
+                     snode = g_list_find (slist, split); // else first split
+                }
             }
             else
             {
                 split = xaccTransGetSplit (tnode->data, 0);
-                snode = g_list_find (slist, split);
+                snode = g_list_find (slist, split); // else first split
             }
 
             *iter = gtm_make_iter (model, flags, tnode, snode);
@@ -1332,12 +1376,24 @@
         if (tnode->data == model->priv->btrans)
         {
             flags |= BLANK;
-            snode = NULL;
+
+            if (xaccTransCountSplits (tnode->data) == 0)
+            {
+                if (model->priv->bsplit_parent_node == tnode)
+                    snode = model->priv->bsplit_node; // blank split
+                else
+                    snode = NULL; // blank trans with no splits
+            }
+            else
+            {
+                split = xaccTransGetSplit (tnode->data, 0);
+                snode = g_list_find (slist, split); // else first split
+            }
         }
         else
         {
             split = xaccTransGetSplit (tnode->data, 0);
-            snode = g_list_find (slist, split);
+            snode = g_list_find (slist, split); // else first split
         }
     }
 
@@ -1358,12 +1414,12 @@
             if (((tnode->data == model->priv->btrans) || (xaccTransCountSplits (tnode->data) == 0)) && (tnode == model->priv->bsplit_parent_node))
             {
                 flags |= BLANK;
-                snode = model->priv->bsplit_node;
+                snode = model->priv->bsplit_node; // blank split on blank trans
             }
             else
             {
                 split = xaccTransGetSplit (tnode->data, 0);
-                snode = g_list_find (slist, split);
+                snode = g_list_find (slist, split); // else first split
             }
         }
     }
@@ -1394,13 +1450,13 @@
 
     tnode = iter->user_data2;
 
-    if (IS_TROW1 (iter)) //Normal Transaction TROW1
+    if (IS_TROW1 (iter)) // Normal Transaction TROW1
     {
         LEAVE ("Transaction Row 1 is yes");
         return TRUE;
     }
 
-    if (IS_TROW2 (iter) && !(IS_BLANK (iter))) //Normal Transaction TROW2
+    if (IS_TROW2 (iter) && !(IS_BLANK (iter))) // Normal Transaction TROW2
     {
         if (xaccTransCountSplits (tnode->data) != 0) // with splits
 	{
@@ -1417,7 +1473,7 @@
         }
     }
 
-    if (IS_TROW2 (iter) && IS_BLANK (iter) && (tnode == model->priv->bsplit_parent_node)) //Blank Transaction TROW2
+    if (IS_TROW2 (iter) && IS_BLANK (iter) && (tnode == model->priv->bsplit_parent_node)) // Blank Transaction TROW2
     {
         LEAVE ("Blank Transaction Row 2 is yes");
         return TRUE;
@@ -1486,7 +1542,7 @@
         tnode = g_list_nth (model->priv->tlist, n);
 
         if (!tnode) {
-            PERR("Trans list should never be NULL.");
+            PERR("Index greater than trans list.");
             goto fail;
         }
 
@@ -1496,12 +1552,24 @@
         if (tnode->data == model->priv->btrans)
         {
             flags |= BLANK;
-            snode = NULL;
+
+            if (xaccTransCountSplits (tnode->data) == 0)
+            {
+                if (model->priv->bsplit_parent_node == tnode)
+                    snode = model->priv->bsplit_node; // blank split
+                else
+                    snode = NULL; // blank trans with no splits
+            }
+            else
+            {
+                split = xaccTransGetSplit (tnode->data, 0);
+                snode = g_list_find (slist, split); // else first split
+            }
         }
         else
         {
             split = xaccTransGetSplit (tnode->data, 0);
-            snode = g_list_find (slist, split);
+            snode = g_list_find (slist, split); // else first split
         }
 
         *iter = gtm_make_iter (model, flags, tnode, snode);
@@ -1925,15 +1993,14 @@
 
     iter = gtm_make_iter (model, TROW1, tnode, NULL);
     gtm_insert_row_at (model, &iter);
-    path = gnc_tree_model_split_reg_get_path (GTK_TREE_MODEL (model), &iter);
-    gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter);
-    gtk_tree_path_free (path);
 
     iter = gtm_make_iter (model, TROW2, tnode, NULL);
     gtm_insert_row_at (model, &iter);
     path = gnc_tree_model_split_reg_get_path (GTK_TREE_MODEL (model), &iter);
+
+    gtk_tree_path_up (path); // to TROW1
+    gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
     gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter);
-    gtk_tree_path_free (path);
 
     DEBUG("insert %d splits for transaction %p\n", xaccTransCountSplits (trans), trans);
 
@@ -1945,6 +2012,11 @@
             gtm_insert_row_at (model, &iter);
         }
     }
+    gtk_tree_path_down (path); // to TROW2
+    gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+    gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model), path, &iter);
+    gtk_tree_path_free (path);
+
     LEAVE(" ");
 }
 
@@ -2515,7 +2587,38 @@
     }
 }
 
+static int
+gtm_account_order_by_name (const Account *aa, const Account *ab)
+{
+    const char *na, *nb;
+    int retval;
 
+    na = xaccAccountGetName (aa);
+    nb = xaccAccountGetName (ab);
+
+    retval = g_utf8_collate (na, nb);
+    if (retval)
+       return retval;
+
+    return 0;
+}
+
+static int
+gtm_account_order_by_full_name (const Account *aa, const Account *ab)
+{
+    char *fna, *fnb;
+    int retval;
+
+    fna = gnc_account_get_full_name (aa);
+    fnb = gnc_account_get_full_name (ab);
+
+    retval = g_utf8_collate (fna, fnb);
+    if (retval)
+       return retval;
+
+    return 0;
+}
+
 /* Return the GtkListstore of Accounts */
 void
 gnc_tree_model_split_reg_update_account_list (GncTreeModelSplitReg *model)
@@ -2524,7 +2627,7 @@
     Account *root;
     Account *acc;
     GtkTreeIter iter;
-    GList *accts, *ptr;
+    GList *accts, *accts_cpy, *ptr;
     gboolean valid;
     const gchar *name;
     gchar *fname;
@@ -2536,10 +2639,19 @@
     gtk_list_store_clear (priv->account_list);
 
     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++)
+    // Get a list of accounts.
+    accts = gnc_account_get_descendants (root);
+
+    // Copy the accts, put it in full name order. 
+    accts_cpy = g_list_copy (accts);
+
+    if (gnc_gconf_get_bool (GCONF_GENERAL_REGISTER, "show_leaf_account_names", NULL))
+        accts_cpy = g_list_sort (accts_cpy, (GCompareFunc)gtm_account_order_by_name);
+    else
+        accts_cpy = g_list_sort (accts_cpy, (GCompareFunc)gtm_account_order_by_full_name);
+
+    for (ptr = accts_cpy, i = 0; ptr; ptr = g_list_next (ptr), i++)
     {
         acc = ptr->data;
 
@@ -2553,6 +2665,7 @@
         }
     }
     g_list_free (accts);
+    g_list_free (accts_cpy);
 }
 
 
@@ -2704,7 +2817,6 @@
                 gtm_changed_row_at (model, &iter2);
                 g_signal_emit_by_name (model, "refresh_view", NULL);
             }
-
             break;
         case QOF_EVENT_DESTROY:
             if (priv->btrans == trans)

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c	2013-04-07 20:54:35 UTC (rev 22882)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-split-reg.c	2013-04-07 22:14:09 UTC (rev 22883)
@@ -281,6 +281,7 @@
 #define BLUECELL "#1D80DF"
 #define BLACKCELL "#CBCBD2"
 #define YELLOWCELL "#FFEF98"
+#define ORANGECELL "#F39536"
 
 
 /* This could be a preference setting, the minimum length of characters in order to start completing */
@@ -756,10 +757,10 @@
     // This will refresh the view.
     g_signal_connect (G_OBJECT (model), "refresh_view", G_CALLBACK (gtv_split_reg_refresh_cb), view);
 
-    // This should be for key navigation, tabbing...
+    // This is for key navigation, tabbing...
     g_signal_connect (G_OBJECT (view), "key-press-event", G_CALLBACK (gtv_split_reg_key_press_cb), NULL);
 
-    // This should be for mouse buttons...
+    // This is for mouse buttons...
     g_signal_connect (G_OBJECT (view), "button_press_event", G_CALLBACK (gtv_split_reg_button_cb), NULL);
 
     return view;
@@ -907,6 +908,9 @@
 {
     GncTreeViewSplitReg *view = user_data;
 
+    /* Refilter the tree view register */
+    gnc_tree_view_split_reg_refilter (view);
+
     if (view->reg_closing != TRUE)
         /* Set the view format */
         g_idle_add ((GSourceFunc)gnc_tree_view_split_reg_set_format, view);
@@ -1046,6 +1050,10 @@
     gtk_tree_path_free (spath);
     gtk_tree_path_free (new_mpath);
 
+    /* give gtk+ a chance to handle pending events */
+//    while (gtk_events_pending ())
+//        gtk_main_iteration ();
+
     /* Refilter the tree view register */
     gnc_tree_view_split_reg_refilter (view);
 
@@ -1158,13 +1166,22 @@
 
     /* Rate from trans-curr to split-comm */
     rate_split_ok = xaccTransGetRateForCommodity (trans, xfer_comm, split, &rate_split);
+    DEBUG("rate_split_ok %d and xfer_comm %s", rate_split_ok, gnc_commodity_get_fullname (xfer_comm));
 
     /* Rate from trans-curr to reg-comm */
     rate_reg_ok = xaccTransGetRateForCommodity (trans, reg_comm, split, &rate_reg);
+    DEBUG("rate_reg_ok %d and reg_comm %s", rate_reg_ok, gnc_commodity_get_fullname (reg_comm));
 
     /* Are we expanded */
     expanded = view->priv->expanded;
 
+    if (gnc_commodity_equal (trans_curr, xfer_comm) && rate_split_ok)
+    {
+        xaccSplitSetAmount (split, amount);
+        xaccSplitSetValue (split, amount);
+        return TRUE;
+    }
+
     if (rate_reg_ok && rate_split_ok && !force)
     {
         value = gnc_numeric_div (amount, rate_reg, gnc_commodity_get_fraction (trans_curr), GNC_HOW_DENOM_REDUCE);
@@ -1440,6 +1457,7 @@
 static void
 set_number_for_input (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input, gint viewcol)
 {
+    GncTreeModelSplitReg *model;
     gnc_numeric  price;
     gnc_numeric  amount;
     gnc_numeric  value;
@@ -1452,9 +1470,34 @@
     gboolean recalc_price = FALSE;
     gboolean recalc_value = FALSE;
     int denom;
+    Account *account;
 
     ENTER("set_number_for_input trans %p and split %p and input is %s and viewcol is %d", trans, split, gnc_numeric_to_string (input), viewcol);
 
+
+//FIXME ## Trading ## Copied from split-register, needs testing
+
+    model = gnc_tree_view_split_reg_get_model_from_view (view);
+
+    account = gnc_tree_model_split_reg_get_anchor (model);
+
+    if (!account)
+        account = xaccSplitGetAccount (split);
+
+    if (!xaccAccountIsPriced (account))
+        return;
+
+    /* If we are using commodity trading accounts then the value may
+       not really be the value.  Punt if so. */
+    if (xaccTransUseTradingAccounts (xaccSplitGetParent (split)))
+    {
+        gnc_commodity *acc_commodity;
+        acc_commodity = xaccAccountGetCommodity (account);
+        if (!(xaccAccountIsPriced (account) || !gnc_commodity_is_iso (acc_commodity)))
+            return;
+    }
+//FIXME
+
     if (gnc_numeric_zero_p (input))
     {
         xaccSplitSetValue (split, input);
@@ -1503,7 +1546,7 @@
         }
     }
 
-    if (viewcol == COL_CREDIT || viewcol == COL_DEBIT)
+    if ((viewcol == COL_CREDIT || viewcol == COL_DEBIT) && !view->priv->expanded)
     {
         amount_changed = TRUE;
         if (gnc_numeric_zero_p (value))
@@ -1514,6 +1557,17 @@
             return;
         }
     }
+    else if ((viewcol == COL_CREDIT || viewcol == COL_DEBIT) && view->priv->expanded)
+    {
+        value_changed = TRUE;
+        if (gnc_numeric_zero_p (value))
+        {
+            xaccSplitSetValue (split, input);
+            xaccSplitSetAmount (split, input);
+            LEAVE("");
+            return;
+        }
+    }
 
     DEBUG("value_changed %d, price_changed %d, amount_changed %d", value_changed, price_changed, amount_changed);
 
@@ -1660,30 +1714,32 @@
             value = gnc_numeric_mul (amount, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
             xaccSplitSetValue (split, value);
         }
+    }
 
-        /* If the number of splits is two, change other split to balance */
-        if ((xaccTransCountSplits (trans) == 2) && view->priv->expanded)
-        {
-            Split *osplit;
-            gnc_commodity *split_com;
+    /* If the number of splits is two, change other split to balance */
+    if ((xaccTransCountSplits (trans) == 2) && view->priv->expanded)
+    {
+        Split *osplit;
+        gnc_commodity *osplit_com;
 
-            osplit = get_other_split (view, trans);
+        osplit = get_other_split (view, trans);
 
-            split_com = xaccAccountGetCommodity (xaccSplitGetAccount (osplit));
+        value = xaccSplitGetValue (split);
 
-            if (gnc_commodity_is_currency (split_com))
+        osplit_com = xaccAccountGetCommodity (xaccSplitGetAccount (osplit));
+
+        if (gnc_commodity_is_currency (osplit_com))
+        {
+            if (!gnc_numeric_negative_p (value))
             {
-                if (gnc_numeric_negative_p (value))
-                {
-                    xaccSplitSetValue (osplit, gnc_numeric_neg (value));
-                    xaccSplitSetAmount (osplit, gnc_numeric_neg (value));
-                }
-                else
-                {
-                    xaccSplitSetValue (osplit, value);
-                    xaccSplitSetAmount (osplit, value);
-                }
+                xaccSplitSetValue (osplit, gnc_numeric_neg (value));
+                xaccSplitSetAmount (osplit, gnc_numeric_neg (value));
             }
+            else
+            {
+                xaccSplitSetValue (osplit, value);
+                xaccSplitSetAmount (osplit, value);
+            }
         }
     }
     LEAVE("");
@@ -1746,6 +1802,7 @@
 static gboolean
 get_split_pair (GncTreeViewSplitReg *view, Transaction *trans, Split **osplit, Split **split)
 {
+    GncTreeModelSplitReg *model;
     QofBook       *book;
 
     gint count = xaccTransCountSplits (trans);
@@ -1753,9 +1810,11 @@
 
     book = gnc_get_current_book();
 
-    if (count == 0)
+    model = gnc_tree_view_split_reg_get_model_from_view (view);
+
+    if (count == 0) // blank trans
     {
-        *split = xaccMallocSplit (book);
+        *split = gnc_tree_model_split_get_blank_split (model);
         xaccSplitSetAccount (*split, anchor);
         xaccSplitSetParent (*split, trans);
         *osplit = xaccMallocSplit (book);
@@ -2547,7 +2606,7 @@
         if (read_only && !open_edited)
             g_object_set(cell, "cell-background", REDCELL, (gchar*)NULL);
         else if (read_only && open_edited)
-            g_object_set(cell, "cell-background", YELLOWCELL, (gchar*)NULL);
+            g_object_set(cell, "cell-background", ORANGECELL, (gchar*)NULL);
         else if (xaccTransInFutureByPostedDate (trans))
             g_object_set(cell, "cell-background", BLUECELL, (gchar*)NULL);
         else
@@ -2851,9 +2910,14 @@
         "The current transaction has changed.  Would you like to "
         "record the changes, or discard the changes?");
 
+    // Look for dirty_trans not being new_trans. 
     if (!view->priv->dirty_trans || view->priv->dirty_trans == new_trans)
         return FALSE;
 
+    // Test if the transaction is balanced.
+    if (gnc_tree_control_split_reg_balance_trans (view, view->priv->dirty_trans))
+        return TRUE;
+
     model = gnc_tree_view_split_reg_get_model_from_view (view);
 
     window = gnc_tree_view_split_reg_get_parent (view);
@@ -2864,10 +2928,11 @@
                                     "%s", title);
     gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
                                              "%s", message);
-    gtk_dialog_add_buttons(
-        GTK_DIALOG(dialog),_("_Discard Changes"), GTK_RESPONSE_REJECT,
-        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-        _("_Record Changes"), GTK_RESPONSE_ACCEPT, NULL);
+
+    gtk_dialog_add_buttons (GTK_DIALOG(dialog),_("_Discard Changes"), GTK_RESPONSE_REJECT,
+                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                            _("_Record Changes"), GTK_RESPONSE_ACCEPT, NULL);
+
     response = gnc_dialog_run (GTK_DIALOG (dialog), "transaction_changed");
     gtk_widget_destroy (dialog);
 
@@ -3820,6 +3885,7 @@
 gtv_split_reg_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
 {
     GncTreeViewSplitReg *view = GNC_TREE_VIEW_SPLIT_REG (widget);
+    GncTreeModelSplitReg *model;
     GtkTreeViewColumn *col;
     GtkTreePath *spath;
 
@@ -3829,6 +3895,8 @@
 
 //g_print("column title is %s and path is %s\n", gtk_tree_view_column_get_title (col), gtk_tree_path_to_string (spath));
 
+    model = gnc_tree_view_split_reg_get_model_from_view (view);
+
     if (event->type != GDK_KEY_PRESS)
         return FALSE;
 
@@ -3878,12 +3946,32 @@
         /* Have we stepped off the end */
         if (!spath || !gnc_tree_view_path_is_valid (GNC_TREE_VIEW (view), spath)) // We have stepped off the end
         {
-            /* no need to restore cursor because we won't move. */
-            //Only ask for confirmation if data was edited
-            if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT(view), "data-edited")))
+            //Ask for confirmation if data has been edited, transaction_changed_confirm return TRUE if canceled
+            if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (view), "data-edited")) && transaction_changed_confirm (view, NULL))
             {
-	        transaction_changed_confirm (GNC_TREE_VIEW_SPLIT_REG (view), NULL);
-                g_object_set_data (G_OBJECT (view), "data-edited", GINT_TO_POINTER (FALSE));
+                /* Restore position - Cancel / Discard */
+                if (view->priv->current_ref != NULL)
+                {
+                    gtk_tree_row_reference_free (view->priv->current_ref);
+                    view->priv->current_ref = NULL;
+                }
+                view->priv->current_ref = gtk_tree_row_reference_copy (view->priv->edit_ref);
+
+                // Jump to the first split of dirty_trans.
+                gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0));
+
+                /* Remove the blank split and re-add - done so we keep it last in list */ 
+                gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, TRUE);
+                gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, FALSE);
+
+//                if (xaccTransCountSplits (view->priv->dirty_trans) > 2) //FIXME Maybe we should just expand for split-trans
+//                {
+                /* give gtk+ a chance to handle pending events */
+                while (gtk_events_pending ())
+                    gtk_main_iteration ();
+
+                gnc_tree_view_split_reg_expand_trans (view, NULL);
+//                }
             }
         }
         else
@@ -3986,14 +4074,28 @@
             }
             view->priv->current_ref = gtk_tree_row_reference_copy (view->priv->edit_ref);
 
-            gnc_tree_view_split_reg_default_selection (view);
+            // Jump to the first split of dirty_trans.
+            gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0));
+
+            /* Remove the blank split and re-add - done so we keep it last in list */ 
+            gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, TRUE);
+            gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, FALSE);
+
+//            if (xaccTransCountSplits (view->priv->dirty_trans) > 2) //FIXME Maybe we should just expand for split-trans
+//            {
+                /* give gtk+ a chance to handle pending events */
+                while (gtk_events_pending ())
+                    gtk_main_iteration ();
+
+                gnc_tree_view_split_reg_expand_trans (view, NULL);
+//            }
+
             return;
         }
         else
-        {
+       {
 //g_print("Commit and skip\n");
             /* Commit and skip */
-
             /* Move the blank split */ 
             gnc_tree_model_split_reg_set_blank_split_parent (model, trans, FALSE);
         }
@@ -4093,10 +4195,6 @@
     model = gnc_tree_view_split_reg_get_model_from_view (view);
     g_return_if_fail (model);
 
-    //FIXME this may be a hack, blank split is not part of blank trans when entering
-    // action field in two line mode..
-    bsplit_action = xaccSplitGetAction (gnc_tree_model_split_get_blank_split (model));
-
     gnc_tree_model_split_reg_get_split_and_trans (
         model, &m_iter, &is_trow1, &is_trow2, &is_split, &is_blank, &split, &trans);
 
@@ -4128,6 +4226,10 @@
             /* set per book option */
             gnc_set_num_action (trans, get_this_split (view, trans),
                                                                 new_text, NULL);
+
+            // Set the last number value for this account.
+            if (gnc_strisnum (new_text))
+                xaccAccountSetLastNum (xaccSplitGetAccount (get_this_split (view, trans)), new_text);
         }
         if (is_trow2)
         {
@@ -4140,7 +4242,13 @@
             /* Set split-action with gnc_set_num_action which is the same as
              * xaccSplitSetAction with these arguments */
             gnc_set_num_action (NULL, split, NULL, new_text);
+
+
+            // Set the last number value for this account.
+            if (gnc_strisnum (new_text))
+                xaccAccountSetLastNum (xaccSplitGetAccount (split), new_text);
         }
+
         break;
 
     case COL_DESCNOTES:
@@ -4200,19 +4308,13 @@
     case COL_DEBIT:
     case COL_CREDIT:
         {
-
             Account       *acct, *old_acct;
             gnc_numeric    input;
             Split         *osplit = NULL;
-            QofBook       *book; //do we have this
-            Account       *root; // do we have this
             gboolean       valid_input = FALSE;
             gboolean       force = FALSE;
             gboolean       input_used = FALSE;
 
-            book = gnc_get_current_book();
-            root = gnc_book_get_root_account (book);
-
             gtv_begin_edit (view, NULL, trans);
 
             /* Get the split pair if anchored to a register */
@@ -4228,10 +4330,12 @@
             /* Setup the account field */
             if (viewcol == COL_TRANSVOID)
             {
-                if (view->priv->acct_short_names)
-                    acct = gnc_account_lookup_by_name (root, new_text);
-                else
-                    acct = gnc_account_lookup_by_full_name (root, new_text);
+                acct = gnc_tree_control_split_reg_get_account_by_name (view, new_text);
+                if (acct == NULL)
+                {
+                    PERR("Account is NULL");
+                    break;
+                }
 
                 if (acct != NULL && is_split)
                 {
@@ -4247,9 +4351,6 @@
                     if (!gnc_commodity_equiv (xaccAccountGetCommodity (old_acct), xaccAccountGetCommodity (acct)))
                         force = TRUE;
                 }
-                //FIXME see above...
-                if (bsplit_action != NULL)
-                    xaccSplitSetAction (split, bsplit_action);
             }
             else
             {
@@ -4356,6 +4457,70 @@
 }
 
 
+/* Callback for Account seperator key */
+static void
+gtv_split_reg_acct_cb (GtkEntry    *entry,
+                          const gchar *text,
+                          gint         length,
+                          gint        *position,
+                          gpointer     user_data)
+{
+    GtkEditable *editable = GTK_EDITABLE (entry);
+    GncTreeViewSplitReg *view = GNC_TREE_VIEW_SPLIT_REG (user_data);
+    GtkEntryCompletion *completion;
+    GtkTreeModel *model;
+    GtkTreeIter  iter;
+
+    const gchar *sep_char;
+    const gchar *entered_string;
+    gchar       *item = NULL;
+    gboolean     valid;
+
+    entered_string = gtk_editable_get_chars (editable, 0, -1);
+
+    sep_char = gnc_get_account_separator_string ();
+
+    if (g_strcmp0 (text, sep_char) != 0) // test for seperator char.
+        return;
+
+    // Get the completion and model
+    completion = gtk_entry_get_completion (entry);
+    model = gtk_entry_completion_get_model (completion);
+
+    // Get the first item in the list
+    valid = gtk_tree_model_get_iter_first (model, &iter);
+    while (valid)
+    {
+        // Walk through the list, reading each row
+        if (view->priv->acct_short_names)
+            gtk_tree_model_get (model, &iter, 0, &item, -1);
+        else
+            gtk_tree_model_get (model, &iter, 1, &item, -1);
+
+        if (g_str_has_prefix (g_utf8_strdown (item, -1), g_utf8_strdown (entered_string, -1)))
+        {
+            if (g_utf8_strlen (entered_string, -1) < g_utf8_strlen (item, -1))
+                 break;
+        }
+        valid = gtk_tree_model_iter_next (model, &iter);
+    }
+
+    g_signal_handlers_block_by_func (editable, (gpointer) gtv_split_reg_acct_cb, user_data);
+
+    gtk_editable_delete_text (editable, 0, -1);
+    gtk_editable_set_position (editable, 0);
+
+    if (strlen (entered_string) == 1)
+        gtk_editable_insert_text (editable, item, -1, position);
+    else
+        gtk_editable_insert_text (editable, g_strconcat(item, sep_char, NULL), -1, position);
+
+    g_signal_handlers_unblock_by_func (editable, (gpointer) gtv_split_reg_acct_cb, user_data);
+
+    g_signal_stop_emission_by_name (editable, "insert_text");
+}
+
+
 /* Callback for changing reconcile setting with space bar */
 static void
 gtv_split_reg_recn_cb (GtkEntry    *entry,
@@ -4503,17 +4668,19 @@
         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);
+        gtk_entry_completion_set_minimum_key_length (completion, 1);
 //??        g_signal_connect(G_OBJECT(completion), "match-selected", (GCallback) gtv_split_reg_match_selected_cb, view);
         g_object_unref (completion);
 
         //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 (GTK_ENTRY (entry)), "insert_text", (GCallback) gtv_split_reg_acct_cb, view);
+
 //??        g_signal_connect (G_OBJECT (cr), "changed", (GCallback) gtv_split_reg_changed_cb, view);
         g_signal_connect (G_OBJECT (editable), "remove-widget", (GCallback) remove_edit_combo, view);
 
-        DEBUG("Current String tv is '%s'", g_strdup(gtk_entry_get_text (entry)));
+        DEBUG("Current String tv is '%s'", g_strdup (gtk_entry_get_text (entry)));
     }
 
     /* NUMBER / ACTION COLUMN */
@@ -4902,7 +5069,6 @@
 void
 gnc_tree_view_split_reg_delete_current_trans (GncTreeViewSplitReg *view)
 {
-    GncTreeModelSplitReg  *model;
     Transaction           *trans;
     gboolean               was_open;
 
@@ -4935,12 +5101,31 @@
 gboolean
 gnc_tree_view_split_reg_enter (GncTreeViewSplitReg *view)
 {
+    GncTreeModelSplitReg  *model;
+
+    model = gnc_tree_view_split_reg_get_model_from_view (view);
+
     /* Make sure we have stopped editing */
     gnc_tree_view_split_reg_finish_edit (view);
 
     /* Ask for confirmation if data has been edited, transaction_changed_confirm return TRUE if canceled */
     if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (view), "data-edited")) && transaction_changed_confirm (view, NULL))
     {
+        // Jump to the first split of dirty_trans.
+        gnc_tree_control_split_reg_jump_to_split (view, xaccTransGetSplit (view->priv->dirty_trans, 0)); 
+
+        /* Remove the blank split and re-add - done so we keep it last in list */ 
+        gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, TRUE);
+        gnc_tree_model_split_reg_set_blank_split_parent (model, view->priv->dirty_trans, FALSE);
+
+//                if (xaccTransCountSplits (view->priv->dirty_trans) > 2) //FIXME Maybe we should just expand for split-trans
+//                {
+        /* give gtk+ a chance to handle pending events */
+        while (gtk_events_pending ())
+             gtk_main_iteration ();
+
+        gnc_tree_view_split_reg_expand_trans (view, NULL);
+//                }
         return FALSE;
     }
     return TRUE;
@@ -4986,6 +5171,11 @@
     view->change_allowed = FALSE;
 
     view->priv->auto_complete = FALSE; // reset auto_complete has run flag
+
+    /* This updates the plugin page gui */
+    if (view->moved_cb)
+        (view->moved_cb)(view, view->moved_cb_data);
+
     LEAVE(" ");
 }
 
@@ -5110,6 +5300,11 @@
     gtk_tree_path_free (spath);
 
     view->priv->expanded = FALSE;
+
+    /* This updates the plugin page gui */
+    if (view->moved_cb)
+        (view->moved_cb)(view, view->moved_cb_data);
+
     LEAVE(" ");
 }
 
@@ -5145,6 +5340,10 @@
     gtk_tree_path_free (mpath);
     gtk_tree_path_free (spath);
 
+    /* This updates the plugin page gui */
+    if (view->moved_cb)
+        (view->moved_cb)(view, view->moved_cb_data);
+
     LEAVE(" ");
 }
 



More information about the gnucash-changes mailing list