r15921 - gnucash/trunk - Move more account properties from the public data structure to a

David Hampton hampton at cvs.gnucash.org
Wed Apr 18 00:50:35 EDT 2007


Author: hampton
Date: 2007-04-18 00:50:34 -0400 (Wed, 18 Apr 2007)
New Revision: 15921
Trac: http://svn.gnucash.org/trac/changeset/15921

Added:
   gnucash/trunk/src/engine/test/test-account-object.c
Modified:
   gnucash/trunk/lib/libqof/qof/gnc-numeric.h
   gnucash/trunk/src/backend/postgres/checkpoint.c
   gnucash/trunk/src/engine/Account.c
   gnucash/trunk/src/engine/Account.h
   gnucash/trunk/src/engine/AccountP.h
   gnucash/trunk/src/engine/Period.c
   gnucash/trunk/src/engine/Scrub2.c
   gnucash/trunk/src/engine/Split.c
   gnucash/trunk/src/engine/cap-gains.c
   gnucash/trunk/src/engine/test/
   gnucash/trunk/src/engine/test/Makefile.am
Log:
Move more account properties from the public data structure to a
private data structure, with access to them as properties of the
object.


Modified: gnucash/trunk/lib/libqof/qof/gnc-numeric.h
===================================================================
--- gnucash/trunk/lib/libqof/qof/gnc-numeric.h	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/lib/libqof/qof/gnc-numeric.h	2007-04-18 04:50:34 UTC (rev 15921)
@@ -451,6 +451,7 @@
   @{
 */
 GType gnc_numeric_get_type( void );
+#define GNC_NUMERIC (gnc_numeric_get_type ())
 
 /** @} */
 

Modified: gnucash/trunk/src/backend/postgres/checkpoint.c
===================================================================
--- gnucash/trunk/src/backend/postgres/checkpoint.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/backend/postgres/checkpoint.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -496,7 +496,11 @@
    cleared_baln = gnc_numeric_create (cl_b, deno);
    reconciled_baln = gnc_numeric_create (rec_b, deno);
 
-   xaccAccountSetStartingBalance (acc, baln, cleared_baln, reconciled_baln);
+   g_object_set(acc,
+                "start-balance", &baln,
+                "start-cleared-balance", &cleared_baln,
+                "start-reconcoled-balance", &reconciled_baln,
+                NULL);
 
    {
         char buf[80];

Modified: gnucash/trunk/src/engine/Account.c
===================================================================
--- gnucash/trunk/src/engine/Account.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/Account.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -128,27 +128,28 @@
     Account *parent;    /* back-pointer to parent */
     GList *children;    /* list of sub-accounts */
 
-//    /* protected data, cached parameters */
-//    gnc_numeric starting_balance;
-//    gnc_numeric starting_cleared_balance;
-//    gnc_numeric starting_reconciled_balance;
-//
-//    gnc_numeric balance;
-//    gnc_numeric cleared_balance;
-//    gnc_numeric reconciled_balance;
+    /* protected data - should only be set by backends */
+    gnc_numeric starting_balance;
+    gnc_numeric starting_cleared_balance;
+    gnc_numeric starting_reconciled_balance;
 
+    /* cached parameters */
+    gnc_numeric balance;
+    gnc_numeric cleared_balance;
+    gnc_numeric reconciled_balance;
+
+    gboolean balance_dirty;     /* balances in splits incorrect */
+
     /* version number, used for tracking multiuser updates */
     gint32 version;
     guint32 version_check;  /* data aging timestamp */
 
-//    SplitList *splits;       /* list of split pointers */
+    GList *splits;              /* list of split pointers */
+    gboolean sort_dirty;        /* sort order of splits is bad */
 
     LotList   *lots;		/* list of lot pointers */
     GNCPolicy *policy;		/* Cached pointer to policy method */
 
-//    gboolean balance_dirty;  /* balances in splits incorrect */
-//    gboolean sort_dirty;     /* sort order of splits is bad */
-
     /* The "mark" flag can be used by the user to mark this account
      * in any way desired.  Handy for specialty traversals of the 
      * account tree. */
@@ -246,17 +247,17 @@
 //    priv->commodity = NULL;
 //    priv->commodity_scu = 0;
 //    priv->non_standard_scu = FALSE;
-//
-//    priv->balance = gnc_numeric_zero();
-//    priv->cleared_balance = gnc_numeric_zero();
-//    priv->reconciled_balance = gnc_numeric_zero();
-//
-//    priv->starting_balance = gnc_numeric_zero();
-//    priv->starting_cleared_balance = gnc_numeric_zero();
-//    priv->starting_reconciled_balance = gnc_numeric_zero();
-//
-//    priv->balance_dirty = FALSE;
-//    priv->sort_dirty = FALSE;
+
+    priv->balance = gnc_numeric_zero();
+    priv->cleared_balance = gnc_numeric_zero();
+    priv->reconciled_balance = gnc_numeric_zero();
+    priv->starting_balance = gnc_numeric_zero();
+    priv->starting_cleared_balance = gnc_numeric_zero();
+    priv->starting_reconciled_balance = gnc_numeric_zero();
+    priv->balance_dirty = FALSE;
+
+    priv->splits = NULL;
+    priv->sort_dirty = FALSE;
  }
 
 static void
@@ -304,6 +305,30 @@
 	    // NEED TO BE CONVERTED TO A G_TYPE_ENUM
 	    g_value_set_int(value, priv->type);
 	    break;
+	case PROP_SORT_DIRTY:
+	    g_value_set_boolean(value, priv->sort_dirty);
+	    break;
+	case PROP_BALANCE_DIRTY:
+	    g_value_set_boolean(value, priv->balance_dirty);
+	    break;
+	case PROP_START_BALANCE:
+	    g_value_set_boxed(value, &priv->starting_balance);
+	    break;
+	case PROP_START_CLEARED_BALANCE:
+	    g_value_set_boxed(value, &priv->starting_cleared_balance);
+	    break;
+	case PROP_START_RECONCILED_BALANCE:
+	    g_value_set_boxed(value, &priv->starting_reconciled_balance);
+	    break;
+	case PROP_END_BALANCE:
+	    g_value_set_boxed(value, &priv->balance);
+	    break;
+	case PROP_END_CLEARED_BALANCE:
+	    g_value_set_boxed(value, &priv->cleared_balance);
+	    break;
+	case PROP_END_RECONCILED_BALANCE:
+	    g_value_set_boxed(value, &priv->reconciled_balance);
+	    break;
 	case PROP_ACCT_VERSION:
 	    g_value_set_int(value, priv->version);
 	    break;
@@ -363,6 +388,24 @@
 	    // NEED TO BE CONVERTED TO A G_TYPE_ENUM
 	    xaccAccountSetType(account, g_value_get_int(value));
 	    break;
+	case PROP_SORT_DIRTY:
+	    gnc_account_set_sort_dirty(account);
+	    break;
+	case PROP_BALANCE_DIRTY:
+	    gnc_account_set_balance_dirty(account);
+	    break;
+	case PROP_START_BALANCE:
+	    number = g_value_get_boxed(value);
+	    gnc_account_set_start_balance(account, *number);
+	    break;
+	case PROP_START_CLEARED_BALANCE:
+	    number = g_value_get_boxed(value);
+	    gnc_account_set_start_cleared_balance(account, *number);
+	    break;
+	case PROP_START_RECONCILED_BALANCE:
+	    number = g_value_get_boxed(value);
+	    gnc_account_set_start_reconciled_balance(account, *number);
+	    break;
 	case PROP_ACCT_VERSION:
 	    xaccAccountSetVersion(account, g_value_get_int(value));
 	    break;
@@ -480,6 +523,120 @@
 
     g_object_class_install_property
 	(gobject_class,
+	 PROP_BALANCE_DIRTY,
+	 g_param_spec_boolean("sort-dirty",
+                              "Sort Dirty",
+                              "TRUE if the splits in the account needs to be "
+                              "resorted.  This flag is set by the accounts "
+                              "code for certain internal modifications, or "
+                              "when external code calls the engine to say a "
+                              "split has been modified in a way that may "
+                              "affect the sort order of the account. Note: "
+                              "This value can only be set to TRUE.",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_BALANCE_DIRTY,
+	 g_param_spec_boolean("balance-dirty",
+                              "Balance Dirty",
+                              "TRUE if the running balances in the account "
+                              "needs to be recalculated.  This flag is set "
+                              "by the accounts code for certain internal "
+                              "modifications, or when external code calls "
+                              "the engine to say a split has been modified. "
+                              "Note: This value can only be set to TRUE.",
+                              FALSE,
+                              G_PARAM_READWRITE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_START_BALANCE,
+	 g_param_spec_boxed("start-balance",
+                            "Starting Balance",
+                            "The starting balance for the account.  This "
+                            "parameter is intended for use with backends that "
+                            "do not return the complete list of splits for an "
+                            "account, but rather return a partial list.  In "
+                            "such a case, the backend will typically return "
+                            "all of the splits after some certain date, and "
+                            "the 'starting balance' will represent the "
+                            "summation of the splits up to that date.",
+                            GNC_NUMERIC,
+                            G_PARAM_READWRITE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_START_CLEARED_BALANCE,
+	 g_param_spec_boxed("start-cleared-balance",
+                            "Starting Cleared Balance",
+                            "The starting cleared balance for the account.  "
+                            "This parameter is intended for use with backends "
+                            "that do not return the complete list of splits "
+                            "for an account, but rather return a partial "
+                            "list.  In such a case, the backend will "
+                            "typically return all of the splits after "
+                            "some certain date, and the 'starting cleared "
+                            "balance' will represent the summation of the "
+                            "splits up to that date.",
+                            GNC_NUMERIC,
+                            G_PARAM_READWRITE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_START_RECONCILED_BALANCE,
+	 g_param_spec_boxed("start-reconciled-balance",
+			    "Starting Reconciled Balance",
+                            "The starting reconciled balance for the "
+                            "account.  This parameter is intended for use "
+                            "with backends that do not return the complete "
+                            "list of splits for an account, but rather return "
+                            "a partial list.  In such a case, the backend "
+                            "will typically return all of the splits after "
+                            "some certain date, and the 'starting recontiled "
+                            "balance' will represent the summation of the "
+                            "splits up to that date.",
+			     GNC_NUMERIC,
+			     G_PARAM_READWRITE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_END_BALANCE,
+	 g_param_spec_boxed("end-balance",
+                            "Ending Account Balance",
+                            "This is the current ending balance for the "
+                            "account.  It is computed from the sum of the "
+                            "starting balance and all splits in the account.",
+                            GNC_NUMERIC,
+                            G_PARAM_READABLE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_END_CLEARED_BALANCE,
+	 g_param_spec_boxed("end-cleared-balance",
+			    "Ending Account Cleared Balance",
+                            "This is the current ending cleared balance for "
+                            "the account.  It is computed from the sum of the "
+                            "starting balance and all cleared splits in the "
+                            "account.",
+                            GNC_NUMERIC,
+                            G_PARAM_READABLE));
+
+    g_object_class_install_property
+	(gobject_class,
+	 PROP_END_RECONCILED_BALANCE,
+	 g_param_spec_boxed("end-reconciled-balance",
+                            "Ending Account Reconciled Balance",
+                            "This is the current ending reconciled balance "
+                            "for the account.  It is computed from the sum of "
+                            "the starting balance and all reconciled splits "
+                            "in the account.",
+                            GNC_NUMERIC,
+                            G_PARAM_READABLE));
+
+    g_object_class_install_property
+	(gobject_class,
 	 PROP_ACCT_VERSION,
 	 g_param_spec_int ("acct-version",
 			   "Version",
@@ -557,25 +714,12 @@
   ENTER ("book=%p\n", book);
   qof_instance_init_data (&acc->inst, GNC_ID_ACCOUNT, book);
 
-  acc->balance = gnc_numeric_zero();
-  acc->cleared_balance = gnc_numeric_zero();
-  acc->reconciled_balance = gnc_numeric_zero();
-
-  acc->starting_balance = gnc_numeric_zero();
-  acc->starting_cleared_balance = gnc_numeric_zero();
-  acc->starting_reconciled_balance = gnc_numeric_zero();
-
   acc->idata = 0;
 
   acc->commodity = NULL;
   acc->commodity_scu = 0;
   acc->non_standard_scu = FALSE;
 
-  acc->splits = NULL;
-
-  acc->balance_dirty = FALSE;
-  acc->sort_dirty = FALSE;
-
   LEAVE ("account=%p\n", acc);
 }
 
@@ -818,7 +962,7 @@
   /* NB there shouldn't be any splits by now ... they should 
    * have been all been freed by CommitEdit().  We can remove this
    * check once we know the warning isn't occurring any more. */
-  if (acc->splits) 
+  if (priv->splits) 
   {
     GList *slist;
     PERR (" instead of calling xaccFreeAccount(), please call \n"
@@ -826,14 +970,14 @@
   
     acc->inst.editlevel = 0;
 
-    slist = g_list_copy(acc->splits);
+    slist = g_list_copy(priv->splits);
     for (lp = slist; lp; lp = lp->next) {
       Split *s = (Split *) lp->data;
       g_assert(xaccSplitGetAccount(s) == acc);
       xaccSplitDestroy (s);
     }
     g_list_free(slist);
-    g_assert(acc->splits == NULL);
+    g_assert(priv->splits == NULL);
   }
 
   CACHE_REPLACE(priv->accountName, NULL);
@@ -847,16 +991,16 @@
   priv->parent = NULL;
   priv->children = NULL;
 
-  acc->balance  = gnc_numeric_zero();
-  acc->cleared_balance = gnc_numeric_zero();
-  acc->reconciled_balance = gnc_numeric_zero();
+  priv->balance  = gnc_numeric_zero();
+  priv->cleared_balance = gnc_numeric_zero();
+  priv->reconciled_balance = gnc_numeric_zero();
 
   priv->type = ACCT_TYPE_NONE;
   acc->commodity = NULL;
 
   priv->version = 0;
-  acc->balance_dirty = FALSE;
-  acc->sort_dirty = FALSE;
+  priv->balance_dirty = FALSE;
+  priv->sort_dirty = FALSE;
 
   /* qof_instance_release (&acc->inst); */
   g_object_unref(acc);
@@ -930,7 +1074,7 @@
     PINFO ("freeing splits for account %p (%s)",
            acc, priv->accountName ? priv->accountName : "(null)");
 
-    slist = g_list_copy(acc->splits);
+    slist = g_list_copy(priv->splits);
     for (lp = slist; lp; lp = lp->next)
     {
       Split *s = lp->data;
@@ -942,7 +1086,7 @@
        deleting all the splits in it.  The splits will just get
        recreated and put right back into the same account!
 
-       g_assert(acc->splits == NULL || qof_book_shutting_down(acc->inst.book));
+       g_assert(priv->splits == NULL || qof_book_shutting_down(acc->inst.book));
     */
 
     if (!qof_book_shutting_down(acc->inst.book)) {
@@ -1143,13 +1287,13 @@
     return FALSE;
   }
 
-  if (!gnc_numeric_equal (aa->starting_balance, ab->starting_balance))
+  if (!gnc_numeric_equal(priv_aa->starting_balance, priv_ab->starting_balance))
   {
     char *str_a;
     char *str_b;
 
-    str_a = gnc_numeric_to_string (aa->starting_balance);
-    str_b = gnc_numeric_to_string (ab->starting_balance);
+    str_a = gnc_numeric_to_string(priv_aa->starting_balance);
+    str_b = gnc_numeric_to_string(priv_ab->starting_balance);
 
     PWARN ("starting balances differ: %s vs %s", str_a, str_b);
 
@@ -1159,14 +1303,14 @@
     return FALSE;
   }
 
-  if (!gnc_numeric_equal (aa->starting_cleared_balance,
-                          ab->starting_cleared_balance))
+  if (!gnc_numeric_equal(priv_aa->starting_cleared_balance,
+                         priv_ab->starting_cleared_balance))
   {
     char *str_a;
     char *str_b;
 
-    str_a = gnc_numeric_to_string (aa->starting_cleared_balance);
-    str_b = gnc_numeric_to_string (ab->starting_cleared_balance);
+    str_a = gnc_numeric_to_string(priv_aa->starting_cleared_balance);
+    str_b = gnc_numeric_to_string(priv_ab->starting_cleared_balance);
 
     PWARN ("starting cleared balances differ: %s vs %s", str_a, str_b);
 
@@ -1176,14 +1320,14 @@
     return FALSE;
   }
 
-  if (!gnc_numeric_equal (aa->starting_reconciled_balance,
-                          ab->starting_reconciled_balance))
+  if (!gnc_numeric_equal(priv_aa->starting_reconciled_balance,
+                         priv_ab->starting_reconciled_balance))
   {
     char *str_a;
     char *str_b;
 
-    str_a = gnc_numeric_to_string (aa->starting_reconciled_balance);
-    str_b = gnc_numeric_to_string (ab->starting_reconciled_balance);
+    str_a = gnc_numeric_to_string(priv_aa->starting_reconciled_balance);
+    str_b = gnc_numeric_to_string(priv_ab->starting_reconciled_balance);
 
     PWARN ("starting reconciled balances differ: %s vs %s", str_a, str_b);
 
@@ -1193,13 +1337,13 @@
     return FALSE;
   }
 
-  if (!gnc_numeric_equal (aa->balance, ab->balance))
+  if (!gnc_numeric_equal(priv_aa->balance, priv_ab->balance))
   {
     char *str_a;
     char *str_b;
 
-    str_a = gnc_numeric_to_string (aa->balance);
-    str_b = gnc_numeric_to_string (ab->balance);
+    str_a = gnc_numeric_to_string(priv_aa->balance);
+    str_b = gnc_numeric_to_string(priv_ab->balance);
 
     PWARN ("balances differ: %s vs %s", str_a, str_b);
 
@@ -1209,13 +1353,13 @@
     return FALSE;
   }
 
-  if (!gnc_numeric_equal (aa->cleared_balance, ab->cleared_balance))
+  if (!gnc_numeric_equal(priv_aa->cleared_balance, priv_ab->cleared_balance))
   {
     char *str_a;
     char *str_b;
 
-    str_a = gnc_numeric_to_string (aa->cleared_balance);
-    str_b = gnc_numeric_to_string (ab->cleared_balance);
+    str_a = gnc_numeric_to_string(priv_aa->cleared_balance);
+    str_b = gnc_numeric_to_string(priv_ab->cleared_balance);
 
     PWARN ("cleared balances differ: %s vs %s", str_a, str_b);
 
@@ -1225,13 +1369,13 @@
     return FALSE;
   }
 
-  if (!gnc_numeric_equal (aa->reconciled_balance, ab->reconciled_balance))
+  if (!gnc_numeric_equal(priv_aa->reconciled_balance, priv_ab->reconciled_balance))
   {
     char *str_a;
     char *str_b;
 
-    str_a = gnc_numeric_to_string (aa->reconciled_balance);
-    str_b = gnc_numeric_to_string (ab->reconciled_balance);
+    str_a = gnc_numeric_to_string(priv_aa->reconciled_balance);
+    str_b = gnc_numeric_to_string(priv_ab->reconciled_balance);
 
     PWARN ("reconciled balances differ: %s vs %s", str_a, str_b);
 
@@ -1244,8 +1388,8 @@
   /* no parent; always compare downwards. */
 
   {
-    GList *la = aa->splits;
-    GList *lb = ab->splits;
+    GList *la = priv_aa->splits;
+    GList *lb = priv_ab->splits;
 
     if ((la && !lb) || (!la && lb))
     {
@@ -1290,14 +1434,137 @@
 
 /********************************************************************\
 \********************************************************************/
+
+gboolean
+gnc_account_get_sort_dirty (Account *acc)
+{
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    return GET_PRIVATE(acc)->sort_dirty;
+}
+                            
 void
+gnc_account_set_sort_dirty (Account *acc)
+{
+    AccountPrivate *priv;
+
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
+
+    if (acc->inst.do_free)
+	return;
+
+    priv = GET_PRIVATE(acc);
+    priv->sort_dirty = TRUE;
+}
+
+gboolean
+gnc_account_get_balance_dirty (Account *acc)
+{
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    return GET_PRIVATE(acc)->balance_dirty;
+}
+
+void
+gnc_account_set_balance_dirty (Account *acc)
+{
+    AccountPrivate *priv;
+
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
+
+    if (acc->inst.do_free)
+	return;
+
+    priv = GET_PRIVATE(acc);
+    priv->balance_dirty = TRUE;
+}
+
+/********************************************************************\
+\********************************************************************/
+
+gboolean
+gnc_account_find_split (Account *acc, Split *s)
+{
+    AccountPrivate *priv;
+    GList *node;
+
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
+
+    priv = GET_PRIVATE(acc);
+    node = g_list_find(priv->splits, s);
+    return node ? TRUE : FALSE;
+}
+
+gboolean
+gnc_account_insert_split (Account *acc, Split *s)
+{
+    AccountPrivate *priv;
+    GList *node;
+
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
+
+    priv = GET_PRIVATE(acc);
+    node = g_list_find(priv->splits, s);
+    if (node)
+	return FALSE;
+
+    if (acc->inst.editlevel == 0) {
+	priv->splits = g_list_insert_sorted(priv->splits, s,
+					   (GCompareFunc)xaccSplitOrder);
+    } else {
+	priv->splits = g_list_prepend(priv->splits, s);
+	priv->sort_dirty = TRUE;
+    }
+
+    //FIXME: find better event
+    qof_event_gen (&acc->inst, QOF_EVENT_MODIFY, NULL);
+    /* Also send an event based on the account */
+    qof_event_gen(&acc->inst, GNC_EVENT_ITEM_ADDED, s);
+
+    priv->balance_dirty = TRUE;
+//  DRH: Should the below be added? It is present in the delete path.
+//  xaccAccountRecomputeBalance(acc);
+    return TRUE;
+}
+
+gboolean
+gnc_account_remove_split (Account *acc, Split *s)
+{
+    AccountPrivate *priv;
+    GList *node;
+
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_return_val_if_fail(GNC_IS_SPLIT(s), FALSE);
+
+    priv = GET_PRIVATE(acc);
+    node = g_list_find(priv->splits, s);
+    if (NULL == node)
+	return FALSE;
+
+    priv->splits = g_list_delete_link(priv->splits, node);
+    //FIXME: find better event type
+    qof_event_gen(&acc->inst, QOF_EVENT_MODIFY, NULL);
+    // And send the account-based event, too
+    qof_event_gen(&acc->inst, GNC_EVENT_ITEM_REMOVED, s);
+
+    priv->balance_dirty = TRUE;
+    xaccAccountRecomputeBalance(acc);
+    return TRUE;
+}
+
+void
 xaccAccountSortSplits (Account *acc, gboolean force)
 {
-  if (!acc || !acc->sort_dirty || (!force && acc->inst.editlevel > 0)) return;
+    AccountPrivate *priv;
 
-  acc->splits = g_list_sort(acc->splits, (GCompareFunc)xaccSplitOrder);
-  acc->sort_dirty = FALSE;
-  acc->balance_dirty = TRUE;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
+
+    priv = GET_PRIVATE(acc);
+    if (!priv->sort_dirty || (!force && acc->inst.editlevel > 0))
+        return;
+    priv->splits = g_list_sort(priv->splits, (GCompareFunc)xaccSplitOrder);
+    priv->sort_dirty = FALSE;
+    priv->balance_dirty = TRUE;
 }
 
 static void
@@ -1494,7 +1761,7 @@
   /* optimizations */
   from_priv = GET_PRIVATE(accfrom);
   to_priv = GET_PRIVATE(accto);
-  if (!accfrom->splits || accfrom == accto)
+  if (!from_priv->splits || accfrom == accto)
       return;
 
   /* check for book mix-up */
@@ -1504,27 +1771,27 @@
   xaccAccountBeginEdit(accfrom);
   xaccAccountBeginEdit(accto);
   /* Begin editing both accounts and all transactions in accfrom. */
-  g_list_foreach(accfrom->splits, (GFunc)xaccPreSplitMove, NULL);
+  g_list_foreach(from_priv->splits, (GFunc)xaccPreSplitMove, NULL);
 
   /* Concatenate accfrom's lists of splits and lots to accto's lists. */
-  //accto->splits = g_list_concat(accto->splits, accfrom->splits);
+  //to_priv->splits = g_list_concat(to_priv->splits, from_priv->splits);
   //to_priv->lots = g_list_concat(to_priv->lots, from_priv->lots);
 
   /* Set appropriate flags. */
-  //accfrom->balance_dirty = TRUE;
-  //accfrom->sort_dirty = FALSE;
-  //accto->balance_dirty = TRUE;
-  //accto->sort_dirty = TRUE;
+  //from_priv->balance_dirty = TRUE;
+  //from_priv->sort_dirty = FALSE;
+  //to_priv->balance_dirty = TRUE;
+  //to_priv->sort_dirty = TRUE;
 
   /*
    * Change each split's account back pointer to accto.
    * Convert each split's amount to accto's commodity.
    * Commit to editing each transaction.
    */
-  g_list_foreach(accfrom->splits, (GFunc)xaccPostSplitMove, (gpointer)accto);
+  g_list_foreach(from_priv->splits, (GFunc)xaccPostSplitMove, (gpointer)accto);
 
   /* Finally empty accfrom. */
-  g_assert(accfrom->splits == NULL);
+  g_assert(from_priv->splits == NULL);
   g_assert(from_priv->lots == NULL);
   xaccAccountCommitEdit(accfrom);
   xaccAccountCommitEdit(accto);
@@ -1575,17 +1842,17 @@
 
   priv = GET_PRIVATE(acc);
   if (acc->inst.editlevel > 0) return;
-  if (!acc->balance_dirty) return;
+  if (!priv->balance_dirty) return;
   if (acc->inst.do_free) return;
   if (qof_book_shutting_down(acc->inst.book)) return;
 
-  balance            = acc->starting_balance;
-  cleared_balance    = acc->starting_cleared_balance;
-  reconciled_balance = acc->starting_reconciled_balance;
+  balance            = priv->starting_balance;
+  cleared_balance    = priv->starting_cleared_balance;
+  reconciled_balance = priv->starting_reconciled_balance;
 
   PINFO ("acct=%s starting baln=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT,
 	 priv->accountName, balance.num, balance.denom);
-  for(lp = acc->splits; lp; lp = lp->next) 
+  for(lp = priv->splits; lp; lp = lp->next) 
   {
     Split *split = (Split *) lp->data;
     gnc_numeric amt = xaccSplitGetAmount (split);
@@ -1611,35 +1878,15 @@
     last_split = split;
   }
 
-  acc->balance = balance;
-  acc->cleared_balance = cleared_balance;
-  acc->reconciled_balance = reconciled_balance;
-
-  acc->balance_dirty = FALSE;
-
+  priv->balance = balance;
+  priv->cleared_balance = cleared_balance;
+  priv->reconciled_balance = reconciled_balance;
+  priv->balance_dirty = FALSE;
 }
 
 /********************************************************************\
 \********************************************************************/
 
-void 
-xaccAccountSetStartingBalance(Account *acc,
-                              const gnc_numeric start_baln,
-                              const gnc_numeric start_cleared_baln,
-                              const gnc_numeric start_reconciled_baln)  
-{
-  if (!acc) return;
-
-  acc->starting_balance = start_baln;
-  acc->starting_cleared_balance = start_cleared_baln;
-  acc->starting_reconciled_balance = start_reconciled_baln;
-
-  acc->balance_dirty = TRUE;
-}
-
-/********************************************************************\
-\********************************************************************/
-
 /* The sort order is used to implicitly define an 
  * order for report generation */
 
@@ -1741,7 +1988,7 @@
 
   xaccAccountBeginEdit(acc);
   priv->type = tip;
-  acc->balance_dirty = TRUE; /* new type may affect balance computation */
+  priv->balance_dirty = TRUE; /* new type may affect balance computation */
   mark_account(acc);
   xaccAccountCommitEdit(acc);
 }
@@ -1841,9 +2088,11 @@
 void 
 xaccAccountSetCommodity (Account * acc, gnc_commodity * com) 
 {
+  AccountPrivate *priv;
   GList *lp;
   if (!acc || !com || com == acc->commodity) return;
 
+  priv = GET_PRIVATE(acc);
   xaccAccountBeginEdit(acc);
 
   acc->commodity = com;
@@ -1851,7 +2100,7 @@
   acc->non_standard_scu = FALSE;
 
   /* iterate over splits */
-  for (lp = acc->splits; lp; lp = lp->next)
+  for (lp = priv->splits; lp; lp = lp->next)
   {
       Split *s = (Split *) lp->data;
       Transaction *trans = xaccSplitGetParent (s);
@@ -1861,8 +2110,8 @@
       xaccTransCommitEdit (trans);
   }
 
-  acc->sort_dirty = TRUE;  /* Not needed. */
-  acc->balance_dirty = TRUE;
+  priv->sort_dirty = TRUE;  /* Not needed. */
+  priv->balance_dirty = TRUE;
   mark_account (acc);
 
   if (gnc_commodity_is_iso(com)) {
@@ -2531,27 +2780,96 @@
   return acc ? acc->commodity : NULL;
 }
 
+/********************************************************************\
+\********************************************************************/
+
+gnc_numeric 
+gnc_account_get_start_balance (Account *acc)
+{
+  g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
+
+  return GET_PRIVATE(acc)->starting_balance;
+}
+
+void 
+gnc_account_set_start_balance (Account *acc, const gnc_numeric start_baln)
+{
+  AccountPrivate *priv;
+
+  g_return_if_fail(GNC_IS_ACCOUNT(acc));
+
+  priv = GET_PRIVATE(acc);
+  priv->starting_balance = start_baln;
+  priv->balance_dirty = TRUE;
+}
+
+gnc_numeric 
+gnc_account_get_start_cleared_balance (Account *acc)
+{
+  g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
+
+  return GET_PRIVATE(acc)->starting_cleared_balance;
+}
+
+void 
+gnc_account_set_start_cleared_balance (Account *acc,
+				       const gnc_numeric start_baln)
+{
+  AccountPrivate *priv;
+
+  g_return_if_fail(GNC_IS_ACCOUNT(acc));
+
+  priv = GET_PRIVATE(acc);
+  priv->starting_balance = start_baln;
+  priv->balance_dirty = TRUE;
+}
+
+gnc_numeric 
+gnc_account_get_start_reconciled_balance (Account *acc)
+{
+  g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
+
+  return GET_PRIVATE(acc)->starting_reconciled_balance;
+}
+
+void 
+gnc_account_set_start_reconciled_balance (Account *acc,
+					  const gnc_numeric start_baln)
+{
+  AccountPrivate *priv;
+
+  g_return_if_fail(GNC_IS_ACCOUNT(acc));
+
+  priv = GET_PRIVATE(acc);
+  priv->starting_balance = start_baln;
+  priv->balance_dirty = TRUE;
+}
+
 gnc_numeric
 xaccAccountGetBalance (const Account *acc) 
 {
-  return acc ? acc->balance : gnc_numeric_zero();
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
+    return GET_PRIVATE(acc)->balance;
 }
 
 gnc_numeric
 xaccAccountGetClearedBalance (const Account *acc)
 {
-  return acc ? acc->cleared_balance : gnc_numeric_zero();
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
+    return GET_PRIVATE(acc)->cleared_balance;
 }
 
 gnc_numeric
 xaccAccountGetReconciledBalance (const Account *acc)
 {
-  return acc ? acc->reconciled_balance : gnc_numeric_zero();
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), gnc_numeric_zero());
+    return GET_PRIVATE(acc)->reconciled_balance;
 }
 
 gnc_numeric
 xaccAccountGetProjectedMinimumBalance (const Account *acc)
 {
+  AccountPrivate *priv;
   GList *node;
   time_t today;
   gnc_numeric lowest = gnc_numeric_zero ();
@@ -2559,8 +2877,9 @@
 
   if (!acc) return gnc_numeric_zero ();
 
+  priv = GET_PRIVATE(acc);
   today = gnc_timet_get_today_end();
-  for (node = g_list_last (acc->splits); node; node = node->prev)
+  for (node = g_list_last(priv->splits); node; node = node->prev)
   {
     Split *split = node->data;
 
@@ -2592,6 +2911,7 @@
    * xaccAccountForEachTransaction by using gpointer return
    * values rather than gints.
    */
+  AccountPrivate *priv;
   GList   *lp;
   Timespec ts, trans_ts;
   gboolean found = FALSE;
@@ -2602,7 +2922,8 @@
   xaccAccountSortSplits (acc, TRUE); /* just in case, normally a noop */
   xaccAccountRecomputeBalance (acc); /* just in case, normally a noop */
 
-  balance = acc->balance;
+  priv = GET_PRIVATE(acc);
+  balance = priv->balance;
 
   /* Since transaction post times are stored as a Timespec,
    * convert date into a Timespec as well rather than converting
@@ -2619,7 +2940,7 @@
   ts.tv_sec = date;
   ts.tv_nsec = 0;
 
-  lp = acc->splits;
+  lp = priv->splits;
   while( lp && !found )
   {
     xaccTransGetDatePostedTS( xaccSplitGetParent( (Split *)lp->data ),
@@ -2661,13 +2982,15 @@
 gnc_numeric
 xaccAccountGetPresentBalance (const Account *acc)
 {
+  AccountPrivate *priv;
   GList *node;
   time_t today;
 
   g_return_val_if_fail(acc, gnc_numeric_zero());
 
+  priv = GET_PRIVATE(acc);
   today = gnc_timet_get_today_end();
-  for (node = g_list_last (acc->splits); node; node = node->prev)
+  for (node = g_list_last(priv->splits); node; node = node->prev)
   {
     Split *split = node->data;
 
@@ -2961,11 +3284,20 @@
 /********************************************************************\
 \********************************************************************/
 
+/* THIS API NEEDS TO CHANGE.
+ *
+ * This code exposes the internal structure of the account object to
+ * external callers by returning the actual list used by the object.
+ * It should instead return a copy of the split list that the caller
+ * is required to free.  That change would provide the freedom of
+ * allowing the internal organization to change data structures if
+ * necessary for whatever reason, while leaving the external API
+ * unchanged. */
 SplitList *
 xaccAccountGetSplitList (const Account *acc) 
 {
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
-    return acc->splits;
+    return GET_PRIVATE(acc)->splits;
 }
 
 LotList *
@@ -3755,6 +4087,7 @@
 finder_help_function(const Account *acc, const char *description,
                      Split **split, Transaction **trans )
 {
+  AccountPrivate *priv;
   GList *slp;
 
   /* First, make sure we set the data to NULL BEFORE we start */
@@ -3767,7 +4100,8 @@
   /* Why is this loop iterated backwards ?? Presumably because the split
    * list is in date order, and the most recent matches should be 
    * returned!?  */
-  for (slp = g_list_last (acc->splits); slp; slp = slp->prev) {
+  priv = GET_PRIVATE(acc);
+  for (slp = g_list_last(priv->splits); slp; slp = slp->prev) {
     Split *lsplit = slp->data;
     Transaction *ltrans = xaccSplitGetParent(lsplit);
 
@@ -3933,8 +4267,8 @@
       gnc_account_merge_children (acc_a);
 
       /* consolidate transactions */
-      while (acc_b->splits)
-	xaccSplitSetAccount (acc_b->splits->data, acc_a);
+      while (priv_b->splits)
+	xaccSplitSetAccount (priv_b->splits->data, acc_a);
 
       /* move back one before removal. next iteration around the loop
        * will get the node after node_b */
@@ -3971,8 +4305,12 @@
 void
 xaccAccountBeginStagedTransactionTraversals (const Account *account)
 {
-  if (account)
-      xaccSplitsBeginStagedTransactionTraversals (account->splits);
+    AccountPrivate *priv;
+
+    if (!account)
+        return;
+    priv = GET_PRIVATE(account);
+    xaccSplitsBeginStagedTransactionTraversals(priv->splits);
 }
 
 gboolean
@@ -4005,7 +4343,8 @@
 
 static void do_one_account (Account *account, gpointer data)
 {
-  g_list_foreach(account->splits, (GFunc)do_one_split, NULL);
+    AccountPrivate *priv = GET_PRIVATE(account);
+    g_list_foreach(priv->splits, (GFunc)do_one_split, NULL);
 }
 
 /* Replacement for xaccGroupBeginStagedTransactionTraversals */
@@ -4025,6 +4364,7 @@
                                        TransactionCallback thunk,
                                        void *cb_data)
 {
+  AccountPrivate *priv;
   GList *split_p;
   Transaction *trans;
   Split *s;
@@ -4032,7 +4372,8 @@
 
   if (!acc) return 0;
 
-  for(split_p = acc->splits; split_p; split_p = g_list_next(split_p)) {
+  priv = GET_PRIVATE(acc);
+  for(split_p = priv->splits; split_p; split_p = g_list_next(split_p)) {
     s = split_p->data;
     trans = s->parent;   
     if (trans && (trans->marker < stage)) {
@@ -4070,7 +4411,7 @@
   }
 
   /* Now this account */
-  for(split_p = acc->splits; split_p; split_p = g_list_next(split_p)) {
+  for(split_p = priv->splits; split_p; split_p = g_list_next(split_p)) {
     s = split_p->data;
     trans = s->parent;   
     if (trans && (trans->marker < stage)) {

Modified: gnucash/trunk/src/engine/Account.h
===================================================================
--- gnucash/trunk/src/engine/Account.h	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/Account.h	2007-04-18 04:50:34 UTC (rev 15921)
@@ -275,6 +275,80 @@
 /** Is the account a stock, mutual fund or currency? */
 gboolean xaccAccountIsPriced(const Account *acc);
 
+/** This function will set the starting commodity balance for this
+ *  account.  This routine is intended for use with backends that do
+ *  not return the complete list of splits for an account, but rather
+ *  return a partial list.  In such a case, the backend will typically
+ *  return all of the splits after some certain date, and the
+ *  'starting balance' will represent the summation of the splits up
+ *  to that date. */
+void gnc_account_set_start_balance (Account *acc,
+                                    const gnc_numeric start_baln);
+
+/** This function will set the starting cleared commodity balance for
+ *  this account.  This routine is intended for use with backends that
+ *  do not return the complete list of splits for an account, but
+ *  rather return a partial list.  In such a case, the backend will
+ *  typically return all of the splits after some certain date, and
+ *  the 'starting balance' will represent the summation of the splits
+ *  up to that date. */
+void gnc_account_set_start_cleared_balance (Account *acc,
+                                            const gnc_numeric start_baln);
+
+/** This function will set the starting reconciled commodity balance
+ *  for this account.  This routine is intended for use with backends
+ *  that do not return the complete list of splits for an account, but
+ *  rather return a partial list.  In such a case, the backend will
+ *  typically return all of the splits after some certain date, and
+ *  the 'starting balance' will represent the summation of the splits
+ *  up to that date. */
+void gnc_account_set_start_reconciled_balance (Account *acc,
+                                               const gnc_numeric start_baln);
+
+/** Tell the account that the running balances may be incorrect and
+ *  need to be recomputed.
+ *
+ *  @param acc Set the flag on this account. */
+void gnc_account_set_balance_dirty (Account *acc);
+
+/** Tell the account believes that the splits may be incorrectly
+ *  sorted and need to be resorted.
+ *
+ *  @param acc Set the flag on this account. */
+void gnc_account_set_sort_dirty (Account *acc);
+
+/** Find the given split in an account.
+ *
+ *  @param acc The account whose splits are to be searched.
+ *
+ *  @param s The split to be found.
+ *
+ *  @result TRUE is the split is found in the accounts list of splits.
+ *  FALSE otherwise.  */
+gboolean gnc_account_find_split (Account *acc, Split *s);
+
+/** Insert the given split from an account.
+ *
+ *  @param acc The account to which the split should be added.
+ *
+ *  @param s The split to be added.
+ *
+ *  @result TRUE is the split is successfully added to the set of
+ *  splits in the account.  FALSE if the addition fails for any reason
+ *  (including that the split is already in the account). */
+gboolean gnc_account_insert_split (Account *acc, Split *s);
+
+/** Remove the given split from an account.
+ *
+ *  @param acc The account from which the split should be removed.
+ *
+ *  @param s The split to be removed.
+ *
+ *  @result TRUE is the split is successfully removed from the set of
+ *  splits in the account.  FALSE if the removal fails for any
+ *  reason. */
+gboolean gnc_account_remove_split (Account *acc, Split *s);
+
 /** Get the account's name */
 const char * xaccAccountGetName (const Account *account);
 /** Get the account's accounting code */
@@ -292,7 +366,46 @@
 gint32 xaccAccountGetVersion (const Account* acc);
 /** Get the account version_check number */
 guint32 gnc_account_get_version_check (const Account *acc);
+/** Retrieve the starting commodity balance for this account. */
+gnc_numeric gnc_account_get_start_balance (Account *acc);
 
+/** Retrieve the starting cleared commodity balance for this
+ *  account. */
+gnc_numeric gnc_account_get_start_cleared_balance (Account *acc);
+
+/** Retrieve the starting reconciled commodity balance for this
+ *  account. */
+gnc_numeric gnc_account_get_start_reconciled_balance (Account *acc);
+
+/** Get an indication of whether the account believes that the running
+ *  balances may be incorrect and need to be recomputed.
+ *
+ *  @param acc Retrieve the flag on this account.
+ *
+ *  @return TRUE if the running account balances need to be recomputed.
+ *  FALSE if they are correct. */
+gboolean gnc_account_get_balance_dirty (Account *acc);
+
+/** Get an indication of whether the account believes that the splits
+ *  may be incorrectly sorted and need to be resorted.
+ *
+ *  @param acc Retrieve the flag on this account.
+ *
+ *  @return TRUE if the splits in the account need to be resorted.
+ *  FALSE if the sort order is correct. */
+gboolean gnc_account_get_sort_dirty (Account *acc);
+
+/** The following recompute the partial balances (stored with the
+ *  transaction) and the total balance, for this account 
+ */
+void xaccAccountRecomputeBalance (Account *);
+
+/** The xaccAccountSortSplits() routine will resort the account's 
+ *  splits if the sort is dirty. If 'force' is true, the account 
+ *  is sorted even if the editlevel is not zero. 
+ */
+void xaccAccountSortSplits (Account *acc, gboolean force);
+
 /** The xaccAccountGetFullName routine returns the fully qualified name
  * of the account using the given separator char. The name must be
  * g_free'd after use. The fully qualified name of an account is the
@@ -864,7 +977,11 @@
  *    data structure: do not delete it when done; treat it as a read-only
  *    structure.  Note that some routines (such as xaccAccountRemoveSplit())
  *    modify this list directly, and could leave you with a corrupted 
- *    pointer. */
+ *    pointer.
+ * @note This should be changed so that the returned value is a copy
+ * of the list. No other part of the code should have access to the
+ * internal data structure used by this object.
+ */
 SplitList* xaccAccountGetSplitList (const Account *account);
 
 /** The xaccAccountMoveAllSplits() routine reassigns each of the splits

Modified: gnucash/trunk/src/engine/AccountP.h
===================================================================
--- gnucash/trunk/src/engine/AccountP.h	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/AccountP.h	2007-04-18 04:50:34 UTC (rev 15921)
@@ -65,58 +65,16 @@
   int commodity_scu;
   gboolean non_standard_scu;
 
-  /* protected data, cached parameters */
-  gnc_numeric starting_balance;
-  gnc_numeric starting_cleared_balance;
-  gnc_numeric starting_reconciled_balance;
-
-  gnc_numeric balance;
-  gnc_numeric cleared_balance;
-  gnc_numeric reconciled_balance;
-
-  SplitList *splits;       /* list of split pointers */
-
-  gboolean balance_dirty;  /* balances in splits incorrect */
-  gboolean sort_dirty;     /* sort order of splits is bad */
-
   /* -------------------------------------------------------------- */
   /* Backend private expansion data */
   guint32  idata;     /* used by the sql backend for kvp management */
 };
 
-/* The xaccAccountSortSplits() routine will resort the account's 
- * splits if the sort is dirty. If 'force' is true, the account 
- * is sorted even if the editlevel is not zero. 
- */
-void xaccAccountSortSplits (Account *acc, gboolean force);
-
-/* The following recompute the partial balances (stored with the
- * transaction) and the total balance, for this account 
- */
-void xaccAccountRecomputeBalance (Account *);
-
 /* Set the account's GUID. This should only be done when reading
  * an account from a datafile, or some other external source. Never
  * call this on an existing account! */
 void xaccAccountSetGUID (Account *account, const GUID *guid);
 
-/* The xaccAccountSetStartingBalance() routine will set the starting
- *    commodity balance for this account.  This routine is intended for
- *    use with backends that do not return the complete list of splits
- *    for an account, but rather return a partial list.  In such a case,
- *    the backend will typically return all of the splits after some 
- *    certain date, and the 'starting balance' will represent the summation 
- *    of the splits up to that date.
- *
- *    This routine is in the private .h file because only backends are 
- *    allowed to set the starting balance.  This is *not* a user interface
- *    function.
- */
-void xaccAccountSetStartingBalance(Account *account, 
-                                   const gnc_numeric start_baln, 
-                                   const gnc_numeric start_cleared_baln, 
-                                   const gnc_numeric start_reconciled_baln); 
-
 /* Register Accounts with the engine */
 gboolean xaccAccountRegister (void);
 

Modified: gnucash/trunk/src/engine/Period.c
===================================================================
--- gnucash/trunk/src/engine/Period.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/Period.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -112,8 +112,7 @@
       else
       {
         xaccAccountInsertSplit (twin, s);
-        twin->balance_dirty = TRUE;
-        twin->sort_dirty = TRUE;
+        g_object_set(twin, "sort-dirty", TRUE, "balance-dirty", TRUE, NULL);
       }
    }
 
@@ -179,8 +178,7 @@
         if (s->acc != twin)
         {
            xaccAccountInsertSplit (twin, s);
-           twin->balance_dirty = TRUE;
-           twin->sort_dirty = TRUE;
+           g_object_set(twin, "sort-dirty", TRUE, "balance-dirty", TRUE, NULL);
         }
       }
    }

Modified: gnucash/trunk/src/engine/Scrub2.c
===================================================================
--- gnucash/trunk/src/engine/Scrub2.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/Scrub2.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -57,7 +57,7 @@
 void
 xaccAccountAssignLots (Account *acc)
 {
-   SplitList *node;
+   SplitList *splits, *node;
 
    if (!acc) return;
 
@@ -65,7 +65,8 @@
    xaccAccountBeginEdit (acc);
 
 restart_loop:
-   for (node=acc->splits; node; node=node->next)
+   splits = xaccAccountGetSplitList(acc);
+   for (node=splits; node; node=node->next)
    {
       Split * split = node->data;
 

Modified: gnucash/trunk/src/engine/Split.c
===================================================================
--- gnucash/trunk/src/engine/Split.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/Split.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -296,17 +296,11 @@
   g_object_unref(split);
 }
 
-static void mark_acc(Account *acc)
-{
-    if (acc && !acc->inst.do_free) {
-        acc->balance_dirty = TRUE;
-        acc->sort_dirty = TRUE;
-    }
-}
-
 void mark_split (Split *s)
 {
-  mark_acc(s->acc);
+  if (s->acc) {
+    g_object_set(s->acc, "sort-dirty", TRUE, "balance-dirty", TRUE, NULL);
+  }
 
   /* set dirty flag on lot too. */
   if (s->lot) s->lot->is_closed = -1;
@@ -526,41 +520,21 @@
 
     /* Possibly remove the split from the original account... */
     if (orig_acc && (orig_acc != acc || s->inst.do_free)) {
-        GList *node = g_list_find (orig_acc->splits, s);
-        if (node) {
-            orig_acc->splits = g_list_delete_link (orig_acc->splits, node);
-            //FIXME: find better event type
-            qof_event_gen (&orig_acc->inst, QOF_EVENT_MODIFY, NULL);
-	    // And send the account-based event, too
-	    qof_event_gen(&orig_acc->inst, GNC_EVENT_ITEM_REMOVED, s);
-        } else PERR("Account lost track of moved or deleted split.");
-        orig_acc->balance_dirty = TRUE;
-        xaccAccountRecomputeBalance(orig_acc);
+        if (!gnc_account_remove_split(orig_acc, s)) {
+          PERR("Account lost track of moved or deleted split.");
+        }
     }
 
     /* ... and insert it into the new account if needed */
-    if (orig_acc != s->acc && !s->inst.do_free) {
-        if (!g_list_find(acc->splits, s)) {
-            if (acc->inst.editlevel == 0) {
-                acc->splits = g_list_insert_sorted(
-                    acc->splits, s, (GCompareFunc)xaccSplitOrder);
-            } else {
-                acc->splits = g_list_prepend(acc->splits, s);
-                acc->sort_dirty = TRUE;
-            }
-
+    if (acc && (orig_acc != acc) && !s->inst.do_free) {
+        if (gnc_account_insert_split(acc, s)) {
             /* If the split's lot belonged to some other account, we
                leave it so. */
             if (s->lot && (NULL == s->lot->account))
                 xaccAccountInsertLot (acc, s->lot);
-
-            //FIXME: find better event
-            qof_event_gen (&acc->inst, QOF_EVENT_MODIFY, NULL);
-
-	    /* Also send an event based on the account */
-	    qof_event_gen(&acc->inst, GNC_EVENT_ITEM_ADDED, s);
-        } else PERR("Account grabbed split prematurely.");
-        acc->balance_dirty = TRUE;
+        } else {
+            PERR("Account grabbed split prematurely.");
+        }
         xaccSplitSetAmount(s, xaccSplitGetAmount(s));
     }
 
@@ -585,8 +559,10 @@
     /* This is because Splits don't call qof_commit_edit(). */
     qof_instance_set_dirty(QOF_INSTANCE(s->parent));
 
-    mark_acc(acc);
-    xaccAccountRecomputeBalance(acc);
+    if (acc) {
+        g_object_set(acc, "sort-dirty", TRUE, "balance-dirty", TRUE, NULL);
+        xaccAccountRecomputeBalance(acc);
+    }
     if (s->inst.do_free)
         xaccFreeSplit(s);
 }

Modified: gnucash/trunk/src/engine/cap-gains.c
===================================================================
--- gnucash/trunk/src/engine/cap-gains.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/cap-gains.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -79,7 +79,7 @@
 xaccAccountHasTrades (Account *acc)
 {
    gnc_commodity *acc_comm;
-   SplitList *node;
+   SplitList *splits, *node;
 
    if (!acc) return FALSE;
 
@@ -88,7 +88,8 @@
       
    acc_comm = acc->commodity;
 
-   for (node=acc->splits; node; node=node->next)
+   splits = xaccAccountGetSplitList(acc);
+   for (node=splits; node; node=node->next)
    {
       Split *s = node->data;
       Transaction *t = s->parent;


Property changes on: gnucash/trunk/src/engine/test
___________________________________________________________________
Name: svn:ignore
   - *.log
Makefile
Makefile.in
.deps
.libs
test-load-engine
test-book-merge
test-commodities
test-date
test-freq-spec
test-guid
test-group-vs-book
test-link
test-lots
test-numeric
test-object
test-period
test-print-queries
test-query
test-querynew
test-recurrence
test-recursive
test-resolve-file-path
test-scm-query
test-split-vs-account
test-transaction-reversal
test-transaction-voiding
test-book-merge
semantic.cache
TAGS
*.exe

   + *.log
Makefile
Makefile.in
.deps
.libs
test-load-engine
test-book-merge
test-commodities
test-date
test-freq-spec
test-guid
test-group-vs-book
test-link
test-lots
test-numeric
test-object
test-period
test-print-queries
test-query
test-querynew
test-recurrence
test-recursive
test-resolve-file-path
test-scm-query
test-split-vs-account
test-transaction-reversal
test-transaction-voiding
test-book-merge
semantic.cache
TAGS
*.exe
test-account-object


Modified: gnucash/trunk/src/engine/test/Makefile.am
===================================================================
--- gnucash/trunk/src/engine/test/Makefile.am	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/test/Makefile.am	2007-04-18 04:50:34 UTC (rev 15921)
@@ -31,6 +31,7 @@
   test-object \
   test-commodities \
   test-create-account \
+  test-account-object \
   test-group-vs-book \
   test-lots \
   test-period \
@@ -66,6 +67,7 @@
   test-freq-spec \
   test-recurrence \
   test-guid \
+  test-account-object \
   test-group-vs-book \
   test-load-engine \
   test-period \

Added: gnucash/trunk/src/engine/test/test-account-object.c
===================================================================
--- gnucash/trunk/src/engine/test/test-account-object.c	2007-04-17 22:47:31 UTC (rev 15920)
+++ gnucash/trunk/src/engine/test/test-account-object.c	2007-04-18 04:50:34 UTC (rev 15921)
@@ -0,0 +1,102 @@
+/***************************************************************************
+ *            test-account-object.c
+ *
+ *  Copyright (C) 2007 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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+/** 
+ * @file test-account-object.c
+ * @brief Minimal test of reading/writing account parameters
+ * @author David Hampton <hampton at employees.org>
+ */
+
+#include "config.h"
+#include <unistd.h>
+#include <glib.h>
+#include "qof.h"
+#include "Account.h"
+#include "cashobjects.h"
+#include "test-stuff.h"
+#include "test-engine-stuff.h"
+
+static void
+run_test (void)
+{
+  QofSession *sess;
+  QofBook *book;
+  Account *acc;
+  gnc_numeric *start, *end, end2, delta, zero, five;
+
+  sess = get_random_session ();
+  book = qof_session_get_book (sess);
+  do_test ((NULL != book), "create random data");
+  acc = get_random_account(book);
+
+  /*****/
+
+  g_object_get(acc, "start-balance", &start, "end-balance", &end, NULL);
+  end2 = xaccAccountGetBalance(acc);
+  delta = gnc_numeric_sub(*end, *start, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
+
+  do_test (gnc_numeric_zero_p(*start), "start balance is zero");
+  do_test (gnc_numeric_zero_p(*end), "end balance is zero");
+  do_test (gnc_numeric_zero_p(delta), "delta is zero");
+  do_test (gnc_numeric_zero_p(end2), "end2 balance is zero");
+
+  /*****/
+
+  five = gnc_numeric_create(5, 1);
+  g_object_set(acc, "start-balance", &five, NULL);
+  xaccAccountRecomputeBalance(acc);
+  g_object_get(acc, "start-balance", &start, "end-balance", &end, NULL);
+  end2 = xaccAccountGetBalance(acc);
+
+  delta = gnc_numeric_sub(*end, five, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
+  do_test (gnc_numeric_zero_p(delta), "end balance matches");
+  delta = gnc_numeric_sub(end2, five, GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
+  do_test (gnc_numeric_zero_p(delta), "end2 balance matches");
+
+  /*****/
+
+  qof_session_end (sess);
+
+}
+
+int
+main (int argc, char **argv)
+{
+    gint i;
+
+    qof_init();
+    if (!cashobjects_register())
+        exit(1);
+
+    /* Any tests that cause an error or warning to be printed
+     * automatically fail! */
+    g_log_set_always_fatal( G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING );
+    /* Set up a reproducible test-case */
+    srand(0);
+
+    /* Run the tests */
+    run_test ();
+
+    print_test_results();
+
+    qof_close();
+    return get_rv();
+}



More information about the gnucash-changes mailing list