QOF  0.7.5
qofgobj.c
1 /********************************************************************\
2  * qofgobj.c -- QOF to GLib GObject mapping *
3  * *
4  * Copyright (c) 2000,2001,2004 Linas Vepstas <linas@linas.org> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA gnu@gnu.org *
22  * *
23 \********************************************************************/
24 
25 #include "config.h"
26 #include <glib.h>
27 #include "qof.h"
28 #include "qofgobj.h"
29 
30 static QofLogModule log_module = QOF_MOD_QUERY;
31 
32 static gboolean initialized = FALSE;
33 static GSList *paramList = NULL;
34 static GSList *classList = NULL;
35 
36 /* =================================================================== */
37 
38 #if 0
39 static gboolean
40 clear_table (gpointer key, gpointer value, gpointer user_data)
41 {
42  g_slist_free (value);
43  return TRUE;
44 }
45 #endif
46 
47 void
49 {
50  if (initialized)
51  return;
52  initialized = TRUE;
53 
54  // gobjectClassTable = g_hash_table_new (g_str_hash, g_str_equal);
55 
56  /* Init the other subsystems that we need */
57  qof_object_initialize ();
58  qof_query_init ();
59 }
60 
61 void
62 qof_gobject_shutdown (void)
63 {
64  GSList *n;
65 
66  if (!initialized)
67  return;
68  initialized = FALSE;
69 
70 // GSList *n;
71  for (n = paramList; n; n = n->next)
72  g_free (n->data);
73  g_slist_free (paramList);
74 
75  for (n = classList; n; n = n->next)
76  g_free (n->data);
77  g_slist_free (classList);
78 
79 #if 0
80  // XXX also need to walk over books, and collection and delete
81  // the collection get_data instance lists !!
82  // without this we have a memory leak !!
83  g_hash_table_foreach_remove (gobjectParamTable, clear_table, NULL);
84  g_hash_table_destroy (gobjectParamTable);
85 #endif
86 }
87 
88 /* =================================================================== */
89 
90 #define GOBJECT_TABLE "GobjectTable"
91 
92 void
93 qof_gobject_register_instance (QofBook * book, QofType type, GObject * gob)
94 {
95  QofCollection *coll;
96  GSList *instance_list;
97 
98  if (!book || !type)
99  return;
100 
101  coll = qof_book_get_collection (book, type);
102 
103  instance_list = qof_collection_get_data (coll);
104  instance_list = g_slist_prepend (instance_list, gob);
105  qof_collection_set_data (coll, instance_list);
106 }
107 
108 /* =================================================================== */
109 
110 static gpointer
111 qof_gobject_getter (gpointer data, QofParam * getter)
112 {
113  GObject *gob = data;
114  const char *str;
115 
116  GParamSpec *gps = getter->param_userdata;
117 
118  /* Note that the return type must actually be of type
119  * getter->param_type but we just follow the hard-coded
120  * mapping below ... */
121  if (G_IS_PARAM_SPEC_STRING (gps))
122  {
123  GValue gval;
124  g_value_init (&gval, G_TYPE_STRING);
125  g_object_get_property (gob, getter->param_name, &gval);
126 
127  str = g_value_get_string (&gval);
128  return (gpointer) str;
129  }
130  else if (G_IS_PARAM_SPEC_INT (gps))
131  {
132  long ival;
133 
134  GValue gval;
135  g_value_init (&gval, G_TYPE_INT);
136  g_object_get_property (gob, getter->param_name, &gval);
137 
138  ival = g_value_get_int (&gval);
139  return (gpointer) ival;
140  }
141  else if (G_IS_PARAM_SPEC_UINT (gps))
142  {
143  long ival;
144  GValue gval;
145  g_value_init (&gval, G_TYPE_UINT);
146  g_object_get_property (gob, getter->param_name, &gval);
147 
148  ival = g_value_get_uint (&gval);
149  return (gpointer) ival;
150  }
151  else if (G_IS_PARAM_SPEC_BOOLEAN (gps))
152  {
153  gboolean ival;
154 
155  GValue gval;
156  g_value_init (&gval, G_TYPE_BOOLEAN);
157  g_object_get_property (gob, getter->param_name, &gval);
158 
159  ival = g_value_get_boolean (&gval);
160  return GINT_TO_POINTER (ival);
161  }
162 
163  PWARN ("unhandled parameter type %s for paramter %s",
164  G_PARAM_SPEC_TYPE_NAME (gps), getter->param_name);
165  return NULL;
166 }
167 
168 static double
169 qof_gobject_double_getter (gpointer data, QofParam * getter)
170 {
171  GObject *gob = data;
172  double fval;
173 
174  GParamSpec *gps = getter->param_userdata;
175 
176  /* Note that the return type must actually be of type
177  * getter->param_type but we just follow the hard-coded
178  * mapping below ... */
179  if (G_IS_PARAM_SPEC_FLOAT (gps))
180  {
181  GValue gval;
182  g_value_init (&gval, G_TYPE_FLOAT);
183  g_object_get_property (gob, getter->param_name, &gval);
184 
185  fval = g_value_get_float (&gval);
186  return fval;
187  }
188  else if (G_IS_PARAM_SPEC_DOUBLE (gps))
189  {
190  GValue gval;
191  g_value_init (&gval, G_TYPE_DOUBLE);
192  g_object_get_property (gob, getter->param_name, &gval);
193 
194  fval = g_value_get_double (&gval);
195  return fval;
196  }
197 
198  PWARN ("unhandled parameter type %s for paramter %s",
199  G_PARAM_SPEC_TYPE_NAME (gps), getter->param_name);
200  return 0.0;
201 }
202 
203 /* =================================================================== */
204 /* Loop over every instance of the given type in the collection
205  * of instances that we have on hand.
206  */
207 static void
208 qof_gobject_foreach (QofCollection * coll, QofEntityForeachCB cb,
209  gpointer ud)
210 {
211  GSList *n;
212  n = qof_collection_get_data (coll);
213  for (; n; n = n->next)
214  {
215  cb (n->data, ud);
216  }
217 }
218 
219 /* =================================================================== */
220 
221 void
222 qof_gobject_register (QofType e_type, GObjectClass * obclass)
223 {
224  guint i, j;
225  QofParam *qof_param_list, *qpar;
226  QofObject *class_def;
227  GParamSpec **prop_list, *gparam;
228  guint n_props;
229 
230  /* Get the GObject properties, convert to QOF properties */
231  prop_list = g_object_class_list_properties (obclass, &n_props);
232 
233  qof_param_list = g_new0 (QofParam, n_props);
234  paramList = g_slist_prepend (paramList, qof_param_list);
235 
236  PINFO ("object %s has %d props", e_type, n_props);
237  j = 0;
238  for (i = 0; i < n_props; i++)
239  {
240  gparam = prop_list[i];
241  qpar = &qof_param_list[j];
242 
243  PINFO ("param %d %s is type %s",
244  i, gparam->name, G_PARAM_SPEC_TYPE_NAME (gparam));
245 
246  qpar->param_name = g_param_spec_get_name (gparam);
247  qpar->param_getfcn = (QofAccessFunc) qof_gobject_getter;
248  qpar->param_setfcn = NULL;
249  qpar->param_userdata = gparam;
250  if ((G_IS_PARAM_SPEC_INT (gparam)) ||
251  (G_IS_PARAM_SPEC_UINT (gparam)) ||
252  (G_IS_PARAM_SPEC_ENUM (gparam)) ||
253  (G_IS_PARAM_SPEC_FLAGS (gparam)))
254  {
255  qpar->param_type = QOF_TYPE_INT32;
256  j++;
257  }
258  else if ((G_IS_PARAM_SPEC_INT64 (gparam)) ||
259  (G_IS_PARAM_SPEC_UINT64 (gparam)))
260  {
261  qpar->param_type = QOF_TYPE_INT64;
262  j++;
263  }
264  else if (G_IS_PARAM_SPEC_BOOLEAN (gparam))
265  {
266  qpar->param_type = QOF_TYPE_BOOLEAN;
267  j++;
268  }
269  else if (G_IS_PARAM_SPEC_STRING (gparam))
270  {
271  qpar->param_type = QOF_TYPE_STRING;
272  j++;
273  }
274  else if ((G_IS_PARAM_SPEC_POINTER (gparam)) ||
275  (G_IS_PARAM_SPEC_OBJECT (gparam)))
276  {
277  /* No-op, silently ignore. Someday we should handle this ... */
278  }
279  else if ((G_IS_PARAM_SPEC_FLOAT (gparam)) ||
280  (G_IS_PARAM_SPEC_DOUBLE (gparam)))
281  {
282  qpar->param_getfcn = (QofAccessFunc) qof_gobject_double_getter;
283  qpar->param_type = QOF_TYPE_DOUBLE;
284  j++;
285  }
286  else if (G_IS_PARAM_SPEC_CHAR (gparam))
287  {
288  qpar->param_type = QOF_TYPE_CHAR;
289  j++;
290  }
291  else
292  {
293  PWARN ("Unknown/unhandled parameter type %s on %s:%s\n",
294  G_PARAM_SPEC_TYPE_NAME (gparam), e_type, qpar->param_name);
295  }
296  }
297 
298  /* NULL-terminated list! */
299  qof_param_list[j].param_type = NULL;
300 
301  qof_class_register (e_type, NULL, qof_param_list);
302 
303  /* ------------------------------------------------------ */
304  /* Now do the class itself */
305  class_def = g_new0 (QofObject, 1);
306  classList = g_slist_prepend (classList, class_def);
307 
308  class_def->interface_version = QOF_OBJECT_VERSION;
309  class_def->e_type = e_type;
310  /* We could let the user specify a "nick" here, but
311  * the actual class name seems reasonable, e.g. for debugging. */
312  class_def->type_label = G_OBJECT_CLASS_NAME (obclass);
313  class_def->create = NULL;
314  class_def->book_begin = NULL;
315  class_def->book_end = NULL;
316  class_def->is_dirty = NULL;
317  class_def->mark_clean = NULL;
318  class_def->foreach = qof_gobject_foreach;
319  class_def->printable = NULL;
320  class_def->version_cmp = NULL;
321 
322  qof_object_register (class_def);
323 }
324 
325 /* ======================= END OF FILE ================================ */