コード例 #1
0
static void
gnc_plugin_business_cmd_export_employee (GtkAction *action, GncMainWindowActionData *mw)
{
    QofSession *current_session, *chart_session;
    QofBook *book;
    QofCollection *coll;
    gchar *filename;
    gboolean success;

    current_session = gnc_get_current_session();
    book = qof_session_get_book(current_session);
    chart_session = qof_session_new();
    success = FALSE;
    filename = gnc_file_dialog(_("Export Employees to XML"), NULL,
                               NULL, GNC_FILE_DIALOG_EXPORT);
    if (filename)
    {
        gchar* url = g_strdup_printf( "qsf:%s", filename );
        qof_session_begin(chart_session, url, TRUE, TRUE);
        coll = qof_book_get_collection(book, GNC_ID_EMPLOYEE);
        success = qof_instance_copy_coll_r(chart_session, coll);
        if (success)
        {
            qof_session_save(chart_session, NULL);
        }
        g_free(url);
    }
    show_session_error(qof_session_get_error(chart_session), filename,
                       GNC_FILE_DIALOG_EXPORT);
    qof_session_end(chart_session);
    g_free(filename);
    gnc_set_current_session(current_session);
}
コード例 #2
0
void
qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
                    QofInstanceForeachCB cb, void * user_data)
{
    QofCollection *col;
    const QofObject *obj;

    if (!book || !type_name)
    {
        return;
    }
    PINFO ("type=%s", type_name);

    obj = qof_object_lookup (type_name);
    if (!obj)
    {
        PERR ("No object of type %s", type_name);
        return;
    }
    col = qof_book_get_collection (book, obj->e_type);
    if (!obj)
    {
        return;
    }
    if (obj->foreach)
    {
        obj->foreach (col, cb, user_data);
    }
    return;
}
コード例 #3
0
ファイル: test-qofobject.c プロジェクト: Bob-IT/gnucash
static void
test_qof_object_foreach( Fixture *fixture, gconstpointer pData )
{
    gint user_data;
    QofBook *book = NULL;
    QofCollection *col = NULL;

    /* setup */
    book = qof_book_new();
    g_assert( book );
    g_assert_cmpint( g_list_length( get_object_modules() ), == , 0 );
    qof_object_register( fixture->qofobject );
    g_assert_cmpint( g_list_length( get_object_modules() ), == , 1 );
    col = qof_book_get_collection( book, fixture->qofobject->e_type ); /* make col already exist */
    g_assert( col );

    g_test_message( "Test foreach and data" );
    foreach_cb_struct.user_data = ( gpointer ) &user_data;
    foreach_cb_struct.is_called = FALSE;
    foreach_cb_struct.col = col;
    foreach_cb_struct.cb = mock_instance_foreach_cb;
    fixture->qofobject->foreach = mock_foreach;
    qof_object_foreach( fixture->qofobject->e_type, book, mock_instance_foreach_cb, ( gpointer ) &user_data );
    g_assert( foreach_cb_struct.is_called == TRUE );

    qof_book_destroy( book );
}
コード例 #4
0
ファイル: qofsession.c プロジェクト: kleopatra999/gnucash-2
gboolean qof_instance_copy_one_r(QofSession *new_session, QofInstance *ent)
{
    struct recurse_s store;
    QofCollection *coll;
    gboolean success;

    if ((!new_session) || (!ent))
    {
        return FALSE;
    }
    store.session = new_session;
    success = TRUE;
    store.success = success;
    store.ref_list = qof_class_get_referenceList(ent->e_type);
    success = qof_instance_copy_to_session(new_session, ent);
    if (success == TRUE)
    {
        coll = qof_book_get_collection(qof_session_get_book(new_session), ent->e_type);
        if (coll)
        {
            qof_collection_foreach(coll, recurse_ent_cb, &store);
        }
    }
    return success;
}
コード例 #5
0
ファイル: test-guid.cpp プロジェクト: Bob-IT/gnucash
static void
run_test (void)
{
    int i;
    QofSession *sess;
    QofBook *book;
    QofInstance *ent;
    QofCollection *col;
    QofIdType type;
    GncGUID guid;

    sess = get_random_session ();
    book = qof_session_get_book (sess);
    do_test ((NULL != book), "book not created");

    col = qof_book_get_collection (book, "asdf");
    type = qof_collection_get_type (col);

    for (i = 0; i < NENT; i++)
    {
        ent = static_cast<QofInstance*>(g_object_new(QOF_TYPE_INSTANCE, NULL));
        guid_replace(&guid);
        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;
        qof_collection_insert_entity (col, ent);
        do_test ((NULL != qof_collection_lookup_entity (col, &guid)),
                 "guid not found");
    }

    /* Make valgrind happy -- destroy the session. */
    qof_session_destroy(sess);
}
コード例 #6
0
ファイル: SX-book.c プロジェクト: Mechtilde/gnucash
SchedXactions*
gnc_book_get_schedxactions(QofBook *book)
{
    QofCollection *col;
    col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
    return gnc_collection_get_schedxactions(col);
}
コード例 #7
0
ファイル: SX-book.c プロジェクト: Mechtilde/gnucash
Account *
gnc_book_get_template_root( const QofBook *book )
{
    QofCollection *col;
    if (!book) return NULL;
    col = qof_book_get_collection (book, GNC_ID_SXTG);
    return gnc_collection_get_template_root (col);
}
コード例 #8
0
ファイル: SchedXaction.c プロジェクト: goodvibes2/gnucash
/**
 * Destroys all SXes in the book because the book is being destroyed.
 *
 * @param book Book being destroyed
 */
static void
gnc_sx_book_end(QofBook* book)
{
    QofCollection *col;

    col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
    qof_collection_foreach(col, destroy_sx_on_book_close, NULL);
}
コード例 #9
0
ファイル: gncEntry.c プロジェクト: kleopatra999/gnucash-2
/** Handles book end - frees all entries from the book
 *
 * @param book Book being closed
 */
static void
gnc_entry_book_end(QofBook* book)
{
    QofCollection *col;

    col = qof_book_get_collection(book, GNC_ID_ENTRY);
    qof_collection_foreach(col, destroy_entry_on_book_close, NULL);
}
コード例 #10
0
ファイル: gncEmployee.c プロジェクト: nishmu/gnucash
/** Handles book end - frees all employees from the book
 *
 * @param book Book being closed
 */
static void
gnc_employee_book_end(QofBook* book)
{
    QofCollection *col;

    col = qof_book_get_collection(book, GNC_ID_EMPLOYEE);
    qof_collection_foreach(col, destroy_employee_on_book_close, NULL);
}
コード例 #11
0
ファイル: gnc-lots-sql.cpp プロジェクト: tmertens/gnucash
bool
GncSqlLotsBackend::write (GncSqlBackend* be)
{
    g_return_val_if_fail (be != NULL, FALSE);
    write_objects_t data{be, true, this};

    qof_collection_foreach (qof_book_get_collection (be->book(), GNC_ID_LOT),
                            (QofInstanceForeachCB)do_save_lot, &data);
    return data.is_ok;
}
コード例 #12
0
static gboolean
write_lots( GncSqlBackend* be )
{
    write_objects_t data;

    g_return_val_if_fail( be != NULL, FALSE );

    data.be = be;
    data.is_ok = TRUE;
    qof_collection_foreach( qof_book_get_collection( be->book, GNC_ID_LOT ),
                            (QofInstanceForeachCB)do_save_lot, &data );
    return data.is_ok;
}
コード例 #13
0
ファイル: qofgobj.c プロジェクト: nizarklai/gnucash-1
void
qof_gobject_register_instance (QofBook *book, QofType type, GObject *gob)
{
    QofCollection *coll;
    GSList *instance_list;

    if (!book || !type) return;

    coll = qof_book_get_collection (book, type);

    instance_list = qof_collection_get_data (coll);
    instance_list = g_slist_prepend (instance_list, gob);
    qof_collection_set_data (coll, instance_list);
}
コード例 #14
0
ファイル: SX-book.c プロジェクト: Mechtilde/gnucash
static void
book_sxes_setup(QofBook *book)
{
    QofCollection *col;
    SchedXactions *sxes;

    col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
    sxes = g_object_new (GNC_TYPE_SCHEDXACTIONS, NULL);
    g_assert(sxes);
    qof_instance_init_data(&sxes->inst, GNC_ID_SXES, book);
    sxes->sx_list = NULL;
    sxes->sx_notsaved = TRUE;
    qof_collection_set_data(col, sxes);
}
コード例 #15
0
ファイル: test-dbi-stuff.c プロジェクト: nishmu/gnucash
void
do_compare( QofBook* book_1, QofBook* book_2, const gchar* id, QofInstanceForeachCB cb, const gchar* msg )
{
    QofCollection* coll;
    CompareInfoStruct info;

    coll = qof_book_get_collection( book_1, id );
    info.book_1 = book_1;
    info.book_2 = book_2;
    info.result = TRUE;
    qof_collection_foreach(coll, cb, &info);

    do_test( info.result, msg );
}
コード例 #16
0
ファイル: SX-book.c プロジェクト: Mechtilde/gnucash
static void
book_sxes_end(QofBook* book)
{
    QofCollection *col;
    SchedXactions *sxes;

    col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
    sxes = qof_collection_get_data(col);
    if (sxes != NULL)
    {
        g_object_unref(sxes);
        qof_collection_set_data(col, NULL);
    }
}
コード例 #17
0
ファイル: gnc-budget-sql.cpp プロジェクト: Bob-IT/gnucash
bool
GncSqlBudgetBackend::write (GncSqlBackend* sql_be)
{
    write_objects_t data;

    g_return_val_if_fail (sql_be != NULL, FALSE);

    data.be = sql_be;
    data.is_ok = TRUE;
    data.obe = this;
    qof_collection_foreach (qof_book_get_collection (sql_be->book(), GNC_ID_BUDGET),
                            (QofInstanceForeachCB)do_save, &data);

    return data.is_ok;
}
コード例 #18
0
/* CAS: Even though it works, something feels not-quite-right with
 * this design.  The idea here is to _not_ provide yet another
 * implementation of GtkTreeModel, this time for budgets.  Instead,
 * right now, we're using the already implemented GtkListStore.  This
 * has a couple consequences: 1) We allocate a new store upon every
 * call, so the memory is owned by caller.  2) The model won't reflect
 * later updates to the book, so the model shouldn't be expected to
 * track asynchronous changes.
 *
 * If, for some reason, I decide I can't live with or remove those
 * consequences, I still think there must be some better way than
 * re-implementing GtkTreeModel.  One idea I'm toying with is to
 * implement a GtkTreeModel for QofCollections, which would offer only
 * the GncGUID as a field.  Then, TreeViews could add their own columns
 * with custom CellDataFuncs to display the object-specific fields.
 * Or, something like that.  :)
 *
 */
GtkTreeModel *
gnc_tree_model_budget_new(QofBook *book)
{
    GtkListStore* store;

    store = gtk_list_store_new (BUDGET_LIST_NUM_COLS,
                                G_TYPE_POINTER,
                                G_TYPE_STRING,
                                G_TYPE_STRING);

    qof_collection_foreach(qof_book_get_collection(book, GNC_ID_BUDGET),
                           add_budget_to_model, GTK_TREE_MODEL(store));

    return GTK_TREE_MODEL(store);
}
コード例 #19
0
ファイル: SX-book.c プロジェクト: Mechtilde/gnucash
void
gnc_book_set_template_root (QofBook *book, Account *templateRoot)
{
    QofCollection *col;
    if (!book) return;

    if (templateRoot && gnc_account_get_book(templateRoot) != book)
    {
        g_critical("cannot mix and match books freely!");
        return;
    }

    col = qof_book_get_collection (book, GNC_ID_SXTG);
    gnc_collection_set_template_root (col, templateRoot);
}
コード例 #20
0
ファイル: test-recursive.c プロジェクト: nizarklai/gnucash-1
static void
test_recursion (QofSession *original, guint counter)
{
    QofSession *copy;
    QofCollection *grand_coll;
    struct tally c;
    QofBook *book;
    guint d, e, f;

    c.nulls = 0;
    c.total = 0;
    c.collect = 0;
    c.book = NULL;
    book = qof_session_get_book(original);
    grand_coll = qof_book_get_collection(book, GRAND_MODULE_NAME);
    copy = qof_session_new();
    if (debug)
    {
        /*         FIXME XML backend can't handle STDOUT
         *         qof_session_begin(copy, QOF_STDOUT, TRUE, FALSE); */
    }
    /* TODO: implement QOF_TYPE_CHOICE testing. */
    qof_instance_copy_coll_r(copy, grand_coll);
    /* test the original */
    qof_object_foreach(GRAND_MODULE_NAME, book, check_cb, &c);
    book = qof_session_get_book(copy);
    /* test the copy */
    d = c.nulls;
    e = c.total;
    f = c.collect;
    c.nulls = 0;
    c.total = 0;
    c.collect = 0;
    c.book = book;
    qof_object_foreach(GRAND_MODULE_NAME, book, check_cb, &c);
    do_test((d == c.nulls), "Null parents do not match");
    do_test((e == c.total), "Total parents do not match");
    do_test((f == c.collect), "Number of children in descendents does not match");
    if (counter == 4 && debug == TRUE)
    {
        /*      FIXME XML backend can't handle STDOUT
         *      qof_session_save(copy, NULL);
                qof_session_save(original, NULL); */
    }
    qof_session_end(copy);
    copy = NULL;
}
コード例 #21
0
void
qof_object_mark_clean (QofBook *book)
{
    GList *l;

    if (!book) return;
    for (l = object_modules; l; l = l->next)
    {
        QofObject *obj = l->data;
        if (obj->mark_clean)
        {
            QofCollection *col;
            col = qof_book_get_collection (book, obj->e_type);
            (obj->mark_clean) (col);
        }
    }
}
コード例 #22
0
bool
qof_object_is_dirty (const QofBook *book)
{
    GList *l;

    if (!book) return false;
    for (l = object_modules; l; l = l->next)
    {
        QofObject *obj = l->data;
        if (obj->is_dirty)
        {
            QofCollection *col;
            col = qof_book_get_collection (book, obj->e_type);
            if (obj->is_dirty (col)) return true;
        }
    }
    return false;
}
コード例 #23
0
ファイル: qofinstance.c プロジェクト: kleopatra999/gnucash-2
void
qof_instance_init_data (QofInstance *inst, QofIdType type, QofBook *book)
{
    QofInstancePrivate *priv;
    QofCollection *col;
    QofIdType col_type;

    g_return_if_fail(QOF_IS_INSTANCE(inst));
    priv = GET_PRIVATE(inst);
    g_return_if_fail(!priv->book);

    priv->book = book;
    col = qof_book_get_collection (book, type);
    g_return_if_fail(col != NULL);

    /* XXX We passed redundant info to this routine ... but I think that's
     * OK, it might eliminate programming errors. */

    col_type = qof_collection_get_type(col);
    if (safe_strcmp(col_type, type))
    {
        PERR ("attempt to insert \"%s\" into \"%s\"", type, col_type);
        return;
    }
    priv = GET_PRIVATE(inst);
    inst->e_type = CACHE_INSERT (type);

    do
    {
        guid_new(&priv->guid);

        if (NULL == qof_collection_lookup_entity (col, &priv->guid))
            break;

        PWARN("duplicate id created, trying again");
    }
    while (1);

    priv->collection = col;

    qof_collection_insert_entity (col, inst);
}
コード例 #24
0
ファイル: qofsession.c プロジェクト: kleopatra999/gnucash-2
static void
qof_instance_coll_foreach(QofInstance *original, gpointer user_data)
{
    QofInstanceCopyData *qecd;
    const GncGUID *g;
    QofBook *targetBook;
    QofCollection *coll;
    QofInstance *copy;

    g_return_if_fail(original != NULL);
    g_return_if_fail(user_data != NULL);
    copy = NULL;
    qecd = (QofInstanceCopyData*)user_data;
    targetBook = qof_session_get_book(qecd->new_session);
    g = qof_instance_get_guid(original);
    coll = qof_book_get_collection(targetBook, original->e_type);
    copy = qof_collection_lookup_entity(coll, g);
    if (copy)
    {
        qecd->error = TRUE;
    }
}
コード例 #25
0
ファイル: qofsession.c プロジェクト: kleopatra999/gnucash-2
static gboolean
qof_instance_guid_match(QofSession *new_session, QofInstance *original)
{
    QofInstance *copy;
    const GncGUID *g;
    QofIdTypeConst type;
    QofBook *targetBook;
    QofCollection *coll;

    copy = NULL;
    g_return_val_if_fail(original != NULL, FALSE);
    targetBook = qof_session_get_book(new_session);
    g_return_val_if_fail(targetBook != NULL, FALSE);
    g = qof_instance_get_guid(original);
    type = g_strdup(original->e_type);
    coll = qof_book_get_collection(targetBook, type);
    copy = qof_collection_lookup_entity(coll, g);
    if (copy)
    {
        return TRUE;
    }
    return FALSE;
}
コード例 #26
0
ファイル: top-level.c プロジェクト: nizarklai/gnucash-1
static gboolean
validate_type(const char *url_type, const char *location,
              const char *entity_type, GNCURLResult *result,
              GncGUID *guid, QofInstance **entity)
{
    QofCollection *col;
    QofBook     * book = gnc_get_current_book();
    if (!string_to_guid (location + strlen(url_type), guid))
    {
        result->error_message = g_strdup_printf (_("Bad URL: %s"), location);
        return FALSE;
    }
    col = qof_book_get_collection (book, entity_type);
    *entity = qof_collection_lookup_entity (col, guid);
    if (NULL == *entity)
    {
        result->error_message = g_strdup_printf (_("Entity Not Found: %s"),
                                location);
        return FALSE;
    }

    return TRUE;
}
コード例 #27
0
ファイル: test-qofobject.c プロジェクト: Bob-IT/gnucash
static void
test_qof_object_foreach_sorted( Fixture *fixture, gconstpointer pData )
{
    int i;
    gint32 list_length = g_test_rand_int_range( 0, 5 );
    gint user_data;
    QofBook *book = NULL;
    QofCollection *col = NULL;
    foreach_for_sorted_struct.instances = NULL;

    /* setup */
    book = qof_book_new();
    g_assert( book );
    g_assert_cmpint( g_list_length( get_object_modules() ), == , 0 );
    qof_object_register( fixture->qofobject );
    g_assert_cmpint( g_list_length( get_object_modules() ), == , 1 );

    fixture->qofobject->foreach = mock_foreach_for_sorted;
    /* init instances */
    col = qof_book_get_collection( book, fixture->qofobject->e_type );
    for (i = 0; i < list_length; i++ )
    {
        QofInstance * inst = g_object_new( QOF_TYPE_INSTANCE, NULL );
        g_assert( QOF_IS_INSTANCE( inst ) );
        foreach_for_sorted_struct.instances = g_list_append( foreach_for_sorted_struct.instances, inst );
        qof_collection_insert_entity( col, inst );
    }
    g_assert_cmpint( list_length, == , g_list_length( foreach_for_sorted_struct.instances ) );

    foreach_for_sorted_struct.call_count = 0;
    foreach_for_sorted_struct.user_data = &user_data;
    qof_object_foreach_sorted( fixture->qofobject->e_type, book, mock_instance_foreach_cb_for_sorted, ( gpointer ) &user_data );
    g_assert_cmpint( list_length, == , foreach_for_sorted_struct.call_count );

    qof_book_destroy( book );
    g_list_free( foreach_for_sorted_struct.instances );
}
コード例 #28
0
ファイル: qofinstance.c プロジェクト: kleopatra999/gnucash-2
QofInstance *
qof_instance_lookup_twin (const QofInstance *src, QofBook *target_book)
{
    QofCollection *col;
    KvpFrame *fr;
    GncGUID * twin_guid;
    QofInstance * twin;
    QofInstancePrivate *bpriv;

    if (!src || !target_book) return NULL;
    ENTER (" ");

    bpriv = GET_PRIVATE(QOF_INSTANCE(target_book));
    fr = gnc_kvp_bag_find_by_guid (src->kvp_data, "gemini",
                                   "book_guid", &bpriv->guid);

    twin_guid = kvp_frame_get_guid (fr, "inst_guid");

    col = qof_book_get_collection (target_book, src->e_type);
    twin = (QofInstance *) qof_collection_lookup_entity (col, twin_guid);

    LEAVE (" found twin=%p", twin);
    return twin;
}
コード例 #29
0
ファイル: test-recursive.c プロジェクト: nizarklai/gnucash-1
static void
create_data (QofSession *original, guint counter)
{
    QofCollection *coll;
    QofBook *start;
    mygrand *grand1;
    myparent *parent1;
    mychild *child1;

    start = qof_session_get_book(original);
    grand1 = (mygrand*)qof_object_new_instance(GRAND_MODULE_NAME, start);
    do_test ((NULL != &grand1->inst), "instance init");
    switch (counter)
    {
    case 0 :   /* NULL tree */
    {
        do_test((grand1 != NULL), "empty tree check");
        coll = qof_book_get_collection(start, GRAND_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Too many grandparents found - should be 1");
        coll = qof_book_get_collection(start, CHILD_MODULE_NAME);
        do_test((qof_collection_count(coll) == 0),
                "child found, should be empty");
        coll = qof_book_get_collection(start, PARENT_MODULE_NAME);
        do_test((qof_collection_count(coll) == 0),
                "tree not empty: parent found");
        break;
    }
    case 1 :   /* one parent, no child */
    {
        parent1 = (myparent*)qof_object_new_instance(PARENT_MODULE_NAME, start);
        grand_setChild(grand1, parent1);
        do_test((parent1 != NULL), "single parent check");
        do_test((grand_getChild(grand1) == parent1), "set child in grandparent");
        coll = qof_book_get_collection(start, GRAND_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of grandparents, should be 1");
        coll = qof_book_get_collection(start, CHILD_MODULE_NAME);
        do_test((qof_collection_count(coll) == 0),
                "Should be no child entities this iteration.");
        coll = qof_book_get_collection(start, PARENT_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of parents found, should be 1");
        break;
    }
    case 2 :   /* one parent, one child */
    {
        parent1 = (myparent*)qof_object_new_instance(PARENT_MODULE_NAME, start);
        grand_setChild(grand1, parent1);
        child1 = (mychild*)qof_object_new_instance(CHILD_MODULE_NAME, start);
        parent1 = grand_getChild(grand1);
        parent_setChild(parent1, child1);
        do_test((child1 != NULL), "one parent with one related child");
        do_test((child1 == parent_getChild(parent1)), "child of single parent");
        coll = qof_book_get_collection(start, GRAND_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of grandparents. Should be 1");
        coll = qof_book_get_collection(start, CHILD_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of child entities, should be 1");
        coll = qof_book_get_collection(start, PARENT_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of parents. Should be 1");
        break;
    }
    case 3 :   /* same grand, new parent, same child */
    {
        child1 = (mychild*)qof_object_new_instance(CHILD_MODULE_NAME, start);
        parent1 = (myparent*)qof_object_new_instance(PARENT_MODULE_NAME, start);
        grand_setChild(grand1, parent1);
        parent_setChild(parent1, child1);
        do_test((parent1 == grand_getChild(grand1)), "same grandparent, new parent");
        do_test((child1 == parent_getChild(parent1)), "new parent, same child");
        coll = qof_book_get_collection(start, GRAND_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of grandparents. Should be 1, Iteration 3.");
        coll = qof_book_get_collection(start, CHILD_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of child entities, should be 1. Iteration 3.");
        coll = qof_book_get_collection(start, PARENT_MODULE_NAME);
        do_test((qof_collection_count(coll) == 1),
                "Wrong number of parents. Should be 1. Iteration 3.");
        break;
    }
    case 4 :   /* new grand, unrelated parent, child unrelated to grand */
    {
        grand1 = (mygrand*)qof_object_new_instance(GRAND_MODULE_NAME, start);
        parent1 = (myparent*)qof_object_new_instance(PARENT_MODULE_NAME, start);
        child1 = (mychild*)qof_object_new_instance(CHILD_MODULE_NAME, start);
        parent_setChild(parent1, child1);
        do_test((NULL == grand_getChild(grand1)), "new grand, unrelated parent");
        do_test((child1 == parent_getChild(parent1)), "child unrelated to grand");
        coll = grand_getDescend(grand1);
        do_test((coll != NULL), "grandparent not valid");
        if (coll)
        {
            QofInstance *ent;

            ent = QOF_INSTANCE(child1);
            qof_collection_add_entity(coll, ent);
            grand_setDescend(grand1, coll);
            qof_collection_destroy(coll);
            do_test((g_list_length(grand1->descend) > 0), "entity not added");
            do_test((qof_collection_count(grand_getDescend(grand1)) > 0),
                    "empty collection returned");
        }
        break;
    }
    }
}