[Gnucash-changes] QOF to GObject glue code.

Linas Vepstas linas at cvs.gnucash.org
Sun Apr 18 23:35:52 EDT 2004


Log Message:
-----------
QOF to GObject glue code.  Not currently built or used by
GnuCash; checked in here to keep gnucash in sync with qof files.

Added Files:
-----------
    gnucash/src/engine:
        qofgobj.c
        qofgobj.h

Revision Data
-------------
--- /dev/null
+++ src/engine/qofgobj.h
@@ -0,0 +1,82 @@
+/********************************************************************\
+ * qofgobj.h -- QOF to GLib GObject mapping                         *
+ *                                                                  *
+ * 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       *
+ * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
+ * Boston, MA  02111-1307,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+#ifndef QOF_GOBJ_H
+#define QOF_GOBJ_H
+
+/** @addtogroup Engine
+    @{ */
+/** @file qofgobj.h
+    @brief QOF to GLib GObject mapping
+    @author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
+*/
+
+/** The API defined in this file allows a user to register any
+ *  GLib GObject (and any object derived from one, e.g. GTK/Gnome)
+ *  with the QOF system so that it becomes searchable.  
+ *
+ * XXX Only GObject properties are searchable, data and other 
+ * hanging off the GObject is not.  Fix this.
+ */  
+
+#include <glib-object.h>
+#include <qof/qofbook.h>
+#include <qof/qofclass.h>
+
+/** Initalize and shut down this subsystem. */
+void qof_gobject_init(void);
+void qof_gobject_shutdown (void);
+
+/** Register a GObject class with the QOF subsystem.
+ *  Doing this will make the properties associated with
+ *  this GObject searchable using the QOF subsystem.
+ *
+ *  The QofType can be any string you desire, although typically
+ *  you might want to set it to G_OBJECT_CLASS_NAME() of the 
+ *  object class.  Note that this type will become the name of
+ *  the "table" that is searched by SQL queries:
+ *  e.g. in order to be able to say "SELECT * FROM MyStuff;"
+ *  you must first say:
+ *   qof_gobject_register ("MyStuff", gobj_class);
+ */
+void qof_gobject_register (QofType type, GObjectClass *obclass);
+
+/** Register an instance of a GObject with the QOF subsystem.
+ *
+ *  The QofType can be any string you desire, although typically
+ *  you might want to set it to G_OBJECT_CLASS_NAME() of the 
+ *  object class.  Note that this type will become the name of
+ *  the "table" that is searched by SQL queries:
+ *  e.g. in order to be able to say "SELECT * FROM MyStuff;"
+ *  you must first say:
+ *   qof_gobject_register_instance (book, "MyStuff", obj);
+ *
+ *  The 'book' argument specifies an anchor point for the collection
+ *  of all of the registered instances.  By working with disjoint books,
+ *  you can have multiple disjoint searchable sets of objects.
+ */
+
+void qof_gobject_register_instance (QofBook *book, QofType, GObject *);
+
+#endif /* QOF_GOBJ_H */
+/** @} */
+
--- /dev/null
+++ src/engine/qofgobj.c
@@ -0,0 +1,309 @@
+/********************************************************************\
+ * qofgobj.c -- QOF to GLib GObject mapping                         *
+ *                                                                  *
+ * 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       *
+ * 59 Temple Place - Suite 330        Fax:    +1-617-542-2652       *
+ * Boston, MA  02111-1307,  USA       gnu at gnu.org                   *
+ *                                                                  *
+\********************************************************************/
+
+#include <qof/gnc-trace.h>
+#include <qof/qof.h>
+#include <qof/qofgobj.h>
+
+static short module = MOD_QUERY;
+
+static gboolean initialized = FALSE;
+static GSList *paramList = NULL;
+static GSList *classList = NULL;
+
+/* =================================================================== */
+
+#if 0
+static gboolean 
+clear_table (gpointer key, gpointer value, gpointer user_data)
+{
+  g_slist_free (value);
+  return TRUE;
+}
+#endif
+
+void 
+qof_gobject_init(void)
+{
+  if (initialized) return;
+  initialized = TRUE;
+                                                                                
+  // gobjectClassTable = g_hash_table_new (g_str_hash, g_str_equal);
+
+	/* Init the other subsystems that we need */
+	qof_object_initialize();
+	qof_query_init ();
+}
+
+void 
+qof_gobject_shutdown (void)
+{
+  if (!initialized) return;
+  initialized = FALSE;
+                                                                                
+	GSList *n;
+	for (n=paramList; n; n=n->next) g_free(n->data);
+	g_slist_free (paramList);
+
+	for (n=classList; n; n=n->next) g_free(n->data);
+	g_slist_free (classList);
+
+#if 0
+  // XXX also need to walk over books, and collection and delete
+  // the collection get_data instance lists !!
+  // without this we have a memory leak !!
+  g_hash_table_foreach_remove (gobjectParamTable, clear_table, NULL);
+  g_hash_table_destroy (gobjectParamTable);
+#endif
+}
+
+/* =================================================================== */
+
+#define GOBJECT_TABLE  "GobjectTable"
+
+void 
+qof_gobject_register_instance (QofBook *book, QofType type, GObject *gob)
+{
+	if (!book || !type) return;
+
+	QofCollection *coll = qof_book_get_collection (book, type);
+
+	GSList * instance_list = qof_collection_get_data (coll);
+	instance_list = g_slist_prepend (instance_list, gob);
+   qof_collection_set_data (coll, instance_list);
+}
+
+/* =================================================================== */
+
+static gpointer
+qof_gobject_getter (gpointer data, QofParam *getter)
+{
+	GObject *gob = data;
+
+	GParamSpec *gps = getter->param_userdata;
+
+	/* Note that the return type must actually be of type
+	 * getter->param_type but we just follow the hard-coded 
+	 * mapping below ... */
+	if (G_IS_PARAM_SPEC_STRING(gps))
+	{
+		GValue gval = {G_TYPE_INVALID};
+		g_value_init (&gval, G_TYPE_STRING);
+		g_object_get_property (gob, getter->param_name, &gval);
+
+      const char * str = g_value_get_string (&gval);
+      return (gpointer) str;
+   }
+	else
+	if (G_IS_PARAM_SPEC_INT(gps))
+	{
+		GValue gval = {G_TYPE_INVALID};
+		g_value_init (&gval, G_TYPE_INT);
+		g_object_get_property (gob, getter->param_name, &gval);
+
+      int ival = g_value_get_int (&gval);
+      return (gpointer) ival;
+   }
+	else
+	if (G_IS_PARAM_SPEC_UINT(gps))
+	{
+		GValue gval = {G_TYPE_INVALID};
+		g_value_init (&gval, G_TYPE_UINT);
+		g_object_get_property (gob, getter->param_name, &gval);
+
+      int ival = g_value_get_uint (&gval);
+      return (gpointer) ival;
+   }
+	else
+	if (G_IS_PARAM_SPEC_BOOLEAN(gps))
+	{
+		GValue gval = {G_TYPE_INVALID};
+		g_value_init (&gval, G_TYPE_BOOLEAN);
+		g_object_get_property (gob, getter->param_name, &gval);
+
+      int ival = g_value_get_boolean (&gval);
+      return (gpointer) ival;
+   }
+
+	PWARN ("unhandled parameter type %s for paramter %s", 
+	        G_PARAM_SPEC_TYPE_NAME(gps), getter->param_name);
+	return NULL;
+}
+
+static double
+qof_gobject_double_getter (gpointer data, QofParam *getter)
+{
+	GObject *gob = data;
+
+	GParamSpec *gps = getter->param_userdata;
+
+	/* Note that the return type must actually be of type
+	 * getter->param_type but we just follow the hard-coded 
+	 * mapping below ... */
+	if (G_IS_PARAM_SPEC_FLOAT(gps))
+	{
+		GValue gval = {G_TYPE_INVALID};
+		g_value_init (&gval, G_TYPE_FLOAT);
+		g_object_get_property (gob, getter->param_name, &gval);
+
+      double fval = g_value_get_float (&gval);
+      return fval;
+   }
+	else
+	if (G_IS_PARAM_SPEC_DOUBLE(gps))
+	{
+		GValue gval = {G_TYPE_INVALID};
+		g_value_init (&gval, G_TYPE_DOUBLE);
+		g_object_get_property (gob, getter->param_name, &gval);
+
+      double fval = g_value_get_double (&gval);
+      return fval;
+   }
+
+	PWARN ("unhandled parameter type %s for paramter %s", 
+	        G_PARAM_SPEC_TYPE_NAME(gps), getter->param_name);
+	return 0.0;
+}
+
+/* =================================================================== */
+/* Loop over every instance of the given type in the collection
+ * of instances that we have on hand.
+ */
+static void
+qof_gobject_foreach (QofCollection *coll, QofEntityForeachCB cb, gpointer ud)
+{
+   GSList *n;
+	n = qof_collection_get_data (coll);
+   for (; n; n=n->next)
+   {
+      cb (n->data, ud);
+   }
+}
+                                                                                
+/* =================================================================== */
+
+void
+qof_gobject_register (QofType e_type, GObjectClass *obclass)
+{
+
+	/* Get the GObject properties, convert to QOF properties */
+	GParamSpec **prop_list;
+	int n_props;
+	prop_list = g_object_class_list_properties (obclass, &n_props);
+
+	QofParam * qof_param_list = g_new0 (QofParam, n_props);
+	paramList = g_slist_prepend (paramList, qof_param_list);
+
+	PINFO ("object %s has %d props", e_type, n_props);
+	int i, j=0;
+	for (i=0; i<n_props; i++)
+	{
+		GParamSpec *gparam = prop_list[i];
+		QofParam *qpar = &qof_param_list[j];
+
+		PINFO ("param %d %s is type %s", 
+		      i, gparam->name, G_PARAM_SPEC_TYPE_NAME(gparam));
+
+		qpar->param_name = g_param_spec_get_name (gparam);
+		qpar->param_getfcn = qof_gobject_getter;
+		qpar->param_setfcn = NULL;
+		qpar->param_userdata = gparam;
+		if ((G_IS_PARAM_SPEC_INT(gparam))  ||
+		    (G_IS_PARAM_SPEC_UINT(gparam)) ||
+		    (G_IS_PARAM_SPEC_ENUM(gparam)) ||
+		    (G_IS_PARAM_SPEC_FLAGS(gparam)))
+		{
+			qpar->param_type = QOF_TYPE_INT32;
+			j++;
+		} 
+		else
+		if ((G_IS_PARAM_SPEC_INT64(gparam)) ||
+		    (G_IS_PARAM_SPEC_UINT64(gparam)))
+		{
+			qpar->param_type = QOF_TYPE_INT64;
+			j++;
+		} 
+		else
+		if (G_IS_PARAM_SPEC_BOOLEAN(gparam))
+		{
+			qpar->param_type = QOF_TYPE_BOOLEAN;
+			j++;
+		} 
+		else
+		if (G_IS_PARAM_SPEC_STRING(gparam))
+		{
+			qpar->param_type = QOF_TYPE_STRING;
+			j++;
+		} 
+		else
+		if ((G_IS_PARAM_SPEC_POINTER(gparam)) ||
+		    (G_IS_PARAM_SPEC_OBJECT(gparam)))
+		{
+			/* No-op, silently ignore.  Someday we should handle this ...  */
+		} 
+		else
+		if ((G_IS_PARAM_SPEC_FLOAT(gparam)) ||
+		    (G_IS_PARAM_SPEC_DOUBLE(gparam)))
+		{
+			qpar->param_getfcn = (QofAccessFunc) qof_gobject_double_getter;
+			qpar->param_type = QOF_TYPE_DOUBLE;
+			j++;
+		} 
+		else
+		if (G_IS_PARAM_SPEC_CHAR(gparam))
+		{
+			qpar->param_type = QOF_TYPE_CHAR;
+			j++;
+		} 
+		else
+		{
+			PWARN ("Unknown/unhandled parameter type %s on %s:%s\n", 
+			    G_PARAM_SPEC_TYPE_NAME(gparam), e_type, qpar->param_name);
+		}
+	}
+
+	/* NULL-terminated list! */
+	qof_param_list[j].param_type = NULL;
+
+   qof_class_register (e_type, NULL, qof_param_list);
+
+	/* ------------------------------------------------------ */
+   /* Now do the class itself */
+	QofObject *class_def = g_new0 (QofObject, 1);
+	classList = g_slist_prepend (classList, class_def);
+
+	class_def->interface_version = QOF_OBJECT_VERSION;
+	class_def->e_type = e_type;
+	/* We could let the user specify a "nick" here, but
+	 * the actual class name seems reasonable, e.g. for debugging. */
+	class_def->type_label = G_OBJECT_CLASS_NAME (obclass);
+	class_def->book_begin = NULL;
+	class_def->book_end = NULL;
+	class_def->is_dirty = NULL;
+	class_def->mark_clean = NULL;
+	class_def->foreach = qof_gobject_foreach;
+	class_def->printable = NULL;
+ 
+   qof_object_register (class_def);
+}
+
+/* ======================= END OF FILE ================================ */


More information about the Gnucash-changes mailing list