3
* Copyright (C) 2003 - 2004 Vivien Malerba
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22
#include "mg-parameter.h"
26
#include "mg-entity.h"
28
#include "mg-qfield.h"
29
#include "mg-server-data-type.h"
30
#include "mg-xml-storage.h"
31
#include "mg-referer.h"
34
* Main static functions
36
static void mg_parameter_class_init (MgParameterClass * class);
37
static void mg_parameter_init (MgParameter * srv);
38
static void mg_parameter_dispose (GObject * object);
39
static void mg_parameter_finalize (GObject * object);
41
static void mg_parameter_set_property (GObject *object,
45
static void mg_parameter_get_property (GObject *object,
50
/* Referer interface */
51
static void mg_parameter_referer_init (MgRefererIface *iface);
52
static GSList *mg_parameter_get_ref_objects (MgReferer *iface);
53
static void mg_parameter_replace_refs (MgReferer *iface, GHashTable *replacements);
55
static void mg_parameter_add_for_field (MgParameter *param, MgQfield *for_field);
56
static void mg_parameter_del_for_field (MgParameter *param, MgQfield *for_field);
57
static void mg_parameter_set_data_type (MgParameter *param, MgServerDataType *type);
59
static void nullified_object_cb (MgBase *obj, MgParameter *param);
60
static void nullified_for_field_cb (MgBase *obj, MgParameter *param);
61
static void nullified_depend_on_cb (MgBase *obj, MgParameter *param);
62
static void nullified_source_field_cb (MgBase *obj, MgParameter *param);
63
static void nullified_alias_of_cb (MgBase *obj, MgParameter *param);
65
static void alias_of_changed_cb (MgParameter *alias_of, MgParameter *param);
67
static void mg_parameter_signal_changed (MgBase *base, gboolean block_changed_signal);
69
static void mg_parameter_dump (MgParameter *parameter, guint offset);
72
static void mg_parameter_set_full_bind_param (MgParameter *param, MgParameter *alias_of);
74
/* get a pointer to the parents to be able to call their destructor */
75
static GObjectClass *parent_class = NULL;
83
static gint mg_parameter_signals[LAST_SIGNAL] = { };
91
PROP_USE_DEFAULT_VALUE,
97
struct _MgParameterPrivate
100
MgServerDataType *type;
101
MgParameter *alias_of; /* FULL bind to param */
102
MgParameter *change_with; /* SIMPLE bind to param */
104
gboolean invalid_forced;
106
gboolean default_forced;
108
GdaValue *default_value; /* CAN be either NULL or of any type */
109
gboolean not_null; /* TRUE if 'value' must not be NULL when passed to destination fields */
111
MgQfield *in_field; /* if not NULL, limits the possible values for the parameter */
112
GSList *dependencies; /* other MgParameter objects on which the parameter depends on */
114
gchar *plugin; /* plugin to be used for user interaction */
116
gboolean user_input_required;
120
GQuark mg_parameter_error_quark (void)
124
quark = g_quark_from_static_string ("mg_parameter_error");
129
mg_parameter_get_type (void)
131
static GType type = 0;
134
static const GTypeInfo info = {
135
sizeof (MgParameterClass),
136
(GBaseInitFunc) NULL,
137
(GBaseFinalizeFunc) NULL,
138
(GClassInitFunc) mg_parameter_class_init,
141
sizeof (MgParameter),
143
(GInstanceInitFunc) mg_parameter_init
146
static const GInterfaceInfo referer_info = {
147
(GInterfaceInitFunc) mg_parameter_referer_init,
152
type = g_type_register_static (MG_BASE_TYPE, "MgParameter", &info, 0);
153
g_type_add_interface_static (type, MG_REFERER_TYPE, &referer_info);
159
mg_parameter_referer_init (MgRefererIface *iface)
161
iface->activate = NULL;
162
iface->deactivate = NULL;
163
iface->is_active = NULL;
164
iface->get_ref_objects = mg_parameter_get_ref_objects;
165
iface->replace_refs = mg_parameter_replace_refs;
169
mg_parameter_class_init (MgParameterClass * class)
171
GObjectClass *object_class = G_OBJECT_CLASS (class);
173
parent_class = g_type_class_peek_parent (class);
176
/* virtual functions */
177
MG_BASE_CLASS (class)->signal_changed = mg_parameter_signal_changed;
179
MG_BASE_CLASS (class)->dump = (void (*)(MgBase *, guint)) mg_parameter_dump;
182
object_class->dispose = mg_parameter_dispose;
183
object_class->finalize = mg_parameter_finalize;
186
object_class->set_property = mg_parameter_set_property;
187
object_class->get_property = mg_parameter_get_property;
188
g_object_class_install_property (object_class, PROP_PLUGIN,
189
g_param_spec_string ("handler_plugin", NULL, NULL, NULL,
190
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
191
g_object_class_install_property (object_class, PROP_USE_DEFAULT_VALUE,
192
g_param_spec_boolean ("use_default_value", NULL, NULL, FALSE,
193
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
194
g_object_class_install_property (object_class, PROP_SIMPLE_BIND,
195
g_param_spec_pointer ("simple_bind", NULL, NULL, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
196
g_object_class_install_property (object_class, PROP_FULL_BIND,
197
g_param_spec_pointer ("full_bind", NULL, NULL, (G_PARAM_READABLE | G_PARAM_WRITABLE)));
201
mg_parameter_init (MgParameter *parameter)
203
parameter->priv = g_new0 (MgParameterPrivate, 1);
204
parameter->priv->for_fields = NULL;
205
parameter->priv->type = NULL;
206
parameter->priv->alias_of = NULL;
207
parameter->priv->change_with = NULL;
209
parameter->priv->invalid_forced = FALSE;
210
parameter->priv->valid = FALSE;
211
parameter->priv->default_forced = FALSE;
212
parameter->priv->value = NULL;
213
parameter->priv->default_value = NULL;
215
parameter->priv->not_null = FALSE;
216
parameter->priv->in_field = NULL;
217
parameter->priv->dependencies = NULL;
218
parameter->priv->plugin = NULL;
219
parameter->priv->user_input_required = FALSE;
224
* @conf: a #MgConf object
225
* @type: the #MgServerDataType requested
227
* Creates a new parameter of type @type
229
* Returns: a new #MgParameter object
232
mg_parameter_new (MgConf *conf, MgServerDataType *type)
237
g_return_val_if_fail (conf && IS_MG_CONF (conf), NULL);
238
g_return_val_if_fail (type && IS_MG_SERVER_DATA_TYPE (type), NULL);
240
obj = g_object_new (MG_PARAMETER_TYPE, "conf", conf, NULL);
241
param = MG_PARAMETER (obj);
243
mg_parameter_set_data_type (param, type);
249
* mg_parameter_new_copy
250
* @orig: a #MgParameter object to copy
254
* Returns: a new #MgParameter object
257
mg_parameter_new_copy (MgParameter *orig)
263
g_return_val_if_fail (orig && IS_MG_PARAMETER (orig), NULL);
264
g_return_val_if_fail (orig->priv, NULL);
266
obj = g_object_new (MG_PARAMETER_TYPE, "conf", mg_base_get_conf (MG_BASE (orig)), NULL);
267
param = MG_PARAMETER (obj);
269
mg_base_set_name (MG_BASE (param), mg_base_get_name (MG_BASE (orig)));
270
mg_base_set_description (MG_BASE (param), mg_base_get_description (MG_BASE (orig)));
272
/* setting which require calling another function */
273
mg_parameter_set_data_type (param, orig->priv->type);
274
list = orig->priv->for_fields;
276
mg_parameter_add_for_field (param, MG_QFIELD (list->data));
277
list = g_slist_next (list);
279
if (orig->priv->alias_of)
280
mg_parameter_set_full_bind_param (param, orig->priv->alias_of);
281
if (orig->priv->change_with)
282
mg_parameter_bind_to_param (param, orig->priv->change_with);
284
if (orig->priv->in_field)
285
mg_parameter_set_source_field (param, orig->priv->in_field, NULL);
286
list = orig->priv->dependencies;
288
mg_parameter_add_dependency (param, MG_PARAMETER (list->data));
289
list = g_slist_next (list);
292
/* direct settings */
293
param->priv->invalid_forced = orig->priv->invalid_forced;
294
param->priv->valid = orig->priv->valid;
295
param->priv->default_forced = orig->priv->default_forced;
296
if (orig->priv->value)
297
param->priv->value = gda_value_copy (orig->priv->value);
298
if (orig->priv->default_value)
299
param->priv->default_value = gda_value_copy (orig->priv->default_value);
300
param->priv->not_null = orig->priv->not_null;
301
if (orig->priv->plugin)
302
param->priv->plugin = g_strdup (orig->priv->plugin);
303
param->priv->user_input_required = orig->priv->user_input_required;
309
* mg_parameter_new_with_dest_field
310
* @field: the #MgQfield object the parameter is for
311
* @type: the #MgServerDataType requested
313
* Creates a new parameter to be passed to @field for the operations where a parameter is required;
314
* other #MgQfield can also be added by using the mg_parameter_add_dest_field() method.
316
* Returns: a new #MgParameter object
319
mg_parameter_new_with_dest_field (MgQfield *field, MgServerDataType *type)
325
g_return_val_if_fail (field && IS_MG_QFIELD (field), NULL);
326
g_return_val_if_fail (type && IS_MG_SERVER_DATA_TYPE (type), NULL);
328
conf = mg_base_get_conf (MG_BASE (field));
329
g_return_val_if_fail (conf, NULL);
331
obj = g_object_new (MG_PARAMETER_TYPE, "conf", conf, NULL);
332
param = MG_PARAMETER (obj);
334
mg_parameter_add_for_field (param, field);
335
mg_parameter_set_data_type (param, type);
341
mg_parameter_add_for_field (MgParameter *param, MgQfield *for_field)
343
if (!g_slist_find (param->priv->for_fields, for_field)) {
344
param->priv->for_fields = g_slist_append (param->priv->for_fields, for_field);
345
g_signal_connect (G_OBJECT (for_field), "nullified",
346
G_CALLBACK (nullified_for_field_cb), param);
347
g_object_ref (G_OBJECT (for_field));
352
mg_parameter_del_for_field (MgParameter *param, MgQfield *for_field)
354
if (g_slist_find (param->priv->for_fields, for_field)) {
355
g_signal_handlers_disconnect_by_func (G_OBJECT (for_field),
356
G_CALLBACK (nullified_for_field_cb), param);
357
g_object_unref (G_OBJECT (for_field));
358
param->priv->for_fields = g_slist_remove (param->priv->for_fields, for_field);
363
mg_parameter_set_data_type (MgParameter *param, MgServerDataType *type)
365
if (param->priv->type) {
366
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->type),
367
G_CALLBACK (nullified_object_cb), param);
368
g_object_unref (G_OBJECT (param->priv->type));
369
param->priv->type = NULL;
373
param->priv->type = type;
374
g_signal_connect (G_OBJECT (type), "nullified",
375
G_CALLBACK (nullified_object_cb), param);
376
g_object_ref (G_OBJECT (param->priv->type));
381
nullified_for_field_cb (MgBase *obj, MgParameter *param)
383
mg_parameter_del_for_field (param, MG_QFIELD (obj));
387
nullified_object_cb (MgBase *obj, MgParameter *param)
389
mg_base_nullify (MG_BASE (param));
393
mg_parameter_dispose (GObject *object)
395
MgParameter *parameter;
397
g_return_if_fail (object != NULL);
398
g_return_if_fail (IS_MG_PARAMETER (object));
400
parameter = MG_PARAMETER (object);
401
if (parameter->priv) {
402
mg_base_nullify_check (MG_BASE (object));
404
mg_parameter_bind_to_param (parameter, NULL);
405
mg_parameter_set_full_bind_param (parameter, NULL);
407
if (parameter->priv->in_field)
408
mg_parameter_set_source_field (parameter, NULL, NULL);
410
while (parameter->priv->for_fields)
411
mg_parameter_del_for_field (parameter, MG_QFIELD (parameter->priv->for_fields->data));
413
while (parameter->priv->dependencies)
414
mg_parameter_del_dependency (parameter, MG_PARAMETER (parameter->priv->dependencies->data));
416
mg_parameter_set_data_type (parameter, NULL);
418
if (parameter->priv->value) {
419
gda_value_free (parameter->priv->value);
420
parameter->priv->value = NULL;
423
if (parameter->priv->default_value) {
424
gda_value_free (parameter->priv->default_value);
425
parameter->priv->default_value = NULL;
430
parent_class->dispose (object);
434
mg_parameter_finalize (GObject * object)
436
MgParameter *parameter;
438
g_return_if_fail (object != NULL);
439
g_return_if_fail (IS_MG_PARAMETER (object));
441
parameter = MG_PARAMETER (object);
442
if (parameter->priv) {
443
if (parameter->priv->plugin)
444
g_free (parameter->priv->plugin);
446
g_free (parameter->priv);
447
parameter->priv = NULL;
451
parent_class->finalize (object);
456
mg_parameter_set_property (GObject *object,
462
MgParameter *parameter;
464
parameter = MG_PARAMETER (object);
465
if (parameter->priv) {
468
ptr = g_value_get_string (value);
469
if (parameter->priv->plugin) {
470
g_free (parameter->priv->plugin);
471
parameter->priv->plugin = NULL;
474
parameter->priv->plugin = g_strdup (ptr);
476
case PROP_USE_DEFAULT_VALUE:
477
parameter->priv->default_forced = g_value_get_boolean (value);
479
case PROP_SIMPLE_BIND:
480
mg_parameter_bind_to_param (parameter, g_value_get_pointer (value));
483
mg_parameter_set_full_bind_param (parameter, g_value_get_pointer (value));
490
mg_parameter_get_property (GObject *object,
495
MgParameter *parameter;
497
parameter = MG_PARAMETER (object);
498
if (parameter->priv) {
501
g_value_set_string (value, parameter->priv->plugin);
503
case PROP_USE_DEFAULT_VALUE:
504
g_value_set_boolean (value, parameter->priv->default_forced);
506
case PROP_SIMPLE_BIND:
507
g_value_set_pointer (value, parameter->priv->change_with);
510
g_value_set_pointer (value, parameter->priv->alias_of);
518
* mg_parameter_add_dest_field
519
* @param: a #MgParameter object
520
* @field: the #MgQfield object the parameter is for
522
* Adds a #MgQfield object for which the parameter is for
525
mg_parameter_add_dest_field (MgParameter *param, MgQfield *field)
527
g_return_if_fail (param && IS_MG_PARAMETER (param));
528
g_return_if_fail (param->priv);
529
g_return_if_fail (field && IS_MG_QFIELD (field));
531
mg_parameter_add_for_field (param, field);
535
* mg_parameter_get_dest_fields
536
* @param: a #MgParameter object
538
* Get the #MgQfield objects which created @param (and which will use its value)
540
* Returns: the list of #MgQfield object
543
mg_parameter_get_dest_fields (MgParameter *param)
545
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
546
g_return_val_if_fail (param->priv, NULL);
548
return param->priv->for_fields;
552
* mg_parameter_get_data_type
553
* @param: a #MgParameter object
555
* Get the requested data type for @param.
557
* Returns: the data type
560
mg_parameter_get_data_type (MgParameter *param)
562
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
563
g_return_val_if_fail (param->priv, NULL);
565
return param->priv->type;
570
* mg_parameter_get_value
571
* @param: a #MgParameter object
573
* Get the value held into the parameter
575
* Returns: the value (a NULL value returns a GDA_VALUE_TYPE_NULL GdaValue)
578
mg_parameter_get_value (MgParameter *param)
580
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
581
g_return_val_if_fail (param->priv, NULL);
583
if (!param->priv->alias_of) {
584
if (!param->priv->value)
585
param->priv->value = gda_value_new_null ();
586
return param->priv->value;
589
return mg_parameter_get_value (param->priv->alias_of);
594
* mg_parameter_set_value
595
* @param: a #MgParameter object
596
* @value: a value to set the parameter to
598
* Sets the value within the parameter. If @param is an alias for another
599
* parameter, then the value is also set for that other parameter.
601
* The action of any call to mg_parameter_declare_invalid() is cancelled
602
* as soon as this method is called, even if @param's value does not change.
604
* If the value is not different from the one already contained within @param,
605
* then @param is not chaged and no signal is emitted.
608
mg_parameter_set_value (MgParameter *param, const GdaValue *value)
610
gboolean changed = TRUE;
611
g_return_if_fail (param && IS_MG_PARAMETER (param));
612
g_return_if_fail (param->priv);
613
const GdaValue *current_val;
615
param->priv->invalid_forced = FALSE;
617
/* param will be changed? */
618
current_val = mg_parameter_get_value (param);
619
if (current_val == value)
622
if (changed && gda_value_is_null (current_val) && ((value && gda_value_is_null (value)) || !value))
625
if (changed && value && (gda_value_get_type (value) == gda_value_get_type (current_val)))
626
changed = gda_value_compare (value, current_val);
628
/* param's validity */
629
param->priv->valid = TRUE;
630
if (!value || gda_value_is_null (value))
631
if (param->priv->not_null)
632
param->priv->valid = FALSE;
635
(gda_value_get_type (value) != GDA_VALUE_TYPE_NULL) &&
636
(gda_value_get_type (value) != mg_server_data_type_get_gda_type (param->priv->type)))
637
param->priv->valid = FALSE;
640
g_print ("Changed param %p (%s): value %s --> %s \t(type %d -> %d) VALID: %d CHANGED: %d\n", param, mg_base_get_name (param),
641
current_val ? gda_value_stringify (current_val) : "_NULL_",
642
value ? gda_value_stringify (value) : "_NULL_",
643
current_val ? gda_value_get_type (current_val) : 0,
644
value ? gda_value_get_type (value) : 0, param->priv->valid, changed);
647
/* end of procedure if the value has not been changed, after calculating the param's validity */
649
if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (param), "changed_pending"))) {
650
gboolean changed_blocked;
651
g_object_get (G_OBJECT (param), "changed_blocked", &changed_blocked, NULL);
652
if (!changed_blocked) {
653
g_object_set_data (G_OBJECT (param), "changed_pending", NULL);
654
mg_base_changed (MG_BASE (param));
660
/* the parameter does not have the default value forced since it has changed */
661
param->priv->default_forced = FALSE;
663
/* real setting of the value */
664
if (param->priv->alias_of) {
666
g_print ("Param %p is alias of param %p => propagating changes to param %p\n",
667
param, param->priv->alias_of, param->priv->alias_of);
669
mg_parameter_set_value (param->priv->alias_of, value);
672
gboolean changed_blocked;
673
if (param->priv->value) {
674
gda_value_free (param->priv->value);
675
param->priv->value = NULL;
679
param->priv->value = gda_value_copy (value);
681
/* if the MgBase has "changed_blocked" property TRUE, then store that the next time we need
682
* to emit the "changed" signal even if the stored value has not changed "
684
g_object_get (G_OBJECT (param), "changed_blocked", &changed_blocked, NULL);
686
g_object_set_data (G_OBJECT (param), "changed_pending", GINT_TO_POINTER (TRUE));
688
mg_base_changed (MG_BASE (param));
694
* mg_parameter_declare_invalid
695
* @param: a #MgParameter object
697
* Forces a parameter to be invalid; to set it valid again, a new value must be assigned
698
* to it using mg_parameter_set_value().
701
mg_parameter_declare_invalid (MgParameter *param)
703
g_return_if_fail (param && IS_MG_PARAMETER (param));
704
g_return_if_fail (param->priv);
707
g_print ("Param %p (%s): declare invalid\n", param, mg_base_get_name (param));
710
if (param->priv->invalid_forced)
713
param->priv->invalid_forced = TRUE;
714
param->priv->valid = FALSE;
716
if (param->priv->value) {
717
gda_value_free (param->priv->value);
718
param->priv->value = NULL;
721
/* if we are an alias, then we forward the value setting to the master */
722
if (param->priv->alias_of)
723
mg_parameter_declare_invalid (param->priv->alias_of);
725
mg_base_changed (MG_BASE (param));
730
* mg_parameter_is_valid
731
* @param: a #MgParameter object
733
* Get the validity of @param (that is, of the value held by @param)
735
* Returns: TRUE if @param's value can safely be used
738
mg_parameter_is_valid (MgParameter *param)
740
g_return_val_if_fail (param && IS_MG_PARAMETER (param), FALSE);
741
g_return_val_if_fail (param->priv, FALSE);
743
if (param->priv->alias_of)
744
return mg_parameter_is_valid (param->priv->alias_of);
746
if (param->priv->invalid_forced)
749
if (param->priv->default_forced)
750
return param->priv->default_value ? TRUE : FALSE;
752
return param->priv->valid;
758
* mg_parameter_get_default_value
759
* @param: a #MgParameter object
761
* Get the default value held into the parameter. WARNING: the default value does not need to be of
762
* the same type as the one required by @param.
764
* Returns: the default value
767
mg_parameter_get_default_value (MgParameter *param)
769
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
770
g_return_val_if_fail (param->priv, NULL);
772
return param->priv->default_value;
777
* mg_parameter_set_default_value
778
* @param: a #MgParameter object
779
* @value: a value to set the parameter's default value to
781
* Sets the default value within the parameter. WARNING: the default value does not need to be of
782
* the same type as the one required by @param.
785
mg_parameter_set_default_value (MgParameter *param, const GdaValue *value)
787
g_return_if_fail (param && IS_MG_PARAMETER (param));
788
g_return_if_fail (param->priv);
790
if (param->priv->default_value) {
791
gda_value_free (param->priv->default_value);
792
param->priv->default_value = NULL;
796
param->priv->default_value = gda_value_copy (value);
798
mg_base_changed (MG_BASE (param));
802
* mg_parameter_set_not_null
803
* @param: a #MgParameter object
806
* Sets if the parameter can have a NULL value. If @not_null is TRUE, then that won't be allowed
809
mg_parameter_set_not_null (MgParameter *param, gboolean not_null)
811
g_return_if_fail (param && IS_MG_PARAMETER (param));
812
g_return_if_fail (param->priv);
814
if (not_null != param->priv->not_null) {
815
param->priv->not_null = not_null;
817
/* updating the parameter's validity regarding the NULL value */
819
(!param->priv->value || gda_value_is_null (param->priv->value)))
820
param->priv->valid = TRUE;
823
(!param->priv->value || gda_value_is_null (param->priv->value)))
824
param->priv->valid = FALSE;
826
mg_base_changed (MG_BASE (param));
831
* mg_parameter_get_not_null
832
* @param: a #MgParameter object
834
* Get wether the parameter can be NULL or not
836
* Returns: TRUE if the parameter cannot be NULL
839
mg_parameter_get_not_null (MgParameter *param)
841
g_return_val_if_fail (param && IS_MG_PARAMETER (param), FALSE);
842
g_return_val_if_fail (param->priv, FALSE);
844
return param->priv->not_null;
848
* mg_parameter_set_source_field
849
* @param: a #MgParameter object
850
* @field: a #MgQfield object or NULL
851
* @error: location to store error, or %NULL
853
* Sets a limit on the possible values for the @param parameter: they must be among the values of @field when the SELECT
854
* query to which @field belongs is executed. @field must be of the same type
855
* as the requested type for @param.
857
* @field is not copied, just referenced (maybe it'd better to make a copy of it...)
859
* Returns: TRUE if no error occurred
862
mg_parameter_set_source_field (MgParameter *param, MgQfield *field, GError **error)
864
g_return_val_if_fail (param && IS_MG_PARAMETER (param), FALSE);
865
g_return_val_if_fail (param->priv, FALSE);
867
if (param->priv->in_field) {
868
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->in_field),
869
G_CALLBACK (nullified_source_field_cb), param);
870
g_object_unref (G_OBJECT (param->priv->in_field));
871
param->priv->in_field = NULL;
878
g_return_val_if_fail (IS_MG_QFIELD (field), FALSE);
879
ent = mg_field_get_entity (MG_FIELD (field));
880
if (! IS_MG_QUERY (ent)) {
883
MG_PARAMETER_QUERY_LIMIT_ERROR,
884
_("A parameter can only get its value within a query"));
887
query = MG_QUERY (ent);
889
/* test to see if @query is well formed for the job */
890
if (!mg_query_is_select_query (query)) {
893
MG_PARAMETER_QUERY_LIMIT_ERROR,
894
_("Parameter: query to limit range is not a selection query"));
898
param->priv->in_field = field;
899
g_signal_connect (G_OBJECT (field), "nullified",
900
G_CALLBACK (nullified_source_field_cb), param);
901
g_object_ref (G_OBJECT (param->priv->in_field));
907
nullified_source_field_cb (MgBase *obj, MgParameter *param)
909
mg_parameter_set_source_field (param, NULL, NULL);
913
* mg_parameter_get_limit_query
914
* @param: a #MgParameter object
916
* Get the query field which limits the possible value for the parameter.
918
* Returns: the #MgQfield, or %NULL
921
mg_parameter_get_source_field (MgParameter *param)
923
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
924
g_return_val_if_fail (param->priv, NULL);
926
return param->priv->in_field;
930
* mg_parameter_add_dependency
931
* @param: a #MgParameter object
932
* @depend_on: a #MgParameter object
934
* Tell @param that its value will depend on the value of @depend_on
937
mg_parameter_add_dependency (MgParameter *param, MgParameter *depend_on)
939
g_return_if_fail (param && IS_MG_PARAMETER (param));
940
g_return_if_fail (param->priv);
941
g_return_if_fail (depend_on && IS_MG_PARAMETER (depend_on));
942
g_return_if_fail (depend_on->priv);
943
g_return_if_fail (!g_slist_find (depend_on->priv->dependencies, param));
945
if (!g_slist_find (param->priv->dependencies, depend_on) && (depend_on != param)) {
946
param->priv->dependencies = g_slist_append (param->priv->dependencies, depend_on);
947
g_signal_connect (G_OBJECT (depend_on), "nullified",
948
G_CALLBACK (nullified_depend_on_cb), param);
949
g_object_ref (G_OBJECT (depend_on));
954
* mg_parameter_del_dependency
955
* @param: a #MgParameter object
956
* @depend_on: a #MgParameter object
958
* Remove the @depend_on dependency from @param
961
mg_parameter_del_dependency (MgParameter *param, MgParameter *depend_on)
963
g_return_if_fail (param && IS_MG_PARAMETER (param));
964
g_return_if_fail (param->priv);
965
g_return_if_fail (depend_on && IS_MG_PARAMETER (depend_on));
966
g_return_if_fail (depend_on->priv);
968
if (g_slist_find (param->priv->dependencies, depend_on)) {
969
g_signal_handlers_disconnect_by_func (G_OBJECT (depend_on),
970
G_CALLBACK (nullified_depend_on_cb), param);
971
g_object_unref (G_OBJECT (depend_on));
972
param->priv->dependencies = g_slist_remove (param->priv->dependencies, depend_on);
977
nullified_depend_on_cb (MgBase *obj, MgParameter *param)
979
mg_parameter_del_dependency (param, MG_PARAMETER (obj));
983
* mg_parameter_get_dependencies
984
* @param: a #MgParameter object
986
* Get the list of #MgParameter @param depends on
988
* Returns: the list of parameters
991
mg_parameter_get_dependencies (MgParameter *param)
993
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
994
g_return_val_if_fail (param->priv, NULL);
996
return param->priv->dependencies;
1000
* mg_parameter_replace_ref
1001
* @param: a #MgParameter object
1002
* @replacements: the (objects to be replaced, replacing object) pairs
1004
* Replace references to some objects by references to some other objects,
1005
* as listed in @replacements.
1008
mg_parameter_replace_ref (MgParameter *param, GHashTable *replacements)
1013
g_return_if_fail (param && IS_MG_PARAMETER (param));
1014
g_return_if_fail (param->priv);
1016
/* Destination fields */
1017
list = param->priv->for_fields;
1019
ref = g_hash_table_lookup (replacements, list->data);
1020
if (ref) /* we don't actually replace the ref, but simply add one destination field */
1021
mg_parameter_add_dest_field (param, ref);
1023
list = g_slist_next (list);
1027
list = param->priv->dependencies;
1029
ref = g_hash_table_lookup (replacements, list->data);
1031
g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1032
G_CALLBACK (nullified_depend_on_cb), param);
1033
g_object_unref (G_OBJECT (list->data));
1035
g_signal_connect (G_OBJECT (ref), "nullified",
1036
G_CALLBACK (nullified_depend_on_cb), param);
1037
g_object_ref (G_OBJECT (ref));
1039
list = g_slist_next (list);
1043
if (param->priv->in_field) {
1044
ref = g_hash_table_lookup (replacements, param->priv->in_field);
1046
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->in_field),
1047
G_CALLBACK (nullified_source_field_cb), param);
1048
g_object_unref (G_OBJECT (param->priv->in_field));
1049
param->priv->in_field = MG_QFIELD (ref);
1050
g_signal_connect (G_OBJECT (param->priv->in_field), "nullified",
1051
G_CALLBACK (nullified_source_field_cb), param);
1052
g_object_ref (G_OBJECT (param->priv->in_field));
1058
* mg_parameter_bind_to_param
1059
* @param: a #MgParameter
1060
* @bind_to: a #MgParameter or %NULL
1062
* Sets @param to change when @bind_to changes (and does not make @bind_to change when @param changes)
1065
mg_parameter_bind_to_param (MgParameter *param, MgParameter *bind_to)
1067
const GdaValue *cvalue;
1068
GdaValue *value1 = NULL, *value2 = NULL;
1070
g_return_if_fail (param && IS_MG_PARAMETER (param));
1071
g_return_if_fail (param->priv);
1073
if (param->priv->change_with == bind_to)
1076
/* get a copy of the current values of @param and @bind_to */
1078
g_return_if_fail (bind_to && IS_MG_PARAMETER (bind_to));
1079
g_return_if_fail (bind_to->priv);
1080
g_return_if_fail (param->priv->type == bind_to->priv->type);
1081
cvalue = mg_parameter_get_value (bind_to);
1082
if (cvalue && !gda_value_is_null (cvalue))
1083
value2 = gda_value_copy (cvalue);
1086
cvalue = mg_parameter_get_value (param);
1087
if (cvalue && !gda_value_is_null (cvalue))
1088
value1 = gda_value_copy (cvalue);
1090
/* get rid of the old alias */
1091
if (param->priv->change_with) {
1092
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->change_with),
1093
G_CALLBACK (nullified_alias_of_cb), param);
1094
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->change_with),
1095
G_CALLBACK (alias_of_changed_cb), param);
1096
param->priv->change_with = NULL;
1099
/* setting the new alias or reseting the value if there is no new alias */
1101
gboolean equal = FALSE;
1103
param->priv->change_with = bind_to;
1104
g_signal_connect (G_OBJECT (param->priv->change_with), "nullified",
1105
G_CALLBACK (nullified_alias_of_cb), param);
1106
g_signal_connect (G_OBJECT (param->priv->change_with), "changed",
1107
G_CALLBACK (alias_of_changed_cb), param);
1109
/* if alias_of has a different value than param, then we set param to the new value */
1110
if (value1 && value2 &&
1111
(gda_value_get_type (value1) == gda_value_get_type (value2)))
1112
equal = !gda_value_compare (value1, value2);
1114
if (!value1 && !value2)
1118
mg_parameter_set_value (param, value2);
1121
if (value1) gda_value_free (value1);
1122
if (value2) gda_value_free (value2);
1126
* mg_parameter_set_full_bind_param
1127
* @param: a #MgParameter
1128
* @alias_of: a #MgParameter or %NULL
1130
* Sets @param to change when @alias_of changes and makes @alias_of change when @param changes.
1131
* The difference with mg_parameter_bind_to_param is that when @param changes, then @alias_of also
1135
mg_parameter_set_full_bind_param (MgParameter *param, MgParameter *alias_of)
1137
const GdaValue *cvalue;
1138
GdaValue *value1 = NULL, *value2 = NULL;
1140
g_return_if_fail (param && IS_MG_PARAMETER (param));
1141
g_return_if_fail (param->priv);
1143
if (param->priv->alias_of == alias_of)
1146
/* get a copy of the current values of @param and @alias_of */
1148
g_return_if_fail (alias_of && IS_MG_PARAMETER (alias_of));
1149
g_return_if_fail (alias_of->priv);
1150
g_return_if_fail (param->priv->type == alias_of->priv->type);
1151
cvalue = mg_parameter_get_value (alias_of);
1152
if (cvalue && !gda_value_is_null (cvalue))
1153
value2 = gda_value_copy (cvalue);
1156
cvalue = mg_parameter_get_value (param);
1157
if (cvalue && !gda_value_is_null (cvalue))
1158
value1 = gda_value_copy (cvalue);
1161
/* get rid of the old alias */
1162
if (param->priv->alias_of) {
1163
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->alias_of),
1164
G_CALLBACK (nullified_alias_of_cb), param);
1165
g_signal_handlers_disconnect_by_func (G_OBJECT (param->priv->alias_of),
1166
G_CALLBACK (alias_of_changed_cb), param);
1167
param->priv->alias_of = NULL;
1170
/* setting the new alias or reseting the value if there is no new alias */
1172
gboolean equal = FALSE;
1174
/* get rid of the internal param's value */
1175
if (param->priv->value) {
1176
gda_value_free (param->priv->value);
1177
param->priv->value = NULL;
1180
param->priv->alias_of = alias_of;
1181
g_signal_connect (G_OBJECT (param->priv->alias_of), "nullified",
1182
G_CALLBACK (nullified_alias_of_cb), param);
1183
g_signal_connect (G_OBJECT (param->priv->alias_of), "changed",
1184
G_CALLBACK (alias_of_changed_cb), param);
1186
/* if alias_of has a different value than param, then we emit a CHANGED signal */
1187
if (value1 && value2 &&
1188
(gda_value_get_type (value1) == gda_value_get_type (value2)))
1189
equal = !gda_value_compare (value1, value2);
1191
if (!value1 && !value2)
1196
mg_base_changed (MG_BASE (param));
1199
/* restore the value that was in the previous alias parameter,
1200
* if there was such a value, and don't emit a signal */
1201
g_assert (! param->priv->value);
1203
param->priv->value = value1;
1207
if (value1) gda_value_free (value1);
1208
if (value2) gda_value_free (value2);
1212
nullified_alias_of_cb (MgBase *obj, MgParameter *param)
1214
if ((gpointer) obj == (gpointer) param->priv->alias_of)
1215
mg_parameter_set_full_bind_param (param, NULL);
1217
mg_parameter_bind_to_param (param, NULL);
1221
alias_of_changed_cb (MgParameter *alias_of, MgParameter *param)
1223
if ((gpointer) alias_of == (gpointer) param->priv->alias_of) {
1224
/* callback used as full bind */
1225
mg_base_changed (MG_BASE (param));
1228
/* callback used as simple bind */
1229
mg_parameter_set_value (param, mg_parameter_get_value (alias_of));
1234
mg_parameter_signal_changed (MgBase *base, gboolean block_changed_signal)
1236
MgParameter *param = MG_PARAMETER (base);
1238
if (param->priv->alias_of) {
1239
if (block_changed_signal)
1240
mg_base_block_changed (MG_BASE (param->priv->alias_of));
1242
mg_base_unblock_changed (MG_BASE (param->priv->alias_of));
1247
* mg_parameter_get_bind_param
1248
* @param: a #MgParameter
1250
* Get the parameter which makes @param change its value when the param's value is changed.
1252
* Returns: the #MgParameter or %NULL
1255
mg_parameter_get_bind_param (MgParameter *param)
1257
g_return_val_if_fail (param && IS_MG_PARAMETER (param), NULL);
1258
g_return_val_if_fail (param->priv, NULL);
1260
return param->priv->change_with;
1265
* mg_parameter_requires_user_input
1266
* @param: a #MgParameter
1268
* Tells if the parameter is configured in a way that even if there is a value, it requires
1269
* that the user at least validates that value, or change it.
1271
* Returns: TRUE if user input is required
1274
mg_parameter_requires_user_input (MgParameter *param)
1276
g_return_val_if_fail (param && IS_MG_PARAMETER (param), FALSE);
1277
g_return_val_if_fail (param->priv, FALSE);
1279
return param->priv->user_input_required;
1283
* mg_parameter_set_user_input_required
1284
* @param: a #MgParameter
1287
* Sets if the user input is required for @param (even though it may already have
1288
* a value) and be valid.
1291
mg_parameter_set_user_input_required (MgParameter *param, gboolean input_required)
1293
g_return_if_fail (param && IS_MG_PARAMETER (param));
1294
g_return_if_fail (param->priv);
1296
param->priv->user_input_required = input_required;
1302
mg_parameter_dump (MgParameter *parameter, guint offset)
1307
g_return_if_fail (parameter);
1308
g_return_if_fail (IS_MG_PARAMETER (parameter));
1310
/* string for the offset */
1311
str = g_new0 (gchar, offset+1);
1312
for (i=0; i<offset; i++)
1317
if (parameter->priv) {
1319
g_print ("%s" D_COL_H1 "MgParameter %p (%s), type=%s\n" D_COL_NOR, str, parameter,
1320
mg_base_get_name (MG_BASE (parameter)), mg_base_get_name (MG_BASE (parameter->priv->type)));
1322
list = parameter->priv->for_fields;
1324
gchar *xmlid = mg_xml_storage_get_xml_id (MG_XML_STORAGE (list->data));
1325
if (list == parameter->priv->for_fields)
1326
g_print ("%sFor fields: ", str);
1329
g_print ("%p (%s)", list->data, xmlid);
1332
list = g_slist_next (list);
1334
if (parameter->priv->for_fields)
1337
if (parameter->priv->in_field) {
1338
gchar *xmlid = mg_xml_storage_get_xml_id (MG_XML_STORAGE (parameter->priv->in_field));
1339
g_print ("%sDepends on query field %p (%s)\n", str, parameter->priv->in_field, xmlid);
1343
if (parameter->priv->alias_of) {
1344
g_print ("%sAlias of parameter %p (%s)\n", str, parameter->priv->alias_of,
1345
mg_base_get_name (MG_BASE (parameter->priv->alias_of)));
1346
mg_parameter_dump (parameter->priv->alias_of, offset + 5);
1349
list = parameter->priv->dependencies;
1351
if (list == parameter->priv->dependencies)
1352
g_print ("%sParam dependencies:", str);
1355
g_print ("%p", list->data);
1356
list = g_slist_next (list);
1358
if (parameter->priv->dependencies)
1361
list = parameter->priv->dependencies;
1363
mg_parameter_dump (MG_PARAMETER (list->data), offset + 5);
1364
list = g_slist_next (list);
1368
g_print ("%s" D_COL_ERR "Using finalized object %p" D_COL_NOR, str, parameter);
1376
* MgReferer interface implementation
1380
mg_parameter_get_ref_objects (MgReferer *iface)
1382
GSList *list = NULL;
1384
g_return_val_if_fail (iface && IS_MG_PARAMETER (iface), NULL);
1385
g_return_val_if_fail (MG_PARAMETER (iface)->priv, NULL);
1393
mg_parameter_replace_refs (MgReferer *iface, GHashTable *replacements)
1395
MgParameter *parameter;
1399
g_return_if_fail (iface && IS_MG_PARAMETER (iface));
1400
g_return_if_fail (MG_PARAMETER (iface)->priv);
1402
parameter = MG_PARAMETER (iface);
1404
repl = g_hash_table_lookup (replacements, parameter->priv->type);
1406
mg_parameter_set_data_type (parameter, MG_SERVER_DATA_TYPE (repl));
1408
list = parameter->priv->for_fields;
1410
repl = g_hash_table_lookup (replacements, list->data);
1412
mg_parameter_del_for_field (parameter, MG_QFIELD (list->data));
1413
mg_parameter_add_for_field (parameter, MG_QFIELD (repl));
1415
list = g_slist_next (list);
1418
if (parameter->priv->alias_of) {
1419
repl = g_hash_table_lookup (replacements, parameter->priv->alias_of);
1421
mg_parameter_set_full_bind_param (parameter, repl);
1424
if (parameter->priv->change_with) {
1425
repl = g_hash_table_lookup (replacements, parameter->priv->change_with);
1427
mg_parameter_bind_to_param (parameter, MG_PARAMETER (repl));
1430
if (parameter->priv->in_field) {
1431
repl = g_hash_table_lookup (replacements, parameter->priv->in_field);
1433
mg_parameter_set_source_field (parameter, MG_QFIELD (repl), NULL);
1436
list = parameter->priv->dependencies;
1438
repl = g_hash_table_lookup (replacements, list->data);
1440
mg_parameter_del_dependency (parameter, MG_PARAMETER (list->data));
1441
mg_parameter_add_dependency (parameter, MG_PARAMETER (repl));
1443
list = g_slist_next (list);