mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-26 02:40:43 -06:00
0b8a944f30
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@11964 57a11ea4-9604-0410-9ed3-97b8803252fd
327 lines
9.2 KiB
C
327 lines
9.2 KiB
C
/********************************************************************\
|
|
* 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; i<n_props; i++)
|
|
{
|
|
gparam = prop_list[i];
|
|
qpar = &qof_param_list[j];
|
|
|
|
PINFO ("param %d %s is type %s",
|
|
i, gparam->name, 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 ================================ */
|