1 /*
2 * Copyright (C) 2008 - 2011 Murray Cumming <murrayc@murrayc.com>
3 * Copyright (C) 2008 - 2013 Vivien Malerba <malerba@gnome-db.org>
4 * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
5 * Copyright (C) 2010 David King <davidk@openismus.com>
6 * Copyright (C) 2013 Daniel Espinosa <esodan@gmail.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24 #include <stdarg.h>
25 #include <string.h>
26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
28 #endif
29 #include <glib/gi18n-lib.h>
30 #ifdef HAVE_LOCALE_H
31 #include <locale.h>
32 #endif
33 #include "gda-set.h"
34 #include "gda-marshal.h"
35 #include "gda-data-model.h"
36 #include "gda-data-model-import.h"
37 #include "gda-holder.h"
38 #include "gda-connection.h"
39 #include "gda-server-provider.h"
40 #include "gda-util.h"
41 #include <libgda/gda-custom-marshal.h>
42 #include <libgda/gda-types.h>
43
44 extern xmlDtdPtr gda_paramlist_dtd;
45 extern gchar *gda_lang_locale;
46
47 #ifdef GSEAL_ENABLE
48 /**
49 * GdaSetGroup:
50 * @nodes: (element-type Gda.SetNode): list of GdaSetNode, at least one entry
51 * @nodes_source: (allow-none): if NULL, then @nodes contains exactly one entry
52 *
53 * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
54 * Don't try to use #gda_set_group_free on a struct that was created manually.
55 */
56 struct _GdaSetGroup {
57 GSList *nodes; /* list of GdaSetNode, at least one entry */
58 GdaSetSource *nodes_source; /* if NULL, then @nodes contains exactly one entry */
59
60 /*< private >*/
61 /* Padding for future expansion */
62 gpointer _gda_reserved1;
63 gpointer _gda_reserved2;
64 };
65 #else
66 #endif
67 /*
68 Register GdaSetGroup type
69 */
70 GType
gda_set_group_get_type(void)71 gda_set_group_get_type (void)
72 {
73 static GType type = 0;
74
75 if (G_UNLIKELY (type == 0)) {
76 if (type == 0)
77 type = g_boxed_type_register_static ("GdaSetGroup",
78 (GBoxedCopyFunc) gda_set_group_copy,
79 (GBoxedFreeFunc) gda_set_group_free);
80 }
81
82 return type;
83 }
84
85 /**
86 * gda_set_group_new:
87 * @node: a #GdaSetNode struct
88 *
89 * Creates a new #GdaSetGroup struct. If @source is %NULL then new group contains
90 * just one #GdaSetNode.
91 *
92 * Return: (transfer full): a new #GdaSetGroup struct.
93 *
94 * Since: 5.2
95 */
96 GdaSetGroup*
gda_set_group_new(GdaSetNode * node)97 gda_set_group_new (GdaSetNode *node)
98 {
99 GdaSetGroup *sg;
100
101 g_return_val_if_fail (node, NULL);
102
103 sg = g_new0 (GdaSetGroup, 1);
104 sg->nodes_source = NULL;
105 sg->nodes = NULL;
106 sg->nodes = g_slist_append (sg->nodes, node);
107 return sg;
108 }
109
110 /**
111 * gda_set_group_copy:
112 * @sg: a #GdaSetGroup
113 *
114 * Copy constructor.
115 *
116 * Returns: a new #GdaSetGroup
117 *
118 * Since: 5.2
119 */
120 GdaSetGroup *
gda_set_group_copy(GdaSetGroup * sg)121 gda_set_group_copy (GdaSetGroup *sg)
122 {
123 g_return_val_if_fail (sg, NULL);
124
125 GdaSetGroup *n;
126 n = g_new0 (GdaSetGroup, 1);
127 n->nodes_source = sg->nodes_source;
128 n->nodes = g_slist_copy (sg->nodes);
129 return n;
130 }
131
132 /**
133 * gda_set_group_free:
134 * @sg: (allow-none): a #GdaSetGroup struct to free
135 *
136 * Frees any resources taken by @sg struct. If @sg is %NULL, then nothing happens.
137 *
138 * Since: 5.2
139 */
140 void
gda_set_group_free(GdaSetGroup * sg)141 gda_set_group_free (GdaSetGroup *sg)
142 {
143 g_return_if_fail(sg);
144 g_slist_free (sg->nodes);
145 g_free (sg);
146 }
147
148 /**
149 * gda_set_group_set_source:
150 * @sg: a #GdaSetGroup
151 * @source: a #GdaSetSource to set
152 *
153 * Since: 5.2
154 */
155 void
gda_set_group_set_source(GdaSetGroup * sg,GdaSetSource * source)156 gda_set_group_set_source (GdaSetGroup *sg, GdaSetSource *source)
157 {
158 g_return_if_fail (sg);
159 sg->nodes_source = source;
160 }
161
162 /**
163 * gda_set_group_get_source:
164 * @sg: a #GdaSetGroup
165 *
166 * Returns: a #GdaSetSource. If %NULL then @sg contains just one element.
167 *
168 * Since: 5.2
169 */
170 GdaSetSource*
gda_set_group_get_source(GdaSetGroup * sg)171 gda_set_group_get_source (GdaSetGroup *sg)
172 {
173 g_return_val_if_fail (sg, NULL);
174 return sg->nodes_source;
175 }
176
177 /**
178 * gda_set_group_add_node:
179 * @sg: a #GdaSetGroup
180 * @node: a #GdaSetNode to set
181 *
182 * Since: 5.2
183 */
184 void
gda_set_group_add_node(GdaSetGroup * sg,GdaSetNode * node)185 gda_set_group_add_node (GdaSetGroup *sg, GdaSetNode *node)
186 {
187 g_return_if_fail (sg);
188 g_return_if_fail (node);
189 sg->nodes = g_slist_append (sg->nodes, node);
190 }
191
192 /**
193 * gda_set_group_get_node:
194 * @sg: a #GdaSetGroup
195 *
196 * This method always return first #GdaSetNode in @sg.
197 *
198 * Returns: first #GdaSetNode in @sg.
199 *
200 * Since: 5.2
201 */
202 GdaSetNode*
gda_set_group_get_node(GdaSetGroup * sg)203 gda_set_group_get_node (GdaSetGroup *sg)
204 {
205 g_return_val_if_fail (sg, NULL);
206 g_return_val_if_fail (sg->nodes, NULL);
207 return GDA_SET_NODE (sg->nodes->data);
208 }
209
210 /**
211 * gda_set_group_get_nodes:
212 * @sg: a #GdaSetGroup
213 *
214 * Returns a #GSList with the #GdaSetNode grouped by @sg. You must use
215 * #g_slist_free on returned list.
216 *
217 * Returns: (transfer none) (element-type Gda.SetNode): a #GSList with all nodes in @sg.
218 *
219 * Since: 5.2
220 */
221 GSList*
gda_set_group_get_nodes(GdaSetGroup * sg)222 gda_set_group_get_nodes (GdaSetGroup *sg)
223 {
224 g_return_val_if_fail (sg, NULL);
225 g_return_val_if_fail (sg->nodes, NULL);
226 return sg->nodes;
227 }
228
229 /**
230 * gda_set_group_get_n_nodes:
231 * @sg: a #GdaSetGroup
232 *
233 * Returns: number of nodes in @sg.
234 *
235 * Since: 5.2
236 */
237 gint
gda_set_group_get_n_nodes(GdaSetGroup * sg)238 gda_set_group_get_n_nodes (GdaSetGroup *sg)
239 {
240 g_return_val_if_fail (sg, -1);
241 return g_slist_length (sg->nodes);
242 }
243
244 #ifdef GSEAL_ENABLE
245 /**
246 * GdaSetSource:
247 * @data_model: Can't be NULL
248 * @nodes: (element-type Gda.SetNode): list of #GdaSetNode for which source_model == @data_model
249 *
250 * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
251 * Don't try to use #gda_set_source_free on a struct that was created manually.
252 **/
253 struct _GdaSetSource {
254 GdaDataModel *data_model; /* Can't be NULL */
255 GSList *nodes; /* list of #GdaSetNode for which source_model == @data_model */
256
257 /*< private >*/
258 /* Padding for future expansion */
259 gpointer _gda_reserved1;
260 gpointer _gda_reserved2;
261 gpointer _gda_reserved3;
262 gpointer _gda_reserved4;
263 };
264 #else
265 #endif
266
267 /*
268 Register GdaSetSource type
269 */
270 GType
gda_set_source_get_type(void)271 gda_set_source_get_type (void)
272 {
273 static GType type = 0;
274
275 if (G_UNLIKELY (type == 0)) {
276 if (type == 0)
277 type = g_boxed_type_register_static ("GdaSetSource",
278 (GBoxedCopyFunc) gda_set_source_copy,
279 (GBoxedFreeFunc) gda_set_source_free);
280 }
281
282 return type;
283 }
284
285 /**
286 * gda_set_source_new:
287 * @model: a #GdaDataModel
288 *
289 * Creates a new #GdaSetSource struct.
290 *
291 * Return: (transfer full): a new #GdaSetSource struct.
292 *
293 * Since: 5.2
294 */
295 GdaSetSource*
gda_set_source_new(GdaDataModel * model)296 gda_set_source_new (GdaDataModel *model)
297 {
298 g_return_val_if_fail (model != NULL && GDA_IS_DATA_MODEL (model), NULL);
299 GdaSetSource *s = g_new0 (GdaSetSource, 1);
300 s->nodes = NULL;
301 s->data_model = g_object_ref (model);
302
303 return s;
304 }
305
306 /**
307 * gda_set_source_copy:
308 * @s: a #GdaSetGroup
309 *
310 * Copy constructor.
311 *
312 * Returns: a new #GdaSetSource
313 *
314 * Since: 5.2
315 */
316 GdaSetSource *
gda_set_source_copy(GdaSetSource * s)317 gda_set_source_copy (GdaSetSource *s)
318 {
319 GdaSetSource *n;
320 g_return_val_if_fail (s, NULL);
321 n = gda_set_source_new (gda_set_source_get_data_model (s));
322 n->nodes = g_slist_copy (s->nodes);
323 return n;
324 }
325
326 /**
327 * gda_set_source_free:
328 * @s: (allow-none): a #GdaSetSource struct to free
329 *
330 * Frees any resources taken by @s struct. If @s is %NULL, then nothing happens.
331 *
332 * Since: 5.2
333 */
334 void
gda_set_source_free(GdaSetSource * s)335 gda_set_source_free (GdaSetSource *s)
336 {
337 g_return_if_fail(s);
338 g_object_unref (s->data_model);
339 g_slist_free (s->nodes); /* FIXME: A source must own its nodes, then they must be freed here
340 this leaves to others responsability free nodes BEFORE
341 to free this source */
342 g_free (s);
343 }
344
345 /**
346 * gda_set_source_get_data_model:
347 * @s: a #GdaSetSource
348 *
349 * Returns: (transfer none): a #GdaDataModel used by @s
350 *
351 * Since: 5.2
352 */
353 GdaDataModel*
gda_set_source_get_data_model(GdaSetSource * s)354 gda_set_source_get_data_model (GdaSetSource *s)
355 {
356 g_return_val_if_fail (s, NULL);
357 return s->data_model;
358 }
359
360 /**
361 * gda_set_source_set_data_model:
362 * @s: a #GdaSetSource struct to free
363 * @model: a #GdaDataModel
364 *
365 * Set a #GdaDataModel
366 *
367 * Since: 5.2
368 */
369 void
gda_set_source_set_data_model(GdaSetSource * s,GdaDataModel * model)370 gda_set_source_set_data_model (GdaSetSource *s, GdaDataModel *model)
371 {
372 g_return_if_fail (s);
373 g_return_if_fail (GDA_IS_DATA_MODEL (model));
374 s->data_model = g_object_ref (model);
375 }
376
377 /**
378 * gda_set_source_add_node:
379 * @s: a #GdaSetSource
380 * @node: a #GdaSetNode to add
381 *
382 * Set a #GdaDataModel
383 *
384 * Since: 5.2
385 */
386 void
gda_set_source_add_node(GdaSetSource * s,GdaSetNode * node)387 gda_set_source_add_node (GdaSetSource *s, GdaSetNode *node)
388 {
389 g_return_if_fail (s);
390 g_return_if_fail (node);
391 s->nodes = g_slist_append (s->nodes, node);
392 }
393
394 /**
395 * gda_set_source_get_nodes:
396 * @s: a #GdaSetSource
397 *
398 * Returns: (transfer none) (element-type Gda.SetNode): a list of #GdaSetNode structs
399 *
400 * Since: 5.2
401 */
402 GSList*
gda_set_source_get_nodes(GdaSetSource * s)403 gda_set_source_get_nodes (GdaSetSource *s)
404 {
405 g_return_val_if_fail (s, NULL);
406 g_return_val_if_fail (s->nodes, NULL);
407 return s->nodes;
408 }
409
410 /**
411 * gda_set_source_get_n_nodes:
412 * @s: a #GdaSetSource
413 *
414 * Returns: number of nodes in @sg.
415 *
416 * Since: 5.2
417 */
418 gint
gda_set_source_get_n_nodes(GdaSetSource * s)419 gda_set_source_get_n_nodes (GdaSetSource *s)
420 {
421 g_return_val_if_fail (s, -1);
422 return g_slist_length (s->nodes);
423 }
424 #ifdef GSEAL_ENABLE
425 /**
426 * GdaSetNode:
427 * @holder: a #GdaHolder. It can't be NULL
428 * @source_model: a #GdaDataModel. It could be NULL
429 * @source_column: a #gint with the number of column in @source_model
430 *
431 * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
432 * Don't try to use #gda_set_node_free on a struct that was created manually.
433 */
434 struct _GdaSetNode {
435 GdaHolder *holder; /* Can't be NULL */
436 GdaDataModel *source_model; /* may be NULL */
437 gint source_column; /* unused if @source_model is NULL */
438
439 /*< private >*/
440 /* Padding for future expansion */
441 gpointer _gda_reserved1;
442 gpointer _gda_reserved2;
443 };
444 #endif
445 /*
446 Register GdaSetNode type
447 */
448 GType
gda_set_node_get_type(void)449 gda_set_node_get_type (void)
450 {
451 static GType type = 0;
452
453 if (G_UNLIKELY (type == 0)) {
454 if (type == 0)
455 type = g_boxed_type_register_static ("GdaSetNode",
456 (GBoxedCopyFunc) gda_set_node_copy,
457 (GBoxedFreeFunc) gda_set_node_free);
458 }
459
460 return type;
461 }
462
463 /**
464 * gda_set_node_new:
465 * @holder: a #GdaHolder to used by new #GdaSetNode
466 *
467 * Creates a new #GdaSetNode struct.
468 *
469 * Return: (transfer full): a new #GdaSetNode struct.
470 *
471 * Since: 5.2
472 */
473 GdaSetNode*
gda_set_node_new(GdaHolder * holder)474 gda_set_node_new (GdaHolder *holder)
475 {
476 g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
477 GdaSetNode *n = g_new0 (GdaSetNode, 1);
478 n->holder = holder;
479 n->source_model = NULL;
480 return n;
481 }
482
483 /**
484 * gda_set_node_copy:
485 * @node: a #GdaSetNode to copy from
486 *
487 * Copy constructor.
488 *
489 * Returns: a new #GdaSetNode
490 *
491 * Since: 5.2
492 */
493 GdaSetNode *
gda_set_node_copy(GdaSetNode * node)494 gda_set_node_copy (GdaSetNode *node)
495 {
496 g_return_val_if_fail (node, NULL);
497
498 GdaSetNode *n;
499 n = gda_set_node_new (gda_set_node_get_holder (node));
500 gda_set_node_set_source_column (n, gda_set_node_get_source_column (node));
501 gda_set_node_set_holder (n, gda_set_node_get_holder (node));
502 gda_set_node_set_data_model (n, gda_set_node_get_data_model (node));
503 return n;
504 }
505
506 /**
507 * gda_set_node_free:
508 * @node: (allow-none): a #GdaSetNode struct to free
509 *
510 * Frees any resources taken by @node struct. If @node is %NULL, then nothing happens.
511 *
512 * Since: 5.2
513 */
514 void
gda_set_node_free(GdaSetNode * node)515 gda_set_node_free (GdaSetNode *node)
516 {
517 if (node == NULL)
518 return;
519 g_free (node);
520 }
521
522 /**
523 * gda_set_node_get_holder:
524 * @node: a #GdaSetNode struct to get holder from
525 *
526 * Returns: (transfer none): the #GdaHolder used by @node
527 *
528 * Since: 5.2
529 */
530 GdaHolder*
gda_set_node_get_holder(GdaSetNode * node)531 gda_set_node_get_holder (GdaSetNode *node)
532 {
533 g_return_val_if_fail (node, NULL);
534 return node->holder;
535 }
536
537 /**
538 * gda_set_node_set_holder:
539 * @node: a #GdaSetNode struct to set holder to
540 *
541 * Set a #GdaHolder to @node.
542 *
543 * Since: 5.2
544 */
545 void
gda_set_node_set_holder(GdaSetNode * node,GdaHolder * holder)546 gda_set_node_set_holder (GdaSetNode *node, GdaHolder *holder)
547 {
548 g_return_if_fail (node);
549 g_return_if_fail (GDA_IS_HOLDER (holder));
550 node->holder = holder;
551 }
552
553 /**
554 * gda_set_node_get_data_model:
555 * @node: a #GdaSetNode struct to get holder from
556 *
557 * Returns: (transfer none): the #GdaDataModel used by @node
558 *
559 * Since: 5.2
560 */
561 GdaDataModel*
gda_set_node_get_data_model(GdaSetNode * node)562 gda_set_node_get_data_model (GdaSetNode *node)
563 {
564 g_return_val_if_fail (node, NULL);
565 return node->source_model;
566 }
567
568 /**
569 * gda_set_node_set_data_model:
570 * @node: a #GdaSetNode struct to set data model to
571 * @model: (allow-none): a #GdaDataModel to be used by @node
572 *
573 * Set a #GdaDataModel to be used by @node. @model increment its reference
574 * counting when set. Internally referenced column number is set to first column
575 * in @model.
576 *
577 * Since: 5.2
578 */
579 void
gda_set_node_set_data_model(GdaSetNode * node,GdaDataModel * model)580 gda_set_node_set_data_model (GdaSetNode *node, GdaDataModel *model)
581 {
582 g_return_if_fail (node);
583 if (GDA_IS_DATA_MODEL (model)) {
584 node->source_model = model;
585 node->source_column = 0;
586 }
587 else {
588 node->source_model = NULL;
589 node->source_column = -1;
590 }
591 }
592
593 /**
594 * gda_set_node_get_source_column:
595 * @node: a #GdaSetNode struct to get column source from
596 *
597 * Returns: the number of column referenced in a given #GdaDataModel. If negative
598 * no column is referenced or no #GdaDataModel is used by @node.
599 *
600 * Since: 5.2
601 */
602 gint
gda_set_node_get_source_column(GdaSetNode * node)603 gda_set_node_get_source_column (GdaSetNode *node)
604 {
605 g_return_val_if_fail (node, -1);
606 return node->source_column;
607 }
608
609 /**
610 * gda_set_node_set_source_column:
611 * @node: a #GdaSetNode struct to set column source to, from an used data model
612 *
613 * Set column number in the #GdaDataModel used @node. If no #GdaDataModel is set
614 * then column is set to invalid (-1);
615 *
616 * Since: 5.2
617 */
618 void
gda_set_node_set_source_column(GdaSetNode * node,gint column)619 gda_set_node_set_source_column (GdaSetNode *node, gint column)
620 {
621 g_return_if_fail (column >= 0);
622 if (GDA_IS_DATA_MODEL (node->source_model)) {
623 if (column < gda_data_model_get_n_columns (node->source_model))
624 node->source_column = column;
625 }
626 }
627
628 /*
629 * Main static functions
630 */
631 static void gda_set_class_init (GdaSetClass *class);
632 static void gda_set_init (GdaSet *set);
633 static void gda_set_dispose (GObject *object);
634 static void gda_set_finalize (GObject *object);
635
636 static void set_remove_node (GdaSet *set, GdaSetNode *node);
637 static void set_remove_source (GdaSet *set, GdaSetSource *source);
638
639
640 static void changed_holder_cb (GdaHolder *holder, GdaSet *dataset);
641 static GError *validate_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *dataset);
642 static void source_changed_holder_cb (GdaHolder *holder, GdaSet *dataset);
643 static void att_holder_changed_cb (GdaHolder *holder, const gchar *att_name, const GValue *att_value, GdaSet *dataset);
644 static void holder_notify_cb (GdaHolder *holder, GParamSpec *pspec, GdaSet *dataset);
645
646
647 static void compute_public_data (GdaSet *set);
648 static gboolean gda_set_real_add_holder (GdaSet *set, GdaHolder *holder);
649
650 /* get a pointer to the parents to be able to call their destructor */
651 static GObjectClass *parent_class = NULL;
652
653 /* properties */
654 enum
655 {
656 PROP_0,
657 PROP_ID,
658 PROP_NAME,
659 PROP_DESCR,
660 PROP_HOLDERS,
661 PROP_VALIDATE_CHANGES
662 };
663
664 /* signals */
665 enum
666 {
667 HOLDER_CHANGED,
668 PUBLIC_DATA_CHANGED,
669 HOLDER_ATTR_CHANGED,
670 VALIDATE_HOLDER_CHANGE,
671 VALIDATE_SET,
672 HOLDER_TYPE_SET,
673 SOURCE_MODEL_CHANGED,
674 LAST_SIGNAL
675 };
676
677 static gint gda_set_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0, 0 };
678
679
680 /* private structure */
681 struct _GdaSetPrivate
682 {
683 gchar *id;
684 gchar *name;
685 gchar *descr;
686 GHashTable *holders_hash; /* key = GdaHoler ID, value = GdaHolder */
687 GArray *holders_array;
688 gboolean read_only;
689 gboolean validate_changes;
690 };
691
692 static void
gda_set_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)693 gda_set_set_property (GObject *object,
694 guint param_id,
695 const GValue *value,
696 GParamSpec *pspec)
697 {
698 GdaSet* set;
699 set = GDA_SET (object);
700
701 switch (param_id) {
702 case PROP_ID:
703 g_free (set->priv->id);
704 set->priv->id = g_value_dup_string (value);
705 break;
706 case PROP_NAME:
707 g_free (set->priv->name);
708 set->priv->name = g_value_dup_string (value);
709 break;
710 case PROP_DESCR:
711 g_free (set->priv->descr);
712 set->priv->descr = g_value_dup_string (value);
713 break;
714 case PROP_HOLDERS: {
715 /* add the holders */
716 GSList* holders;
717 for (holders = (GSList*) g_value_get_pointer (value); holders; holders = holders->next)
718 gda_set_real_add_holder (set, GDA_HOLDER (holders->data));
719 compute_public_data (set);
720 break;
721 }
722 case PROP_VALIDATE_CHANGES:
723 if (set->priv->validate_changes != g_value_get_boolean (value)) {
724 GSList *list;
725 set->priv->validate_changes = g_value_get_boolean (value);
726 for (list = set->holders; list; list = list->next) {
727 GdaHolder *holder = (GdaHolder*) list->data;
728 g_object_set ((GObject*) holder, "validate-changes",
729 set->priv->validate_changes, NULL);
730 if (set->priv->validate_changes)
731 g_signal_connect ((GObject*) holder, "validate-change",
732 G_CALLBACK (validate_change_holder_cb), set);
733 else
734 g_signal_handlers_disconnect_by_func ((GObject*) holder,
735 G_CALLBACK (validate_change_holder_cb),
736 set);
737 }
738 }
739 break;
740 default:
741 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
742 break;
743 }
744 }
745
746 static void
gda_set_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)747 gda_set_get_property (GObject *object,
748 guint param_id,
749 GValue *value,
750 GParamSpec *pspec)
751 {
752 GdaSet* set;
753 set = GDA_SET (object);
754
755 switch (param_id) {
756 case PROP_ID:
757 g_value_set_string (value, set->priv->id);
758 break;
759 case PROP_NAME:
760 if (set->priv->name)
761 g_value_set_string (value, set->priv->name);
762 else
763 g_value_set_string (value, set->priv->id);
764 break;
765 case PROP_DESCR:
766 g_value_set_string (value, set->priv->descr);
767 break;
768 case PROP_VALIDATE_CHANGES:
769 g_value_set_boolean (value, set->priv->validate_changes);
770 break;
771 default:
772 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
773 break;
774 }
775 }
776
777 /* module error */
gda_set_error_quark(void)778 GQuark gda_set_error_quark (void)
779 {
780 static GQuark quark;
781 if (!quark)
782 quark = g_quark_from_static_string ("gda_set_error");
783 return quark;
784 }
785
786
787 GType
gda_set_get_type(void)788 gda_set_get_type (void)
789 {
790 static GType type = 0;
791
792 if (G_UNLIKELY (type == 0)) {
793 static GMutex registering;
794 static const GTypeInfo info = {
795 sizeof (GdaSetClass),
796 (GBaseInitFunc) NULL,
797 (GBaseFinalizeFunc) NULL,
798 (GClassInitFunc) gda_set_class_init,
799 NULL,
800 NULL,
801 sizeof (GdaSet),
802 0,
803 (GInstanceInitFunc) gda_set_init,
804 0
805 };
806
807 g_mutex_lock (®istering);
808 if (type == 0)
809 type = g_type_register_static (G_TYPE_OBJECT, "GdaSet", &info, 0);
810 g_mutex_unlock (®istering);
811 }
812
813 return type;
814 }
815
816 static gboolean
validate_accumulator(G_GNUC_UNUSED GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,G_GNUC_UNUSED gpointer data)817 validate_accumulator (G_GNUC_UNUSED GSignalInvocationHint *ihint,
818 GValue *return_accu,
819 const GValue *handler_return,
820 G_GNUC_UNUSED gpointer data)
821 {
822 GError *error;
823
824 error = g_value_get_boxed (handler_return);
825 g_value_set_boxed (return_accu, error);
826
827 return error ? FALSE : TRUE; /* stop signal if an error has been set */
828 }
829
830 static GError *
m_validate_holder_change(G_GNUC_UNUSED GdaSet * set,G_GNUC_UNUSED GdaHolder * holder,G_GNUC_UNUSED const GValue * new_value)831 m_validate_holder_change (G_GNUC_UNUSED GdaSet *set, G_GNUC_UNUSED GdaHolder *holder,
832 G_GNUC_UNUSED const GValue *new_value)
833 {
834 return NULL;
835 }
836
837 static GError *
m_validate_set(G_GNUC_UNUSED GdaSet * set)838 m_validate_set (G_GNUC_UNUSED GdaSet *set)
839 {
840 return NULL;
841 }
842
843 static void
gda_set_class_init(GdaSetClass * class)844 gda_set_class_init (GdaSetClass *class)
845 {
846 GObjectClass *object_class = G_OBJECT_CLASS (class);
847
848 parent_class = g_type_class_peek_parent (class);
849
850 gda_set_signals[HOLDER_CHANGED] =
851 g_signal_new ("holder-changed",
852 G_TYPE_FROM_CLASS (object_class),
853 G_SIGNAL_RUN_FIRST,
854 G_STRUCT_OFFSET (GdaSetClass, holder_changed),
855 NULL, NULL,
856 _gda_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
857 GDA_TYPE_HOLDER);
858
859 /**
860 * GdaSet::validate-holder-change:
861 * @set: the #GdaSet
862 * @holder: the #GdaHolder which is going to change
863 * @new_value: the proposed new value for @holder
864 *
865 * Gets emitted when a #GdaHolder's in @set is going to change its value. One can connect to
866 * this signal to control which values @holder can have (for example to implement some business rules)
867 *
868 * Returns: NULL if @holder is allowed to change its value to @new_value, or a #GError
869 * otherwise.
870 */
871 gda_set_signals[VALIDATE_HOLDER_CHANGE] =
872 g_signal_new ("validate-holder-change",
873 G_TYPE_FROM_CLASS (object_class),
874 G_SIGNAL_RUN_LAST,
875 G_STRUCT_OFFSET (GdaSetClass, validate_holder_change),
876 validate_accumulator, NULL,
877 _gda_marshal_ERROR__OBJECT_VALUE, G_TYPE_ERROR, 2,
878 GDA_TYPE_HOLDER, G_TYPE_VALUE);
879 /**
880 * GdaSet::validate-set:
881 * @set: the #GdaSet
882 *
883 * Gets emitted when gda_set_is_valid() is called, use
884 * this signal to control which combination of values @set's holder can have (for example to implement some business rules)
885 *
886 * Returns: NULL if @set's contents has been validated, or a #GError
887 * otherwise.
888 */
889 gda_set_signals[VALIDATE_SET] =
890 g_signal_new ("validate-set",
891 G_TYPE_FROM_CLASS (object_class),
892 G_SIGNAL_RUN_LAST,
893 G_STRUCT_OFFSET (GdaSetClass, validate_set),
894 validate_accumulator, NULL,
895 _gda_marshal_ERROR__VOID, G_TYPE_ERROR, 0);
896 /**
897 * GdaSet::holder-attr-changed:
898 * @set: the #GdaSet
899 * @holder: the GdaHolder for which an attribute changed
900 * @attr_name: attribute's name
901 * @attr_value: attribute's value
902 *
903 * Gets emitted when an attribute for any of the #GdaHolder objects managed by @set has changed
904 */
905 gda_set_signals[HOLDER_ATTR_CHANGED] =
906 g_signal_new ("holder-attr-changed",
907 G_TYPE_FROM_CLASS (object_class),
908 G_SIGNAL_RUN_FIRST,
909 G_STRUCT_OFFSET (GdaSetClass, holder_attr_changed),
910 NULL, NULL,
911 _gda_marshal_VOID__OBJECT_STRING_VALUE, G_TYPE_NONE, 3,
912 GDA_TYPE_HOLDER, G_TYPE_STRING, G_TYPE_VALUE);
913 /**
914 * GdaSet::public-data-changed:
915 * @set: the #GdaSet
916 *
917 * Gets emitted when @set's public data (#GdaSetNode, #GdaSetGroup or #GdaSetSource values) have changed
918 */
919 gda_set_signals[PUBLIC_DATA_CHANGED] =
920 g_signal_new ("public-data-changed",
921 G_TYPE_FROM_CLASS (object_class),
922 G_SIGNAL_RUN_FIRST,
923 G_STRUCT_OFFSET (GdaSetClass, public_data_changed),
924 NULL, NULL,
925 _gda_marshal_VOID__VOID, G_TYPE_NONE, 0);
926
927 /**
928 * GdaSet::holder-type-set:
929 * @set: the #GdaSet
930 * @holder: the #GdaHolder for which the #GType has been set
931 *
932 * Gets emitted when @holder in @set has its type finally set, in case
933 * it was #GDA_TYPE_NULL
934 *
935 * Since: 4.2
936 */
937 gda_set_signals[HOLDER_TYPE_SET] =
938 g_signal_new ("holder-type-set",
939 G_TYPE_FROM_CLASS (object_class),
940 G_SIGNAL_RUN_FIRST,
941 G_STRUCT_OFFSET (GdaSetClass, holder_type_set),
942 NULL, NULL,
943 _gda_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
944 GDA_TYPE_HOLDER);
945
946 /**
947 * GdaSet::source-model-changed:
948 * @set: the #GdaSet
949 * @source: the #GdaSetSource for which the @data_model attribute has changed
950 *
951 * Gets emitted when the data model in @source has changed
952 *
953 * Since: 4.2
954 */
955 gda_set_signals[SOURCE_MODEL_CHANGED] =
956 g_signal_new ("source-model-changed",
957 G_TYPE_FROM_CLASS (object_class),
958 G_SIGNAL_RUN_FIRST,
959 G_STRUCT_OFFSET (GdaSetClass, source_model_changed),
960 NULL, NULL,
961 _gda_marshal_VOID__POINTER, G_TYPE_NONE, 1,
962 G_TYPE_POINTER);
963
964
965 class->holder_changed = NULL;
966 class->validate_holder_change = m_validate_holder_change;
967 class->validate_set = m_validate_set;
968 class->holder_attr_changed = NULL;
969 class->public_data_changed = NULL;
970 class->holder_type_set = NULL;
971 class->source_model_changed = NULL;
972
973 /* Properties */
974 object_class->set_property = gda_set_set_property;
975 object_class->get_property = gda_set_get_property;
976 g_object_class_install_property (object_class, PROP_ID,
977 g_param_spec_string ("id", NULL, "Id", NULL,
978 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
979 g_object_class_install_property (object_class, PROP_NAME,
980 g_param_spec_string ("name", NULL, "Name", NULL,
981 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
982 g_object_class_install_property (object_class, PROP_DESCR,
983 g_param_spec_string ("description", NULL, "Description", NULL,
984 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
985 g_object_class_install_property (object_class, PROP_HOLDERS,
986 g_param_spec_pointer ("holders", "GSList of GdaHolders",
987 "GdaHolder objects the set should contain", (
988 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
989 /**
990 * GdaSet:validate-changes:
991 *
992 * Defines if the "validate-set" signal gets emitted when
993 * any holder in the data set changes. This property also affects the
994 * GdaHolder:validate-changes property.
995 *
996 * Since: 5.2.0
997 */
998 g_object_class_install_property (object_class, PROP_VALIDATE_CHANGES,
999 g_param_spec_boolean ("validate-changes", NULL, "Defines if the validate-set signal is emitted", TRUE,
1000 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
1001 object_class->dispose = gda_set_dispose;
1002 object_class->finalize = gda_set_finalize;
1003 }
1004
1005 static void
gda_set_init(GdaSet * set)1006 gda_set_init (GdaSet *set)
1007 {
1008 set->priv = g_new0 (GdaSetPrivate, 1);
1009 set->holders = NULL;
1010 set->nodes_list = NULL;
1011 set->sources_list = NULL;
1012 set->groups_list = NULL;
1013 set->priv->holders_hash = g_hash_table_new (g_str_hash, g_str_equal);
1014 set->priv->holders_array = NULL;
1015 set->priv->read_only = FALSE;
1016 set->priv->validate_changes = TRUE;
1017 }
1018
1019
1020 /**
1021 * gda_set_new:
1022 * @holders: (element-type Gda.Holder) (transfer none): a list of #GdaHolder objects
1023 *
1024 * Creates a new #GdaSet object, and populates it with the list given as argument.
1025 * The list can then be freed as it is copied. All the value holders in @holders are referenced counted
1026 * and modified, so they should not be used anymore afterwards.
1027 *
1028 * Returns: a new #GdaSet object
1029 */
1030 GdaSet *
gda_set_new(GSList * holders)1031 gda_set_new (GSList *holders)
1032 {
1033 GObject *obj;
1034
1035 obj = g_object_new (GDA_TYPE_SET, NULL);
1036 for (; holders; holders = holders->next)
1037 gda_set_real_add_holder ((GdaSet*) obj, GDA_HOLDER (holders->data));
1038 compute_public_data ((GdaSet*) obj);
1039
1040 return (GdaSet*) obj;
1041 }
1042
1043 /**
1044 * gda_set_new_read_only:
1045 * @holders: (element-type Gda.Holder) (transfer none): a list of #GdaHolder objects
1046 *
1047 * Creates a new #GdaSet like gda_set_new(), but does not allow modifications to any of the #GdaHolder
1048 * object in @holders. This function is used for Libgda's database providers' implementation.
1049 *
1050 * Returns: a new #GdaSet object
1051 *
1052 * Since: 4.2
1053 */
1054 GdaSet *
gda_set_new_read_only(GSList * holders)1055 gda_set_new_read_only (GSList *holders)
1056 {
1057 GObject *obj;
1058
1059 obj = g_object_new (GDA_TYPE_SET, NULL);
1060 ((GdaSet*) obj)->priv->read_only = TRUE;
1061 for (; holders; holders = holders->next)
1062 gda_set_real_add_holder ((GdaSet*) obj, GDA_HOLDER (holders->data));
1063 compute_public_data ((GdaSet*) obj);
1064
1065 return (GdaSet*) obj;
1066 }
1067
1068 /**
1069 * gda_set_copy:
1070 * @set: a #GdaSet object
1071 *
1072 * Creates a new #GdaSet object, copy of @set
1073 *
1074 * Returns: (transfer full): a new #GdaSet object
1075 */
1076 GdaSet *
gda_set_copy(GdaSet * set)1077 gda_set_copy (GdaSet *set)
1078 {
1079 GdaSet *copy;
1080 GSList *list, *holders = NULL;
1081 g_return_val_if_fail (GDA_IS_SET (set), NULL);
1082
1083 for (list = set->holders; list; list = list->next)
1084 holders = g_slist_prepend (holders, gda_holder_copy (GDA_HOLDER (list->data)));
1085 holders = g_slist_reverse (holders);
1086
1087 copy = g_object_new (GDA_TYPE_SET, "holders", holders, NULL);
1088 g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
1089 g_slist_free (holders);
1090
1091 return copy;
1092 }
1093
1094 /**
1095 * gda_set_new_inline:
1096 * @nb: the number of value holders which will be contained in the new #GdaSet
1097 * @...: a serie of a (const gchar*) id, (GType) type, and value
1098 *
1099 * Creates a new #GdaSet containing holders defined by each triplet in ...
1100 * For each triplet (id, Glib type and value),
1101 * the value must be of the correct type (gchar * if type is G_STRING, ...)
1102 *
1103 * Note that this function is a utility function and that only a limited set of types are supported. Trying
1104 * to use an unsupported type will result in a warning, and the returned value holder holding a safe default
1105 * value.
1106 *
1107 * Returns: (transfer full): a new #GdaSet object
1108 */
1109 GdaSet *
gda_set_new_inline(gint nb,...)1110 gda_set_new_inline (gint nb, ...)
1111 {
1112 GdaSet *set = NULL;
1113 GSList *holders = NULL;
1114 va_list ap;
1115 gchar *id;
1116 gint i;
1117 gboolean allok = TRUE;
1118
1119 /* build the list of holders */
1120 va_start (ap, nb);
1121 for (i = 0; i < nb; i++) {
1122 GType type;
1123 GdaHolder *holder;
1124 GValue *value;
1125 GError *lerror = NULL;
1126
1127 id = va_arg (ap, char *);
1128 type = va_arg (ap, GType);
1129 holder = (GdaHolder *) g_object_new (GDA_TYPE_HOLDER, "g-type", type, "id", id, NULL);
1130
1131 value = gda_value_new (type);
1132 if (type == G_TYPE_BOOLEAN)
1133 g_value_set_boolean (value, va_arg (ap, int));
1134 else if (type == G_TYPE_STRING)
1135 g_value_set_string (value, va_arg (ap, gchar *));
1136 else if (type == G_TYPE_OBJECT)
1137 g_value_set_object (value, va_arg (ap, gpointer));
1138 else if (type == G_TYPE_INT)
1139 g_value_set_int (value, va_arg (ap, gint));
1140 else if (type == G_TYPE_UINT)
1141 g_value_set_uint (value, va_arg (ap, guint));
1142 else if (type == GDA_TYPE_BINARY)
1143 gda_value_set_binary (value, va_arg (ap, GdaBinary *));
1144 else if (type == G_TYPE_INT64)
1145 g_value_set_int64 (value, va_arg (ap, gint64));
1146 else if (type == G_TYPE_UINT64)
1147 g_value_set_uint64 (value, va_arg (ap, guint64));
1148 else if (type == GDA_TYPE_SHORT)
1149 gda_value_set_short (value, va_arg (ap, int));
1150 else if (type == GDA_TYPE_USHORT)
1151 gda_value_set_ushort (value, va_arg (ap, guint));
1152 else if (type == G_TYPE_CHAR)
1153 g_value_set_schar (value, va_arg (ap, gint));
1154 else if (type == G_TYPE_UCHAR)
1155 g_value_set_uchar (value, va_arg (ap, guint));
1156 else if (type == G_TYPE_FLOAT)
1157 g_value_set_float (value, va_arg (ap, double));
1158 else if (type == G_TYPE_DOUBLE)
1159 g_value_set_double (value, va_arg (ap, gdouble));
1160 else if (type == GDA_TYPE_NUMERIC)
1161 gda_value_set_numeric (value, va_arg (ap, GdaNumeric *));
1162 else if (type == G_TYPE_DATE)
1163 g_value_set_boxed (value, va_arg (ap, GDate *));
1164 else if (type == G_TYPE_LONG)
1165 g_value_set_long (value, va_arg (ap, glong));
1166 else if (type == G_TYPE_ULONG)
1167 g_value_set_ulong (value, va_arg (ap, gulong));
1168 else if (type == G_TYPE_GTYPE)
1169 g_value_set_gtype (value, va_arg(ap, GType));
1170 else if (type == GDA_TYPE_TIMESTAMP)
1171 gda_value_set_timestamp (value, va_arg(ap, GdaTimestamp *));
1172 else if (type == GDA_TYPE_TIME)
1173 gda_value_set_time (value, va_arg(ap, GdaTime *));
1174 else {
1175 g_warning (_("%s() does not handle values of type '%s'."),
1176 __FUNCTION__, g_type_name (type));
1177 g_object_unref (holder);
1178 allok = FALSE;
1179 break;
1180 }
1181
1182 if (!gda_holder_take_value (holder, value, &lerror)) {
1183 g_warning (_("Unable to set holder's value: %s"),
1184 lerror && lerror->message ? lerror->message : _("No detail"));
1185 if (lerror)
1186 g_error_free (lerror);
1187 g_object_unref (holder);
1188 allok = FALSE;
1189 break;
1190 }
1191 holders = g_slist_append (holders, holder);
1192 }
1193 va_end (ap);
1194
1195 /* create the set */
1196 if (allok)
1197 set = gda_set_new (holders);
1198 if (holders) {
1199 g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
1200 g_slist_free (holders);
1201 }
1202 return set;
1203 }
1204
1205 /**
1206 * gda_set_set_holder_value: (skip)
1207 * @set: a #GdaSet object
1208 * @error: (allow-none): a place to store errors, or %NULL
1209 * @holder_id: the ID of the holder to set the value
1210 * @...: value, of the correct type, depending on the requested holder's type (not NULL)
1211 *
1212 * Set the value of the #GdaHolder which ID is @holder_id to a specified value
1213 *
1214 * Returns: %TRUE if no error occurred and the value was set correctly
1215 */
1216 gboolean
gda_set_set_holder_value(GdaSet * set,GError ** error,const gchar * holder_id,...)1217 gda_set_set_holder_value (GdaSet *set, GError **error, const gchar *holder_id, ...)
1218 {
1219 GdaHolder *holder;
1220 va_list ap;
1221 GValue *value;
1222 GType type;
1223
1224 g_return_val_if_fail (GDA_IS_SET (set), FALSE);
1225 g_return_val_if_fail (set->priv, FALSE);
1226
1227 holder = gda_set_get_holder (set, holder_id);
1228 if (!holder) {
1229 g_set_error (error, GDA_SET_ERROR, GDA_SET_HOLDER_NOT_FOUND_ERROR,
1230 _("GdaHolder with ID '%s' not found in set"), holder_id);
1231 return FALSE;
1232 }
1233 type = gda_holder_get_g_type (holder);
1234 va_start (ap, holder_id);
1235 value = gda_value_new (type);
1236 if (type == G_TYPE_BOOLEAN)
1237 g_value_set_boolean (value, va_arg (ap, int));
1238 else if (type == G_TYPE_STRING)
1239 g_value_set_string (value, va_arg (ap, gchar *));
1240 else if (type == G_TYPE_OBJECT)
1241 g_value_set_object (value, va_arg (ap, gpointer));
1242 else if (type == G_TYPE_INT)
1243 g_value_set_int (value, va_arg (ap, gint));
1244 else if (type == G_TYPE_UINT)
1245 g_value_set_uint (value, va_arg (ap, guint));
1246 else if (type == GDA_TYPE_BINARY)
1247 gda_value_set_binary (value, va_arg (ap, GdaBinary *));
1248 else if (type == G_TYPE_INT64)
1249 g_value_set_int64 (value, va_arg (ap, gint64));
1250 else if (type == G_TYPE_UINT64)
1251 g_value_set_uint64 (value, va_arg (ap, guint64));
1252 else if (type == GDA_TYPE_SHORT)
1253 gda_value_set_short (value, va_arg (ap, int));
1254 else if (type == GDA_TYPE_USHORT)
1255 gda_value_set_ushort (value, va_arg (ap, guint));
1256 else if (type == G_TYPE_CHAR)
1257 g_value_set_schar (value, va_arg (ap, gint));
1258 else if (type == G_TYPE_UCHAR)
1259 g_value_set_uchar (value, va_arg (ap, guint));
1260 else if (type == G_TYPE_FLOAT)
1261 g_value_set_float (value, va_arg (ap, double));
1262 else if (type == G_TYPE_DOUBLE)
1263 g_value_set_double (value, va_arg (ap, gdouble));
1264 else if (type == GDA_TYPE_NUMERIC)
1265 gda_value_set_numeric (value, va_arg (ap, GdaNumeric *));
1266 else if (type == G_TYPE_DATE)
1267 g_value_set_boxed (value, va_arg (ap, GDate *));
1268 else if (type == GDA_TYPE_TIMESTAMP)
1269 gda_value_set_timestamp (value, va_arg (ap, GdaTimestamp*));
1270 else if (type == GDA_TYPE_TIME)
1271 gda_value_set_time (value, va_arg (ap, GdaTime*));
1272 else if (type == G_TYPE_LONG)
1273 g_value_set_long (value, va_arg (ap, glong));
1274 else if (type == G_TYPE_ULONG)
1275 g_value_set_ulong (value, va_arg (ap, gulong));
1276 else if (type == G_TYPE_GTYPE)
1277 g_value_set_gtype (value, va_arg (ap, GType));
1278 else {
1279 g_set_error (error, GDA_SET_ERROR, GDA_SET_IMPLEMENTATION_ERROR,
1280 _("%s() does not handle values of type '%s'."),
1281 __FUNCTION__, g_type_name (type));
1282 va_end (ap);
1283 return FALSE;
1284 }
1285
1286 va_end (ap);
1287 return gda_holder_take_value (holder, value, error);
1288 }
1289
1290 /**
1291 * gda_set_get_holder_value:
1292 * @set: a #GdaSet object
1293 * @holder_id: the ID of the holder to set the value
1294 *
1295 * Get the value of the #GdaHolder which ID is @holder_id
1296 *
1297 * Returns: (allow-none) (transfer none): the requested GValue, or %NULL (see gda_holder_get_value())
1298 */
1299 const GValue *
gda_set_get_holder_value(GdaSet * set,const gchar * holder_id)1300 gda_set_get_holder_value (GdaSet *set, const gchar *holder_id)
1301 {
1302 GdaHolder *holder;
1303
1304 g_return_val_if_fail (GDA_IS_SET (set), FALSE);
1305 g_return_val_if_fail (set->priv, FALSE);
1306
1307 holder = gda_set_get_holder (set, holder_id);
1308 if (holder)
1309 return gda_holder_get_value (holder);
1310 else
1311 return NULL;
1312 }
1313
1314 static void
xml_validity_error_func(void * ctx,const char * msg,...)1315 xml_validity_error_func (void *ctx, const char *msg, ...)
1316 {
1317 va_list args;
1318 gchar *str, *str2, *newerr;
1319
1320 va_start (args, msg);
1321 str = g_strdup_vprintf (msg, args);
1322 va_end (args);
1323
1324 str2 = *((gchar **) ctx);
1325
1326 if (str2) {
1327 newerr = g_strdup_printf ("%s\n%s", str2, str);
1328 g_free (str2);
1329 }
1330 else
1331 newerr = g_strdup (str);
1332 g_free (str);
1333
1334 *((gchar **) ctx) = newerr;
1335 }
1336
1337 /**
1338 * gda_set_new_from_spec_string:
1339 * @xml_spec: a string
1340 * @error: (allow-none): a place to store the error, or %NULL
1341 *
1342 * Creates a new #GdaSet object from the @xml_spec
1343 * specifications
1344 *
1345 * Returns: (transfer full): a new object, or %NULL if an error occurred
1346 */
1347 GdaSet *
gda_set_new_from_spec_string(const gchar * xml_spec,GError ** error)1348 gda_set_new_from_spec_string (const gchar *xml_spec, GError **error)
1349 {
1350 xmlDocPtr doc;
1351 xmlNodePtr root;
1352 GdaSet *set;
1353
1354 /* string parsing */
1355 doc = xmlParseMemory (xml_spec, strlen (xml_spec));
1356 if (!doc)
1357 return NULL;
1358
1359 {
1360 /* doc validation */
1361 xmlValidCtxtPtr validc;
1362 int xmlcheck;
1363 gchar *err_str = NULL;
1364 xmlDtdPtr old_dtd = NULL;
1365
1366 validc = g_new0 (xmlValidCtxt, 1);
1367 validc->userData = &err_str;
1368 validc->error = xml_validity_error_func;
1369 validc->warning = NULL;
1370
1371 xmlcheck = xmlDoValidityCheckingDefaultValue;
1372 xmlDoValidityCheckingDefaultValue = 1;
1373
1374 /* replace the DTD with ours */
1375 if (gda_paramlist_dtd) {
1376 old_dtd = doc->intSubset;
1377 doc->intSubset = gda_paramlist_dtd;
1378 }
1379
1380 #ifndef G_OS_WIN32
1381 if (doc->intSubset && !xmlValidateDocument (validc, doc)) {
1382 if (gda_paramlist_dtd)
1383 doc->intSubset = old_dtd;
1384 xmlFreeDoc (doc);
1385 g_free (validc);
1386
1387 if (err_str) {
1388 g_set_error (error,
1389 GDA_SET_ERROR,
1390 GDA_SET_XML_SPEC_ERROR,
1391 "XML spec. does not conform to DTD:\n%s", err_str);
1392 g_free (err_str);
1393 }
1394 else
1395 g_set_error (error,
1396 GDA_SET_ERROR,
1397 GDA_SET_XML_SPEC_ERROR,
1398 "%s", "XML spec. does not conform to DTD");
1399
1400 xmlDoValidityCheckingDefaultValue = xmlcheck;
1401 return NULL;
1402 }
1403 #endif
1404 if (gda_paramlist_dtd)
1405 doc->intSubset = old_dtd;
1406 xmlDoValidityCheckingDefaultValue = xmlcheck;
1407 g_free (validc);
1408 }
1409
1410 /* doc is now non NULL */
1411 root = xmlDocGetRootElement (doc);
1412 if (strcmp ((gchar*)root->name, "data-set-spec") != 0){
1413 g_set_error (error, GDA_SET_ERROR, GDA_SET_XML_SPEC_ERROR,
1414 _("Spec's root node != 'data-set-spec': '%s'"), root->name);
1415 return NULL;
1416 }
1417
1418 /* creating holders */
1419 root = root->xmlChildrenNode;
1420 while (xmlNodeIsText (root))
1421 root = root->next;
1422
1423 set = gda_set_new_from_spec_node (root, error);
1424 xmlFreeDoc(doc);
1425 return set;
1426 }
1427
1428
1429 /**
1430 * gda_set_new_from_spec_node:
1431 * @xml_spec: a #xmlNodePtr for a <parameters> tag
1432 * @error: (allow-none): a place to store the error, or %NULL
1433 *
1434 * Creates a new #GdaSet object from the @xml_spec
1435 * specifications
1436 *
1437 * Returns: (transfer full): a new object, or %NULL if an error occurred
1438 */
1439 GdaSet *
gda_set_new_from_spec_node(xmlNodePtr xml_spec,GError ** error)1440 gda_set_new_from_spec_node (xmlNodePtr xml_spec, GError **error)
1441 {
1442 GdaSet *set = NULL;
1443 GSList *holders = NULL, *sources = NULL;
1444 GSList *list;
1445 const gchar *lang = gda_lang_locale;
1446
1447 xmlNodePtr cur;
1448 gboolean allok = TRUE;
1449 gchar *str;
1450
1451 if (strcmp ((gchar*)xml_spec->name, "parameters") != 0){
1452 g_set_error (error, GDA_SET_ERROR, GDA_SET_XML_SPEC_ERROR,
1453 _("Missing node <parameters>: '%s'"), xml_spec->name);
1454 return NULL;
1455 }
1456
1457 /* Holders' sources, not mandatory: makes the @sources list */
1458 cur = xml_spec->next;
1459 while (cur && (xmlNodeIsText (cur) || strcmp ((gchar*)cur->name, "sources")))
1460 cur = cur->next;
1461 if (allok && cur && !strcmp ((gchar*)cur->name, "sources")){
1462 for (cur = cur->xmlChildrenNode; (cur != NULL) && allok; cur = cur->next) {
1463 if (xmlNodeIsText (cur))
1464 continue;
1465
1466 if (!strcmp ((gchar*)cur->name, "gda_array")) {
1467 GdaDataModel *model;
1468 GSList *errors;
1469
1470 model = gda_data_model_import_new_xml_node (cur);
1471 errors = gda_data_model_import_get_errors (GDA_DATA_MODEL_IMPORT (model));
1472 if (errors) {
1473 GError *err = (GError *) errors->data;
1474 g_set_error (error, GDA_SET_ERROR, GDA_SET_XML_SPEC_ERROR,
1475 "%s", err->message);
1476 g_object_unref (model);
1477 model = NULL;
1478 allok = FALSE;
1479 }
1480 else {
1481 sources = g_slist_prepend (sources, model);
1482 str = (gchar*)xmlGetProp(cur, (xmlChar*) "name");
1483 if (str)
1484 g_object_set_data_full (G_OBJECT (model), "name", str, xmlFree);
1485 }
1486 }
1487 }
1488 }
1489
1490 /* holders */
1491 for (cur = xml_spec->xmlChildrenNode; cur && allok; cur = cur->next) {
1492 if (xmlNodeIsText (cur))
1493 continue;
1494
1495 if (!strcmp ((gchar*)cur->name, "parameter")) {
1496 GdaHolder *holder = NULL;
1497 gchar *str, *id;
1498 xmlChar *this_lang;
1499 xmlChar *gdatype;
1500
1501 /* don't care about entries for the wrong locale */
1502 this_lang = xmlGetProp(cur, (xmlChar*)"lang");
1503 if (this_lang && strncmp ((gchar*)this_lang, lang, strlen ((gchar*)this_lang))) {
1504 g_free (this_lang);
1505 continue;
1506 }
1507
1508 /* find if there is already a holder with the same ID */
1509 id = (gchar*)xmlGetProp(cur, (xmlChar*)"id");
1510 for (list = holders; list && !holder; list = list->next) {
1511 str = (gchar *) gda_holder_get_id ((GdaHolder *) list->data);
1512 if (str && id && !strcmp (str, id))
1513 holder = (GdaHolder *) list->data;
1514 }
1515 if (id)
1516 xmlFree (id);
1517
1518 if (holder && !this_lang) {
1519 xmlFree (this_lang);
1520 continue;
1521 }
1522 g_free (this_lang);
1523
1524
1525 /* find data type and create GdaHolder */
1526 gdatype = xmlGetProp (cur, BAD_CAST "gdatype");
1527
1528 if (!holder) {
1529 GType gt;
1530 gt = gdatype ? gda_g_type_from_string ((gchar *) gdatype) : G_TYPE_STRING;
1531 if (gt == G_TYPE_INVALID)
1532 gt = GDA_TYPE_NULL;
1533 holder = (GdaHolder*) (g_object_new (GDA_TYPE_HOLDER,
1534 "g-type", gt,
1535 NULL));
1536 holders = g_slist_append (holders, holder);
1537 }
1538 if (gdatype)
1539 xmlFree (gdatype);
1540
1541 /* set holder's attributes */
1542 if (! gda_utility_holder_load_attributes (holder, cur, sources, error))
1543 allok = FALSE;
1544 }
1545 }
1546
1547 /* setting prepared new names from sources (models) */
1548 for (list = sources; list; list = list->next) {
1549 str = g_object_get_data (G_OBJECT (list->data), "newname");
1550 if (str) {
1551 g_object_set_data_full (G_OBJECT (list->data), "name", g_strdup (str), g_free);
1552 g_object_set_data (G_OBJECT (list->data), "newname", NULL);
1553 }
1554 str = g_object_get_data (G_OBJECT (list->data), "newdescr");
1555 if (str) {
1556 g_object_set_data_full (G_OBJECT (list->data), "descr", g_strdup (str), g_free);
1557 g_object_set_data (G_OBJECT (list->data), "newdescr", NULL);
1558 }
1559 }
1560
1561 /* holders' values, constraints: TODO */
1562
1563 /* GdaSet creation */
1564 if (allok) {
1565 xmlChar *prop;;
1566 set = gda_set_new (holders);
1567
1568 prop = xmlGetProp(xml_spec, (xmlChar*)"id");
1569 if (prop) {
1570 set->priv->id = g_strdup ((gchar*)prop);
1571 xmlFree (prop);
1572 }
1573 prop = xmlGetProp(xml_spec, (xmlChar*)"name");
1574 if (prop) {
1575 set->priv->name = g_strdup ((gchar*)prop);
1576 xmlFree (prop);
1577 }
1578 prop = xmlGetProp(xml_spec, (xmlChar*)"descr");
1579 if (prop) {
1580 set->priv->descr = g_strdup ((gchar*)prop);
1581 xmlFree (prop);
1582 }
1583 }
1584
1585 g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
1586 g_slist_free (holders);
1587 g_slist_foreach (sources, (GFunc) g_object_unref, NULL);
1588 g_slist_free (sources);
1589
1590 return set;
1591 }
1592
1593 /**
1594 * gda_set_remove_holder:
1595 * @set: a #GdaSet object
1596 * @holder: the #GdaHolder to remove from @set
1597 *
1598 * Removes a #GdaHolder from the list of holders managed by @set
1599 */
1600 void
gda_set_remove_holder(GdaSet * set,GdaHolder * holder)1601 gda_set_remove_holder (GdaSet *set, GdaHolder *holder)
1602 {
1603 GdaSetNode *node;
1604 GdaDataModel *model;
1605
1606 g_return_if_fail (GDA_IS_SET (set));
1607 g_return_if_fail (set->priv);
1608 g_return_if_fail (g_slist_find (set->holders, holder));
1609
1610 if (set->priv->validate_changes)
1611 g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1612 G_CALLBACK (validate_change_holder_cb), set);
1613 if (! set->priv->read_only) {
1614 g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1615 G_CALLBACK (changed_holder_cb), set);
1616 g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1617 G_CALLBACK (source_changed_holder_cb), set);
1618 g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1619 G_CALLBACK (att_holder_changed_cb), set);
1620 }
1621 g_signal_handlers_disconnect_by_func (holder,
1622 G_CALLBACK (holder_notify_cb), set);
1623
1624 /* now destroy the GdaSetNode and the GdaSetSource if necessary */
1625 node = gda_set_get_node (set, holder);
1626 g_assert (node);
1627 model = gda_set_node_get_data_model (node);
1628 if (GDA_IS_DATA_MODEL (model)) {
1629 GdaSetSource *source;
1630 GSList *nodes;
1631
1632 source = gda_set_get_source_for_model (set, model);
1633 g_assert (source);
1634 nodes = gda_set_source_get_nodes (source);
1635 g_assert (nodes);
1636 if (! nodes->next)
1637 set_remove_source (set, source);
1638 }
1639 set_remove_node (set, node);
1640
1641 set->holders = g_slist_remove (set->holders, holder);
1642 g_hash_table_remove (set->priv->holders_hash, gda_holder_get_id (holder));
1643 if (set->priv->holders_array) {
1644 g_array_free (set->priv->holders_array, TRUE);
1645 set->priv->holders_array = NULL;
1646 }
1647 g_object_unref (G_OBJECT (holder));
1648 }
1649
1650 static void
source_changed_holder_cb(G_GNUC_UNUSED GdaHolder * holder,GdaSet * set)1651 source_changed_holder_cb (G_GNUC_UNUSED GdaHolder *holder, GdaSet *set)
1652 {
1653 compute_public_data (set);
1654 }
1655
1656 static void
att_holder_changed_cb(GdaHolder * holder,const gchar * att_name,const GValue * att_value,GdaSet * set)1657 att_holder_changed_cb (GdaHolder *holder, const gchar *att_name, const GValue *att_value, GdaSet *set)
1658 {
1659 #ifdef GDA_DEBUG_signal
1660 g_print (">> 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1661 #endif
1662 g_signal_emit (G_OBJECT (set), gda_set_signals[HOLDER_ATTR_CHANGED], 0, holder, att_name, att_value);
1663 #ifdef GDA_DEBUG_signal
1664 g_print ("<< 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1665 #endif
1666 }
1667
1668 static GError *
validate_change_holder_cb(GdaHolder * holder,const GValue * value,GdaSet * set)1669 validate_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *set)
1670 {
1671 /* signal the holder validate-change */
1672 GError *error = NULL;
1673 if (set->priv->read_only)
1674 g_set_error (&error, GDA_SET_ERROR, GDA_SET_READ_ONLY_ERROR, "%s", _("Data set does not allow modifications"));
1675 else {
1676 #ifdef GDA_DEBUG_signal
1677 g_print (">> 'VALIDATE_HOLDER_CHANGE' from %s\n", __FUNCTION__);
1678 #endif
1679 g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_HOLDER_CHANGE], 0, holder, value, &error);
1680 #ifdef GDA_DEBUG_signal
1681 g_print ("<< 'VALIDATE_HOLDER_CHANGED' from %s\n", __FUNCTION__);
1682 #endif
1683 }
1684 return error;
1685 }
1686
1687 static void
changed_holder_cb(GdaHolder * holder,GdaSet * set)1688 changed_holder_cb (GdaHolder *holder, GdaSet *set)
1689 {
1690 /* signal the holder change */
1691 #ifdef GDA_DEBUG_signal
1692 g_print (">> 'HOLDER_CHANGED' from %s\n", __FUNCTION__);
1693 #endif
1694 g_signal_emit (G_OBJECT (set), gda_set_signals[HOLDER_CHANGED], 0, holder);
1695 #ifdef GDA_DEBUG_signal
1696 g_print ("<< 'HOLDER_CHANGED' from %s\n", __FUNCTION__);
1697 #endif
1698 }
1699
1700 static void
group_free(GdaSetGroup * group,G_GNUC_UNUSED gpointer data)1701 group_free (GdaSetGroup *group, G_GNUC_UNUSED gpointer data)
1702 {
1703 gda_set_group_free (group);
1704 }
1705
1706 static void
gda_set_dispose(GObject * object)1707 gda_set_dispose (GObject *object)
1708 {
1709 GdaSet *set;
1710 GSList *list;
1711
1712 g_return_if_fail (object != NULL);
1713 g_return_if_fail (GDA_IS_SET (object));
1714
1715 set = GDA_SET (object);
1716 /* free the holders list */
1717 if (set->holders) {
1718 for (list = set->holders; list; list = list->next) {
1719 if (set->priv->validate_changes)
1720 g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1721 G_CALLBACK (validate_change_holder_cb), set);
1722 if (! set->priv->read_only) {
1723 g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1724 G_CALLBACK (changed_holder_cb), set);
1725 g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1726 G_CALLBACK (source_changed_holder_cb), set);
1727 g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1728 G_CALLBACK (att_holder_changed_cb), set);
1729 }
1730 g_object_unref (list->data);
1731 }
1732 g_slist_free (set->holders);
1733 }
1734 if (set->priv->holders_hash) {
1735 g_hash_table_destroy (set->priv->holders_hash);
1736 set->priv->holders_hash = NULL;
1737 }
1738 if (set->priv->holders_array) {
1739 g_array_free (set->priv->holders_array, TRUE);
1740 set->priv->holders_array = NULL;
1741 }
1742
1743 /* free the nodes if there are some */
1744 while (set->nodes_list)
1745 set_remove_node (set, GDA_SET_NODE (set->nodes_list->data));
1746 while (set->sources_list)
1747 set_remove_source (set, GDA_SET_SOURCE (set->sources_list->data));
1748
1749 g_slist_foreach (set->groups_list, (GFunc) group_free, NULL);
1750 g_slist_free (set->groups_list);
1751 set->groups_list = NULL;
1752
1753 /* parent class */
1754 parent_class->dispose (object);
1755 }
1756
1757 static void
gda_set_finalize(GObject * object)1758 gda_set_finalize (GObject *object)
1759 {
1760 GdaSet *set;
1761
1762 g_return_if_fail (object != NULL);
1763 g_return_if_fail (GDA_IS_SET (object));
1764
1765 set = GDA_SET (object);
1766 if (set->priv) {
1767 g_free (set->priv->id);
1768 g_free (set->priv->name);
1769 g_free (set->priv->descr);
1770 g_free (set->priv);
1771 set->priv = NULL;
1772 }
1773
1774 /* parent class */
1775 parent_class->finalize (object);
1776 }
1777
1778 /*
1779 * Resets and computes set->nodes, and if some nodes already exist, they are previously discarded
1780 */
1781 static void
compute_public_data(GdaSet * set)1782 compute_public_data (GdaSet *set)
1783 {
1784 GSList *list;
1785 GdaSetNode *node;
1786 GdaSetSource *source;
1787 GdaSetGroup *group;
1788 GHashTable *groups = NULL;
1789
1790 /*
1791 * Get rid of all the previous structures
1792 */
1793 while (set->nodes_list)
1794 set_remove_node (set, GDA_SET_NODE (set->nodes_list->data));
1795 while (set->sources_list)
1796 set_remove_source (set, GDA_SET_SOURCE (set->sources_list->data));
1797
1798 g_slist_foreach (set->groups_list, (GFunc) group_free, NULL);
1799 g_slist_free (set->groups_list);
1800 set->groups_list = NULL;
1801
1802 /*
1803 * Creation of the GdaSetNode structures
1804 */
1805 for (list = set->holders; list; list = list->next) {
1806 GdaHolder *holder = GDA_HOLDER (list->data);
1807 gint col;
1808 node = gda_set_node_new (holder);
1809 gda_set_node_set_data_model (node, gda_holder_get_source_model (holder, &col));
1810 gda_set_node_set_source_column (node, col);
1811 set->nodes_list = g_slist_prepend (set->nodes_list, node);
1812 }
1813 set->nodes_list = g_slist_reverse (set->nodes_list);
1814
1815 /*
1816 * Creation of the GdaSetSource and GdaSetGroup structures
1817 */
1818 for (list = set->nodes_list; list;list = list->next) {
1819 node = GDA_SET_NODE (list->data);
1820
1821 /* source */
1822 source = NULL;
1823 if (gda_set_node_get_data_model (node)) {
1824 source = gda_set_get_source_for_model (set, gda_set_node_get_data_model (node));
1825 if (source)
1826 gda_set_source_add_node (source, node);
1827 else {
1828 source = gda_set_source_new (gda_set_node_get_data_model (node));
1829 gda_set_source_add_node (source, node);
1830 set->sources_list = g_slist_prepend (set->sources_list, source);
1831 }
1832 }
1833
1834 /* group */
1835 group = NULL;
1836 if (gda_set_node_get_data_model (node) && groups)
1837 group = g_hash_table_lookup (groups, gda_set_node_get_data_model (node));
1838 if (group)
1839 gda_set_group_add_node (group, node);
1840 else {
1841 group = gda_set_group_new (node);
1842 gda_set_group_set_source (group, source);
1843 set->groups_list = g_slist_prepend (set->groups_list, group);
1844 if (gda_set_node_get_data_model (node)) {
1845 if (!groups)
1846 groups = g_hash_table_new (NULL, NULL); /* key = source model,
1847 value = GdaSetGroup */
1848 g_hash_table_insert (groups, gda_set_node_get_data_model (node), group);
1849 }
1850 }
1851 }
1852 set->groups_list = g_slist_reverse (set->groups_list);
1853 if (groups)
1854 g_hash_table_destroy (groups);
1855
1856 #ifdef GDA_DEBUG_signal
1857 g_print (">> 'PUBLIC_DATA_CHANGED' from %p\n", set);
1858 #endif
1859 g_signal_emit (set, gda_set_signals[PUBLIC_DATA_CHANGED], 0);
1860 #ifdef GDA_DEBUG_signal
1861 g_print ("<< 'PUBLIC_DATA_CHANGED' from %p\n", set);
1862 #endif
1863 }
1864
1865 /**
1866 * gda_set_add_holder:
1867 * @set: a #GdaSet object
1868 * @holder: a #GdaHolder object
1869 *
1870 * Adds @holder to the list of holders managed within @set.
1871 *
1872 * NOTE: if @set already has a #GdaHolder with the same ID as @holder, then @holder
1873 * will not be added to the set (even if @holder's type or value is not the same as the
1874 * one already in @set).
1875 *
1876 * Returns: TRUE if @holder has been added to @set (and FALSE if it has not been added because there is another #GdaHolder
1877 * with the same ID)
1878 */
1879 gboolean
gda_set_add_holder(GdaSet * set,GdaHolder * holder)1880 gda_set_add_holder (GdaSet *set, GdaHolder *holder)
1881 {
1882 gboolean added;
1883 g_return_val_if_fail (GDA_IS_SET (set), FALSE);
1884 g_return_val_if_fail (GDA_IS_HOLDER (holder), FALSE);
1885
1886 added = gda_set_real_add_holder (set, holder);
1887 if (added)
1888 compute_public_data (set);
1889 return added;
1890 }
1891
1892 static void
holder_notify_cb(GdaHolder * holder,GParamSpec * pspec,GdaSet * dataset)1893 holder_notify_cb (GdaHolder *holder, GParamSpec *pspec, GdaSet *dataset)
1894 {
1895 GType gtype;
1896 gtype = gda_holder_get_g_type (holder);
1897 if (!strcmp (pspec->name, "g-type")) {
1898 g_assert (gtype != GDA_TYPE_NULL);
1899 g_signal_emit (dataset, gda_set_signals[HOLDER_TYPE_SET], 0, holder);
1900 }
1901 else if (!strcmp (pspec->name, "name")) {
1902 #ifdef GDA_DEBUG_signal
1903 g_print (">> 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1904 #endif
1905 g_signal_emit (G_OBJECT (dataset), gda_set_signals[HOLDER_ATTR_CHANGED], 0, holder,
1906 GDA_ATTRIBUTE_NAME, gda_holder_get_attribute (holder, GDA_ATTRIBUTE_NAME));
1907 #ifdef GDA_DEBUG_signal
1908 g_print ("<< 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1909 #endif
1910 }
1911 else if (!strcmp (pspec->name, "description")) {
1912 #ifdef GDA_DEBUG_signal
1913 g_print (">> 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1914 #endif
1915 g_signal_emit (G_OBJECT (dataset), gda_set_signals[HOLDER_ATTR_CHANGED], 0, holder,
1916 GDA_ATTRIBUTE_DESCRIPTION, gda_holder_get_attribute (holder, GDA_ATTRIBUTE_DESCRIPTION));
1917 #ifdef GDA_DEBUG_signal
1918 g_print ("<< 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1919 #endif
1920 }
1921 }
1922
1923 static gboolean
gda_set_real_add_holder(GdaSet * set,GdaHolder * holder)1924 gda_set_real_add_holder (GdaSet *set, GdaHolder *holder)
1925 {
1926 GdaHolder *similar;
1927 const gchar *hid;
1928
1929 /*
1930 * try to find a similar holder in the set->holders:
1931 * a holder B is similar to a holder A if it has the same ID
1932 */
1933 hid = gda_holder_get_id (holder);
1934 if (!hid) {
1935 g_warning (_("GdaHolder needs to have an ID"));
1936 return FALSE;
1937 }
1938
1939 similar = (GdaHolder*) g_hash_table_lookup (set->priv->holders_hash, hid);
1940 if (!similar) {
1941 /* really add @holder to the set */
1942 set->holders = g_slist_append (set->holders, holder);
1943 g_hash_table_insert (set->priv->holders_hash, (gchar*) hid, holder);
1944 if (set->priv->holders_array) {
1945 g_array_free (set->priv->holders_array, TRUE);
1946 set->priv->holders_array = NULL;
1947 }
1948 g_object_ref (holder);
1949 if (set->priv->validate_changes)
1950 g_signal_connect (G_OBJECT (holder), "validate-change",
1951 G_CALLBACK (validate_change_holder_cb), set);
1952 if (! set->priv->read_only) {
1953 g_signal_connect (G_OBJECT (holder), "changed",
1954 G_CALLBACK (changed_holder_cb), set);
1955 g_signal_connect (G_OBJECT (holder), "source-changed",
1956 G_CALLBACK (source_changed_holder_cb), set);
1957 g_signal_connect (G_OBJECT (holder), "attribute-changed",
1958 G_CALLBACK (att_holder_changed_cb), set);
1959 }
1960 if (gda_holder_get_g_type (holder) == GDA_TYPE_NULL)
1961 g_signal_connect (G_OBJECT (holder), "notify::g-type",
1962 G_CALLBACK (holder_notify_cb), set);
1963 g_signal_connect (G_OBJECT (holder), "notify::name",
1964 G_CALLBACK (holder_notify_cb), set);
1965 g_signal_connect (G_OBJECT (holder), "notify::description",
1966 G_CALLBACK (holder_notify_cb), set);
1967 return TRUE;
1968 }
1969 else if (similar == holder)
1970 return FALSE;
1971 else {
1972 #ifdef GDA_DEBUG_NO
1973 g_print ("In Set %p, Holder %p and %p are similar, keeping %p only\n", set, similar, holder, similar);
1974 #endif
1975 return FALSE;
1976 }
1977 }
1978
1979
1980 /**
1981 * gda_set_merge_with_set:
1982 * @set: a #GdaSet object
1983 * @set_to_merge: a #GdaSet object
1984 *
1985 * Add to @set all the holders of @set_to_merge.
1986 * Note1: only the #GdaHolder of @set_to_merge for which no holder in @set has the same ID are merged
1987 * Note2: all the #GdaHolder merged in @set are still used by @set_to_merge.
1988 */
1989 void
gda_set_merge_with_set(GdaSet * set,GdaSet * set_to_merge)1990 gda_set_merge_with_set (GdaSet *set, GdaSet *set_to_merge)
1991 {
1992 GSList *holders;
1993 g_return_if_fail (GDA_IS_SET (set));
1994 g_return_if_fail (set_to_merge && GDA_IS_SET (set_to_merge));
1995
1996 for (holders = set_to_merge->holders; holders; holders = holders->next)
1997 gda_set_real_add_holder (set, GDA_HOLDER (holders->data));
1998 compute_public_data (set);
1999 }
2000
2001 static void
set_remove_node(GdaSet * set,GdaSetNode * node)2002 set_remove_node (GdaSet *set, GdaSetNode *node)
2003 {
2004 g_return_if_fail (g_slist_find (set->nodes_list, node));
2005 gda_set_node_free (node);
2006 set->nodes_list = g_slist_remove (set->nodes_list, node);
2007 }
2008
2009 static void
set_remove_source(GdaSet * set,GdaSetSource * source)2010 set_remove_source (GdaSet *set, GdaSetSource *source)
2011 {
2012 g_return_if_fail (g_slist_find (set->sources_list, source));
2013 gda_set_source_free (source);
2014 set->sources_list = g_slist_remove (set->sources_list, source);
2015 }
2016
2017 /**
2018 * gda_set_is_valid:
2019 * @set: a #GdaSet object
2020 * @error: (allow-none): a place to store validation errors, or %NULL
2021 *
2022 * This method tells if all @set's #GdaHolder objects are valid, and if
2023 * they represent a valid combination of values, as defined by rules
2024 * external to Libgda: the "validate-set" signal is emitted and if none of the signal handlers return an
2025 * error, then the returned value is TRUE, otherwise the return value is FALSE as soon as a signal handler
2026 * returns an error.
2027 *
2028 * Returns: TRUE if the set is valid
2029 */
2030 gboolean
gda_set_is_valid(GdaSet * set,GError ** error)2031 gda_set_is_valid (GdaSet *set, GError **error)
2032 {
2033 GSList *holders;
2034
2035 g_return_val_if_fail (GDA_IS_SET (set), FALSE);
2036 g_return_val_if_fail (set->priv, FALSE);
2037
2038 for (holders = set->holders; holders; holders = holders->next) {
2039 if (!gda_holder_is_valid (GDA_HOLDER (holders->data))) {
2040 g_set_error (error, GDA_SET_ERROR, GDA_SET_INVALID_ERROR,
2041 "%s", _("One or more values are invalid"));
2042 return FALSE;
2043 }
2044 }
2045
2046 return _gda_set_validate (set, error);
2047 }
2048
2049 gboolean
_gda_set_validate(GdaSet * set,GError ** error)2050 _gda_set_validate (GdaSet *set, GError **error)
2051 {
2052 /* signal the holder validate-set */
2053 GError *lerror = NULL;
2054 #ifdef GDA_DEBUG_signal
2055 g_print (">> 'VALIDATE_SET' from %s\n", __FUNCTION__);
2056 #endif
2057 g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_SET], 0, &lerror);
2058 #ifdef GDA_DEBUG_signal
2059 g_print ("<< 'VALIDATE_SET' from %s\n", __FUNCTION__);
2060 #endif
2061 if (lerror) {
2062 g_propagate_error (error, lerror);
2063 return FALSE;
2064 }
2065 return TRUE;
2066 }
2067
2068
2069 /**
2070 * gda_set_get_holder:
2071 * @set: a #GdaSet object
2072 * @holder_id: the ID of the requested value holder
2073 *
2074 * Finds a #GdaHolder using its ID
2075 *
2076 * Returns: (transfer none): the requested #GdaHolder or %NULL
2077 */
2078 GdaHolder *
gda_set_get_holder(GdaSet * set,const gchar * holder_id)2079 gda_set_get_holder (GdaSet *set, const gchar *holder_id)
2080 {
2081 g_return_val_if_fail (GDA_IS_SET (set), NULL);
2082 g_return_val_if_fail (holder_id, NULL);
2083
2084 return (GdaHolder *) g_hash_table_lookup (set->priv->holders_hash, holder_id);
2085 }
2086
2087 /**
2088 * gda_set_get_nth_holder:
2089 * @set: a #GdaSet object
2090 * @pos: the position of the requested #GdaHolder, starting at %0
2091 *
2092 * Finds a #GdaHolder using its position
2093 *
2094 * Returns: (transfer none): the requested #GdaHolder or %NULL
2095 *
2096 * Since: 4.2
2097 */
2098 GdaHolder *
gda_set_get_nth_holder(GdaSet * set,gint pos)2099 gda_set_get_nth_holder (GdaSet *set, gint pos)
2100 {
2101 g_return_val_if_fail (GDA_IS_SET (set), NULL);
2102 g_return_val_if_fail (pos >= 0, NULL);
2103
2104 if (! set->priv->holders_array) {
2105 GSList *list;
2106 set->priv->holders_array = g_array_sized_new (FALSE, FALSE, sizeof (GdaHolder*),
2107 g_slist_length (set->holders));
2108 for (list = set->holders; list; list = list->next)
2109 g_array_append_val (set->priv->holders_array, list->data);
2110 }
2111 if ((guint)pos >= set->priv->holders_array->len)
2112 return NULL;
2113 else
2114 return g_array_index (set->priv->holders_array, GdaHolder*, pos);
2115 }
2116
2117 /**
2118 * gda_set_get_node:
2119 * @set: a #GdaSet object
2120 * @holder: a #GdaHolder object
2121 *
2122 * Finds a #GdaSetNode holding information for @holder, don't modify the returned structure
2123 *
2124 * Returns: (transfer none): the requested #GdaSetNode or %NULL
2125 */
2126 GdaSetNode *
gda_set_get_node(GdaSet * set,GdaHolder * holder)2127 gda_set_get_node (GdaSet *set, GdaHolder *holder)
2128 {
2129 GdaSetNode *retval = NULL;
2130 GSList *list;
2131
2132 g_return_val_if_fail (GDA_IS_SET (set), NULL);
2133 g_return_val_if_fail (set->priv, NULL);
2134 g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
2135 /* FIXME: May is better to use holder's hash for better performance */
2136 g_return_val_if_fail (g_slist_find (set->holders, holder), NULL);
2137
2138 for (list = set->nodes_list; list && !retval; list = list->next) {
2139 GdaHolder *node_holder;
2140 retval = GDA_SET_NODE (list->data);
2141 node_holder = gda_set_node_get_holder (retval);
2142 if (node_holder == holder) /* FIXME: May is better to compare holders ID */
2143 break;
2144 else
2145 retval = NULL;
2146 }
2147 return retval;
2148 }
2149
2150 /**
2151 * gda_set_get_source:
2152 * @set: a #GdaSet object
2153 * @holder: a #GdaHolder object
2154 *
2155 * Finds a #GdaSetSource which contains the #GdaDataModel restricting the possible values of
2156 * @holder, don't modify the returned structure.
2157 *
2158 * Returns: (transfer none): the requested #GdaSetSource or %NULL
2159 */
2160 GdaSetSource *
gda_set_get_source(GdaSet * set,GdaHolder * holder)2161 gda_set_get_source (GdaSet *set, GdaHolder *holder)
2162 {
2163 GdaSetNode *node;
2164 GdaDataModel *node_model;
2165
2166 node = gda_set_get_node (set, holder);
2167 node_model = gda_set_node_get_data_model (node);
2168 if (node && GDA_IS_DATA_MODEL (node_model))
2169 return gda_set_get_source_for_model (set, node_model);
2170 else
2171 return NULL;
2172 }
2173
2174 /**
2175 * gda_set_get_group:
2176 * @set: a #GdaSet object
2177 * @holder: a #GdaHolder object
2178 *
2179 * Finds a #GdaSetGroup which lists a #GdaSetNode containing @holder,
2180 * don't modify the returned structure.
2181 *
2182 * Returns: (transfer none): the requested #GdaSetGroup or %NULL
2183 */
2184 GdaSetGroup *
gda_set_get_group(GdaSet * set,GdaHolder * holder)2185 gda_set_get_group (GdaSet *set, GdaHolder *holder)
2186 {
2187 GdaSetNode *node;
2188 GdaSetGroup *retval = NULL;
2189 GSList *list, *sublist;
2190 GdaHolder *node_holder;
2191
2192 g_return_val_if_fail (GDA_IS_SET (set), NULL);
2193 g_return_val_if_fail (set->priv, NULL);
2194 g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
2195 /* FIXME: May is better to use holder's hash for better performance */
2196 g_return_val_if_fail (g_slist_find (set->holders, holder), NULL);
2197
2198 for (list = set->groups_list; list && !retval; list = list->next) {
2199 retval = GDA_SET_GROUP (list->data);
2200 sublist = gda_set_group_get_nodes (retval);
2201 while (sublist && !retval) {
2202 node = GDA_SET_NODE (sublist->data);
2203 if (node) {
2204 node_holder = gda_set_node_get_holder (node);
2205 if (node_holder == holder) /* FIXME: May is better to compare holders ID */
2206 break;
2207 else {
2208 sublist = g_slist_next (sublist);
2209 retval = NULL;
2210 }
2211 }
2212 }
2213 }
2214 return retval;
2215 }
2216
2217
2218 /**
2219 * gda_set_get_source_for_model:
2220 * @set: a #GdaSet object
2221 * @model: a #GdaDataModel object
2222 *
2223 * Finds the #GdaSetSource structure used in @set for which @model is a
2224 * the data model (the returned structure should not be modified).
2225 *
2226 * Returns: (transfer none): the requested #GdaSetSource pointer or %NULL.
2227 */
2228 GdaSetSource *
gda_set_get_source_for_model(GdaSet * set,GdaDataModel * model)2229 gda_set_get_source_for_model (GdaSet *set, GdaDataModel *model)
2230 {
2231 GdaSetSource *retval = NULL;
2232 GdaDataModel *source_model;
2233 GSList *list;
2234
2235 g_return_val_if_fail (GDA_IS_SET (set), NULL);
2236 g_return_val_if_fail (set->priv, NULL);
2237 g_return_val_if_fail (GDA_IS_DATA_MODEL (model), NULL);
2238
2239 list = set->sources_list;
2240 while (list && !retval) {
2241 retval = GDA_SET_SOURCE (list->data);
2242 source_model = gda_set_source_get_data_model (retval);
2243 if (GDA_IS_DATA_MODEL (source_model)) {
2244 if (source_model == model)
2245 break;
2246 else
2247 retval = NULL;
2248 }
2249 list = g_slist_next (list);
2250 }
2251
2252 return retval;
2253 }
2254
2255 /**
2256 * gda_set_replace_source_model:
2257 * @set: a #GdaSet object
2258 * @source: a pointer to a #GdaSetSource in @set
2259 * @model: a #GdaDataModel
2260 *
2261 * Replaces @source->data_model with @model, which must have the same
2262 * characteristics as @source->data_model (same column types)
2263 *
2264 * Also for each #GdaHolder for which @source->data_model is a source model,
2265 * this method calls gda_holder_set_source_model() with @model to replace
2266 * the source by the new model
2267 *
2268 * Since: 4.2
2269 */
2270 void
gda_set_replace_source_model(GdaSet * set,GdaSetSource * source,GdaDataModel * model)2271 gda_set_replace_source_model (GdaSet *set, GdaSetSource *source, GdaDataModel *model)
2272 {
2273 GdaDataModel *source_model;
2274
2275 g_return_if_fail (GDA_IS_SET (set));
2276 g_return_if_fail (source);
2277 g_return_if_fail (g_slist_find (set->sources_list, source));
2278 g_return_if_fail (GDA_IS_DATA_MODEL (model));
2279
2280 /* compare models */
2281 gint ncols, i;
2282
2283 source_model = gda_set_source_get_data_model (source);
2284 if (GDA_IS_DATA_MODEL (source_model)) {
2285 ncols = gda_data_model_get_n_columns (source_model);
2286 /* FIXME: This way to compare two Data Models could be useful as a function
2287 * gda_data_model_compare (GdaDataModel)
2288 **/
2289 if (ncols != gda_data_model_get_n_columns (model)) {
2290 g_warning (_("Replacing data model must have the same characteristics as the "
2291 "data model it replaces"));
2292 return;
2293 }
2294 for (i = 0; i < ncols; i++) {
2295 GdaColumn *c1, *c2;
2296 GType t1, t2;
2297 c1 = gda_data_model_describe_column (source->data_model, i);
2298 c2 = gda_data_model_describe_column (model, i);
2299 t1 = gda_column_get_g_type (c1);
2300 t2 = gda_column_get_g_type (c2);
2301
2302 if ((t1 != GDA_TYPE_NULL) && (t2 != GDA_TYPE_NULL) && (t1 != t2)) {
2303 g_warning (_("Replacing data model must have the same characteristics as the "
2304 "data model it replaces"));
2305 return;
2306 }
2307 }
2308 }
2309
2310 /* actually swap the models */
2311 GSList *list;
2312 gda_set_source_set_data_model (source, model);
2313 for (list = gda_set_source_get_nodes (source); list; list = list->next) {
2314 GdaSetNode *node = GDA_SET_NODE (list->data);
2315 gda_set_node_set_data_model (node, model);
2316 g_signal_handlers_block_by_func (G_OBJECT (node->holder),
2317 G_CALLBACK (source_changed_holder_cb), set);
2318 gda_holder_set_source_model (GDA_HOLDER (node->holder), model, node->source_column,
2319 NULL);
2320 g_signal_handlers_unblock_by_func (G_OBJECT (node->holder),
2321 G_CALLBACK (source_changed_holder_cb), set);
2322
2323 }
2324 #ifdef GDA_DEBUG_signal
2325 g_print (">> 'SOURCE_MODEL_CHANGED' from %s\n", __FUNCTION__);
2326 #endif
2327 g_signal_emit (G_OBJECT (set), gda_set_signals[SOURCE_MODEL_CHANGED], 0, source);
2328 #ifdef GDA_DEBUG_signal
2329 g_print ("<< 'SOURCE_MODEL_CHANGED' from %s\n", __FUNCTION__);
2330 #endif
2331 }
2332
2333 #ifdef GDA_DEBUG_NO
2334 static void holder_dump (GdaHolder *holder);
2335 static void set_node_dump (GdaSetNode *node);
2336 static void set_source_dump (GdaSetSource *source);
2337 static void set_group_dump (GdaSetGroup *group);
2338
2339 static void
holder_dump(GdaHolder * holder)2340 holder_dump (GdaHolder *holder)
2341 {
2342 g_print (" GdaHolder %p (%s)\n", holder, holder ? gda_holder_get_id (holder) : "---");
2343 }
2344
2345 static void
set_source_dump(GdaSetSource * source)2346 set_source_dump (GdaSetSource *source)
2347 {
2348 g_print (" GdaSetSource %p\n", source);
2349 if (source) {
2350 g_print (" - data_model: %p\n", source->data_model);
2351 GSList *list;
2352 for (list = source->nodes; list; list = list->next)
2353 g_print (" - node: %p\n", list->data);
2354 }
2355 }
2356
2357 static void
set_group_dump(GdaSetGroup * group)2358 set_group_dump (GdaSetGroup *group)
2359 {
2360 g_print (" GdaSetGroup %p\n", group);
2361 if (group) {
2362 GSList *list;
2363 for (list = gda_set_group_get_nodes (group); list; list = list->next)
2364 g_print (" - node: %p\n", list->data);
2365 g_print (" - GdaSetSource: %p\n", group->nodes_source);
2366 }
2367 }
2368
2369 static void
set_node_dump(GdaSetNode * node)2370 set_node_dump (GdaSetNode *node)
2371 {
2372 g_print (" GdaSetNode: %p\n", node);
2373 g_print (" - holder: %p (%s)\n", node->holder, node->holder ? gda_holder_get_id (node->holder) : "ERROR : no GdaHolder!");
2374 g_print (" - source_model: %p\n", node->source_model);
2375 g_print (" - source_column: %d\n", node->source_column);
2376 }
2377
2378 void
gda_set_dump(GdaSet * set)2379 gda_set_dump (GdaSet *set)
2380 {
2381 g_print ("=== GdaSet %p ===\n", set);
2382 g_slist_foreach (set->holders, (GFunc) holder_dump, NULL);
2383 g_slist_foreach (set->nodes_list, (GFunc) set_node_dump, NULL);
2384 g_slist_foreach (set->sources_list, (GFunc) set_source_dump, NULL);
2385 g_slist_foreach (set->groups_list, (GFunc) set_group_dump, NULL);
2386 g_print ("=== GdaSet %p END ===\n", set);
2387 }
2388 #endif
2389