r18893 - gnucash/trunk/src/libqof/qof - Add some new gobject-related infrastructure so that when deleting an object, it can be determined if there are other objects with references to that object (bug 140400).

Phil Longstaff plongstaff at code.gnucash.org
Fri Mar 12 05:14:27 EST 2010


Author: plongstaff
Date: 2010-03-12 05:14:27 -0500 (Fri, 12 Mar 2010)
New Revision: 18893
Trac: http://svn.gnucash.org/trac/changeset/18893

Modified:
   gnucash/trunk/src/libqof/qof/qofinstance.c
   gnucash/trunk/src/libqof/qof/qofinstance.h
Log:
Add some new gobject-related infrastructure so that when deleting an object, it can be determined if there are other objects with references to that object (bug 140400).

Some routines are normal routines, and some routines use the gobject structure to allow different implementations by different object types.

Per-instance routine: gboolean qof_instance_refers_to_object(QofInstance* A, QofInstance* B) - returns TRUE/FALSE whether object A contains a reference to object B.
Normal routine: GList* qof_instance_get_referring_object_list_from_collection(QofCollection* c, QofInstance* B) - Calls qof_instance_refers_to_object() for each object in the collection, and returns a list of the objects which contain a reference to B.
Per-instance routine: GList* qof_instance_get_typed_referring_object_list(QofInstance* A, QofInstance* B) - returns a list of all objects of the same type as A which contain a reference to B.  Being per-instance allows an object to use knowledge to avoid scanning cases where there are no references (e.g. billterms do not contain references to splits), or a scan is not needed (references from splits to an account can be determined using xaccAccountGetSplitList()).  This routine can do a scan by calling qof_instnace_get_referring_object_list_from_collection().
Normal routine: qof_instance_get_referring_object_list(QofInstance* A) - For all collections in the book, gets an instance and calls its qof_instance_get_typed_referring_object_list() routine, concatenating all of the returned lists.  This is the routine that external code can call to get a list of all objects with references to an object A.  The list must be freed by the caller but the contents must not.
Per-instance routine: gchar* qof_instance_get_display_name(QofInstance* A) - returns a string which can identify object A to the user.  This could be used to display a list of the objects returned by qof_instance_get_referring_object_list() ("Invoice 0004 for customer C") so that the user can modify those objects to remove the references.  Note that this is going to require internationalization, which has not been implemented yet.  If not overridden by the object class, the default string is "Object <type> <address>" e.g. "Object gncCustomer 0x12345678".


Modified: gnucash/trunk/src/libqof/qof/qofinstance.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofinstance.c	2010-03-12 10:04:27 UTC (rev 18892)
+++ gnucash/trunk/src/libqof/qof/qofinstance.c	2010-03-12 10:14:27 UTC (rev 18893)
@@ -135,6 +135,10 @@
 
     g_type_class_add_private(klass, sizeof(QofInstancePrivate));
 
+    klass->get_display_name = NULL;
+    klass->refers_to_object = NULL;
+    klass->get_typed_referring_object_list = NULL;
+
     g_object_class_install_property
     (object_class,
      PROP_GUID,
@@ -907,6 +911,136 @@
     return twin;
 }
 
+/* Returns a displayable name to represent this object */
+gchar* qof_instance_get_display_name(const QofInstance* inst)
+{
+    g_return_val_if_fail( inst != NULL, NULL );
+
+    if ( QOF_INSTANCE_GET_CLASS(inst)->get_display_name != NULL )
+    {
+        return QOF_INSTANCE_GET_CLASS(inst)->get_display_name(inst);
+    }
+    else
+    {
+        /* Not implemented - return default string */
+        return g_strdup_printf("Object %s %p", 
+                            qof_collection_get_type(qof_instance_get_collection(inst)),
+                            inst);
+    }
+}
+
+typedef struct {
+    const QofInstance* inst;
+    GList* list;
+} GetReferringObjectHelperData;
+
+static void
+get_referring_object_instance_helper(QofInstance* inst, gpointer user_data)
+{
+    QofInstance** pInst = (QofInstance**)user_data;
+
+    if (*pInst == NULL)
+    {
+        *pInst = inst;
+    }
+}
+
+static void
+get_referring_object_helper(QofCollection* coll, gpointer user_data)
+{
+    QofInstance* first_instance = NULL;
+    GetReferringObjectHelperData* data = (GetReferringObjectHelperData*)user_data;
+
+    qof_collection_foreach(coll, get_referring_object_instance_helper, &first_instance);
+
+    if (first_instance != NULL)
+    {
+        GList* new_list = qof_instance_get_typed_referring_object_list(first_instance, data->inst);
+        data->list = g_list_concat(data->list, new_list);
+    }
+}
+
+/* Returns a list of objects referring to this object */
+GList* qof_instance_get_referring_object_list(const QofInstance* inst)
+{
+    GetReferringObjectHelperData data;
+
+    g_return_val_if_fail( inst != NULL, NULL );
+
+    /* scan all collections */
+    data.inst = inst;
+    data.list = NULL;
+
+    qof_book_foreach_collection(qof_instance_get_book(inst),
+                                    get_referring_object_helper,
+                                    &data);
+    return data.list;
+}
+
+static void
+get_typed_referring_object_instance_helper(QofInstance* inst, gpointer user_data)
+{
+    GetReferringObjectHelperData* data = (GetReferringObjectHelperData*)user_data;
+
+    if (qof_instance_refers_to_object(inst, data->inst))
+    {
+        data->list = g_list_prepend(data->list, inst);
+    }
+}
+
+GList*
+qof_instance_get_referring_object_list_from_collection(const QofCollection* coll, const QofInstance* ref)
+{
+    GetReferringObjectHelperData data;
+
+    g_return_val_if_fail( coll != NULL, NULL );
+    g_return_val_if_fail( ref != NULL, NULL );
+
+    data.inst = ref;
+    data.list = NULL;
+
+    qof_collection_foreach(coll, get_typed_referring_object_instance_helper, &data);
+    return data.list;
+}
+
+GList*
+qof_instance_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
+{
+    g_return_val_if_fail( inst != NULL, NULL );
+    g_return_val_if_fail( ref != NULL, NULL );
+
+    if ( QOF_INSTANCE_GET_CLASS(inst)->get_typed_referring_object_list != NULL )
+    {
+        return QOF_INSTANCE_GET_CLASS(inst)->get_typed_referring_object_list(inst, ref);
+    }
+    else
+    {
+        /* Not implemented - by default, loop through all objects of this object's type and check
+           them individually. */
+        QofCollection* coll;
+
+        coll = qof_instance_get_collection(inst);
+        return qof_instance_get_referring_object_list_from_collection(coll, ref);
+    }
+}
+
+/* Check if this object refers to a specific object */
+gboolean qof_instance_refers_to_object(const QofInstance* inst, const QofInstance* ref)
+{
+    g_return_val_if_fail( inst != NULL, FALSE );
+    g_return_val_if_fail( ref != NULL, FALSE );
+
+    if ( QOF_INSTANCE_GET_CLASS(inst)->refers_to_object != NULL )
+    {
+        return QOF_INSTANCE_GET_CLASS(inst)->refers_to_object(inst, ref);
+    }
+    else
+    {
+        /* Not implemented - default = NO */
+        return FALSE;
+    }
+}
+
 /* =================================================================== */
 /* Entity edit and commit utilities */
 /* =================================================================== */

Modified: gnucash/trunk/src/libqof/qof/qofinstance.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofinstance.h	2010-03-12 10:04:27 UTC (rev 18892)
+++ gnucash/trunk/src/libqof/qof/qofinstance.h	2010-03-12 10:14:27 UTC (rev 18893)
@@ -78,6 +78,15 @@
 struct _QofInstanceClass
 {
     GObjectClass parent_class;
+
+    /* Returns a displayable string to represent this object */
+    gchar* (*get_display_name)(const QofInstance*);
+
+    /* Does this object refer to a specific object */
+    gboolean (*refers_to_object)(const QofInstance* inst, const QofInstance* ref);
+
+    /* Returns a list of my type of object which refers to an object */
+    GList* (*get_typed_referring_object_list)(const QofInstance* inst, const QofInstance* ref);
 };
 
 /** Return the GType of a QofInstance */
@@ -247,7 +256,7 @@
  *    instance 'src' in the given other 'book' (if the twin exists).
  *
  *    When instances are gemini'ed or cloned, both of the pair are marked
- *    with the guid of thier copy, thus allowing the sibling-copy of
+ *    with the guid of their copy, thus allowing the sibling-copy of
  *    an instance to be found.  Since the sibling may end up in a
  *    different book, we need a way of finding it, given only that we
  *    know the book, and that we know its twin.
@@ -259,6 +268,33 @@
  */
 QofInstance * qof_instance_lookup_twin (const QofInstance *src, QofBook *book);
 
+/**
+ * Returns a displayable name for this object.  The returned string must be freed by the caller.
+ */
+gchar* qof_instance_get_display_name(const QofInstance* inst);
+
+/**
+ * Returns a list of objects which refer to a specific object.  The list must be freed by the caller,
+ * but the objects on the list must not.
+ */
+GList* qof_instance_get_referring_object_list(const QofInstance* inst);
+
+/** Does this object refer to a specific object */
+gboolean qof_instance_refers_to_object(const QofInstance* inst, const QofInstance* ref);
+
+/** Returns a list of my type of object which refers to an object.  For example, when called as
+        qof_instance_get_typed_referring_object_list(taxtable, account);
+    it will return the list of taxtables which refer to a specific account.  The result should be the
+    same regardless of which taxtable object is used.  The list must be freed by the caller but the
+    objects on the list must not.
+ */
+GList* qof_instance_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref);
+
+/** Returns a list of objects from the collection which refer to the specific object.  The list must be
+    freed by the caller but the objects on the list must not.
+ */
+GList* qof_instance_get_referring_object_list_from_collection(const QofCollection* coll, const QofInstance* ref);
+
 /* @} */
 /* @} */
 #endif /* QOF_INSTANCE_H */



More information about the gnucash-changes mailing list