gnucash master: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Sat Jul 4 20:10:11 EDT 2015


Updated	 via  https://github.com/Gnucash/gnucash/commit/56c33163 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cc515150 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/20a52028 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4623cff3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/e81b8166 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d3e62f41 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ff07762f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3590de10 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/fd935d3b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9e142124 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/78b5b7cb (commit)
	 via  https://github.com/Gnucash/gnucash/commit/7c4e1f7f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/09871847 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/45a01b0f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/831a3601 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ab30b4c6 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c721bf9f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3956ee0f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/171669ec (commit)
	 via  https://github.com/Gnucash/gnucash/commit/435aef03 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/13377f56 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/55e4d30a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8b534835 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9b3f6078 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/fa221885 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cb9d8c93 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/095d1781 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/61ecdda8 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a4c748e2 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/f631f6e6 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/68dedc1b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/43e93e5f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ccd74059 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/dcc9bfec (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b4e02407 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4f4711c5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/232dd4c0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/eb2d5560 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/57ba9742 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/50bb5c16 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cadd1976 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c941a52a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c2d44b89 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d86a0b23 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/db5317f8 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1bd6afe3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ac29ad3c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/45e41a07 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/39c52151 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/97b44a71 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/97031fa6 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/eccdfd0a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/54255772 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c9785be3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/32d4fff3 (commit)
	from  https://github.com/Gnucash/gnucash/commit/31cfa0a9 (commit)



commit 56c331637975764ee5505011f0dd348a1021ad6d
Merge: 31cfa0a cc51515
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jul 4 17:00:53 2015 -0700

    Merge branch 'kvp-cleanup'
    
    Remove the KVP C API and consolidate use in a few files in libqof. For
    almost all future use KVP should be accessed via
    qof_instance_set/get_kvp() or qof_book_get/set_option(). These
    interfaces will ensure that changes to KVP are immediately committed
    unless they're called from inside a begin_edit/commit block to
    consolidate a database transaction.
    
    Some exceptional corner cases where direct access to KvpFrames are
    abstracted into new objects in libqof. The KVP "bag" interface of
    kvp-utils is removed and its single in Split.c made more direct with
    qof_instance_kvp_foo_guid functions.
    
    Account, Transaction, and Split use qof_instance_copy_kvp and
    qof_instance_swap_kvp as part of their rollback facilities.
    
    Resolves bugs 87652, 120250, 736139, and 736687.


commit cc515150d9e844b93f048085730c04a10ee4a011
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jul 4 16:09:04 2015 -0700

    Bug 120250 - KVP XML loader ignores '0' timestamps?

diff --git a/src/backend/xml/sixtp-dom-parsers.cpp b/src/backend/xml/sixtp-dom-parsers.cpp
index 49f6311..f9354d3 100644
--- a/src/backend/xml/sixtp-dom-parsers.cpp
+++ b/src/backend/xml/sixtp-dom-parsers.cpp
@@ -236,13 +236,10 @@ static KvpValue*
 dom_tree_to_timespec_kvp_value (xmlNodePtr node)
 {
     Timespec ts;
-    KvpValue * ret = NULL;
+    KvpValue * ret = nullptr;
 
     ts = dom_tree_to_timespec (node);
-    if (ts.tv_sec || ts.tv_nsec)
-    {
-        ret = new KvpValue{ts};
-    }
+    ret = new KvpValue{ts};
     return ret;
 }
 

commit 20a52028994941f14c7496ea452b49edbc3a44aa
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jul 4 15:57:33 2015 -0700

    Bug 87652 - KVP modification does not change 'dirty' flag.

diff --git a/src/import-export/aqb/test/test-kvp.c b/src/import-export/aqb/test/test-kvp.c
index 137522e..ceed115 100644
--- a/src/import-export/aqb/test/test-kvp.c
+++ b/src/import-export/aqb/test/test-kvp.c
@@ -26,6 +26,7 @@
 // for the gnc_ab_get_book_template_list() et al. functions
 #include "import-export/aqb/gnc-ab-kvp.h"
 #include <gnc-aqbanking-templates.h>
+#include <qofinstance-p.h>
 #include "engine/gnc-hooks.h"
 
 static char* get_filepath(const char* filename)
@@ -117,7 +118,9 @@ test_qofsession_aqb_kvp( void )
             g_assert_cmpint(g_list_length(templ_list), ==, 1);
 
             templ = templ_list->data;
-            g_assert_cmpstr(gnc_ab_trans_templ_get_name(templ), ==, ORIGINAL_NAME); // ok, name from file is here
+	    //Raise the edit level so that we can check that it's marked dirty.
+	    qof_instance_increase_editlevel(QOF_INSTANCE(book));
+	    g_assert_cmpstr(gnc_ab_trans_templ_get_name(templ), ==, ORIGINAL_NAME); // ok, name from file is here
 
             // Now we change the name into something else and verify it can be saved
             gnc_ab_trans_templ_set_name(templ, CHANGED_NAME);
diff --git a/src/libqof/qof/gnc-aqbanking-templates.cpp b/src/libqof/qof/gnc-aqbanking-templates.cpp
index 6c5c526..54f9b6f 100644
--- a/src/libqof/qof/gnc-aqbanking-templates.cpp
+++ b/src/libqof/qof/gnc-aqbanking-templates.cpp
@@ -193,9 +193,11 @@ gnc_ab_set_book_template_list (QofBook *b, GList *template_list)
     kvp_list = g_list_reverse (kvp_list);
     auto value = new KvpValue(g_list_copy_deep(kvp_list, copy_list_value,
                                                nullptr));
+    qof_book_begin_edit(b);
     KvpFrame *toplevel = qof_instance_get_slots (QOF_INSTANCE (b));
     delete toplevel->set_path({"hbci", "template-list"}, value);
     qof_instance_set_dirty_flag (QOF_INSTANCE (b), TRUE);
+    qof_book_commit_edit(b);
 }
 
 const gchar *

commit 4623cff38d4619374d749cca51096eb0e3aa55fb
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jul 3 16:14:00 2015 -0700

    Document new KVP API in Doxygen, including relevant bits from src/docs/design.

diff --git a/src/engine/kvp_doc.txt b/src/engine/kvp_doc.txt
index f39f53f..e9f6717 100644
--- a/src/engine/kvp_doc.txt
+++ b/src/engine/kvp_doc.txt
@@ -6,7 +6,7 @@ API: \ref KVP
 
 This file documents the use of keys in the key-value pair system
 used by the GnuCash Application (both the engine, and non-engine, GUI
-pieces).  Before assigning keys for use, please read the Key-Value 
+pieces).  Before assigning keys for use, please read the Key-Value
 Policy in the GnuCash Design Document located under src/doc/design.
 
 The format of the data below is:
@@ -16,7 +16,7 @@ Name: The name of the key, including key names of parent frames
       filename. Use the '/' character to separate keys.
 
 Type: The type of value stored in the key. The types are listed in
-      'kvp_frame.h'.
+      'kvp-value.hpp'.
 
 Entities: Which engine entities (Accounts, Transactions, Splits)
           can use this key. Use 'All' if every entity could have
@@ -24,7 +24,7 @@ Entities: Which engine entities (Accounts, Transactions, Splits)
 
 Use: The use to which the key will be put. Include any requirements
      for using the key here. Also include any API calls which use
-     the key. If more than one entity can use the key, 
+     the key. If more than one entity can use the key,
 
 Example:
 
@@ -44,7 +44,7 @@ Please put the keys in alphabetical order.
 
 [ \ref kvpA ] [ \ref kvpB ] [ \ref kvpC ] [ \ref kvpD ] [ \ref kvpE ]
 [ \ref kvpF ] [ \ref kvpG ] [ \ref kvpH ] [ \ref kvpJ ] [ \ref kvpK ] [ \ref kvpL ]\n
-[ \ref kvpM ] [ \ref kvpN ] [ \ref kvpO ] [ \ref kvpP ] [ \ref kvpQ ] 
+[ \ref kvpM ] [ \ref kvpN ] [ \ref kvpO ] [ \ref kvpP ] [ \ref kvpQ ]
 [ \ref kvpR ] [ \ref kvpS ] [ \ref kvpT ] [ \ref kvpU ] [ \ref kvpV ] [ \ref kvpW ]
 
 \subsection kvpA A
@@ -62,7 +62,7 @@ Use:  kvp subdirectory holding info relating to accounting periods, including
 
 \verbatim
 Name: /book/accounting-period
-Type: string, enum {none, week, month, quarter, trimester, year} 
+Type: string, enum {none, week, month, quarter, trimester, year}
 	XXX not used, should be UIFreqSpec stuff ..
 Entities: Book
 Use:  An enumerated identifier indicating how often books are supposed
@@ -74,7 +74,7 @@ Use:  An enumerated identifier indicating how often books are supposed
 Name: /book/close-date
 Type: Timespec
 Entities: Book
-Use:  The posted closing date of this book.  This book only contains 
+Use:  The posted closing date of this book.  This book only contains
       transactions whose posted date is earlier than this closing date.
 \endverbatim
 
@@ -82,7 +82,7 @@ Use:  The posted closing date of this book.  This book only contains
 Name: /book/closed-acct
 Type: GUID
 Entities: Transaction
-Use:  The GUID of the account for which this transaction represents the 
+Use:  The GUID of the account for which this transaction represents the
       opening balance.  This value will occur *only* in transactions that
       are opening balances.
 \endverbatim
@@ -91,7 +91,7 @@ Use:  The GUID of the account for which this transaction represents the
 Name: /book/closed-book
 Type: GUID
 Entities: Transaction
-Use:  The GUID of the book for which this transaction represents the 
+Use:  The GUID of the book for which this transaction represents the
       opening balance.  This value will occur *only* in transactions that
       are opening balances.
 \endverbatim
@@ -173,7 +173,7 @@ Entities: Book
 Use:  Holders for a bunch of counters for various types.  Used specifically
       in the business objects for ID counters.  The counter name is the path
       that follows /counters/, e.g. "/counters/GncCustomer"
-\endverbatim      
+\endverbatim
 
 \verbatim
 Name: /counter_formats/...
@@ -224,7 +224,7 @@ Use:  GUID of the split that records the capital gains for this split.
 Name: /gemini/
 Type: kvp_glist
 Entities: Account, Book
-Use:  kvp bag holding frames that identify accounts or books 
+Use:  kvp bag holding frames that identify accounts or books
       that are copies of this account.
 \endverbatim
 
@@ -247,7 +247,7 @@ Use:  guid of another account that is a copy of this one.
 Name: /gemini/<type>/book_guid
 Type: guid
 Entities: Account, Book
-Use:  When this appears in an account, then it contains the guid of 
+Use:  When this appears in an account, then it contains the guid of
       the book that the other account belongs to.  When this appears
       in a book, then this is the guid of the other book.
 \endverbatim
@@ -304,7 +304,7 @@ Name: /hbci/config-filename
 Type: string
 Entitied: Book
 Use: OpenHBCI configuration file name, where the real HBCI
-configuration for the OpenHBCI library can be found 
+configuration for the OpenHBCI library can be found
 \endverbatim
 
 \subsection kvpJ J
@@ -328,15 +328,15 @@ Type: kvp_frame
 Entities: Account
 Use: Frame holding info regarding how lots should be managed in this
      account, including what accounting policy to use, where realized
-     gains should be reported, and etc. 
+     gains should be reported, and etc.
 \endverbatim
 
 \verbatim
 Name: /lot-mgmt/gains-acct/
 Type: frame
 Entities: Account
-Use: When a lot in this account is double-balanced, this frame 
-     holds per-currency accounts to which realized gains are to 
+Use: When a lot in this account is double-balanced, this frame
+     holds per-currency accounts to which realized gains are to
      be posted.
 \endverbatim
 
@@ -361,7 +361,7 @@ Name: /lot-split/
 Type: kvp_glist
 Entities: Split
 Use:  A bag of kvp frames holding identification of splits
-      that were split off of this split.  Same style as the 
+      that were split off of this split.  Same style as the
       /gemini/, look there for additional doco's.
 \endverbatim
 
@@ -380,7 +380,7 @@ Use:  The GUID of the peer split which was split from this split.
 Name: /notes
 Type: string
 Entities: Account, Lot, Transaction
-Use: A user-suplied 'Notes' text field.  The user can set this to 
+Use: A user-suplied 'Notes' text field.  The user can set this to
      any value and change it at any time for any reason.
      Accessors: xaccAccountGetNotes(), xaccAccountSetNotes(),
      xaccTransGetNotes(), xaccTransSetNotes()
@@ -533,7 +533,7 @@ Use: Store the formula for the credit side of the split
 Name: /sched-xaction/debit-formula
 Type: string
 Entities: Split associated with a SchedXaction
-Use: Formula for the debit.  Either the credit or the 
+Use: Formula for the debit.  Either the credit or the
      debit formula must be empty.
 \endverbatim
 
@@ -571,7 +571,7 @@ Use: A boolean flag indicated whether the Account is tax-related.
 Name: /title
 Type: string
 Entities: Lot
-Use:  A user-supplied title for the lot.  The user can set this to 
+Use:  A user-supplied title for the lot.  The user can set this to
       any value and change it at any time for any reason.
 \endverbatim
 
@@ -606,7 +606,7 @@ Use: This frame is used to store keys which are editable directly by
 Name: void-reason
 Type: string
 Entities: Transaction
-Use: This string is used to store the reason why a transaction has been 
+Use: This string is used to store the reason why a transaction has been
 voided.  Note that it should only exist if the transaction has been voided.
 \endverbatim
 
diff --git a/src/libqof/qof/kvp-value.hpp b/src/libqof/qof/kvp-value.hpp
index 350e9ab..e97fb36 100644
--- a/src/libqof/qof/kvp-value.hpp
+++ b/src/libqof/qof/kvp-value.hpp
@@ -37,6 +37,12 @@ extern "C"
 
 //Must be a struct because it's exposed to C so that it can in turn be
 //translated to/from Scheme.
+/** @addtogroup KVP
+ * @{
+ */
+
+/** Implements KvpValue using boost::variant.
+ */
 struct KvpValueImpl
 {
     public:
@@ -134,7 +140,7 @@ struct KvpValueImpl
 
 int
 compare(const KvpValueImpl *, const KvpValue *) noexcept;
-
+/** @} Close Doxygen AddToGroup */
 template <typename T>
 KvpValueImpl::KvpValueImpl(T newvalue) noexcept:
     datastore(newvalue)
@@ -153,7 +159,9 @@ KvpValueImpl::set(T val) noexcept
 {
     this->datastore = val;
 }
-
+/** @ingroup KVP
+    @{ */
+/** @internal @{ */
 /** Convert a kvp_value into a GValue. Frames aren't converted.
  * @param kval: A KvpValue.
  * @return GValue*. Must be freed with g_free().
@@ -172,7 +180,8 @@ KvpValue* kvp_value_from_gvalue (const GValue *gval);
  * \param value: A GValue* created by kvp_frame_get_gvalue
  */
 void gnc_gvalue_free (GValue *value);
-
+/** @} Close Doxygen Internal */
+/** @} Close Doxygen Group */
 extern "C" GType gnc_value_list_get_type (void);
 #define GNC_TYPE_VALUE_LIST (gnc_value_list_get_type ())
 
diff --git a/src/libqof/qof/kvp_frame.hpp b/src/libqof/qof/kvp_frame.hpp
index 5aae496..f765a6d 100644
--- a/src/libqof/qof/kvp_frame.hpp
+++ b/src/libqof/qof/kvp_frame.hpp
@@ -39,6 +39,35 @@
  * passed as either '/'-delimited strings or as std::vectors of keys. Unlike
  * file system paths, the tokens '.' and '..' have no special meaning.
  *
+ * KVP is an implementation detail whose direct use should be avoided; create an
+ * abstraction object in libqof to keep KVP encapsulated here and ensure that
+ * KVP modifications are written to the database. Two generic abstractions are
+ * provided:
+ *
+ * * @ref qof_instance_set_kvp and @ref qof_instance_get_kvp provide single-item
+     access via GValues to support object properties.
+
+ * * @ref qof_book_set_option and @ref qof_book_get_option provide similar
+     access for book options.
+
+ *
+ * @ref kvpvalues provides a catolog of KVP entries including what objects
+ * they're part of and how they're used.
+ *
+ * ## Purpose
+ * KVP is used to extend the class structure without directly reflecting the extension in the database or xML schema. The backend will directly load and store KVP slots without any checking, which allows older versions of GnuCash to load the database without complaint and without damaging the KVP data that they don't understand.
+ *
+ * When a feature is entirely implemented in KVP and doesn't affect the meaning of the books or other features, this isn't a problem, but when it's not true then it should be registered in @ref UtilFeature so that older versions of GnuCash will refuse to load the database.
+ *
+ * ## Policy
+ * * Document every KVP slot in src/engine/kvp_doc.txt so that it is presented
+ * in @ref kvpvalues.
+ * * Register a feature in @ref UtilFeature if the use of the KVP in any way affects the books or business computations.
+ * * Key strings should be all lower case with '-', not spaces, separating words and '/' separating frames. Prefer longer and more descriptive names to abbreviations, and define a global const char[] to the key or path string so that the compiler will catch any typos.
+ * * Make good use of the hierarchical nature of KVP by using frames to group related slots.
+ * * Don't use the KVP API directly outside of libqof, and prefer to use the QofInstance and QofBook functions whenever feasible. If those functions aren't feasible write a class in libqof to abstract the use of KVP.
+ * * Avoid re-using key names in different contexts (e.g. Transactions and Splits) unless the slot is used for the same purpose in both.
+ * @{
 */
 
 #ifndef GNC_KVP_FRAME_TYPE
@@ -49,23 +78,33 @@
 #include <string>
 #include <vector>
 #include <cstring>
-
-class cstring_comparer
-{
-    public:
-    /* Returns true if one is less than two. */
-    bool operator()(const char * one, const char * two) const
-    {
-        auto ret = std::strcmp(one, two) < 0;
-        return ret;
-    }
-};
-
 using Path = std::vector<std::string>;
 
+/** Implements KvpFrame.
+ *  It's a struct because QofInstance needs to use the typename to declare a
+ *  KvpFrame* member, and QofInstance's API is C until its children are all
+ *  rewritten in C++.
+ *
+ * N.B.**  Writes to KvpFrames must** be wrapped in BeginEdit and Commit
+ * for the containing QofInstance and the QofInstance must be marked dirty. This
+ * is not** done by the KvpFrame API. In general Kvp items should be
+ * accessed using either QofInstance or QofBook methods in order to ensure that
+ * this is done.
+ * @{
+ */
 struct KvpFrameImpl
 {
-    typedef std::map<const char *, KvpValue*, cstring_comparer> map_type;
+    class cstring_comparer
+    {
+    public:
+	/* Returns true if one is less than two. */
+	bool operator()(const char * one, const char * two) const
+	    {
+		auto ret = std::strcmp(one, two) < 0;
+		return ret;
+	    }
+    };
+    using map_type = std::map<const char *, KvpValue*, cstring_comparer>;
 
     public:
     KvpFrameImpl() noexcept {};
@@ -98,8 +137,8 @@ struct KvpFrameImpl
      * Set the value with the key in a subframe following the keys in path,
      * replacing and returning the old value if it exists or nullptr if it
      * doesn't. Creates any missing intermediate frames.
-     * @param path: The path of subframes as a '/'-delimited string leading to the frame in which to
-     * insert/replace.
+     * @param path: The path of subframes as a '/'-delimited string leading to
+     * the frame in which to insert/replace.
      * @param newvalue: The value to set at key.
      * @return The old value if there was one or nullptr.
      */
@@ -112,8 +151,8 @@ struct KvpFrameImpl
      * Set the value with the key in a subframe following the keys in path,
      * replacing and returning the old value if it exists or nullptr if it
      * doesn't. Creates any missing intermediate frames.
-     * @param path: The path of subframes as a std::vector leading to the frame in which to
-     * insert/replace.
+     * @param path: The path of subframes as a std::vector leading to the
+     * frame in which to insert/replace.
      * @param newvalue: The value to set at key.
      * @return The old value if there was one or nullptr.
      */
@@ -158,4 +197,6 @@ struct KvpFrameImpl
 
 int compare (const KvpFrameImpl &, const KvpFrameImpl &) noexcept;
 int compare (const KvpFrameImpl *, const KvpFrameImpl *) noexcept;
+/** @} Doxygen Group */
+
 #endif
diff --git a/src/libqof/qof/qofbook.h b/src/libqof/qof/qofbook.h
index 04448f7..50750ce 100644
--- a/src/libqof/qof/qofbook.h
+++ b/src/libqof/qof/qofbook.h
@@ -354,6 +354,9 @@ void qof_book_begin_edit(QofBook *book);
 void qof_book_commit_edit(QofBook *book);
 
 /* Access functions for options. */
+/** @ingroup KVP
+ @{
+ */
 /** Load a GNCOptionsDB from KVP data.
  * @param book: The book.
  * @param load_cb: A callback function that does the loading.
@@ -394,7 +397,7 @@ KvpValue* qof_book_get_option (QofBook *book, GSList *path);
  * @param list: A GList of keys which from a path under KVP_OPTION_PATH.
  */
 void qof_book_options_delete (QofBook *book);
-
+/** @} End of Doxygen Include */
 /** deprecated */
 #define qof_book_get_guid(X) qof_entity_get_guid (QOF_INSTANCE(X))
 
diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 16eeee0..0c0d4fd 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -106,11 +106,33 @@ void qof_instance_set_version_check (gpointer inst, guint32 value);
 void qof_instance_copy_version_check (gpointer to, gconstpointer from);
 void qof_instance_set_idata(gpointer inst, guint32 idata);
 /* Convenience functions to save some typing in property handlers */
+/** @ingroup KVP
+ * @{ */
+/** Report whether a QofInstance has anything stored in KVP
+ * @param inst The QofInstance
+ * @return TRUE if Kvp isn't empty.
+ */
 gboolean qof_instance_has_kvp (QofInstance *inst);
+/** Sets a KVP slot to a value from a GValue. The key can be a '/'-delimited
+ * path, and intermediate container frames will be created if necessary.
+ * Commits the change to the QofInstance.
+ * @param inst: The QofInstance on which to set the value.
+ * @param key: The key for the slot or '/'-delimited path
+ * @param value: A GValue containing an item of a type which KvpValue knows
+ * how to store.
+ */
 void qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value);
-void qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *value);
-/* Functions to isolate the KVP mechanism inside QOF for cases where GValue
- * operations won't work.
+/** Retrieves the contents of a KVP slot into a provided GValue.
+ * @param inst: The QofInstance
+ * @param key: The key of or '/'-delimited path to the slot.
+ * @param value: A GValue into which to store the value of the slot. It will be
+ *               set to the correct type.
+ */
+void qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue
+*value);
+/** @} Close out the DOxygen ingroup */
+/* Functions to isolate the KVP mechanism inside QOF for cases where
+GValue * operations won't work.
  */
 void qof_instance_copy_kvp (QofInstance *to, const QofInstance *from);
 void qof_instance_swap_kvp (QofInstance *a, QofInstance *b);
diff --git a/src/libqof/qof/qofinstance.h b/src/libqof/qof/qofinstance.h
index 98b854f..df4f382 100644
--- a/src/libqof/qof/qofinstance.h
+++ b/src/libqof/qof/qofinstance.h
@@ -66,13 +66,7 @@ typedef struct KvpFrameImpl KvpFrame;
 struct QofInstance_s
 {
     GObject object;
-
     QofIdType        e_type;		   /**<	Entity type */
-
-    /* kvp_data is a key-value pair database for storing arbirtary
-     * information associated with this instance.
-     * See src/engine/kvp_doc.txt for a list and description of the
-     * important keys. */
     KvpFrame *kvp_data;
 };
 

commit e81b816658f4849937f430fffa6743808d222ca6
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jul 3 16:12:29 2015 -0700

    Update doxygen config to use C++ files and drop obsolete commands.
    
    Also turn on autobrief, STL support, and reduce the tab size to 4.

diff --git a/src/doc/doxygen.cfg.in b/src/doc/doxygen.cfg.in
index 0907011..d00310b 100644
--- a/src/doc/doxygen.cfg.in
+++ b/src/doc/doxygen.cfg.in
@@ -153,7 +153,7 @@ SHORT_NAMES            = NO
 # comments will behave just like regular Qt-style comments
 # (thus requiring an explicit @brief command for a brief description.)
 
-JAVADOC_AUTOBRIEF      = NO
+JAVADOC_AUTOBRIEF      = YES
 
 # If the QT_AUTOBRIEF tag is set to YES then Doxygen will
 # interpret the first line (until the first dot) of a Qt-style
@@ -186,7 +186,7 @@ SEPARATE_MEMBER_PAGES  = NO
 # The TAB_SIZE tag can be used to set the number of spaces in a tab.
 # Doxygen uses this value to replace tabs by spaces in code fragments.
 
-TAB_SIZE               = 8
+TAB_SIZE               = 4
 
 # This tag can be used to specify a number of aliases that acts
 # as commands in the documentation. An alias has the form "name=value".
@@ -266,7 +266,7 @@ AUTOLINK_SUPPORT       = YES
 # func(std::string) {}). This also makes the inheritance and collaboration
 # diagrams that involve STL classes more complete and accurate.
 
-BUILTIN_STL_SUPPORT    = NO
+BUILTIN_STL_SUPPORT    = YES
 
 # If you use Microsoft's C++/CLI language, you should set this option to YES to
 # enable parsing support.
@@ -675,7 +675,9 @@ FILE_PATTERNS          = *.c \
                          *.h \
                          *.txt \
                          *.py \
-                         *.pl
+                         *.pl \
+                         *.cpp \
+                         *.hpp
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories
 # should be searched for input files as well. Possible values are YES and NO.
@@ -703,7 +705,7 @@ EXCLUDE_SYMLINKS       = YES
 # against the file with absolute path, so to exclude all test directories
 # for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       =
+EXCLUDE_PATTERNS       = */test/*
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
 # (namespaces, classes, functions, etc.) that should be excluded from the
@@ -1460,18 +1462,6 @@ GENERATE_XML           = NO
 
 XML_OUTPUT             = xml
 
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA             =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD                =
-
 # If the XML_PROGRAMLISTING tag is set to YES Doxygen will
 # dump the program listings (including syntax highlighting
 # and cross-referencing information) to the XML output. Note that

commit d3e62f41bed68ed897f8f9492ea3553ad0e77b08
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 30 12:04:34 2015 -0700

    Remove the KVP C API.
    
    All access to KVP is now implemented in C++11.

diff --git a/src/libqof/qof/Makefile.am b/src/libqof/qof/Makefile.am
index 7bfc7b0..8d23077 100644
--- a/src/libqof/qof/Makefile.am
+++ b/src/libqof/qof/Makefile.am
@@ -59,7 +59,6 @@ qofinclude_HEADERS = \
    gnc-timezone.hpp  \
    gnc-datetime.hpp  \
    guid.h            \
-   kvp_frame.h       \
    kvp_frame.hpp     \
    kvp-value.hpp     \
    qof.h             \
diff --git a/src/libqof/qof/kvp-value.hpp b/src/libqof/qof/kvp-value.hpp
index 3b53167..350e9ab 100644
--- a/src/libqof/qof/kvp-value.hpp
+++ b/src/libqof/qof/kvp-value.hpp
@@ -153,6 +153,26 @@ KvpValueImpl::set(T val) noexcept
 {
     this->datastore = val;
 }
+
+/** Convert a kvp_value into a GValue. Frames aren't converted.
+ * @param kval: A KvpValue.
+ * @return GValue*. Must be freed with g_free().
+ */
+GValue* gvalue_from_kvp_value (const KvpValue *kval);
+
+/** Convert a gvalue into a kvpvalue.
+ * @param gval: A GValue of a type KvpValue can digest.
+ * @return KvpValue created from the GValue's contents.
+ */
+KvpValue* kvp_value_from_gvalue (const GValue *gval);
+
+/**
+ * \brief Convenience function to release the value in a GValue
+ * acquired by kvp_frame_get_gvalue and to free the GValue.
+ * \param value: A GValue* created by kvp_frame_get_gvalue
+ */
+void gnc_gvalue_free (GValue *value);
+
 extern "C" GType gnc_value_list_get_type (void);
 #define GNC_TYPE_VALUE_LIST (gnc_value_list_get_type ())
 
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index 8a8cdaf..d38eedf 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -30,7 +30,6 @@ extern "C"
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
-#include "kvp_frame.h"
 }
 
 #include "kvp-value.hpp"
@@ -275,940 +274,6 @@ int compare(const KvpFrameImpl & one, const KvpFrameImpl & two) noexcept
     return 0;
 }
 
-KvpFrame *
-kvp_frame_new(void)
-{
-    auto ret = new KvpFrameImpl();
-    return static_cast<KvpFrame *>(ret);
-}
-
-void
-kvp_frame_delete(KvpFrame * frame)
-{
-    if (!frame) return;
-    auto realframe = static_cast<KvpFrameImpl *>(frame);
-    delete realframe;
-}
-
-const char **
-kvp_frame_get_keys(const KvpFrame * frame)
-{
-    if (!frame) return nullptr;
-    auto realframe = static_cast<KvpFrameImpl const *>(frame);
-    const auto & keys = realframe->get_keys();
-    const char ** ret = g_new(const char *, keys.size() + 1);
-    unsigned int spot {0};
-    std::for_each(keys.begin(), keys.end(),
-        [&ret,&spot](const std::string &a)
-        {
-            ret[spot++] = g_strdup(a.c_str());
-        }
-    );
-    ret[keys.size()] = nullptr;
-    return ret;
-}
-
-gboolean
-kvp_frame_is_empty(const KvpFrame * frame)
-{
-    return frame->empty();
-}
-
-KvpFrame *
-kvp_frame_copy(const KvpFrame * frame)
-{
-    auto ret = new KvpFrameImpl(*static_cast<KvpFrameImpl const *>(frame));
-    return ret;
-}
-
-/* Replace the old value with the new value.  Return the old value.
- * Passing in a null value into this routine has the effect of
- * removing the key from the KVP tree.
- */
-static KvpValue *
-kvp_frame_replace_slot_nc (KvpFrame* frame, const char* slot, KvpValue* value)
-{
-    if (!frame) return nullptr;
-    return frame->set(slot, value);
-}
-
-/* Passing in a null value into this routine has the effect
- * of deleting the old value stored at this slot.
- */
-static inline void
-kvp_frame_set_slot_destructively(KvpFrame* frame, const char* slot,
-                                 KvpValue* value)
-{
-    delete frame->set(slot, value);
-}
-
-/* ============================================================ */
-/* Get the named frame, or create it if it doesn't exist.
- * gcc -O3 should inline it.  It performs no error checks,
- * the caller is responsible of passing good keys and frames.
- */
-static inline KvpFrame *
-get_or_make (KvpFrame *fr, const char * key)
-{
-    KvpFrame *next_frame;
-    KvpValue *value;
-
-    value = kvp_frame_get_slot (fr, key);
-    if (value)
-    {
-        next_frame = kvp_value_get_frame (value);
-    }
-    else
-    {
-        next_frame = kvp_frame_new ();
-        kvp_frame_set_slot_nc (fr, key,
-                               kvp_value_new_frame_nc (next_frame));
-    }
-    return next_frame;
-}
-
-/* Get pointer to last frame in path. If the path doesn't exist,
- * it is created.  The string stored in keypath will be hopelessly
- * mangled .
- */
-static inline KvpFrame *
-kvp_frame_get_frame_slash_trash (KvpFrame *frame, char *key_path)
-{
-    char *key, *next;
-    if (!frame || !key_path) return frame;
-
-    key = key_path;
-    key --;
-
-    while (key)
-    {
-        key ++;
-        while ('/' == *key)
-        {
-            key++;
-        }
-        if (0x0 == *key) break;    /* trailing slash */
-        next = strchr (key, '/');
-        if (next) *next = 0x0;
-
-        frame = get_or_make (frame, key);
-        if (!frame) break;  /* error - should never happen */
-
-        key = next;
-    }
-    return frame;
-}
-
-/* ============================================================ */
-/* Get pointer to last frame in path, or NULL if the path doesn't
- * exist. The string stored in keypath will be hopelessly mangled .
- */
-static inline const KvpFrame *
-kvp_frame_get_frame_or_null_slash_trash (const KvpFrame *frame, char *key_path)
-{
-    KvpValue *value;
-    char *key, *next;
-    if (!frame || !key_path) return NULL;
-
-    key = key_path;
-    key --;
-
-    while (key)
-    {
-        key ++;
-        while ('/' == *key)
-        {
-            key++;
-        }
-        if (0x0 == *key) break;    /* trailing slash */
-        next = strchr (key, '/');
-        if (next) *next = 0x0;
-
-        value = kvp_frame_get_slot (frame, key);
-        if (!value) return NULL;
-        frame = kvp_value_get_frame (value);
-        if (!frame) return NULL;
-
-        key = next;
-    }
-    return frame;
-}
-
-/* Return pointer to last frame in path, and also store the
- * last dangling part of path in 'end_key'.  If path doesn't
- * exist, it is created.
- */
-
-static inline KvpFrame *
-get_trailer_make (KvpFrame * frame, const char * key_path, char **end_key)
-{
-    char *last_key;
-
-    if (!frame || !key_path || (0 == key_path[0])) return NULL;
-
-    last_key = strrchr (const_cast<char*>(key_path), '/');
-    if (NULL == last_key)
-    {
-        last_key = (char *) key_path;
-    }
-    else if (last_key == key_path)
-    {
-        last_key ++;
-    }
-    else if (0 == last_key[1])
-    {
-        return NULL;
-    }
-    else
-    {
-        char *root, *lkey;
-        root = g_strdup (key_path);
-        lkey = strrchr (root, '/');
-        *lkey = 0;
-        frame = kvp_frame_get_frame_slash_trash (frame, root);
-        g_free(root);
-
-        last_key ++;
-    }
-
-    *end_key = last_key;
-    return frame;
-}
-
-
-/* Return pointer to last frame in path, or NULL if the path
- * doesn't exist.  Also store the last dangling part of path
- * in 'end_key'.
- */
-
-static inline const KvpFrame *
-get_trailer_or_null (const KvpFrame * frame, const char * key_path, char **end_key)
-{
-    char *last_key;
-
-    if (!frame || !key_path || (0 == key_path[0])) return NULL;
-
-    last_key = strrchr (const_cast<char*>(key_path), '/');
-    if (NULL == last_key)
-    {
-        last_key = (char *) key_path;
-    }
-    else if (last_key == key_path)
-    {
-        last_key ++;
-    }
-    else if (0 == last_key[1])
-    {
-        return NULL;
-    }
-    else
-    {
-        char *root, *lkey;
-        root = g_strdup (key_path);
-        lkey = strrchr (root, '/');
-        *lkey = 0;
-        frame = kvp_frame_get_frame_or_null_slash_trash (frame, root);
-        g_free(root);
-
-        last_key ++;
-    }
-
-    *end_key = last_key;
-    return frame;
-}
-
-void
-kvp_frame_set_gint64(KvpFrame * frame, const char * path, gint64 ival)
-{
-    KvpValue *value;
-    value = kvp_value_new_gint64 (ival);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_double(KvpFrame * frame, const char * path, double dval)
-{
-    KvpValue *value;
-    value = kvp_value_new_double (dval);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_numeric(KvpFrame * frame, const char * path, gnc_numeric nval)
-{
-    KvpValue *value;
-    value = kvp_value_new_gnc_numeric (nval);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_string(KvpFrame * frame, const char * path, const char* str)
-{
-    KvpValue *value;
-    value = kvp_value_new_string (str);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_guid(KvpFrame * frame, const char * path, const GncGUID *guid)
-{
-    KvpValue *value;
-    value = kvp_value_new_guid (guid);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_timespec(KvpFrame * frame, const char * path, Timespec ts)
-{
-    KvpValue *value;
-    value = kvp_value_new_timespec (ts);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_frame(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
-    KvpValue *value;
-    value = kvp_value_new_frame (fr);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_frame_nc(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
-    KvpValue *value;
-    value = kvp_value_new_frame_nc (fr);
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-/* ============================================================ */
-
-KvpFrame *
-kvp_frame_set_value_nc (KvpFrame * frame, const char * key_path,
-                        KvpValue * value)
-{
-    char *last_key;
-
-    frame = get_trailer_make (frame, key_path, &last_key);
-    if (!frame) return NULL;
-    kvp_frame_set_slot_destructively(frame, last_key, value);
-    return frame;
-}
-
-KvpFrame *
-kvp_frame_set_value (KvpFrame * frame, const char * key_path,
-                     const KvpValue * value)
-{
-    KvpValue *new_value = NULL;
-    char *last_key;
-
-    frame = get_trailer_make (frame, key_path, &last_key);
-    if (!frame) return NULL;
-
-    if (value) new_value = kvp_value_copy(value);
-    kvp_frame_set_slot_destructively(frame, last_key, new_value);
-    return frame;
-}
-
-KvpValue *
-kvp_frame_replace_value_nc (KvpFrame * frame, const char * key_path,
-                            KvpValue * new_value)
-{
-    KvpValue * old_value;
-    char *last_key;
-
-    last_key = NULL;
-    if (new_value)
-    {
-        frame = get_trailer_make (frame, key_path, &last_key);
-    }
-    else
-    {
-        frame = (KvpFrame *) get_trailer_or_null (frame, key_path, &last_key);
-    }
-    if (!frame) return NULL;
-
-    old_value = kvp_frame_replace_slot_nc (frame, last_key, new_value);
-    return old_value;
-}
-
-static KvpFrame *
-kvp_frame_add_value_nc(KvpFrame * frame, const char * path, KvpValue *value)
-{
-    char *key = NULL;
-    KvpValueImpl * oldvalue;
-    KvpFrame* orig_frame = frame;
-
-    frame = (KvpFrame *) get_trailer_or_null (frame, path, &key);
-    oldvalue = static_cast<KvpValueImpl *> (kvp_frame_get_slot (frame, key));
-    auto newvalue = static_cast<KvpValueImpl *> (value);
-
-    ENTER ("old frame=%s", kvp_frame_to_string(frame));
-    if (oldvalue)
-    {
-        kvp_frame_replace_slot_nc (frame, key, oldvalue->add (newvalue));
-        LEAVE ("new frame=%s", kvp_frame_to_string (frame));
-        return frame;
-    }
-
-    /* Hmm, if we are here, the path doesn't exist. We need to
-     * create the path, add the value to it. */
-    frame = orig_frame;
-    frame = kvp_frame_set_value_nc (frame, path, value);
-    LEAVE ("new frame=%s", kvp_frame_to_string(frame));
-    return frame;
-}
-
-void
-kvp_frame_add_frame_nc(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
-    KvpValue *value;
-    value = kvp_value_new_frame_nc (fr);
-    frame = kvp_frame_add_value_nc (frame, path, value);
-    if (!frame) kvp_value_delete (value);
-}
-
-/* ============================================================ */
-
-void
-kvp_frame_set_slot(KvpFrame * frame, const char * slot,
-                   KvpValue * value)
-{
-    KvpValue* new_value{nullptr};
-    if (!frame) return;
-    g_return_if_fail (slot && *slot != '\0');
-
-    if (value) new_value = kvp_value_copy(value);
-    delete frame->set(slot, new_value);
-}
-
-void
-kvp_frame_set_slot_nc(KvpFrame * frame, const char * slot,
-                      KvpValue * value)
-{
-    if (!frame) return;
-    g_return_if_fail (slot && *slot != '\0');
-
-    frame->set(slot, value);
-}
-
-KvpValue *
-kvp_frame_get_slot(const KvpFrame * frame, const char * slot)
-{
-    if (!frame) return nullptr;
-    return frame->get_slot(slot);
-}
-
-void
-kvp_frame_set_slot_path (KvpFrame *frame,
-                         KvpValue * new_value,
-                         const char *first_key, ...)
-{
-    va_list ap;
-    const char *key;
-
-    if (!frame) return;
-
-    g_return_if_fail (first_key && *first_key != '\0');
-
-    va_start (ap, first_key);
-
-    key = first_key;
-
-    while (TRUE)
-    {
-        KvpValue *value;
-        const char *next_key;
-
-        next_key = va_arg (ap, const char *);
-        if (!next_key)
-        {
-            kvp_frame_set_slot (frame, key, new_value);
-            break;
-        }
-
-        g_return_if_fail (*next_key != '\0');
-
-        value = kvp_frame_get_slot (frame, key);
-        if (!value)
-        {
-            KvpFrame *new_frame = kvp_frame_new ();
-            KvpValue *frame_value = kvp_value_new_frame (new_frame);
-
-            kvp_frame_set_slot_nc (frame, key, frame_value);
-
-            value = kvp_frame_get_slot (frame, key);
-            if (!value) break;
-        }
-
-        frame = kvp_value_get_frame (value);
-        if (!frame) break;
-
-        key = next_key;
-    }
-
-    va_end (ap);
-}
-
-void
-kvp_frame_set_slot_path_gslist (KvpFrame *frame,
-                                KvpValue * new_value,
-                                GSList *key_path)
-{
-    if (!frame || !key_path) return;
-
-    while (TRUE)
-    {
-        const char *key = static_cast<char*>(key_path->data);
-        KvpValue *value;
-
-        if (!key)
-            return;
-
-        g_return_if_fail (*key != '\0');
-
-        key_path = key_path->next;
-        if (!key_path)
-        {
-            kvp_frame_set_slot (frame, key, new_value);
-            return;
-        }
-
-        value = kvp_frame_get_slot (frame, key);
-        if (!value)
-        {
-            KvpFrame *new_frame = kvp_frame_new ();
-            KvpValue *frame_value = kvp_value_new_frame (new_frame);
-
-            kvp_frame_set_slot_nc (frame, key, frame_value);
-
-            value = kvp_frame_get_slot (frame, key);
-            if (!value)
-                return;
-        }
-
-        frame = kvp_value_get_frame (value);
-        if (!frame)
-            return;
-    }
-}
-
-gint64
-kvp_frame_get_gint64(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_gint64(kvp_frame_get_slot (frame, key));
-}
-double
-kvp_frame_get_double(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_double(kvp_frame_get_slot (frame, key));
-}
-
-gnc_numeric
-kvp_frame_get_numeric(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_numeric(kvp_frame_get_slot (frame, key));
-}
-
-const char *
-kvp_frame_get_string(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_string(kvp_frame_get_slot (frame, key));
-}
-
-GncGUID *
-kvp_frame_get_guid(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_guid(kvp_frame_get_slot (frame, key));
-}
-
-Timespec
-kvp_frame_get_timespec(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_timespec(kvp_frame_get_slot (frame, key));
-}
-
-KvpFrame *
-kvp_frame_get_frame(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_value_get_frame(kvp_frame_get_slot (frame, key));
-}
-
-KvpValue *
-kvp_frame_get_value(const KvpFrame *frame, const char *path)
-{
-    char *key = NULL;
-    frame = get_trailer_or_null (frame, path, &key);
-    return kvp_frame_get_slot (frame, key);
-}
-
-/* ============================================================ */
-
-KvpFrame *
-kvp_frame_get_frame_slash (KvpFrame *frame, const char *key_path)
-{
-    char *root;
-    if (!frame || !key_path) return frame;
-
-    root = g_strdup (key_path);
-    frame = kvp_frame_get_frame_slash_trash (frame, root);
-    g_free(root);
-    return frame;
-}
-
-/* ============================================================ */
-
-KvpValue *
-kvp_frame_get_slot_path (KvpFrame *frame,
-                         const char *first_key, ...)
-{
-    va_list ap;
-    KvpValue *value;
-    const char *key;
-
-    if (!frame || !first_key) return NULL;
-
-    va_start (ap, first_key);
-
-    key = first_key;
-    value = NULL;
-
-    while (TRUE)
-    {
-        value = kvp_frame_get_slot (frame, key);
-        if (!value) break;
-
-        key = va_arg (ap, const char *);
-        if (!key) break;
-
-        frame = kvp_value_get_frame (value);
-        if (!frame)
-        {
-            value = NULL;
-            break;
-        }
-    }
-
-    va_end (ap);
-
-    return value;
-}
-
-KvpValue *
-kvp_frame_get_slot_path_gslist (KvpFrame *frame,
-                                const GSList *key_path)
-{
-    if (!frame || !key_path) return NULL;
-
-    while (TRUE)
-    {
-        const char *key = static_cast<const char*>(key_path->data);
-        KvpValue *value;
-
-        if (!key) break;
-
-        value = kvp_frame_get_slot (frame, key);
-        if (!value) break;
-
-        key_path = key_path->next;
-        if (!key_path) return value;
-
-        frame = kvp_value_get_frame (value);
-        if (!frame) break;
-    }
-    return NULL;
-}
-
-
-/* *******************************************************************
- * Kvpvalue functions
- ********************************************************************/
-
-KvpValue *
-kvp_value_new_gint64(int64_t value)
-{
-    return new KvpValueImpl{value};
-}
-
-KvpValue *
-kvp_value_new_double(double value)
-{
-    return new KvpValueImpl{value};
-}
-
-KvpValue *
-kvp_value_new_boolean(gboolean value)
-{
-    if (!value) return {};
-    return new KvpValueImpl{g_strdup("true")};
-}
-
-KvpValue *
-kvp_value_new_numeric(gnc_numeric value)
-{
-    return new KvpValueImpl{value};
-}
-
-KvpValue *
-kvp_value_new_string(const char * value)
-{
-    if (!value) return {};
-    return new KvpValueImpl{g_strdup(value)};
-}
-
-KvpValue *
-kvp_value_new_guid(const GncGUID * value)
-{
-    if (!value) return {};
-    return new KvpValueImpl{guid_copy(value)};
-}
-
-KvpValue *
-kvp_value_new_timespec(Timespec value)
-{
-    return new KvpValueImpl{value};
-}
-
-KvpValue *
-kvp_value_new_gdate(GDate value)
-{
-    return new KvpValueImpl{value};
-}
-
-KvpValue *
-kvp_value_new_glist(const GList * value)
-{
-    if (!value) return {};
-    return nullptr;
-}
-
-KvpValue *
-kvp_value_new_glist_nc(GList * value)
-{
-    if (!value) return {};
-    return new KvpValueImpl{value};
-}
-
-KvpValue *
-kvp_value_new_frame(const KvpFrame * value)
-{
-    if (!value) return {};
-    return new KvpValueImpl{kvp_frame_copy(value)};
-}
-
-KvpValue *
-kvp_value_new_frame_nc(KvpFrame * value)
-{
-    if (!value) return {};
-    return new KvpValueImpl{value};
-}
-
-void
-kvp_value_delete(KvpValue * value)
-{
-    if (!value) return;
-    KvpValueImpl * realvalue {static_cast<KvpValueImpl *>(value)};
-    delete realvalue;
-}
-
-int64_t
-kvp_value_get_gint64(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<int64_t>();
-}
-
-double
-kvp_value_get_double(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<double>();
-}
-
-bool
-kvp_value_get_boolean (const KvpValue *ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl *value {static_cast<const KvpValueImpl*>(ovalue)};
-    const char* str = value->get<char*>();
-    return str && strcmp(str, "true") == 0;
-}
-
-gnc_numeric
-kvp_value_get_numeric(const KvpValue * ovalue)
-{
-    //if (!ovalue) return {}; The code depends on no segfault and zero being returned here.
-    if (!ovalue) return gnc_numeric_zero();
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<gnc_numeric>();
-}
-
-const char *
-kvp_value_get_string(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<const char*>();
-}
-
-GncGUID *
-kvp_value_get_guid(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<GncGUID*>();
-}
-
-Timespec
-kvp_value_get_timespec(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<Timespec>();
-}
-
-GDate
-kvp_value_get_gdate(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<GDate>();
-}
-
-GList *
-kvp_value_get_glist(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<GList*>();
-}
-
-KvpFrame *
-kvp_value_get_frame(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<KvpFrame*>();
-}
-
-KvpFrame *
-kvp_value_replace_frame_nc(KvpValue * ovalue, KvpFrame * newframe)
-{
-    if (!ovalue) return {};
-    KvpValueImpl * value {static_cast<KvpValueImpl *>(ovalue)};
-    return value->replace_frame_nc (newframe);
-}
-
-GList *
-kvp_value_replace_glist_nc(KvpValue * ovalue, GList *newlist)
-{
-    if (!ovalue) return {};
-    KvpValueImpl * value {static_cast<KvpValueImpl *>(ovalue)};
-    return value->replace_glist_nc (newlist);
-}
-
-KvpValue *
-kvp_value_copy(const KvpValue * ovalue)
-{
-    if (!ovalue) return {};
-    auto value = static_cast<const KvpValueImpl *>(ovalue);
-    KvpValueImpl * ret = new KvpValueImpl(*value);
-    return static_cast<KvpValue *>(ret);
-}
-
-void
-kvp_frame_for_each_slot(KvpFrame *f,
-                        void (*proc)(const char *key,
-                                     KvpValue *value,
-                                     gpointer data),
-                        gpointer data)
-{
-    if (!f) return;
-    auto realframe = static_cast<KvpFrameImpl *>(f);
-    realframe->for_each_slot(proc, data);
-}
-
-int
-kvp_value_compare(const KvpValue * okva, const KvpValue * okvb)
-{
-    auto kva = static_cast<const KvpValueImpl *>(okva);
-    auto kvb = static_cast<const KvpValueImpl *>(okvb);
-    return compare(kva, kvb);
-}
-
-gint
-kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb)
-{
-    auto realone = static_cast<const KvpFrameImpl *>(fa);
-    auto realtwo = static_cast<const KvpFrameImpl *>(fb);
-    return compare(realone, realtwo);
-}
-
-char *
-kvp_value_to_string(const KvpValue * val)
-{
-    if (!val) return g_strdup("");
-    auto realval = static_cast<const KvpValueImpl *>(val);
-    return realval->to_string();
-}
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-void init_static_test_pointers( void );
-
-#ifdef __cplusplus
-}
-#endif
-
-KvpFrame* ( *p_get_trailer_make )( KvpFrame *frame, const char *key_path, char **end_key );
-KvpFrame* ( *p_get_or_make )( KvpFrame *fr, const char * key );
-const KvpFrame* ( *p_kvp_frame_get_frame_or_null_slash_trash )( const KvpFrame *frame, char *key_path );
-const KvpFrame* ( *p_get_trailer_or_null )( const KvpFrame * frame, const char * key_path, char **end_key );
-
-void
-init_static_test_pointers( void )
-{
-    p_get_trailer_make = get_trailer_make;
-    p_get_or_make = get_or_make;
-    p_kvp_frame_get_frame_or_null_slash_trash = kvp_frame_get_frame_or_null_slash_trash;
-    p_get_trailer_or_null = get_trailer_or_null;
-}
-
-char*
-kvp_frame_to_string(const KvpFrame *frame)
-{
-    auto realframe = static_cast<KvpFrameImpl const *>(frame);
-    /*We'll use g_strdup
-     because it will be freed using g_free.*/
-    return g_strdup(realframe->to_string().c_str());
-}
 
 static void
 gvalue_list_from_kvp_value (KvpValue *kval, gpointer pList)
@@ -1246,40 +311,41 @@ gvalue_from_kvp_value (const KvpValue *kval)
     {
         case KvpValue::Type::INT64:
             g_value_init (val, G_TYPE_INT64);
-            g_value_set_int64 (val, kvp_value_get_gint64 (kval));
+            g_value_set_int64 (val, kval->get<int64_t>());
             break;
         case KvpValue::Type::DOUBLE:
             g_value_init (val, G_TYPE_DOUBLE);
-            g_value_set_double (val, kvp_value_get_double (kval));
+            g_value_set_double (val, kval->get<double>());
             break;
         case KvpValue::Type::NUMERIC:
             g_value_init (val, GNC_TYPE_NUMERIC);
-            num = kvp_value_get_numeric (kval);
+            num = kval->get<gnc_numeric>();
             g_value_set_boxed (val, &num);
             break;
         case KvpValue::Type::STRING:
             g_value_init (val, G_TYPE_STRING);
-            g_value_set_string (val, kvp_value_get_string (kval));
+            g_value_set_string (val, kval->get<const char*>());
             break;
         case KvpValue::Type::GUID:
             g_value_init (val, GNC_TYPE_GUID);
-            g_value_set_boxed (val, kvp_value_get_guid (kval));
+            g_value_set_boxed (val, kval->get<GncGUID*>());
             break;
         case KvpValue::Type::TIMESPEC:
             g_value_init (val, GNC_TYPE_TIMESPEC);
-            tm = kvp_value_get_timespec (kval);
+            tm = kval->get<Timespec>();
             g_value_set_boxed (val, &tm);
             break;
         case KvpValue::Type::GDATE:
             g_value_init (val, G_TYPE_DATE);
-            gdate = kvp_value_get_gdate (kval);
+            gdate = kval->get<GDate>();
             g_value_set_boxed (val, &gdate);
             break;
         case KvpValue::Type::GLIST:
         {
             GList *gvalue_list = NULL;
-            GList *kvp_list = kvp_value_get_glist (kval);
-            g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value, &gvalue_list);
+            GList *kvp_list = kval->get<GList*>();
+            g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value,
+                            &gvalue_list);
             g_value_init (val, GNC_TYPE_VALUE_LIST);
             gvalue_list = g_list_reverse (gvalue_list);
             g_value_set_boxed (val, gvalue_list);
@@ -1308,28 +374,41 @@ kvp_value_from_gvalue (const GValue *gval)
     g_return_val_if_fail (G_VALUE_TYPE (gval), NULL);
 
     if (type == G_TYPE_INT64)
-        val = kvp_value_new_gint64 (g_value_get_int64 (gval));
+        val = new KvpValue(g_value_get_int64 (gval));
     else if (type == G_TYPE_DOUBLE)
-        val = kvp_value_new_double (g_value_get_double (gval));
+        val = new KvpValue(g_value_get_double (gval));
     else if (type == G_TYPE_BOOLEAN)
-        val = kvp_value_new_boolean (g_value_get_boolean (gval));
+    {
+        auto bval = g_value_get_boolean(gval);
+        if (bval)
+            val = new KvpValue(g_strdup("true"));
+    }
     else if (type == GNC_TYPE_NUMERIC)
-        val = kvp_value_new_numeric (*(gnc_numeric*)g_value_get_boxed (gval));
+        val = new KvpValue(*(gnc_numeric*)g_value_get_boxed (gval));
     else if (type == G_TYPE_STRING)
-        val = kvp_value_new_string (g_value_get_string (gval));
+    {
+        auto string = g_value_get_string(gval);
+        if (string != nullptr)
+            val = new KvpValue(g_strdup(string));
+    }
     else if (type == GNC_TYPE_GUID)
-        val = kvp_value_new_guid ((GncGUID*)g_value_get_boxed (gval));
+    {
+        auto boxed = g_value_get_boxed(gval);
+        if (boxed != nullptr)
+            val = new KvpValue(guid_copy(static_cast<GncGUID*>(boxed)));
+    }
     else if (type == GNC_TYPE_TIMESPEC)
-        val = kvp_value_new_timespec (*(Timespec*)g_value_get_boxed (gval));
+        val = new KvpValue(*(Timespec*)g_value_get_boxed (gval));
     else if (type == G_TYPE_DATE)
-        val = kvp_value_new_gdate (*(GDate*)g_value_get_boxed (gval));
+        val = new KvpValue(*(GDate*)g_value_get_boxed (gval));
     else if (type == GNC_TYPE_VALUE_LIST)
     {
         GList *gvalue_list = (GList*)g_value_get_boxed (gval);
         GList *kvp_list = NULL;
-        g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue, &kvp_list);
+        g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue,
+                        &kvp_list);
         kvp_list = g_list_reverse (kvp_list);
-        val = kvp_value_new_glist_nc (kvp_list);
+        val = new KvpValue(kvp_list);
 //      g_list_free_full (gvalue_list, (GDestroyNotify)g_value_unset);
 //      gvalue_list = NULL;
     }
@@ -1339,21 +418,7 @@ kvp_value_from_gvalue (const GValue *gval)
 
     return val;
 }
-
-GValue*
-kvp_frame_get_gvalue (KvpFrame *frame, const gchar *key)
-{
-    KvpValue *kval = kvp_frame_get_value (frame, key);
-    GValue *value = gvalue_from_kvp_value (kval);
-    return value;
-}
-
-void
-kvp_frame_set_gvalue (KvpFrame *frame, const gchar *key, const GValue *value)
-{
-    kvp_frame_set_value_nc (frame, key, kvp_value_from_gvalue (value));
-}
-
+/* The following are required for using KvpValue GLists as GValues */
 static void
 gnc_gvalue_copy (GValue *src, gpointer uData)
 {
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
deleted file mode 100644
index 3b02e67..0000000
--- a/src/libqof/qof/kvp_frame.h
+++ /dev/null
@@ -1,586 +0,0 @@
-/********************************************************************\
- * kvp_frame.h -- Implements a key-value frame system               *
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
- *                                                                  *
-\********************************************************************/
-/** @addtogroup KVP
-
- * A KvpFrame is a set of associations between character strings
- * (keys) and KvpValue structures.  A KvpValue is a union with
- * possible types enumerated in the KvpValue::Type enum, and includes,
- * among other things, ints, doubles, strings, guid's, lists, time
- * and numeric values.  KvpValues may also be other frames, so
- * KVP is inherently hierarchical.
- *
- * Values are stored in a 'slot' associated with a key.
- * Pointers passed as arguments into set_slot and get_slot are the
- * responsibility of the caller.  Pointers returned by get_slot are
- * owned by the kvp_frame.  Make copies as needed.
- *
- * A 'path' is a sequence of keys that can be followed to a value.
- * Paths may be specified as varargs (variable number of arguments
- * to a subrutine, NULL-terminated), as a GSList, or as a standard
- * URL-like path name.  The later is parsed and treated in the same
- * way as file paths would be: / separates keys, /./ is treated as /
- * and /../ means backup one level.  Repeated slashes are treated
- * as one slash.
- *
- * Note that although, in principle, keys may contain the / and . and
- * .. characters,  doing so may lead to confusion, and will make
- * path-string parsing routines fail.  In other words, don't use
- * a key such as 'some/key' or 'some/./other/../key' because you
- * may get unexpected results.
- *
- * To set a value into a frame, you will want to use one of the
- * kvp_frame_set_xxx() routines.  Most of the other routines provide
- * only low-level access that you probably shouldn't use.
-
-@{
-*/
-/** @file kvp_frame.h
-    @brief A key-value frame system
-    @author Copyright (C) 2000 Bill Gribble
-    @author Copyright (C) 2003 Linas Vepstas <linas at linas.org>
-*/
-
-#ifndef KVP_FRAME_H
-#define KVP_FRAME_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "gnc-date.h"
-#include "gnc-numeric.h"
-#include "guid.h"
-
-#define QOF_MOD_KVP "qof.kvp"
-
-/** Opaque frame structure */
-typedef struct KvpFrameImpl KvpFrame;
-
-typedef struct KvpValueImpl KvpValue;
-
-/** @name KvpFrame Constructors
- @{
-*/
-
-/** Return a new empty instance of KvpFrame */
-KvpFrame   * kvp_frame_new(void);
-
-/** Perform a deep (recursive) delete of the frame and any subframes.
-
- * kvp_frame_delete and kvp_value_delete are deep (recursive) deletes.
- * kvp_frame_copy and kvp_value_copy are deep value copies.
- */
-void         kvp_frame_delete(KvpFrame * frame);
-
-/** Perform a deep (recursive) value copy, copying the fraame,
- *  subframes, and the values as well. */
-KvpFrame   * kvp_frame_copy(const KvpFrame * frame);
-
-/** Return TRUE if the KvpFrame is empty */
-gboolean     kvp_frame_is_empty(const KvpFrame * frame);
-
-/** @} */
-
-/** @name KvpFrame Basic Value Storing
-@{
-*/
-
-/**
- * Retrieve the keys for the frame.
- *
- * Returns a null-terminated array of the keys which can be
- * used to look up values and determine the pairs in this frame.
- *
- * The caller should free the array using g_free, but should
- * not free the keys.
- */
-const char ** kvp_frame_get_keys(const KvpFrame * frame);
-
-/**    store the value of the
- *     gint64 at the indicated path. If not all frame components of
- *     the path exist, they are created.
- *
- */
-void kvp_frame_set_gint64(KvpFrame * frame, const gchar * path, gint64 ival);
-/**
- *     store the value of the
- *     double at the indicated path. If not all frame components of
- *     the path exist, they are created.
-*/
-void kvp_frame_set_double(KvpFrame * frame, const gchar * path, double dval);
-
-/** \deprecated
-
-Use kvp_frame_set_numeric instead of kvp_frame_set_gnc_numeric
-*/
-#define kvp_frame_set_gnc_numeric kvp_frame_set_numeric
-/**    store the value of the
- *     gnc_numeric at the indicated path.
- *     If not all frame components of
- *     the path exist, they are created.
- */
-void kvp_frame_set_numeric(KvpFrame * frame, const gchar * path, gnc_numeric nval);
-/**    store the value of the
- *     Timespec at the indicated path.
- *     If not all frame components of
- *     the path exist, they are created.
- */
-void kvp_frame_set_timespec(KvpFrame * frame, const gchar * path, Timespec ts);
-
-/** \brief Store a copy of the string at the indicated path.
-
- *    If not all frame components of the path
- *    exist, they are created.  If there was another string previously
- *    stored at that path, the old copy is deleted.
- *
- *    Similarly, the set_guid and set_frame will make copies and
- *    store those.  Old copies, if any, are deleted.
- *
- * The kvp_frame_set_frame_nc() routine works as above, but does
- *    *NOT* copy the frame.
- */
-void kvp_frame_set_string(KvpFrame * frame, const gchar * path, const gchar* str);
-void kvp_frame_set_guid(KvpFrame * frame, const gchar * path, const GncGUID *guid);
-
-void kvp_frame_set_frame(KvpFrame *frame, const gchar *path, KvpFrame *chld);
-void kvp_frame_set_frame_nc(KvpFrame *frame, const gchar *path, KvpFrame *chld);
-
-/** The kvp_frame_set_value() routine copies the value into the frame,
- *    at the location 'path'.   If the path contains slashes '/', these
- *    are assumed to represent a sequence of keys.  The returned value
- *    is a pointer to the actual frame into which the value was inserted;
- *    it is NULL if the frame couldn't be found (and thus the value wasn't
- *    inserted).  The old value at this location, if any, is destroyed.
- *
- *    Pointers passed as arguments into this routine are the responsibility
- *    of the caller; the pointers are *not* taken over or managed.
- */
-KvpFrame *   kvp_frame_set_value(KvpFrame * frame,
-                                 const gchar * path, const KvpValue * value);
-/**
- * The kvp_frame_set_value_nc() routine puts the value (without copying
- *    it) into the frame, putting it at the location 'path'.  If the path
- *    contains slashes '/', these are assumed to represent a sequence of keys.
- *    The returned value is a pointer to the actual frame into which the value
- *    was inserted; it is NULL if the frame couldn't be found (and thus the
- *    value wasn't inserted).  The old value at this location, if any,
- *    is destroyed.
- *
- *    This routine is handy for avoiding excess memory allocations & frees.
- *    Note that because the KvpValue was grabbed, you can't just delete
- *    unless you remove the key as well (or unless you replace the value).
- */
-KvpFrame *    kvp_frame_set_value_nc(KvpFrame * frame,
-                                     const gchar * path, KvpValue * value);
-
-/** The kvp_frame_replace_value_nc() routine places the new value
- *    at the indicated path.   It returns the old value, if any.
- *    It returns NULL if there was an error, or if there was no
- *    old value. If the path doesn't exist, it is created, unless
- *    new_value is NULL.  Passing in a NULL new_value has the
- *    effect of deleting the trailing slot (i.e. the trailing path
- *    element).
- */
-KvpValue * kvp_frame_replace_value_nc (KvpFrame * frame, const gchar * slot,
-                                       KvpValue * new_value);
-/** @} */
-
-/** @name KvpFrame Glist Bag Storing
- @{
-*/
-
-/** \brief Store the given kvp_frame to the glist bag at the indicated path (non-copying)
-
- *    If not all frame components
- *    of the path exist, they are created.  If there was another
- *    item previously stored at that path, then the path is converted
- *    to a bag, and the old value, along with the new value, is added
- *    to the bag.
- *
- * This method does *NOT* copy the frame.
- */
-void kvp_frame_add_frame_nc(KvpFrame *frame, const gchar *path, KvpFrame *chld);
-
-
-/** @} */
-
-/** @name KvpFrame Value Fetching
-
-  Value accessors.  These all take a unix-style slash-separated
-  path as an argument, and return the value stored at that location.
-  If the object at the end of that path is not of the type that was
-  asked for, then a NULL or a zero is returned.  So, for example,
-  asking for a string when the path stored an int will return a NULL.
-  In some future date, this may be changed to a looser type system,
-  such as perl's automatic re-typing (e.g. an integer value might be
-  converted to a printed string representing that value).
-
-  If any part of the path does not exist, then NULL or zero will be
-  returned.
-
-  The values returned for GncGUID, GList, KvpFrame and string
-  are "non-copying" -- the returned item is the actual item stored.
-  Do not delete this item unless you take the required care to avoid
-  possible bad pointer derefrences (i.e. core dumps).  Also, be
-  careful hanging on to those references if you are also storing
-  at the same path names: the referenced item will be freed during
-  the store.
-
-  That is, if you get a string value (or guid or frame),
-  and then store something else at that path, the string that you've
-  gotten will be freed during the store (internally, by the set_*()
-  routines), and you will be left hanging onto an invalid pointer.
-@{
-*/
-
-gint64      kvp_frame_get_gint64(const KvpFrame *frame, const gchar *path);
-double      kvp_frame_get_double(const KvpFrame *frame, const gchar *path);
-gnc_numeric kvp_frame_get_numeric(const KvpFrame *frame, const gchar *path);
-const gchar * kvp_frame_get_string(const KvpFrame *frame, const gchar *path);
-GncGUID      * kvp_frame_get_guid(const KvpFrame *frame, const gchar *path);
-Timespec    kvp_frame_get_timespec(const KvpFrame *frame, const gchar *path);
-KvpValue  * kvp_frame_get_value(const KvpFrame *frame, const gchar *path);
-
-/** Value accessor.  Takes a unix-style slash-separated path as an
- *  argument, and return the KvpFrame stored at that location.  If the
- *  KvpFrame does not exist, then a NULL is returned.
- *
- *  @note The semantics here have changed: In gnucash-1.8, if the
- *  KvpFrame did not exist, this function automatically created one
- *  and returned it. However, now this function will return NULL in
- *  this case and the caller has to create a KvpFrame on his own. The
- *  old functionality is now implemented by
- *  kvp_frame_get_frame_path(). This happened on 2003-09-14, revision
- *  1.31. FIXME: Is it really a good idea to change the semantics of
- *  an existing function and move the old semantics to a new
- *  function??! It would save us a lot of trouble if the new semantics
- *  would have been available in a new function!
- *
- *  @return The KvpFrame at the specified path, or NULL if it doesn't
- *  exist.
-*/
-/*@ dependent @*/
-KvpFrame* kvp_frame_get_frame(const KvpFrame *frame, const gchar *path);
-
-KvpFrame* kvp_frame_get_frame_slash (KvpFrame *frame,
-                                     const gchar *path);
-
-/** @} */
-/** @name KvpFrame KvpValue low-level storing routines.
-
-You probably shouldn't be using these low-level routines
-
- All of the kvp_frame_set_slot_*() routines set the slot values
-    "destructively", in that if there was an old value there, that
-    old value is destroyed (and the memory freed).  Thus, one
-    should not hang on to value pointers, as these will get
-    trashed if set_slot is called on the corresponding key.
-
-    If you want the old value, use kvp_frame_replace_slot().
- @{
-*/
-
-/** The kvp_frame_replace_slot_nc() routine places the new value into
- *    the indicated frame, for the given key.  It returns the old
- *    value, if any.  It returns NULL if the slot doesn't exist,
- *    if there was some other an error, or if there was no old value.
- *    Passing in a NULL new_value has the effect of deleting that
- *    slot.
- */
-/* KvpValue * kvp_frame_replace_slot_nc (KvpFrame * frame, const gchar * slot, */
-/*                                       KvpValue * new_value); */
-
-
-/** The kvp_frame_set_slot() routine copies the value into the frame,
- *    associating it with a copy of 'key'.  Pointers passed as arguments
- *    into kvp_frame_set_slot are the responsibility of the caller;
- *    the pointers are *not* taken over or managed.  The old value at
- *    this location, if any, is destroyed.
- */
-void          kvp_frame_set_slot(KvpFrame * frame,
-                                 const gchar * key, KvpValue * value);
-/**
- * The kvp_frame_set_slot_nc() routine puts the value (without copying
- *    it) into the frame, associating it with a copy of 'key'.  This
- *    routine is handy for avoiding excess memory allocations & frees.
- *    Note that because the KvpValue was grabbed, you can't just delete
- *    unless you remove the key as well (or unless you replace the value).
- *    The old value at this location, if any, is destroyed.
- */
-void          kvp_frame_set_slot_nc(KvpFrame * frame,
-                                    const gchar * key, KvpValue * value);
-
-/** The kvp_frame_set_slot_path() routine walks the hierarchy,
- *     using the key values to pick each branch.  When the terminal
- *     node is reached, the value is copied into it.  The old value
- *     at this location, if any, is destroyed.
- */
-void          kvp_frame_set_slot_path (KvpFrame *frame,
-                                       KvpValue *value,
-                                       const gchar *first_key, ...);
-
-/** The kvp_frame_set_slot_path_gslist() routine walks the hierarchy,
- *     using the key values to pick each branch.  When the terminal node
- *     is reached, the value is copied into it.  The old value at this
- *     location, if any, is destroyed.
- */
-void          kvp_frame_set_slot_path_gslist (KvpFrame *frame,
-        KvpValue *value,
-        GSList *key_path);
-
-/** @} */
-
-/** @name KvpFrame KvpValue Low-Level Retrieval Routines
-
-  You probably shouldn't be using these low-level routines
-
-  Returns the KvpValue in the given KvpFrame 'frame' that is
-  associated with 'key'.  If there is no key in the frame, NULL
-  is returned.  If the value associated with the key is NULL,
-  NULL is returned.
-
-  Pointers passed as arguments into get_slot are the responsibility
-  of the caller.  Pointers returned by get_slot are owned by the
-  kvp_frame.  Make copies as needed.
- @{
-*/
-KvpValue   * kvp_frame_get_slot(const KvpFrame * frame, const gchar * key);
-
-/** This routine return the value at the end of the
- * path, or NULL if any portion of the path doesn't exist.
- */
-KvpValue   * kvp_frame_get_slot_path (KvpFrame *frame,
-                                      const gchar *first_key, ...);
-
-/** This routine return the value at the end of the
- * path, or NULL if any portion of the path doesn't exist.
- */
-KvpValue   * kvp_frame_get_slot_path_gslist (KvpFrame *frame,
-        const GSList *key_path);
-
-/**
- * Similar returns as strcmp.
- */
-gint          kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb);
-
-gint          double_compare(double v1, double v2);
-/** @} */
-
-
-/** @name KvpValue Constructors
-
- You probably shouldn't be using these low-level routines
-
- The following routines are constructors for kvp_value.
- Those with pointer arguments copy in the value.
- The *_nc() versions do *not* copy in thier values,
- but use them directly.
- @{
- */
-KvpValue   * kvp_value_new_gint64(gint64 value);
-KvpValue   * kvp_value_new_double(double value);
-
-/** \deprecated
-
-Use kvp_value_new_numeric instead of kvp_value_new_gnc_numeric
-*/
-#define kvp_value_new_gnc_numeric kvp_value_new_numeric
-KvpValue   * kvp_value_new_numeric(gnc_numeric value);
-KvpValue   * kvp_value_new_string(const gchar * value);
-KvpValue   * kvp_value_new_guid(const GncGUID * guid);
-KvpValue   * kvp_value_new_timespec(Timespec timespec);
-KvpValue   * kvp_value_new_frame(const KvpFrame * value);
-KvpValue   * kvp_value_new_gdate(GDate date);
-
-/** Creates a KvpValue from a <b>GList of kvp_value's</b>! (Not to be
- *  confused with GList's of something else!) */
-KvpValue   * kvp_value_new_glist(const GList * value);
-
-/** Creates a KvpValue from a <b>GList of kvp_value's</b>! (Not to be
- * confused with GList's of something else!)
- *
- * This value constructor is non-copying (KvpValue takes pointer
- * ownership). The values *must* have been allocated via glib
- * allocators! (gnew, etc.) */
-KvpValue   * kvp_value_new_glist_nc(GList *lst);
-
-/** value constructors (non-copying - KvpValue takes pointer ownership)
-   values *must* have been allocated via glib allocators! (gnew, etc.) */
-KvpValue   * kvp_value_new_frame_nc(KvpFrame * value);
-
-/** This is a deep (recursive) delete. */
-void          kvp_value_delete(KvpValue * value);
-
-/** This is a deep value copy. */
-KvpValue   * kvp_value_copy(const KvpValue * value);
-
-/** Replace old frame value with new, return old frame */
-KvpFrame * kvp_value_replace_frame_nc(KvpValue *value, KvpFrame * newframe);
-
-/** Replace old glist value with new, return old glist */
-GList * kvp_value_replace_glist_nc(KvpValue *value, GList *newlist);
-
-/** @} */
-
-
-/** @name KvpValue Value access
-
- You probably shouldn't be using these low-level routines
- @{
-*/
-
-/** Value accessors. Those for GncGUID, GList, KvpFrame and
- *   string are non-copying -- the caller can modify the value
- *   directly. Just don't free it, or you screw up everything.
- *   Note that if another value is stored at the key location
- *   that this value came from, then this value will be
- *   uncermoniously deleted, and you will be left pointing to
- *   garbage.  So don't store values at the same time you are
- *   examining their contents.
- */
-
-gint64      kvp_value_get_gint64(const KvpValue * value);
-double      kvp_value_get_double(const KvpValue * value);
-gnc_numeric kvp_value_get_numeric(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-const char* kvp_value_get_string(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-GncGUID        * kvp_value_get_guid(const KvpValue * value);
-
-/** Returns the GList of kvp_frame's (not to be confused with GList's
- * of something else!) from the given kvp_frame.  This one is
- * non-copying -- the caller can modify the value directly. */
-GList       * kvp_value_get_glist(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-/*@ dependent @*/
-KvpFrame   * kvp_value_get_frame(const KvpValue * value);
-Timespec    kvp_value_get_timespec(const KvpValue * value);
-
-/** Value accessor for GDate */
-GDate    kvp_value_get_gdate(const KvpValue * value);
-
-/**
- * Similar returns as strcmp.
- **/
-gint          kvp_value_compare(const KvpValue *va, const KvpValue *vb);
-
-/** @} */
-
-/** \brief Debug version of kvp_value_to_string
-
-This version is used only by ::qof_query_printValueForParam,
-itself a debugging and development utility function.
-*/
-gchar* kvp_value_to_string(const KvpValue *val);
-
-/** @name  Iterators
-@{
-*/
-/** Traverse all of the slots in the given kvp_frame.  This function
-   does not descend recursively to traverse any kvp_frames stored as
-   slot values.  You must handle that in proc, with a suitable
-   recursive call if desired. */
-void kvp_frame_for_each_slot(KvpFrame *f,
-                             void (*proc)(const gchar *key,
-                                     KvpValue *value,
-                                     gpointer data),
-                             gpointer data);
-
-/** @} */
-
-/** Internal helper routines, you probably shouldn't be using these. */
-gchar* kvp_frame_to_string(const KvpFrame *frame);
-
-/** Convert a kvp_value into a GValue. Frames aren't converted.
- * @param kval: A KvpValue.
- * @return GValue*. Must be freed with g_free().
- */
-GValue* gvalue_from_kvp_value (const KvpValue *kval);
-
-/** Convert a gvalue into a kvpvalue.
- * @param gval: A GValue of a type KvpValue can digest.
- * @return KvpValue created from the GValue's contents.
- */
-KvpValue* kvp_value_from_gvalue (const GValue *gval);
-
-/** KvpItem: GValue Exchange
- * \brief Transfer of KVP to and from GValue, with the key
- *
- * Used to parameterize KVP <-> GValue exchanges.
- */
-typedef struct
-{
-    const gchar   *key;
-    GValue        *value;
-}KvpItem;
-
-/** Return a KvpItem containing the value of a KvpFrame
- *
- * Structure types (gnc_numeric, Timespec) are converted to pointers
- * and must be extracted with g_value_get_boxed. A KVP_TYPE_GLIST will
- * have all of its contents converted from KvpValues to GValues, so
- * the return type will be a GValue containing a GList of GValue*, not
- * GValue.  Use gnc_value_list_free() to free such a list if you take
- * it out of the GValue.
- *
- * \param frame: (transfer-none) The KvpFrame retrieved with kvp_get_frame_foo()
- * \param key: (transfer-none) A slash-delimited string with the path to
- * the stored value. Must not be NULL or empty.
- * \return (transfer-full) A KvpItem* which must be freed with kvp_item_free().
- */
-GValue *kvp_frame_get_gvalue (KvpFrame *frame, const gchar *key);
-
-/** Replace or create a Kvp slot from a KvpItem
- *
- * Structure types (gnc_numeric, Timespec) should be stored as
- * boxed-type pointers in the GValue with the appropriate type from
- * qof.h. Lists should be stored as a GValue containing a GList of
- * GValues of type convertable to KvpValues. Unsupported types will
- * emit a warning message and will be skipped.
- *
- * \param frame: (transfer none) The KvpFrame into which the value
- * will be added.
- * \param key: (transfer none) The subkey of the frame at which to
- * store the value
- * \param value: GValue containing the paramter to store.
- */
-void kvp_frame_set_gvalue (KvpFrame *frame, const gchar *key, const GValue *value);
-
-/**
- * \brief Convenience function to release the value in a GValue
- * acquired by kvp_frame_get_gvalue and to free the GValue.
- * \param value: A GValue* created by kvp_frame_get_gvalue
- */
-void gnc_gvalue_free (GValue *value);
-
- /** @} */
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/libqof/qof/kvp_frame.hpp b/src/libqof/qof/kvp_frame.hpp
index 46ec14b..5aae496 100644
--- a/src/libqof/qof/kvp_frame.hpp
+++ b/src/libqof/qof/kvp_frame.hpp
@@ -1,6 +1,7 @@
 /********************************************************************\
  * kvp-frame.hpp -- Implements a key-value frame system             *
  * Copyright (C) 2014 Aaron Laws                                    *
+ * Copyright 2015 John Ralls                                        *
  *                                                                  *
  * This program is free software; you can redistribute it and/or    *
  * modify it under the terms of the GNU General Public License as   *
@@ -20,6 +21,25 @@
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  *                                                                  *
 \********************************************************************/
+/** @addtogroup KVP
+
+ * A KvpFrame is a set of associations between character strings
+ * (keys) and KvpValues.  A KvpValue is notionally a union with
+ * possible types enumerated in the KvpValue::Type enum, and includes,
+ * among other things, ints, doubles, strings, guids, lists, time
+ * and numeric values.  KvpValues may also be other frames, so
+ * KVP is inherently hierarchical.
+ *
+ * Values are stored in a 'slot' associated with a key.
+ * Pointers passed as arguments into set_slot and get_slot are the
+ * responsibility of the caller.  Pointers returned by get_slot are
+ * owned by the kvp_frame.  Make copies as needed.
+ *
+ * A 'path' is a sequence of keys that can be followed to a value.  Paths are
+ * passed as either '/'-delimited strings or as std::vectors of keys. Unlike
+ * file system paths, the tokens '.' and '..' have no special meaning.
+ *
+*/
 
 #ifndef GNC_KVP_FRAME_TYPE
 #define GNC_KVP_FRAME_TYPE
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index 080ab25..ffd8182 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -38,7 +38,6 @@ extern "C"
 #include "qof.h"
 #include "qofbook-p.h"
 #include "qofid-p.h"
-#include "kvp_frame.h"
 #include "kvp_frame.hpp"
 #include "qofinstance-p.h"
 
diff --git a/src/libqof/qof/test/Makefile.am b/src/libqof/qof/test/Makefile.am
index e233cc1..96fe8de 100644
--- a/src/libqof/qof/test/Makefile.am
+++ b/src/libqof/qof/test/Makefile.am
@@ -22,7 +22,7 @@ test_qof_SOURCES = \
 test_qof_HEADERS = \
 	$(top_srcdir)/${MODULEPATH}/qofbook.h \
 	$(top_srcdir)/${MODULEPATH}/qofinstance.h \
-	$(top_srcdir)/${MODULEPATH}/kvp_frame.h \
+	$(top_srcdir)/${MODULEPATH}/kvp_frame.hpp \
 	$(top_srcdir)/${MODULEPATH}/qofobject.h \
 	$(top_srcdir)/${MODULEPATH}/qofsession.h \
 	$(top_srcdir)/src/test-core/unittest-support.h

commit ff07762f612d16f7d7e366d1d4170f2276f03b54
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jun 27 15:39:54 2015 -0700

    Move the KVP_TYPE enum to kvp-value.hpp.
    
    This had some extraordinary knock-on effects because C++11 treats enums
    very differently from C, so any C code that directly accessed the enum
    had to be converted to C++.
    
    That included test-engine-stuff, and because it quite sensibly builds as
    a ranlib archive instead of a shared library everything that uses it must
    at least link as C++. Fortunately automake takes care of doing this when
    the default extension for check_PROGRAMS is cpp, even if the source file
    is C.

diff --git a/src/app-utils/test/Makefile.am b/src/app-utils/test/Makefile.am
index c0cf529..5dbe1bb 100644
--- a/src/app-utils/test/Makefile.am
+++ b/src/app-utils/test/Makefile.am
@@ -8,6 +8,8 @@ check_PROGRAMS = \
   test-sx \
   test-app-utils
 
+AM_DEFAULT_SOURCE_EXT = .cpp
+
 TESTS =  \
   test-load-module \
   ${check_PROGRAMS}
@@ -16,7 +18,7 @@ test_exp_parser_SOURCES = \
   test-exp-parser.c
 
 test_print_parse_amount_SOURCES = \
-  test-print-parse-amount.c
+  test-print-parse-amount.cpp
 
 GNC_TEST_DEPS = --gnc-module-dir ${top_builddir}/src/engine \
   --gnc-module-dir ${top_builddir}/src/app-utils \
diff --git a/src/app-utils/test/test-option-util.cpp b/src/app-utils/test/test-option-util.cpp
index 16f0f35..7bc7b9b 100644
--- a/src/app-utils/test/test-option-util.cpp
+++ b/src/app-utils/test/test-option-util.cpp
@@ -228,8 +228,8 @@ test_option_save_book_currency (Fixture *fixture, gconstpointer pData)
                         scm_cons (scm_from_utf8_string("GTQ"),
                         scm_cons (scm_from_locale_symbol("fifo"), SCM_EOL)))));
     qof_book_save_options (book, gnc_option_db_save, odb, TRUE);
-    g_assert_cmpstr (kvp_frame_get_string(slots, "options/Accounts/Book Currency"), == , "GTQ");
-    g_assert_cmpstr (kvp_frame_get_string(slots, "options/Accounts/Default Gains Policy"), == , "fifo");
+    g_assert_cmpstr (slots->get_slot("options/Accounts/Book Currency")->get<const char*>(), == , "GTQ");
+    g_assert_cmpstr (slots->get_slot("options/Accounts/Default Gains Policy")->get<const char*>(), == , "fifo");
 
     gnc_option_db_destroy (odb);
 }
diff --git a/src/app-utils/test/test-print-parse-amount.c b/src/app-utils/test/test-print-parse-amount.cpp
similarity index 91%
rename from src/app-utils/test/test-print-parse-amount.c
rename to src/app-utils/test/test-print-parse-amount.cpp
index 5f7a4e6..83ac43c 100644
--- a/src/app-utils/test/test-print-parse-amount.c
+++ b/src/app-utils/test/test-print-parse-amount.cpp
@@ -1,3 +1,5 @@
+extern "C"
+{
 #include "config.h"
 #include <glib.h>
 #include <stdlib.h>
@@ -8,6 +10,7 @@
 #include "test-engine-stuff.h"
 #include "test-stuff.h"
 #include <unittest-support.h>
+}
 
 static void
 test_num_print_info (gnc_numeric n, GNCPrintAmountInfo print_info, int line)
@@ -16,13 +19,13 @@ test_num_print_info (gnc_numeric n, GNCPrintAmountInfo print_info, int line)
     const char *s;
     gboolean ok, print_ok;
 
-    gchar *msg = "[PrintAmountInternal()] Bad numeric from rounding: GNC_ERROR_OVERFLOW.";
-    gchar *log_domain = "gnc.gui";
-    guint loglevel = G_LOG_LEVEL_WARNING, hdlr;
-    TestErrorStruct check = { loglevel, log_domain, msg };
+    auto msg = "[PrintAmountInternal()] Bad numeric from rounding: GNC_ERROR_OVERFLOW.";
+    auto log_domain = "gnc.gui";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING);
+    auto check = test_error_struct_new (log_domain, loglevel, msg);
 
     /* Throws overflows during rounding step in xaccPrintAmount when the "fraction" is high. See bug 665707. */
-    hdlr = g_log_set_handler (log_domain, loglevel,
+    auto hdlr = g_log_set_handler (log_domain, loglevel,
                               (GLogFunc)test_checked_handler, &check);
     s = xaccPrintAmount (n, print_info);
     print_ok = (s && s[0] != '\0');
@@ -41,6 +44,7 @@ test_num_print_info (gnc_numeric n, GNCPrintAmountInfo print_info, int line)
                   "start: %s, string %s, finish: %s (line %d)",
                   gnc_numeric_to_string (n), s,
                   gnc_numeric_to_string (n_parsed), line);
+    test_error_struct_free (check);
 
 }
 
diff --git a/src/app-utils/test/test-scm-query-string.c b/src/app-utils/test/test-scm-query-string.c
index c3bb1a5..e2831e8 100644
--- a/src/app-utils/test/test-scm-query-string.c
+++ b/src/app-utils/test/test-scm-query-string.c
@@ -96,9 +96,6 @@ main_helper (void *closure, int argc, char **argv)
 
     xaccLogDisable ();
 
-    /* double->string->double is not idempotent */
-    kvp_exclude_type (KVP_TYPE_DOUBLE);
-
     /* Initialize to a known RNG position */
     srand(1);
 
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 257d30f..bbe2993 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -64,7 +64,7 @@ typedef struct
     gboolean is_ok;
     /*@ dependent @*/
     KvpFrame* pKvpFrame;
-    KvpValueType value_type;
+    KvpValue::Type value_type;
     GList *pList;
     context_t context;
     /*@ dependent @*/
@@ -77,7 +77,7 @@ static /*@ null @*/ gpointer get_obj_guid( gpointer pObject );
 static void set_obj_guid( void );
 static /*@ null @*/ gpointer get_path( gpointer pObject );
 static void set_path( gpointer pObject, /*@ null @*/ gpointer pValue );
-static KvpValueType get_slot_type( gpointer pObject );
+static KvpValue::Type get_slot_type( gpointer pObject );
 static void set_slot_type( gpointer pObject, /*@ null @*/ gpointer pValue );
 static gint64 get_int64_val( gpointer pObject );
 static void set_int64_val( gpointer pObject, gint64 pValue );
@@ -322,12 +322,12 @@ set_path( gpointer pObject, /*@ null @*/ gpointer pValue )
     pInfo->path = g_string_new( (gchar*)pValue );
 }
 
-static KvpValueType
+static KvpValue::Type
 get_slot_type( gpointer pObject )
 {
     slot_info_t* pInfo = (slot_info_t*)pObject;
 
-    g_return_val_if_fail( pObject != NULL, KVP_TYPE_INVALID );
+    g_return_val_if_fail( pObject != NULL, KvpValue::Type::INVALID );
 
 //    return (gpointer)kvp_value_get_type( pInfo->pKvpValue );
     return pInfo->value_type;
@@ -341,7 +341,7 @@ set_slot_type( gpointer pObject, /*@ null @*/ gpointer pValue )
     g_return_if_fail( pObject != NULL );
     g_return_if_fail( pValue != NULL );
 
-    pInfo->value_type = static_cast<KvpValueType>(GPOINTER_TO_INT(pValue));
+    pInfo->value_type = static_cast<KvpValue::Type>(GPOINTER_TO_INT(pValue));
 }
 
 static gint64
@@ -351,7 +351,7 @@ get_int64_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, 0 );
 
-    if ( pInfo->pKvpValue->get_type() == KVP_TYPE_GINT64 )
+    if ( pInfo->pKvpValue->get_type() == KvpValue::Type::INT64 )
     {
         return pInfo->pKvpValue->get<int64_t>();
     }
@@ -369,7 +369,7 @@ set_int64_val( gpointer pObject, gint64 value )
 
     g_return_if_fail( pObject != NULL );
 
-    if ( pInfo->value_type != KVP_TYPE_GINT64 ) return;
+    if ( pInfo->value_type != KvpValue::Type::INT64 ) return;
     pValue = new KvpValue{value};
     set_slot_from_value( pInfo, pValue );
 }
@@ -381,7 +381,7 @@ get_string_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if ( pInfo->pKvpValue->get_type() == KVP_TYPE_STRING )
+    if ( pInfo->pKvpValue->get_type() == KvpValue::Type::STRING )
     {
         return (gpointer)pInfo->pKvpValue->get<const char*>();
     }
@@ -397,7 +397,7 @@ set_string_val( gpointer pObject, /*@ null @*/ gpointer pValue )
     slot_info_t* pInfo = (slot_info_t*)pObject;
     g_return_if_fail( pObject != NULL );
 
-    if (pInfo->value_type != KVP_TYPE_STRING || pValue == NULL)
+    if (pInfo->value_type != KvpValue::Type::STRING || pValue == NULL)
         return;
     auto string = g_strdup(static_cast<const char*>(pValue));
     auto value = new KvpValue{string};
@@ -412,7 +412,7 @@ get_double_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if (pInfo->pKvpValue->get_type() == KVP_TYPE_DOUBLE)
+    if (pInfo->pKvpValue->get_type() == KvpValue::Type::DOUBLE)
     {
         d_val = pInfo->pKvpValue->get<double>();
         return (gpointer)&d_val;
@@ -431,7 +431,7 @@ set_double_val( gpointer pObject, /*@ null @*/ gpointer pValue )
 
     g_return_if_fail( pObject != NULL );
 
-    if ( pInfo->value_type != KVP_TYPE_DOUBLE || pValue == NULL ) return;
+    if ( pInfo->value_type != KvpValue::Type::DOUBLE || pValue == NULL ) return;
     value = new KvpValue{*(static_cast<double*>(pValue))};
     set_slot_from_value( pInfo, value );
 }
@@ -443,7 +443,7 @@ get_timespec_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, gnc_dmy2timespec( 1, 1, 1970 ) );
 
-//if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_TIMESPEC ) {
+//if( kvp_value_get_type( pInfo->pKvpValue ) == KvpValue::Type::TIMESPEC ) {
     return pInfo->pKvpValue->get<Timespec>();
 }
 
@@ -455,7 +455,7 @@ set_timespec_val( gpointer pObject, Timespec ts )
 
     g_return_if_fail( pObject != NULL );
 
-    if ( pInfo->value_type != KVP_TYPE_TIMESPEC ) return;
+    if ( pInfo->value_type != KvpValue::Type::TIMESPEC ) return;
     value = new KvpValue{ts};
     set_slot_from_value( pInfo, value );
 }
@@ -467,7 +467,7 @@ get_guid_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if (pInfo->pKvpValue->get_type() == KVP_TYPE_GUID)
+    if (pInfo->pKvpValue->get_type() == KvpValue::Type::GUID)
     {
         return (gpointer)pInfo->pKvpValue->get<GncGUID*>();
     }
@@ -487,13 +487,13 @@ set_guid_val( gpointer pObject, /*@ null @*/ gpointer pValue )
 
     switch ( pInfo->value_type)
     {
-    case KVP_TYPE_GUID:
+    case KvpValue::Type::GUID:
     {
         auto new_guid = guid_copy(static_cast<GncGUID*>(pValue));
         set_slot_from_value(pInfo, new KvpValue{new_guid});
         break;
     }
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
     {
         slot_info_t *newInfo = slot_info_copy( pInfo, (GncGUID*)pValue );
         KvpValue *pValue = NULL;
@@ -509,7 +509,7 @@ set_guid_val( gpointer pObject, /*@ null @*/ gpointer pValue )
         g_free( key );
         break;
     }
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
     {
         slot_info_t *newInfo = slot_info_copy( pInfo, (GncGUID*)pValue ) ;
         auto newFrame = new KvpFrame;
@@ -554,7 +554,7 @@ get_numeric_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, gnc_numeric_zero() );
 
-    if (pInfo->pKvpValue->get_type() == KVP_TYPE_NUMERIC)
+    if (pInfo->pKvpValue->get_type() == KvpValue::Type::NUMERIC)
     {
         return pInfo->pKvpValue->get<gnc_numeric>();
     }
@@ -572,7 +572,7 @@ set_numeric_val( gpointer pObject, gnc_numeric value )
 
     g_return_if_fail( pObject != NULL );
 
-    if ( pInfo->value_type != KVP_TYPE_NUMERIC ) return;
+    if ( pInfo->value_type != KvpValue::Type::NUMERIC ) return;
     set_slot_from_value(pInfo, new KvpValue{value});
 }
 
@@ -584,7 +584,7 @@ get_gdate_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if (pInfo->pKvpValue->get_type() == KVP_TYPE_GDATE)
+    if (pInfo->pKvpValue->get_type() == KvpValue::Type::GDATE)
     {
         date = pInfo->pKvpValue->get<GDate>();
         return &date;
@@ -603,7 +603,7 @@ set_gdate_val( gpointer pObject, GDate* value )
 
     g_return_if_fail( pObject != NULL );
 
-    if ( pInfo->value_type != KVP_TYPE_GDATE ) return;
+    if ( pInfo->value_type != KvpValue::Type::GDATE ) return;
     set_slot_from_value(pInfo, new KvpValue{*value});
 }
 
@@ -653,7 +653,7 @@ save_slot( const gchar* key, KvpValue* value, gpointer data )
 
     switch ( pSlot_info->value_type )
     {
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
     {
         auto pKvpFrame = value->get<KvpFrame*>();
         auto guid = guid_new();
@@ -672,7 +672,7 @@ save_slot( const gchar* key, KvpValue* value, gpointer data )
         g_slice_free( slot_info_t, pNewInfo );
     }
     break;
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
     {
         GncGUID guid = guid_new_return();
         slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid );
@@ -711,7 +711,7 @@ gboolean
 gnc_sql_slots_save( GncSqlBackend* be, const GncGUID* guid, gboolean is_infant,
                     QofInstance *inst)
 {
-     slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
+     slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KvpValue::Type::INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
      KvpFrame *pFrame = qof_instance_get_slots (inst);
 
     g_return_val_if_fail( be != NULL, FALSE );
@@ -739,7 +739,7 @@ gnc_sql_slots_delete( GncSqlBackend* be, const GncGUID* guid )
     GncSqlResult* result;
     gchar guid_buf[GUID_ENCODING_LENGTH + 1];
     GncSqlStatement* stmt;
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
+    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KvpValue::Type::INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
 
     g_return_val_if_fail( be != NULL, FALSE );
     g_return_val_if_fail( guid != NULL, FALSE );
@@ -747,7 +747,7 @@ gnc_sql_slots_delete( GncSqlBackend* be, const GncGUID* guid )
     (void)guid_to_string_buff( guid, guid_buf );
 
     buf = g_strdup_printf( "SELECT * FROM %s WHERE obj_guid='%s' and slot_type in ('%d', '%d') and not guid_val is null",
-                           TABLE_NAME, guid_buf, KVP_TYPE_FRAME, KVP_TYPE_GLIST );
+                           TABLE_NAME, guid_buf, KvpValue::Type::FRAME, KvpValue::Type::GLIST );
     stmt = gnc_sql_create_statement_from_sql( be, buf );
     g_free( buf );
     if ( stmt != NULL )
@@ -821,7 +821,7 @@ load_slot( slot_info_t *pInfo, GncSqlRow* row )
 void
 gnc_sql_slots_load( GncSqlBackend* be, QofInstance* inst )
 {
-    slot_info_t info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
+    slot_info_t info = { NULL, NULL, TRUE, NULL, KvpValue::Type::INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
     g_return_if_fail( be != NULL );
     g_return_if_fail( inst != NULL );
 
@@ -886,7 +886,7 @@ load_obj_guid( const GncSqlBackend* be, GncSqlRow* row )
 static void
 load_slot_for_list_item( GncSqlBackend* be, GncSqlRow* row, QofCollection* coll )
 {
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, NULL };
+    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KvpValue::Type::INVALID, NULL, FRAME, NULL, NULL };
     const GncGUID* guid;
     QofInstance* inst;
 
@@ -972,7 +972,7 @@ gnc_sql_slots_load_for_list( GncSqlBackend* be, GList* list )
 static void
 load_slot_for_book_object( GncSqlBackend* be, GncSqlRow* row, BookLookupFn lookup_fn )
 {
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, NULL };
+    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KvpValue::Type::INVALID, NULL, FRAME, NULL, NULL };
     const GncGUID* guid;
     QofInstance* inst;
 
diff --git a/src/backend/xml/sixtp-dom-generators.cpp b/src/backend/xml/sixtp-dom-generators.cpp
index 11ef34a..b0086c1 100644
--- a/src/backend/xml/sixtp-dom-generators.cpp
+++ b/src/backend/xml/sixtp-dom-generators.cpp
@@ -260,7 +260,7 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
 
     switch (val->get_type())
     {
-    case KVP_TYPE_STRING:
+    case KvpValue::Type::STRING:
     {
 	auto newstr = g_strdup(val->get<const char*>());
         val_node = xmlNewTextChild(node, NULL, BAD_CAST tag,
@@ -268,10 +268,10 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
 	g_free (newstr);
         break;
     }
-    case KVP_TYPE_TIMESPEC:
+    case KvpValue::Type::TIMESPEC:
         val_node = NULL;
         break;
-    case KVP_TYPE_GDATE:
+    case KvpValue::Type::GDATE:
     {
         auto d = val->get<GDate>();
         val_node = gdate_to_dom_tree(tag, &d);
@@ -285,30 +285,30 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
 
     switch (val->get_type())
     {
-    case KVP_TYPE_GINT64:
+    case KvpValue::Type::INT64:
         add_text_to_node(val_node, "integer",
                          g_strdup_printf("%" G_GINT64_FORMAT,
                                          val->get<int64_t>()));
         break;
-    case KVP_TYPE_DOUBLE:
+    case KvpValue::Type::DOUBLE:
         add_text_to_node(val_node, "double",
                          double_to_string(val->get<double>()));
         break;
-    case KVP_TYPE_NUMERIC:
+    case KvpValue::Type::NUMERIC:
         add_text_to_node(val_node, "numeric",
                          gnc_numeric_to_string(val->get<gnc_numeric>()));
         break;
-    case KVP_TYPE_STRING:
+    case KvpValue::Type::STRING:
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string");
         break;
-    case KVP_TYPE_GUID:
+    case KvpValue::Type::GUID:
     {
         gchar guidstr[GUID_ENCODING_LENGTH+1];
         guid_to_string_buff(val->get<GncGUID*>(), guidstr);
         add_text_to_node(val_node, "guid", guidstr);
         break;
     }
-    case KVP_TYPE_TIMESPEC:
+    case KvpValue::Type::TIMESPEC:
     {
         auto ts = val->get<Timespec>();
         val_node = timespec_to_dom_tree (tag, &ts);
@@ -316,10 +316,10 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
         xmlAddChild (node, val_node);
         break;
     }
-    case KVP_TYPE_GDATE:
+    case KvpValue::Type::GDATE:
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "gdate");
         break;
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "list");
         for (auto cursor = val->get<GList*>(); cursor; cursor = cursor->next)
         {
@@ -327,7 +327,7 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
             add_kvp_value_node(val_node, "slot:value", val);
         }
         break;
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
     {
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "frame");
 
diff --git a/src/backend/xml/test/test-kvp-frames.cpp b/src/backend/xml/test/test-kvp-frames.cpp
index 7c13ca8..5fd4c8f 100644
--- a/src/backend/xml/test/test-kvp-frames.cpp
+++ b/src/backend/xml/test/test-kvp-frames.cpp
@@ -110,7 +110,7 @@ test_kvp_frames1(void)
 
     for (i = 0; i < 20; i++)
     {
-        auto test_val1 = get_random_kvp_value(i % KVP_TYPE_FRAME);
+        auto test_val1 = get_random_kvp_value(i % KvpValue::Type::FRAME);
         auto test_frame1 = new KvpFrame;
         auto test_key = get_random_string_without("/");
 
diff --git a/src/engine/kvp-scm.cpp b/src/engine/kvp-scm.cpp
index 49e1174..ca92cdc 100644
--- a/src/engine/kvp-scm.cpp
+++ b/src/engine/kvp-scm.cpp
@@ -72,45 +72,47 @@ gnc_scm_to_kvp_value_ptr(SCM val)
 SCM
 gnc_kvp_value_ptr_to_scm(KvpValue* val)
 {
-    switch (kvp_value_get_type(val))
+    if (val == nullptr) return SCM_BOOL_F;
+    
+    switch (val->get_type())
     {
-    case KVP_TYPE_GINT64:
+    case KvpValue::Type::INT64:
         return scm_from_int64(val->get<int64_t>());
         break;
-    case KVP_TYPE_DOUBLE:
+    case KvpValue::Type::DOUBLE:
         return scm_from_double (val->get<double>());
         break;
-    case KVP_TYPE_NUMERIC:
+    case KvpValue::Type::NUMERIC:
         return gnc_numeric_to_scm(val->get<gnc_numeric>());
         break;
-    case KVP_TYPE_STRING:
+    case KvpValue::Type::STRING:
     {
         auto string = val->get<const char*>();
         return string ? scm_from_utf8_string(string) : SCM_BOOL_F;
         break;
     }
-    case KVP_TYPE_GUID:
+    case KvpValue::Type::GUID:
     {
-        auto tempguid = kvp_value_get_guid(val);
+        auto tempguid = val->get<GncGUID*>();
         return gnc_guid2scm(*tempguid);
     }
     break;
-    case KVP_TYPE_TIMESPEC:
+    case KvpValue::Type::TIMESPEC:
         return gnc_timespec2timepair(val->get<Timespec>());
         break;
 
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
     {
         auto frame = val->get<KvpFrame*>();
         if (frame != nullptr)
             return SWIG_NewPointerObj(frame, SWIG_TypeQuery("_p_KvpFrame"), 0);
     }
     break;
-    case KVP_TYPE_GDATE:
+    case KvpValue::Type::GDATE:
         return gnc_timespec2timepair(gdate_to_timespec(val->get<GDate>()));
 
         /* FIXME: handle types below */
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
     default:
 	break;
     }
diff --git a/src/engine/test-core/test-engine-stuff.cpp b/src/engine/test-core/test-engine-stuff.cpp
index 6955f7b..3cae5df 100644
--- a/src/engine/test-core/test-engine-stuff.cpp
+++ b/src/engine/test-core/test-engine-stuff.cpp
@@ -105,8 +105,8 @@ set_max_kvp_frame_elements (gint max_kvp_frame_elements)
     kvp_frame_max_elements = MAX (max_kvp_frame_elements, 1);
 }
 
-void
-kvp_exclude_type (KvpValueType kvp_type)
+static void
+kvp_exclude_type (KvpValue::Type kvp_type)
 {
     gint *key;
 
@@ -120,7 +120,7 @@ kvp_exclude_type (KvpValueType kvp_type)
 }
 
 static gboolean
-kvp_type_excluded (KvpValueType kvp_type)
+kvp_type_excluded (KvpValue::Type kvp_type)
 {
     gint key = kvp_type;
 
@@ -238,25 +238,25 @@ static KvpFrame* get_random_kvp_frame_depth (gint depth);
 static KvpValue*
 get_random_kvp_value_depth (int type, gint depth)
 {
-    KvpValueType datype;
+    KvpValue::Type datype;
     KvpValue *ret;
 
     if (type == -1)
     {
-        datype = static_cast<KvpValueType>(get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME));
+        datype = static_cast<KvpValue::Type>(get_random_int_in_range(KvpValue::Type::INT64, KvpValue::Type::FRAME));
     }
 
     else if (type == -2)
     {
-        datype = static_cast<KvpValueType>(get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1));
+        datype = static_cast<KvpValue::Type>(get_random_int_in_range(KvpValue::Type::INT64, KvpValue::Type::FRAME - 1));
     }
     else
-        datype = static_cast<KvpValueType>(type);
-    
-    if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
+        datype = static_cast<KvpValue::Type>(type);
+
+    if (datype == KvpValue::Type::FRAME && depth >= kvp_max_depth)
         return NULL;
 
-    if (datype == KVP_TYPE_GLIST && depth >= kvp_max_depth)
+    if (datype == KvpValue::Type::GLIST && depth >= kvp_max_depth)
         return NULL;
 
     if (kvp_type_excluded (datype))
@@ -264,57 +264,50 @@ get_random_kvp_value_depth (int type, gint depth)
 
     switch (datype)
     {
-    case KVP_TYPE_GINT64:
-        ret = kvp_value_new_gint64(get_random_gint64());
+    case KvpValue::Type::INT64:
+        ret = new KvpValue(get_random_gint64());
         break;
 
-    case KVP_TYPE_DOUBLE:
+    case KvpValue::Type::DOUBLE:
         ret = NULL;
         break;
 
-    case KVP_TYPE_NUMERIC:
-        ret = kvp_value_new_gnc_numeric(get_random_gnc_numeric(GNC_DENOM_AUTO));
+    case KvpValue::Type::NUMERIC:
+        ret = new KvpValue(get_random_gnc_numeric(GNC_DENOM_AUTO));
         break;
 
-    case KVP_TYPE_STRING:
+    case KvpValue::Type::STRING:
     {
         gchar *tmp_str;
         tmp_str = get_random_string();
         if (!tmp_str)
             return NULL;
 
-        ret = kvp_value_new_string(tmp_str);
-        g_free(tmp_str);
+        ret = new KvpValue(tmp_str);
     }
     break;
 
-    case KVP_TYPE_GUID:
+    case KvpValue::Type::GUID:
     {
-        GncGUID *tmp_guid;
-        tmp_guid = get_random_guid();
-        ret = kvp_value_new_guid(tmp_guid);
-        g_free(tmp_guid);
+        return new KvpValue(get_random_guid());
     }
     break;
 
-    case KVP_TYPE_TIMESPEC:
+    case KvpValue::Type::TIMESPEC:
     {
         Timespec *ts = get_random_timespec();
-        ret = kvp_value_new_timespec (*ts);
+        ret = new KvpValue(*ts);
         g_free(ts);
     }
     break;
 
-    case KVP_TYPE_GLIST:
-        ret = kvp_value_new_glist_nc(get_random_glist_depth (depth + 1));
+    case KvpValue::Type::GLIST:
+        ret = new KvpValue(get_random_glist_depth (depth + 1));
         break;
 
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
     {
-        KvpFrame *tmp_frame;
-        tmp_frame = get_random_kvp_frame_depth(depth + 1);
-        ret = kvp_value_new_frame(tmp_frame);
-        kvp_frame_delete(tmp_frame);
+        return new KvpValue(get_random_kvp_frame_depth(depth + 1));
     }
     break;
 
@@ -328,14 +321,13 @@ get_random_kvp_value_depth (int type, gint depth)
 static KvpFrame*
 get_random_kvp_frame_depth (gint depth)
 {
-    KvpFrame *ret;
     int vals_to_add;
     gboolean val_added;
 
     if (depth >= kvp_max_depth)
         return NULL;
 
-    ret = kvp_frame_new();
+    auto ret = new KvpFrame;
 
     vals_to_add = get_random_int_in_range(1, kvp_frame_max_elements);
     val_added = FALSE;
@@ -367,7 +359,7 @@ get_random_kvp_frame_depth (gint depth)
 
         val_added = TRUE;
 
-        kvp_frame_set_slot_nc(ret, key, val);
+        ret->set_path(key, val);
 
         g_free(key);
     }
diff --git a/src/engine/test-core/test-engine-stuff.h b/src/engine/test-core/test-engine-stuff.h
index 73360b4..f5ab980 100644
--- a/src/engine/test-core/test-engine-stuff.h
+++ b/src/engine/test-core/test-engine-stuff.h
@@ -13,11 +13,12 @@ extern "C"
 #include <stdint.h>
 
 #include "qof.h"
-#include <kvp_frame.h>
 #include "Query.h"
 #include "gnc-pricedb.h"
 #include "SchedXaction.h"
 
+typedef struct KvpValueImpl KvpValue;
+typedef struct KvpFrameImpl KvpFrame;
 Timespec* get_random_timespec(void);
 void random_timespec_zero_nsec (gboolean zero_nsec);
 void random_timespec_usec_resolution (gboolean usec_resolution);
@@ -36,7 +37,7 @@ KvpFrame* get_random_kvp_frame(void);
 gnc_numeric get_random_gnc_numeric(int64_t);
 GncGUID* get_random_guid(void);
 
-void kvp_exclude_type (KvpValueType kvp_type);
+//void kvp_exclude_type (KvpValueType kvp_type);
 void set_max_kvp_depth (gint max_kvp_depth);
 void set_max_kvp_frame_elements (gint max_kvp_frame_elements);
 void set_max_account_tree_depth (gint max_tree_depth);
diff --git a/src/engine/test/Makefile.am b/src/engine/test/Makefile.am
index 7366d75..545a5ef 100644
--- a/src/engine/test/Makefile.am
+++ b/src/engine/test/Makefile.am
@@ -23,6 +23,8 @@ LDADD = \
   ${top_builddir}/src/core-utils/libgnc-core-utils.la \
   ${GLIB_LIBS}
 
+test_guid_SOURCES = test-guid.cpp
+
 # these tests are ordered kind more or less in the order
 # that they should be executed, with more basic tests coming first.
 #
@@ -73,6 +75,7 @@ TESTS_ENVIRONMENT = \
   $(shell ${abs_top_srcdir}/src/gnc-test-env.pl --noexports ${GNC_TEST_DEPS})
 
 check_PROGRAMS = ${TEST_GROUP_1} ${TEST_GROUP_2}
+AM_DEFAULT_SOURCE_EXT = .cpp
 
 TESTS = ${TEST_GROUP_1} test-create-account ${TEST_GROUP_2}
 
diff --git a/src/engine/test/test-guid.c b/src/engine/test/test-guid.cpp
similarity index 91%
rename from src/engine/test/test-guid.c
rename to src/engine/test/test-guid.cpp
index fdb2408..923e59d 100644
--- a/src/engine/test/test-guid.c
+++ b/src/engine/test/test-guid.cpp
@@ -25,7 +25,8 @@
  * Try to create duplicate GncGUID's, which should never happen.
  *
  */
-
+extern "C"
+{
 #include "config.h"
 #include <ctype.h>
 #include <glib.h>
@@ -33,7 +34,7 @@
 #include "test-stuff.h"
 #include "test-engine-stuff.h"
 #include "qof.h"
-
+}
 #define NENT 50123
 
 static void test_null_guid(void)
@@ -70,9 +71,10 @@ run_test (void)
 
     for (i = 0; i < NENT; i++)
     {
-        ent = g_object_new(QOF_TYPE_INSTANCE, NULL);
+        ent = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE, NULL));
         guid_replace(&guid);
-        ent = g_object_new(QOF_TYPE_INSTANCE, "guid", &guid, NULL);
+        ent = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE,
+                                                     "guid", &guid, NULL));
         do_test ((NULL == qof_collection_lookup_entity (col, &guid)),
                  "duplicate guid");
         ent->e_type = type;
diff --git a/src/libqof/qof/gnc-aqbanking-templates.cpp b/src/libqof/qof/gnc-aqbanking-templates.cpp
index 21bd057..6c5c526 100644
--- a/src/libqof/qof/gnc-aqbanking-templates.cpp
+++ b/src/libqof/qof/gnc-aqbanking-templates.cpp
@@ -105,7 +105,7 @@ private:
 KvpFrame*
 _GncABTransTempl::make_kvp_frame()
 {
-    auto frame = kvp_frame_new();
+    auto frame = new KvpFrame;
     frame->set(TT_NAME, new KvpValue(m_name.c_str()));
     frame->set(TT_RNAME, new KvpValue(m_recipient_name.c_str()));
     frame->set(TT_RACC, new KvpValue(m_recipient_account.c_str()));
diff --git a/src/libqof/qof/kvp-value.cpp b/src/libqof/qof/kvp-value.cpp
index ce79dfc..bd07419 100644
--- a/src/libqof/qof/kvp-value.cpp
+++ b/src/libqof/qof/kvp-value.cpp
@@ -71,29 +71,29 @@ KvpValueImpl::add(KvpValueImpl * val) noexcept
     return new KvpValueImpl(list);
 }
 
-KvpValueType
+KvpValue::Type
 KvpValueImpl::get_type() const noexcept
 {
     if (datastore.type() == typeid(int64_t))
-        return KvpValueType::KVP_TYPE_GINT64;
+        return KvpValue::Type::INT64;
     else if (datastore.type() == typeid(double))
-        return KvpValueType::KVP_TYPE_DOUBLE;
+        return KvpValue::Type::DOUBLE;
     else if (datastore.type() == typeid(gnc_numeric))
-        return KvpValueType::KVP_TYPE_NUMERIC;
+        return KvpValue::Type::NUMERIC;
     else if (datastore.type() == typeid(const gchar *))
-        return KvpValueType::KVP_TYPE_STRING;
+        return KvpValue::Type::STRING;
     else if (datastore.type() == typeid(GncGUID *))
-        return KvpValueType::KVP_TYPE_GUID;
+        return KvpValue::Type::GUID;
     else if (datastore.type() == typeid(Timespec))
-        return KvpValueType::KVP_TYPE_TIMESPEC;
+        return KvpValue::Type::TIMESPEC;
     else if (datastore.type() == typeid(GList *))
-        return KvpValueType::KVP_TYPE_GLIST;
+        return KvpValue::Type::GLIST;
     else if (datastore.type() == typeid(KvpFrameImpl *))
-        return KvpValueType::KVP_TYPE_FRAME;
+        return KvpValue::Type::FRAME;
     else if (datastore.type() == typeid(GDate))
-        return KvpValueType::KVP_TYPE_GDATE;
+        return KvpValue::Type::GDATE;
 
-    return KVP_TYPE_INVALID;
+    return KvpValue::Type::INVALID;
 }
 
 KvpFrame *
@@ -129,14 +129,7 @@ struct to_string_visitor : boost::static_visitor<void>
 
     void operator()(KvpFrame * val)
     {
-        auto tmp1 = kvp_frame_to_string(val);
-        output << "KVP_VALUE_FRAME(";
-        if (tmp1)
-        {
-            output << tmp1;
-            g_free(tmp1);
-        }
-        output << ")";
+        output << "KVP_VALUE_FRAME(" << val->to_string() << ")";
     }
 
     void operator()(GDate val)
@@ -224,6 +217,55 @@ KvpValueImpl::to_string() const noexcept
     return g_strdup(ret.str().c_str());
 }
 
+static int
+kvp_glist_compare(const GList * list1, const GList * list2)
+{
+    const GList *lp1;
+    const GList *lp2;
+
+    if (list1 == list2) return 0;
+
+    /* Nothing is always less than something */
+    if (!list1 && list2) return -1;
+    if (list1 && !list2) return 1;
+
+    lp1 = list1;
+    lp2 = list2;
+    while (lp1 && lp2)
+    {
+        KvpValue *v1 = (KvpValue *) lp1->data;
+        KvpValue *v2 = (KvpValue *) lp2->data;
+        gint vcmp = compare(v1, v2);
+        if (vcmp != 0) return vcmp;
+        lp1 = lp1->next;
+        lp2 = lp2->next;
+    }
+    if (!lp1 && lp2) return -1;
+    if (!lp2 && lp1) return 1;
+    return 0;
+}
+
+static GList *
+kvp_glist_copy(const GList * list)
+{
+    GList * retval = NULL;
+    GList * lptr;
+
+    if (!list) return retval;
+
+    /* Duplicate the backbone of the list (this duplicates the POINTERS
+     * to the values; we need to deep-copy the values separately) */
+    retval = g_list_copy((GList *) list);
+
+    /* This step deep-copies the values */
+    for (lptr = retval; lptr; lptr = lptr->next)
+    {
+        lptr->data = new KvpValue(*static_cast<KvpValue *>(lptr->data));
+    }
+
+    return retval;
+}
+
 struct compare_visitor : boost::static_visitor<int>
 {
     template <typename T, typename U>
@@ -269,7 +311,7 @@ template <> int compare_visitor::operator()(GList * const & one, GList * const &
 }
 template <> int compare_visitor::operator()(KvpFrame * const & one, KvpFrame * const & two) const
 {
-    return kvp_frame_compare(one, two);
+    return compare(one, two);
 }
 template <> int compare_visitor::operator()(double const & one, double const & two) const
 {
@@ -307,10 +349,16 @@ struct delete_visitor : boost::static_visitor<void>
     operator()(T &) { /*do nothing*/ }
 };
 
+static void
+destroy_value(void* item)
+{
+    delete static_cast<KvpValue*>(item);
+}
+
 template <> void
 delete_visitor::operator()(GList * & value)
 {
-    kvp_glist_delete(value);
+    g_list_free_full(value, destroy_value);
 }
 template <> void
 delete_visitor::operator()(gchar * & value)
@@ -344,7 +392,8 @@ KvpValueImpl::duplicate(const KvpValueImpl& other) noexcept
     else if (other.datastore.type() == typeid(GList*))
         this->datastore = kvp_glist_copy(other.get<GList *>());
     else if (other.datastore.type() == typeid(KvpFrame*))
-        this->datastore = kvp_frame_copy(other.get<KvpFrame *>());
+        this->datastore = new KvpFrame(*other.get<KvpFrame *>());
     else
         this->datastore = other.datastore;
 }
+
diff --git a/src/libqof/qof/kvp-value.hpp b/src/libqof/qof/kvp-value.hpp
index c7a96e1..3b53167 100644
--- a/src/libqof/qof/kvp-value.hpp
+++ b/src/libqof/qof/kvp-value.hpp
@@ -34,11 +34,27 @@ extern "C"
 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
 #endif
 #include <boost/variant.hpp>
-#include "kvp_frame.h"
 
+//Must be a struct because it's exposed to C so that it can in turn be
+//translated to/from Scheme.
 struct KvpValueImpl
 {
     public:
+    enum Type
+    {
+        INVALID = -1,
+        INT64 = 1, /**< QOF_TYPE_INT64  gint64 */
+        DOUBLE,     /**< QOF_TYPE_DOUBLE  gdouble */
+        NUMERIC,    /**< QOF_TYPE_NUMERIC */
+        STRING,     /**< QOF_TYPE_STRING gchar* */
+        GUID,       /**< QOF_TYPE_GUID */
+        TIMESPEC,   /**< QOF_TYPE_DATE */
+        PLACEHOLDER_DONT_USE, /* Replaces KVP_TYPE_BINARY */
+        GLIST,      /**< no QOF equivalent. */
+        FRAME,      /**< no QOF equivalent. */
+        GDATE,      /**< no QOF equivalent. */
+    };
+
     /**
      * Performs a deep copy
      */
@@ -90,7 +106,7 @@ struct KvpValueImpl
      */
     KvpValueImpl * add (KvpValueImpl *) noexcept;
 
-    KvpValueType get_type() const noexcept;
+    KvpValueImpl::Type get_type() const noexcept;
 
     char * to_string() const noexcept;
 
@@ -137,5 +153,7 @@ KvpValueImpl::set(T val) noexcept
 {
     this->datastore = val;
 }
+extern "C" GType gnc_value_list_get_type (void);
+#define GNC_TYPE_VALUE_LIST (gnc_value_list_get_type ())
 
 #endif
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index 475ae5a..8a8cdaf 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -30,6 +30,7 @@ extern "C"
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include "kvp_frame.h"
 }
 
 #include "kvp-value.hpp"
@@ -39,6 +40,9 @@ extern "C"
 #include <algorithm>
 #include <vector>
 
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = "qof.kvp";
+
 static const char delim = '/';
 
 KvpFrameImpl::KvpFrameImpl(const KvpFrameImpl & rhs) noexcept
@@ -99,7 +103,7 @@ walk_path_or_nullptr(const KvpFrameImpl* frame, Path& path)
     for(auto key:path)
     {
         auto slot = cur_frame->get_slot(key.c_str());
-        if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
+        if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
             return nullptr;
         cur_frame = slot->get<KvpFrame*>();
     }
@@ -130,7 +134,7 @@ walk_path_and_create(KvpFrameImpl* frame, Path path)
             continue;
         }
         auto slot = frame->get_slot(key.c_str());
-        if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
+        if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
         {
             auto new_frame = new KvpFrame;
             delete frame->set(key.c_str(), new KvpValue{new_frame});
@@ -271,9 +275,6 @@ int compare(const KvpFrameImpl & one, const KvpFrameImpl & two) noexcept
     return 0;
 }
 
-/* This static indicates the debugging module that this .o belongs to.  */
-static QofLogModule log_module = QOF_MOD_KVP;
-
 KvpFrame *
 kvp_frame_new(void)
 {
@@ -940,78 +941,9 @@ kvp_frame_get_slot_path_gslist (KvpFrame *frame,
     return NULL;
 }
 
-/* *******************************************************************
- * kvp glist functions
- ********************************************************************/
-
-void
-kvp_glist_delete(GList * list)
-{
-    GList *node;
-    if (!list) return;
-
-    /* Delete the data in the list */
-    for (node = list; node; node = node->next)
-    {
-        KvpValue *val = static_cast<KvpValue*>(node->data);
-        kvp_value_delete(val);
-    }
-
-    /* Free the backbone */
-    g_list_free(list);
-}
-
-GList *
-kvp_glist_copy(const GList * list)
-{
-    GList * retval = NULL;
-    GList * lptr;
-
-    if (!list) return retval;
-
-    /* Duplicate the backbone of the list (this duplicates the POINTERS
-     * to the values; we need to deep-copy the values separately) */
-    retval = g_list_copy((GList *) list);
-
-    /* This step deep-copies the values */
-    for (lptr = retval; lptr; lptr = lptr->next)
-    {
-        lptr->data = kvp_value_copy(static_cast<KvpValue *>(lptr->data));
-    }
-
-    return retval;
-}
-
-gint
-kvp_glist_compare(const GList * list1, const GList * list2)
-{
-    const GList *lp1;
-    const GList *lp2;
-
-    if (list1 == list2) return 0;
-
-    /* Nothing is always less than something */
-    if (!list1 && list2) return -1;
-    if (list1 && !list2) return 1;
-
-    lp1 = list1;
-    lp2 = list2;
-    while (lp1 && lp2)
-    {
-        KvpValue *v1 = (KvpValue *) lp1->data;
-        KvpValue *v2 = (KvpValue *) lp2->data;
-        gint vcmp = kvp_value_compare(v1, v2);
-        if (vcmp != 0) return vcmp;
-        lp1 = lp1->next;
-        lp2 = lp2->next;
-    }
-    if (!lp1 && lp2) return -1;
-    if (!lp2 && lp1) return 1;
-    return 0;
-}
 
 /* *******************************************************************
- * KvpValue functions
+ * Kvpvalue functions
  ********************************************************************/
 
 KvpValue *
@@ -1069,7 +1001,7 @@ KvpValue *
 kvp_value_new_glist(const GList * value)
 {
     if (!value) return {};
-    return new KvpValueImpl{kvp_glist_copy(value)};
+    return nullptr;
 }
 
 KvpValue *
@@ -1101,14 +1033,6 @@ kvp_value_delete(KvpValue * value)
     delete realvalue;
 }
 
-KvpValueType
-kvp_value_get_type(const KvpValue * oldval)
-{
-    if (!oldval) return KVP_TYPE_INVALID;
-    const KvpValueImpl * value {static_cast<const KvpValueImpl *>(oldval)};
-    return value->get_type();
-}
-
 int64_t
 kvp_value_get_gint64(const KvpValue * ovalue)
 {
@@ -1318,44 +1242,40 @@ gvalue_from_kvp_value (const KvpValue *kval)
     if (kval == NULL) return NULL;
     val = g_slice_new0 (GValue);
 
-    switch (kvp_value_get_type(kval))
+    switch (kval->get_type())
     {
-        case KVP_TYPE_GINT64:
+        case KvpValue::Type::INT64:
             g_value_init (val, G_TYPE_INT64);
             g_value_set_int64 (val, kvp_value_get_gint64 (kval));
             break;
-        case KVP_TYPE_DOUBLE:
+        case KvpValue::Type::DOUBLE:
             g_value_init (val, G_TYPE_DOUBLE);
             g_value_set_double (val, kvp_value_get_double (kval));
             break;
-        case KVP_TYPE_BOOLEAN:
-            g_value_init (val, G_TYPE_BOOLEAN);
-            g_value_set_boolean (val, kvp_value_get_boolean (kval));
-            break;
-        case KVP_TYPE_NUMERIC:
+        case KvpValue::Type::NUMERIC:
             g_value_init (val, GNC_TYPE_NUMERIC);
             num = kvp_value_get_numeric (kval);
             g_value_set_boxed (val, &num);
             break;
-        case KVP_TYPE_STRING:
+        case KvpValue::Type::STRING:
             g_value_init (val, G_TYPE_STRING);
             g_value_set_string (val, kvp_value_get_string (kval));
             break;
-        case KVP_TYPE_GUID:
+        case KvpValue::Type::GUID:
             g_value_init (val, GNC_TYPE_GUID);
             g_value_set_boxed (val, kvp_value_get_guid (kval));
             break;
-        case KVP_TYPE_TIMESPEC:
+        case KvpValue::Type::TIMESPEC:
             g_value_init (val, GNC_TYPE_TIMESPEC);
             tm = kvp_value_get_timespec (kval);
             g_value_set_boxed (val, &tm);
             break;
-        case KVP_TYPE_GDATE:
+        case KvpValue::Type::GDATE:
             g_value_init (val, G_TYPE_DATE);
             gdate = kvp_value_get_gdate (kval);
             g_value_set_boxed (val, &gdate);
             break;
-        case KVP_TYPE_GLIST:
+        case KvpValue::Type::GLIST:
         {
             GList *gvalue_list = NULL;
             GList *kvp_list = kvp_value_get_glist (kval);
@@ -1366,7 +1286,7 @@ gvalue_from_kvp_value (const KvpValue *kval)
             break;
         }
 /* No transfer of KVP frames outside of QofInstance-derived classes! */
-        case KVP_TYPE_FRAME:
+        case KvpValue::Type::FRAME:
             PWARN ("Error! Attempt to transfer KvpFrame!");
         default:
             PWARN ("Error! Invalid KVP Transfer Request!");
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index 190aa94..3b02e67 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -22,7 +22,7 @@
 
  * A KvpFrame is a set of associations between character strings
  * (keys) and KvpValue structures.  A KvpValue is a union with
- * possible types enumerated in the KvpValueType enum, and includes,
+ * possible types enumerated in the KvpValue::Type enum, and includes,
  * among other things, ints, doubles, strings, guid's, lists, time
  * and numeric values.  KvpValues may also be other frames, so
  * KVP is inherently hierarchical.
@@ -75,44 +75,8 @@ extern "C"
 /** Opaque frame structure */
 typedef struct KvpFrameImpl KvpFrame;
 
-/** A KvpValue is a union with possible types enumerated in the
- * KvpValueType enum. */
 typedef struct KvpValueImpl KvpValue;
 
-/** \brief possible types in the union KvpValue
- * \todo : People have asked for boolean values,
- *  e.g. in xaccAccountSetAutoInterestXfer
- *
- * \todo In the long run, this should be synchronized with the
- * core QOF types, which in turn should be synced to the g_types
- * in GLib.  Unfortunately, this requires writing a pile of code
- * to handle all of the different cases.
- * An alternative might be to make kvp values inherit from the
- * core g_types (i.e. add new core g_types) ??
- */
-typedef enum
-{
-    KVP_TYPE_INVALID = -1,
-    KVP_TYPE_GINT64 = 1, /**< QOF_TYPE_INT64  gint64 */
-    KVP_TYPE_DOUBLE,     /**< QOF_TYPE_DOUBLE  gdouble */
-    KVP_TYPE_NUMERIC,    /**< QOF_TYPE_NUMERIC */
-    KVP_TYPE_STRING,     /**< QOF_TYPE_STRING gchar* */
-    KVP_TYPE_GUID,       /**< QOF_TYPE_GUID */
-    KVP_TYPE_TIMESPEC,   /**< QOF_TYPE_DATE */
-    KVP_TYPE_PLACEHOLDER_DONT_USE, /* Replaces KVP_TYPE_BINARY */
-    KVP_TYPE_GLIST,      /**< no QOF equivalent. */
-    KVP_TYPE_FRAME,      /**< no QOF equivalent. */
-    KVP_TYPE_GDATE,      /**< no QOF equivalent. */
-    KVP_TYPE_BOOLEAN,    /**< QOF_TYPE_BOOLEAN gboolean */
-} KvpValueType;
-
-/** \deprecated Deprecated backwards compat token
-
-do \b not use these in new code.
- */
-/** \deprecated Deprecated backwards compat token */
-#define kvp_value_t KvpValueType
-
 /** @name KvpFrame Constructors
  @{
 */
@@ -420,31 +384,6 @@ gint          kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb);
 
 gint          double_compare(double v1, double v2);
 /** @} */
-/** @name KvpValue List Convenience Functions
-
-  You probably shouldn't be using these low-level routines
-
- kvp_glist_compare() compares <b>GLists of kvp_values</b> (not to
- be confused with GLists of something else):  it iterates over
- the list elements, performing a kvp_value_compare on each.
- @{
-*/
-gint        kvp_glist_compare(const GList * list1, const GList * list2);
-
-/** kvp_glist_copy() performs a deep copy of a <b>GList of
- *     kvp_values</b> (not to be confused with GLists of something
- *     else): same as mapping kvp_value_copy() over the elements and
- *     then copying the spine.
- */
-GList     * kvp_glist_copy(const GList * list);
-
-/** kvp_glist_delete() performs a deep delete of a <b>GList of
- *     kvp_values</b> (not to be confused with GLists of something
- *     else): same as mapping * kvp_value_delete() over the elements
- *     and then deleting the GList.
- */
-void        kvp_glist_delete(GList * list);
-/** @} */
 
 
 /** @name KvpValue Constructors
@@ -509,9 +448,6 @@ GList * kvp_value_replace_glist_nc(KvpValue *value, GList *newlist);
  @{
 */
 
-KvpValueType kvp_value_get_type(const KvpValue * value);
-
-
 /** Value accessors. Those for GncGUID, GList, KvpFrame and
  *   string are non-copying -- the caller can modify the value
  *   directly. Just don't free it, or you screw up everything.
@@ -642,10 +578,7 @@ void kvp_frame_set_gvalue (KvpFrame *frame, const gchar *key, const GValue *valu
  */
 void gnc_gvalue_free (GValue *value);
 
-GType gnc_value_list_get_type (void);
-#define GNC_TYPE_VALUE_LIST (gnc_value_list_get_type ())
-
-/** @} */
+ /** @} */
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index e04332c..080ab25 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -1134,11 +1134,11 @@ qof_instance_kvp_add_guid (const QofInstance *inst, const char* path,
 inline static gboolean
 kvp_match_guid (KvpValue *v, const char *key, const GncGUID *guid)
 {
-    if (v->get_type() != KVP_TYPE_FRAME)
+    if (v->get_type() != KvpValue::Type::FRAME)
         return FALSE;
     auto frame = v->get<KvpFrame*>();
     auto val = frame->get_slot(key);
-    if (val == nullptr || val->get_type() != KVP_TYPE_GUID)
+    if (val == nullptr || val->get_type() != KvpValue::Type::GUID)
         return FALSE;
     auto this_guid = val->get<GncGUID*>();
 
@@ -1157,10 +1157,10 @@ qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
 
     switch (v->get_type())
     {
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
         return kvp_match_guid (v, key, guid);
         break;
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
     {
         auto list = v->get<GList*>();
         for (auto node = list; node != NULL; node = node->next)
@@ -1192,14 +1192,14 @@ qof_instance_kvp_remove_guid (const QofInstance *inst, const char *path,
 
     switch (v->get_type())
     {
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
         if (kvp_match_guid (v, key, guid))
         {
             delete inst->kvp_data->set_path({path}, nullptr);
             delete v;
         }
         break;
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
     {
         auto list = v->get<GList*>();
         for (auto node = list; node != nullptr; node = node->next)
@@ -1236,14 +1236,14 @@ qof_instance_kvp_merge_guids (const QofInstance *target,
     auto target_val = target->kvp_data->get_slot(path);
     switch (v->get_type())
     {
-    case KVP_TYPE_FRAME:
+    case KvpValue::Type::FRAME:
         if (target_val)
             target_val->add(v);
         else
             target->kvp_data->set_path({path}, v);
         donor->kvp_data->set(path, nullptr); //Contents moved, Don't delete!
         break;
-    case KVP_TYPE_GLIST:
+    case KvpValue::Type::GLIST:
         if (target_val)
         {
             auto list = target_val->get<GList*>();
@@ -1305,7 +1305,7 @@ qof_instance_foreach_slot (const QofInstance *inst, const char* path,
                            void* data)
 {
     auto slot = inst->kvp_data->get_slot(path);
-    if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
+    if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
         return;
     auto frame = slot->get<KvpFrame*>();
     wrap_param new_data {proc, data};
diff --git a/src/libqof/qof/test/test-kvp-frame.cpp b/src/libqof/qof/test/test-kvp-frame.cpp
index 3082474..4f30dd8 100644
--- a/src/libqof/qof/test/test-kvp-frame.cpp
+++ b/src/libqof/qof/test/test-kvp-frame.cpp
@@ -144,7 +144,7 @@ TEST_F (KvpFrameTest, GetKeys)
 
     assert_contains (keys, k1);
     auto frameval = t_root.get_slot(k1);
-    ASSERT_EQ(frameval->get_type(), KVP_TYPE_FRAME);
+    ASSERT_EQ(frameval->get_type(), KvpValue::Type::FRAME);
     keys = frameval->get<KvpFrame*>()->get_keys();
     assert_contains (keys, k2);
     assert_contains (keys, k3);
@@ -158,7 +158,7 @@ TEST_F (KvpFrameTest, GetLocalSlot)
     auto k4 = "top/first";
 
     auto frameval = t_root.get_slot("top");
-    ASSERT_EQ(frameval->get_type(), KVP_TYPE_FRAME);
+    ASSERT_EQ(frameval->get_type(), KvpValue::Type::FRAME);
     auto f1 = frameval->get<KvpFrame*>();
     EXPECT_EQ (t_int_val, f1->get_slot(k1));
     EXPECT_EQ (t_str_val, f1->get_slot(k2));
diff --git a/src/libqof/qof/test/test-kvp-value.cpp b/src/libqof/qof/test/test-kvp-value.cpp
index 537a6a0..ef8bd93 100644
--- a/src/libqof/qof/test/test-kvp-value.cpp
+++ b/src/libqof/qof/test/test-kvp-value.cpp
@@ -65,7 +65,7 @@ TEST (KvpValueTest, Add)
     auto v4 = new KvpValueImpl {*v3};
     auto new_one = v3->add (v4);
     EXPECT_NE (new_one, v3);
-    EXPECT_EQ (new_one->get_type (), KvpValueType::KVP_TYPE_GLIST);
+    EXPECT_EQ (new_one->get_type (), KvpValue::Type::GLIST);
     EXPECT_NE (new_one->get<GList*> (), nullptr);
     /* also deletes v3 and v4 because they're "in" new_one */
     delete new_one;

commit 3590de108504c8c44cca7c0ef9875f8e4801a137
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jun 26 12:24:34 2015 -0700

    Convert tests to C++ and the KVP C++ API.

diff --git a/0001-Change-gtkmacintegration-gtk2-include-directory-back.patch b/0001-Change-gtkmacintegration-gtk2-include-directory-back.patch
new file mode 100644
index 0000000..74774cf
--- /dev/null
+++ b/0001-Change-gtkmacintegration-gtk2-include-directory-back.patch
@@ -0,0 +1,41 @@
+From b9de55c8711b07c0fdf83d9838c8a5d65222e887 Mon Sep 17 00:00:00 2001
+From: John Ralls <jralls at ceridwen.us>
+Date: Sun, 24 May 2015 18:05:04 -0700
+Subject: [PATCH] Change gtkmacintegration-gtk2 include directory back to
+ gtkmacintegration.
+
+As of gtk-mac-integration-2.0.8.
+---
+ src/core-utils/binreloc.c         | 2 +-
+ src/gnome-utils/gnc-main-window.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/core-utils/binreloc.c b/src/core-utils/binreloc.c
+index 6a2a55f..4e72494 100644
+--- a/src/core-utils/binreloc.c
++++ b/src/core-utils/binreloc.c
+@@ -24,7 +24,7 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #ifdef MAC_INTEGRATION
+-#include <gtkmacintegration-gtk2/gtkosxapplication.h>
++#include <gtkmacintegration/gtkosxapplication.h>
+ #endif
+ #endif /* ENABLE_BINRELOC */
+ #include <stdio.h>
+diff --git a/src/gnome-utils/gnc-main-window.c b/src/gnome-utils/gnc-main-window.c
+index 89462ef..c77637d 100644
+--- a/src/gnome-utils/gnc-main-window.c
++++ b/src/gnome-utils/gnc-main-window.c
+@@ -70,7 +70,7 @@
+ #include "gnc-autosave.h"
+ #include "print-session.h"
+ #ifdef MAC_INTEGRATION
+-#include <gtkmacintegration-gtk2/gtkosxapplication.h>
++#include <gtkmacintegration/gtkosxapplication.h>
+ #endif
+ #ifdef HAVE_SYS_STAT_H
+ # include <sys/types.h>
+-- 
+2.2.2
+
diff --git a/src/app-utils/test/Makefile.am b/src/app-utils/test/Makefile.am
index 4000490..c0cf529 100644
--- a/src/app-utils/test/Makefile.am
+++ b/src/app-utils/test/Makefile.am
@@ -67,11 +67,10 @@ AM_CPPFLAGS = \
 
 test_app_utils_SOURCES = \
 	test-app-utils.c \
-	test-option-util.c \
+	test-option-util.cpp \
 	test-gnc-ui-util.c
 
-
-test_app_utils_CFLAGS = \
+test_app_utils_CXXFLAGS = \
 	${DEFAULT_INCLUDES} \
 	-I${top_srcdir}/${MODULEPATH}/ \
 	-DTESTPROG=test_app_utils \
diff --git a/src/app-utils/test/test-option-util.c b/src/app-utils/test/test-option-util.cpp
similarity index 92%
rename from src/app-utils/test/test-option-util.c
rename to src/app-utils/test/test-option-util.cpp
index 3a261c2..16f0f35 100644
--- a/src/app-utils/test/test-option-util.c
+++ b/src/app-utils/test/test-option-util.cpp
@@ -21,17 +21,19 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  ********************************************************************/
-
+#include <kvp_frame.hpp>
+#include <gmp.h> 
+extern "C"
+{
 #include <config.h>
 #include <glib.h>
 #include <unittest-support.h>
 #include <qofbookslots.h>
-#include <kvp_frame.h>
-
 #include "../option-util.h"
+}
 
 static const gchar *suitename = "/app-utils/option-util";
-void test_suite_option_util (void);
+extern "C" void test_suite_option_util (void);
 
 typedef struct
 {
@@ -42,7 +44,7 @@ typedef struct
 /* Expose a mostly-private QofInstance function to load options into
  * the Book.
  */
-extern KvpFrame *qof_instance_get_slots (const QofInstance*);
+extern "C" KvpFrame *qof_instance_get_slots (const QofInstance*);
 
 static void
 setup (Fixture *fixture, gconstpointer pData)
@@ -66,8 +68,8 @@ setup_kvp (Fixture *fixture, gconstpointer pData)
                      "autoreadonly-days", (double)21,
                      NULL);
 
-    kvp_frame_set_string (slots, "options/Business/Company Name",
-			  "Bogus Company");
+    slots->set_path("options/Business/Company Name",
+               new KvpValue("Bogus Company"));
     qof_commit_edit (QOF_INSTANCE (book));
 }
 
@@ -205,10 +207,10 @@ test_option_save (Fixture *fixture, gconstpointer pData)
 					       OPTION_NAME_AUTO_READONLY_DAYS,
 					       17));
     qof_book_save_options (book, gnc_option_db_save, odb, TRUE);
-    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Use Trading Accounts"), == , "t");
-    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Use Split Action Field for Number"), == , "t");
-    g_assert_cmpstr (kvp_frame_get_string (slots, "options/Business/Company Name"), ==, "Bogus Company");
-    g_assert_cmpfloat (kvp_frame_get_double (slots, "options/Accounts/Day Threshold for Read-Only Transactions (red line)"), ==, 17);
+    g_assert_cmpstr (slots->get_slot("options/Accounts/Use Trading Accounts")->get<const char*>(), == , "t");
+    g_assert_cmpstr (slots->get_slot("options/Accounts/Use Split Action Field for Number")->get<const char*>(), == , "t");
+    g_assert_cmpstr (slots->get_slot("options/Business/Company Name")->get<const char*>(), ==, "Bogus Company");
+    g_assert_cmpfloat (slots->get_slot("options/Accounts/Day Threshold for Read-Only Transactions (red line)")->get<double>(), ==, 17);
 
     gnc_option_db_destroy (odb);
 }
@@ -232,7 +234,7 @@ test_option_save_book_currency (Fixture *fixture, gconstpointer pData)
     gnc_option_db_destroy (odb);
 }
 
-void
+extern "C" void
 test_suite_option_util (void)
 {
     GNC_TEST_ADD (suitename, "Option DB Load", Fixture, NULL, setup_kvp, test_option_load, teardown);
diff --git a/src/backend/dbi/test/Makefile.am b/src/backend/dbi/test/Makefile.am
index ee3308b..a2b5b80 100644
--- a/src/backend/dbi/test/Makefile.am
+++ b/src/backend/dbi/test/Makefile.am
@@ -58,8 +58,8 @@ endif
 
 test_backend_dbi_SOURCES = \
     test-backend-dbi.c \
-    test-backend-dbi-basic.c \
-    test-dbi-stuff.c \
+    test-backend-dbi-basic.cpp \
+    test-dbi-stuff.cpp \
     test-dbi-business-stuff.c
 
 test_backend_dbi_LDFLAGS="-ldbi"
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.c b/src/backend/dbi/test/test-backend-dbi-basic.cpp
similarity index 91%
rename from src/backend/dbi/test/test-backend-dbi-basic.c
rename to src/backend/dbi/test/test-backend-dbi-basic.cpp
index b692f92..cd00f22 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.c
+++ b/src/backend/dbi/test/test-backend-dbi-basic.cpp
@@ -4,7 +4,10 @@
  *  Created on: 2011-04-23
  *      Author: phil
  */
+#include <kvp_frame.hpp>
 
+extern "C"
+{
 #include "config.h"
 
 #include <sys/types.h>
@@ -12,7 +15,6 @@
 #include <glib/gstdio.h>
 
 #include <qof.h>
-#include <kvp_frame.h>
 #include <unittest-support.h>
 #include <test-stuff.h>
 #include <test-dbi-stuff.h>
@@ -34,6 +36,7 @@
 /* For version_control */
 #include <gnc-prefs.h>
 #include <qofsession-p.h>
+}
 
 #if LIBDBI_VERSION >= 900
 #define HAVE_LIBDBI_R 1
@@ -43,7 +46,7 @@ static dbi_inst dbi_instance = NULL;
 #endif
 
 static const gchar* suitename = "/backend/dbi";
-void test_suite_gnc_backend_dbi (void);
+extern "C" void test_suite_gnc_backend_dbi (void);
 
 typedef struct
 {
@@ -80,7 +83,6 @@ setup_memory (Fixture *fixture, gconstpointer pData)
     gchar *url = (gchar*)pData;
     QofBook* book;
     Account *root, *acct1, *acct2;
-    KvpFrame* frame;
     Transaction* tx;
     Split *spl1, *spl2;
     gnc_commodity_table* table;
@@ -98,15 +100,16 @@ setup_memory (Fixture *fixture, gconstpointer pData)
     xaccAccountSetName (acct1, "Bank 1");
     xaccAccountSetCommodity (acct1, currency);
 
-    frame = qof_instance_get_slots (QOF_INSTANCE(acct1));
-    kvp_frame_set_gint64 (frame, "int64-val", 100);
-    kvp_frame_set_double (frame, "double-val", 3.14159);
-    kvp_frame_set_numeric (frame, "numeric-val", gnc_numeric_zero());
+    auto frame = qof_instance_get_slots (QOF_INSTANCE(acct1));
+    frame->set("int64-val", new KvpValue(INT64_C(100)));
+    frame->set("double-val", new KvpValue(3.14159));
+    frame->set("numeric-val", new KvpValue(gnc_numeric_zero()));
 
-    kvp_frame_set_timespec (frame, "timespec-val", timespec_now ());
+    frame->set("timespec-val", new KvpValue(timespec_now ()));
 
-    kvp_frame_set_string (frame, "string-val", "abcdefghijklmnop");
-    kvp_frame_set_guid (frame, "guid-val", qof_instance_get_guid (QOF_INSTANCE(acct1)));
+    frame->set("string-val", new KvpValue("abcdefghijklmnop"));
+    auto guid = qof_instance_get_guid (QOF_INSTANCE(acct1));
+    frame->set("guid-val", new KvpValue(const_cast<GncGUID*>(guid)));
 
     gnc_account_append_child (root, acct1);
 
@@ -228,9 +231,9 @@ destroy_database (gchar* url)
     gchar *basename = NULL;
     gint portnum = 0;
     gchar *port = NULL;
-    gchar *pgsql = "pgsql";
+    auto pgsql = "pgsql";
     dbi_conn conn = NULL;
-    gchar *errfmt = "Unable to delete tables in %s: %s";
+    auto errfmt = "Unable to delete tables in %s: %s";
     gint fail = 0;
     dbi_result tables;
     GSList *list = NULL;
@@ -296,11 +299,11 @@ destroy_database (gchar* url)
 static void
 teardown (Fixture *fixture, gconstpointer pData)
 {
-    gchar *lockfile = g_strdup_printf ("%s/test-dbi.xml.LCK",
+    auto lockfile = g_strdup_printf ("%s/test-dbi.xml.LCK",
                                        g_path_get_dirname (DBI_TEST_XML_FILENAME));
-    gchar *msg = g_strdup_printf ("[xml_session_end()] Error on g_unlink(%s): 2: No such file or directory", lockfile);
-    gchar *logdomain = "gnc.backend";
-    guint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
+    auto msg = g_strdup_printf ("[xml_session_end()] Error on g_unlink(%s): 2: No such file or directory", lockfile);
+    auto logdomain = "gnc.backend";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
     TestErrorStruct *check = test_error_struct_new (logdomain, loglevel, msg);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
                      (GLogFunc)test_checked_handler);
@@ -335,7 +338,8 @@ test_conn_index_functions (QofBackend *qbe)
     for  (iter = index_list; iter != NULL; iter = g_slist_next (iter))
     {
         const char *errmsg;
-        conn->provider->drop_index (be->conn, iter->data);
+        conn->provider->drop_index (be->conn,
+                                    static_cast<const char*>(iter->data));
         g_assert (DBI_ERROR_NONE == dbi_conn_error (conn->conn, &errmsg));
     }
 
@@ -354,9 +358,9 @@ test_dbi_store_and_reload (Fixture *fixture, gconstpointer pData)
     QofSession* session_3;
     QofBackend *be;
 
-    gchar *msg = "[gnc_dbi_unlock()] There was no lock entry in the Lock table";
-    gchar *log_domain = "gnc.backend.dbi";
-    guint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
+    auto msg = "[gnc_dbi_unlock()] There was no lock entry in the Lock table";
+    auto log_domain = "gnc.backend.dbi";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
     TestErrorStruct *check = test_error_struct_new (log_domain, loglevel, msg);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
                      (GLogFunc)test_checked_handler);
@@ -402,13 +406,13 @@ test_dbi_store_and_reload (Fixture *fixture, gconstpointer pData)
 static void
 test_dbi_safe_save (Fixture *fixture, gconstpointer pData)
 {
-    gchar *url = (gchar*)pData;
+    auto url = (gchar*)pData;
     QofSession *session_1 = NULL, *session_2 = NULL;
     QofBackend *be;
 
-    gchar *msg = "[gnc_dbi_unlock()] There was no lock entry in the Lock table";
-    gchar *log_domain = "gnc.backend.dbi";
-    guint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
+    auto msg = "[gnc_dbi_unlock()] There was no lock entry in the Lock table";
+    auto log_domain = "gnc.backend.dbi";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
     TestErrorStruct *check = test_error_struct_new (log_domain, loglevel, msg);
 
     if (fixture->filename)
@@ -479,7 +483,7 @@ cleanup:
 static void
 test_dbi_version_control (Fixture *fixture, gconstpointer pData)
 {
-    gchar *url = (gchar*)pData;
+    auto url = (gchar*)pData;
     QofSession *sess;
     QofBook *book;
     QofBackend *qbe;
@@ -548,9 +552,9 @@ test_dbi_business_store_and_reload (Fixture *fixture, gconstpointer pData)
     QofSession* session_3;
     const gchar* url = (gchar*)pData;
 
-    gchar *msg = "[gnc_dbi_unlock()] There was no lock entry in the Lock table";
-    gchar *log_domain = "gnc.backend.dbi";
-    guint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
+    auto msg = "[gnc_dbi_unlock()] There was no lock entry in the Lock table";
+    auto log_domain = "gnc.backend.dbi";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
     TestErrorStruct *check = test_error_struct_new (log_domain, loglevel, msg);
     if (fixture->filename)
         url = fixture->filename;
@@ -577,9 +581,9 @@ test_dbi_business_store_and_reload (Fixture *fixture, gconstpointer pData)
 }
 
 static void
-create_dbi_test_suite (gchar *dbm_name, gchar *url)
+create_dbi_test_suite (const char *dbm_name, const char *url)
 {
-    gchar *subsuite = g_strdup_printf ("%s/%s", suitename, dbm_name);
+    auto subsuite = g_strdup_printf ("%s/%s", suitename, dbm_name);
     GNC_TEST_ADD (subsuite, "store_and_reload", Fixture, url, setup,
                   test_dbi_store_and_reload, teardown);
     GNC_TEST_ADD (subsuite, "safe_save", Fixture, url, setup_memory,
@@ -592,7 +596,7 @@ create_dbi_test_suite (gchar *dbm_name, gchar *url)
 
 }
 
-void
+extern "C" void
 test_suite_gnc_backend_dbi (void)
 {
     dbi_driver driver = NULL;
diff --git a/src/backend/dbi/test/test-dbi-stuff.c b/src/backend/dbi/test/test-dbi-stuff.cpp
similarity index 92%
rename from src/backend/dbi/test/test-dbi-stuff.c
rename to src/backend/dbi/test/test-dbi-stuff.cpp
index e6ad4a6..f9e4899 100644
--- a/src/backend/dbi/test/test-dbi-stuff.c
+++ b/src/backend/dbi/test/test-dbi-stuff.cpp
@@ -22,10 +22,10 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  *  02110-1301, USA.
  */
-
+extern "C"
+{
 #include <config.h>
 #include <qof.h>
-#include <kvp_frame.h>
 #include <qofsession-p.h>
 #include <cashobjects.h>
 #include <test-dbi-stuff.h>
@@ -38,6 +38,9 @@
 #include <SX-book.h>
 #include <gnc-lot.h>
 #include "../gnc-backend-dbi-priv.h"
+}
+
+#include <kvp_frame.hpp>
 
 G_GNUC_UNUSED static QofLogModule log_module = "test-dbi";
 
@@ -98,7 +101,7 @@ get_sx_by_guid (QofBook* book, const GncGUID *guid)
         const GncGUID *sx_guid;
         sx_guid = qof_instance_get_guid (QOF_INSTANCE(sxitem->data));
         if (guid_equal (sx_guid, guid))
-            return sxitem->data;
+            return static_cast<SchedXaction*>(sxitem->data);
     }
     return NULL;
 }
@@ -127,7 +130,8 @@ compare_recurrences (GList *rl_1, GList *rl_2)
     for (ritem1 = rl_1, ritem2 = rl_2; ritem1 != NULL && ritem2 != NULL;
             ritem1 = g_list_next (ritem1), ritem2 = g_list_next (ritem2))
     {
-        Recurrence *r1 = ritem1->data, *r2 = ritem2->data;
+        auto r1 = static_cast<Recurrence*>(ritem1->data);
+        auto r2 = static_cast<Recurrence*>(ritem2->data);
 
         TEST_GDATES_EQUAL (&r1->start, &r2->start);
         g_assert_cmpint (r1->ptype, ==, r2->ptype);
@@ -185,8 +189,8 @@ compare_single_lot( QofInstance* inst, gpointer user_data )
                                 gnc_lot_get_account (lot_2), FALSE ));
     g_assert_cmpint (gnc_lot_is_closed (lot_1), ==, gnc_lot_is_closed (lot_2));
 
-    g_assert (kvp_frame_compare (qof_instance_get_slots (QOF_INSTANCE (lot_1)),
-                                 qof_instance_get_slots (QOF_INSTANCE (lot_2))) == 0);
+    g_assert (compare (qof_instance_get_slots (QOF_INSTANCE (lot_1)),
+                       qof_instance_get_slots (QOF_INSTANCE (lot_2))) == 0);
     splits1 = gnc_lot_get_split_list (lot_1);
     splits2 = gnc_lot_get_split_list (lot_2);
     g_assert_cmpint (g_list_length (splits1), ==, g_list_length (splits2));
@@ -197,7 +201,8 @@ compare_single_lot( QofInstance* inst, gpointer user_data )
         split2 = xaccSplitLookup (qof_instance_get_guid (split1->data),
                                   info->book_2);
         g_assert (GNC_IS_SPLIT (split2));
-        g_assert (xaccSplitEqual (split1->data, split2, TRUE, TRUE, TRUE));
+        g_assert (xaccSplitEqual (static_cast<Split*>(split1->data),
+                                  split2, TRUE, TRUE, TRUE));
     }
 }
 
@@ -221,7 +226,8 @@ test_conn_index_functions( QofBackend *qbe )
     for ( iter = index_list; iter != NULL; iter = g_slist_next( iter) )
     {
         const char *errmsg;
-        conn->provider->drop_index (be->conn, iter->data);
+        conn->provider->drop_index (be->conn,
+                                    static_cast<const char*>(iter->data));
         g_assert (DBI_ERROR_NONE == dbi_conn_error( conn->conn, &errmsg));
     }
 
diff --git a/src/backend/dbi/test/test-dbi-stuff.h b/src/backend/dbi/test/test-dbi-stuff.h
index 92c23ba..c9a025a 100644
--- a/src/backend/dbi/test/test-dbi-stuff.h
+++ b/src/backend/dbi/test/test-dbi-stuff.h
@@ -25,7 +25,10 @@
 
 #ifndef _TEST_DBI_STUFF_H_
 #define _TEST_DBI_STUFF_H_
-
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 #include "qof.h"
 
 typedef struct
@@ -37,5 +40,7 @@ typedef struct
 void compare_books( QofBook* book_1, QofBook* book_2 );
 
 void do_compare( QofBook* book_1, QofBook* book_2, const gchar* id, QofInstanceForeachCB cb, const gchar* msg );
-
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/src/backend/xml/test/Makefile.am b/src/backend/xml/test/Makefile.am
index 40c1048..b1d24c6 100644
--- a/src/backend/xml/test/Makefile.am
+++ b/src/backend/xml/test/Makefile.am
@@ -29,7 +29,7 @@ test_kvp_frames_SOURCES = \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
   ${top_srcdir}/src/backend/xml/sixtp-to-dom-parser.c \
   ${top_srcdir}/src/backend/xml/gnc-xml-helper.c \
-  test-kvp-frames.c
+  test-kvp-frames.cpp
 
 # the xml backend is now a GModule - this test does
 # not load it as a module and cannot link to it
@@ -221,7 +221,7 @@ TESTS_ENVIRONMENT = \
 
 check_LTLIBRARIES = libgnc-test-file-stuff.la
 
-libgnc_test_file_stuff_la_SOURCES = test-file-stuff.c
+libgnc_test_file_stuff_la_SOURCES = test-file-stuff.cpp
 libgnc_test_file_stuff_la_LIBADD = \
   ${top_builddir}/src/engine/libgncmod-engine.la
 
diff --git a/src/backend/xml/test/test-file-stuff.c b/src/backend/xml/test/test-file-stuff.cpp
similarity index 96%
rename from src/backend/xml/test/test-file-stuff.c
rename to src/backend/xml/test/test-file-stuff.cpp
index c763275..86017e0 100644
--- a/src/backend/xml/test/test-file-stuff.c
+++ b/src/backend/xml/test/test-file-stuff.cpp
@@ -20,7 +20,10 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  *  02110-1301, USA.
  */
+#include <kvp_frame.hpp>
 
+extern "C"
+{
 #include "config.h"
 
 #include <unistd.h>
@@ -40,13 +43,13 @@
 #include "test-stuff.h"
 #include "io-gncxml-gen.h"
 #include "sixtp-utils.h"
-
 /*
 #define __DEBUG 1
 */
 /***********************************************************************/
 
 extern KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
+}
 
 static int
 files_return(int ret, const char* msg)
@@ -109,7 +112,7 @@ print_dom_tree(gpointer data_for_children, GSList* data_from_children,
     if (parent_data == NULL)
     {
         xmlElemDump((FILE*)global_data, NULL, (xmlNodePtr)data_for_children);
-        xmlFreeNode(data_for_children);
+        xmlFreeNode(static_cast<xmlNodePtr>(data_for_children));
     }
     return TRUE;
 }
@@ -252,25 +255,22 @@ equals_node_val_vs_kvp_frame(xmlNodePtr node, const KvpFrame *frm)
 
     g_return_val_if_fail(cmpfrm, FALSE);
 
-    if (kvp_frame_compare(frm, cmpfrm) == 0)
+    if (compare(frm, cmpfrm) == 0)
     {
-        kvp_frame_delete(cmpfrm);
+        delete cmpfrm;
         return TRUE;
     }
     else
     {
-        gchar *frm1str;
-        gchar *frm2str;
-
-        frm1str = kvp_frame_to_string(frm);
-        frm2str = kvp_frame_to_string(cmpfrm);
+        auto frm1str = g_strdup(frm->to_string().c_str());
+        auto frm2str = g_strdup(cmpfrm->to_string().c_str());
 
         printf("%s vs %s\n", frm1str, frm2str);
 
         g_free(frm1str);
         g_free(frm2str);
 
-        kvp_frame_delete(cmpfrm);
+        delete cmpfrm;
         return FALSE;
     }
 }
diff --git a/src/backend/xml/test/test-file-stuff.h b/src/backend/xml/test/test-file-stuff.h
index 812a047..c2d8d39 100644
--- a/src/backend/xml/test/test-file-stuff.h
+++ b/src/backend/xml/test/test-file-stuff.h
@@ -4,17 +4,19 @@
 
 #ifndef TEST_FILE_STUFF_H
 #define TEST_FILE_STUFF_H
-
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 #include <glib.h>
 
-#include <kvp_frame.h>
 #include <gnc-commodity.h>
 #include <gnc-engine.h>
 #include <gnc-xml-helper.h>
 #include <io-gncxml-gen.h>
 #include <sixtp.h>
 
-
+typedef struct KvpFrameImpl KvpFrame;
 
 void write_dom_node_to_file(xmlNodePtr node, int fd);
 
@@ -40,5 +42,7 @@ void
 test_files_in_dir(int argc, char **argv, gxpf_callback cb,
                   sixtp *parser, const char *parser_tag,
                   QofBook *book);
-
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/src/backend/xml/test/test-kvp-frames.c b/src/backend/xml/test/test-kvp-frames.c
deleted file mode 100644
index 1727282..0000000
--- a/src/backend/xml/test/test-kvp-frames.c
+++ /dev/null
@@ -1,227 +0,0 @@
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "test-stuff.h"
-#include "test-engine-stuff.h"
-#include "test-file-stuff.h"
-
-#include "qof.h"
-
-#include "sixtp-dom-generators.h"
-#include "sixtp-dom-parsers.h"
-
-#define GNC_V2_STRING "gnc-v2"
-const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
-extern KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
-
-static void
-test_kvp_get_slot(int run,
-                  KvpFrame *test_frame1, const KvpValue *test_val1,
-                  const gchar *test_key)
-{
-    const KvpValue *test_val2;
-    test_val2 = kvp_frame_get_slot(test_frame1, test_key);
-    if (kvp_value_compare(test_val1, test_val2) == 0)
-    {
-        success_args("kvp_frame_get_slot", __FILE__, __LINE__, "run=%d", run);
-    }
-    else
-    {
-        gchar *tmp;
-        failure_args("kvp_frame_get_slot", __FILE__, __LINE__, "run=%d", run);
-        tmp = kvp_value_to_string(test_val2);
-        printf("    Value is %s\n", tmp);
-        g_free(tmp);
-    }
-}
-
-static void
-test_kvp_copy_compare(int run,
-                      KvpFrame *test_frame1, const KvpValue *test_val1,
-                      const gchar *test_key)
-{
-    KvpFrame *test_frame2;
-
-    test_frame2 = kvp_frame_copy(test_frame1);
-
-    do_test_args(test_frame2 != NULL, "kvp_frame_copy",
-                 __FILE__, __LINE__, "run=%d", run);
-
-    if (kvp_frame_compare(test_frame1, test_frame2) == 0)
-    {
-        success_args("kvp_frame_copy->kvp_frame_compare",
-                     __FILE__, __LINE__, "run=%d", run);
-    }
-    else
-    {
-        gchar *tmp;
-        failure_args("kvp_frame_copy->kvp_frame_compare",
-                     __FILE__, __LINE__, "run=%d", run);
-        tmp =  kvp_frame_to_string(test_frame1);
-        printf("Frame1 is %s\n", tmp);
-        g_free(tmp);
-        tmp =  kvp_frame_to_string(test_frame2);
-        printf("Frame2 is %s\n", tmp);
-        g_free(tmp);
-    }
-
-    kvp_frame_delete(test_frame2);
-}
-
-static void
-test_kvp_copy_get_slot(int run,
-                       KvpFrame *test_frame1, const KvpValue *test_val1,
-                       const gchar *test_key)
-{
-    KvpFrame *test_frame2;
-    const KvpValue *test_val2;
-
-    test_frame2 = kvp_frame_copy(test_frame1);
-    test_val2 = kvp_frame_get_slot(test_frame2, test_key);
-    if (kvp_value_compare(test_val1, test_val2) == 0)
-    {
-        success_args("kvp_frame_copy->kvp_frame_get_slot",
-                     __FILE__, __LINE__, "run=%d", run);
-    }
-    else
-    {
-        gchar *tmp;
-        failure_args("kvp_frame_copy->kvp_frame_get_slot",
-                     __FILE__, __LINE__, "run=%d", run);
-        tmp =  kvp_frame_to_string(test_frame1);
-        printf("Frame1 is %s\n", tmp);
-        g_free(tmp);
-        tmp =  kvp_frame_to_string(test_frame2);
-        printf("Frame2 is %s\n", tmp);
-        g_free(tmp);
-    }
-    kvp_frame_delete(test_frame2);
-}
-
-static void
-test_kvp_create_delete(void)
-{
-    KvpFrame *test_frame;
-
-    test_frame = kvp_frame_new();
-
-    if (test_frame != NULL)
-    {
-        kvp_frame_delete(test_frame);
-        test_frame = NULL;
-        success("kvp_frame_new");
-    }
-    else
-    {
-        failure("kvp_frame_new");
-    }
-}
-
-static void
-test_kvp_frames1(void)
-{
-    int i;
-
-    for (i = 0; i < 20; i++)
-    {
-        KvpFrame *test_frame1;
-        gchar *test_key;
-        KvpValue *test_val1;
-
-        test_val1 = get_random_kvp_value(i % KVP_TYPE_FRAME);
-
-        test_frame1 = kvp_frame_new();
-        test_key = get_random_string_without("/");
-
-        kvp_frame_set_slot(test_frame1, test_key, test_val1);
-
-        test_kvp_get_slot(i, test_frame1, test_val1, test_key);
-        test_kvp_copy_compare(i, test_frame1, test_val1, test_key);
-        test_kvp_copy_get_slot(i, test_frame1, test_val1, test_key);
-
-        kvp_value_delete(test_val1);
-        g_free(test_key);
-        kvp_frame_delete(test_frame1);
-    }
-}
-
-static void
-test_kvp_printing(void)
-{
-    int i;
-    for (i = 0; i < 20; i++)
-    {
-        KvpFrame *ran_frame;
-        gchar *char_rep;
-
-        ran_frame = get_random_kvp_frame();
-        char_rep = kvp_frame_to_string(ran_frame);
-
-        /* if we don't crash it's good :) */
-        /* puts(char_rep); */
-
-        g_free(char_rep);
-        kvp_frame_delete(ran_frame);
-    }
-}
-
-static void
-test_kvp_xml_stuff(void)
-{
-    int i;
-    for (i = 0; i < 20; i++)
-    {
-        QofInstance *inst = g_object_new (QOF_TYPE_INSTANCE, NULL);
-        KvpFrame *test_frame2;
-        xmlNodePtr test_node;
-
-        inst->kvp_data = get_random_kvp_frame();
-
-        test_node = qof_instance_slots_to_dom_tree("test-kvp", inst);
-
-        if (!test_node)
-        {
-            failure_args("xml stuff", __FILE__, __LINE__,
-                         "kvp_frame_to_dom_tree produced NULL");
-        }
-        else
-        {
-            test_frame2 = dom_tree_to_kvp_frame(test_node);
-
-            if (kvp_frame_compare(inst->kvp_data, test_frame2) == 0)
-            {
-                success("xml stuff");
-            }
-            else
-            {
-                gchar *tmp;
-                failure("xml stuff");
-                tmp = kvp_frame_to_string(inst->kvp_data);
-                printf("   with kvp_frame 1:\n%s\n", tmp);
-                g_free(tmp);
-                printf("   and xml:\n");
-                xmlElemDump(stdout, NULL, test_node);
-                printf("\n");
-                tmp = kvp_frame_to_string(test_frame2);
-                printf("   and kvp_frame 2:\n%s\n", tmp);
-                g_free(tmp);
-            }
-            kvp_frame_delete(test_frame2);
-            xmlFreeNode(test_node);
-        }
-        g_object_unref (inst);
-    }
-}
-
-int
-main(int argc, char** argv)
-{
-    qof_init();
-    test_kvp_create_delete();
-    test_kvp_printing();
-    test_kvp_frames1();
-    test_kvp_xml_stuff();
-    print_test_results();
-    exit(get_rv());
-}
diff --git a/src/backend/xml/test/test-kvp-frames.cpp b/src/backend/xml/test/test-kvp-frames.cpp
new file mode 100644
index 0000000..7c13ca8
--- /dev/null
+++ b/src/backend/xml/test/test-kvp-frames.cpp
@@ -0,0 +1,196 @@
+#include <kvp_frame.hpp>
+
+extern "C"
+{
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "test-stuff.h"
+#include "test-engine-stuff.h"
+#include "test-file-stuff.h"
+
+#include "qof.h"
+
+#include "sixtp-dom-generators.h"
+#include "sixtp-dom-parsers.h"
+
+#define GNC_V2_STRING "gnc-v2"
+const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
+extern KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
+}
+
+static void
+test_kvp_get_slot(int run,
+                  KvpFrame *test_frame1, const KvpValue *test_val1,
+                  const gchar *test_key)
+{
+    auto test_val2 = test_frame1->get_slot(test_key);
+    auto msg = "KvpFrame::get_slot";
+    if (compare(test_val1, test_val2) == 0)
+    {
+        success_args(msg, __FILE__, __LINE__, "run=%d", run);
+    }
+    else
+    {
+        gchar *tmp;
+        failure_args(msg, __FILE__, __LINE__, "run=%d", run);
+        printf("    Value is %s\n", test_val2->to_string());
+    }
+}
+
+static void
+test_kvp_copy_compare(int run,
+                      KvpFrame *test_frame1, const KvpValue *test_val1,
+                      const gchar *test_key)
+{
+    auto test_frame2 = new KvpFrame(*test_frame1);
+    auto msg = "compare after KvpFrame copy construction";
+    do_test_args(test_frame2 != NULL, "KvpFrame Copy Constructor",
+                 __FILE__, __LINE__, "run=%d", run);
+
+    if (compare(test_frame1, test_frame2) == 0)
+    {
+        success_args(msg, __FILE__, __LINE__, "run=%d", run);
+    }
+    else
+    {
+        gchar *tmp;
+        failure_args(msg, __FILE__, __LINE__, "run=%d", run);
+        printf("Frame1 is %s\n", test_frame1->to_string().c_str());
+        printf("Frame2 is %s\n",test_frame2->to_string().c_str());
+    }
+
+    delete test_frame2;
+}
+
+static void
+test_kvp_copy_get_slot(int run,
+                       KvpFrame *test_frame1, const KvpValue *test_val1,
+                       const gchar *test_key)
+{
+    auto test_frame2 = new KvpFrame(*test_frame1);
+    auto test_val2 = test_frame2->get_slot(test_key);
+    auto msg = "KvpFrame::get_slot() from a copy-constructed frame";
+    if (compare(test_val1, test_val2) == 0)
+    {
+        success_args(msg, __FILE__, __LINE__, "run=%d", run);
+    }
+    else
+    {
+        gchar *tmp;
+        failure_args(msg, __FILE__, __LINE__, "run=%d", run);
+        printf("Frame1 is %s\n", test_frame1->to_string().c_str());
+        printf("Frame2 is %s\n", test_frame2->to_string().c_str());
+    }
+    delete test_frame2;
+}
+
+static void
+test_kvp_create_delete(void)
+{
+    auto test_frame = new KvpFrame;
+    auto msg = "KvpFrame default constructor";
+    if (test_frame != nullptr)
+    {
+        delete test_frame;
+        test_frame = nullptr;
+        success(msg);
+    }
+    else
+    {
+        failure(msg);
+    }
+}
+
+static void
+test_kvp_frames1(void)
+{
+    int i;
+
+    for (i = 0; i < 20; i++)
+    {
+        auto test_val1 = get_random_kvp_value(i % KVP_TYPE_FRAME);
+        auto test_frame1 = new KvpFrame;
+        auto test_key = get_random_string_without("/");
+
+        test_frame1->set(test_key, test_val1);
+
+        test_kvp_get_slot(i, test_frame1, test_val1, test_key);
+        test_kvp_copy_compare(i, test_frame1, test_val1, test_key);
+        test_kvp_copy_get_slot(i, test_frame1, test_val1, test_key);
+
+        delete test_val1;
+        g_free(test_key);
+        delete test_frame1;
+    }
+}
+
+static void
+test_kvp_printing(void)
+{
+    int i;
+    for (i = 0; i < 20; i++)
+    {
+        auto ran_frame = get_random_kvp_frame();
+        assert(!ran_frame->to_string().empty());
+        delete ran_frame;
+    }
+}
+
+static void
+test_kvp_xml_stuff(void)
+{
+    int i;
+    for (i = 0; i < 20; i++)
+    {
+        auto inst = static_cast<QofInstance *>(g_object_new (QOF_TYPE_INSTANCE, NULL));
+        KvpFrame *test_frame2;
+        xmlNodePtr test_node;
+
+        inst->kvp_data = get_random_kvp_frame();
+        auto msg = "XML Stuff";
+
+        test_node = qof_instance_slots_to_dom_tree("test-kvp", inst);
+
+        if (!test_node)
+        {
+            failure_args("xml stuff", __FILE__, __LINE__,
+                         "kvp_frame_to_dom_tree produced NULL");
+        }
+        else
+        {
+            test_frame2 = dom_tree_to_kvp_frame(test_node);
+
+            if (compare(inst->kvp_data, test_frame2) == 0)
+            {
+                success(msg);
+            }
+            else
+            {
+                failure(msg);
+                printf("  With KvpFrame 1:\n%s\n",
+                       inst->kvp_data->to_string().c_str());
+                printf("  and XML:\n");
+                xmlElemDump(stdout, NULL, test_node);
+                printf("\n   and kvp_frame 2:\n%s\n",
+                       test_frame2->to_string().c_str());
+            }
+            delete test_frame2;
+            xmlFreeNode(test_node);
+        }
+        g_object_unref (inst);
+    }
+}
+
+int
+main(int argc, char** argv)
+{
+    qof_init();
+    test_kvp_create_delete();
+    test_kvp_printing();
+    test_kvp_frames1();
+    test_kvp_xml_stuff();
+    print_test_results();
+    exit(get_rv());
+}
diff --git a/src/engine/test-core/Makefile.am b/src/engine/test-core/Makefile.am
index 76618e7..928f79a 100644
--- a/src/engine/test-core/Makefile.am
+++ b/src/engine/test-core/Makefile.am
@@ -6,7 +6,7 @@ LDADD = \
   ${top_builddir}/src/libqof/qof/libgnc-qof.la \
   ${GLIB_LIBS}
 
-libgncmod_test_engine_la_SOURCES = gncmod-test-engine.c test-engine-stuff.c
+libgncmod_test_engine_la_SOURCES = gncmod-test-engine.c test-engine-stuff.cpp
 libgncmod_test_engine_la_LDFLAGS = -module
 libgncmod_test_engine_la_LIBADD = \
   ${top_builddir}/src/gnc-module/libgnc-module.la \
diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.cpp
similarity index 92%
rename from src/engine/test-core/test-engine-stuff.c
rename to src/engine/test-core/test-engine-stuff.cpp
index 0969bfb..6955f7b 100644
--- a/src/engine/test-core/test-engine-stuff.c
+++ b/src/engine/test-core/test-engine-stuff.cpp
@@ -15,6 +15,10 @@
  * Created by Linux Developers Group, 2001
  * Updates Linas Vepstas July 2004
  */
+#include <kvp_frame.hpp>
+
+extern "C"
+{
 #include "config.h"
 
 #include <sys/types.h>
@@ -44,6 +48,7 @@
 #include "test-engine-stuff.h"
 #include "test-stuff.h"
 #include "test-engine-strings.h"
+}
 
 static gboolean glist_strings_only = FALSE;
 
@@ -128,12 +133,6 @@ kvp_type_excluded (KvpValueType kvp_type)
     return FALSE;
 }
 
-void
-random_glist_strings_only (gboolean strings_only)
-{
-    glist_strings_only = strings_only;
-}
-
 static gboolean zero_nsec = FALSE;
 
 void
@@ -189,14 +188,11 @@ get_random_glist_depth (gint depth)
 
     for (i = 0; i < count; i++)
     {
-        KvpValueType kvpt;
-        KvpValue *value;
-
-        kvpt = glist_strings_only ? KVP_TYPE_STRING : -2;
+        KvpValue *value = nullptr;
 
         do
         {
-            value = get_random_kvp_value_depth (kvpt, depth + 1);
+            value = get_random_kvp_value_depth (-2, depth + 1);
         }
         while (!value);
 
@@ -206,12 +202,6 @@ get_random_glist_depth (gint depth)
     return ret;
 }
 
-GList*
-get_random_glist(void)
-{
-    return get_random_glist_depth (0);
-}
-
 /* ========================================================== */
 /* Time/Date, GncGUID data stuff */
 
@@ -248,19 +238,21 @@ static KvpFrame* get_random_kvp_frame_depth (gint depth);
 static KvpValue*
 get_random_kvp_value_depth (int type, gint depth)
 {
-    int datype = type;
+    KvpValueType datype;
     KvpValue *ret;
 
-    if (datype == -1)
+    if (type == -1)
     {
-        datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME);
+        datype = static_cast<KvpValueType>(get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME));
     }
 
-    if (datype == -2)
+    else if (type == -2)
     {
-        datype = get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1);
+        datype = static_cast<KvpValueType>(get_random_int_in_range(KVP_TYPE_GINT64, KVP_TYPE_FRAME - 1));
     }
-
+    else
+        datype = static_cast<KvpValueType>(type);
+    
     if (datype == KVP_TYPE_FRAME && depth >= kvp_max_depth)
         return NULL;
 
@@ -496,13 +488,13 @@ get_random_commodity_from_table (gnc_commodity_table *table)
         GList *commodities;
         char *name_space;
 
-        name_space = get_random_list_element (namespaces);
+        name_space = static_cast<char*>(get_random_list_element (namespaces));
 
         commodities = gnc_commodity_table_get_commodities (table, name_space);
         if (!commodities)
             continue;
 
-        com = get_random_list_element (commodities);
+        com = static_cast<gnc_commodity*>(get_random_list_element (commodities));
 
         g_list_free (commodities);
 
@@ -604,7 +596,7 @@ make_random_changes_to_commodity_table (gnc_commodity_table *table)
 
     for (node = namespaces; node; node = node->next)
     {
-        const char *ns = node->data;
+        auto ns = static_cast<const char *>(node->data);
         GList *commodities;
         GList *com_node;
 
@@ -615,7 +607,7 @@ make_random_changes_to_commodity_table (gnc_commodity_table *table)
 
         for (com_node = commodities; com_node; com_node = com_node->next)
         {
-            gnc_commodity *com = com_node->data;
+            auto com = static_cast<gnc_commodity *>(com_node->data);
 
             gnc_commodity_table_remove (table, com);
             make_random_changes_to_commodity (com);
@@ -748,7 +740,7 @@ get_random_pricedb(QofBook *book)
 static gboolean
 price_accumulator (GNCPrice *p, gpointer data)
 {
-    GList **list = data;
+    auto list = static_cast<GList**>(data);
 
     *list = g_list_prepend (*list, p);
 
@@ -767,7 +759,7 @@ make_random_changes_to_pricedb (QofBook *book, GNCPriceDB *pdb)
 
     for (node = list; node; node = node->next)
     {
-        GNCPrice *p = node->data;
+        auto p = static_cast<GNCPrice *>(node->data);
 
         switch (get_random_int_in_range (0, 5))
         {
@@ -898,7 +890,6 @@ get_random_account_tree (QofBook *book)
 static void
 add_random_splits(QofBook *book, Transaction *trn, GList *account_list)
 {
-    Account *acc, *bcc;
     Split *s1, *s2;
     gnc_numeric val;
     int s2_scu;
@@ -906,11 +897,11 @@ add_random_splits(QofBook *book, Transaction *trn, GList *account_list)
     /* Gotta have at least two different accounts */
     if (1 >= g_list_length (account_list)) return;
 
-    acc = get_random_list_element (account_list);
+    auto acc = static_cast<Account*>(get_random_list_element (account_list));
     xaccTransBeginEdit(trn);
     s1 = get_random_split(book, acc, trn);
 
-    bcc = get_random_list_element (account_list);
+    auto bcc = static_cast<Account*>(get_random_list_element (account_list));
     if ((bcc == acc) && (!do_bork()))
     {
         /* Make sure that each side of the transaction is in
@@ -919,7 +910,7 @@ add_random_splits(QofBook *book, Transaction *trn, GList *account_list)
          * this case? */
         while (bcc == acc)
         {
-            bcc = get_random_list_element (account_list);
+            bcc = static_cast<Account*>(get_random_list_element (account_list));
         }
     }
 
@@ -994,10 +985,8 @@ make_random_changes_to_transaction_and_splits (QofBook *book,
         splits = xaccTransGetSplitList (trans);
         for (node = splits; node; node = node->next)
         {
-            Split *split = node->data;
-            Account *account;
-
-            account = get_random_list_element (accounts);
+            auto split = static_cast<Split *>(node->data);
+            auto account = static_cast<Account*>(get_random_list_element (accounts));
 
             xaccAccountInsertSplit (account, split);
         }
@@ -1022,7 +1011,7 @@ make_random_changes_to_transaction_and_splits (QofBook *book,
     splits = xaccTransGetSplitList (trans);
     for (node = splits; node; node = node->next)
     {
-        Split *split = node->data;
+        auto split = static_cast<Split *>(node->data);
 
         if (get_random_boolean ())
             make_random_changes_to_split (split);
@@ -1038,7 +1027,7 @@ static int
 add_trans_helper (Transaction *trans, gpointer data)
 {
     TransInfo *ti;
-    GList **list = data;
+    auto list = static_cast<GList **>(data);
 
     ti = g_new (TransInfo, 1);
 
@@ -1069,7 +1058,7 @@ make_random_changes_to_level (QofBook *book, Account *parent)
         gnc_account_append_child (parent, new_account);
     else
     {
-        account = get_random_list_element (accounts);
+        account = static_cast<Account*>(get_random_list_element (accounts));
 
         gnc_account_append_child (account, new_account);
     }
@@ -1083,7 +1072,7 @@ make_random_changes_to_level (QofBook *book, Account *parent)
     /* Mess with the accounts */
     for (node = accounts; node; node = node->next)
     {
-        Account *account = node->data;
+        auto account = static_cast<Account *>(node->data);
 
         if (get_random_boolean ())
             make_random_changes_to_account (book, account);
@@ -1095,7 +1084,7 @@ make_random_changes_to_level (QofBook *book, Account *parent)
 
     for (node = transes; node; node = node->next)
     {
-        TransInfo *ti = node->data;
+        auto ti = static_cast<TransInfo *>(node->data);
         Transaction *trans = xaccTransLookup (&ti->guid, book);
 
         if (!trans)
@@ -1106,7 +1095,7 @@ make_random_changes_to_level (QofBook *book, Account *parent)
 
     for (node = transes; node; node = node->next)
     {
-        TransInfo *ti = node->data;
+        auto ti = static_cast<TransInfo *>(node->data);
 
         g_free (ti);
     }
@@ -1114,18 +1103,18 @@ make_random_changes_to_level (QofBook *book, Account *parent)
     transes = NULL;
 
     /* delete an account */
-    account = get_random_list_element (accounts);
+    account = static_cast<Account*>(get_random_list_element (accounts));
 
     splits = xaccAccountGetSplitList (account);
     splits = g_list_copy (splits);
 
     for (node = splits; node; node = node->next)
     {
-        Split *split = node->data;
+        auto split = static_cast<Split *>(node->data);
 
         do
         {
-            new_account = get_random_list_element (accounts);
+            new_account = static_cast<Account*>(get_random_list_element (accounts));
         }
         while (new_account == account);
 
@@ -1147,12 +1136,12 @@ make_random_changes_to_level (QofBook *book, Account *parent)
 
         while (i--)
         {
-            Account *a1, *a2;
+            Account *a2;
 
-            a1 = get_random_list_element (accounts);
+            auto a1 = static_cast<Account*>(get_random_list_element (accounts));
 
             if (get_random_boolean ())
-                a2 = get_random_list_element (accounts);
+                a2 = static_cast<Account*>(get_random_list_element (accounts));
             else
                 a2 = NULL;
 
@@ -1191,7 +1180,7 @@ get_random_account(QofBook *book)
                                          sane_account_names);
 
     tmp_int = get_random_int_in_range(ACCT_TYPE_BANK, NUM_ACCOUNT_TYPES - 1);
-    xaccAccountSetType(ret, tmp_int);
+    xaccAccountSetType(ret, static_cast<GNCAccountType>(tmp_int));
 
     set_account_random_string(ret, xaccAccountSetCode);
     set_account_random_string(ret, xaccAccountSetDescription);
@@ -1224,7 +1213,7 @@ make_random_changes_to_account (QofBook *book, Account *account)
     set_account_random_string (account, xaccAccountSetName);
 
     tmp_int = get_random_int_in_range (ACCT_TYPE_BANK, NUM_ACCOUNT_TYPES - 1);
-    xaccAccountSetType (account, tmp_int);
+    xaccAccountSetType (account, static_cast<GNCAccountType>(tmp_int));
 
     set_account_random_string (account, xaccAccountSetCode);
     set_account_random_string (account, xaccAccountSetDescription);
@@ -1387,7 +1376,7 @@ set_tran_random_string(Transaction* trn,
                        void(*func)(Transaction *act, const gchar*str))
 {
     gchar *tmp_str = get_random_string();
-    if (!trn || !(&trn->inst))
+    if (!trn)
     {
         return;
     }
@@ -1660,7 +1649,7 @@ set_query_sort (QofQuery *q, sort_type_t sort_code)
 {
     GSList *p1 = NULL, *p2 = NULL, *p3 = NULL, *standard;
 
-    standard = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
+    standard = g_slist_prepend (NULL, const_cast<char*>(QUERY_DEFAULT_SORT));
 
     switch (sort_code)
     {
@@ -1668,36 +1657,36 @@ set_query_sort (QofQuery *q, sort_type_t sort_code)
         p1 = standard;
         break;
     case BY_DATE:
-        p1 = g_slist_prepend (p1, TRANS_DATE_POSTED);
-        p1 = g_slist_prepend (p1, SPLIT_TRANS);
+        p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_DATE_POSTED));
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
         p2 = standard;
         break;
     case BY_DATE_ENTERED:
-        p1 = g_slist_prepend (p1, TRANS_DATE_ENTERED);
-        p1 = g_slist_prepend (p1, SPLIT_TRANS);
+        p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_DATE_ENTERED));
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
         p2 = standard;
         break;
     case BY_DATE_RECONCILED:
-        p1 = g_slist_prepend (p1, SPLIT_RECONCILE);
-        p2 = g_slist_prepend (p2, SPLIT_DATE_RECONCILED);
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_RECONCILE));
+        p2 = g_slist_prepend (p2, const_cast<char*>(SPLIT_DATE_RECONCILED));
         p3 = standard;
         break;
     case BY_NUM:
-        p1 = g_slist_prepend (p1, TRANS_NUM);
-        p1 = g_slist_prepend (p1, SPLIT_TRANS);
+        p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_NUM));
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
         p2 = standard;
         break;
     case BY_AMOUNT:
-        p1 = g_slist_prepend (p1, SPLIT_VALUE);
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_VALUE));
         p2 = standard;
         break;
     case BY_MEMO:
-        p1 = g_slist_prepend (p1, SPLIT_MEMO);
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_MEMO));
         p2 = standard;
         break;
     case BY_DESC:
-        p1 = g_slist_prepend (p1, TRANS_DESCRIPTION);
-        p1 = g_slist_prepend (p1, SPLIT_TRANS);
+        p1 = g_slist_prepend (p1, const_cast<char*>(TRANS_DESCRIPTION));
+        p1 = g_slist_prepend (p1, const_cast<char*>(SPLIT_TRANS));
         p2 = standard;
         break;
     case BY_NONE:
@@ -1712,6 +1701,13 @@ set_query_sort (QofQuery *q, sort_type_t sort_code)
     qof_query_set_sort_order (q, p1, p2, p3);
 }
 
+template <typename T> inline T
+compare_param(int max)
+{
+    auto ret = get_random_int_in_range (max == 1 ? 0 : 1, max);
+    return static_cast<T>(ret);
+}
+
 QofQuery *
 get_random_query(void)
 {
@@ -1744,7 +1740,7 @@ get_random_query(void)
             xaccQueryAddAccountGUIDMatch
             (q,
              guids,
-             get_random_int_in_range (1, QOF_GUID_MATCH_NONE),
+             compare_param<QofGuidMatch>(QOF_GUID_MATCH_NONE),
              get_random_queryop ());
             free_random_guids (guids);
             break;
@@ -1755,7 +1751,7 @@ get_random_query(void)
                                      string,
                                      get_random_boolean (),
                                      get_random_boolean (),
-                                     get_random_int_in_range (1, QOF_COMPARE_CONTAINS),
+                                     compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
                                      get_random_queryop ());
             g_free (string);
             break;
@@ -1763,19 +1759,19 @@ get_random_query(void)
         case 3: /* PR_BALANCE */
             xaccQueryAddBalanceMatch
             (q,
-             get_random_boolean (),
+             compare_param<QofQueryCompare> (1),
              get_random_queryop ());
             break;
 
         case 4: /* PR_CLEARED */
             xaccQueryAddClearedMatch
             (q,
-             get_random_int_in_range (1,
+             static_cast<cleared_match_t>(get_random_int_in_range (1,
                                       CLEARED_NO |
                                       CLEARED_CLEARED |
                                       CLEARED_RECONCILED |
                                       CLEARED_FROZEN |
-                                      CLEARED_VOIDED),
+                                                                   CLEARED_VOIDED)),
              get_random_queryop ());
             break;
 
@@ -1798,7 +1794,7 @@ get_random_query(void)
                                           string,
                                           get_random_boolean (),
                                           get_random_boolean (),
-                                          get_random_int_in_range (1, QOF_COMPARE_CONTAINS),
+                                          compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
                                           get_random_queryop ());
             g_free (string);
             break;
@@ -1821,7 +1817,7 @@ get_random_query(void)
                                    string,
                                    get_random_boolean (),
                                    get_random_boolean (),
-                                   get_random_int_in_range (1, QOF_COMPARE_CONTAINS),
+                                   compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
                                    get_random_queryop ());
             g_free (string);
             break;
@@ -1832,7 +1828,7 @@ get_random_query(void)
                                      string,
                                      get_random_boolean (),
                                      get_random_boolean (),
-                                     get_random_int_in_range (1, QOF_COMPARE_CONTAINS),
+                                     compare_param<QofQueryCompare>(QOF_COMPARE_CONTAINS),
                                      get_random_queryop ());
             g_free (string);
             break;
@@ -1841,7 +1837,7 @@ get_random_query(void)
             xaccQueryAddSharePriceMatch
             (q,
              get_random_gnc_numeric (GNC_DENOM_AUTO),
-             get_random_int_in_range (1, QOF_COMPARE_NEQ),
+             compare_param<QofQueryCompare> (QOF_COMPARE_NEQ),
              get_random_queryop ());
             break;
 
@@ -1849,7 +1845,7 @@ get_random_query(void)
             xaccQueryAddSharesMatch
             (q,
              get_random_gnc_numeric (GNC_DENOM_AUTO),
-             get_random_int_in_range (1, QOF_COMPARE_NEQ),
+             compare_param<QofQueryCompare> (QOF_COMPARE_NEQ),
              get_random_queryop ());
             break;
 
@@ -1857,8 +1853,8 @@ get_random_query(void)
             xaccQueryAddValueMatch
             (q,
              get_random_gnc_numeric (GNC_DENOM_AUTO),
-             get_random_int_in_range (1, QOF_NUMERIC_MATCH_ANY),
-             get_random_int_in_range (1, QOF_COMPARE_NEQ),
+             compare_param<QofNumericMatch> (QOF_NUMERIC_MATCH_ANY),
+             compare_param<QofQueryCompare> (QOF_COMPARE_NEQ),
              get_random_queryop ());
             break;
 
@@ -1870,7 +1866,7 @@ get_random_query(void)
     }
 
     if (gnc_engine_debug_random) printf ("\n");
-    set_query_sort (q, get_random_int_in_range (1, BY_NONE));
+    set_query_sort (q, compare_param<sort_type_t>(BY_NONE));
 
     qof_query_set_sort_increasing (q,
                                    get_random_boolean (),
@@ -2088,7 +2084,7 @@ make_trans_query (Transaction *trans, TestQueryTypes query_types)
         list = NULL;
         for (node = xaccTransGetSplitList (trans); node; node = node->next)
         {
-            Split * split = node->data;
+            auto split = static_cast<Split * >(node->data);
             list = g_list_prepend (list, xaccSplitGetAccount (split));
         }
         xaccQueryAddAccountMatch (q, list, QOF_GUID_MATCH_ALL, QOF_QUERY_AND);
diff --git a/src/engine/test-core/test-engine-stuff.h b/src/engine/test-core/test-engine-stuff.h
index 557bba8..73360b4 100644
--- a/src/engine/test-core/test-engine-stuff.h
+++ b/src/engine/test-core/test-engine-stuff.h
@@ -4,7 +4,10 @@
 
 #ifndef TEST_ENGINE_STUFF_H
 #define TEST_ENGINE_STUFF_H
-
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 #include <glib.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -32,9 +35,7 @@ bin_data* get_random_binary_data(void);
 KvpFrame* get_random_kvp_frame(void);
 gnc_numeric get_random_gnc_numeric(int64_t);
 GncGUID* get_random_guid(void);
-GList* get_random_glist(void);
 
-void random_glist_strings_only (gboolean strings_only);
 void kvp_exclude_type (KvpValueType kvp_type);
 void set_max_kvp_depth (gint max_kvp_depth);
 void set_max_kvp_frame_elements (gint max_kvp_frame_elements);
@@ -95,4 +96,7 @@ SchedXaction* add_daily_sx(gchar *name, const GDate *start, const GDate *end, co
 SchedXaction* add_once_sx(gchar *name, const GDate *when);
 void remove_sx(SchedXaction *sx);
 
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/src/engine/test/Makefile.am b/src/engine/test/Makefile.am
index 8f1cf03..7366d75 100644
--- a/src/engine/test/Makefile.am
+++ b/src/engine/test/Makefile.am
@@ -94,7 +94,7 @@ EXTRA_DIST += \
 
 test_engine_SOURCES = \
 	test-engine.c \
-	utest-Account.c \
+	utest-Account.cpp \
 	utest-Budget.c \
 	utest-Entry.c \
 	utest-Invoice.c \
@@ -124,7 +124,7 @@ libutest_Split_la_CXXFLAGS = -Wno-write-strings $(AM_CXXFLAGS)
 libutest_Split_la_LIBADD = $(LDADD)
 
 libutest_Trans_la_SOURCES = \
-	utest-Transaction.c
+	utest-Transaction.cpp
 
 libutest_Trans_la_LIBADD = $(LDADD)
 
diff --git a/src/engine/test/gtest-import-map.cpp b/src/engine/test/gtest-import-map.cpp
index a4d4885..e24a64f 100644
--- a/src/engine/test/gtest-import-map.cpp
+++ b/src/engine/test/gtest-import-map.cpp
@@ -26,7 +26,6 @@ extern "C"
 #include "../Account.h"
 #include <qof.h>
 #include <qofinstance-p.h>
-#include <kvp_frame.h>
 
 struct GncImportMatchMap
 {
@@ -48,6 +47,7 @@ extern void gnc_imap_add_account_bayes (GncImportMatchMap *imap,
 					Account *acc);
 }
 
+#include <kvp_frame.hpp>
 #include <gtest/gtest.h>
 
 class ImapTest : public testing::Test
@@ -103,14 +103,12 @@ protected:
 TEST_F(ImapPlainTest, FindAccount)
 {
     auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
-    auto acc1_val = kvp_value_new_guid(xaccAccountGetGUID(t_expense_account1));
-    auto acc2_val = kvp_value_new_guid(xaccAccountGetGUID(t_expense_account2));
-    kvp_frame_set_slot_path(root, acc1_val, IMAP_FRAME, "foo", "bar", NULL);
-    kvp_frame_set_slot_path(root, acc2_val, IMAP_FRAME, "baz", "waldo", NULL);
-    kvp_frame_set_slot_path(root, acc1_val, IMAP_FRAME, "pepper", NULL);
-    kvp_frame_set_slot_path(root, acc2_val, IMAP_FRAME, "salt", NULL);
-    kvp_value_delete(acc1_val);
-    kvp_value_delete(acc2_val);
+    auto acc1_val = new KvpValue(const_cast<GncGUID*>(xaccAccountGetGUID(t_expense_account1)));
+    auto acc2_val = new KvpValue(const_cast<GncGUID*>(xaccAccountGetGUID(t_expense_account2)));
+    root->set_path({IMAP_FRAME, "foo", "bar"}, acc1_val);
+    root->set_path({IMAP_FRAME, "baz", "waldo"}, acc2_val);
+    root->set_path({IMAP_FRAME, "pepper"}, acc1_val);
+    root->set_path({IMAP_FRAME, "salt"}, acc2_val);
 
     EXPECT_EQ(t_expense_account1, gnc_imap_find_account(t_imap, "foo", "bar"));
     EXPECT_EQ(t_expense_account2,
@@ -140,17 +138,17 @@ TEST_F(ImapPlainTest, AddAccount)
     qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
 
     auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
-    auto value = kvp_frame_get_slot_path(root, IMAP_FRAME, "foo", "bar", NULL);
+    auto value = root->get_slot({IMAP_FRAME, "foo", "bar"});
     auto check_account = [this](KvpValue* v) {
-        return xaccAccountLookup(kvp_value_get_guid(v), this->t_imap->book); };
+        return xaccAccountLookup(v->get<GncGUID*>(), this->t_imap->book); };
     EXPECT_EQ(t_expense_account1, check_account(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "baz", "waldo", NULL);
+    value = root->get_slot({IMAP_FRAME, "baz", "waldo"});
     EXPECT_EQ(t_expense_account2, check_account(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "pepper", NULL);
+    value = root->get_slot({IMAP_FRAME, "pepper"});
     EXPECT_EQ(t_expense_account1, check_account(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "salt", NULL);
+    value = root->get_slot({IMAP_FRAME, "salt"});
     EXPECT_EQ(t_expense_account2, check_account(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "pork", "sausage", NULL);
+    value = root->get_slot({IMAP_FRAME, "pork", "sausage"});
     EXPECT_EQ(nullptr, value);
 }
 
@@ -205,21 +203,14 @@ TEST_F(ImapBayesTest, FindAccountBayes)
     auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
     auto acct1_name = gnc_account_get_full_name(t_expense_account1);
     auto acct2_name = gnc_account_get_full_name(t_expense_account2);
-    auto value = kvp_value_new_gint64(42);
+    auto value = new KvpValue(INT64_C(42));
 
-    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
-                            foo, acct1_name, NULL);
-    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
-                            bar, acct1_name, NULL);
-    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
-                            baz, acct2_name, NULL);
-    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
-                            waldo, acct2_name, NULL);
-    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
-                            pepper, acct1_name, NULL);
-    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
-                            salt, acct2_name, NULL);
-    kvp_value_delete(value);
+    root->set_path({IMAP_FRAME_BAYES, foo, acct1_name}, value);
+    root->set_path({IMAP_FRAME_BAYES, bar, acct1_name}, value);
+    root->set_path({IMAP_FRAME_BAYES, baz, acct2_name}, value);
+    root->set_path({IMAP_FRAME_BAYES, waldo, acct2_name}, value);
+    root->set_path({IMAP_FRAME_BAYES, pepper, acct1_name}, value);
+    root->set_path({IMAP_FRAME_BAYES, salt, acct2_name}, value);
 
     auto account = gnc_imap_find_account_bayes(t_imap, t_list1);
     EXPECT_EQ(t_expense_account1, account);
@@ -252,37 +243,28 @@ TEST_F(ImapBayesTest, AddAccountBayes)
     auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
     auto acct1_name = gnc_account_get_full_name(t_expense_account1);
     auto acct2_name = gnc_account_get_full_name(t_expense_account2);
-    auto value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, "foo", "bar", NULL);
+    auto value = root->get_slot({IMAP_FRAME_BAYES, "foo", "bar"});
     auto check_account = [this](KvpValue* v) {
-        return (kvp_value_get_string(v),
-                                 this->t_imap->book); };
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, foo, acct1_name,
-                                    NULL);
-    EXPECT_EQ(1, kvp_value_get_gint64(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, bar, acct1_name,
-                                    NULL);
-    EXPECT_EQ(1, kvp_value_get_gint64(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, baz, acct2_name,
-                                    NULL);
-    EXPECT_EQ(1, kvp_value_get_gint64(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, waldo, acct2_name,
-                                    NULL);
-    EXPECT_EQ(1, kvp_value_get_gint64(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, pepper, acct1_name,
-                                    NULL);
-    EXPECT_EQ(1, kvp_value_get_gint64(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, salt, acct2_name,
-                                    NULL);
-    EXPECT_EQ(1, kvp_value_get_gint64(value));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, baz, acct1_name,
-                                    NULL);
-    EXPECT_EQ(0, kvp_value_get_gint64(value));
+        return (v->get<const char*>(), this->t_imap->book); };
+    value = root->get_slot({IMAP_FRAME_BAYES, foo, acct1_name});
+    EXPECT_EQ(1, value->get<int64_t>());
+    value = root->get_slot({IMAP_FRAME_BAYES, bar, acct1_name});
+    EXPECT_EQ(1, value->get<int64_t>());
+    value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_name});
+    EXPECT_EQ(1, value->get<int64_t>());
+    value = root->get_slot({IMAP_FRAME_BAYES, waldo, acct2_name});
+    EXPECT_EQ(1, value->get<int64_t>());
+    value = root->get_slot({IMAP_FRAME_BAYES, pepper, acct1_name});
+    EXPECT_EQ(1, value->get<int64_t>());
+    value = root->get_slot({IMAP_FRAME_BAYES, salt, acct2_name});
+    EXPECT_EQ(1, value->get<int64_t>());
+    value = root->get_slot({IMAP_FRAME_BAYES, baz, acct1_name});
+    EXPECT_EQ(nullptr, value);
 
     qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
     gnc_imap_add_account_bayes(t_imap, t_list2, t_expense_account2);
     qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
     qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
-    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, baz, acct2_name,
-                                    NULL);
-    EXPECT_EQ(2, kvp_value_get_gint64(value));
+    value = root->get_slot({IMAP_FRAME_BAYES, baz, acct2_name});
+    EXPECT_EQ(2, value->get<int64_t>());
 }
diff --git a/src/engine/test/utest-Account.c b/src/engine/test/utest-Account.cpp
similarity index 89%
rename from src/engine/test/utest-Account.c
rename to src/engine/test/utest-Account.cpp
index f1c6914..747f9d6 100644
--- a/src/engine/test/utest-Account.c
+++ b/src/engine/test/utest-Account.cpp
@@ -18,14 +18,15 @@
  * Free Software Foundation           Voice:  +1-617-542-5942       *
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-********************************************************************/
+ ********************************************************************/
+extern "C"
+{
 #include "config.h"
 #include <string.h>
 #include <glib.h>
 #include <unittest-support.h>
 #include <gnc-event.h>
 #include <gnc-gdate-utils.h>
-#include <kvp_frame.h>
 #include <qofinstance-p.h>
 /* Add specific headers for this class */
 #include "../Account.h"
@@ -44,6 +45,9 @@
 #endif
 static const gchar *suitename = "/engine/Account";
 void test_suite_account (void);
+}
+
+#include <kvp_frame.hpp>
 
 typedef struct
 {
@@ -54,20 +58,20 @@ typedef struct
 typedef struct
 {
     GNCAccountType type;
-    char *name;
-    char *parent;
-    char *code;
-    char *desc;
-    char *color;
-    char *notes;
-    char *num;
+    const char *name;
+    const char *parent;
+    const char *code;
+    const char *desc;
+    const char *color;
+    const char *notes;
+    const char *num;
     GNCPolicy *policy;
 } AccountParms;
 
 typedef struct
 {
-    char *memo;
-    char *account;
+    const char *memo;
+    const char *account;
     char reconciled;
     gnc_numeric amount;
     gnc_numeric value;
@@ -76,7 +80,7 @@ typedef struct
 
 typedef struct
 {
-    gchar *desc;
+    const char *desc;
     gint date_offset;
     SplitParms splits[2];
 } TxnParms;
@@ -265,10 +269,10 @@ static SetupData complex_data = {G_N_ELEMENTS (complex_accts),
 static Split*
 insert_split (Account *parent, Transaction *txn, SplitParms *p)
 {
-    QofBook *book = gnc_account_get_book (parent);
-    Split *split = xaccMallocSplit (book);
-    Account *acct = gnc_account_lookup_by_name (parent, p->account);
-    LotList* lotlist = xaccAccountGetLotList (acct);
+    auto book = gnc_account_get_book (parent);
+    auto split = xaccMallocSplit (book);
+    auto acct = gnc_account_lookup_by_name (parent, p->account);
+    auto lotlist = xaccAccountGetLotList (acct);
     GNCLot* lot = NULL;
     g_assert (acct != NULL);
     xaccSplitSetParent (split, txn);
@@ -297,31 +301,32 @@ insert_split (Account *parent, Transaction *txn, SplitParms *p)
 static void
 setup (Fixture *fixture, gconstpointer pData)
 {
-    QofBook *book = qof_book_new ();
-    Account *root = gnc_account_create_root (book), *acct = NULL;
-    SetupData *parms = (SetupData *)pData;
+    auto book = qof_book_new ();
+    auto root = gnc_account_create_root (book);
+    auto parms = static_cast<const SetupData*>(pData);
     TxnParms *t_arr;
     AccountParms *p_arr;
-    GHashTable *accts = g_hash_table_new (g_str_hash, g_str_equal);
+    auto accts = g_hash_table_new (g_str_hash, g_str_equal);
     guint ind;
 
-    g_hash_table_insert (accts, "root", root);
+    auto root_str = static_cast<char*>(CACHE_INSERT("root"));
+    g_hash_table_insert (accts, root_str, root);
     fixture->func = _utest_account_fill_functions ();
     if (parms == NULL)
     {
         fixture->acct = root;
         return;
     }
-    acct = root;
+    auto acct = root;
 
     p_arr  = (AccountParms*)parms->accounts;
     for (ind = 0; ind < parms->num_accounts; ind++)
     {
-        Account *child = xaccMallocAccount (book);
+        auto child = xaccMallocAccount (book);
         AccountParms p = p_arr[ind];
         if (p.parent && strlen (p.parent) > 0)
         {
-            Account *parent = g_hash_table_lookup (accts, p.parent);
+            auto parent = static_cast<Account*>(g_hash_table_lookup (accts, p.parent));
             g_assert (parent != NULL);
             gnc_account_append_child (parent, child);
         }
@@ -332,7 +337,7 @@ setup (Fixture *fixture, gconstpointer pData)
         if (p.name)
         {
             xaccAccountSetName (acct, p.name);
-            g_hash_table_insert (accts, p.name, acct);
+            g_hash_table_insert (accts, const_cast<char*>(p.name), acct);
         }
         if (p.code)
             xaccAccountSetCode (acct, p.code);
@@ -427,27 +432,28 @@ static void
 test_gnc_account_name_violations_errmsg ()
 {
     GList *badnames = NULL, *nonames = NULL, *node = NULL;
-    gchar *separator = ":", *message, *validation_message, *account_list = NULL;
+    auto separator = ":";
+    char *account_list = NULL;
     /* FUT wants to free the strings, so we alloc them */
     badnames = g_list_prepend (badnames, g_strdup ("Foo:bar"));
     badnames = g_list_prepend (badnames, g_strdup ("baz"));
     badnames = g_list_prepend (badnames, g_strdup ("waldo:pepper"));
-    message = gnc_account_name_violations_errmsg (separator, nonames);
+    auto message = gnc_account_name_violations_errmsg (separator, nonames);
     for (node = badnames; node; node = g_list_next (node))
     {
         if (!account_list)
-            account_list = g_strdup (node->data);
+            account_list = g_strdup (static_cast<char*>(node->data));
         else
         {
-            gchar *tmp_list = g_strconcat ( account_list, "\n",
-                                            node->data, NULL);
+            auto tmp_list = g_strconcat ( account_list, "\n",
+                                          static_cast<char*>(node->data), NULL);
             g_free (account_list);
             account_list = tmp_list;
         }
     }
     message = gnc_account_name_violations_errmsg (separator, nonames);
     g_assert (message == NULL);
-    validation_message = g_strdup_printf (
+    auto validation_message = g_strdup_printf (
         "The separator character \"%s\" is used in one or more account "
         "names.\n\nThis will result in unexpected behaviour. "
         "Either change the account names or choose another separator "
@@ -464,33 +470,33 @@ GList *gnc_account_list_name_violations (QofBook *book, const gchar *separator)/
 static void
 test_gnc_account_list_name_violations (Fixture *fixture, gconstpointer pData)
 {
-    guint log_level = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    gchar *log_domain = "gnc.engine";
+    auto log_level = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto log_domain = "gnc.engine";
 #ifdef USE_CLANG_FUNC_SIG
 #define _func "GList *gnc_account_list_name_violations(QofBook *, const gchar *)"
 #else
 #define _func "gnc_account_list_name_violations"
 #endif
-    gchar *msg = _func ": assertion " _Q "separator != NULL' failed";
+    auto msg = _func ": assertion " _Q "separator != NULL' failed";
 #undef _func
-    TestErrorStruct check = { log_level, log_domain, msg, 0 };
+    auto check = test_error_struct_new(log_domain, log_level, msg);
     GList *results, *res_iter;
-    gchar *sep = ":";
+    auto sep = ":";
     QofBook *book = gnc_account_get_book (fixture->acct);
     /* Because of GLib bug 653052, we have to set the logging user_data to
      * affect the test_log_fatal_handler
      */
-    GLogFunc oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
+    GLogFunc oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, check);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check);
     g_assert (gnc_account_list_name_violations (NULL, NULL) == NULL);
-    g_assert_cmpint (check.hits, ==, 1);
+    g_assert_cmpint (check->hits, ==, 1);
     g_assert (gnc_account_list_name_violations (book, NULL) == NULL);
-    g_assert_cmpint (check.hits, ==, 2);
+    g_assert_cmpint (check->hits, ==, 2);
     g_assert (gnc_account_list_name_violations (NULL, sep) == NULL);
     g_log_set_default_handler (oldlogger, NULL);
     results = gnc_account_list_name_violations (book, sep);
     g_assert_cmpuint (g_list_length (results), == , 2);
-    g_assert_cmpint (check.hits, ==, 2);
+    g_assert_cmpint (check->hits, ==, 2);
     for (res_iter = results; res_iter; res_iter = g_list_next (res_iter))
         test_free (res_iter->data);
     g_list_free (results);
@@ -546,8 +552,8 @@ gnc_account_init (Account* acc)// 1
 static void
 test_gnc_account_create_and_destroy (void)
 {
-    Account *acc = g_object_new (GNC_TYPE_ACCOUNT, NULL);
-    gchar *name, *fname, *code, *desc, *color, *notes, *tax_code, *tax_src;
+    auto acc = static_cast<Account*>(g_object_new (GNC_TYPE_ACCOUNT, NULL));
+    char *name, *fname, *code, *desc, *color, *notes, *tax_code, *tax_src;
     GNCAccountType type;
     gnc_commodity *commo;
     gint commo_scu, mark;
@@ -660,10 +666,10 @@ Simple pass-through for qof_collection_get_data ()
 static void
 test_gnc_book_set_get_root_account (Fixture *fixture, gconstpointer pData)
 {
-    guint log_level = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    gchar *log_domain = "gnc.account";
-    gchar *msg = "[gnc_book_set_root_account()] cannot mix and match books freely!";
-    TestErrorStruct check = { log_level, log_domain, msg, 0 };
+    auto log_level = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto log_domain = "gnc.account";
+    auto msg = "[gnc_book_set_root_account()] cannot mix and match books freely!";
+    auto check = test_error_struct_new(log_domain, log_level, msg);
     Account *acc1, *acc2;
     QofBook* book1 = qof_book_new ();
     GLogFunc oldlogger;
@@ -679,12 +685,12 @@ test_gnc_book_set_get_root_account (Fixture *fixture, gconstpointer pData)
     /* Now try to set the book's root account to the fixture
      * accout. Should throw an error.
      */
-    oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
+    oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, check);
     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler,
-                                  &check);
+                                  check);
     gnc_book_set_root_account (book1, fixture->acct);
     g_assert (gnc_book_get_root_account (book1) == acc1);
-    g_assert_cmpint (check.hits, ==, 1);
+    g_assert_cmpint (check->hits, ==, 1);
     g_log_set_default_handler (oldlogger, NULL);
     /* Check that if we set the same root, it stays set */
     gnc_book_set_root_account (book2, fixture->acct);
@@ -728,7 +734,7 @@ test_gnc_account_create_root (void)
     QofBook *book = qof_book_new ();
     QofCollection *coll = qof_book_get_collection (book, GNC_ID_ROOT_ACCOUNT);
     Account *acc;
-    gchar *name;
+    char *name;
     AccountTestFunctions *func = _utest_account_fill_functions ();
     /* Can't use gnc_book_get_root_account, it creates one if it doesn't
      * yet exist */
@@ -752,27 +758,28 @@ test_xaccCloneAccount (Fixture *fixture, gconstpointer pData)
 {
     Account *clone;
     QofBook *book = gnc_account_get_book (fixture->acct);
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
 #ifdef USE_CLANG_FUNC_SIG
 #define _func "Account *xaccCloneAccount(const Account *, QofBook *)"
 #else
 #define _func "xaccCloneAccount"
 #endif
-    gchar *msg1 = _func ": assertion " _Q "GNC_IS_ACCOUNT(from)' failed";
-    gchar *msg2 = _func ": assertion " _Q "QOF_IS_BOOK(book)' failed";
+    auto msg1 = _func ": assertion " _Q "GNC_IS_ACCOUNT(from)' failed";
+    auto msg2 = _func ": assertion " _Q "QOF_IS_BOOK(book)' failed";
 #undef _func
-    TestErrorStruct check = { loglevel, "gnc.engine", msg1, 0 };
-    GLogFunc oldlogger;
+    auto check = test_error_struct_new("gnc.engine", loglevel, msg1);
     AccountPrivate *acct_p, *clone_p;
-    oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler, &check);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
+    auto oldlogger = g_log_set_default_handler ((GLogFunc)test_null_handler,
+                                                check);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check);
     clone = xaccCloneAccount (NULL, book);
     g_assert (clone == NULL);
-    g_assert_cmpint (check.hits, ==, 1);
-    check.msg = msg2;
+    g_assert_cmpint (check->hits, ==, 1);
+    g_free(check->msg);
+    check->msg = g_strdup(msg2);
     clone = xaccCloneAccount (fixture->acct, NULL);
     g_assert (clone == NULL);
-    g_assert_cmpint (check.hits, ==, 2);
+    g_assert_cmpint (check->hits, ==, 2);
     g_log_set_default_handler (oldlogger, NULL);
     /* Now test the real clone */
     clone = xaccCloneAccount (fixture->acct, book);
@@ -783,12 +790,13 @@ test_xaccCloneAccount (Fixture *fixture, gconstpointer pData)
     g_assert (clone_p->accountName == acct_p->accountName);
     g_assert (clone_p->accountCode == acct_p->accountCode);
     g_assert (clone_p->description == acct_p->description);
-    g_assert (kvp_frame_compare (clone->inst.kvp_data,
-                                 fixture->acct->inst.kvp_data) == 0);
+    g_assert (compare (clone->inst.kvp_data,
+                       fixture->acct->inst.kvp_data) == 0);
     g_assert (gnc_commodity_equal (clone_p->commodity, acct_p->commodity));
     g_assert (clone_p->commodity_scu == acct_p->commodity_scu);
     g_assert (clone_p->non_standard_scu == acct_p->non_standard_scu);
     /* Clean Up */
+    test_error_struct_free(check);
     g_object_unref (clone);
 
 }
@@ -854,18 +862,18 @@ acc_free
 static void
 test_xaccFreeAccount (Fixture *fixture, gconstpointer pData)
 {
-    gchar *msg1 = "[xaccFreeAccount()]  instead of calling xaccFreeAccount(), please call \n"
+    auto msg1 = "[xaccFreeAccount()]  instead of calling xaccFreeAccount(), please call \n"
                   " xaccAccountBeginEdit(); xaccAccountDestroy(); \n";
 #ifdef USE_CLANG_FUNC_SIG
 #define _func "int xaccTransGetSplitIndex(const Transaction *, const Split *)"
 #else
 #define _func "xaccTransGetSplitIndex"
 #endif
-    gchar *msg2 = _func ": assertion " _Q "trans && split' failed";
+    auto msg2 = _func ": assertion " _Q "trans && split' failed";
 #undef _func
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    TestErrorStruct check1 = { loglevel, "gnc.account", msg1, 0 };
-    TestErrorStruct check2 = { loglevel, "gnc.engine", msg2, 0 };
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check1 = test_error_struct_new("gnc.account", loglevel, msg1);
+    auto check2 = test_error_struct_new("gnc.engine", loglevel, msg2);
     QofBook *book = gnc_account_get_book (fixture->acct);
     Account *parent = gnc_account_get_parent (fixture->acct);
     AccountPrivate *p_priv = fixture->func->get_private (parent);
@@ -873,12 +881,12 @@ test_xaccFreeAccount (Fixture *fixture, gconstpointer pData)
     guint i = 0;
     guint hdlr1, hdlr2;
     gnc_commodity *commodity = gnc_commodity_new (book, "US Dollar", "CURRENCY", "USD", "0", 100);
-    test_add_error (&check1);
-    test_add_error (&check2);
+    test_add_error (check1);
+    test_add_error (check2);
     hdlr1 = g_log_set_handler ("gnc.account", loglevel,
-                               (GLogFunc)test_checked_handler, &check1);
+                               (GLogFunc)test_checked_handler, check1);
     hdlr2 = g_log_set_handler ("gnc.engine", loglevel,
-                               (GLogFunc)test_checked_handler, &check2);
+                               (GLogFunc)test_checked_handler, check2);
     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
     for (i = 0; i < numItems; i++)
     {
@@ -894,8 +902,8 @@ test_xaccFreeAccount (Fixture *fixture, gconstpointer pData)
     g_assert (p_priv->splits != NULL);
     g_assert (p_priv->parent != NULL);
     g_assert (p_priv->commodity != NULL);
-    g_assert_cmpint (check1.hits, ==, 0);
-    g_assert_cmpint (check2.hits, ==, 0);
+    g_assert_cmpint (check1->hits, ==, 0);
+    g_assert_cmpint (check2->hits, ==, 0);
     /* Now set the other private parts to something so that they can be set back */
     p_priv->cleared_balance = gnc_numeric_create ( 5, 12);
     p_priv->reconciled_balance = gnc_numeric_create ( 5, 12);
@@ -903,8 +911,8 @@ test_xaccFreeAccount (Fixture *fixture, gconstpointer pData)
     p_priv->balance_dirty = TRUE;
     p_priv->sort_dirty = TRUE;
     fixture->func->xaccFreeAccount (parent);
-    g_assert_cmpint (check1.hits, ==, 6);
-    g_assert_cmpint (check2.hits, ==, 6);
+    g_assert_cmpint (check1->hits, ==, 6);
+    g_assert_cmpint (check2->hits, ==, 6);
     /* cleanup what's left */
     g_log_remove_handler ("gnc.account", hdlr1);
     g_log_remove_handler ("gnc.engine", hdlr2);
@@ -968,18 +976,18 @@ Also tests:
 static void
 test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
 {
-    gchar *msg1 = "[xaccFreeAccount()]  instead of calling xaccFreeAccount(), please call \n"
+    auto msg1 = "[xaccFreeAccount()]  instead of calling xaccFreeAccount(), please call \n"
                   " xaccAccountBeginEdit(); xaccAccountDestroy(); \n";
 #ifdef USE_CLANG_FUNC_SIG
 #define _func "int xaccTransGetSplitIndex(const Transaction *, const Split *)"
 #else
 #define _func "xaccTransGetSplitIndex"
 #endif
-    gchar *msg2 = _func ": assertion " _Q "trans && split' failed";
+    auto msg2 = _func ": assertion " _Q "trans && split' failed";
 #undef _func
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    TestErrorStruct check1 = { loglevel, "gnc.account", msg1, 0 };
-    TestErrorStruct check2 = { loglevel, "gnc.engine", msg2, 0 };
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check1 = test_error_struct_new("gnc.account", loglevel, msg1);
+    auto check2 = test_error_struct_new("gnc.engine", loglevel, msg2);
     guint hdlr1, hdlr2;
     TestSignal sig1, sig2;
     QofBook *book = gnc_account_get_book (fixture->acct);
@@ -988,12 +996,12 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
     const guint numItems = 3;
     guint i = 0;
     gnc_commodity *commodity = gnc_commodity_new (book, "US Dollar", "CURRENCY", "USD", "0", 100);
-    test_add_error (&check1);
-    test_add_error (&check2);
+    test_add_error (check1);
+    test_add_error (check2);
     hdlr1 = g_log_set_handler ("gnc.account", loglevel,
-                               (GLogFunc)test_checked_handler, &check1);
+                               (GLogFunc)test_checked_handler, check1);
     hdlr2 = g_log_set_handler ("gnc.engine", loglevel,
-                               (GLogFunc)test_checked_handler, &check2);
+                               (GLogFunc)test_checked_handler, check2);
     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
     for (i = 0; i < numItems; i++)
     {
@@ -1009,8 +1017,8 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
     g_assert (p_priv->splits != NULL);
     g_assert (p_priv->parent != NULL);
     g_assert (p_priv->commodity != NULL);
-    g_assert_cmpint (check1.hits, ==, 0);
-    g_assert_cmpint (check2.hits, ==, 0);
+    g_assert_cmpint (check1->hits, ==, 0);
+    g_assert_cmpint (check2->hits, ==, 0);
 
     sig1 = test_signal_new (&parent->inst, QOF_EVENT_MODIFY, NULL);
     sig2 = test_signal_new (&parent->inst, QOF_EVENT_DESTROY, NULL);
@@ -1025,8 +1033,8 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
     g_assert (p_priv->splits != NULL);
     g_assert (p_priv->parent != NULL);
     g_assert (p_priv->commodity != NULL);
-    g_assert_cmpint (check1.hits, ==, 0);
-    g_assert_cmpint (check2.hits, ==, 0);
+    g_assert_cmpint (check1->hits, ==, 0);
+    g_assert_cmpint (check2->hits, ==, 0);
     /* xaccAccountDestroy destroys the account by calling
      * qof_instance_set_destroying (), then xaccAccountCommitEdit ();
      */
@@ -1035,8 +1043,8 @@ test_xaccAccountCommitEdit (Fixture *fixture, gconstpointer pData)
     /* So this time we make sure that the account is destroyed */
     test_signal_assert_hits (sig1, 2);
     test_signal_assert_hits (sig2, 1);
-    g_assert_cmpint (check1.hits, ==, 2);
-    g_assert_cmpint (check2.hits, ==, 12);
+    g_assert_cmpint (check1->hits, ==, 2);
+    g_assert_cmpint (check2->hits, ==, 12);
     /* And clean up */
     test_signal_free (sig1);
     test_signal_free (sig2);
@@ -1092,22 +1100,22 @@ test_gnc_account_insert_remove_split (Fixture *fixture, gconstpointer pData)
 #else
 #define _func "gnc_account_insert_split"
 #endif
-    gchar *msg1 = _func ": assertion " _Q "GNC_IS_ACCOUNT(acc)' failed";
-    gchar *msg2 = _func ": assertion " _Q "GNC_IS_SPLIT(s)' failed";
+    auto msg1 = _func ": assertion " _Q "GNC_IS_ACCOUNT(acc)' failed";
+    auto msg2 = _func ": assertion " _Q "GNC_IS_SPLIT(s)' failed";
 #undef _func
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-//    gchar *log_domain = "gnc.engine";
-    TestErrorStruct check1 = { loglevel, "gnc.engine", msg1, 0 };
-    TestErrorStruct check2 = { loglevel, "gnc.engine", msg2, 0 };
-    TestErrorStruct check3 = { loglevel, "gnc.engine", NULL, 0 };
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+//    auto log_domain = "gnc.engine";
+    auto check1 = test_error_struct_new("gnc.engine", loglevel, msg1);
+    auto check2 = test_error_struct_new("gnc.engine", loglevel, msg2);
+    auto check3 = test_error_struct_new("gnc.engine", loglevel, NULL);
     guint logger;
     sig1 = test_signal_new (&fixture->acct->inst, QOF_EVENT_MODIFY, NULL);
     sig2 = test_signal_new (&fixture->acct->inst, GNC_EVENT_ITEM_ADDED, split1);
 
-    test_add_error (&check1);
-    test_add_error (&check2);
+    test_add_error (check1);
+    test_add_error (check2);
     logger = g_log_set_handler ("gnc.engine", loglevel,
-                                (GLogFunc)test_null_handler, &check3);
+                                (GLogFunc)test_null_handler, check3);
     g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_list_handler, NULL);
 
     /* Check that the call fails with invalid account and split (throws) */
@@ -1129,9 +1137,9 @@ test_gnc_account_insert_remove_split (Fixture *fixture, gconstpointer pData)
     /* g_assert (!priv->balance_dirty); */
     /* test_signal_assert_hits (sig1, 0); */
     /* test_signal_assert_hits (sig2, 0); */
-    g_assert_cmpint (check1.hits, ==, 1);
-    g_assert_cmpint (check2.hits, ==, 1);
-    g_assert_cmpint (check3.hits, ==, 0);
+    g_assert_cmpint (check1->hits, ==, 1);
+    g_assert_cmpint (check2->hits, ==, 1);
+    g_assert_cmpint (check3->hits, ==, 0);
     g_log_remove_handler ("gnc.engine", logger);
     test_clear_error_list ();
 
@@ -1321,10 +1329,9 @@ test_xaccAccountRecomputeBalance (Fixture *fixture, gconstpointer pData)
                 clr_bal = gnc_numeric_zero ();
     SetupData *sdata = (SetupData*)pData;
     TxnParms* t_arr;
-    int ind;
     g_assert (sdata != NULL);
     t_arr = (TxnParms*)sdata->txns;
-    for (ind = 0; ind < sdata->num_txns; ind++)
+    for (unsigned int ind = 0; ind < sdata->num_txns; ind++)
     {
         SplitParms p = t_arr[ind].splits[1];
         bal = gnc_numeric_add_fixed (bal, p.amount);
@@ -1474,12 +1481,14 @@ test_gnc_account_append_remove_child (Fixture *fixture, gconstpointer pData)
     QofBook *fbook = qof_book_new ();
     Account *froot = gnc_account_create_root (fbook);
     Account *account = xaccMallocAccount (fbook);
-    gchar *logdomain = "gnc.account";
-    gchar *msg1 = "[gnc_account_append_child()] reparenting accounts across books is not correctly supported\n";
-    gchar *msg2 = "[gnc_account_remove_child()] account not a child of parent";
+    auto logdomain = "gnc.account";
+    auto msg1 = "[gnc_account_append_child()] reparenting accounts across books is not correctly supported\n";
+    auto msg2 = "[gnc_account_remove_child()] account not a child of parent";
     guint log_handler = 0;
-    TestErrorStruct check_warn = {G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL, "gnc.account", msg1, 0 };
-    TestErrorStruct check_err = {G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL, "gnc.account", msg2, 0 };
+    auto loglevelc = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto loglevelw = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
+    auto check_warn = test_error_struct_new("gnc.account", loglevelw, msg1);
+    auto check_err = test_error_struct_new("gnc.account", loglevelc, msg2);
     TestSignal sig1, sig2, sig3;
     AccountTestFunctions *func = _utest_account_fill_functions ();
     AccountPrivate *frpriv = func->get_private (froot),
@@ -1494,25 +1503,29 @@ test_gnc_account_append_remove_child (Fixture *fixture, gconstpointer pData)
     test_signal_assert_hits (sig1, 1);
     test_signal_assert_hits (sig2, 0);
     test_signal_assert_hits (sig3, 0);
-    g_assert_cmpint (check_warn.hits, ==, 0);
-    g_assert_cmpint (check_err.hits, ==, 0);
+    g_assert_cmpint (check_warn->hits, ==, 0);
+    g_assert_cmpint (check_err->hits, ==, 0);
     g_assert (qof_instance_get_dirty (QOF_INSTANCE (froot)));
     g_assert (qof_instance_get_dirty (QOF_INSTANCE (account)));
     g_assert (g_list_find (frpriv->children, account));
     g_assert (qof_collection_lookup_entity (
                   qof_book_get_collection (fbook, GNC_ID_ACCOUNT),
                   acct_guid));
-    log_handler = g_log_set_handler (logdomain, G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, (GLogFunc)test_null_handler, &check_warn);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check_warn);
+    auto loglevelr = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING |
+                                                 G_LOG_FLAG_FATAL |
+                                                 G_LOG_FLAG_RECURSION);
+    log_handler = g_log_set_handler (logdomain, loglevelr,
+                                     (GLogFunc)test_null_handler, check_warn);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check_warn);
     gnc_account_append_child (fixture->acct, account);
     g_log_remove_handler (logdomain, log_handler);
-    g_assert_cmpstr (msg1, == , check_warn.msg);
+    g_assert_cmpstr (msg1, == , check_warn->msg);
     g_assert (gnc_account_get_parent (account) == fixture->acct);
     test_signal_assert_hits (sig1, 2);
     test_signal_assert_hits (sig2, 1);
     test_signal_assert_hits (sig3, 1);
-    g_assert_cmpint (check_warn.hits, ==, 1);
-    g_assert_cmpint (check_err.hits, ==, 0);
+    g_assert_cmpint (check_warn->hits, ==, 1);
+    g_assert_cmpint (check_err->hits, ==, 0);
     g_assert (!qof_collection_lookup_entity (
                   qof_book_get_collection (fbook, GNC_ID_ACCOUNT),
                   acct_guid));
@@ -1528,24 +1541,24 @@ test_gnc_account_append_remove_child (Fixture *fixture, gconstpointer pData)
     test_signal_free (sig3);
     sig1 = test_signal_new (&account->inst, QOF_EVENT_REMOVE, NULL);
     sig2 = test_signal_new (&(fixture->acct)->inst, QOF_EVENT_MODIFY, NULL);
-    log_handler = g_log_set_handler (logdomain, G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL,
-                                     (GLogFunc)test_null_handler, &check_err);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check_err);
+    log_handler = g_log_set_handler (logdomain, loglevelc,
+                                     (GLogFunc)test_null_handler, check_err);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check_err);
     gnc_account_remove_child (froot, account);
     g_log_remove_handler (logdomain, log_handler);
 
     test_signal_assert_hits (sig1, 0);
     test_signal_assert_hits (sig2, 0);
-    g_assert_cmpint (check_err.hits, ==, 1);
-    g_assert_cmpint (check_warn.hits, ==, 1);
+    g_assert_cmpint (check_err->hits, ==, 1);
+    g_assert_cmpint (check_warn->hits, ==, 1);
 
     gnc_account_remove_child (fixture->acct, account);
     g_assert (gnc_account_get_parent (account) == NULL);
     g_assert (g_list_find (apriv->children, account) == NULL);
     test_signal_assert_hits (sig1, 1);
     test_signal_assert_hits (sig2, 1);
-    g_assert_cmpint (check_warn.hits, ==, 1);
-    g_assert_cmpint (check_err.hits, ==, 1);
+    g_assert_cmpint (check_warn->hits, ==, 1);
+    g_assert_cmpint (check_err->hits, ==, 1);
     test_signal_free (sig1);
     test_signal_free (sig2);
     xaccAccountBeginEdit (account);
@@ -1706,23 +1719,23 @@ test_gnc_account_lookup_by_full_name_helper ( Fixture *fixture,
         gconstpointer pData )
 {
     Account *root, *target;
-    gchar *names1[] = {"income", "taxable", "int", NULL};
-    gchar *names2[] =  {"income", "exempt", "int", NULL};
-    gchar *names3[] = {"expense", "taxable", "int", NULL};
-    gchar *code;
+    const char *names1[] = {"income", "taxable", "int", NULL};
+    const char *names2[] =  {"income", "exempt", "int", NULL};
+    const char *names3[] = {"expense", "taxable", "int", NULL};
+    char *code;
     AccountTestFunctions *func = _utest_account_fill_functions ();
 
     root = gnc_account_get_root (fixture->acct);
-    target = func->gnc_account_lookup_by_full_name_helper (root, names1);
+    target = func->gnc_account_lookup_by_full_name_helper (root, const_cast<char**>(names1));
     g_assert (target != NULL);
     g_object_get (target, "code", &code, NULL);
     g_assert_cmpstr (code, == , "4160");
     g_free (code);
-    target = func->gnc_account_lookup_by_full_name_helper (root, names2);
+    target = func->gnc_account_lookup_by_full_name_helper (root, const_cast<char**>(names2));
     g_assert (target != NULL);
     g_object_get (target, "code", &code, NULL);
     g_assert_cmpstr (code, == , "4210");
-    target = func->gnc_account_lookup_by_full_name_helper (root, names3);
+    target = func->gnc_account_lookup_by_full_name_helper (root, const_cast<char**>(names3));
     g_assert (target == NULL);
     g_free (code);
 }
@@ -1733,9 +1746,9 @@ static void
 test_gnc_account_lookup_by_full_name (Fixture *fixture, gconstpointer pData)
 {
     Account *root, *target;
-    gchar *names1 = "income:taxable:int";
-    gchar *names2 =  "income:exempt:int";
-    gchar *names3 = "expense:taxable:int";
+    auto names1 = "income:taxable:int";
+    auto names2 =  "income:exempt:int";
+    auto names3 = "expense:taxable:int";
     gchar *code;
 
     root = gnc_account_get_root (fixture->acct);
@@ -1831,13 +1844,12 @@ test_gnc_account_foreach_descendant_until (Fixture *fixture, gconstpointer pData
     Account *first = gnc_account_lookup_by_code (root, "2000");
     Account *second = gnc_account_lookup_by_code (root, "4000");
     Account *expected = gnc_account_lookup_by_code (root, "4160");
-    Account *result;
-    guint counter = 0;
-    result = gnc_account_foreach_descendant_until (first, thunk2, &counter);
+    unsigned int counter = 0;
+    auto result = static_cast<Account*>(gnc_account_foreach_descendant_until (first, thunk2, &counter));
     g_assert_cmpint (counter, == , 11);
     g_assert (result == NULL);
     counter = 0;
-    result = gnc_account_foreach_descendant_until (second, thunk2, &counter);
+    result = static_cast<Account*>(gnc_account_foreach_descendant_until (second, thunk2, &counter));
     g_assert (result == expected);
     g_assert_cmpint (counter, == , 6);
 }
@@ -2051,7 +2063,7 @@ test_xaccAccountFindOpenLots (Fixture *fixture, gconstpointer pData)
 static gpointer
 bogus_for_each_lot_func (GNCLot *lot, gpointer data)
 {
-    guint *count = data;
+    auto count = static_cast<unsigned int *>(data);
     ++*count;
     return (*count > 4 ? lot : NULL);
 }
@@ -2108,6 +2120,14 @@ test_xaccAccountHasAncestor (Fixture *fixture, gconstpointer pData)
     g_assert (!xaccAccountHasAncestor (ltcg, expense));
 
 }
+inline GNCAccountType& operator++(GNCAccountType& x)
+{
+    using AcctTypeType = std::underlying_type<GNCAccountType>;
+    if (x < ACCT_TYPE_LAST)
+        x = static_cast<GNCAccountType>(x + 1);
+    return x;
+}
+
 /* xaccAccountTypeEnumAsString
  * xaccAccountStringToType
  * xaccAccountStringToEnum
@@ -2118,19 +2138,19 @@ xaccAccountTypeEnumAsString (GNCAccountType type)// C: 5 in 3 */
 static void
 test_xaccAccountType_Stuff (void)
 {
-    GNCAccountType  type;
-    gint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    gchar *logdomain = "gnc.account";
-    gchar *msg1 = g_strdup_printf ("[xaccAccountTypeEnumAsString()] asked to translate unknown account type %d.\n", ACCT_TYPE_LAST);
-    gchar *msg2 = "[xaccAccountStringToType()] asked to translate unknown account type string (null).\n";
-    gchar *msg3 = "[xaccAccountStringToType()] asked to translate unknown account type string LAST.\n";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto logdomain = "gnc.account";
+    auto msg1 = g_strdup_printf ("[xaccAccountTypeEnumAsString()] asked to translate unknown account type %d.\n", ACCT_TYPE_LAST);
+    auto msg2 = "[xaccAccountStringToType()] asked to translate unknown account type string (null).\n";
+    auto msg3 = "[xaccAccountStringToType()] asked to translate unknown account type string LAST.\n";
     guint loghandler = 0;
-    TestErrorStruct check1 = { loglevel, logdomain, msg1, 0 };
-    TestErrorStruct check2 = { loglevel, logdomain, msg2, 0 };
-    TestErrorStruct check3 = { loglevel, logdomain, msg3, 0 };
-    Account *acc = g_object_new (GNC_TYPE_ACCOUNT, NULL);
+    auto check1 = test_error_struct_new(logdomain, loglevel, msg1);
+    auto check2 = test_error_struct_new(logdomain, loglevel, msg2);
+    auto check3 = test_error_struct_new(logdomain, loglevel, msg3);
+    auto acc = static_cast<Account*>(g_object_new (GNC_TYPE_ACCOUNT, NULL));
+    GNCAccountType type;
 
-    for (type = ACCT_TYPE_NONE; type < ACCT_TYPE_LAST; type = type + 1)
+    for (type = ACCT_TYPE_NONE; type < ACCT_TYPE_LAST; ++type)
     {
         const gchar *type_name = xaccAccountTypeEnumAsString (type);
         const gchar *typestr;
@@ -2145,19 +2165,19 @@ test_xaccAccountType_Stuff (void)
         typestr_uc = g_ascii_strup (typestr, strlen (typestr));
         if (type == ACCT_TYPE_PAYABLE || type == ACCT_TYPE_RECEIVABLE)
         {
-            gchar *cmpstr = g_strconcat ("A/", type_name, NULL);
+            auto cmpstr = g_strconcat ("A/", type_name, NULL);
             g_assert_cmpstr (typestr_uc, == , cmpstr);
             g_free (cmpstr);
         }
         else if (type == ACCT_TYPE_CREDIT)
         {
-            gchar *cmpstr = g_strconcat (type_name, " CARD", NULL);
+            auto cmpstr = g_strconcat (type_name, " CARD", NULL);
             g_assert_cmpstr (typestr_uc, == , cmpstr);
             g_free (cmpstr);
         }
         else if (type == ACCT_TYPE_MUTUAL)
         {
-            gchar *cmpstr = g_strconcat (type_name, " FUND", NULL);
+            auto cmpstr = g_strconcat (type_name, " FUND", NULL);
             g_assert_cmpstr (typestr_uc, == , cmpstr);
             g_free (cmpstr);
         }
@@ -2178,25 +2198,25 @@ test_xaccAccountType_Stuff (void)
     g_object_unref (acc);
 
     loghandler = g_log_set_handler (logdomain, loglevel,
-                                    (GLogFunc)test_null_handler, &check1);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check1);
+                                    (GLogFunc)test_null_handler, check1);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check1);
     g_assert (!xaccAccountTypeEnumAsString (ACCT_TYPE_LAST));
-    g_assert_cmpint (check1.hits, ==, 1);
+    g_assert_cmpint (check1->hits, ==, 1);
 
     g_log_remove_handler (logdomain, loghandler);
     g_free (msg1);
     loghandler = g_log_set_handler (logdomain, loglevel,
-                                    (GLogFunc)test_null_handler, &check2);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check2);
+                                    (GLogFunc)test_null_handler, check2);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check2);
     g_assert (!xaccAccountStringToType (NULL, &type));
-    g_assert_cmpint (check2.hits, ==, 1);
+    g_assert_cmpint (check2->hits, ==, 1);
 
     g_log_remove_handler (logdomain, loghandler);
     loghandler = g_log_set_handler (logdomain, loglevel,
-                                    (GLogFunc)test_null_handler, &check3);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check3);
+                                    (GLogFunc)test_null_handler, check3);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check3);
     g_assert (!xaccAccountStringToType ("LAST", &type));
-    g_assert_cmpint (check3.hits, ==, 1);
+    g_assert_cmpint (check3->hits, ==, 1);
 
     g_log_remove_handler (logdomain, loghandler);
 
@@ -2227,27 +2247,27 @@ test_xaccAccountType_Compatibility (void)
     guint32 trading_compat = ((1 << ACCT_TYPE_TRADING) | (1 << ACCT_TYPE_ROOT));
     guint32 compat;
     GNCAccountType  type;
-    gchar *msg1 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_ROOT);
-    gchar *msg2 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_SAVINGS);
-    gchar *logdomain = "gnc.account";
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    TestErrorStruct check1 = { loglevel, logdomain, msg1, 0 };
-    TestErrorStruct check2 = { loglevel, logdomain, msg2, 0 };
+    auto msg1 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_ROOT);
+    auto msg2 = g_strdup_printf ("[xaccParentAccountTypesCompatibleWith()] bad account type: %d", ACCT_TYPE_SAVINGS);
+    auto logdomain = "gnc.account";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check1 = test_error_struct_new(logdomain, loglevel, msg1);
+    auto check2 = test_error_struct_new(logdomain, loglevel, msg2);
     gint loghandler;
 
-    for (type = ACCT_TYPE_BANK; type < NUM_ACCOUNT_TYPES; type = type + 1)
+    for (type = ACCT_TYPE_BANK; type < NUM_ACCOUNT_TYPES; type = ++type)
     {
         GNCAccountType child;
         if (type == ACCT_TYPE_ROOT)
         {
             loghandler = g_log_set_handler (logdomain, loglevel,
-                                            (GLogFunc)test_null_handler, &check1);
+                                            (GLogFunc)test_null_handler, check1);
             g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler,
-                                          &check1);
+                                          check1);
             compat = xaccParentAccountTypesCompatibleWith (type);
             g_log_remove_handler (logdomain, loghandler);
             g_assert_cmpint (compat, == , 0);
-            g_assert_cmpint (check1.hits, ==, 1);
+            g_assert_cmpint (check1->hits, ==, 1);
             g_free (msg1);
             continue;
         }
@@ -2262,7 +2282,7 @@ test_xaccAccountType_Compatibility (void)
             g_assert_cmpint (compat, == , equity_compat);
         else if (type == ACCT_TYPE_TRADING)
             g_assert_cmpint (compat, == , trading_compat);
-        for (child = ACCT_TYPE_NONE; child < ACCT_TYPE_LAST; child = child + 1)
+        for (child = ACCT_TYPE_NONE; child < ACCT_TYPE_LAST; child = ++child)
             if (1 << child & compat)
                 g_assert (xaccAccountTypesCompatible (type, child));
             else
@@ -2270,12 +2290,12 @@ test_xaccAccountType_Compatibility (void)
     }
 
     loghandler = g_log_set_handler (logdomain, loglevel,
-                                    (GLogFunc)test_null_handler, &check2);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check2);
-    compat = xaccParentAccountTypesCompatibleWith (type = type + 1);
+                                    (GLogFunc)test_null_handler, check2);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check2);
+    compat = xaccParentAccountTypesCompatibleWith (++type);
     g_log_remove_handler (logdomain, loghandler);
     g_assert_cmpint (compat, == , 0);
-    g_assert_cmpint (check2.hits, ==, 1);
+    g_assert_cmpint (check2->hits, ==, 1);
     g_free (msg2);
 }
 /* More KVP getters & setters
@@ -2379,13 +2399,13 @@ test_gnc_account_merge_children (Fixture *fixture, gconstpointer pData)
     gfloat baz_balance = gnc_numeric_to_double (xaccAccountGetBalance (baz));
     gfloat baz2_balance = gnc_numeric_to_double (xaccAccountGetBalance (baz2));
     TestSignal sig1, sig2, sig3;
-    gchar *logdomain = "gnc.engine";
-    gint loglevel =  G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    gchar *msg = "[xaccSplitCommitEdit ()] Account grabbed split prematurely.";
-    TestErrorStruct check = { loglevel, logdomain, msg, 0 };
+    auto logdomain = "gnc.engine";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto msg = "[xaccSplitCommitEdit ()] Account grabbed split prematurely.";
+    auto check = test_error_struct_new(logdomain, loglevel, msg);
     guint hdlr = g_log_set_handler (logdomain, loglevel,
-    			   (GLogFunc)test_null_handler, &check);
-    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, &check);
+    			   (GLogFunc)test_null_handler, check);
+    g_test_log_set_fatal_handler ((GTestLogFatalFunc)test_checked_handler, check);
 
     sig1 = test_signal_new (QOF_INSTANCE (baz), QOF_EVENT_MODIFY, NULL);
     sig2 = test_signal_new (QOF_INSTANCE (baz2), QOF_EVENT_MODIFY, NULL);
@@ -2480,10 +2500,11 @@ test_xaccAccountTreeForEachTransaction (Fixture *fixture, gconstpointer pData )
     g_assert_cmpint (td.count, == , 9);
     g_assert_cmpint (result, == , 0);
     td.count = 0;
-    td.name = "pepper";
+    td.name = g_strdup("pepper");
     result = xaccAccountTreeForEachTransaction (root, thunk3, &td);
     g_assert_cmpint (td.count, == , result);
     g_assert_cmpint (result, < , 9);
+    g_free(td.name);
 }
 /* xaccAccountForEachTransaction
 gint
@@ -2502,10 +2523,11 @@ test_xaccAccountForEachTransaction (Fixture *fixture, gconstpointer pData )
     g_assert_cmpint (td.count, == , 9);
     g_assert_cmpint (result, == , 0);
     td.count = 0;
-    td.name = "pepper";
+    td.name = g_strdup("pepper");
     result = xaccAccountForEachTransaction (money, thunk3, &td);
     g_assert_cmpint (td.count, == , result);
     g_assert_cmpint (result, < , 9);
+    g_free(td.name);
 }
 
 
diff --git a/src/engine/test/utest-Split.cpp b/src/engine/test/utest-Split.cpp
index 5612990..d692b6a 100644
--- a/src/engine/test/utest-Split.cpp
+++ b/src/engine/test/utest-Split.cpp
@@ -21,11 +21,8 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  ********************************************************************/
-#ifdef __cplusplus
 extern "C"
 {
-#endif
-
 #include "config.h"
 #include <string.h>
 #include <glib.h>
@@ -38,7 +35,6 @@ extern "C"
 #include <TransactionP.h>
 #include <gnc-lot.h>
 #include <gnc-event.h>
-#include <kvp_frame.h>
 #include <qofinstance-p.h>
 
 #ifdef HAVE_GLIB_2_38
@@ -52,10 +48,9 @@ extern "C"
 
 static const gchar *suitename = "/engine/Split";
 void test_suite_split ( void );
-
-#ifdef __cplusplus
 }
-#endif
+
+#include <kvp_frame.hpp>
 
 typedef struct
 {
@@ -308,7 +303,7 @@ test_xaccDupeSplit (Fixture *fixture, gconstpointer pData)
     g_assert (split->lot == f_split->lot);
     g_assert_cmpstr (split->memo, ==, f_split->memo);
     g_assert_cmpstr (split->action, ==, f_split->action);
-    g_assert (kvp_frame_compare (split->inst.kvp_data, f_split->inst.kvp_data) == 0);
+    g_assert (compare (split->inst.kvp_data, f_split->inst.kvp_data) == 0);
     g_assert_cmpint (split->reconciled, ==, f_split->reconciled);
     g_assert (timespec_equal (&(split->date_reconciled), &(f_split->date_reconciled)));
     g_assert (gnc_numeric_equal (split->value, f_split->value));
@@ -343,7 +338,7 @@ test_xaccSplitCloneNoKvp (Fixture *fixture, gconstpointer pData)
     g_assert (split->lot == f_split->lot);
     g_assert_cmpstr (split->memo, ==, f_split->memo);
     g_assert_cmpstr (split->action, ==, f_split->action);
-    g_assert (kvp_frame_is_empty (split->inst.kvp_data));
+    g_assert (split->inst.kvp_data->empty());
     g_assert_cmpint (split->reconciled, ==, f_split->reconciled);
     g_assert (timespec_equal (&(split->date_reconciled), &(f_split->date_reconciled)));
     g_assert (gnc_numeric_equal (split->value, f_split->value));
@@ -743,12 +738,12 @@ test_xaccSplitDetermineGainStatus (Fixture *fixture, gconstpointer pData)
 
     fixture->split->gains = GAINS_STATUS_UNKNOWN;
     fixture->split->gains_split = NULL;
-    g_assert (kvp_frame_get_slot (fixture->split->inst.kvp_data, "gains_source") == NULL);
+    g_assert (fixture->split->inst.kvp_data->get_slot("gains_source") == NULL);
     xaccSplitDetermineGainStatus (fixture->split);
     g_assert (fixture->split->gains_split == NULL);
     g_assert_cmpint (fixture->split->gains, ==, GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY);
 
-    kvp_frame_set_guid (fixture->split->inst.kvp_data, "gains-source", g_guid);
+    fixture->split->inst.kvp_data->set("gains-source", new KvpValue(const_cast<GncGUID*>(g_guid)));
     g_assert (fixture->split->gains_split == NULL);
     fixture->split->gains = GAINS_STATUS_UNKNOWN;
     xaccSplitDetermineGainStatus (fixture->split);
@@ -1778,13 +1773,13 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
     Split *split1 = xaccMallocSplit (book);
     Split *split2 = xaccMallocSplit (book);
     Account *acc2 = xaccMallocAccount (book);
-    KvpValue *kvpnow = kvp_value_new_gint64 (gnc_time (NULL));
+    KvpValue *kvpnow = new KvpValue (gnc_time (NULL));
 
     g_assert (xaccSplitGetOtherSplit (NULL) == NULL);
     g_assert (xaccSplitGetOtherSplit (split1) == NULL);
 
     g_assert (xaccTransUseTradingAccounts (txn) == FALSE);
-    g_assert (kvp_frame_get_slot (split->inst.kvp_data, "lot-split") == NULL);
+    g_assert (split->inst.kvp_data->get_slot("lot-split") == NULL);
     g_assert_cmpint (xaccTransCountSplits (txn), !=, 2);
     g_assert (xaccSplitGetOtherSplit (split) == NULL);
 
@@ -1795,18 +1790,18 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
     xaccSplitSetParent (split2, txn);
     g_assert (xaccSplitGetOtherSplit (split) == NULL);
 
-    kvp_frame_set_slot (split->inst.kvp_data, "lot-split", kvpnow);
-    g_assert (kvp_frame_get_slot (split->inst.kvp_data, "lot-split"));
+    split->inst.kvp_data->set("lot-split", kvpnow);
+    g_assert (split->inst.kvp_data->get_slot("lot-split"));
     g_assert (xaccSplitGetOtherSplit (split) == NULL);
 
-    kvp_frame_set_slot (split1->inst.kvp_data, "lot-split", kvpnow);
-    g_assert (kvp_frame_get_slot (split1->inst.kvp_data, "lot-split"));
+    split1->inst.kvp_data->set("lot-split", kvpnow);
+    g_assert (split1->inst.kvp_data->get_slot("lot-split"));
     g_assert (xaccSplitGetOtherSplit (split) == split2);
 
-    kvp_frame_set_slot (split->inst.kvp_data, "lot-split", NULL);
-    g_assert (kvp_frame_get_slot (split->inst.kvp_data, "lot-split") == NULL);
-    kvp_frame_set_slot (split1->inst.kvp_data, "lot-split", NULL);
-    g_assert (kvp_frame_get_slot (split1->inst.kvp_data, "lot-split") == NULL);
+    split->inst.kvp_data->set("lot-split", NULL);
+    g_assert (split->inst.kvp_data->get_slot("lot-split") == NULL);
+    split1->inst.kvp_data->set("lot-split", NULL);
+    g_assert (split1->inst.kvp_data->get_slot("lot-split") == NULL);
     qof_book_begin_edit (book);
     qof_instance_set (QOF_INSTANCE (book),
 		      "trading-accts", "t",
diff --git a/src/engine/test/utest-Transaction.c b/src/engine/test/utest-Transaction.cpp
similarity index 85%
rename from src/engine/test/utest-Transaction.c
rename to src/engine/test/utest-Transaction.cpp
index ec5d6d3..a07270b 100644
--- a/src/engine/test/utest-Transaction.c
+++ b/src/engine/test/utest-Transaction.cpp
@@ -21,6 +21,8 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  ********************************************************************/
+extern "C"
+{
 #include <config.h>
 #include <string.h>
 #include <glib.h>
@@ -33,7 +35,6 @@
 #include "../gnc-lot.h"
 #include "../gnc-event.h"
 #include <qof.h>
-#include <kvp_frame.h>
 #include <qofbackend-p.h>
 
 #ifdef HAVE_GLIB_2_38
@@ -47,6 +48,9 @@
 
 static const gchar *suitename = "/engine/Transaction";
 void test_suite_transaction ( void );
+}
+
+#include <kvp_frame.hpp>
 
 /* Copied from Transaction.c. Changing these values will break
  * existing databases, which is a good reason to fail a test.
@@ -117,15 +121,14 @@ setup (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_book_new ();
     MockBackend *mbe = mock_backend_new ();
-    Split *split1 = NULL, *split2 = NULL;
     Transaction *txn;
     Timespec entered = gnc_dmy2timespec (20, 4, 2012);
     Timespec posted = gnc_dmy2timespec (21, 4, 2012);
-    KvpFrame *frame = kvp_frame_new ();
+    auto frame = new KvpFrame ();
 
     qof_book_set_backend (book, (QofBackend*)mbe);
-    split1 = xaccMallocSplit (book);
-    split2 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
+    auto split2 = xaccMallocSplit (book);
     txn = xaccMallocTransaction (book);
     fixture->txn = txn;
     fixture->curr = gnc_commodity_new (book, "Gnu Rand", "CURRENCY", "GNR", "", 240);
@@ -138,23 +141,23 @@ setup (Fixture *fixture, gconstpointer pData)
     txn->date_posted.tv_nsec = posted.tv_nsec;
     txn->date_entered.tv_sec = entered.tv_sec;
     txn->date_entered.tv_nsec = entered.tv_nsec;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (100000, 1000);
     split1->value = gnc_numeric_create (3200, 240);
     split2->amount = gnc_numeric_create (-3200, 240);
     split2->value = gnc_numeric_create (-3200, 240);
     split1->acc = fixture->acc1;
     split2->acc = fixture->acc2;
-    txn->num = CACHE_INSERT ("123");
-    txn->description = CACHE_INSERT ("Waldo Pepper");
+    txn->num = static_cast<char*>(CACHE_INSERT ("123"));
+    txn->description = static_cast<char*>(CACHE_INSERT ("Waldo Pepper"));
     xaccTransBeginEdit (txn);
     {
         xaccTransSetCurrency (txn, fixture->curr);
         xaccSplitSetParent (split1, txn);
         xaccSplitSetParent (split2, txn);
-        kvp_frame_set_string (frame, trans_notes_str, "Salt pork sausage");
-        kvp_frame_set_double (frame, "/qux/quux/corge", 123.456);
+        frame->set(trans_notes_str, new KvpValue("Salt pork sausage"));
+        frame->set_path("/qux/quux/corge", new KvpValue(123.456));
         qof_instance_set_slots (QOF_INSTANCE (txn), frame);
     }
     xaccTransCommitEdit (txn);
@@ -174,8 +177,6 @@ setup_with_gains (GainsFixture *fixture, gconstpointer pData)
 {
     QofBook *book;
     Fixture *base = &(fixture->base);
-    Split *gains_split1 = NULL, *gains_split2 = NULL;
-    Split *base_split = NULL;
 
     setup (base, NULL);
 
@@ -183,8 +184,8 @@ setup_with_gains (GainsFixture *fixture, gconstpointer pData)
     fixture->gains_txn = xaccMallocTransaction (book);
     fixture->gains_acc = xaccMallocAccount (book);
     xaccAccountSetCommodity (fixture->gains_acc, base->curr);
-    gains_split1 = xaccMallocSplit (book);
-    gains_split2 = xaccMallocSplit (book);
+    auto gains_split1 = xaccMallocSplit (book);
+    auto gains_split2 = xaccMallocSplit (book);
     gains_split1->acc = base->acc1;
     gains_split2->acc = fixture->gains_acc;
     gains_split1->amount = gnc_numeric_create (30, 240);
@@ -198,7 +199,7 @@ setup_with_gains (GainsFixture *fixture, gconstpointer pData)
         xaccSplitSetParent (gains_split2, fixture->gains_txn);
     }
     xaccTransCommitEdit (fixture->gains_txn);
-    base_split = g_list_nth_data (base->txn->splits, 1);
+    auto base_split = static_cast<Split*>(g_list_nth_data (base->txn->splits, 1));
     base_split->gains_split = gains_split1;
 }
 
@@ -237,10 +238,10 @@ void check_open (const Transaction *trans)// Local: 1:0:0
 static void
 test_check_open (Fixture *fixture, gconstpointer pData)
 {
-    gchar *msg = g_strdup_printf ("[check_open()] transaction %p not open for editing", fixture->txn);
-    GLogLevelFlags loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    TestErrorStruct *check = test_error_struct_new ("gnc.engine", loglevel,
-                             msg);
+    auto msg = g_strdup_printf ("[check_open()] transaction %p not open for editing", fixture->txn);
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL |
+                                                G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new ("gnc.engine", loglevel, msg);
     g_free (msg);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
                      (GLogFunc)test_checked_handler);
@@ -260,7 +261,7 @@ static void
 test_xaccTransStillHasSplit (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split = xaccMallocSplit (book);
+    auto split = xaccMallocSplit (book);
     g_assert (!xaccTransStillHasSplit (fixture->txn, split));
     xaccSplitSetParent (split, fixture->txn);
     g_assert (xaccTransStillHasSplit (fixture->txn, split));
@@ -280,7 +281,7 @@ void mark_trans (Transaction *trans)// Local: 3:0:0
 #define check_split_dirty(xsplit, test)                \
 {                                                      \
     gboolean sort_dirty, balance_dirty;                \
-    Split *split = xsplit;                             \
+    auto split = xsplit;                             \
     g_object_get (split->acc,                          \
 		  "sort-dirty", &sort_dirty,           \
 		  "balance-dirty", &balance_dirty,     \
@@ -299,7 +300,7 @@ test_mark_trans (Fixture *fixture, gconstpointer pData)
     {
         if (!splits->data) continue;
         g_assert (!qof_instance_get_dirty_flag (splits->data));
-        check_split_dirty (splits->data, FALSE);
+        check_split_dirty (static_cast<Split*>(splits->data), FALSE);
     }
     fixture->func->mark_trans (fixture->txn);
     g_assert (!qof_instance_get_dirty_flag (fixture->txn));
@@ -307,7 +308,7 @@ test_mark_trans (Fixture *fixture, gconstpointer pData)
     {
         if (!splits->data) continue;
         g_assert (!qof_instance_get_dirty_flag (splits->data));
-        check_split_dirty (splits->data, TRUE);
+        check_split_dirty (static_cast<Split*>(splits->data), TRUE);
     }
 }
 /* gen_event_trans
@@ -316,7 +317,7 @@ void gen_event_trans (Transaction *trans)// Local: 2:0:0
 static void
 test_gen_event_trans (Fixture *fixture, gconstpointer pData)
 {
-    Split *split = fixture->txn->splits->data;
+    auto split = static_cast<Split*>(fixture->txn->splits->data);
     GNCLot *lot = gnc_lot_new (qof_instance_get_book (QOF_INSTANCE (fixture->txn)));
     TestSignal sig1 = test_signal_new (QOF_INSTANCE (fixture->acc1),
                                        GNC_EVENT_ITEM_CHANGED, split);
@@ -340,7 +341,7 @@ gnc_transaction_init(Transaction* trans)*/
 static void
 test_gnc_transaction_init ()
 {
-    Transaction *txn = g_object_new (GNC_TYPE_TRANSACTION, NULL);
+    auto txn = static_cast<Transaction*>(g_object_new (GNC_TYPE_TRANSACTION, NULL));
     g_assert_cmpstr (txn->num, ==, "");
     g_assert_cmpstr (txn->description, ==, "");
     g_assert (txn->common_currency == NULL);
@@ -361,9 +362,9 @@ static void
 test_gnc_transaction_dispose ()
 {
     QofBook *book = qof_book_new ();
-    Transaction *txn = g_object_new (GNC_TYPE_TRANSACTION, "book", book, NULL);
-    Split *split = g_object_new (GNC_TYPE_SPLIT, "book", book, NULL);
-    Split *s_ref = split;
+    auto txn = static_cast<Transaction*>(g_object_new (GNC_TYPE_TRANSACTION, "book", book, NULL));
+    auto split = static_cast<Split*>(g_object_new (GNC_TYPE_SPLIT, "book", book, NULL));
+    auto s_ref = split;
     gnc_commodity *curr = gnc_commodity_new (book, "Gnu Rand", "CURRENCY",
                           "GNR", "", 240), *t_curr = NULL;
     gnc_commodity *c_ref = curr;
@@ -398,7 +399,7 @@ gnc_transaction_finalize(GObject* txnp)*/
 static void
 test_gnc_transaction_finalize ()
 {
-    Transaction *txn = g_object_new (GNC_TYPE_TRANSACTION, NULL);
+    auto txn = static_cast<Transaction*>(g_object_new (GNC_TYPE_TRANSACTION, NULL));
     test_destroy (txn);
 }
 /* gnc_transaction_get_property
@@ -409,21 +410,20 @@ static void
 test_gnc_transaction_set_get_property (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_book_new ();
-    Transaction *txn = g_object_new (GNC_TYPE_TRANSACTION, "book", book, NULL);
-    gchar *num = "42", *desc = "The Answer", *t_num = NULL, *t_desc = NULL, *phony = NULL;
+    auto txn = static_cast<Transaction*>(g_object_new (GNC_TYPE_TRANSACTION, "book", book, NULL));
+    auto num = "42", desc = "The Answer";
+    gchar *t_num = NULL, *t_desc = NULL, *phony = NULL;
     gnc_commodity *curr = gnc_commodity_new (book, "Gnu Rand", "CURRENCY",
                           "GNR", "", 240), *t_curr = NULL;
     Timespec now = timespec_now (), *t_entered = NULL, *t_posted = NULL;
     time_t secs = (time_t)now.tv_sec;
-    gchar *msg1 = "g_object_set_valist: object class " _Q "Transaction' has no property named " _Q "bogus'";
-    gchar *msg2 = g_strdup_printf ("[xaccTransSetDateInternal] addr=%p set date to %" G_GUINT64_FORMAT ".%09ld %s",
+    auto msg1 = "g_object_set_valist: object class " _Q "Transaction' has no property named " _Q "bogus'";
+    auto msg2 = g_strdup_printf ("[xaccTransSetDateInternal] addr=%p set date to %" G_GUINT64_FORMAT ".%09ld %s",
                                    txn, now.tv_sec, now.tv_nsec, ctime (&secs));
-    GLogLevelFlags loglevel1 = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
-    GLogLevelFlags loglevel2 = G_LOG_LEVEL_INFO;
-    TestErrorStruct *check1 = test_error_struct_new ("GLib-GObject",
-                              loglevel1, msg1);
-    TestErrorStruct *check2 = test_error_struct_new ("gnc.engine",
-                              loglevel2, msg2);
+    auto loglevel1 = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
+    auto loglevel2 =static_cast<GLogLevelFlags>(G_LOG_LEVEL_INFO);
+    auto check1 = test_error_struct_new ("GLib-GObject", loglevel1, msg1);
+    auto check2 = test_error_struct_new ("gnc.engine", loglevel2, msg2);
     g_free (msg2);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check1,
                      (GLogFunc)test_checked_handler);
@@ -494,12 +494,11 @@ test_xaccMallocTransaction (Fixture *fixture, gconstpointer pData)
 #else
 #define _func "xaccMallocTransaction"
 #endif
-    gchar *msg = _func ": assertion " _Q "book' failed";
+    auto msg = _func ": assertion " _Q "book' failed";
 #undef _func
-    gchar *logdomain = "gnc.engine";
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    TestErrorStruct *check = test_error_struct_new ("gnc.engine", loglevel,
-                             msg);
+    auto logdomain = "gnc.engine";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new ("gnc.engine", loglevel, msg);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
                      (GLogFunc)test_checked_handler);
     test_signal_assert_hits (sig1, 0);
@@ -526,8 +525,8 @@ test_xaccTransSortSplits (Fixture *fixture, gconstpointer pData)
 {
     Transaction *txn = fixture->txn;
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (txn));
-    Split *split1 = txn->splits->data;
-    Split *split2 = txn->splits->next->data;
+    auto split1 = static_cast<Split*>(txn->splits->data);
+    auto split2 = static_cast<Split*>(txn->splits->next->data);
     Split *split[3];
     guint i;
     GList *node;
@@ -587,8 +586,8 @@ test_dupe_trans (Fixture *fixture, gconstpointer pData)
 
     oldtxn->date_posted = posted;
     oldtxn->date_entered = entered;
-    kvp_frame_set_string (oldtxn->inst.kvp_data, "/foo/bar/baz",
-                          "The Great Waldo Pepper");
+    oldtxn->inst.kvp_data->set("/foo/bar/baz",
+                               new KvpValue("The Great Waldo Pepper"));
 
     newtxn = fixture->func->dupe_trans (oldtxn);
 
@@ -597,7 +596,8 @@ test_dupe_trans (Fixture *fixture, gconstpointer pData)
     for (newnode = newtxn->splits; newnode && oldnode;
             newnode = g_list_next (newnode))
     {
-        g_assert (xaccSplitEqual (newnode->data, oldnode->data,
+        g_assert (xaccSplitEqual (static_cast<Split*>(newnode->data),
+                                  static_cast<Split*>(oldnode->data),
                                   TRUE, FALSE, TRUE));
         oldnode = g_list_next (oldnode);
     }
@@ -613,7 +613,7 @@ test_dupe_trans (Fixture *fixture, gconstpointer pData)
     g_assert (guid_equal (qof_instance_get_guid (QOF_INSTANCE (newtxn)),
                           guid_null ()));
     g_assert (qof_instance_get_book (QOF_INSTANCE (newtxn)) == old_book);
-    g_assert (kvp_frame_compare (oldtxn->inst.kvp_data, newtxn->inst.kvp_data) == 0);
+    g_assert (compare (oldtxn->inst.kvp_data, newtxn->inst.kvp_data) == 0);
 
     test_destroy (newtxn);
 }
@@ -648,7 +648,8 @@ test_xaccTransClone (Fixture *fixture, gconstpointer pData)
     for (newnode = newtxn->splits; newnode && oldnode;
             newnode = g_list_next (newnode))
     {
-        g_assert (xaccSplitEqual (newnode->data, oldnode->data,
+        g_assert (xaccSplitEqual (static_cast<Split*>(newnode->data),
+                                  static_cast<Split*>(oldnode->data),
                                   FALSE, FALSE, FALSE));
         oldnode = g_list_next (oldnode);
     }
@@ -664,7 +665,7 @@ test_xaccTransClone (Fixture *fixture, gconstpointer pData)
     g_assert (newtxn->common_currency == fixture->curr);
 
     g_assert (qof_instance_get_book (QOF_INSTANCE (newtxn)) == old_book);
-    g_assert (kvp_frame_compare (oldtxn->inst.kvp_data, newtxn->inst.kvp_data) == 0);
+    g_assert (compare (oldtxn->inst.kvp_data, newtxn->inst.kvp_data) == 0);
 
     test_destroy (newtxn);
 }
@@ -690,7 +691,7 @@ test_xaccTransCopyFromClipBoard (Fixture *fixture, gconstpointer pData)
     Transaction *to_txn = xaccMallocTransaction (book);
     Timespec now = timespec_now();
     Timespec never = {0, 0};
-    KvpFrame *to_frame = to_txn->inst.kvp_data;
+    auto to_frame = to_txn->inst.kvp_data;
 
     xaccAccountSetCommodity (acc1, fixture->comm);
     xaccTransCopyFromClipBoard (txn, to_txn, fixture->acc1, acc1, FALSE);
@@ -743,13 +744,14 @@ test_xaccFreeTransaction (Fixture *fixture, gconstpointer pData)
 {
     Transaction *txn = fixture->txn;
     Transaction *orig = xaccMallocTransaction (qof_instance_get_book (QOF_INSTANCE (txn)));
-    Split *split = txn->splits->data;
-    gchar *txn_num = "321";
-    g_object_add_weak_pointer (G_OBJECT (txn->splits->data), (gpointer)&split);
+    auto split = static_cast<Split*>(txn->splits->data);
+    auto txn_num = "321";
+    g_object_add_weak_pointer (G_OBJECT (txn->splits->data),
+                               reinterpret_cast<void**>(&split));
     /* so the "free" doesn't, leaving the structure for us to test */
     g_object_ref (txn);
     g_object_ref (orig);
-    orig->num = CACHE_INSERT (txn_num);
+    orig->num = static_cast<char*>(CACHE_INSERT (txn_num));
     txn->orig = orig;
 
     fixture->func->xaccFreeTransaction (txn);
@@ -791,21 +793,20 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
     Transaction *txn1 = xaccTransClone (txn0);
     const GncGUID *guid_f_txn = qof_instance_get_guid (txn0);
     gchar entered[DATE_BUF_SIZE], posted[DATE_BUF_SIZE];
-    gchar *msg1 = "[xaccTransEqual] one is NULL";
+    auto msg1 = "[xaccTransEqual] one is NULL";
     gchar *msg2 = NULL;
-    gchar *cleanup_fmt = "[trans_cleanup_commit] get rid of rollback trans=%p";
+    auto cleanup_fmt = "[trans_cleanup_commit] get rid of rollback trans=%p";
     gchar split_guid0[GUID_ENCODING_LENGTH + 1];
     gchar split_guid1[GUID_ENCODING_LENGTH + 1];
-    gchar *logdomain = "gnc.engine";
-    guint loglevel = G_LOG_LEVEL_INFO;
-    TestErrorStruct *check = test_error_struct_new (logdomain, loglevel, msg1);
-    TestErrorStruct check2 = {loglevel, logdomain, msg2, 0};
-    TestErrorStruct check3 = {loglevel, logdomain, "", 0};
-    TestErrorStruct *cleanup = test_error_struct_new (logdomain, loglevel, "");
-    Split *split0 = xaccTransGetSplit (txn0, 0);
-    Split *split1;
+    auto logdomain = "gnc.engine";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_INFO);
+    auto check = test_error_struct_new (logdomain, loglevel, msg1);
+    auto check2 = test_error_struct_new(logdomain, loglevel, msg2);
+    auto check3 = test_error_struct_new(logdomain, loglevel, "");
+    auto cleanup = test_error_struct_new (logdomain, loglevel, "");
+    auto split0 = xaccTransGetSplit (txn0, 0);
     test_add_error (check);
-    test_add_error (&check2);
+    test_add_error (check2);
     test_add_error (cleanup);
 
     fixture->hdlrs = test_log_set_handler (fixture->hdlrs, check,
@@ -869,7 +870,7 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
     xaccTransBeginEdit (clone);
     cleanup->msg = g_strdup_printf (cleanup_fmt, clone->orig);
     clone->date_entered.tv_sec = txn0->date_entered.tv_sec;
-    clone->num = "123";
+    clone->num = g_strdup("123");
     xaccTransCommitEdit (clone);
     g_free (cleanup->msg);
     g_free (check->msg);
@@ -879,15 +880,17 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
     g_assert (xaccTransEqual (txn1, clone, TRUE, FALSE, TRUE, TRUE));
     g_assert_cmpint (check->hits, ==, 5);
 
-    txn1->num = "321";
+    txn1->num = g_strdup("321");
     g_free (check->msg);
     check->msg = g_strdup ("[xaccTransEqual] num differs: 321 vs 123");
     g_assert (!xaccTransEqual (txn1, txn0, TRUE, FALSE, TRUE, TRUE));
     g_assert_cmpint (check->hits, ==, 6);
 
-    clone->num = CACHE_INSERT("123");
-    txn1->num = "123";
-    clone->description = "salt pork";
+    g_free(clone->num);
+    clone->num = static_cast<char*>(CACHE_INSERT("123"));
+    g_free(txn1->num);
+    txn1->num = g_strdup("123");
+    clone->description = g_strdup("salt pork");
     g_free (check->msg);
     check->msg = g_strdup ("[xaccTransEqual] descriptions differ: salt pork vs Waldo Pepper");
     g_assert (!xaccTransEqual (clone, txn0, TRUE, FALSE, TRUE, TRUE));
@@ -899,47 +902,47 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
 
     xaccTransBeginEdit (clone);
     cleanup->msg = g_strdup_printf (cleanup_fmt, clone->orig);
-    clone->description = CACHE_INSERT ("Waldo Pepper");
-    kvp_frame_set_double (qof_instance_get_slots (QOF_INSTANCE (clone)),
-                          "/qux/quux/corge", 654.321);
+    g_free(clone->description);
+    clone->description = static_cast<char*>(CACHE_INSERT ("Waldo Pepper"));
+    auto frame = qof_instance_get_slots (QOF_INSTANCE (clone));
+    frame->set("/qux/quux/corge", new KvpValue(654.321));
     xaccTransCommitEdit (clone);
     g_free (cleanup->msg);
     g_free (check->msg);
-    check->msg = g_strdup ("[xaccTransEqual] kvp frames differ:\n{\n    notes => KVP_VALUE_STRING(Salt pork sausage),\n    qux => KVP_VALUE_FRAME({\n    quux => KVP_VALUE_FRAME({\n    corge => KVP_VALUE_DOUBLE(654.321),\n}\n),\n}\n),\n}\n\n\nvs\n\n{\n    notes => KVP_VALUE_STRING(Salt pork sausage),\n    qux => KVP_VALUE_FRAME({\n    quux => KVP_VALUE_FRAME({\n    corge => KVP_VALUE_DOUBLE(123.456),\n}\n),\n}\n),\n}\n");
+    check->msg = g_strdup ("[xaccTransEqual] kvp frames differ:\n{\n     => KVP_VALUE_FRAME({\n    qux => KVP_VALUE_FRAME({\n    quux => KVP_VALUE_FRAME({\n    corge => KVP_VALUE_DOUBLE(654.321),\n}\n),\n}\n),\n}\n),\n    notes => KVP_VALUE_STRING(Salt pork sausage),\n}\n\n\nvs\n\n{\n     => KVP_VALUE_FRAME({\n    qux => KVP_VALUE_FRAME({\n    quux => KVP_VALUE_FRAME({\n    corge => KVP_VALUE_DOUBLE(123.456),\n}\n),\n}\n),\n}\n),\n    notes => KVP_VALUE_STRING(Salt pork sausage),\n}\n");
 
     g_assert (!xaccTransEqual (clone, txn0, TRUE, FALSE, TRUE, TRUE));
 
     g_assert_cmpint (check->hits, ==, 9);
     xaccTransBeginEdit (clone);
     cleanup->msg = g_strdup_printf (cleanup_fmt, clone->orig);
-    clone->description = CACHE_INSERT ("Waldo Pepper");
-    kvp_frame_set_double (qof_instance_get_slots (QOF_INSTANCE (clone)),
-                          "/qux/quux/corge", 123.456);
+    clone->description = static_cast<char*>(CACHE_INSERT ("Waldo Pepper"));
+    frame->set("/qux/quux/corge", new KvpValue(123.456));
     xaccTransCommitEdit (clone);
     g_free (cleanup->msg);
     g_free (check->msg);
     check->msg = g_strdup ("[xaccSplitEqual] GUIDs differ");
-    split1 = xaccTransGetSplit (clone, 0);
+    auto split1 = xaccTransGetSplit (clone, 0);
     guid_to_string_buff (qof_instance_get_guid (split0), split_guid0);
     guid_to_string_buff (qof_instance_get_guid (split1), split_guid1);
-    check2.msg = g_strdup_printf (
+    check2->msg = g_strdup_printf (
                      "[xaccTransEqual] splits %s and %s differ", split_guid1, split_guid0);
 
     g_assert (!xaccTransEqual (clone, txn0, TRUE, TRUE, TRUE, TRUE));
     g_assert (xaccTransEqual (clone, txn0, FALSE, FALSE, FALSE, TRUE));
     g_assert_cmpint (check->hits, ==, 10);
-    g_assert_cmpint (check2.hits, ==, 1);
+    g_assert_cmpint (check2->hits, ==, 1);
 
     g_free (check->msg);
-    g_free (check2.msg);
+    g_free (check2->msg);
     check->msg = g_strdup("[xaccSplitEqual] amounts differ: 13333/1000 vs 100000/1000");
-    check2.msg = g_strdup_printf (
+    check2->msg = g_strdup_printf (
                      "[xaccTransEqual] splits %s and %s differ", split_guid0, split_guid0);
     qof_instance_set_guid (split1, qof_instance_get_guid (split0));
     g_assert (!xaccTransEqual (clone, txn0, TRUE, TRUE, TRUE, TRUE));
     g_assert (xaccTransEqual (clone, txn0, TRUE, FALSE, FALSE, TRUE));
     g_assert_cmpint (check->hits, ==, 11);
-    g_assert_cmpint (check2.hits, ==, 2);
+    g_assert_cmpint (check2->hits, ==, 2);
 
     qof_instance_set_guid (xaccTransGetSplit (txn1, 0),
                            qof_instance_get_guid (split0));
@@ -951,26 +954,26 @@ test_xaccTransEqual (Fixture *fixture, gconstpointer pData)
         Split* split01 = xaccTransGetSplit (txn0, 1);
         Split* split10 = xaccTransGetSplit (txn1, 0);
         Split* split11 = xaccTransGetSplit (txn1, 1);
-        gchar *bal00 = gnc_numeric_to_string (split00->balance);
-        gchar *bal01 = gnc_numeric_to_string (split01->balance);
-        gchar *bal10 = gnc_numeric_to_string (split10->balance);
-        gchar *bal11 = gnc_numeric_to_string (split11->balance);
+        auto bal00 = gnc_numeric_to_string (split00->balance);
+        auto bal01 = gnc_numeric_to_string (split01->balance);
+        auto bal10 = gnc_numeric_to_string (split10->balance);
+        auto bal11 = gnc_numeric_to_string (split11->balance);
         check->msg = g_strdup_printf("[xaccSplitEqualCheckBal] balances differ: %s vs %s", bal10, bal00);
-        check3.msg = g_strdup_printf("[xaccSplitEqualCheckBal] balances differ: %s vs %s", bal11, bal01);
+        check3->msg = g_strdup_printf("[xaccSplitEqualCheckBal] balances differ: %s vs %s", bal11, bal01);
 
-        test_add_error (&check3);
+        test_add_error (check3);
         g_assert (!xaccTransEqual (txn1, txn0, TRUE, TRUE, TRUE, TRUE));
         g_assert (xaccTransEqual (txn1, txn0, TRUE, TRUE, FALSE, TRUE));
         g_assert_cmpint (check->hits, ==, 12);
-        g_assert_cmpint (check2.hits, ==, 3);
-        g_assert_cmpint (check3.hits, ==, 0);
+        g_assert_cmpint (check2->hits, ==, 3);
+        g_assert_cmpint (check3->hits, ==, 0);
 
         split10->balance = split00->balance;
         split11->balance = split01->balance;
         g_assert (xaccTransEqual (txn1, txn0, TRUE, TRUE, TRUE, TRUE));
     }
-    g_free (check3.msg);
-    g_free (check2.msg);
+    g_free (check3->msg);
+    g_free (check2->msg);
 }
 /* xaccTransUseTradingAccounts
 xaccTransUseTradingAccounts
@@ -999,12 +1002,12 @@ static void
 test_xaccTransGetImbalanceValue (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split1 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
     g_assert (gnc_numeric_equal (xaccTransGetImbalanceValue (fixture->txn),
                                  gnc_numeric_zero ()));
     split1->acc = fixture->acc1;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (100000, 1000);
     split1->value = gnc_numeric_create (3200, 240);
     xaccTransBeginEdit (fixture->txn);
@@ -1022,15 +1025,15 @@ static void
 test_xaccTransGetImbalance (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split1 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
     MonetaryList *mlist;
     g_assert (xaccTransGetImbalance (NULL) == NULL);
     mlist = xaccTransGetImbalance (fixture->txn);
     g_assert_cmpint (g_list_length (mlist), ==, 0);
 
     split1->acc = fixture->acc1;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (100000, 1000);
     split1->value = gnc_numeric_create (3200, 240);
     xaccTransBeginEdit (fixture->txn);
@@ -1046,8 +1049,8 @@ test_xaccTransGetImbalance_trading (Fixture *fixture,
                                     gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split1 = xaccMallocSplit (book);
-    Split *split2 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
+    auto split2 = xaccMallocSplit (book);
     Account *acc1 = xaccMallocAccount (book);
     Account *acc2 = xaccMallocAccount (book);
     gnc_numeric value;
@@ -1071,13 +1074,13 @@ test_xaccTransGetImbalance_trading (Fixture *fixture,
     g_assert (!xaccTransIsBalanced (fixture->txn));
     /* Make it look like a proper trading accounts transactionm */
     split1->acc = acc1;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (-10000, 100);
     split1->value = gnc_numeric_create (-3200, 240);
     split2->acc = acc2;
-    split2->memo = CACHE_INSERT ("foo");
-    split2->action = CACHE_INSERT ("bar");
+    split2->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split2->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split2->amount = gnc_numeric_create (3000, 240);
     split2->value = gnc_numeric_create (3200, 240);
     xaccTransBeginEdit (fixture->txn);
@@ -1114,13 +1117,13 @@ static void
 test_xaccTransIsBalanced (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split1 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
     g_assert (!xaccTransIsBalanced (NULL));
     g_assert (xaccTransIsBalanced (fixture->txn));
 
     split1->acc = fixture->acc1;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (100000, 1000);
     split1->value = gnc_numeric_create (3200, 240);
     xaccTransBeginEdit (fixture->txn);
@@ -1134,8 +1137,8 @@ static void
 test_xaccTransIsBalanced_trading (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split1 = xaccMallocSplit (book);
-    Split *split2 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
+    auto split2 = xaccMallocSplit (book);
     Account *acc1 = xaccMallocAccount (book);
     Account *acc2 = xaccMallocAccount (book);
 
@@ -1152,13 +1155,13 @@ test_xaccTransIsBalanced_trading (Fixture *fixture, gconstpointer pData)
     /* The setup transaction is unbalanced in a trading-accounts environment. */
     g_assert (!xaccTransIsBalanced (fixture->txn));
     split1->acc = acc1;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (3200, 240);
     split1->value = gnc_numeric_create (3200, 240);
     split2->acc = acc2;
-    split2->memo = CACHE_INSERT ("foo");
-    split2->action = CACHE_INSERT ("bar");
+    split2->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split2->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split2->amount = gnc_numeric_create (-10000, 100);
     split2->value = gnc_numeric_create (-3000, 240);
     xaccTransBeginEdit (fixture->txn);
@@ -1218,8 +1221,8 @@ test_xaccTransGetRateForCommodity (Fixture *fixture, gconstpointer pData)
 {
     gnc_numeric rate = gnc_numeric_zero ();
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *split0 = xaccMallocSplit (book);
-    Split *split1 = xaccTransFindSplitByAccount(fixture->txn, fixture->acc1);
+    auto split0 = xaccMallocSplit (book);
+    auto split1 = xaccTransFindSplitByAccount(fixture->txn, fixture->acc1);
     g_assert (!xaccTransGetRateForCommodity (NULL, fixture->comm,
               split0, &rate));
     g_assert (!xaccTransGetRateForCommodity (fixture->txn, NULL,
@@ -1246,11 +1249,10 @@ xaccTransGetAccountConvRate(const Transaction *txn, const Account *acc)// C: 5 i
 static void
 test_xaccTransGetAccountConvRate (Fixture *fixture, gconstpointer pData)
 {
-    gchar *msg1 = "[xaccTransGetAccountConvRate()] How can amount be nonzero and value be zero?";
-    guint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
-    TestErrorStruct *check = test_error_struct_new ("gnc.engine", loglevel,
-                             msg1);
-    Split *split1 = xaccTransFindSplitByAccount(fixture->txn, fixture->acc1);
+    auto msg1 = "[xaccTransGetAccountConvRate()] How can amount be nonzero and value be zero?";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new ("gnc.engine", loglevel, msg1);
+    auto split1 = xaccTransFindSplitByAccount(fixture->txn, fixture->acc1);
     gnc_numeric rate;
 
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
@@ -1281,12 +1283,11 @@ test_xaccTransGetAccountBalance (Fixture *fixture, gconstpointer pData)
 #else
 #define _func "xaccTransGetAccountBalance"
 #endif
-    gchar *msg1 = _func ": assertion " _Q "account && trans' failed";
+    auto msg1 = _func ": assertion " _Q "account && trans' failed";
 #undef _func
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    TestErrorStruct *check = test_error_struct_new ("gnc.engine", loglevel,
-                             msg1);
-    Split *split1 = xaccTransFindSplitByAccount(fixture->txn, fixture->acc1);
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new ("gnc.engine", loglevel, msg1);
+    auto split1 = xaccTransFindSplitByAccount(fixture->txn, fixture->acc1);
     gnc_numeric rate;
 
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
@@ -1323,7 +1324,7 @@ test_xaccTransSetCurrency (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
     gnc_commodity *curr = gnc_commodity_new (book, "Japanese Yen", "CURRENCY", "JPY", "Â¥", 1);
-    Split *split1 = xaccTransFindSplitByAccount (fixture->txn, fixture->acc1);
+    auto split1 = xaccTransFindSplitByAccount (fixture->txn, fixture->acc1);
     gnc_numeric old_val = xaccSplitGetValue (split1);
     /* Prevent commit in xaccTransSetCurrency() */
     xaccTransBeginEdit(fixture->txn);
@@ -1344,12 +1345,12 @@ test_xaccTransBeginEdit ()
     QofBook *book = qof_book_new ();
     Transaction *txn = xaccMallocTransaction (book);
     Transaction *dupe = NULL;
-    gchar *msg1 = "[xaccOpenLog] Attempt to open disabled transaction log";
-    gchar *msg2 = "[xaccTransWriteLog] Attempt to write disabled transaction log";
-    guint loglevel = G_LOG_LEVEL_INFO;
-    gchar *logdomain = "gnc.translog";
-    TestErrorStruct *check1 = test_error_struct_new (logdomain, loglevel, msg1);
-    TestErrorStruct *check2 = test_error_struct_new (logdomain, loglevel, msg2);
+    auto msg1 = "[xaccOpenLog] Attempt to open disabled transaction log";
+    auto msg2 = "[xaccTransWriteLog] Attempt to write disabled transaction log";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_INFO);
+    auto logdomain = "gnc.translog";
+    auto check1 = test_error_struct_new (logdomain, loglevel, msg1);
+    auto check2 = test_error_struct_new (logdomain, loglevel, msg2);
     guint hdlr = g_log_set_handler (logdomain, loglevel,
                                     (GLogFunc)test_list_handler, NULL);
     test_add_error (check1);
@@ -1435,7 +1436,7 @@ test_destroy_gains (GainsFixture *fixture, gconstpointer pData)
      * function that isn't protected.
      */
     Fixture *base = &(fixture->base);
-    Split *base_split = g_list_nth_data (base->txn->splits, 1);
+    auto base_split = static_cast<Split*>(g_list_nth_data (base->txn->splits, 1));
     xaccTransBeginEdit (fixture->gains_txn); /* Protect it from being actually destroyed */
     base->func->destroy_gains (base->txn);
     g_assert (qof_instance_get_destroying (QOF_INSTANCE (fixture->gains_txn)));
@@ -1452,12 +1453,12 @@ static void
 test_do_destroy (GainsFixture *fixture, gconstpointer pData)
 {
     Fixture *base = &(fixture->base);
-    Split *base_split = g_list_nth_data (base->txn->splits, 1);
+    auto base_split =  static_cast<Split*>(g_list_nth_data (base->txn->splits, 1));
     QofBook *book = qof_instance_get_book (base->txn);
     TestSignal sig = test_signal_new (QOF_INSTANCE (base->txn),
                                       QOF_EVENT_DESTROY, NULL);
     g_object_add_weak_pointer (G_OBJECT (base->txn->splits->data),
-                               (gpointer)&base_split);
+                               reinterpret_cast<void**>(&base_split));
     g_object_ref (base->txn);
     g_object_ref (fixture->gains_txn);
 
@@ -1491,7 +1492,7 @@ test_was_trans_emptied (Fixture *fixture, gconstpointer pData)
 static void trans_on_error(Transaction *trans, QofBackendError errcode)// Local: 0:1:0 callback for qof_commit_edit_part2, xaccTransCommitEdit
 */
 
-static QofBackendError errorvalue = 0;
+static QofBackendError errorvalue = ERR_BACKEND_NO_ERR;
 static void
 commit_error_cb (gpointer data, QofBackendError errcode)
 {
@@ -1502,13 +1503,13 @@ static void
 test_trans_on_error (Fixture *fixture, gconstpointer pData)
 {
     QofBackendError errcode = ERR_BACKEND_MODIFIED;
-    gchar *msg =
+    auto msg =
         "[trans_on_error()] Another user has modified this transaction\n"
         "\tjust a moment ago. Please look at their changes,\n"
         "\tand try again, if needed.\n";
-    gchar *logdomain = "gnc.engine";
-    guint loglevel = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
-    TestErrorStruct *check = test_error_struct_new (logdomain, loglevel, msg);
+    auto logdomain = "gnc.engine";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new (logdomain, loglevel, msg);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
                      (GLogFunc)test_checked_handler);
     gnc_engine_add_commit_error_callback ((EngineCommitErrorCallback)commit_error_cb, NULL);
@@ -1518,7 +1519,7 @@ test_trans_on_error (Fixture *fixture, gconstpointer pData)
     g_assert_cmpint (check->hits, ==, 1);
     g_assert_cmpint ((guint)errorvalue, ==, (guint)errcode);
     g_assert_cmpint (qof_instance_get_editlevel (fixture->txn), ==, 0);
-    errorvalue = 0;
+    errorvalue = ERR_BACKEND_NO_ERR;
 }
 /* trans_cleanup_commit
 static void trans_cleanup_commit(Transaction *trans)// Local: 0:1:0 callback for qof_commit_edit_part2, xaccTransCommitEdit
@@ -1527,22 +1528,22 @@ static void
 test_trans_cleanup_commit (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->txn));
-    Split *destr_split = xaccMallocSplit (book);
-    Split *bogus_split = xaccMallocSplit (book);
-    Split *split0 = fixture->txn->splits->data;
+    auto destr_split = xaccMallocSplit (book);
+    auto bogus_split = xaccMallocSplit (book);
+    auto split0 = static_cast<Split*>(fixture->txn->splits->data);
     Account *acct0 = split0->acc;
     Transaction *orig = NULL;
-    TestSignal *sig_d_remove = test_signal_new (QOF_INSTANCE (destr_split),
+    auto sig_d_remove = test_signal_new (QOF_INSTANCE (destr_split),
                                QOF_EVENT_REMOVE, NULL);
-    TestSignal *sig_b_remove = test_signal_new (QOF_INSTANCE (bogus_split),
+    auto sig_b_remove = test_signal_new (QOF_INSTANCE (bogus_split),
                                QOF_EVENT_REMOVE, NULL);
-    TestSignal *sig_d_destroy = test_signal_new (QOF_INSTANCE (destr_split),
+    auto sig_d_destroy = test_signal_new (QOF_INSTANCE (destr_split),
                                 QOF_EVENT_DESTROY, NULL);
-    TestSignal *sig_b_modify = test_signal_new (QOF_INSTANCE (bogus_split),
+    auto sig_b_modify = test_signal_new (QOF_INSTANCE (bogus_split),
                                QOF_EVENT_MODIFY, NULL);
-    TestSignal *sig_t_modify = test_signal_new (QOF_INSTANCE (fixture->txn),
+    auto sig_t_modify = test_signal_new (QOF_INSTANCE (fixture->txn),
                                QOF_EVENT_MODIFY, NULL);
-    TestSignal *sig_a_changed = test_signal_new (QOF_INSTANCE (acct0),
+    auto sig_a_changed = test_signal_new (QOF_INSTANCE (acct0),
                                 GNC_EVENT_ITEM_CHANGED, NULL);
 
     xaccTransBeginEdit (fixture->txn);
@@ -1605,8 +1606,8 @@ static void
 test_xaccTransCommitEdit (void)
 {
     QofBook *book = qof_book_new ();
-    Split *split1 = xaccMallocSplit (book);
-    Split *split2 = xaccMallocSplit (book);
+    auto split1 = xaccMallocSplit (book);
+    auto split2 = xaccMallocSplit (book);
     Transaction *txn = xaccMallocTransaction (book);
     Account *acc1 = xaccMallocAccount (book);
     Account *acc2 = xaccMallocAccount (book);
@@ -1617,11 +1618,11 @@ test_xaccTransCommitEdit (void)
 
     Timespec posted = gnc_dmy2timespec (21, 4, 2012);
 
-    TestSignal *sig_1_modify = test_signal_new (QOF_INSTANCE (split1),
+    auto sig_1_modify = test_signal_new (QOF_INSTANCE (split1),
                                QOF_EVENT_MODIFY, NULL);
-    TestSignal *sig_2_modify = test_signal_new (QOF_INSTANCE (split2),
+    auto sig_2_modify = test_signal_new (QOF_INSTANCE (split2),
                                QOF_EVENT_MODIFY, NULL);
-    TestSignal *sig_txn_destroy = test_signal_new (QOF_INSTANCE (txn),
+    auto sig_txn_destroy = test_signal_new (QOF_INSTANCE (txn),
                                   QOF_EVENT_DESTROY, NULL);
 
 
@@ -1629,8 +1630,8 @@ test_xaccTransCommitEdit (void)
     xaccAccountSetCommodity (acc2, curr);
     txn->date_posted.tv_sec = posted.tv_sec;
     txn->date_posted.tv_nsec = posted.tv_nsec;
-    split1->memo = CACHE_INSERT ("foo");
-    split1->action = CACHE_INSERT ("bar");
+    split1->memo = static_cast<char*>(CACHE_INSERT ("foo"));
+    split1->action = static_cast<char*>(CACHE_INSERT ("bar"));
     split1->amount = gnc_numeric_create (100000, 1000);
     split1->value = gnc_numeric_create (3200, 240);
     /* Note, deliberately imblanced to force xaccTransScrubImbalance
@@ -1640,8 +1641,8 @@ test_xaccTransCommitEdit (void)
     split2->value = gnc_numeric_create (-3000, 240);
     split1->acc = acc1;
     split2->acc = acc2;
-    txn->num = CACHE_INSERT ("123");
-    txn->description = CACHE_INSERT ("Waldo Pepper");
+    txn->num = static_cast<char*>(CACHE_INSERT ("123"));
+    txn->description = static_cast<char*>(CACHE_INSERT ("Waldo Pepper"));
     xaccTransBeginEdit (txn);
     {
         xaccTransSetCurrency (txn, curr);
@@ -1689,20 +1690,20 @@ test_xaccTransRollbackEdit (Fixture *fixture, gconstpointer pData)
     Timespec orig_post = txn->date_posted;
     Timespec orig_entered = txn->date_entered;
     KvpFrame *base_frame = NULL;
-    TestSignal *sig_account = test_signal_new (QOF_INSTANCE (fixture->acc1),
+    auto sig_account = test_signal_new (QOF_INSTANCE (fixture->acc1),
                               GNC_EVENT_ITEM_CHANGED, NULL);
     MockBackend *mbe = (MockBackend*)qof_book_get_backend (book);
-    Split *split_00 = txn->splits->data, *split_01 = txn->splits->next->data;
-    Split *split_02 = xaccMallocSplit (book);
-    Split *split_10 = NULL, *split_11 = NULL;
+    auto split_00 = static_cast<Split*>(txn->splits->data);
+    auto split_01 = static_cast<Split*>(txn->splits->next->data);
+    auto split_02 = xaccMallocSplit (book);
 
     xaccTransBeginEdit (txn);
     qof_instance_set_destroying (txn, TRUE);
     orig = txn->orig;
     base_frame = orig->inst.kvp_data; /* DupeTransaction copies the kvp_frame */
     g_object_ref (orig); /* Keep rollback from actually freeing it */
-    txn->num = "321";
-    txn->description = "salt peanuts";
+    txn->num = static_cast<char*>(CACHE_INSERT("321"));
+    txn->description = static_cast<char*>(CACHE_INSERT("salt peanuts"));
     txn->common_currency = NULL;
     txn->inst.kvp_data = NULL;
     txn->date_entered = new_entered;
@@ -1712,9 +1713,9 @@ test_xaccTransRollbackEdit (Fixture *fixture, gconstpointer pData)
     qof_instance_set_dirty (QOF_INSTANCE (split_01));
     xaccSplitSetParent (split_02, txn);
     g_object_ref (split_02);
-    split_10 = xaccDupeSplit(orig->splits->data);
+    auto split_10 = xaccDupeSplit(static_cast<Split*>(orig->splits->data));
     g_object_ref (split_10);
-    split_11 = xaccDupeSplit(orig->splits->next->data);
+    auto split_11 = xaccDupeSplit(static_cast<Split*>(orig->splits->next->data));
     g_object_ref (split_11);
     qof_instance_increase_editlevel (QOF_INSTANCE (txn)); /* So it's 2 */
     xaccTransRollbackEdit (txn);
@@ -1735,10 +1736,10 @@ test_xaccTransRollbackEdit (Fixture *fixture, gconstpointer pData)
     g_assert_cmpuint (test_signal_return_hits (sig_account), ==, 1);
     g_assert_cmpuint (g_list_length (txn->splits), ==, 2);
     g_assert_cmpint (GPOINTER_TO_INT(split_02->memo), ==, 1);
-    g_assert (xaccSplitEqual (txn->splits->data, split_10,
-                              FALSE, FALSE, FALSE));
-    g_assert (xaccSplitEqual (txn->splits->next->data, split_10,
+    g_assert (xaccSplitEqual (static_cast<Split*>(txn->splits->data), split_10,
                               FALSE, FALSE, FALSE));
+    g_assert (xaccSplitEqual (static_cast<Split*>(txn->splits->next->data),
+                              split_10, FALSE, FALSE, FALSE));
     g_assert_cmpstr (mbe->last_call, ==, "rollback");
     g_assert_cmpuint (qof_instance_get_editlevel (QOF_INSTANCE (txn)), ==, 0);
     g_assert (qof_instance_get_destroying (txn) == FALSE);
@@ -1754,10 +1755,9 @@ static void
 test_xaccTransRollbackEdit_BackendErrors (Fixture *fixture, gconstpointer pData)
 {
     MockBackend *mbe = (MockBackend*)qof_book_get_backend (qof_instance_get_book (fixture->txn));
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL;
-    gchar *msg = "[xaccTransRollbackEdit()] Rollback Failed.  Ouch!";
-    TestErrorStruct *check = test_error_struct_new ("gnc.engine",
-                             loglevel, msg);
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto msg = "[xaccTransRollbackEdit()] Rollback Failed.  Ouch!";
+    auto check = test_error_struct_new ("gnc.engine", loglevel, msg);
     fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check,
                      (GLogFunc)test_checked_handler);
     g_object_ref (fixture->txn);
@@ -1795,13 +1795,13 @@ test_xaccTransOrder_num_action (Fixture *fixture, gconstpointer pData)
     g_assert_cmpint (xaccTransOrder_num_action (NULL, NULL, NULL, NULL), ==, 0);
     g_assert_cmpint (xaccTransOrder_num_action (txnA, NULL, txnB, NULL), ==,
                      qof_instance_guid_compare (txnA, txnB));
-    txnB->description = CACHE_INSERT ("Salt Peanuts");
+    txnB->description = static_cast<char*>(CACHE_INSERT ("Salt Peanuts"));
     g_assert_cmpint (xaccTransOrder_num_action (txnA, NULL, txnB, NULL), >=, 1);
     txnB->date_entered.tv_sec += 1;
     g_assert_cmpint (xaccTransOrder_num_action (txnA, NULL, txnB, NULL), ==, -1);
-    txnB->num = CACHE_INSERT ("101");
+    txnB->num = static_cast<char*>(CACHE_INSERT ("101"));
     g_assert_cmpint (xaccTransOrder_num_action (txnA, NULL, txnB, NULL), ==, 1);
-    txnB->num = CACHE_INSERT ("one-oh-one");
+    txnB->num = static_cast<char*>(CACHE_INSERT ("one-oh-one"));
     g_assert_cmpint (xaccTransOrder_num_action (txnA, NULL, txnB, NULL), ==, 1);
     g_assert_cmpint (xaccTransOrder_num_action (txnA, "24", txnB, "42"), ==, -1);
     txnB->date_posted.tv_sec -= 1;
@@ -1870,26 +1870,25 @@ static void
 test_xaccTransVoid (Fixture *fixture, gconstpointer pData)
 {
     /* Actual function variables start here. */
-    KvpFrame *frame = fixture->txn->inst.kvp_data;
-    gchar *void_reason = "Voided for Unit Test";
-    gchar *txn_notes = g_strdup (kvp_frame_get_string (frame, trans_notes_str));
-    KvpValue *val;
+    auto frame = fixture->txn->inst.kvp_data;
+    auto void_reason = "Voided for Unit Test";
+    auto txn_notes = g_strdup (frame->get_slot(trans_notes_str)->get<const char*>());
     Timespec now = timespec_now ();
     char iso8601_str[ISO_DATELENGTH + 1] = "";
     GList *split = NULL;
 
     xaccTransVoid (fixture->txn, void_reason);
-    g_assert_cmpstr (kvp_frame_get_string (frame, trans_notes_str), ==,
+    g_assert_cmpstr (frame->get_slot(trans_notes_str)->get<const char*>(), ==,
                      "Voided transaction");
-    g_assert_cmpstr (kvp_frame_get_string (frame, void_former_notes_str), ==,
-                     txn_notes);
-    g_assert_cmpstr (kvp_frame_get_string (frame, void_reason_str), ==,
+    g_assert_cmpstr (frame->get_slot(void_former_notes_str)->get<const char*>(),
+                     ==, txn_notes);
+    g_assert_cmpstr (frame->get_slot(void_reason_str)->get<const char*>(), ==,
                      void_reason);
     gnc_timespec_to_iso8601_buff (now, iso8601_str);
-    g_assert_cmpstr (kvp_frame_get_string (frame, void_time_str), ==,
+    g_assert_cmpstr (frame->get_slot(void_time_str)->get<const char*>(), ==,
                      iso8601_str);
-    g_assert_cmpstr (kvp_frame_get_string (frame, TRANS_READ_ONLY_REASON), ==,
-                     "Transaction Voided");
+    g_assert_cmpstr (frame->get_slot(TRANS_READ_ONLY_REASON)->get<const char*>(),
+                     ==, "Transaction Voided");
     for (split = fixture->txn->splits; split; split=g_list_next (split))
     {
         g_assert (gnc_numeric_zero_p (((Split*)(split->data))->value));
@@ -1898,12 +1897,12 @@ test_xaccTransVoid (Fixture *fixture, gconstpointer pData)
 
     xaccTransUnvoid (fixture->txn);
 
-    g_assert_cmpstr (kvp_frame_get_string (frame, trans_notes_str), ==,
+    g_assert_cmpstr (frame->get_slot(trans_notes_str)->get<const char*>(), ==,
                      txn_notes);
-    g_assert (kvp_frame_get_slot (frame, void_former_notes_str) == NULL);
-    g_assert (kvp_frame_get_slot (frame, void_reason_str) == NULL);
-    g_assert (kvp_frame_get_slot (frame, void_time_str) == NULL);
-    g_assert (kvp_frame_get_slot (frame, TRANS_READ_ONLY_REASON) == NULL);
+    g_assert (frame->get_slot(void_former_notes_str) == NULL);
+    g_assert (frame->get_slot(void_reason_str) == NULL);
+    g_assert (frame->get_slot(void_time_str) == NULL);
+    g_assert (frame->get_slot(TRANS_READ_ONLY_REASON) == NULL);
     for (split = fixture->txn->splits; split; split=g_list_next (split))
     {
         g_assert (!gnc_numeric_zero_p (((Split*)(split->data))->value));
@@ -1921,10 +1920,10 @@ static void
 test_xaccTransReverse (Fixture *fixture, gconstpointer pData)
 {
     Transaction *rev = xaccTransReverse (fixture->txn);
-    KvpFrame *frame = fixture->txn->inst.kvp_data;
+    auto frame = fixture->txn->inst.kvp_data;
     GList *orig_splits = NULL, *rev_splits = NULL;
 
-    g_assert (guid_equal (kvp_frame_get_guid (frame, TRANS_REVERSED_BY),
+    g_assert (guid_equal (frame->get_slot(TRANS_REVERSED_BY)->get<GncGUID*>(),
                           xaccTransGetGUID (rev)));
 
     g_assert (qof_instance_is_dirty (QOF_INSTANCE (rev)));
@@ -1936,8 +1935,8 @@ test_xaccTransReverse (Fixture *fixture, gconstpointer pData)
             orig_splits = g_list_next (orig_splits),
             rev_splits = g_list_next (rev_splits))
     {
-        Split *orig_split = orig_splits->data;
-        Split *rev_split = rev_splits->data;
+        auto orig_split = static_cast<Split*>(orig_splits->data);
+        auto rev_split = static_cast<Split*>(rev_splits->data);
         g_assert (gnc_numeric_equal (orig_split->amount,
                                      gnc_numeric_neg (rev_split->amount)));
         g_assert (gnc_numeric_equal (orig_split->value,
@@ -1961,8 +1960,8 @@ static void
 test_xaccTransScrubGainsDate_no_dirty (GainsFixture *fixture,
                                        gconstpointer pData)
 {
-    Split *base_split = g_list_nth_data (fixture->base.txn->splits, 1);
-    Split *gains_split = base_split->gains_split;
+    auto base_split = static_cast<Split *>(g_list_nth_data (fixture->base.txn->splits, 1));
+    auto gains_split = base_split->gains_split;
 
     base_split->gains = GAINS_STATUS_GAINS;
     gains_split->gains = GAINS_STATUS_GAINS;
@@ -1980,8 +1979,8 @@ static void
 test_xaccTransScrubGainsDate_base_dirty (GainsFixture *fixture,
         gconstpointer pData)
 {
-    Split *base_split = g_list_nth_data (fixture->base.txn->splits, 1);
-    Split *gains_split = base_split->gains_split;
+    auto base_split = static_cast<Split *>(g_list_nth_data (fixture->base.txn->splits, 1));
+    auto gains_split = base_split->gains_split;
 
     base_split->gains = GAINS_STATUS_GAINS | GAINS_STATUS_DATE_DIRTY;
     gains_split->gains = GAINS_STATUS_GAINS;
@@ -1999,8 +1998,8 @@ static void
 test_xaccTransScrubGainsDate_gains_dirty (GainsFixture *fixture,
         gconstpointer pData)
 {
-    Split *base_split = g_list_nth_data (fixture->base.txn->splits, 1);
-    Split *gains_split = base_split->gains_split;
+    auto base_split = static_cast<Split*>(g_list_nth_data (fixture->base.txn->splits, 1));
+    auto gains_split = base_split->gains_split;
 
     base_split->gains = GAINS_STATUS_GAINS;
     gains_split->gains = GAINS_STATUS_GAINS | GAINS_STATUS_DATE_DIRTY;
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index 8e8ff35..475ae5a 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -143,6 +143,12 @@ walk_path_and_create(KvpFrameImpl* frame, Path path)
 }
 
 KvpValue*
+KvpFrameImpl::set_path(const char* path, KvpValue* value) noexcept
+{
+    return set_path(make_vector(path), value);
+}
+
+KvpValue*
 KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
 {
     auto cur_frame = this;
diff --git a/src/libqof/qof/kvp_frame.hpp b/src/libqof/qof/kvp_frame.hpp
index 322e9fa..46ec14b 100644
--- a/src/libqof/qof/kvp_frame.hpp
+++ b/src/libqof/qof/kvp_frame.hpp
@@ -78,7 +78,21 @@ struct KvpFrameImpl
      * Set the value with the key in a subframe following the keys in path,
      * replacing and returning the old value if it exists or nullptr if it
      * doesn't. Creates any missing intermediate frames.
-     * @param path: The path of subframes leading to the frame in which to
+     * @param path: The path of subframes as a '/'-delimited string leading to the frame in which to
+     * insert/replace.
+     * @param newvalue: The value to set at key.
+     * @return The old value if there was one or nullptr.
+     */
+    KvpValue* set_path(const char* path, KvpValue* newvalue) noexcept;
+    /**
+     * Make a string representation of the frame. Mostly useful for debugging.
+     * @return A std::string representing the frame and all its children.
+     */
+    /**
+     * Set the value with the key in a subframe following the keys in path,
+     * replacing and returning the old value if it exists or nullptr if it
+     * doesn't. Creates any missing intermediate frames.
+     * @param path: The path of subframes as a std::vector leading to the frame in which to
      * insert/replace.
      * @param newvalue: The value to set at key.
      * @return The old value if there was one or nullptr.
diff --git a/src/libqof/qof/test/Makefile.am b/src/libqof/qof/test/Makefile.am
index 48eaf3f..e233cc1 100644
--- a/src/libqof/qof/test/Makefile.am
+++ b/src/libqof/qof/test/Makefile.am
@@ -12,8 +12,7 @@ test_qof_SOURCES = \
 	test-gnc-date.c \
 	test-qof.c \
 	test-qofbook.c \
-	test-qofinstance.c \
-	test-kvp_frame.c \
+	test-qofinstance.cpp \
 	test-qofobject.c \
 	test-qofsession.c \
 	test-qof-string-cache.c \
diff --git a/src/libqof/qof/test/test-kvp_frame.c b/src/libqof/qof/test/test-kvp_frame.c
deleted file mode 100644
index 8717374..0000000
--- a/src/libqof/qof/test/test-kvp_frame.c
+++ /dev/null
@@ -1,1703 +0,0 @@
-/********************************************************************
- * test-kvp_frame.c: GLib g_test test suite for kvp_frame.c.		    *
- * Copyright 2011 John Ralls <jralls at ceridwen.us>		    *
- *                                                                  *
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-********************************************************************/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "config.h"
-#include <string.h>
-#include <glib.h>
-#include <unittest-support.h>
-#include <qof.h>
-#include <kvp_frame.h>
-#ifdef __cplusplus
-}
-#endif
-
-
-
-static const gchar *suitename = "/qof/kvp_frame";
-void test_suite_kvp_frame ( void );
-
-typedef struct
-{
-    KvpFrame *frame;
-    GSList *hdlrs;
-} Fixture;
-
-static void
-setup( Fixture *fixture, gconstpointer pData )
-{
-    fixture->frame = kvp_frame_new();
-    fixture->hdlrs = NULL;
-}
-
-static void
-teardown( Fixture *fixture, gconstpointer pData )
-{
-    kvp_frame_delete( fixture->frame );
-    g_slist_free_full (fixture->hdlrs, test_free_log_handler);
-    test_clear_error_list ();
-}
-
-static gchar* glist_to_string( const GList *list )
-{
-    KvpValue * val = kvp_value_new_glist( list );
-    gchar * ret = kvp_value_to_string( val );
-    kvp_value_delete( val );
-    return ret;
-}
-
-extern KvpFrame* ( *p_get_trailer_make )( KvpFrame *frame, const char *key_path, char **end_key );
-extern KvpFrame* ( *p_get_or_make )( KvpFrame *fr, const char * key );
-extern const KvpFrame* ( *p_kvp_frame_get_frame_or_null_slash_trash )( const KvpFrame *frame, char *key_path );
-extern const KvpFrame* ( *p_get_trailer_or_null )( const KvpFrame * frame, const char * key_path, char **end_key );
-
-extern void init_static_test_pointers( void );
-
-static void
-setup_static( Fixture *fixture, gconstpointer pData )
-{
-    fixture->frame = kvp_frame_new();
-    fixture->hdlrs = NULL;
-    init_static_test_pointers();
-    g_assert( p_get_trailer_make && p_get_or_make && p_get_trailer_or_null && 
-              p_kvp_frame_get_frame_or_null_slash_trash );
-}
-
-static void
-teardown_static( Fixture *fixture, gconstpointer pData )
-{
-    kvp_frame_delete( fixture->frame );
-    g_slist_free_full (fixture->hdlrs, test_free_log_handler);
-    test_clear_error_list ();
-    p_get_trailer_make = NULL;
-    p_get_or_make = NULL;
-    p_kvp_frame_get_frame_or_null_slash_trash = NULL;
-    p_get_trailer_or_null = NULL;
-}
-
-static GncGUID*
-populate_frame (KvpFrame *frame)
-{
-    GList *list = NULL;
-    Timespec ts;
-    GncGUID *guid;
-    GDate gdate;
-
-    ts.tv_sec = 1;
-    ts.tv_nsec = 1;
-    guid = guid_new ();
-    g_date_set_dmy (&gdate, 26, 1, 1957);
-
-    kvp_frame_set_gint64( frame, "gint64-type", 100 );
-    kvp_frame_set_double( frame, "double-type", 3.14159 );
-    kvp_frame_set_numeric( frame, "numeric-type", gnc_numeric_zero() );
-    kvp_frame_set_timespec( frame, "timespec-type", ts );
-    kvp_frame_set_string( frame, "string-type", "abcdefghijklmnop" );
-    kvp_frame_set_guid( frame, "guid-type", guid );
-    kvp_frame_set_value_nc (frame, "gdate-type", kvp_value_new_gdate (gdate));
-    kvp_frame_set_frame( frame, "frame-type", kvp_frame_new() );
-
-    list = g_list_prepend (list, kvp_value_new_guid (guid));
-    list = g_list_prepend (list, kvp_value_new_string ("qrstuvwxyz"));
-    list = g_list_prepend (list, kvp_value_new_timespec (ts));
-    list = g_list_prepend (list, kvp_value_new_numeric (gnc_numeric_create (256, 120)));
-    list = g_list_prepend (list, kvp_value_new_double (0.4342944819));
-    list = g_list_prepend (list, kvp_value_new_gint64 (0x1f2e3d4c5b6a79LL));
-    kvp_frame_set_value (frame, "list-type", kvp_value_new_glist_nc (list));
-
-    return guid;
-}
-
-static void
-test_kvp_frame_new_delete( void )
-{
-    KvpFrame *frame;
-    GncGUID *guid;
-
-    frame = kvp_frame_new();
-    g_assert( frame );
-    g_assert( kvp_frame_is_empty( frame ) );
-
-    guid = populate_frame (frame);
-
-    g_assert( !kvp_frame_is_empty( frame ) );
-
-    kvp_frame_delete( frame );
-    g_assert( frame );
-    guid_free (guid);
-}
-
-static void
-test_kvp_frame_copy( Fixture *fixture, gconstpointer pData )
-{
-    KvpFrame *to_copy = NULL;
-    gint64 test_gint64, copy_gint64;
-    double test_double, copy_double;
-    gnc_numeric test_gnc_numeric, copy_gnc_numeric;
-    Timespec test_ts, copy_ts;
-    const char* test_str, *copy_str;
-    GncGUID *test_guid, *copy_guid;
-    KvpFrame *test_frame, *copy_frame;
-
-    /* init data in source frame */
-    test_gint64 = 111;
-    test_double = 1.1;
-    test_gnc_numeric = gnc_numeric_zero();
-    test_ts.tv_sec = 1;
-    test_ts.tv_nsec = 1;
-    test_str = "abcdefghijklmnop";
-    test_guid = guid_new();
-    test_frame = kvp_frame_new();
-
-    g_assert( fixture->frame );
-    kvp_frame_set_gint64( fixture->frame, "gint64-type", test_gint64 );
-    kvp_frame_set_double( fixture->frame, "double-type", test_double );
-    kvp_frame_set_numeric( fixture->frame, "numeric-type", test_gnc_numeric );
-    kvp_frame_set_timespec( fixture->frame, "timespec-type", test_ts );
-    kvp_frame_set_string( fixture->frame, "string-type", test_str );
-    kvp_frame_set_guid( fixture->frame, "guid-type", test_guid );
-    kvp_frame_set_frame( fixture->frame, "frame-type", test_frame );
-    g_assert( !kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test frame copy" );
-    to_copy = kvp_frame_copy( fixture->frame );
-    g_assert( to_copy );
-    g_assert( !kvp_frame_is_empty( to_copy ) );
-    g_assert( to_copy != fixture->frame );
-
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, to_copy ), == , 0 );
-    copy_gint64 = kvp_frame_get_gint64( to_copy, "gint64-type" );
-    g_assert( &copy_gint64 != &test_gint64 );
-    g_assert_cmpint( copy_gint64, == , test_gint64 );
-    copy_double = kvp_frame_get_double( to_copy, "double-type" );
-    g_assert( &copy_double != &test_double );
-    g_assert_cmpfloat( copy_double, == , test_double );
-    copy_gnc_numeric = kvp_frame_get_numeric( to_copy, "numeric-type" );
-    g_assert( &copy_gnc_numeric != &test_gnc_numeric );
-    g_assert_cmpfloat( copy_gnc_numeric.num, == , test_gnc_numeric.num );
-    g_assert_cmpfloat( copy_gnc_numeric.denom, == , test_gnc_numeric.denom );
-    copy_ts = kvp_frame_get_timespec( to_copy, "timespec-type" );
-    g_assert( &copy_ts != &test_ts );
-    g_assert_cmpfloat( copy_ts.tv_sec, == , test_ts.tv_sec );
-    g_assert_cmpfloat( copy_ts.tv_nsec, == , test_ts.tv_nsec );
-    copy_str = kvp_frame_get_string( to_copy, "string-type" );
-    g_assert( copy_str != test_str );
-    g_assert_cmpstr( copy_str, == , test_str );
-    copy_guid = kvp_frame_get_guid( to_copy, "guid-type" );
-    g_assert( copy_guid != test_guid );
-    g_assert( guid_equal( copy_guid, test_guid ) );
-    copy_frame = kvp_frame_get_frame( to_copy, "frame-type");
-    g_assert( copy_frame );
-    g_assert( kvp_frame_is_empty( copy_frame ) );
-    g_assert( copy_frame != test_frame );
-    g_assert_cmpint( kvp_frame_compare( copy_frame, test_frame ), == , 0 );
-
-    kvp_frame_delete( to_copy );
-    guid_free( test_guid );
-}
-
-static void
-test_kvp_frame_set_foo( Fixture *fixture, gconstpointer pData )
-{
-    gnc_numeric test_gnc_numeric, copy_gnc_numeric;
-    Timespec test_ts, copy_ts;
-    GncGUID *test_guid, *copy_guid;
-
-    test_gnc_numeric = gnc_numeric_zero();
-    test_ts.tv_sec = 1;
-    test_ts.tv_nsec = 1;
-    test_guid = guid_new();
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test gint64 setup and replace, test frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test" ) == NULL );
-    kvp_frame_set_gint64( fixture->frame, "/test/gint64", 1 );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test" ) != NULL );
-    g_assert_cmpint( kvp_frame_get_gint64( fixture->frame, "/test/gint64" ), == , 1 );
-    kvp_frame_set_gint64( fixture->frame, "/test/gint64", 5 );
-    g_assert_cmpint( kvp_frame_get_gint64( fixture->frame, "/test/gint64" ), == , 5 );
-
-    g_test_message( "Test double setup and replace, test2 frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test2" ) == NULL );
-    kvp_frame_set_double( fixture->frame, "/test2/double", 1.1 );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test2" ) != NULL );
-    g_assert_cmpfloat( kvp_frame_get_double( fixture->frame, "/test2/double" ), == , 1.1 );
-    kvp_frame_set_double( fixture->frame, "/test2/double", 5.5 );
-    g_assert_cmpfloat( kvp_frame_get_double( fixture->frame, "/test2/double" ), == , 5.5 );
-
-    g_test_message( "Test double setup and replace, test3 frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test3" ) == NULL );
-    kvp_frame_set_numeric( fixture->frame, "/test3/numeric", test_gnc_numeric );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test3" ) != NULL );
-    copy_gnc_numeric = kvp_frame_get_numeric( fixture->frame, "/test3/numeric" );
-    g_assert_cmpint( copy_gnc_numeric.num, == , 0 );
-    g_assert_cmpint( copy_gnc_numeric.denom, == , 1 );
-    test_gnc_numeric.num = 2;
-    test_gnc_numeric.denom = 3;
-    kvp_frame_set_numeric( fixture->frame, "/test3/numeric", test_gnc_numeric );
-    copy_gnc_numeric = kvp_frame_get_numeric( fixture->frame, "/test3/numeric" );
-    g_assert_cmpint( copy_gnc_numeric.num, == , 2 );
-    g_assert_cmpint( copy_gnc_numeric.denom, == , 3 );
-
-    g_test_message( "Test timespec setup and replace, test4 frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test4" ) == NULL );
-    kvp_frame_set_timespec( fixture->frame, "/test4/timespec", test_ts );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test4" ) != NULL );
-    copy_ts = kvp_frame_get_timespec( fixture->frame, "/test4/timespec" );
-    g_assert_cmpint( copy_ts.tv_sec, == , 1 );
-    g_assert_cmpint( copy_ts.tv_nsec, == , 1 );
-    test_ts.tv_sec = 7;
-    test_ts.tv_nsec = 13;
-    kvp_frame_set_timespec( fixture->frame, "/test4/timespec", test_ts );
-    copy_ts = kvp_frame_get_timespec( fixture->frame, "/test4/timespec" );
-    g_assert_cmpint( copy_ts.tv_sec, == , 7 );
-    g_assert_cmpint( copy_ts.tv_nsec, == , 13 );
-
-    g_test_message( "Test string setup and replace, test5 frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test5" ) == NULL );
-    kvp_frame_set_string( fixture->frame, "/test5/string", "one string" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test5" ) != NULL );
-    g_assert_cmpstr( kvp_frame_get_string( fixture->frame, "/test5/string" ), == , "one string" );
-    kvp_frame_set_string( fixture->frame, "/test5/string", "another string" );
-    g_assert_cmpstr( kvp_frame_get_string( fixture->frame, "/test5/string" ), == , "another string" );
-
-    g_test_message( "Test guid setup and replace, test6 frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test6" ) == NULL );
-    kvp_frame_set_guid( fixture->frame, "/test6/guid", test_guid );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test6" ) != NULL );
-    copy_guid = kvp_frame_get_guid( fixture->frame, "/test6/guid" );
-    g_assert( guid_equal( copy_guid, test_guid ) );
-    kvp_frame_set_guid( fixture->frame, "/test6/guid", guid_null() );
-    copy_guid = kvp_frame_get_guid( fixture->frame, "/test6/guid" );
-    g_assert( guid_equal( copy_guid, guid_null() ) );
-
-    g_test_message( "Test frame setup and replace, test7 frame is created" );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test7" ) == NULL );
-    kvp_frame_set_frame( fixture->frame, "/test7", kvp_frame_new() );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test7" ) != NULL );
-    kvp_frame_set_frame( fixture->frame, "/test7", NULL );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test7" ) == NULL );
-}
-
-static void
-test_kvp_frame_get_frame_slash( Fixture *fixture, gconstpointer pData )
-{
-    KvpFrame *result_frame = NULL;
-    /* Mostly testing static routine kvp_frmae_get_frame_slash_trash */
-    g_assert( fixture->frame );
-
-    g_test_message( "Test path with one slash same frame should be returned" );
-    result_frame = kvp_frame_get_frame_slash( fixture->frame, "/" );
-    g_assert( result_frame );
-    g_assert( result_frame == fixture->frame );
-
-    g_test_message( "Test path with trailing slash same frame should be returned" );
-    result_frame = kvp_frame_get_frame_slash( fixture->frame, "/////" );
-    g_assert( result_frame );
-    g_assert( result_frame == fixture->frame );
-
-    g_test_message( "Test new frame is created" );
-    result_frame = kvp_frame_get_frame_slash( fixture->frame, "/test" );
-    g_assert( result_frame );
-    g_assert( result_frame != fixture->frame );
-    g_assert( result_frame == kvp_frame_get_frame( fixture->frame, "/test" ) );
-
-    g_test_message( "Test trailing slashes are ignored and frame created" );
-    result_frame = kvp_frame_get_frame_slash( fixture->frame, "////test2/////" );
-    g_assert( result_frame );
-    g_assert( result_frame != fixture->frame );
-    g_assert( result_frame == kvp_frame_get_frame( fixture->frame, "/test2" ) );
-    g_assert( result_frame != kvp_frame_get_frame( fixture->frame, "/test" ) );
-
-    g_test_message( "Test frames are created along the path if not exist and last frame is returned" );
-    result_frame = kvp_frame_get_frame_slash( fixture->frame, "////test3/////test4//////" );
-    g_assert( result_frame );
-    g_assert( result_frame != fixture->frame );
-    g_assert( result_frame != kvp_frame_get_frame( fixture->frame, "/test2" ) );
-    g_assert( result_frame != kvp_frame_get_frame( fixture->frame, "/test" ) );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test3" ) != NULL );
-    g_assert( result_frame != kvp_frame_get_frame( fixture->frame, "/test3" ) );
-    g_assert( result_frame == kvp_frame_get_frame( fixture->frame, "/test3/test4" ) );
-
-    g_test_message( "Test existing frame is returned" );
-    g_assert( result_frame == kvp_frame_get_frame_slash( fixture->frame, "////test3/////test4//////" ) );
-}
-
-static void
-test_kvp_frame_get_slot_path( Fixture *fixture, gconstpointer pData )
-{
-    KvpValue *result_value = NULL ;
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test with non existing path should return NULL" );
-    result_value = kvp_frame_get_slot_path( fixture->frame, "test", "test2", NULL );
-    g_assert( !result_value );
-
-    g_test_message( "Test with existing value set to current frame" );
-    kvp_frame_set_gint64( fixture->frame, "/test", 1 );
-    result_value = kvp_frame_get_slot_path( fixture->frame, "test", NULL );
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_GINT64 );
-    g_assert_cmpint( kvp_value_get_gint64( result_value ), == , 1 );
-
-    g_test_message( "Test should return null as test is not a frame" );
-    kvp_frame_set_gint64( fixture->frame, "/test/test2", 2 );
-    result_value = kvp_frame_get_slot_path( fixture->frame, "test", "test2", NULL );
-    g_assert( !result_value );
-
-    g_test_message( "Test should return last value in the path" );
-    kvp_frame_set_gint64( fixture->frame, "/test2/test3", 2 );
-    result_value = kvp_frame_get_slot_path( fixture->frame, "test2", "test3", NULL );
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_GINT64 );
-    g_assert_cmpint( kvp_value_get_gint64( result_value ), == , 2 );
-
-    g_test_message( "Test should return null as last value in the path does not exist" );
-    result_value = kvp_frame_get_slot_path( fixture->frame, "test2", "test3", "test4", NULL );
-    g_assert( !result_value );
-}
-
-static void
-test_kvp_frame_get_slot_path_gslist( Fixture *fixture, gconstpointer pData )
-{
-    /* similar to previous test except path is passed as GSList*/
-    GSList *path_list = NULL;
-    KvpValue *result_value = NULL ;
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test with non existing path should return NULL" );
-    path_list = g_slist_append (path_list, "test");
-    path_list = g_slist_append (path_list, "test2");
-    result_value = kvp_frame_get_slot_path_gslist( fixture->frame, path_list );
-    g_assert( !result_value );
-
-    g_test_message( "Test with existing value set to current frame" );
-    path_list = g_slist_remove( path_list, "test2" );
-    kvp_frame_set_gint64( fixture->frame, "/test", 1 );
-    result_value = kvp_frame_get_slot_path_gslist( fixture->frame, path_list );
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_GINT64 );
-    g_assert_cmpint( kvp_value_get_gint64( result_value ), == , 1 );
-
-    g_test_message( "Test should return null as test is not a frame" );
-    path_list = g_slist_append (path_list, "test2");
-    kvp_frame_set_gint64( fixture->frame, "/test/test2", 2 );
-    result_value = kvp_frame_get_slot_path_gslist( fixture->frame, path_list );
-    g_assert( !result_value );
-
-    g_test_message( "Test should return last value in the path" );
-    path_list = g_slist_remove( path_list, "test" );
-    path_list = g_slist_append (path_list, "test3");
-    kvp_frame_set_gint64( fixture->frame, "/test2/test3", 2 );
-    result_value = kvp_frame_get_slot_path_gslist( fixture->frame, path_list );
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_GINT64 );
-    g_assert_cmpint( kvp_value_get_gint64( result_value ), == , 2 );
-
-    g_test_message( "Test should return null as last value in the path does not exist" );
-    path_list = g_slist_append (path_list, "test4");
-    result_value = kvp_frame_get_slot_path_gslist( fixture->frame, path_list );
-    g_assert( !result_value );
-    g_slist_free( path_list );
-}
-
-static void
-test_kvp_frame_add_frame_nc( Fixture *fixture, gconstpointer pData )
-{
-    /* basically we test static function kvp_frame_add_value_nc
-     * if path not exist it's created
-     * if gslist exist on the path new value added to the list
-     * if any other value exist it's converted to gslist and newvalue added
-     */
-    KvpFrame *test_frame = NULL,
-              *test_frame2 = NULL,
-               *test_frame3 = NULL,
-                *result_frame = NULL;
-    KvpValue *result_value = NULL;
-    GList *result_list = NULL;
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test when path does not exist it is created" );
-    result_frame = kvp_frame_get_frame( fixture->frame, "/test/test2/test3" );
-    g_assert( !result_frame );
-    test_frame = kvp_frame_new();
-    kvp_frame_add_frame_nc( fixture->frame, "/test/test2/test3", test_frame );
-    result_frame = kvp_frame_get_frame( fixture->frame, "/test/test2/test3" );
-    g_assert( result_frame );
-    g_assert( result_frame == test_frame ); /* no copying done */
-    result_frame = kvp_frame_get_frame( fixture->frame, "/test/test2" );
-    g_assert( result_frame != test_frame );
-    result_frame = kvp_frame_get_frame( fixture->frame, "/test" );
-    g_assert( result_frame != test_frame );
-
-    g_test_message( "Test when value exist on the path it's converted to bag and new value added" );
-    test_frame2 = kvp_frame_new();
-    kvp_frame_add_frame_nc( fixture->frame, "/test/test2/test3", test_frame2 );
-    result_value = kvp_frame_get_value( fixture->frame, "/test/test2/test3" );
-    result_list = kvp_value_get_glist( result_value );
-    g_assert( result_list );
-    g_assert_cmpint( g_list_length( result_list ), == , 2 );
-    result_value = g_list_first( result_list )->data;
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_FRAME );
-    g_assert( kvp_value_get_frame( result_value ) == test_frame );
-    result_value = g_list_next( result_list )->data;
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_FRAME );
-    g_assert( kvp_value_get_frame( result_value ) == test_frame2 );
-
-    g_test_message( "Test when bag exists on the path new values are added to it" );
-    test_frame3 = kvp_frame_new();
-    kvp_frame_add_frame_nc( fixture->frame, "/test/test2/test3", test_frame3 );
-    result_value = kvp_frame_get_value( fixture->frame, "/test/test2/test3" );
-    g_assert( result_list == kvp_value_get_glist( result_value ) ); /* same list used */
-    g_assert_cmpint( g_list_length( result_list ), == , 3 );
-    result_value = g_list_first( result_list )->data;
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_FRAME );
-    g_assert( kvp_value_get_frame( result_value ) == test_frame );
-    result_value = g_list_next( result_list )->data;
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_FRAME );
-    g_assert( kvp_value_get_frame( result_value ) == test_frame2 );
-    result_value = g_list_last( result_list )->data;
-    g_assert( result_value );
-    g_assert( kvp_value_get_type( result_value ) == KVP_TYPE_FRAME );
-    g_assert( kvp_value_get_frame( result_value ) == test_frame3 );
-}
-
-static void
-test_kvp_value_copy( void )
-{
-    KvpValue *gint64_orig_value, *gint64_copy_value;
-    KvpValue *double_orig_value, *double_copy_value;
-    KvpValue *numeric_orig_value, *numeric_copy_value;
-    KvpValue *string_orig_value, *string_copy_value;
-    KvpValue *guid_orig_value, *guid_copy_value;
-    KvpValue *timespec_orig_value, *timespec_copy_value;
-    KvpValue *glist_orig_value, *glist_copy_value;
-    KvpValue *frame_orig_value, *frame_copy_value;
-
-    /* data init */
-    gnc_numeric gnc_numeric_orig, gnc_numeric_copy;
-    GncGUID *guid_orig, *guid_copy;
-    Timespec ts_orig, ts_copy;
-    GList *list_orig, *list_copy;
-    KvpFrame *frame_orig, *frame_copy;
-
-    gnc_numeric_orig = gnc_numeric_zero();
-    guid_orig = guid_new();
-    ts_orig.tv_sec = 1;
-    ts_orig.tv_nsec = 1;
-    list_orig = NULL;
-    list_orig = g_list_append( list_orig, kvp_value_new_string( "abcdefghijklmnop" ) );
-    frame_orig = kvp_frame_new();
-
-    g_test_message( "Test creates original values and checks copies of them" );
-    gint64_orig_value = kvp_value_new_gint64( 2 );
-    double_orig_value = kvp_value_new_double( 3.3 );
-    numeric_orig_value = kvp_value_new_gnc_numeric( gnc_numeric_orig );
-    string_orig_value = kvp_value_new_string( "abcdefghijklmnop" );
-    guid_orig_value = kvp_value_new_guid( guid_orig );
-    timespec_orig_value = kvp_value_new_timespec( ts_orig );
-    glist_orig_value = kvp_value_new_glist( list_orig );
-    frame_orig_value = kvp_value_new_frame( frame_orig );
-    g_assert( gint64_orig_value && double_orig_value && numeric_orig_value && string_orig_value
-              && guid_orig_value && timespec_orig_value && glist_orig_value && frame_orig_value );
-
-    /* copy values */
-    gint64_copy_value = kvp_value_copy( gint64_orig_value );
-    g_assert( gint64_copy_value );
-    g_assert( gint64_copy_value != gint64_orig_value );
-    g_assert( kvp_value_get_type( gint64_copy_value ) == KVP_TYPE_GINT64 );
-    g_assert_cmpint( kvp_value_get_gint64( gint64_copy_value ), == , 2 );
-
-    double_copy_value = kvp_value_copy( double_orig_value );
-    g_assert( double_copy_value );
-    g_assert( double_copy_value != double_orig_value );
-    g_assert( kvp_value_get_type( double_copy_value ) == KVP_TYPE_DOUBLE );
-    g_assert_cmpfloat( kvp_value_get_double( double_copy_value ), == , 3.3 );
-
-    numeric_copy_value = kvp_value_copy( numeric_orig_value );
-    g_assert( numeric_copy_value );
-    g_assert( numeric_copy_value != numeric_orig_value );
-    g_assert( kvp_value_get_type( numeric_copy_value ) == KVP_TYPE_NUMERIC );
-    gnc_numeric_copy = kvp_value_get_numeric( numeric_copy_value );
-    g_assert_cmpfloat( gnc_numeric_copy.num, == , gnc_numeric_orig.num );
-    g_assert_cmpfloat( gnc_numeric_copy.denom, == , gnc_numeric_orig.denom );
-
-    string_copy_value = kvp_value_copy( string_orig_value );
-    g_assert( string_copy_value );
-    g_assert( string_copy_value != string_orig_value );
-    g_assert( kvp_value_get_type( string_copy_value ) == KVP_TYPE_STRING );
-    g_assert_cmpstr( kvp_value_get_string( string_copy_value ), == , "abcdefghijklmnop" );
-
-    guid_copy_value = kvp_value_copy( guid_orig_value );
-    g_assert( guid_copy_value );
-    g_assert( guid_copy_value != guid_orig_value );
-    g_assert( kvp_value_get_type( guid_copy_value ) == KVP_TYPE_GUID );
-    guid_copy = kvp_value_get_guid( guid_copy_value );
-    g_assert( guid_orig != guid_copy );
-    g_assert( guid_equal( guid_orig, guid_copy ) );
-
-    timespec_copy_value = kvp_value_copy( timespec_orig_value );
-    g_assert( timespec_copy_value );
-    g_assert( timespec_copy_value != timespec_orig_value );
-    g_assert( kvp_value_get_type( timespec_copy_value ) == KVP_TYPE_TIMESPEC );
-    ts_copy = kvp_value_get_timespec( timespec_copy_value );
-    g_assert_cmpfloat( ts_copy.tv_sec, == , ts_orig.tv_sec );
-    g_assert_cmpfloat( ts_copy.tv_nsec, == , ts_orig.tv_nsec );
-
-    glist_copy_value = kvp_value_copy( glist_orig_value );
-    g_assert( glist_copy_value );
-    g_assert( glist_copy_value != glist_orig_value );
-    g_assert( kvp_value_get_type( glist_copy_value ) == KVP_TYPE_GLIST );
-    list_copy = kvp_value_get_glist( glist_copy_value );
-    g_assert( list_copy != list_orig );
-    g_assert_cmpint( g_list_length( list_copy ), == , g_list_length( list_orig ) );
-    g_assert_cmpint( kvp_glist_compare( list_orig, list_copy ), == , 0 );
-
-    frame_copy_value = kvp_value_copy( frame_orig_value );
-    g_assert( frame_copy_value );
-    g_assert( frame_copy_value != frame_orig_value );
-    g_assert( kvp_value_get_type( frame_copy_value ) == KVP_TYPE_FRAME );
-    frame_copy = kvp_value_get_frame( frame_copy_value );
-    g_assert_cmpint( kvp_frame_compare( frame_orig, frame_copy ), == , 0 );
-
-    /* destroy objects */
-    kvp_value_delete( gint64_orig_value );
-    kvp_value_delete( double_orig_value );
-    kvp_value_delete( numeric_orig_value );
-    kvp_value_delete( string_orig_value );
-    kvp_value_delete( guid_orig_value );
-    kvp_value_delete( timespec_orig_value );
-    kvp_value_delete( glist_orig_value );
-    kvp_value_delete( frame_orig_value );
-
-    kvp_value_delete( gint64_copy_value );
-    kvp_value_delete( double_copy_value );
-    kvp_value_delete( numeric_copy_value );
-    kvp_value_delete( string_copy_value );
-    kvp_value_delete( guid_copy_value );
-    kvp_value_delete( timespec_copy_value );
-    kvp_value_delete( glist_copy_value );
-    kvp_value_delete( frame_copy_value );
-}
-
-static void
-test_kvp_glist_copy( void )
-{
-    GList *value_list = NULL, *copy_list = NULL, *lp1 = NULL, *lp2 = NULL;
-    KvpValue *gint64_value;
-    KvpValue *double_value;
-    KvpValue *numeric_value;
-    KvpValue *string_value;
-    KvpValue *guid_value;
-    KvpValue *timespec_value;
-    KvpValue *glist_value;
-    KvpValue *frame_value;
-
-    gnc_numeric gnc_numeric_orig;
-    GncGUID *guid_orig;
-    Timespec ts_orig;
-    GList *list_orig;
-    KvpFrame *frame_orig;
-
-    gnc_numeric_orig = gnc_numeric_zero();
-    guid_orig = guid_new();
-    ts_orig.tv_sec = 1;
-    ts_orig.tv_nsec = 1;
-    list_orig = NULL;
-    list_orig = g_list_append( list_orig, kvp_value_new_string( "abcdefghijklmnop" ) );
-    frame_orig = kvp_frame_new();
-
-    gint64_value = kvp_value_new_gint64( 2 );
-    double_value = kvp_value_new_double( 3.3 );
-    numeric_value = kvp_value_new_gnc_numeric( gnc_numeric_orig );
-    string_value = kvp_value_new_string( "abcdefghijklmnop" );
-    guid_value = kvp_value_new_guid( guid_orig );
-    timespec_value = kvp_value_new_timespec( ts_orig );
-    glist_value = kvp_value_new_glist( list_orig );
-    frame_value = kvp_value_new_frame( frame_orig );
-
-    value_list = g_list_append( value_list, gint64_value );
-    value_list = g_list_append( value_list, double_value );
-    value_list = g_list_append( value_list, numeric_value );
-    value_list = g_list_append( value_list, string_value );
-    value_list = g_list_append( value_list, guid_value );
-    value_list = g_list_append( value_list, timespec_value );
-    value_list = g_list_append( value_list, glist_value );
-    value_list = g_list_append( value_list, frame_value );
-    g_assert( value_list );
-    g_assert_cmpint( g_list_length( value_list ), == , 8 );
-
-    g_test_message( "Test list and all values are copied to new list" );
-    copy_list = kvp_glist_copy( value_list );
-    g_assert( copy_list );
-    g_assert( copy_list != value_list );
-    g_assert_cmpint( g_list_length( copy_list ), == , 8 );
-    lp1 = value_list;
-    lp2 = copy_list;
-    while (lp1 && lp2)
-    {
-        KvpValue *v1 = (KvpValue *) lp1->data;
-        KvpValue *v2 = (KvpValue *) lp2->data;
-        g_assert( v1 != v2 );
-        g_assert_cmpint( kvp_value_compare(v1, v2), == , 0 );
-        lp1 = lp1->next;
-        lp2 = lp2->next;
-    }
-    g_assert_cmpint( kvp_glist_compare( value_list, copy_list ), == , 0 );
-
-    /* destroy */
-    kvp_glist_delete( value_list );
-    kvp_glist_delete( copy_list );
-}
-
-static void
-test_kvp_glist_compare( void )
-{
-    GList *list1 = NULL, *list2 = NULL;
-
-    KvpValue *gint64_value;
-    KvpValue *double_value;
-    KvpValue *numeric_value;
-    KvpValue *string_value;
-    KvpValue *guid_value;
-    KvpValue *timespec_value;
-    KvpValue *glist_value;
-    KvpValue *frame_value;
-
-    gnc_numeric gnc_numeric_orig;
-    GncGUID *guid_orig;
-    Timespec ts_orig;
-    GList *list_orig;
-    KvpFrame *frame_orig;
-
-    gnc_numeric_orig = gnc_numeric_zero();
-    guid_orig = guid_new();
-    ts_orig.tv_sec = 1;
-    ts_orig.tv_nsec = 1;
-    list_orig = NULL;
-    list_orig = g_list_append( list_orig, kvp_value_new_string( "abcdefghijklmnop" ) );
-    frame_orig = kvp_frame_new();
-
-    gint64_value = kvp_value_new_gint64( 2 );
-    double_value = kvp_value_new_double( 3.3 );
-    numeric_value = kvp_value_new_gnc_numeric( gnc_numeric_orig );
-    string_value = kvp_value_new_string( "abcdefghijklmnop" );
-    guid_value = kvp_value_new_guid( guid_orig );
-    timespec_value = kvp_value_new_timespec( ts_orig );
-    glist_value = kvp_value_new_glist( list_orig );
-    frame_value = kvp_value_new_frame( frame_orig );
-
-    /* init list 1 */
-    list1 = g_list_append( list1, gint64_value );
-    list1 = g_list_append( list1, double_value );
-    list1 = g_list_append( list1, numeric_value );
-    list1 = g_list_append( list1, string_value );
-    list1 = g_list_append( list1, guid_value );
-    list1 = g_list_append( list1, timespec_value );
-    list1 = g_list_append( list1, glist_value );
-    list1 = g_list_append( list1, frame_value );
-    g_assert( list1 );
-    g_assert_cmpint( g_list_length( list1 ), == , 8 );
-
-    g_test_message( "Test when list is the same" );
-    list2 = list1;
-    g_assert_cmpint( kvp_glist_compare( list1, list2 ), == , 0 );
-
-    g_test_message( "Test when list1 is null" );
-    g_assert_cmpint( kvp_glist_compare( NULL, list2 ), == , -1 );
-
-    g_test_message( "Test when list2 is null" );
-    g_assert_cmpint( kvp_glist_compare( list1, NULL ), == , 1 );
-
-    g_test_message( "Copy list and test they are equal" );
-    list2 = kvp_glist_copy( list1 );
-    g_assert( list1 != list2 );
-    g_assert_cmpint( g_list_length( list1 ), == , g_list_length( list2 ) );
-    g_assert_cmpint( kvp_glist_compare( list1, list2 ), == , 0 );
-
-    g_test_message( "Test when list 1 is shorter lists are not equal" );
-    list1 = g_list_remove( list1, frame_value );
-    g_assert_cmpint( g_list_length( list1 ), == , 7 );
-    g_assert_cmpint( g_list_length( list2 ), == , 8 );
-    g_assert_cmpint( kvp_glist_compare( list1, list2 ), == , -1 );
-
-    g_test_message( "Test when list 2 is shorter lists are not equal" );
-    list1 = g_list_append( list1, frame_value );
-    list1 = g_list_append( list1, frame_value );
-    g_assert_cmpint( g_list_length( list1 ), == , 9 );
-    g_assert_cmpint( g_list_length( list2 ), == , 8 );
-    g_assert_cmpint( kvp_glist_compare( list1, list2 ), == , 1 );
-
-    g_test_message( "Test when data is not equal lists are not equal" );
-    list1 = g_list_remove( list1, frame_value );
-    g_assert_cmpint( g_list_length( list1 ), == , g_list_length( list2 ) );
-    g_assert_cmpint( kvp_glist_compare( list1, list2 ), == , 0 );
-    list1 = g_list_remove( list1, gint64_value );
-    kvp_value_delete( gint64_value );
-    list1 = g_list_prepend( list1, kvp_value_new_gint64( 5 ) );
-    g_assert_cmpint( g_list_length( list1 ), == , g_list_length( list2 ) );
-    g_assert_cmpint( kvp_glist_compare( list1, list2 ), != , 0 );
-
-    /* delete lists */
-    kvp_glist_delete( list1 );
-    kvp_glist_delete( list2 );
-}
-
-static void
-test_kvp_value_compare( void )
-{
-    KvpValue *gint64_orig_value, *gint64_copy_value;
-    KvpValue *double_orig_value, *double_copy_value;
-    KvpValue *numeric_orig_value, *numeric_copy_value;
-    KvpValue *string_orig_value, *string_copy_value;
-    KvpValue *guid_orig_value, *guid_copy_value;
-    KvpValue *timespec_orig_value, *timespec_copy_value;
-    KvpValue *glist_orig_value, *glist_copy_value;
-    KvpValue *frame_orig_value, *frame_copy_value;
-
-    /* data init */
-    gnc_numeric gnc_numeric_orig, gnc_numeric_copy;
-    GncGUID *guid_orig, *guid_copy;
-    Timespec ts_orig, ts_copy;
-    GList *list_orig, *list_copy;
-    KvpFrame *frame_orig, *frame_copy;
-
-    gnc_numeric_orig = gnc_numeric_zero();
-    gnc_numeric_copy = gnc_numeric_zero();
-    guid_orig = guid_new();
-    guid_copy = guid_new();
-    ts_orig.tv_sec = 1;
-    ts_orig.tv_nsec = 1;
-    ts_copy.tv_sec = 2;
-    ts_copy.tv_nsec = 2;
-    list_orig = NULL;
-    list_orig = g_list_append( list_orig, kvp_value_new_string( "abcdefghijklmnop" ) );
-    list_copy = NULL;
-    list_copy = g_list_append( list_copy, kvp_value_new_string( "abcdefg" ) );
-    frame_orig = kvp_frame_new();
-    frame_copy = kvp_frame_new();
-
-    gint64_orig_value = kvp_value_new_gint64( 2 );
-    gint64_copy_value = kvp_value_new_gint64( 5 );
-    double_orig_value = kvp_value_new_double( 3.3 );
-    double_copy_value = kvp_value_new_double( 3.5 );
-    numeric_orig_value = kvp_value_new_gnc_numeric( gnc_numeric_orig );
-    numeric_copy_value = kvp_value_new_gnc_numeric( gnc_numeric_copy );
-    string_orig_value = kvp_value_new_string( "abcdefghijklmnop" );
-    string_copy_value = kvp_value_new_string( "abcdefghijklmnop" );
-    guid_orig_value = kvp_value_new_guid( guid_orig );
-    guid_copy_value = kvp_value_new_guid( guid_copy );
-    timespec_orig_value = kvp_value_new_timespec( ts_orig );
-    timespec_copy_value = kvp_value_new_timespec( ts_copy );
-    glist_orig_value = kvp_value_new_glist( list_orig );
-    glist_copy_value = kvp_value_new_glist( list_copy );
-    frame_orig_value = kvp_value_new_frame( frame_orig );
-    frame_copy_value = kvp_value_new_frame( frame_copy );
-
-    g_test_message( "Test the same kvpvalue is equal" );
-    g_assert_cmpint( kvp_value_compare( gint64_orig_value, gint64_orig_value ), == , 0 );
-
-    g_test_message( "Test first value is null" );
-    g_assert_cmpint( kvp_value_compare( NULL, gint64_orig_value ), == , -1 );
-
-    g_test_message( "Test second value is null" );
-    g_assert_cmpint( kvp_value_compare( gint64_orig_value, NULL ), == , 1 );
-
-    g_test_message( "Test diffrent data types first is lesser" );
-    g_assert_cmpint( kvp_value_compare( gint64_orig_value, double_orig_value ), == , -1 );
-
-    g_test_message( "Test diffrent data types second is lesser" );
-    g_assert_cmpint( kvp_value_compare( double_orig_value, gint64_orig_value ), == , 1 );
-
-    /* testing all different cases of data equality is not the aim
-     * of this test. Rather we check that all data types are being compared.
-     */
-    g_test_message( "Test different kvpvalues of all the types" );
-    g_assert_cmpint( kvp_value_compare( gint64_orig_value, gint64_copy_value ), == , -1 );
-    g_assert_cmpint( kvp_value_compare( gint64_copy_value, gint64_orig_value ), == , 1 );
-    g_assert_cmpint( kvp_value_compare( double_orig_value, double_copy_value ), == , -1 );
-    g_assert_cmpint( kvp_value_compare( numeric_orig_value, numeric_copy_value ), == , gnc_numeric_compare( gnc_numeric_orig, gnc_numeric_copy ) );
-    g_assert_cmpint( kvp_value_compare( string_orig_value, string_copy_value ), == , strcmp( "abcdefghijklmnop", "abcdefghijklmnop" ) );
-    g_assert_cmpint( kvp_value_compare( guid_orig_value, guid_copy_value ), == , guid_compare( guid_orig, guid_copy ) );
-    g_assert_cmpint( kvp_value_compare( timespec_orig_value, timespec_copy_value ), == , timespec_cmp( &ts_orig, &ts_copy ) );
-    g_assert_cmpint( kvp_value_compare( glist_orig_value, glist_copy_value ), == , kvp_glist_compare( list_orig, list_copy ) );
-    g_assert_cmpint( kvp_value_compare( frame_orig_value, frame_copy_value ), == , kvp_frame_compare( frame_orig, frame_copy ) );
-
-    /* destroy objects */
-    kvp_value_delete( gint64_orig_value );
-    kvp_value_delete( double_orig_value );
-    kvp_value_delete( numeric_orig_value );
-    kvp_value_delete( string_orig_value );
-    kvp_value_delete( guid_orig_value );
-    kvp_value_delete( timespec_orig_value );
-    kvp_value_delete( glist_orig_value );
-    kvp_value_delete( frame_orig_value );
-
-    kvp_value_delete( gint64_copy_value );
-    kvp_value_delete( double_copy_value );
-    kvp_value_delete( numeric_copy_value );
-    kvp_value_delete( string_copy_value );
-    kvp_value_delete( guid_copy_value );
-    kvp_value_delete( timespec_copy_value );
-    kvp_value_delete( glist_copy_value );
-    kvp_value_delete( frame_copy_value );
-}
-
-static void
-test_kvp_value_new_foo_nc( void )
-{
-    KvpValue *glist_value_nc, *frame_value_nc;
-    void *val;
-    guint64 size;
-    GList *list = NULL;
-    KvpFrame *frame = NULL;
-
-    g_test_message( "Test new glist is not copied" );
-    list = g_list_append( list, kvp_value_new_gint64( 2 ) );
-    g_assert_cmpint( g_list_length( list ), == , 1 );
-    glist_value_nc = kvp_value_new_glist_nc( list );
-    g_assert( glist_value_nc );
-    g_assert( kvp_value_get_type( glist_value_nc ) == KVP_TYPE_GLIST );
-    g_assert( kvp_value_get_glist( glist_value_nc ) == list );
-
-    g_test_message( "Test new frame is not copied" );
-    frame = kvp_frame_new();
-    frame_value_nc = kvp_value_new_frame_nc( frame );
-    g_assert( frame_value_nc );
-    g_assert( kvp_value_get_type( frame_value_nc ) == KVP_TYPE_FRAME );
-    g_assert( kvp_value_get_frame( frame_value_nc ) == frame );
-
-    kvp_value_delete( glist_value_nc );
-    kvp_value_delete( frame_value_nc );
-}
-
-static void
-test_kvp_frame_compare( Fixture *fixture, gconstpointer pData )
-{
-    KvpFrame *cmp_frame = NULL;
-
-    cmp_frame = kvp_frame_new();
-    g_assert( cmp_frame );
-
-    g_test_message( "Test the same frame is equal with itself" );
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, fixture->frame ), == , 0 );
-
-    g_test_message( "Test first frame null second not null" );
-    g_assert_cmpint( kvp_frame_compare( NULL, fixture->frame ), == , -1 );
-
-    g_test_message( "Test first frame not null second null" );
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, NULL ), == , 1 );
-
-    g_test_message( "Test first frame is empty second not empty" );
-    kvp_frame_set_gint64( fixture->frame, "/test/test2", 64 );
-    g_assert( !kvp_frame_is_empty( fixture->frame ) );
-    g_assert( kvp_frame_is_empty( cmp_frame ) );
-    g_assert_cmpint( kvp_frame_compare( cmp_frame, fixture->frame ), == , -1 );
-
-    g_test_message( "Test first frame is not empty second is empty" );
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, cmp_frame ), == , 1 );
-
-    g_test_message( "Test when frames are equal" );
-    kvp_frame_set_gint64( cmp_frame, "/test/test2", 64 );
-    g_assert( !kvp_frame_is_empty( cmp_frame ) );
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, cmp_frame ), == , 0 );
-
-    g_test_message( "Test when frames have equal data but second frame has additional slot set" );
-    kvp_frame_set_string( fixture->frame, "/test/test3", "abcdefghijklmnop" );
-    g_assert_cmpint( kvp_frame_compare( cmp_frame, fixture->frame ), == , -1 );
-
-    g_test_message( "Test when frames have equal data but first frame has additional slot set" );
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, cmp_frame ), == , 1 );
-
-    g_test_message( "Test when frames have equal number of slots second frame has different data in one slot" );
-    kvp_frame_set_string( cmp_frame, "/test/test3", "abcdefg" );
-    g_assert_cmpint( kvp_frame_compare( cmp_frame, fixture->frame ), < , 0 );
-
-    g_test_message( "Test when frames have equal number of slots second frame has different data in one slot" );
-    g_assert_cmpint( kvp_frame_compare( fixture->frame, cmp_frame ), > , 0 );
-
-    kvp_frame_delete( cmp_frame );
-}
-
-static void
-test_kvp_value_to_string( void )
-{
-    gchar guidstr[GUID_ENCODING_LENGTH+1];
-    gchar *str_tmp2, *str_tmp3;
-    gchar *result;
-    KvpValue *gint64_value;
-    KvpValue *double_value;
-    KvpValue *numeric_value;
-    KvpValue *string_value;
-    KvpValue *guid_value;
-    KvpValue *timespec_value;
-    KvpValue *glist_value;
-    KvpValue *frame_value;
-
-    gnc_numeric gnc_numeric_orig;
-    GncGUID *guid_orig;
-    Timespec ts_orig;
-    GList *list_orig;
-    KvpFrame *frame_orig;
-
-    gnc_numeric_orig = gnc_numeric_zero();
-    guid_orig = guid_new();
-    ts_orig.tv_sec = 1;
-    ts_orig.tv_nsec = 1;
-    list_orig = NULL;
-    list_orig = g_list_append( list_orig, kvp_value_new_string( "abcdefghijklmnop" ) );
-    frame_orig = kvp_frame_new();
-
-    gint64_value = kvp_value_new_gint64( 2 );
-    double_value = kvp_value_new_double( 3.3 );
-    numeric_value = kvp_value_new_gnc_numeric( gnc_numeric_orig );
-    string_value = kvp_value_new_string( "abcdefghijklmnop" );
-    guid_value = kvp_value_new_guid( guid_orig );
-    timespec_value = kvp_value_new_timespec( ts_orig );
-    glist_value = kvp_value_new_glist( list_orig );
-    frame_value = kvp_value_new_frame( frame_orig );
-
-    g_test_message( "Test value string representation with different data types" );
-    result = kvp_value_to_string( gint64_value );
-    g_assert( result );
-    g_assert_cmpstr( result, == , "KVP_VALUE_GINT64(2)" );
-    g_free( result );
-
-    result = kvp_value_to_string( double_value );
-    g_assert( result );
-    g_assert_cmpstr( result, == , "KVP_VALUE_DOUBLE(3.3)" );
-    g_free( result );
-
-    result = kvp_value_to_string( numeric_value );
-    g_assert( result );
-    g_assert_cmpstr( result, == , "KVP_VALUE_NUMERIC(0/1)" );
-    g_free( result );
-
-    result = kvp_value_to_string( string_value );
-    g_assert( result );
-    g_assert_cmpstr( result, == , "KVP_VALUE_STRING(abcdefghijklmnop)" );
-    g_free( result );
-
-    result = kvp_value_to_string( guid_value );
-    g_assert( result );
-    guid_to_string_buff( kvp_value_get_guid( guid_value ), guidstr);
-    str_tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", guidstr);
-    g_assert_cmpstr( result, == , str_tmp2 );
-    g_free( result );
-    g_free( str_tmp2 );
-
-    result = kvp_value_to_string( timespec_value );
-    g_assert( result );
-    str_tmp2 = g_new0 (char, 40);
-    gnc_timespec_to_iso8601_buff( kvp_value_get_timespec( timespec_value ), str_tmp2 );
-    str_tmp3 = g_strdup_printf("KVP_VALUE_TIMESPEC(%s)", str_tmp2);
-    g_assert_cmpstr( result, == , str_tmp3 );
-    g_free( result );
-    g_free( str_tmp2 );
-    g_free( str_tmp3 );
-
-    result = kvp_value_to_string( glist_value );
-    g_assert( result );
-    g_assert_cmpstr( result, == , "KVP_VALUE_GLIST([  KVP_VALUE_STRING(abcdefghijklmnop), ])" );
-    g_free( result );
-
-    result = kvp_value_to_string( frame_value );
-    g_assert( result );
-    g_assert_cmpstr( result, == , "KVP_VALUE_FRAME({\n}\n)" );
-    g_free( result );
-
-    kvp_value_delete( gint64_value );
-    kvp_value_delete( double_value );
-    kvp_value_delete( numeric_value );
-    kvp_value_delete( string_value );
-    kvp_value_delete( guid_value );
-    kvp_value_delete( timespec_value );
-    kvp_value_delete( glist_value );
-    kvp_value_delete( frame_value );
-}
-
-static void
-test_kvp_frame_to_string( Fixture *fixture, gconstpointer pData )
-{
-    gchar *result;
-    gnc_numeric test_gnc_numeric;
-    GncGUID *test_guid;
-    Timespec test_ts;
-    KvpFrame *test_frame;
-
-    test_gnc_numeric = gnc_numeric_zero();
-    test_guid = guid_new();
-    test_ts.tv_sec = 1;
-    test_ts.tv_nsec = 1;
-    test_frame = kvp_frame_new();
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test empty frame" );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert_cmpstr( result, == , "{\n}\n" );
-    g_free( result );
-
-    /* slots can be randomly distributed in hash table
-     * instead of checking the whole return string we rather check if certain entries exist in it
-     */
-    g_test_message( "Test with all data types and nested frames" );
-    kvp_frame_set_gint64( fixture->frame, "/gint64-type", 2 );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    gint64-type => KVP_VALUE_GINT64(2),\n" ) != NULL );
-    g_free( result );
-
-    kvp_frame_set_double( fixture->frame, "/double-type", 3.3 );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    double-type => KVP_VALUE_DOUBLE(3.3),\n" ) != NULL );
-    g_free( result );
-
-    kvp_frame_set_numeric( fixture->frame, "/numeric-type", test_gnc_numeric );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    numeric-type => KVP_VALUE_NUMERIC(0/1),\n" ) != NULL );
-    g_free( result );
-
-    kvp_frame_set_timespec( fixture->frame, "/timespec-type", test_ts );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    timespec-type => KVP_VALUE_TIMESPEC" ) != NULL );
-    g_free( result );
-
-    kvp_frame_set_string( fixture->frame, "/string-type", "abcdefghijklmnop" );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    string-type => KVP_VALUE_STRING(abcdefghijklmnop),\n" ) != NULL );
-    g_free( result );
-
-    kvp_frame_set_guid( fixture->frame, "/guid-type", test_guid );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    guid-type => KVP_VALUE_GUID" ) != NULL );
-    g_free( result );
-
-    kvp_frame_set_frame( fixture->frame, "/nested/frame-type", test_frame );
-    result = kvp_frame_to_string( fixture->frame );
-    g_assert( g_strrstr( result, "    nested => KVP_VALUE_FRAME({\n    frame-type => KVP_VALUE_FRAME({\n}\n),\n}\n),\n" ) != NULL );
-    g_free( result );
-}
-
-static void
-test_kvp_frame_set_slot_path( Fixture *fixture, gconstpointer pData )
-{
-    KvpValue *input_value, *output_value;
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test with a simple value added to the empty frame" );
-    input_value = kvp_value_new_gint64( 2 );
-    kvp_frame_set_slot_path( fixture->frame, input_value, "test", NULL );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test", NULL );
-    g_assert( output_value );
-    g_assert( input_value != output_value ); /* copied */
-    g_assert_cmpint( kvp_value_compare( output_value, input_value ), == , 0 );
-    kvp_value_delete( input_value );
-
-    g_test_message( "Test when value is being replaced" );
-    input_value = kvp_value_new_double( 3.3 );
-    kvp_frame_set_slot_path( fixture->frame, input_value, "test", NULL );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test", NULL );
-    g_assert( output_value );
-    g_assert( input_value != output_value ); /* copied */
-    g_assert_cmpint( kvp_value_compare( output_value, input_value ), == , 0 ); /* old value removed */
-    kvp_value_delete( input_value );
-
-    g_test_message( "Test when existing path elements are not frames" );
-    input_value = kvp_value_new_string( "abcdefghijklmnop" );
-    kvp_frame_set_slot_path( fixture->frame, input_value, "test", "test2", NULL );
-    g_assert( kvp_frame_get_slot_path( fixture->frame, "test2", NULL ) == NULL );/* was not added */
-    g_assert_cmpint( kvp_value_compare( output_value, kvp_frame_get_slot_path( fixture->frame, "test", NULL ) ), == , 0 ); /* nothing changed */
-    kvp_value_delete( input_value );
-
-    g_test_message( "Test frames are created along the path when needed" );
-    input_value = kvp_value_new_string( "abcdefghijklmnop" );
-    kvp_frame_set_slot_path( fixture->frame, input_value, "test2", "test3", NULL );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test2", NULL );
-    g_assert( output_value );
-    g_assert( kvp_value_get_type( output_value ) == KVP_TYPE_FRAME );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test2", "test3", NULL );
-    g_assert( output_value );
-    g_assert( input_value != output_value ); /* copied */
-    g_assert_cmpint( kvp_value_compare( output_value, input_value ), == , 0 );
-    kvp_value_delete( input_value );
-}
-
-static void
-test_kvp_frame_set_slot_path_gslist( Fixture *fixture, gconstpointer pData )
-{
-    /* similar to previous test except path is passed as GSList*/
-    GSList *path_list = NULL;
-    KvpValue *input_value, *output_value;
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test with a simple value added to the empty frame" );
-    path_list = g_slist_append( path_list, "test" );
-    input_value = kvp_value_new_gint64( 2 );
-    kvp_frame_set_slot_path_gslist( fixture->frame, input_value, path_list );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test", NULL );
-    g_assert( output_value );
-    g_assert( input_value != output_value ); /* copied */
-    g_assert_cmpint( kvp_value_compare( output_value, input_value ), == , 0 );
-    kvp_value_delete( input_value );
-
-    g_test_message( "Test when value is being replaced" );
-    input_value = kvp_value_new_double( 3.3 );
-    kvp_frame_set_slot_path_gslist( fixture->frame, input_value, path_list );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test", NULL );
-    g_assert( output_value );
-    g_assert( input_value != output_value ); /* copied */
-    g_assert_cmpint( kvp_value_compare( output_value, input_value ), == , 0 ); /* old value removed */
-    kvp_value_delete( input_value );
-
-    g_test_message( "Test when existing path elements are not frames" );
-    path_list = g_slist_append( path_list, "test2");
-    input_value = kvp_value_new_string( "abcdefghijklmnop" );
-    kvp_frame_set_slot_path_gslist( fixture->frame, input_value, path_list );
-    g_assert( kvp_frame_get_slot_path( fixture->frame, "test2", NULL ) == NULL );/* was not added */
-    g_assert_cmpint( kvp_value_compare( output_value, kvp_frame_get_slot_path( fixture->frame, "test", NULL ) ), == , 0 ); /* nothing changed */
-    kvp_value_delete( input_value );
-
-    g_test_message( "Test frames are created along the path when needed" );
-    path_list = g_slist_remove( path_list, "test" );
-    path_list = g_slist_append( path_list, "test3");
-    input_value = kvp_value_new_string( "abcdefghijklmnop" );
-    kvp_frame_set_slot_path_gslist( fixture->frame, input_value, path_list );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test2", NULL );
-    g_assert( output_value );
-    g_assert( kvp_value_get_type( output_value ) == KVP_TYPE_FRAME );
-    output_value = kvp_frame_get_slot_path( fixture->frame, "test2", "test3", NULL );
-    g_assert( output_value );
-    g_assert( input_value != output_value ); /* copied */
-    g_assert_cmpint( kvp_value_compare( output_value, input_value ), == , 0 );
-    kvp_value_delete( input_value );
-
-    g_slist_free( path_list );
-}
-
-static void
-test_kvp_frame_replace_slot_nc( Fixture *fixture, gconstpointer pData )
-{
-    KvpValue *orig_value, *orig_value2;
-    const char ** keys;
-    /* test indirectly static function kvp_frame_replace_slot_nc */
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test when new value is created frame hash init and value stored in hash" );
-    orig_value = kvp_value_new_gint64( 2 );
-    kvp_frame_set_slot( fixture->frame, "test", orig_value );
-    g_assert( !kvp_frame_is_empty( fixture->frame ) );
-    keys = kvp_frame_get_keys( fixture->frame );
-    g_assert( keys );
-    g_assert( !keys[1] );
-    g_assert( orig_value != kvp_frame_get_value( fixture->frame, keys[0] ) );
-    g_assert_cmpint( kvp_value_compare( kvp_frame_get_value( fixture->frame, keys[0] ), orig_value ), ==, 0 );
-    g_free( keys );
-
-    g_test_message( "Test when value is replaced" );
-    orig_value2 = kvp_value_new_gint64( 5 );
-    kvp_frame_set_slot( fixture->frame, "test", orig_value2 );
-    keys = kvp_frame_get_keys( fixture->frame );
-    g_assert( keys );
-    g_assert( !keys[1] );
-    g_assert( orig_value != kvp_frame_get_value( fixture->frame, keys[0] ) );
-    g_assert_cmpint( kvp_value_compare( kvp_frame_get_value( fixture->frame, keys[0] ), orig_value2 ), ==, 0 );
-    g_assert_cmpint( kvp_value_compare( kvp_frame_get_value( fixture->frame, keys[0] ), orig_value ), !=, 0 );
-    g_free( keys );
-
-    kvp_value_delete( orig_value );
-    kvp_value_delete( orig_value2 );
-}
-
-static void
-test_get_trailer_make( Fixture *fixture, gconstpointer pData )
-{
-    char *last_key = NULL;
-    KvpValue *frame_value = NULL;
-    KvpFrame *frame = NULL, *frame2 = NULL;
-
-    g_test_message( "Test null frame and empty string checks" );
-    g_assert( p_get_trailer_make( NULL, "test", &last_key ) == NULL );
-    g_assert( !last_key );
-    g_assert( p_get_trailer_make( fixture->frame, NULL, &last_key ) == NULL );
-    g_assert( !last_key );
-    g_assert( p_get_trailer_make( fixture->frame, "", &last_key ) == NULL );
-    g_assert( !last_key );
-
-    g_test_message( "Test single frame on the path with no slash" );
-    g_assert( p_get_trailer_make( fixture->frame, "test", &last_key ) == fixture->frame );
-    g_assert_cmpstr( last_key, == , "test" );
-
-    g_test_message( "Test single frame on the path with slash" );
-    last_key = NULL;
-    g_assert( p_get_trailer_make( fixture->frame, "/test", &last_key ) == fixture->frame );
-    g_assert_cmpstr( last_key, == , "test" );
-
-    g_test_message( "Test path of trailing slash" );
-    last_key = NULL;
-    g_assert( p_get_trailer_make( fixture->frame, "test/", &last_key ) == NULL );
-    g_assert( !last_key );
-
-    g_test_message( "Test path of two entries: frame for test should be created" );
-    /* test is considered to be last frame on the path
-     * and it is returned. Currently it doesn't exist and will be created
-     * test2 is stripped away and returned as last entry of the path
-     */
-    last_key = NULL;
-    frame = p_get_trailer_make( fixture->frame, "/test/test2", &last_key );
-    g_assert( frame );
-    g_assert( frame != fixture->frame );
-    frame_value = kvp_frame_get_slot( fixture->frame, "test" );
-    g_assert( frame_value );
-    g_assert( kvp_value_get_frame( frame_value ) == frame );
-    frame_value = kvp_frame_get_slot( frame, "test2" );
-    g_assert( !frame_value );
-    g_assert_cmpstr( last_key, == , "test2" );
-
-    g_test_message( "Test path of two entries: test frame already exist" );
-    /* here test frame already exist and should be returned
-     */
-    last_key = NULL;
-    g_assert( frame == p_get_trailer_make( fixture->frame, "/test/test2", &last_key ) );
-    g_assert_cmpstr( last_key, == , "test2" );
-
-    g_test_message( "Test path of three entries: neither frame exist" );
-    /* test3 and test4 frames will be created. test4 will be created inside test3 frame
-     * while test3 inside fixture->frame. test4 will be returned
-     * test5 stripped away and returned in last_key
-     */
-    last_key = NULL;
-    frame = p_get_trailer_make( fixture->frame, "/test3/test4/test5", &last_key );
-    g_assert( frame );
-    g_assert( frame != fixture->frame );
-    frame_value = kvp_frame_get_slot( fixture->frame, "test3" );
-    g_assert( frame_value );
-    frame2 = kvp_value_get_frame( frame_value );
-    g_assert( frame2 != frame );
-    g_assert( frame2 != fixture->frame );
-    frame_value = kvp_frame_get_slot( frame2, "test4" );
-    g_assert( frame_value );
-    g_assert( kvp_value_get_frame( frame_value ) == frame );
-    frame_value = kvp_frame_get_slot( frame, "test5" );
-    g_assert( !frame_value );
-    g_assert_cmpstr( last_key, == , "test5" );
-}
-
-static void
-test_kvp_value_glist_to_string( Fixture *fixture, gconstpointer pData )
-{
-    /*
-     * kvp_value_glist_to_string and kvp_value_to_string call each other
-     */
-    GList *value_list = NULL;
-    gchar *result;
-
-    gnc_numeric gnc_numeric_orig;
-    GList *list_orig;
-    KvpFrame *frame_orig;
-
-    gnc_numeric_orig = gnc_numeric_zero();
-    list_orig = NULL;
-    list_orig = g_list_append( list_orig, kvp_value_new_string( "abcdefghijklmnop" ) );
-    frame_orig = kvp_frame_new();
-
-    g_test_message( "Test empty list" );
-    result = glist_to_string( value_list );
-    g_assert_cmpstr( result, == , "" );
-    g_free( result );
-
-    g_test_message( "Test list with simple and complex values" );
-    value_list = g_list_append( value_list, kvp_value_new_gint64( 2 ) );
-    value_list = g_list_append( value_list, kvp_value_new_double( 3.3 ) );
-    value_list = g_list_append( value_list, kvp_value_new_gnc_numeric( gnc_numeric_orig ) );
-    value_list = g_list_append( value_list, kvp_value_new_string( "abcdefghijklmnop" ) );
-    value_list = g_list_append( value_list, kvp_value_new_glist( list_orig ) );
-    value_list = g_list_append( value_list, kvp_value_new_frame( frame_orig ) );
-    g_assert( value_list );
-    g_assert_cmpint( g_list_length( value_list ), == , 6 );
-    result = glist_to_string( value_list );
-
-    g_assert_cmpstr( result, == , "KVP_VALUE_GLIST([  KVP_VALUE_GINT64(2), KVP_VALUE_DOUBLE(3.3), KVP_VALUE_NUMERIC(0/1), KVP_VALUE_STRING(abcdefghijklmnop), KVP_VALUE_GLIST([  KVP_VALUE_STRING(abcdefghijklmnop), ]), KVP_VALUE_FRAME({\n}\n), ])" );
-    g_free( result );
-
-    kvp_glist_delete( value_list );
-}
-
-static void
-test_get_or_make( Fixture *fixture, gconstpointer pData )
-{
-    KvpFrame *test_frame = NULL;
-
-    g_assert( fixture->frame );
-    g_assert( kvp_frame_is_empty( fixture->frame ) );
-
-    g_test_message( "Test new frame is created" );
-    test_frame = p_get_or_make( fixture->frame, "test" );
-    g_assert( test_frame );
-    g_assert( test_frame != fixture->frame );
-    g_assert( kvp_frame_get_frame( fixture->frame, "test" ) == test_frame );
-
-    g_test_message( "Test existing frame is returned" );
-    g_assert( test_frame == p_get_or_make( fixture->frame, "test" ) );
-    g_assert( kvp_frame_get_frame( fixture->frame, "test" ) == test_frame );
-}
-
-static void
-test_kvp_frame_get_frame_or_null_slash_trash( Fixture *fixture, gconstpointer pData )
-{
-    g_test_message( "Test null checks" );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( NULL, "test" ) == NULL );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( fixture->frame, NULL ) == NULL );
-
-    g_test_message( "Test single slash and trailing slash path" );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( fixture->frame, "/" ) == fixture->frame );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( fixture->frame, "////" ) == fixture->frame );
-
-    g_test_message( "Test non existing path" );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( fixture->frame, "/test" ) == NULL );
-
-    g_test_message( "Test existing path when value is not frame" );
-    kvp_frame_set_gint64( fixture->frame, "/test", 2 );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( fixture->frame, "/test" ) == NULL );
-
-    g_test_message( "Test existing path when value is frame" );
-    kvp_frame_set_frame( fixture->frame, "/test2", kvp_frame_new() );
-    g_assert( p_kvp_frame_get_frame_or_null_slash_trash( fixture->frame, "/test2" ) != NULL );
-}
-
-static void
-test_get_trailer_or_null( Fixture *fixture, gconstpointer pData )
-{
-    char *last_key = NULL;
-    KvpFrame *frame = NULL;
-    const KvpFrame* frame2 = NULL;
-
-    g_test_message( "Test null frame and empty string checks" );
-    g_assert( p_get_trailer_or_null( NULL, "test", &last_key ) == NULL );
-    g_assert( !last_key );
-    g_assert( p_get_trailer_or_null( fixture->frame, NULL, &last_key ) == NULL );
-    g_assert( !last_key );
-    g_assert( p_get_trailer_or_null( fixture->frame, "", &last_key ) == NULL );
-    g_assert( !last_key );
-
-    g_test_message( "Test single frame on the path with no slash" );
-    g_assert( p_get_trailer_or_null( fixture->frame, "test", &last_key ) == fixture->frame );
-    g_assert_cmpstr( last_key, == , "test" );
-
-    g_test_message( "Test single frame on the path with slash" );
-    last_key = NULL;
-    g_assert( p_get_trailer_or_null( fixture->frame, "/test", &last_key ) == fixture->frame );
-    g_assert_cmpstr( last_key, == , "test" );
-
-    g_test_message( "Test path of trailing slash" );
-    last_key = NULL;
-    g_assert( p_get_trailer_or_null( fixture->frame, "test/", &last_key ) == NULL );
-    g_assert( !last_key );
-
-    g_test_message( "Test with non existing path" );
-    last_key = NULL;
-    g_assert( p_get_trailer_or_null( fixture->frame, "/test/test2", &last_key ) == NULL );
-    g_assert_cmpstr( last_key, == , "test2" );
-
-    g_test_message( "Test with existing path" );
-    last_key = NULL;
-    frame = kvp_frame_new();
-    kvp_frame_set_frame( fixture->frame, "/test/test2", frame );
-    frame2 = p_get_trailer_or_null( fixture->frame, "/test/test2", &last_key );
-    g_assert( kvp_frame_get_frame( fixture->frame, "/test") == frame2 );
-    g_assert_cmpstr( last_key, == , "test2" );
-}
-
-static void
-test_kvp_frame_get_gvalue (Fixture *fixture, gconstpointer pData)
-{
-    KvpFrame *frame = fixture->frame;
-    GValue *value;
-    Timespec ts = {1, 1};
-    GncGUID *guid = populate_frame (frame);
-    GDate date;
-    gchar *log_domain = "qof.kvp";
-    gint log_level = G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL;
-    gchar *msg1 = "[gvalue_from_kvp_value()] Error! Attempt to transfer KvpFrame!";
-    gchar *msg2 = "[gvalue_from_kvp_value()] Error! Invalid KVP Transfer Request!";
-#undef _func
-    TestErrorStruct *check1 = test_error_struct_new (log_domain, log_level,
-							msg1);
-    TestErrorStruct *check2 = test_error_struct_new (log_domain, log_level,
-							msg2);
-    fixture->hdlrs = test_log_set_fatal_handler (fixture->hdlrs, check1,
-						 (GLogFunc)test_list_handler);
-    test_add_error (check1);
-    test_add_error (check2);
-
-    g_date_clear (&date, 1);
-    g_date_set_dmy (&date, 26, 1, 1957);
-
-    value = kvp_frame_get_gvalue (frame, "gint64-type");
-    g_assert (value != NULL);
-    g_assert (G_VALUE_HOLDS_INT64 (value));
-    g_assert_cmpint (g_value_get_int64 (value), ==, 100);
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "double-type");
-    g_assert (value != NULL);
-    g_assert (G_VALUE_HOLDS_DOUBLE (value));
-    g_assert_cmpfloat (g_value_get_double (value), ==, 3.14159);
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "numeric-type");
-    g_assert (value != NULL);
-    g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_NUMERIC);
-    g_assert (gnc_numeric_zero_p (*(gnc_numeric*)g_value_get_boxed (value)));
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "timespec-type");
-    g_assert (value != NULL);
-    g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_TIMESPEC);
-    g_assert (timespec_equal (&ts, (Timespec*)g_value_get_boxed (value)));
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "string-type");
-    g_assert (value != NULL);
-    g_assert (G_VALUE_HOLDS_STRING (value));
-    g_assert_cmpstr (g_value_get_string (value), ==, "abcdefghijklmnop");
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "guid-type");
-    g_assert (value != NULL);
-    g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_GUID);
-    g_assert (guid_equal (guid, (GncGUID*)g_value_get_boxed (value)));
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "gdate-type");
-    g_assert (value != NULL);
-    g_assert_cmpint (G_VALUE_TYPE (value), ==, G_TYPE_DATE);
-    g_assert_cmpint (g_date_compare (&date, (GDate*)g_value_get_boxed (value)), ==, 0);
-    gnc_gvalue_free (value);
-
-    value = kvp_frame_get_gvalue (frame, "frame-type");
-    g_assert (value == NULL);
-    g_assert_cmpint (check1->hits, ==, 1);
-    g_assert_cmpint (check2->hits, ==, 1);
-
-    value = kvp_frame_get_gvalue (frame, "list-type");
-    g_assert (value != NULL);
-    g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_VALUE_LIST);
-    {
-	GList *list = (GList*)g_value_get_boxed (value);
-	GValue *value = NULL;
-
-	value = (GValue*)(list->data);
-	g_assert (G_VALUE_HOLDS_INT64 (value));
-	g_assert (g_value_get_int64 (value) == 0x1f2e3d4c5b6a79LL);
-	list = g_list_next (list);
-
-	value = (GValue*)(list->data);
-	g_assert (G_VALUE_HOLDS_DOUBLE (value));
-	g_assert_cmpfloat (g_value_get_double (value), ==, 0.4342944819);
-	list = g_list_next (list);
-
-	value = (GValue*)(list->data);
-	g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_NUMERIC);
-	g_assert (gnc_numeric_eq (*(gnc_numeric*)g_value_get_boxed (value),
-				  gnc_numeric_create (256, 120)));
-	list = g_list_next (list);
-
-	value = (GValue*)(list->data);
-	g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_TIMESPEC);
-	g_assert (timespec_equal (&ts, (Timespec*)g_value_get_boxed (value)));
-	list = g_list_next (list);
-
-	value = (GValue*)(list->data);
-	g_assert (G_VALUE_HOLDS_STRING (value));
-	g_assert_cmpstr (g_value_get_string (value), ==, "qrstuvwxyz");
-	list = g_list_next (list);
-
-	value = (GValue*)(list->data);
-	g_assert_cmpint (G_VALUE_TYPE (value), ==, GNC_TYPE_GUID);
-	g_assert (guid_equal (guid, (GncGUID*)g_value_get_boxed (value)));
-	list = g_list_next (list);
-
-	g_assert (list == NULL);
-
-    }
-    gnc_gvalue_free (value);
-}
-
-static void
-test_kvp_frame_set_gvalue (Fixture *fixture, gconstpointer pData)
-{
-/* Bit of a shortcut: We'll use kvp_frame_get_item to make our KvpItem
- * and feed it into a new frame; something of a round-trip test.
- */
-    KvpFrame *o_frame = fixture->frame;
-    KvpFrame *n_frame = kvp_frame_new ();
-    GValue *value;
-    GList *o_list, *n_list;
-
-    populate_frame (o_frame);
-
-    value = kvp_frame_get_gvalue (o_frame, "gint64-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "gint64-type", value);
-    g_assert_cmpint (kvp_frame_get_gint64 (o_frame, "gint64-type"), ==,
-		     kvp_frame_get_gint64 (n_frame, "gint64-type"));
-
-    value = kvp_frame_get_gvalue (o_frame, "double-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "double-type", value);
-    g_assert_cmpint (kvp_frame_get_double (o_frame, "double-type"), ==,
-		     kvp_frame_get_double (n_frame, "double-type"));
-
-    value = kvp_frame_get_gvalue (o_frame, "numeric-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "numeric-type", value);
-    g_assert (gnc_numeric_equal (kvp_frame_get_numeric (o_frame, "numeric-type"),
-				 kvp_frame_get_numeric (n_frame, "numeric-type")));
-
-    value = kvp_frame_get_gvalue (o_frame, "timespec-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "timespec-type", value);
-    {
-	Timespec o_ts = kvp_frame_get_timespec (o_frame, "timespec-type");
-	Timespec n_ts = kvp_frame_get_timespec (n_frame, "timespec-type");
-	g_assert (timespec_equal (&o_ts, &n_ts));
-    }
-
-    value = kvp_frame_get_gvalue (o_frame, "string-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "string-type", value);
-    g_assert_cmpstr (kvp_frame_get_string (o_frame, "string-type"), ==,
-		     kvp_frame_get_string (n_frame, "string-type"));
-
-    value = kvp_frame_get_gvalue (o_frame, "gdate-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "gdate-type", value);
-    {
-	GDate o_date = kvp_value_get_gdate (kvp_frame_get_slot (o_frame,
-								"gdate-type"));
-	GDate n_date = kvp_value_get_gdate (kvp_frame_get_slot (n_frame,
-								"gdate-type"));
-	g_assert_cmpint (g_date_compare (&o_date, &n_date), ==, 0);
-    }
-
-    value = kvp_frame_get_gvalue (o_frame, "guid-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "guid-type", value);
-    g_assert (guid_equal (kvp_frame_get_guid (o_frame, "guid-type"),
-			  kvp_frame_get_guid (n_frame, "guid-type")));
-
-    value = kvp_frame_get_gvalue (o_frame, "list-type");
-    g_assert (value != NULL);
-    kvp_frame_set_gvalue (n_frame, "list-type", value);
-    o_list = kvp_value_get_glist (kvp_frame_get_slot (o_frame, "list_type"));
-    n_list = kvp_value_get_glist (kvp_frame_get_slot (n_frame, "list_type"));
-
-    g_assert_cmpint (g_list_length (o_list), ==, g_list_length (n_list));
-    while (o_list && n_list)
-    {
-	g_assert_cmpint (kvp_value_compare ((KvpValue*)o_list->data,
-					    (KvpValue*)n_list->data), ==, 0);
-	o_list = g_list_next (o_list);
-	n_list = g_list_next (n_list);
-    }
-    kvp_frame_delete (n_frame);
-}
-
-static void
-test_kvp_frame_get_keys( void )
-{
-    KvpFrame * frame = kvp_frame_new();
-    const char * key1 = "number one";
-    const char * key2 = "number one/number two";
-    const char * key3 = "number three";
-    const char * val1 = "Value1";
-    const char * val2 = "Value2";
-    const char * val3 = "Value3";
-    unsigned int spot = 0;
-    const char ** keys;
-    kvp_frame_set_string(frame, key1, val1);
-    kvp_frame_set_string(frame, key2, val2);
-    kvp_frame_set_string(frame, key3, val3);
-    keys = kvp_frame_get_keys(frame);
-
-    g_assert(keys);
-    g_assert(keys[spot]);
-    g_assert(strcmp(keys[spot++], val1));
-    g_assert(keys[spot]);
-    g_assert(strcmp(keys[spot++], val3));
-    g_assert(!keys[spot]);
-
-    g_free(keys);
-    kvp_frame_delete(frame);
-}
-
-void
-test_suite_kvp_frame( void )
-{
-    GNC_TEST_ADD_FUNC( suitename, "kvp frame new and delete", test_kvp_frame_new_delete );
-    GNC_TEST_ADD( suitename, "kvp frame copy", Fixture, NULL, setup, test_kvp_frame_copy, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame set foo", Fixture, NULL, setup, test_kvp_frame_set_foo, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame get frame slash", Fixture, NULL, setup, test_kvp_frame_get_frame_slash, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame get slot path", Fixture, NULL, setup, test_kvp_frame_get_slot_path, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame get slot path gslist", Fixture, NULL, setup, test_kvp_frame_get_slot_path_gslist, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame add frame nc", Fixture, NULL, setup, test_kvp_frame_add_frame_nc, teardown );
-    GNC_TEST_ADD_FUNC( suitename, "kvp value copy", test_kvp_value_copy );
-    GNC_TEST_ADD_FUNC( suitename, "kvp glist copy", test_kvp_glist_copy );
-    GNC_TEST_ADD_FUNC( suitename, "kvp glist compare", test_kvp_glist_compare );
-    GNC_TEST_ADD_FUNC( suitename, "kvp value compare", test_kvp_value_compare );
-    GNC_TEST_ADD_FUNC( suitename, "kvp value new foo no copy", test_kvp_value_new_foo_nc );
-    GNC_TEST_ADD( suitename, "kvp frame compare", Fixture, NULL, setup, test_kvp_frame_compare, teardown );
-    GNC_TEST_ADD_FUNC( suitename, "kvp value to string", test_kvp_value_to_string );
-    GNC_TEST_ADD( suitename, "kvp frame to string", Fixture, NULL, setup, test_kvp_frame_to_string, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame set slot path", Fixture, NULL, setup, test_kvp_frame_set_slot_path, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame set slot path gslist", Fixture, NULL, setup, test_kvp_frame_set_slot_path_gslist, teardown );
-    GNC_TEST_ADD( suitename, "kvp frame replace slot nc", Fixture, NULL, setup, test_kvp_frame_replace_slot_nc, teardown );
-    GNC_TEST_ADD_FUNC( suitename, "kvp frame get keys", test_kvp_frame_get_keys );
-    GNC_TEST_ADD( suitename, "get trailer make", Fixture, NULL, setup_static, test_get_trailer_make, teardown_static );
-    GNC_TEST_ADD( suitename, "kvp value glist to string", Fixture, NULL, setup_static, test_kvp_value_glist_to_string, teardown_static );
-    GNC_TEST_ADD( suitename, "get or make", Fixture, NULL, setup_static, test_get_or_make, teardown_static );
-    GNC_TEST_ADD( suitename, "kvp frame get frame or null slash trash", Fixture, NULL, setup_static, test_kvp_frame_get_frame_or_null_slash_trash, teardown_static );
-    GNC_TEST_ADD( suitename, "get trailer or null", Fixture, NULL, setup_static, test_get_trailer_or_null, teardown_static );
-    GNC_TEST_ADD ( suitename, "kvp frame get gvalue", Fixture, NULL, setup, test_kvp_frame_get_gvalue, teardown);
-    GNC_TEST_ADD ( suitename, "kvp frame set gvalue", Fixture, NULL, setup, test_kvp_frame_set_gvalue, teardown);
-}
diff --git a/src/libqof/qof/test/test-qof.c b/src/libqof/qof/test/test-qof.c
index b019e6c..cd7ce43 100644
--- a/src/libqof/qof/test/test-qof.c
+++ b/src/libqof/qof/test/test-qof.c
@@ -27,7 +27,6 @@
 
 extern void test_suite_qofbook();
 extern void test_suite_qofinstance();
-extern void test_suite_kvp_frame();
 extern void test_suite_qofobject();
 extern void test_suite_qofsession();
 extern void test_suite_gnc_date();
@@ -47,7 +46,6 @@ main (int   argc,
     test_suite_gnc_guid();
     test_suite_qofbook();
     test_suite_qofinstance();
-    test_suite_kvp_frame();
     test_suite_qofobject();
     test_suite_qofsession();
     test_suite_gnc_date();
diff --git a/src/libqof/qof/test/test-qofinstance.c b/src/libqof/qof/test/test-qofinstance.cpp
similarity index 93%
rename from src/libqof/qof/test/test-qofinstance.c
rename to src/libqof/qof/test/test-qofinstance.cpp
index ab1e630..a25a904 100644
--- a/src/libqof/qof/test/test-qofinstance.c
+++ b/src/libqof/qof/test/test-qofinstance.cpp
@@ -19,15 +19,17 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
+extern "C"
+{
 #include <config.h>
 #include <glib.h>
 #include <unittest-support.h>
 #include "../qof.h"
 #include "../qofbackend-p.h"
-#include "../kvp_frame.h"
-
+}
+#include "../kvp_frame.hpp"
 static const gchar *suitename = "/qof/qofinstance";
-void test_suite_qofinstance ( void );
+extern "C" void test_suite_qofinstance ( void );
 static gchar* error_message;
 static gboolean is_called;
 
@@ -56,7 +58,7 @@ fatal_handler ( const char * log_domain,
 static void
 setup( Fixture *fixture, gconstpointer pData )
 {
-    fixture->inst = g_object_new(QOF_TYPE_INSTANCE, NULL);
+    fixture->inst = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE, NULL));
 }
 
 static void
@@ -122,16 +124,16 @@ test_instance_new_destroy( void )
     QofInstanceClass *klass;
     /* test var */
     Timespec *timespec_priv;
-    gchar *msg1 = "qof_instance_get_collection: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
-    gchar *msg2 = "qof_instance_get_editlevel: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
-    gchar *msg3 = "qof_instance_get_destroying: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
-    gchar *msg4 = "qof_instance_get_dirty_flag: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
-    gchar *log_domain = "qof";
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL, hdlr;
-    TestErrorStruct check = { loglevel, log_domain, msg1 };
+    const char *msg1 = "qof_instance_get_collection: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
+    const char *msg2 = "qof_instance_get_editlevel: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
+    const char *msg3 = "qof_instance_get_destroying: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
+    const char *msg4 = "qof_instance_get_dirty_flag: assertion " _Q "QOF_IS_INSTANCE(ptr)' failed";
+    const char *log_domain = "qof";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new(log_domain, loglevel, msg1);
 
     g_test_message( "Testing qofinstance object initialization" );
-    inst = g_object_new(QOF_TYPE_INSTANCE, NULL);
+    inst = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE, NULL));
     g_assert( QOF_IS_INSTANCE( inst ) );
     /* test class fields */
     klass = QOF_INSTANCE_GET_CLASS( inst );
@@ -162,27 +164,31 @@ test_instance_new_destroy( void )
     g_assert( !QOF_IS_INSTANCE( inst ) );
     /* set fatal handler */
     g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )fatal_handler, NULL );
-    hdlr = g_log_set_handler (log_domain, loglevel,
-                              (GLogFunc)test_checked_handler, &check);
+    auto hdlr = g_log_set_handler (log_domain, loglevel,
+                                   (GLogFunc)test_checked_handler, check);
     g_assert( qof_instance_get_collection( inst ) == NULL );
     g_assert( g_strrstr( error_message, "assertion " _Q "QOF_IS_INSTANCE(ptr)' failed" ) != NULL );
     g_free( error_message );
 
-    check.msg = msg2;
+    g_free(check->msg);
+    check->msg = g_strdup(msg2);
     g_assert_cmpint( qof_instance_get_editlevel( inst ), == , 0 );
     g_assert( g_strrstr( error_message, "assertion " _Q "QOF_IS_INSTANCE(ptr)' failed" ) != NULL );
     g_free( error_message );
 
-    check.msg = msg3;
+    g_free(check->msg);
+    check->msg = g_strdup(msg3);
     g_assert( !qof_instance_get_destroying( inst ) );
     g_assert( g_strrstr( error_message, "assertion " _Q "QOF_IS_INSTANCE(ptr)' failed" ) != NULL );
     g_free( error_message );
 
-    check.msg = msg4;
+    g_free(check->msg);
+    check->msg = g_strdup(msg4);
     g_assert( !qof_instance_get_dirty_flag( inst ) );
     g_assert( g_strrstr( error_message, "assertion " _Q "QOF_IS_INSTANCE(ptr)' failed" ) != NULL );
     g_free( error_message );
     g_log_remove_handler (log_domain, hdlr);
+    test_error_struct_free(check);
 }
 
 static void
@@ -197,7 +203,7 @@ test_instance_init_data( void )
     char guid_id_after[GUID_ENCODING_LENGTH + 1];
 
     /* set up */
-    inst = g_object_new( QOF_TYPE_INSTANCE, NULL );
+    inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
     g_assert( QOF_IS_INSTANCE( inst ) );
     book = qof_book_new();
     g_assert( QOF_IS_BOOK( book ) );
@@ -244,7 +250,7 @@ test_instance_get_set_slots( Fixture *fixture, gconstpointer pData )
     g_assert( qof_instance_get_dirty_flag( fixture->inst ) );
 
     g_test_message( "Test when kvp frame is not the same" );
-    kvp_frame2 = kvp_frame_new();
+    kvp_frame2 = new KvpFrame;
     g_assert( kvp_frame != kvp_frame2 );
     qof_instance_set_slots( fixture->inst, kvp_frame2 );
     g_assert( kvp_frame2 == qof_instance_get_slots( fixture->inst ) );
@@ -265,8 +271,8 @@ test_instance_version_cmp( void )
     Timespec timespec_left, timespec_right;
 
     /* set up*/
-    left = g_object_new( QOF_TYPE_INSTANCE, NULL );
-    right = g_object_new( QOF_TYPE_INSTANCE, NULL );
+    left = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
+    right = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
 
     g_test_message( "Test both null" );
     result = qof_instance_version_cmp( NULL, NULL );
@@ -498,10 +504,10 @@ static void
 test_instance_commit_edit( Fixture *fixture, gconstpointer pData )
 {
     gboolean result;
-    gchar *msg = "[qof_commit_edit()] unbalanced call - resetting (was -2)";
-    gchar *log_domain = "qof.engine";
-    guint loglevel = G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL, hdlr;
-    TestErrorStruct check = { loglevel, log_domain, msg };
+    const gchar *msg = "[qof_commit_edit()] unbalanced call - resetting (was -2)";
+    const gchar *log_domain = "qof.engine";
+    auto loglevel = static_cast<GLogLevelFlags>(G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_FATAL);
+    auto check = test_error_struct_new(log_domain, loglevel, msg);
 
     g_test_message( "Test when instance set to null" );
     result = qof_commit_edit( NULL );
@@ -522,8 +528,8 @@ test_instance_commit_edit( Fixture *fixture, gconstpointer pData )
 
     g_test_message( "Test when instance's editlevel < 0" );
     g_test_log_set_fatal_handler ( ( GTestLogFatalFunc )fatal_handler, NULL );
-    hdlr = g_log_set_handler (log_domain, loglevel,
-                              (GLogFunc)test_checked_handler, &check);
+    auto hdlr = g_log_set_handler (log_domain, loglevel,
+                                   (GLogFunc)test_checked_handler, check);
     qof_instance_decrease_editlevel( fixture->inst );
     g_assert_cmpint( qof_instance_get_editlevel( fixture->inst ), == , -1 );
     result = qof_commit_edit( fixture->inst );
@@ -531,6 +537,7 @@ test_instance_commit_edit( Fixture *fixture, gconstpointer pData )
     g_assert_cmpstr( error_message, == , "[qof_commit_edit()] unbalanced call - resetting (was -2)" );
     g_free( error_message );
     g_log_remove_handler (log_domain, hdlr);
+    test_error_struct_free(check);
 }
 
 /* backend commit test start */
@@ -728,7 +735,7 @@ test_instance_refers_to_object( Fixture *fixture, gconstpointer pData )
 {
     QofInstance * ref;
 
-    ref = g_object_new( QOF_TYPE_INSTANCE, NULL );
+    ref = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
     g_assert( fixture->inst );
     g_assert( ref );
     g_assert( QOF_INSTANCE_GET_CLASS( fixture->inst )->refers_to_object == NULL );
@@ -784,7 +791,7 @@ test_instance_get_referring_object_list_from_collection( void )
     book = qof_book_new();
     g_assert( book );
     g_assert( QOF_IS_BOOK( book ) );
-    ref =  g_object_new( QOF_TYPE_INSTANCE, NULL );
+    ref =  static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
     g_assert( ref );
     g_assert( QOF_IS_INSTANCE( ref ) );
     QOF_INSTANCE_GET_CLASS( ref )->refers_to_object = NULL;
@@ -795,7 +802,7 @@ test_instance_get_referring_object_list_from_collection( void )
      */
     for (i = 0; i < list_length; i++ )
     {
-        QofInstance *inst = g_object_new( QOF_TYPE_INSTANCE, NULL );
+        auto inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
         g_assert( inst );
         qof_instance_init_data( inst, type, book );
         inst_list = g_list_append ( inst_list, inst );
@@ -860,8 +867,8 @@ test_instance_get_typed_referring_object_list( void )
     GList* result = NULL;
 
     /* setup */
-    inst = g_object_new( QOF_TYPE_INSTANCE, NULL );
-    ref = g_object_new( QOF_TYPE_INSTANCE, NULL );
+    inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
+    ref = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
     book = qof_book_new();
     g_assert( inst );
     g_assert( ref );
@@ -945,9 +952,9 @@ test_instance_get_referring_object_list( void )
     book = qof_book_new();
     g_assert( book );
     g_assert( QOF_IS_BOOK( book ) );
-    ref1 = g_object_new( QOF_TYPE_INSTANCE, NULL );
+    ref1 = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
     g_assert( ref1 );
-    ref2 = g_object_new( QOF_TYPE_INSTANCE, NULL );
+    ref2 = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
     g_assert( ref2 );
     qof_instance_init_data( ref1, type1, book );
     qof_instance_init_data( ref2, type2, book );
@@ -963,7 +970,7 @@ test_instance_get_referring_object_list( void )
      */
     for (i = 0; i < col1_length; i++ )
     {
-        QofInstance *inst = g_object_new( QOF_TYPE_INSTANCE, NULL );
+        auto inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
         g_assert( inst );
         qof_instance_init_data( inst, type1, book );
         inst_list1 = g_list_append ( inst_list1, inst );
@@ -974,7 +981,7 @@ test_instance_get_referring_object_list( void )
 
     for (j = 0; j < col2_length; j++ )
     {
-        QofInstance *inst = g_object_new( QOF_TYPE_INSTANCE, NULL );
+        auto inst = static_cast<QofInstance*>(g_object_new( QOF_TYPE_INSTANCE, NULL ));
         g_assert( inst );
         qof_instance_init_data( inst, type2, book );
         inst_list2 = g_list_append ( inst_list2, inst );
@@ -1046,7 +1053,7 @@ test_instance_get_referring_object_list( void )
     qof_book_destroy( book );
 }
 
-void
+extern "C" void
 test_suite_qofinstance ( void )
 {
     GNC_TEST_ADD( suitename, "set get book", Fixture, NULL, setup, test_instance_set_get_book, teardown );
diff --git a/src/test-core/test-stuff.h b/src/test-core/test-stuff.h
index 8ef9d4b..c7fa548 100644
--- a/src/test-core/test-stuff.h
+++ b/src/test-core/test-stuff.h
@@ -37,21 +37,6 @@ Otherwise, only failures are printed out.
 #include <glib.h>
 #include <stdlib.h>
 
-/**
- * Use this to indicate the result of a test.
- * The result is TRUE for success, FALSE for failure.
- * title describes the test
- * Tests are automatically identified by their source file and line.
- */
-#define do_test( result, title ) do_test_call( result, title, __FILE__, __LINE__ )
-#define success( title ) success_call( title, __FILE__, __LINE__ );
-#define failure( title ) failure_call( title, __FILE__, __LINE__ );
-
-/** This one doesn't work because macros can't take a variable number of arguments.
- * well, apparently gcc can, but it's non-standard.
- * Apparently C99 can, too, but it's not exactly standard either.
-#define do_test_args( result, title, format ) do_test_call( result, title, __FILE__, __LINE__, format, ... );
-*/
 
 
 /* Privately used to indicate a test result. You may use these if you
@@ -117,6 +102,22 @@ void failure_args(
     const char *format,
     ... );
 
+/**
+ * Use this to indicate the result of a test.
+ * The result is TRUE for success, FALSE for failure.
+ * title describes the test
+ * Tests are automatically identified by their source file and line.
+ */
+#define do_test( result, title ) do_test_call( result, title, __FILE__, __LINE__ )
+#define success( title ) success_call( title, __FILE__, __LINE__ );
+#define failure( title ) failure_call( title, __FILE__, __LINE__ );
+
+/** This one doesn't work because macros can't take a variable number of arguments.
+ * well, apparently gcc can, but it's non-standard.
+ * Apparently C99 can, too, but it's not exactly standard either.
+#define do_test_args( result, title, format ) do_test_call( result, title, __FILE__, __LINE__, format, ... );
+*/
+
 gboolean get_random_boolean(void);
 gint get_random_int_in_range(int start, int end);
 void random_character_include_funky_chars (gboolean use_funky_chars);
diff --git a/src/test-core/unittest-support.c b/src/test-core/unittest-support.c
index 8e257ba..86cbe44 100644
--- a/src/test-core/unittest-support.c
+++ b/src/test-core/unittest-support.c
@@ -29,7 +29,7 @@ typedef struct
 {
     gpointer data;
     gboolean called;
-    gchar *msg;
+    char *msg;
 } TestStruct;
 
 static TestStruct tdata;
@@ -41,7 +41,8 @@ test_list_nohit_handler (const char *log_domain, GLogLevelFlags log_level,
                          const gchar *msg, gpointer user_data);
 
 TestErrorStruct*
-test_error_struct_new (gchar *log_domain, GLogLevelFlags log_level, gchar *msg)
+test_error_struct_new (const char *log_domain, GLogLevelFlags log_level,
+                       const char *msg)
 {
     TestErrorStruct *err = g_slice_new0 (TestErrorStruct);
     err->log_domain = g_strdup (log_domain);
diff --git a/src/test-core/unittest-support.h b/src/test-core/unittest-support.h
index fa4d07b..9d6ded8 100644
--- a/src/test-core/unittest-support.h
+++ b/src/test-core/unittest-support.h
@@ -87,8 +87,8 @@
 typedef struct
 {
     GLogLevelFlags log_level;
-    gchar *log_domain;
-    gchar *msg;
+    char *log_domain;
+    char *msg;
     guint hits;
 } TestErrorStruct;
 
@@ -105,9 +105,9 @@ typedef struct
  * @param msg: The exact error message that the logger will emit
  * @return: A TestErrorStruct *
  */
-TestErrorStruct* test_error_struct_new (gchar *log_domain,
-                                        GLogLevelFlags log_level,
-                                        gchar *msg);
+TestErrorStruct* test_error_struct_new (const char *log_domain,
+                                        const GLogLevelFlags log_level,
+                                        const char *msg);
 
 /**
  * Free a TestErrorStruct created with test_error_struct_new

commit fd935d3b8273aaa62890315a631482b5c4e82752
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 23 17:09:51 2015 -0700

    Convert libqof kvp calls to C++.

diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 28b58ed..257d30f 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -270,10 +270,11 @@ set_slot_from_value( slot_info_t *pInfo, KvpValue *pValue)
         auto frame = pInfo->pKvpFrame;
         if ( path )
         {
-            frame = frame->get_slot(path)->get<KvpFrame*>();
+            frame->set_path({path, key}, pValue);
             g_free( path );
         }
-        frame->set(key, pValue);
+        else
+            frame->set(key, pValue);
         g_free( key );
         break;
     }
diff --git a/src/libqof/qof/gnc-aqbanking-templates.cpp b/src/libqof/qof/gnc-aqbanking-templates.cpp
index 42f4569..21bd057 100644
--- a/src/libqof/qof/gnc-aqbanking-templates.cpp
+++ b/src/libqof/qof/gnc-aqbanking-templates.cpp
@@ -30,10 +30,10 @@
 extern "C"
 {
 #include "gnc-aqbanking-templates.h"
-#include "kvp_frame.h"
 #include "qofinstance-p.h"
 }
 
+#include "kvp_frame.hpp"
 #include "gnc-rational.hpp"
 
 namespace {
@@ -106,18 +106,13 @@ KvpFrame*
 _GncABTransTempl::make_kvp_frame()
 {
     auto frame = kvp_frame_new();
-    kvp_frame_set_slot(frame, TT_NAME, kvp_value_new_string(m_name.c_str()));
-    kvp_frame_set_slot(frame, TT_RNAME,
-                       kvp_value_new_string(m_recipient_name.c_str()));
-    kvp_frame_set_slot(frame, TT_RACC,
-                       kvp_value_new_string(m_recipient_account.c_str()));
-    kvp_frame_set_slot(frame, TT_RBCODE,
-                       kvp_value_new_string(m_recipient_bankcode.c_str()));
-    kvp_frame_set_slot(frame, TT_AMOUNT, kvp_value_new_gnc_numeric(m_amount));
-    kvp_frame_set_slot(frame, TT_PURPOS,
-                       kvp_value_new_string(m_purpose.c_str()));
-    kvp_frame_set_slot(frame, TT_PURPOSCT,
-                       kvp_value_new_string(m_purpose_continuation.c_str()));
+    frame->set(TT_NAME, new KvpValue(m_name.c_str()));
+    frame->set(TT_RNAME, new KvpValue(m_recipient_name.c_str()));
+    frame->set(TT_RACC, new KvpValue(m_recipient_account.c_str()));
+    frame->set(TT_RBCODE, new KvpValue(m_recipient_bankcode.c_str()));
+    frame->set(TT_AMOUNT, new KvpValue(m_amount));
+    frame->set(TT_PURPOS, new KvpValue(m_purpose.c_str()));
+    frame->set(TT_PURPOSCT, new KvpValue(m_purpose_continuation.c_str()));
     return frame;
 }
 
@@ -141,19 +136,25 @@ GList*
 gnc_ab_trans_templ_list_new_from_book(QofBook *b)
 {
     GList *retval = NULL;
-    KvpFrame *toplevel = qof_instance_get_slots (QOF_INSTANCE (b));
-    KvpFrame *hbci = kvp_frame_get_frame (toplevel, "hbci");
-    KvpValue *listval = kvp_frame_get_slot (hbci, "template-list");
-    GList *list = kvp_value_get_glist (listval);
+    auto toplevel = qof_instance_get_slots (QOF_INSTANCE (b));
+    auto slot = toplevel->get_slot({"hbci", "template-list"});
+    if (slot == nullptr)
+        return retval;
+    auto list = slot->get<GList*>();
     for (auto node = list; node != NULL; node = g_list_next (node))
     {
-        KvpFrame *frame = kvp_value_get_frame (static_cast<KvpValue*>(node->data));
-        auto func = [frame](const char* key)
-            {return kvp_value_get_string(kvp_frame_get_slot(frame, key));};
-        auto templ = new _GncABTransTempl (func(TT_NAME), func(TT_RNAME),
-                                           func(TT_RACC), func(TT_RBCODE),
-                                           kvp_value_get_numeric(kvp_frame_get_slot(frame, TT_AMOUNT)),
-                                           func(TT_PURPOS), func(TT_PURPOSCT));
+        KvpFrame *frame = static_cast<KvpValue*>(node->data)->get<KvpFrame*>();
+        auto c_func = [frame](const char* key)
+            { auto slot = frame->get_slot(key);
+              return slot == nullptr ? std::string("") : std::string(slot->get<const char*>());};
+        auto n_func = [frame](const char* key)
+            { auto slot = frame->get_slot(key);
+              return slot == nullptr ? gnc_numeric_zero() : slot->get<gnc_numeric>();};
+        auto amt_slot = frame->get_slot(TT_AMOUNT);
+        auto templ = new _GncABTransTempl (c_func(TT_NAME), c_func(TT_RNAME),
+                                           c_func(TT_RACC), c_func(TT_RBCODE),
+                                           n_func(TT_AMOUNT), c_func(TT_PURPOS),
+                                           c_func(TT_PURPOSCT));
         retval = g_list_prepend (retval, templ);
     }
     retval = g_list_reverse (retval);
@@ -172,6 +173,12 @@ gnc_ab_trans_templ_list_free (GList *l)
     for(GList *node = l; node != NULL; node = g_list_next(node))
         delete static_cast<_GncABTransTempl*>(node->data);
 }
+static void*
+copy_list_value(const void* pvalue, void* pdata)
+{
+    auto new_value = new KvpValue(*static_cast<const KvpValue*>(pvalue));
+    return new_value;
+}
 
 void
 gnc_ab_set_book_template_list (QofBook *b, GList *template_list)
@@ -179,14 +186,15 @@ gnc_ab_set_book_template_list (QofBook *b, GList *template_list)
     GList *kvp_list = NULL;
     for (auto node = template_list; node != NULL; node = g_list_next (node))
     {
-        auto value = kvp_value_new_frame_nc (static_cast<_GncABTransTempl*>(node->data)->make_kvp_frame());
+        auto templ = static_cast<_GncABTransTempl*>(node->data);
+        auto value = new KvpValue(templ->make_kvp_frame());
         kvp_list = g_list_prepend (kvp_list, value);
     }
     kvp_list = g_list_reverse (kvp_list);
-    auto value = kvp_value_new_glist_nc(kvp_list);
+    auto value = new KvpValue(g_list_copy_deep(kvp_list, copy_list_value,
+                                               nullptr));
     KvpFrame *toplevel = qof_instance_get_slots (QOF_INSTANCE (b));
-    KvpFrame *hbci = kvp_frame_get_frame (toplevel, "hbci");
-    kvp_frame_set_slot_nc (hbci, "template-list", value);
+    delete toplevel->set_path({"hbci", "template-list"}, value);
     qof_instance_set_dirty_flag (QOF_INSTANCE (b), TRUE);
 }
 
diff --git a/src/libqof/qof/gnc-int128.hpp b/src/libqof/qof/gnc-int128.hpp
index 47cf69a..067d395 100644
--- a/src/libqof/qof/gnc-int128.hpp
+++ b/src/libqof/qof/gnc-int128.hpp
@@ -29,7 +29,11 @@ extern "C"
 {
 #ifndef __STDC_LIMIT_MACROS
 #define  __STDC_LIMIT_MACROS 1
+#endif
+#ifndef __STDC_CONSTANT_MACROS
 #define  __STDC_CONSTANT_MACROS 1
+#endif
+#ifndef __STDC_FORMAT_MACROS
 #define  __STDC_FORMAT_MACROS 1
 #endif
 #include <inttypes.h>
diff --git a/src/libqof/qof/kvp-value.hpp b/src/libqof/qof/kvp-value.hpp
index 2ab80d3..c7a96e1 100644
--- a/src/libqof/qof/kvp-value.hpp
+++ b/src/libqof/qof/kvp-value.hpp
@@ -28,13 +28,13 @@ extern "C"
 {
 #include "config.h"
 #include "qof.h"
-#include "kvp_frame.h"
 }
 #include <boost/version.hpp>
 #if BOOST_VERSION == 105600
 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
 #endif
 #include <boost/variant.hpp>
+#include "kvp_frame.h"
 
 struct KvpValueImpl
 {
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index 8a5b401..8e8ff35 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -1280,8 +1280,6 @@ kvp_frame_to_string(const KvpFrame *frame)
     return g_strdup(realframe->to_string().c_str());
 }
 
-static KvpValue *kvp_value_from_gvalue (const GValue*);
-
 static void
 gvalue_list_from_kvp_value (KvpValue *kval, gpointer pList)
 {
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index fa1acc3..190aa94 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -586,6 +586,12 @@ gchar* kvp_frame_to_string(const KvpFrame *frame);
  */
 GValue* gvalue_from_kvp_value (const KvpValue *kval);
 
+/** Convert a gvalue into a kvpvalue.
+ * @param gval: A GValue of a type KvpValue can digest.
+ * @return KvpValue created from the GValue's contents.
+ */
+KvpValue* kvp_value_from_gvalue (const GValue *gval);
+
 /** KvpItem: GValue Exchange
  * \brief Transfer of KVP to and from GValue, with the key
  *
diff --git a/src/libqof/qof/qofbook-p.h b/src/libqof/qof/qofbook-p.h
index 8907149..48e963f 100644
--- a/src/libqof/qof/qofbook-p.h
+++ b/src/libqof/qof/qofbook-p.h
@@ -36,13 +36,11 @@
 #ifndef QOF_BOOK_P_H
 #define QOF_BOOK_P_H
 
-#include "kvp_frame.h"
 #include "qofbackend.h"
 #include "qofbook.h"
 #include "qofid.h"
 #include "qofid-p.h"
 #include "qofinstance-p.h"
-
 #ifdef __cplusplus
 extern "C"
 {
diff --git a/src/libqof/qof/qofbook.cpp b/src/libqof/qof/qofbook.cpp
index 68df399..d72cb6d 100644
--- a/src/libqof/qof/qofbook.cpp
+++ b/src/libqof/qof/qofbook.cpp
@@ -56,7 +56,7 @@ extern "C"
 #include "qofid-p.h"
 #include "qofobject-p.h"
 #include "qofbookslots.h"
-#include "kvp_frame.h"
+#include "kvp_frame.hpp"
 
 static QofLogModule log_module = QOF_MOD_ENGINE;
 #define AB_KEY "hbci"
@@ -649,11 +649,11 @@ qof_book_get_counter (QofBook *book, const char *counter_name)
         return -1;
     }
 
-    value = kvp_frame_get_slot_path (kvp, "counters", counter_name, NULL);
+    value = kvp->get_slot({"counters", counter_name});
     if (value)
     {
         /* found it */
-        return kvp_value_get_gint64 (value);
+        return value->get<int64_t>();
     }
     else
     {
@@ -703,9 +703,8 @@ qof_book_increment_and_format_counter (QofBook *book, const char *counter_name)
 
     /* Save off the new counter */
     qof_book_begin_edit(book);
-    value = kvp_value_new_gint64 (counter);
-    kvp_frame_set_slot_path (kvp, value, "counters", counter_name, NULL);
-    kvp_value_delete (value);
+    value = new KvpValue(counter);
+    delete kvp->set_path({"counters", counter_name}, value);
     qof_instance_set_dirty (QOF_INSTANCE (book));
     qof_book_commit_edit(book);
 
@@ -753,10 +752,10 @@ qof_book_get_counter_format(const QofBook *book, const char *counter_name)
     format = NULL;
 
     /* Get the format string */
-    value = kvp_frame_get_slot_path (kvp, "counter_formats", counter_name, NULL);
+    value = kvp->get_slot({"counter_formats", counter_name});
     if (value)
     {
-        format = kvp_value_get_string (value);
+        format = value->get<const char*>();
         error = qof_book_validate_counter_format(format);
         if (error != NULL)
         {
@@ -915,19 +914,13 @@ qof_book_get_book_currency (QofBook *book)
         return NULL;
     }
 
-    /* See if there is a book currency */
-    value = kvp_frame_get_slot_path (kvp,
-                                     KVP_OPTION_PATH,
-                                     OPTION_SECTION_ACCOUNTS,
-                                     OPTION_NAME_BOOK_CURRENCY,
-                                     NULL);
-    if (!value)
-    /* No book-currency */
-    {
-        return NULL;
-    }
+    /* See if there is a book currency. */
+    value = kvp->get_slot({KVP_OPTION_PATH, OPTION_SECTION_ACCOUNTS,
+                           OPTION_NAME_BOOK_CURRENCY});
+    if (!value) /* No book-currency */
+        return nullptr;
 
-    return kvp_value_get_string (value);
+    return value->get<const char*>();
 }
 
 /** Returns pointer to default gain/loss policy for book, if one exists in the
@@ -957,19 +950,14 @@ qof_book_get_default_gains_policy (QofBook *book)
     }
 
     /* See if there is a default gain/loss policy */
-    value = kvp_frame_get_slot_path (kvp,
-                                     KVP_OPTION_PATH,
-                                     OPTION_SECTION_ACCOUNTS,
-                                     OPTION_NAME_DEFAULT_GAINS_POLICY,
-                                     NULL);
+    value = kvp->get_slot({KVP_OPTION_PATH, OPTION_SECTION_ACCOUNTS,
+                           OPTION_NAME_DEFAULT_GAINS_POLICY});
     if (!value)
     /* No default gain/loss policy, therefore not valid book-currency
        accounting method */
-    {
-        return NULL;
-    }
+        return nullptr;
 
-    return kvp_value_get_string (value);
+    return g_strdup(value->get<const char*>());
 }
 
 
@@ -1009,11 +997,8 @@ gboolean qof_book_uses_autoreadonly (const QofBook *book)
 
 gint qof_book_get_num_days_autoreadonly (const QofBook *book)
 {
-    KvpValue *kvp_val;
-    double tmp = 0;
-    KvpFrame *frame = qof_instance_get_slots (QOF_INSTANCE (book));
-
     g_assert(book);
+    double tmp;
     qof_instance_get (QOF_INSTANCE (book),
 		      "autoreadonly-days", &tmp,
 		      NULL);
@@ -1038,16 +1023,18 @@ GDate* qof_book_get_autoreadonly_gdate (const QofBook *book)
 const char*
 qof_book_get_string_option(const QofBook* book, const char* opt_name)
 {
-    return kvp_frame_get_string(qof_instance_get_slots(QOF_INSTANCE (book)),
-				opt_name);
+    auto slot = qof_instance_get_slots(QOF_INSTANCE (book))->get_slot(opt_name);
+    if (slot == nullptr)
+        return nullptr;
+    return slot->get<const char*>();
 }
 
 void
 qof_book_set_string_option(QofBook* book, const char* opt_name, const char* opt_val)
 {
     qof_book_begin_edit(book);
-    kvp_frame_set_string(qof_instance_get_slots(QOF_INSTANCE (book)),
-						opt_name, opt_val);
+    auto frame = qof_instance_get_slots(QOF_INSTANCE(book));
+    delete frame->set(opt_name, new KvpValue(opt_val));
     qof_instance_set_dirty (QOF_INSTANCE (book));
     qof_book_commit_edit(book);
 }
@@ -1068,7 +1055,7 @@ static void commit_err (G_GNUC_UNUSED QofInstance *inst, QofBackendError errcode
 static void
 add_feature_to_hash (const gchar *key, KvpValue *value, gpointer user_data)
 {
-    gchar *descr = g_strdup(kvp_value_get_string (value));
+    gchar *descr = g_strdup(value->get<const char*>());
     g_hash_table_insert (*(GHashTable**)user_data, (gchar*)key, descr);
 }
 
@@ -1079,8 +1066,8 @@ qof_book_get_features (QofBook *book)
     GHashTable *features = g_hash_table_new_full (g_str_hash, g_str_equal,
                                                   NULL, g_free);
 
-    frame = kvp_frame_get_frame (frame, GNC_FEATURES);
-    kvp_frame_for_each_slot (frame, &add_feature_to_hash, &features);
+    frame = frame->get_slot(GNC_FEATURES)->get<KvpFrame*>();
+    frame->for_each_slot(&add_feature_to_hash, &features);
     return features;
 }
 
@@ -1088,9 +1075,8 @@ void
 qof_book_set_feature (QofBook *book, const gchar *key, const gchar *descr)
 {
     KvpFrame *frame = qof_instance_get_slots (QOF_INSTANCE (book));
-    gchar *path = g_strconcat (GNC_FEATURES, key, NULL);
     qof_book_begin_edit (book);
-    kvp_frame_set_string (frame, path, descr);
+    delete frame->set_path({GNC_FEATURES, key}, new KvpValue(descr));
     qof_instance_set_dirty (QOF_INSTANCE (book));
     qof_book_commit_edit (book);
 }
@@ -1127,9 +1113,11 @@ void
 qof_book_set_option (QofBook *book, KvpValue *value, GSList *path)
 {
     KvpFrame *root = qof_instance_get_slots (QOF_INSTANCE (book));
-    KvpFrame *options = kvp_frame_get_frame_slash (root, KVP_OPTION_PATH);
+    Path path_v {KVP_OPTION_PATH};
+    for (auto item = path; item != nullptr; item = g_slist_next(item))
+        path_v.push_back(static_cast<const char*>(item->data));
     qof_book_begin_edit (book);
-    kvp_frame_set_slot_path_gslist (options, value, path);
+    delete root->set_path(path_v, value);
     qof_instance_set_dirty (QOF_INSTANCE (book));
     qof_book_commit_edit (book);
 }
@@ -1138,15 +1126,19 @@ KvpValue*
 qof_book_get_option (QofBook *book, GSList *path)
 {
     KvpFrame *root = qof_instance_get_slots(QOF_INSTANCE (book));
-    KvpFrame *options = kvp_frame_get_frame(root, KVP_OPTION_PATH);
-    return kvp_frame_get_slot_path_gslist(options, path);
+    Path path_v {KVP_OPTION_PATH};
+    for (auto item = path; item != nullptr; item = g_slist_next(item))
+        path_v.push_back(static_cast<const char*>(item->data));
+    return root->get_slot(path_v);
 }
 
 void
 qof_book_options_delete (QofBook *book)
 {
     KvpFrame *root = qof_instance_get_slots(QOF_INSTANCE (book));
-    kvp_frame_delete (kvp_frame_get_frame(root, KVP_OPTION_PATH));
+    auto option = root->get_slot(KVP_OPTION_PATH);
+    if (option != nullptr)
+        delete option->get<KvpFrame*>();
 }
 
 /* QofObject function implementation and registration */
diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 3ff5f72..16eeee0 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -115,6 +115,7 @@ void qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *va
 void qof_instance_copy_kvp (QofInstance *to, const QofInstance *from);
 void qof_instance_swap_kvp (QofInstance *a, QofInstance *b);
 int qof_instance_compare_kvp (const QofInstance *a, const QofInstance *b);
+/** Returns a g_strdup'd string which must be g_freed. */
 char* qof_instance_kvp_as_string (const QofInstance *inst);
 void qof_instance_kvp_add_guid (const QofInstance *inst, const char* path,
                                 const Timespec time, const char* key,
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index 1865b48..e04332c 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -39,6 +39,7 @@ extern "C"
 #include "qofbook-p.h"
 #include "qofid-p.h"
 #include "kvp_frame.h"
+#include "kvp_frame.hpp"
 #include "qofinstance-p.h"
 
 static QofLogModule log_module = QOF_MOD_ENGINE;
@@ -260,7 +261,7 @@ qof_instance_init (QofInstance *inst)
 
     priv = GET_PRIVATE(inst);
     priv->book = NULL;
-    inst->kvp_data = kvp_frame_new();
+    inst->kvp_data = new KvpFrame;
     priv->last_update.tv_sec = 0;
     priv->last_update.tv_nsec = -1;
     priv->editlevel = 0;
@@ -335,8 +336,8 @@ qof_instance_finalize_real (GObject *instp)
     QofInstancePrivate *priv;
     QofInstance* inst = QOF_INSTANCE(instp);
 
-    kvp_frame_delete (inst->kvp_data);
-    inst->kvp_data = NULL;
+    delete inst->kvp_data;
+    inst->kvp_data = nullptr;
 
     priv = GET_PRIVATE(inst);
     priv->editlevel = 0;
@@ -587,7 +588,7 @@ qof_instance_set_slots (QofInstance *inst, KvpFrame *frm)
     priv = GET_PRIVATE(inst);
     if (inst->kvp_data && (inst->kvp_data != frm))
     {
-        kvp_frame_delete(inst->kvp_data);
+        delete inst->kvp_data;
     }
 
     priv->dirty = TRUE;
@@ -665,7 +666,6 @@ qof_instance_get_dirty_flag (gconstpointer ptr)
     return GET_PRIVATE(ptr)->dirty;
 }
 
-/* Watch out: This function is still used (as a "friend") in src/import-export/aqb/gnc-ab-kvp.c */
 void
 qof_instance_set_dirty_flag (gconstpointer inst, gboolean flag)
 {
@@ -1069,19 +1069,19 @@ qof_commit_edit_part2(QofInstance *inst,
 gboolean
 qof_instance_has_kvp (QofInstance *inst)
 {
-    return (inst->kvp_data != NULL && !kvp_frame_is_empty (inst->kvp_data));
+    return (inst->kvp_data != NULL && !inst->kvp_data->empty());
 }
 
 void
 qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value)
 {
-    kvp_frame_set_gvalue (inst->kvp_data, key, value);
+    delete inst->kvp_data->set_path({key}, kvp_value_from_gvalue(value));
 }
 
 void
 qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *value)
 {
-    GValue *temp = kvp_frame_get_gvalue (inst->kvp_data, key);
+    auto temp = gvalue_from_kvp_value (inst->kvp_data->get_slot(key));
     if (G_IS_VALUE (temp))
     {
         if (G_IS_VALUE (value))
@@ -1095,7 +1095,8 @@ qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *value)
 void
 qof_instance_copy_kvp (QofInstance *to, const QofInstance *from)
 {
-    to->kvp_data = kvp_frame_copy(from->kvp_data);
+    delete to->kvp_data;
+    to->kvp_data = new KvpFrame(*from->kvp_data);
 }
 
 void
@@ -1107,40 +1108,39 @@ qof_instance_swap_kvp (QofInstance *a, QofInstance *b)
 int
 qof_instance_compare_kvp (const QofInstance *a, const QofInstance *b)
 {
-    return kvp_frame_compare (a->kvp_data, b->kvp_data);
+    return compare(a->kvp_data, b->kvp_data);
 }
 
 char*
 qof_instance_kvp_as_string (const QofInstance *inst)
 {
-    return kvp_frame_to_string (inst->kvp_data);
+    //The std::string is a local temporary and doesn't survive this function.
+    return g_strdup(inst->kvp_data->to_string().c_str());
 }
 
 void
 qof_instance_kvp_add_guid (const QofInstance *inst, const char* path,
-                       const Timespec time, const char *key,
-                       const GncGUID *guid)
+                           const Timespec time, const char *key,
+                           const GncGUID *guid)
 {
-    KvpFrame *slot = NULL, *container = NULL;
-    /* We're in the process of being destroyed */
     g_return_if_fail (inst->kvp_data != NULL);
 
-    container = kvp_frame_new();
-    kvp_frame_set_guid (container, key, guid);
-    kvp_frame_set_timespec (container, "date", time);
-    kvp_frame_add_frame_nc (inst->kvp_data, path, container);
+    auto container = new KvpFrame;
+    container->set(key, new KvpValue(const_cast<GncGUID*>(guid)));
+    container->set("date", new KvpValue(time));
+    delete inst->kvp_data->set_path({path}, new KvpValue(container));
 }
 
 inline static gboolean
 kvp_match_guid (KvpValue *v, const char *key, const GncGUID *guid)
 {
-    GncGUID *this_guid = NULL;
-    KvpFrame *frame = kvp_value_get_frame (v);
-    if (frame == NULL)
+    if (v->get_type() != KVP_TYPE_FRAME)
         return FALSE;
-    this_guid = kvp_frame_get_guid (frame, key);
-    if (this_guid == NULL)
+    auto frame = v->get<KvpFrame*>();
+    auto val = frame->get_slot(key);
+    if (val == nullptr || val->get_type() != KVP_TYPE_GUID)
         return FALSE;
+    auto this_guid = val->get<GncGUID*>();
 
     return guid_equal (this_guid, guid);
 }
@@ -1149,24 +1149,23 @@ gboolean
 qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
                            const char* key, const GncGUID *guid)
 {
-    KvpValue *v = NULL;
     g_return_val_if_fail (inst->kvp_data != NULL, FALSE);
     g_return_val_if_fail (guid != NULL, FALSE);
 
-    v = kvp_frame_get_value (inst->kvp_data, path);
-    if (v == NULL) return FALSE;
-    
-    switch (kvp_value_get_type (v))
+    auto v = inst->kvp_data->get_slot(path);
+    if (v == nullptr) return FALSE;
+
+    switch (v->get_type())
     {
     case KVP_TYPE_FRAME:
         return kvp_match_guid (v, key, guid);
         break;
     case KVP_TYPE_GLIST:
     {
-        GList *list = kvp_value_get_glist (v), *node = NULL;
-        for (node = list; node != NULL; node = node->next)
+        auto list = v->get<GList*>();
+        for (auto node = list; node != NULL; node = node->next)
         {
-            KvpValue *val = static_cast<KvpValue*>(node->data);
+            auto val = static_cast<KvpValue*>(node->data);
             if (kvp_match_guid (val, key, guid))
             {
                 return TRUE;
@@ -1185,35 +1184,32 @@ void
 qof_instance_kvp_remove_guid (const QofInstance *inst, const char *path,
                           const char *key, const GncGUID *guid)
 {
-    KvpValue *v = NULL;
     g_return_if_fail (inst->kvp_data != NULL);
     g_return_if_fail (guid != NULL);
 
-    v = kvp_frame_get_value (inst->kvp_data, path);
+    auto v = inst->kvp_data->get_slot(path);
     if (v == NULL) return;
 
-    switch (kvp_value_get_type (v))
+    switch (v->get_type())
     {
     case KVP_TYPE_FRAME:
         if (kvp_match_guid (v, key, guid))
         {
-            kvp_frame_replace_value_nc (inst->kvp_data, path, NULL);
-            kvp_value_replace_frame_nc (v, NULL);
-            kvp_value_delete (v);
+            delete inst->kvp_data->set_path({path}, nullptr);
+            delete v;
         }
         break;
     case KVP_TYPE_GLIST:
     {
-        GList *list = kvp_value_get_glist (v), *node = NULL;
-        for (node = list; node != NULL; node = node->next)
+        auto list = v->get<GList*>();
+        for (auto node = list; node != nullptr; node = node->next)
         {
-            KvpValue *val = static_cast<KvpValue*>(node->data);
+            auto val = static_cast<KvpValue*>(node->data);
             if (kvp_match_guid (val, key, guid))
             {
-                kvp_value_replace_frame_nc (val, NULL);
                 list = g_list_delete_link (list, node);
-                kvp_value_replace_glist_nc (v, list);
-                kvp_value_delete (val);
+                v->set(list);
+                delete val;
                 break;
             }
         }
@@ -1230,38 +1226,34 @@ void
 qof_instance_kvp_merge_guids (const QofInstance *target,
                               const QofInstance *donor, const char *path)
 {
-    KvpValue *v = NULL;
     g_return_if_fail (target != NULL);
     g_return_if_fail (donor != NULL);
 
     if (! qof_instance_has_slot (donor, path)) return;
-    v = kvp_frame_get_value (donor->kvp_data, path);
+    auto v = donor->kvp_data->get_slot(path);
     if (v == NULL) return;
 
-    switch (kvp_value_get_type (v))
+    auto target_val = target->kvp_data->get_slot(path);
+    switch (v->get_type())
     {
     case KVP_TYPE_FRAME:
-        kvp_frame_add_frame_nc (target->kvp_data, path,
-                                kvp_value_get_frame (v));
-        kvp_value_replace_frame_nc (v, NULL);
-        kvp_value_delete (v);
+        if (target_val)
+            target_val->add(v);
+        else
+            target->kvp_data->set_path({path}, v);
+        donor->kvp_data->set(path, nullptr); //Contents moved, Don't delete!
         break;
     case KVP_TYPE_GLIST:
-    {
-        GList *list = kvp_value_get_glist (v), *node = NULL;
-        while (list)
+        if (target_val)
         {
-            KvpValue *val = static_cast<KvpValue*>(list->data);
-            kvp_frame_add_frame_nc (target->kvp_data, path,
-                                    kvp_value_get_frame (val));
-            kvp_value_replace_frame_nc (val, NULL);
-            list = g_list_remove_link (list, list);
-            kvp_value_delete (val);
+            auto list = target_val->get<GList*>();
+            list = g_list_concat(list, v->get<GList*>());
+            target_val->set(list);
         }
-        kvp_value_replace_glist_nc (v, list);
-        kvp_value_delete (v);
+        else
+            target->kvp_data->set(path, v);
+        donor->kvp_data->set(path, nullptr); //Contents moved, Don't delete!
         break;
-    }
     default:
         PWARN ("Instance KVP on path %s contains the wrong type.", path);
         break;
@@ -1271,29 +1263,33 @@ qof_instance_kvp_merge_guids (const QofInstance *target,
 gboolean
 qof_instance_has_slot (const QofInstance *inst, const char *path)
 {
-    return kvp_frame_get_value (inst->kvp_data, path) != NULL;
+    return inst->kvp_data->get_slot(path) != NULL;
 }
 
 void
 qof_instance_slot_delete (const QofInstance *inst, const char *path)
 {
-    kvp_frame_set_frame_nc (inst->kvp_data, path, NULL);
+    inst->kvp_data->set(path, nullptr);
 }
 
 void
 qof_instance_slot_delete_if_empty (const QofInstance *inst, const char *path)
 {
-    KvpFrame *frame = kvp_frame_get_frame (inst->kvp_data, path);
-    if (frame && kvp_frame_is_empty (frame))
-        kvp_frame_set_frame_nc (inst->kvp_data, path, NULL);
+    auto slot = inst->kvp_data->get_slot(path);
+    if (slot)
+    {
+        auto frame = slot->get<KvpFrame*>();
+        if (frame && frame->empty())
+            inst->kvp_data->set(path, nullptr);
+    }
 }
-
+namespace {
 struct wrap_param
 {
     void (*proc)(const char*, const GValue*, void*);
     void *user_data;
 };
-
+}
 static void
 wrap_gvalue_function (const char* key, KvpValue *val, gpointer data)
 {
@@ -1308,10 +1304,12 @@ qof_instance_foreach_slot (const QofInstance *inst, const char* path,
                            void (*proc)(const char*, const GValue*, void*),
                            void* data)
 {
-    KvpFrame* frame = kvp_frame_get_frame (inst->kvp_data, path);
-    if (!frame) return;
+    auto slot = inst->kvp_data->get_slot(path);
+    if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
+        return;
+    auto frame = slot->get<KvpFrame*>();
     wrap_param new_data {proc, data};
-    kvp_frame_for_each_slot(frame, wrap_gvalue_function, &new_data);
+    frame->for_each_slot(wrap_gvalue_function, &new_data);
 }
 
 /* ========================== END OF FILE ======================= */

commit 9e142124f4f1187446d3d7f7dab5e691a5f6da66
Author: John Ralls <jralls at ceridwen.us>
Date:   Mon Jun 22 15:00:10 2015 -0700

    Convert kvp-scm to C++ and to using the KVP C++ API.
    
    The binding remains C to simplify interaction of these two functions with
    SWIG and Scheme.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index ea745f9..82fe8cb 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -184,7 +184,7 @@ src/engine/gnc-pricedb.c
 src/engine/gnc-session.c
 src/engine/gncTaxTable.c
 src/engine/gncVendor.c
-src/engine/kvp-scm.c
+src/engine/kvp-scm.cpp
 src/engine/policy.c
 src/engine/Query.c
 src/engine/Recurrence.c
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
index 1d5b308..f268547 100644
--- a/src/engine/Makefile.am
+++ b/src/engine/Makefile.am
@@ -38,7 +38,7 @@ libgncmod_engine_la_SOURCES = \
   gnc-session.c \
   gncmod-engine.c \
   swig-engine.c \
-  kvp-scm.c \
+  kvp-scm.cpp \
   engine-helpers.c \
   glib-helpers.c  \
   policy.c \
diff --git a/src/engine/engine-helpers.c b/src/engine/engine-helpers.c
index 58dddbb..34eb45f 100644
--- a/src/engine/engine-helpers.c
+++ b/src/engine/engine-helpers.c
@@ -38,7 +38,6 @@
 #include "guile-mappings.h"
 #include "gnc-guile-utils.h"
 #include <qof.h>
-#include <kvp_frame.h>
 #include <qofbookslots.h>
 
 /** \todo Code dependent on the private query headers
@@ -668,287 +667,6 @@ gnc_query_path_free (GSList *path)
     g_slist_free (path);
 }
 
-static KvpValueType
-gnc_scm2KvpValueType (SCM value_type_scm)
-{
-    return scm_to_int(value_type_scm);
-}
-
-static SCM gnc_kvp_frame2scm (KvpFrame *frame);
-
-static SCM
-gnc_kvp_value2scm (const KvpValue *value)
-{
-    SCM value_scm = SCM_EOL;
-    KvpValueType value_t;
-    SCM scm;
-    const gchar *string;
-
-    if (!value) return SCM_BOOL_F;
-
-    value_t = kvp_value_get_type (value);
-
-    value_scm = scm_cons (scm_from_long  (value_t), value_scm);
-
-    switch (value_t)
-    {
-    case KVP_TYPE_GINT64:
-        scm = scm_from_int64 (kvp_value_get_gint64 (value));
-        break;
-
-    case KVP_TYPE_DOUBLE:
-        scm = scm_from_double  (kvp_value_get_double (value));
-        break;
-
-    case KVP_TYPE_STRING:
-        string = kvp_value_get_string (value);
-        scm = string ? scm_from_utf8_string (string) : SCM_BOOL_F;
-        break;
-
-    case KVP_TYPE_GUID:
-        scm = gnc_guid2scm (*kvp_value_get_guid (value));
-        break;
-
-    case KVP_TYPE_TIMESPEC:
-        scm = gnc_timespec2timepair (kvp_value_get_timespec (value));
-        break;
-
-    case KVP_TYPE_NUMERIC:
-    {
-        gnc_numeric n = kvp_value_get_numeric (value);
-        scm = gnc_query_numeric2scm (n);
-        break;
-    }
-
-    case KVP_TYPE_GLIST:
-    {
-        GList *node;
-
-        scm = SCM_EOL;
-        for (node = kvp_value_get_glist (value); node; node = node->next)
-            scm = scm_cons (gnc_kvp_value2scm (node->data), scm);
-        scm = scm_reverse (scm);
-        break;
-    }
-
-    case KVP_TYPE_FRAME:
-        scm = gnc_kvp_frame2scm (kvp_value_get_frame (value));
-        break;
-
-    default:
-        scm = SCM_BOOL_F;
-        break;
-    }
-
-    value_scm = scm_cons (scm, value_scm);
-
-    return scm_reverse (value_scm);
-}
-
-typedef struct
-{
-    SCM scm;
-} KVPSCMData;
-
-static void
-kvp_frame_slot2scm (const char *key, KvpValue *value, gpointer data)
-{
-    KVPSCMData *ksd = data;
-    SCM value_scm;
-    SCM key_scm;
-    SCM pair;
-
-    key_scm = key ? scm_from_utf8_string (key) : SCM_BOOL_F;
-    value_scm = gnc_kvp_value2scm (value);
-    pair = scm_cons (key_scm, value_scm);
-
-    ksd->scm = scm_cons (pair, ksd->scm);
-}
-
-static SCM
-gnc_kvp_frame2scm (KvpFrame *frame)
-{
-    KVPSCMData ksd;
-
-    if (!frame) return SCM_BOOL_F;
-
-    ksd.scm = SCM_EOL;
-
-    kvp_frame_for_each_slot (frame, kvp_frame_slot2scm, &ksd);
-
-    return ksd.scm;
-}
-
-static KvpFrame * gnc_scm2KvpFrame (SCM frame_scm);
-
-static KvpValue *
-gnc_scm2KvpValue (SCM value_scm)
-{
-    KvpValueType value_t;
-    KvpValue *value = NULL;
-    SCM type_scm;
-    SCM val_scm;
-
-    if (!scm_is_list (value_scm) || scm_is_null (value_scm))
-        return NULL;
-
-    type_scm = SCM_CAR (value_scm);
-    value_t = gnc_scm2KvpValueType (type_scm);
-
-    value_scm = SCM_CDR (value_scm);
-    if (!scm_is_list (value_scm) || scm_is_null (value_scm))
-        return NULL;
-
-    val_scm = SCM_CAR (value_scm);
-
-    switch (value_t)
-    {
-    case KVP_TYPE_GINT64:
-        value = kvp_value_new_gint64 (scm_to_int64 (val_scm));
-        break;
-
-    case KVP_TYPE_DOUBLE:
-        value = kvp_value_new_double (scm_to_double (val_scm));
-        break;
-
-    case KVP_TYPE_STRING:
-    {
-        gchar * str;
-        str = gnc_scm_to_utf8_string (val_scm);
-        value = kvp_value_new_string (str);
-        g_free (str);
-        break;
-    }
-
-    case KVP_TYPE_GUID:
-    {
-        if (val_scm != SCM_BOOL_F)
-        {
-            GncGUID guid = gnc_scm2guid (val_scm);
-            value = kvp_value_new_guid (&guid);
-        }
-        else
-            value = NULL;
-        break;
-    }
-
-    case KVP_TYPE_TIMESPEC:
-    {
-        Timespec ts = gnc_timepair2timespec (val_scm);
-        value = kvp_value_new_timespec(ts);
-        break;
-    }
-
-    case KVP_TYPE_GDATE:
-    {
-        Timespec ts = gnc_timepair2timespec (val_scm);
-        value = kvp_value_new_gdate(timespec_to_gdate(ts));
-        break;
-    }
-
-    case KVP_TYPE_NUMERIC:
-    {
-        gnc_numeric n;
-
-        if (!gnc_query_numeric_p (val_scm))
-            return NULL;
-
-        n = gnc_query_scm2numeric (val_scm);
-
-        value = kvp_value_new_gnc_numeric (n);
-        break;
-    }
-
-    case KVP_TYPE_GLIST:
-    {
-        GList *list = NULL;
-        GList *node;
-
-        for (; scm_is_list (val_scm) && !scm_is_null (val_scm);
-                val_scm = SCM_CDR (val_scm))
-        {
-            SCM scm = SCM_CAR (val_scm);
-
-            list = g_list_prepend (list, gnc_scm2KvpValue (scm));
-        }
-
-        list = g_list_reverse (list);
-
-        value = kvp_value_new_glist (list);
-
-        for (node = list; node; node = node->next)
-            kvp_value_delete (node->data);
-        g_list_free (list);
-        break;
-    }
-
-    case KVP_TYPE_FRAME:
-    {
-        KvpFrame *frame;
-
-        frame = gnc_scm2KvpFrame (val_scm);
-        value = kvp_value_new_frame (frame);
-        kvp_frame_delete (frame);
-        break;
-    }
-    default:
-	break;
-    }
-
-    return value;
-}
-
-static KvpFrame *
-gnc_scm2KvpFrame (SCM frame_scm)
-{
-    KvpFrame * frame;
-
-    if (!scm_is_list (frame_scm)) return NULL;
-
-    frame = kvp_frame_new ();
-
-    for (; scm_is_list (frame_scm) && !scm_is_null (frame_scm);
-            frame_scm = SCM_CDR (frame_scm))
-    {
-        SCM pair = SCM_CAR (frame_scm);
-        KvpValue *value;
-        SCM key_scm;
-        SCM val_scm;
-        gchar *key;
-
-        if (!scm_is_pair (pair))
-            continue;
-
-        key_scm = SCM_CAR (pair);
-        val_scm = SCM_CDR (pair);
-
-        if (!scm_is_string (key_scm))
-            continue;
-
-        key = scm_to_utf8_string (key_scm); /* key should be freed with free !
-                                                 This is automatically taken care
-                                                 of by scm_dynwind_free below. */
-        scm_dynwind_begin (0);
-        scm_dynwind_free (key); /* free key whenever the dynwind context ends */
-        if (!key)
-        {
-            scm_dynwind_end ();
-            continue;
-        }
-        value = gnc_scm2KvpValue (val_scm); /* can exit non-locally so justifies
-                                               the use of scm_dynwind context
-                                               protection */
-        if (!value)
-        {
-            scm_dynwind_end ();
-            continue;
-        }
-        kvp_frame_set_slot_nc (frame, key, value);
-        scm_dynwind_end ();
-    }
-
-    return frame;
-}
 
 static SCM
 gnc_queryterm2scm (const QofQueryTerm *qt)
diff --git a/src/engine/kvp-scm.c b/src/engine/kvp-scm.cpp
similarity index 60%
rename from src/engine/kvp-scm.c
rename to src/engine/kvp-scm.cpp
index 82d0e73..49e1174 100644
--- a/src/engine/kvp-scm.c
+++ b/src/engine/kvp-scm.cpp
@@ -1,14 +1,19 @@
+#include <libguile.h>
+
+extern "C"
+{
 #include "config.h"
 
 #include <qof.h>
-#include <kvp_frame.h>
-#include <libguile.h>
 #include "engine-helpers-guile.h"
 
-#include "kvp-scm.h"
 #include "guile-mappings.h"
 #include "gnc-guile-utils.h"
 #include "swig-runtime.h"
+#include "kvp-scm.h"
+}
+
+#include <kvp_frame.hpp>
 
 /* NOTE: There are some problems with this approach. Currently,
  *       guids are stored simply as strings in scheme, so some
@@ -25,43 +30,40 @@ gnc_scm_to_kvp_value_ptr(SCM val)
         /* in guile 1.8 (exact? ) only works on numbers */
         if (scm_is_exact (val) && gnc_gh_gint64_p(val))
         {
-            return kvp_value_new_gint64(scm_to_int64(val));
+            return new KvpValue{scm_to_int64(val)};
         }
         else
         {
-            return kvp_value_new_double(scm_to_double(val));
+            return new KvpValue{scm_to_double(val)};
         }
     }
     else if (gnc_numeric_p(val))
     {
-        return kvp_value_new_gnc_numeric(gnc_scm_to_numeric(val));
+        return new KvpValue{gnc_scm_to_numeric(val)};
     }
     else if (gnc_guid_p(val))
     {
-        GncGUID tmpguid = gnc_scm2guid(val);
-        return kvp_value_new_guid(&tmpguid);
+        auto guid = gnc_scm2guid(val);
+        auto tmpguid = guid_copy(&guid);
+        return new KvpValue{tmpguid};
     }
     else if (gnc_timepair_p(val))
     {
         Timespec ts = gnc_timepair2timespec(val);
-        return kvp_value_new_timespec(ts);
+        return new KvpValue{ts};
     }
     else if (scm_is_string(val))
     {
-        gchar *newstr;
-        KvpValue *ret;
-        newstr = gnc_scm_to_utf8_string (val);
-        ret = kvp_value_new_string(newstr);
-        g_free (newstr);
-        return ret;
+        return new KvpValue{gnc_scm_to_utf8_string(val)};
     }
     else if (SWIG_IsPointerOfType(val, SWIG_TypeQuery("_p_KvpFrame")))
     {
 #define FUNC_NAME G_STRFUNC
-        KvpFrame *frame = SWIG_MustGetPtr(val, SWIG_TypeQuery("_p_KvpFrame"),
-                                          1, 0);
+        auto vp_frame = SWIG_MustGetPtr(val,
+                                        SWIG_TypeQuery("_p_KvpFrame"), 1, 0);
+        KvpFrame *frame = static_cast<KvpFrame*>(vp_frame);
 #undef FUNC_NAME
-        return kvp_value_new_frame (frame);
+        return new KvpValue{frame};
     }
     /* FIXME: add list handler here */
     return NULL;
@@ -70,41 +72,42 @@ gnc_scm_to_kvp_value_ptr(SCM val)
 SCM
 gnc_kvp_value_ptr_to_scm(KvpValue* val)
 {
-    const gchar *string;
     switch (kvp_value_get_type(val))
     {
     case KVP_TYPE_GINT64:
-        return scm_from_int64(kvp_value_get_gint64(val));
+        return scm_from_int64(val->get<int64_t>());
         break;
     case KVP_TYPE_DOUBLE:
-        return scm_from_double (kvp_value_get_double(val));
+        return scm_from_double (val->get<double>());
         break;
     case KVP_TYPE_NUMERIC:
-        return gnc_numeric_to_scm(kvp_value_get_numeric(val));
+        return gnc_numeric_to_scm(val->get<gnc_numeric>());
         break;
     case KVP_TYPE_STRING:
-        string = kvp_value_get_string(val);
+    {
+        auto string = val->get<const char*>();
         return string ? scm_from_utf8_string(string) : SCM_BOOL_F;
         break;
+    }
     case KVP_TYPE_GUID:
     {
-        GncGUID *tempguid = kvp_value_get_guid(val);
+        auto tempguid = kvp_value_get_guid(val);
         return gnc_guid2scm(*tempguid);
     }
     break;
     case KVP_TYPE_TIMESPEC:
-        return gnc_timespec2timepair(kvp_value_get_timespec(val));
+        return gnc_timespec2timepair(val->get<Timespec>());
         break;
 
     case KVP_TYPE_FRAME:
     {
-        KvpFrame *frame = kvp_value_get_frame(val);
-        if (frame)
+        auto frame = val->get<KvpFrame*>();
+        if (frame != nullptr)
             return SWIG_NewPointerObj(frame, SWIG_TypeQuery("_p_KvpFrame"), 0);
     }
     break;
     case KVP_TYPE_GDATE:
-        return gnc_timespec2timepair(gdate_to_timespec(kvp_value_get_gdate(val)));
+        return gnc_timespec2timepair(gdate_to_timespec(val->get<GDate>()));
 
         /* FIXME: handle types below */
     case KVP_TYPE_GLIST:
diff --git a/src/engine/kvp-scm.h b/src/engine/kvp-scm.h
index 4bca011..c8949e8 100644
--- a/src/engine/kvp-scm.h
+++ b/src/engine/kvp-scm.h
@@ -1,11 +1,18 @@
 #ifndef KVP_SCM_H
 #define KVP_SCM_H
 
-#include "qof.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <qof.h>
 #include <libguile.h>
 
 KvpValue* gnc_scm_to_kvp_value_ptr(SCM kvpval);
 SCM gnc_kvp_value_ptr_to_scm(KvpValue* val);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* KVP_SCM_H */
 

commit 78b5b7cb5be248955d992b749c1b999dd79f432a
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jun 21 17:34:36 2015 -0700

    Convert gnc-slots-sql.cpp to use the Kvp C++ API.
    
    Plus a few minor C++11 tweaks.

diff --git a/src/backend/sql/gnc-backend-sql.c b/src/backend/sql/gnc-backend-sql.c
index 7d9f748..e52a42c 100644
--- a/src/backend/sql/gnc-backend-sql.c
+++ b/src/backend/sql/gnc-backend-sql.c
@@ -37,7 +37,6 @@
 #include <qof.h>
 #include <qofquery-p.h>
 #include <qofquerycore-p.h>
-#include <kvp_frame.h>
 #include <Account.h>
 #include <TransLog.h>
 #include <gnc-engine.h>
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 1c5f77a..28b58ed 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -33,8 +33,6 @@ extern "C"
 
 #include <qof.h>
 #include <gnc-engine.h>
-#include <kvp_frame.h>
-
 #include "gnc-backend-sql.h"
 
 #include "gnc-slots-sql.h"
@@ -43,6 +41,9 @@ extern "C"
 #include "splint-defs.h"
 #endif
 }
+
+#include <kvp_frame.hpp>
+
 /*@ unused @*/ static QofLogModule log_module = G_LOG_DOMAIN;
 
 #define TABLE_NAME "slots"
@@ -252,7 +253,7 @@ set_slot_from_value( slot_info_t *pInfo, KvpValue *pValue)
     case FRAME:
     {
         gchar *key = get_key_from_path( pInfo->path );
-        kvp_frame_set_value_nc( pInfo->pKvpFrame, key, pValue );
+        pInfo->pKvpFrame->set(key, pValue);
         g_free( key );
         break;
     }
@@ -266,13 +267,13 @@ set_slot_from_value( slot_info_t *pInfo, KvpValue *pValue)
     {
         gchar *key = get_key_from_path( pInfo->path );
         gchar *path = get_path_from_path( pInfo->path );
-        KvpFrame* frame = pInfo->pKvpFrame;
+        auto frame = pInfo->pKvpFrame;
         if ( path )
         {
-            frame = kvp_frame_get_frame_slash( frame, path );
+            frame = frame->get_slot(path)->get<KvpFrame*>();
             g_free( path );
         }
-        kvp_frame_set_value_nc( frame, key, pValue );
+        frame->set(key, pValue);
         g_free( key );
         break;
     }
@@ -349,9 +350,9 @@ get_int64_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, 0 );
 
-    if ( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_GINT64 )
+    if ( pInfo->pKvpValue->get_type() == KVP_TYPE_GINT64 )
     {
-        return kvp_value_get_gint64( pInfo->pKvpValue );
+        return pInfo->pKvpValue->get<int64_t>();
     }
     else
     {
@@ -368,7 +369,7 @@ set_int64_val( gpointer pObject, gint64 value )
     g_return_if_fail( pObject != NULL );
 
     if ( pInfo->value_type != KVP_TYPE_GINT64 ) return;
-    pValue = kvp_value_new_gint64( value );
+    pValue = new KvpValue{value};
     set_slot_from_value( pInfo, pValue );
 }
 
@@ -379,9 +380,9 @@ get_string_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if ( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_STRING )
+    if ( pInfo->pKvpValue->get_type() == KVP_TYPE_STRING )
     {
-        return (gpointer)kvp_value_get_string( pInfo->pKvpValue );
+        return (gpointer)pInfo->pKvpValue->get<const char*>();
     }
     else
     {
@@ -393,12 +394,12 @@ static void
 set_string_val( gpointer pObject, /*@ null @*/ gpointer pValue )
 {
     slot_info_t* pInfo = (slot_info_t*)pObject;
-    KvpValue *value = NULL;
-
     g_return_if_fail( pObject != NULL );
 
-    if ( pInfo->value_type != KVP_TYPE_STRING || pValue == NULL ) return;
-    value = kvp_value_new_string( (gchar*)pValue );
+    if (pInfo->value_type != KVP_TYPE_STRING || pValue == NULL)
+        return;
+    auto string = g_strdup(static_cast<const char*>(pValue));
+    auto value = new KvpValue{string};
     set_slot_from_value( pInfo, value );
 }
 
@@ -410,9 +411,9 @@ get_double_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if ( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_DOUBLE )
+    if (pInfo->pKvpValue->get_type() == KVP_TYPE_DOUBLE)
     {
-        d_val = kvp_value_get_double( pInfo->pKvpValue );
+        d_val = pInfo->pKvpValue->get<double>();
         return (gpointer)&d_val;
     }
     else
@@ -430,7 +431,7 @@ set_double_val( gpointer pObject, /*@ null @*/ gpointer pValue )
     g_return_if_fail( pObject != NULL );
 
     if ( pInfo->value_type != KVP_TYPE_DOUBLE || pValue == NULL ) return;
-    value = kvp_value_new_double( *((double*)pValue) );
+    value = new KvpValue{*(static_cast<double*>(pValue))};
     set_slot_from_value( pInfo, value );
 }
 
@@ -442,7 +443,7 @@ get_timespec_val( gpointer pObject )
     g_return_val_if_fail( pObject != NULL, gnc_dmy2timespec( 1, 1, 1970 ) );
 
 //if( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_TIMESPEC ) {
-    return kvp_value_get_timespec( pInfo->pKvpValue );
+    return pInfo->pKvpValue->get<Timespec>();
 }
 
 static void
@@ -454,7 +455,7 @@ set_timespec_val( gpointer pObject, Timespec ts )
     g_return_if_fail( pObject != NULL );
 
     if ( pInfo->value_type != KVP_TYPE_TIMESPEC ) return;
-    value = kvp_value_new_timespec( ts );
+    value = new KvpValue{ts};
     set_slot_from_value( pInfo, value );
 }
 
@@ -465,9 +466,9 @@ get_guid_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if ( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_GUID )
+    if (pInfo->pKvpValue->get_type() == KVP_TYPE_GUID)
     {
-        return (gpointer)kvp_value_get_guid( pInfo->pKvpValue );
+        return (gpointer)pInfo->pKvpValue->get<GncGUID*>();
     }
     else
     {
@@ -487,8 +488,8 @@ set_guid_val( gpointer pObject, /*@ null @*/ gpointer pValue )
     {
     case KVP_TYPE_GUID:
     {
-        KvpValue *value = kvp_value_new_guid( (GncGUID*)pValue );
-        set_slot_from_value( pInfo, value );
+        auto new_guid = guid_copy(static_cast<GncGUID*>(pValue));
+        set_slot_from_value(pInfo, new KvpValue{new_guid});
         break;
     }
     case KVP_TYPE_GLIST:
@@ -500,8 +501,8 @@ set_guid_val( gpointer pObject, /*@ null @*/ gpointer pValue )
         newInfo->context = LIST;
 
         slots_load_info( newInfo );
-        pValue = kvp_value_new_glist_nc( newInfo->pList );
-        kvp_frame_set_slot_nc(pInfo->pKvpFrame, key, pValue);
+        pValue = new KvpValue{newInfo->pList};
+        pInfo->pKvpFrame->set(key, pValue);
         g_string_free( newInfo->path, TRUE );
         g_slice_free( slot_info_t, newInfo );
         g_free( key );
@@ -510,14 +511,14 @@ set_guid_val( gpointer pObject, /*@ null @*/ gpointer pValue )
     case KVP_TYPE_FRAME:
     {
         slot_info_t *newInfo = slot_info_copy( pInfo, (GncGUID*)pValue ) ;
-        KvpFrame *newFrame = kvp_frame_new();
+        auto newFrame = new KvpFrame;
         newInfo->pKvpFrame = newFrame;
 
         switch ( pInfo->context )
         {
         case LIST:
         {
-            KvpValue *value = kvp_value_new_frame_nc( newFrame );
+            auto value = new KvpValue{newFrame};
             gchar *key = get_key_from_path( pInfo->path );
             newInfo->path = g_string_assign( newInfo->path, key );
             pInfo->pList = g_list_append( pInfo->pList, value );
@@ -528,7 +529,7 @@ set_guid_val( gpointer pObject, /*@ null @*/ gpointer pValue )
         default:
         {
             gchar *key = get_key_from_path( pInfo->path );
-            kvp_frame_set_frame_nc( pInfo->pKvpFrame, key, newFrame );
+            pInfo->pKvpFrame->set(key, new KvpValue{newFrame});
             g_free( key );
             break;
         }
@@ -552,9 +553,9 @@ get_numeric_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, gnc_numeric_zero() );
 
-    if ( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_NUMERIC )
+    if (pInfo->pKvpValue->get_type() == KVP_TYPE_NUMERIC)
     {
-        return kvp_value_get_numeric( pInfo->pKvpValue );
+        return pInfo->pKvpValue->get<gnc_numeric>();
     }
     else
     {
@@ -571,8 +572,7 @@ set_numeric_val( gpointer pObject, gnc_numeric value )
     g_return_if_fail( pObject != NULL );
 
     if ( pInfo->value_type != KVP_TYPE_NUMERIC ) return;
-    pValue = kvp_value_new_numeric( value );
-    set_slot_from_value( pInfo, pValue );
+    set_slot_from_value(pInfo, new KvpValue{value});
 }
 
 static GDate*
@@ -583,9 +583,9 @@ get_gdate_val( gpointer pObject )
 
     g_return_val_if_fail( pObject != NULL, NULL );
 
-    if ( kvp_value_get_type( pInfo->pKvpValue ) == KVP_TYPE_GDATE )
+    if (pInfo->pKvpValue->get_type() == KVP_TYPE_GDATE)
     {
-        date = kvp_value_get_gdate( pInfo->pKvpValue );
+        date = pInfo->pKvpValue->get<GDate>();
         return &date;
     }
     else
@@ -603,8 +603,7 @@ set_gdate_val( gpointer pObject, GDate* value )
     g_return_if_fail( pObject != NULL );
 
     if ( pInfo->value_type != KVP_TYPE_GDATE ) return;
-    pValue = kvp_value_new_gdate( *value );
-    set_slot_from_value( pInfo, pValue );
+    set_slot_from_value(pInfo, new KvpValue{*value});
 }
 
 static slot_info_t *
@@ -649,24 +648,24 @@ save_slot( const gchar* key, KvpValue* value, gpointer data )
         (void)g_string_append( pSlot_info->path, "/" );
     }
     (void)g_string_append( pSlot_info->path, key );
-    pSlot_info->value_type = kvp_value_get_type( value );
+    pSlot_info->value_type = value->get_type();
 
     switch ( pSlot_info->value_type )
     {
     case KVP_TYPE_FRAME:
     {
-        KvpFrame* pKvpFrame = kvp_value_get_frame( value );
-        GncGUID guid = guid_new_return();
-        slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid );
+        auto pKvpFrame = value->get<KvpFrame*>();
+        auto guid = guid_new();
+        slot_info_t *pNewInfo = slot_info_copy( pSlot_info, guid );
         KvpValue *oldValue = pSlot_info->pKvpValue;
-        pSlot_info->pKvpValue = kvp_value_new_guid( &guid );
+        pSlot_info->pKvpValue = new KvpValue{guid};
         pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be,
                             OP_DB_INSERT, TABLE_NAME,
                             TABLE_NAME, pSlot_info,
                             col_table );
         g_return_if_fail( pSlot_info->is_ok );
-        kvp_frame_for_each_slot( pKvpFrame, save_slot, pNewInfo );
-        kvp_value_delete( pSlot_info->pKvpValue );
+        pKvpFrame->for_each_slot(save_slot, pNewInfo);
+        delete pSlot_info->pKvpValue;
         pSlot_info->pKvpValue = oldValue;
         g_string_free( pNewInfo->path, TRUE );
         g_slice_free( slot_info_t, pNewInfo );
@@ -674,22 +673,21 @@ save_slot( const gchar* key, KvpValue* value, gpointer data )
     break;
     case KVP_TYPE_GLIST:
     {
-        GList *cursor;
         GncGUID guid = guid_new_return();
         slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid );
         KvpValue *oldValue = pSlot_info->pKvpValue;
-        pSlot_info->pKvpValue = kvp_value_new_guid( &guid );
+        pSlot_info->pKvpValue = new KvpValue{&guid};
         pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be,
                             OP_DB_INSERT, TABLE_NAME,
                             TABLE_NAME, pSlot_info,
                             col_table );
         g_return_if_fail( pSlot_info->is_ok );
-        for (cursor = kvp_value_get_glist(value); cursor; cursor = cursor->next)
+        for (auto cursor = value->get<GList*>(); cursor; cursor = cursor->next)
         {
-            KvpValue *val = (KvpValue*)cursor->data;
+            auto val = static_cast<KvpValue*>(cursor->data);
             save_slot("", val, pNewInfo);
         }
-        kvp_value_delete( pSlot_info->pKvpValue );
+        delete pSlot_info->pKvpValue;
         pSlot_info->pKvpValue = oldValue;
         g_string_free( pNewInfo->path, TRUE );
         g_slice_free( slot_info_t, pNewInfo );
@@ -727,7 +725,7 @@ gnc_sql_slots_save( GncSqlBackend* be, const GncGUID* guid, gboolean is_infant,
 
     slot_info.be = be;
     slot_info.guid = guid;
-    kvp_frame_for_each_slot( pFrame, save_slot, &slot_info );
+    pFrame->for_each_slot(save_slot, &slot_info);
     (void)g_string_free( slot_info.path, TRUE );
 
     return slot_info.is_ok;

commit 7c4e1f7f2a0ca83a201038f6fc086566bbcabab7
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jun 21 15:10:33 2015 -0700

    Fix slash handling in keys.
    
    In actual use '/' is a path delimiter indicating a child KvpFrame. The
    previous implementation created keys for single frames with embedded '/'
    characters.
    
    Memory management issues in make_vector necessitated changing Path to a
    std::vector<std::string>>.

diff --git a/src/backend/xml/test/test-kvp-frames.c b/src/backend/xml/test/test-kvp-frames.c
index 09a5890..1727282 100644
--- a/src/backend/xml/test/test-kvp-frames.c
+++ b/src/backend/xml/test/test-kvp-frames.c
@@ -132,7 +132,7 @@ test_kvp_frames1(void)
         test_val1 = get_random_kvp_value(i % KVP_TYPE_FRAME);
 
         test_frame1 = kvp_frame_new();
-        test_key = get_random_string();
+        test_key = get_random_string_without("/");
 
         kvp_frame_set_slot(test_frame1, test_key, test_val1);
 
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index e3246c0..8a5b401 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -39,6 +39,8 @@ extern "C"
 #include <algorithm>
 #include <vector>
 
+static const char delim = '/';
+
 KvpFrameImpl::KvpFrameImpl(const KvpFrameImpl & rhs) noexcept
 {
     std::for_each(rhs.m_valuemap.begin(), rhs.m_valuemap.end(),
@@ -51,12 +53,28 @@ KvpFrameImpl::KvpFrameImpl(const KvpFrameImpl & rhs) noexcept
     );
 }
 
+static inline Path
+make_vector(std::string key)
+{
+    Path path;
+    for (auto length = key.find(delim); length != std::string::npos;)
+    {
+        path.push_back(key.substr(0, length));
+        key = key.substr(length + 1);
+        length = key.find(delim);
+    }
+    path.push_back(key);
+    return path;
+}
+
 KvpValue*
 KvpFrameImpl::set(const char* key, KvpValue* value) noexcept
 {
     if (!key) return nullptr;
-    auto spot = m_valuemap.find(key);
+    if (strchr(key, delim))
+        return set(make_vector(key), value);
     KvpValue* ret {nullptr};
+    auto spot = m_valuemap.find(key);
     if (spot != m_valuemap.end())
     {
         qof_string_cache_remove(spot->first);
@@ -66,7 +84,8 @@ KvpFrameImpl::set(const char* key, KvpValue* value) noexcept
 
     if (value)
     {
-        auto cachedkey = static_cast<const char *>(qof_string_cache_insert(key));
+        auto cachedkey =
+            static_cast<const char *>(qof_string_cache_insert(key));
         m_valuemap.insert({cachedkey,value});
     }
 
@@ -79,7 +98,7 @@ walk_path_or_nullptr(const KvpFrameImpl* frame, Path& path)
     KvpFrameImpl* cur_frame = const_cast<KvpFrameImpl*>(frame);
     for(auto key:path)
     {
-        auto slot = cur_frame->get_slot(key);
+        auto slot = cur_frame->get_slot(key.c_str());
         if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
             return nullptr;
         cur_frame = slot->get<KvpFrame*>();
@@ -87,37 +106,52 @@ walk_path_or_nullptr(const KvpFrameImpl* frame, Path& path)
     return cur_frame;
 }
 
-
 KvpValue*
 KvpFrameImpl::set(Path path, KvpValue* value) noexcept
 {
-    const char* last_key = path.back();
+    auto last_key = path.back();
     path.pop_back();
     auto cur_frame = walk_path_or_nullptr(this, path);
     if (cur_frame == nullptr)
         return nullptr;
-    return cur_frame->set(last_key, value);
+    if (last_key.find(delim) != std::string::npos)
+        return set(make_vector(last_key), value);
+    return cur_frame->set(last_key.c_str(), value);
 }
 
-KvpValue*
-KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
+static inline KvpFrameImpl*
+walk_path_and_create(KvpFrameImpl* frame, Path path)
 {
-    auto cur_frame = this;
-    const char* last_key = path.back();
-    path.pop_back();
-    for(auto key:path)
+     for(auto key:path)
     {
-        auto slot = cur_frame->get_slot(key);
+        if (key.find(delim) != std::string::npos)
+        {
+            frame = walk_path_and_create(frame, make_vector(key));
+            continue;
+        }
+        auto slot = frame->get_slot(key.c_str());
         if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
         {
             auto new_frame = new KvpFrame;
-            delete cur_frame->set(key, new KvpValue{new_frame});
-            cur_frame = new_frame;
+            delete frame->set(key.c_str(), new KvpValue{new_frame});
+            frame = new_frame;
             continue;
         }
-        cur_frame = slot->get<KvpFrame*>();
+        frame = slot->get<KvpFrame*>();
     }
-    return cur_frame->set(last_key, value);
+    return frame;
+}
+
+KvpValue*
+KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
+{
+    auto cur_frame = this;
+    auto last_key = path.back();
+    path.pop_back();
+    cur_frame = walk_path_and_create(const_cast<KvpFrame*>(this), path);
+    if (last_key.find(delim) != std::string::npos)
+        return set_path(make_vector(last_key), value);
+    return cur_frame->set(last_key.c_str(), value);
 }
 
 std::string
@@ -173,6 +207,9 @@ KvpFrameImpl::for_each_slot(void (*proc)(const char *key, KvpValue *value,
 KvpValueImpl *
 KvpFrameImpl::get_slot(const char * key) const noexcept
 {
+    if (!key) return nullptr;
+    if (strchr(key, delim))
+        return get_slot(make_vector(key));
     auto spot = m_valuemap.find(key);
     if (spot == m_valuemap.end())
         return nullptr;
@@ -182,12 +219,14 @@ KvpFrameImpl::get_slot(const char * key) const noexcept
 KvpValueImpl *
 KvpFrameImpl::get_slot(Path path) const noexcept
 {
-    const char* last_key = path.back();
+    auto last_key = path.back();
     path.pop_back();
     auto cur_frame = walk_path_or_nullptr(this, path);
     if (cur_frame == nullptr)
         return nullptr;
-    return cur_frame->get_slot(last_key);
+    if (last_key.find(delim) != std::string::npos)
+        return get_slot(make_vector(last_key));
+    return cur_frame->get_slot(last_key.c_str());
 
 }
 
diff --git a/src/libqof/qof/kvp_frame.hpp b/src/libqof/qof/kvp_frame.hpp
index 8d5b43d..322e9fa 100644
--- a/src/libqof/qof/kvp_frame.hpp
+++ b/src/libqof/qof/kvp_frame.hpp
@@ -41,7 +41,7 @@ class cstring_comparer
     }
 };
 
-using Path = std::vector<const char*>;
+using Path = std::vector<std::string>;
 
 struct KvpFrameImpl
 {
diff --git a/src/libqof/qof/test/test-kvp-frame.cpp b/src/libqof/qof/test/test-kvp-frame.cpp
index 0fa9e45..3082474 100644
--- a/src/libqof/qof/test/test-kvp-frame.cpp
+++ b/src/libqof/qof/test/test-kvp-frame.cpp
@@ -57,10 +57,14 @@ TEST_F (KvpFrameTest, SetLocal)
     auto f1 = new KvpFrameImpl;
     auto v1 = new KvpValueImpl {15.0};
     auto v2 = new KvpValueImpl { (int64_t)52};
-    std::string k1 {"first key"};
+    const char* k1 = "first key";
+    const char* k2 = "first key/second key";
 
-    EXPECT_EQ (nullptr, f1->set (k1.c_str (), v1));
-    EXPECT_EQ (v1, f1->set (k1.c_str (), v2));
+    EXPECT_EQ (nullptr, f1->set (k1, v1));
+    auto first_frame = new KvpFrame;
+    EXPECT_EQ (v1, f1->set (k1, new KvpValue{first_frame}));
+    EXPECT_EQ (nullptr, f1->set(k2, v2));
+    EXPECT_EQ (v2, first_frame->get_slot("second key"));
 
     delete f1; //this should also delete v2.
     delete v1;
@@ -81,6 +85,24 @@ TEST_F (KvpFrameTest, SetPath)
     delete v1;
 }
 
+TEST_F (KvpFrameTest, SetPathSlash)
+{
+    Path path1 {"top", "second/twenty", "twenty-first"};
+    Path path2 {"top", "third", "thirty-first"};
+    auto v1 = new KvpValueImpl {15.0};
+    auto v2 = new KvpValueImpl { (int64_t)52};
+
+    EXPECT_EQ (nullptr, t_root.set(path1, v1));
+    EXPECT_EQ (nullptr, t_root.set(path1, v2));
+    auto second_frame = t_root.get_slot("top")->get<KvpFrame*>()->get_slot("second")->get<KvpFrame*>();
+    second_frame->set("twenty", new KvpValue{new KvpFrame});
+    EXPECT_EQ (nullptr, t_root.set(path1, v1));
+    EXPECT_EQ (v1, t_root.set(path1, v2));
+    EXPECT_EQ (v2, t_root.get_slot(path1));
+    EXPECT_EQ (nullptr, t_root.get_slot(path2));
+    delete v1;
+}
+
 TEST_F (KvpFrameTest, SetPathWithCreate)
 {
     Path path1 {"top", "second", "twenty-first"};
@@ -95,6 +117,22 @@ TEST_F (KvpFrameTest, SetPathWithCreate)
     EXPECT_EQ (v1, t_root.get_slot(path2));
 }
 
+TEST_F (KvpFrameTest, SetPathWithCreateSlash)
+{
+    Path path1 {"top", "second/twenty", "twenty-first"};
+    Path path2 {"top", "third", "thirty-first"};
+    Path path1a {"top", "second", "twenty", "twenty-first"};
+    auto v1 = new KvpValueImpl {15.0};
+    auto v2 = new KvpValueImpl { (int64_t)52};
+
+    EXPECT_EQ (nullptr, t_root.set_path(path1, v1));
+    EXPECT_EQ (v1, t_root.set_path(path1, v2));
+    EXPECT_EQ (nullptr, t_root.set_path(path2, v1));
+    EXPECT_EQ (v2, t_root.get_slot(path1));
+    EXPECT_EQ (v2, t_root.get_slot(path1a));
+    EXPECT_EQ (v1, t_root.get_slot(path2));
+}
+
 TEST_F (KvpFrameTest, GetKeys)
 {
     auto k1 = "top";
@@ -117,6 +155,7 @@ TEST_F (KvpFrameTest, GetLocalSlot)
     auto k1 = "first";
     auto k2 = "third";
     auto k3 = "doesn't exist";
+    auto k4 = "top/first";
 
     auto frameval = t_root.get_slot("top");
     ASSERT_EQ(frameval->get_type(), KVP_TYPE_FRAME);
@@ -124,12 +163,15 @@ TEST_F (KvpFrameTest, GetLocalSlot)
     EXPECT_EQ (t_int_val, f1->get_slot(k1));
     EXPECT_EQ (t_str_val, f1->get_slot(k2));
     EXPECT_EQ (nullptr, f1->get_slot(k3));
+    EXPECT_EQ (t_int_val, t_root.get_slot(k4));
 }
 
 TEST_F (KvpFrameTest, GetSlotPath)
 {
     Path path1 {"top", "second", "twenty-first"};
     Path path2 {"top", "third", "thirty-first"};
+    Path path3 {"top", "second", "twenty", "twenty-first"};
+    Path path3a {"top", "second/twenty", "twenty-first"};
     auto v1 = new KvpValueImpl {15.0};
     auto v2 = new KvpValueImpl { (int64_t)52};
 
@@ -137,7 +179,8 @@ TEST_F (KvpFrameTest, GetSlotPath)
     EXPECT_EQ (nullptr, t_root.set(path2, v2));
     EXPECT_EQ (v1, t_root.get_slot(path1));
     EXPECT_EQ (nullptr, t_root.get_slot(path2));
-    delete v2;
+    t_root.set_path(path3, v1);
+    EXPECT_EQ (v1, t_root.get_slot(path3a));
 }
 
 TEST_F (KvpFrameTest, Empty)

commit 0987184709abb675bcf9299c93ab5db8b9bf6c59
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 18 13:55:55 2015 -0700

    Add path-vector get/set functions to KvpFrameImpl.
    
    Needed for Scheme access. The C functions used GList.

diff --git a/src/backend/xml/io-gncxml-v1.cpp b/src/backend/xml/io-gncxml-v1.cpp
index 29fcad6..3cfbc9f 100644
--- a/src/backend/xml/io-gncxml-v1.cpp
+++ b/src/backend/xml/io-gncxml-v1.cpp
@@ -806,7 +806,7 @@ kvp_frame_slot_end_handler(gpointer data_for_children,
     if (key_node_count != 1) return(FALSE);
 
     value_cr->should_cleanup = TRUE;
-    f->replace_nc(key, value);
+    f->set(key, value);
     if (delete_value)
         delete value;
     return(TRUE);
diff --git a/src/backend/xml/sixtp-dom-parsers.cpp b/src/backend/xml/sixtp-dom-parsers.cpp
index 71a92ad..49f6311 100644
--- a/src/backend/xml/sixtp-dom-parsers.cpp
+++ b/src/backend/xml/sixtp-dom-parsers.cpp
@@ -446,7 +446,7 @@ dom_tree_to_kvp_frame_given(xmlNodePtr node, KvpFrame *frame)
                 if (val)
                 {
                     //We're deleting the old KvpValue returned by replace_nc().
-                    delete frame->replace_nc(key, val);
+                    delete frame->set(key, val);
                 }
                 else
                 {
diff --git a/src/libqof/qof/kvp-value.cpp b/src/libqof/qof/kvp-value.cpp
index d24c6be..ce79dfc 100644
--- a/src/libqof/qof/kvp-value.cpp
+++ b/src/libqof/qof/kvp-value.cpp
@@ -325,7 +325,7 @@ delete_visitor::operator()(GncGUID * & value)
 template <> void
 delete_visitor::operator()(KvpFrame * & value)
 {
-    kvp_frame_delete(value);
+    delete value;
 }
 
 KvpValueImpl::~KvpValueImpl() noexcept
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index b60ff16..e3246c0 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -51,11 +51,12 @@ KvpFrameImpl::KvpFrameImpl(const KvpFrameImpl & rhs) noexcept
     );
 }
 
-KvpValueImpl * KvpFrameImpl::replace_nc(const char * key, KvpValueImpl * value) noexcept
+KvpValue*
+KvpFrameImpl::set(const char* key, KvpValue* value) noexcept
 {
     if (!key) return nullptr;
     auto spot = m_valuemap.find(key);
-    KvpValueImpl * ret {nullptr};
+    KvpValue* ret {nullptr};
     if (spot != m_valuemap.end())
     {
         qof_string_cache_remove(spot->first);
@@ -72,6 +73,53 @@ KvpValueImpl * KvpFrameImpl::replace_nc(const char * key, KvpValueImpl * value)
     return ret;
 }
 
+static inline KvpFrameImpl*
+walk_path_or_nullptr(const KvpFrameImpl* frame, Path& path)
+{
+    KvpFrameImpl* cur_frame = const_cast<KvpFrameImpl*>(frame);
+    for(auto key:path)
+    {
+        auto slot = cur_frame->get_slot(key);
+        if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
+            return nullptr;
+        cur_frame = slot->get<KvpFrame*>();
+    }
+    return cur_frame;
+}
+
+
+KvpValue*
+KvpFrameImpl::set(Path path, KvpValue* value) noexcept
+{
+    const char* last_key = path.back();
+    path.pop_back();
+    auto cur_frame = walk_path_or_nullptr(this, path);
+    if (cur_frame == nullptr)
+        return nullptr;
+    return cur_frame->set(last_key, value);
+}
+
+KvpValue*
+KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
+{
+    auto cur_frame = this;
+    const char* last_key = path.back();
+    path.pop_back();
+    for(auto key:path)
+    {
+        auto slot = cur_frame->get_slot(key);
+        if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
+        {
+            auto new_frame = new KvpFrame;
+            delete cur_frame->set(key, new KvpValue{new_frame});
+            cur_frame = new_frame;
+            continue;
+        }
+        cur_frame = slot->get<KvpFrame*>();
+    }
+    return cur_frame->set(last_key, value);
+}
+
 std::string
 KvpFrameImpl::to_string() const noexcept
 {
@@ -131,6 +179,18 @@ KvpFrameImpl::get_slot(const char * key) const noexcept
     return spot->second;
 }
 
+KvpValueImpl *
+KvpFrameImpl::get_slot(Path path) const noexcept
+{
+    const char* last_key = path.back();
+    path.pop_back();
+    auto cur_frame = walk_path_or_nullptr(this, path);
+    if (cur_frame == nullptr)
+        return nullptr;
+    return cur_frame->get_slot(last_key);
+
+}
+
 int compare(const KvpFrameImpl * one, const KvpFrameImpl * two) noexcept
 {
     if (one && !two) return 1;
@@ -205,9 +265,7 @@ kvp_frame_get_keys(const KvpFrame * frame)
 gboolean
 kvp_frame_is_empty(const KvpFrame * frame)
 {
-    if (!frame) return TRUE;
-    auto realframe = static_cast<KvpFrameImpl const *>(frame);
-    return realframe->get_keys().size() == 0;
+    return frame->empty();
 }
 
 KvpFrame *
@@ -222,26 +280,20 @@ kvp_frame_copy(const KvpFrame * frame)
  * removing the key from the KVP tree.
  */
 static KvpValue *
-kvp_frame_replace_slot_nc (KvpFrame * frame, const char * slot,
-                           KvpValue * new_value)
+kvp_frame_replace_slot_nc (KvpFrame* frame, const char* slot, KvpValue* value)
 {
-    if (!frame) return NULL;
-
-    auto realframe = static_cast<KvpFrameImpl *>(frame);
-    auto realnewvalue = static_cast<KvpValueImpl *>(new_value);
-    return realframe->replace_nc(slot, realnewvalue);
+    if (!frame) return nullptr;
+    return frame->set(slot, value);
 }
 
 /* Passing in a null value into this routine has the effect
  * of deleting the old value stored at this slot.
  */
 static inline void
-kvp_frame_set_slot_destructively(KvpFrame * frame, const char * slot,
-                                 KvpValue * new_value)
+kvp_frame_set_slot_destructively(KvpFrame* frame, const char* slot,
+                                 KvpValue* value)
 {
-    KvpValue * old_value;
-    old_value = kvp_frame_replace_slot_nc (frame, slot, new_value);
-    kvp_value_delete (old_value);
+    delete frame->set(slot, value);
 }
 
 /* ============================================================ */
@@ -584,14 +636,12 @@ void
 kvp_frame_set_slot(KvpFrame * frame, const char * slot,
                    KvpValue * value)
 {
-    KvpValue *new_value = NULL;
-
+    KvpValue* new_value{nullptr};
     if (!frame) return;
-
     g_return_if_fail (slot && *slot != '\0');
 
     if (value) new_value = kvp_value_copy(value);
-    kvp_frame_set_slot_destructively(frame, slot, new_value);
+    delete frame->set(slot, new_value);
 }
 
 void
@@ -599,18 +649,16 @@ kvp_frame_set_slot_nc(KvpFrame * frame, const char * slot,
                       KvpValue * value)
 {
     if (!frame) return;
-
     g_return_if_fail (slot && *slot != '\0');
 
-    kvp_frame_set_slot_destructively(frame, slot, value);
+    frame->set(slot, value);
 }
 
 KvpValue *
 kvp_frame_get_slot(const KvpFrame * frame, const char * slot)
 {
-    if (!frame) return NULL;
-    auto realframe = static_cast<const KvpFrameImpl *>(frame);
-    return realframe->get_slot(slot);
+    if (!frame) return nullptr;
+    return frame->get_slot(slot);
 }
 
 void
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index 7de7dc4..fa1acc3 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -315,10 +315,10 @@ KvpValue  * kvp_frame_get_value(const KvpFrame *frame, const gchar *path);
  *  exist.
 */
 /*@ dependent @*/
-KvpFrame  * kvp_frame_get_frame(const KvpFrame *frame, const gchar *path);
+KvpFrame* kvp_frame_get_frame(const KvpFrame *frame, const gchar *path);
 
-KvpFrame    * kvp_frame_get_frame_slash (KvpFrame *frame,
-        const gchar *path);
+KvpFrame* kvp_frame_get_frame_slash (KvpFrame *frame,
+                                     const gchar *path);
 
 /** @} */
 /** @name KvpFrame KvpValue low-level storing routines.
diff --git a/src/libqof/qof/kvp_frame.hpp b/src/libqof/qof/kvp_frame.hpp
index 3f5e3dc..8d5b43d 100644
--- a/src/libqof/qof/kvp_frame.hpp
+++ b/src/libqof/qof/kvp_frame.hpp
@@ -41,9 +41,11 @@ class cstring_comparer
     }
 };
 
+using Path = std::vector<const char*>;
+
 struct KvpFrameImpl
 {
-    typedef std::map<const char *, KvpValueImpl *, cstring_comparer> map_type;
+    typedef std::map<const char *, KvpValue*, cstring_comparer> map_type;
 
     public:
     KvpFrameImpl() noexcept {};
@@ -54,22 +56,67 @@ struct KvpFrameImpl
     KvpFrameImpl(const KvpFrameImpl &) noexcept;
 
     /**
-     * Replaces the KvpValueImpl at the specified spot, and returns
-     * the old KvpValueImpl which used to occupy the spot.
-     *
-     * If no KvpValueImpl was at the spot, nullptr is returned.
+     * Set the value with the key in the immediate frame, replacing and
+     * returning the old value if it exists or nullptr if it doesn't.
+     * @param key: The key to insert/replace.
+     * @param newvalue: The value to set at key.
+     * @return The old value if there was one or nullptr.
+     */
+    KvpValue* set(const char * key, KvpValue* newvalue) noexcept;
+    /**
+     * Set the value with the key in a subframe following the keys in path,
+     * replacing and returning the old value if it exists or nullptr if it
+     * doesn't.
+     * @throw invalid_argument if the path doesn't exist.
+     * @param path: The path of subframes leading to the frame in which to
+     * insert/replace.
+     * @param newvalue: The value to set at key.
+     * @return The old value if there was one or nullptr.
+     */
+    KvpValue* set(Path path, KvpValue* newvalue) noexcept;
+    /**
+     * Set the value with the key in a subframe following the keys in path,
+     * replacing and returning the old value if it exists or nullptr if it
+     * doesn't. Creates any missing intermediate frames.
+     * @param path: The path of subframes leading to the frame in which to
+     * insert/replace.
+     * @param newvalue: The value to set at key.
+     * @return The old value if there was one or nullptr.
+     */
+    KvpValue* set_path(Path path, KvpValue* newvalue) noexcept;
+    /**
+     * Make a string representation of the frame. Mostly useful for debugging.
+     * @return A std::string representing the frame and all its children.
      */
-    KvpValueImpl * replace_nc(const char * key, KvpValueImpl * newvalue) noexcept;
-
     std::string to_string() const noexcept;
-
+    /**
+     * Report the keys in the immediate frame. Be sensible about using this, it
+     * isn't a very efficient way to iterate.
+     * @return std::vector of keys as std::strings.
+     */
     std::vector<std::string> get_keys() const noexcept;
 
-    KvpValueImpl * get_slot(const char * key) const noexcept;
-
-    void for_each_slot(void (*proc)(const char *key, KvpValue *value, void * data), void *data) const noexcept;
+    /** Get the value for the key or nullptr if it doesn't exist.
+     * @param key: The key.
+     * @return The value at the key or nullptr.
+     */
+    KvpValue* get_slot(const char * key) const noexcept;
+    /** Get the value for the tail of the path or nullptr if it doesn't exist.
+     * @param path: Path of keys leading to the desired value.
+     * @return The value at the key or nullptr.
+     */
+    KvpValue* get_slot(Path keys) const noexcept;
+    /** Convenience wrapper for std::for_each, which should be preferred.
+     */
+    void for_each_slot(void (*proc)(const char *key, KvpValue *value,
+                                    void * data),
+                       void *data) const noexcept;
 
-    friend int compare(const KvpFrameImpl &, const KvpFrameImpl &) noexcept;
+    /** Test for emptiness
+     * @return true if the frame contains nothing.
+     */
+    bool empty() const noexcept { return m_valuemap.empty(); }
+    friend int compare(const KvpFrameImpl&, const KvpFrameImpl&) noexcept;
 
     private:
     map_type m_valuemap;
diff --git a/src/libqof/qof/test/test-kvp-frame.cpp b/src/libqof/qof/test/test-kvp-frame.cpp
index 432c811..0fa9e45 100644
--- a/src/libqof/qof/test/test-kvp-frame.cpp
+++ b/src/libqof/qof/test/test-kvp-frame.cpp
@@ -27,6 +27,24 @@
 #include <gtest/gtest.h>
 #include <algorithm>
 
+class KvpFrameTest : public ::testing::Test
+{
+public:
+    KvpFrameTest() :
+        t_int_val{new KvpValue {INT64_C(15)}},
+        t_str_val{new KvpValue{"a value"}}     {
+        auto f1 = new KvpFrame;
+        t_root.set("top", new KvpValue{f1});
+        f1->set("first", t_int_val);
+        f1->set("second", new KvpValue{new KvpFrame});
+        f1->set("third", t_str_val);
+    }
+protected:
+    KvpFrameImpl t_root;
+    KvpValue *t_int_val;
+    KvpValue *t_str_val;
+};
+
 template <typename A, typename B> void
 assert_contains (std::vector<A> vec, B const & b)
 {
@@ -34,57 +52,98 @@ assert_contains (std::vector<A> vec, B const & b)
     EXPECT_NE (val, vec.end ());
 }
 
-TEST (KvpFrameTest, Replace)
+TEST_F (KvpFrameTest, SetLocal)
 {
     auto f1 = new KvpFrameImpl;
     auto v1 = new KvpValueImpl {15.0};
     auto v2 = new KvpValueImpl { (int64_t)52};
     std::string k1 {"first key"};
 
-    EXPECT_EQ (nullptr, f1->replace_nc (k1.c_str (), v1));
-    EXPECT_EQ (v1, f1->replace_nc (k1.c_str (), v2));
+    EXPECT_EQ (nullptr, f1->set (k1.c_str (), v1));
+    EXPECT_EQ (v1, f1->set (k1.c_str (), v2));
 
     delete f1; //this should also delete v2.
     delete v1;
 }
 
-TEST (KvpFrameTest, GetKeys)
+TEST_F (KvpFrameTest, SetPath)
 {
-    auto k1 = "first key";
-    auto k2 = "second key";
-    auto k3 = "first key/third key";
-    auto f1 = new KvpFrameImpl;
-    auto v1 = new KvpValueImpl {15.2};
-    auto v2 = new KvpValueImpl { (int64_t)12};
-    auto v3 = new KvpValueImpl {strdup ("Never again")};
+    Path path1 {"top", "second", "twenty-first"};
+    Path path2 {"top", "third", "thirty-first"};
+    auto v1 = new KvpValueImpl {15.0};
+    auto v2 = new KvpValueImpl { (int64_t)52};
 
-    f1->replace_nc (k1, v1);
-    f1->replace_nc (k2, v2);
-    f1->replace_nc (k3, v3);
+    EXPECT_EQ (nullptr, t_root.set(path1, v1));
+    EXPECT_EQ (v1, t_root.set(path1, v2));
+    EXPECT_EQ (nullptr, t_root.set(path2, v1));
+    EXPECT_EQ (v2, t_root.get_slot(path1));
+    EXPECT_EQ (nullptr, t_root.get_slot(path2));
+    delete v1;
+}
 
-    auto keys = f1->get_keys ();
-    EXPECT_EQ (keys.size (), 3);
+TEST_F (KvpFrameTest, SetPathWithCreate)
+{
+    Path path1 {"top", "second", "twenty-first"};
+    Path path2 {"top", "third", "thirty-first"};
+    auto v1 = new KvpValueImpl {15.0};
+    auto v2 = new KvpValueImpl { (int64_t)52};
+
+    EXPECT_EQ (nullptr, t_root.set_path(path1, v1));
+    EXPECT_EQ (v1, t_root.set_path(path1, v2));
+    EXPECT_EQ (nullptr, t_root.set_path(path2, v1));
+    EXPECT_EQ (v2, t_root.get_slot(path1));
+    EXPECT_EQ (v1, t_root.get_slot(path2));
+}
+
+TEST_F (KvpFrameTest, GetKeys)
+{
+    auto k1 = "top";
+    auto k2 = "first";
+    auto k3 = "second";
+
+    auto keys = t_root.get_keys ();
+    EXPECT_EQ (keys.size (), 1);
 
     assert_contains (keys, k1);
+    auto frameval = t_root.get_slot(k1);
+    ASSERT_EQ(frameval->get_type(), KVP_TYPE_FRAME);
+    keys = frameval->get<KvpFrame*>()->get_keys();
     assert_contains (keys, k2);
     assert_contains (keys, k3);
+}
 
-    delete f1;//This should delete our KvpValueImpls, and our string above, too.
+TEST_F (KvpFrameTest, GetLocalSlot)
+{
+    auto k1 = "first";
+    auto k2 = "third";
+    auto k3 = "doesn't exist";
+
+    auto frameval = t_root.get_slot("top");
+    ASSERT_EQ(frameval->get_type(), KVP_TYPE_FRAME);
+    auto f1 = frameval->get<KvpFrame*>();
+    EXPECT_EQ (t_int_val, f1->get_slot(k1));
+    EXPECT_EQ (t_str_val, f1->get_slot(k2));
+    EXPECT_EQ (nullptr, f1->get_slot(k3));
 }
 
-TEST (KvpFrameTest, GetSlot)
+TEST_F (KvpFrameTest, GetSlotPath)
 {
-    auto f1 = new KvpFrameImpl;
-    auto v1 = new KvpValueImpl {2.2};
-    auto v2 = new KvpValueImpl { (int64_t)4};
-    auto k1 = "first key";
-    auto k2 = "first key/second key";
-
-    f1->replace_nc (k1, v1);
-    EXPECT_EQ (v1, f1->get_slot(k1));
-    f1->replace_nc (k2, v2);
-    EXPECT_EQ (v2, f1->get_slot(k2));
-    EXPECT_EQ (v1, f1->get_slot(k1));
-
-    delete f1;//which will delete both kvpvalues, too.
+    Path path1 {"top", "second", "twenty-first"};
+    Path path2 {"top", "third", "thirty-first"};
+    auto v1 = new KvpValueImpl {15.0};
+    auto v2 = new KvpValueImpl { (int64_t)52};
+
+    EXPECT_EQ (nullptr, t_root.set(path1, v1));
+    EXPECT_EQ (nullptr, t_root.set(path2, v2));
+    EXPECT_EQ (v1, t_root.get_slot(path1));
+    EXPECT_EQ (nullptr, t_root.get_slot(path2));
+    delete v2;
+}
+
+TEST_F (KvpFrameTest, Empty)
+{
+    KvpFrameImpl f1, f2;
+    f2.set("value", new KvpValue {2.2});
+    EXPECT_TRUE(f1.empty());
+    EXPECT_FALSE(f2.empty());
 }

commit 45a01b0f67a3fca1781be2df91153be29410e05f
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 18 13:02:00 2015 -0700

    Change the KVP string storage type from char* to const char*.
    
    Because we don't want to be able to get a pointer to the KvpValue and
    change its contents without using KvpValue::set().

diff --git a/src/backend/xml/sixtp-dom-generators.cpp b/src/backend/xml/sixtp-dom-generators.cpp
index b27ec22..11ef34a 100644
--- a/src/backend/xml/sixtp-dom-generators.cpp
+++ b/src/backend/xml/sixtp-dom-generators.cpp
@@ -262,7 +262,7 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
     {
     case KVP_TYPE_STRING:
     {
-	auto newstr = g_strdup(val->get<char*>());
+	auto newstr = g_strdup(val->get<const char*>());
         val_node = xmlNewTextChild(node, NULL, BAD_CAST tag,
 				   checked_char_cast (newstr));
 	g_free (newstr);
diff --git a/src/core-utils/gnc-features.c b/src/core-utils/gnc-features.c
index 5b341c9..8e73333 100644
--- a/src/core-utils/gnc-features.c
+++ b/src/core-utils/gnc-features.c
@@ -124,7 +124,7 @@ gchar *gnc_features_test_unknown (QofBook *book)
 	g_list_free(features_list);
 	return msg;
     }
-
+    g_hash_table_unref (features_used);
     return NULL;
 }
 
diff --git a/src/libqof/qof/kvp-value.cpp b/src/libqof/qof/kvp-value.cpp
index 499b575..d24c6be 100644
--- a/src/libqof/qof/kvp-value.cpp
+++ b/src/libqof/qof/kvp-value.cpp
@@ -80,7 +80,7 @@ KvpValueImpl::get_type() const noexcept
         return KvpValueType::KVP_TYPE_DOUBLE;
     else if (datastore.type() == typeid(gnc_numeric))
         return KvpValueType::KVP_TYPE_NUMERIC;
-    else if (datastore.type() == typeid(gchar *))
+    else if (datastore.type() == typeid(const gchar *))
         return KvpValueType::KVP_TYPE_STRING;
     else if (datastore.type() == typeid(GncGUID *))
         return KvpValueType::KVP_TYPE_GUID;
@@ -202,7 +202,7 @@ struct to_string_visitor : boost::static_visitor<void>
         output << ")";
     }
 
-    void operator()(char * val)
+    void operator()(const char * val)
     {
         output << "KVP_VALUE_STRING(" << val << ")";
     }
@@ -243,7 +243,7 @@ struct compare_visitor : boost::static_visitor<int>
         return 0;
     }
 };
-template <> int compare_visitor::operator()(char * const & one, char * const & two) const
+template <> int compare_visitor::operator()(const char * const & one, const char * const & two) const
 {
     return strcmp(one, two);
 }
@@ -337,8 +337,8 @@ KvpValueImpl::~KvpValueImpl() noexcept
 void
 KvpValueImpl::duplicate(const KvpValueImpl& other) noexcept
 {
-    if (other.datastore.type() == typeid(gchar *))
-        this->datastore = g_strdup(other.get<gchar *>());
+    if (other.datastore.type() == typeid(const gchar *))
+        this->datastore = g_strdup(other.get<const gchar *>());
     else if (other.datastore.type() == typeid(GncGUID*))
         this->datastore = guid_copy(other.get<GncGUID *>());
     else if (other.datastore.type() == typeid(GList*))
diff --git a/src/libqof/qof/kvp-value.hpp b/src/libqof/qof/kvp-value.hpp
index ebd8cb6..2ab80d3 100644
--- a/src/libqof/qof/kvp-value.hpp
+++ b/src/libqof/qof/kvp-value.hpp
@@ -108,7 +108,7 @@ struct KvpValueImpl
         int64_t,
         double,
         gnc_numeric,
-        char *,
+        const char*,
         GncGUID *,
         Timespec,
         GList *,
diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index 3dd415f..b60ff16 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -1050,12 +1050,12 @@ kvp_value_get_numeric(const KvpValue * ovalue)
     return value->get<gnc_numeric>();
 }
 
-char *
+const char *
 kvp_value_get_string(const KvpValue * ovalue)
 {
     if (!ovalue) return {};
     const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
-    return value->get<char*>();
+    return value->get<const char*>();
 }
 
 GncGUID *
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index 8053539..7de7dc4 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -528,7 +528,7 @@ gnc_numeric kvp_value_get_numeric(const KvpValue * value);
 
 /** Value accessor. This one is non-copying -- the caller can modify
  * the value directly. */
-char        * kvp_value_get_string(const KvpValue * value);
+const char* kvp_value_get_string(const KvpValue * value);
 
 /** Value accessor. This one is non-copying -- the caller can modify
  * the value directly. */
diff --git a/src/libqof/qof/qofbook.cpp b/src/libqof/qof/qofbook.cpp
index ebc7694..68df399 100644
--- a/src/libqof/qof/qofbook.cpp
+++ b/src/libqof/qof/qofbook.cpp
@@ -1068,7 +1068,7 @@ static void commit_err (G_GNUC_UNUSED QofInstance *inst, QofBackendError errcode
 static void
 add_feature_to_hash (const gchar *key, KvpValue *value, gpointer user_data)
 {
-    gchar *descr = kvp_value_get_string (value);
+    gchar *descr = g_strdup(kvp_value_get_string (value));
     g_hash_table_insert (*(GHashTable**)user_data, (gchar*)key, descr);
 }
 
@@ -1076,7 +1076,8 @@ GHashTable *
 qof_book_get_features (QofBook *book)
 {
     KvpFrame *frame = qof_instance_get_slots (QOF_INSTANCE (book));
-    GHashTable *features = g_hash_table_new (g_str_hash, g_str_equal);
+    GHashTable *features = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                  NULL, g_free);
 
     frame = kvp_frame_get_frame (frame, GNC_FEATURES);
     kvp_frame_for_each_slot (frame, &add_feature_to_hash, &features);

commit 831a36012287724e37e45bb75aa95d519e01046a
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 16 13:43:16 2015 -0700

    XML Backend:Replace C KVP function calls with C++.

diff --git a/src/backend/xml/io-gncxml-v1.cpp b/src/backend/xml/io-gncxml-v1.cpp
index ebfc2f7..29fcad6 100644
--- a/src/backend/xml/io-gncxml-v1.cpp
+++ b/src/backend/xml/io-gncxml-v1.cpp
@@ -43,7 +43,6 @@ extern "C"
 #include <TransLog.h>
 #include <gnc-pricedb.h>
 #include <gnc-pricedb-p.h>
-#include <kvp_frame.h>
 #include "io-gncxml.h"
 
 #include "sixtp.h"
@@ -52,6 +51,7 @@ extern "C"
 #include "sixtp-parsers.h"
 #include "sixtp-utils.h"
 }
+#include <kvp_frame.hpp>
 
 /* from Transaction-xml-parser-v1.c */
 static sixtp* gnc_transaction_parser_new(void);
@@ -438,8 +438,8 @@ gnc_is_xml_data_file(const gchar *filename)
 static void
 kvp_value_result_cleanup(sixtp_child_result *cr)
 {
-    KvpValue *v = (KvpValue *) cr->data;;
-    if (v) kvp_value_delete(v);
+    KvpValue *v = static_cast<KvpValue*>(cr->data);
+    if (v) delete v;
 }
 
 static sixtp*
@@ -489,7 +489,7 @@ simple_kvp_value_parser_new(sixtp_end_handler end_handler)
   g_free(txt);							\
   g_return_val_if_fail(ok, FALSE);				\
 								\
-  kvpv = kvp_value_new_##TYPE(val);				\
+  kvpv = new KvpValue{val};                                     \
   g_return_val_if_fail(kvpv, FALSE);				\
     								\
   *result = kvpv;						\
@@ -567,7 +567,7 @@ string_kvp_value_end_handler(gpointer data_for_children,
     txt = concatenate_child_result_chars(data_from_children);
     g_return_val_if_fail(txt, FALSE);
 
-    kvpv = kvp_value_new_string(txt);
+    kvpv = new KvpValue{g_strdup(txt)};
     g_free(txt);
     g_return_val_if_fail(kvpv, FALSE);
 
@@ -605,7 +605,7 @@ guid_kvp_value_end_handler(gpointer data_for_children,
 
     g_return_val_if_fail(ok, FALSE);
 
-    kvpv = kvp_value_new_guid(&val);
+    kvpv = new KvpValue{guid_copy(&val)};
     g_return_val_if_fail(kvpv, FALSE);
 
     *result = kvpv;
@@ -660,11 +660,10 @@ glist_kvp_value_end_handler(gpointer data_for_children,
         cr->should_cleanup = FALSE;
     }
 
-    kvp_result = kvp_value_new_glist_nc(result_glist);
+    kvp_result = new KvpValue{result_glist};
     if (!kvp_result)
-    {
-        kvp_glist_delete(result_glist);
-    }
+        g_list_free_full(result_glist,
+                         [](void* data){ delete static_cast<KvpValue*>(data);});
     *result = kvp_result;
     return(TRUE);
 }
@@ -791,7 +790,7 @@ kvp_frame_slot_end_handler(gpointer data_for_children,
             if (is_child_result_from_node_named(cr, "frame"))
             {
                 KvpFrame *frame = static_cast<KvpFrame*>(cr->data);
-                value = kvp_value_new_frame (frame);
+                value = new KvpValue{frame};
                 delete_value = TRUE;
             }
             else
@@ -807,9 +806,9 @@ kvp_frame_slot_end_handler(gpointer data_for_children,
     if (key_node_count != 1) return(FALSE);
 
     value_cr->should_cleanup = TRUE;
-    kvp_frame_set_slot(f, key, value);
+    f->replace_nc(key, value);
     if (delete_value)
-        kvp_value_delete (value);
+        delete value;
     return(TRUE);
 }
 
@@ -880,8 +879,7 @@ kvp_frame_start_handler(GSList* sibling_data, gpointer parent_data,
                         gpointer global_data, gpointer *data_for_children,
                         gpointer *result, const gchar *tag, gchar **attrs)
 {
-    KvpFrame *f = kvp_frame_new();
-    g_return_val_if_fail(f, FALSE);
+    auto f = new KvpFrame;
     *data_for_children = f;
     return(TRUE);
 }
@@ -892,9 +890,8 @@ kvp_frame_end_handler(gpointer data_for_children,
                       gpointer parent_data, gpointer global_data,
                       gpointer *result, const gchar *tag)
 {
-    KvpFrame *f = (KvpFrame *) data_for_children;
-    g_return_val_if_fail(f, FALSE);
-    *result = f;
+    g_return_val_if_fail(data_for_children != NULL, FALSE);
+    *result = data_for_children;
     return(TRUE);
 }
 
@@ -907,15 +904,15 @@ kvp_frame_fail_handler(gpointer data_for_children,
                        gpointer *result,
                        const gchar *tag)
 {
-    KvpFrame *f = (KvpFrame *) data_for_children;
-    if (f) kvp_frame_delete(f);
+    auto f = static_cast<KvpFrame*>(data_for_children);
+    if (f) delete f;
 }
 
 static void
 kvp_frame_result_cleanup(sixtp_child_result *cr)
 {
-    KvpFrame *f = (KvpFrame *) cr->data;;
-    if (f) kvp_frame_delete(f);
+    auto f = static_cast<KvpFrame*>(cr->data);;
+    if (f) delete f;
 }
 
 static sixtp*
@@ -1247,9 +1244,9 @@ account_restore_after_child_handler(gpointer data_for_children,
     if (child_result->type != SIXTP_CHILD_RESULT_NODE) return(TRUE);
     if (strcmp(child_result->tag, "slots") == 0)
     {
-        KvpFrame *f = (KvpFrame *) child_result->data;
+        auto f = static_cast<KvpFrame*>(child_result->data);
         g_return_val_if_fail(f, FALSE);
-        if (a->inst.kvp_data) kvp_frame_delete(a->inst.kvp_data);
+        if (a->inst.kvp_data) delete a->inst.kvp_data;
         a->inst.kvp_data = f;
         child_result->should_cleanup = FALSE;
     }
@@ -2481,9 +2478,9 @@ txn_restore_split_after_child_handler(gpointer data_for_children,
 
     if (strcmp(child_result->tag, "slots") == 0)
     {
-        KvpFrame *f = (KvpFrame *) child_result->data;
+        KvpFrame *f = static_cast<KvpFrame*>(child_result->data);
         g_return_val_if_fail(f, FALSE);
-        if (s->inst.kvp_data) kvp_frame_delete(s->inst.kvp_data);
+        if (s->inst.kvp_data) delete s->inst.kvp_data;
         s->inst.kvp_data = f;
         child_result->should_cleanup = FALSE;
     }
diff --git a/src/backend/xml/sixtp-dom-generators.cpp b/src/backend/xml/sixtp-dom-generators.cpp
index 7f60c19..b27ec22 100644
--- a/src/backend/xml/sixtp-dom-generators.cpp
+++ b/src/backend/xml/sixtp-dom-generators.cpp
@@ -29,12 +29,13 @@ extern "C"
 
 #include "gnc-xml-helper.h"
 #include <gnc-date.h>
-#include <kvp_frame.h>
 
 #include "sixtp-dom-generators.h"
 #include "sixtp-utils.h"
 }
 
+#include <kvp_frame.hpp>
+
 static QofLogModule log_module = GNC_MOD_IO;
 
 xmlNodePtr
@@ -250,49 +251,52 @@ add_text_to_node(xmlNodePtr node, const gchar *type, gchar *val)
     g_free(newval);
 }
 
-static void
-add_kvp_slot(const char * key, KvpValue* value, xmlNodePtr node);
+static void add_kvp_slot(const char * key, KvpValue* value, void* data);
 
 static void
 add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
 {
     xmlNodePtr val_node;
-    kvp_value_t kvp_type;
 
-    kvp_type = kvp_value_get_type(val);
-
-    if (kvp_type == KVP_TYPE_STRING)
+    switch (val->get_type())
+    {
+    case KVP_TYPE_STRING:
     {
-	gchar *newstr = g_strdup (kvp_value_get_string(val));
+	auto newstr = g_strdup(val->get<char*>());
         val_node = xmlNewTextChild(node, NULL, BAD_CAST tag,
 				   checked_char_cast (newstr));
 	g_free (newstr);
+        break;
     }
-    else if (kvp_type == KVP_TYPE_TIMESPEC)
+    case KVP_TYPE_TIMESPEC:
         val_node = NULL;
-    else if (kvp_type == KVP_TYPE_GDATE)
+        break;
+    case KVP_TYPE_GDATE:
     {
-        GDate d = kvp_value_get_gdate(val);
+        auto d = val->get<GDate>();
         val_node = gdate_to_dom_tree(tag, &d);
         xmlAddChild (node, val_node);
+        break;
     }
-    else
+    default:
         val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, NULL);
+        break;
+    }
 
-    switch (kvp_value_get_type(val))
+    switch (val->get_type())
     {
     case KVP_TYPE_GINT64:
         add_text_to_node(val_node, "integer",
                          g_strdup_printf("%" G_GINT64_FORMAT,
-                                         kvp_value_get_gint64(val)));
+                                         val->get<int64_t>()));
         break;
     case KVP_TYPE_DOUBLE:
         add_text_to_node(val_node, "double",
-                         double_to_string(kvp_value_get_double(val)));
+                         double_to_string(val->get<double>()));
         break;
     case KVP_TYPE_NUMERIC:
         add_text_to_node(val_node, "numeric",
-                         gnc_numeric_to_string(kvp_value_get_numeric(val)));
+                         gnc_numeric_to_string(val->get<gnc_numeric>()));
         break;
     case KVP_TYPE_STRING:
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string");
@@ -300,64 +304,50 @@ add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
     case KVP_TYPE_GUID:
     {
         gchar guidstr[GUID_ENCODING_LENGTH+1];
-        guid_to_string_buff(kvp_value_get_guid(val), guidstr);
+        guid_to_string_buff(val->get<GncGUID*>(), guidstr);
         add_text_to_node(val_node, "guid", guidstr);
         break;
     }
     case KVP_TYPE_TIMESPEC:
     {
-        Timespec ts = kvp_value_get_timespec (val);
-
+        auto ts = val->get<Timespec>();
         val_node = timespec_to_dom_tree (tag, &ts);
         xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "timespec");
         xmlAddChild (node, val_node);
+        break;
     }
-    break;
     case KVP_TYPE_GDATE:
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "gdate");
-    break;
+        break;
     case KVP_TYPE_GLIST:
-    {
-        GList *cursor;
-
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "list");
-        for (cursor = kvp_value_get_glist(val); cursor; cursor = cursor->next)
+        for (auto cursor = val->get<GList*>(); cursor; cursor = cursor->next)
         {
-            KvpValue *val = (KvpValue*)cursor->data;
+            auto val = static_cast<KvpValue*>(cursor->data);
             add_kvp_value_node(val_node, "slot:value", val);
         }
-    }
-
-    break;
+        break;
     case KVP_TYPE_FRAME:
     {
-        KvpFrame *frame;
-        const char ** keys;
-        unsigned int i;
-
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "frame");
 
-        frame = kvp_value_get_frame (val);
+        auto frame = val->get<KvpFrame*>();
         if (!frame)
             break;
-
-        keys = kvp_frame_get_keys(frame);
-        for (i = 0; keys[i]; ++i)
-            add_kvp_slot(keys[i], kvp_frame_get_value(frame, keys[i]), val_node);
-        g_free(keys);
+        frame->for_each_slot(add_kvp_slot, static_cast<void*>(val_node));
+        break;
     }
-    break;
     default:
 	break;
     }
 }
 
 static void
-add_kvp_slot(const char * key, KvpValue* value, xmlNodePtr node)
+add_kvp_slot(const char * key, KvpValue* value, void* data)
 {
-    xmlNodePtr slot_node;
-    gchar *newkey = g_strdup ((gchar*)key);
-    slot_node = xmlNewChild(node, NULL, BAD_CAST "slot", NULL);
+    auto newkey = g_strdup ((gchar*)key);
+    auto node = static_cast<xmlNodePtr>(data);
+    auto slot_node = xmlNewChild(node, NULL, BAD_CAST "slot", NULL);
 
     xmlNewTextChild(slot_node, NULL, BAD_CAST "slot:key",
 		    checked_char_cast (newkey));
@@ -371,19 +361,12 @@ qof_instance_slots_to_dom_tree(const char *tag, const QofInstance* inst)
     xmlNodePtr ret;
     const char ** keys;
     unsigned int i;
-    KvpFrame *frame = qof_instance_get_slots(QOF_INSTANCE (inst));
+    KvpFrame *frame = qof_instance_get_slots(inst);
     if (!frame)
-    {
         return nullptr;
-    }
 
     ret = xmlNewNode(nullptr, BAD_CAST tag);
-
-    keys = kvp_frame_get_keys(frame);
-    for (i = 0; keys[i]; ++i)
-        add_kvp_slot(keys[i], kvp_frame_get_value(frame, keys[i]), ret);
-    g_free(keys);
-
+    frame->for_each_slot(add_kvp_slot, static_cast<void*>(ret));
     return ret;
 }
 
diff --git a/src/backend/xml/sixtp-dom-parsers.cpp b/src/backend/xml/sixtp-dom-parsers.cpp
index 115b133..71a92ad 100644
--- a/src/backend/xml/sixtp-dom-parsers.cpp
+++ b/src/backend/xml/sixtp-dom-parsers.cpp
@@ -29,10 +29,12 @@ extern "C"
 
 #include "gnc-xml-helper.h"
 #include <gnc-engine.h>
-#include <kvp_frame.h>
 #include "sixtp-utils.h"
 #include "sixtp-dom-parsers.h"
 }
+
+#include <kvp_frame.hpp>
+
 static QofLogModule log_module = GNC_MOD_IO;
 
 GncGUID*
@@ -59,7 +61,7 @@ dom_tree_to_guid(xmlNodePtr node)
         /* handle new and guid the same for the moment */
         if ((g_strcmp0("guid", type) == 0) || (g_strcmp0("new", type) == 0))
         {
-            GncGUID *gid = g_new(GncGUID, 1);
+            auto gid = guid_new();
             char *guid_str;
 
             guid_str = (char*)xmlNodeGetContent (node->xmlChildrenNode);
@@ -91,7 +93,7 @@ dom_tree_to_integer_kvp_value(xmlNodePtr node)
 
     if (string_to_gint64(text, &daint))
     {
-        ret = kvp_value_new_gint64(daint);
+        ret = new KvpValue{daint};
     }
     g_free(text);
 
@@ -174,7 +176,7 @@ dom_tree_to_double_kvp_value(xmlNodePtr node)
 
     if (string_to_double(text, &dadoub))
     {
-        ret = kvp_value_new_double(dadoub);
+        ret = new KvpValue{dadoub};
     }
 
     g_free(text);
@@ -192,7 +194,7 @@ dom_tree_to_numeric_kvp_value(xmlNodePtr node)
 
     if (danum)
     {
-        ret = kvp_value_new_gnc_numeric(*danum);
+        ret = new KvpValue{*danum};
     }
 
     g_free(danum);
@@ -209,11 +211,9 @@ dom_tree_to_string_kvp_value(xmlNodePtr node)
     datext = dom_tree_to_text(node);
     if (datext)
     {
-        ret = kvp_value_new_string(datext);
+        ret = new KvpValue{datext};
     }
 
-    g_free(datext);
-
     return ret;
 }
 
@@ -226,11 +226,9 @@ dom_tree_to_guid_kvp_value(xmlNodePtr node)
     daguid = dom_tree_to_guid(node);
     if (daguid)
     {
-        ret = kvp_value_new_guid(daguid);
+        ret = new KvpValue{daguid};
     }
 
-    g_free(daguid);
-
     return ret;
 }
 
@@ -243,7 +241,7 @@ dom_tree_to_timespec_kvp_value (xmlNodePtr node)
     ts = dom_tree_to_timespec (node);
     if (ts.tv_sec || ts.tv_nsec)
     {
-        ret = kvp_value_new_timespec (ts);
+        ret = new KvpValue{ts};
     }
     return ret;
 }
@@ -258,7 +256,7 @@ dom_tree_to_gdate_kvp_value (xmlNodePtr node)
 
     if (date)
     {
-        ret = kvp_value_new_gdate(*date);
+        ret = new KvpValue{*date};
     }
 
     g_free(date);
@@ -333,7 +331,7 @@ dom_tree_to_list_kvp_value(xmlNodePtr node)
         }
     }
 
-    ret = kvp_value_new_glist_nc(list);
+    ret = new KvpValue{list};
 
     return ret;
 }
@@ -348,11 +346,9 @@ dom_tree_to_frame_kvp_value(xmlNodePtr node)
 
     if (frame)
     {
-        ret = kvp_value_new_frame(frame);
+        ret = new KvpValue{frame};
     }
 
-    kvp_frame_delete(frame);
-
     return ret;
 }
 
@@ -449,7 +445,8 @@ dom_tree_to_kvp_frame_given(xmlNodePtr node, KvpFrame *frame)
             {
                 if (val)
                 {
-                    kvp_frame_set_slot_nc(frame, key, val);
+                    //We're deleting the old KvpValue returned by replace_nc().
+                    delete frame->replace_nc(key, val);
                 }
                 else
                 {
@@ -467,17 +464,14 @@ dom_tree_to_kvp_frame_given(xmlNodePtr node, KvpFrame *frame)
 KvpFrame*
 dom_tree_to_kvp_frame(xmlNodePtr node)
 {
-    KvpFrame *ret;
-
     g_return_val_if_fail(node, NULL);
 
-    ret = kvp_frame_new();
+    auto ret = new KvpFrame;
 
     if (dom_tree_to_kvp_frame_given(node, ret))
         return ret;
 
-    kvp_frame_delete(ret);
-
+    delete ret;
     return NULL;
 }
 

commit ab30b4c680ba50ce13477cb4c5654d5c5f7b2fd8
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jun 14 14:52:25 2015 -0700

    Remove #include "kvp_frame.h" from qof.h and add it where it's legitimately used.

diff --git a/src/app-utils/test/test-option-util.c b/src/app-utils/test/test-option-util.c
index f1adf73..3a261c2 100644
--- a/src/app-utils/test/test-option-util.c
+++ b/src/app-utils/test/test-option-util.c
@@ -26,6 +26,7 @@
 #include <glib.h>
 #include <unittest-support.h>
 #include <qofbookslots.h>
+#include <kvp_frame.h>
 
 #include "../option-util.h"
 
diff --git a/src/backend/dbi/test/test-backend-dbi-basic.c b/src/backend/dbi/test/test-backend-dbi-basic.c
index b3203f0..b692f92 100644
--- a/src/backend/dbi/test/test-backend-dbi-basic.c
+++ b/src/backend/dbi/test/test-backend-dbi-basic.c
@@ -12,6 +12,7 @@
 #include <glib/gstdio.h>
 
 #include <qof.h>
+#include <kvp_frame.h>
 #include <unittest-support.h>
 #include <test-stuff.h>
 #include <test-dbi-stuff.h>
diff --git a/src/backend/dbi/test/test-dbi-stuff.c b/src/backend/dbi/test/test-dbi-stuff.c
index c0e1d1e..e6ad4a6 100644
--- a/src/backend/dbi/test/test-dbi-stuff.c
+++ b/src/backend/dbi/test/test-dbi-stuff.c
@@ -23,17 +23,18 @@
  *  02110-1301, USA.
  */
 
-#include "config.h"
-#include "qof.h"
-#include "qofsession-p.h"
-#include "cashobjects.h"
-#include "test-dbi-stuff.h"
+#include <config.h>
+#include <qof.h>
+#include <kvp_frame.h>
+#include <qofsession-p.h>
+#include <cashobjects.h>
+#include <test-dbi-stuff.h>
 #include <unittest-support.h>
 
-#include "Account.h"
-#include "Split.h"
-#include "Transaction.h"
-#include "gnc-commodity.h"
+#include <Account.h>
+#include <Split.h>
+#include <Transaction.h>
+#include <gnc-commodity.h>
 #include <SX-book.h>
 #include <gnc-lot.h>
 #include "../gnc-backend-dbi-priv.h"
diff --git a/src/backend/sql/gnc-backend-sql.c b/src/backend/sql/gnc-backend-sql.c
index 1e68004..7d9f748 100644
--- a/src/backend/sql/gnc-backend-sql.c
+++ b/src/backend/sql/gnc-backend-sql.c
@@ -34,17 +34,18 @@
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 
-#include "qof.h"
-#include "qofquery-p.h"
-#include "qofquerycore-p.h"
-#include "Account.h"
-#include "TransLog.h"
-#include "gnc-engine.h"
-#include "SX-book.h"
-#include "Recurrence.h"
-#include "gncBillTerm.h"
-#include "gncTaxTable.h"
-#include "gncInvoice.h"
+#include <qof.h>
+#include <qofquery-p.h>
+#include <qofquerycore-p.h>
+#include <kvp_frame.h>
+#include <Account.h>
+#include <TransLog.h>
+#include <gnc-engine.h>
+#include <SX-book.h>
+#include <Recurrence.h>
+#include <gncBillTerm.h>
+#include <gncTaxTable.h>
+#include <gncInvoice.h>
 
 #include "gnc-backend-sql.h"
 
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index bff1eab..1c5f77a 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -31,8 +31,9 @@ extern "C"
 
 #include <glib.h>
 
-#include "qof.h"
-#include "gnc-engine.h"
+#include <qof.h>
+#include <gnc-engine.h>
+#include <kvp_frame.h>
 
 #include "gnc-backend-sql.h"
 
diff --git a/src/backend/xml/io-gncxml-v1.cpp b/src/backend/xml/io-gncxml-v1.cpp
index 23a575b..ebfc2f7 100644
--- a/src/backend/xml/io-gncxml-v1.cpp
+++ b/src/backend/xml/io-gncxml-v1.cpp
@@ -33,16 +33,17 @@ extern "C"
 
 #include <glib.h>
 
-#include "gnc-xml-helper.h"
-#include "Account.h"
-#include "AccountP.h"
-#include "Query.h"
-#include "Scrub.h"
-#include "Transaction.h"
-#include "TransactionP.h"
-#include "TransLog.h"
-#include "gnc-pricedb.h"
-#include "gnc-pricedb-p.h"
+#include <gnc-xml-helper.h>
+#include <Account.h>
+#include <AccountP.h>
+#include <Query.h>
+#include <Scrub.h>
+#include <Transaction.h>
+#include <TransactionP.h>
+#include <TransLog.h>
+#include <gnc-pricedb.h>
+#include <gnc-pricedb-p.h>
+#include <kvp_frame.h>
 #include "io-gncxml.h"
 
 #include "sixtp.h"
diff --git a/src/backend/xml/sixtp-dom-generators.cpp b/src/backend/xml/sixtp-dom-generators.cpp
index 8160ad4..7f60c19 100644
--- a/src/backend/xml/sixtp-dom-generators.cpp
+++ b/src/backend/xml/sixtp-dom-generators.cpp
@@ -29,6 +29,7 @@ extern "C"
 
 #include "gnc-xml-helper.h"
 #include <gnc-date.h>
+#include <kvp_frame.h>
 
 #include "sixtp-dom-generators.h"
 #include "sixtp-utils.h"
diff --git a/src/backend/xml/sixtp-dom-parsers.cpp b/src/backend/xml/sixtp-dom-parsers.cpp
index f95059e..115b133 100644
--- a/src/backend/xml/sixtp-dom-parsers.cpp
+++ b/src/backend/xml/sixtp-dom-parsers.cpp
@@ -28,7 +28,8 @@ extern "C"
 #include <string.h>
 
 #include "gnc-xml-helper.h"
-#include "gnc-engine.h"
+#include <gnc-engine.h>
+#include <kvp_frame.h>
 #include "sixtp-utils.h"
 #include "sixtp-dom-parsers.h"
 }
diff --git a/src/backend/xml/test/test-file-stuff.h b/src/backend/xml/test/test-file-stuff.h
index 08dac54..812a047 100644
--- a/src/backend/xml/test/test-file-stuff.h
+++ b/src/backend/xml/test/test-file-stuff.h
@@ -7,11 +7,12 @@
 
 #include <glib.h>
 
-#include "gnc-commodity.h"
-#include "gnc-engine.h"
-#include "gnc-xml-helper.h"
-#include "io-gncxml-gen.h"
-#include "sixtp.h"
+#include <kvp_frame.h>
+#include <gnc-commodity.h>
+#include <gnc-engine.h>
+#include <gnc-xml-helper.h>
+#include <io-gncxml-gen.h>
+#include <sixtp.h>
 
 
 
diff --git a/src/engine/engine-helpers.c b/src/engine/engine-helpers.c
index 81f75bd..58dddbb 100644
--- a/src/engine/engine-helpers.c
+++ b/src/engine/engine-helpers.c
@@ -37,8 +37,10 @@
 #include "gnc-session.h"
 #include "guile-mappings.h"
 #include "gnc-guile-utils.h"
-#include "qof.h"
-#include "qofbookslots.h"
+#include <qof.h>
+#include <kvp_frame.h>
+#include <qofbookslots.h>
+
 /** \todo Code dependent on the private query headers
 qofquery-p.h and qofquerycore-p.h may need to be modified.
 These files are temporarily exported for QOF 0.6.0 but
diff --git a/src/engine/kvp-scm.c b/src/engine/kvp-scm.c
index 1e51f34..82d0e73 100644
--- a/src/engine/kvp-scm.c
+++ b/src/engine/kvp-scm.c
@@ -1,6 +1,7 @@
 #include "config.h"
 
-#include "qof.h"
+#include <qof.h>
+#include <kvp_frame.h>
 #include <libguile.h>
 #include "engine-helpers-guile.h"
 
diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c
index 89d5cde..0969bfb 100644
--- a/src/engine/test-core/test-engine-stuff.c
+++ b/src/engine/test-core/test-engine-stuff.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <qof.h>
 #include <qofinstance-p.h>
 
 #include "Account.h"
diff --git a/src/engine/test-core/test-engine-stuff.h b/src/engine/test-core/test-engine-stuff.h
index 25b9fba..557bba8 100644
--- a/src/engine/test-core/test-engine-stuff.h
+++ b/src/engine/test-core/test-engine-stuff.h
@@ -10,6 +10,7 @@
 #include <stdint.h>
 
 #include "qof.h"
+#include <kvp_frame.h>
 #include "Query.h"
 #include "gnc-pricedb.h"
 #include "SchedXaction.h"
diff --git a/src/engine/test/utest-Account.c b/src/engine/test/utest-Account.c
index ea7f74d..f1c6914 100644
--- a/src/engine/test/utest-Account.c
+++ b/src/engine/test/utest-Account.c
@@ -25,6 +25,7 @@
 #include <unittest-support.h>
 #include <gnc-event.h>
 #include <gnc-gdate-utils.h>
+#include <kvp_frame.h>
 #include <qofinstance-p.h>
 /* Add specific headers for this class */
 #include "../Account.h"
diff --git a/src/engine/test/utest-Split.cpp b/src/engine/test/utest-Split.cpp
index 6a5000c..5612990 100644
--- a/src/engine/test/utest-Split.cpp
+++ b/src/engine/test/utest-Split.cpp
@@ -38,6 +38,7 @@ extern "C"
 #include <TransactionP.h>
 #include <gnc-lot.h>
 #include <gnc-event.h>
+#include <kvp_frame.h>
 #include <qofinstance-p.h>
 
 #ifdef HAVE_GLIB_2_38
diff --git a/src/engine/test/utest-Transaction.c b/src/engine/test/utest-Transaction.c
index 7611c2c..ec5d6d3 100644
--- a/src/engine/test/utest-Transaction.c
+++ b/src/engine/test/utest-Transaction.c
@@ -33,6 +33,7 @@
 #include "../gnc-lot.h"
 #include "../gnc-event.h"
 #include <qof.h>
+#include <kvp_frame.h>
 #include <qofbackend-p.h>
 
 #ifdef HAVE_GLIB_2_38
diff --git a/src/libqof/qof/kvp-value.hpp b/src/libqof/qof/kvp-value.hpp
index bfdfc33..ebd8cb6 100644
--- a/src/libqof/qof/kvp-value.hpp
+++ b/src/libqof/qof/kvp-value.hpp
@@ -28,6 +28,7 @@ extern "C"
 {
 #include "config.h"
 #include "qof.h"
+#include "kvp_frame.h"
 }
 #include <boost/version.hpp>
 #if BOOST_VERSION == 105600
diff --git a/src/libqof/qof/qofbook.cpp b/src/libqof/qof/qofbook.cpp
index 2aa09b1..ebc7694 100644
--- a/src/libqof/qof/qofbook.cpp
+++ b/src/libqof/qof/qofbook.cpp
@@ -56,6 +56,7 @@ extern "C"
 #include "qofid-p.h"
 #include "qofobject-p.h"
 #include "qofbookslots.h"
+#include "kvp_frame.h"
 
 static QofLogModule log_module = QOF_MOD_ENGINE;
 #define AB_KEY "hbci"
diff --git a/src/libqof/qof/qofbook.h b/src/libqof/qof/qofbook.h
index a51bad7..04448f7 100644
--- a/src/libqof/qof/qofbook.h
+++ b/src/libqof/qof/qofbook.h
@@ -49,9 +49,9 @@ extern "C"
 #ifndef SWIG
 
 typedef struct _QofBookClass  QofBookClass;
+typedef struct KvpValueImpl KvpValue;
 
 #include "qofid.h"
-#include "kvp_frame.h"
 #include "qofinstance.h"
 
 /* --- type macros --- */
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index a765cae..1865b48 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -38,6 +38,7 @@ extern "C"
 #include "qof.h"
 #include "qofbook-p.h"
 #include "qofid-p.h"
+#include "kvp_frame.h"
 #include "qofinstance-p.h"
 
 static QofLogModule log_module = QOF_MOD_ENGINE;
diff --git a/src/libqof/qof/qofinstance.h b/src/libqof/qof/qofinstance.h
index ca485c3..98b854f 100644
--- a/src/libqof/qof/qofinstance.h
+++ b/src/libqof/qof/qofinstance.h
@@ -46,7 +46,6 @@ typedef struct _QofBook       QofBook;
 #include "qofid.h"
 #include "guid.h"
 #include "gnc-date.h"
-#include "kvp_frame.h"
 #include "qof-gobject.h"
 
 /* --- type macros --- */
@@ -62,6 +61,8 @@ typedef struct _QofBook       QofBook;
 #define QOF_INSTANCE_GET_CLASS(o)    \
      (G_TYPE_INSTANCE_GET_CLASS ((o), QOF_TYPE_INSTANCE, QofInstanceClass))
 
+typedef struct KvpFrameImpl KvpFrame;
+
 struct QofInstance_s
 {
     GObject object;
diff --git a/src/libqof/qof/test/test-kvp_frame.c b/src/libqof/qof/test/test-kvp_frame.c
index 2dc272c..8717374 100644
--- a/src/libqof/qof/test/test-kvp_frame.c
+++ b/src/libqof/qof/test/test-kvp_frame.c
@@ -27,13 +27,14 @@ extern "C"
 #include "config.h"
 #include <string.h>
 #include <glib.h>
-#include "unittest-support.h"
-
+#include <unittest-support.h>
+#include <qof.h>
+#include <kvp_frame.h>
 #ifdef __cplusplus
 }
 #endif
 
-#include "qof.h"
+
 
 static const gchar *suitename = "/qof/kvp_frame";
 void test_suite_kvp_frame ( void );
diff --git a/src/libqof/qof/test/test-qofinstance.c b/src/libqof/qof/test/test-qofinstance.c
index b6b317f..ab1e630 100644
--- a/src/libqof/qof/test/test-qofinstance.c
+++ b/src/libqof/qof/test/test-qofinstance.c
@@ -24,6 +24,7 @@
 #include <unittest-support.h>
 #include "../qof.h"
 #include "../qofbackend-p.h"
+#include "../kvp_frame.h"
 
 static const gchar *suitename = "/qof/qofinstance";
 void test_suite_qofinstance ( void );

commit c721bf9f48a8eb9792fb8f33cfa2dc525c668091
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jun 14 14:50:31 2015 -0700

    Remove the unused backend-configuration member and virtual setter/getters.
    
    Not used, and if it was it would be an inappropriate use of KVP.

diff --git a/src/backend/dbi/gnc-backend-dbi.c b/src/backend/dbi/gnc-backend-dbi.c
index 03f6463..8c96bd0 100644
--- a/src/backend/dbi/gnc-backend-dbi.c
+++ b/src/backend/dbi/gnc-backend-dbi.c
@@ -1763,8 +1763,6 @@ init_sql_backend( GncDbiBackend* dbi_be )
      * configured for multiuser access. */
     be->sync = gnc_dbi_safe_sync_all;
     be->safe_sync = gnc_dbi_safe_sync_all;
-    be->load_config = NULL;
-    be->get_config = NULL;
 
     be->compile_query = gnc_sql_compile_query;
     be->run_query = gnc_sql_run_query;
diff --git a/src/backend/sql/test/utest-gnc-backend-sql.c b/src/backend/sql/test/utest-gnc-backend-sql.c
index 4ab0446..b15f3ea 100644
--- a/src/backend/sql/test/utest-gnc-backend-sql.c
+++ b/src/backend/sql/test/utest-gnc-backend-sql.c
@@ -583,7 +583,7 @@ test_gnc_sql_convert_timespec_to_string ()
     GncSqlBackend be = {{
             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-            0, NULL, 0, "", NULL, 0, "", NULL, NULL
+            0, NULL, 0, "", NULL
         },
         NULL, NULL, FALSE, FALSE, FALSE, 0, 0, NULL,
         "%4d-%02d-%02d %02d:%02d:%02d"
diff --git a/src/backend/xml/gnc-backend-xml.c b/src/backend/xml/gnc-backend-xml.c
index 0aacf4f..2eff9a7 100644
--- a/src/backend/xml/gnc-backend-xml.c
+++ b/src/backend/xml/gnc-backend-xml.c
@@ -1251,8 +1251,6 @@ gnc_backend_new(void)
     be->process_events = NULL;
 
     be->sync = xml_sync_all;
-    be->load_config = NULL;
-    be->get_config = NULL;
 
     be->export_fn = gnc_xml_be_write_accounts_to_file;
 
diff --git a/src/import-export/aqb/test/test-aqb.c b/src/import-export/aqb/test/test-aqb.c
index e18cd96..43286f5 100644
--- a/src/import-export/aqb/test/test-aqb.c
+++ b/src/import-export/aqb/test/test-aqb.c
@@ -40,7 +40,7 @@ main (int   argc,
     qof_init(); 			/* Initialize the GObject system */
     qof_log_init_filename_special("stderr"); /* Init the log system */
     g_test_init ( &argc, &argv, NULL ); 	/* initialize test program */
-    qof_log_set_level("gnc", G_LOG_LEVEL_DEBUG);
+    qof_log_set_level("gnc", (QofLogLevel)G_LOG_LEVEL_DEBUG);
     g_test_bug_base("https://bugzilla.gnome.org/show_bug.cgi?id="); /* init the bugzilla URL */
     /* Disable the transaction log */
     xaccLogDisable();
diff --git a/src/libqof/qof/qofbackend-p.h b/src/libqof/qof/qofbackend-p.h
index 9b7074b..b2ed3bf 100644
--- a/src/libqof/qof/qofbackend-p.h
+++ b/src/libqof/qof/qofbackend-p.h
@@ -304,9 +304,6 @@ struct QofBackend_s
 
     void (*sync) (QofBackend *, /*@ dependent @*/ QofBook *);
     void (*safe_sync) (QofBackend *, /*@ dependent @*/ QofBook *);
-    void (*load_config) (QofBackend *, KvpFrame *);
-    /*@ observer @*/
-    KvpFrame* (*get_config) (QofBackend *);
 
     gboolean (*events_pending) (QofBackend *);
     gboolean (*process_events) (QofBackend *);
@@ -318,7 +315,6 @@ struct QofBackend_s
     QofBackendError last_err;
     char * error_msg;
 
-    KvpFrame* backend_configuration;
     gint config_count;
     /** Each backend resolves a fully-qualified file path.
      * This holds the filepath and communicates it to the frontends.
diff --git a/src/libqof/qof/qofbackend.cpp b/src/libqof/qof/qofbackend.cpp
index 56b4d91..33fbbef 100644
--- a/src/libqof/qof/qofbackend.cpp
+++ b/src/libqof/qof/qofbackend.cpp
@@ -138,7 +138,6 @@ qof_backend_init(QofBackend *be)
 
     be->sync = NULL;
     be->safe_sync = NULL;
-    be->load_config = NULL;
 
     be->events_pending = NULL;
     be->process_events = NULL;
@@ -147,7 +146,6 @@ qof_backend_init(QofBackend *be)
     if (be->error_msg) g_free (be->error_msg);
     be->error_msg = NULL;
     be->percentage = NULL;
-    be->backend_configuration = kvp_frame_new();
 
     /* to be removed */
     be->price_lookup = NULL;
@@ -159,8 +157,6 @@ qof_backend_destroy(QofBackend *be)
 {
     g_free(be->error_msg);
     be->error_msg = NULL;
-    kvp_frame_delete(be->backend_configuration);
-    be->backend_configuration = NULL;
 }
 
 void

commit 3956ee0f01188910b5845c99cfc83fb4d9720423
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jun 14 14:48:25 2015 -0700

    Remove the rest of the KVP direct-query functions.

diff --git a/src/engine/engine-helpers.c b/src/engine/engine-helpers.c
index e1c9357..81f75bd 100644
--- a/src/engine/engine-helpers.c
+++ b/src/engine/engine-helpers.c
@@ -1024,14 +1024,6 @@ gnc_queryterm2scm (const QofQueryTerm *qt)
         qt_scm = scm_cons (pdata->char_list ? scm_from_utf8_string (pdata->char_list) : SCM_BOOL_F, qt_scm);
 
     }
-    else if (!g_strcmp0 (pd->type_name, QOF_TYPE_KVP))
-    {
-        query_kvp_t pdata = (query_kvp_t) pd;
-
-        qt_scm = scm_cons (gnc_query_path2scm (pdata->path), qt_scm);
-        qt_scm = scm_cons (gnc_kvp_value2scm (pdata->value), qt_scm);
-
-    }
     else
     {
         PWARN ("query core type %s not supported", pd->type_name);
@@ -1234,31 +1226,6 @@ gnc_scm2query_term_query_v2 (SCM qt_scm)
             pd = qof_query_char_predicate (options, char_list);
             g_free (char_list);
         }
-        else if (!g_strcmp0 (type, QOF_TYPE_KVP))
-        {
-            GSList *kvp_path;
-            KvpValue *value;
-
-            scm = SCM_CAR (qt_scm);
-            qt_scm = SCM_CDR (qt_scm);
-            if (!scm_is_list (scm))
-                break;
-            kvp_path = gnc_query_scm2path (scm);
-
-            scm = SCM_CAR (qt_scm);
-            qt_scm = SCM_CDR (qt_scm);
-            if (scm_is_null (scm))
-            {
-                gnc_query_path_free (kvp_path);
-                break;
-            }
-            value = gnc_scm2KvpValue (scm);
-
-            pd = qof_query_kvp_predicate (compare_how, kvp_path, value);
-            gnc_query_path_free (kvp_path);
-            kvp_value_delete (value);
-
-        }
         else
         {
             PWARN ("query core type %s not supported", type);
diff --git a/src/libqof/qof/qof.h b/src/libqof/qof/qof.h
index be030c6..282d690 100644
--- a/src/libqof/qof/qof.h
+++ b/src/libqof/qof/qof.h
@@ -79,7 +79,6 @@
 #include "gnc-numeric.h"
 #include "qofutil.h"
 #include "guid.h"
-#include "kvp_frame.h"
 #include "qofbackend.h"
 #include "qofid-p.h"
 #include "qofbook.h"
diff --git a/src/libqof/qof/qofquery.cpp b/src/libqof/qof/qofquery.cpp
index e015735..3810fa4 100644
--- a/src/libqof/qof/qofquery.cpp
+++ b/src/libqof/qof/qofquery.cpp
@@ -1808,19 +1808,6 @@ qof_query_printValueForParam (QofQueryPredData *pd, GString * gs)
                                 gnc_num_dbg_to_string (pdata->amount));
         return;
     }
-    if (!g_strcmp0 (pd->type_name, QOF_TYPE_KVP))
-    {
-        GSList *node;
-        query_kvp_t pdata = (query_kvp_t) pd;
-        g_string_append_printf (gs, " kvp path: ");
-        for (node = pdata->path; node; node = node->next)
-        {
-            g_string_append_printf (gs, "/%s", (gchar *) node->data);
-        }
-        g_string_append_printf (gs, " kvp value: %s ",
-                                kvp_value_to_string (pdata->value));
-        return;
-    }
     if (!g_strcmp0 (pd->type_name, QOF_TYPE_INT64))
     {
         query_int64_t pdata = (query_int64_t) pd;
diff --git a/src/libqof/qof/qofquerycore.cpp b/src/libqof/qof/qofquerycore.cpp
index 3804acd..68a6f62 100644
--- a/src/libqof/qof/qofquerycore.cpp
+++ b/src/libqof/qof/qofquerycore.cpp
@@ -81,9 +81,6 @@ static const char * query_boolean_type = QOF_TYPE_BOOLEAN;
 typedef char (*query_char_getter) (gpointer, QofParam *);
 static const char * query_char_type = QOF_TYPE_CHAR;
 
-typedef KvpFrame * (*query_kvp_getter) (gpointer, QofParam *);
-static const char * query_kvp_type = QOF_TYPE_KVP;
-
 typedef QofCollection * (*query_collect_getter) (gpointer, QofParam*);
 static const char * query_collect_type = QOF_TYPE_COLLECT;
 
@@ -1219,152 +1216,6 @@ char_to_string (gpointer object, QofParam *getter)
     return g_strdup_printf ("%c", num);
 }
 
-/* QOF_TYPE_KVP ================================================ */
-
-static int
-kvp_match_predicate (gpointer object, QofParam *getter,
-                     QofQueryPredData *pd)
-{
-    int compare;
-    KvpFrame *kvp;
-    KvpValue *value;
-    query_kvp_t pdata = (query_kvp_t)pd;
-
-    VERIFY_PREDICATE (query_kvp_type);
-
-    kvp = ((query_kvp_getter)getter->param_getfcn) (object, getter);
-    if (!kvp)
-        return 0;
-
-    value = kvp_frame_get_slot_path_gslist (kvp, pdata->path);
-    if (!value)
-        return 0;
-
-    if (kvp_value_get_type (value) != kvp_value_get_type (pdata->value))
-        return 0;
-
-    compare = kvp_value_compare (value, pdata->value);
-
-    switch (pd->how)
-    {
-    case QOF_COMPARE_LT:
-        return (compare < 0);
-    case QOF_COMPARE_LTE:
-        return (compare <= 0);
-    case QOF_COMPARE_EQUAL:
-        return (compare == 0);
-    case QOF_COMPARE_GTE:
-        return (compare >= 0);
-    case QOF_COMPARE_GT:
-        return (compare > 0);
-    case QOF_COMPARE_NEQ:
-        return (compare != 0);
-    default:
-        PWARN ("bad match type: %d", pd->how);
-        return 0;
-    }
-}
-
-static void
-kvp_free_pdata (QofQueryPredData *pd)
-{
-    query_kvp_t pdata = (query_kvp_t)pd;
-    QofQueryParamList *node;
-
-    VERIFY_PDATA (query_kvp_type);
-    kvp_value_delete (pdata->value);
-    for (node = pdata->path; node; node = node->next)
-    {
-        g_free (node->data);
-        node->data = NULL;
-    }
-    g_slist_free (pdata->path);
-    g_free (pdata);
-}
-
-static QofQueryPredData *
-kvp_copy_predicate (const QofQueryPredData *pd)
-{
-    const query_kvp_t pdata = (const query_kvp_t)pd;
-    VERIFY_PDATA_R (query_kvp_type);
-    return qof_query_kvp_predicate (pd->how, pdata->path, pdata->value);
-}
-
-static gboolean
-kvp_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
-{
-    const query_kvp_t pd1 = (const query_kvp_t) p1;
-    const query_kvp_t pd2 = (const query_kvp_t) p2;
-    QofQueryParamList *n1, *n2;
-
-    n1 = pd1->path;
-    n2 = pd2->path;
-
-    for ( ; n1 && n2; n1 = n1->next, n2 = n2->next)
-    {
-        if (g_strcmp0 (static_cast<char*>(n1->data),
-		       static_cast<char*>(n2->data)) != 0)
-            return FALSE;
-    }
-
-    if (n1 || n2)
-        return FALSE;
-
-    return (kvp_value_compare (pd1->value, pd2->value) == 0);
-}
-
-QofQueryPredData *
-qof_query_kvp_predicate (QofQueryCompare how,
-                         QofQueryParamList *path, const KvpValue *value)
-{
-    query_kvp_t pdata;
-    QofQueryParamList *node;
-
-    g_return_val_if_fail (path && value, NULL);
-
-    pdata = g_new0 (query_kvp_def, 1);
-    pdata->pd.type_name = query_kvp_type;
-    pdata->pd.how = how;
-    pdata->value = kvp_value_copy (value);
-    pdata->path = g_slist_copy (path);
-    for (node = pdata->path; node; node = node->next)
-        node->data = g_strdup (static_cast<char*>(node->data));
-
-    return ((QofQueryPredData*)pdata);
-}
-
-QofQueryPredData *
-qof_query_kvp_predicate_path (QofQueryCompare how,
-                              const char *path, const KvpValue *value)
-{
-    QofQueryPredData *pd;
-    QofQueryParamList *spath = NULL;
-    char *str, *p;
-
-    if (!path) return NULL;
-
-    str = g_strdup (path);
-    p = str;
-    if (0 == *p) return NULL;
-    if ('/' == *p) p++;
-
-    while (p)
-    {
-        spath = g_slist_append (spath, p);
-        p = strchr (p, '/');
-        if (p)
-        {
-            *p = 0;
-            p++;
-        }
-    }
-
-    pd = qof_query_kvp_predicate (how, spath, value);
-    g_free (str);
-    return pd;
-}
-
-
 /* QOF_TYPE_COLLECT =============================================== */
 
 static int
@@ -1826,10 +1677,6 @@ static void init_tables (void)
             char_predicate_equal
         },
         {
-            QOF_TYPE_KVP, kvp_match_predicate, NULL, kvp_copy_predicate,
-            kvp_free_pdata, NULL, kvp_predicate_equal
-        },
-        {
             QOF_TYPE_COLLECT, collect_match_predicate, collect_compare_func,
             collect_copy_predicate, collect_free_pdata, NULL,
             collect_predicate_equal
diff --git a/src/libqof/qof/qofquerycore.h b/src/libqof/qof/qofquerycore.h
index 8fb2d45..f602357 100644
--- a/src/libqof/qof/qofquerycore.h
+++ b/src/libqof/qof/qofquerycore.h
@@ -34,7 +34,6 @@
 
 #include "gnc-numeric.h"
 #include "gnc-date.h"
-#include "kvp_frame.h"
 #include "qofclass.h"
 
 #ifdef __cplusplus
@@ -137,7 +136,7 @@ typedef enum
 } QofCharMatch;
 
 /** No extended comparisons for QOF_TYPE_INT32, QOF_TYPE_INT64,
- *  QOF_TYPE_DOUBLE, QOF_TYPE_BOOLEAN, QOF_TYPE_KVP
+ *  QOF_TYPE_DOUBLE, QOF_TYPE_BOOLEAN
  */
 
 /** Head of Predicate Data structures.  All PData must start like this. */
@@ -177,20 +176,6 @@ QofQueryPredData *qof_query_collect_predicate (QofGuidMatch options,
         QofCollection *coll);
 QofQueryPredData *qof_query_choice_predicate  (QofGuidMatch options, GList *guids);
 
-/** The qof_query_kvp_predicate() matches the object that has
- *  the value 'value' located at the path 'path'.  In a certain
- *  sense, the 'path' is handled as if it were a parameter.
- */
-QofQueryPredData *qof_query_kvp_predicate (QofQueryCompare how,
-        QofQueryParamList *path,
-        const KvpValue *value);
-
-/** Same predicate as above, except that 'path' is assumed to be
- * a string containing slash-separated pathname. */
-QofQueryPredData *qof_query_kvp_predicate_path (QofQueryCompare how,
-        const gchar *path,
-        const KvpValue *value);
-
 /** Copy a predicate. */
 QofQueryPredData *qof_query_core_predicate_copy (const QofQueryPredData *pdata);
 

commit 171669ec68b3096c21b7b6db49cb266868017865
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun Jun 14 12:45:36 2015 -0700

    Change io-gncxml-v2.c to C++.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 58c75b9..ea745f9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -87,7 +87,7 @@ src/backend/xml/gnc-vendor-xml-v2.c
 src/backend/xml/gnc-xml-helper.c
 src/backend/xml/io-example-account.c
 src/backend/xml/io-gncxml-gen.c
-src/backend/xml/io-gncxml-v1.c
+src/backend/xml/io-gncxml-v1.cpp
 src/backend/xml/io-gncxml-v2.c
 src/backend/xml/io-utils.c
 src/backend/xml/sixtp.c
diff --git a/src/backend/xml/Makefile.am b/src/backend/xml/Makefile.am
index e7bb12e..34aeb2a 100644
--- a/src/backend/xml/Makefile.am
+++ b/src/backend/xml/Makefile.am
@@ -42,7 +42,7 @@ libgnc_backend_xml_utils_la_SOURCES = \
   gnc-xml-helper.c \
   io-example-account.c \
   io-gncxml-gen.c \
-  io-gncxml-v1.c \
+  io-gncxml-v1.cpp \
   io-gncxml-v2.c \
   io-utils.c \
   sixtp-dom-generators.cpp \
diff --git a/src/backend/xml/io-gncxml-v1.c b/src/backend/xml/io-gncxml-v1.cpp
similarity index 99%
rename from src/backend/xml/io-gncxml-v1.c
rename to src/backend/xml/io-gncxml-v1.cpp
index 536c5c9..23a575b 100644
--- a/src/backend/xml/io-gncxml-v1.c
+++ b/src/backend/xml/io-gncxml-v1.cpp
@@ -24,7 +24,8 @@
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  *                                                                  *
  *******************************************************************/
-
+extern "C"
+{
 #include "config.h"
 
 #include <stdlib.h>
@@ -49,6 +50,7 @@
 #include "sixtp-stack.h"
 #include "sixtp-parsers.h"
 #include "sixtp-utils.h"
+}
 
 /* from Transaction-xml-parser-v1.c */
 static sixtp* gnc_transaction_parser_new(void);
@@ -787,13 +789,13 @@ kvp_frame_slot_end_handler(gpointer data_for_children,
         {
             if (is_child_result_from_node_named(cr, "frame"))
             {
-                KvpFrame *frame = cr->data;
+                KvpFrame *frame = static_cast<KvpFrame*>(cr->data);
                 value = kvp_value_new_frame (frame);
                 delete_value = TRUE;
             }
             else
             {
-                value = cr->data;
+                value = static_cast<KvpValue*>(cr->data);
                 delete_value = FALSE;
             }
 
@@ -1401,7 +1403,7 @@ acc_restore_type_end_handler(gpointer data_for_children,
 {
     Account *acc = (Account *) parent_data;
     gchar *txt = NULL;
-    int type;
+    GNCAccountType type;
     gboolean ok;
 
     g_return_val_if_fail(acc, FALSE);
diff --git a/src/backend/xml/io-gncxml.h b/src/backend/xml/io-gncxml.h
index e5e8059..2fc1457 100644
--- a/src/backend/xml/io-gncxml.h
+++ b/src/backend/xml/io-gncxml.h
@@ -32,6 +32,10 @@
 
 #ifndef IO_GNCXML_H
 #define IO_GNCXML_H
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 
 #include <glib.h>
 #include "qof.h"
@@ -47,4 +51,7 @@ gboolean qof_session_load_from_xml_file(QofBook *, const char * filename);
  */
 gboolean gnc_is_xml_data_file(const gchar *name);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* IO_GNCXML_H */

commit 435aef03b7a4f057abffb60578ff5ecfeff0fac4
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jun 13 17:28:11 2015 -0700

    Isolate direct KVP operations.
    
    Into sixtp-dom-parser, sixtp-dom-generator, and gnc-slots-sql.
    The XML V1 file io-gncxml-v1.c is not yet done.

diff --git a/src/backend/xml/gnc-account-xml-v2.c b/src/backend/xml/gnc-account-xml-v2.c
index 9d31027..25f6f1e 100644
--- a/src/backend/xml/gnc-account-xml-v2.c
+++ b/src/backend/xml/gnc-account-xml-v2.c
@@ -71,16 +71,12 @@ const gchar *account_version_string = "2.0.0";
 #define act_hidden_string "act:hidden"
 #define act_placeholder_string "act:placeholder"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance *);
-
 xmlNodePtr
 gnc_account_dom_tree_create(Account *act,
                             gboolean exporting,
                             gboolean allow_incompat)
 {
     const char *str;
-    KvpFrame *kf;
     xmlNodePtr ret;
     GList *lots, *n;
     Account *parent;
@@ -137,16 +133,9 @@ gnc_account_dom_tree_create(Account *act,
         xmlAddChild(ret, text_to_dom_tree(act_description_string, str));
     }
 
-    kf = qof_instance_get_slots (QOF_INSTANCE (act));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(act_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(act_slots_string,
+                                                    QOF_INSTANCE(act)));
     parent = gnc_account_get_parent(act);
     if (parent)
     {
@@ -371,9 +360,7 @@ static gboolean
 account_slots_handler (xmlNodePtr node, gpointer act_pdata)
 {
     struct account_pdata *pdata = act_pdata;
-
-    return dom_tree_to_kvp_frame_given
-           (node, qof_instance_get_slots (QOF_INSTANCE (pdata->account)));
+    return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->account));
 }
 
 static gboolean
diff --git a/src/backend/xml/gnc-address-xml-v2.c b/src/backend/xml/gnc-address-xml-v2.c
index 75cf60d..40eb112 100644
--- a/src/backend/xml/gnc-address-xml-v2.c
+++ b/src/backend/xml/gnc-address-xml-v2.c
@@ -58,9 +58,6 @@ const gchar *address_version_string = "2.0.0";
 #define addr_email_string	"addr:email"
 #define addr_slots_string	"addr:slots"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance*);
-
 static void
 maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
 {
@@ -72,7 +69,6 @@ xmlNodePtr
 gnc_address_to_dom_tree (const char *tag, GncAddress *addr)
 {
     xmlNodePtr ret;
-    KvpFrame *kf;
 
     ret = xmlNewNode(NULL, BAD_CAST tag);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST address_version_string);
@@ -88,16 +84,9 @@ gnc_address_to_dom_tree (const char *tag, GncAddress *addr)
     maybe_add_string (ret, addr_fax_string, gncAddressGetFax (addr));
     maybe_add_string (ret, addr_email_string, gncAddressGetEmail (addr));
 
-    kf = qof_instance_get_slots (QOF_INSTANCE(addr));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(addr_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+     /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(addr_slots_string,
+                                                    QOF_INSTANCE(addr)));
     return ret;
 }
 
@@ -190,9 +179,7 @@ static gboolean
 address_slots_handler (xmlNodePtr node, gpointer addr_pdata)
 {
     struct address_pdata *pdata = addr_pdata;
-
-    return dom_tree_to_kvp_frame_given
-        (node, qof_instance_get_slots (QOF_INSTANCE (pdata->address)));
+    return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->address));
 }
 
 static struct dom_tree_handler address_handlers_v2[] =
diff --git a/src/backend/xml/gnc-bill-term-xml-v2.c b/src/backend/xml/gnc-bill-term-xml-v2.c
index fa4d421..6e04d68 100644
--- a/src/backend/xml/gnc-bill-term-xml-v2.c
+++ b/src/backend/xml/gnc-bill-term-xml-v2.c
@@ -79,7 +79,7 @@ const gchar *billterm_version_string = "2.0.0";
 static xmlNodePtr
 billterm_dom_tree_create (GncBillTerm *term)
 {
-    xmlNodePtr ret, data, kvpnode;
+    xmlNodePtr ret, data;
 
     ret = xmlNewNode(NULL, BAD_CAST gnc_billterm_string);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST billterm_version_string);
@@ -95,10 +95,9 @@ billterm_dom_tree_create (GncBillTerm *term)
     xmlAddChild(ret, int_to_dom_tree (billterm_invisible_string,
                                       gncBillTermGetInvisible (term)));
 
-    kvpnode = kvp_frame_to_dom_tree (billterm_slots_string,
-                                     qof_instance_get_slots (QOF_INSTANCE(term)));
-    if (kvpnode) xmlAddChild (ret, kvpnode);
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(billterm_slots_string,
+                                                    QOF_INSTANCE(term)));
 
     /* We should not be our own child */
     if (gncBillTermGetChild(term) != term)
@@ -401,8 +400,7 @@ static gboolean
 billterm_slots_handler (xmlNodePtr node, gpointer billterm_pdata)
 {
     struct billterm_pdata *pdata = billterm_pdata;
-    return dom_tree_to_kvp_frame_given (node,
-                                        qof_instance_get_slots (QOF_INSTANCE(pdata->term)));
+    return dom_tree_create_instance_slots (node, QOF_INSTANCE(pdata->term));
 }
 
 static struct dom_tree_handler billterm_handlers_v2[] =
diff --git a/src/backend/xml/gnc-book-xml-v2.c b/src/backend/xml/gnc-book-xml-v2.c
index 6fcae46..851aefa 100644
--- a/src/backend/xml/gnc-book-xml-v2.c
+++ b/src/backend/xml/gnc-book-xml-v2.c
@@ -109,13 +109,9 @@ gnc_book_dom_tree_create(QofBook *book)
     xmlAddChild(ret, guid_to_dom_tree(book_id_string,
                                       qof_book_get_guid(book)));
 
-    if (qof_instance_get_slots (QOF_INSTANCE (book)))
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
-                             qof_instance_get_slots (QOF_INSTANCE (book)));
-        if (kvpnode)
-            xmlAddChild(ret, kvpnode);
-    }
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(book_slots_string,
+                                                    QOF_INSTANCE(book)));
 
 #ifdef IMPLEMENT_BOOK_DOM_TREES_LATER
     /* theoretically, we should be adding all the below to the book
@@ -153,7 +149,7 @@ gnc_book_dom_tree_create(QofBook *book)
 gboolean
 write_book_parts(FILE *out, QofBook *book)
 {
-    xmlNodePtr domnode;
+     xmlNodePtr domnode, slotsnode;
 
     domnode = guid_to_dom_tree(book_id_string, qof_book_get_guid(book));
     xmlElemDump(out, NULL, domnode);
@@ -162,18 +158,16 @@ write_book_parts(FILE *out, QofBook *book)
     if (ferror(out) || fprintf(out, "\n") < 0)
         return FALSE;
 
-    if (qof_instance_get_slots (QOF_INSTANCE (book)))
+ 
+    slotsnode = qof_instance_slots_to_dom_tree(book_slots_string,
+                                             QOF_INSTANCE(book));
+    if (slotsnode)
     {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
-                             qof_instance_get_slots (QOF_INSTANCE (book)));
-        if (kvpnode)
-        {
-            xmlElemDump(out, NULL, kvpnode);
-            xmlFreeNode(kvpnode);
-
-            if (ferror(out) || fprintf(out, "\n") < 0)
-                return FALSE;
-        }
+         xmlElemDump(out, NULL, slotsnode);
+         xmlFreeNode(slotsnode);
+
+         if (ferror(out) || fprintf(out, "\n") < 0)
+              return FALSE;
     }
 
     return TRUE;
@@ -203,7 +197,7 @@ book_slots_handler (xmlNodePtr node, gpointer book_pdata)
 
     /* the below works only because the get is gaurenteed to return
      * a frame, even if its empty */
-    success = dom_tree_to_kvp_frame_given (node, qof_instance_get_slots (QOF_INSTANCE (book)));
+    success = dom_tree_create_instance_slots(node, QOF_INSTANCE (book));
 
     g_return_val_if_fail(success, FALSE);
 
diff --git a/src/backend/xml/gnc-budget-xml-v2.c b/src/backend/xml/gnc-budget-xml-v2.c
index 13ada1e..07aadae 100644
--- a/src/backend/xml/gnc-budget-xml-v2.c
+++ b/src/backend/xml/gnc-budget-xml-v2.c
@@ -57,7 +57,6 @@ xmlNodePtr
 gnc_budget_dom_tree_create(GncBudget *bgt)
 {
     xmlNodePtr ret;
-    KvpFrame *kf;
 
     ENTER ("(budget=%p)", bgt);
 
@@ -79,14 +78,9 @@ gnc_budget_dom_tree_create(GncBudget *bgt)
     /* field: Recurrence*  */
     xmlAddChild(ret, recurrence_to_dom_tree(bgt_recurrence_string,
                                             gnc_budget_get_recurrence(bgt)));
-    /* slots */
-    kf = qof_instance_get_slots(QOF_INSTANCE(bgt));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(bgt_slots_string, kf);
-        if (kvpnode)
-            xmlAddChild(ret, kvpnode);
-    }
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(bgt_slots_string,
+                                                    QOF_INSTANCE(bgt)));
 
     LEAVE (" ");
     return ret;
@@ -159,8 +153,7 @@ budget_recurrence_handler (xmlNodePtr node, gpointer bgt)
 static gboolean
 budget_slots_handler (xmlNodePtr node, gpointer bgt)
 {
-    return dom_tree_to_kvp_frame_given(
-               node, qof_instance_get_slots(QOF_INSTANCE(bgt)));
+     return dom_tree_create_instance_slots(node, QOF_INSTANCE(bgt));
 }
 
 static struct dom_tree_handler budget_handlers[] =
diff --git a/src/backend/xml/gnc-commodity-xml-v2.c b/src/backend/xml/gnc-commodity-xml-v2.c
index eddb392..1d7206c 100644
--- a/src/backend/xml/gnc-commodity-xml-v2.c
+++ b/src/backend/xml/gnc-commodity-xml-v2.c
@@ -66,11 +66,10 @@ gnc_commodity_dom_tree_create(const gnc_commodity *com)
     const char *string;
     xmlNodePtr ret;
     gboolean currency = gnc_commodity_is_iso(com);
-    xmlNodePtr kvpnode =
-        kvp_frame_to_dom_tree(cmdty_slots,
-                              qof_instance_get_slots(QOF_INSTANCE(com)));
+    xmlNodePtr slotsnode =
+        qof_instance_slots_to_dom_tree(cmdty_slots, QOF_INSTANCE(com));
 
-    if (currency && !gnc_commodity_get_quote_flag(com) && !kvpnode)
+    if (currency && !gnc_commodity_get_quote_flag(com) && !slotsnode)
         return NULL;
 
     ret = xmlNewNode(NULL, BAD_CAST gnc_commodity_string);
@@ -114,8 +113,8 @@ gnc_commodity_dom_tree_create(const gnc_commodity *com)
             xmlAddChild(ret, text_to_dom_tree(cmdty_quote_tz, string));
     }
 
-    if (kvpnode)
-        xmlAddChild(ret, kvpnode);
+    if (slotsnode)
+        xmlAddChild(ret, slotsnode);
 
     return ret;
 }
@@ -172,8 +171,7 @@ set_commodity_value(xmlNodePtr node, gnc_commodity* com)
     else if (g_strcmp0((char*)node->name, cmdty_slots) == 0)
     {
         /* We ignore the results here */
-        dom_tree_to_kvp_frame_given(node,
-                                    qof_instance_get_slots(QOF_INSTANCE(com)));
+        dom_tree_create_instance_slots(node, QOF_INSTANCE(com));
     }
     else
     {
diff --git a/src/backend/xml/gnc-customer-xml-v2.c b/src/backend/xml/gnc-customer-xml-v2.c
index 890f3e5..faf8e90 100644
--- a/src/backend/xml/gnc-customer-xml-v2.c
+++ b/src/backend/xml/gnc-customer-xml-v2.c
@@ -77,7 +77,7 @@ const gchar *customer_version_string = "2.0.0";
 static xmlNodePtr
 customer_dom_tree_create (GncCustomer *cust)
 {
-    xmlNodePtr ret, kvpnode;
+    xmlNodePtr ret;
     gnc_numeric num;
     GncBillTerm *term;
     GncTaxTable *taxtable;
@@ -132,9 +132,9 @@ customer_dom_tree_create (GncCustomer *cust)
         xmlAddChild (ret, guid_to_dom_tree (cust_taxtable_string,
                                             qof_instance_get_guid(QOF_INSTANCE(taxtable))));
 
-    kvpnode = kvp_frame_to_dom_tree (cust_slots_string,
-                                     qof_instance_get_slots (QOF_INSTANCE(cust)));
-    if (kvpnode) xmlAddChild (ret, kvpnode);
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(cust_slots_string,
+                                                    QOF_INSTANCE(cust)));
 
     return ret;
 }
@@ -367,8 +367,7 @@ static gboolean
 customer_slots_handler (xmlNodePtr node, gpointer cust_pdata)
 {
     struct customer_pdata *pdata = cust_pdata;
-    return dom_tree_to_kvp_frame_given (node,
-                                        qof_instance_get_slots (QOF_INSTANCE(pdata->customer)));
+    return dom_tree_create_instance_slots(node, QOF_INSTANCE(pdata->customer));
 }
 
 static struct dom_tree_handler customer_handlers_v2[] =
diff --git a/src/backend/xml/gnc-employee-xml-v2.c b/src/backend/xml/gnc-employee-xml-v2.c
index 242a907..d7cb7ec 100644
--- a/src/backend/xml/gnc-employee-xml-v2.c
+++ b/src/backend/xml/gnc-employee-xml-v2.c
@@ -76,7 +76,7 @@ maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
 static xmlNodePtr
 employee_dom_tree_create (GncEmployee *employee)
 {
-    xmlNodePtr ret, kvpnode;
+    xmlNodePtr ret;
     gnc_numeric num;
     Account* ccard_acc;
 
@@ -118,10 +118,9 @@ employee_dom_tree_create (GncEmployee *employee)
         xmlAddChild(ret, guid_to_dom_tree(employee_ccard_string,
                                           qof_instance_get_guid(QOF_INSTANCE(ccard_acc))));
 
-    kvpnode = kvp_frame_to_dom_tree (employee_slots_string,
-                                     qof_instance_get_slots (QOF_INSTANCE(employee)));
-    if (kvpnode) xmlAddChild (ret, kvpnode);
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(employee_slots_string,
+                                                    QOF_INSTANCE(employee)));
     return ret;
 }
 
@@ -294,8 +293,7 @@ static gboolean
 employee_slots_handler (xmlNodePtr node, gpointer employee_pdata)
 {
     struct employee_pdata *pdata = employee_pdata;
-    return dom_tree_to_kvp_frame_given (
-               node, qof_instance_get_slots (QOF_INSTANCE(pdata->employee)));
+    return dom_tree_create_instance_slots (node, QOF_INSTANCE(pdata->employee));
 }
 
 static struct dom_tree_handler employee_handlers_v2[] =
diff --git a/src/backend/xml/gnc-entry-xml-v2.c b/src/backend/xml/gnc-entry-xml-v2.c
index 9e35e81..a892fb2 100644
--- a/src/backend/xml/gnc-entry-xml-v2.c
+++ b/src/backend/xml/gnc-entry-xml-v2.c
@@ -92,9 +92,6 @@ const gchar *entry_version_string = "2.0.0";
 #define entry_bill_string "entry:bill"
 #define entry_slots_string "entry:slots"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance*);
-
 static void
 maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
 {
@@ -118,7 +115,6 @@ entry_dom_tree_create (GncEntry *entry)
     GncTaxTable *taxtable;
     GncOrder *order;
     GncInvoice *invoice;
-    KvpFrame *kf;
 
     ret = xmlNewNode(NULL, BAD_CAST gnc_entry_string);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST entry_version_string);
@@ -215,16 +211,9 @@ entry_dom_tree_create (GncEntry *entry)
         xmlAddChild (ret, guid_to_dom_tree (entry_order_string,
                                             qof_instance_get_guid(QOF_INSTANCE (order))));
 
-    kf = qof_instance_get_slots (QOF_INSTANCE(entry));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(entry_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(entry_slots_string,
+                                                    QOF_INSTANCE(entry)));
     return ret;
 }
 
@@ -677,8 +666,7 @@ entry_slots_handler (xmlNodePtr node, gpointer entry_pdata)
 {
     struct entry_pdata *pdata = entry_pdata;
 
-    return dom_tree_to_kvp_frame_given
-        (node, qof_instance_get_slots (QOF_INSTANCE (pdata->entry)));
+    return dom_tree_create_instance_slots(node, QOF_INSTANCE (pdata->entry));
 }
 
 static struct dom_tree_handler entry_handlers_v2[] =
diff --git a/src/backend/xml/gnc-invoice-xml-v2.c b/src/backend/xml/gnc-invoice-xml-v2.c
index 00ad56d..319b2e8 100644
--- a/src/backend/xml/gnc-invoice-xml-v2.c
+++ b/src/backend/xml/gnc-invoice-xml-v2.c
@@ -72,9 +72,6 @@ const gchar *invoice_version_string = "2.0.0";
 #define invoice_tochargeamt_string "invoice:charge-amt"
 #define invoice_slots_string "invoice:slots"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance *);
-
 static void
 maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
 {
@@ -93,7 +90,6 @@ static xmlNodePtr
 invoice_dom_tree_create (GncInvoice *invoice)
 {
     xmlNodePtr ret;
-    KvpFrame *kf;
     Timespec ts;
     Transaction *txn;
     GNCLot *lot;
@@ -160,16 +156,9 @@ invoice_dom_tree_create (GncInvoice *invoice)
     if (! gnc_numeric_zero_p (amt))
         xmlAddChild (ret, gnc_numeric_to_dom_tree (invoice_tochargeamt_string, &amt));
 
-    kf = qof_instance_get_slots (QOF_INSTANCE(invoice));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(invoice_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+     /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(invoice_slots_string,
+                                                    QOF_INSTANCE(invoice)));
     return ret;
 }
 
@@ -411,9 +400,7 @@ static gboolean
 invoice_slots_handler (xmlNodePtr node, gpointer invoice_pdata)
 {
     struct invoice_pdata *pdata = invoice_pdata;
-
-    return dom_tree_to_kvp_frame_given
-           (node, qof_instance_get_slots (QOF_INSTANCE (pdata->invoice)));
+    return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->invoice));
 }
 
 static struct dom_tree_handler invoice_handlers_v2[] =
diff --git a/src/backend/xml/gnc-job-xml-v2.c b/src/backend/xml/gnc-job-xml-v2.c
index 59f4507..72b86a9 100644
--- a/src/backend/xml/gnc-job-xml-v2.c
+++ b/src/backend/xml/gnc-job-xml-v2.c
@@ -62,14 +62,10 @@ const gchar *job_version_string = "2.0.0";
 #define job_active_string "job:active"
 #define job_slots_string "job:slots"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance*);
-
 static xmlNodePtr
 job_dom_tree_create (GncJob *job)
 {
     xmlNodePtr ret;
-    KvpFrame *kf;
 
     ret = xmlNewNode(NULL, BAD_CAST gnc_job_string);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST job_version_string);
@@ -91,15 +87,9 @@ job_dom_tree_create (GncJob *job)
     xmlAddChild(ret, int_to_dom_tree(job_active_string,
                                      gncJobGetActive (job)));
 
-    kf = qof_instance_get_slots (QOF_INSTANCE(job));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(job_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(job_slots_string,
+                                                    QOF_INSTANCE(job)));
 
     return ret;
 }
@@ -209,8 +199,7 @@ job_slots_handler (xmlNodePtr node, gpointer job_pdata)
 {
     struct job_pdata *pdata = job_pdata;
 
-    return dom_tree_to_kvp_frame_given
-        (node, qof_instance_get_slots (QOF_INSTANCE (pdata->job)));
+    return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->job));
 }
 
 static struct dom_tree_handler job_handlers_v2[] =
diff --git a/src/backend/xml/gnc-lot-xml-v2.c b/src/backend/xml/gnc-lot-xml-v2.c
index afe681a..40eaf37 100644
--- a/src/backend/xml/gnc-lot-xml-v2.c
+++ b/src/backend/xml/gnc-lot-xml-v2.c
@@ -53,30 +53,20 @@ const gchar *lot_version_string = "2.0.0";
 #define gnc_lot_string "gnc:lot"
 #define lot_id_string "lot:id"
 #define lot_slots_string "lot:slots"
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance *);
 
 xmlNodePtr
 gnc_lot_dom_tree_create(GNCLot *lot)
 {
     xmlNodePtr ret;
-    KvpFrame *kf;
 
     ENTER("(lot=%p)", lot);
     ret = xmlNewNode(NULL, BAD_CAST gnc_lot_string);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST lot_version_string);
 
     xmlAddChild(ret, guid_to_dom_tree(lot_id_string, gnc_lot_get_guid(lot)));
-
-    kf = qof_instance_get_slots (QOF_INSTANCE (lot));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(lot_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(lot_slots_string,
+                                                    QOF_INSTANCE(lot)));
 
     LEAVE("");
     return ret;
@@ -113,8 +103,7 @@ lot_slots_handler (xmlNodePtr node, gpointer p)
     gboolean success;
 
     ENTER("(lot=%p)", pdata->lot);
-    success = dom_tree_to_kvp_frame_given
-	(node, qof_instance_get_slots (QOF_INSTANCE (pdata->lot)));
+    success = dom_tree_create_instance_slots(node, QOF_INSTANCE (pdata->lot));
 
     LEAVE("");
     g_return_val_if_fail(success, FALSE);
diff --git a/src/backend/xml/gnc-order-xml-v2.c b/src/backend/xml/gnc-order-xml-v2.c
index 40fb677..0adb39b 100644
--- a/src/backend/xml/gnc-order-xml-v2.c
+++ b/src/backend/xml/gnc-order-xml-v2.c
@@ -64,9 +64,6 @@ const gchar *order_version_string = "2.0.0";
 #define order_active_string "order:active"
 #define order_slots_string "order:slots"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance*);
-
 static void
 maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
 {
@@ -79,7 +76,6 @@ order_dom_tree_create (GncOrder *order)
 {
     xmlNodePtr ret;
     Timespec ts;
-    KvpFrame *kf;
 
     ret = xmlNewNode(NULL, BAD_CAST gnc_order_string);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST order_version_string);
@@ -106,15 +102,9 @@ order_dom_tree_create (GncOrder *order)
     xmlAddChild(ret, int_to_dom_tree(order_active_string,
                                      gncOrderGetActive (order)));
 
-    kf = qof_instance_get_slots (QOF_INSTANCE(order));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(order_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(order_slots_string,
+                                                    QOF_INSTANCE(order)));
 
     return ret;
 }
@@ -250,8 +240,7 @@ order_slots_handler (xmlNodePtr node, gpointer order_pdata)
 {
     struct order_pdata *pdata = order_pdata;
 
-    return dom_tree_to_kvp_frame_given
-        (node, qof_instance_get_slots (QOF_INSTANCE (pdata->order)));
+    return dom_tree_create_instance_slots(node, QOF_INSTANCE (pdata->order));
 }
 
 static struct dom_tree_handler order_handlers_v2[] =
diff --git a/src/backend/xml/gnc-schedxaction-xml-v2.c b/src/backend/xml/gnc-schedxaction-xml-v2.c
index 2fd90ca..46aa150 100644
--- a/src/backend/xml/gnc-schedxaction-xml-v2.c
+++ b/src/backend/xml/gnc-schedxaction-xml-v2.c
@@ -190,17 +190,9 @@ gnc_schedXaction_dom_tree_create(SchedXaction *sx)
         }
     }
 
-    /* output kvp_frame */
-    {
-        xmlNodePtr kvpnode =
-            kvp_frame_to_dom_tree( SX_SLOTS,
-                                   xaccSchedXactionGetSlots(sx) );
-        if ( kvpnode )
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(SX_SLOTS,
+                                                    QOF_INSTANCE(sx)));
     return ret;
 }
 
@@ -629,7 +621,7 @@ sx_slots_handler( xmlNodePtr node, gpointer sx_pdata )
     struct sx_pdata *pdata = sx_pdata;
     SchedXaction *sx = pdata->sx;
 
-    return dom_tree_to_kvp_frame_given( node, xaccSchedXactionGetSlots (sx) );
+    return dom_tree_create_instance_slots(node, QOF_INSTANCE(sx));
 }
 
 struct dom_tree_handler sx_dom_handlers[] =
diff --git a/src/backend/xml/gnc-tax-table-xml-v2.c b/src/backend/xml/gnc-tax-table-xml-v2.c
index dda332c..2a7daa6 100644
--- a/src/backend/xml/gnc-tax-table-xml-v2.c
+++ b/src/backend/xml/gnc-tax-table-xml-v2.c
@@ -67,9 +67,6 @@ const gchar *taxtable_version_string = "2.0.0";
 #define ttentry_type_string "tte:type"
 #define ttentry_amount_string "tte:amount"
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance*);
-
 static void
 maybe_add_guid (xmlNodePtr ptr, const char *tag, GncTaxTable *table)
 {
@@ -107,7 +104,6 @@ taxtable_dom_tree_create (GncTaxTable *table)
 {
     xmlNodePtr ret, entries;
     GList *list;
-    KvpFrame *kf;
 
     ret = xmlNewNode(NULL, BAD_CAST gnc_taxtable_string);
     xmlSetProp(ret, BAD_CAST "version", BAD_CAST taxtable_version_string);
@@ -134,16 +130,9 @@ taxtable_dom_tree_create (GncTaxTable *table)
         xmlAddChild(entries, ttentry_dom_tree_create (entry));
     }
 
-    kf = qof_instance_get_slots (QOF_INSTANCE(table));
-    if (kf)
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(taxtable_slots_string, kf);
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(taxtable_slots_string,
+                                                    QOF_INSTANCE(table)));
     return ret;
 }
 
@@ -384,8 +373,7 @@ taxtable_slots_handler (xmlNodePtr node, gpointer taxtable_pdata)
 {
     struct taxtable_pdata *pdata = taxtable_pdata;
 
-    return dom_tree_to_kvp_frame_given
-        (node, qof_instance_get_slots (QOF_INSTANCE (pdata->table)));
+    return dom_tree_create_instance_slots(node, QOF_INSTANCE (pdata->table));
 }
 
 static struct dom_tree_handler taxtable_handlers_v2[] =
diff --git a/src/backend/xml/gnc-transaction-xml-v2.c b/src/backend/xml/gnc-transaction-xml-v2.c
index a2a3513..40f871c 100644
--- a/src/backend/xml/gnc-transaction-xml-v2.c
+++ b/src/backend/xml/gnc-transaction-xml-v2.c
@@ -49,9 +49,6 @@
 
 const gchar *transaction_version_string = "2.0.0";
 
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance *);
-
 static void
 add_gnc_num(xmlNodePtr node, const gchar *tag, gnc_numeric num)
 {
@@ -130,15 +127,9 @@ split_to_dom_tree(const gchar *tag, Split *spl)
                                                gnc_lot_get_guid(lot)));
         }
     }
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree("split:slots",
-                             qof_instance_get_slots (QOF_INSTANCE (spl)));
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree("split:slots",
+                                                    QOF_INSTANCE(spl)));
     return ret;
 }
 
@@ -193,14 +184,9 @@ gnc_transaction_dom_tree_create(Transaction *trn)
     }
     g_free (str);
 
-    {
-        xmlNodePtr kvpnode = kvp_frame_to_dom_tree("trn:slots",
-                             qof_instance_get_slots (QOF_INSTANCE (trn)));
-        if (kvpnode)
-        {
-            xmlAddChild(ret, kvpnode);
-        }
-    }
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree("trn:slots",
+                                                    QOF_INSTANCE(trn)));
 
     add_trans_splits(ret, trn);
 
@@ -370,8 +356,8 @@ spl_slots_handler(xmlNodePtr node, gpointer data)
     struct split_pdata *pdata = data;
     gboolean successful;
 
-    successful = dom_tree_to_kvp_frame_given(node,
-                 qof_instance_get_slots (QOF_INSTANCE (pdata->split)));
+    successful = dom_tree_create_instance_slots(node,
+                                                QOF_INSTANCE (pdata->split));
     g_return_val_if_fail(successful, FALSE);
 
     return TRUE;
@@ -530,7 +516,7 @@ trn_slots_handler(xmlNodePtr node, gpointer trans_pdata)
     Transaction *trn = pdata->trans;
     gboolean successful;
 
-    successful = dom_tree_to_kvp_frame_given(node, qof_instance_get_slots (QOF_INSTANCE (trn)));
+    successful = dom_tree_create_instance_slots(node, QOF_INSTANCE (trn));
 
     g_return_val_if_fail(successful, FALSE);
 
diff --git a/src/backend/xml/gnc-vendor-xml-v2.c b/src/backend/xml/gnc-vendor-xml-v2.c
index e54efb9..5ab47f1 100644
--- a/src/backend/xml/gnc-vendor-xml-v2.c
+++ b/src/backend/xml/gnc-vendor-xml-v2.c
@@ -73,7 +73,7 @@ const gchar *vendor_version_string = "2.0.0";
 static xmlNodePtr
 vendor_dom_tree_create (GncVendor *vendor)
 {
-    xmlNodePtr ret, kvpnode;
+    xmlNodePtr ret;
     GncBillTerm *term;
     GncTaxTable *taxtable;
 
@@ -118,10 +118,9 @@ vendor_dom_tree_create (GncVendor *vendor)
         xmlAddChild (ret, guid_to_dom_tree (vendor_taxtable_string,
                                             qof_instance_get_guid(QOF_INSTANCE(taxtable))));
 
-    kvpnode = kvp_frame_to_dom_tree (vendor_slots_string,
-                                     qof_instance_get_slots (QOF_INSTANCE(vendor)));
-    if (kvpnode) xmlAddChild (ret, kvpnode);
-
+    /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
+    xmlAddChild(ret, qof_instance_slots_to_dom_tree(vendor_slots_string,
+                                                    QOF_INSTANCE(vendor)));
     return ret;
 }
 
@@ -313,8 +312,7 @@ static gboolean
 vendor_slots_handler (xmlNodePtr node, gpointer vendor_pdata)
 {
     struct vendor_pdata *pdata = vendor_pdata;
-    return dom_tree_to_kvp_frame_given (
-               node, qof_instance_get_slots (QOF_INSTANCE(pdata->vendor)));
+    return dom_tree_create_instance_slots(node, QOF_INSTANCE(pdata->vendor));
 
 }
 
diff --git a/src/backend/xml/sixtp-dom-generators.cpp b/src/backend/xml/sixtp-dom-generators.cpp
index 665aebd..8160ad4 100644
--- a/src/backend/xml/sixtp-dom-generators.cpp
+++ b/src/backend/xml/sixtp-dom-generators.cpp
@@ -365,18 +365,18 @@ add_kvp_slot(const char * key, KvpValue* value, xmlNodePtr node)
 }
 
 xmlNodePtr
-kvp_frame_to_dom_tree(const char *tag, const KvpFrame *frame)
+qof_instance_slots_to_dom_tree(const char *tag, const QofInstance* inst)
 {
     xmlNodePtr ret;
     const char ** keys;
     unsigned int i;
-
+    KvpFrame *frame = qof_instance_get_slots(QOF_INSTANCE (inst));
     if (!frame)
     {
-        return NULL;
+        return nullptr;
     }
 
-    ret = xmlNewNode(NULL, BAD_CAST tag);
+    ret = xmlNewNode(nullptr, BAD_CAST tag);
 
     keys = kvp_frame_get_keys(frame);
     for (i = 0; keys[i]; ++i)
diff --git a/src/backend/xml/sixtp-dom-generators.h b/src/backend/xml/sixtp-dom-generators.h
index 09b14b5..18b5ff2 100644
--- a/src/backend/xml/sixtp-dom-generators.h
+++ b/src/backend/xml/sixtp-dom-generators.h
@@ -47,7 +47,8 @@ gchar * timespec_nsec_to_string(const Timespec *ts);
 gchar * timespec_sec_to_string(const Timespec *ts);
 xmlNodePtr gdate_to_dom_tree(const char *tag, const GDate *spec);
 xmlNodePtr gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num);
-xmlNodePtr kvp_frame_to_dom_tree(const char *tag, const KvpFrame *frame);
+xmlNodePtr qof_instance_slots_to_dom_tree(const char *tag,
+                                          const QofInstance *inst);
 xmlNodePtr guint_to_dom_tree(const char *tag, guint an_int);
 xmlNodePtr recurrence_to_dom_tree(const gchar *tag, const Recurrence *r);
 
diff --git a/src/backend/xml/sixtp-dom-parsers.cpp b/src/backend/xml/sixtp-dom-parsers.cpp
index aa00165..f95059e 100644
--- a/src/backend/xml/sixtp-dom-parsers.cpp
+++ b/src/backend/xml/sixtp-dom-parsers.cpp
@@ -79,7 +79,7 @@ dom_tree_to_guid(xmlNodePtr node)
     }
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_integer_kvp_value(xmlNodePtr node)
 {
     gchar *text;
@@ -162,7 +162,7 @@ dom_tree_to_boolean(xmlNodePtr node, gboolean* b)
     }
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_double_kvp_value(xmlNodePtr node)
 {
     gchar *text;
@@ -181,7 +181,7 @@ dom_tree_to_double_kvp_value(xmlNodePtr node)
     return ret;
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_numeric_kvp_value(xmlNodePtr node)
 {
     gnc_numeric *danum;
@@ -199,7 +199,7 @@ dom_tree_to_numeric_kvp_value(xmlNodePtr node)
     return ret;
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_string_kvp_value(xmlNodePtr node)
 {
     gchar *datext;
@@ -216,7 +216,7 @@ dom_tree_to_string_kvp_value(xmlNodePtr node)
     return ret;
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_guid_kvp_value(xmlNodePtr node)
 {
     GncGUID *daguid;
@@ -233,7 +233,7 @@ dom_tree_to_guid_kvp_value(xmlNodePtr node)
     return ret;
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_timespec_kvp_value (xmlNodePtr node)
 {
     Timespec ts;
@@ -247,7 +247,7 @@ dom_tree_to_timespec_kvp_value (xmlNodePtr node)
     return ret;
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_gdate_kvp_value (xmlNodePtr node)
 {
     GDate *date;
@@ -304,7 +304,14 @@ string_to_binary(const gchar *str,  void **v, guint64 *data_len)
     return(TRUE);
 }
 
-KvpValue*
+static KvpValue* dom_tree_to_kvp_value(xmlNodePtr node);
+//needed for test access as well as internal use.
+extern "C"
+{
+    KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
+}
+
+static KvpValue*
 dom_tree_to_list_kvp_value(xmlNodePtr node)
 {
     GList *list = NULL;
@@ -330,7 +337,7 @@ dom_tree_to_list_kvp_value(xmlNodePtr node)
     return ret;
 }
 
-KvpValue*
+static KvpValue*
 dom_tree_to_frame_kvp_value(xmlNodePtr node)
 {
     KvpFrame *frame;
@@ -369,7 +376,7 @@ struct kvp_val_converter val_converters[] =
     { 0, 0 },
 };
 
-KvpValue*
+static KvpValue*
 dom_tree_to_kvp_value(xmlNodePtr node)
 {
     xmlChar *xml_type;
@@ -404,7 +411,7 @@ dom_tree_to_kvp_value(xmlNodePtr node)
     return ret;
 }
 
-gboolean
+static gboolean
 dom_tree_to_kvp_frame_given(xmlNodePtr node, KvpFrame *frame)
 {
     xmlNodePtr mark;
@@ -473,6 +480,12 @@ dom_tree_to_kvp_frame(xmlNodePtr node)
     return NULL;
 }
 
+gboolean
+dom_tree_create_instance_slots(xmlNodePtr node, QofInstance *inst)
+{
+    KvpFrame *frame = qof_instance_get_slots(inst);
+    return dom_tree_to_kvp_frame_given(node, frame);
+}
 
 gchar *
 dom_tree_to_text(xmlNodePtr tree)
diff --git a/src/backend/xml/sixtp-dom-parsers.h b/src/backend/xml/sixtp-dom-parsers.h
index efae18a..f96db25 100644
--- a/src/backend/xml/sixtp-dom-parsers.h
+++ b/src/backend/xml/sixtp-dom-parsers.h
@@ -50,21 +50,7 @@ GDate* dom_tree_to_gdate(xmlNodePtr node);
 gnc_numeric* dom_tree_to_gnc_numeric(xmlNodePtr node);
 gchar * dom_tree_to_text(xmlNodePtr tree);
 gboolean string_to_binary(const gchar *str,  void **v, guint64 *data_len);
-
-gboolean dom_tree_to_kvp_frame_given(xmlNodePtr node, KvpFrame *frame);
-
-KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
-KvpValue* dom_tree_to_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_integer_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_double_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_numeric_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_string_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_guid_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_timespec_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_binary_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_list_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_frame_kvp_value(xmlNodePtr node);
-KvpValue* dom_tree_to_gdate_kvp_value (xmlNodePtr node);
+gboolean dom_tree_create_instance_slots(xmlNodePtr node, QofInstance *inst);
 
 gboolean dom_tree_to_integer(xmlNodePtr node, gint64 *daint);
 gboolean dom_tree_to_guint16(xmlNodePtr node, guint16 *i);
diff --git a/src/backend/xml/test/test-file-stuff.c b/src/backend/xml/test/test-file-stuff.c
index 2385d38..c763275 100644
--- a/src/backend/xml/test/test-file-stuff.c
+++ b/src/backend/xml/test/test-file-stuff.c
@@ -46,6 +46,8 @@
 */
 /***********************************************************************/
 
+extern KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
+
 static int
 files_return(int ret, const char* msg)
 {
diff --git a/src/backend/xml/test/test-kvp-frames.c b/src/backend/xml/test/test-kvp-frames.c
index ac2825b..09a5890 100644
--- a/src/backend/xml/test/test-kvp-frames.c
+++ b/src/backend/xml/test/test-kvp-frames.c
@@ -13,6 +13,7 @@
 
 #define GNC_V2_STRING "gnc-v2"
 const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
+extern KvpFrame* dom_tree_to_kvp_frame(xmlNodePtr node);
 
 static void
 test_kvp_get_slot(int run,
@@ -171,13 +172,13 @@ test_kvp_xml_stuff(void)
     int i;
     for (i = 0; i < 20; i++)
     {
-        KvpFrame *test_frame1;
+        QofInstance *inst = g_object_new (QOF_TYPE_INSTANCE, NULL);
         KvpFrame *test_frame2;
         xmlNodePtr test_node;
 
-        test_frame1 = get_random_kvp_frame();
+        inst->kvp_data = get_random_kvp_frame();
 
-        test_node = kvp_frame_to_dom_tree("test-kvp", test_frame1);
+        test_node = qof_instance_slots_to_dom_tree("test-kvp", inst);
 
         if (!test_node)
         {
@@ -188,7 +189,7 @@ test_kvp_xml_stuff(void)
         {
             test_frame2 = dom_tree_to_kvp_frame(test_node);
 
-            if (kvp_frame_compare(test_frame1, test_frame2) == 0)
+            if (kvp_frame_compare(inst->kvp_data, test_frame2) == 0)
             {
                 success("xml stuff");
             }
@@ -196,7 +197,7 @@ test_kvp_xml_stuff(void)
             {
                 gchar *tmp;
                 failure("xml stuff");
-                tmp = kvp_frame_to_string(test_frame1);
+                tmp = kvp_frame_to_string(inst->kvp_data);
                 printf("   with kvp_frame 1:\n%s\n", tmp);
                 g_free(tmp);
                 printf("   and xml:\n");
@@ -209,8 +210,7 @@ test_kvp_xml_stuff(void)
             kvp_frame_delete(test_frame2);
             xmlFreeNode(test_node);
         }
-
-        kvp_frame_delete(test_frame1);
+        g_object_unref (inst);
     }
 }
 
diff --git a/src/engine/SchedXaction.h b/src/engine/SchedXaction.h
index f4f9454..e79ae3d 100644
--- a/src/engine/SchedXaction.h
+++ b/src/engine/SchedXaction.h
@@ -319,8 +319,6 @@ gboolean SXRegister (void);
 #define xaccSchedXactionIsDirty(X) qof_instance_is_dirty (QOF_INSTANCE(X))
 /** \deprecated */
 #define xaccSchedXactionGetGUID(X) qof_entity_get_guid(QOF_INSTANCE(X))
-/** \deprecated */
-#define xaccSchedXactionGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X))
 
 #endif /* XACC_SCHEDXACTION_H */
 

commit 13377f56d5f2c4eb26cb1f6ad0a22bb5dd98b7f3
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jun 13 15:33:03 2015 -0700

    Cpp files in CMakelists.txt.

diff --git a/src/backend/sql/CMakeLists.txt b/src/backend/sql/CMakeLists.txt
index 3f463a6..22381fc 100644
--- a/src/backend/sql/CMakeLists.txt
+++ b/src/backend/sql/CMakeLists.txt
@@ -34,7 +34,7 @@ SET (libgnc_backend_sql_SOURCES
   gnc-price-sql.c
   gnc-recurrence-sql.c
   gnc-schedxaction-sql.c
-  gnc-slots-sql.c
+  gnc-slots-sql.cpp
   gnc-tax-table-sql.c
   gnc-transaction-sql.c
   gnc-vendor-sql.c
diff --git a/src/backend/xml/CMakeLists.txt b/src/backend/xml/CMakeLists.txt
index fec23e2..26158ad 100644
--- a/src/backend/xml/CMakeLists.txt
+++ b/src/backend/xml/CMakeLists.txt
@@ -49,8 +49,8 @@ SET (libgnc_backend_xml_SOURCES
   io-gncxml-v1.c 
   io-gncxml-v2.c 
   io-utils.c 
-  sixtp-dom-generators.c 
-  sixtp-dom-parsers.c 
+  sixtp-dom-generators.cpp
+  sixtp-dom-parsers.cpp
   sixtp-stack.c 
   sixtp-to-dom-parser.c 
   sixtp-utils.c 

commit 55e4d30a44ac65a4e2c4d3e82cd13fdde2b05d0e
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jun 12 15:53:33 2015 -0700

    Pass QofInstance instead of KvpFrame to gnc_sql_slots_save.

diff --git a/src/backend/sql/gnc-account-sql.c b/src/backend/sql/gnc-account-sql.c
index 7d6b3a3..cf887dd 100644
--- a/src/backend/sql/gnc-account-sql.c
+++ b/src/backend/sql/gnc-account-sql.c
@@ -383,7 +383,7 @@ gnc_sql_save_account( GncSqlBackend* be, QofInstance* inst )
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {
diff --git a/src/backend/sql/gnc-backend-sql.c b/src/backend/sql/gnc-backend-sql.c
index 2124be9..1e68004 100644
--- a/src/backend/sql/gnc-backend-sql.c
+++ b/src/backend/sql/gnc-backend-sql.c
@@ -3072,7 +3072,7 @@ gnc_sql_commit_standard_item( GncSqlBackend* be, QofInstance* inst, const gchar*
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {
diff --git a/src/backend/sql/gnc-budget-sql.c b/src/backend/sql/gnc-budget-sql.c
index 4c697c9..cd4db4a 100644
--- a/src/backend/sql/gnc-budget-sql.c
+++ b/src/backend/sql/gnc-budget-sql.c
@@ -430,7 +430,7 @@ save_budget( GncSqlBackend* be, QofInstance* inst )
             }
             if ( is_ok )
             {
-                is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+                is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
             }
         }
         else
diff --git a/src/backend/sql/gnc-commodity-sql.c b/src/backend/sql/gnc-commodity-sql.c
index 040b17c..9e3bccb 100644
--- a/src/backend/sql/gnc-commodity-sql.c
+++ b/src/backend/sql/gnc-commodity-sql.c
@@ -213,7 +213,7 @@ do_commit_commodity( GncSqlBackend* be, QofInstance* inst, gboolean force_insert
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {
diff --git a/src/backend/sql/gnc-employee-sql.c b/src/backend/sql/gnc-employee-sql.c
index 5b18a1e..3e09f1c 100644
--- a/src/backend/sql/gnc-employee-sql.c
+++ b/src/backend/sql/gnc-employee-sql.c
@@ -198,7 +198,7 @@ save_employee( GncSqlBackend* be, QofInstance* inst )
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {
diff --git a/src/backend/sql/gnc-invoice-sql.c b/src/backend/sql/gnc-invoice-sql.c
index 72c1cd2..fc99e68 100644
--- a/src/backend/sql/gnc-invoice-sql.c
+++ b/src/backend/sql/gnc-invoice-sql.c
@@ -221,7 +221,7 @@ save_invoice( GncSqlBackend* be, QofInstance* inst )
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {
diff --git a/src/backend/sql/gnc-schedxaction-sql.c b/src/backend/sql/gnc-schedxaction-sql.c
index b0a3ab5..058cd3b 100644
--- a/src/backend/sql/gnc-schedxaction-sql.c
+++ b/src/backend/sql/gnc-schedxaction-sql.c
@@ -206,7 +206,7 @@ gnc_sql_save_schedxaction( GncSqlBackend* be, QofInstance* inst )
         // Now, commit any slots
         if ( op == OP_DB_INSERT || op == OP_DB_UPDATE )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {
diff --git a/src/backend/sql/gnc-slots-sql.cpp b/src/backend/sql/gnc-slots-sql.cpp
index 9bd6b5c..bff1eab 100644
--- a/src/backend/sql/gnc-slots-sql.cpp
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -708,7 +708,8 @@ save_slot( const gchar* key, KvpValue* value, gpointer data )
 }
 
 gboolean
-gnc_sql_slots_save( GncSqlBackend* be, const GncGUID* guid, gboolean is_infant, KvpFrame* pFrame )
+gnc_sql_slots_save( GncSqlBackend* be, const GncGUID* guid, gboolean is_infant,
+                    QofInstance *inst)
 {
      slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
      KvpFrame *pFrame = qof_instance_get_slots (inst);
diff --git a/src/backend/sql/gnc-slots-sql.h b/src/backend/sql/gnc-slots-sql.h
index a9d6685..28b6cb4 100644
--- a/src/backend/sql/gnc-slots-sql.h
+++ b/src/backend/sql/gnc-slots-sql.h
@@ -35,7 +35,6 @@ extern "C"
 
 #include <glib.h>
 #include "guid.h"
-#include "kvp_frame.h"
 #include "qof.h"
 #include "gnc-backend-sql.h"
 
@@ -45,11 +44,11 @@ extern "C"
  * @param be SQL backend
  * @param guid Object guid
  * @param is_infant Is this an infant object?
- * @param pFrame Top-level KVP frame
+ * @param inst The QodInstance owning the slots.
  * @return TRUE if successful, FALSE if error
  */
 gboolean gnc_sql_slots_save( GncSqlBackend* be, const GncGUID* guid,
-                             gboolean is_infant, KvpFrame* pFrame );
+                             gboolean is_infant, QofInstance *inst );
 
 /**
  * gnc_sql_slots_delete - Deletes slots for an object from the db.
diff --git a/src/backend/sql/gnc-tax-table-sql.c b/src/backend/sql/gnc-tax-table-sql.c
index fbf5d37..bb5f068 100644
--- a/src/backend/sql/gnc-tax-table-sql.c
+++ b/src/backend/sql/gnc-tax-table-sql.c
@@ -454,7 +454,7 @@ save_taxtable( GncSqlBackend* be, QofInstance* inst )
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
             if ( is_ok )
             {
                 is_ok = save_tt_entries( be, guid, gncTaxTableGetEntries( tt ) );
diff --git a/src/backend/sql/gnc-transaction-sql.c b/src/backend/sql/gnc-transaction-sql.c
index f48ce71..0b4eb40 100644
--- a/src/backend/sql/gnc-transaction-sql.c
+++ b/src/backend/sql/gnc-transaction-sql.c
@@ -627,10 +627,7 @@ commit_split( GncSqlBackend* be, QofInstance* inst )
 
     if ( is_ok && !qof_instance_get_destroying (inst))
     {
-        is_ok = gnc_sql_slots_save( be,
-                                    guid,
-                                    is_infant,
-                                    qof_instance_get_slots( inst ) );
+        is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
     }
 
     return is_ok;
@@ -724,7 +721,7 @@ save_transaction( GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits )
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
             if ( ! is_ok )
             {
                 err = "Slots save failed. Check trace log for SQL errors";
diff --git a/src/backend/sql/gnc-vendor-sql.c b/src/backend/sql/gnc-vendor-sql.c
index 94cae4d..23ede09 100644
--- a/src/backend/sql/gnc-vendor-sql.c
+++ b/src/backend/sql/gnc-vendor-sql.c
@@ -194,7 +194,7 @@ save_vendor( GncSqlBackend* be, QofInstance* inst )
         guid = qof_instance_get_guid( inst );
         if ( !qof_instance_get_destroying(inst) )
         {
-            is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) );
+            is_ok = gnc_sql_slots_save( be, guid, is_infant, inst);
         }
         else
         {

commit 8b53483562e3c6b070205563eea572035b046a85
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jun 13 14:21:19 2015 -0700

    Change gnc-slots-sql, sixtp-dom-generators, and sixtp-dom-parsers to C++.
    
    So that they'll be able to use the C++ Kvp classes.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index af02822..58c75b9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -58,7 +58,7 @@ src/backend/sql/gnc-owner-sql.c
 src/backend/sql/gnc-price-sql.c
 src/backend/sql/gnc-recurrence-sql.c
 src/backend/sql/gnc-schedxaction-sql.c
-src/backend/sql/gnc-slots-sql.c
+src/backend/sql/gnc-slots-sql.cpp
 src/backend/sql/gnc-tax-table-sql.c
 src/backend/sql/gnc-transaction-sql.c
 src/backend/sql/gnc-vendor-sql.c
@@ -91,8 +91,8 @@ src/backend/xml/io-gncxml-v1.c
 src/backend/xml/io-gncxml-v2.c
 src/backend/xml/io-utils.c
 src/backend/xml/sixtp.c
-src/backend/xml/sixtp-dom-generators.c
-src/backend/xml/sixtp-dom-parsers.c
+src/backend/xml/sixtp-dom-generators.cpp
+src/backend/xml/sixtp-dom-parsers.cpp
 src/backend/xml/sixtp-stack.c
 src/backend/xml/sixtp-to-dom-parser.c
 src/backend/xml/sixtp-utils.c
diff --git a/src/backend/sql/Makefile.am b/src/backend/sql/Makefile.am
index d656030..11a7bd5 100644
--- a/src/backend/sql/Makefile.am
+++ b/src/backend/sql/Makefile.am
@@ -38,7 +38,7 @@ libgnc_backend_sql_la_SOURCES = \
   gnc-price-sql.c \
   gnc-recurrence-sql.c \
   gnc-schedxaction-sql.c \
-  gnc-slots-sql.c \
+  gnc-slots-sql.cpp \
   gnc-tax-table-sql.c \
   gnc-transaction-sql.c \
   gnc-vendor-sql.c \
diff --git a/src/backend/sql/gnc-slots-sql.c b/src/backend/sql/gnc-slots-sql.cpp
similarity index 97%
rename from src/backend/sql/gnc-slots-sql.c
rename to src/backend/sql/gnc-slots-sql.cpp
index 0611e3e..9bd6b5c 100644
--- a/src/backend/sql/gnc-slots-sql.c
+++ b/src/backend/sql/gnc-slots-sql.cpp
@@ -25,7 +25,8 @@
  * This file implements the top-level QofBackend API for saving/
  * restoring data to/from an SQL db
  */
-
+extern "C"
+{
 #include "config.h"
 
 #include <glib.h>
@@ -40,7 +41,7 @@
 #ifdef S_SPLINT_S
 #include "splint-defs.h"
 #endif
-
+}
 /*@ unused @*/ static QofLogModule log_module = G_LOG_DOMAIN;
 
 #define TABLE_NAME "slots"
@@ -323,7 +324,7 @@ get_slot_type( gpointer pObject )
 {
     slot_info_t* pInfo = (slot_info_t*)pObject;
 
-    g_return_val_if_fail( pObject != NULL, 0 );
+    g_return_val_if_fail( pObject != NULL, KVP_TYPE_INVALID );
 
 //    return (gpointer)kvp_value_get_type( pInfo->pKvpValue );
     return pInfo->value_type;
@@ -337,7 +338,7 @@ set_slot_type( gpointer pObject, /*@ null @*/ gpointer pValue )
     g_return_if_fail( pObject != NULL );
     g_return_if_fail( pValue != NULL );
 
-    pInfo->value_type = (KvpValueType)pValue;
+    pInfo->value_type = static_cast<KvpValueType>(GPOINTER_TO_INT(pValue));
 }
 
 static gint64
@@ -709,7 +710,8 @@ save_slot( const gchar* key, KvpValue* value, gpointer data )
 gboolean
 gnc_sql_slots_save( GncSqlBackend* be, const GncGUID* guid, gboolean is_infant, KvpFrame* pFrame )
 {
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new(NULL) };
+     slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
+     KvpFrame *pFrame = qof_instance_get_slots (inst);
 
     g_return_val_if_fail( be != NULL, FALSE );
     g_return_val_if_fail( guid != NULL, FALSE );
@@ -736,7 +738,7 @@ gnc_sql_slots_delete( GncSqlBackend* be, const GncGUID* guid )
     GncSqlResult* result;
     gchar guid_buf[GUID_ENCODING_LENGTH + 1];
     GncSqlStatement* stmt;
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new(NULL) };
+    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
 
     g_return_val_if_fail( be != NULL, FALSE );
     g_return_val_if_fail( guid != NULL, FALSE );
@@ -818,7 +820,7 @@ load_slot( slot_info_t *pInfo, GncSqlRow* row )
 void
 gnc_sql_slots_load( GncSqlBackend* be, QofInstance* inst )
 {
-    slot_info_t info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new(NULL) };
+    slot_info_t info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, g_string_new(NULL) };
     g_return_if_fail( be != NULL );
     g_return_if_fail( inst != NULL );
 
@@ -883,7 +885,7 @@ load_obj_guid( const GncSqlBackend* be, GncSqlRow* row )
 static void
 load_slot_for_list_item( GncSqlBackend* be, GncSqlRow* row, QofCollection* coll )
 {
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, NULL };
+    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, NULL };
     const GncGUID* guid;
     QofInstance* inst;
 
@@ -969,7 +971,7 @@ gnc_sql_slots_load_for_list( GncSqlBackend* be, GList* list )
 static void
 load_slot_for_book_object( GncSqlBackend* be, GncSqlRow* row, BookLookupFn lookup_fn )
 {
-    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, NULL };
+    slot_info_t slot_info = { NULL, NULL, TRUE, NULL, KVP_TYPE_INVALID, NULL, FRAME, NULL, NULL };
     const GncGUID* guid;
     QofInstance* inst;
 
diff --git a/src/backend/sql/gnc-slots-sql.h b/src/backend/sql/gnc-slots-sql.h
index e7f00eb..a9d6685 100644
--- a/src/backend/sql/gnc-slots-sql.h
+++ b/src/backend/sql/gnc-slots-sql.h
@@ -28,6 +28,10 @@
 
 #ifndef GNC_SLOTS_SQL_H
 #define GNC_SLOTS_SQL_H
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 
 #include <glib.h>
 #include "guid.h"
@@ -88,4 +92,7 @@ void gnc_sql_slots_load_for_sql_subquery( GncSqlBackend* be, const gchar* subque
 
 void gnc_sql_init_slots_handler( void );
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* GNC_SLOTS_SQL_H */
diff --git a/src/backend/xml/Makefile.am b/src/backend/xml/Makefile.am
index 7709aa1..e7bb12e 100644
--- a/src/backend/xml/Makefile.am
+++ b/src/backend/xml/Makefile.am
@@ -45,8 +45,8 @@ libgnc_backend_xml_utils_la_SOURCES = \
   io-gncxml-v1.c \
   io-gncxml-v2.c \
   io-utils.c \
-  sixtp-dom-generators.c \
-  sixtp-dom-parsers.c \
+  sixtp-dom-generators.cpp \
+  sixtp-dom-parsers.cpp \
   sixtp-stack.c \
   sixtp-to-dom-parser.c \
   sixtp-utils.c \
diff --git a/src/backend/xml/sixtp-dom-generators.c b/src/backend/xml/sixtp-dom-generators.cpp
similarity index 97%
rename from src/backend/xml/sixtp-dom-generators.c
rename to src/backend/xml/sixtp-dom-generators.cpp
index 083bb72..665aebd 100644
--- a/src/backend/xml/sixtp-dom-generators.c
+++ b/src/backend/xml/sixtp-dom-generators.cpp
@@ -20,7 +20,8 @@
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  *                                                                  *
  ********************************************************************/
-
+extern "C"
+{
 #define __EXTENSIONS__
 
 #include "config.h"
@@ -31,6 +32,7 @@
 
 #include "sixtp-dom-generators.h"
 #include "sixtp-utils.h"
+}
 
 static QofLogModule log_module = GNC_MOD_IO;
 
@@ -237,11 +239,11 @@ double_to_string(double value)
 }
 
 static void
-add_text_to_node(xmlNodePtr node, gchar *type, gchar *val)
+add_text_to_node(xmlNodePtr node, const gchar *type, gchar *val)
 {
     gchar *newtype = g_strdup (type);
     gchar *newval = g_strdup (val);
-    xmlSetProp(node, BAD_CAST "type", checked_char_cast (type));
+    xmlSetProp(node, BAD_CAST "type", BAD_CAST type);
     xmlNodeSetContent(node, checked_char_cast (val));
     g_free (newtype);
     g_free(newval);
@@ -251,7 +253,7 @@ static void
 add_kvp_slot(const char * key, KvpValue* value, xmlNodePtr node);
 
 static void
-add_kvp_value_node(xmlNodePtr node, gchar *tag, KvpValue* val)
+add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val)
 {
     xmlNodePtr val_node;
     kvp_value_t kvp_type;
diff --git a/src/backend/xml/sixtp-dom-generators.h b/src/backend/xml/sixtp-dom-generators.h
index 9a8b3b7..09b14b5 100644
--- a/src/backend/xml/sixtp-dom-generators.h
+++ b/src/backend/xml/sixtp-dom-generators.h
@@ -24,6 +24,10 @@
 #ifndef SIXTP_DOM_GENERATORS_H
 #define SIXTP_DOM_GENERATORS_H
 
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 #include <glib.h>
 
 #include "gnc-xml-helper.h"
@@ -49,4 +53,7 @@ xmlNodePtr recurrence_to_dom_tree(const gchar *tag, const Recurrence *r);
 
 gchar* double_to_string(double value);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* _SIXTP_DOM_GENERATORS_H_ */
diff --git a/src/backend/xml/sixtp-dom-parsers.c b/src/backend/xml/sixtp-dom-parsers.cpp
similarity index 99%
rename from src/backend/xml/sixtp-dom-parsers.c
rename to src/backend/xml/sixtp-dom-parsers.cpp
index 1eb9c03..aa00165 100644
--- a/src/backend/xml/sixtp-dom-parsers.c
+++ b/src/backend/xml/sixtp-dom-parsers.cpp
@@ -20,7 +20,8 @@
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
  *                                                                  *
  ********************************************************************/
-
+extern "C"
+{
 #include "config.h"
 
 #include <glib.h>
@@ -30,7 +31,7 @@
 #include "gnc-engine.h"
 #include "sixtp-utils.h"
 #include "sixtp-dom-parsers.h"
-
+}
 static QofLogModule log_module = GNC_MOD_IO;
 
 GncGUID*
@@ -350,7 +351,7 @@ dom_tree_to_frame_kvp_value(xmlNodePtr node)
 
 struct kvp_val_converter
 {
-    gchar *tag;
+    const gchar *tag;
     KvpValue* (*converter)(xmlNodePtr node);
 };
 
@@ -683,7 +684,8 @@ dom_tree_to_gdate(xmlNodePtr node)
                     }
                     g_free(content);
                     seen_date = TRUE;
-                    g_date_set_dmy( ret, day, month, year );
+                    g_date_set_dmy( ret, day, static_cast<GDateMonth>(month),
+                                    year );
                     if ( !g_date_valid( ret ) )
                     {
                         PWARN("invalid date");
diff --git a/src/backend/xml/sixtp-dom-parsers.h b/src/backend/xml/sixtp-dom-parsers.h
index b48f8b5..efae18a 100644
--- a/src/backend/xml/sixtp-dom-parsers.h
+++ b/src/backend/xml/sixtp-dom-parsers.h
@@ -23,6 +23,10 @@
 
 #ifndef SIXTP_DOM_PARSERS_H
 #define SIXTP_DOM_PARSERS_H
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 
 #include <glib.h>
 
@@ -88,5 +92,7 @@ gboolean dom_tree_generic_parse(xmlNodePtr node,
                                 struct dom_tree_handler *handlers,
                                 gpointer data);
 
-
+#ifdef __cplusplus
+}
+#endif
 #endif /* _SIXTP_DOM_PARSERS_H_ */
diff --git a/src/backend/xml/test/Makefile.am b/src/backend/xml/test/Makefile.am
index d399353..40c1048 100644
--- a/src/backend/xml/test/Makefile.am
+++ b/src/backend/xml/test/Makefile.am
@@ -2,8 +2,8 @@
 SUBDIRS = test-files
 
 test_date_converting_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -12,8 +12,8 @@ test_date_converting_SOURCES = \
   test-date-converting.c
 
 test_dom_converters1_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -22,8 +22,8 @@ test_dom_converters1_SOURCES = \
   test-dom-converters1.c
 
 test_kvp_frames_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -36,8 +36,8 @@ test_kvp_frames_SOURCES = \
 # and remain portable.
 
 test_load_example_account_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -60,8 +60,8 @@ test_load_example_account_SOURCES = \
   test-load-example-account.c
 
 test_string_converters_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -70,8 +70,8 @@ test_string_converters_SOURCES = \
   test-string-converters.c
 
 test_xml_account_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -93,8 +93,8 @@ test_xml_account_SOURCES = \
   test-xml-account.c
 
 test_xml_commodity_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -116,8 +116,8 @@ test_xml_commodity_SOURCES = \
   test-xml-commodity.c
 
 test_xml_pricedb_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -139,8 +139,8 @@ test_xml_pricedb_SOURCES = \
   test-xml-pricedb.c
 
 test_xml_transaction_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \
@@ -162,8 +162,8 @@ test_xml_transaction_SOURCES = \
   test-xml-transaction.c
 
 test_xml2_is_file_SOURCES = \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.c \
-  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.c \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-parsers.cpp \
+  ${top_srcdir}/src/backend/xml/sixtp-dom-generators.cpp \
   ${top_srcdir}/src/backend/xml/sixtp-utils.c \
   ${top_srcdir}/src/backend/xml/sixtp.c \
   ${top_srcdir}/src/backend/xml/sixtp-stack.c \

commit 9b3f6078fc1d69eec32c5846fd93918dd5107d1a
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jun 12 15:19:45 2015 -0700

    Abstract options handling to QofBook.
    
    Eliminates direct KVP access in app-utils, all of which centered around
    options.
    
    Beneficial side effect: With all option writes now handled by
    qof_book_set_option(), the problem of options not being committed is
    eliminated.
    
    The options system is unnecessarily complex, with much back-and-forth
    between C and Guile. It needs to be completely rewritten, but that's a
    project for its own branch.

diff --git a/src/app-utils/app-utils.scm b/src/app-utils/app-utils.scm
index cbac0df..840aed5 100644
--- a/src/app-utils/app-utils.scm
+++ b/src/app-utils/app-utils.scm
@@ -148,9 +148,8 @@
 
 (define (gnc:option-get-value category key)
   ;;Access an option directly
-    (kvp-frame-get-slot-path-gslist
-    (qof-book-get-slots (gnc-get-current-book))
-    (append gnc:*kvp-option-path* (list category key))))
+  (qof-book-get-option (gnc-get-current-book)
+                       (list category key)))
 (export gnc:option-get-value)
 ;; config-var.scm
 (export gnc:make-config-var)
diff --git a/src/app-utils/business-helpers.c b/src/app-utils/business-helpers.c
index 618e01e..fce223b 100644
--- a/src/app-utils/business-helpers.c
+++ b/src/app-utils/business-helpers.c
@@ -33,7 +33,7 @@ GncTaxTable* gnc_business_get_default_tax_table (QofBook *book, GncOwnerType own
     GNCOptionDB *odb;
 
     odb = gnc_option_db_new_for_type (GNC_ID_BOOK);
-    qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
+    qof_book_load_options (book, gnc_option_db_load, odb);
 
     switch (ownertype)
     {
diff --git a/src/app-utils/business-options.scm b/src/app-utils/business-options.scm
index dbe6ba7..3559220 100644
--- a/src/app-utils/business-options.scm
+++ b/src/app-utils/business-options.scm
@@ -73,9 +73,9 @@
 	     (gnc:error "Illegal invoice value set"))))
      (lambda () (convert-to-invoice (default-getter)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f option p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b option p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
 	 (if (and v (string? v))
 	     (begin
 	       (set! option v)
@@ -134,9 +134,9 @@
 	     (gnc:error "Illegal customer value set"))))
      (lambda () (convert-to-customer (default-getter)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f option p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b option p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
 	 (if (and v (string? v))
 	     (begin
 	       (set! option v)
@@ -195,9 +195,9 @@
 	     (gnc:error "Illegal vendor value set"))))
      (lambda () (convert-to-vendor (default-getter)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f option p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b option p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
 	 (if (and v (string? v))
 	     (begin
 	       (set! option v)
@@ -256,9 +256,9 @@
 	     (gnc:error "Illegal employee value set"))))
      (lambda () (convert-to-employee (default-getter)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f option p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b option p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
 	 (if (and v (string? v))
 	     (begin
 	       (set! option v)
@@ -355,14 +355,14 @@
 	       (gnc:error "Illegal owner value set"))))
        (lambda () (convert-to-owner (default-getter)))
        (gnc:restore-form-generator value->string)
-       (lambda (f p)
-	 (kvp-frame-set-slot-path-gslist f (symbol->string (car option))
+       (lambda (b p)
+	 (qof-book-set-option b (symbol->string (car option))
 				      (append p '("type")))
-	 (kvp-frame-set-slot-path-gslist f (cdr option)
+	 (qof-book-set-option b (cdr option)
 				      (append p '("value"))))
-       (lambda (f p)
-	 (let ((t (kvp-frame-get-slot-path-gslist f (append p '("type"))))
-	       (v (kvp-frame-get-slot-path-gslist f (append p '("value")))))
+       (lambda (b p)
+	 (let ((t (qof-book-get-option b (append p '("type"))))
+	       (v (qof-book-get-option b (append p '("value")))))
 	   (if (and t v (string? t) (string? v))
 	       (begin
 		 (set! option (cons (string->symbol t) v))
@@ -422,9 +422,9 @@
 	     (gnc:error "Illegal taxtable value set"))))
      (lambda () (convert-to-taxtable (default-getter)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f option p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b option p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
 	 (if (and v (string? v))
 	     (begin
 	       (set! option v)
@@ -450,9 +450,9 @@
          documentation-string
          default-value)
   (let ((option (gnc:make-number-range-option section name sort-tag documentation-string default-value 0 999999999 0 1)))
-     (gnc:set-option-scm->kvp option (lambda (f p) (kvp-frame-set-slot-path-gslist f (inexact->exact ((gnc:option-getter option))) (list "counters" key))))
-     (gnc:set-option-kvp->scm option (lambda (f p)
-                               (let ((v (kvp-frame-get-slot-path-gslist f (list "counters" key))))
+     (gnc:set-option-scm->kvp option (lambda (b p) (qof-book-set-option b (inexact->exact ((gnc:option-getter option))) (list "counters" key))))
+     (gnc:set-option-kvp->scm option (lambda (b p)
+                               (let ((v (qof-book-get-option b (list "counters" key))))
                                  (if (and v (integer? v))
                                      ((gnc:option-setter option) v)))))
      option))
@@ -467,9 +467,9 @@
          documentation-string
          default-value)
   (let ((option (gnc:make-string-option section name sort-tag documentation-string default-value)))
-     (gnc:set-option-scm->kvp option (lambda (f p) (kvp-frame-set-slot-path-gslist f ((gnc:option-getter option)) (list "counter_formats" key))))
-     (gnc:set-option-kvp->scm option (lambda (f p)
-                               (let ((v (kvp-frame-get-slot-path-gslist f (list "counter_formats" key))))
+     (gnc:set-option-scm->kvp option (lambda (b p) (qof-book-set-option b ((gnc:option-getter option)) (list "counter_formats" key))))
+     (gnc:set-option-kvp->scm option (lambda (b p)
+                               (let ((v (qof-book-get-option b (list "counter_formats" key))))
                                  (if (and v (string? v))
                                      ((gnc:option-setter option) v)))))
      option))
diff --git a/src/app-utils/option-util.c b/src/app-utils/option-util.c
index ee719bd..d3ee994 100644
--- a/src/app-utils/option-util.c
+++ b/src/app-utils/option-util.c
@@ -313,13 +313,12 @@ gnc_option_db_new_for_type(QofIdType id_type)
 }
 
 void
-gnc_option_db_load_from_kvp(GNCOptionDB* odb, KvpFrame *slots)
+gnc_option_db_load(GNCOptionDB* odb, QofBook *book)
 {
     static SCM kvp_to_scm = SCM_UNDEFINED;
-    static SCM kvp_option_path = SCM_UNDEFINED;
-    SCM scm_slots;
+    SCM scm_book;
 
-    if (!odb || !slots) return;
+    if (!odb || !book) return;
 
     if (kvp_to_scm == SCM_UNDEFINED)
     {
@@ -332,29 +331,19 @@ gnc_option_db_load_from_kvp(GNCOptionDB* odb, KvpFrame *slots)
         }
     }
 
-    if (kvp_option_path == SCM_UNDEFINED)
-    {
-        kvp_option_path = scm_c_eval_string("gnc:*kvp-option-path*");
-        if (kvp_option_path == SCM_UNDEFINED)
-        {
-            PERR ("can't find the option path");
-            return;
-        }
-    }
-    scm_slots = SWIG_NewPointerObj(slots, SWIG_TypeQuery("_p_KvpFrame"), 0);
+    scm_book = SWIG_NewPointerObj(book, SWIG_TypeQuery("_p_QofBook"), 0);
 
-    scm_call_3 (kvp_to_scm, odb->guile_options, scm_slots, kvp_option_path);
+    scm_call_2 (kvp_to_scm, odb->guile_options, scm_book);
 }
 
 void
-gnc_option_db_save_to_kvp(GNCOptionDB* odb, KvpFrame *slots, gboolean clear_kvp)
+gnc_option_db_save(GNCOptionDB* odb, QofBook *book, gboolean clear_all)
 {
     static SCM scm_to_kvp = SCM_UNDEFINED;
-    static SCM kvp_option_path = SCM_UNDEFINED;
-    SCM scm_slots;
-    SCM scm_clear_kvp;
+    SCM scm_book;
+    SCM scm_clear_all;
 
-    if (!odb || !slots) return;
+    if (!odb || !book) return;
 
     if (scm_to_kvp == SCM_UNDEFINED)
     {
@@ -367,19 +356,10 @@ gnc_option_db_save_to_kvp(GNCOptionDB* odb, KvpFrame *slots, gboolean clear_kvp)
         }
     }
 
-    if (kvp_option_path == SCM_UNDEFINED)
-    {
-        kvp_option_path = scm_c_eval_string("gnc:*kvp-option-path*");
-        if (kvp_option_path == SCM_UNDEFINED)
-        {
-            PERR ("can't find the option path");
-            return;
-        }
-    }
-    scm_slots = SWIG_NewPointerObj(slots, SWIG_TypeQuery("_p_KvpFrame"), 0);
-    scm_clear_kvp = scm_from_bool (clear_kvp);
+    scm_book = SWIG_NewPointerObj(book, SWIG_TypeQuery("_p_QofBook"), 0);
+    scm_clear_all = scm_from_bool (clear_all);
 
-    scm_call_4 (scm_to_kvp, odb->guile_options, scm_slots, kvp_option_path, scm_clear_kvp);
+    scm_call_3 (scm_to_kvp, odb->guile_options, scm_book, scm_clear_all);
 }
 /********************************************************************\
  * gnc_option_db_destroy                                            *
diff --git a/src/app-utils/option-util.h b/src/app-utils/option-util.h
index 13ad3fb..996223d 100644
--- a/src/app-utils/option-util.h
+++ b/src/app-utils/option-util.h
@@ -71,8 +71,8 @@ void          gnc_option_db_destroy(GNCOptionDB *odb);
  * in the kvp.
  */
 GNCOptionDB * gnc_option_db_new_for_type(QofIdType id_type);
-void gnc_option_db_load_from_kvp(GNCOptionDB* odb, KvpFrame *slots);
-void gnc_option_db_save_to_kvp(GNCOptionDB* odb, KvpFrame *slots, gboolean clear_kvp);
+void gnc_option_db_load(GNCOptionDB* odb, QofBook *book);
+void gnc_option_db_save(GNCOptionDB* odb, QofBook *book, gboolean clear_all);
 
 void gnc_register_kvp_option_generator(QofIdType id_type, SCM generator);
 
diff --git a/src/app-utils/options.scm b/src/app-utils/options.scm
index 1ed4dda..6132fbe 100644
--- a/src/app-utils/options.scm
+++ b/src/app-utils/options.scm
@@ -37,8 +37,8 @@
          ;; value.
          generate-restore-form
          ;; the scm->kvp and kvp->scm functions should save and load
-         ;; the option to a kvp.  The arguments to these function will be
-         ;; a kvp-frame and a base key-path list for this option.
+         ;; the option to the book.  The arguments to these function will be
+         ;; a book and a base key-path list for this option.
          scm->kvp
          kvp->scm
          ;; Validation func should accept a value and return (#t value)
@@ -211,9 +211,9 @@
      (lambda (x) (set! value x))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f value p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b value p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
              (set! value v))))
      (lambda (x)
@@ -235,9 +235,9 @@
      (lambda (x) (set! value x))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f value p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b value p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
              (set! value v))))
      (lambda (x)
@@ -269,9 +269,9 @@
      (lambda (x) (set! value x))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)     
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f value p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b value p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
              (set! value v))))
      (lambda (x)
@@ -308,9 +308,9 @@
       (lambda (x) (set! value (currency->scm x)))
       (lambda ()  (scm->currency default-value))
       (gnc:restore-form-generator value->string)
-      (lambda (f p) (kvp-frame-set-slot-path-gslist f value p))
-      (lambda (f p)
-        (let ((v (kvp-frame-get-slot-path-gslist f p)))
+      (lambda (b p) (qof-book-set-option b value p))
+      (lambda (b p)
+        (let ((v (qof-book-get-option b p)))
           (if (and v (string? v))
               (set! value v))))
       (lambda (x) (list #t x))
@@ -369,14 +369,14 @@
 	" (gnc-get-current-book)))))"))
 
      ;; scm->kvp -- commit the change
-     ;; f -- kvp-frame;  p -- key-path
-     (lambda (f p) 
-       (kvp-frame-set-slot-path-gslist 
-	f (gncBudgetGetGUID selection-budget) p))
+     ;; b -- book;  p -- key-path
+     (lambda (b p) 
+       (qof-book-set-option 
+	b (gncBudgetGetGUID selection-budget) p))
 
      ;; kvp->scm -- get the stored value
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
 	     (begin 
 	       (set! selection-budget (gnc-budget-lookup v (gnc-get-current-book)))))))
@@ -441,12 +441,12 @@
                       (set! value (commodity->scm x))))
       (lambda () default-value)
       (gnc:restore-form-generator value->string)
-      (lambda (f p) 
-        (kvp-frame-set-slot-path-gslist f (cadr value) (append p '("ns")))
-        (kvp-frame-set-slot-path-gslist f (caddr value) (append p '("monic"))))
-      (lambda (f p)
-        (let ((ns (kvp-frame-get-slot-path-gslist f (append p '("ns"))))
-              (monic (kvp-frame-get-slot-path-gslist f (append p '("monic")))))
+      (lambda (b p) 
+        (qof-book-set-option b (cadr value) (append p '("ns")))
+        (qof-book-set-option b (caddr value) (append p '("monic"))))
+      (lambda (b p)
+        (let ((ns (qof-book-get-option b (append p '("ns"))))
+              (monic (qof-book-get-option b (append p '("monic")))))
           (if (and ns monic (string? ns) (string? monic))
               (set! value (list 'commodity-scm ns monic)))))
       (lambda (x) (list #t x))
@@ -500,14 +500,14 @@
                  (setter-function-called-cb x)))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f 
+     (lambda (b p) (qof-book-set-option b
 		    ;; As no boolean KvpValue exists, as a workaround
 		    ;; we store the string "t" for TRUE and "f" for
 		    ;; FALSE in a string KvpValue.
                     (if value "t" "f") 
                     p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
 	 ;; As no boolean KvpValue exists, as a workaround we store
 	 ;; the string "t" for TRUE and "f" for FALSE.
          (cond ((equal? v "t") (set! v #t))
@@ -582,17 +582,17 @@
            (gnc:error "Illegal date value set:" date)))
      default-getter
      (gnc:restore-form-generator value->string)
-     (lambda (f p)
-       (kvp-frame-set-slot-path-gslist f (symbol->string (car value))
+     (lambda (b p)
+       (qof-book-set-option b (symbol->string (car value))
                                        (append p '("type")))
-       (kvp-frame-set-slot-path-gslist f
+       (qof-book-set-option b
                                        (if (symbol? (cdr value))
                                            (symbol->string (cdr value))
                                            (cdr value))
                                        (append p '("value"))))
-     (lambda (f p)
-       (let ((t (kvp-frame-get-slot-path-gslist f (append p '("type"))))
-             (v (kvp-frame-get-slot-path-gslist f (append p '("value")))))
+     (lambda (b p)
+       (let ((t (qof-book-get-option b (append p '("type"))))
+             (v (qof-book-get-option b (append p '("value")))))
          (if (and t v (string? t))
              (set! value (cons (string->symbol t)
                                (if (string? v) (string->symbol v) v))))))
@@ -720,25 +720,25 @@
              (gnc:error "Illegal account list value set"))))
      (lambda () (map convert-to-account (default-getter)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p)
+     (lambda (b p)
        (define (save-acc list count)
          (if (not (null? list))
              (let ((key (string-append "acc" (gnc:value->string count))))
-               (kvp-frame-set-slot-path-gslist f (car list) (append p (list key)))
+               (qof-book-set-option b (car list) (append p (list key)))
                (save-acc (cdr list) (+ 1 count)))))
 
        (if option-set
            (begin
-             (kvp-frame-set-slot-path-gslist f (length option)
+             (qof-book-set-option b (length option)
                                              (append p '("len")))
              (save-acc option 0))))
-     (lambda (f p)
-       (let ((len (kvp-frame-get-slot-path-gslist f (append p '("len")))))
+     (lambda (b p)
+       (let ((len (qof-book-get-option b (append p '("len")))))
          (define (load-acc count)
            (if (< count len)
                (let* ((key (string-append "acc" (gnc:value->string count)))
-                      (guid (kvp-frame-get-slot-path-gslist
-                             f (append p (list key)))))
+                      (guid (qof-book-get-option
+                             b (append p (list key)))))
                  (cons guid (load-acc (+ count 1))))
                '()))
          
@@ -839,9 +839,9 @@
              (gnc:error "Illegal account value set"))))
      (lambda () (convert-to-account (get-default)))
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f option p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b option p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
              (set! option v))))
      validator
@@ -918,9 +918,9 @@
            (gnc:error "Illegal Multichoice option set")))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f (symbol->string value) p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b (symbol->string value) p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
              (set! value (string->symbol v)))))
      (lambda (x)
@@ -1004,9 +1004,9 @@
            (gnc:error "Illegal Radiobutton option set")))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f (symbol->string value) p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b (symbol->string value) p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (string? v))
              (set! value (string->symbol v)))))
      (lambda (x)
@@ -1066,21 +1066,21 @@
            (gnc:error "Illegal list option set")))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p)
+     (lambda (b p)
        (define (save-item list count)
          (if (not (null? list))
              (let ((key (string-append "item" (gnc:value->string count))))
-               (kvp-frame-set-slot-path-gslist f (car list) (append p (list key)))
+               (qof-book-set-option b (car list) (append p (list key)))
                (save-item (cdr list) (+ 1 count)))))
-       (kvp-frame-set-slot-path-gslist f (length value) (append p '("len")))
+       (qof-book-set-option b (length value) (append p '("len")))
        (save-item value 0))
-     (lambda (f p)
-       (let ((len (kvp-frame-get-slot-path-gslist f (append p '("len")))))
+     (lambda (b p)
+       (let ((len (qof-book-get-option b (append p '("len")))))
          (define (load-item count)
            (if (< count len)
                (let* ((key (string-append "item" (gnc:value->string count)))
-                      (val (kvp-frame-get-slot-path-gslist
-                            f (append p (list key)))))
+                      (val (qof-book-get-option
+                            b (append p (list key)))))
                  (cons val (load-item (+ count 1))))
                '()))
 
@@ -1118,9 +1118,9 @@
      (lambda (x) (set! value x))
      (lambda () default-value)
      (gnc:restore-form-generator value->string)
-     (lambda (f p) (kvp-frame-set-slot-path-gslist f value p))
-     (lambda (f p)
-       (let ((v (kvp-frame-get-slot-path-gslist f p)))
+     (lambda (b p) (qof-book-set-option b value p))
+     (lambda (b p)
+       (let ((v (qof-book-get-option b p)))
          (if (and v (number? v))
              (set! value v))))
      (lambda (x)
@@ -1277,19 +1277,19 @@
      (lambda (x) (set! value x))
      (lambda () (def-value))
      (gnc:restore-form-generator value->string)
+     (lambda (b p)
+       (qof-book-set-option
+        b (symbol->string (car value)) (append p '("fmt")))
+       (qof-book-set-option
+        b (symbol->string (cadr value)) (append p '("month")))
+       (qof-book-set-option
+        b (if (caddr value) 1 0) (append p '("years")))
+       (qof-book-set-option  (cadddr value) (append p '("custom"))))
      (lambda (f p)
-       (kvp-frame-set-slot-path-gslist
-        f (symbol->string (car value)) (append p '("fmt")))
-       (kvp-frame-set-slot-path-gslist
-        f (symbol->string (cadr value)) (append p '("month")))
-       (kvp-frame-set-slot-path-gslist
-        f (if (caddr value) 1 0) (append p '("years")))
-       (kvp-frame-set-slot-path-gslist f (cadddr value) (append p '("custom"))))
-     (lambda (f p)
-       (let ((fmt (kvp-frame-get-slot-path-gslist f (append p '("fmt"))))
-             (month (kvp-frame-get-slot-path-gslist f (append p '("month"))))
-             (years (kvp-frame-get-slot-path-gslist f (append p '("years"))))
-             (custom (kvp-frame-get-slot-path-gslist f (append p '("custom")))))
+       (let ((fmt (qof-book-get-option f (append p '("fmt"))))
+             (month (qof-book-get-option f (append p '("month"))))
+             (years (qof-book-get-option f (append p '("years"))))
+             (custom (qof-book-get-option f (append p '("custom")))))
          (if (and
               fmt (string? fmt)
               month (string? month)
@@ -1364,14 +1364,11 @@
          (value->string (lambda ()
                           (string-append "'" (gnc:value->string
                                                (car value)))))
-         (trading-accounts-path (list (car gnc:*kvp-option-path*)
-                                      gnc:*option-section-accounts*
+         (trading-accounts-path (list gnc:*option-section-accounts*
                                       gnc:*option-name-trading-accounts*))
-         (book-currency-path (list (car gnc:*kvp-option-path*)
-                                   gnc:*option-section-accounts*
+         (book-currency-path (list gnc:*option-section-accounts*
                                    gnc:*option-name-book-currency*))
-         (gains-policy-path (list (car gnc:*kvp-option-path*)
-                                  gnc:*option-section-accounts*
+         (gains-policy-path (list gnc:*option-section-accounts*
                                   gnc:*option-name-default-gains-policy*)))
     (gnc:make-option
      section name sort-tag 'currency-accounting
@@ -1387,26 +1384,26 @@
                                 (cons default-cap-gains-policy-value '())))
                     (cons default-radiobutton-value '())))
      (gnc:restore-form-generator value->string)
-     (lambda (f p)
+     (lambda (b p)
        (if (eq? 'book-currency (car value))
            (begin
              ;; Currency = selected currency
-             (kvp-frame-set-slot-path-gslist
-                f
+             (qof-book-set-option
+                b
                 (currency->scm (cadr value))
                 book-currency-path)
              ;; Default Gains Policy = selected policy
-             (kvp-frame-set-slot-path-gslist
-                f
+             (qof-book-set-option
+                b
                 (symbol->string (caddr value))
                 gains-policy-path))
            (if (eq? 'trading (car value))
                ;; Use Trading Accounts = "t"
-               (kvp-frame-set-slot-path-gslist f "t" trading-accounts-path))))
-     (lambda (f p)
+               (qof-book-set-option b "t" trading-accounts-path))))
+     (lambda (b p)
        (let* ((trading-option-path-kvp?
-                       (kvp-frame-get-slot-path-gslist
-                        f trading-accounts-path))
+                       (qof-book-get-option
+                        b trading-accounts-path))
               (trading? (if (and trading-option-path-kvp?
                                  (string=? "t" trading-option-path-kvp?))
                             #t
@@ -1416,11 +1413,11 @@
               (v (if trading?
                      'trading
                      (let* ((book-currency-option-path-kvp?
-                                 (kvp-frame-get-slot-path-gslist
-                                     f book-currency-path))
+                                 (qof-book-get-option
+                                     b book-currency-path))
                             (gains-policy-option-path-kvp?
-                                 (kvp-frame-get-slot-path-gslist
-                                     f gains-policy-path))
+                                 (qof-book-get-option
+                                     b gains-policy-path))
                             (book-currency?
                                (if (and book-currency-option-path-kvp?
                                         gains-policy-option-path-kvp?
@@ -1650,7 +1647,7 @@
 
     (call-with-output-string generate-forms))
 
-  (define (scm->kvp kvp-frame key-path)
+  (define (scm->kvp book)
     (options-for-each
      (lambda (option)
        (let ((value (gnc:option-value option))
@@ -1663,18 +1660,16 @@
              (let ((save-fcn (gnc:option-scm->kvp option)))
                (gnc:debug "save-fcn: " save-fcn)
                (if save-fcn
-                   (save-fcn kvp-frame (append key-path
-                                               (list section name))))))))))
+                   (save-fcn book (list section name)))))))))
 
-  (define (kvp->scm kvp-frame key-path)
+  (define (kvp->scm book)
     (options-for-each
      (lambda (option)
        (let ((section (gnc:option-section option))
              (name (gnc:option-name option))
              (load-fcn (gnc:option-kvp->scm option)))
          (if load-fcn
-             (load-fcn kvp-frame (append key-path
-                                         (list section name))))))))
+             (load-fcn book (list section name)))))))
 
   (define (register-callback section name callback)
     (let ((id last-callback-id)
@@ -1774,13 +1769,13 @@
 (define (gnc:generate-restore-forms options options-string)
   ((options 'generate-restore-forms) options-string))
 
-(define (gnc:options-scm->kvp options kvp-frame key-path clear-kvp?)
-  (if clear-kvp?
-      (gnc-kvp-frame-delete-at-path kvp-frame key-path))
-  ((options 'scm->kvp) kvp-frame key-path))
+(define (gnc:options-scm->kvp options book clear-option?)
+  (if clear-option?
+      (qof-book-options-delete book))
+  ((options 'scm->kvp) book))
 
-(define (gnc:options-kvp->scm options kvp-frame key-path)
-  ((options 'kvp->scm) kvp-frame key-path))
+(define (gnc:options-kvp->scm options book)
+  ((options 'kvp->scm) book))
 
 (define (gnc:options-clear-changes options)
   ((options 'clear-changes)))
diff --git a/src/app-utils/test/test-option-util.c b/src/app-utils/test/test-option-util.c
index 9a0a188..f1adf73 100644
--- a/src/app-utils/test/test-option-util.c
+++ b/src/app-utils/test/test-option-util.c
@@ -1,5 +1,5 @@
 /********************************************************************
- * test-option-util.c: GLib g_test test suite for Split.c.	    *
+ * test-option-util.cpp: GLib test suite for option-util.c.	    *
  * Copyright 2013 John Ralls <jralls at ceridwen.us>		    *
  *                                                                  *
  * This program is free software; you can redistribute it and/or    *
@@ -93,14 +93,14 @@ teardown (Fixture *fixture, gconstpointer pData)
 }
 
 static void
-test_option_load_from_kvp (Fixture *fixture, gconstpointer pData)
+test_option_load (Fixture *fixture, gconstpointer pData)
 {
     gchar *str = NULL;
     SCM symbol_value;
     QofBook *book = fixture->book;
     GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
 
-    qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
+    qof_book_load_options (book, gnc_option_db_load, odb);
     symbol_value = gnc_currency_accounting_option_value_get_method (
                         gnc_option_db_lookup_option (odb,
                             OPTION_SECTION_ACCOUNTS,
@@ -127,7 +127,7 @@ test_option_load_from_kvp (Fixture *fixture, gconstpointer pData)
 }
 
 static void
-test_option_load_from_kvp_book_currency (Fixture *fixture, gconstpointer pData)
+test_option_load_book_currency (Fixture *fixture, gconstpointer pData)
 {
     gchar *str = NULL;
     SCM symbol_value;
@@ -137,7 +137,7 @@ test_option_load_from_kvp_book_currency (Fixture *fixture, gconstpointer pData)
     QofBook *book = fixture->book;
     GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
 
-    qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
+    qof_book_load_options (book, gnc_option_db_load, odb);
     symbol_value = gnc_currency_accounting_option_value_get_method (
                         gnc_option_db_lookup_option (odb,
                             OPTION_SECTION_ACCOUNTS,
@@ -186,7 +186,7 @@ test_option_load_from_kvp_book_currency (Fixture *fixture, gconstpointer pData)
 }
 
 static void
-test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
+test_option_save (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = fixture->book;
     GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
@@ -203,7 +203,7 @@ test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
     g_assert (gnc_option_db_set_number_option (odb, OPTION_SECTION_ACCOUNTS,
 					       OPTION_NAME_AUTO_READONLY_DAYS,
 					       17));
-    qof_book_save_options (book, gnc_option_db_save_to_kvp, odb, TRUE);
+    qof_book_save_options (book, gnc_option_db_save, odb, TRUE);
     g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Use Trading Accounts"), == , "t");
     g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Use Split Action Field for Number"), == , "t");
     g_assert_cmpstr (kvp_frame_get_string (slots, "options/Business/Company Name"), ==, "Bogus Company");
@@ -213,7 +213,7 @@ test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
 }
 
 static void
-test_option_save_to_kvp_book_currency (Fixture *fixture, gconstpointer pData)
+test_option_save_book_currency (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = fixture->book;
     GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
@@ -224,9 +224,9 @@ test_option_save_to_kvp_book_currency (Fixture *fixture, gconstpointer pData)
 						scm_cons (scm_from_locale_symbol("book-currency"),
                         scm_cons (scm_from_utf8_string("GTQ"),
                         scm_cons (scm_from_locale_symbol("fifo"), SCM_EOL)))));
-    qof_book_save_options (book, gnc_option_db_save_to_kvp, odb, TRUE);
-    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Book Currency"), == , "GTQ");
-    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Default Gains Policy"), == , "fifo");
+    qof_book_save_options (book, gnc_option_db_save, odb, TRUE);
+    g_assert_cmpstr (kvp_frame_get_string(slots, "options/Accounts/Book Currency"), == , "GTQ");
+    g_assert_cmpstr (kvp_frame_get_string(slots, "options/Accounts/Default Gains Policy"), == , "fifo");
 
     gnc_option_db_destroy (odb);
 }
@@ -234,9 +234,8 @@ test_option_save_to_kvp_book_currency (Fixture *fixture, gconstpointer pData)
 void
 test_suite_option_util (void)
 {
-    GNC_TEST_ADD (suitename, "Option DB Load from KVP", Fixture, NULL, setup_kvp, test_option_load_from_kvp, teardown);
-    GNC_TEST_ADD (suitename, "Option DB Load from KVP - Book Currency", Fixture, NULL, setup_kvp_book_currency, test_option_load_from_kvp_book_currency, teardown);
-    GNC_TEST_ADD (suitename, "Option DB Save to KVP", Fixture, NULL, setup, test_option_save_to_kvp, teardown);
-    GNC_TEST_ADD (suitename, "Option DB Save to KVP - Book Currency", Fixture, NULL, setup, test_option_save_to_kvp_book_currency, teardown);
-
+    GNC_TEST_ADD (suitename, "Option DB Load", Fixture, NULL, setup_kvp, test_option_load, teardown);
+    GNC_TEST_ADD (suitename, "Option DB Load - Book Currency", Fixture, NULL, setup_kvp_book_currency, test_option_load_book_currency, teardown);
+    GNC_TEST_ADD (suitename, "Option DB Save", Fixture, NULL, setup, test_option_save, teardown);
+    GNC_TEST_ADD (suitename, "Option DB Save - Book Currency", Fixture, NULL, setup, test_option_save_book_currency, teardown);
 }
diff --git a/src/engine/engine.i b/src/engine/engine.i
index 99d1c5a..5a8637c 100644
--- a/src/engine/engine.i
+++ b/src/engine/engine.i
@@ -142,18 +142,6 @@ functions. */
 
 QofSession * qof_session_new (void);
 QofBook * qof_session_get_book (QofSession *session);
-/* This horror is to permit the scheme options in
- * src/app-utils/options.scm to read and write the book's KVP (another
- * horror) directly. It should be refactored into book functions that
- * handle the KVP access.
- */
-%inline {
-  KvpFrame *qof_book_get_slots (QofBook *book);
-  extern KvpFrame *qof_instance_get_slots (QofInstance*);
-  KvpFrame *qof_book_get_slots (QofBook *book) {
-       return qof_instance_get_slots (QOF_INSTANCE (book));
-  }
-}
 // TODO: Unroll/remove
 const char *qof_session_get_url (QofSession *session);
 
@@ -238,10 +226,9 @@ Account * gnc_book_get_template_root(QofBook *book);
 %typemap(out) KvpValue * " $result = gnc_kvp_value_ptr_to_scm($1); "
 %typemap(in) GSList *key_path " $1 = gnc_scm_to_gslist_string($input);"
 
-void gnc_kvp_frame_delete_at_path(KvpFrame *frame, GSList *key_path);
-void kvp_frame_set_slot_path_gslist(
-   KvpFrame *frame, KvpValue *new_value, GSList *key_path);
-KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, GSList *key_path);
+void qof_book_options_delete (QofBook *book);
+void qof_book_set_option (QofBook *book, KvpValue *new_value, GSList *key_path);
+KvpValue* qof_book_get_option (QofBook *book, GSList *key_path);
 
 %clear GSList *key_path;
 
diff --git a/src/engine/kvp-scm.c b/src/engine/kvp-scm.c
index 52522a3..1e51f34 100644
--- a/src/engine/kvp-scm.c
+++ b/src/engine/kvp-scm.c
@@ -112,9 +112,3 @@ gnc_kvp_value_ptr_to_scm(KvpValue* val)
     }
     return SCM_BOOL_F;
 }
-
-void
-gnc_kvp_frame_delete_at_path (KvpFrame *frame, GSList *key_path)
-{
-    kvp_frame_set_slot_path_gslist (frame, NULL, key_path);
-}
diff --git a/src/engine/kvp-scm.h b/src/engine/kvp-scm.h
index 8085c6d..4bca011 100644
--- a/src/engine/kvp-scm.h
+++ b/src/engine/kvp-scm.h
@@ -6,7 +6,6 @@
 
 KvpValue* gnc_scm_to_kvp_value_ptr(SCM kvpval);
 SCM gnc_kvp_value_ptr_to_scm(KvpValue* val);
-void gnc_kvp_frame_delete_at_path(KvpFrame *frame, GSList *key_path);
 
 #endif /* KVP_SCM_H */
 
diff --git a/src/gnome-utils/gnc-main-window.c b/src/gnome-utils/gnc-main-window.c
index c77637d..3dd8b4c 100644
--- a/src/gnome-utils/gnc-main-window.c
+++ b/src/gnome-utils/gnc-main-window.c
@@ -3950,7 +3950,7 @@ gnc_book_options_dialog_apply_cb(GNCOptionWin * optionwin,
 
     gnc_option_db_commit (options);
     qof_book_begin_edit (book);
-    qof_book_save_options (book, gnc_option_db_save_to_kvp, options, TRUE);
+    qof_book_save_options (book, gnc_option_db_save, options, TRUE);
     use_split_action_for_num_after =
         qof_book_use_split_action_for_num_field (gnc_get_current_book ());
     if (use_split_action_for_num_before != use_split_action_for_num_after)
@@ -3976,7 +3976,7 @@ gnc_book_options_dialog_cb (gboolean modal, gchar *title)
     GNCOptionWin *optionwin;
 
     options = gnc_option_db_new_for_type (QOF_ID_BOOK);
-    qof_book_load_options (book, gnc_option_db_load_from_kvp, options);
+    qof_book_load_options (book, gnc_option_db_load, options);
     gnc_option_db_clean (options);
 
     optionwin = gnc_options_dialog_new_modal (modal,
diff --git a/src/gnome-utils/gnome-utils.scm b/src/gnome-utils/gnome-utils.scm
index ec55c07..988b8ad 100644
--- a/src/gnome-utils/gnome-utils.scm
+++ b/src/gnome-utils/gnome-utils.scm
@@ -23,7 +23,5 @@
 (export gnc:make-menu)
 (export gnc:make-separator)
 
-(export gnc:kvp-option-dialog)
-
 (load-from-path "gnc-menu-extensions")
 
diff --git a/src/gnome/assistant-hierarchy.c b/src/gnome/assistant-hierarchy.c
index d45941d..cacbf21 100644
--- a/src/gnome/assistant-hierarchy.c
+++ b/src/gnome/assistant-hierarchy.c
@@ -1021,7 +1021,7 @@ finish_book_options_helper(GNCOptionWin * optionwin,
     if (!options) return;
 
     gnc_option_db_commit (options);
-    qof_book_save_options (book, gnc_option_db_save_to_kvp, options, TRUE);
+    qof_book_save_options (book, gnc_option_db_save, options, TRUE);
     use_split_action_for_num_after =
         qof_book_use_split_action_for_num_field (book);
     if (use_split_action_for_num_before != use_split_action_for_num_after)
@@ -1127,7 +1127,7 @@ assistant_instert_book_options_page (hierarchy_data *data)
 
     data->options = gnc_option_db_new_for_type (QOF_ID_BOOK);
     qof_book_load_options (gnc_get_current_book (),
-			   gnc_option_db_load_from_kvp, data->options);
+			   gnc_option_db_load, data->options);
     gnc_option_db_clean (data->options);
 
     data->optionwin = gnc_options_dialog_new_modal (TRUE, _("New Book Options"));
diff --git a/src/libqof/qof/qofbook.cpp b/src/libqof/qof/qofbook.cpp
index 8d7f7db..2aa09b1 100644
--- a/src/libqof/qof/qofbook.cpp
+++ b/src/libqof/qof/qofbook.cpp
@@ -1096,17 +1096,20 @@ qof_book_set_feature (QofBook *book, const gchar *key, const gchar *descr)
 void
 qof_book_load_options (QofBook *book, GNCOptionLoad load_cb, GNCOptionDB *odb)
 {
-    KvpFrame *slots = qof_instance_get_slots (QOF_INSTANCE (book));
-    load_cb (odb, slots);
+    load_cb (odb, book);
 }
 
 void
 qof_book_save_options (QofBook *book, GNCOptionSave save_cb,
 		       GNCOptionDB* odb, gboolean clear)
 {
-    KvpFrame *slots = qof_instance_get_slots (QOF_INSTANCE (book));
-    save_cb (odb, slots, clear);
-    qof_instance_set_dirty (QOF_INSTANCE (book));
+    /* Wrap this in begin/commit so that it commits only once instead of doing
+     * so for every option. Qof_book_set_option will take care of dirtying the
+     * book.
+     */
+    qof_book_begin_edit (book);
+    save_cb (odb, book, clear);
+    qof_book_commit_edit (book);
 }
 
 static void noop (QofInstance *inst) {}
@@ -1118,6 +1121,32 @@ qof_book_commit_edit(QofBook *book)
     qof_commit_edit_part2 (&book->inst, commit_err, noop, noop/*lot_free*/);
 }
 
+void
+qof_book_set_option (QofBook *book, KvpValue *value, GSList *path)
+{
+    KvpFrame *root = qof_instance_get_slots (QOF_INSTANCE (book));
+    KvpFrame *options = kvp_frame_get_frame_slash (root, KVP_OPTION_PATH);
+    qof_book_begin_edit (book);
+    kvp_frame_set_slot_path_gslist (options, value, path);
+    qof_instance_set_dirty (QOF_INSTANCE (book));
+    qof_book_commit_edit (book);
+}
+
+KvpValue*
+qof_book_get_option (QofBook *book, GSList *path)
+{
+    KvpFrame *root = qof_instance_get_slots(QOF_INSTANCE (book));
+    KvpFrame *options = kvp_frame_get_frame(root, KVP_OPTION_PATH);
+    return kvp_frame_get_slot_path_gslist(options, path);
+}
+
+void
+qof_book_options_delete (QofBook *book)
+{
+    KvpFrame *root = qof_instance_get_slots(QOF_INSTANCE (book));
+    kvp_frame_delete (kvp_frame_get_frame(root, KVP_OPTION_PATH));
+}
+
 /* QofObject function implementation and registration */
 gboolean qof_book_register (void)
 {
diff --git a/src/libqof/qof/qofbook.h b/src/libqof/qof/qofbook.h
index 776a441..a51bad7 100644
--- a/src/libqof/qof/qofbook.h
+++ b/src/libqof/qof/qofbook.h
@@ -71,8 +71,8 @@ typedef void (*QofBookDirtyCB) (QofBook *, gboolean dirty, gpointer user_data);
 
 typedef struct gnc_option_db GNCOptionDB;
 
-typedef void (*GNCOptionSave) (GNCOptionDB*, KvpFrame*, gboolean);
-typedef void (*GNCOptionLoad) (GNCOptionDB*, KvpFrame*);
+typedef void (*GNCOptionSave) (GNCOptionDB*, QofBook*, gboolean);
+typedef void (*GNCOptionLoad) (GNCOptionDB*, QofBook*);
 
 /* Book structure */
 struct _QofBook
@@ -353,13 +353,47 @@ void qof_book_set_feature (QofBook *book, const gchar *key, const gchar *descr);
 void qof_book_begin_edit(QofBook *book);
 void qof_book_commit_edit(QofBook *book);
 
-/* Access functions for loading and saving the file options */
+/* Access functions for options. */
+/** Load a GNCOptionsDB from KVP data.
+ * @param book: The book.
+ * @param load_cb: A callback function that does the loading.
+ * @param odb: The GNCOptionDB to load.
+ */
 void qof_book_load_options (QofBook *book, GNCOptionLoad load_cb,
 			    GNCOptionDB *odb);
-void
-qof_book_save_options (QofBook *book, GNCOptionSave save_cb,
-		       GNCOptionDB* odb, gboolean clear);
+/** Save a GNCOptionsDB back to the book's KVP.
+ * @param book: The book.
+ * @param save_cb: A callback function that does the saving.
+ * @param odb: The GNCOptionsDB to save from.
+ * @param clear: Should the GNCOptionsDB be emptied after the save?
+ */
+void qof_book_save_options (QofBook *book, GNCOptionSave save_cb,
+                            GNCOptionDB* odb, gboolean clear);
+/** Save a single option value.
+ * Used from Scheme, the KvpValue<-->SCM translation is handled by the functions
+ * in kvp-scm.c and automated by SWIG. The starting element is set as
+ * KVP_OPTION_PATH in qofbookslots.h.
+ * @param book: The book.
+ * @param value: The KvpValue to store.
+ * @param path: A GSList of keys which form a path under KVP_OPTION_PATH.
+ */
+void qof_book_set_option (QofBook *book, KvpValue *value, GSList *path);
+
+/** Read a single option value.
+ * Used from Scheme, the KvpValue<-->SCM translation is handled by the functions
+ * in kvp-scm.c and automated by SWIG. The starting element is set as
+ * KVP_OPTION_PATH in qofbookslots.h.
+ * @param book: The book.
+ * @param path: A GSList of keys which form a path under KVP_OPTION_PATH.
+ */
+KvpValue* qof_book_get_option (QofBook *book, GSList *path);
 
+/** Delete the options.
+ * Primarily used from Scheme to clear out the options before saving a new set.
+ * @param book: The book.
+ * @param list: A GList of keys which from a path under KVP_OPTION_PATH.
+ */
+void qof_book_options_delete (QofBook *book);
 
 /** deprecated */
 #define qof_book_get_guid(X) qof_entity_get_guid (QOF_INSTANCE(X))

commit fa22188549d2f60cfae030215ec1f279580d3299
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri Jun 12 12:22:43 2015 -0700

    Remove gnc:kvp-option-dialog, make gnc_make_kvp_options static.
    
    gnc:kvp-option-dialog is unused, was only external user of gnc_make_kvp_options.

diff --git a/src/app-utils/app-utils.i b/src/app-utils/app-utils.i
index 7f6506d..d3accbf 100644
--- a/src/app-utils/app-utils.i
+++ b/src/app-utils/app-utils.i
@@ -106,7 +106,6 @@ gnc_numeric gnc_convert_from_euro(const gnc_commodity * currency,
 time64 gnc_accounting_period_fiscal_start(void);
 time64 gnc_accounting_period_fiscal_end(void);
 
-SCM gnc_make_kvp_options(QofIdType id_type);
 void gnc_register_kvp_option_generator(QofIdType id_type, SCM generator);
 
 %typemap(in) GList * {
diff --git a/src/app-utils/option-util.c b/src/app-utils/option-util.c
index 829749e..ee719bd 100644
--- a/src/app-utils/option-util.c
+++ b/src/app-utils/option-util.c
@@ -269,6 +269,39 @@ gnc_option_db_find (SCM guile_options)
 }
 
 /* Create an option DB for a particular data type */
+/* For now, this is global, just like when it was in guile.
+   But, it should be make per-book. */
+static GHashTable *kvp_registry = NULL;
+
+static void
+init_table(void)
+{
+    if (!kvp_registry)
+        kvp_registry = g_hash_table_new(g_str_hash, g_str_equal);
+}
+
+
+/*  create a new options object for the requested type */
+static SCM
+gnc_make_kvp_options(QofIdType id_type)
+{
+    GList *list, *p;
+    SCM gnc_new_options = SCM_UNDEFINED;
+    SCM options = SCM_UNDEFINED;
+
+    init_table();
+    list = g_hash_table_lookup(kvp_registry, id_type);
+    gnc_new_options = scm_c_eval_string("gnc:new-options");
+    options = scm_call_0(gnc_new_options);
+
+    for (p = list; p; p = p->next)
+    {
+        SCM generator = p->data;
+        scm_call_1(generator, options);
+    }
+    return options;
+}
+
 GNCOptionDB *
 gnc_option_db_new_for_type(QofIdType id_type)
 {
@@ -2928,17 +2961,6 @@ SCM gnc_dateformat_option_set_value(QofDateFormat format, GNCDateMonthFormat mon
     return value;
 }
 
-/* For now, this is global, just like when it was in guile.
-   But, it should be make per-book. */
-static GHashTable *kvp_registry = NULL;
-
-static void
-init_table(void)
-{
-    if (!kvp_registry)
-        kvp_registry = g_hash_table_new(g_str_hash, g_str_equal);
-}
-
 /*
  * the generator should be a procedure that takes one argument,
  * an options object.  The procedure should fill in the options with
@@ -2954,25 +2976,3 @@ gnc_register_kvp_option_generator(QofIdType id_type, SCM generator)
     g_hash_table_insert(kvp_registry, (gpointer) id_type, list);
     scm_gc_protect_object(generator);
 }
-
-
-/*  create a new options object for the requested type */
-SCM
-gnc_make_kvp_options(QofIdType id_type)
-{
-    GList *list, *p;
-    SCM gnc_new_options = SCM_UNDEFINED;
-    SCM options = SCM_UNDEFINED;
-
-    init_table();
-    list = g_hash_table_lookup(kvp_registry, id_type);
-    gnc_new_options = scm_c_eval_string("gnc:new-options");
-    options = scm_call_0(gnc_new_options);
-
-    for (p = list; p; p = p->next)
-    {
-        SCM generator = p->data;
-        scm_call_1(generator, options);
-    }
-    return options;
-}
diff --git a/src/app-utils/option-util.h b/src/app-utils/option-util.h
index 5b16c7d..13ad3fb 100644
--- a/src/app-utils/option-util.h
+++ b/src/app-utils/option-util.h
@@ -75,7 +75,6 @@ void gnc_option_db_load_from_kvp(GNCOptionDB* odb, KvpFrame *slots);
 void gnc_option_db_save_to_kvp(GNCOptionDB* odb, KvpFrame *slots, gboolean clear_kvp);
 
 void gnc_register_kvp_option_generator(QofIdType id_type, SCM generator);
-SCM gnc_make_kvp_options(QofIdType id_type);
 
 void gnc_option_db_set_ui_callbacks (GNCOptionDB *odb,
                                      GNCOptionGetUIValue get_ui_value,
diff --git a/src/gnome-utils/gnome-utils.scm b/src/gnome-utils/gnome-utils.scm
index 8b3968f..ec55c07 100644
--- a/src/gnome-utils/gnome-utils.scm
+++ b/src/gnome-utils/gnome-utils.scm
@@ -27,19 +27,3 @@
 
 (load-from-path "gnc-menu-extensions")
 
-(define (gnc:kvp-option-dialog id-type slots title changed_cb)
-  (let* ((options (gnc-make-kvp-options id-type))
-	 (optiondb (gnc-option-db-new options))
-	 (optionwin (gnc-options-dialog-new title)))
-
-    (define (apply-cb)
-      (gnc:options-scm->kvp options slots gnc:*kvp-option-path* #t)
-      (if changed_cb (changed_cb)))
-
-    (define (close-cb)
-      (gnc-options-dialog-destroy optionwin)
-      (gnc-option-db-destroy optiondb))
-
-    (gnc:options-kvp->scm options slots gnc:*kvp-option-path*)
-    (gnc-options-dialog-set-scm-callbacks optionwin apply-cb close-cb)
-    (gnc-options-dialog-build-contents optionwin optiondb)))

commit cb9d8c93b7a8e2cbe2c2853ce254d07d2d992681
Author: John Ralls <jralls at ceridwen.us>
Date:   Wed Jun 10 13:52:44 2015 -0700

    Use gnc:company-info instead of directly accessing the KVP in reports.

diff --git a/src/app-utils/app-utils.scm b/src/app-utils/app-utils.scm
index ccd78f9..cbac0df 100644
--- a/src/app-utils/app-utils.scm
+++ b/src/app-utils/app-utils.scm
@@ -146,6 +146,12 @@
 (export gnc:send-options)
 (export gnc:save-options)
 
+(define (gnc:option-get-value category key)
+  ;;Access an option directly
+    (kvp-frame-get-slot-path-gslist
+    (qof-book-get-slots (gnc-get-current-book))
+    (append gnc:*kvp-option-path* (list category key))))
+(export gnc:option-get-value)
 ;; config-var.scm
 (export gnc:make-config-var)
 (export gnc:config-var-description-get)
@@ -318,9 +324,7 @@
 
 (define (gnc:company-info key)
   ;; Access company info from key-value pairs for current book
-  (kvp-frame-get-slot-path-gslist
-    (qof-book-get-slots (gnc-get-current-book))
-    (append gnc:*kvp-option-path* (list gnc:*business-label* key))))
+ (gnc:option-get-value gnc:*business-label* key))
 
 (export gnc:*business-label* gnc:*company-name*  gnc:*company-addy* 
         gnc:*company-id*     gnc:*company-phone* gnc:*company-fax* 
diff --git a/src/report/business-reports/balsheet-eg.scm b/src/report/business-reports/balsheet-eg.scm
index bc30d4a..4ad4f9b 100644
--- a/src/report/business-reports/balsheet-eg.scm
+++ b/src/report/business-reports/balsheet-eg.scm
@@ -117,12 +117,6 @@
       '()
       (cadr l))))
 
-(define (gnc:company-info key) ; this should be in business-utils.scm soon
-  ;; Access company info from key-value pairs for current book
-  (kvp-frame-get-slot-path-gslist
-    (qof-book-get-slots (gnc-get-current-book))
-    (append gnc:*kvp-option-path* (list gnc:*business-label* key))))
-
 (define (add-to-cc cc com num neg?)
   ; add a numeric and commodity to a commodity-collector,
   ; changing sign if required
diff --git a/src/report/business-reports/customer-summary.scm b/src/report/business-reports/customer-summary.scm
index 00592c1..fcd1136 100644
--- a/src/report/business-reports/customer-summary.scm
+++ b/src/report/business-reports/customer-summary.scm
@@ -614,13 +614,8 @@
 (define (make-myname-table book)
   (let* ((table (gnc:make-html-table))
          (table-outer (gnc:make-html-table))
-         (slots (qof-book-get-slots book))
-         (name (kvp-frame-get-slot-path-gslist
-                slots (append gnc:*kvp-option-path*
-                              (list gnc:*business-label* gnc:*company-name*))))
-         (addy (kvp-frame-get-slot-path-gslist
-                slots (append gnc:*kvp-option-path*
-                              (list gnc:*business-label* gnc:*company-addy*)))))
+         (name (gnc:company-info gnc:*company-name*))
+         (addy (gnc:company-info gnc:*company-addy*)))
 
     (gnc:html-table-set-style!
      table "table"
diff --git a/src/report/business-reports/easy-invoice.scm b/src/report/business-reports/easy-invoice.scm
index 709f863..eacbd0f 100644
--- a/src/report/business-reports/easy-invoice.scm
+++ b/src/report/business-reports/easy-invoice.scm
@@ -631,13 +631,8 @@
 
 (define (make-myname-table book)
   (let* ((table (gnc:make-html-table))
-	 (slots (qof-book-get-slots book))
-	 (name (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-name*))))
-	 (addy (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-addy*)))))
+	 (name (gnc:company-info gnc:*company-name*))
+	 (addy (gnc:company-info gnc:*company-addy*)))
 
     (gnc:html-table-set-style!
      table "table"
@@ -748,11 +743,7 @@
         (add-html! document "<td align='right'>")
 
         (if (opt-val "Display" "My Company ID")
-          (let* ((book (gncInvoiceGetBook invoice))
-                 (slots (qof-book-get-slots book))
-	         (taxid (kvp-frame-get-slot-path-gslist
-		    slots (append gnc:*kvp-option-path*
-		                  (list gnc:*business-label* gnc:*company-id*)))))
+          (let* ((taxid (gnc:company-info gnc:*company-id*)))
                  (if (and taxid (> (string-length taxid) 0))
                    (begin
                      (add-html! document taxid)
diff --git a/src/report/business-reports/fancy-invoice.scm b/src/report/business-reports/fancy-invoice.scm
index b7c1af0..db726a9 100644
--- a/src/report/business-reports/fancy-invoice.scm
+++ b/src/report/business-reports/fancy-invoice.scm
@@ -688,28 +688,13 @@
 
 (define (make-myname-table book date-format title)
   (let* ((table (gnc:make-html-table))
-	 (slots (qof-book-get-slots book))
-	 (name (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-name*))))
-;;	 (contact (kvp-frame-get-slot-path-gslist
-;;		slots (append gnc:*kvp-option-path*
-;;			      (list gnc:*business-label* gnc:*company-contact*))))
-	 (addy (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-addy*))))
-	 (id (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-id*))))
-	 (phone (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-phone*))))
-	 (fax (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-fax*))))
-	 (url (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-url*))))
+	 (name (gnc:company-info gnc:*company-name*))
+;;	 (contact (gnc:company-info gnc:*company-contact*))
+	 (addy (gnc:company-info gnc:*company-addy*))
+	 (id (gnc:company-info gnc:*company-id*))
+	 (phone (gnc:company-info gnc:*company-phone*))
+	 (fax (gnc:company-info gnc:*company-fax*))
+	 (url (gnc:company-info gnc:*company-url*))
 	 (invoice-cell (gnc:make-html-table-cell))
 	 (name-cell (gnc:make-html-table-cell))
 
@@ -830,9 +815,7 @@
 
 
     (if (not (null? invoice))
-	(let* ((book (gncInvoiceGetBook invoice))
-	      (slots (qof-book-get-slots book))
-	      (date-object #f)
+	(let* ((date-object #f)
 	      (helper-table (gnc:make-html-table))
 	      (title (title-string default-title custom-title)))
 	  (set! table (make-entry-table invoice
@@ -964,10 +947,7 @@
 	  (make-break! document)
 
 	  (if (opt-val "Display" "Payable to")
-	      (let* ((name (kvp-frame-get-slot-path-gslist
-			    slots (append gnc:*kvp-option-path*
-					  (list gnc:*business-label*
-						gnc:*company-name*))))
+	      (let* ((name (gnc:company-info gnc:*company-name*))
 		     (name-str (opt-val "Display" "Payable to string")))
 		(if (and name (> (string-length name) 0))
 		(gnc:html-document-add-object!
@@ -979,10 +959,7 @@
 	  (make-break! document)
 
 	  (if (opt-val "Display" "Company contact")
-	      (let* ((contact (kvp-frame-get-slot-path-gslist
-			       slots (append gnc:*kvp-option-path*
-					     (list gnc:*business-label*
-						   gnc:*company-contact*))))
+	      (let* ((contact (gnc:company-info gnc:*company-contact*))
 		     (contact-str (opt-val "Display" "Company contact string")))
 		(if (and contact (> (string-length contact) 0))
 	        (gnc:html-document-add-object!
diff --git a/src/report/business-reports/invoice.scm b/src/report/business-reports/invoice.scm
index 2baf6bb..d9add63 100644
--- a/src/report/business-reports/invoice.scm
+++ b/src/report/business-reports/invoice.scm
@@ -607,13 +607,8 @@
 
 (define (make-myname-table book date-format)
   (let* ((table (gnc:make-html-table))
-	 (slots (qof-book-get-slots book))
-	 (name (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-name*))))
-	 (addy (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-addy*)))))
+	 (name (gnc:company-info gnc:*company-name*))
+	 (addy (gnc:company-info gnc:*company-addy*)))
 
     (gnc:html-table-set-style!
      table "table"
diff --git a/src/report/business-reports/job-report.scm b/src/report/business-reports/job-report.scm
index eb5f158..61328af 100644
--- a/src/report/business-reports/job-report.scm
+++ b/src/report/business-reports/job-report.scm
@@ -514,13 +514,8 @@
 
 (define (make-myname-table book date-format)
   (let* ((table (gnc:make-html-table))
-	 (slots (qof-book-get-slots book))
-	 (name (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-name*))))
-	 (addy (kvp-frame-get-slot-path-gslist
-		slots (append gnc:*kvp-option-path*
-			      (list gnc:*business-label* gnc:*company-addy*)))))
+	 (name (gnc:company-info gnc:*company-name*))
+	 (addy (gnc:company-info gnc:*company-addy*)))
 
     (gnc:html-table-set-style!
      table "table"
diff --git a/src/report/business-reports/owner-report.scm b/src/report/business-reports/owner-report.scm
index fbade6e..eeb81e7 100644
--- a/src/report/business-reports/owner-report.scm
+++ b/src/report/business-reports/owner-report.scm
@@ -719,13 +719,8 @@
 
 (define (make-myname-table book date-format)
   (let* ((table (gnc:make-html-table))
-     (slots (qof-book-get-slots book))
-     (name (kvp-frame-get-slot-path-gslist
-        slots (append gnc:*kvp-option-path*
-                  (list gnc:*business-label* gnc:*company-name*))))
-     (addy (kvp-frame-get-slot-path-gslist
-        slots (append gnc:*kvp-option-path*
-                  (list gnc:*business-label* gnc:*company-addy*)))))
+     (name (gnc:company-info gnc:*company-name*))
+     (addy (gnc:company-info gnc:*company-addy*)))
 
     (gnc:html-table-set-style!
      table "table"
diff --git a/src/report/business-reports/receipt.eguile.scm b/src/report/business-reports/receipt.eguile.scm
index 36009e1..829da36 100644
--- a/src/report/business-reports/receipt.eguile.scm
+++ b/src/report/business-reports/receipt.eguile.scm
@@ -41,15 +41,14 @@
            (currency   (gncInvoiceGetCurrency   opt-invoice))
            (entries    (gncInvoiceGetEntries    opt-invoice))
            (splits     '())
-           (slots      (qof-book-get-slots book))
-           (coyname    (coy-info slots gnc:*company-name*))
-           (coycontact (coy-info slots gnc:*company-contact*))
-           (coyaddr    (coy-info slots gnc:*company-addy*))
-           (coyid      (coy-info slots gnc:*company-id*))
-           (coyphone   (coy-info slots gnc:*company-phone*))
-           (coyfax     (coy-info slots gnc:*company-fax*))
-           (coyurl     (coy-info slots gnc:*company-url*))
-           (coyemail   (coy-info slots gnc:*company-email*))
+           (coyname    (gnc:company-info gnc:*company-name*))
+           (coycontact (gnc:company-info gnc:*company-contact*))
+           (coyaddr    (gnc:company-info gnc:*company-addy*))
+           (coyid      (gnc:company-info gnc:*company-id*))
+           (coyphone   (gnc:company-info gnc:*company-phone*))
+           (coyfax     (gnc:company-info gnc:*company-fax*))
+           (coyurl     (gnc:company-info gnc:*company-url*))
+           (coyemail   (gnc:company-info gnc:*company-email*))
            (owneraddr  (gnc:owner-get-name-and-address-dep owner))
            (billcontact (gncAddressGetName (gnc:owner-get-address owner)))
            ; flags and counters
diff --git a/src/report/business-reports/receipt.scm b/src/report/business-reports/receipt.scm
index c405215..4e69995 100644
--- a/src/report/business-reports/receipt.scm
+++ b/src/report/business-reports/receipt.scm
@@ -69,12 +69,6 @@
         (display-comm-coll-total amttot #f))
       (if (and (not amt?) (not pc?)) (display (_ "n/a"))))))        ; neither
 
-(define (coy-info slots key)
-  ;; Extract a value from the company info key-value pairs
-  (kvp-frame-get-slot-path-gslist
-    slots
-    (append gnc:*kvp-option-path* (list gnc:*business-label* key))))
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Define all the options
 
diff --git a/src/report/business-reports/taxinvoice.eguile.scm b/src/report/business-reports/taxinvoice.eguile.scm
index 9d1972a..75a5f81 100644
--- a/src/report/business-reports/taxinvoice.eguile.scm
+++ b/src/report/business-reports/taxinvoice.eguile.scm
@@ -47,15 +47,14 @@
            (currency     (gncInvoiceGetCurrency   opt-invoice))
            (entries      (gncInvoiceGetEntries    opt-invoice))
            (splits      '());'
-           (slots        (qof-book-get-slots book))
-           (coyname      (coy-info slots gnc:*company-name*))
-           (coycontact   (coy-info slots gnc:*company-contact*))
-           (coyaddr      (coy-info slots gnc:*company-addy*))
-           (coyid        (coy-info slots gnc:*company-id*))
-           (coyphone     (coy-info slots gnc:*company-phone*))
-           (coyfax       (coy-info slots gnc:*company-fax*))
-           (coyurl       (coy-info slots gnc:*company-url*))
-           (coyemail     (coy-info slots gnc:*company-email*))
+           (coyname      (gnc:company-info gnc:*company-name*))
+           (coycontact   (gnc:company-info gnc:*company-contact*))
+           (coyaddr      (gnc:company-info gnc:*company-addy*))
+           (coyid        (gnc:company-info gnc:*company-id*))
+           (coyphone     (gnc:company-info gnc:*company-phone*))
+           (coyfax       (gnc:company-info gnc:*company-fax*))
+           (coyurl       (gnc:company-info gnc:*company-url*))
+           (coyemail     (gnc:company-info gnc:*company-email*))
            (owneraddr  (gnc:owner-get-address-dep owner))
            (ownername  (gnc:owner-get-name-dep owner))
            (jobnumber  (gncJobGetID (gncOwnerGetJob (gncInvoiceGetOwner  opt-invoice))))
diff --git a/src/report/business-reports/taxinvoice.scm b/src/report/business-reports/taxinvoice.scm
index b4ea9cc..06f4b17 100644
--- a/src/report/business-reports/taxinvoice.scm
+++ b/src/report/business-reports/taxinvoice.scm
@@ -76,12 +76,6 @@
         (display-comm-coll-total amttot #f))
       (if (and (not amt?) (not pc?)) (display (_ "n/a"))))))        ; neither
 
-(define (coy-info slots key)
-  ;; Extract a value from the company info key-value pairs
-  (kvp-frame-get-slot-path-gslist
-    slots 
-    (append gnc:*kvp-option-path* (list gnc:*business-label* key))))
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Define all the options
 
diff --git a/src/report/locale-specific/us/taxtxf-de_DE.scm b/src/report/locale-specific/us/taxtxf-de_DE.scm
index ab4e904..85b554e 100644
--- a/src/report/locale-specific/us/taxtxf-de_DE.scm
+++ b/src/report/locale-specific/us/taxtxf-de_DE.scm
@@ -752,11 +752,8 @@
                                 (localtime 
                                  (car (timespecCanonicalDayTime
                                        (cons (current-time) 0))))))
-	  (tax-nr (or 
-		   (kvp-frame-get-slot-path-gslist
-		    (qof-book-get-slots (gnc-get-current-book))
-		    (append gnc:*kvp-option-path*
-			    (list gnc:*tax-label* gnc:*tax-nr-label*)))
+	  (tax-nr (or
+                   (gnc:option-get-value gnc:*tax-label* gnc:*tax-nr-label*)
 		   ""))
 	  )
 

commit 095d1781f0175bd551c0836eb8d5e2f8826374b0
Author: John Ralls <jralls at ceridwen.us>
Date:   Wed Jun 10 10:43:43 2015 -0700

    Remove a couple of distracting comments about KVP.

diff --git a/src/app-utils/gnc-accounting-period.c b/src/app-utils/gnc-accounting-period.c
index e7dd8e7..f6bf987 100644
--- a/src/app-utils/gnc-accounting-period.c
+++ b/src/app-utils/gnc-accounting-period.c
@@ -101,7 +101,6 @@ static GDate *
 get_fy_end(void)
 {
     QofBook *book;
-    KvpFrame *book_frame;
     GDate *date = NULL;
 
     book = gnc_get_current_book();
diff --git a/src/app-utils/gnc-sx-instance-model.c b/src/app-utils/gnc-sx-instance-model.c
index 139fd88..153554c 100644
--- a/src/app-utils/gnc-sx-instance-model.c
+++ b/src/app-utils/gnc-sx-instance-model.c
@@ -1027,7 +1027,6 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
                      g_date_get_month(&creation_data->instance->date),
                      g_date_get_year(&creation_data->instance->date));
 
-    /* the accounts and amounts are in the kvp_frames of the splits. */
     template_splits = xaccTransGetSplitList(template_txn);
     txn_splits = xaccTransGetSplitList(new_txn);
     if ((template_splits == NULL) || (txn_splits == NULL))
@@ -1555,9 +1554,6 @@ create_cashflow_helper(Transaction *template_txn, void *user_data)
             xaccTransGetDescription(template_txn),
             xaccSchedXactionGetName(creation_data->sx));
 
-    /* The accounts and amounts are in the kvp_frames of the
-     * splits. Hence, we iterate over all splits of this
-     * transaction. */
     template_splits = xaccTransGetSplitList(template_txn);
 
     if (template_splits == NULL)

commit 61ecdda8454b743133b807621a6398a24c0df95c
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 9 16:49:56 2015 -0700

    Miscellaneous KVP cleanup.
    
    Everything but the backends and app-utils.

diff --git a/src/gnome-utils/dialog-preferences.c b/src/gnome-utils/dialog-preferences.c
index 96f9159..470ec6b 100644
--- a/src/gnome-utils/dialog-preferences.c
+++ b/src/gnome-utils/dialog-preferences.c
@@ -1062,7 +1062,6 @@ gnc_preferences_dialog_create(void)
     gnc_commodity *locale_currency;
     const gchar *currency_name;
     QofBook *book;
-    KvpFrame *book_frame;
     gint64 month, day;
     GDate fy_end;
     gboolean date_is_valid = FALSE;
diff --git a/src/gnome-utils/gnc-tree-view-owner.c b/src/gnome-utils/gnc-tree-view-owner.c
index 51d3cac..a94e3b3 100644
--- a/src/gnome-utils/gnc-tree-view-owner.c
+++ b/src/gnome-utils/gnc-tree-view-owner.c
@@ -954,16 +954,16 @@ owner_cell_kvp_data_func (GtkTreeViewColumn *tree_column,
                           gpointer key)
 {
     GncOwner *owner;
-    kvp_frame * frame;
+    GValue v = G_VALUE_INIT;
 
     g_return_if_fail (GTK_IS_TREE_MODEL_SORT (s_model));
     owner = gnc_tree_view_owner_get_owner_from_iter(s_model, s_iter);
-    frame = gncOwnerGetSlots(owner);
-
-    g_object_set (G_OBJECT (cell),
-                  "text", kvp_frame_get_string(frame, (gchar *)key),
-                  "xalign", 0.0,
-                  NULL);
+    qof_instance_get_kvp (QOF_INSTANCE (owner), (gchar*)key, &v);
+    if (G_VALUE_HOLDS_STRING)
+         g_object_set (G_OBJECT (cell),
+                       "text", g_value_get_string (&v),
+                       "xalign", 0.0,
+                       NULL);
 
 }
 
diff --git a/src/import-export/import-account-matcher.c b/src/import-export/import-account-matcher.c
index 27d7fe3..723b384 100644
--- a/src/import-export/import-account-matcher.c
+++ b/src/import-export/import-account-matcher.c
@@ -76,7 +76,7 @@ static AccountPickerDialog* gnc_import_new_account_picker(void)
 /**************************************************
  * test_acct_online_id_match
  *
- * test for match of kvp_frame of account
+ * test for match of account online_ids.
  **************************************************/
 static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id)
 {
diff --git a/src/import-export/import-account-matcher.h b/src/import-export/import-account-matcher.h
index 6c345cc..b663af3 100644
--- a/src/import-export/import-account-matcher.h
+++ b/src/import-export/import-account-matcher.h
@@ -52,11 +52,11 @@ typedef struct
 } AccountPickerDialog;
 
 /**  Must be called with a string containing a unique identifier for the
-  account.  If an account with a matching online_id kvp_frame is
+  account.  If an account with a matching online_id is
   found, the function immediately returns with a pointer to that
   account.  Otherwise, the user is prompted to select a GnuCash
   account or create a new one (in both cases, the unique identifier is
-  written to the account's kvp_frame, so the user won't be prompted
+  written to the account, so the user won't be prompted
   again).  If the user refuses to select or create an account, NULL is
   returned.
 
@@ -70,7 +70,7 @@ typedef struct
     selector that allows you to select an account whose GncGUID will be
     remembered elsewhere.  You would fill account_human_description to tell
     the user what he is looking for.  In this mode, the  online_id
-    kvp_frame of the found account will not be touched.  To use this mode,
+    field of the found account will not be touched.  To use this mode,
     auto_create must NOT be set to 0.
 
     @param account_human_description
@@ -136,7 +136,7 @@ AccountPickerDialog * gnc_import_account_assist_setup (GtkWidget *parent);
 
 
 /**  Must be called with an AccountPickerDialog structure allready setup.
-     If an account with a matching online_id kvp_frame is found, which is
+     If an account with a matching online_id is found, which is
      allready present in the dialog structure, the function returns with a
      pointer to that account or NULL if not found.
 
diff --git a/src/import-export/import-backend.c b/src/import-export/import-backend.c
index 60466e1..fdd219d 100644
--- a/src/import-export/import-backend.c
+++ b/src/import-export/import-backend.c
@@ -1116,7 +1116,7 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
 /********************************************************************\
  * check_trans_online_id() Callback function used by
  * gnc_import_exists_online_id.  Takes pointers to transaction and split,
- * returns 0 if their online_id kvp_frames do NOT match, or if the split
+ * returns 0 if their online_ids  do NOT match, or if the split
  * belongs to the transaction
 \********************************************************************/
 static gint check_trans_online_id(Transaction *trans1, void *user_data)
diff --git a/src/import-export/import-utilities.h b/src/import-export/import-utilities.h
index fd0d599..2ef484c 100644
--- a/src/import-export/import-utilities.h
+++ b/src/import-export/import-utilities.h
@@ -40,7 +40,7 @@
 #include "Account.h"
 
 /** @name Setter-getters
-    Setter and getter functions for the online_id kvp_frame for
+    Setter and getter functions for the online_id field for
     Accounts.
 	@{
 */
@@ -49,7 +49,7 @@ void gnc_import_set_acc_online_id(Account * account,
                                   const gchar * string_value);
 /** @} */
 /** @name Setter-getters
-    Setter and getter functions for the online_id kvp_frame for
+    Setter and getter functions for the online_id field for
     Transactions.
 	@{
 */
@@ -61,7 +61,7 @@ void gnc_import_set_trans_online_id(Transaction * transaction,
 gboolean gnc_import_trans_has_online_id(Transaction * transaction);
 
 /** @name Setter-getters
-    Setter and getter functions for the online_id kvp_frame for
+    Setter and getter functions for the online_id field for
     Splits.
 	@{
 */
diff --git a/src/register/ledger-core/split-register-model-save.c b/src/register/ledger-core/split-register-model-save.c
index f456daa..a4032ef 100644
--- a/src/register/ledger-core/split-register-model-save.c
+++ b/src/register/ledger-core/split-register-model-save.c
@@ -660,7 +660,6 @@ gnc_template_register_save_xfrm_cell (BasicCell * cell,
     SRInfo *info = gnc_split_register_get_info (reg);
     Account *template_acc;
     const GncGUID *acctGUID;
-    KvpFrame *kvpf;
     Account *acct;
 
     g_return_if_fail (gnc_basic_cell_has_name (cell, XFRM_CELL));

commit a4c748e20115c47185d02ba8be7eea21d9ff631c
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 9 16:19:41 2015 -0700

    Miscellaneous KVP cleanup in Engine.
    
    Doesn't include tests or Scheme support.

diff --git a/src/engine/Split.h b/src/engine/Split.h
index 487deba..db8fb63 100644
--- a/src/engine/Split.h
+++ b/src/engine/Split.h
@@ -338,7 +338,7 @@ gnc_numeric xaccSplitGetReconciledBalance (const Split *split);
  *
  * @param check_txn_splits If the pointers are not equal, but
  * everything else so far is equal (including memo, amount, value,
- * kvp_frame), then, when comparing the parenting transactions with
+ * kvp), then, when comparing the parenting transactions with
  * xaccTransEqual(), set its argument check_splits to be TRUE.
  */
 gboolean xaccSplitEqual(const Split *sa, const Split *sb,
@@ -515,8 +515,6 @@ gnc_numeric xaccSplitVoidFormerValue(const Split *split);
  * override so the gnome-search dialog displays the right type.
  @{
 */
-#define SPLIT_KVP		"kvp"
-
 #define SPLIT_DATE_RECONCILED	"date-reconciled"
 #define SPLIT_BALANCE		"balance"
 #define SPLIT_CLEARED_BALANCE	"cleared-balance"
diff --git a/src/engine/TransactionP.h b/src/engine/TransactionP.h
index 87b89bf..bc93442 100644
--- a/src/engine/TransactionP.h
+++ b/src/engine/TransactionP.h
@@ -164,13 +164,6 @@ QofBackend * xaccTransactionGetBackend (Transaction *trans);
 void xaccEnableDataScrubbing(void);
 void xaccDisableDataScrubbing(void);
 
-/** Set the KvpFrame slots of this transaction to the given frm by
- *  * directly using the frm pointer (i.e. non-copying).
- *   * XXX this is wrong, nedds to be replaced with a transactional thingy
- *   in kvp + qofinstance. for now, this is a quasi-unctional placeholder.
- *    */
-#define xaccTransSetSlots_nc(T,F) qof_instance_set_slots(QOF_INSTANCE(T),F)
-
 void xaccTransRemoveSplit (Transaction *trans, const Split *split);
 void check_open (const Transaction *trans);
 
diff --git a/src/engine/gnc-commodity.c b/src/engine/gnc-commodity.c
index adbbcab..ce1e11d 100644
--- a/src/engine/gnc-commodity.c
+++ b/src/engine/gnc-commodity.c
@@ -940,8 +940,7 @@ gnc_commodity_copy(gnc_commodity * dest, const gnc_commodity *src)
     gnc_commodity_set_quote_flag (dest, src_priv->quote_flag);
     gnc_commodity_set_quote_source (dest, gnc_commodity_get_quote_source (src));
     gnc_commodity_set_quote_tz (dest, src_priv->quote_tz);
-    kvp_frame_delete (dest->inst.kvp_data);
-    dest->inst.kvp_data = kvp_frame_copy (src->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE (dest), QOF_INSTANCE (src));
 }
 
 gnc_commodity *
@@ -967,8 +966,7 @@ gnc_commodity_clone(const gnc_commodity *src, QofBook *dest_book)
 
     gnc_commodity_set_quote_source (dest, gnc_commodity_get_quote_source (src));
 
-    kvp_frame_delete (dest->inst.kvp_data);
-    dest->inst.kvp_data = kvp_frame_copy (src->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE (dest), QOF_INSTANCE (src));
 
     reset_printname(dest_priv);
     reset_unique_name(dest_priv);
@@ -1087,11 +1085,14 @@ static gboolean
 gnc_commodity_get_auto_quote_control_flag(const gnc_commodity *cm)
 {
     const char *str;
+    GValue v = G_VALUE_INIT;
 
     if (!cm) return FALSE;
-
-    str = kvp_frame_get_string(cm->inst.kvp_data, "auto_quote_control");
-    return !str || (strcmp(str, "false") != 0);
+    qof_instance_get_kvp (QOF_INSTANCE (cm), "auto_quote_control", &v);
+    if (G_VALUE_HOLDS_STRING (&v) &&
+        strcmp(g_value_get_string (&v), "false") == 0)
+        return FALSE;
+    return TRUE;
 }
 
 /********************************************************************
@@ -1148,8 +1149,12 @@ const char*
 gnc_commodity_get_user_symbol(const gnc_commodity *cm)
 {
     const char *str;
+    GValue v = G_VALUE_INIT;
     if (!cm) return NULL;
-    return kvp_frame_get_string(cm->inst.kvp_data, "user_symbol");
+    qof_instance_get_kvp (QOF_INSTANCE(cm), "user_symbol", &v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        return g_value_get_string (&v);
+    return NULL;
 }
 
 /********************************************************************
@@ -1308,6 +1313,7 @@ static void
 gnc_commodity_set_auto_quote_control_flag(gnc_commodity *cm,
         const gboolean flag)
 {
+    GValue v = G_VALUE_INIT;
     ENTER ("(cm=%p, flag=%d)", cm, flag);
 
     if (!cm)
@@ -1315,10 +1321,15 @@ gnc_commodity_set_auto_quote_control_flag(gnc_commodity *cm,
         LEAVE("");
         return;
     }
-
     gnc_commodity_begin_edit(cm);
-    kvp_frame_set_string(cm->inst.kvp_data,
-                         "auto_quote_control", flag ? NULL : "false");
+    if (flag)
+        qof_instance_set_kvp (QOF_INSTANCE (cm), "auto_quote_control", NULL);
+    else
+    {
+        g_value_init (&v, G_TYPE_STRING);
+        g_value_set_string (&v, "false");
+        qof_instance_set_kvp (QOF_INSTANCE (cm), "auto_quote_control", &v);
+    }
     mark_commodity_dirty(cm);
     gnc_commodity_commit_edit(cm);
     LEAVE("");
@@ -1431,7 +1442,7 @@ void
 gnc_commodity_set_user_symbol(gnc_commodity * cm, const char * user_symbol)
 {
     struct lconv *lc;
-
+    GValue v = G_VALUE_INIT;
     if (!cm) return;
 
     ENTER ("(cm=%p, symbol=%s)", cm, user_symbol ? user_symbol : "(null)");
@@ -1448,8 +1459,15 @@ gnc_commodity_set_user_symbol(gnc_commodity * cm, const char * user_symbol)
 	user_symbol = NULL;
     else if (!g_strcmp0(user_symbol, gnc_commodity_get_default_symbol(cm)))
 	user_symbol = NULL;
+    if (user_symbol)
+    {
+        g_value_init (&v, G_TYPE_STRING);
+        g_value_set_string (&v, user_symbol);
+        qof_instance_set_kvp (QOF_INSTANCE(cm), "user_symbol", &v);
+    }
+    else
+        qof_instance_set_kvp (QOF_INSTANCE(cm), "user_symbol", NULL);
 
-    kvp_frame_set_string(cm->inst.kvp_data, "user_symbol", user_symbol);
     mark_commodity_dirty(cm);
     gnc_commodity_commit_edit(cm);
 
diff --git a/src/engine/gncAddress.c b/src/engine/gncAddress.c
index 103e35a..0aa3547 100644
--- a/src/engine/gncAddress.c
+++ b/src/engine/gncAddress.c
@@ -495,7 +495,7 @@ static void address_free (QofInstance *inst)
 void gncAddressCommitEdit (GncAddress *addr)
 {
     /* GnuCash 2.6.3 and earlier didn't handle address kvp's... */
-    if (!kvp_frame_is_empty (addr->inst.kvp_data))
+     if (qof_instance_has_kvp(QOF_INSTANCE(addr)))
         gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (addr)), GNC_FEATURE_KVP_EXTRA_DATA);
 
     if (!qof_commit_edit (QOF_INSTANCE(addr))) return;
diff --git a/src/engine/gncEntry.c b/src/engine/gncEntry.c
index 10557aa..e0ea400 100644
--- a/src/engine/gncEntry.c
+++ b/src/engine/gncEntry.c
@@ -1532,8 +1532,9 @@ static void entry_free (QofInstance *inst)
 void gncEntryCommitEdit (GncEntry *entry)
 {
     /* GnuCash 2.6.3 and earlier didn't handle entry kvp's... */
-    if (!kvp_frame_is_empty (entry->inst.kvp_data))
-        gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (entry)), GNC_FEATURE_KVP_EXTRA_DATA);
+    if (qof_instance_has_kvp(QOF_INSTANCE(entry)))
+        gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (entry)),
+                               GNC_FEATURE_KVP_EXTRA_DATA);
 
     if (!qof_commit_edit (QOF_INSTANCE(entry))) return;
     qof_commit_edit_part2 (&entry->inst, gncEntryOnError,
diff --git a/src/engine/gncInvoice.c b/src/engine/gncInvoice.c
index 1163ac1..2daeff2 100644
--- a/src/engine/gncInvoice.c
+++ b/src/engine/gncInvoice.c
@@ -338,7 +338,7 @@ GncInvoice *gncInvoiceCopy (const GncInvoice *from)
     GncInvoice *invoice;
     QofBook* book;
     GList *node;
-    gint64 is_cn;
+    GValue v = G_VALUE_INIT;
 
     g_assert(from);
     book = qof_instance_get_book(from);
@@ -354,8 +354,9 @@ GncInvoice *gncInvoiceCopy (const GncInvoice *from)
     invoice->billing_id = CACHE_INSERT (from->billing_id);
     invoice->active = from->active;
 
-    is_cn = kvp_frame_get_gint64(from->inst.kvp_data, GNC_INVOICE_IS_CN);
-    kvp_frame_set_gint64(invoice->inst.kvp_data, GNC_INVOICE_IS_CN, is_cn);
+    qof_instance_get_kvp (QOF_INSTANCE (from), GNC_INVOICE_IS_CN, &v);
+    if (G_VALUE_HOLDS_INT64 (&v))
+         qof_instance_set_kvp (QOF_INSTANCE (invoice), GNC_INVOICE_IS_CN, &v);
 
     invoice->terms = from->terms;
     gncBillTermIncRef (invoice->terms);
@@ -545,10 +546,12 @@ void gncInvoiceSetActive (GncInvoice *invoice, gboolean active)
 
 void gncInvoiceSetIsCreditNote (GncInvoice *invoice, gboolean credit_note)
 {
+     GValue v = G_VALUE_INIT;
     if (!invoice) return;
     gncInvoiceBeginEdit (invoice);
-    kvp_frame_set_gint64(invoice->inst.kvp_data, GNC_INVOICE_IS_CN,
-                         credit_note ? 1 : 0);
+    g_value_init (&v, G_TYPE_INT64);
+    g_value_set_int64(&v, credit_note ? 1 : 0);
+    qof_instance_set_kvp (QOF_INSTANCE (invoice), GNC_INVOICE_IS_CN, &v);
     mark_invoice (invoice);
     gncInvoiceCommitEdit (invoice);
 
@@ -1035,8 +1038,10 @@ gboolean gncInvoiceGetActive (const GncInvoice *invoice)
 
 gboolean gncInvoiceGetIsCreditNote (const GncInvoice *invoice)
 {
+    GValue v = G_VALUE_INIT;
     if (!invoice) return FALSE;
-    if (kvp_frame_get_gint64(invoice->inst.kvp_data, GNC_INVOICE_IS_CN))
+    qof_instance_get_kvp (QOF_INSTANCE(invoice), GNC_INVOICE_IS_CN, &v);
+    if (G_VALUE_HOLDS_INT64(&v) && g_value_get_int64(&v))
         return TRUE;
     else
         return FALSE;
diff --git a/src/engine/gncTaxTable.c b/src/engine/gncTaxTable.c
index 2c525f4..636c13e 100644
--- a/src/engine/gncTaxTable.c
+++ b/src/engine/gncTaxTable.c
@@ -655,8 +655,9 @@ static void table_free (QofInstance *inst)
 void gncTaxTableCommitEdit (GncTaxTable *table)
 {
     /* GnuCash 2.6.3 and earlier didn't handle taxtable kvp's... */
-    if (!kvp_frame_is_empty (table->inst.kvp_data))
-        gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (table)), GNC_FEATURE_KVP_EXTRA_DATA);
+     if (qof_instance_has_kvp (QOF_INSTANCE (table)))
+          gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (table)),
+                                 GNC_FEATURE_KVP_EXTRA_DATA);
 
     if (!qof_commit_edit (QOF_INSTANCE(table))) return;
     qof_commit_edit_part2 (&table->inst, gncTaxTableOnError,
diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c
index 631834a..89d5cde 100644
--- a/src/engine/test-core/test-engine-stuff.c
+++ b/src/engine/test-core/test-engine-stuff.c
@@ -1464,7 +1464,7 @@ get_random_transaction_with_currency(QofBook *book,
     trn_add_ran_timespec(trans, xaccTransSetDateEnteredTS);
 
     f = get_random_kvp_frame();
-    xaccTransSetSlots_nc(trans, f);
+    qof_instance_set_slots (QOF_INSTANCE (trans), f);
 
     add_random_splits(book, trans, account_list);
 
@@ -1525,7 +1525,7 @@ make_random_changes_to_transaction (QofBook *book, Transaction *trans)
 
     set_tran_random_string (trans, xaccTransSetDescription);
 
-    xaccTransSetSlots_nc (trans, get_random_kvp_frame());
+    qof_instance_set_slots (QOF_INSTANCE (trans), get_random_kvp_frame());
 
     /* Do split manipulations in higher-level functions */
 

commit f631f6e6c5cfea901c729c5fd554fef0fe861438
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 9 14:46:09 2015 -0700

    Fix formatting, line too long.

diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index e56e22f..3dd415f 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -109,8 +109,9 @@ KvpFrameImpl::get_keys() const noexcept
 }
 
 void
-KvpFrameImpl::for_each_slot(void (*proc)(const char *key, KvpValue *value, void * data),
-              void *data) const noexcept
+KvpFrameImpl::for_each_slot(void (*proc)(const char *key, KvpValue *value,
+                                         void * data),
+                            void *data) const noexcept
 {
     if (!proc) return;
     std::for_each (m_valuemap.begin(), m_valuemap.end(),

commit 68dedc1ba2cbdff3b777a0769eed322546a122fc
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 9 17:00:09 2015 -0700

    Reimplement gnc_template_register_get_debcred_entry.
    
    So that it at least returns something reasonable. Note the comment, though.

diff --git a/src/register/ledger-core/split-register-model.c b/src/register/ledger-core/split-register-model.c
index 07dea27..82d0f30 100644
--- a/src/register/ledger-core/split-register-model.c
+++ b/src/register/ledger-core/split-register-model.c
@@ -2155,20 +2155,24 @@ gnc_split_register_get_default_help (VirtualLocation virt_loc,
     return g_strdup (help);
 }
 
+/* This function has been #if-zeroed for a year; in all released versions since
+ * 2001 it has issued dire warnings about being wrong, and returned nothing
+ * because it was querying a non-existent slot.
+ *
+ * Now it retrieves the sx-debit-numeric or sx-credit-numeric properties from
+ * the split. I'm not sure that it's what was originally intended, but at least
+ * it can do something now.	<jralls, 8 June 2015>
+ */
 static const char *
 gnc_template_register_get_debcred_entry (VirtualLocation virt_loc,
         gboolean translate,
         gboolean *conditionally_changed,
         gpointer user_data)
 {
-    PERR("The function called always returned either NULL or an empty string "
-	 "while issuing dire warnings about how incorrect it is. That code "
-	 "has been removed and the function if called raises this error and "
-	 "returns NULL");
-    return NULL;
-#if 0
     SplitRegister *reg = user_data;
     Split *split;
+    gnc_numeric amount;
+    const char * cell_name;
 
     split = gnc_split_register_get_split (reg, virt_loc.vcell_loc);
     if (!split)
@@ -2177,43 +2181,20 @@ gnc_template_register_get_debcred_entry (VirtualLocation virt_loc,
                 conditionally_changed,
                 user_data);
 
-    kvpf = xaccSplitGetSlots (split);
-    PWARN( "We're very close to \"wrong\".  \"Fix it immediately!!!\"" );
-
-    if (kvpf)
-    {
-        gnc_numeric amount;
-        const char * cell_name;
-        char *str;
-
-        PWARN("This code is wrong.  Fix it immediately!!!!");
-        str = kvp_value_get_string(
-                  kvp_frame_get_slot_path(kvpf, "sched-xaction", "amnt", NULL));
-
-        amount = gnc_numeric_zero ();
-        string_to_gnc_numeric (str, &amount);
-
-        if (gnc_numeric_zero_p (amount))
-            return "";
-
-        cell_name = gnc_table_get_cell_name (reg->table, virt_loc);
-
-        if (gnc_numeric_negative_p (amount) &&
-                gnc_cell_name_equal (cell_name, DEBT_CELL))
-            return "";
-
-        if (gnc_numeric_positive_p (amount) &&
-                gnc_cell_name_equal (cell_name, CRED_CELL))
-            return "";
-
-        amount = gnc_numeric_abs (amount);
-
-        /* FIXME: This should be fixed to be correct for the "fake" account. */
-        return xaccPrintAmount (amount, gnc_default_print_info (FALSE));
-    }
+    cell_name = gnc_table_get_cell_name (reg->table, virt_loc);
+    if (gnc_cell_name_equal (cell_name, DEBT_CELL))
+        qof_instance_get (QOF_INSTANCE (split),
+                          "sx-debit-numeric", &amount,
+                          NULL);
+    else
+        qof_instance_get (QOF_INSTANCE (split),
+                          "sx-credit-numeric", &amount,
+                          NULL);
+    if (gnc_numeric_zero_p (amount))
+        return "";
 
-    return NULL;
-#endif
+    amount = gnc_numeric_abs (amount);
+    return xaccPrintAmount (amount, gnc_default_print_info (FALSE));
 }
 
 static void

commit 43e93e5fb5f1c511de056679c8dafe563b50ef51
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 9 14:43:58 2015 -0700

    Modify gnc_imap... functions to use KVP indirectly, provide unit tests.

diff --git a/src/engine/Account.c b/src/engine/Account.c
index 7ae196d..706463f 100644
--- a/src/engine/Account.c
+++ b/src/engine/Account.c
@@ -5029,7 +5029,6 @@ xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc,
 
 typedef struct _GncImportMatchMap
 {
-    KvpFrame *  frame;
     Account *   acc;
     QofBook *   book;
 } GncImportMatchMap;
@@ -5050,15 +5049,10 @@ GncImportMatchMap *
 gnc_account_create_imap (Account *acc)
 {
     GncImportMatchMap *imap;
-    KvpFrame *frame;
 
     if (!acc) return NULL;
-    frame = qof_instance_get_slots (QOF_INSTANCE (acc));
-    g_return_val_if_fail (frame != NULL, NULL);
-    g_return_val_if_fail (frame != NULL, NULL);
 
     imap = g_new0(GncImportMatchMap, 1);
-    imap->frame = frame;
 
     /* Cache the book for easy lookups; store the account/book for
      * marking dirtiness
@@ -5140,16 +5134,16 @@ struct token_accounts_info
  * \note Can always assume that keys are unique, reduces code in this function
  */
 static void
-buildTokenInfo(const char *key, KvpValue *value, gpointer data)
+buildTokenInfo(const char *key, const GValue *value, gpointer data)
 {
     struct token_accounts_info *tokenInfo = (struct token_accounts_info*)data;
     struct account_token_count* this_account;
 
     //  PINFO("buildTokenInfo: account '%s', token_count: '%ld'\n", (char*)key,
-    //                  (long)kvp_value_get_gint64(value));
+    //                  (long)g_value_get_int64(value));
 
     /* add the count to the total_count */
-    tokenInfo->total_count += kvp_value_get_gint64(value);
+    tokenInfo->total_count += g_value_get_int64(value);
 
     /* allocate a new structure for this account and it's token count */
     this_account = (struct account_token_count*)
@@ -5157,7 +5151,7 @@ buildTokenInfo(const char *key, KvpValue *value, gpointer data)
 
     /* fill in the account name and number of tokens found for this account name */
     this_account->account_name = (char*)key;
-    this_account->token_count = kvp_value_get_gint64(value);
+    this_account->token_count = g_value_get_int64(value);
 
     /* append onto the glist a pointer to the new account_token_count structure */
     tokenInfo->accounts = g_list_prepend(tokenInfo->accounts, this_account);
@@ -5262,8 +5256,6 @@ gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
     GHashTable *final_probabilities = g_hash_table_new(g_str_hash,
                                                        g_str_equal);
     struct account_info account_i;
-    KvpValue* value;
-    KvpFrame* token_frame;
 
     ENTER(" ");
 
@@ -5281,40 +5273,20 @@ gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
     for (current_token = tokens; current_token;
          current_token = current_token->next)
     {
-        /* zero out the token_accounts_info structure */
+        char* path = g_strdup_printf (IMAP_FRAME_BAYES "/%s",
+                                            (char*)current_token->data);
+   /* zero out the token_accounts_info structure */
         memset(&tokenInfo, 0, sizeof(struct token_accounts_info));
 
         PINFO("token: '%s'", (char*)current_token->data);
 
-        /* find the slot for the given token off of the source account
-         * for these tokens, search off of the IMAP_FRAME_BAYES path so
-         * we aren't looking from the parent of the entire kvp tree
-         */
-        value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
-                                        (char*)current_token->data, NULL);
-
-        /* if value is null we should skip over this token */
-        if (!value)
-            continue;
-
-        /* convert the slot(value) into a the frame that contains the
-         * list of accounts
-         */
-        token_frame = kvp_value_get_frame(value);
-
-        /* token_frame should NEVER be null */
-        if (!token_frame)
-        {
-            PERR("token '%s' has no accounts", (char*)current_token->data);
-            continue; /* skip over this token */
-        }
-
         /* process the accounts for this token, adding the account if it
          * doesn't already exist or adding to the existing accounts token
          * count if it does
          */
-        kvp_frame_for_each_slot(token_frame, buildTokenInfo, &tokenInfo);
-
+        qof_instance_foreach_slot(QOF_INSTANCE (imap->acc), path,
+                                  buildTokenInfo, &tokenInfo);
+        g_free (path);
         /* for each account we have just found, see if the account
          * already exists in the list of account probabilities, if not
          * add it
@@ -5477,7 +5449,8 @@ gnc_imap_add_account_bayes(GncImportMatchMap *imap,
             token_count += count;
         }
         token_count++;
-        g_value_init (&value, G_TYPE_INT64);
+        if (!G_IS_VALUE (&value))
+            g_value_init (&value, G_TYPE_INT64);
         g_value_set_int64 (&value, token_count);
         qof_instance_set_kvp (QOF_INSTANCE (imap->acc), kvp_path, &value);
         g_free (kvp_path);
diff --git a/src/engine/test/Makefile.am b/src/engine/test/Makefile.am
index 87a2cb5..8f1cf03 100644
--- a/src/engine/test/Makefile.am
+++ b/src/engine/test/Makefile.am
@@ -128,6 +128,32 @@ libutest_Trans_la_SOURCES = \
 
 libutest_Trans_la_LIBADD = $(LDADD)
 
+if WITH_GOOGLE_TEST
+test_import_map_SOURCES = \
+        gtest-import-map.cpp
+test_import_map_LDADD = \
+        ${top_builddir}/src/libqof/qof/libgnc-qof.la \
+        ${top_builddir}/src/engine/libgncmod-engine.la \
+        ${GLIB_LIBS} \
+        ${GTEST_LIBS}
+
+if !GOOGLE_TEST_LIBS
+nodist_test_import_map_SOURCES = \
+        ${GTEST_SRC}/src/gtest_main.cc
+test_import_map_LDADD += ${top_builddir}/src/test-core/libgtest.a
+endif
+
+test_import_map_CPPFLAGS = \
+        -I${GTEST_HEADERS} \
+        -I${top_srcdir}/${MODULEPATH} \
+        -I${top_srcdir}/src/libqof/qof \
+        -I${top_srcdir}/src/core-utils \
+        ${GLIB_CFLAGS}
+
+TEST_GROUP_1 += test-import-map
+endif
+
+
 
 clean-local:
 	rm -f translog.*
diff --git a/src/engine/test/gtest-import-map.cpp b/src/engine/test/gtest-import-map.cpp
new file mode 100644
index 0000000..a4d4885
--- /dev/null
+++ b/src/engine/test/gtest-import-map.cpp
@@ -0,0 +1,288 @@
+/********************************************************************
+ * test-import-map.cpp: Test import match maps.                     *
+ * Copyright 2015 John Ralls <jralls at ceridwen.us>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+extern "C"
+{
+#include <config.h>
+#include "../Account.h"
+#include <qof.h>
+#include <qofinstance-p.h>
+#include <kvp_frame.h>
+
+struct GncImportMatchMap
+{
+    Account *acc;
+    QofBook *book;
+};
+
+extern GncImportMatchMap * gnc_account_create_imap (Account *acc);
+extern Account* gnc_imap_find_account(GncImportMatchMap *imap,
+				      const char* category,
+				      const char *key);
+extern void gnc_imap_add_account (GncImportMatchMap *imap,
+				  const char *category,
+				  const char *key, Account *acc);
+extern Account* gnc_imap_find_account_bayes (GncImportMatchMap *imap,
+					     GList* tokens);
+extern void gnc_imap_add_account_bayes (GncImportMatchMap *imap,
+					GList* tokens,
+					Account *acc);
+}
+
+#include <gtest/gtest.h>
+
+class ImapTest : public testing::Test
+{
+protected:
+    void SetUp() {
+        QofBook *book = qof_book_new();
+        Account *root = gnc_account_create_root(book);
+        t_bank_account = xaccMallocAccount(book);
+        t_expense_account1 = xaccMallocAccount(book);
+        xaccAccountSetName(t_expense_account1, "Food");
+        gnc_account_append_child(root, t_expense_account1);
+        t_expense_account2 = xaccMallocAccount(book);
+        xaccAccountSetName(t_expense_account2, "Drink");
+        gnc_account_append_child(root, t_expense_account2);
+    }
+    void TearDown() {
+        qof_book_destroy (gnc_account_get_book (t_bank_account));
+    }
+    Account *t_bank_account {};
+    Account *t_expense_account1 {};
+    Account *t_expense_account2 {};
+};
+
+TEST_F(ImapTest, CreateImap) {
+    GncImportMatchMap *imap = gnc_account_create_imap (t_bank_account);
+    EXPECT_NE(nullptr, imap);
+    EXPECT_EQ(t_bank_account, imap->acc);
+    EXPECT_EQ(gnc_account_get_book(t_bank_account), imap->book);
+
+    g_free(imap);
+}
+
+static const char* IMAP_FRAME = "import-map";
+static const char* IMAP_FRAME_BAYES = "import-map-bayes";
+
+class ImapPlainTest : public ImapTest
+{
+protected:
+    void SetUp() {
+        ImapTest::SetUp();
+        t_imap = gnc_account_create_imap (t_bank_account);
+    }
+
+    void TearDown() {
+        g_free(t_imap);
+        ImapTest::TearDown();
+    }
+
+    GncImportMatchMap *t_imap {};
+};
+
+TEST_F(ImapPlainTest, FindAccount)
+{
+    auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
+    auto acc1_val = kvp_value_new_guid(xaccAccountGetGUID(t_expense_account1));
+    auto acc2_val = kvp_value_new_guid(xaccAccountGetGUID(t_expense_account2));
+    kvp_frame_set_slot_path(root, acc1_val, IMAP_FRAME, "foo", "bar", NULL);
+    kvp_frame_set_slot_path(root, acc2_val, IMAP_FRAME, "baz", "waldo", NULL);
+    kvp_frame_set_slot_path(root, acc1_val, IMAP_FRAME, "pepper", NULL);
+    kvp_frame_set_slot_path(root, acc2_val, IMAP_FRAME, "salt", NULL);
+    kvp_value_delete(acc1_val);
+    kvp_value_delete(acc2_val);
+
+    EXPECT_EQ(t_expense_account1, gnc_imap_find_account(t_imap, "foo", "bar"));
+    EXPECT_EQ(t_expense_account2,
+              gnc_imap_find_account(t_imap, "baz", "waldo"));
+    EXPECT_EQ(t_expense_account1,
+              gnc_imap_find_account(t_imap, NULL, "pepper"));
+    EXPECT_EQ(t_expense_account2, gnc_imap_find_account(t_imap, NULL, "salt"));
+    EXPECT_EQ(nullptr, gnc_imap_find_account(t_imap, "salt", NULL));
+}
+
+TEST_F(ImapPlainTest, AddAccount)
+{
+// prevent the embedded beginedit/commitedit from doing anything
+    qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
+    qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
+    gnc_imap_add_account(t_imap, "foo", "bar", t_expense_account1);
+    gnc_imap_add_account(t_imap, "baz", "waldo", t_expense_account2);
+    gnc_imap_add_account(t_imap, NULL, "pepper", t_expense_account1);
+    gnc_imap_add_account(t_imap, NULL, "salt", t_expense_account2);
+    EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
+    EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
+    qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
+    gnc_imap_add_account(t_imap, NULL, NULL, t_expense_account2);
+    EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
+    gnc_imap_add_account(t_imap, "pork", "sausage", NULL);
+    EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
+    qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
+
+    auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
+    auto value = kvp_frame_get_slot_path(root, IMAP_FRAME, "foo", "bar", NULL);
+    auto check_account = [this](KvpValue* v) {
+        return xaccAccountLookup(kvp_value_get_guid(v), this->t_imap->book); };
+    EXPECT_EQ(t_expense_account1, check_account(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "baz", "waldo", NULL);
+    EXPECT_EQ(t_expense_account2, check_account(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "pepper", NULL);
+    EXPECT_EQ(t_expense_account1, check_account(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "salt", NULL);
+    EXPECT_EQ(t_expense_account2, check_account(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME, "pork", "sausage", NULL);
+    EXPECT_EQ(nullptr, value);
+}
+
+static const char* foo = "foo";
+static const char* bar = "bar";
+static const char* baz = "baz";
+static const char* waldo = "waldo";
+static const char* pepper = "pepper";
+static const char* salt = "salt";
+static const char* pork = "pork";
+static const char* sausage = "sausage";
+
+
+
+class ImapBayesTest : public ImapPlainTest
+{
+protected:
+    void SetUp() {
+        ImapPlainTest::SetUp();
+        t_list1 = g_list_prepend(t_list1, const_cast<char*>(foo));
+        t_list1 = g_list_prepend(t_list1, const_cast<char*>(bar));
+        t_list2 = g_list_prepend(t_list2, const_cast<char*>(baz));
+        t_list2 = g_list_prepend(t_list2, const_cast<char*>(waldo));
+        t_list3 = g_list_prepend(t_list3, const_cast<char*>(pepper));
+        t_list4 = g_list_prepend(t_list4, const_cast<char*>(salt));
+        t_list5 = g_list_prepend(t_list5, const_cast<char*>(pork));
+        t_list5 = g_list_prepend(t_list5, const_cast<char*>(sausage));
+    }
+    void TearDown() {
+        g_list_free(t_list1);
+        g_list_free(t_list2);
+        g_list_free(t_list3);
+        g_list_free(t_list4);
+        g_list_free(t_list5);
+        t_list1 = nullptr;
+        t_list2 = nullptr;
+        t_list3 = nullptr;
+        t_list4 = nullptr;
+        t_list5 = nullptr;
+        ImapPlainTest::TearDown();
+    }
+
+    GList *t_list1 {};
+    GList *t_list2 {};
+    GList *t_list3 {};
+    GList *t_list4 {};
+    GList *t_list5 {};
+};
+
+TEST_F(ImapBayesTest, FindAccountBayes)
+{
+    auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
+    auto acct1_name = gnc_account_get_full_name(t_expense_account1);
+    auto acct2_name = gnc_account_get_full_name(t_expense_account2);
+    auto value = kvp_value_new_gint64(42);
+
+    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
+                            foo, acct1_name, NULL);
+    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
+                            bar, acct1_name, NULL);
+    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
+                            baz, acct2_name, NULL);
+    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
+                            waldo, acct2_name, NULL);
+    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
+                            pepper, acct1_name, NULL);
+    kvp_frame_set_slot_path(root, value, IMAP_FRAME_BAYES,
+                            salt, acct2_name, NULL);
+    kvp_value_delete(value);
+
+    auto account = gnc_imap_find_account_bayes(t_imap, t_list1);
+    EXPECT_EQ(t_expense_account1, account);
+    account = gnc_imap_find_account_bayes(t_imap, t_list2);
+    EXPECT_EQ(t_expense_account2, account);
+    account = gnc_imap_find_account_bayes(t_imap, t_list3);
+    EXPECT_EQ(t_expense_account1, account);
+    account = gnc_imap_find_account_bayes(t_imap, t_list4);
+    EXPECT_EQ(t_expense_account2, account);
+    account = gnc_imap_find_account_bayes(t_imap, t_list5);
+    EXPECT_EQ(nullptr, account);
+}
+
+TEST_F(ImapBayesTest, AddAccountBayes)
+{
+    // prevent the embedded beginedit/commitedit from doing anything
+    qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
+    qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
+    gnc_imap_add_account_bayes(t_imap, t_list1, t_expense_account1);
+    gnc_imap_add_account_bayes(t_imap, t_list2, t_expense_account2);
+    gnc_imap_add_account_bayes(t_imap, t_list3, t_expense_account1);
+    gnc_imap_add_account_bayes(t_imap, t_list4, t_expense_account2);
+    EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
+    EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
+    qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
+    gnc_imap_add_account_bayes(t_imap, t_list5, NULL);
+    EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
+    qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
+
+    auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
+    auto acct1_name = gnc_account_get_full_name(t_expense_account1);
+    auto acct2_name = gnc_account_get_full_name(t_expense_account2);
+    auto value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, "foo", "bar", NULL);
+    auto check_account = [this](KvpValue* v) {
+        return (kvp_value_get_string(v),
+                                 this->t_imap->book); };
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, foo, acct1_name,
+                                    NULL);
+    EXPECT_EQ(1, kvp_value_get_gint64(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, bar, acct1_name,
+                                    NULL);
+    EXPECT_EQ(1, kvp_value_get_gint64(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, baz, acct2_name,
+                                    NULL);
+    EXPECT_EQ(1, kvp_value_get_gint64(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, waldo, acct2_name,
+                                    NULL);
+    EXPECT_EQ(1, kvp_value_get_gint64(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, pepper, acct1_name,
+                                    NULL);
+    EXPECT_EQ(1, kvp_value_get_gint64(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, salt, acct2_name,
+                                    NULL);
+    EXPECT_EQ(1, kvp_value_get_gint64(value));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, baz, acct1_name,
+                                    NULL);
+    EXPECT_EQ(0, kvp_value_get_gint64(value));
+
+    qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
+    gnc_imap_add_account_bayes(t_imap, t_list2, t_expense_account2);
+    qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
+    qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
+    value = kvp_frame_get_slot_path(root, IMAP_FRAME_BAYES, baz, acct2_name,
+                                    NULL);
+    EXPECT_EQ(2, kvp_value_get_gint64(value));
+}

commit ccd74059a252ffbe23d589326dbe1ed89d2a76a8
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 9 14:42:39 2015 -0700

    Implement qof_instance_for_each_slot().
    
    Wraps kvp_frame_for_each_slot().

diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index b2b4683..e56e22f 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -1192,7 +1192,6 @@ kvp_frame_to_string(const KvpFrame *frame)
     return g_strdup(realframe->to_string().c_str());
 }
 
-static GValue *gvalue_from_kvp_value (KvpValue *);
 static KvpValue *kvp_value_from_gvalue (const GValue*);
 
 static void
@@ -1216,8 +1215,8 @@ kvp_value_list_from_gvalue (GValue *gval, gpointer pList)
     *kvplist = g_list_prepend (*kvplist, kvp);
 }
 
-static GValue*
-gvalue_from_kvp_value (KvpValue *kval)
+GValue*
+gvalue_from_kvp_value (const KvpValue *kval)
 {
     GValue *val;
     gnc_numeric num;
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index 493098e..8053539 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -580,6 +580,12 @@ void kvp_frame_for_each_slot(KvpFrame *f,
 /** Internal helper routines, you probably shouldn't be using these. */
 gchar* kvp_frame_to_string(const KvpFrame *frame);
 
+/** Convert a kvp_value into a GValue. Frames aren't converted.
+ * @param kval: A KvpValue.
+ * @return GValue*. Must be freed with g_free().
+ */
+GValue* gvalue_from_kvp_value (const KvpValue *kval);
+
 /** KvpItem: GValue Exchange
  * \brief Transfer of KVP to and from GValue, with the key
  *
diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 1914e1a..3ff5f72 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -129,7 +129,9 @@ gboolean qof_instance_has_slot (const QofInstance *inst, const char *path);
 void qof_instance_slot_delete (const QofInstance *inst, const char *path);
 void qof_instance_slot_delete_if_empty (const QofInstance *inst,
                                         const char *path);
-
+void qof_instance_foreach_slot (const QofInstance *inst, const char *path,
+                                void(*proc)(const char*, const GValue*, void*),
+                                void* data);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index ffea2ff..a765cae 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -1287,5 +1287,31 @@ qof_instance_slot_delete_if_empty (const QofInstance *inst, const char *path)
         kvp_frame_set_frame_nc (inst->kvp_data, path, NULL);
 }
 
+struct wrap_param
+{
+    void (*proc)(const char*, const GValue*, void*);
+    void *user_data;
+};
+
+static void
+wrap_gvalue_function (const char* key, KvpValue *val, gpointer data)
+{
+    auto param = static_cast<wrap_param*>(data);
+    GValue *gv = gvalue_from_kvp_value(val);
+    param->proc(key, gv, param->user_data);
+    g_slice_free (GValue, gv);
+}
+
+void
+qof_instance_foreach_slot (const QofInstance *inst, const char* path,
+                           void (*proc)(const char*, const GValue*, void*),
+                           void* data)
+{
+    KvpFrame* frame = kvp_frame_get_frame (inst->kvp_data, path);
+    if (!frame) return;
+    wrap_param new_data {proc, data};
+    kvp_frame_for_each_slot(frame, wrap_gvalue_function, &new_data);
+}
+
 /* ========================== END OF FILE ======================= */
 

commit dcc9bfec36c36c52f1833a354a96edd5ab37e040
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jun 6 12:08:28 2015 -0700

    Reimplement AQBanking template list in C++ and in libqof.
    
    It requires direct manipulation of KVP, so it needs to be hidden away in
    libqof.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index ba27f7f..af02822 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -396,7 +396,6 @@ src/import-export/aqb/gnc-ab-getbalance.c
 src/import-export/aqb/gnc-ab-gettrans.c
 src/import-export/aqb/gnc-ab-kvp.c
 src/import-export/aqb/gnc-ab-transfer.c
-src/import-export/aqb/gnc-ab-trans-templ.c
 src/import-export/aqb/gnc-ab-utils.c
 src/import-export/aqb/gnc-file-aqb-import.c
 src/import-export/aqb/gnc-gwen-gui.c
@@ -463,6 +462,7 @@ src/import-export/qif-imp/qif-objects.scm
 src/import-export/qif-imp/qif-parse.scm
 src/import-export/qif-imp/qif-to-gnc.scm
 src/import-export/qif-imp/qif-utils.scm
+src/libqof/qof/gnc-aqbanking-templates.cpp
 src/libqof/qof/gnc-date.cpp
 src/libqof/qof/gnc-int128.cpp
 src/libqof/qof/gnc-numeric.cpp
diff --git a/src/import-export/aqb/Makefile.am b/src/import-export/aqb/Makefile.am
index a79a82b..ad95462 100644
--- a/src/import-export/aqb/Makefile.am
+++ b/src/import-export/aqb/Makefile.am
@@ -9,7 +9,6 @@ libgncmod_aqbanking_la_SOURCES = \
   gnc-ab-getbalance.c \
   gnc-ab-gettrans.c \
   gnc-ab-kvp.c \
-  gnc-ab-trans-templ.c \
   gnc-ab-transfer.c \
   gnc-ab-utils.c \
   gnc-file-aqb-import.c \
@@ -24,7 +23,6 @@ noinst_HEADERS = \
   gnc-ab-getbalance.h \
   gnc-ab-gettrans.h \
   gnc-ab-kvp.h \
-  gnc-ab-trans-templ.h \
   gnc-ab-transfer.h \
   gnc-ab-utils.h \
   gnc-file-aqb-import.h \
diff --git a/src/import-export/aqb/dialog-ab-trans.c b/src/import-export/aqb/dialog-ab-trans.c
index 67a3687..ed5d606 100644
--- a/src/import-export/aqb/dialog-ab-trans.c
+++ b/src/import-export/aqb/dialog-ab-trans.c
@@ -41,10 +41,10 @@
 #include <aqbanking/jobsepatransfer.h>
 #include <aqbanking/jobsepadebitnote.h>
 
+#include <gnc-aqbanking-templates.h>
 #include "dialog-ab-trans.h"
 #include "dialog-transfer.h"
 #include "dialog-utils.h"
-#include "gnc-ab-trans-templ.h"
 #include "gnc-ab-utils.h"
 #include "gnc-amount-edit.h"
 #include "gnc-ui.h"
diff --git a/src/import-export/aqb/gnc-ab-kvp.c b/src/import-export/aqb/gnc-ab-kvp.c
index ee1b330..7b1e781 100644
--- a/src/import-export/aqb/gnc-ab-kvp.c
+++ b/src/import-export/aqb/gnc-ab-kvp.c
@@ -114,44 +114,3 @@ gnc_ab_set_account_trans_retrieval(Account *a, Timespec time)
 		      NULL);
     xaccAccountCommitEdit(a);
 }
-
-
-#define AB_KEY "hbci"
-#define AB_TEMPLATES "template-list"
-static KvpFrame *gnc_ab_get_book_kvp(QofBook *b, gboolean create);
-
-
-/* EFFECTIVE FRIEND FUNCTION */
-extern KvpFrame *qof_instance_get_slots (const QofInstance *);
-/* EFFECTIVE FRIEND FUNCTION */
-extern void qof_instance_set_dirty_flag (gconstpointer inst, gboolean flag);
-
-GList *
-gnc_ab_get_book_template_list(QofBook *b)
-{
-    KvpFrame *frame = gnc_ab_get_book_kvp(b, FALSE);
-    KvpValue *value = kvp_frame_get_slot(frame, AB_TEMPLATES);
-    return kvp_value_get_glist(value);
-}
-
-void
-gnc_ab_set_book_template_list(QofBook *b, GList *template_list)
-{
-    KvpFrame *frame = gnc_ab_get_book_kvp(b, TRUE);
-    KvpValue *value = kvp_value_new_glist_nc(template_list);
-    kvp_frame_set_slot_nc(frame, AB_TEMPLATES, value);
-    qof_instance_set_dirty_flag(QOF_INSTANCE(b), TRUE);
-}
-
-static KvpFrame *
-gnc_ab_get_book_kvp(QofBook *b, gboolean create)
-{
-    KvpFrame *toplevel = qof_instance_get_slots(QOF_INSTANCE(b));
-    KvpFrame *result = kvp_frame_get_frame(toplevel, AB_KEY);
-    if (!result && create)
-    {
-        result = kvp_frame_new();
-        kvp_frame_add_frame_nc(toplevel, AB_KEY, result);
-    }
-    return result;
-}
diff --git a/src/import-export/aqb/gnc-ab-kvp.h b/src/import-export/aqb/gnc-ab-kvp.h
index a17b800..1c21b28 100644
--- a/src/import-export/aqb/gnc-ab-kvp.h
+++ b/src/import-export/aqb/gnc-ab-kvp.h
@@ -43,9 +43,7 @@ G_BEGIN_DECLS
  *  @{ */
 
 /**
- * Return a non-copied pointer to the accountid string in the Account @a a.
- * The gchar* is still owned by the kvp_frame, so don't free it until you want
- * to delete the whole kvp_frame.
+ * Return accountid string in the Account @a a.
  *
  * @param a Account
  * @return Account ID
@@ -62,9 +60,7 @@ const gchar *gnc_ab_get_account_accountid(const Account *a);
 void gnc_ab_set_account_accountid(Account *a, const gchar *id);
 
 /**
- * Return a non-copied pointer to the bankcode string in the Account @a a.  The
- * gchar* is still owned by the kvp_frame, so don't free it until you want to
- * delete the whole kvp_frame.
+ * Return the bankcode string in the Account @a a.
  *
  * @param a Account
  * @return Bank code
@@ -116,33 +112,4 @@ void gnc_ab_set_account_trans_retrieval(Account *a, Timespec time);
 
 /** @} */
 
-/** @name Book
- *  @{ */
-
-/**
- * Return a non-copied pointer to the GList of kvp_frames which eventually are
- * the template transactions, stored in the given book.
- *
- * @param b Book
- * @return Template list
- */
-GList *gnc_ab_get_book_template_list(QofBook *b);
-
-/**
- * Set the GList of kvp_frames of template transactions in the Book @a b to @a
- * template_list.  No copy of the GList will be stored, the callee becomes the
- * owner and the caller must not free it.  The book will be marked "dirty".
- *
- * @param b Book
- * @param template_list Template list
- */
-void gnc_ab_set_book_template_list(QofBook *b, GList *template_list);
-
-/** @} */
-
-G_END_DECLS
-
-/** @} */
-/** @} */
-
 #endif /* GNC_AB_KVP_H */
diff --git a/src/import-export/aqb/gnc-ab-trans-templ.c b/src/import-export/aqb/gnc-ab-trans-templ.c
deleted file mode 100644
index f76e574..0000000
--- a/src/import-export/aqb/gnc-ab-trans-templ.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * gnc-ab-trans-templ.c --
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, contact:
- *
- * Free Software Foundation           Voice:  +1-617-542-5942
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
- * Boston, MA  02110-1301,  USA       gnu at gnu.org
- */
-
-/**
- * @internal
- * @file gnc-ab-trans-templ.c
- * @brief Templates for AqBanking transactions
- * @author Copyright (C) 2002 Christian Stimming <stimming at tuhh.de>
- * @author Copyright (C) 2008 Andreas Koehler <andi5.py at gmx.net>
- */
-
-#include "config.h"
-
-#include "gnc-ab-trans-templ.h"
-
-/* This static indicates the debugging module that this .o belongs to.  */
-G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
-
-/* KvpFrame slot names */
-#define TT_NAME "name"
-#define TT_RNAME "rnam"
-#define TT_RACC "racc"
-#define TT_RBCODE "rbcd"
-#define TT_PURPOS "purp"
-#define TT_PURPOSCT "purc"
-#define TT_AMOUNT "amou"
-
-struct _GncABTransTempl
-{
-    /* Name of this Template */
-    gchar *name;
-    gchar *name_key; /* Collation key */
-
-    /* Recipient */
-    gchar *recp_name;
-    gchar *recp_account;
-    gchar *recp_bankcode;
-
-    /* Amount */
-    gnc_numeric amount;
-
-    /* Purpose, description */
-    gchar *purpose;
-    gchar *purpose_cont;
-};
-
-
-GncABTransTempl *
-gnc_ab_trans_templ_new(void)
-{
-    return gnc_ab_trans_templ_new_full(NULL, NULL, NULL, NULL,
-                                       gnc_numeric_zero(), NULL, NULL);
-}
-
-GncABTransTempl *
-gnc_ab_trans_templ_new_full(const char *name, const char *recp_name,
-                            const char *recp_account, const char *recp_bankcode,
-                            gnc_numeric amount, const char *purpose,
-                            const char *purpose_cont)
-{
-    GncABTransTempl *r = g_new(GncABTransTempl, 1);
-    r->name = g_strdup(name);
-    r->name_key = g_utf8_collate_key(name, -1);
-    r->recp_name = g_strdup(recp_name);
-    r->recp_account = g_strdup(recp_account);
-    r->recp_bankcode = g_strdup(recp_bankcode);
-    r->amount = amount;
-    r->purpose = g_strdup(purpose);
-    r->purpose_cont = g_strdup(purpose_cont);
-
-    return r;
-}
-
-GncABTransTempl *
-gnc_ab_trans_templ_new_from_kvp(const KvpFrame *k)
-{
-    g_return_val_if_fail(k, NULL);
-
-    return gnc_ab_trans_templ_new_full(
-               kvp_value_get_string(kvp_frame_get_slot(k, TT_NAME)),
-               kvp_value_get_string(kvp_frame_get_slot(k, TT_RNAME)),
-               kvp_value_get_string(kvp_frame_get_slot(k, TT_RACC)),
-               kvp_value_get_string(kvp_frame_get_slot(k, TT_RBCODE)),
-               kvp_value_get_numeric(kvp_frame_get_slot(k, TT_AMOUNT)),
-               kvp_value_get_string(kvp_frame_get_slot(k, TT_PURPOS)),
-               kvp_value_get_string(kvp_frame_get_slot(k, TT_PURPOSCT)));
-}
-
-GList *
-gnc_ab_trans_templ_list_new_from_kvp_list(GList *v)
-{
-    GList *res = NULL;
-    GList *iter;
-
-    for (iter = v; iter; iter = iter->next)
-    {
-        KvpFrame *frame = kvp_value_get_frame((KvpValue*) iter->data);
-        res = g_list_prepend(res, gnc_ab_trans_templ_new_from_kvp(frame));
-    }
-    res = g_list_reverse(res);
-
-    return res;
-}
-
-void
-gnc_ab_trans_templ_free(GncABTransTempl *t)
-{
-    if (!t) return;
-    g_free(t->name);
-    g_free(t->name_key);
-    g_free(t->recp_name);
-    g_free(t->recp_account);
-    g_free(t->recp_bankcode);
-    g_free(t->purpose);
-    g_free(t->purpose_cont);
-    g_free(t);
-}
-
-void
-gnc_ab_trans_templ_list_free(GList *l)
-{
-    GList *iter;
-    for (iter = l; iter; iter = iter->next)
-        gnc_ab_trans_templ_free((GncABTransTempl*) iter->data);
-    g_list_free(l);
-}
-
-KvpFrame *
-gnc_ab_trans_templ_to_kvp(const GncABTransTempl *t)
-{
-    KvpFrame *k;
-
-    g_return_val_if_fail(t, NULL);
-
-    k = kvp_frame_new();
-    kvp_frame_set_slot(k, TT_NAME, kvp_value_new_string(t->name));
-    kvp_frame_set_slot(k, TT_RNAME, kvp_value_new_string(t->recp_name));
-    kvp_frame_set_slot(k, TT_RACC, kvp_value_new_string(t->recp_account));
-    kvp_frame_set_slot(k, TT_RBCODE, kvp_value_new_string(t->recp_bankcode));
-    kvp_frame_set_slot(k, TT_AMOUNT, kvp_value_new_gnc_numeric(t->amount));
-    kvp_frame_set_slot(k, TT_PURPOS, kvp_value_new_string(t->purpose));
-    kvp_frame_set_slot(k, TT_PURPOSCT, kvp_value_new_string(t->purpose_cont));
-
-    return k;
-}
-
-GList *
-gnc_ab_trans_templ_list_to_kvp_list(GList *k)
-{
-    GList *res = NULL;
-    GList *iter;
-
-    for (iter = k; iter; iter = iter->next)
-    {
-        GncABTransTempl *t = (GncABTransTempl*) iter->data;
-        KvpValue *value = kvp_value_new_frame_nc(gnc_ab_trans_templ_to_kvp(t));
-        res = g_list_prepend(res, value);
-    }
-    res = g_list_reverse(res);
-
-    return res;
-}
-
-const gchar *
-gnc_ab_trans_templ_get_name(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, NULL);
-    return t->name;
-}
-
-const gchar *
-gnc_ab_trans_templ_get_recp_name(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, NULL);
-    return t->recp_name;
-}
-
-const gchar *
-gnc_ab_trans_templ_get_recp_account(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, NULL);
-    return t->recp_account;
-}
-
-const gchar *
-gnc_ab_trans_templ_get_recp_bankcode(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, NULL);
-    return t->recp_bankcode;
-}
-
-gnc_numeric
-gnc_ab_trans_templ_get_amount(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, gnc_numeric_zero());
-    return t->amount;
-}
-
-const gchar *
-gnc_ab_trans_templ_get_purpose(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, NULL);
-    return t->purpose;
-}
-
-const gchar *
-gnc_ab_trans_templ_get_purpose_cont(const GncABTransTempl *t)
-{
-    g_return_val_if_fail(t, NULL);
-    return t->purpose_cont;
-}
-
-void
-gnc_ab_trans_templ_set_name(GncABTransTempl *t, const gchar *name)
-{
-    g_return_if_fail(t);
-    g_free(t->name);
-    t->name = g_strdup(name);
-}
-
-void
-gnc_ab_trans_templ_set_recp_name(GncABTransTempl *t, const gchar *recp_name)
-{
-    g_return_if_fail(t);
-    g_free(t->recp_name);
-    t->recp_name = g_strdup(recp_name);
-}
-
-void
-gnc_ab_trans_templ_set_recp_account(GncABTransTempl *t,
-                                    const gchar *recp_account)
-{
-    g_return_if_fail(t);
-    g_free(t->recp_account);
-    t->recp_account = g_strdup(recp_account);
-}
-
-void
-gnc_ab_trans_templ_set_recp_bankcode(GncABTransTempl *t,
-                                     const gchar *recp_bankcode)
-{
-    g_return_if_fail(t);
-    g_free(t->recp_bankcode);
-    t->recp_bankcode = g_strdup(recp_bankcode);
-}
-
-void
-gnc_ab_trans_templ_set_amount(GncABTransTempl *t, gnc_numeric amount)
-{
-    g_return_if_fail(t);
-    t->amount = amount;
-}
-
-void
-gnc_ab_trans_templ_set_purpose(GncABTransTempl *t, const gchar *purpose)
-{
-    g_return_if_fail(t);
-    g_free(t->purpose);
-    t->purpose = g_strdup(purpose);
-}
-
-void
-gnc_ab_trans_templ_set_purpose_cont(GncABTransTempl *t,
-                                    const gchar *purpose_cont)
-{
-    g_return_if_fail(t);
-    g_free(t->purpose_cont);
-    t->purpose_cont = g_strdup(purpose_cont);
-}
diff --git a/src/import-export/aqb/gnc-ab-transfer.c b/src/import-export/aqb/gnc-ab-transfer.c
index 9ca81c0..ec21267 100644
--- a/src/import-export/aqb/gnc-ab-transfer.c
+++ b/src/import-export/aqb/gnc-ab-transfer.c
@@ -35,12 +35,12 @@
 #include <gtk/gtk.h>
 #include <aqbanking/banking.h>
 
-#include "Transaction.h"
+#include <gnc-aqbanking-templates.h>
+#include <Transaction.h>
 #include "dialog-transfer.h"
 #include "gnc-ab-transfer.h"
 #include "gnc-ab-kvp.h"
 #include "gnc-ab-utils.h"
-#include "gnc-ab-trans-templ.h"
 #include "gnc-gwen-gui.h"
 #include "gnc-ui.h"
 
@@ -62,8 +62,7 @@ save_templates(GtkWidget *parent, Account *gnc_acc, GList *templates,
                   "but you cancelled the transfer dialog. "
                   "Do you nevertheless want to store the changes?")))
     {
-        GList *kvp_list = gnc_ab_trans_templ_list_to_kvp_list(templates);
-        gnc_ab_set_book_template_list(gnc_account_get_book(gnc_acc), kvp_list);
+        gnc_ab_set_book_template_list(gnc_account_get_book(gnc_acc), templates);
     }
 }
 
@@ -119,8 +118,8 @@ gnc_ab_maketrans(GtkWidget *parent, Account *gnc_acc,
     }
 
     /* Get list of template transactions */
-    templates = gnc_ab_trans_templ_list_new_from_kvp_list(
-                    gnc_ab_get_book_template_list(gnc_account_get_book(gnc_acc)));
+    templates = gnc_ab_trans_templ_list_new_from_book(
+         gnc_account_get_book(gnc_acc));
 
     /* Create new ABTransDialog */
     td = gnc_ab_trans_dialog_new(parent, ab_acc,
diff --git a/src/import-export/aqb/gnc-ab-utils.h b/src/import-export/aqb/gnc-ab-utils.h
index 12d112a..feec881 100644
--- a/src/import-export/aqb/gnc-ab-utils.h
+++ b/src/import-export/aqb/gnc-ab-utils.h
@@ -127,8 +127,7 @@ gint gnc_AB_BANKING_fini(AB_BANKING *api);
 /**
  * Get the corresponding AqBanking account to the GnuCash account @a gnc_acc.
  * Of course this only works after the GnuCash account has been set up for
- * AqBanking use, i.e. the kvp_frame "hbci/..." has been filled with
- * information.
+ * AqBanking use, i.e. the account's hbci data have been set up and populated.
  *
  * @param api The AB_BANKING to get the AB_ACCOUNT from
  * @param gnc_acc The GnuCash account to query for AB_ACCOUNT reference data
diff --git a/src/import-export/aqb/test/test-kvp.c b/src/import-export/aqb/test/test-kvp.c
index dcb6df1..137522e 100644
--- a/src/import-export/aqb/test/test-kvp.c
+++ b/src/import-export/aqb/test/test-kvp.c
@@ -25,7 +25,7 @@
 
 // for the gnc_ab_get_book_template_list() et al. functions
 #include "import-export/aqb/gnc-ab-kvp.h"
-#include "import-export/aqb/gnc-ab-trans-templ.h"
+#include <gnc-aqbanking-templates.h>
 #include "engine/gnc-hooks.h"
 
 static char* get_filepath(const char* filename)
@@ -78,14 +78,6 @@ test_qofsession_aqb_kvp( void )
         //printf("io_err2 = %d\n", io_err);
         g_assert(io_err == 0);
 
-        // No HBCI slot exists, of course
-
-        {
-            // No HBCI slot exists, of course
-            GList *mylist = gnc_ab_get_book_template_list(qof_session_get_book(new_session));
-            g_assert(mylist == 0);
-        }
-
         g_free(newfile);
         g_free(file1);
 
@@ -121,11 +113,7 @@ test_qofsession_aqb_kvp( void )
             const char* ORIGINAL_NAME = "Some Name";
             const char* CHANGED_NAME = "Some Changed Name";
 
-            GList *kvp_list = gnc_ab_get_book_template_list(book);
-            g_assert(kvp_list != 0); // do we have the slot?!
-            g_assert_cmpint(g_list_length(kvp_list), ==, 1);
-
-            templ_list = gnc_ab_trans_templ_list_new_from_kvp_list(kvp_list);
+            templ_list = gnc_ab_trans_templ_list_new_from_book (book);
             g_assert_cmpint(g_list_length(templ_list), ==, 1);
 
             templ = templ_list->data;
@@ -134,21 +122,16 @@ test_qofsession_aqb_kvp( void )
             // Now we change the name into something else and verify it can be saved
             gnc_ab_trans_templ_set_name(templ, CHANGED_NAME);
             {
-                GList *kvp_list_new = gnc_ab_trans_templ_list_to_kvp_list(templ_list);
-                gnc_ab_trans_templ_list_free(templ_list);
                 g_assert(!qof_instance_get_dirty(QOF_INSTANCE(book))); // not yet dirty
 
                 // Here we save the changed kvp
-                gnc_ab_set_book_template_list(book, kvp_list_new);
+                gnc_ab_set_book_template_list(book, templ_list);
                 g_assert(qof_instance_get_dirty(QOF_INSTANCE(book))); // yup, now dirty
+                gnc_ab_trans_templ_list_free(templ_list);
             }
 
             {
-                GList *mylist = gnc_ab_get_book_template_list(book);
-                g_assert(mylist != 0);
-                g_assert_cmpint(g_list_length(mylist), ==, 1);
-
-                templ_list = gnc_ab_trans_templ_list_new_from_kvp_list(mylist);
+                templ_list = gnc_ab_trans_templ_list_new_from_book (book);
                 g_assert_cmpint(g_list_length(templ_list), ==, 1);
 
                 templ = templ_list->data;
diff --git a/src/libqof/qof/Makefile.am b/src/libqof/qof/Makefile.am
index 86d393e..7bfc7b0 100644
--- a/src/libqof/qof/Makefile.am
+++ b/src/libqof/qof/Makefile.am
@@ -23,6 +23,7 @@ AM_CPPFLAGS = \
   $(BOOST_CPPFLAGS)
 
 libgnc_qof_la_SOURCES =  \
+   gnc-aqbanking-templates.cpp \
    gnc-date.cpp        \
    gnc-int128.cpp      \
    gnc-numeric.cpp     \
@@ -50,6 +51,7 @@ libgnc_qof_la_SOURCES =  \
 qofincludedir = ${pkgincludedir}
 
 qofinclude_HEADERS = \
+   gnc-aqbanking-templates.h \
    gnc-date-p.h      \
    gnc-date.h        \
    gnc-numeric.h     \
diff --git a/src/libqof/qof/gnc-aqbanking-templates.cpp b/src/libqof/qof/gnc-aqbanking-templates.cpp
new file mode 100644
index 0000000..42f4569
--- /dev/null
+++ b/src/libqof/qof/gnc-aqbanking-templates.cpp
@@ -0,0 +1,292 @@
+/********************************************************************
+ * gnc-aqbanking-templates.cpp implements transaction templates     *
+ * for AQBanking.                                                   *
+ * Copyright 2015 John Ralls <jralls at ceridwen.us>                   *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ *                                                                  *
+ ********************************************************************/
+
+/** Class for managing AQBanking Transaction Templates.
+ */
+
+#include <string>
+
+extern "C"
+{
+#include "gnc-aqbanking-templates.h"
+#include "kvp_frame.h"
+#include "qofinstance-p.h"
+}
+
+#include "gnc-rational.hpp"
+
+namespace {
+    static const char* TT_NAME {"name"};
+    static const char* TT_RNAME {"rnam"};
+    static const char* TT_RACC {"racc"};
+    static const char* TT_RBCODE {"rbcd"};
+    static const char* TT_PURPOS {"purp"};
+    static const char* TT_PURPOSCT {"purc"};
+    static const char* TT_AMOUNT {"amou"};
+}
+
+struct _GncABTransTempl
+{
+public:
+    _GncABTransTempl () :
+        m_name(), m_recipient_name(), m_recipient_account(),
+        m_recipient_bankcode(), m_amount(gnc_numeric_zero()), m_purpose(),
+        m_purpose_continuation() {}
+    _GncABTransTempl (const std::string& name,
+                      const std::string& recip_name,
+                      const std::string& recip_account,
+                      const std::string& recip_code,
+                      const GncRational& amount,
+                      const std::string& purpose,
+                      const std::string& purpose_cont) :
+        m_name(name), m_recipient_name(recip_name),
+        m_recipient_account(recip_account), m_recipient_bankcode(recip_code),
+        m_amount(amount), m_purpose(purpose),
+        m_purpose_continuation(purpose_cont) {}
+    KvpFrame* make_kvp_frame();
+    const char* name() const { return m_name.c_str(); }
+    const char* recipient_name() const { return m_recipient_name.c_str(); }
+    const char* recipient_account() const
+        {
+            return m_recipient_account.c_str();
+        }
+    const char* recipient_bankcode() const
+        {
+            return m_recipient_bankcode.c_str();
+        }
+    const GncRational amount() const { return m_amount; }
+    const char* purpose() const { return m_purpose.c_str(); }
+    const char* purpose_continuation() const
+        {
+            return m_purpose_continuation.c_str();
+        }
+    void set_name (const char* name) { m_name = name; }
+    void set_recipient_name (const char* name) { m_recipient_name = name; }
+    void set_recipient_account (const char* account) {
+        m_recipient_account = account;
+    }
+    void set_recipient_bankcode (const char* code) {
+        m_recipient_bankcode = code;
+    }
+    void set_amount (GncRational amount) { m_amount = amount; }
+    void set_purpose (const char* purpose) { m_purpose = purpose; }
+    void set_purpose_continuation (const char* name) { m_name = name; }
+private:
+    std::string m_name;
+    std::string m_recipient_name;
+    std::string m_recipient_account;
+    std::string m_recipient_bankcode;
+    GncRational m_amount;
+    std::string m_purpose;
+    std::string m_purpose_continuation;
+};
+
+KvpFrame*
+_GncABTransTempl::make_kvp_frame()
+{
+    auto frame = kvp_frame_new();
+    kvp_frame_set_slot(frame, TT_NAME, kvp_value_new_string(m_name.c_str()));
+    kvp_frame_set_slot(frame, TT_RNAME,
+                       kvp_value_new_string(m_recipient_name.c_str()));
+    kvp_frame_set_slot(frame, TT_RACC,
+                       kvp_value_new_string(m_recipient_account.c_str()));
+    kvp_frame_set_slot(frame, TT_RBCODE,
+                       kvp_value_new_string(m_recipient_bankcode.c_str()));
+    kvp_frame_set_slot(frame, TT_AMOUNT, kvp_value_new_gnc_numeric(m_amount));
+    kvp_frame_set_slot(frame, TT_PURPOS,
+                       kvp_value_new_string(m_purpose.c_str()));
+    kvp_frame_set_slot(frame, TT_PURPOSCT,
+                       kvp_value_new_string(m_purpose_continuation.c_str()));
+    return frame;
+}
+
+GncABTransTempl*
+gnc_ab_trans_templ_new()
+{
+    return new _GncABTransTempl;
+}
+
+GncABTransTempl*
+gnc_ab_trans_templ_new_full(const gchar *name, const gchar *recp_name,
+                            const gchar *recp_account,
+                            const gchar *recp_bankcode, gnc_numeric amount,
+                            const gchar *purpose, const gchar *purpose_cont)
+{
+    return new _GncABTransTempl(name, recp_name, recp_account, recp_bankcode,
+                                amount, purpose, purpose_cont);
+}
+
+GList*
+gnc_ab_trans_templ_list_new_from_book(QofBook *b)
+{
+    GList *retval = NULL;
+    KvpFrame *toplevel = qof_instance_get_slots (QOF_INSTANCE (b));
+    KvpFrame *hbci = kvp_frame_get_frame (toplevel, "hbci");
+    KvpValue *listval = kvp_frame_get_slot (hbci, "template-list");
+    GList *list = kvp_value_get_glist (listval);
+    for (auto node = list; node != NULL; node = g_list_next (node))
+    {
+        KvpFrame *frame = kvp_value_get_frame (static_cast<KvpValue*>(node->data));
+        auto func = [frame](const char* key)
+            {return kvp_value_get_string(kvp_frame_get_slot(frame, key));};
+        auto templ = new _GncABTransTempl (func(TT_NAME), func(TT_RNAME),
+                                           func(TT_RACC), func(TT_RBCODE),
+                                           kvp_value_get_numeric(kvp_frame_get_slot(frame, TT_AMOUNT)),
+                                           func(TT_PURPOS), func(TT_PURPOSCT));
+        retval = g_list_prepend (retval, templ);
+    }
+    retval = g_list_reverse (retval);
+    return retval;
+}
+
+void
+gnc_ab_trans_templ_free (GncABTransTempl *t)
+{
+    delete t;
+}
+
+void
+gnc_ab_trans_templ_list_free (GList *l)
+{
+    for(GList *node = l; node != NULL; node = g_list_next(node))
+        delete static_cast<_GncABTransTempl*>(node->data);
+}
+
+void
+gnc_ab_set_book_template_list (QofBook *b, GList *template_list)
+{
+    GList *kvp_list = NULL;
+    for (auto node = template_list; node != NULL; node = g_list_next (node))
+    {
+        auto value = kvp_value_new_frame_nc (static_cast<_GncABTransTempl*>(node->data)->make_kvp_frame());
+        kvp_list = g_list_prepend (kvp_list, value);
+    }
+    kvp_list = g_list_reverse (kvp_list);
+    auto value = kvp_value_new_glist_nc(kvp_list);
+    KvpFrame *toplevel = qof_instance_get_slots (QOF_INSTANCE (b));
+    KvpFrame *hbci = kvp_frame_get_frame (toplevel, "hbci");
+    kvp_frame_set_slot_nc (hbci, "template-list", value);
+    qof_instance_set_dirty_flag (QOF_INSTANCE (b), TRUE);
+}
+
+const gchar *
+gnc_ab_trans_templ_get_name(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, NULL);
+    return t->name();
+}
+
+const gchar *
+gnc_ab_trans_templ_get_recp_name(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, NULL);
+    return t->recipient_name();
+}
+
+const gchar *
+gnc_ab_trans_templ_get_recp_account(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, NULL);
+    return t->recipient_account();
+}
+
+const gchar *
+gnc_ab_trans_templ_get_recp_bankcode(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, NULL);
+    return t->recipient_bankcode();
+}
+
+gnc_numeric
+gnc_ab_trans_templ_get_amount(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, gnc_numeric_zero());
+    return t->amount();
+}
+
+const gchar *
+gnc_ab_trans_templ_get_purpose(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, NULL);
+    return t->purpose();
+}
+
+const gchar *
+gnc_ab_trans_templ_get_purpose_cont(const GncABTransTempl *t)
+{
+    g_return_val_if_fail(t, NULL);
+    return t->purpose_continuation();
+}
+
+void
+gnc_ab_trans_templ_set_name(GncABTransTempl *t, const gchar *name)
+{
+    g_return_if_fail(t);
+    t->set_name(name);
+}
+
+void
+gnc_ab_trans_templ_set_recp_name(GncABTransTempl *t, const gchar *recp_name)
+{
+    g_return_if_fail(t);
+    t->set_recipient_name(recp_name);
+}
+
+void
+gnc_ab_trans_templ_set_recp_account(GncABTransTempl *t,
+                                    const gchar *recp_account)
+{
+    g_return_if_fail(t);
+    t->set_recipient_account(recp_account);
+}
+
+void
+gnc_ab_trans_templ_set_recp_bankcode(GncABTransTempl *t,
+                                     const gchar *recp_bankcode)
+{
+    g_return_if_fail(t);
+    t->set_recipient_bankcode(recp_bankcode);
+}
+
+void
+gnc_ab_trans_templ_set_amount(GncABTransTempl *t, gnc_numeric amount)
+{
+    g_return_if_fail(t);
+    t->set_amount(amount);
+}
+
+void
+gnc_ab_trans_templ_set_purpose(GncABTransTempl *t, const gchar *purpose)
+{
+    g_return_if_fail(t);
+    t->set_purpose(purpose);
+}
+
+void
+gnc_ab_trans_templ_set_purpose_cont(GncABTransTempl *t,
+                                    const gchar *purpose_cont)
+{
+    g_return_if_fail(t);
+    t->set_purpose_continuation (purpose_cont);
+}
diff --git a/src/import-export/aqb/gnc-ab-trans-templ.h b/src/libqof/qof/gnc-aqbanking-templates.h
similarity index 86%
rename from src/import-export/aqb/gnc-ab-trans-templ.h
rename to src/libqof/qof/gnc-aqbanking-templates.h
index 2b41c4f..9350d5c 100644
--- a/src/import-export/aqb/gnc-ab-trans-templ.h
+++ b/src/libqof/qof/gnc-aqbanking-templates.h
@@ -33,8 +33,13 @@
 #ifndef GNC_AB_TRANS_TEMPL_H
 #define GNC_AB_TRANS_TEMPL_H
 
-#include <glib.h>
+#ifdef __cplusplus
+extern "C"
+{
+#endif
 
+#include <config.h>
+#include <glib.h>
 #include "qof.h"
 
 G_BEGIN_DECLS
@@ -67,25 +72,25 @@ GncABTransTempl *gnc_ab_trans_templ_new_full(
     const gchar *purpose_cont);
 
 /**
- * Create a template, taking the values from a KvpFrame.
+ * Obtain the list of QofTemplates saved in a Book.
  *
- * @param k KvpFrame
- * @return A newly allocated GncABTransTempl
+ * @param b QofBook containing the templates.
+ * @return A GList of newly allocated GncABTransTempls
  */
-GncABTransTempl *gnc_ab_trans_templ_new_from_kvp(const KvpFrame *k);
+GList *gnc_ab_trans_templ_list_new_from_book(QofBook *b);
 
 /**
- * Create a list of templates from a list of kvp_values which in turn
- * contain a KvpFrame.
+ * Set the GList of kvp_frames of template transactions in the Book @a b to @a
+ * template_list.  No copy of the GList will be stored, the callee becomes the
+ * owner and the caller must not free it.  The book will be marked "dirty".
  *
- * @param v GList of kvp_values
- * @return A GList of newly allocated GncABTransTempls
+ * @param b Book
+ * @param template_list Template list
  */
-GList *gnc_ab_trans_templ_list_new_from_kvp_list(GList *v);
+void gnc_ab_set_book_template_list(QofBook *b, GList *template_list);
 
 /**
  * Free the memory used by a template.
- *
  * @param t GncABTransTempl to be freed
  */
 void gnc_ab_trans_templ_free(GncABTransTempl *t);
@@ -98,23 +103,6 @@ void gnc_ab_trans_templ_free(GncABTransTempl *t);
 void gnc_ab_trans_templ_list_free(GList *l);
 
 /**
- * Create a KvpFrame a given template.
- *
- * @param t Template
- * @return A newly allocated KvpFrame
- */
-KvpFrame *gnc_ab_trans_templ_to_kvp(const GncABTransTempl *t);
-
-/**
- * Create a list of kvp_values, which in turn contain a KvpFrame, from a list
- * of templates.
- *
- * @param k GList of GncABTransTempls
- * @return GList of newly allocated kvp_values
- */
-GList *gnc_ab_trans_templ_list_to_kvp_list(GList *k);
-
-/**
  * @param t Template
  * @return Name of the template, an internal string
  */
@@ -217,7 +205,9 @@ void gnc_ab_trans_templ_set_purpose_cont(GncABTransTempl *t,
         const gchar *purpose_cont);
 
 G_END_DECLS
-
+#ifdef __cplusplus
+}
+#endif
 #endif /* GNC_AB_TRANS_TEMPL_H */
 /** @} */
 /** @} */

commit b4e024078311a846f3f066ce1449e0dee422ba2d
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat Jun 6 10:10:31 2015 -0700

    Make the instance const in qof_instance_get_kvp().

diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 7582ad7..1914e1a 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -108,7 +108,7 @@ void qof_instance_set_idata(gpointer inst, guint32 idata);
 /* Convenience functions to save some typing in property handlers */
 gboolean qof_instance_has_kvp (QofInstance *inst);
 void qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value);
-void qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value);
+void qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *value);
 /* Functions to isolate the KVP mechanism inside QOF for cases where GValue
  * operations won't work.
  */
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index 3ae1e87..ffea2ff 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -1078,7 +1078,7 @@ qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value)
 }
 
 void
-qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value)
+qof_instance_get_kvp (const QofInstance *inst, const gchar *key, GValue *value)
 {
     GValue *temp = kvp_frame_get_gvalue (inst->kvp_data, key);
     if (G_IS_VALUE (temp))

commit 4f4711c564c4eabd99ea74cab907226a2b3cc268
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 4 13:32:15 2015 -0700

    Convert Scrub.c from using direct KVP to routing them through qof_instance.

diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c
index 42d4a38..0bc9794 100644
--- a/src/engine/Scrub.c
+++ b/src/engine/Scrub.c
@@ -50,6 +50,7 @@
 #include "Transaction.h"
 #include "TransactionP.h"
 #include "gnc-commodity.h"
+#include <qofinstance-p.h>
 
 #undef G_LOG_DOMAIN
 #define G_LOG_DOMAIN "gnc.engine.scrub"
@@ -1157,11 +1158,10 @@ xaccAccountDeleteOldData (Account *account)
 {
     if (!account) return;
     xaccAccountBeginEdit (account);
-
-    kvp_frame_set_slot_nc (account->inst.kvp_data, "old-currency", NULL);
-    kvp_frame_set_slot_nc (account->inst.kvp_data, "old-security", NULL);
-    kvp_frame_set_slot_nc (account->inst.kvp_data, "old-currency-scu", NULL);
-    kvp_frame_set_slot_nc (account->inst.kvp_data, "old-security-scu", NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (account), "old-currency", NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (account), "old-security", NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (account), "old-currency-scu", NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (account), "old-security-scu", NULL);
     qof_instance_set_dirty (QOF_INSTANCE (account));
     xaccAccountCommitEdit (account);
 }
@@ -1262,30 +1262,28 @@ xaccAccountTreeScrubQuoteSources (Account *root, gnc_commodity_table *table)
 void
 xaccAccountScrubKvp (Account *account)
 {
+    GValue v = G_VALUE_INIT;
     const gchar *str;
     gchar *str2;
-    KvpFrame *frame;
 
     if (!account) return;
 
-    str = kvp_frame_get_string(account->inst.kvp_data, "notes");
-    if (str)
+    qof_instance_get_kvp (QOF_INSTANCE (account), "notes", &v);
+    if (G_VALUE_HOLDS_STRING (&v))
     {
-        str2 = g_strstrip(g_strdup(str));
+        str2 = g_strstrip(g_value_dup_string(&v));
         if (strlen(str2) == 0)
-            kvp_frame_set_slot_nc (account->inst.kvp_data, "notes", NULL);
+            qof_instance_slot_delete (QOF_INSTANCE (account), "notes");
         g_free(str2);
     }
 
-    str = kvp_frame_get_string(account->inst.kvp_data, "placeholder");
-    if (str && strcmp(str, "false") == 0)
-        kvp_frame_set_slot_nc (account->inst.kvp_data, "placeholder", NULL);
+    qof_instance_get_kvp (QOF_INSTANCE (account), "placeholder", &v);
+    if ((G_VALUE_HOLDS_STRING (&v) &&
+        strcmp(g_value_get_string (&v), "false") == 0) ||
+        (G_VALUE_HOLDS_BOOLEAN (&v) && ! g_value_get_boolean (&v)))
+        qof_instance_slot_delete (QOF_INSTANCE (account), "placeholder");
 
-    frame = kvp_frame_get_frame(account->inst.kvp_data, "hbci");
-    if (frame && kvp_frame_is_empty(frame))
-    {
-        kvp_frame_set_frame_nc(account->inst.kvp_data, "hbci", NULL);
-    }
+    qof_instance_slot_delete_if_empty (QOF_INSTANCE (account), "hbci");
 }
 
 /* ================================================================ */

commit 232dd4c0dc35d15b0f8c8c91e30d76f8cf5913b1
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 4 13:31:14 2015 -0700

    Provide qof_instance with functions to delete slots.

diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 783a9a4..7582ad7 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -126,6 +126,9 @@ gboolean qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
 void qof_instance_kvp_merge_guids (const QofInstance *target,
                                    const QofInstance *donor, const char* path);
 gboolean qof_instance_has_slot (const QofInstance *inst, const char *path);
+void qof_instance_slot_delete (const QofInstance *inst, const char *path);
+void qof_instance_slot_delete_if_empty (const QofInstance *inst,
+                                        const char *path);
 
 #ifdef __cplusplus
 }
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index ed0b2a2..3ae1e87 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -1273,5 +1273,19 @@ qof_instance_has_slot (const QofInstance *inst, const char *path)
     return kvp_frame_get_value (inst->kvp_data, path) != NULL;
 }
 
+void
+qof_instance_slot_delete (const QofInstance *inst, const char *path)
+{
+    kvp_frame_set_frame_nc (inst->kvp_data, path, NULL);
+}
+
+void
+qof_instance_slot_delete_if_empty (const QofInstance *inst, const char *path)
+{
+    KvpFrame *frame = kvp_frame_get_frame (inst->kvp_data, path);
+    if (frame && kvp_frame_is_empty (frame))
+        kvp_frame_set_frame_nc (inst->kvp_data, path, NULL);
+}
+
 /* ========================== END OF FILE ======================= */
 

commit eb2d556086e3aa768211b615e2efcaa2cd4bdb98
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 4 13:29:01 2015 -0700

    Move initializing the GValue to the correct type to qof_instance_set_kvp.
    
    And ensure that all returns are checked to be the expected type.

diff --git a/src/engine/Account.c b/src/engine/Account.c
index 02b0916..7ae196d 100644
--- a/src/engine/Account.c
+++ b/src/engine/Account.c
@@ -2314,12 +2314,9 @@ static const char*
 get_kvp_string_tag (const Account *acc, const char *tag)
 {
     GValue v = G_VALUE_INIT;
-    const char* s;
     if (acc == NULL || tag == NULL) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (acc), tag, &v);
-    s = g_value_get_string (&v);
-    return s;
+    return G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
 }
 
 void
@@ -3110,13 +3107,13 @@ gnc_commodity *
 DxaccAccountGetCurrency (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
-    const char *s;
+    const char *s = NULL;
     gnc_commodity_table *table;
 
     if (!acc) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "old-currency", &v);
-    s = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        s = g_value_get_string (&v);
     if (!s) return NULL;
 
     table = gnc_commodity_table_get_table (qof_instance_get_book(acc));
@@ -3789,9 +3786,8 @@ xaccAccountGetTaxRelated (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_BOOLEAN);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "tax-related", &v);
-    return g_value_get_boolean (&v);
+    return G_VALUE_HOLDS_BOOLEAN (&v) ? g_value_get_boolean (&v) : FALSE;
 }
 
 void
@@ -3814,10 +3810,8 @@ xaccAccountGetTaxUSCode (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "/tax-US/code", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_STRING (&v), FALSE);
-    return g_value_get_string (&v);
+    return G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
 }
 
 void
@@ -3839,11 +3833,9 @@ xaccAccountGetTaxUSPayerNameSource (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE(acc),
                           "/tax-US/payer-name-source", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_STRING (&v), FALSE);
-    return g_value_get_string (&v);
+    return G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
  }
 
 void
@@ -3863,13 +3855,12 @@ xaccAccountSetTaxUSPayerNameSource (Account *acc, const char *source)
 gint64
 xaccAccountGetTaxUSCopyNumber (const Account *acc)
 {
-    gint64 copy_number;
+    gint64 copy_number = 0;
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_INT64);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "/tax-US/copy-number", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
-    copy_number = g_value_get_int64 (&v);
+    if (G_VALUE_HOLDS_INT64 (&v))
+        copy_number = g_value_get_int64 (&v);
 
     return (copy_number == 0) ? 1 : copy_number;
 }
@@ -3902,10 +3893,12 @@ xaccAccountGetPlaceholder (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_BOOLEAN);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "placeholder", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (&v), FALSE);
-    return g_value_get_boolean (&v);
+    if (G_VALUE_HOLDS_BOOLEAN (&v))
+         return g_value_get_boolean (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         return strcmp (g_value_get_string (&v), "true") == 0;
+    return FALSE;
 }
 
 void
@@ -3951,10 +3944,8 @@ xaccAccountGetHidden (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_BOOLEAN);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "hidden", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (&v), FALSE);
-    return g_value_get_boolean (&v);
+    return G_VALUE_HOLDS_BOOLEAN (&v) ? g_value_get_boolean (&v) : FALSE;
 }
 
 void
@@ -4256,13 +4247,12 @@ xaccAccountIsPriced(const Account *acc)
 gboolean
 xaccAccountGetReconcileLastDate (const Account *acc, time64 *last_date)
 {
-    gint64 date;
+    gint64 date = 0;
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_INT64);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "reconcile-info/last-date", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
-    date = g_value_get_int64 (&v);
+    if (G_VALUE_HOLDS_INT64 (&v))
+        date = g_value_get_int64 (&v);
 
     if (date)
     {
@@ -4298,18 +4288,18 @@ xaccAccountGetReconcileLastInterval (const Account *acc,
                                      int *months, int *days)
 {
     GValue v1, v2;
-    int m, d;
+    int64_t m = 0, d = 0;
 
     if (!acc) return FALSE;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v1, G_TYPE_INT64);
     qof_instance_get_kvp (QOF_INSTANCE(acc),
                           "reconcile-info/last-interval/months", &v1);
-    g_value_init (&v2, G_TYPE_INT64);
     qof_instance_get_kvp (QOF_INSTANCE(acc),
                           "reconcile-info/last-interval/days", &v2);
-    m = g_value_get_int64 (&v1);
-    d = g_value_get_int64 (&v2);
+    if (G_VALUE_HOLDS_INT64 (&v1))
+        m = g_value_get_int64 (&v1);
+    if (G_VALUE_HOLDS_INT64 (&v2))
+        d = g_value_get_int64 (&v2);
     if (m && d)
     {
         if (months)
@@ -4349,14 +4339,13 @@ xaccAccountSetReconcileLastInterval (Account *acc, int months, int days)
 gboolean
 xaccAccountGetReconcilePostponeDate (const Account *acc, time64 *postpone_date)
 {
-    gint64 date;
+    gint64 date = 0;
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_INT64);
     qof_instance_get_kvp (QOF_INSTANCE(acc),
                           "reconcile-info/postpone/date", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
-    date = g_value_get_int64 (&v);
+    if (G_VALUE_HOLDS_INT64 (&v))
+        date = g_value_get_int64 (&v);
 
     if (date)
     {
@@ -4392,14 +4381,13 @@ gboolean
 xaccAccountGetReconcilePostponeBalance (const Account *acc,
                                         gnc_numeric *balance)
 {
-    gnc_numeric bal;
+    gnc_numeric bal = gnc_numeric_zero ();
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, GNC_TYPE_NUMERIC);
     qof_instance_get_kvp (QOF_INSTANCE(acc),
                           "reconcile-info/postpone/balance", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
-    bal = *(gnc_numeric*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_INT64 (&v))
+        bal = *(gnc_numeric*)g_value_get_boxed (&v);
 
     if (bal.denom)
     {
@@ -4455,11 +4443,9 @@ xaccAccountGetAutoInterestXfer (const Account *acc, gboolean default_value)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_BOOLEAN);
     qof_instance_get_kvp (QOF_INSTANCE(acc),
                           "reconcile-info/auto-interest-transfer", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (&v), FALSE);
-    return g_value_get_boolean (&v);
+    return G_VALUE_HOLDS_BOOLEAN (&v) ? g_value_get_boolean (&v) : FALSE;
 }
 
 /********************************************************************\
@@ -4488,10 +4474,8 @@ xaccAccountGetLastNum (const Account *acc)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "last-num", &v);
-    g_return_val_if_fail (G_VALUE_HOLDS_STRING (&v), FALSE);
-    return g_value_get_string (&v);
+    return G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
 }
 
 /********************************************************************\
@@ -4562,13 +4546,13 @@ xaccAccountGainsAccount (Account *acc, gnc_commodity *curr)
     GValue v = G_VALUE_INIT;
     gchar *curr_name = g_strdup_printf ("/lot-mgmt/gains-act/%s",
                                       gnc_commodity_get_unique_name (curr));
-    GncGUID *guid;
+    GncGUID *guid = NULL;
     Account *gains_account;
 
     g_return_val_if_fail (acc != NULL, NULL);
-    g_value_init (&v, GNC_TYPE_GUID);
     qof_instance_get_kvp (QOF_INSTANCE(acc), curr_name, &v);
-    guid = (GncGUID*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        guid = (GncGUID*)g_value_get_boxed (&v);
     if (guid == NULL) /* No gains account for this currency */
     {
         gains_account = GetOrMakeOrphanAccount (gnc_account_get_root (acc),
@@ -4630,9 +4614,8 @@ dxaccAccountGetPriceSrc(const Account *acc)
 
     if (!xaccAccountIsPriced(acc)) return NULL;
 
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE(acc), "old-price-source", &v);
-    return g_value_get_string (&v);
+    return G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
 }
 
 /********************************************************************\
@@ -4661,9 +4644,8 @@ dxaccAccountGetQuoteTZ(const Account *acc)
     GValue v = G_VALUE_INIT;
     if (!acc) return NULL;
     if (!xaccAccountIsPriced(acc)) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (acc), "old-quote-tz", &v);
-    return g_value_get_string (&v);
+    return G_VALUE_HOLDS_STRING (&v) ? g_value_get_string (&v) : NULL;
 }
 
 /********************************************************************\
@@ -4700,10 +4682,9 @@ xaccAccountGetReconcileChildrenStatus(const Account *acc)
      */
     GValue v = G_VALUE_INIT;
     if (!acc) return FALSE;
-    g_value_init (&v, G_TYPE_BOOLEAN);
     qof_instance_get_kvp (QOF_INSTANCE (acc),
                           "reconcile-info/include-children", &v);
-    return g_value_get_int64 (&v);
+    return G_VALUE_HOLDS_INT64 (&v) ? g_value_get_int64 (&v) : FALSE;
 }
 
 /********************************************************************\
@@ -5095,7 +5076,7 @@ gnc_imap_find_account (GncImportMatchMap *imap,
                        const char *key)
 {
     GValue v = G_VALUE_INIT;
-    GncGUID * guid;
+    GncGUID * guid = NULL;
     char *kvp_path;
 
     if (!imap || !key) return NULL;
@@ -5103,9 +5084,9 @@ gnc_imap_find_account (GncImportMatchMap *imap,
         kvp_path = g_strdup_printf (IMAP_FRAME "/%s", key);
     else
         kvp_path = g_strdup_printf (IMAP_FRAME "/%s/%s", category, key);
-    g_value_init (&v, GNC_TYPE_GUID);
     qof_instance_get_kvp (QOF_INSTANCE (imap->acc), kvp_path, &v);
-    guid = (GncGUID*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        guid = (GncGUID*)g_value_get_boxed (&v);
     g_free (kvp_path);
     return xaccAccountLookup (guid, imap->book);
 }
@@ -5483,7 +5464,6 @@ gnc_imap_add_account_bayes(GncImportMatchMap *imap,
                                     (char*)current_token->data,
                                     account_fullname);
 
-        g_value_init (&value, G_TYPE_INT64);
         qof_instance_get_kvp (QOF_INSTANCE (imap->acc), kvp_path, &value);
         /* if the token/account is already in the tree, read the current
          * value from the tree and use this for the basis of the value we
diff --git a/src/engine/Split.c b/src/engine/Split.c
index fc95158..a8d5f17 100644
--- a/src/engine/Split.c
+++ b/src/engine/Split.c
@@ -1085,7 +1085,7 @@ xaccSplitDetermineGainStatus (Split *split)
 {
     Split *other;
     GValue v = G_VALUE_INIT;
-    GncGUID *guid;
+    GncGUID *guid = NULL;
 
     if (GAINS_STATUS_UNKNOWN != split->gains) return;
 
@@ -1097,9 +1097,9 @@ xaccSplitDetermineGainStatus (Split *split)
         return;
     }
 
-    g_value_init (&v, GNC_TYPE_GUID);
     qof_instance_get_kvp (QOF_INSTANCE (split), "gains-source", &v);
-    guid = (GncGUID*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        guid = (GncGUID*)g_value_get_boxed (&v);
     if (!guid)
     {
         // CHECKME: We leave split->gains_split alone.  Is that correct?
@@ -2012,12 +2012,12 @@ const char *
 xaccSplitGetType(const Split *s)
 {
     GValue v = G_VALUE_INIT;
-    const char *split_type;
+    const char *split_type = NULL;
 
     if (!s) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (s), "split-type", &v);
-    split_type = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        split_type = g_value_get_string (&v);
     return split_type ? split_type : "normal";
 }
 
@@ -2167,11 +2167,11 @@ gnc_numeric
 xaccSplitVoidFormerAmount(const Split *split)
 {
     GValue v = G_VALUE_INIT;
-    gnc_numeric *num;
+    gnc_numeric *num = NULL;
     g_return_val_if_fail(split, gnc_numeric_zero());
-    g_value_init (&v, GNC_TYPE_NUMERIC);
     qof_instance_get_kvp (QOF_INSTANCE (split), void_former_amt_str, &v);
-    num = (gnc_numeric*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        num = (gnc_numeric*)g_value_get_boxed (&v);
     return num ? *num : gnc_numeric_zero();
 }
 
@@ -2179,11 +2179,11 @@ gnc_numeric
 xaccSplitVoidFormerValue(const Split *split)
 {
     GValue v = G_VALUE_INIT;
-    gnc_numeric *num;
+    gnc_numeric *num = NULL;
     g_return_val_if_fail(split, gnc_numeric_zero());
-    g_value_init (&v, GNC_TYPE_NUMERIC);
     qof_instance_get_kvp (QOF_INSTANCE (split), void_former_val_str, &v);
-    num = (gnc_numeric*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        num = (gnc_numeric*)g_value_get_boxed (&v);
     return num ? *num : gnc_numeric_zero();
 }
 
diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c
index df03fb9..bd0db9d 100644
--- a/src/engine/Transaction.c
+++ b/src/engine/Transaction.c
@@ -2200,9 +2200,10 @@ xaccTransGetAssociation (const Transaction *trans)
 {
     GValue v = G_VALUE_INIT;
     if (!trans) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), assoc_uri_str, &v);
-    return g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         return g_value_get_string (&v);
+    return NULL;
 }
 
 const char *
@@ -2210,9 +2211,10 @@ xaccTransGetNotes (const Transaction *trans)
 {
     GValue v = G_VALUE_INIT;
     if (!trans) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
-    return g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         return g_value_get_string (&v);
+    return NULL;
 }
 
 gboolean
@@ -2220,9 +2222,10 @@ xaccTransGetIsClosingTxn (const Transaction *trans)
 {
     GValue v = G_VALUE_INIT;
     if (!trans) return FALSE;
-    g_value_init (&v, G_TYPE_INT64);
     qof_instance_get_kvp (QOF_INSTANCE (trans), trans_is_closing_str, &v);
-    return g_value_get_int64 (&v);
+    if (G_VALUE_HOLDS_INT64 (&v))
+         return g_value_get_int64 (&v);
+    return FALSE;
 }
 
 /********************************************************************\
@@ -2273,9 +2276,9 @@ xaccTransGetDatePostedGDate (const Transaction *trans)
          * from there because it doesn't suffer from time zone
          * shifts. */
 	GValue v = G_VALUE_INIT;
-	g_value_init (&v, G_TYPE_DATE);
 	qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_DATE_POSTED, &v);
-	result = *(GDate*)g_value_get_boxed (&v);
+        if (G_VALUE_HOLDS_BOXED (&v))
+             result = *(GDate*)g_value_get_boxed (&v);
 	if (! g_date_valid (&result))
             result = timespec_to_gdate(xaccTransRetDatePostedTS(trans));
     }
@@ -2299,9 +2302,9 @@ xaccTransGetDateDueTS (const Transaction *trans, Timespec *ts)
     GValue v = G_VALUE_INIT;
     if (!trans || !ts) return;
 
-    g_value_init (&v, GNC_TYPE_TIMESPEC);
     qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_DATE_DUE_KVP, &v);
-    *ts = *(Timespec*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+         *ts = *(Timespec*)g_value_get_boxed (&v);
     if (ts->tv_sec == 0)
         xaccTransGetDatePostedTS (trans, ts);
 }
@@ -2317,13 +2320,13 @@ xaccTransRetDateDueTS (const Transaction *trans)
 char
 xaccTransGetTxnType (const Transaction *trans)
 {
-    const char *s;
+    const char *s = NULL;
     GValue v = G_VALUE_INIT;
 
     if (!trans) return TXN_TYPE_NONE;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_TXN_TYPE_KVP, &v);
-    s = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         s = g_value_get_string (&v);
     if (s && strlen (s) == 0)
 	return *s;
 
@@ -2337,11 +2340,11 @@ xaccTransGetReadOnly (const Transaction *trans)
      * for performance reasons, since its checked every trans commit.
      */
     GValue v = G_VALUE_INIT;
-    const char *s;
+    const char *s = NULL;
     if (trans == NULL) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE(trans), TRANS_READ_ONLY_REASON, &v);
-    s = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         s = g_value_get_string (&v);
     if (s && strlen (s))
 	return s;
 
@@ -2529,9 +2532,11 @@ xaccTransVoid(Transaction *trans, const char *reason)
     g_return_if_fail(trans && reason);
 
     xaccTransBeginEdit(trans);
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
-    qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
+    else
+        g_value_init (&v, G_TYPE_STRING);
 
     g_value_set_string (&v, _("Voided transaction"));
     qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
@@ -2552,13 +2557,13 @@ xaccTransVoid(Transaction *trans, const char *reason)
 gboolean
 xaccTransGetVoidStatus(const Transaction *trans)
 {
-    const char *s;
+    const char *s = NULL;
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(trans, FALSE);
 
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
-    s = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         s = g_value_get_string (&v);
     return s && strlen(s);
 }
 
@@ -2568,22 +2573,23 @@ xaccTransGetVoidReason(const Transaction *trans)
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(trans, FALSE);
 
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
-    return g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+         return g_value_get_string (&v);
+    return NULL;
 }
 
 Timespec
 xaccTransGetVoidTime(const Transaction *tr)
 {
     GValue v = G_VALUE_INIT;
-    const char *s;
+    const char *s = NULL;
     Timespec void_time = {0, 0}, *ts;
 
     g_return_val_if_fail(tr, void_time);
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (tr), void_time_str, &v);
-    s = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        s = g_value_get_string (&v);
     if (s)
 	return gnc_iso8601_to_timespec_gmt (s);
     return void_time;
@@ -2593,17 +2599,18 @@ void
 xaccTransUnvoid (Transaction *trans)
 {
     GValue v = G_VALUE_INIT;
-    const char *s;
+    const char *s = NULL;
     g_return_if_fail(trans);
 
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
-    s = g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        s = g_value_get_string (&v);
     if (s == NULL) return; /* Transaction isn't voided. Bail. */
     xaccTransBeginEdit(trans);
 
     qof_instance_get_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
-    qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
     qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, NULL);
     qof_instance_set_kvp (QOF_INSTANCE (trans), void_reason_str, NULL);
     qof_instance_set_kvp (QOF_INSTANCE (trans), void_time_str, NULL);
@@ -2648,10 +2655,11 @@ xaccTransGetReversedBy(const Transaction *trans)
 {
     GValue v = G_VALUE_INIT;
     g_return_val_if_fail(trans, NULL);
-    g_value_init (&v, GNC_TYPE_GUID);
     qof_instance_get_kvp (QOF_INSTANCE(trans), TRANS_REVERSED_BY, &v);
-    return xaccTransLookup((GncGUID*)g_value_get_boxed (&v),
-			   qof_instance_get_book(trans));
+    if (G_VALUE_HOLDS_BOXED (&v))
+        return xaccTransLookup((GncGUID*)g_value_get_boxed (&v),
+                               qof_instance_get_book(trans));
+    return NULL;
 }
 
 void
@@ -2698,9 +2706,9 @@ xaccTransScrubGainsDate (Transaction *trans)
         xaccSplitDetermineGainStatus(s);
 
         if ((GAINS_STATUS_GAINS & s->gains) &&
-                s->gains_split &&
-                ((s->gains_split->gains & GAINS_STATUS_DATE_DIRTY) ||
-                 (s->gains & GAINS_STATUS_DATE_DIRTY)))
+            s->gains_split &&
+            ((s->gains_split->gains & GAINS_STATUS_DATE_DIRTY) ||
+             (s->gains & GAINS_STATUS_DATE_DIRTY)))
         {
             Transaction *source_trans = s->gains_split->parent;
             ts = source_trans->date_posted;
@@ -2752,8 +2760,8 @@ restart:
                    if ((s->gains & GAINS_STATUS_VDIRTY) ||
                        (s->gains_split &&
                         (s->gains_split->gains & GAINS_STATUS_VDIRTY)))
-                   xaccSplitComputeCapGains(s, gain_acc);
-                  );
+                       xaccSplitComputeCapGains(s, gain_acc);
+        );
 
     LEAVE("(trans=%p)", trans);
 }
@@ -2825,85 +2833,85 @@ trans_is_balanced_p (const Transaction *trans)
 gboolean xaccTransRegister (void)
 {
     static QofParam params[] =
-    {
-        {
-            TRANS_NUM, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccTransGetNum,
-            (QofSetterFunc)qofTransSetNum,
-            qof_string_number_compare_func
-        },
-        {
-            TRANS_DESCRIPTION, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccTransGetDescription,
-            (QofSetterFunc)qofTransSetDescription
-        },
-        {
-            TRANS_DATE_ENTERED, QOF_TYPE_DATE,
-            (QofAccessFunc)xaccTransRetDateEnteredTS,
-            (QofSetterFunc)qofTransSetDateEntered
-        },
-        {
-            TRANS_DATE_POSTED, QOF_TYPE_DATE,
-            (QofAccessFunc)xaccTransRetDatePostedTS,
-            (QofSetterFunc)qofTransSetDatePosted
-        },
-        {
-            TRANS_DATE_DUE, QOF_TYPE_DATE,
-            (QofAccessFunc)xaccTransRetDateDueTS, NULL
-        },
-        {
-            TRANS_IMBALANCE, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccTransGetImbalanceValue, NULL
-        },
-        {
-            TRANS_NOTES, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccTransGetNotes,
-            (QofSetterFunc)qofTransSetNotes
-        },
         {
-            TRANS_ASSOCIATION, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccTransGetAssociation,
-            (QofSetterFunc)xaccTransSetAssociation
-        },
-        {
-            TRANS_IS_CLOSING, QOF_TYPE_BOOLEAN,
-            (QofAccessFunc)xaccTransGetIsClosingTxn, NULL
-        },
-        {
-            TRANS_IS_BALANCED, QOF_TYPE_BOOLEAN,
-            (QofAccessFunc)trans_is_balanced_p, NULL
-        },
-        {
-            TRANS_TYPE, QOF_TYPE_CHAR,
-            (QofAccessFunc)xaccTransGetTxnType,
-            (QofSetterFunc)xaccTransSetTxnType
-        },
-        {
-            TRANS_VOID_STATUS, QOF_TYPE_BOOLEAN,
-            (QofAccessFunc)xaccTransGetVoidStatus, NULL
-        },
-        {
-            TRANS_VOID_REASON, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccTransGetVoidReason, NULL
-        },
-        {
-            TRANS_VOID_TIME, QOF_TYPE_DATE,
-            (QofAccessFunc)xaccTransGetVoidTime, NULL
-        },
-        {
-            TRANS_SPLITLIST, GNC_ID_SPLIT,
-            (QofAccessFunc)xaccTransGetSplitList, NULL
-        },
-        {
-            QOF_PARAM_BOOK, QOF_ID_BOOK,
-            (QofAccessFunc)qof_instance_get_book, NULL
-        },
-        {
-            QOF_PARAM_GUID, QOF_TYPE_GUID,
-            (QofAccessFunc)qof_entity_get_guid, NULL
-        },
-        { NULL },
-    };
+            {
+                TRANS_NUM, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccTransGetNum,
+                (QofSetterFunc)qofTransSetNum,
+                qof_string_number_compare_func
+            },
+            {
+                TRANS_DESCRIPTION, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccTransGetDescription,
+                (QofSetterFunc)qofTransSetDescription
+            },
+            {
+                TRANS_DATE_ENTERED, QOF_TYPE_DATE,
+                (QofAccessFunc)xaccTransRetDateEnteredTS,
+                (QofSetterFunc)qofTransSetDateEntered
+            },
+            {
+                TRANS_DATE_POSTED, QOF_TYPE_DATE,
+                (QofAccessFunc)xaccTransRetDatePostedTS,
+                (QofSetterFunc)qofTransSetDatePosted
+            },
+            {
+                TRANS_DATE_DUE, QOF_TYPE_DATE,
+                (QofAccessFunc)xaccTransRetDateDueTS, NULL
+            },
+            {
+                TRANS_IMBALANCE, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccTransGetImbalanceValue, NULL
+            },
+            {
+                TRANS_NOTES, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccTransGetNotes,
+                (QofSetterFunc)qofTransSetNotes
+            },
+            {
+                TRANS_ASSOCIATION, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccTransGetAssociation,
+                (QofSetterFunc)xaccTransSetAssociation
+            },
+            {
+                TRANS_IS_CLOSING, QOF_TYPE_BOOLEAN,
+                (QofAccessFunc)xaccTransGetIsClosingTxn, NULL
+            },
+            {
+                TRANS_IS_BALANCED, QOF_TYPE_BOOLEAN,
+                (QofAccessFunc)trans_is_balanced_p, NULL
+            },
+            {
+                TRANS_TYPE, QOF_TYPE_CHAR,
+                (QofAccessFunc)xaccTransGetTxnType,
+                (QofSetterFunc)xaccTransSetTxnType
+            },
+            {
+                TRANS_VOID_STATUS, QOF_TYPE_BOOLEAN,
+                (QofAccessFunc)xaccTransGetVoidStatus, NULL
+            },
+            {
+                TRANS_VOID_REASON, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccTransGetVoidReason, NULL
+            },
+            {
+                TRANS_VOID_TIME, QOF_TYPE_DATE,
+                (QofAccessFunc)xaccTransGetVoidTime, NULL
+            },
+            {
+                TRANS_SPLITLIST, GNC_ID_SPLIT,
+                (QofAccessFunc)xaccTransGetSplitList, NULL
+            },
+            {
+                QOF_PARAM_BOOK, QOF_ID_BOOK,
+                (QofAccessFunc)qof_instance_get_book, NULL
+            },
+            {
+                QOF_PARAM_GUID, QOF_TYPE_GUID,
+                (QofAccessFunc)qof_entity_get_guid, NULL
+            },
+            { NULL },
+        };
 
     qof_class_register (GNC_ID_TRANS, (QofSortFunc)xaccTransOrder, params);
 
diff --git a/src/engine/gnc-budget.c b/src/engine/gnc-budget.c
index c9be5d1..f748f75 100644
--- a/src/engine/gnc-budget.c
+++ b/src/engine/gnc-budget.c
@@ -554,14 +554,16 @@ gnc_budget_is_account_period_value_set(const GncBudget *budget,
 {
     GValue v = G_VALUE_INIT;
     gchar path[BUF_SIZE];
+    gconstpointer ptr = NULL;
 
     g_return_val_if_fail(GNC_IS_BUDGET(budget), FALSE);
     g_return_val_if_fail(account, FALSE);
 
     make_period_path (account, period_num, path);
-    g_value_init (&v, GNC_TYPE_NUMERIC);
     qof_instance_get_kvp (QOF_INSTANCE (budget), path, &v);
-    return (g_value_get_boxed (&v) != NULL);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        ptr = g_value_get_boxed (&v);
+    return (ptr != NULL);
 }
 
 gnc_numeric
@@ -569,17 +571,17 @@ gnc_budget_get_account_period_value(const GncBudget *budget,
                                     const Account *account,
                                     guint period_num)
 {
-    gnc_numeric *numeric;
+    gnc_numeric *numeric = NULL;
     gchar path[BUF_SIZE];
     GValue v = G_VALUE_INIT;
 
     g_return_val_if_fail(GNC_IS_BUDGET(budget), gnc_numeric_zero());
     g_return_val_if_fail(account, gnc_numeric_zero());
 
-    g_value_init (&v, GNC_TYPE_NUMERIC);
     make_period_path (account, period_num, path);
     qof_instance_get_kvp (QOF_INSTANCE (budget), path, &v);
-    numeric = (gnc_numeric*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        numeric = (gnc_numeric*)g_value_get_boxed (&v);
 
     if (numeric)
         return *numeric;
diff --git a/src/engine/gnc-lot.c b/src/engine/gnc-lot.c
index 7e7145c..e31fd74 100644
--- a/src/engine/gnc-lot.c
+++ b/src/engine/gnc-lot.c
@@ -436,9 +436,10 @@ gnc_lot_get_title (const GNCLot *lot)
 {
     GValue v = G_VALUE_INIT;
     if (!lot) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (lot), "/title", &v);
-    return g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        return g_value_get_string (&v);
+    return NULL;
 }
 
 const char *
@@ -446,9 +447,10 @@ gnc_lot_get_notes (const GNCLot *lot)
 {
     GValue v = G_VALUE_INIT;
     if (!lot) return NULL;
-    g_value_init (&v, G_TYPE_STRING);
     qof_instance_get_kvp (QOF_INSTANCE (lot), "/notes", &v);
-    return g_value_get_string (&v);
+    if (G_VALUE_HOLDS_STRING (&v))
+        return g_value_get_string (&v);
+    return NULL;
 }
 
 void
diff --git a/src/engine/gncJob.c b/src/engine/gncJob.c
index 284f1b5..bd4c672 100644
--- a/src/engine/gncJob.c
+++ b/src/engine/gncJob.c
@@ -454,11 +454,11 @@ const char * gncJobGetReference (const GncJob *job)
 gnc_numeric gncJobGetRate (const GncJob *job)
 {
     GValue v = G_VALUE_INIT;
-    gnc_numeric *rate;
+    gnc_numeric *rate = NULL;
     if (!job) return gnc_numeric_zero ();
-    g_value_init (&v, GNC_TYPE_NUMERIC);
     qof_instance_get_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, &v);
-    rate = (gnc_numeric*)g_value_get_boxed (&v);
+    if (G_VALUE_HOLDS_BOXED (&v))
+        rate = (gnc_numeric*)g_value_get_boxed (&v);
     if (rate)
         return *rate;
     return gnc_numeric_zero();
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index 28c45ea..ed0b2a2 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -1081,8 +1081,11 @@ void
 qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value)
 {
     GValue *temp = kvp_frame_get_gvalue (inst->kvp_data, key);
-    if (temp)
+    if (G_IS_VALUE (temp))
     {
+        if (G_IS_VALUE (value))
+            g_value_unset (value);
+        g_value_init (value, G_VALUE_TYPE (temp));
 	g_value_copy (temp, value);
 	gnc_gvalue_free (temp);
     }

commit 57ba97422de3da59e363fd152b172de009beacc8
Author: John Ralls <jralls at ceridwen.us>
Date:   Tue Jun 2 13:02:16 2015 -0700

    Rename the hash-table functions so that they don't contain "kvp".
    
    They don't have anything to do with KVP. What were they doing in kvp-utils
    in the first place?

diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 95bc252..8411b91 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -53,32 +53,32 @@ typedef struct
 {
      gpointer key;
      gpointer value;
-} GHashTableKVPair;
+} HashEntry;
 
 static void
-kv_pair_helper(gpointer key, gpointer val, gpointer user_data)
+hash_entry_insert(gpointer key, gpointer val, gpointer user_data)
 {
     GSList **result = (GSList **) user_data;
-    GHashTableKVPair *kvp = g_new(GHashTableKVPair, 1);
+    HashEntry *entry = g_new(HashEntry, 1);
 
-    kvp->key = key;
-    kvp->value = val;
-    *result = g_slist_prepend(*result, kvp);
+    entry->key = key;
+    entry->value = val;
+    *result = g_slist_prepend(*result, entry);
 }
 
 static GSList *
-g_hash_table_key_value_pairs(GHashTable *table)
+hash_table_to_list(GHashTable *table)
 {
     GSList *result_list = NULL;
-    g_hash_table_foreach(table, kv_pair_helper, &result_list);
+    g_hash_table_foreach(table, hash_entry_insert, &result_list);
     return result_list;
 }
 
 static void
-g_hash_table_kv_pair_free_gfunc(gpointer data, G_GNUC_UNUSED gpointer user_data)
+hash_entry_free_gfunc(gpointer data, G_GNUC_UNUSED gpointer user_data)
 {
-    GHashTableKVPair *kvp = (GHashTableKVPair *) data;
-    g_free(kvp);
+    HashEntry *entry = (HashEntry *) data;
+    g_free(entry);
 }
 
 /* GObject Initialization */
@@ -2293,10 +2293,10 @@ unstable_price_traversal(GNCPriceDB *db,
 }
 
 static gint
-compare_kvpairs_by_commodity_key(gconstpointer a, gconstpointer b)
+compare_hash_entries_by_commodity_key(gconstpointer a, gconstpointer b)
 {
-    GHashTableKVPair *kvpa = (GHashTableKVPair *) a;
-    GHashTableKVPair *kvpb = (GHashTableKVPair *) b;
+    HashEntry *he_a = (HashEntry *) a;
+    HashEntry *he_b = (HashEntry *) b;
     gnc_commodity *ca;
     gnc_commodity *cb;
     int cmp_result;
@@ -2306,8 +2306,8 @@ compare_kvpairs_by_commodity_key(gconstpointer a, gconstpointer b)
     if (!a) return -1;
     if (!b) return 1;
 
-    ca = (gnc_commodity *) kvpa->key;
-    cb = (gnc_commodity *) kvpb->key;
+    ca = (gnc_commodity *) he_a->key;
+    cb = (gnc_commodity *) he_b->key;
 
     cmp_result = g_strcmp0(gnc_commodity_get_namespace(ca),
                            gnc_commodity_get_namespace(cb));
@@ -2329,22 +2329,22 @@ stable_price_traversal(GNCPriceDB *db,
 
     if (!db || !f) return FALSE;
 
-    currency_hashes = g_hash_table_key_value_pairs(db->commodity_hash);
+    currency_hashes = hash_table_to_list(db->commodity_hash);
     currency_hashes = g_slist_sort(currency_hashes,
-                                   compare_kvpairs_by_commodity_key);
+                                   compare_hash_entries_by_commodity_key);
 
     for (i = currency_hashes; i; i = i->next)
     {
-        GHashTableKVPair *kv_pair = (GHashTableKVPair *) i->data;
-        GHashTable *currency_hash = (GHashTable *) kv_pair->value;
-        GSList *price_lists = g_hash_table_key_value_pairs(currency_hash);
+        HashEntry *entry = (HashEntry *) i->data;
+        GHashTable *currency_hash = (GHashTable *) entry->value;
+        GSList *price_lists = hash_table_to_list(currency_hash);
         GSList *j;
 
-        price_lists = g_slist_sort(price_lists, compare_kvpairs_by_commodity_key);
+        price_lists = g_slist_sort(price_lists, compare_hash_entries_by_commodity_key);
         for (j = price_lists; j; j = j->next)
         {
-            GHashTableKVPair *pricelist_kvp = (GHashTableKVPair *) j->data;
-            GList *price_list = (GList *) pricelist_kvp->value;
+            HashEntry *pricelist_entry = (HashEntry *) j->data;
+            GList *price_list = (GList *) pricelist_entry->value;
             GList *node;
 
             for (node = (GList *) price_list; node; node = node->next)
@@ -2358,7 +2358,7 @@ stable_price_traversal(GNCPriceDB *db,
         }
         if (price_lists)
         {
-            g_slist_foreach(price_lists, g_hash_table_kv_pair_free_gfunc, NULL);
+            g_slist_foreach(price_lists, hash_entry_free_gfunc, NULL);
             g_slist_free(price_lists);
             price_lists = NULL;
         }
@@ -2366,7 +2366,7 @@ stable_price_traversal(GNCPriceDB *db,
 
     if (currency_hashes)
     {
-        g_slist_foreach(currency_hashes, g_hash_table_kv_pair_free_gfunc, NULL);
+        g_slist_foreach(currency_hashes, hash_entry_free_gfunc, NULL);
         g_slist_free(currency_hashes);
     }
     return ok;

commit 50bb5c162a5bbeff34a3fa60393be45ef5e0a623
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 31 18:14:21 2015 -0700

    Remove "FIXME" comments about KvpFrame in SX-ttinfo.c.
    
    SX splits and regular splits have different requirements for Kvp. A
    regular split's Kvp contains information that applies to that one split
    alone so it would be a mistake to propagate it into SX. Meanwhile the SX
    split puts its formulas in Kvp, and we certainly don't want those going
    into regular splits.

diff --git a/src/engine/SX-ttinfo.c b/src/engine/SX-ttinfo.c
index 052d964..66ce1cd 100644
--- a/src/engine/SX-ttinfo.c
+++ b/src/engine/SX-ttinfo.c
@@ -27,7 +27,6 @@
 
 #include "SX-ttinfo.h"
 
-/* KvpFrame policy? */
 struct TTInfo_s
 {
     /* FIXME add notes field */
@@ -41,7 +40,6 @@ struct TTInfo_s
 struct TTSplitInfo_s
 {
     char *action; /* owned by us */
-    /* FIXME: What about the split's KvpFrame */
     char *memo; /* owned by us */
     char *credit_formula, *debit_formula; /* owned by us */
     Account *acc;

commit cadd1976df634fbb72ad14c9be6778354b59b3ca
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 31 18:01:47 2015 -0700

    Remove kvp-utils.
    
    No longer required.

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1fa3f1d..ba27f7f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -469,7 +469,6 @@ src/libqof/qof/gnc-numeric.cpp
 src/libqof/qof/gnc-rational.cpp
 src/libqof/qof/guid.cpp
 src/libqof/qof/kvp_frame.cpp
-src/libqof/qof/kvp-util.cpp
 src/libqof/qof/kvp-value.cpp
 src/libqof/qof/qofbackend.cpp
 src/libqof/qof/qofbook.cpp
diff --git a/src/doc/books.txt b/src/doc/books.txt
index 7258fb1..3b132e0 100644
--- a/src/doc/books.txt
+++ b/src/doc/books.txt
@@ -283,11 +283,6 @@ Plan A has been implemented in the engine.  To quickly summarize:
       it with the appropriate keys, markup, etc. and to carry balances 
       forward, etc.
 
--  src/engine/kvp-util.[ch]
-      Gemini code: code which allows 'linked lists' to be created, using
-      nothing but kvp trees and guid's.  These links are used to identify
-      peer accounts/ peer transactions, etc.
-
 -  src/engine/gnc-lot.[ch]
       Implements accounting Lots.
 
diff --git a/src/libqof/CMakeLists.txt b/src/libqof/CMakeLists.txt
index 590bb5e..aa916d0 100644
--- a/src/libqof/CMakeLists.txt
+++ b/src/libqof/CMakeLists.txt
@@ -15,7 +15,6 @@ SET (libgnc_qof_SOURCES
    qof/gnc-numeric.cpp
    qof/gnc-rational.cpp
    qof/guid.cpp
-   qof/kvp-util.cpp
    qof/kvp_frame.cpp
    qof/kvp-value.cpp
    qof/qofbackend.cpp
@@ -51,8 +50,6 @@ SET (libgnc_qof_HEADERS
    qof/gnc-date.h
    qof/gnc-numeric.h
    qof/guid.h
-   qof/kvp-util-p.h
-   qof/kvp-util.h
    qof/kvp_frame.h
    qof/qof.h
    qof/qofbackend-p.h
diff --git a/src/libqof/qof/Makefile.am b/src/libqof/qof/Makefile.am
index 7350398..86d393e 100644
--- a/src/libqof/qof/Makefile.am
+++ b/src/libqof/qof/Makefile.am
@@ -30,7 +30,6 @@ libgnc_qof_la_SOURCES =  \
    gnc-timezone.cpp    \
    gnc-datetime.cpp    \
    guid.cpp            \
-   kvp-util.cpp        \
    kvp_frame.cpp       \
    kvp-value.cpp       \
    qofbackend.cpp      \
@@ -58,8 +57,6 @@ qofinclude_HEADERS = \
    gnc-timezone.hpp  \
    gnc-datetime.hpp  \
    guid.h            \
-   kvp-util-p.h      \
-   kvp-util.h        \
    kvp_frame.h       \
    kvp_frame.hpp     \
    kvp-value.hpp     \
diff --git a/src/libqof/qof/kvp-util-p.h b/src/libqof/qof/kvp-util-p.h
deleted file mode 100644
index b3655e3..0000000
--- a/src/libqof/qof/kvp-util-p.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/********************************************************************\
- * kvp-util-p.h -- misc odd-job kvp utils (private file)            *
- *                                                                  *
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
- *                                                                  *
-\********************************************************************/
-
-#ifndef XACC_KVP_UTIL_P_H
-#define XACC_KVP_UTIL_P_H
-
-#include "guid.h"
-#include "kvp_frame.h"
-
-/** @addtogroup KVP
-    @{
-*/
-/** @file kvp-util-p.h
- * @brief misc odd-job kvp utils engine-private routines
- * @author Copyright (C) 2001, 2003 Linas Vepstas <linas at linas.org>               *
-*/
-/** @name KvpBag Bags of GncGUID Pointers
- @{
-*/
-
-/** The gnc_kvp_bag_add() routine is used to maintain a collection
- *  of pointers in a kvp tree.
- *
- *  The thing being pointed at is uniquely identified by its GncGUID.
- *  This routine is typically used to create a linked list, and/or
- *  a collection of pointers to objects that are 'related' to each
- *  other in some way.
- *
- *  The var-args should be pairs of strings (const char *) followed by
- *  the corresponding GncGUID pointer (const GncGUID *).  Terminate the varargs
- *  with a NULL as the last string argument.
- *
- *  The actual 'pointer' is stored in a subdirectory in a bag located at
- *  the node directory 'path'.  A 'bag' is merely a collection of
- *  (unamed) values.  The name of our bag is 'path'. A bag can contain
- *  any kind of values, including frames.  This routine will create a
- *  frame, and put it in the bag.  The frame will contain named data
- *  from the subroutine arguments.  Thus, for example:
- *
- *  gnc_kvp_array (kvp, "foo", secs, "acct_guid", aguid,
- *                                   "book_guid", bguid, NULL);
- *
- *  will create a frame containing "/acct_guid" and "/book_guid", whose
- *  values are aguid and bguid respecitvely.  The frame will also
- *  contain "/date", whose value will be secs.  This frame will be
- *  placed into the bag located at "foo".
- *
- *  This routine returns a pointer to the frame that was created, or
- *  NULL if an error occured.
- */
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-KvpFrame * gnc_kvp_bag_add (KvpFrame *kvp_root, const char *path, time64 secs,
-                            const char *first_name, ...);
-
-
-/** The gnc_kvp_bag_merge() routine will move the bag contents from
- *    the 'kvp_from', to the 'into' bag.  It will then delete the
- *    'from' bag from the kvp tree.
- */
-void gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath,
-                        KvpFrame *kvp_from, const char *frompath);
-
-/** The gnc_kvp_bag_find_by_guid() routine examines the bag pointed
- *    located at root.  It looks for a frame in that bag that has the
- *    guid value of "desired_guid" filed under the key name "guid_name".
- *    If it finds that matching guid, then it returns a pointer to
- *    the KVP frame that contains it.  If it is not found, or if there
- *    is any other error, NULL is returned.
- */
-
-KvpFrame * gnc_kvp_bag_find_by_guid (KvpFrame *root,  const char * path,
-                                     const char *guid_name, const GncGUID *desired_guid);
-
-
-/** Remove the given frame from the bag.  The frame is removed,
- *  however, it is not deleted.  Note that the frame pointer must
- *  be a pointer to the actual frame (for example, as returned by
- *  gnc_kvp_bag_find_by_guid() for by gnc_kvp_bag_add()), and not
- *  some copy of the frame.
- */
-
-void gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path,
-                               KvpFrame *fr);
-
-/** @} */
-/** @} */
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* XACC_KVP_UTIL_P_H */
diff --git a/src/libqof/qof/kvp-util.cpp b/src/libqof/qof/kvp-util.cpp
deleted file mode 100644
index 33f88ff..0000000
--- a/src/libqof/qof/kvp-util.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-/********************************************************************\
- * kvp_util.cpp -- misc odd-job kvp utils                           *
- * Copyright (C) 2001 Linas Vepstas <linas at linas.org>               *
- *                                                                  *
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
- *                                                                  *
-\********************************************************************/
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#include "config.h"
-
-#include <glib.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-}
-#endif
-
-#include "kvp_frame.h"
-#include "kvp-util.h"
-#include "kvp-util-p.h"
-
-/* ================================================================ */
-
-static KvpFrame *
-gnc_kvp_array_va (KvpFrame *kvp_root, const char * path,
-                  time64 secs, const char * first_name, va_list ap)
-{
-    KvpFrame *cwd;
-    Timespec ts;
-    const char *name;
-
-    if (!kvp_root) return NULL;
-    if (!first_name) return NULL;
-
-    /* Create subdirectory and put the actual data */
-    cwd = kvp_frame_new();
-
-    /* Record the time */
-    ts.tv_sec = secs;
-    ts.tv_nsec = 0;
-    kvp_frame_set_timespec (cwd, "date", ts);
-
-    /* Loop over the args */
-    name = first_name;
-    while (name)
-    {
-        const GncGUID *guid;
-        guid = va_arg (ap, const GncGUID *);
-
-        kvp_frame_set_guid (cwd, name, guid);
-
-        name = va_arg (ap, const char *);
-    }
-
-    /* Attach cwd into the array */
-    kvp_frame_add_frame_nc (kvp_root, path, cwd);
-    return cwd;
-}
-
-/* ================================================================ */
-
-KvpFrame *
-gnc_kvp_bag_add (KvpFrame *pwd, const char * path,
-                 time64 secs, const char *first_name, ...)
-{
-    KvpFrame *cwd;
-    va_list ap;
-    va_start (ap, first_name);
-    cwd = gnc_kvp_array_va (pwd, path, secs, first_name, ap);
-    va_end (ap);
-    return cwd;
-}
-
-/* ================================================================ */
-
-#define MATCH_GUID(elt) {                                       \
-  KvpFrame *fr = kvp_value_get_frame (elt);                     \
-  if (fr) {                                                     \
-     GncGUID *guid = kvp_frame_get_guid (fr, guid_name);           \
-     if (guid && guid_equal (desired_guid, guid)) return fr;    \
-  }                                                             \
-}
-
-KvpFrame *
-gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
-                          const char *guid_name, const GncGUID *desired_guid)
-{
-    KvpValue *arr;
-    KvpValueType valtype;
-    GList *node;
-
-    arr = kvp_frame_get_value (root, path);
-    valtype = kvp_value_get_type (arr);
-    if (KVP_TYPE_FRAME == valtype)
-    {
-        MATCH_GUID (arr);
-        return NULL;
-    }
-
-    /* Its gotta be a single isolated frame, or a list of them. */
-    if (KVP_TYPE_GLIST != valtype) return NULL;
-
-    for (node = kvp_value_get_glist(arr); node; node = node->next)
-    {
-        KvpValue *va = static_cast<KvpValue*>(node->data);
-        MATCH_GUID (va);
-    }
-    return NULL;
-}
-
-/* ================================================================ */
-
-void
-gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)
-{
-    KvpValue *arr;
-    KvpValueType valtype;
-    GList *node, *listhead;
-
-    arr = kvp_frame_get_value (root, path);
-    valtype = kvp_value_get_type (arr);
-    if (KVP_TYPE_FRAME == valtype)
-    {
-        if (fr == kvp_value_get_frame (arr))
-        {
-            KvpValue *old_val = kvp_frame_replace_value_nc (root, path, NULL);
-            kvp_value_replace_frame_nc (old_val, NULL);
-            kvp_value_delete (old_val);
-        }
-        return;
-    }
-
-    /* Its gotta be a single isolated frame, or a list of them. */
-    if (KVP_TYPE_GLIST != valtype) return;
-
-    listhead = kvp_value_get_glist(arr);
-    for (node = listhead; node; node = node->next)
-    {
-        KvpValue *va = static_cast<KvpValue*>(node->data);
-        if (fr == kvp_value_get_frame (va))
-        {
-            listhead = g_list_remove_link (listhead, node);
-            g_list_free_1 (node);
-            kvp_value_replace_glist_nc (arr, listhead);
-            kvp_value_replace_frame_nc (va, NULL);
-            kvp_value_delete (va);
-            return;
-        }
-    }
-}
-
-/* ================================================================ */
-
-static KvpFrame *
-gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
-{
-    KvpValue *arr, *va;
-    KvpValueType valtype;
-    GList *node;
-
-    arr = kvp_frame_get_value (root, path);
-    valtype = kvp_value_get_type (arr);
-    if (KVP_TYPE_FRAME == valtype)
-    {
-        return kvp_value_get_frame(arr);
-    }
-
-    /* Its gotta be a single isolated frame, or a list of them. */
-    if (KVP_TYPE_GLIST != valtype) return NULL;
-
-    node = kvp_value_get_glist(arr);
-    if (NULL == node) return NULL;
-
-    va = static_cast<KvpValue*>(node->data);
-    return kvp_value_get_frame(va);
-}
-
-void
-gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath,
-                   KvpFrame *kvp_from, const char *frompath)
-{
-    KvpFrame *fr;
-
-    fr = gnc_kvp_bag_get_first (kvp_from, frompath);
-    while (fr)
-    {
-        gnc_kvp_bag_remove_frame (kvp_from, frompath, fr);
-        kvp_frame_add_frame_nc (kvp_into, intopath, fr);
-        fr = gnc_kvp_bag_get_first (kvp_from, frompath);
-    }
-}
-
-/* ================================================================ */
-/*
- * See header for docs.
- */
-
-static void
-kv_pair_helper(gpointer key, gpointer val, gpointer user_data)
-{
-    GSList **result = (GSList **) user_data;
-    GHashTableKVPair *kvp = g_new(GHashTableKVPair, 1);
-
-    kvp->key = key;
-    kvp->value = val;
-    *result = g_slist_prepend(*result, kvp);
-}
-
-GSList *
-g_hash_table_key_value_pairs(GHashTable *table)
-{
-    GSList *result_list = NULL;
-    g_hash_table_foreach(table, kv_pair_helper, &result_list);
-    return result_list;
-}
-
-void
-g_hash_table_kv_pair_free_gfunc(gpointer data, G_GNUC_UNUSED gpointer user_data)
-{
-    GHashTableKVPair *kvp = (GHashTableKVPair *) data;
-    g_free(kvp);
-}
-
-/*======================== END OF FILE =============================*/
diff --git a/src/libqof/qof/kvp-util.h b/src/libqof/qof/kvp-util.h
deleted file mode 100644
index 1c6da4c..0000000
--- a/src/libqof/qof/kvp-util.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/********************************************************************\
- * kvp-util.h -- misc KVP utilities                                 *
- * Copyright (C) 2003 Linas Vepstas <linas at linas.org>               *
- *                                                                  *
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-\********************************************************************/
-
-/** @addtogroup KVP
-    @{
-*/
-/** @file kvp-util.h
-    @brief QOF KVP utility functions
- */
-/**  @name Hash Utilities
- @{
-*/
-
-#ifndef GNC_KVP_UTIL_H
-#define GNC_KVP_UTIL_H
-
-typedef struct
-{
-    gpointer key;
-    gpointer value;
-} GHashTableKVPair;
-
-/**
-  Returns a GSList* of all the
-  keys and values in a given hash table.  Data elements of lists are
-  actual hash elements, so be careful, and deallocation of the
-  GHashTableKVPairs in the result list are the caller's
-  responsibility.  A typical sequence might look like this:
-
-    GSList *kvps = g_hash_table_key_value_pairs(hash);
-    ... use kvps->data->key and kvps->data->val, etc. here ...
-    g_slist_foreach(kvps, g_hash_table_kv_pair_free_gfunc, NULL);
-    g_slist_free(kvps);
-
-*/
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-GSList *g_hash_table_key_value_pairs(GHashTable *table);
-void g_hash_table_kv_pair_free_gfunc(gpointer data, gpointer user_data);
-
-#ifdef __cplusplus
-}
-#endif
-
-/***********************************************************************/
-
-/** @} */
-/** @} */
-#endif /* GNC_KVP_UTIL_H */
diff --git a/src/libqof/qof/qof.h b/src/libqof/qof/qof.h
index 68ad9ff..be030c6 100644
--- a/src/libqof/qof/qof.h
+++ b/src/libqof/qof/qof.h
@@ -80,8 +80,6 @@
 #include "qofutil.h"
 #include "guid.h"
 #include "kvp_frame.h"
-#include "kvp-util.h"
-#include "kvp-util-p.h"
 #include "qofbackend.h"
 #include "qofid-p.h"
 #include "qofbook.h"

commit c941a52a9fb9159a4c6c9718a6ae70997b7e389f
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 31 18:00:55 2015 -0700

    Copy GHash/KVP functions from kvp-util to the one place they're used.

diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c
index 23fbae0..95bc252 100644
--- a/src/engine/gnc-pricedb.c
+++ b/src/engine/gnc-pricedb.c
@@ -49,6 +49,38 @@ enum
     PROP_VALUE,		/* Table, 2 fields (numeric) */
 };
 
+typedef struct
+{
+     gpointer key;
+     gpointer value;
+} GHashTableKVPair;
+
+static void
+kv_pair_helper(gpointer key, gpointer val, gpointer user_data)
+{
+    GSList **result = (GSList **) user_data;
+    GHashTableKVPair *kvp = g_new(GHashTableKVPair, 1);
+
+    kvp->key = key;
+    kvp->value = val;
+    *result = g_slist_prepend(*result, kvp);
+}
+
+static GSList *
+g_hash_table_key_value_pairs(GHashTable *table)
+{
+    GSList *result_list = NULL;
+    g_hash_table_foreach(table, kv_pair_helper, &result_list);
+    return result_list;
+}
+
+static void
+g_hash_table_kv_pair_free_gfunc(gpointer data, G_GNUC_UNUSED gpointer user_data)
+{
+    GHashTableKVPair *kvp = (GHashTableKVPair *) data;
+    g_free(kvp);
+}
+
 /* GObject Initialization */
 G_DEFINE_TYPE(GNCPrice, gnc_price, QOF_TYPE_INSTANCE);
 

commit c2d44b89fbd025df564d4fec6958f8ddb5a1fd16
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 31 17:59:52 2015 -0700

    Replace Scrub2 direct KVP access with Split lot-guid accessors.

diff --git a/src/engine/Scrub2.c b/src/engine/Scrub2.c
index 5532785..757589d 100644
--- a/src/engine/Scrub2.c
+++ b/src/engine/Scrub2.c
@@ -242,17 +242,13 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
 static inline gboolean
 is_subsplit (Split *split)
 {
-    KvpValue *kval;
 
     /* generic stop-progress conditions */
     if (!split) return FALSE;
     g_return_val_if_fail (split->parent, FALSE);
 
     /* If there are no sub-splits, then there's nothing to do. */
-    kval = kvp_frame_get_slot (split->inst.kvp_data, "lot-split");
-    if (!kval) return FALSE;
-
-    return TRUE;
+    return xaccSplitHasPeers (split);
 }
 
 /* ================================================================= */
@@ -267,30 +263,9 @@ is_subsplit (Split *split)
 static void
 remove_guids (Split *sa, Split *sb)
 {
-    KvpFrame *ksub;
-
-    /* Find and remove the matching guid's */
-    ksub = (KvpFrame*)gnc_kvp_bag_find_by_guid (sa->inst.kvp_data, "lot-split",
-            "peer_guid", qof_instance_get_guid(sb));
-    if (ksub)
-    {
-        gnc_kvp_bag_remove_frame (sa->inst.kvp_data, "lot-split", ksub);
-        kvp_frame_delete (ksub);
-    }
-
-    /* Now do it in the other direction */
-    ksub = (KvpFrame*)gnc_kvp_bag_find_by_guid (sb->inst.kvp_data, "lot-split",
-            "peer_guid", qof_instance_get_guid(sa));
-    if (ksub)
-    {
-        gnc_kvp_bag_remove_frame (sb->inst.kvp_data, "lot-split", ksub);
-        kvp_frame_delete (ksub);
-    }
-
-    /* Finally, merge b's lot-splits, if any, into a's */
-    /* This is an important step, if it got busted into many pieces. */
-    gnc_kvp_bag_merge (sa->inst.kvp_data, "lot-split",
-                       sb->inst.kvp_data, "lot-split");
+     xaccSplitRemovePeerSplit (sa, sb);
+     xaccSplitRemovePeerSplit (sb, sa);
+     xaccSplitMergePeerSplits (sa, sb);
 }
 
 /* The merge_splits() routine causes the amount & value of sb
@@ -350,7 +325,6 @@ xaccScrubMergeSubSplits (Split *split, gboolean strict)
     Transaction *txn;
     SplitList *node;
     GNCLot *lot;
-    const GncGUID *guid;
 
     if (strict && (FALSE == is_subsplit (split))) return FALSE;
 
@@ -376,9 +350,7 @@ restart:
              * example.  Only worry about adjacent sub-splits.  By
              * repeatedly merging adjacent subsplits, we'll get the non-
              * adjacent ones too. */
-            guid = qof_instance_get_guid(s);
-            if (gnc_kvp_bag_find_by_guid (split->inst.kvp_data, "lot-split",
-                                          "peer_guid", guid) == NULL)
+            if (!xaccSplitIsPeerSplit (split, s))
                 continue;
         }
 

commit d86a0b23787a98c2f120300f1b3856682a5955a4
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 31 17:59:01 2015 -0700

    Replace the lot-split and peer_guid properties with accessor functions.
    
    The properties weren't backwards compatible with existing books, nor
    would they work in the multiple-peers case.

diff --git a/src/engine/Split.c b/src/engine/Split.c
index 88b0f58..fc95158 100644
--- a/src/engine/Split.c
+++ b/src/engine/Split.c
@@ -92,8 +92,6 @@ enum
     PROP_SX_SHARES,             /* KVP */
     PROP_LOT,                   /* KVP */
     PROP_ONLINE_ACCOUNT,        /* KVP */
-    PROP_LOT_SPLIT,             /* KVP */
-    PROP_PEER_GUID,             /* KVP */
     PROP_GAINS_SPLIT,           /* KVP */
     PROP_GAINS_SOURCE,          /* KVP */
     PROP_RUNTIME_0,
@@ -161,77 +159,69 @@ gnc_split_get_property(GObject         *object,
     split = GNC_SPLIT(object);
     switch (prop_id)
     {
-    case PROP_ACTION:
-        g_value_set_string(value, split->action);
-        break;
-    case PROP_MEMO:
-        g_value_set_string(value, split->memo);
-        break;
-    case PROP_VALUE:
-        g_value_set_boxed(value, &split->value);
-        break;
-    case PROP_AMOUNT:
-        g_value_set_boxed(value, &split->amount);
-        break;
-    case PROP_RECONCILE_DATE:
-        g_value_set_boxed(value, &split->date_reconciled);
-        break;
-    case PROP_TX:
-        g_value_take_object(value, split->parent);
-        break;
-    case PROP_ACCOUNT:
-        g_value_take_object(value, split->acc);
-        break;
-    case PROP_LOT:
-        g_value_take_object(value, split->lot);
-        break;
-    case PROP_SX_CREDIT_FORMULA:
-        key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_CREDIT_NUMERIC:
-        key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_DEBIT_FORMULA:
-        key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_DEBIT_NUMERIC:
-        key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_ACCOUNT:
-        key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_SHARES:
-        key = GNC_SX_ID "/" GNC_SX_SHARES;
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_ONLINE_ACCOUNT:
-        key = "online_id";
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_LOT_SPLIT:
-        key = "lot-split";
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_PEER_GUID:
-        key = "peer_guid";
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_GAINS_SPLIT:
-        key = "gains-split";
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_GAINS_SOURCE:
-        key = "gains-source";
-        qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-        break;
+        case PROP_ACTION:
+            g_value_set_string(value, split->action);
+            break;
+        case PROP_MEMO:
+            g_value_set_string(value, split->memo);
+            break;
+        case PROP_VALUE:
+            g_value_set_boxed(value, &split->value);
+            break;
+        case PROP_AMOUNT:
+            g_value_set_boxed(value, &split->amount);
+            break;
+        case PROP_RECONCILE_DATE:
+            g_value_set_boxed(value, &split->date_reconciled);
+            break;
+        case PROP_TX:
+            g_value_take_object(value, split->parent);
+            break;
+        case PROP_ACCOUNT:
+            g_value_take_object(value, split->acc);
+            break;
+        case PROP_LOT:
+            g_value_take_object(value, split->lot);
+            break;
+        case PROP_SX_CREDIT_FORMULA:
+            key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_CREDIT_NUMERIC:
+            key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_DEBIT_FORMULA:
+            key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_DEBIT_NUMERIC:
+            key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_ACCOUNT:
+            key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_SHARES:
+            key = GNC_SX_ID "/" GNC_SX_SHARES;
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_ONLINE_ACCOUNT:
+            key = "online_id";
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_GAINS_SPLIT:
+            key = "gains-split";
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_GAINS_SOURCE:
+            key = "gains-source";
+            qof_instance_get_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+            break;
     }
 }
 
@@ -253,79 +243,71 @@ gnc_split_set_property(GObject         *object,
 
     switch (prop_id)
     {
-    case PROP_ACTION:
-        xaccSplitSetAction(split, g_value_get_string(value));
-        break;
-    case PROP_MEMO:
-        xaccSplitSetMemo(split, g_value_get_string(value));
-        break;
-    case PROP_VALUE:
-        number = g_value_get_boxed(value);
-        xaccSplitSetValue(split, *number);
-        break;
-    case PROP_AMOUNT:
-        number = g_value_get_boxed(value);
-        xaccSplitSetAmount(split, *number);
-        break;
-    case PROP_RECONCILE_DATE:
-        xaccSplitSetDateReconciledTS(split, g_value_get_boxed(value));
-        break;
-    case PROP_TX:
-        xaccSplitSetParent(split, g_value_get_object(value));
-        break;
-    case PROP_ACCOUNT:
-        xaccSplitSetAccount(split, g_value_get_object(value));
-        break;
-    case PROP_LOT:
-        xaccSplitSetLot(split, g_value_get_object(value));
-        break;
-    case PROP_SX_CREDIT_FORMULA:
-        key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_CREDIT_NUMERIC:
-        key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_DEBIT_FORMULA:
-        key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_DEBIT_NUMERIC:
-        key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_ACCOUNT:
-        key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_SX_SHARES:
-        key = GNC_SX_ID "/" GNC_SX_SHARES;
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_ONLINE_ACCOUNT:
-        key = "online_id";
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_LOT_SPLIT:
-        key = "lot-split";
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_PEER_GUID:
-        key = "peer_guid";
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_GAINS_SPLIT:
-        key = "gains-split";
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    case PROP_GAINS_SOURCE:
-        key = "gains-source";
-        qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-        break;
+        case PROP_ACTION:
+            xaccSplitSetAction(split, g_value_get_string(value));
+            break;
+        case PROP_MEMO:
+            xaccSplitSetMemo(split, g_value_get_string(value));
+            break;
+        case PROP_VALUE:
+            number = g_value_get_boxed(value);
+            xaccSplitSetValue(split, *number);
+            break;
+        case PROP_AMOUNT:
+            number = g_value_get_boxed(value);
+            xaccSplitSetAmount(split, *number);
+            break;
+        case PROP_RECONCILE_DATE:
+            xaccSplitSetDateReconciledTS(split, g_value_get_boxed(value));
+            break;
+        case PROP_TX:
+            xaccSplitSetParent(split, g_value_get_object(value));
+            break;
+        case PROP_ACCOUNT:
+            xaccSplitSetAccount(split, g_value_get_object(value));
+            break;
+        case PROP_LOT:
+            xaccSplitSetLot(split, g_value_get_object(value));
+            break;
+        case PROP_SX_CREDIT_FORMULA:
+            key = GNC_SX_ID "/" GNC_SX_CREDIT_FORMULA;
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_CREDIT_NUMERIC:
+            key = GNC_SX_ID "/" GNC_SX_CREDIT_NUMERIC;
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_DEBIT_FORMULA:
+            key = GNC_SX_ID "/" GNC_SX_DEBIT_FORMULA;
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_DEBIT_NUMERIC:
+            key = GNC_SX_ID "/" GNC_SX_DEBIT_NUMERIC;
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_ACCOUNT:
+            key = GNC_SX_ID "/" GNC_SX_ACCOUNT;
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_SX_SHARES:
+            key = GNC_SX_ID "/" GNC_SX_SHARES;
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_ONLINE_ACCOUNT:
+            key = "online_id";
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_GAINS_SPLIT:
+            key = "gains-split";
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        case PROP_GAINS_SOURCE:
+            key = "gains-source";
+            qof_instance_set_kvp (QOF_INSTANCE (split), key, value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+            break;
     }
 }
 
@@ -340,202 +322,182 @@ gnc_split_class_init(SplitClass* klass)
     gobject_class->get_property = gnc_split_get_property;
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_ACTION,
-     g_param_spec_string("action",
-                         "Action",
-                         "The action is an arbitrary string assigned "
-                         "by the user.  It is intended to be a short "
-                         "string that contains extra information about "
-                         "this split.",
-                         NULL,
-                         G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_ACTION,
+         g_param_spec_string("action",
+                             "Action",
+                             "The action is an arbitrary string assigned "
+                             "by the user.  It is intended to be a short "
+                             "string that contains extra information about "
+                             "this split.",
+                             NULL,
+                             G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_MEMO,
-     g_param_spec_string("memo",
-                         "Memo",
-                         "The action is an arbitrary string assigned "
-                         "by the user.  It is intended to be a short "
-                         "string that describes the purpose of "
-                         "this split.",
-                         NULL,
-                         G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_MEMO,
+         g_param_spec_string("memo",
+                             "Memo",
+                             "The action is an arbitrary string assigned "
+                             "by the user.  It is intended to be a short "
+                             "string that describes the purpose of "
+                             "this split.",
+                             NULL,
+                             G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_VALUE,
-     g_param_spec_boxed("value",
-                        "Split Value",
-                        "The value for this split in the common currency. "
-                        "The value and the amount provide enough information to "
-                        "calculate a conversion rate.",
-                        GNC_TYPE_NUMERIC,
-                        G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_VALUE,
+         g_param_spec_boxed("value",
+                            "Split Value",
+                            "The value for this split in the common currency. "
+                            "The value and the amount provide enough information to "
+                            "calculate a conversion rate.",
+                            GNC_TYPE_NUMERIC,
+                            G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_AMOUNT,
-     g_param_spec_boxed("amount",
-                        "Split Amount",
-                        "The value for this split in the currency of its account. "
-                        "The value and the amount provide enough information to "
-                        "calculate a conversion rate.",
-                        GNC_TYPE_NUMERIC,
-                        G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_AMOUNT,
+         g_param_spec_boxed("amount",
+                            "Split Amount",
+                            "The value for this split in the currency of its account. "
+                            "The value and the amount provide enough information to "
+                            "calculate a conversion rate.",
+                            GNC_TYPE_NUMERIC,
+                            G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_RECONCILE_DATE,
-     g_param_spec_boxed("reconcile-date",
-                        "Reconcile Date",
-                        "The date this split was reconciled.",
-                        GNC_TYPE_TIMESPEC,
-                        G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_RECONCILE_DATE,
+         g_param_spec_boxed("reconcile-date",
+                            "Reconcile Date",
+                            "The date this split was reconciled.",
+                            GNC_TYPE_TIMESPEC,
+                            G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_TX,
-     g_param_spec_object ("transaction",
-                          "Transaction",
-                          "The transaction that this split belongs to.",
-                          GNC_TYPE_TRANSACTION,
-                          G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_TX,
+         g_param_spec_object ("transaction",
+                              "Transaction",
+                              "The transaction that this split belongs to.",
+                              GNC_TYPE_TRANSACTION,
+                              G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_ACCOUNT,
-     g_param_spec_object ("account",
-                          "Account",
-                          "The account that this split belongs to.",
-                          GNC_TYPE_ACCOUNT,
-                          G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_ACCOUNT,
+         g_param_spec_object ("account",
+                              "Account",
+                              "The account that this split belongs to.",
+                              GNC_TYPE_ACCOUNT,
+                              G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_LOT,
-     g_param_spec_object ("lot",
-                          "Lot",
-                          "The lot that this split belongs to.",
-                          GNC_TYPE_LOT,
-                          G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_LOT,
+         g_param_spec_object ("lot",
+                              "Lot",
+                              "The lot that this split belongs to.",
+                              GNC_TYPE_LOT,
+                              G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_SX_DEBIT_FORMULA,
-     g_param_spec_string("sx-debit-formula",
-                         "Schedule Transaction Debit Formula",
-                         "The formula used to calculate the actual debit "
-                         "amount when a real split is generated from this "
-                         "SX split.",
-                         NULL,
-                         G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_SX_DEBIT_FORMULA,
+         g_param_spec_string("sx-debit-formula",
+                             "Schedule Transaction Debit Formula",
+                             "The formula used to calculate the actual debit "
+                             "amount when a real split is generated from this "
+                             "SX split.",
+                             NULL,
+                             G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_SX_DEBIT_NUMERIC,
-     g_param_spec_boxed("sx-debit-numeric",
-                        "Scheduled Transaction Debit Numeric",
-                        "Numeric value to plug into the Debit Formula when a "
-                        "real split is generated from this SX split.",
-                        GNC_TYPE_NUMERIC,
-                        G_PARAM_READWRITE));
-
-     g_object_class_install_property
-    (gobject_class,
-     PROP_SX_CREDIT_FORMULA,
-     g_param_spec_string("sx-credit-formula",
-                         "Schedule Transaction Credit Formula",
-                         "The formula used to calculate the actual credit "
-                         "amount when a real split is generated from this "
-                         "SX split.",
-                         NULL,
-                         G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_SX_DEBIT_NUMERIC,
+         g_param_spec_boxed("sx-debit-numeric",
+                            "Scheduled Transaction Debit Numeric",
+                            "Numeric value to plug into the Debit Formula when a "
+                            "real split is generated from this SX split.",
+                            GNC_TYPE_NUMERIC,
+                            G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_SX_CREDIT_NUMERIC,
-     g_param_spec_boxed("sx-credit-numeric",
-                        "Scheduled Transaction Credit Numeric",
-                        "Numeric value to plug into the Credit Formula when a "
-                        "real split is generated from this SX split.",
-                        GNC_TYPE_NUMERIC,
-                        G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_SX_CREDIT_FORMULA,
+         g_param_spec_string("sx-credit-formula",
+                             "Schedule Transaction Credit Formula",
+                             "The formula used to calculate the actual credit "
+                             "amount when a real split is generated from this "
+                             "SX split.",
+                             NULL,
+                             G_PARAM_READWRITE));
+
+    g_object_class_install_property
+        (gobject_class,
+         PROP_SX_CREDIT_NUMERIC,
+         g_param_spec_boxed("sx-credit-numeric",
+                            "Scheduled Transaction Credit Numeric",
+                            "Numeric value to plug into the Credit Formula when a "
+                            "real split is generated from this SX split.",
+                            GNC_TYPE_NUMERIC,
+                            G_PARAM_READWRITE));
 /* FIXME: PROP_SX_SHARES should be stored as a gnc_numeric, but the function
  * which uses it, gnc_template_register_save_shares_cell, stores a
  * phony string. This is maintained until backwards compatibility can
  * be established.
  */
     g_object_class_install_property
-    (gobject_class,
-     PROP_SX_SHARES,
-     g_param_spec_string("sx-shares",
-                        "Scheduled Transaction Shares",
-                        "Numeric value of shares to insert in a new split when "
-                        "it's generated from this SX split.",
-                        NULL,
-                        G_PARAM_READWRITE));
-
-     g_object_class_install_property
-    (gobject_class,
-     PROP_SX_ACCOUNT,
-     g_param_spec_boxed("sx-account",
-                        "Scheduled Transaction Account",
-                        "The target account for a scheduled transaction split.",
-                        GNC_TYPE_GUID,
-                        G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_SX_SHARES,
+         g_param_spec_string("sx-shares",
+                             "Scheduled Transaction Shares",
+                             "Numeric value of shares to insert in a new split when "
+                             "it's generated from this SX split.",
+                             NULL,
+                             G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_ONLINE_ACCOUNT,
-     g_param_spec_string ("online-id",
-                          "Online Account ID",
-                          "The online account which corresponds to this "
-                          "account for OFX/HCBI import",
-                          NULL,
-                          G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_SX_ACCOUNT,
+         g_param_spec_boxed("sx-account",
+                            "Scheduled Transaction Account",
+                            "The target account for a scheduled transaction split.",
+                            GNC_TYPE_GUID,
+                            G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_LOT_SPLIT,
-     g_param_spec_int64 ("lot-split",
-                         "Lot Split",
-                         "Indicates that the split was divided into two "
-                         "splits in order to balance a lot capital gains "
-                         "transaction. Contains a timestamp of the action.",
-                         G_MININT64, G_MAXINT64, 0,
-                         G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_ONLINE_ACCOUNT,
+         g_param_spec_string ("online-id",
+                              "Online Account ID",
+                              "The online account which corresponds to this "
+                              "account for OFX/HCBI import",
+                              NULL,
+                              G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_PEER_GUID,
-     g_param_spec_boxed ("peer-guid",
-                          "Peer GUID",
-                          "The other split in the division.",
-                          GNC_TYPE_GUID,
-                          G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_GAINS_SPLIT,
+         g_param_spec_boxed ("gains-split",
+                             "Gains Split",
+                             "The capital gains split associated with this "
+                             "split when this split represents the proceeds "
+                             "from the sale of a commodity inside a Lot.",
+                             GNC_TYPE_GUID,
+                             G_PARAM_READWRITE));
 
     g_object_class_install_property
-    (gobject_class,
-     PROP_GAINS_SPLIT,
-     g_param_spec_boxed ("gains-split",
-                          "Gains Split",
-                          "The capital gains split associated with this "
-                          "split when this split represents the proceeds "
-                          "from the sale of a commodity inside a Lot.",
-                          GNC_TYPE_GUID,
-                          G_PARAM_READWRITE));
-
-    g_object_class_install_property
-    (gobject_class,
-     PROP_GAINS_SOURCE,
-     g_param_spec_boxed ("gains-source",
-                          "Gains Source",
-                          "The source split for which this split this is "
-                          "the gains split. ",
-                          GNC_TYPE_GUID,
-                          G_PARAM_READWRITE));
+        (gobject_class,
+         PROP_GAINS_SOURCE,
+         g_param_spec_boxed ("gains-source",
+                             "Gains Source",
+                             "The source split for which this split this is "
+                             "the gains split. ",
+                             GNC_TYPE_GUID,
+                             G_PARAM_READWRITE));
 }
 
 /********************************************************************\
@@ -687,21 +649,21 @@ xaccSplitCopyKvp (const Split *from, Split *to)
 void
 xaccSplitCopyOnto(const Split *from_split, Split *to_split)
 {
-   if (!from_split || !to_split) return;
-   xaccTransBeginEdit (to_split->parent);
+    if (!from_split || !to_split) return;
+    xaccTransBeginEdit (to_split->parent);
 
-   xaccSplitSetMemo(to_split, xaccSplitGetMemo(from_split));
-   xaccSplitSetAction(to_split, xaccSplitGetAction(from_split));
-   xaccSplitSetAmount(to_split, xaccSplitGetAmount(from_split));
-   xaccSplitSetValue(to_split, xaccSplitGetValue(from_split));
-   /* Setting the account is okay here because, even though the from
-      split might not really belong to the account it claims to,
-      setting the account won't cause any event involving from. */
-   xaccSplitSetAccount(to_split, xaccSplitGetAccount(from_split));
-   /* N.B. Don't set parent. */
+    xaccSplitSetMemo(to_split, xaccSplitGetMemo(from_split));
+    xaccSplitSetAction(to_split, xaccSplitGetAction(from_split));
+    xaccSplitSetAmount(to_split, xaccSplitGetAmount(from_split));
+    xaccSplitSetValue(to_split, xaccSplitGetValue(from_split));
+    /* Setting the account is okay here because, even though the from
+       split might not really belong to the account it claims to,
+       setting the account won't cause any event involving from. */
+    xaccSplitSetAccount(to_split, xaccSplitGetAccount(from_split));
+    /* N.B. Don't set parent. */
 
-   qof_instance_set_dirty(QOF_INSTANCE(to_split));
-   xaccTransCommitEdit(to_split->parent);
+    qof_instance_set_dirty(QOF_INSTANCE(to_split));
+    xaccTransCommitEdit(to_split->parent);
 }
 
 /*################## Added for Reg2 #################*/
@@ -724,7 +686,7 @@ xaccSplitDump (const Split *split, const char *tag)
     printf("    Gains:    %p\n", split->gains_split);
     printf("    Memo:     %s\n", split->memo ? split->memo : "(null)");
     printf("    Action:   %s\n", split->action ? split->action : "(null)");
-    printf("    KVP Data: %s\n", qof_instance_kvp_as_string (QOF_INSTANCE (split));
+    printf("    KVP Data: %s\n", qof_instance_kvp_as_string (QOF_INSTANCE (split)));
     printf("    Recncld:  %c (date %s)\n", split->reconciled,
            gnc_print_date(split->date_reconciled));
     printf("    Value:    %s\n", gnc_numeric_to_string(split->value));
@@ -1273,7 +1235,7 @@ xaccSplitSetAmount (Split *s, gnc_numeric amt)
         g_assert (gnc_numeric_check (s->amount) == GNC_ERROR_OK);
     }
     else
-         s->amount = amt;
+        s->amount = amt;
 
     SET_GAINS_ADIRTY(s);
     mark_split (s);
@@ -1502,7 +1464,7 @@ xaccSplitDestroy (Split *split)
     acc = split->acc;
     trans = split->parent;
     if (acc && !qof_instance_get_destroying(acc)
-            && xaccTransGetReadOnly(trans))
+        && xaccTransGetReadOnly(trans))
         return FALSE;
 
     xaccTransBeginEdit(trans);
@@ -1535,7 +1497,7 @@ xaccSplitOrder (const Split *sa, const Split *sb)
     /* sort in transaction order, but use split action rather than trans num
      * according to book option */
     action_for_num = qof_book_use_split_action_for_num_field
-                                                        (xaccSplitGetBook (sa));
+        (xaccSplitGetBook (sa));
     if (action_for_num)
         retval = xaccTransOrder_num_action (sa->parent, sa->action,
                                             sb->parent, sb->action);
@@ -1627,7 +1589,7 @@ get_corr_account_split(const Split *sa, const Split **retval)
         current_value = xaccSplitGetValue (current_split);
         current_value_positive = gnc_numeric_positive_p(current_value);
         if ((sa_value_positive && !current_value_positive) ||
-                (!sa_value_positive && current_value_positive))
+            (!sa_value_positive && current_value_positive))
         {
             if (seen_one)
             {
@@ -1809,18 +1771,18 @@ qofSplitSetReconcile (Split *split, char recn)
     g_return_if_fail(split);
     switch (recn)
     {
-    case NREC:
-    case CREC:
-    case YREC:
-    case FREC:
-    case VREC:
-        split->reconciled = recn;
-        mark_split (split);
-        xaccAccountRecomputeBalance (split->acc);
-        break;
-    default:
-        PERR("Bad reconciled flag");
-        break;
+        case NREC:
+        case CREC:
+        case YREC:
+        case FREC:
+        case VREC:
+            split->reconciled = recn;
+            mark_split (split);
+            xaccAccountRecomputeBalance (split->acc);
+            break;
+        default:
+            PERR("Bad reconciled flag");
+            break;
     }
 }
 
@@ -1832,19 +1794,19 @@ xaccSplitSetReconcile (Split *split, char recn)
 
     switch (recn)
     {
-    case NREC:
-    case CREC:
-    case YREC:
-    case FREC:
-    case VREC:
-        split->reconciled = recn;
-        mark_split (split);
-        qof_instance_set_dirty(QOF_INSTANCE(split));
-        xaccAccountRecomputeBalance (split->acc);
-        break;
-    default:
-        PERR("Bad reconciled flag");
-        break;
+        case NREC:
+        case CREC:
+        case YREC:
+        case FREC:
+        case VREC:
+            split->reconciled = recn;
+            mark_split (split);
+            qof_instance_set_dirty(QOF_INSTANCE(split));
+            xaccAccountRecomputeBalance (split->acc);
+            break;
+        default:
+            PERR("Bad reconciled flag");
+            break;
     }
     xaccTransCommitEdit(split->parent);
 
@@ -2077,6 +2039,70 @@ xaccSplitMakeStockSplit(Split *s)
     xaccTransCommitEdit(s->parent);
 }
 
+void
+xaccSplitAddPeerSplit (Split *split, const Split *other_split,
+                       time64 timestamp)
+{
+    const GncGUID* guid;
+
+    g_return_if_fail (split != NULL);
+    g_return_if_fail (other_split != NULL);
+
+    guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
+    xaccTransBeginEdit (split->parent);
+    qof_instance_kvp_add_guid (QOF_INSTANCE (split), "lot-split",
+                               timespec_now(), "peer_guid", guid);
+    mark_split (split);
+    qof_instance_set_dirty (QOF_INSTANCE (split));
+    xaccTransCommitEdit (split->parent);
+}
+
+gboolean
+xaccSplitHasPeers (const Split *split)
+{
+    return qof_instance_has_slot (QOF_INSTANCE (split), "lot-split");
+}
+
+gboolean
+xaccSplitIsPeerSplit (const Split *split, const Split *other_split)
+{
+    const GncGUID* guid;
+
+    g_return_val_if_fail (split != NULL, FALSE);
+    g_return_val_if_fail (other_split != NULL, FALSE);
+
+    guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
+    return qof_instance_kvp_has_guid (QOF_INSTANCE (split), "lot-split",
+                                      "peer_guid", guid);
+}
+
+void
+xaccSplitRemovePeerSplit (Split *split, const Split *other_split)
+{
+    const GncGUID* guid;
+
+    g_return_if_fail (split != NULL);
+    g_return_if_fail (other_split != NULL);
+
+    guid = qof_instance_get_guid (QOF_INSTANCE (other_split));
+    xaccTransBeginEdit (split->parent);
+    qof_instance_kvp_remove_guid (QOF_INSTANCE (split), "lot-split",
+                                  "peer_guid", guid);
+    mark_split (split);
+    qof_instance_set_dirty (QOF_INSTANCE (split));
+    xaccTransCommitEdit (split->parent);
+}
+
+void
+xaccSplitMergePeerSplits (Split *split, const Split *other_split)
+{
+    xaccTransBeginEdit (split->parent);
+    qof_instance_kvp_merge_guids (QOF_INSTANCE (split),
+                                  QOF_INSTANCE (other_split), "lot-split");
+    mark_split (split);
+    qof_instance_set_dirty (QOF_INSTANCE (split));
+    xaccTransCommitEdit (split->parent);
+}
 
 /********************************************************************\
 \********************************************************************/
@@ -2097,28 +2123,17 @@ xaccSplitGetOtherSplit (const Split *split)
     Transaction *trans;
     int count, num_splits;
     Split *other = NULL;
-    gint64 lot_split;
+    gboolean lot_split;
     gboolean trading_accts;
 
     if (!split) return NULL;
     trans = split->parent;
     if (!trans) return NULL;
 
-#ifdef OLD_ALGO_HAS_ONLY_TWO_SPLITS
-    Split *s1, *s2;
-    if (g_list_length (trans->splits) != 2) return NULL;
-
-    s1 = g_list_nth_data (trans->splits, 0);
-    s2 = g_list_nth_data (trans->splits, 1);
-
-    if (s1 == split) return s2;
-    return s1;
-#endif
-
     trading_accts = xaccTransUseTradingAccounts (trans);
     num_splits = xaccTransCountSplits(trans);
     count = num_splits;
-    g_object_get (G_OBJECT (split), "lot-split", &lot_split, NULL);
+    lot_split = qof_instance_has_slot(QOF_INSTANCE (split), "lot-split");
     if (!lot_split && !trading_accts && (2 != count)) return NULL;
 
     for (i = 0; i < num_splits; i++)
@@ -2129,14 +2144,13 @@ xaccSplitGetOtherSplit (const Split *split)
             --count;
             continue;
         }
-	g_object_get (G_OBJECT (s), "lot-split", &lot_split, NULL);
-        if (lot_split)
+        if (qof_instance_has_slot (QOF_INSTANCE (s), "lot-split"))
         {
             --count;
             continue;
         }
         if (trading_accts &&
-                xaccAccountGetType(xaccSplitGetAccount(s)) == ACCT_TYPE_TRADING)
+            xaccAccountGetType(xaccSplitGetAccount(s)) == ACCT_TYPE_TRADING)
         {
             --count;
             continue;
@@ -2277,93 +2291,93 @@ qofSplitSetAccount(Split *s, QofInstance *ent)
 gboolean xaccSplitRegister (void)
 {
     static const QofParam params[] =
-    {
         {
-            SPLIT_DATE_RECONCILED, QOF_TYPE_DATE,
-            (QofAccessFunc)xaccSplitRetDateReconciledTS,
-            (QofSetterFunc)xaccSplitSetDateReconciledTS
-        },
+            {
+                SPLIT_DATE_RECONCILED, QOF_TYPE_DATE,
+                (QofAccessFunc)xaccSplitRetDateReconciledTS,
+                (QofSetterFunc)xaccSplitSetDateReconciledTS
+            },
 
-        /* d-* are deprecated query params, should not be used in new
-         * queries, should be removed from old queries. */
-        {
-            "d-share-amount", QOF_TYPE_DOUBLE,
-            (QofAccessFunc)DxaccSplitGetShareAmount, NULL
-        },
-        {
-            "d-share-int64", QOF_TYPE_INT64,
-            (QofAccessFunc)qof_entity_get_guid, NULL
-        },
-        {
-            SPLIT_BALANCE, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitGetBalance, NULL
-        },
-        {
-            SPLIT_CLEARED_BALANCE, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitGetClearedBalance, NULL
-        },
-        {
-            SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitGetReconciledBalance, NULL
-        },
-        {
-            SPLIT_MEMO, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccSplitGetMemo, (QofSetterFunc)qofSplitSetMemo
-        },
-        {
-            SPLIT_ACTION, QOF_TYPE_STRING,
-            (QofAccessFunc)xaccSplitGetAction, (QofSetterFunc)qofSplitSetAction
-        },
-        {
-            SPLIT_RECONCILE, QOF_TYPE_CHAR,
-            (QofAccessFunc)xaccSplitGetReconcile,
-            (QofSetterFunc)qofSplitSetReconcile
-        },
-        {
-            SPLIT_AMOUNT, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitGetAmount, (QofSetterFunc)qofSplitSetAmount
-        },
-        {
-            SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitGetSharePrice,
-            (QofSetterFunc)qofSplitSetSharePrice
-        },
-        {
-            SPLIT_VALUE, QOF_TYPE_DEBCRED,
-            (QofAccessFunc)xaccSplitGetValue, (QofSetterFunc)qofSplitSetValue
-        },
-        { SPLIT_TYPE, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetType, NULL },
-        {
-            SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitVoidFormerAmount, NULL
-        },
-        {
-            SPLIT_VOIDED_VALUE, QOF_TYPE_NUMERIC,
-            (QofAccessFunc)xaccSplitVoidFormerValue, NULL
-        },
-        { SPLIT_LOT, GNC_ID_LOT, (QofAccessFunc)xaccSplitGetLot, NULL },
-        {
-            SPLIT_TRANS, GNC_ID_TRANS,
-            (QofAccessFunc)xaccSplitGetParent,
-            (QofSetterFunc)qofSplitSetParentTrans
-        },
-        {
-            SPLIT_ACCOUNT, GNC_ID_ACCOUNT,
-            (QofAccessFunc)xaccSplitGetAccount, (QofSetterFunc)qofSplitSetAccount
-        },
-        { SPLIT_ACCOUNT_GUID, QOF_TYPE_GUID, split_account_guid_getter, NULL },
-        /*  these are no-ops to register the parameter names (for sorting) but
-            they return an allocated object which getters cannot do.  */
-        { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
-        { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
-        { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
-        { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, NULL },
-        {
-            QOF_PARAM_GUID, QOF_TYPE_GUID,
-            (QofAccessFunc)qof_entity_get_guid, NULL
-        },
-        { NULL },
-    };
+            /* d-* are deprecated query params, should not be used in new
+             * queries, should be removed from old queries. */
+            {
+                "d-share-amount", QOF_TYPE_DOUBLE,
+                (QofAccessFunc)DxaccSplitGetShareAmount, NULL
+            },
+            {
+                "d-share-int64", QOF_TYPE_INT64,
+                (QofAccessFunc)qof_entity_get_guid, NULL
+            },
+            {
+                SPLIT_BALANCE, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitGetBalance, NULL
+            },
+            {
+                SPLIT_CLEARED_BALANCE, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitGetClearedBalance, NULL
+            },
+            {
+                SPLIT_RECONCILED_BALANCE, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitGetReconciledBalance, NULL
+            },
+            {
+                SPLIT_MEMO, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccSplitGetMemo, (QofSetterFunc)qofSplitSetMemo
+            },
+            {
+                SPLIT_ACTION, QOF_TYPE_STRING,
+                (QofAccessFunc)xaccSplitGetAction, (QofSetterFunc)qofSplitSetAction
+            },
+            {
+                SPLIT_RECONCILE, QOF_TYPE_CHAR,
+                (QofAccessFunc)xaccSplitGetReconcile,
+                (QofSetterFunc)qofSplitSetReconcile
+            },
+            {
+                SPLIT_AMOUNT, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitGetAmount, (QofSetterFunc)qofSplitSetAmount
+            },
+            {
+                SPLIT_SHARE_PRICE, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitGetSharePrice,
+                (QofSetterFunc)qofSplitSetSharePrice
+            },
+            {
+                SPLIT_VALUE, QOF_TYPE_DEBCRED,
+                (QofAccessFunc)xaccSplitGetValue, (QofSetterFunc)qofSplitSetValue
+            },
+            { SPLIT_TYPE, QOF_TYPE_STRING, (QofAccessFunc)xaccSplitGetType, NULL },
+            {
+                SPLIT_VOIDED_AMOUNT, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitVoidFormerAmount, NULL
+            },
+            {
+                SPLIT_VOIDED_VALUE, QOF_TYPE_NUMERIC,
+                (QofAccessFunc)xaccSplitVoidFormerValue, NULL
+            },
+            { SPLIT_LOT, GNC_ID_LOT, (QofAccessFunc)xaccSplitGetLot, NULL },
+            {
+                SPLIT_TRANS, GNC_ID_TRANS,
+                (QofAccessFunc)xaccSplitGetParent,
+                (QofSetterFunc)qofSplitSetParentTrans
+            },
+            {
+                SPLIT_ACCOUNT, GNC_ID_ACCOUNT,
+                (QofAccessFunc)xaccSplitGetAccount, (QofSetterFunc)qofSplitSetAccount
+            },
+            { SPLIT_ACCOUNT_GUID, QOF_TYPE_GUID, split_account_guid_getter, NULL },
+            /*  these are no-ops to register the parameter names (for sorting) but
+                they return an allocated object which getters cannot do.  */
+            { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
+            { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
+            { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
+            { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, NULL },
+            {
+                QOF_PARAM_GUID, QOF_TYPE_GUID,
+                (QofAccessFunc)qof_entity_get_guid, NULL
+            },
+            { NULL },
+        };
 
     qof_class_register (GNC_ID_SPLIT, (QofSortFunc)xaccSplitOrder, params);
     qof_class_register (SPLIT_ACCT_FULLNAME,
diff --git a/src/engine/Split.h b/src/engine/Split.h
index cc512d1..487deba 100644
--- a/src/engine/Split.h
+++ b/src/engine/Split.h
@@ -356,6 +356,29 @@ Split      * xaccSplitLookup (const GncGUID *guid, QofBook *book);
 /* Get a GList of unique transactions containing the given list of Splits. */
 GList *xaccSplitListGetUniqueTransactions(const GList *splits);
 /*################## Added for Reg2 #################*/
+/** Add a peer split to this split's lot-split list.
+ * @param other_split: The split whose guid to add
+ * @param timestamp: The time to be recorded for the split.
+ */
+void xaccSplitAddPeerSplit (Split *split, const Split *other_split,
+                            const time64 timestamp);
+/** Does this split have peers?
+ */
+gboolean xaccSplitHasPeers (const Split *split);
+/** Report if a split is a peer of this one.
+ * @param other_split: The split to test for being a peer of this one.
+ * @return: True if other_split is registered as a peer of this one.
+ */
+gboolean xaccSplitIsPeerSplit (const Split *split, const Split *other_split);
+/** Remove a peer split from this split's lot-split list.
+ * @param other_split: The split whose guid to remove
+ */
+void xaccSplitRemovePeerSplit (Split *split, const Split *other_split);
+
+/** Merge the other_split's peer splits into split's peers.
+ * @param other_split: The split donating the peer splits.
+ */
+void xaccSplitMergePeerSplits (Split *split, const Split *other_split);
 
 /**
  * The xaccSplitGetOtherSplit() is a convenience routine that returns
diff --git a/src/engine/cap-gains.c b/src/engine/cap-gains.c
index 4003c67..f89289b 100644
--- a/src/engine/cap-gains.c
+++ b/src/engine/cap-gains.c
@@ -404,16 +404,8 @@ xaccSplitAssignToLot (Split *split, GNCLot *lot)
         /* Set the lot-split and peer_guid properties on the two
          * splits to indicate that they're linked. 
          */
-        qof_instance_set (QOF_INSTANCE (split),
-                          "lot-split", now,
-                          "peer_guid", xaccSplitGetGUID (new_split),
-                          NULL);
-
-        qof_instance_set (QOF_INSTANCE (new_split),
-                          "lot-split", now,
-                          "peer_guid", xaccSplitGetGUID (split),
-                          NULL);
-
+        xaccSplitAddPeerSplit(split, new_split, now);
+        xaccSplitAddPeerSplit(new_split, split, now);
         xaccAccountInsertSplit (acc, new_split);
         xaccTransAppendSplit (trans, new_split);
         /* Set the amount and value after the split is in the transaction

commit db5317f80fd77571ad6ba65b85b7867c5c9f9419
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 31 17:56:39 2015 -0700

    Rewrite the gnc_kvp_bag functions in qofinstance.
    
    They were over general and were used in only one place not in QOF.

diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index e048679..783a9a4 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -109,11 +109,23 @@ void qof_instance_set_idata(gpointer inst, guint32 idata);
 gboolean qof_instance_has_kvp (QofInstance *inst);
 void qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value);
 void qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value);
+/* Functions to isolate the KVP mechanism inside QOF for cases where GValue
+ * operations won't work.
+ */
 void qof_instance_copy_kvp (QofInstance *to, const QofInstance *from);
 void qof_instance_swap_kvp (QofInstance *a, QofInstance *b);
 int qof_instance_compare_kvp (const QofInstance *a, const QofInstance *b);
 char* qof_instance_kvp_as_string (const QofInstance *inst);
-
+void qof_instance_kvp_add_guid (const QofInstance *inst, const char* path,
+                                const Timespec time, const char* key,
+                                const GncGUID *guid);
+void qof_instance_kvp_remove_guid (const QofInstance *inst, const char *path,
+                                   const char* key, const GncGUID *guid);
+gboolean qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
+                                    const char* key, const GncGUID *guid);
+void qof_instance_kvp_merge_guids (const QofInstance *target,
+                                   const QofInstance *donor, const char* path);
+gboolean qof_instance_has_slot (const QofInstance *inst, const char *path);
 
 #ifdef __cplusplus
 }
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index 161fc35..28c45ea 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -36,7 +36,6 @@ extern "C"
 
 #include <utility>
 #include "qof.h"
-#include "kvp-util-p.h"
 #include "qofbook-p.h"
 #include "qofid-p.h"
 #include "qofinstance-p.h"
@@ -1069,22 +1068,19 @@ qof_commit_edit_part2(QofInstance *inst,
 gboolean
 qof_instance_has_kvp (QofInstance *inst)
 {
-    KvpFrame *frame = qof_instance_get_slots (inst);
-    return (frame != NULL && !kvp_frame_is_empty (frame));
+    return (inst->kvp_data != NULL && !kvp_frame_is_empty (inst->kvp_data));
 }
 
 void
 qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value)
 {
-    KvpFrame *frame = qof_instance_get_slots (inst);
-    kvp_frame_set_gvalue (frame, key, value);
+    kvp_frame_set_gvalue (inst->kvp_data, key, value);
 }
 
 void
 qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value)
 {
-    KvpFrame *frame = qof_instance_get_slots (inst);
-    GValue *temp = kvp_frame_get_gvalue (frame, key);
+    GValue *temp = kvp_frame_get_gvalue (inst->kvp_data, key);
     if (temp)
     {
 	g_value_copy (temp, value);
@@ -1116,5 +1112,163 @@ qof_instance_kvp_as_string (const QofInstance *inst)
     return kvp_frame_to_string (inst->kvp_data);
 }
 
+void
+qof_instance_kvp_add_guid (const QofInstance *inst, const char* path,
+                       const Timespec time, const char *key,
+                       const GncGUID *guid)
+{
+    KvpFrame *slot = NULL, *container = NULL;
+    /* We're in the process of being destroyed */
+    g_return_if_fail (inst->kvp_data != NULL);
+
+    container = kvp_frame_new();
+    kvp_frame_set_guid (container, key, guid);
+    kvp_frame_set_timespec (container, "date", time);
+    kvp_frame_add_frame_nc (inst->kvp_data, path, container);
+}
+
+inline static gboolean
+kvp_match_guid (KvpValue *v, const char *key, const GncGUID *guid)
+{
+    GncGUID *this_guid = NULL;
+    KvpFrame *frame = kvp_value_get_frame (v);
+    if (frame == NULL)
+        return FALSE;
+    this_guid = kvp_frame_get_guid (frame, key);
+    if (this_guid == NULL)
+        return FALSE;
+
+    return guid_equal (this_guid, guid);
+}
+
+gboolean
+qof_instance_kvp_has_guid (const QofInstance *inst, const char *path,
+                           const char* key, const GncGUID *guid)
+{
+    KvpValue *v = NULL;
+    g_return_val_if_fail (inst->kvp_data != NULL, FALSE);
+    g_return_val_if_fail (guid != NULL, FALSE);
+
+    v = kvp_frame_get_value (inst->kvp_data, path);
+    if (v == NULL) return FALSE;
+    
+    switch (kvp_value_get_type (v))
+    {
+    case KVP_TYPE_FRAME:
+        return kvp_match_guid (v, key, guid);
+        break;
+    case KVP_TYPE_GLIST:
+    {
+        GList *list = kvp_value_get_glist (v), *node = NULL;
+        for (node = list; node != NULL; node = node->next)
+        {
+            KvpValue *val = static_cast<KvpValue*>(node->data);
+            if (kvp_match_guid (val, key, guid))
+            {
+                return TRUE;
+            }
+        }
+        break;
+    }
+    default:
+        PWARN ("Instance KVP on path %s contains the wrong type.", path);
+        break;
+    }
+    return FALSE;
+}
+
+void
+qof_instance_kvp_remove_guid (const QofInstance *inst, const char *path,
+                          const char *key, const GncGUID *guid)
+{
+    KvpValue *v = NULL;
+    g_return_if_fail (inst->kvp_data != NULL);
+    g_return_if_fail (guid != NULL);
+
+    v = kvp_frame_get_value (inst->kvp_data, path);
+    if (v == NULL) return;
+
+    switch (kvp_value_get_type (v))
+    {
+    case KVP_TYPE_FRAME:
+        if (kvp_match_guid (v, key, guid))
+        {
+            kvp_frame_replace_value_nc (inst->kvp_data, path, NULL);
+            kvp_value_replace_frame_nc (v, NULL);
+            kvp_value_delete (v);
+        }
+        break;
+    case KVP_TYPE_GLIST:
+    {
+        GList *list = kvp_value_get_glist (v), *node = NULL;
+        for (node = list; node != NULL; node = node->next)
+        {
+            KvpValue *val = static_cast<KvpValue*>(node->data);
+            if (kvp_match_guid (val, key, guid))
+            {
+                kvp_value_replace_frame_nc (val, NULL);
+                list = g_list_delete_link (list, node);
+                kvp_value_replace_glist_nc (v, list);
+                kvp_value_delete (val);
+                break;
+            }
+        }
+        break;
+    }
+    default:
+        PWARN ("Instance KVP on path %s contains the wrong type.", path);
+        break;
+    }
+    return;
+}
+
+void
+qof_instance_kvp_merge_guids (const QofInstance *target,
+                              const QofInstance *donor, const char *path)
+{
+    KvpValue *v = NULL;
+    g_return_if_fail (target != NULL);
+    g_return_if_fail (donor != NULL);
+
+    if (! qof_instance_has_slot (donor, path)) return;
+    v = kvp_frame_get_value (donor->kvp_data, path);
+    if (v == NULL) return;
+
+    switch (kvp_value_get_type (v))
+    {
+    case KVP_TYPE_FRAME:
+        kvp_frame_add_frame_nc (target->kvp_data, path,
+                                kvp_value_get_frame (v));
+        kvp_value_replace_frame_nc (v, NULL);
+        kvp_value_delete (v);
+        break;
+    case KVP_TYPE_GLIST:
+    {
+        GList *list = kvp_value_get_glist (v), *node = NULL;
+        while (list)
+        {
+            KvpValue *val = static_cast<KvpValue*>(list->data);
+            kvp_frame_add_frame_nc (target->kvp_data, path,
+                                    kvp_value_get_frame (val));
+            kvp_value_replace_frame_nc (val, NULL);
+            list = g_list_remove_link (list, list);
+            kvp_value_delete (val);
+        }
+        kvp_value_replace_glist_nc (v, list);
+        kvp_value_delete (v);
+        break;
+    }
+    default:
+        PWARN ("Instance KVP on path %s contains the wrong type.", path);
+        break;
+    }
+}
+
+gboolean
+qof_instance_has_slot (const QofInstance *inst, const char *path)
+{
+    return kvp_frame_get_value (inst->kvp_data, path) != NULL;
+}
+
 /* ========================== END OF FILE ======================= */
 

commit 1bd6afe38489ac7979b51982a2759622dfc3f7f7
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat May 30 18:15:54 2015 -0700

    Move KVP_TYPE_BOOLEAN to the end of the enum.
    
    So that it doesn't change the numeric values of other entries, which
    would introduce a database incompatibility.

diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index 136006e..493098e 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -95,15 +95,15 @@ typedef enum
     KVP_TYPE_INVALID = -1,
     KVP_TYPE_GINT64 = 1, /**< QOF_TYPE_INT64  gint64 */
     KVP_TYPE_DOUBLE,     /**< QOF_TYPE_DOUBLE  gdouble */
-    KVP_TYPE_BOOLEAN,    /**< QOF_TYPE_BOOLEAN gboolean */
     KVP_TYPE_NUMERIC,    /**< QOF_TYPE_NUMERIC */
     KVP_TYPE_STRING,     /**< QOF_TYPE_STRING gchar* */
     KVP_TYPE_GUID,       /**< QOF_TYPE_GUID */
     KVP_TYPE_TIMESPEC,   /**< QOF_TYPE_DATE */
     KVP_TYPE_PLACEHOLDER_DONT_USE, /* Replaces KVP_TYPE_BINARY */
     KVP_TYPE_GLIST,      /**< no QOF equivalent. */
-    KVP_TYPE_FRAME,       /**< no QOF equivalent. */
-    KVP_TYPE_GDATE       /**< no QOF equivalent. */
+    KVP_TYPE_FRAME,      /**< no QOF equivalent. */
+    KVP_TYPE_GDATE,      /**< no QOF equivalent. */
+    KVP_TYPE_BOOLEAN,    /**< QOF_TYPE_BOOLEAN gboolean */
 } KvpValueType;
 
 /** \deprecated Deprecated backwards compat token

commit ac29ad3cef184f674097a9de7c78f026ac9f65af
Author: John Ralls <jralls at ceridwen.us>
Date:   Sat May 23 15:05:52 2015 -0700

    Remove direct query of KVP.
    
    Wasn't actually used anywhere, and it's not something we want to
    support.

diff --git a/src/engine/Query.c b/src/engine/Query.c
index d475fdb..c82795d 100644
--- a/src/engine/Query.c
+++ b/src/engine/Query.c
@@ -565,32 +565,6 @@ xaccQueryAddGUIDMatch(QofQuery * q, const GncGUID *guid,
     qof_query_add_guid_match (q, param_list, guid, op);
 }
 
-void
-xaccQueryAddKVPMatch(QofQuery *q, GSList *path, const KvpValue *value,
-                     QofQueryCompare how, QofIdType id_type,
-                     QofQueryOp op)
-{
-    GSList *param_list = NULL;
-    QofQueryPredData *pred_data;
-
-    if (!q || !path || !value || !id_type)
-        return;
-
-    pred_data = qof_query_kvp_predicate (how, path, value);
-    if (!pred_data)
-        return;
-
-    if (!g_strcmp0 (id_type, GNC_ID_SPLIT))
-        param_list = qof_query_build_param_list (SPLIT_KVP, NULL);
-    else if (!g_strcmp0 (id_type, GNC_ID_TRANS))
-        param_list = qof_query_build_param_list (SPLIT_TRANS, TRANS_KVP, NULL);
-    else if (!g_strcmp0 (id_type, GNC_ID_ACCOUNT))
-        param_list = qof_query_build_param_list (SPLIT_ACCOUNT, ACCOUNT_KVP, NULL);
-    else
-        PERR ("Invalid match type: %s", id_type);
-
-    qof_query_add_term (q, param_list, pred_data, op);
-}
 
 /********************************************************************
  * xaccQueryAddClosingTransMatch
diff --git a/src/engine/Query.h b/src/engine/Query.h
index aec579e..0d27ad1 100644
--- a/src/engine/Query.h
+++ b/src/engine/Query.h
@@ -186,10 +186,6 @@ void xaccQueryAddClearedMatch(QofQuery * q, cleared_match_t how, QofQueryOp op);
 void xaccQueryAddGUIDMatch(QofQuery * q, const GncGUID *guid,
                            QofIdType id_type, QofQueryOp op);
 
-/** given kvp value is on right side of comparison */
-void xaccQueryAddKVPMatch(QofQuery *q, GSList *path, const KvpValue *value,
-                          QofQueryCompare how, QofIdType id_type,
-                          QofQueryOp op);
 
 /*******************************************************************
  *  compatibility interface with old QofQuery API
diff --git a/src/engine/engine-helpers.c b/src/engine/engine-helpers.c
index 0e2f36b..e1c9357 100644
--- a/src/engine/engine-helpers.c
+++ b/src/engine/engine-helpers.c
@@ -477,32 +477,6 @@ gnc_scm2amt_match_how (SCM how_scm)
     return res;
 }
 
-static QofQueryCompare
-gnc_scm2kvp_match_how (SCM how_scm)
-{
-    QofQueryCompare res;
-    gchar *how = gnc_scm_symbol_to_locale_string (how_scm);
-
-    if (!g_strcmp0 (how, "kvp-match-lt"))
-        res = QOF_COMPARE_LT;
-    else if (!g_strcmp0 (how, "kvp-match-lte"))
-        res = QOF_COMPARE_LTE;
-    else if (!g_strcmp0 (how, "kvp-match-eq"))
-        res = QOF_COMPARE_EQUAL;
-    else if (!g_strcmp0 (how, "kvp-match-gte"))
-        res = QOF_COMPARE_GTE;
-    else if (!g_strcmp0 (how, "kvp-match-gt"))
-        res = QOF_COMPARE_GT;
-    else
-    {
-        PINFO ("invalid kvp match: %s", how);
-        res = QOF_COMPARE_EQUAL;
-    }
-
-    g_free (how);
-    return res;
-}
-
 static int
 gnc_scm2bitfield (SCM field_scm)
 {
@@ -558,33 +532,6 @@ gnc_scm2balance_match_how (SCM how_scm, gboolean *resp)
     return TRUE;
 }
 
-static QofIdType
-gnc_scm2kvp_match_where (SCM where_scm)
-{
-    QofIdType res;
-    gchar *where;
-
-    if (!scm_is_list (where_scm))
-        return NULL;
-
-    where = gnc_scm_symbol_to_locale_string (SCM_CAR(where_scm));
-
-    if (!g_strcmp0 (where, "kvp-match-split"))
-        res = GNC_ID_SPLIT;
-    else if (!g_strcmp0 (where, "kvp-match-trans"))
-        res = GNC_ID_TRANS;
-    else if (!g_strcmp0 (where, "kvp-match-account"))
-        res = GNC_ID_ACCOUNT;
-    else
-    {
-        PINFO ("Unknown kvp-match-where: %s", where);
-        res = NULL;
-    }
-
-    g_free (where);
-    return res;
-}
-
 static SCM
 gnc_guid_glist2scm (const GList *account_guids)
 {
@@ -1646,48 +1593,6 @@ gnc_scm2query_term_query_v1 (SCM query_term_scm)
             ok = TRUE;
 
         }
-        else if (!g_strcmp0 (pd_type, "pd-kvp"))
-        {
-            GSList *path;
-            KvpValue *value;
-            QofQueryCompare how;
-            QofIdType where;
-
-            /* how */
-            if (scm_is_null (query_term_scm))
-                break;
-            scm = SCM_CAR (query_term_scm);
-            query_term_scm = SCM_CDR (query_term_scm);
-            how = gnc_scm2kvp_match_how (scm);
-
-            /* where */
-            if (scm_is_null (query_term_scm))
-                break;
-            scm = SCM_CAR (query_term_scm);
-            query_term_scm = SCM_CDR (query_term_scm);
-            where = gnc_scm2kvp_match_where (scm);
-
-            /* path */
-            if (scm_is_null (query_term_scm))
-                break;
-            scm = SCM_CAR (query_term_scm);
-            query_term_scm = SCM_CDR (query_term_scm);
-            path = gnc_query_scm2path (scm);
-
-            /* value */
-            if (scm_is_null (query_term_scm))
-                break;
-            scm = SCM_CAR (query_term_scm);
-            query_term_scm = SCM_CDR (query_term_scm);
-            value = gnc_scm2KvpValue (scm);
-
-            xaccQueryAddKVPMatch (q, path, value, how, where, QOF_QUERY_OR);
-
-            gnc_query_path_free (path);
-            kvp_value_delete (value);
-            ok = TRUE;
-
-        }
         else
         {
             PINFO ("Unknown Predicate: %s", pd_type);
diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c
index 857e9b2..631834a 100644
--- a/src/engine/test-core/test-engine-stuff.c
+++ b/src/engine/test-core/test-engine-stuff.c
@@ -1812,20 +1812,6 @@ get_random_query(void)
             break;
 
         case 8: /* PR_KVP */
-            path = get_random_kvp_path ();
-            do
-            {
-                value = get_random_kvp_value_depth (-2, kvp_max_depth);
-            }
-            while (!value);
-            xaccQueryAddKVPMatch (q,
-                                  path,
-                                  value,
-                                  get_random_int_in_range (1, QOF_COMPARE_NEQ),
-                                  get_random_id_type (),
-                                  get_random_queryop ());
-            kvp_value_delete (value);
-            free_random_kvp_path (path);
             break;
 
         case 9: /* PR_MEMO */
@@ -1977,39 +1963,6 @@ typedef struct
     QofQuery *q;
 } KVPQueryData;
 
-static void
-add_kvp_value_query (const char *key, KvpValue *value, gpointer data)
-{
-    KVPQueryData *kqd = data;
-    GSList *node;
-
-    kqd->path = g_slist_append (kqd->path, (gpointer) key);
-
-    if (kvp_value_get_type (value) == KVP_TYPE_FRAME)
-        kvp_frame_for_each_slot (kvp_value_get_frame (value),
-                                 add_kvp_value_query, data);
-    else
-        xaccQueryAddKVPMatch (kqd->q, kqd->path, value,
-                              QOF_COMPARE_EQUAL, kqd->where,
-                              QOF_QUERY_AND);
-
-    node = g_slist_last (kqd->path);
-    kqd->path = g_slist_remove_link (kqd->path, node);
-    g_slist_free_1 (node);
-}
-
-static void
-add_kvp_query (QofQuery *q, KvpFrame *frame, QofIdType where)
-{
-    KVPQueryData kqd;
-
-    kqd.where = where;
-    kqd.path = NULL;
-    kqd.q = q;
-
-    kvp_frame_for_each_slot (frame, add_kvp_value_query, &kqd);
-}
-
 static gboolean include_price = TRUE;
 
 void
@@ -2021,17 +1974,11 @@ trans_query_include_price (gboolean include_price_in)
 TestQueryTypes
 get_random_query_type (void)
 {
-    switch (get_random_int_in_range (0, 4))
+    switch (get_random_int_in_range (0, 1))
     {
     case 0:
         return SIMPLE_QT;
     case 1:
-        return SPLIT_KVP_QT;
-    case 2:
-        return TRANS_KVP_QT;
-    case 3:
-        return ACCOUNT_KVP_QT;
-    case 4:
         return GUID_QT;
     default:
         return SIMPLE_QT;
@@ -2178,15 +2125,6 @@ make_trans_query (Transaction *trans, TestQueryTypes query_types)
                                GNC_ID_ACCOUNT, QOF_QUERY_AND);
     }
 
-    if (query_types & SPLIT_KVP_QT)
-        add_kvp_query (q, qof_instance_get_slots (QOF_INSTANCE (s)), GNC_ID_SPLIT);
-
-    if (query_types & TRANS_KVP_QT)
-        add_kvp_query (q, qof_instance_get_slots (QOF_INSTANCE (trans)), GNC_ID_TRANS);
-
-    if (query_types & ACCOUNT_KVP_QT)
-        add_kvp_query (q, qof_instance_get_slots (QOF_INSTANCE (a)), GNC_ID_ACCOUNT);
-
     return q;
 }
 
diff --git a/src/engine/test/test-scm-query-import.scm b/src/engine/test/test-scm-query-import.scm
index 61d68cd..0e1ef38 100644
--- a/src/engine/test/test-scm-query-import.scm
+++ b/src/engine/test/test-scm-query-import.scm
@@ -73,8 +73,7 @@ f^Vh4^6~sr4FJBY>
 U\"Uzm`V9w
 tUpg,>&Rf\"vp0(%#Xh'nxSP7JDL5HJ8N]V34Tomuj2v)f(	O7IA[}Mfz(Vnoj/F(")))) (primary-sort by-none) (secondary-sort by-date-entered) (tertiary-sort by-date-reconciled) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 44703))
 
-   '((terms (((pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 1.64746029726043e-215) (pd-account pr-account #t acct-match-none ()) (pd-balance pr-balance #f (balance-match-unbalanced))) ((pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 1.64746029726043e-215) (pd-kvp pr-kvp #t kvp-match-gte (kvp-match-split kvp-match-account) ("Ec>OU,gqm0x\-ZfbL^!<l)W},!)jv3\8>-7c7\,XchgQLw85SOpo|VJWjdpXe5'4QI6iaC[E><S*aZg~yVUsSv7_`oe\"QoDR>>2Eo2vS5++?K\EBDgmn=m_MtaVvxgM[t2P\"!$
-&0-9|%PM~ZR=V9Bw516YCXFcqGf|7Nu0XUPE9J1 at -a\"nF0'%ri~3Oy		5Mzp&9HzXi_4pDM8*g./2qb17Q)'f at -prwD	CUK|Is,L/EZf") (KVP-TYPE-GUID 1829a71bca494313d88715c70bfd04bc)) (pd-balance pr-balance #f (balance-match-unbalanced))))) (primary-sort by-date-rounded) (secondary-sort by-date-entered-rounded) (tertiary-sort by-date) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #f) (max-splits 49280))
+   '((terms (((pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 1.64746029726043e-215) (pd-account pr-account #t acct-match-none ()) (pd-balance pr-balance #f (balance-match-unbalanced))) ((pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 1.64746029726043e-215) (pd-balance pr-balance #f (balance-match-unbalanced))))) (primary-sort by-date-rounded) (secondary-sort by-date-entered-rounded) (tertiary-sort by-date) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #f) (max-splits 49280))
 
    '((terms (((pd-string pr-num #t #t #f "/~W
 ~3+?&x^bi5?t-dt(n6vU`}3l/drQR!^FN|eZdWe|'s#p]sJNU)O|C>OsU]2zvV^d$q9 !Q|~&q4X?84A'*ZMgF!4t&7?C)2D.LBJ1dJ?Mm>\"VNq{HtNol#J-Qu#	CnSFJh_h&/_agHS?g>6g90(tq(r4.t
@@ -106,19 +105,13 @@ uN\"2W.w'BLg-08Tj^Jv$Ftk at 7F,L-'p.x.`])Ii JBe 0v4.+@>8UJC7\9]vX1IiF?\"f[8fF)\F}$n
 
    '((terms (((pd-guid pr-guid #t 18790e0a69dc0b7bd212e66458636efb "gs]pcC|b") (pd-amount pr-shares #t amt-match-exactly QOF-NUMERIC-MATCH-ANY 4.22730383040921e-17)))) (primary-sort by-none) (secondary-sort by-reconcile) (tertiary-sort by-date-entered-rounded) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 12121))
 
-   '((terms (((pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.06956179639452e-138) (pd-kvp pr-kvp #t kvp-match-gt (kvp-match-account) ("/Qo|_TMC%. `T%k{gs^*d at 8rCc`L Weovrw^d]Kw?&>8 (gg7t,)igFV&|=C'bga8PS4qbA2_~c9ygld3}\UCp,\"s]+ZYVpx0AQ64K#q?l3
->+LS|ey7
-efs60}r!HDX!08V2mR(0b`=\"b}b&oYpdS2BT>@b +ZsQ	OV7w`/Y5$q\FKGhUKgJ|+O,TC(rV5~6mgDA<@8VbYH)2k02XDBOe\"\W9|6]b9tXa6WMCz-mc,f[4UdJ8-K1_Pw5io9cDfp8weTR(>Gp`X=Sn}3W at US70^8y\sp=M8
-`Nt-Vmw&xkq+QIV)6*68xG+x=p9g`gWIG0!2yPp])#3pq{j`8!9=xsV'd\"V4LHz4]H{78aq|x#I>UU.W7r0\"HBT|\m_73eq)ud=}qP_W/?bZGgg'{nOKe
-Ep1fjagDPTu=T_Q-gh)Db8l|<YYL<HuU`w>nQ302wA+nqSz]sSIn).|2*+	EN#K_\"nsF at P+r}<UG`'[0d?{|?8`_Pp^g/rEe`,ZW#\"1Nn6#5(WyA1	ab IwGV@>$5v( 0Q!B44o`Ss") (KVP-TYPE-NUMERIC (7849742814491100012 . 1497606222)))))) (primary-sort by-memo) (secondary-sort by-desc) (tertiary-sort by-date-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 37463))
+   '((terms (((pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.06956179639452e-138)))) (primary-sort by-memo) (secondary-sort by-desc) (tertiary-sort by-date-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 37463))
 
    '((terms (((pd-guid pr-guid #f 33960059c4ec5ba399a673e63e2c4bd8 "QO$m$
 *W=e&1Z") (pd-amount pr-price #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 2.24964711382668e138) (pd-string pr-action #f #t #t "C65fF4g") (pd-guid pr-guid #t 9ce8a7189a378f858610b07de4fdf581 "y'#_BD*w[-K\\")) ((pd-guid pr-guid #t 33960059c4ec5ba399a673e63e2c4bd8 "QO$m$
 *W=e&1Z") (pd-string pr-action #t #t #t "C65fF4g") (pd-guid pr-guid #t 9ce8a7189a378f858610b07de4fdf581 "y'#_BD*w[-K\\")) ((pd-amount pr-price #t amt-match-exactly QOF-NUMERIC-MATCH-ANY 2.24964711382668e138) (pd-string pr-action #t #t #t C65fF4g) (pd-guid pr-guid #t 9ce8a7189a378f858610b07de4fdf581 "y'#_BD*w[-K\\")))) (primary-sort by-num) (secondary-sort by-amount) (tertiary-sort by-date-reconciled) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 36860))
 
-   '((terms (((pd-kvp pr-kvp #f kvp-match-lt (kvp-match-split kvp-match-trans kvp-match-account) (0%f$6j$x2\9uAAnh!) (KVP-TYPE-NUMERIC (4914088713915763074 . 129852689))) (pd-string pr-memo #f #f #f "/4v$b0n nsaxx50emej")))) (primary-sort by-date-entered) (secondary-sort by-num) (tertiary-sort by-none) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #f) (max-splits 34487))
-
-   '((terms (((pd-kvp pr-kvp #t kvp-match-gt (kvp-match-split) (",ZjNCE\"yMM/r>u!-iF") (KVP-TYPE-STRING "OF\\?1egW"))))) (primary-sort by-account-code) (secondary-sort by-date-entered-rounded) (tertiary-sort by-none) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -43316))
+   '((terms (((pd-string pr-memo #f #f #f "/4v$b0n nsaxx50emej")))) (primary-sort by-date-entered) (secondary-sort by-num) (tertiary-sort by-none) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #f) (max-splits 34487))
 
    '((terms (((pd-amount pr-value #t amt-match-atmost QOF-NUMERIC-MATCH-DEBIT 1.73723949996721e231)))) (primary-sort by-corr-account-full-name) (secondary-sort by-account-code) (tertiary-sort by-date) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #f) (max-splits -42662))
 
@@ -127,30 +120,14 @@ Ep1fjagDPTu=T_Q-gh)Db8l|<YYL<HuU`w>nQ302wA+nqSz]sSIn).|2*+	EN#K_\"nsF at P+r}<UG`'[
    '((terms (((pd-string pr-desc #f #f #t "[F
 mSQW'C]t`NboD$%0") (pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-CREDIT 4.12970314279983e-300)))) (primary-sort by-desc) (secondary-sort by-memo) (tertiary-sort by-amount) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -15896))
 
-   '((terms (((pd-amount pr-shares #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 9.64353083878203e246) (pd-kvp pr-kvp #f kvp-match-gte (kvp-match-split kvp-match-trans) ("YrS&CR%SROK}uzx)]h] #a((LRl$`Ss
-|eM3n]HVns+V
-
-J zGtxsLbJ!3m_fJT66hnS24u'0a*Rq,wx$~_{1nvzL0C7v+n0>%YA3tk|p ^Y$(-}cWrx}+ZE=*oZV\"hM(  mi_CK{&(G3U[$S6w!RM7x9lH?1l2[-n%fB]<MjtwDaIV?'M|dh\"[q+Zq
-b-'1-z^8|.&S)i=9!lv Fhzdx7uo p*xP9uvc{%J	bfCA `.6y{Cq5Jq") (KVP-TYPE-GINT64 1641015724138329431))) ((pd-string pr-desc #t #f #f "tpqhfev'l") (pd-kvp pr-kvp #f kvp-match-gte (kvp-match-split kvp-match-trans) ("YrS&CR%SROK}uzx)]h] #a((LRl$`Ss
-|eM3n]HVns+V
-
-J zGtxsLbJ!3m_fJT66hnS24u'0a*Rq,wx$~_{1nvzL0C7v+n0>%YA3tk|p ^Y$(-}cWrx}+ZE=*oZV\"hM(  mi_CK{&(G3U[$S6w!RM7x9lH?1l2[-n%fB]<MjtwDaIV?'M|dh\"[q+Zq
-b-'1-z^8|.&S)i=9!lv Fhzdx7uo p*xP9uvc{%J	bfCA `.6y{Cq5Jq") (KVP-TYPE-GINT64 1641015724138329431))) ((pd-string pr-desc #f #f #t "nC$Qqzlo`2>nYgA") (pd-kvp pr-kvp #f kvp-match-gte (kvp-match-split kvp-match-trans) ("YrS&CR%SROK}uzx)]h] #a((LRl$`Ss
-|eM3n]HVns+V
-
-J zGtxsLbJ!3m_fJT66hnS24u'0a*Rq,wx$~_{1nvzL0C7v+n0>%YA3tk|p ^Y$(-}cWrx}+ZE=*oZV\"hM(  mi_CK{&(G3U[$S6w!RM7x9lH?1l2[-n%fB]<MjtwDaIV?'M|dh\"[q+Zq
-b-'1-z^8|.&S)i=9!lv Fhzdx7uo p*xP9uvc{%J	bfCA `.6y{Cq5Jq") (KVP-TYPE-GINT64 1641015724138329431))) ((pd-string pr-desc #t #f #t nC$Qqzlo`2>nYgA) (pd-string pr-desc #f #f #f "tpqhfev'l") (pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 9.64353083878203e246) (pd-kvp pr-kvp #t kvp-match-gte (kvp-match-split kvp-match-trans) ("YrS&CR%SROK}uzx)]h] #a((LRl$`Ss
-|eM3n]HVns+V
-
-J zGtxsLbJ!3m_fJT66hnS24u'0a*Rq,wx$~_{1nvzL0C7v+n0>%YA3tk|p ^Y$(-}cWrx}+ZE=*oZV\"hM(  mi_CK{&(G3U[$S6w!RM7x9lH?1l2[-n%fB]<MjtwDaIV?'M|dh\"[q+Zq
-b-'1-z^8|.&S)i=9!lv Fhzdx7uo p*xP9uvc{%J	bfCA `.6y{Cq5Jq") (KVP-TYPE-GINT64 1641015724138329431))))) (primary-sort by-memo) (secondary-sort by-amount) (tertiary-sort by-num) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -13211))
+   '((terms (((pd-amount pr-shares #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 9.64353083878203e246)) ((pd-string pr-desc #t #f #f "tpqhfev'l")) ((pd-string pr-desc #f #f #t "nC$Qqzlo`2>nYgA")) ((pd-string pr-desc #t #f #t nC$Qqzlo`2>nYgA) (pd-string pr-desc #f #f #f "tpqhfev'l") (pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 9.64353083878203e246)))) (primary-sort by-memo) (secondary-sort by-amount) (tertiary-sort by-num) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -13211))
 
    '((terms (((pd-amount pr-value #t amt-match-atmost QOF-NUMERIC-MATCH-CREDIT 3.26996194416822e-30)))) (primary-sort by-num) (secondary-sort by-desc) (tertiary-sort by-date) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #f) (max-splits 27766))
 
    '((terms (((pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 2.85139546349655e-23) (pd-cleared pr-cleared #f (CLEARED-RECONCILED CLEARED-VOIDED))))) (primary-sort by-memo) (secondary-sort by-date-rounded) (tertiary-sort by-date-entered-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 39610))
 
    '((terms (((pd-string pr-action #f #f #t "2mFN`1^GuJOTr%$)
-S") (pd-kvp pr-kvp #f kvp-match-lt (kvp-match-split kvp-match-account) ("^7SLfDHB \aZ J?") (KVP-TYPE-DOUBLE 1.6397473681711e162)) (pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-DEBIT 3.15279547396611e-153)) ((pd-string pr-action #f #f #t "2mFN`1^GuJOTr%$)
+S") (pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-DEBIT 3.15279547396611e-153)) ((pd-string pr-action #f #f #t "2mFN`1^GuJOTr%$)
 S") (pd-string pr-action #f #t #f "S/7kF\*4,ABM") (pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-DEBIT 3.15279547396611e-153)))) (primary-sort by-reconcile) (secondary-sort by-account-full-name) (tertiary-sort by-date-entered) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits -11705))
 
    '((terms (((pd-string pr-memo #t #t #t "nJvO\"+ at 3glb\17iT{Y9")))) (primary-sort by-date-entered) (secondary-sort by-account-code) (tertiary-sort by-desc) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -12193))
@@ -159,19 +136,13 @@ S") (pd-string pr-action #f #t #f "S/7kF\*4,ABM") (pd-amount pr-value #f amt-mat
 
    '((terms (((pd-string pr-num #t #f #t kWj%rF4'nmxx`) (pd-string pr-action #f #f #f "4}`p^',5fo|	gqj\"lf")) ((pd-string pr-num #f #f #t "kWj%rF4'nmxx`") (pd-string pr-action #t #f #f "4}`p^',5fo|	gqj\"lf")))) (primary-sort by-date-reconciled) (secondary-sort by-account-full-name) (tertiary-sort by-date-reconciled-rounded) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -15649))
 
-   '((terms (((pd-kvp pr-kvp #f kvp-match-lt (kvp-match-split) ("+ p}?EVpAl xH{V._YL at J1v]ec9GH1 >]K\%7=yE EgJA>W<]DEm<B+WK4UQ)H]XRp89	@Xv1 at S?(Q|
-eAp2l}KhL LglM*4_q*<,RC`AJ/NG6!%~CV!jY@|w3t8L^RXovp?E\YDgGgXjsb3g{#wgBqP~8uoXJXJQ?PBm44#PN<<7VjkIWh$u&kq$[J^A
-[#5z5R/XIz#.ZNy)iZ%Vl#bjtg}E$
-\"#+!*,1dSaLtCC8iEE95N,|X|wdQM<7{gG!L_'!Wu7J|SqIN,c8*t7q-y8g}D2YrVc^6rG.%&k\)vE7]H-NX}j#xcp$d0D\2V\"5iHnOZL,`$]6?%QVR='ksYRCIC=3.owx[1FyVagNoG IM<%^]\".Z~U^vnkA|94e.VB2L|k2\zF1R=n4WF#2V\sh&@08fg>?ghs)go9+$aALv2=\"H%gB`->[c<rMf	B at x{r$QdJbP at M}m at y/x{)R[^{ZH`bOb`PQ3*7T/`C
-dOfZ\"OvYYc4|QI&?3bS4PHyIyvQp	?J|2bm6DSh$~)
-nQYy5`Hcy}$ |um O	LJ") (KVP-TYPE-DOUBLE 1.05469420086343e75)) (pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 23475509.5431048)))) (primary-sort by-corr-account-code) (secondary-sort by-standard) (tertiary-sort by-account-code) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 11726))
+   '((terms (((pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 23475509.5431048)))) (primary-sort by-corr-account-code) (secondary-sort by-standard) (tertiary-sort by-account-code) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 11726))
 
    '((terms (((pd-balance pr-balance #t (balance-match-balanced balance-match-unbalanced)) (pd-amount pr-value #t amt-match-atmost QOF-NUMERIC-MATCH-DEBIT 9.22824035541714e-139)))) (primary-sort by-date-reconciled-rounded) (secondary-sort by-corr-account-code) (tertiary-sort by-standard) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -41473))
 
    '((terms (((pd-string pr-memo #t #f #f "'pb%yl!zyn") (pd-amount pr-price #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 5.16279398584784e281)) ((pd-string pr-memo #f #f #f "'pb%yl!zyn") (pd-amount pr-price #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 5.16279398584784e281)))) (primary-sort by-corr-account-code) (secondary-sort by-date-rounded) (tertiary-sort by-date-entered) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 5299))
 
-   '((terms (((pd-kvp pr-kvp #f kvp-match-lte (kvp-match-split kvp-match-trans) ("$ \c]
-<q yKq") (KVP-TYPE-GUID f6fa898ea9f381ae4a1b6e5a268e5626)) (pd-guid pr-guid #t 759948802afe011061d1a342b32c8f31 "i	]X\2I^ydGY4Ed-|/")) ((pd-cleared pr-cleared #f (CLEARED-CLEARED)) (pd-guid pr-guid #t 759948802afe011061d1a342b32c8f31 "i	]X\2I^ydGY4Ed-|/")) ((pd-string pr-memo #t #f #f "{t1k/")))) (primary-sort by-memo) (secondary-sort by-date-entered-rounded) (tertiary-sort by-date-rounded) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -4310))
+   '((terms (((pd-guid pr-guid #t 759948802afe011061d1a342b32c8f31 "i	]X\2I^ydGY4Ed-|/")) ((pd-cleared pr-cleared #f (CLEARED-CLEARED)) (pd-guid pr-guid #t 759948802afe011061d1a342b32c8f31 "i	]X\2I^ydGY4Ed-|/")) ((pd-string pr-memo #t #f #f "{t1k/")))) (primary-sort by-memo) (secondary-sort by-date-entered-rounded) (tertiary-sort by-date-rounded) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -4310))
 
    '((terms (((pd-amount pr-shares #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 3.50856623605167e-243)))) (primary-sort by-desc) (secondary-sort by-standard) (tertiary-sort by-corr-account-code) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 1550))
 
@@ -190,7 +161,7 @@ nQYy5`Hcy}$ |um O	LJ") (KVP-TYPE-DOUBLE 1.05469420086343e75)) (pd-amount pr-pric
 
    '((terms (((pd-amount pr-shares #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 3.6086738132056e-265) (pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.91890421925465e137) (pd-account pr-account #t acct-match-any ())) ((pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 4.08135187738323e-39) (pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.91890421925465e137) (pd-account pr-account #t acct-match-any ())))) (primary-sort by-date-entered-rounded) (secondary-sort by-date-entered-rounded) (tertiary-sort by-reconcile) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 29956))
 
-   '((terms (((pd-amount pr-shares #t amt-match-exactly QOF-NUMERIC-MATCH-ANY 6.60021429524694e295) (pd-amount pr-value #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.39568881600667e228) (pd-amount pr-value #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 2.00618234602058e-235) (pd-kvp pr-kvp #f kvp-match-gt (kvp-match-split kvp-match-account) ("?[{[3'") (KVP-TYPE-STRING B!YpYi4l))) ((pd-amount pr-shares #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 6.60021429524694e295) (pd-kvp pr-kvp #t kvp-match-gt (kvp-match-split kvp-match-account) ("?[{[3'") (KVP-TYPE-STRING B!YpYi4l))) ((pd-amount pr-value #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.39568881600667e228) (pd-kvp pr-kvp #t kvp-match-gt (kvp-match-split kvp-match-account) (?[{[3') (KVP-TYPE-STRING B!YpYi4l))) ((pd-amount pr-value #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 2.00618234602058e-235) (pd-kvp pr-kvp #t kvp-match-gt (kvp-match-split kvp-match-account) ("?[{[3'") (KVP-TYPE-STRING B!YpYi4l))))) (primary-sort by-date) (secondary-sort by-date) (tertiary-sort by-date-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -12620))
+   '((terms (((pd-amount pr-shares #t amt-match-exactly QOF-NUMERIC-MATCH-ANY 6.60021429524694e295) (pd-amount pr-value #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.39568881600667e228)) ((pd-amount pr-shares #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 6.60021429524694e295)) ((pd-amount pr-value #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.39568881600667e228) (primary-sort by-date) (secondary-sort by-date) (tertiary-sort by-date-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -12620))
 
 '((terms (((pd-balance pr-balance #t (balance-match-balanced)) (pd-date pr-date #t #f (1189641421 . 1025202362) #f (1350490027 . 783368690)) (pd-string pr-memo #f #f #t "hGI?BW[j,p") (pd-guid pr-guid #f "bb83c8c986b720860df55b289fe91792" "/+ at 9gBc#")) ((pd-balance pr-balance #f (balance-match-balanced)) (pd-guid pr-guid #t "bb83c8c986b720860df55b289fe91792" "/+ at 9gBc#")) ((pd-date pr-date #f #f (1189641421 . 1025202362) #f (1350490027 . 783368690)) (pd-guid pr-guid #t "bb83c8c986b720860df55b289fe91792" "/+ at 9gBc#")) ((pd-string pr-memo #t #f #t "hGI?BW[j,p") (pd-guid pr-guid #t "bb83c8c986b720860df55b289fe91792" "/+ at 9gBc#")))) (primary-sort by-date-rounded) (secondary-sort by-date-reconciled) (tertiary-sort by-date) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 39910))
 
@@ -204,7 +175,7 @@ nQYy5`Hcy}$ |um O	LJ") (KVP-TYPE-DOUBLE 1.05469420086343e75)) (pd-amount pr-pric
 
 '((terms (((pd-account pr-account #f acct-match-none ())) ((pd-guid pr-guid #f "737bf61b64e3efef0b50fe46537aee43" "?6+")))) (primary-sort by-date-entered-rounded) (secondary-sort by-none) (tertiary-sort by-date-rounded) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 15903))
 
-'((terms (((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652))) ((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652))) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652))) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-kvp pr-kvp #t kvp-match-lt (kvp!
 -match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652))) ((pd-kvp pr-kvp #f kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-kvp pr-kvp #f kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652))) ((pd-kvp pr-kvp #f kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-kvp pr-kvp #f kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652)) (pd-kvp pr-kvp #t kvp-match-lt (kvp-match-trans) ("9ck,(Wv fC77P&" "=IDX" "O7?#Ov!K" "P4*4SLBU#WbFy8j9w" "i>ss=oZ-I?5") (KVP-TYPE-GINT64 2764623878556742652))) ((pd-string pr-memo #f #f #t "fc9\\\"|F5mM< <dGJ1")))) (primary-sort by-date) (secondary-sort by-corr-account-full-name) (tertiary-sort by-corr-account-code) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasin!
 g #f) (max-splits 46595))
+'((terms (((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-string pr-num #t #t #f "O`?<'zmw)m8")) ((pd-string pr-num #f #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUM) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-string pr-num #t #t #f "O`?<'zmw)m8")) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221) (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-amount pr-shares #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-string pr-num #t #t #f "O`?<'zmw)m8") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-string pr-num #t #t #f "O`?<'zmw)m8")) ((pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 8.50729589618366e221)) ((pd-string pr-memo #f #f #t "fc9\\\"|F5mM< <dGJ1")))) (primary-sort by-date) (secondary-sort by-corr-account-full-name) (tertiary-sort by-corr-account-code) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 46595))
 
 '((terms (((pd-date pr-date #t #f (1299997995 . 899284031) #f (357398920 . 1990229340)) (pd-guid pr-guid #t "d4b559388018799d97a75f9e8751816b" "DTl'U\"ZS'9]v%>>H") (pd-amount pr-shares #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 6.63684905521978e109)) ((pd-string pr-memo #t #t #t "yh=.,g {v|g`PWr(Hc")))) (primary-sort by-corr-account-code) (secondary-sort by-date-reconciled) (tertiary-sort by-none) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -41257))
 
@@ -220,8 +191,6 @@ nQYy5`Hcy}$ |um O	LJ") (KVP-TYPE-DOUBLE 1.05469420086343e75)) (pd-amount pr-pric
 MA ]X6?p5}aQh ]p
 _[<{,hfEE\\t4!+V~CB_")))) (primary-sort by-memo) (secondary-sort by-memo) (tertiary-sort by-date) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 44200))
 
-'((terms (((pd-kvp pr-kvp #t kvp-match-gte (kvp-match-split) (".Vjrx6 N0" "0FJ^CSx|3&.AK~^tY" "elN_Stl3Q}t<=g" "+vXJ8*cNp?cN, ^h%Rv") (KVP-TYPE-NUMERIC (6557572410956937199 . 1335913515)))))) (primary-sort by-reconcile) (secondary-sort by-date-entered) (tertiary-sort by-date-reconciled-rounded) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits -9876))
-
 '((terms (((pd-guid pr-guid #t "7ef7bd5ec010f51c3576b945cedf677d" "iqfR mUo}7Y,!Z4Q") (pd-date pr-date #t #t (1671673525 . 126144767) #t (2040266038 . 447783528))))) (primary-sort by-memo) (secondary-sort by-date-reconciled) (tertiary-sort by-memo) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 7692))
 
 '((terms (((pd-balance pr-balance #f (balance-match-balanced balance-match-unbalanced)) (pd-cleared pr-cleared #t (CLEARED-CLEARED CLEARED-FROZEN))) ((pd-amount pr-shares #f amt-match-atmost QOF-NUMERIC-MATCH-ANY 1.02029999000694e-79) (pd-cleared pr-cleared #t (CLEARED-CLEARED CLEARED-FROZEN))))) (primary-sort by-standard) (secondary-sort by-date-reconciled) (tertiary-sort by-amount) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 9367))
@@ -230,7 +199,7 @@ _[<{,hfEE\\t4!+V~CB_")))) (primary-sort by-memo) (secondary-sort by-memo) (terti
 
 '((terms (((pd-guid pr-guid #f "b7b0b2de931b3300d34cc136d61388dd" "m*ba	1r~D&") (pd-date pr-date #f #f (1494621524 . 683689430) #f (749666912 . 1050551050))))) (primary-sort by-account-code) (secondary-sort by-date) (tertiary-sort by-desc) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -6668))
 
-'((terms (((pd-string pr-num #f #f #t "QL22+") (pd-balance pr-balance #f (balance-match-balanced)) (pd-kvp pr-kvp #f kvp-match-gte (kvp-match-split kvp-match-account) ("%\"|5Y") (KVP-TYPE-GUID "51cf13f972ff2140dbda3f2e71aeb9f3"))) ((pd-cleared pr-cleared #f (CLEARED-NO CLEARED-FROZEN))))) (primary-sort by-date-entered-rounded) (secondary-sort by-date-reconciled-rounded) (tertiary-sort by-standard) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -21190))
+'((terms (((pd-string pr-num #f #f #t "QL22+") (pd-balance pr-balance #f (balance-match-balanced))) ((pd-cleared pr-cleared #f (CLEARED-NO CLEARED-FROZEN))))) (primary-sort by-date-entered-rounded) (secondary-sort by-date-reconciled-rounded) (tertiary-sort by-standard) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -21190))
 
 '((terms (((pd-balance pr-balance #f (balance-match-balanced)) (pd-amount pr-value #f amt-match-exactly QOF-NUMERIC-MATCH-ANY 4.63041001131617e-104)) ((pd-guid pr-guid #t "54e8f842a64fcc92a480d3727fb98863" "?=W?*M	N_[=\\ Nu
 c4&rIG-ANp~j4'8c3\"1\\>9JY&L8Q=XXR05vpsx4*6 at 2 ~j++F\\q4&~HC,0M	v/bn[Gx'HaHJG1S!yuw [ybJ'Nsgm^uBVm
@@ -263,20 +232,8 @@ zKa[]Xp2M+@$HP!HBBfz\\H<t?ZY%*%~QWU\\Yp-Wz at 3") (pd-amount pr-price #f amt-match-
 
 '((terms (((pd-guid pr-guid #f "e19481332e748722cf062e5c95d31f5d" "9GrogU*c6") (pd-string pr-num #f #t #f "32]zr-)]B//kc-[rX") (pd-account pr-account #f acct-match-all ())) ((pd-guid pr-guid #t "e19481332e748722cf062e5c95d31f5d" "9GrogU*c6") (pd-account pr-account #t acct-match-all ())) ((pd-string pr-num #t #t #f "32]zr-)]B//kc-[rX") (pd-account pr-account #t acct-match-all ())))) (primary-sort by-date-entered-rounded) (secondary-sort by-corr-account-full-name) (tertiary-sort by-date-reconciled-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #f) (max-splits -14267))
 
-'((terms (((pd-kvp pr-kvp #t kvp-match-lte (kvp-match-split kvp-match-trans kvp-match-account) ("\"8,V" "c&-/T10yW!UEJ," "Zc]`4?sD0
-.nm" "`9Xnh5(x>=s(>" "0}y6$3|f^|*CDW") (KVP-TYPE-STRING "~A Z fYe>Bo"))))) (primary-sort by-account-full-name) (secondary-sort by-date-entered) (tertiary-sort by-corr-account-code) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #f) (max-splits -26061))
-
 '((terms (((pd-guid pr-guid #f "0dbdf5a0198d239e4be42843af646dc6" "QPARm'.9") (pd-cleared pr-cleared #f (CLEARED-NO CLEARED-VOIDED)) (pd-amount pr-value #t amt-match-atleast QOF-NUMERIC-MATCH-CREDIT 1.34610194996531e270)))) (primary-sort by-date-entered) (secondary-sort by-date-entered) (tertiary-sort by-date-rounded) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits -17627))
 
-'((terms (((pd-kvp pr-kvp #t kvp-match-lt (kvp-match-account) ("._`g9|z" "J6p*WhU9/lkBzu?") (KVP-TYPE-STRING "3z} \"/=GG{?%Ud `Wu)qCm
-O\\]nvw]vA_HM^+hU1RB)(a-m	Q#RwK
-Z_$W)C~lG9S]n$YL?#!9a\\wo kh#Hr[zqgp2@')Ro!>xRS.xtZyzWK6j*Vnq%Yn!xVn{PUTx_hhI$Fv1v/S`zbfs-Iq$cs	m\\
-lf	6.Nf7Hs]#'RJ9uUKv]Ib+\"&Sj-@[8mS5cof9lJ50\\0?bidX,p03MBS]k.u0%bk,nH&#(W88Q-`=^`\\I0VngD'N(gXQ+~AqqGd-'/I&'PHg~|_$JPiEY,qj(	JEy48MN
-22[xz6]m3J-|<ChZ[ekr\\6t Q3pk1H<#C7F?\"iZB'Uy4mg.Xkr|$w.-m~cx|81qh?J+>,a(|+UsFg
-WuSc3w(h2Pq\\1|0L~eE^w=QT+PUxNogLZ&ywpJ]azG)eyJNjLpJ8+Il~VM>]Xs0F 	2)}vHL.4O_	x/Q]Eg HAO#|,)7zY)]l
-p7A.^>}y
-S.bVf 10F$|f?ac4.{]7"))))) (primary-sort by-date-reconciled-rounded) (secondary-sort by-reconcile) (tertiary-sort by-account-code) (primary-increasing #t) (secondary-increasing #t) (tertiary-increasing #t) (max-splits -20024))
-
 '((terms (((pd-string pr-num #t #t #t "X{|0\"EBv#KMv") (pd-date pr-date #t #t (1266228215 . 1895492974) #t (718257219 . 1304496951))) ((pd-string pr-action #t #f #t "bOm at -r4}wv`eJ$")))) (primary-sort by-corr-account-full-name) (secondary-sort by-date) (tertiary-sort by-standard) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 32210))
 
 '((terms (((pd-string pr-action #t #f #f "^i$yaoymg")))) (primary-sort by-corr-account-full-name) (secondary-sort by-date-entered) (tertiary-sort by-corr-account-full-name) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits -24604))
@@ -301,21 +258,7 @@ S.bVf 10F$|f?ac4.{]7"))))) (primary-sort by-date-reconciled-rounded) (secondary-
 
 '((terms (((pd-balance pr-balance #t (balance-match-unbalanced)) (pd-account pr-account #f acct-match-none ())) ((pd-date pr-date #t #f (2090358271 . 661270215) #f (1483999557 . 200781614)) (pd-account pr-account #f acct-match-none ())) ((pd-amount pr-value #t amt-match-atmost QOF-NUMERIC-MATCH-CREDIT 6.94161381654072e-188)))) (primary-sort by-date-entered) (secondary-sort by-desc) (tertiary-sort by-date-reconciled-rounded) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 7094))
 
-'((terms (((pd-account pr-account #t acct-match-none ()) (pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)) ((pd-account pr-account #t acct-match-any ()) (pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)) ((pd-kvp pr-kvp #f kvp-match-gte (kvp-match-split kvp-match-account) ("z(o4d'LVWww+VcM>a?.ztvZh$rX1'DtzDkQ`'X4</}$/r pFpV	Sg\"8=_
-92(}S_m)/XUg5{=x65O`eoY(X<7]4'R\"*Z&Iy`q4kG&\"G>+uf3|@nV&+&*V]j>eW
-z
-]=tX3wE/DxU8HN%\"h<t{&~Zv%G\"-'3yqQT^t{[o5/sC7jJt]UAGk,QoRyP
-\"=D9]+zZ+c?Yan'~?ajDt`(Nl at 5O|L.e\\y%w0~	kPX=fC0_ at iRV&LuT,9\"ByhQe~+8m+}Shv=ha,Q~Dwd.4O/\\C%/h!ipY2W_Am<}mRBaX2nx-Jmv
-	nQcz(mKYbrfO)gMNR')6eV/'RbG<osH.p0[]H7~.>+9	f$q1^\\7P%gy1.
-onp2s42Xwo6%8JKb7qxcgotLyrYq5j%TK+Nd&\"@6` WHY-dG02L 6pa D 
-6+9BO<zWC6\"|A4?BUm/\"z<Fy>)gVu*MJ7" "l-X,Sn") (KVP-TYPE-GINT64 9119873325614483559)) (pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)) ((pd-kvp pr-kvp #t kvp-match-gte (kvp-match-split kvp-match-account) ("z(o4d'LVWww+VcM>a?.ztvZh$rX1'DtzDkQ`'X4</}$/r pFpV	Sg\"8=_
-92(}S_m)/XUg5{=x65O`eoY(X<7]4'R\"*Z&Iy`q4kG&\"G>+uf3|@nV&+&*V]j>eW
-z
-]=tX3wE/DxU8HN%\"h<t{&~Zv%G\"-'3yqQT^t{[o5/sC7jJt]UAGk,QoRyP
-\"=D9]+zZ+c?Yan'~?ajDt`(Nl at 5O|L.e\\y%w0~	kPX=fC0_ at iRV&LuT,9\"ByhQe~+8m+}Shv=ha,Q~Dwd.4O/\\C%/h!ipY2W_Am<}mRBaX2nx-Jmv
-	nQcz(mKYbrfO)gMNR')6eV/'RbG<osH.p0[]H7~.>+9	f$q1^\\7P%gy1.
-onp2s42Xwo6%8JKb7qxcgotLyrYq5j%TK+Nd&\"@6` WHY-dG02L 6pa D 
-6+9BO<zWC6\"|A4?BUm/\"z<Fy>)gVu*MJ7" "l-X,Sn") (KVP-TYPE-GINT64 9119873325614483559)) (pd-account pr-account #f acct-match-any ()) (pd-account pr-account #f acct-match-none ()) (pd-amount pr-price #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)))) (primary-sort by-corr-account-code) (secondary-sort by-corr-account-code) (tertiary-sort by-amount) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 344))
+'((terms (((pd-account pr-account #t acct-match-none ()) (pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)) ((pd-account pr-account #t acct-match-any ()) (pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)) ((pd-amount pr-price #f amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)) ((pd-account pr-account #f acct-match-any ()) (pd-account pr-account #f acct-match-none ()) (pd-amount pr-price #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.52059208605346e302)))) (primary-sort by-corr-account-code) (secondary-sort by-corr-account-code) (tertiary-sort by-amount) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 344))
 
 '((terms (((pd-amount pr-shares #t amt-match-atmost QOF-NUMERIC-MATCH-ANY 7.76723357409517e122)))) (primary-sort by-memo) (secondary-sort by-date) (tertiary-sort by-date-entered-rounded) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits 6970))
 
@@ -323,12 +266,12 @@ onp2s42Xwo6%8JKb7qxcgotLyrYq5j%TK+Nd&\"@6` WHY-dG02L 6pa D
 
 '((terms (((pd-balance pr-balance #t (balance-match-unbalanced))))) (primary-sort by-date-entered-rounded) (secondary-sort by-amount) (tertiary-sort by-date-entered-rounded) (primary-increasing #f) (secondary-increasing #t) (tertiary-increasing #t) (max-splits 43879))
 
-'((terms (((pd-account pr-account #f acct-match-all ()) (pd-kvp pr-kvp #f kvp-match-gte (kvp-match-trans kvp-match-account) ("X`E%)+v.(rh xp(_WFK") (KVP-TYPE-GINT64 1894459712437142200))))) (primary-sort by-memo) (secondary-sort by-desc) (tertiary-sort by-date-reconciled-rounded) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -26988))
+'((terms (((pd-account pr-account #f acct-match-all ())))) (primary-sort by-memo) (secondary-sort by-desc) (tertiary-sort by-date-reconciled-rounded) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -26988))
 
 '((terms (((pd-balance pr-balance #f (balance-match-balanced balance-match-unbalanced)) (pd-amount pr-value #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.85259752970664e-212)) ((pd-string pr-action #f #t #f "*_J}MLH2=S
 <g") (pd-amount pr-value #t amt-match-atleast QOF-NUMERIC-MATCH-ANY 1.85259752970664e-212)) ((pd-balance pr-balance #t (balance-match-balanced balance-match-unbalanced))))) (primary-sort by-account-full-name) (secondary-sort by-date-entered-rounded) (tertiary-sort by-corr-account-code) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #f) (max-splits -6740))
 
-'((terms (((pd-amount pr-value #t amt-match-atleast QOF-NUMERIC-MATCH-CREDIT 1.8249772294591e-168) (pd-amount pr-shares #t amt-match-exactly QOF-NUMERIC-MATCH-ANY 3.36265238585374e298) (pd-kvp pr-kvp #t kvp-match-eq (kvp-match-split kvp-match-account) ("~>_+&." "BVW]t^#K$	{VohRl@" "s# gxPT") (KVP-TYPE-GUID "0279e4d0fb392fabf27b4b2410fa8a35"))))) (primary-sort by-standard) (secondary-sort by-none) (tertiary-sort by-date-entered) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits -6558))
+'((terms (((pd-amount pr-value #t amt-match-atleast QOF-NUMERIC-MATCH-CREDIT 1.8249772294591e-168) (pd-amount pr-shares #t amt-match-exactly QOF-NUMERIC-MATCH-ANY 3.36265238585374e298)))) (primary-sort by-standard) (secondary-sort by-none) (tertiary-sort by-date-entered) (primary-increasing #f) (secondary-increasing #f) (tertiary-increasing #t) (max-splits -6558))
 
 '((terms (((pd-cleared pr-cleared #t (CLEARED-CLEARED CLEARED-RECONCILED))))) (primary-sort by-num) (secondary-sort by-account-code) (tertiary-sort by-corr-account-full-name) (primary-increasing #t) (secondary-increasing #f) (tertiary-increasing #f) (max-splits 21219))
 

commit 45e41a07b14b4a274a5d843f12785daefbb17b9b
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 10 18:16:30 2015 -0700

    Convert gnc-budget, gnc-lot, and gncJob to qof_instance_foo_kvp.

diff --git a/src/engine/gnc-budget.c b/src/engine/gnc-budget.c
index 8fd057d..c9be5d1 100644
--- a/src/engine/gnc-budget.c
+++ b/src/engine/gnc-budget.c
@@ -42,11 +42,11 @@ static QofLogModule log_module = GNC_MOD_ENGINE;
 enum
 {
     PROP_0,
-    PROP_NAME,			/* Table */
-    PROP_DESCRIPTION,		/* Table */
-    PROP_NUM_PERIODS,		/* Table */
+    PROP_NAME,                  /* Table */
+    PROP_DESCRIPTION,           /* Table */
+    PROP_NUM_PERIODS,           /* Table */
     PROP_RUNTIME_0,
-    PROP_RECURRENCE,		/* Cached pointer; Recurrence table holds budget guid */
+    PROP_RECURRENCE,            /* Cached pointer; Recurrence table holds budget guid */
 };
 
 struct budget_s
@@ -159,7 +159,7 @@ gnc_budget_set_property( GObject* object,
 
     budget = GNC_BUDGET(object);
     if (prop_id < PROP_RUNTIME_0)
-	g_assert (qof_instance_get_editlevel(budget));
+        g_assert (qof_instance_get_editlevel(budget));
 
     switch ( prop_id )
     {
@@ -476,24 +476,29 @@ gnc_budget_get_num_periods(const GncBudget* budget)
 #define BUF_SIZE (10 + GUID_ENCODING_LENGTH + \
    GNC_BUDGET_MAX_NUM_PERIODS_DIGITS)
 
+static inline void
+make_period_path (const Account *account, guint period_num, char *path)
+{
+    const GncGUID *guid;
+    gchar *bufend;
+    guid = xaccAccountGetGUID(account);
+    bufend = guid_to_string_buff(guid, path);
+    g_sprintf(bufend, "/%d", period_num);
+}
 /* period_num is zero-based */
 /* What happens when account is deleted, after we have an entry for it? */
 void
 gnc_budget_unset_account_period_value(GncBudget *budget, const Account *account,
                                       guint period_num)
 {
-    const GncGUID *guid;
-    KvpFrame *frame;
     gchar path[BUF_SIZE];
-    gchar *bufend;
 
-    gnc_budget_begin_edit(budget);
-    frame = qof_instance_get_slots(QOF_INSTANCE(budget));
-    guid = xaccAccountGetGUID(account);
-    bufend = guid_to_string_buff(guid, path);
-    g_sprintf(bufend, "/%d", period_num);
+    g_return_if_fail (budget != NULL);
+    g_return_if_fail (account != NULL);
+    make_period_path (account, period_num, path);
 
-    kvp_frame_set_value(frame, path, NULL);
+    gnc_budget_begin_edit(budget);
+    qof_instance_set_kvp (QOF_INSTANCE (budget), path, NULL);
     qof_instance_set_dirty(&budget->inst);
     gnc_budget_commit_edit(budget);
 
@@ -507,10 +512,7 @@ void
 gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
                                     guint period_num, gnc_numeric val)
 {
-    const GncGUID *guid;
-    KvpFrame *frame;
     gchar path[BUF_SIZE];
-    gchar *bufend;
 
     /* Watch out for an off-by-one error here:
      * period_num starts from 0 while num_periods starts from 1 */
@@ -520,16 +522,21 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
         return;
     }
 
-    gnc_budget_begin_edit(budget);
-    frame = qof_instance_get_slots(QOF_INSTANCE(budget));
-    guid = xaccAccountGetGUID(account);
-    bufend = guid_to_string_buff(guid, path);
-    g_sprintf(bufend, "/%d", period_num);
+    g_return_if_fail (budget != NULL);
+    g_return_if_fail (account != NULL);
+
+    make_period_path (account, period_num, path);
 
+    gnc_budget_begin_edit(budget);
     if (gnc_numeric_check(val))
-        kvp_frame_set_value(frame, path, NULL);
+        qof_instance_set_kvp (QOF_INSTANCE (budget), path, NULL);
     else
-        kvp_frame_set_numeric(frame, path, val);
+    {
+        GValue v = G_VALUE_INIT;
+        g_value_init (&v, GNC_TYPE_NUMERIC);
+        g_value_set_boxed (&v, &val);
+        qof_instance_set_kvp (QOF_INSTANCE (budget), path, &v);
+    }
     qof_instance_set_dirty(&budget->inst);
     gnc_budget_commit_edit(budget);
 
@@ -541,42 +548,42 @@ gnc_budget_set_account_period_value(GncBudget *budget, const Account *account,
    Maybe this should move to Account.h */
 
 gboolean
-gnc_budget_is_account_period_value_set(const GncBudget *budget, const Account *account,
+gnc_budget_is_account_period_value_set(const GncBudget *budget,
+                                       const Account *account,
                                        guint period_num)
 {
+    GValue v = G_VALUE_INIT;
     gchar path[BUF_SIZE];
-    gchar *bufend;
-    KvpFrame *frame;
 
     g_return_val_if_fail(GNC_IS_BUDGET(budget), FALSE);
     g_return_val_if_fail(account, FALSE);
 
-    frame = qof_instance_get_slots(QOF_INSTANCE(budget));
-    bufend = guid_to_string_buff(xaccAccountGetGUID(account), path);
-    g_sprintf(bufend, "/%d", period_num);
-    return (kvp_frame_get_value(frame, path) != NULL);
+    make_period_path (account, period_num, path);
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    qof_instance_get_kvp (QOF_INSTANCE (budget), path, &v);
+    return (g_value_get_boxed (&v) != NULL);
 }
 
 gnc_numeric
-gnc_budget_get_account_period_value(const GncBudget *budget, const Account *account,
+gnc_budget_get_account_period_value(const GncBudget *budget,
+                                    const Account *account,
                                     guint period_num)
 {
-    gnc_numeric numeric;
+    gnc_numeric *numeric;
     gchar path[BUF_SIZE];
-    gchar *bufend;
-    KvpFrame *frame;
+    GValue v = G_VALUE_INIT;
 
-    numeric = gnc_numeric_zero();
-    g_return_val_if_fail(GNC_IS_BUDGET(budget), numeric);
-    g_return_val_if_fail(account, numeric);
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), gnc_numeric_zero());
+    g_return_val_if_fail(account, gnc_numeric_zero());
 
-    frame = qof_instance_get_slots(QOF_INSTANCE(budget));
-    bufend = guid_to_string_buff(xaccAccountGetGUID(account), path);
-    g_sprintf(bufend, "/%d", period_num);
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    make_period_path (account, period_num, path);
+    qof_instance_get_kvp (QOF_INSTANCE (budget), path, &v);
+    numeric = (gnc_numeric*)g_value_get_boxed (&v);
 
-    numeric = kvp_frame_get_numeric(frame, path);
-    /* This still returns zero if unset, but callers can check for that. */
-    return numeric;
+    if (numeric)
+        return *numeric;
+    return gnc_numeric_zero();
 }
 
 
@@ -637,16 +644,14 @@ gnc_budget_get_default (QofBook *book)
 
     g_return_val_if_fail(book, NULL);
 
-    /* See if there is a budget selected in the KVP perferences */
-
     qof_instance_get (QOF_INSTANCE (book),
-		      "default-budget", &default_budget_guid,
-		      NULL);
+                      "default-budget", &default_budget_guid,
+                      NULL);
     if (default_budget_guid != NULL)
     {
-	col = qof_book_get_collection(book, GNC_ID_BUDGET);
-	bgt = (GncBudget *) qof_collection_lookup_entity(col,
-							 default_budget_guid);
+        col = qof_book_get_collection(book, GNC_ID_BUDGET);
+        bgt = (GncBudget *) qof_collection_lookup_entity(col,
+                                                         default_budget_guid);
     }
 
     /* Revert to 2.2.x behavior if the book has no default budget. */
diff --git a/src/engine/gnc-lot.c b/src/engine/gnc-lot.c
index 876bd00..7e7145c 100644
--- a/src/engine/gnc-lot.c
+++ b/src/engine/gnc-lot.c
@@ -64,15 +64,15 @@ struct gnc_lot_s
 enum
 {
     PROP_0,
-//  PROP_ACCOUNT, 	/* Table */
-    PROP_IS_CLOSED,	/* Table */
+//  PROP_ACCOUNT,       /* Table */
+    PROP_IS_CLOSED,     /* Table */
 
-    PROP_INVOICE,	/* KVP */
-    PROP_OWNER_TYPE,	/* KVP */
-    PROP_OWNER_GUID,	/* KVP */
+    PROP_INVOICE,       /* KVP */
+    PROP_OWNER_TYPE,    /* KVP */
+    PROP_OWNER_GUID,    /* KVP */
 
     PROP_RUNTIME_0,
-    PROP_MARKER,	/* Runtime */
+    PROP_MARKER,        /* Runtime */
 };
 
 typedef struct LotPrivate
@@ -138,7 +138,6 @@ gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec*
 {
     GNCLot* lot;
     LotPrivate* priv;
-    KvpFrame *frame;
     gchar *key;
     GValue *temp;
 
@@ -155,17 +154,17 @@ gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec*
         g_value_set_int(value, priv->marker);
         break;
     case PROP_INVOICE:
-	key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
-	qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
-	break;
+        key = GNC_INVOICE_ID "/" GNC_INVOICE_GUID;
+        qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
+        break;
     case PROP_OWNER_TYPE:
-	key = GNC_OWNER_ID"/" GNC_OWNER_TYPE;
-	qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
-	break;
+        key = GNC_OWNER_ID"/" GNC_OWNER_TYPE;
+        qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
+        break;
     case PROP_OWNER_GUID:
-	key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
-	qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
-	break;
+        key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
+        qof_instance_get_kvp (QOF_INSTANCE (lot), key, value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -174,20 +173,19 @@ gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec*
 
 static void
 gnc_lot_set_property (GObject* object,
-		      guint prop_id,
-		      const GValue* value,
-		      GParamSpec* pspec)
+                      guint prop_id,
+                      const GValue* value,
+                      GParamSpec* pspec)
 {
     GNCLot* lot;
     LotPrivate* priv;
-    KvpFrame *frame;
     gchar *key = NULL;
 
     g_return_if_fail(GNC_IS_LOT(object));
 
     lot = GNC_LOT(object);
     if (prop_id < PROP_RUNTIME_0)
-	g_assert (qof_instance_get_editlevel(lot));
+        g_assert (qof_instance_get_editlevel(lot));
 
     priv = GET_PRIVATE(lot);
     switch (prop_id)
@@ -199,17 +197,17 @@ gnc_lot_set_property (GObject* object,
         priv->marker = g_value_get_int(value);
         break;
     case PROP_INVOICE:
-	key = GNC_INVOICE_ID"/" GNC_INVOICE_GUID;
-	qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
-	break;
+        key = GNC_INVOICE_ID"/" GNC_INVOICE_GUID;
+        qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
+        break;
     case PROP_OWNER_TYPE:
-	key = GNC_OWNER_ID "/" GNC_OWNER_TYPE;
-	qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
-	break;
+        key = GNC_OWNER_ID "/" GNC_OWNER_TYPE;
+        qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
+        break;
     case PROP_OWNER_GUID:
-	key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
-	qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
-	break;
+        key = GNC_OWNER_ID "/" GNC_OWNER_GUID;
+        qof_instance_set_kvp (QOF_INSTANCE (lot), key, value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -251,28 +249,28 @@ gnc_lot_class_init(GNCLotClass* klass)
        gobject_class,
         PROP_INVOICE,
         g_param_spec_boxed("invoice",
-			   "Invoice attached to lot",
-			   "Used by GncInvoice",
-			   GNC_TYPE_GUID,
-			   G_PARAM_READWRITE));
+                           "Invoice attached to lot",
+                           "Used by GncInvoice",
+                           GNC_TYPE_GUID,
+                           G_PARAM_READWRITE));
 
      g_object_class_install_property(
        gobject_class,
         PROP_OWNER_TYPE,
         g_param_spec_int64("owner-type",
-			   "Owning Entity Type of  lot",
-			   "Used by GncOwner",
-			   0, G_MAXINT64, 0,
-			   G_PARAM_READWRITE));
+                           "Owning Entity Type of  lot",
+                           "Used by GncOwner",
+                           0, G_MAXINT64, 0,
+                           G_PARAM_READWRITE));
 
      g_object_class_install_property(
        gobject_class,
         PROP_OWNER_GUID,
         g_param_spec_boxed("owner-guid",
-			   "Owner attached to lot",
-			   "Used by GncOwner",
-			   GNC_TYPE_GUID,
-			   G_PARAM_READWRITE));
+                           "Owner attached to lot",
+                           "Used by GncOwner",
+                           GNC_TYPE_GUID,
+                           G_PARAM_READWRITE));
 }
 
 GNCLot *
@@ -436,38 +434,46 @@ gint gnc_lot_count_splits (const GNCLot *lot)
 const char *
 gnc_lot_get_title (const GNCLot *lot)
 {
+    GValue v = G_VALUE_INIT;
     if (!lot) return NULL;
-    return kvp_frame_get_string (qof_instance_get_slots(QOF_INSTANCE (lot)),
-				 "/title");
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (lot), "/title", &v);
+    return g_value_get_string (&v);
 }
 
 const char *
 gnc_lot_get_notes (const GNCLot *lot)
 {
+    GValue v = G_VALUE_INIT;
     if (!lot) return NULL;
-    return kvp_frame_get_string (qof_instance_get_slots(QOF_INSTANCE (lot)),
-				 "/notes");
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (lot), "/notes", &v);
+    return g_value_get_string (&v);
 }
 
 void
 gnc_lot_set_title (GNCLot *lot, const char *str)
 {
+    GValue v = G_VALUE_INIT;
     if (!lot) return;
     qof_begin_edit(QOF_INSTANCE(lot));
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, str);
+    qof_instance_set_kvp (QOF_INSTANCE (lot), "/title", &v);
     qof_instance_set_dirty(QOF_INSTANCE(lot));
-    kvp_frame_set_string (qof_instance_get_slots(QOF_INSTANCE (lot)),
-		       "/title", str);
     gnc_lot_commit_edit(lot);
 }
 
 void
 gnc_lot_set_notes (GNCLot *lot, const char *str)
 {
+    GValue v = G_VALUE_INIT;
     if (!lot) return;
-    gnc_lot_begin_edit(lot);
+    qof_begin_edit(QOF_INSTANCE(lot));
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, str);
+    qof_instance_set_kvp (QOF_INSTANCE (lot), "/notes", &v);
     qof_instance_set_dirty(QOF_INSTANCE(lot));
-    kvp_frame_set_string (qof_instance_get_slots (QOF_INSTANCE (lot)),
-		       "/notes", str);
     gnc_lot_commit_edit(lot);
 }
 
diff --git a/src/engine/gncJob.c b/src/engine/gncJob.c
index 7388b51..284f1b5 100644
--- a/src/engine/gncJob.c
+++ b/src/engine/gncJob.c
@@ -73,13 +73,13 @@ void mark_job (GncJob *job)
 enum
 {
     PROP_0,
-//  PROP_ID,		/* Table */
-    PROP_NAME,		/* Table */
-//  PROP_REFERENCE,	/* Table */
-//  PROP_ACTIVE,	/* Table */
-//  PROP_OWNER_TYPE,	/* Table */
-//  PROP_OWNER,		/* Table */
-    PROP_PDF_DIRNAME,	/* KVP */
+//  PROP_ID,            /* Table */
+    PROP_NAME,          /* Table */
+//  PROP_REFERENCE,     /* Table */
+//  PROP_ACTIVE,        /* Table */
+//  PROP_OWNER_TYPE,    /* Table */
+//  PROP_OWNER,         /* Table */
+    PROP_PDF_DIRNAME,   /* KVP */
 };
 
 /* GObject Initialization */
@@ -120,9 +120,9 @@ gnc_job_get_property (GObject         *object,
         g_value_set_string(value, job->name);
         break;
     case PROP_PDF_DIRNAME:
-	key = OWNER_EXPORT_PDF_DIRNAME;
-	qof_instance_get_kvp (QOF_INSTANCE (job), key, value);
-	break;
+        key = OWNER_EXPORT_PDF_DIRNAME;
+        qof_instance_get_kvp (QOF_INSTANCE (job), key, value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -149,9 +149,9 @@ gnc_job_set_property (GObject         *object,
         gncJobSetName(job, g_value_get_string(value));
         break;
     case PROP_PDF_DIRNAME:
-	key = OWNER_EXPORT_PDF_DIRNAME;
-	qof_instance_set_kvp (QOF_INSTANCE (job), key, value);
-	break;
+        key = OWNER_EXPORT_PDF_DIRNAME;
+        qof_instance_set_kvp (QOF_INSTANCE (job), key, value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -204,10 +204,10 @@ gnc_job_class_init (GncJobClass *klass)
      g_param_spec_string ("export-pdf-dir",
                           "Export PDF Directory Name",
                           "A subdirectory for exporting PDF reports which is "
-			  "appended to the target directory when writing them "
-			  "out. It is retrieved from preferences and stored on "
-			  "each 'Owner' object which prints items after "
-			  "printing.",
+                          "appended to the target directory when writing them "
+                          "out. It is retrieved from preferences and stored on "
+                          "each 'Owner' object which prints items after "
+                          "printing.",
                           NULL,
                           G_PARAM_READWRITE));
 }
@@ -314,16 +314,15 @@ void gncJobSetRate (GncJob *job, gnc_numeric rate)
 
     gncJobBeginEdit (job);
     if (!gnc_numeric_zero_p(rate))
-        kvp_frame_set_numeric(job->inst.kvp_data, GNC_JOB_RATE, rate);
+    {
+        GValue v = G_VALUE_INIT;
+        g_value_init (&v, GNC_TYPE_NUMERIC);
+        g_value_set_boxed (&v, &rate);
+        qof_instance_set_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, &v);
+    }
     else
     {
-        KvpFrame *frame;
-        KvpValue *value;
-
-        value = NULL;
-        frame = kvp_frame_set_value_nc (job->inst.kvp_data,
-                                        GNC_JOB_RATE, value);
-        if (!frame) kvp_value_delete (value);
+        qof_instance_set_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, NULL);
     }
     mark_job (job);
     gncJobCommitEdit (job);
@@ -423,7 +422,7 @@ static void gncJobOnDone (QofInstance *qof) { }
 void gncJobCommitEdit (GncJob *job)
 {
     /* GnuCash 2.6.3 and earlier didn't handle job kvp's... */
-    if (!kvp_frame_is_empty (job->inst.kvp_data))
+    if (qof_instance_has_kvp (QOF_INSTANCE (job)))
         gnc_features_set_used (qof_instance_get_book (QOF_INSTANCE (job)), GNC_FEATURE_KVP_EXTRA_DATA);
 
     if (!qof_commit_edit (QOF_INSTANCE(job))) return;
@@ -454,8 +453,15 @@ const char * gncJobGetReference (const GncJob *job)
 
 gnc_numeric gncJobGetRate (const GncJob *job)
 {
+    GValue v = G_VALUE_INIT;
+    gnc_numeric *rate;
     if (!job) return gnc_numeric_zero ();
-    return kvp_frame_get_numeric(job->inst.kvp_data, GNC_JOB_RATE);
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    qof_instance_get_kvp (QOF_INSTANCE (job), GNC_JOB_RATE, &v);
+    rate = (gnc_numeric*)g_value_get_boxed (&v);
+    if (rate)
+        return *rate;
+    return gnc_numeric_zero();
 }
 
 GncOwner * gncJobGetOwner (GncJob *job)

commit 39c521512b5a18f6eb12770947c1a4e43286b23b
Author: John Ralls <jralls at ceridwen.us>
Date:   Sun May 10 18:15:19 2015 -0700

    Provide qof_instance_has_kvp(); used for feature testing.

diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 2428ad9..e048679 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -106,6 +106,7 @@ void qof_instance_set_version_check (gpointer inst, guint32 value);
 void qof_instance_copy_version_check (gpointer to, gconstpointer from);
 void qof_instance_set_idata(gpointer inst, guint32 idata);
 /* Convenience functions to save some typing in property handlers */
+gboolean qof_instance_has_kvp (QofInstance *inst);
 void qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value);
 void qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value);
 void qof_instance_copy_kvp (QofInstance *to, const QofInstance *from);
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index d545fdf..161fc35 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -1066,6 +1066,13 @@ qof_commit_edit_part2(QofInstance *inst,
     return TRUE;
 }
 
+gboolean
+qof_instance_has_kvp (QofInstance *inst)
+{
+    KvpFrame *frame = qof_instance_get_slots (inst);
+    return (frame != NULL && !kvp_frame_is_empty (frame));
+}
+
 void
 qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value)
 {

commit 97b44a71ec204649500f5c2913a18199882717d0
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 8 15:15:39 2015 -0700

    Convert all Split kV operations to use qof_instance_foo_kvp().
    
    Except for clearing the KVP Frame, which we do by calling qof_instance_dispose().

diff --git a/src/engine/Split.c b/src/engine/Split.c
index 05905bb..88b0f58 100644
--- a/src/engine/Split.c
+++ b/src/engine/Split.c
@@ -571,9 +571,6 @@ xaccSplitReinit(Split * split)
     split->cleared_balance     = gnc_numeric_zero();
     split->reconciled_balance  = gnc_numeric_zero();
 
-    if (split->inst.kvp_data)
-        kvp_frame_delete(split->inst.kvp_data);
-    split->inst.kvp_data = kvp_frame_new();
     qof_instance_set_idata(split, 0);
 
     split->gains = GAINS_STATUS_UNKNOWN;
@@ -625,7 +622,7 @@ xaccDupeSplit (const Split *s)
     split->memo = CACHE_INSERT(s->memo);
     split->action = CACHE_INSERT(s->action);
 
-    split->inst.kvp_data = kvp_frame_copy (s->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE (split), QOF_INSTANCE (s));
 
     split->reconciled = s->reconciled;
     split->date_reconciled = s->date_reconciled;
@@ -675,7 +672,7 @@ xaccSplitCloneNoKvp (const Split *s)
 void
 xaccSplitCopyKvp (const Split *from, Split *to)
 {
-    to->inst.kvp_data = kvp_frame_copy(from->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE (to), QOF_INSTANCE (from));
 }
 
 /*################## Added for Reg2 #################*/
@@ -727,7 +724,7 @@ xaccSplitDump (const Split *split, const char *tag)
     printf("    Gains:    %p\n", split->gains_split);
     printf("    Memo:     %s\n", split->memo ? split->memo : "(null)");
     printf("    Action:   %s\n", split->action ? split->action : "(null)");
-    printf("    KVP Data: %p\n", split->inst.kvp_data);
+    printf("    KVP Data: %s\n", qof_instance_kvp_as_string (QOF_INSTANCE (split));
     printf("    Recncld:  %c (date %s)\n", split->reconciled,
            gnc_print_date(split->date_reconciled));
     printf("    Value:    %s\n", gnc_numeric_to_string(split->value));
@@ -770,10 +767,7 @@ xaccFreeSplit (Split *split)
 
     split->date_reconciled.tv_sec = 0;
     split->date_reconciled.tv_nsec = 0;
-    if (split->inst.kvp_data)
-        kvp_frame_delete(split->inst.kvp_data);
-    split->inst.kvp_data = NULL;
-
+    G_OBJECT_CLASS (QOF_INSTANCE_GET_CLASS (&split->inst))->dispose(G_OBJECT (split));
     // Is this right?
     if (split->gains_split) split->gains_split->gains_split = NULL;
     /* qof_instance_release(&split->inst); */
@@ -859,13 +853,13 @@ xaccSplitEqual(const Split *sa, const Split *sb,
         return FALSE;
     }
 
-    if (kvp_frame_compare(sa->inst.kvp_data, sb->inst.kvp_data) != 0)
+    if (qof_instance_compare_kvp (QOF_INSTANCE (sa), QOF_INSTANCE (sb)) != 0)
     {
         char *frame_a;
         char *frame_b;
 
-        frame_a = kvp_frame_to_string (sa->inst.kvp_data);
-        frame_b = kvp_frame_to_string (sb->inst.kvp_data);
+        frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (sa));
+        frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (sb));
 
         PINFO ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
 
@@ -1128,7 +1122,8 @@ void
 xaccSplitDetermineGainStatus (Split *split)
 {
     Split *other;
-    KvpValue *val;
+    GValue v = G_VALUE_INIT;
+    GncGUID *guid;
 
     if (GAINS_STATUS_UNKNOWN != split->gains) return;
 
@@ -1140,8 +1135,10 @@ xaccSplitDetermineGainStatus (Split *split)
         return;
     }
 
-    val = kvp_frame_get_slot (split->inst.kvp_data, "gains-source");
-    if (!val)
+    g_value_init (&v, GNC_TYPE_GUID);
+    qof_instance_get_kvp (QOF_INSTANCE (split), "gains-source", &v);
+    guid = (GncGUID*)g_value_get_boxed (&v);
+    if (!guid)
     {
         // CHECKME: We leave split->gains_split alone.  Is that correct?
         split->gains = GAINS_STATUS_A_VDIRTY | GAINS_STATUS_DATE_DIRTY;
@@ -1149,10 +1146,10 @@ xaccSplitDetermineGainStatus (Split *split)
     else
     {
         QofCollection *col;
-        col = qof_book_get_collection (qof_instance_get_book(split), GNC_ID_SPLIT);
+        col = qof_book_get_collection (qof_instance_get_book(split),
+				       GNC_ID_SPLIT);
         split->gains = GAINS_STATUS_GAINS;
-        other = (Split *) qof_collection_lookup_entity (col,
-                kvp_value_get_guid (val));
+        other = (Split *) qof_collection_lookup_entity (col, guid);
         split->gains_split = other;
     }
 }
@@ -2052,10 +2049,13 @@ xaccSplitGetBook (const Split *split)
 const char *
 xaccSplitGetType(const Split *s)
 {
+    GValue v = G_VALUE_INIT;
     const char *split_type;
 
     if (!s) return NULL;
-    split_type = kvp_frame_get_string(s->inst.kvp_data, "split-type");
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (s), "split-type", &v);
+    split_type = g_value_get_string (&v);
     return split_type ? split_type : "normal";
 }
 
@@ -2064,10 +2064,13 @@ xaccSplitGetType(const Split *s)
 void
 xaccSplitMakeStockSplit(Split *s)
 {
+    GValue v = G_VALUE_INIT;
     xaccTransBeginEdit (s->parent);
 
     s->value = gnc_numeric_zero();
-    kvp_frame_set_string(s->inst.kvp_data, "split-type", "stock-split");
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, "stock-split");
+    qof_instance_set_kvp (QOF_INSTANCE (s), "split-type", &v);
     SET_GAINS_VDIRTY(s);
     mark_split(s);
     qof_instance_set_dirty(QOF_INSTANCE(s));
@@ -2094,7 +2097,7 @@ xaccSplitGetOtherSplit (const Split *split)
     Transaction *trans;
     int count, num_splits;
     Split *other = NULL;
-    KvpValue *sva;
+    gint64 lot_split;
     gboolean trading_accts;
 
     if (!split) return NULL;
@@ -2115,8 +2118,8 @@ xaccSplitGetOtherSplit (const Split *split)
     trading_accts = xaccTransUseTradingAccounts (trans);
     num_splits = xaccTransCountSplits(trans);
     count = num_splits;
-    sva = kvp_frame_get_slot (split->inst.kvp_data, "lot-split");
-    if (!sva && !trading_accts && (2 != count)) return NULL;
+    g_object_get (G_OBJECT (split), "lot-split", &lot_split, NULL);
+    if (!lot_split && !trading_accts && (2 != count)) return NULL;
 
     for (i = 0; i < num_splits; i++)
     {
@@ -2126,7 +2129,8 @@ xaccSplitGetOtherSplit (const Split *split)
             --count;
             continue;
         }
-        if (kvp_frame_get_slot (s->inst.kvp_data, "lot-split"))
+	g_object_get (G_OBJECT (s), "lot-split", &lot_split, NULL);
+        if (lot_split)
         {
             --count;
             continue;
@@ -2148,27 +2152,40 @@ xaccSplitGetOtherSplit (const Split *split)
 gnc_numeric
 xaccSplitVoidFormerAmount(const Split *split)
 {
+    GValue v = G_VALUE_INIT;
+    gnc_numeric *num;
     g_return_val_if_fail(split, gnc_numeric_zero());
-    return kvp_frame_get_numeric(split->inst.kvp_data, void_former_amt_str);
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    qof_instance_get_kvp (QOF_INSTANCE (split), void_former_amt_str, &v);
+    num = (gnc_numeric*)g_value_get_boxed (&v);
+    return num ? *num : gnc_numeric_zero();
 }
 
 gnc_numeric
 xaccSplitVoidFormerValue(const Split *split)
 {
+    GValue v = G_VALUE_INIT;
+    gnc_numeric *num;
     g_return_val_if_fail(split, gnc_numeric_zero());
-    return kvp_frame_get_numeric(split->inst.kvp_data, void_former_val_str);
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    qof_instance_get_kvp (QOF_INSTANCE (split), void_former_val_str, &v);
+    num = (gnc_numeric*)g_value_get_boxed (&v);
+    return num ? *num : gnc_numeric_zero();
 }
 
 void
 xaccSplitVoid(Split *split)
 {
-    gnc_numeric zero = gnc_numeric_zero();
-    KvpFrame *frame = split->inst.kvp_data;
+    gnc_numeric zero = gnc_numeric_zero(), num;
+    GValue v = G_VALUE_INIT;
 
-    kvp_frame_set_gnc_numeric(frame, void_former_amt_str,
-                              xaccSplitGetAmount(split));
-    kvp_frame_set_gnc_numeric(frame, void_former_val_str,
-                              xaccSplitGetValue(split));
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    num =  xaccSplitGetAmount(split);
+    g_value_set_boxed (&v, &num);
+    qof_instance_set_kvp (QOF_INSTANCE (split), void_former_amt_str, &v);
+    num =  xaccSplitGetValue(split);
+    g_value_set_boxed (&v, &num);
+    qof_instance_set_kvp (QOF_INSTANCE (split), void_former_val_str, &v);
 
     /* Marking dirty handled by SetAmount etc. */
     xaccSplitSetAmount (split, zero);
@@ -2179,13 +2196,11 @@ xaccSplitVoid(Split *split)
 void
 xaccSplitUnvoid(Split *split)
 {
-    KvpFrame *frame = split->inst.kvp_data;
-
     xaccSplitSetAmount (split, xaccSplitVoidFormerAmount(split));
     xaccSplitSetValue (split, xaccSplitVoidFormerValue(split));
     xaccSplitSetReconcile(split, NREC);
-    kvp_frame_set_slot(frame, void_former_amt_str, NULL);
-    kvp_frame_set_slot(frame, void_former_val_str, NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (split), void_former_amt_str, NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (split), void_former_val_str, NULL);
     qof_instance_set_dirty (QOF_INSTANCE (split));
 }
 
@@ -2342,7 +2357,6 @@ gboolean xaccSplitRegister (void)
         { SPLIT_ACCT_FULLNAME, SPLIT_ACCT_FULLNAME, no_op, NULL },
         { SPLIT_CORR_ACCT_NAME, SPLIT_CORR_ACCT_NAME, no_op, NULL },
         { SPLIT_CORR_ACCT_CODE, SPLIT_CORR_ACCT_CODE, no_op, NULL },
-        { SPLIT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
         { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)xaccSplitGetBook, NULL },
         {
             QOF_PARAM_GUID, QOF_TYPE_GUID,

commit 97031fa62a98dda7cced40c0b485450122827726
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 8 15:13:12 2015 -0700

    Correct the kvpvalue type for lot-split in test_xaccSplitOtherSplit.

diff --git a/src/engine/test/utest-Split.cpp b/src/engine/test/utest-Split.cpp
index 4e3425d..6a5000c 100644
--- a/src/engine/test/utest-Split.cpp
+++ b/src/engine/test/utest-Split.cpp
@@ -1777,7 +1777,7 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
     Split *split1 = xaccMallocSplit (book);
     Split *split2 = xaccMallocSplit (book);
     Account *acc2 = xaccMallocAccount (book);
-    KvpValue *kvptrue = kvp_value_new_string ("t");
+    KvpValue *kvpnow = kvp_value_new_gint64 (gnc_time (NULL));
 
     g_assert (xaccSplitGetOtherSplit (NULL) == NULL);
     g_assert (xaccSplitGetOtherSplit (split1) == NULL);
@@ -1794,11 +1794,11 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
     xaccSplitSetParent (split2, txn);
     g_assert (xaccSplitGetOtherSplit (split) == NULL);
 
-    kvp_frame_set_slot (split->inst.kvp_data, "lot-split", kvptrue);
+    kvp_frame_set_slot (split->inst.kvp_data, "lot-split", kvpnow);
     g_assert (kvp_frame_get_slot (split->inst.kvp_data, "lot-split"));
     g_assert (xaccSplitGetOtherSplit (split) == NULL);
 
-    kvp_frame_set_slot (split1->inst.kvp_data, "lot-split", kvptrue);
+    kvp_frame_set_slot (split1->inst.kvp_data, "lot-split", kvpnow);
     g_assert (kvp_frame_get_slot (split1->inst.kvp_data, "lot-split"));
     g_assert (xaccSplitGetOtherSplit (split) == split2);
 

commit eccdfd0aa38585270dff742aa456ffd22b677280
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 8 13:33:40 2015 -0700

    Convert all Transaction KVP operations to use qof_instance_foo_kvp.

diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c
index f695ce8..df03fb9 100644
--- a/src/engine/Transaction.c
+++ b/src/engine/Transaction.c
@@ -312,7 +312,6 @@ gnc_transaction_get_property(GObject* object,
                              GParamSpec* pspec)
 {
     Transaction* tx;
-    KvpFrame *frame;
     gchar *key;
     GValue *temp;
 
@@ -361,7 +360,6 @@ gnc_transaction_set_property(GObject* object,
                              GParamSpec* pspec)
 {
     Transaction* tx;
-    KvpFrame *frame;
     gchar *key;
 
     g_return_if_fail(GNC_IS_TRANSACTION(object));
@@ -633,7 +631,7 @@ dupe_trans (const Transaction *from)
     to->inst.e_type = NULL;
     qof_instance_set_guid(to, guid_null());
     qof_instance_copy_book(to, from);
-    to->inst.kvp_data = kvp_frame_copy (from->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE(to), QOF_INSTANCE(from));
 
     return to;
 }
@@ -688,7 +686,7 @@ xaccTransClone (const Transaction *from)
     int length = g_list_length (from->splits);
 
     xaccTransBeginEdit (to);
-    to->inst.kvp_data = kvp_frame_copy (from->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE (to), QOF_INSTANCE (from));
     g_assert (g_list_length (to->splits) == length);
     for (i = 0; i < length; ++i)
 	xaccSplitCopyKvp (g_list_nth_data (from->splits, i),
@@ -934,13 +932,14 @@ xaccTransEqual(const Transaction *ta, const Transaction *tb,
         return FALSE;
     }
 
-    if (kvp_frame_compare(ta->inst.kvp_data, tb->inst.kvp_data) != 0)
+    if (qof_instance_compare_kvp (QOF_INSTANCE (ta), QOF_INSTANCE (tb)) != 0)
     {
         char *frame_a;
         char *frame_b;
 
-        frame_a = kvp_frame_to_string (ta->inst.kvp_data);
-        frame_b = kvp_frame_to_string (tb->inst.kvp_data);
+        frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (ta));
+        frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (tb));
+
 
         PINFO ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
 
@@ -1688,7 +1687,7 @@ xaccTransRollbackEdit (Transaction *trans)
     trans->date_entered = orig->date_entered;
     trans->date_posted = orig->date_posted;
     SWAP(trans->common_currency, orig->common_currency);
-    SWAP(trans->inst.kvp_data, orig->inst.kvp_data);
+    qof_instance_swap_kvp (QOF_INSTANCE (trans), QOF_INSTANCE (orig));
 
     /* The splits at the front of trans->splits are exactly the same
        splits as in the original, but some of them may have changed, so
@@ -1713,7 +1712,7 @@ xaccTransRollbackEdit (Transaction *trans)
             xaccSplitRollbackEdit(s);
             SWAP(s->action, so->action);
             SWAP(s->memo, so->memo);
-            SWAP(s->inst.kvp_data, so->inst.kvp_data);
+	    qof_instance_copy_kvp (QOF_INSTANCE (s), QOF_INSTANCE (so));
             s->reconciled = so->reconciled;
             s->amount = so->amount;
             s->value = so->value;
@@ -1924,20 +1923,15 @@ xaccTransSetDatePostedSecsNormalized (Transaction *trans, time64 time)
 void
 xaccTransSetDatePostedGDate (Transaction *trans, GDate date)
 {
-    KvpValue* kvp_value;
-    KvpFrame* frame;
+    GValue v = G_VALUE_INIT;
     if (!trans) return;
 
     /* We additionally save this date into a kvp frame to ensure in
      * the future a date which was set as *date* (without time) can
      * clearly be distinguished from the Timespec. */
-    kvp_value = kvp_value_new_gdate(date);
-    frame = kvp_frame_set_value_nc(trans->inst.kvp_data, TRANS_DATE_POSTED, kvp_value);
-    if (!frame)
-    {
-        kvp_value_delete(kvp_value);
-    }
-
+    g_value_init (&v, G_TYPE_DATE);
+    g_value_set_boxed (&v, &date);
+    qof_instance_set_kvp (QOF_INSTANCE(trans), TRANS_DATE_POSTED, &v);
     /* mark dirty and commit handled by SetDateInternal */
     xaccTransSetDateInternal(trans, &trans->date_posted,
                              gdate_to_timespec(date));
@@ -2002,9 +1996,12 @@ xaccTransSetDate (Transaction *trans, int day, int mon, int year)
 void
 xaccTransSetDateDueTS (Transaction *trans, const Timespec *ts)
 {
+    GValue v = G_VALUE_INIT;
     if (!trans || !ts) return;
+    g_value_init (&v, GNC_TYPE_TIMESPEC);
+    g_value_set_boxed (&v, ts);
     xaccTransBeginEdit(trans);
-    kvp_frame_set_timespec (trans->inst.kvp_data, TRANS_DATE_DUE_KVP, *ts);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), TRANS_DATE_DUE_KVP, &v);
     qof_instance_set_dirty(QOF_INSTANCE(trans));
     xaccTransCommitEdit(trans);
 }
@@ -2013,9 +2010,12 @@ void
 xaccTransSetTxnType (Transaction *trans, char type)
 {
     char s[2] = {type, '\0'};
+    GValue v = G_VALUE_INIT;
     g_return_if_fail(trans);
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, s);
     xaccTransBeginEdit(trans);
-    kvp_frame_set_string (trans->inst.kvp_data, TRANS_TXN_TYPE_KVP, s);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), TRANS_TXN_TYPE_KVP, &v);
     qof_instance_set_dirty(QOF_INSTANCE(trans));
     xaccTransCommitEdit(trans);
 }
@@ -2025,8 +2025,8 @@ void xaccTransClearReadOnly (Transaction *trans)
     if (trans)
     {
         xaccTransBeginEdit(trans);
-        kvp_frame_set_slot_path (trans->inst.kvp_data, NULL,
-                                 TRANS_READ_ONLY_REASON, NULL);
+	qof_instance_set_kvp (QOF_INSTANCE (trans),
+			      TRANS_READ_ONLY_REASON, NULL);
         qof_instance_set_dirty(QOF_INSTANCE(trans));
         xaccTransCommitEdit(trans);
     }
@@ -2037,9 +2037,11 @@ xaccTransSetReadOnly (Transaction *trans, const char *reason)
 {
     if (trans && reason)
     {
+	GValue v = G_VALUE_INIT;
+	g_value_init (&v, G_TYPE_STRING);
+	g_value_set_string (&v, reason);
         xaccTransBeginEdit(trans);
-        kvp_frame_set_string (trans->inst.kvp_data,
-                           TRANS_READ_ONLY_REASON, reason);
+	qof_instance_set_kvp (QOF_INSTANCE (trans), TRANS_READ_ONLY_REASON, &v);
         qof_instance_set_dirty(QOF_INSTANCE(trans));
         xaccTransCommitEdit(trans);
     }
@@ -2092,10 +2094,12 @@ xaccTransSetDescription (Transaction *trans, const char *desc)
 void
 xaccTransSetAssociation (Transaction *trans, const char *assoc)
 {
+    GValue v = G_VALUE_INIT;
     if (!trans || !assoc) return;
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, assoc);
     xaccTransBeginEdit(trans);
-
-    kvp_frame_set_string (trans->inst.kvp_data, assoc_uri_str, assoc);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), assoc_uri_str, &v);
     qof_instance_set_dirty(QOF_INSTANCE(trans));
     xaccTransCommitEdit(trans);
 }
@@ -2111,10 +2115,13 @@ qofTransSetNotes (Transaction *trans, const char *notes)
 void
 xaccTransSetNotes (Transaction *trans, const char *notes)
 {
+    GValue v = G_VALUE_INIT;
     if (!trans || !notes) return;
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, notes);
     xaccTransBeginEdit(trans);
 
-    kvp_frame_set_string (trans->inst.kvp_data, trans_notes_str, notes);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
     qof_instance_set_dirty(QOF_INSTANCE(trans));
     xaccTransCommitEdit(trans);
 }
@@ -2126,9 +2133,14 @@ xaccTransSetIsClosingTxn (Transaction *trans, gboolean is_closing)
     xaccTransBeginEdit(trans);
 
     if (is_closing)
-        kvp_frame_set_gint64 (trans->inst.kvp_data, trans_is_closing_str, 1);
+    {
+	GValue v = G_VALUE_INIT;
+	g_value_init (&v, G_TYPE_INT64);
+	g_value_set_int64 (&v, 1);
+        qof_instance_set_kvp (QOF_INSTANCE (trans), trans_is_closing_str, &v);
+    }
     else
-        kvp_frame_replace_value_nc (trans->inst.kvp_data, trans_is_closing_str, NULL);
+	qof_instance_set_kvp (QOF_INSTANCE (trans), trans_is_closing_str, NULL);
     qof_instance_set_dirty(QOF_INSTANCE(trans));
     xaccTransCommitEdit(trans);
 }
@@ -2186,23 +2198,31 @@ xaccTransGetDescription (const Transaction *trans)
 const char *
 xaccTransGetAssociation (const Transaction *trans)
 {
-    return trans ?
-           kvp_frame_get_string (trans->inst.kvp_data, assoc_uri_str) : NULL;
+    GValue v = G_VALUE_INIT;
+    if (!trans) return NULL;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), assoc_uri_str, &v);
+    return g_value_get_string (&v);
 }
 
 const char *
 xaccTransGetNotes (const Transaction *trans)
 {
-    return trans ?
-           kvp_frame_get_string (trans->inst.kvp_data, trans_notes_str) : NULL;
+    GValue v = G_VALUE_INIT;
+    if (!trans) return NULL;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
+    return g_value_get_string (&v);
 }
 
 gboolean
 xaccTransGetIsClosingTxn (const Transaction *trans)
 {
-    return trans ?
-           kvp_frame_get_gint64 (trans->inst.kvp_data, trans_is_closing_str)
-           : FALSE;
+    GValue v = G_VALUE_INIT;
+    if (!trans) return FALSE;
+    g_value_init (&v, G_TYPE_INT64);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), trans_is_closing_str, &v);
+    return g_value_get_int64 (&v);
 }
 
 /********************************************************************\
@@ -2252,11 +2272,11 @@ xaccTransGetDatePostedGDate (const Transaction *trans)
         /* Can we look up this value in the kvp slot? If yes, use it
          * from there because it doesn't suffer from time zone
          * shifts. */
-        const KvpValue* kvp_value =
-            kvp_frame_get_slot(trans->inst.kvp_data, TRANS_DATE_POSTED);
-        if (kvp_value)
-            result = kvp_value_get_gdate(kvp_value);
-        else
+	GValue v = G_VALUE_INIT;
+	g_value_init (&v, G_TYPE_DATE);
+	qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_DATE_POSTED, &v);
+	result = *(GDate*)g_value_get_boxed (&v);
+	if (! g_date_valid (&result))
             result = timespec_to_gdate(xaccTransRetDatePostedTS(trans));
     }
     else
@@ -2276,14 +2296,13 @@ xaccTransRetDateEnteredTS (const Transaction *trans)
 void
 xaccTransGetDateDueTS (const Transaction *trans, Timespec *ts)
 {
-    KvpValue *value;
-
+    GValue v = G_VALUE_INIT;
     if (!trans || !ts) return;
 
-    value = kvp_frame_get_slot (trans->inst.kvp_data, TRANS_DATE_DUE_KVP);
-    if (value)
-        *ts = kvp_value_get_timespec (value);
-    else
+    g_value_init (&v, GNC_TYPE_TIMESPEC);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_DATE_DUE_KVP, &v);
+    *ts = *(Timespec*)g_value_get_boxed (&v);
+    if (ts->tv_sec == 0)
         xaccTransGetDatePostedTS (trans, ts);
 }
 
@@ -2299,9 +2318,14 @@ char
 xaccTransGetTxnType (const Transaction *trans)
 {
     const char *s;
+    GValue v = G_VALUE_INIT;
+
     if (!trans) return TXN_TYPE_NONE;
-    s = kvp_frame_get_string (trans->inst.kvp_data, TRANS_TXN_TYPE_KVP);
-    if (s) return *s;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), TRANS_TXN_TYPE_KVP, &v);
+    s = g_value_get_string (&v);
+    if (s && strlen (s) == 0)
+	return *s;
 
     return TXN_TYPE_NONE;
 }
@@ -2312,8 +2336,16 @@ xaccTransGetReadOnly (const Transaction *trans)
     /* XXX This flag should be cached in the transaction structure
      * for performance reasons, since its checked every trans commit.
      */
-    return trans ? kvp_frame_get_string (
-               trans->inst.kvp_data, TRANS_READ_ONLY_REASON) : NULL;
+    GValue v = G_VALUE_INIT;
+    const char *s;
+    if (trans == NULL) return NULL;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE(trans), TRANS_READ_ONLY_REASON, &v);
+    s = g_value_get_string (&v);
+    if (s && strlen (s))
+	return s;
+
+    return NULL;
 }
 
 static gboolean
@@ -2491,26 +2523,24 @@ gnc_book_count_transactions(QofBook *book)
 void
 xaccTransVoid(Transaction *trans, const char *reason)
 {
-    KvpFrame *frame;
-    KvpValue *val;
-    Timespec now;
+    GValue v = G_VALUE_INIT;
     char iso8601_str[ISO_DATELENGTH + 1] = "";
 
     g_return_if_fail(trans && reason);
 
     xaccTransBeginEdit(trans);
-    frame = trans->inst.kvp_data;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
 
-    val = kvp_frame_get_slot(frame, trans_notes_str);
-    kvp_frame_set_slot(frame, void_former_notes_str, val);
+    g_value_set_string (&v, _("Voided transaction"));
+    qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
+    g_value_set_string (&v, reason);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
 
-    kvp_frame_set_string(frame, trans_notes_str, _("Voided transaction"));
-    kvp_frame_set_string(frame, void_reason_str, reason);
-
-    now.tv_sec = gnc_time (NULL);
-    now.tv_nsec = 0;
-    gnc_timespec_to_iso8601_buff(now, iso8601_str);
-    kvp_frame_set_string(frame, void_time_str, iso8601_str);
+    gnc_timespec_to_iso8601_buff (timespec_now (), iso8601_str);
+    g_value_set_string (&v, iso8601_str);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), void_time_str, &v);
 
     FOR_EACH_SPLIT(trans, xaccSplitVoid(s));
 
@@ -2522,48 +2552,61 @@ xaccTransVoid(Transaction *trans, const char *reason)
 gboolean
 xaccTransGetVoidStatus(const Transaction *trans)
 {
+    const char *s;
+    GValue v = G_VALUE_INIT;
     g_return_val_if_fail(trans, FALSE);
-    return (kvp_frame_get_slot(trans->inst.kvp_data, void_reason_str) != NULL);
+
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
+    s = g_value_get_string (&v);
+    return s && strlen(s);
 }
 
 const char *
 xaccTransGetVoidReason(const Transaction *trans)
 {
-    g_return_val_if_fail(trans, NULL);
-    return kvp_frame_get_string(trans->inst.kvp_data, void_reason_str);
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(trans, FALSE);
+
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
+    return g_value_get_string (&v);
 }
 
 Timespec
 xaccTransGetVoidTime(const Transaction *tr)
 {
-    const char *val;
-    Timespec void_time = {0, 0};
+    GValue v = G_VALUE_INIT;
+    const char *s;
+    Timespec void_time = {0, 0}, *ts;
 
     g_return_val_if_fail(tr, void_time);
-
-    val = kvp_frame_get_string(tr->inst.kvp_data, void_time_str);
-    return val ? gnc_iso8601_to_timespec_gmt(val) : void_time;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (tr), void_time_str, &v);
+    s = g_value_get_string (&v);
+    if (s)
+	return gnc_iso8601_to_timespec_gmt (s);
+    return void_time;
 }
 
 void
 xaccTransUnvoid (Transaction *trans)
 {
-    KvpFrame *frame;
-    KvpValue *val;
-
+    GValue v = G_VALUE_INIT;
+    const char *s;
     g_return_if_fail(trans);
 
-    frame = trans->inst.kvp_data;
-    val = kvp_frame_get_slot(frame, void_reason_str);
-    if (!val) return; /* Transaction isn't voided. Bail. */
-
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), void_reason_str, &v);
+    s = g_value_get_string (&v);
+    if (s == NULL) return; /* Transaction isn't voided. Bail. */
     xaccTransBeginEdit(trans);
 
-    val = kvp_frame_get_slot(frame, void_former_notes_str);
-    kvp_frame_set_slot(frame, trans_notes_str, val);
-    kvp_frame_set_slot_nc(frame, void_former_notes_str, NULL);
-    kvp_frame_set_slot_nc(frame, void_reason_str, NULL);
-    kvp_frame_set_slot_nc(frame, void_time_str, NULL);
+    qof_instance_get_kvp (QOF_INSTANCE (trans), void_former_notes_str, &v);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), trans_notes_str, &v);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), void_former_notes_str, NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), void_reason_str, NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (trans), void_time_str, NULL);
 
     FOR_EACH_SPLIT(trans, xaccSplitUnvoid(s));
 
@@ -2576,7 +2619,7 @@ Transaction *
 xaccTransReverse (Transaction *orig)
 {
     Transaction *trans;
-    KvpValue *kvp_val;
+    GValue v = G_VALUE_INIT;
     g_return_val_if_fail(orig, NULL);
 
     trans = xaccTransClone(orig);
@@ -2591,8 +2634,9 @@ xaccTransReverse (Transaction *orig)
     });
 
     /* Now update the original with a pointer to the new one */
-    kvp_val = kvp_value_new_guid(xaccTransGetGUID(trans));
-    kvp_frame_set_slot_nc(orig->inst.kvp_data, TRANS_REVERSED_BY, kvp_val);
+    g_value_init (&v, GNC_TYPE_GUID);
+    g_value_set_boxed (&v, xaccTransGetGUID(trans));
+    qof_instance_set_kvp (QOF_INSTANCE (orig), TRANS_REVERSED_BY, &v);
 
     qof_instance_set_dirty(QOF_INSTANCE(trans));
     xaccTransCommitEdit(trans);
@@ -2602,11 +2646,12 @@ xaccTransReverse (Transaction *orig)
 Transaction *
 xaccTransGetReversedBy(const Transaction *trans)
 {
-    GncGUID *guid;
-
+    GValue v = G_VALUE_INIT;
     g_return_val_if_fail(trans, NULL);
-    guid = kvp_frame_get_guid(trans->inst.kvp_data, TRANS_REVERSED_BY);
-    return xaccTransLookup(guid, qof_instance_get_book(trans));
+    g_value_init (&v, GNC_TYPE_GUID);
+    qof_instance_get_kvp (QOF_INSTANCE(trans), TRANS_REVERSED_BY, &v);
+    return xaccTransLookup((GncGUID*)g_value_get_boxed (&v),
+			   qof_instance_get_book(trans));
 }
 
 void
@@ -2850,10 +2895,6 @@ gboolean xaccTransRegister (void)
             (QofAccessFunc)xaccTransGetSplitList, NULL
         },
         {
-            TRANS_KVP, QOF_TYPE_KVP,
-            (QofAccessFunc)qof_instance_get_slots, NULL
-        },
-        {
             QOF_PARAM_BOOK, QOF_ID_BOOK,
             (QofAccessFunc)qof_instance_get_book, NULL
         },

commit 542557724cbfbccc9ee5ef59635d668944582842
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 8 13:33:15 2015 -0700

    Convert almost all Account KVP operations to use qof_instance_foo_kvp.
    
    Can't do the import-matcher stuff, it's a bit too hard-wired to KVP.

diff --git a/src/engine/Account.c b/src/engine/Account.c
index 88e00f2..02b0916 100644
--- a/src/engine/Account.c
+++ b/src/engine/Account.c
@@ -61,48 +61,48 @@ enum
 enum
 {
     PROP_0,
-    PROP_NAME,				/* Table */
-    PROP_FULL_NAME,			/* Constructed */
-    PROP_CODE,				/* Table */
-    PROP_DESCRIPTION,			/* Table */
-    PROP_COLOR,				/* KVP */
-    PROP_NOTES,				/* KVP */
-    PROP_TYPE,				/* Table */
-
-//    PROP_PARENT,			/* Table, Not a property */
-    PROP_COMMODITY,			/* Table */
-    PROP_COMMODITY_SCU,			/* Table */
-    PROP_NON_STD_SCU,			/* Table */
-    PROP_END_BALANCE,			/* Constructed */
-    PROP_END_CLEARED_BALANCE,		/* Constructed */
-    PROP_END_RECONCILED_BALANCE,	/* Constructed */
-
-    PROP_TAX_RELATED,			/* KVP */
-    PROP_TAX_CODE,			/* KVP */
-    PROP_TAX_SOURCE,			/* KVP */
-    PROP_TAX_COPY_NUMBER,		/* KVP */
-
-    PROP_HIDDEN,			/* Table slot exists, but in KVP in memory & xml */
-    PROP_PLACEHOLDER,			/* Table slot exists, but in KVP in memory & xml */
-    PROP_FILTER,			/* KVP */
-    PROP_SORT_ORDER,			/* KVP */
-
-    PROP_LOT_NEXT_ID,			/* KVP */
-    PROP_ONLINE_ACCOUNT,		/* KVP */
-    PROP_OFX_INCOME_ACCOUNT,		/* KVP */
-    PROP_AB_ACCOUNT_ID,			/* KVP */
-    PROP_AB_ACCOUNT_UID,		/* KVP */
-    PROP_AB_BANK_CODE,			/* KVP */
-    PROP_AB_TRANS_RETRIEVAL,		/* KVP */
+    PROP_NAME,                          /* Table */
+    PROP_FULL_NAME,                     /* Constructed */
+    PROP_CODE,                          /* Table */
+    PROP_DESCRIPTION,                   /* Table */
+    PROP_COLOR,                         /* KVP */
+    PROP_NOTES,                         /* KVP */
+    PROP_TYPE,                          /* Table */
+
+//    PROP_PARENT,                      /* Table, Not a property */
+    PROP_COMMODITY,                     /* Table */
+    PROP_COMMODITY_SCU,                 /* Table */
+    PROP_NON_STD_SCU,                   /* Table */
+    PROP_END_BALANCE,                   /* Constructed */
+    PROP_END_CLEARED_BALANCE,           /* Constructed */
+    PROP_END_RECONCILED_BALANCE,        /* Constructed */
+
+    PROP_TAX_RELATED,                   /* KVP */
+    PROP_TAX_CODE,                      /* KVP */
+    PROP_TAX_SOURCE,                    /* KVP */
+    PROP_TAX_COPY_NUMBER,               /* KVP */
+
+    PROP_HIDDEN,                        /* Table slot exists, but in KVP in memory & xml */
+    PROP_PLACEHOLDER,                   /* Table slot exists, but in KVP in memory & xml */
+    PROP_FILTER,                        /* KVP */
+    PROP_SORT_ORDER,                    /* KVP */
+
+    PROP_LOT_NEXT_ID,                   /* KVP */
+    PROP_ONLINE_ACCOUNT,                /* KVP */
+    PROP_OFX_INCOME_ACCOUNT,            /* KVP */
+    PROP_AB_ACCOUNT_ID,                 /* KVP */
+    PROP_AB_ACCOUNT_UID,                /* KVP */
+    PROP_AB_BANK_CODE,                  /* KVP */
+    PROP_AB_TRANS_RETRIEVAL,            /* KVP */
 
     PROP_RUNTIME_0,
-    PROP_POLICY,			/* Cached Value */
-    PROP_MARK,				/* Runtime Value */
-    PROP_SORT_DIRTY,			/* Runtime Value */
-    PROP_BALANCE_DIRTY,			/* Runtime Value */
-    PROP_START_BALANCE,			/* Runtime Value */
-    PROP_START_CLEARED_BALANCE,		/* Runtime Value */
-    PROP_START_RECONCILED_BALANCE,	/* Runtime Value */
+    PROP_POLICY,                        /* Cached Value */
+    PROP_MARK,                          /* Runtime Value */
+    PROP_SORT_DIRTY,                    /* Runtime Value */
+    PROP_BALANCE_DIRTY,                 /* Runtime Value */
+    PROP_START_BALANCE,                 /* Runtime Value */
+    PROP_START_CLEARED_BALANCE,         /* Runtime Value */
+    PROP_START_RECONCILED_BALANCE,      /* Runtime Value */
 };
 
 #define GET_PRIVATE(o)  \
@@ -399,35 +399,35 @@ gnc_account_get_property (GObject         *object,
         g_value_set_string(value, xaccAccountGetSortOrder(account));
         break;
     case PROP_LOT_NEXT_ID:
-	key = "lot-mgmt/next-id";
+        key = "lot-mgmt/next-id";
         /* Pre-set the value in case the frame is empty */
-	g_value_set_int64 (value, 0);
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        g_value_set_int64 (value, 0);
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_ONLINE_ACCOUNT:
-	key = "online_id";
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = "online_id";
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_OFX_INCOME_ACCOUNT:
-	key = KEY_ASSOC_INCOME_ACCOUNT;
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = KEY_ASSOC_INCOME_ACCOUNT;
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_ACCOUNT_ID:
-	key = AB_KEY "/" AB_ACCOUNT_ID;
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_ACCOUNT_ID;
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_ACCOUNT_UID:
-	key = AB_KEY "/" AB_ACCOUNT_UID;
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_ACCOUNT_UID;
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_BANK_CODE:
-	key = AB_KEY "/" AB_BANK_CODE;
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_BANK_CODE;
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_TRANS_RETRIEVAL:
-	key = AB_KEY "/" AB_TRANS_RETRIEVAL;
-	qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_TRANS_RETRIEVAL;
+        qof_instance_get_kvp (QOF_INSTANCE (account), key, value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -448,7 +448,7 @@ gnc_account_set_property (GObject         *object,
 
     account = GNC_ACCOUNT(object);
     if (prop_id < PROP_RUNTIME_0)
-	g_assert (qof_instance_get_editlevel(account));
+        g_assert (qof_instance_get_editlevel(account));
 
     switch (prop_id)
     {
@@ -531,33 +531,33 @@ gnc_account_set_property (GObject         *object,
         xaccAccountSetSortOrder(account, g_value_get_string(value));
         break;
     case PROP_LOT_NEXT_ID:
-	key = "lot-mgmt/next-id";
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = "lot-mgmt/next-id";
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_ONLINE_ACCOUNT:
-	key = "online_id";
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = "online_id";
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_OFX_INCOME_ACCOUNT:
-	key = KEY_ASSOC_INCOME_ACCOUNT;
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = KEY_ASSOC_INCOME_ACCOUNT;
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_ACCOUNT_ID:
-	key = AB_KEY "/" AB_ACCOUNT_ID;
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_ACCOUNT_ID;
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_ACCOUNT_UID:
-	key = AB_KEY "/" AB_ACCOUNT_UID;
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_ACCOUNT_UID;
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_BANK_CODE:
-	key = AB_KEY "/" AB_BANK_CODE;
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_BANK_CODE;
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     case PROP_AB_TRANS_RETRIEVAL:
-	key = AB_KEY "/" AB_TRANS_RETRIEVAL;
-	qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
-	break;
+        key = AB_KEY "/" AB_TRANS_RETRIEVAL;
+        qof_instance_set_kvp (QOF_INSTANCE (account), key, value);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -933,7 +933,7 @@ gnc_account_class_init (AccountClass *klass)
      g_param_spec_string ("online-id",
                           "Online Account ID",
                           "The online account which corresponds to this "
-			  "account for OFX import",
+                          "account for OFX import",
                           NULL,
                           G_PARAM_READWRITE));
 
@@ -941,10 +941,10 @@ gnc_account_class_init (AccountClass *klass)
        gobject_class,
        PROP_OFX_INCOME_ACCOUNT,
         g_param_spec_boxed("ofx-income-account",
-			   "Associated income account",
-			   "Used by the OFX importer.",
-			   GNC_TYPE_GUID,
-			   G_PARAM_READWRITE));
+                           "Associated income account",
+                           "Used by the OFX importer.",
+                           GNC_TYPE_GUID,
+                           G_PARAM_READWRITE));
 
     g_object_class_install_property
     (gobject_class,
@@ -952,7 +952,7 @@ gnc_account_class_init (AccountClass *klass)
      g_param_spec_string ("ab-account-id",
                           "AQBanking Account ID",
                           "The AqBanking account which corresponds to this "
-			  "account for AQBanking import",
+                          "account for AQBanking import",
                           NULL,
                           G_PARAM_READWRITE));
     g_object_class_install_property
@@ -961,7 +961,7 @@ gnc_account_class_init (AccountClass *klass)
      g_param_spec_string ("ab-bank-code",
                           "AQBanking Bank Code",
                           "The online account which corresponds to this "
-			  "account for AQBanking import",
+                          "account for AQBanking import",
                           NULL,
                           G_PARAM_READWRITE));
 
@@ -982,7 +982,7 @@ gnc_account_class_init (AccountClass *klass)
      g_param_spec_boxed("ab-trans-retrieval",
                         "AQBanking Last Transaction Retrieval",
                         "The time of the last transaction retrieval for this "
-			"account.",
+                        "account.",
                         GNC_TYPE_TIMESPEC,
                         G_PARAM_READWRITE));
 
@@ -1136,8 +1136,7 @@ xaccCloneAccount(const Account *from, QofBook *book)
     priv->accountCode = CACHE_INSERT(from_priv->accountCode);
     priv->description = CACHE_INSERT(from_priv->description);
 
-    kvp_frame_delete(ret->inst.kvp_data);
-    ret->inst.kvp_data = kvp_frame_copy(from->inst.kvp_data);
+    qof_instance_copy_kvp (QOF_INSTANCE (ret), QOF_INSTANCE (from));
 
     /* The new book should contain a commodity that matches
      * the one in the old book. Find it, use it. */
@@ -1418,8 +1417,8 @@ compare_account_by_name (gconstpointer a, gconstpointer b)
     priv_a = GET_PRIVATE((Account*)a);
     priv_b = GET_PRIVATE((Account*)b);
     if ((priv_a->accountCode && strlen (priv_a->accountCode)) ||
-	(priv_b->accountCode && strlen (priv_b->accountCode)))
-	return g_strcmp0 (priv_a->accountCode, priv_b->accountCode);
+        (priv_b->accountCode && strlen (priv_b->accountCode)))
+        return g_strcmp0 (priv_a->accountCode, priv_b->accountCode);
     return g_strcmp0 (priv_a->accountName, priv_b->accountName);
 }
 
@@ -1435,23 +1434,23 @@ xaccAcctChildrenEqual(const GList *na,
     }
     if (g_list_length ((GList*)na) != g_list_length ((GList*)nb))
     {
-	PINFO ("Accounts have different numbers of children");
-	return (FALSE);
+        PINFO ("Accounts have different numbers of children");
+        return (FALSE);
     }
 
     while (na)
     {
         Account *aa = na->data;
         Account *ab;
-	GList *node = g_list_find_custom ((GList*)nb, aa,
-					  (GCompareFunc)compare_account_by_name);
+        GList *node = g_list_find_custom ((GList*)nb, aa,
+                                          (GCompareFunc)compare_account_by_name);
 
-	if (!node)
-	{
-	    PINFO ("Unable to find matching child account.");
-	    return FALSE;
-	}
-	ab = node->data;
+        if (!node)
+        {
+            PINFO ("Unable to find matching child account.");
+            return FALSE;
+        }
+        ab = node->data;
         if (!xaccAccountEqual(aa, ab, check_guids))
         {
             char sa[GUID_ENCODING_LENGTH + 1];
@@ -1522,13 +1521,13 @@ xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids)
         }
     }
 
-    if (kvp_frame_compare(aa->inst.kvp_data, ab->inst.kvp_data) != 0)
+    if (qof_instance_compare_kvp (QOF_INSTANCE (aa), QOF_INSTANCE (ab)) != 0)
     {
         char *frame_a;
         char *frame_b;
 
-        frame_a = kvp_frame_to_string (aa->inst.kvp_data);
-        frame_b = kvp_frame_to_string (ab->inst.kvp_data);
+        frame_a = qof_instance_kvp_as_string (QOF_INSTANCE (aa));
+        frame_b = qof_instance_kvp_as_string (QOF_INSTANCE (ab));
 
         PWARN ("kvp frames differ:\n%s\n\nvs\n\n%s", frame_a, frame_b);
 
@@ -2283,67 +2282,62 @@ xaccAccountSetDescription (Account *acc, const char *str)
     xaccAccountCommitEdit(acc);
 }
 
-void
-xaccAccountSetColor (Account *acc, const char *str)
+static void
+set_kvp_string_tag (Account *acc, const char *tag, const char *value)
 {
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
     xaccAccountBeginEdit(acc);
-    if (str)
+    if (value)
     {
-        gchar *tmp = g_strstrip(g_strdup(str));
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "color",
-                              strlen(tmp) ? kvp_value_new_string(tmp) : NULL);
+        gchar *tmp = g_strstrip(g_strdup(value));
+	if (strlen (tmp))
+	{
+	     GValue v = G_VALUE_INIT;
+	     g_value_init (&v, G_TYPE_STRING);
+	     g_value_set_string (&v, tmp);
+	     qof_instance_set_kvp (QOF_INSTANCE (acc), tag , &v);
+	}
+	else
+	     qof_instance_set_kvp (QOF_INSTANCE (acc), tag, NULL);
         g_free(tmp);
     }
     else
     {
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "color", NULL);
+	 qof_instance_set_kvp (QOF_INSTANCE (acc), tag, NULL);
     }
     mark_account (acc);
     xaccAccountCommitEdit(acc);
 }
 
+static const char*
+get_kvp_string_tag (const Account *acc, const char *tag)
+{
+    GValue v = G_VALUE_INIT;
+    const char* s;
+    if (acc == NULL || tag == NULL) return NULL;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (acc), tag, &v);
+    s = g_value_get_string (&v);
+    return s;
+}
+
 void
-xaccAccountSetFilter (Account *acc, const char *str)
+xaccAccountSetColor (Account *acc, const char *str)
 {
-    g_return_if_fail(GNC_IS_ACCOUNT(acc));
+    set_kvp_string_tag (acc, "color", str);
+}
 
-    xaccAccountBeginEdit(acc);
-    if (str)
-    {
-        gchar *tmp = g_strstrip(g_strdup(str));
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "filter",
-                              strlen(tmp) ? kvp_value_new_string(tmp) : NULL);
-        g_free(tmp);
-    }
-    else
-    {
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "filter", NULL);
-    }
-    mark_account (acc);
-    xaccAccountCommitEdit(acc);
+void
+xaccAccountSetFilter (Account *acc, const char *str)
+{
+    set_kvp_string_tag (acc, "filter", str);
 }
 
 void
 xaccAccountSetSortOrder (Account *acc, const char *str)
 {
-    g_return_if_fail(GNC_IS_ACCOUNT(acc));
-
-    xaccAccountBeginEdit(acc);
-    if (str)
-    {
-        gchar *tmp = g_strstrip(g_strdup(str));
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "sort-order",
-                              strlen(tmp) ? kvp_value_new_string(tmp) : NULL);
-        g_free(tmp);
-    }
-    else
-    {
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "sort-order", NULL);
-    }
-    mark_account (acc);
-    xaccAccountCommitEdit(acc);
+    set_kvp_string_tag (acc, "sort-order", str);
 }
 
 static void
@@ -2367,22 +2361,7 @@ qofAccountSetParent (Account *acc, QofInstance *parent)
 void
 xaccAccountSetNotes (Account *acc, const char *str)
 {
-    g_return_if_fail(GNC_IS_ACCOUNT(acc));
-
-    xaccAccountBeginEdit(acc);
-    if (str)
-    {
-        gchar *tmp = g_strstrip(g_strdup(str));
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "notes",
-                              strlen(tmp) ? kvp_value_new_string(tmp) : NULL);
-        g_free(tmp);
-    }
-    else
-    {
-        kvp_frame_set_slot_nc(acc->inst.kvp_data, "notes", NULL);
-    }
-    mark_account(acc);
-    xaccAccountCommitEdit(acc);
+    set_kvp_string_tag (acc, "notes", str);
 }
 
 void
@@ -2498,23 +2477,26 @@ void
 DxaccAccountSetCurrency (Account * acc, gnc_commodity * currency)
 {
     QofBook *book;
-    const char *string;
+    GValue v = G_VALUE_INIT;
+    const char *s = gnc_commodity_get_unique_name (currency);
     gnc_commodity *commodity;
+    gnc_commodity_table *table;
 
     if ((!acc) || (!currency)) return;
-
-    xaccAccountBeginEdit(acc);
-    string = gnc_commodity_get_unique_name (currency);
-    kvp_frame_set_slot_nc(acc->inst.kvp_data, "old-currency",
-                          kvp_value_new_string(string));
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, s);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "old-currency", &v);
     mark_account (acc);
     xaccAccountCommitEdit(acc);
 
-    commodity = DxaccAccountGetCurrency (acc);
+    table = gnc_commodity_table_get_table (qof_instance_get_book(acc));
+    commodity = gnc_commodity_table_lookup_unique (table, s);
+
     if (!commodity)
     {
         book = qof_instance_get_book(acc);
-        gnc_commodity_table_insert (gnc_commodity_table_get_table (book), currency);
+        gnc_commodity_table_insert (gnc_commodity_table_get_table (book),
+				    currency);
     }
 }
 
@@ -3100,43 +3082,41 @@ const char *
 xaccAccountGetColor (const Account *acc)
 {
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
-    return acc ? kvp_frame_get_string(acc->inst.kvp_data, "color") : NULL;
+    return get_kvp_string_tag (acc, "color");
 }
 
 const char *
 xaccAccountGetFilter (const Account *acc)
 {
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
-    return acc ? kvp_frame_get_string(acc->inst.kvp_data, "filter") : NULL;
+    return get_kvp_string_tag (acc, "filter");
 }
 
 const char *
 xaccAccountGetSortOrder (const Account *acc)
 {
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 0);
-    return acc ? kvp_frame_get_string(acc->inst.kvp_data, "sort-order") : NULL;
+    return get_kvp_string_tag (acc, "sort-order");
 }
 
 const char *
 xaccAccountGetNotes (const Account *acc)
 {
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
-    return acc ? kvp_frame_get_string(acc->inst.kvp_data, "notes") : NULL;
+    return get_kvp_string_tag (acc, "notes");
 }
 
 gnc_commodity *
 DxaccAccountGetCurrency (const Account *acc)
 {
-    KvpValue *v;
+    GValue v = G_VALUE_INIT;
     const char *s;
     gnc_commodity_table *table;
 
     if (!acc) return NULL;
-
-    v = kvp_frame_get_slot(acc->inst.kvp_data, "old-currency");
-    if (!v) return NULL;
-
-    s = kvp_value_get_string (v);
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "old-currency", &v);
+    s = g_value_get_string (&v);
     if (!s) return NULL;
 
     table = gnc_commodity_table_get_table (qof_instance_get_book(acc));
@@ -3689,7 +3669,7 @@ xaccAccountGetBalanceAsOfDateInCurrency(
 
 gnc_numeric
 xaccAccountGetBalanceChangeForPeriod (Account *acc, time64 t1, time64 t2,
-				      gboolean recurse)
+                                      gboolean recurse)
 {
     gnc_numeric b1, b2;
 
@@ -3732,7 +3712,7 @@ xaccAccountCountSplits (const Account *acc, gboolean include_children)
     nr = g_list_length(xaccAccountGetSplitList(acc));
     if (include_children && (gnc_account_n_children(acc) != 0))
     {
-	for (i=0; i < gnc_account_n_children(acc); i++)
+        for (i=0; i < gnc_account_n_children(acc); i++)
         {
             nr += xaccAccountCountSplits(gnc_account_nth_child(acc, i), TRUE);
         }
@@ -3807,47 +3787,49 @@ xaccAccountForEachLot(const Account *acc,
 gboolean
 xaccAccountGetTaxRelated (const Account *acc)
 {
+    GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-    return kvp_frame_get_gint64(acc->inst.kvp_data, "tax-related");
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "tax-related", &v);
+    return g_value_get_boolean (&v);
 }
 
 void
 xaccAccountSetTaxRelated (Account *acc, gboolean tax_related)
 {
-    KvpValue *new_value;
-
+    GValue v = G_VALUE_INIT;
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
-    if (tax_related)
-        new_value = kvp_value_new_gint64 (tax_related);
-    else
-        new_value = NULL;
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    g_value_set_boolean (&v, tax_related);
 
-    xaccAccountBeginEdit (acc);
-    kvp_frame_set_slot_nc(acc->inst.kvp_data, "tax-related", new_value);
+    xaccAccountBeginEdit(acc);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "tax-related", &v);
     mark_account (acc);
-    xaccAccountCommitEdit (acc);
+    xaccAccountCommitEdit(acc);
 }
 
 const char *
 xaccAccountGetTaxUSCode (const Account *acc)
 {
-    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
-    return kvp_frame_get_string(acc->inst.kvp_data, "tax-US/code");
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "/tax-US/code", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_STRING (&v), FALSE);
+    return g_value_get_string (&v);
 }
 
 void
 xaccAccountSetTaxUSCode (Account *acc, const char *code)
 {
+    GValue v = G_VALUE_INIT;
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, code);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_string (acc->inst.kvp_data, "/tax-US/code", code);
-    if (!code)
-    {
-        KvpFrame  *frame = NULL;
-        kvp_frame_set_frame (acc->inst.kvp_data, "/tax-US", frame);
-    }
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "/tax-US/code", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -3855,19 +3837,25 @@ xaccAccountSetTaxUSCode (Account *acc, const char *code)
 const char *
 xaccAccountGetTaxUSPayerNameSource (const Account *acc)
 {
-    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), NULL);
-    return kvp_frame_get_string(acc->inst.kvp_data,
-                                "tax-US/payer-name-source");
-}
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE(acc),
+                          "/tax-US/payer-name-source", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_STRING (&v), FALSE);
+    return g_value_get_string (&v);
+ }
 
 void
 xaccAccountSetTaxUSPayerNameSource (Account *acc, const char *source)
 {
+    GValue v = G_VALUE_INIT;
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, source);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_string (acc->inst.kvp_data,
-                          "/tax-US/payer-name-source", source);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "/tax-US/payer-name-source", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -3876,10 +3864,13 @@ gint64
 xaccAccountGetTaxUSCopyNumber (const Account *acc)
 {
     gint64 copy_number;
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_INT64);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "/tax-US/copy-number", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
+    copy_number = g_value_get_int64 (&v);
 
-    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), 1);
-    copy_number = kvp_frame_get_gint64(acc->inst.kvp_data,
-                                       "tax-US/copy-number");
     return (copy_number == 0) ? 1 : copy_number;
 }
 
@@ -3887,19 +3878,17 @@ void
 xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
 {
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
-
     xaccAccountBeginEdit (acc);
     if (copy_number != 0)
-        kvp_frame_set_gint64 (acc->inst.kvp_data, "/tax-US/copy-number", copy_number);
+    {
+        GValue v = G_VALUE_INIT;
+        g_value_init (&v, G_TYPE_INT64);
+        g_value_set_int64 (&v, copy_number);
+        qof_instance_set_kvp (QOF_INSTANCE (acc), "/tax-US/copy-number", &v);
+    }
     else
     {
-        KvpFrame * frame;
-        KvpValue *value;
-
-        value = NULL;
-        frame = kvp_frame_set_value_nc (acc->inst.kvp_data,
-                                        "/tax-US/copy-number", value);
-        if (!frame) kvp_value_delete (value);
+        qof_instance_set_kvp (QOF_INSTANCE (acc), "/tax-US/copy-number", NULL);
     }
     mark_account (acc);
     xaccAccountCommitEdit (acc);
@@ -3911,22 +3900,24 @@ xaccAccountSetTaxUSCopyNumber (Account *acc, gint64 copy_number)
 gboolean
 xaccAccountGetPlaceholder (const Account *acc)
 {
-    const char *str;
-
+    GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-
-    str = kvp_frame_get_string(acc->inst.kvp_data, "placeholder");
-    return (str && !strcmp(str, "true"));
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "placeholder", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (&v), FALSE);
+    return g_value_get_boolean (&v);
 }
 
 void
 xaccAccountSetPlaceholder (Account *acc, gboolean val)
 {
+    GValue v = G_VALUE_INIT;
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    g_value_set_boolean (&v, val);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_string (acc->inst.kvp_data,
-                          "placeholder", val ? "true" : NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "placeholder", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -3958,22 +3949,24 @@ xaccAccountGetDescendantPlaceholder (const Account *acc)
 gboolean
 xaccAccountGetHidden (const Account *acc)
 {
-    const char *str;
-
+    GValue v = G_VALUE_INIT;
     g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
-
-    str = kvp_frame_get_string(acc->inst.kvp_data, "hidden");
-    return (str && !strcmp(str, "true"));
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "hidden", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (&v), FALSE);
+    return g_value_get_boolean (&v);
 }
 
 void
 xaccAccountSetHidden (Account *acc, gboolean val)
 {
+    GValue v = G_VALUE_INIT;
     g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    g_value_set_boolean (&v, val);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_string (acc->inst.kvp_data, "hidden",
-                          val ? "true" : NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "hidden", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4263,19 +4256,21 @@ xaccAccountIsPriced(const Account *acc)
 gboolean
 xaccAccountGetReconcileLastDate (const Account *acc, time64 *last_date)
 {
-    KvpValue *v;
-
-    if (!acc) return FALSE;
-
-    v = kvp_frame_get_value(acc->inst.kvp_data, "reconcile-info/last-date");
-
-    if (!v || kvp_value_get_type(v) != KVP_TYPE_GINT64)
-        return FALSE;
-
-    if (last_date)
-        *last_date = kvp_value_get_gint64(v);
+    gint64 date;
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_INT64);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "reconcile-info/last-date", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
+    date = g_value_get_int64 (&v);
 
-    return TRUE;
+    if (date)
+    {
+        if (last_date)
+            *last_date = date;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /********************************************************************\
@@ -4284,11 +4279,13 @@ xaccAccountGetReconcileLastDate (const Account *acc, time64 *last_date)
 void
 xaccAccountSetReconcileLastDate (Account *acc, time64 last_date)
 {
-    if (!acc) return;
+    GValue v = G_VALUE_INIT;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_INT64);
+    g_value_set_int64 (&v, last_date);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_gint64 (acc->inst.kvp_data,
-                          "/reconcile-info/last-date", last_date);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "/reconcile-info/last-date", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4300,23 +4297,28 @@ gboolean
 xaccAccountGetReconcileLastInterval (const Account *acc,
                                      int *months, int *days)
 {
-    KvpValue *v1, *v2;
+    GValue v1, v2;
+    int m, d;
 
     if (!acc) return FALSE;
-
-    v1 = kvp_frame_get_value(acc->inst.kvp_data,
-                             "reconcile-info/last-interval/months");
-    v2 = kvp_frame_get_value(acc->inst.kvp_data,
-                             "reconcile-info/last-interval/days");
-    if (!v1 || (kvp_value_get_type (v1) != KVP_TYPE_GINT64) ||
-            !v2 || (kvp_value_get_type (v2) != KVP_TYPE_GINT64))
-        return FALSE;
-
-    if (months)
-        *months = kvp_value_get_gint64 (v1);
-    if (days)
-        *days = kvp_value_get_gint64 (v2);
-    return TRUE;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v1, G_TYPE_INT64);
+    qof_instance_get_kvp (QOF_INSTANCE(acc),
+                          "reconcile-info/last-interval/months", &v1);
+    g_value_init (&v2, G_TYPE_INT64);
+    qof_instance_get_kvp (QOF_INSTANCE(acc),
+                          "reconcile-info/last-interval/days", &v2);
+    m = g_value_get_int64 (&v1);
+    d = g_value_get_int64 (&v2);
+    if (m && d)
+    {
+        if (months)
+            *months = m;
+        if (days)
+            *days = d;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /********************************************************************\
@@ -4325,18 +4327,18 @@ xaccAccountGetReconcileLastInterval (const Account *acc,
 void
 xaccAccountSetReconcileLastInterval (Account *acc, int months, int days)
 {
-    KvpFrame *frame;
-    if (!acc) return;
+    GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v1, G_TYPE_INT64);
+    g_value_set_int64 (&v1, months);
+    g_value_init (&v2, G_TYPE_INT64);
+    g_value_set_int64 (&v2, days);
     xaccAccountBeginEdit (acc);
-
-    frame = kvp_frame_get_frame_slash (acc->inst.kvp_data,
-                                       "/reconcile-info/last-interval");
-    g_assert(frame);
-
-    kvp_frame_set_gint64 (frame, "months", months);
-    kvp_frame_set_gint64 (frame, "days", days);
-
+    qof_instance_set_kvp (QOF_INSTANCE (acc),
+                          "reconcile-info/last-interval/months", &v1);
+    qof_instance_set_kvp (QOF_INSTANCE (acc),
+                          "reconcile-info/last-interval/days", &v2);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4347,18 +4349,22 @@ xaccAccountSetReconcileLastInterval (Account *acc, int months, int days)
 gboolean
 xaccAccountGetReconcilePostponeDate (const Account *acc, time64 *postpone_date)
 {
-    KvpValue *v;
-
-    if (!acc) return FALSE;
-
-    v = kvp_frame_get_value(acc->inst.kvp_data, "reconcile-info/postpone/date");
-    if (!v || kvp_value_get_type (v) != KVP_TYPE_GINT64)
-        return FALSE;
-
-    if (postpone_date)
-        *postpone_date = kvp_value_get_gint64 (v);
+    gint64 date;
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_INT64);
+    qof_instance_get_kvp (QOF_INSTANCE(acc),
+                          "reconcile-info/postpone/date", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
+    date = g_value_get_int64 (&v);
 
-    return TRUE;
+    if (date)
+    {
+        if (postpone_date)
+            *postpone_date = date;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /********************************************************************\
@@ -4367,13 +4373,14 @@ xaccAccountGetReconcilePostponeDate (const Account *acc, time64 *postpone_date)
 void
 xaccAccountSetReconcilePostponeDate (Account *acc, time64 postpone_date)
 {
-    if (!acc) return;
+    GValue v = G_VALUE_INIT;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_INT64);
+    g_value_set_int64 (&v, postpone_date);
     xaccAccountBeginEdit (acc);
-
-    /* XXX this should be using timespecs, not gints !! */
-    kvp_frame_set_gint64 (acc->inst.kvp_data,
-                          "reconcile-info/postpone/date", postpone_date);
+    qof_instance_set_kvp (QOF_INSTANCE (acc),
+                          "/reconcile-info/postpone/date", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4385,19 +4392,22 @@ gboolean
 xaccAccountGetReconcilePostponeBalance (const Account *acc,
                                         gnc_numeric *balance)
 {
-    KvpValue *v;
-
-    if (!acc) return FALSE;
-
-    v = kvp_frame_get_value(acc->inst.kvp_data,
-                            "reconcile-info/postpone/balance");
-    if (!v || kvp_value_get_type (v) != KVP_TYPE_NUMERIC)
-        return FALSE;
-
-    if (balance)
-        *balance = kvp_value_get_numeric (v);
+    gnc_numeric bal;
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    qof_instance_get_kvp (QOF_INSTANCE(acc),
+                          "reconcile-info/postpone/balance", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_INT64 (&v), FALSE);
+    bal = *(gnc_numeric*)g_value_get_boxed (&v);
 
-    return TRUE;
+    if (bal.denom)
+    {
+        if (balance)
+            *balance = bal;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /********************************************************************\
@@ -4406,11 +4416,14 @@ xaccAccountGetReconcilePostponeBalance (const Account *acc,
 void
 xaccAccountSetReconcilePostponeBalance (Account *acc, gnc_numeric balance)
 {
-    if (!acc) return;
+    GValue v = G_VALUE_INIT;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, GNC_TYPE_NUMERIC);
+    g_value_set_boxed (&v, &balance);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_gnc_numeric (acc->inst.kvp_data,
-                               "/reconcile-info/postpone/balance", balance);
+    qof_instance_set_kvp (QOF_INSTANCE (acc),
+                          "/reconcile-info/postpone/balance", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4425,7 +4438,7 @@ xaccAccountClearReconcilePostpone (Account *acc)
     if (!acc) return;
 
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_value (acc->inst.kvp_data, "reconcile-info/postpone", NULL);
+    qof_instance_set_kvp (QOF_INSTANCE(acc), "reconcile-info/postpone", NULL);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4440,12 +4453,13 @@ xaccAccountClearReconcilePostpone (Account *acc)
 gboolean
 xaccAccountGetAutoInterestXfer (const Account *acc, gboolean default_value)
 {
-    const char *str = NULL;
-    if (!acc) return default_value;
-
-    str = kvp_frame_get_string(acc->inst.kvp_data,
-                               "reconcile-info/auto-interest-transfer");
-    return str ? !strcmp(str, "true") : default_value;
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    qof_instance_get_kvp (QOF_INSTANCE(acc),
+                          "reconcile-info/auto-interest-transfer", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (&v), FALSE);
+    return g_value_get_boolean (&v);
 }
 
 /********************************************************************\
@@ -4454,13 +4468,14 @@ xaccAccountGetAutoInterestXfer (const Account *acc, gboolean default_value)
 void
 xaccAccountSetAutoInterestXfer (Account *acc, gboolean option)
 {
-    if (!acc) return;
+    GValue v = G_VALUE_INIT;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
 
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    g_value_set_boolean (&v, option);
     xaccAccountBeginEdit (acc);
-    /* FIXME: need KVP_TYPE_BOOLEAN for this someday */
-    kvp_frame_set_string (acc->inst.kvp_data,
-                          "/reconcile-info/auto-interest-transfer",
-                          (option ? "true" : "false"));
+    qof_instance_set_kvp (QOF_INSTANCE (acc),
+                          "/reconcile-info/auto-interest-transfer", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4471,7 +4486,12 @@ xaccAccountSetAutoInterestXfer (Account *acc, gboolean option)
 const char *
 xaccAccountGetLastNum (const Account *acc)
 {
-    return acc ? kvp_frame_get_string(acc->inst.kvp_data, "last-num") : NULL;
+    GValue v = G_VALUE_INIT;
+    g_return_val_if_fail(GNC_IS_ACCOUNT(acc), FALSE);
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "last-num", &v);
+    g_return_val_if_fail (G_VALUE_HOLDS_STRING (&v), FALSE);
+    return g_value_get_string (&v);
 }
 
 /********************************************************************\
@@ -4480,10 +4500,13 @@ xaccAccountGetLastNum (const Account *acc)
 void
 xaccAccountSetLastNum (Account *acc, const char *num)
 {
-    if (!acc) return;
+    GValue v = G_VALUE_INIT;
+    g_return_if_fail(GNC_IS_ACCOUNT(acc));
+    g_value_init (&v, G_TYPE_STRING);
 
+    g_value_set_string (&v, num);
     xaccAccountBeginEdit (acc);
-    kvp_frame_set_string(acc->inst.kvp_data, "last-num", num);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "last-num", &v);
     mark_account (acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4536,29 +4559,36 @@ GetOrMakeOrphanAccount (Account *root, gnc_commodity * currency)
 Account *
 xaccAccountGainsAccount (Account *acc, gnc_commodity *curr)
 {
-    KvpFrame *frame = qof_instance_get_slots (QOF_INSTANCE (acc));
-    const gchar *curr_name = gnc_commodity_get_unique_name (curr);
+    GValue v = G_VALUE_INIT;
+    gchar *curr_name = g_strdup_printf ("/lot-mgmt/gains-act/%s",
+                                      gnc_commodity_get_unique_name (curr));
     GncGUID *guid;
     Account *gains_account;
 
-    frame = kvp_frame_get_frame_slash (frame, "/lot-mgmt/gains-act/");
-    guid = kvp_frame_get_guid (frame, curr_name);
+    g_return_val_if_fail (acc != NULL, NULL);
+    g_value_init (&v, GNC_TYPE_GUID);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), curr_name, &v);
+    guid = (GncGUID*)g_value_get_boxed (&v);
     if (guid == NULL) /* No gains account for this currency */
     {
-	gains_account = GetOrMakeOrphanAccount (gnc_account_get_root (acc),
-						curr);
-	guid = (GncGUID*)qof_instance_get_guid (QOF_INSTANCE (gains_account));
-	xaccAccountBeginEdit (acc);
-	{
-	    kvp_frame_set_guid (frame, curr_name, guid);
-	    qof_instance_set_dirty (QOF_INSTANCE (acc));
-	}
-	xaccAccountCommitEdit (acc);
+        gains_account = GetOrMakeOrphanAccount (gnc_account_get_root (acc),
+                                                curr);
+        guid = (GncGUID*)qof_instance_get_guid (QOF_INSTANCE (gains_account));
+        xaccAccountBeginEdit (acc);
+        {
+             GValue vr = G_VALUE_INIT;
+             g_value_init (&vr, GNC_TYPE_GUID);
+             g_value_set_boxed (&vr, guid);
+             qof_instance_set_kvp (QOF_INSTANCE (acc), curr_name, &vr);
+             qof_instance_set_dirty (QOF_INSTANCE (acc));
+        }
+        xaccAccountCommitEdit (acc);
     }
     else
-	gains_account = xaccAccountLookup (guid,
-					   qof_instance_get_book(acc));
+        gains_account = xaccAccountLookup (guid,
+                                           qof_instance_get_book(acc));
 
+    g_free (curr_name);
     return gains_account;
 }
 
@@ -4570,17 +4600,23 @@ dxaccAccountSetPriceSrc(Account *acc, const char *src)
 {
     if (!acc) return;
 
-    xaccAccountBeginEdit(acc);
     if (xaccAccountIsPriced(acc))
     {
-        kvp_frame_set_slot_nc(acc->inst.kvp_data,
-                              "old-price-source",
-                              src ? kvp_value_new_string(src) : NULL);
+        xaccAccountBeginEdit(acc);
+        if (src)
+        {
+            GValue v = G_VALUE_INIT;
+            g_value_init (&v, G_TYPE_STRING);
+            g_value_set_string (&v, src);
+            qof_instance_set_kvp (QOF_INSTANCE(acc),
+                                  "old-price-source", &v);
+        }
+        else
+            qof_instance_set_kvp (QOF_INSTANCE(acc), "old-price-source", NULL);
+
         mark_account (acc);
+        xaccAccountCommitEdit(acc);
     }
-
-    qof_instance_set_dirty(&acc->inst);
-    xaccAccountCommitEdit(acc);
 }
 
 /********************************************************************\
@@ -4589,15 +4625,14 @@ dxaccAccountSetPriceSrc(Account *acc, const char *src)
 const char*
 dxaccAccountGetPriceSrc(const Account *acc)
 {
+    GValue v = G_VALUE_INIT;
     if (!acc) return NULL;
 
-    if (xaccAccountIsPriced(acc))
-    {
-        KvpValue *value = kvp_frame_get_slot(acc->inst.kvp_data,
-                                             "old-price-source");
-        if (value) return (kvp_value_get_string(value));
-    }
-    return NULL;
+    if (!xaccAccountIsPriced(acc)) return NULL;
+
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE(acc), "old-price-source", &v);
+    return g_value_get_string (&v);
 }
 
 /********************************************************************\
@@ -4606,17 +4641,14 @@ dxaccAccountGetPriceSrc(const Account *acc)
 void
 dxaccAccountSetQuoteTZ(Account *acc, const char *tz)
 {
+    GValue v = G_VALUE_INIT;
     if (!acc) return;
-
+    if (!xaccAccountIsPriced(acc)) return;
     xaccAccountBeginEdit(acc);
-    if (xaccAccountIsPriced(acc))
-    {
-        kvp_frame_set_slot_nc(acc->inst.kvp_data,
-                              "old-quote-tz",
-                              tz ? kvp_value_new_string(tz) : NULL);
-        mark_account (acc);
-    }
-    qof_instance_set_dirty(&acc->inst);
+    g_value_init (&v, G_TYPE_STRING);
+    g_value_set_string (&v, tz);
+    qof_instance_set_kvp (QOF_INSTANCE (acc), "old-quote-tz", &v);
+    mark_account (acc);
     xaccAccountCommitEdit(acc);
 }
 
@@ -4626,14 +4658,12 @@ dxaccAccountSetQuoteTZ(Account *acc, const char *tz)
 const char*
 dxaccAccountGetQuoteTZ(const Account *acc)
 {
+    GValue v = G_VALUE_INIT;
     if (!acc) return NULL;
-
-    if (xaccAccountIsPriced(acc))
-    {
-        KvpValue *value = kvp_frame_get_slot(acc->inst.kvp_data, "old-quote-tz");
-        if (value) return (kvp_value_get_string(value));
-    }
-    return NULL;
+    if (!xaccAccountIsPriced(acc)) return NULL;
+    g_value_init (&v, G_TYPE_STRING);
+    qof_instance_get_kvp (QOF_INSTANCE (acc), "old-quote-tz", &v);
+    return g_value_get_string (&v);
 }
 
 /********************************************************************\
@@ -4642,13 +4672,18 @@ dxaccAccountGetQuoteTZ(const Account *acc)
 void
 xaccAccountSetReconcileChildrenStatus(Account *acc, gboolean status)
 {
+    GValue v = G_VALUE_INIT;
     if (!acc) return;
 
     xaccAccountBeginEdit (acc);
-
-    /* XXX FIXME: someday this should use KVP_TYPE_BOOLEAN */
-    kvp_frame_set_gint64 (acc->inst.kvp_data,
-                          "/reconcile-info/include-children", status);
+    /* Would have been nice to use G_TYPE_BOOLEAN, but the other
+     * boolean kvps save the value as "true" or "false" and that would
+     * be file-incompatible with this.
+     */
+    g_value_init (&v, G_TYPE_INT64);
+    g_value_set_int64 (&v, status);
+    qof_instance_set_kvp (QOF_INSTANCE (acc),
+                          "/reconcile-info/include-children", &v);
     mark_account(acc);
     xaccAccountCommitEdit (acc);
 }
@@ -4663,8 +4698,12 @@ xaccAccountGetReconcileChildrenStatus(const Account *acc)
      * is found then we can assume not to include the children, that being
      * the default behaviour
      */
-    return acc ? kvp_frame_get_gint64(acc->inst.kvp_data,
-                                      "reconcile-info/include-children") : FALSE;
+    GValue v = G_VALUE_INIT;
+    if (!acc) return FALSE;
+    g_value_init (&v, G_TYPE_BOOLEAN);
+    qof_instance_get_kvp (QOF_INSTANCE (acc),
+                          "reconcile-info/include-children", &v);
+    return g_value_get_int64 (&v);
 }
 
 /********************************************************************\
@@ -5006,21 +5045,16 @@ xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc,
  * src/import-export/import-backend.c to manipulate the contra-account
  * matching data. See src/import-export/import-backend.c for explanations.
  */
-/* FIXME: These data are stored per-account in KVP and the functions
- * work directly on KVP data structures. This prevents moving KVP to a
- * backend-only abstraction.
- */
-
 
 typedef struct _GncImportMatchMap
 {
-    KvpFrame *	frame;
-    Account *	acc;
-    QofBook *	book;
+    KvpFrame *  frame;
+    Account *   acc;
+    QofBook *   book;
 } GncImportMatchMap;
 
-#define IMAP_FRAME		"import-map"
-#define IMAP_FRAME_BAYES	"import-map-bayes"
+#define IMAP_FRAME              "import-map"
+#define IMAP_FRAME_BAYES        "import-map-bayes"
 GncImportMatchMap * gnc_account_create_imap (Account *acc);
 Account* gnc_imap_find_account(GncImportMatchMap *imap, const char* category,
                                const char *key);
@@ -5057,58 +5091,50 @@ gnc_account_create_imap (Account *acc)
 /* Look up an Account in the map */
 Account*
 gnc_imap_find_account (GncImportMatchMap *imap,
-		       const char *category,
-		       const char *key)
+                       const char *category,
+                       const char *key)
 {
-    KvpValue *value;
+    GValue v = G_VALUE_INIT;
     GncGUID * guid;
+    char *kvp_path;
 
     if (!imap || !key) return NULL;
     if (!category)
-    {
-        category = key;
-        key = NULL;
-    }
-
-    value = kvp_frame_get_slot_path (imap->frame, IMAP_FRAME,
-				     category, key, NULL);
-    if (!value) return NULL;
-
-    guid = kvp_value_get_guid (value);
+        kvp_path = g_strdup_printf (IMAP_FRAME "/%s", key);
+    else
+        kvp_path = g_strdup_printf (IMAP_FRAME "/%s/%s", category, key);
+    g_value_init (&v, GNC_TYPE_GUID);
+    qof_instance_get_kvp (QOF_INSTANCE (imap->acc), kvp_path, &v);
+    guid = (GncGUID*)g_value_get_boxed (&v);
+    g_free (kvp_path);
     return xaccAccountLookup (guid, imap->book);
 }
 
 /* Store an Account in the map */
 void
 gnc_imap_add_account (GncImportMatchMap *imap,
-		      const char *category,
-		      const char *key,
-		      Account *acc)
+                      const char *category,
+                      const char *key,
+                      Account *acc)
 {
-    KvpValue *value;
+    GValue v = G_VALUE_INIT;
+    char *kvp_path;
 
     if (!imap || !key || !acc || (strlen (key) == 0)) return;
     if (!category)
-    {
-        category = key;
-        key = NULL;
-    }
-    g_return_if_fail (acc != NULL);
+        kvp_path = g_strdup_printf (IMAP_FRAME "/%s", key);
+    else
+        kvp_path = g_strdup_printf (IMAP_FRAME "/%s/%s", category, key);
 
-    value = kvp_value_new_guid (xaccAccountGetGUID (acc));
-    g_return_if_fail (value != NULL);
+    g_value_init (&v, GNC_TYPE_GUID);
+    g_value_set_boxed (&v, xaccAccountGetGUID (acc));
     xaccAccountBeginEdit (imap->acc);
-    kvp_frame_set_slot_path (imap->frame, value, IMAP_FRAME, category, key, NULL);
+    qof_instance_set_kvp (QOF_INSTANCE (imap->acc), kvp_path, &v);
+    g_free (kvp_path);
     qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
     xaccAccountCommitEdit (imap->acc);
-    kvp_value_delete (value);
-
-    /* XXX Mark the account (or book) as dirty! */
 }
 
-
-
-
 /*--------------------------------------------------------------------------
  Below here is the bayes transaction to account matching system
 --------------------------------------------------------------------------*/
@@ -5139,7 +5165,7 @@ buildTokenInfo(const char *key, KvpValue *value, gpointer data)
     struct account_token_count* this_account;
 
     //  PINFO("buildTokenInfo: account '%s', token_count: '%ld'\n", (char*)key,
-    //			(long)kvp_value_get_gint64(value));
+    //                  (long)kvp_value_get_gint64(value));
 
     /* add the count to the total_count */
     tokenInfo->total_count += kvp_value_get_gint64(value);
@@ -5238,22 +5264,22 @@ Account*
 gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
 {
     struct token_accounts_info tokenInfo; /**< holds the accounts and total
-					   * token count for a single token */
-    GList *current_token;		  /**< pointer to the current
-					   * token from the input GList
-					   * tokens */
-    GList *current_account_token;	  /**< pointer to the struct
-					   * account_token_count */
+                                           * token count for a single token */
+    GList *current_token;                 /**< pointer to the current
+                                           * token from the input GList
+                                           * tokens */
+    GList *current_account_token;         /**< pointer to the struct
+                                           * account_token_count */
     struct account_token_count *account_c; /**< an account name and the number
-					    * of times a token has appeared
-					    * for the account */
+                                            * of times a token has appeared
+                                            * for the account */
     struct account_probability *account_p; /**< intermediate storage of values
-					    * to compute the bayes probability
-					    * of an account */
+                                            * to compute the bayes probability
+                                            * of an account */
     GHashTable *running_probabilities = g_hash_table_new(g_str_hash,
-							 g_str_equal);
+                                                         g_str_equal);
     GHashTable *final_probabilities = g_hash_table_new(g_str_hash,
-						       g_str_equal);
+                                                       g_str_equal);
     struct account_info account_i;
     KvpValue* value;
     KvpFrame* token_frame;
@@ -5272,7 +5298,7 @@ gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
      * in the input tokens list
      */
     for (current_token = tokens; current_token;
-	 current_token = current_token->next)
+         current_token = current_token->next)
     {
         /* zero out the token_accounts_info structure */
         memset(&tokenInfo, 0, sizeof(struct token_accounts_info));
@@ -5332,8 +5358,8 @@ gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
             if (account_p)
             {
                 account_p->product = (((double)account_c->token_count /
-				      (double)tokenInfo.total_count)
-				      * account_p->product);
+                                      (double)tokenInfo.total_count)
+                                      * account_p->product);
                 account_p->product_difference =
                     ((double)1 - ((double)account_c->token_count /
                                   (double)tokenInfo.total_count))
@@ -5416,19 +5442,14 @@ gnc_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
 /** Updates the imap for a given account using a list of tokens */
 void
 gnc_imap_add_account_bayes(GncImportMatchMap *imap,
-			   GList *tokens,
-			   Account *acc)
+                           GList *tokens,
+                           Account *acc)
 {
     GList *current_token;
-    KvpValue *value;
     gint64 token_count;
-    char* account_fullname;
-    KvpValue *new_value; /* the value that will be added back into
-			   * the kvp tree */
+    char *account_fullname, *kvp_path;
 
     ENTER(" ");
-
-    /* if imap is null return */
     if (!imap)
     {
         LEAVE(" ");
@@ -5445,10 +5466,11 @@ gnc_imap_add_account_bayes(GncImportMatchMap *imap,
     for (current_token = g_list_first(tokens); current_token;
             current_token = current_token->next)
     {
+         GValue value = G_VALUE_INIT;
         /* Jump to next iteration if the pointer is not valid or if the
-        	 string is empty. In HBCI import we almost always get an empty
-        	 string, which doesn't work in the kvp loopkup later. So we
-        	 skip this case here. */
+                 string is empty. In HBCI import we almost always get an empty
+                 string, which doesn't work in the kvp loopkup later. So we
+                 skip this case here. */
         if (!current_token->data || (*((char*)current_token->data) == '\0'))
             continue;
 
@@ -5457,42 +5479,28 @@ gnc_imap_add_account_bayes(GncImportMatchMap *imap,
 
         PINFO("adding token '%s'\n", (char*)current_token->data);
 
-        /* is this token/account_name already in the kvp tree? */
-        value = kvp_frame_get_slot_path(imap->frame, IMAP_FRAME_BAYES,
-                                        (char*)current_token->data,
-					account_fullname,
-                                        NULL);
+        kvp_path = g_strdup_printf (IMAP_FRAME_BAYES "/%s/%s",
+                                    (char*)current_token->data,
+                                    account_fullname);
 
+        g_value_init (&value, G_TYPE_INT64);
+        qof_instance_get_kvp (QOF_INSTANCE (imap->acc), kvp_path, &value);
         /* if the token/account is already in the tree, read the current
          * value from the tree and use this for the basis of the value we
          * are putting back
          */
-        if (value)
+        if (G_VALUE_HOLDS_INT64 (&value))
         {
-            PINFO("found existing value of '%ld'\n",
-                  (long)kvp_value_get_gint64(value));
+            int64_t count = g_value_get_int64 (&value);
+            PINFO("found existing value of '%" G_GINT64_FORMAT "'\n", count);
 
-            /* convert this value back into an integer */
-            token_count += kvp_value_get_gint64(value);
+            token_count += count;
         }
-
-        /* increment the token count */
         token_count++;
-
-        /* create a new value */
-        new_value = kvp_value_new_gint64(token_count);
-
-        /* insert the value into the kvp tree at
-         * /imap->frame/IMAP_FRAME/token_string/account_name_string
-         */
-        kvp_frame_set_slot_path(imap->frame, new_value,
-				IMAP_FRAME_BAYES,
-                                (char*)current_token->data,
-				account_fullname,
-				NULL);
-        /* kvp_frame_set_slot_path() copied the value so we
-         * need to delete this one ;-) */
-        kvp_value_delete(new_value);
+        g_value_init (&value, G_TYPE_INT64);
+        g_value_set_int64 (&value, token_count);
+        qof_instance_set_kvp (QOF_INSTANCE (imap->acc), kvp_path, &value);
+        g_free (kvp_path);
     }
 
     /* free up the account fullname string */
@@ -5629,10 +5637,6 @@ gboolean xaccAccountRegister (void)
             QOF_PARAM_GUID, QOF_TYPE_GUID,
             (QofAccessFunc) qof_instance_get_guid, NULL
         },
-        {
-            ACCOUNT_KVP, QOF_TYPE_KVP,
-            (QofAccessFunc) qof_instance_get_slots, NULL
-        },
         { NULL },
     };
 

commit c9785be334d7a3b27b734629ba880f8fd6f8518d
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 8 13:31:56 2015 -0700

    Provide qof_instance_copy_kvp, qof_instance_swap_kvp, and qof_instance_compare_kvp.
    
    To facilitate abstracting all kV operations to libqof/qof.

diff --git a/src/libqof/qof/qofinstance-p.h b/src/libqof/qof/qofinstance-p.h
index 751b3f0..2428ad9 100644
--- a/src/libqof/qof/qofinstance-p.h
+++ b/src/libqof/qof/qofinstance-p.h
@@ -108,6 +108,11 @@ void qof_instance_set_idata(gpointer inst, guint32 idata);
 /* Convenience functions to save some typing in property handlers */
 void qof_instance_set_kvp (QofInstance *inst, const gchar *key, const GValue *value);
 void qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value);
+void qof_instance_copy_kvp (QofInstance *to, const QofInstance *from);
+void qof_instance_swap_kvp (QofInstance *a, QofInstance *b);
+int qof_instance_compare_kvp (const QofInstance *a, const QofInstance *b);
+char* qof_instance_kvp_as_string (const QofInstance *inst);
+
 
 #ifdef __cplusplus
 }
diff --git a/src/libqof/qof/qofinstance.cpp b/src/libqof/qof/qofinstance.cpp
index 1af2c0a..d545fdf 100644
--- a/src/libqof/qof/qofinstance.cpp
+++ b/src/libqof/qof/qofinstance.cpp
@@ -28,18 +28,13 @@
  * Copyright (c) 2007 David Hampton <hampton at employees.org>
  */
 
-#ifdef __cplusplus
 extern "C"
 {
-#endif
-
 #include "config.h"
 #include <glib.h>
-
-#ifdef __cplusplus
 }
-#endif
 
+#include <utility>
 #include "qof.h"
 #include "kvp-util-p.h"
 #include "qofbook-p.h"
@@ -1090,6 +1085,29 @@ qof_instance_get_kvp (QofInstance *inst, const gchar *key, GValue *value)
     }
 }
 
+void
+qof_instance_copy_kvp (QofInstance *to, const QofInstance *from)
+{
+    to->kvp_data = kvp_frame_copy(from->kvp_data);
+}
+
+void
+qof_instance_swap_kvp (QofInstance *a, QofInstance *b)
+{
+    std::swap(a->kvp_data, b->kvp_data);
+}
+
+int
+qof_instance_compare_kvp (const QofInstance *a, const QofInstance *b)
+{
+    return kvp_frame_compare (a->kvp_data, b->kvp_data);
+}
+
+char*
+qof_instance_kvp_as_string (const QofInstance *inst)
+{
+    return kvp_frame_to_string (inst->kvp_data);
+}
 
 /* ========================== END OF FILE ======================= */
 

commit 32d4fff3669041d83ccf614c24902070caab9132
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu May 7 16:12:54 2015 -0700

    Implement KVP_TYPE_BOOLEAN
    
    In terms of KVP_TYPE_STRING such that TRUE->"true" and FALSE->NULL. This
    provides compatibility with the existing boolean KVP in Account.c.

diff --git a/src/libqof/qof/kvp_frame.cpp b/src/libqof/qof/kvp_frame.cpp
index 4ba546e..b2b4683 100644
--- a/src/libqof/qof/kvp_frame.cpp
+++ b/src/libqof/qof/kvp_frame.cpp
@@ -933,6 +933,13 @@ kvp_value_new_double(double value)
 }
 
 KvpValue *
+kvp_value_new_boolean(gboolean value)
+{
+    if (!value) return {};
+    return new KvpValueImpl{g_strdup("true")};
+}
+
+KvpValue *
 kvp_value_new_numeric(gnc_numeric value)
 {
     return new KvpValueImpl{value};
@@ -1024,6 +1031,15 @@ kvp_value_get_double(const KvpValue * ovalue)
     return value->get<double>();
 }
 
+bool
+kvp_value_get_boolean (const KvpValue *ovalue)
+{
+    if (!ovalue) return {};
+    const KvpValueImpl *value {static_cast<const KvpValueImpl*>(ovalue)};
+    const char* str = value->get<char*>();
+    return str && strcmp(str, "true") == 0;
+}
+
 gnc_numeric
 kvp_value_get_numeric(const KvpValue * ovalue)
 {
@@ -1186,7 +1202,7 @@ gvalue_list_from_kvp_value (KvpValue *kval, gpointer pList)
     GValue *gval = gvalue_from_kvp_value (kval);
     gvlist =  (GList**)pList;
     if (G_VALUE_TYPE (gval))
-	*gvlist = g_list_prepend (*gvlist, gval);
+        *gvlist = g_list_prepend (*gvlist, gval);
 }
 
 static void
@@ -1195,7 +1211,7 @@ kvp_value_list_from_gvalue (GValue *gval, gpointer pList)
     GList **kvplist = (GList**)pList;
     KvpValue *kvp;
     if (!(gval && G_VALUE_TYPE (gval)))
-	return;
+        return;
     kvp = kvp_value_from_gvalue (gval);
     *kvplist = g_list_prepend (*kvplist, kvp);
 }
@@ -1213,55 +1229,59 @@ gvalue_from_kvp_value (KvpValue *kval)
 
     switch (kvp_value_get_type(kval))
     {
-	case KVP_TYPE_GINT64:
-	    g_value_init (val, G_TYPE_INT64);
-	    g_value_set_int64 (val, kvp_value_get_gint64 (kval));
-	    break;
-	case KVP_TYPE_DOUBLE:
-	    g_value_init (val, G_TYPE_DOUBLE);
-	    g_value_set_double (val, kvp_value_get_double (kval));
-	    break;
-	case KVP_TYPE_NUMERIC:
-	    g_value_init (val, GNC_TYPE_NUMERIC);
-	    num = kvp_value_get_numeric (kval);
-	    g_value_set_boxed (val, &num);
-	    break;
-	case KVP_TYPE_STRING:
-	    g_value_init (val, G_TYPE_STRING);
-	    g_value_set_string (val, kvp_value_get_string (kval));
-	    break;
-	case KVP_TYPE_GUID:
-	    g_value_init (val, GNC_TYPE_GUID);
-	    g_value_set_boxed (val, kvp_value_get_guid (kval));
-	    break;
-	case KVP_TYPE_TIMESPEC:
-	    g_value_init (val, GNC_TYPE_TIMESPEC);
-	    tm = kvp_value_get_timespec (kval);
-	    g_value_set_boxed (val, &tm);
-	    break;
-	case KVP_TYPE_GDATE:
-	    g_value_init (val, G_TYPE_DATE);
-	    gdate = kvp_value_get_gdate (kval);
-	    g_value_set_boxed (val, &gdate);
-	    break;
-	case KVP_TYPE_GLIST:
-	{
-	    GList *gvalue_list = NULL;
-	    GList *kvp_list = kvp_value_get_glist (kval);
-	    g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value, &gvalue_list);
-	    g_value_init (val, GNC_TYPE_VALUE_LIST);
-	    gvalue_list = g_list_reverse (gvalue_list);
-	    g_value_set_boxed (val, gvalue_list);
-	    break;
-	}
+        case KVP_TYPE_GINT64:
+            g_value_init (val, G_TYPE_INT64);
+            g_value_set_int64 (val, kvp_value_get_gint64 (kval));
+            break;
+        case KVP_TYPE_DOUBLE:
+            g_value_init (val, G_TYPE_DOUBLE);
+            g_value_set_double (val, kvp_value_get_double (kval));
+            break;
+        case KVP_TYPE_BOOLEAN:
+            g_value_init (val, G_TYPE_BOOLEAN);
+            g_value_set_boolean (val, kvp_value_get_boolean (kval));
+            break;
+        case KVP_TYPE_NUMERIC:
+            g_value_init (val, GNC_TYPE_NUMERIC);
+            num = kvp_value_get_numeric (kval);
+            g_value_set_boxed (val, &num);
+            break;
+        case KVP_TYPE_STRING:
+            g_value_init (val, G_TYPE_STRING);
+            g_value_set_string (val, kvp_value_get_string (kval));
+            break;
+        case KVP_TYPE_GUID:
+            g_value_init (val, GNC_TYPE_GUID);
+            g_value_set_boxed (val, kvp_value_get_guid (kval));
+            break;
+        case KVP_TYPE_TIMESPEC:
+            g_value_init (val, GNC_TYPE_TIMESPEC);
+            tm = kvp_value_get_timespec (kval);
+            g_value_set_boxed (val, &tm);
+            break;
+        case KVP_TYPE_GDATE:
+            g_value_init (val, G_TYPE_DATE);
+            gdate = kvp_value_get_gdate (kval);
+            g_value_set_boxed (val, &gdate);
+            break;
+        case KVP_TYPE_GLIST:
+        {
+            GList *gvalue_list = NULL;
+            GList *kvp_list = kvp_value_get_glist (kval);
+            g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value, &gvalue_list);
+            g_value_init (val, GNC_TYPE_VALUE_LIST);
+            gvalue_list = g_list_reverse (gvalue_list);
+            g_value_set_boxed (val, gvalue_list);
+            break;
+        }
 /* No transfer of KVP frames outside of QofInstance-derived classes! */
-	case KVP_TYPE_FRAME:
-	    PWARN ("Error! Attempt to transfer KvpFrame!");
-	default:
-	    PWARN ("Error! Invalid KVP Transfer Request!");
-	    g_slice_free (GValue, val);
-	    val = NULL;
-	    break;
+        case KVP_TYPE_FRAME:
+            PWARN ("Error! Attempt to transfer KvpFrame!");
+        default:
+            PWARN ("Error! Invalid KVP Transfer Request!");
+            g_slice_free (GValue, val);
+            val = NULL;
+            break;
     }
     return val;
 }
@@ -1270,36 +1290,41 @@ KvpValue*
 kvp_value_from_gvalue (const GValue *gval)
 {
     KvpValue *val = NULL;
-    GType type = G_VALUE_TYPE (gval);
+    GType type;
+    if (gval == NULL)
+        return NULL;
+    type = G_VALUE_TYPE (gval);
     g_return_val_if_fail (G_VALUE_TYPE (gval), NULL);
 
     if (type == G_TYPE_INT64)
-	val = kvp_value_new_gint64 (g_value_get_int64 (gval));
+        val = kvp_value_new_gint64 (g_value_get_int64 (gval));
     else if (type == G_TYPE_DOUBLE)
-	val = kvp_value_new_double (g_value_get_double (gval));
+        val = kvp_value_new_double (g_value_get_double (gval));
+    else if (type == G_TYPE_BOOLEAN)
+        val = kvp_value_new_boolean (g_value_get_boolean (gval));
     else if (type == GNC_TYPE_NUMERIC)
-	val = kvp_value_new_numeric (*(gnc_numeric*)g_value_get_boxed (gval));
+        val = kvp_value_new_numeric (*(gnc_numeric*)g_value_get_boxed (gval));
     else if (type == G_TYPE_STRING)
-	val = kvp_value_new_string (g_value_get_string (gval));
+        val = kvp_value_new_string (g_value_get_string (gval));
     else if (type == GNC_TYPE_GUID)
-	val = kvp_value_new_guid ((GncGUID*)g_value_get_boxed (gval));
+        val = kvp_value_new_guid ((GncGUID*)g_value_get_boxed (gval));
     else if (type == GNC_TYPE_TIMESPEC)
-	val = kvp_value_new_timespec (*(Timespec*)g_value_get_boxed (gval));
+        val = kvp_value_new_timespec (*(Timespec*)g_value_get_boxed (gval));
     else if (type == G_TYPE_DATE)
-	val = kvp_value_new_gdate (*(GDate*)g_value_get_boxed (gval));
+        val = kvp_value_new_gdate (*(GDate*)g_value_get_boxed (gval));
     else if (type == GNC_TYPE_VALUE_LIST)
     {
-	GList *gvalue_list = (GList*)g_value_get_boxed (gval);
-	GList *kvp_list = NULL;
-	g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue, &kvp_list);
-	kvp_list = g_list_reverse (kvp_list);
-	val = kvp_value_new_glist_nc (kvp_list);
-//	g_list_free_full (gvalue_list, (GDestroyNotify)g_value_unset);
-//	gvalue_list = NULL;
+        GList *gvalue_list = (GList*)g_value_get_boxed (gval);
+        GList *kvp_list = NULL;
+        g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue, &kvp_list);
+        kvp_list = g_list_reverse (kvp_list);
+        val = kvp_value_new_glist_nc (kvp_list);
+//      g_list_free_full (gvalue_list, (GDestroyNotify)g_value_unset);
+//      gvalue_list = NULL;
     }
     else
-	PWARN ("Error! Don't know how to make a KvpValue from a %s",
-	       G_VALUE_TYPE_NAME (gval));
+        PWARN ("Error! Don't know how to make a KvpValue from a %s",
+               G_VALUE_TYPE_NAME (gval));
 
     return val;
 }
@@ -1315,7 +1340,7 @@ kvp_frame_get_gvalue (KvpFrame *frame, const gchar *key)
 void
 kvp_frame_set_gvalue (KvpFrame *frame, const gchar *key, const GValue *value)
 {
-  kvp_frame_set_value_nc (frame, key, kvp_value_from_gvalue (value));
+    kvp_frame_set_value_nc (frame, key, kvp_value_from_gvalue (value));
 }
 
 static void
@@ -1356,9 +1381,9 @@ gnc_value_list_get_type (void)
     static GType type = 0;
     if (type == 0)
     {
-	type = g_boxed_type_register_static ("gnc_value_list",
-					     (GBoxedCopyFunc)gnc_value_list_copy,
-					     (GBoxedFreeFunc)gnc_value_list_free);
+        type = g_boxed_type_register_static ("gnc_value_list",
+                                             (GBoxedCopyFunc)gnc_value_list_copy,
+                                             (GBoxedFreeFunc)gnc_value_list_free);
     }
     return type;
 }
diff --git a/src/libqof/qof/kvp_frame.h b/src/libqof/qof/kvp_frame.h
index 724ff63..136006e 100644
--- a/src/libqof/qof/kvp_frame.h
+++ b/src/libqof/qof/kvp_frame.h
@@ -95,14 +95,15 @@ typedef enum
     KVP_TYPE_INVALID = -1,
     KVP_TYPE_GINT64 = 1, /**< QOF_TYPE_INT64  gint64 */
     KVP_TYPE_DOUBLE,     /**< QOF_TYPE_DOUBLE  gdouble */
+    KVP_TYPE_BOOLEAN,    /**< QOF_TYPE_BOOLEAN gboolean */
     KVP_TYPE_NUMERIC,    /**< QOF_TYPE_NUMERIC */
     KVP_TYPE_STRING,     /**< QOF_TYPE_STRING gchar* */
     KVP_TYPE_GUID,       /**< QOF_TYPE_GUID */
     KVP_TYPE_TIMESPEC,   /**< QOF_TYPE_DATE */
     KVP_TYPE_PLACEHOLDER_DONT_USE, /* Replaces KVP_TYPE_BINARY */
     KVP_TYPE_GLIST,      /**< no QOF equivalent. */
-    KVP_TYPE_FRAME       /**< no QOF equivalent. */
-    , KVP_TYPE_GDATE       /**< no QOF equivalent. */
+    KVP_TYPE_FRAME,       /**< no QOF equivalent. */
+    KVP_TYPE_GDATE       /**< no QOF equivalent. */
 } KvpValueType;
 
 /** \deprecated Deprecated backwards compat token



Summary of changes:
 ...acintegration-gtk2-include-directory-back.patch |   41 +
 po/POTFILES.in                                     |   13 +-
 src/app-utils/app-utils.i                          |    1 -
 src/app-utils/app-utils.scm                        |    9 +-
 src/app-utils/business-helpers.c                   |    2 +-
 src/app-utils/business-options.scm                 |   54 +-
 src/app-utils/gnc-accounting-period.c              |    1 -
 src/app-utils/gnc-sx-instance-model.c              |    4 -
 src/app-utils/option-util.c                        |  110 +-
 src/app-utils/option-util.h                        |    5 +-
 src/app-utils/options.scm                          |  203 ++-
 src/app-utils/test/Makefile.am                     |    9 +-
 .../{test-option-util.c => test-option-util.cpp}   |   56 +-
 ...-parse-amount.c => test-print-parse-amount.cpp} |   14 +-
 src/app-utils/test/test-scm-query-string.c         |    3 -
 src/backend/dbi/gnc-backend-dbi.c                  |    2 -
 src/backend/dbi/test/Makefile.am                   |    4 +-
 ...kend-dbi-basic.c => test-backend-dbi-basic.cpp} |   65 +-
 .../test/{test-dbi-stuff.c => test-dbi-stuff.cpp}  |   39 +-
 src/backend/dbi/test/test-dbi-stuff.h              |    9 +-
 src/backend/sql/CMakeLists.txt                     |    2 +-
 src/backend/sql/Makefile.am                        |    2 +-
 src/backend/sql/gnc-account-sql.c                  |    2 +-
 src/backend/sql/gnc-backend-sql.c                  |   24 +-
 src/backend/sql/gnc-budget-sql.c                   |    2 +-
 src/backend/sql/gnc-commodity-sql.c                |    2 +-
 src/backend/sql/gnc-employee-sql.c                 |    2 +-
 src/backend/sql/gnc-invoice-sql.c                  |    2 +-
 src/backend/sql/gnc-schedxaction-sql.c             |    2 +-
 .../sql/{gnc-slots-sql.c => gnc-slots-sql.cpp}     |  153 +-
 src/backend/sql/gnc-slots-sql.h                    |   12 +-
 src/backend/sql/gnc-tax-table-sql.c                |    2 +-
 src/backend/sql/gnc-transaction-sql.c              |    7 +-
 src/backend/sql/gnc-vendor-sql.c                   |    2 +-
 src/backend/sql/test/utest-gnc-backend-sql.c       |    2 +-
 src/backend/xml/CMakeLists.txt                     |    4 +-
 src/backend/xml/Makefile.am                        |    6 +-
 src/backend/xml/gnc-account-xml-v2.c               |   21 +-
 src/backend/xml/gnc-address-xml-v2.c               |   21 +-
 src/backend/xml/gnc-backend-xml.c                  |    2 -
 src/backend/xml/gnc-bill-term-xml-v2.c             |   12 +-
 src/backend/xml/gnc-book-xml-v2.c                  |   34 +-
 src/backend/xml/gnc-budget-xml-v2.c                |   15 +-
 src/backend/xml/gnc-commodity-xml-v2.c             |   14 +-
 src/backend/xml/gnc-customer-xml-v2.c              |   11 +-
 src/backend/xml/gnc-employee-xml-v2.c              |   12 +-
 src/backend/xml/gnc-entry-xml-v2.c                 |   20 +-
 src/backend/xml/gnc-invoice-xml-v2.c               |   21 +-
 src/backend/xml/gnc-job-xml-v2.c                   |   19 +-
 src/backend/xml/gnc-lot-xml-v2.c                   |   19 +-
 src/backend/xml/gnc-order-xml-v2.c                 |   19 +-
 src/backend/xml/gnc-schedxaction-xml-v2.c          |   16 +-
 src/backend/xml/gnc-tax-table-xml-v2.c             |   20 +-
 src/backend/xml/gnc-transaction-xml-v2.c           |   32 +-
 src/backend/xml/gnc-vendor-xml-v2.c                |   12 +-
 .../xml/{io-gncxml-v1.c => io-gncxml-v1.cpp}       |   78 +-
 src/backend/xml/io-gncxml.h                        |    7 +
 ...p-dom-generators.c => sixtp-dom-generators.cpp} |  122 +-
 src/backend/xml/sixtp-dom-generators.h             |   10 +-
 .../{sixtp-dom-parsers.c => sixtp-dom-parsers.cpp} |   89 +-
 src/backend/xml/sixtp-dom-parsers.h                |   24 +-
 src/backend/xml/test/Makefile.am                   |   44 +-
 .../{test-file-stuff.c => test-file-stuff.cpp}     |   22 +-
 src/backend/xml/test/test-file-stuff.h             |   21 +-
 src/backend/xml/test/test-kvp-frames.c             |  227 ---
 src/backend/xml/test/test-kvp-frames.cpp           |  196 +++
 src/core-utils/gnc-features.c                      |    2 +-
 src/doc/books.txt                                  |    5 -
 src/doc/doxygen.cfg.in                             |   24 +-
 src/engine/Account.c                               |  977 ++++++-----
 src/engine/Makefile.am                             |    2 +-
 src/engine/Query.c                                 |   26 -
 src/engine/Query.h                                 |    4 -
 src/engine/SX-ttinfo.c                             |    2 -
 src/engine/SchedXaction.h                          |    2 -
 src/engine/Scrub.c                                 |   34 +-
 src/engine/Scrub2.c                                |   38 +-
 src/engine/Split.c                                 | 1000 ++++++------
 src/engine/Split.h                                 |   27 +-
 src/engine/Transaction.c                           |  407 +++--
 src/engine/TransactionP.h                          |    7 -
 src/engine/cap-gains.c                             |   12 +-
 src/engine/engine-helpers.c                        |  414 +----
 src/engine/engine.i                                |   19 +-
 src/engine/gnc-budget.c                            |  109 +-
 src/engine/gnc-commodity.c                         |   44 +-
 src/engine/gnc-lot.c                               |  110 +-
 src/engine/gnc-pricedb.c                           |   62 +-
 src/engine/gncAddress.c                            |    2 +-
 src/engine/gncEntry.c                              |    5 +-
 src/engine/gncInvoice.c                            |   17 +-
 src/engine/gncJob.c                                |   60 +-
 src/engine/gncTaxTable.c                           |    5 +-
 src/engine/{kvp-scm.c => kvp-scm.cpp}              |   88 +-
 src/engine/kvp-scm.h                               |   10 +-
 src/engine/kvp_doc.txt                             |   40 +-
 src/engine/test-core/Makefile.am                   |    2 +-
 .../{test-engine-stuff.c => test-engine-stuff.cpp} |  273 ++--
 src/engine/test-core/test-engine-stuff.h           |   14 +-
 src/engine/test/Makefile.am                        |   33 +-
 src/engine/test/gtest-import-map.cpp               |  270 ++++
 src/engine/test/{test-guid.c => test-guid.cpp}     |   10 +-
 src/engine/test/test-scm-query-import.scm          |   83 +-
 .../test/{utest-Account.c => utest-Account.cpp}    |  393 ++---
 src/engine/test/utest-Split.cpp                    |   36 +-
 .../{utest-Transaction.c => utest-Transaction.cpp} |  414 ++---
 src/gnome-utils/dialog-preferences.c               |    1 -
 src/gnome-utils/gnc-main-window.c                  |    4 +-
 src/gnome-utils/gnc-tree-view-owner.c              |   14 +-
 src/gnome-utils/gnome-utils.scm                    |   18 -
 src/gnome/assistant-hierarchy.c                    |    4 +-
 src/import-export/aqb/Makefile.am                  |    2 -
 src/import-export/aqb/dialog-ab-trans.c            |    2 +-
 src/import-export/aqb/gnc-ab-kvp.c                 |   41 -
 src/import-export/aqb/gnc-ab-kvp.h                 |   37 +-
 src/import-export/aqb/gnc-ab-trans-templ.c         |  287 ----
 src/import-export/aqb/gnc-ab-transfer.c            |   11 +-
 src/import-export/aqb/gnc-ab-utils.h               |    3 +-
 src/import-export/aqb/test/test-aqb.c              |    2 +-
 src/import-export/aqb/test/test-kvp.c              |   32 +-
 src/import-export/import-account-matcher.c         |    2 +-
 src/import-export/import-account-matcher.h         |    8 +-
 src/import-export/import-backend.c                 |    2 +-
 src/import-export/import-utilities.h               |    6 +-
 src/libqof/CMakeLists.txt                          |    3 -
 src/libqof/qof/Makefile.am                         |    6 +-
 src/libqof/qof/gnc-aqbanking-templates.cpp         |  302 ++++
 .../qof/gnc-aqbanking-templates.h}                 |   48 +-
 src/libqof/qof/gnc-int128.hpp                      |    4 +
 src/libqof/qof/kvp-util-p.h                        |  115 --
 src/libqof/qof/kvp-util.cpp                        |  244 ---
 src/libqof/qof/kvp-util.h                          |   72 -
 src/libqof/qof/kvp-value.cpp                       |  105 +-
 src/libqof/qof/kvp-value.hpp                       |   54 +-
 src/libqof/qof/kvp_frame.cpp                       | 1313 +++------------
 src/libqof/qof/kvp_frame.h                         |  640 --------
 src/libqof/qof/kvp_frame.hpp                       |  168 +-
 src/libqof/qof/qof.h                               |    3 -
 src/libqof/qof/qofbackend-p.h                      |    4 -
 src/libqof/qof/qofbackend.cpp                      |    4 -
 src/libqof/qof/qofbook-p.h                         |    2 -
 src/libqof/qof/qofbook.cpp                         |  117 +-
 src/libqof/qof/qofbook.h                           |   53 +-
 src/libqof/qof/qofinstance-p.h                     |   50 +-
 src/libqof/qof/qofinstance.cpp                     |  256 ++-
 src/libqof/qof/qofinstance.h                       |    9 +-
 src/libqof/qof/qofquery.cpp                        |   13 -
 src/libqof/qof/qofquerycore.cpp                    |  153 --
 src/libqof/qof/qofquerycore.h                      |   17 +-
 src/libqof/qof/test/Makefile.am                    |    5 +-
 src/libqof/qof/test/test-kvp-frame.cpp             |  166 +-
 src/libqof/qof/test/test-kvp-value.cpp             |    2 +-
 src/libqof/qof/test/test-kvp_frame.c               | 1702 --------------------
 src/libqof/qof/test/test-qof.c                     |    2 -
 .../{test-qofinstance.c => test-qofinstance.cpp}   |   80 +-
 .../ledger-core/split-register-model-save.c        |    1 -
 src/register/ledger-core/split-register-model.c    |   65 +-
 src/report/business-reports/balsheet-eg.scm        |    6 -
 src/report/business-reports/customer-summary.scm   |    9 +-
 src/report/business-reports/easy-invoice.scm       |   15 +-
 src/report/business-reports/fancy-invoice.scm      |   43 +-
 src/report/business-reports/invoice.scm            |    9 +-
 src/report/business-reports/job-report.scm         |    9 +-
 src/report/business-reports/owner-report.scm       |    9 +-
 src/report/business-reports/receipt.eguile.scm     |   17 +-
 src/report/business-reports/receipt.scm            |    6 -
 src/report/business-reports/taxinvoice.eguile.scm  |   17 +-
 src/report/business-reports/taxinvoice.scm         |    6 -
 src/report/locale-specific/us/taxtxf-de_DE.scm     |    7 +-
 src/test-core/test-stuff.h                         |   31 +-
 src/test-core/unittest-support.c                   |    5 +-
 src/test-core/unittest-support.h                   |   10 +-
 172 files changed, 4919 insertions(+), 8648 deletions(-)
 create mode 100644 0001-Change-gtkmacintegration-gtk2-include-directory-back.patch
 rename src/app-utils/test/{test-option-util.c => test-option-util.cpp} (79%)
 rename src/app-utils/test/{test-print-parse-amount.c => test-print-parse-amount.cpp} (91%)
 rename src/backend/dbi/test/{test-backend-dbi-basic.c => test-backend-dbi-basic.cpp} (91%)
 rename src/backend/dbi/test/{test-dbi-stuff.c => test-dbi-stuff.cpp} (90%)
 rename src/backend/sql/{gnc-slots-sql.c => gnc-slots-sql.cpp} (87%)
 rename src/backend/xml/{io-gncxml-v1.c => io-gncxml-v1.cpp} (98%)
 rename src/backend/xml/{sixtp-dom-generators.c => sixtp-dom-generators.cpp} (78%)
 rename src/backend/xml/{sixtp-dom-parsers.c => sixtp-dom-parsers.cpp} (94%)
 rename src/backend/xml/test/{test-file-stuff.c => test-file-stuff.cpp} (96%)
 delete mode 100644 src/backend/xml/test/test-kvp-frames.c
 create mode 100644 src/backend/xml/test/test-kvp-frames.cpp
 rename src/engine/{kvp-scm.c => kvp-scm.cpp} (50%)
 rename src/engine/test-core/{test-engine-stuff.c => test-engine-stuff.cpp} (88%)
 create mode 100644 src/engine/test/gtest-import-map.cpp
 rename src/engine/test/{test-guid.c => test-guid.cpp} (91%)
 rename src/engine/test/{utest-Account.c => utest-Account.cpp} (89%)
 rename src/engine/test/{utest-Transaction.c => utest-Transaction.cpp} (85%)
 delete mode 100644 src/import-export/aqb/gnc-ab-trans-templ.c
 create mode 100644 src/libqof/qof/gnc-aqbanking-templates.cpp
 rename src/{import-export/aqb/gnc-ab-trans-templ.h => libqof/qof/gnc-aqbanking-templates.h} (86%)
 delete mode 100644 src/libqof/qof/kvp-util-p.h
 delete mode 100644 src/libqof/qof/kvp-util.cpp
 delete mode 100644 src/libqof/qof/kvp-util.h
 delete mode 100644 src/libqof/qof/kvp_frame.h
 delete mode 100644 src/libqof/qof/test/test-kvp_frame.c
 rename src/libqof/qof/test/{test-qofinstance.c => test-qofinstance.cpp} (93%)



More information about the gnucash-changes mailing list