QOF
0.8.0
|
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 ================================ */