qofgobj.c

00001 /********************************************************************\
00002  * qofgobj.c -- QOF to GLib GObject mapping                         *
00003  *                                                                  *
00004  * Copyright (c) 2000,2001,2004 Linas Vepstas <linas@linas.org>     *
00005  *                                                                  *
00006  * This program is free software; you can redistribute it and/or    *
00007  * modify it under the terms of the GNU General Public License as   *
00008  * published by the Free Software Foundation; either version 2 of   *
00009  * the License, or (at your option) any later version.              *
00010  *                                                                  *
00011  * This program is distributed in the hope that it will be useful,  *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00014  * GNU General Public License for more details.                     *
00015  *                                                                  *
00016  * You should have received a copy of the GNU General Public License*
00017  * along with this program; if not, contact:                        *
00018  *                                                                  *
00019  * Free Software Foundation           Voice:  +1-617-542-5942       *
00020  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00021  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00022  *                                                                  *
00023 \********************************************************************/
00024 
00025 #include "config.h"
00026 #include <glib.h>
00027 #include "qof.h"
00028 #include "qofgobj.h"
00029 
00030 static QofLogModule log_module = QOF_MOD_QUERY;
00031 
00032 static gboolean initialized = FALSE;
00033 static GSList *paramList = NULL;
00034 static GSList *classList = NULL;
00035 
00036 /* =================================================================== */
00037 
00038 #if 0
00039 static gboolean
00040 clear_table (gpointer key, gpointer value, gpointer user_data)
00041 {
00042     g_slist_free (value);
00043     return TRUE;
00044 }
00045 #endif
00046 
00047 void
00048 qof_gobject_init (void)
00049 {
00050     if (initialized)
00051         return;
00052     initialized = TRUE;
00053 
00054     // gobjectClassTable = g_hash_table_new (g_str_hash, g_str_equal);
00055 
00056     /* Init the other subsystems that we need */
00057     qof_object_initialize ();
00058     qof_query_init ();
00059 }
00060 
00061 void
00062 qof_gobject_shutdown (void)
00063 {
00064     GSList *n;
00065 
00066     if (!initialized)
00067         return;
00068     initialized = FALSE;
00069 
00070 //  GSList *n;
00071     for (n = paramList; n; n = n->next)
00072         g_free (n->data);
00073     g_slist_free (paramList);
00074 
00075     for (n = classList; n; n = n->next)
00076         g_free (n->data);
00077     g_slist_free (classList);
00078 
00079 #if 0
00080     // XXX also need to walk over books, and collection and delete
00081     // the collection get_data instance lists !!
00082     // without this we have a memory leak !!
00083     g_hash_table_foreach_remove (gobjectParamTable, clear_table, NULL);
00084     g_hash_table_destroy (gobjectParamTable);
00085 #endif
00086 }
00087 
00088 /* =================================================================== */
00089 
00090 #define GOBJECT_TABLE  "GobjectTable"
00091 
00092 void
00093 qof_gobject_register_instance (QofBook * book, QofType type, GObject * gob)
00094 {
00095     QofCollection *coll;
00096     GSList *instance_list;
00097 
00098     if (!book || !type)
00099         return;
00100 
00101     coll = qof_book_get_collection (book, type);
00102 
00103     instance_list = qof_collection_get_data (coll);
00104     instance_list = g_slist_prepend (instance_list, gob);
00105     qof_collection_set_data (coll, instance_list);
00106 }
00107 
00108 /* =================================================================== */
00109 
00110 static gpointer
00111 qof_gobject_getter (gpointer data, QofParam * getter)
00112 {
00113     GObject *gob = data;
00114     const char *str;
00115 
00116     GParamSpec *gps = getter->param_userdata;
00117 
00118     /* Note that the return type must actually be of type
00119      * getter->param_type but we just follow the hard-coded 
00120      * mapping below ... */
00121     if (G_IS_PARAM_SPEC_STRING (gps))
00122     {
00123         GValue gval;
00124         g_value_init (&gval, G_TYPE_STRING);
00125         g_object_get_property (gob, getter->param_name, &gval);
00126 
00127         str = g_value_get_string (&gval);
00128         return (gpointer) str;
00129     }
00130     else if (G_IS_PARAM_SPEC_INT (gps))
00131     {
00132         long ival;
00133 
00134         GValue gval;
00135         g_value_init (&gval, G_TYPE_INT);
00136         g_object_get_property (gob, getter->param_name, &gval);
00137 
00138         ival = g_value_get_int (&gval);
00139         return (gpointer) ival;
00140     }
00141     else if (G_IS_PARAM_SPEC_UINT (gps))
00142     {
00143         long ival;
00144         GValue gval;
00145         g_value_init (&gval, G_TYPE_UINT);
00146         g_object_get_property (gob, getter->param_name, &gval);
00147 
00148         ival = g_value_get_uint (&gval);
00149         return (gpointer) ival;
00150     }
00151     else if (G_IS_PARAM_SPEC_BOOLEAN (gps))
00152     {
00153         gboolean ival;
00154 
00155         GValue gval;
00156         g_value_init (&gval, G_TYPE_BOOLEAN);
00157         g_object_get_property (gob, getter->param_name, &gval);
00158 
00159         ival = g_value_get_boolean (&gval);
00160         return GINT_TO_POINTER (ival);
00161     }
00162 
00163     PWARN ("unhandled parameter type %s for paramter %s",
00164         G_PARAM_SPEC_TYPE_NAME (gps), getter->param_name);
00165     return NULL;
00166 }
00167 
00168 static double
00169 qof_gobject_double_getter (gpointer data, QofParam * getter)
00170 {
00171     GObject *gob = data;
00172     double fval;
00173 
00174     GParamSpec *gps = getter->param_userdata;
00175 
00176     /* Note that the return type must actually be of type
00177      * getter->param_type but we just follow the hard-coded 
00178      * mapping below ... */
00179     if (G_IS_PARAM_SPEC_FLOAT (gps))
00180     {
00181         GValue gval;
00182         g_value_init (&gval, G_TYPE_FLOAT);
00183         g_object_get_property (gob, getter->param_name, &gval);
00184 
00185         fval = g_value_get_float (&gval);
00186         return fval;
00187     }
00188     else if (G_IS_PARAM_SPEC_DOUBLE (gps))
00189     {
00190         GValue gval;
00191         g_value_init (&gval, G_TYPE_DOUBLE);
00192         g_object_get_property (gob, getter->param_name, &gval);
00193 
00194         fval = g_value_get_double (&gval);
00195         return fval;
00196     }
00197 
00198     PWARN ("unhandled parameter type %s for paramter %s",
00199         G_PARAM_SPEC_TYPE_NAME (gps), getter->param_name);
00200     return 0.0;
00201 }
00202 
00203 /* =================================================================== */
00204 /* Loop over every instance of the given type in the collection
00205  * of instances that we have on hand.
00206  */
00207 static void
00208 qof_gobject_foreach (QofCollection * coll, QofEntityForeachCB cb,
00209     gpointer ud)
00210 {
00211     GSList *n;
00212     n = qof_collection_get_data (coll);
00213     for (; n; n = n->next)
00214     {
00215         cb (n->data, ud);
00216     }
00217 }
00218 
00219 /* =================================================================== */
00220 
00221 void
00222 qof_gobject_register (QofType e_type, GObjectClass * obclass)
00223 {
00224     guint i, j;
00225     QofParam *qof_param_list, *qpar;
00226     QofObject *class_def;
00227     GParamSpec **prop_list, *gparam;
00228     guint n_props;
00229 
00230     /* Get the GObject properties, convert to QOF properties */
00231     prop_list = g_object_class_list_properties (obclass, &n_props);
00232 
00233     qof_param_list = g_new0 (QofParam, n_props);
00234     paramList = g_slist_prepend (paramList, qof_param_list);
00235 
00236     PINFO ("object %s has %d props", e_type, n_props);
00237     j = 0;
00238     for (i = 0; i < n_props; i++)
00239     {
00240         gparam = prop_list[i];
00241         qpar = &qof_param_list[j];
00242 
00243         PINFO ("param %d %s is type %s",
00244             i, gparam->name, G_PARAM_SPEC_TYPE_NAME (gparam));
00245 
00246         qpar->param_name = g_param_spec_get_name (gparam);
00247         qpar->param_getfcn = (QofAccessFunc) qof_gobject_getter;
00248         qpar->param_setfcn = NULL;
00249         qpar->param_userdata = gparam;
00250         if ((G_IS_PARAM_SPEC_INT (gparam)) ||
00251             (G_IS_PARAM_SPEC_UINT (gparam)) ||
00252             (G_IS_PARAM_SPEC_ENUM (gparam)) ||
00253             (G_IS_PARAM_SPEC_FLAGS (gparam)))
00254         {
00255             qpar->param_type = QOF_TYPE_INT32;
00256             j++;
00257         }
00258         else if ((G_IS_PARAM_SPEC_INT64 (gparam)) ||
00259             (G_IS_PARAM_SPEC_UINT64 (gparam)))
00260         {
00261             qpar->param_type = QOF_TYPE_INT64;
00262             j++;
00263         }
00264         else if (G_IS_PARAM_SPEC_BOOLEAN (gparam))
00265         {
00266             qpar->param_type = QOF_TYPE_BOOLEAN;
00267             j++;
00268         }
00269         else if (G_IS_PARAM_SPEC_STRING (gparam))
00270         {
00271             qpar->param_type = QOF_TYPE_STRING;
00272             j++;
00273         }
00274         else if ((G_IS_PARAM_SPEC_POINTER (gparam)) ||
00275             (G_IS_PARAM_SPEC_OBJECT (gparam)))
00276         {
00277             /* No-op, silently ignore.  Someday we should handle this ...  */
00278         }
00279         else if ((G_IS_PARAM_SPEC_FLOAT (gparam)) ||
00280             (G_IS_PARAM_SPEC_DOUBLE (gparam)))
00281         {
00282             qpar->param_getfcn = (QofAccessFunc) qof_gobject_double_getter;
00283             qpar->param_type = QOF_TYPE_DOUBLE;
00284             j++;
00285         }
00286         else if (G_IS_PARAM_SPEC_CHAR (gparam))
00287         {
00288             qpar->param_type = QOF_TYPE_CHAR;
00289             j++;
00290         }
00291         else
00292         {
00293             PWARN ("Unknown/unhandled parameter type %s on %s:%s\n",
00294                 G_PARAM_SPEC_TYPE_NAME (gparam), e_type, qpar->param_name);
00295         }
00296     }
00297 
00298     /* NULL-terminated list! */
00299     qof_param_list[j].param_type = NULL;
00300 
00301     qof_class_register (e_type, NULL, qof_param_list);
00302 
00303     /* ------------------------------------------------------ */
00304     /* Now do the class itself */
00305     class_def = g_new0 (QofObject, 1);
00306     classList = g_slist_prepend (classList, class_def);
00307 
00308     class_def->interface_version = QOF_OBJECT_VERSION;
00309     class_def->e_type = e_type;
00310     /* We could let the user specify a "nick" here, but
00311      * the actual class name seems reasonable, e.g. for debugging. */
00312     class_def->type_label = G_OBJECT_CLASS_NAME (obclass);
00313     class_def->create = NULL;
00314     class_def->book_begin = NULL;
00315     class_def->book_end = NULL;
00316     class_def->is_dirty = NULL;
00317     class_def->mark_clean = NULL;
00318     class_def->foreach = qof_gobject_foreach;
00319     class_def->printable = NULL;
00320     class_def->version_cmp = NULL;
00321 
00322     qof_object_register (class_def);
00323 }
00324 
00325 /* ======================= END OF FILE ================================ */

Generated on Thu Jan 31 22:50:25 2008 for QOF by  doxygen 1.5.4