1 /*
2 * Copyright (C) 2009 - 2012 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2010 David King <davidk@openismus.com>
4 * Copyright (C) 2013 Daniel Espinosa <esodan@gmail.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <string.h>
23 #include <glib/gi18n-lib.h>
24 #include <libgda/libgda.h>
25 #include "gdaui-set.h"
26 #include "marshallers/gdaui-marshal.h"
27
28 #ifdef GSEAL_ENABLE
29 /**
30 * GdauiSetGroup:
31 * @group:
32 * @source:
33 *
34 * The <structname>GdauiSetGroup</structname>.
35 *
36 * To create a new #GdauiSetGroup use #gdaiu_set_group_new.
37 *
38 * To free a #GdauiSetGroup, created by #gdaui_set_group_new, use #gda_set_group_free.
39 *
40 * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
41 * Don't try to use #gdaui_set_group_free on a struct that was created manually.
42 */
43 struct _GdauiSetGroup {
44 GdaSetGroup *group;
45 GdauiSetSource *source; /* if NULL, then @group->nodes contains exactly one entry */
46
47 /*< private >*/
48 /* Padding for future expansion */
49 gpointer _gda_reserved1;
50 gpointer _gda_reserved2;
51 };
52 #else
53 #endif
54
55 /*
56 Register GdauiSetGroup type
57 */
58 GType
gdaui_set_group_get_type(void)59 gdaui_set_group_get_type (void)
60 {
61 static GType type = 0;
62
63 if (G_UNLIKELY (type == 0)) {
64 if (type == 0)
65 type = g_boxed_type_register_static ("GdauiSetGroup",
66 (GBoxedCopyFunc) gdaui_set_group_copy,
67 (GBoxedFreeFunc) gdaui_set_group_free);
68 }
69
70 return type;
71 }
72
73 /**
74 * gdaui_set_group_new:
75 * @group: a #GdaSetGroup
76 *
77 * Creates a new #GdauiSetGroup struct.
78 *
79 * Return: (transfer full): a new #GdauiSetGroup struct.
80 *
81 * Since: 5.2
82 */
83 GdauiSetGroup*
gdaui_set_group_new(GdaSetGroup * group)84 gdaui_set_group_new (GdaSetGroup *group)
85 {
86 g_return_val_if_fail (group, NULL);
87 GdauiSetGroup *sg = g_new0 (GdauiSetGroup, 1);
88 sg->source = NULL;
89 sg->group = group;
90 return sg;
91 }
92
93 /**
94 * gdaui_set_group_copy:
95 * @sg: a #GdauiSetGroup
96 *
97 * Copy constructor.
98 *
99 * Returns: a new #GdauiSetGroup
100 *
101 * Since: 5.2
102 */
103 GdauiSetGroup *
gdaui_set_group_copy(GdauiSetGroup * sg)104 gdaui_set_group_copy (GdauiSetGroup *sg)
105 {
106 g_return_val_if_fail (sg, NULL);
107
108 GdauiSetGroup *n;
109 n = gdaui_set_group_new (gdaui_set_group_get_group (sg));
110 gdaui_set_group_set_source (n, gdaui_set_group_get_source (sg));
111 return n;
112 }
113
114 /**
115 * gdaui_set_group_free:
116 * @sg: (allow-none): a #GdauiSetGroup struct to free
117 *
118 * Frees any resources taken by @sg struct. If @sg is %NULL, then nothing happens.
119 *
120 * Since: 5.2
121 */
122 void
gdaui_set_group_free(GdauiSetGroup * sg)123 gdaui_set_group_free (GdauiSetGroup *sg)
124 {
125 g_return_if_fail(sg);
126 g_free (sg);
127 }
128
129 /**
130 * gdaui_set_group_set_source:
131 * @sg: a #GdauiSetGroup struct to free
132 * @source (allow-none): a #GdauiSetSource struct or NULL
133 *
134 * Set source to @source. if @source is #NULL, then @group nodes contains exactly one entry.
135 *
136 * Since: 5.2
137 */
138 void
gdaui_set_group_set_source(GdauiSetGroup * sg,GdauiSetSource * source)139 gdaui_set_group_set_source (GdauiSetGroup *sg, GdauiSetSource *source)
140 {
141 g_return_if_fail (sg);
142 sg->source = source;
143 }
144
145 /**
146 * gdaui_set_group_get_source:
147 * @sg: a #GdauiSetGroup struct
148 *
149 * Get source used by @sg.
150 *
151 * Returns: used #GdaSetGroup
152 *
153 * Since: 5.2
154 */
155 GdauiSetSource*
gdaui_set_group_get_source(GdauiSetGroup * sg)156 gdaui_set_group_get_source (GdauiSetGroup *sg)
157 {
158 g_return_val_if_fail (sg, NULL);
159 return sg->source;
160 }
161
162 /**
163 * gdaui_set_group_set_group:
164 * @sg: a #GdauiSetGroup struct to free
165 * @group: a #GdaSetGroup struct
166 *
167 * Set source to @source.
168 *
169 * Since: 5.2
170 */
171 void
gdaui_set_group_set_group(GdauiSetGroup * sg,GdaSetGroup * group)172 gdaui_set_group_set_group (GdauiSetGroup *sg, GdaSetGroup *group)
173 {
174 g_return_if_fail (sg);
175 g_warn_if_fail (group);
176 sg->group = sg->group;
177 }
178
179 /**
180 * gdaui_set_group_get_group:
181 * @sg: a #GdauiSetGroup struct to free
182 *
183 * Get group used by @sg.
184 *
185 * Returns: used #GdaSetGroup
186 *
187 * Since: 5.2
188 */
189 GdaSetGroup*
gdaui_set_group_get_group(GdauiSetGroup * sg)190 gdaui_set_group_get_group (GdauiSetGroup *sg)
191 {
192 g_return_val_if_fail (sg, NULL);
193 return sg->group;
194 }
195
196 #ifdef GSEAL_ENABLE
197 /**
198 * GdauiSetSource:
199 * @source: a #GdaSetSource
200 * @shown_cols_index: (array length=shown_n_cols): Array with the column number to be shown from #GdaSetSource
201 * @shown_n_cols: number of elements of @shown_cols_index
202 * @ref_cols_index: (array length=ref_n_cols): Array with the number of columns as PRIMARY KEY in #GdaSetSource
203 * @ref_n_cols: number of elements of @ref_cols_index
204 *
205 * The <structname>GdauiSetSource</structname> is a ...
206 *
207 * To create a new #GdauiSetSource use #gdaui_set_source_new.
208 *
209 * To free a #GdauiSetSource, created by #gdaui_set_source_new, use #gdaui_set_source_free.
210 *
211 * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
212 * Don't try to use #gdaui_set_source_free on a struct that was created manually.
213 */
214 struct _GdauiSetSource {
215 GdaSetSource *source;
216
217 /* displayed columns in 'source->data_model' */
218 gint shown_n_cols;
219 gint *shown_cols_index;
220
221 /* columns used as a reference (corresponding to PK values) in 'source->data_model' */
222 gint ref_n_cols;
223 gint *ref_cols_index;
224
225 /*< private >*/
226 /* Padding for future expansion */
227 gpointer _gda_reserved1;
228 gpointer _gda_reserved2;
229 gpointer _gda_reserved3;
230 gpointer _gda_reserved4;
231 };
232 #else
233 #endif
234
235 /*
236 Register GdauiSetSource type
237 */
238 GType
gdaui_set_source_get_type(void)239 gdaui_set_source_get_type (void)
240 {
241 static GType type = 0;
242
243 if (G_UNLIKELY (type == 0)) {
244 if (type == 0)
245 type = g_boxed_type_register_static ("GdauiSetSource",
246 (GBoxedCopyFunc) gdaui_set_source_copy,
247 (GBoxedFreeFunc) gdaui_set_source_free);
248 }
249
250 return type;
251 }
252
253 /**
254 * gdaui_set_source_new:
255 *
256 * Creates a new #GdauiSetSource struct.
257 *
258 * Return: (transfer full): a new #GdauiSetSource struct.
259 *
260 * Since: 5.2
261 */
262 GdauiSetSource*
gdaui_set_source_new(GdaSetSource * source)263 gdaui_set_source_new (GdaSetSource *source)
264 {
265 g_return_val_if_fail (source, NULL);
266 GdauiSetSource *s = g_new0 (GdauiSetSource, 1);
267 s->source = source;
268 s->shown_n_cols = 0;
269 s->shown_cols_index = NULL;
270 s->ref_n_cols = 0;
271 s->ref_cols_index = NULL;
272
273 return s;
274 }
275
276 /**
277 * gdaui_set_source_copy:
278 * @s: a #GdauiSetGroup
279 *
280 * Copy constructor.
281 *
282 * Returns: a new #GdauiSetSource
283 *
284 * Since: 5.2
285 */
286 GdauiSetSource *
gdaui_set_source_copy(GdauiSetSource * s)287 gdaui_set_source_copy (GdauiSetSource *s)
288 {
289 GdauiSetSource *n;
290 g_return_val_if_fail (s, NULL);
291 n = gdaui_set_source_new (gdaui_set_source_get_source (s));
292 gdaui_set_source_set_ref_columns (n,
293 gdaui_set_source_get_ref_columns (s),
294 gdaui_set_source_get_ref_n_cols (s));
295 gdaui_set_source_set_shown_columns (n,
296 gdaui_set_source_get_shown_columns (s),
297 gdaui_set_source_get_shown_n_cols (s));
298 return n;
299 }
300
301 /**
302 * gdaui_set_source_free:
303 * @s: (allow-none): a #GdauiSetSource struct to free
304 *
305 * Frees any resources taken by @s struct. If @s is %NULL, then nothing happens.
306 *
307 * Since: 5.2
308 */
309 void
gdaui_set_source_free(GdauiSetSource * s)310 gdaui_set_source_free (GdauiSetSource *s)
311 {
312 g_return_if_fail(s);
313 if(s->shown_cols_index)
314 g_free(s->shown_cols_index);
315 if (s->ref_cols_index)
316 g_free(s->ref_cols_index);
317 g_free (s);
318 }
319
320 /**
321 * gdaui_set_source_set_source:
322 * @s: a #GdauiSetSource struct to free
323 * @source: a #GdaSetSource struct
324 *
325 * Set source to @source.
326 *
327 * Since: 5.2
328 */
329 void
gdaui_set_source_set_source(GdauiSetSource * s,GdaSetSource * source)330 gdaui_set_source_set_source (GdauiSetSource *s, GdaSetSource *source)
331 {
332 g_return_if_fail (s);
333 g_return_if_fail (source);
334 s->source = s->source;
335 }
336
337 /**
338 * gdaui_set_source_get_source:
339 * @s: a #GdauiSetGroup struct
340 *
341 * Get source used by @sg.
342 *
343 * Returns: used #GdaSetSource
344 *
345 * Since: 5.2
346 */
347 GdaSetSource*
gdaui_set_source_get_source(GdauiSetSource * s)348 gdaui_set_source_get_source (GdauiSetSource *s)
349 {
350 g_return_val_if_fail (s, NULL);
351 return s->source;
352 }
353
354 /**
355 * gdaui_set_source_get_shown_n_cols:
356 * @s: a #GdauiSetSource
357 *
358 * Returns: number of columns to be shown.
359 *
360 * Since: 5.2
361 */
362 gint
gdaui_set_source_get_shown_n_cols(GdauiSetSource * s)363 gdaui_set_source_get_shown_n_cols (GdauiSetSource *s)
364 {
365 g_return_val_if_fail (s, -1);
366 return s->shown_n_cols;
367 }
368
369 /**
370 * gdaui_set_source_get_shown_columns:
371 * @s: a #GdauiSetSource
372 *
373 * Returns: (array zero-terminated=1) (transfer none): array of of columns to be shown.
374 *
375 * Since: 5.2
376 */
377 gint*
gdaui_set_source_get_shown_columns(GdauiSetSource * s)378 gdaui_set_source_get_shown_columns (GdauiSetSource *s)
379 {
380 g_return_val_if_fail (s, NULL);
381 return s->shown_cols_index;
382 }
383
384 /**
385 * gdaui_set_source_set_shown_columns:
386 * @s: a #GdauiSetSource
387 * @columns: (array length=n_columns): an array of with columns numbers to be shown from a #GdaSetSource
388 * @n_columns: number of columns of the array
389 *
390 * Set the columns to be shown.
391 *
392 * Since: 5.2
393 */
394 void
gdaui_set_source_set_shown_columns(GdauiSetSource * s,gint * columns,gint n_columns)395 gdaui_set_source_set_shown_columns (GdauiSetSource *s, gint *columns, gint n_columns)
396 {
397 gint i;
398 g_return_if_fail (s);
399 g_return_if_fail (columns);
400 if (s->shown_cols_index)
401 g_free (s->shown_cols_index);
402 s->shown_n_cols = n_columns;
403 s->shown_cols_index = g_new0 (gint, s->shown_n_cols+1); /* This adds a null terminated array */
404 for (i = 0; i < n_columns; i++) {
405 s->shown_cols_index[i] = columns[i];
406 }
407 }
408
409 /**
410 * gdaui_set_source_get_ref_n_cols:
411 * @s: a #GdauiSetSource
412 *
413 * Returns: number of columns to referenced.
414 *
415 * Since: 5.2
416 */
417 gint
gdaui_set_source_get_ref_n_cols(GdauiSetSource * s)418 gdaui_set_source_get_ref_n_cols (GdauiSetSource *s)
419 {
420 g_return_val_if_fail (s, -1);
421 return s->ref_n_cols;
422 }
423
424 /**
425 * gdaui_set_source_get_ref_columns:
426 * @s: a #GdauiSetSource
427 *
428 * Returns: (array zero-terminated=1) (transfer none): array of of columns to be shown.
429 *
430 * Since: 5.2
431 */
432 gint*
gdaui_set_source_get_ref_columns(GdauiSetSource * s)433 gdaui_set_source_get_ref_columns (GdauiSetSource *s)
434 {
435 g_return_val_if_fail (s, NULL);
436 return s->ref_cols_index;
437 }
438
439 /**
440 * gdaui_set_source_set_ref_columns:
441 * @s: a #GdauiSetSource struct to free
442 * @columns: (array length=n_columns): an array of with columns numbers of referen (Primary Key) at #GdaSetSource
443 * @n_columns: number of columns of the array
444 *
445 * Set the columns to be shown.
446 *
447 * Since: 5.2
448 */
449 void
gdaui_set_source_set_ref_columns(GdauiSetSource * s,gint * columns,gint n_columns)450 gdaui_set_source_set_ref_columns (GdauiSetSource *s, gint *columns, gint n_columns)
451 {
452 gint i;
453 g_return_if_fail (s);
454 g_return_if_fail (columns);
455 if (s->ref_cols_index)
456 g_free (s->ref_cols_index);
457 s->ref_n_cols = n_columns;
458 s->ref_cols_index = g_new0 (gint, s->ref_n_cols+1); /* This creates a null terminated array */
459 for (i = 0; i < n_columns; i++) {
460 s->ref_cols_index[i] = columns[i];
461 }
462 }
463
464 static void gdaui_set_class_init (GdauiSetClass * class);
465 static void gdaui_set_init (GdauiSet *wid);
466 static void gdaui_set_dispose (GObject *object);
467
468 static void gdaui_set_set_property (GObject *object,
469 guint param_id,
470 const GValue *value,
471 GParamSpec *pspec);
472 static void gdaui_set_get_property (GObject *object,
473 guint param_id,
474 GValue *value,
475 GParamSpec *pspec);
476
477 static void wrapped_set_public_data_changed_cb (GdaSet *wset, GdauiSet *set);
478 static void wrapped_set_source_model_changed_cb (GdaSet *wset, GdaSetSource *source, GdauiSet *set);
479 static void clean_public_data (GdauiSet *set);
480 static void compute_public_data (GdauiSet *set);
481 static void update_public_data (GdauiSet *set);
482 static void compute_shown_columns_index (GdauiSetSource *dsource);
483 static void compute_ref_columns_index (GdauiSetSource *dsource);
484
485 struct _GdauiSetPriv
486 {
487 GdaSet *set;
488 };
489
490 /* get a pointer to the parents to be able to call their destructor */
491 static GObjectClass *parent_class = NULL;
492
493 /* properties */
494 enum {
495 PROP_0,
496 PROP_SET
497 };
498
499 /* signals */
500 enum {
501 PUBLIC_DATA_CHANGED,
502 SOURCE_MODEL_CHANGED,
503 LAST_SIGNAL
504 };
505
506 static gint gdaui_set_signals[LAST_SIGNAL] = { 0, 0 };
507
508 GType
_gdaui_set_get_type(void)509 _gdaui_set_get_type (void) {
510 return gdaui_set_get_type ();
511 }
512
513 GType
gdaui_set_get_type(void)514 gdaui_set_get_type (void)
515 {
516 static GType type = 0;
517
518 if (G_UNLIKELY (type == 0)) {
519 static const GTypeInfo info = {
520 sizeof (GdauiSetClass),
521 (GBaseInitFunc) NULL,
522 (GBaseFinalizeFunc) NULL,
523 (GClassInitFunc) gdaui_set_class_init,
524 NULL,
525 NULL,
526 sizeof (GdauiSet),
527 0,
528 (GInstanceInitFunc) gdaui_set_init,
529 0
530 };
531
532 type = g_type_register_static (G_TYPE_OBJECT, "GdauiSet", &info, 0);
533 }
534
535 return type;
536 }
537
538 static void
gdaui_set_class_init(GdauiSetClass * class)539 gdaui_set_class_init (GdauiSetClass *class)
540 {
541 GObjectClass *object_class = G_OBJECT_CLASS (class);
542
543 parent_class = g_type_class_peek_parent (class);
544 object_class->dispose = gdaui_set_dispose;
545
546 /**
547 * GdauiSet::public-data-changed:
548 * @set: the #GdauiSet
549 *
550 * Gets emitted when @set's public data (#GdauiSetGroup or #GdauiSetSource values) have changed
551 *
552 * Since: 4.2
553 */
554 gdaui_set_signals[PUBLIC_DATA_CHANGED] =
555 g_signal_new ("public-data-changed",
556 G_TYPE_FROM_CLASS (object_class),
557 G_SIGNAL_RUN_FIRST,
558 G_STRUCT_OFFSET (GdauiSetClass, public_data_changed),
559 NULL, NULL,
560 _gdaui_marshal_VOID__VOID, G_TYPE_NONE, 0);
561 /**
562 * GdauiSet::source-model-changed:
563 * @set: the #GdauiSet
564 *
565 * Gets emitted when the data model used in @set's #GdauiSetSource has changed
566 *
567 * Since: 4.2
568 */
569 gdaui_set_signals[SOURCE_MODEL_CHANGED] =
570 g_signal_new ("source-model-changed",
571 G_TYPE_FROM_CLASS (object_class),
572 G_SIGNAL_RUN_FIRST,
573 G_STRUCT_OFFSET (GdauiSetClass, public_data_changed),
574 NULL, NULL,
575 _gdaui_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
576
577 class->public_data_changed = NULL;
578 class->source_model_changed = NULL;
579
580 /* Properties */
581 object_class->set_property = gdaui_set_set_property;
582 object_class->get_property = gdaui_set_get_property;
583 g_object_class_install_property (object_class, PROP_SET,
584 g_param_spec_object ("set", NULL, NULL,
585 GDA_TYPE_SET,
586 G_PARAM_READABLE | G_PARAM_WRITABLE |
587 G_PARAM_CONSTRUCT_ONLY));
588 }
589
590 static void
gdaui_set_init(GdauiSet * set)591 gdaui_set_init (GdauiSet *set)
592 {
593 set->priv = g_new0 (GdauiSetPriv, 1);
594 set->priv->set = NULL;
595 }
596
597 /*
598 * _gdaui_set_new
599 * @set: a #GdaSet
600 *
601 * Creates a new #GdauiSet which wraps @set's properties
602 *
603 * Returns: the new widget
604 *
605 * Deprecated: Since 5.2
606 */
607 GdauiSet *
_gdaui_set_new(GdaSet * set)608 _gdaui_set_new (GdaSet *set)
609 {
610 return gdaui_set_new (set);
611 }
612
613 /**
614 * gdaui_set_new:
615 * @set: a #GdaSet
616 *
617 * Creates a new #GdauiSet which wraps @set's properties
618 *
619 * Returns: the new widget
620 * Since: 5.2
621 **/
622 GdauiSet *
gdaui_set_new(GdaSet * set)623 gdaui_set_new (GdaSet *set)
624 {
625 g_return_val_if_fail (GDA_IS_SET (set), NULL);
626
627 return (GdauiSet *) g_object_new (GDAUI_TYPE_SET, "set", set, NULL);
628 }
629
630 static void
gdaui_set_dispose(GObject * object)631 gdaui_set_dispose (GObject *object)
632 {
633 GdauiSet *set;
634
635 g_return_if_fail (GDAUI_IS_SET (object));
636
637 set = GDAUI_SET (object);
638
639 if (set->priv) {
640 if (set->priv->set) {
641 g_signal_handlers_disconnect_by_func (G_OBJECT (set->priv->set),
642 G_CALLBACK (wrapped_set_public_data_changed_cb), set);
643 g_signal_handlers_disconnect_by_func (G_OBJECT (set->priv->set),
644 G_CALLBACK (wrapped_set_source_model_changed_cb), set);
645
646 g_object_unref (set->priv->set);
647 set->priv->set = NULL;
648 }
649
650 clean_public_data (set);
651
652 g_free (set->priv);
653 set->priv = NULL;
654 }
655
656 /* for the parent class */
657 parent_class->dispose (object);
658 }
659
660 static void
gdaui_set_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)661 gdaui_set_set_property (GObject *object,
662 guint param_id,
663 const GValue *value,
664 GParamSpec *pspec)
665 {
666 GdauiSet *set;
667
668 set = GDAUI_SET (object);
669
670 switch (param_id) {
671 case PROP_SET:
672 set->priv->set = g_value_get_object (value);
673 if (set->priv->set) {
674 g_object_ref (set->priv->set);
675 compute_public_data (set);
676 g_signal_connect (set->priv->set, "public-data-changed",
677 G_CALLBACK (wrapped_set_public_data_changed_cb), set);
678 g_signal_connect (set->priv->set, "source-model-changed",
679 G_CALLBACK (wrapped_set_source_model_changed_cb), set);
680 }
681 break;
682 default:
683 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
684 break;
685 }
686 }
687
688 static void
wrapped_set_public_data_changed_cb(G_GNUC_UNUSED GdaSet * wset,GdauiSet * set)689 wrapped_set_public_data_changed_cb (G_GNUC_UNUSED GdaSet *wset, GdauiSet *set)
690 {
691 update_public_data (set);
692 g_signal_emit (set, gdaui_set_signals[PUBLIC_DATA_CHANGED], 0);
693 }
694
695 static void
wrapped_set_source_model_changed_cb(G_GNUC_UNUSED GdaSet * wset,GdaSetSource * source,GdauiSet * set)696 wrapped_set_source_model_changed_cb (G_GNUC_UNUSED GdaSet *wset, GdaSetSource *source, GdauiSet *set)
697 {
698 GdauiSetSource *uisource = NULL;
699 GSList *list;
700 for (list = set->sources_list; list; list = list->next) {
701 if (((GdauiSetSource*) list->data)->source == source) {
702 uisource = (GdauiSetSource*) list->data;
703 break;
704 }
705 }
706 if (uisource)
707 g_signal_emit (set, gdaui_set_signals[SOURCE_MODEL_CHANGED], 0, uisource);
708 }
709
710 static void
clean_public_data(GdauiSet * set)711 clean_public_data (GdauiSet *set)
712 {
713 GSList *list;
714
715 for (list = set->sources_list; list; list = list->next) {
716 GdauiSetSource *dsource = (GdauiSetSource*) list->data;
717 gdaui_set_source_free (dsource);
718 }
719 g_slist_free (set->sources_list);
720 set->sources_list = NULL;
721
722 for (list = set->groups_list; list; list = list->next) {
723 GdauiSetGroup *dgroup = (GdauiSetGroup*) list->data;
724 gdaui_set_group_free (dgroup);
725 }
726 g_slist_free (set->groups_list);
727 set->groups_list = NULL;
728 }
729
730 static void
compute_public_data(GdauiSet * set)731 compute_public_data (GdauiSet *set)
732 {
733 GSList *list;
734 GdaSet *aset = GDA_SET (set->priv->set);
735 GHashTable *hash;
736
737 /* scan GdaSetSource list */
738 hash = g_hash_table_new (NULL, NULL);
739 for (list = aset->sources_list; list; list = list->next) {
740 GdauiSetSource *dsource;
741 dsource = gdaui_set_source_new (GDA_SET_SOURCE (list->data));
742 set->sources_list = g_slist_prepend (set->sources_list, dsource);
743 g_hash_table_insert (hash, list->data, dsource);
744
745 compute_shown_columns_index (dsource);
746 compute_ref_columns_index (dsource);
747 }
748 set->sources_list = g_slist_reverse (set->sources_list);
749
750 /* scan GdaSetGroup list */
751 for (list = aset->groups_list; list; list = list->next) {
752 GdauiSetGroup *dgroup;
753 g_assert (list->data);
754 dgroup = gdaui_set_group_new (GDA_SET_GROUP (list->data));
755 gdaui_set_group_set_source (dgroup,
756 g_hash_table_lookup (hash,
757 gda_set_group_get_source (GDA_SET_GROUP (list->data))));
758 set->groups_list = g_slist_prepend (set->groups_list, dgroup);
759 }
760 set->groups_list = g_slist_reverse (set->groups_list);
761
762 g_hash_table_destroy (hash);
763 }
764
765 static void
update_public_data(GdauiSet * set)766 update_public_data (GdauiSet *set)
767 {
768 GSList *list, *elist = NULL;
769 GdaSet *aset = GDA_SET (set->priv->set);
770 GHashTable *shash; /* key = GdaSetSource, value = GdauiSetSource */
771 GHashTable *ghash; /* key = GdaSetGroup, value = GdauiSetGroup */
772
773 /* build hash with existing sources in GdauiSet */
774 shash = g_hash_table_new (NULL, NULL);
775 for (list = set->sources_list; list; list = list->next) {
776 GdauiSetSource *dsource = (GdauiSetSource*) list->data;
777 g_hash_table_insert (shash, gdaui_set_source_get_source (dsource), dsource);
778 }
779
780 /* scan GdaSetSource list */
781 elist = set->sources_list;
782 set->sources_list = NULL;
783 for (list = aset->sources_list; list; list = list->next) {
784 GdauiSetSource *dsource;
785 dsource = g_hash_table_lookup (shash, list->data);
786 if (dsource) {
787 set->sources_list = g_slist_prepend (set->sources_list, dsource);
788 continue;
789 }
790 dsource = gdaui_set_source_new (GDA_SET_SOURCE (list->data));
791 set->sources_list = g_slist_prepend (set->sources_list, dsource);
792 g_hash_table_insert (shash, list->data, dsource);
793
794 compute_shown_columns_index (dsource);
795 compute_ref_columns_index (dsource);
796 }
797 set->sources_list = g_slist_reverse (set->sources_list);
798
799 if (elist) {
800 for (list = elist; list; list = list->next) {
801 if (!g_slist_find (set->sources_list, list->data)) {
802 GdauiSetSource *dsource = (GdauiSetSource*) list->data;
803 gdaui_set_source_free (dsource);
804 }
805 }
806 g_slist_free (elist);
807 }
808
809 /* build hash with existing groups */
810 ghash = g_hash_table_new (NULL, NULL);
811 for (list = set->groups_list; list; list = list->next) {
812 GdauiSetGroup *dgroup = (GdauiSetGroup*) list->data;
813 g_hash_table_insert (ghash, gdaui_set_group_get_group (dgroup), dgroup);
814 }
815
816 /* scan GdaSetGroup list */
817 elist = set->groups_list;
818 set->groups_list = NULL;
819 for (list = aset->groups_list; list; list = list->next) {
820 GdauiSetGroup *dgroup;
821 dgroup = g_hash_table_lookup (ghash, list->data);
822 if (dgroup) {
823 set->groups_list = g_slist_prepend (set->groups_list, dgroup);
824 continue;
825 }
826 dgroup = gdaui_set_group_new (GDA_SET_GROUP (list->data));
827 gdaui_set_group_set_source (dgroup, g_hash_table_lookup (shash,
828 gda_set_group_get_source (gdaui_set_group_get_group (dgroup))));
829 set->groups_list = g_slist_prepend (set->groups_list, dgroup);
830 }
831 set->groups_list = g_slist_reverse (set->groups_list);
832
833 if (elist) {
834 for (list = elist; list; list = list->next) {
835 if (!g_slist_find (set->groups_list, list->data)) {
836 GdauiSetGroup *dgroup = (GdauiSetGroup*) list->data;
837 gdaui_set_group_free (dgroup);
838 }
839 }
840 g_slist_free (elist);
841 }
842
843 g_hash_table_destroy (shash);
844 g_hash_table_destroy (ghash);
845 }
846
847 static void
compute_shown_columns_index(GdauiSetSource * dsource)848 compute_shown_columns_index (GdauiSetSource *dsource)
849 {
850 gint ncols, nholders;
851 gint *mask = NULL, masksize = 0;
852
853 nholders = gda_set_source_get_n_nodes (gdaui_set_source_get_source (dsource));
854 g_return_if_fail (nholders > 0);
855 ncols = gda_data_model_get_n_columns (gda_set_source_get_data_model (gdaui_set_source_get_source (dsource)));
856 g_return_if_fail (ncols > 0);
857
858 if (ncols > nholders) {
859 /* we only want columns which are not holders */
860 gint i, current = 0;
861
862 masksize = ncols - nholders;
863 mask = g_new0 (gint, masksize);
864 for (i = 0; i < ncols ; i++) {
865 GSList *list = gda_set_source_get_nodes (gdaui_set_source_get_source (dsource));
866 gboolean found = FALSE;
867 while (list && !found) {
868 if (gda_set_node_get_source_column (GDA_SET_NODE (list->data)) == i)
869 found = TRUE;
870 else
871 list = g_slist_next (list);
872 }
873 if (!found) {
874 mask[current] = i;
875 current ++;
876 }
877 }
878 masksize = current;
879 }
880 else {
881 /* we want all the columns */
882 gint i;
883
884 masksize = ncols;
885 mask = g_new0 (gint, masksize);
886 for (i=0; i<ncols; i++) {
887 mask[i] = i;
888 }
889 }
890 gdaui_set_source_set_shown_columns (dsource, mask, masksize);
891 }
892
893 void
compute_ref_columns_index(GdauiSetSource * dsource)894 compute_ref_columns_index (GdauiSetSource *dsource)
895 {
896 gint ncols, nholders;
897 gint *mask = NULL, masksize = 0;
898
899 nholders = gda_set_source_get_n_nodes (gdaui_set_source_get_source (dsource));
900 g_return_if_fail (nholders > 0);
901 ncols = gda_data_model_get_n_columns (gda_set_source_get_data_model (gdaui_set_source_get_source (dsource)));
902 g_return_if_fail (ncols > 0);
903
904 if (ncols > nholders) {
905 /* we only want columns which are holders */
906 gint i, current = 0;
907
908 masksize = ncols - nholders;
909 mask = g_new0 (gint, masksize);
910 for (i=0; i<ncols ; i++) {
911 GSList *list = gda_set_source_get_nodes (gdaui_set_source_get_source (dsource));
912 gboolean found = FALSE;
913 while (list && !found) {
914 if (gda_set_node_get_source_column (GDA_SET_NODE (list->data)) == i)
915 found = TRUE;
916 else
917 list = g_slist_next (list);
918 }
919 if (found) {
920 mask[current] = i;
921 current ++;
922 }
923 }
924 masksize = current;
925 }
926 else {
927 /* we want all the columns */
928 gint i;
929
930 masksize = ncols;
931 mask = g_new0 (gint, masksize);
932 for (i=0; i<ncols; i++) {
933 mask[i] = i;
934 }
935 }
936 gdaui_set_source_set_ref_columns (dsource, mask, masksize);
937 }
938
939
940 static void
gdaui_set_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)941 gdaui_set_get_property (GObject *object,
942 guint param_id,
943 GValue *value,
944 GParamSpec *pspec)
945 {
946 GdauiSet *set;
947
948 set = GDAUI_SET (object);
949
950 switch (param_id) {
951 case PROP_SET:
952 g_value_set_object (value, set->priv->set);
953 break;
954 default:
955 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
956 break;
957 }
958 }
959
960 /**
961 * _gdaui_set_get_group:
962 * @dbset:
963 * @holder:
964 *
965 * Returns: A new #GdauiSetGroup struct
966 * Deprecated: Since 5.2
967 **/
968 GdauiSetGroup *
_gdaui_set_get_group(GdauiSet * dbset,GdaHolder * holder)969 _gdaui_set_get_group (GdauiSet *dbset, GdaHolder *holder)
970 {
971 return gdaui_set_get_group (dbset, holder);
972 }
973
974 /**
975 * gdaui_set_get_group:
976 * @dbset:
977 * @holder:
978 *
979 * Returns: A new #GdauiSetGroup struct
980 * Since: 5.2
981 **/
982 GdauiSetGroup *
gdaui_set_get_group(GdauiSet * dbset,GdaHolder * holder)983 gdaui_set_get_group (GdauiSet *dbset, GdaHolder *holder)
984 {
985 GdaSetGroup *agroup;
986 GSList *list;
987 g_return_val_if_fail (GDAUI_IS_SET (dbset), NULL);
988 g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
989
990 agroup = gda_set_get_group (dbset->priv->set, holder);
991 if (!agroup)
992 return NULL;
993
994 for (list = dbset->groups_list; list; list = list->next) {
995 if (GDAUI_SET_GROUP (list->data)->group == agroup)
996 return GDAUI_SET_GROUP (list->data);
997 }
998 return NULL;
999 }
1000
1001 #ifdef GDA_DEBUG_NO
1002 static void _gda_set_node_dump (GdaSetNode *node);
1003 static void set_source_dump (GdauiSetSource *source);
1004 static void set_group_dump (GdauiSetGroup *group);
1005
1006 static void
set_source_dump(GdauiSetSource * source)1007 set_source_dump (GdauiSetSource *source)
1008 {
1009 g_print (" GdauiSetSource %p\n", source);
1010 if (source) {
1011 gint i;
1012 g_print (" - GdaSetSource: %p\n", source->source);
1013 for (i = 0; i < source->shown_n_cols; i++)
1014 g_print (" - shown_cols_index [%d]: %d\n", i, source->shown_cols_index[i]);
1015 for (i = 0; i < source->ref_n_cols; i++)
1016 g_print (" - ref_cols_index [%d]: %d\n", i, source->ref_cols_index[i]);
1017 }
1018 }
1019
1020 static void
set_group_dump(GdauiSetGroup * group)1021 set_group_dump (GdauiSetGroup *group)
1022 {
1023 g_print (" GdauiSetGroup %p\n", group);
1024 if (group) {
1025 g_print (" - GdaSetGroup: %p\n", group->group);
1026 if (group->group->nodes)
1027 g_slist_foreach (group->group->nodes, (GFunc) _gda_set_node_dump, NULL);
1028 else
1029 g_print (" ERROR: group has no node!\n");
1030 g_print (" - GdauiSetSource: %p\n", group->source);
1031 }
1032 }
1033
1034 static void
_gda_set_node_dump(GdaSetNode * node)1035 _gda_set_node_dump (GdaSetNode *node)
1036 {
1037 g_print (" - GdaSetNode: %p\n", node);
1038 g_print (" - holder: %p (%s)\n", node->holder, node->holder ? gda_holder_get_id (node->holder) : "ERROR : no GdaHolder!");
1039 g_print (" - source_model: %p\n", node->source_model);
1040 g_print (" - source_column: %d\n", node->source_column);
1041 }
1042
1043 static void
_gdaui_set_dump(GdauiSet * set)1044 _gdaui_set_dump (GdauiSet *set)
1045 {
1046 g_print ("=== GdauiSet %p ===\n", set);
1047 gda_set_dump (set->priv->set);
1048 g_slist_foreach (set->sources_list, (GFunc) set_source_dump, NULL);
1049 g_slist_foreach (set->groups_list, (GFunc) set_group_dump, NULL);
1050 g_print ("=== GdauiSet %p END ===\n", set);
1051 }
1052 #endif
1053