qofgobj.c

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

Generated on Fri Sep 1 15:13:11 2006 for QOF by  doxygen 1.4.7