/********************************************************************\ * 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 * * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * * Boston, MA 02110-1301, USA gnu@gnu.org * * * \********************************************************************/ #include "qof.h" #include "qofgobj.h" static QofLogModule log_module = QOF_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) { GSList *n; 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) { 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); } /* =================================================================== */ static gpointer qof_gobject_getter (gpointer data, QofParam *getter) { GObject *gob = data; const char *str; 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); str = g_value_get_string (&gval); return (gpointer) str; } else if (G_IS_PARAM_SPEC_INT(gps)) { int ival; GValue gval = {G_TYPE_INVALID}; g_value_init (&gval, G_TYPE_INT); g_object_get_property (gob, getter->param_name, &gval); ival = g_value_get_int (&gval); return (gpointer) ival; } else if (G_IS_PARAM_SPEC_UINT(gps)) { int ival; GValue gval = {G_TYPE_INVALID}; g_value_init (&gval, G_TYPE_UINT); g_object_get_property (gob, getter->param_name, &gval); ival = g_value_get_uint (&gval); return (gpointer) ival; } else if (G_IS_PARAM_SPEC_BOOLEAN(gps)) { int ival; GValue gval = {G_TYPE_INVALID}; g_value_init (&gval, G_TYPE_BOOLEAN); g_object_get_property (gob, getter->param_name, &gval); 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; double fval; 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); 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); 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) { int i; int j; QofParam *qof_param_list, *qpar; QofObject *class_def; GParamSpec **prop_list, *gparam; guint n_props; /* Get the GObject properties, convert to QOF properties */ prop_list = g_object_class_list_properties (obclass, &n_props); 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); j=0; for (i=0; iname, G_PARAM_SPEC_TYPE_NAME(gparam)); qpar->param_name = g_param_spec_get_name (gparam); qpar->param_getfcn = (QofAccessFunc)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 */ 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->create = NULL; 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; class_def->version_cmp = NULL; qof_object_register (class_def); } /* ======================= END OF FILE ================================ */