1 /*
2 * Copyright (C) 2009 - 2012 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2010 David King <davidk@openismus.com>
4 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.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 "gdaui-entry-wrapper.h"
23 #include <libgda/gda-data-handler.h>
24 #include <libgda/gda-enums.h>
25
26 static void gdaui_entry_wrapper_class_init (GdauiEntryWrapperClass *klass);
27 static void gdaui_entry_wrapper_init (GdauiEntryWrapper *wid);
28 static void gdaui_entry_wrapper_dispose (GObject *object);
29
30 static void gdaui_entry_wrapper_set_property (GObject *object,
31 guint param_id,
32 const GValue *value,
33 GParamSpec *pspec);
34 static void gdaui_entry_wrapper_get_property (GObject *object,
35 guint param_id,
36 GValue *value,
37 GParamSpec *pspec);
38
39 static void contents_changed_cb (GtkWidget *entry, GdauiEntryWrapper *wrapper);
40 static void contents_activated_cb (GtkWidget *entry, GdauiEntryWrapper *wrapper);
41 static void check_correct_init (GdauiEntryWrapper *wid);
42 static void block_signals (GdauiEntryWrapper *wid);
43 static void unblock_signals (GdauiEntryWrapper *wid);
44
45 /* GdauiDataEntry interface */
46 static void gdaui_entry_wrapper_data_entry_init (GdauiDataEntryIface *iface);
47 static void gdaui_entry_wrapper_set_value_type (GdauiDataEntry *de, GType type);
48 static GType gdaui_entry_wrapper_get_value_type (GdauiDataEntry *de);
49 static void gdaui_entry_wrapper_set_value (GdauiDataEntry *de, const GValue *value);
50 static GValue *gdaui_entry_wrapper_get_value (GdauiDataEntry *de);
51 static void gdaui_entry_wrapper_set_ref_value (GdauiDataEntry *de, const GValue *value);
52 static const GValue *gdaui_entry_wrapper_get_ref_value (GdauiDataEntry *de);
53 static void gdaui_entry_wrapper_set_value_default (GdauiDataEntry *de, const GValue *value);
54 static void gdaui_entry_wrapper_set_attributes (GdauiDataEntry *de, GdaValueAttribute attrs, guint mask);
55 static GdaValueAttribute gdaui_entry_wrapper_get_attributes (GdauiDataEntry *de);
56 static GdaDataHandler *gdaui_entry_wrapper_get_handler (GdauiDataEntry *de);
57 static void gdaui_entry_wrapper_set_editable (GdauiDataEntry *de, gboolean editable);
58 static gboolean gdaui_entry_wrapper_get_editable (GdauiDataEntry *de);
59 static void gdaui_entry_wrapper_grab_focus (GdauiDataEntry *de);
60 static void gdaui_entry_wrapper_set_unknown_color (GdauiDataEntry *de, gdouble red, gdouble green,
61 gdouble blue, gdouble alpha);
62
63 /* properties */
64 enum {
65 PROP_0,
66 PROP_SET_DEFAULT_IF_INVALID
67 };
68
69 struct _GdauiEntryWrapperPriv {
70 gboolean impl_is_correct;
71 GtkWidget *entry;
72 GdauiEntryWrapperClass *real_class;
73 guint signals_blocked;
74
75 GType type;
76 GValue *value_ref;
77 GValue *value_default; /* Can be of any type, not just @type */
78
79 gboolean null_forced;
80 gboolean default_forced;
81
82 gboolean null_possible;
83 gboolean default_possible;
84 gboolean show_actions;
85 gboolean editable;
86 gboolean contents_has_changed; /* since this variable was reset */
87
88 /* property */
89 gboolean set_default_if_invalid;
90 };
91
92 /* get a pointer to the parents to be able to call their destructor */
93 static GObjectClass *parent_class = NULL;
94
95 GType
gdaui_entry_wrapper_get_type(void)96 gdaui_entry_wrapper_get_type (void)
97 {
98 static GType type = 0;
99
100 if (G_UNLIKELY (type == 0)) {
101 static const GTypeInfo info = {
102 sizeof (GdauiEntryWrapperClass),
103 (GBaseInitFunc) NULL,
104 (GBaseFinalizeFunc) NULL,
105 (GClassInitFunc) gdaui_entry_wrapper_class_init,
106 NULL,
107 NULL,
108 sizeof (GdauiEntryWrapper),
109 0,
110 (GInstanceInitFunc) gdaui_entry_wrapper_init,
111 0
112 };
113
114 static const GInterfaceInfo data_entry_info = {
115 (GInterfaceInitFunc) gdaui_entry_wrapper_data_entry_init,
116 NULL,
117 NULL
118 };
119
120 type = g_type_register_static (GDAUI_TYPE_ENTRY_SHELL, "GdauiEntryWrapper", &info, 0);
121 g_type_add_interface_static (type, GDAUI_TYPE_DATA_ENTRY, &data_entry_info);
122 }
123 return type;
124 }
125
126 static void
gdaui_entry_wrapper_data_entry_init(GdauiDataEntryIface * iface)127 gdaui_entry_wrapper_data_entry_init (GdauiDataEntryIface *iface)
128 {
129 iface->set_value_type = gdaui_entry_wrapper_set_value_type;
130 iface->get_value_type = gdaui_entry_wrapper_get_value_type;
131 iface->set_value = gdaui_entry_wrapper_set_value;
132 iface->get_value = gdaui_entry_wrapper_get_value;
133 iface->set_ref_value = gdaui_entry_wrapper_set_ref_value;
134 iface->get_ref_value = gdaui_entry_wrapper_get_ref_value;
135 iface->set_value_default = gdaui_entry_wrapper_set_value_default;
136 iface->set_attributes = gdaui_entry_wrapper_set_attributes;
137 iface->get_attributes = gdaui_entry_wrapper_get_attributes;
138 iface->get_handler = gdaui_entry_wrapper_get_handler;
139 iface->set_editable = gdaui_entry_wrapper_set_editable;
140 iface->get_editable = gdaui_entry_wrapper_get_editable;
141 iface->grab_focus = gdaui_entry_wrapper_grab_focus;
142 iface->set_unknown_color = gdaui_entry_wrapper_set_unknown_color;
143 }
144
145
146 static void
gdaui_entry_wrapper_class_init(GdauiEntryWrapperClass * klass)147 gdaui_entry_wrapper_class_init (GdauiEntryWrapperClass *klass)
148 {
149 GObjectClass *object_class = G_OBJECT_CLASS (klass);
150
151 parent_class = g_type_class_peek_parent (klass);
152
153 /* virtual functions */
154 klass->create_entry = NULL;
155 klass->real_set_value = NULL;
156 klass->real_get_value = NULL;
157
158 /* Properties */
159 object_class->set_property = gdaui_entry_wrapper_set_property;
160 object_class->get_property = gdaui_entry_wrapper_get_property;
161 g_object_class_install_property (object_class, PROP_SET_DEFAULT_IF_INVALID,
162 g_param_spec_boolean ("set-default-if-invalid", NULL, NULL, FALSE,
163 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
164
165 object_class->dispose = gdaui_entry_wrapper_dispose;
166 }
167
168 static void
check_correct_init(GdauiEntryWrapper * wrapper)169 check_correct_init (GdauiEntryWrapper *wrapper)
170 {
171 if (!wrapper->priv->impl_is_correct) {
172 GtkWidget *entry = NULL;
173 GdauiEntryWrapperClass *klass;
174 gboolean class_impl_error = FALSE;;
175
176 klass = GDAUI_ENTRY_WRAPPER_CLASS (G_OBJECT_GET_CLASS (wrapper));
177 if (! klass->create_entry) {
178 g_warning ("create_entry () virtual function not implemented for object class %s\n",
179 G_OBJECT_TYPE_NAME (wrapper));
180 class_impl_error = TRUE;
181 }
182 if (! klass->real_set_value) {
183 g_warning ("real_set_value () virtual function not implemented for object class %s\n",
184 G_OBJECT_TYPE_NAME (wrapper));
185 class_impl_error = TRUE;
186 }
187 if (! klass->real_get_value) {
188 g_warning ("real_get_value () virtual function not implemented for object class %s\n",
189 G_OBJECT_TYPE_NAME (wrapper));
190 class_impl_error = TRUE;
191 }
192 if (! klass->connect_signals) {
193 g_warning ("connect_signals () virtual function not implemented for object class %s\n",
194 G_OBJECT_TYPE_NAME (wrapper));
195 class_impl_error = TRUE;
196 }
197
198 if (!class_impl_error) {
199 wrapper->priv->real_class = klass;
200 wrapper->priv->impl_is_correct = TRUE;
201 entry = (*wrapper->priv->real_class->create_entry) (wrapper);
202
203 gdaui_entry_shell_pack_entry (GDAUI_ENTRY_SHELL (wrapper), entry);
204 gtk_widget_show (entry);
205 wrapper->priv->entry = entry;
206
207 (*wrapper->priv->real_class->connect_signals) (wrapper, G_CALLBACK (contents_changed_cb),
208 G_CALLBACK (contents_activated_cb));
209 }
210 else {
211 /* we need to exit because the program WILL BE unstable and WILL crash */
212 g_assert_not_reached ();
213 }
214 }
215 }
216
217 static void
block_signals(GdauiEntryWrapper * wrapper)218 block_signals (GdauiEntryWrapper *wrapper)
219 {
220 wrapper->priv->signals_blocked ++;
221 }
222
223 static void
unblock_signals(GdauiEntryWrapper * wrapper)224 unblock_signals (GdauiEntryWrapper *wrapper)
225 {
226 wrapper->priv->signals_blocked --;
227 }
228
229
230 static void
gdaui_entry_wrapper_init(GdauiEntryWrapper * wrapper)231 gdaui_entry_wrapper_init (GdauiEntryWrapper *wrapper)
232 {
233 /* Private structure */
234 wrapper->priv = g_new0 (GdauiEntryWrapperPriv, 1);
235 wrapper->priv->impl_is_correct = FALSE;
236 wrapper->priv->entry = NULL;
237 wrapper->priv->real_class = NULL;
238 wrapper->priv->signals_blocked = 0;
239
240 wrapper->priv->type = GDA_TYPE_NULL;
241 wrapper->priv->value_ref = NULL;
242 wrapper->priv->value_default = NULL;
243
244 wrapper->priv->null_forced = FALSE;
245 wrapper->priv->default_forced = FALSE;
246
247 wrapper->priv->null_possible = TRUE;
248 wrapper->priv->default_possible = FALSE;
249 wrapper->priv->show_actions = TRUE;
250 wrapper->priv->editable = TRUE;
251 wrapper->priv->contents_has_changed = FALSE;
252
253 wrapper->priv->set_default_if_invalid = FALSE;
254
255 gtk_widget_set_hexpand (GTK_WIDGET (wrapper), TRUE);
256 }
257
258 static void
gdaui_entry_wrapper_dispose(GObject * object)259 gdaui_entry_wrapper_dispose (GObject *object)
260 {
261 GdauiEntryWrapper *wrapper;
262
263 g_return_if_fail (object != NULL);
264 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (object));
265
266 wrapper = GDAUI_ENTRY_WRAPPER (object);
267
268 if (wrapper->priv) {
269 if (wrapper->priv->value_ref)
270 gda_value_free (wrapper->priv->value_ref);
271 if (wrapper->priv->value_default)
272 gda_value_free (wrapper->priv->value_default);
273
274 g_free (wrapper->priv);
275 wrapper->priv = NULL;
276 }
277
278 /* for the parent class */
279 parent_class->dispose (object);
280 }
281
282
283 static void
gdaui_entry_wrapper_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)284 gdaui_entry_wrapper_set_property (GObject *object,
285 guint param_id,
286 const GValue *value,
287 GParamSpec *pspec)
288 {
289 GdauiEntryWrapper *wrapper = GDAUI_ENTRY_WRAPPER (object);
290 if (wrapper->priv) {
291 switch (param_id) {
292 case PROP_SET_DEFAULT_IF_INVALID: {
293 guint attrs;
294
295 wrapper->priv->set_default_if_invalid = g_value_get_boolean (value);
296 attrs = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (wrapper));
297
298 if (wrapper->priv->set_default_if_invalid && (attrs & GDA_VALUE_ATTR_DATA_NON_VALID)) {
299 GValue *sane_value;
300 GdaDataHandler *dh;
301 GType type;
302
303 check_correct_init (wrapper);
304 dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (wrapper));
305 type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (wrapper));
306 sane_value = gda_data_handler_get_sane_init_value (dh, type);
307 (*wrapper->priv->real_class->real_set_value) (wrapper, sane_value);
308 if (sane_value)
309 gda_value_free (sane_value);
310 }
311 break;
312 default:
313 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
314 break;
315 }
316 }
317 }
318 }
319
320 static void
gdaui_entry_wrapper_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)321 gdaui_entry_wrapper_get_property (GObject *object,
322 guint param_id,
323 GValue *value,
324 GParamSpec *pspec)
325 {
326 GdauiEntryWrapper *wrapper = GDAUI_ENTRY_WRAPPER (object);
327 if (wrapper->priv) {
328 switch (param_id) {
329 case PROP_SET_DEFAULT_IF_INVALID:
330 g_value_set_boolean (value, wrapper->priv->set_default_if_invalid);
331 break;
332 default:
333 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
334 break;
335 }
336 }
337 }
338
339 /**
340 * gdaui_entry_wrapper_contents_changed:
341 * @wrapper: a #GdauiEntryWrapper widget
342 *
343 * Signals to @gwrap that the entry has changed
344 */
345 void
gdaui_entry_wrapper_contents_changed(GdauiEntryWrapper * wrapper)346 gdaui_entry_wrapper_contents_changed (GdauiEntryWrapper *wrapper)
347 {
348 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (wrapper));
349
350 contents_changed_cb (NULL, wrapper);
351 }
352
353 /**
354 * gdaui_entry_wrapper_contents_activated:
355 * @wrapper: a #GdauiEntryWrapper widget
356 *
357 * Signals to @gwrap that the entry has been activated (that is the user
358 * pressed ENTER for example to signify he has finished entering data)
359 */
360 void
gdaui_entry_wrapper_contents_activated(GdauiEntryWrapper * wrapper)361 gdaui_entry_wrapper_contents_activated (GdauiEntryWrapper *wrapper)
362 {
363 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (wrapper));
364
365 contents_activated_cb (NULL, wrapper);
366 }
367
368
369 static void gdaui_entry_wrapper_emit_signal (GdauiEntryWrapper *wrapper);
370 static void
contents_changed_cb(G_GNUC_UNUSED GtkWidget * entry,GdauiEntryWrapper * wrapper)371 contents_changed_cb (G_GNUC_UNUSED GtkWidget *entry, GdauiEntryWrapper *wrapper)
372 {
373 /* @entry is not used */
374 if (! wrapper->priv->signals_blocked) {
375 wrapper->priv->null_forced = FALSE;
376 wrapper->priv->default_forced = FALSE;
377 wrapper->priv->contents_has_changed = TRUE;
378 gdaui_entry_wrapper_emit_signal (wrapper);
379 }
380 }
381
382 static void
contents_activated_cb(G_GNUC_UNUSED GtkWidget * entry,GdauiEntryWrapper * wrapper)383 contents_activated_cb (G_GNUC_UNUSED GtkWidget *entry, GdauiEntryWrapper *wrapper)
384 {
385 /* @entry is not used */
386 if (! wrapper->priv->signals_blocked) {
387 wrapper->priv->null_forced = FALSE;
388 wrapper->priv->default_forced = FALSE;
389 #ifdef debug_signal
390 g_print (">> 'CONTENTS_ACTIVATED' from %s\n", __FUNCTION__);
391 #endif
392 g_signal_emit_by_name (G_OBJECT (wrapper), "contents-activated");
393 #ifdef debug_signal
394 g_print ("<< 'CONTENTS_ACTIVATED' from %s\n", __FUNCTION__);
395 #endif
396 }
397 }
398
399 static void
gdaui_entry_wrapper_emit_signal(GdauiEntryWrapper * wrapper)400 gdaui_entry_wrapper_emit_signal (GdauiEntryWrapper *wrapper)
401 {
402 if (! wrapper->priv->signals_blocked) {
403 #ifdef debug_signal
404 g_print (">> 'CONTENTS_MODIFIED' from %s\n", __FUNCTION__);
405 #endif
406 g_signal_emit_by_name (G_OBJECT (wrapper), "contents-modified");
407 #ifdef debug_signal
408 g_print ("<< 'CONTENTS_MODIFIED' from %s\n", __FUNCTION__);
409 #endif
410 }
411 }
412
413
414
415 /* Interface implementation */
416 static void
gdaui_entry_wrapper_set_value_type(GdauiDataEntry * iface,GType type)417 gdaui_entry_wrapper_set_value_type (GdauiDataEntry *iface, GType type)
418 {
419 GdauiEntryWrapper *wrapper;
420
421 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
422 wrapper = (GdauiEntryWrapper*) iface;
423
424 if (wrapper->priv->type != type) {
425 GValue *value;
426
427 if (wrapper->priv->value_ref) {
428 gda_value_free (wrapper->priv->value_ref);
429 wrapper->priv->value_ref = NULL;
430 }
431 if (wrapper->priv->value_default) {
432 gda_value_free (wrapper->priv->value_default);
433 wrapper->priv->value_default = NULL;
434 }
435
436 wrapper->priv->type = type;
437 wrapper->priv->value_default = gda_value_new_null ();
438
439 /* Set original value */
440 value = gda_value_new_null ();
441 gdaui_entry_wrapper_set_ref_value (GDAUI_DATA_ENTRY (wrapper), value);
442 gda_value_free (value);
443 }
444 }
445
446 static GType
gdaui_entry_wrapper_get_value_type(GdauiDataEntry * iface)447 gdaui_entry_wrapper_get_value_type (GdauiDataEntry *iface)
448 {
449 GdauiEntryWrapper *wrapper;
450
451 g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), G_TYPE_INVALID);
452 wrapper = (GdauiEntryWrapper*) iface;
453
454 return wrapper->priv->type;
455 }
456
457
458 static void
gdaui_entry_wrapper_set_value(GdauiDataEntry * iface,const GValue * value)459 gdaui_entry_wrapper_set_value (GdauiDataEntry *iface, const GValue *value)
460 {
461 GdauiEntryWrapper *wrapper;
462
463 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
464 wrapper = (GdauiEntryWrapper*) iface;
465 check_correct_init (wrapper);
466
467 block_signals (wrapper);
468 if (value) {
469 g_return_if_fail ((G_VALUE_TYPE ((GValue *) value) == wrapper->priv->type) ||
470 (G_VALUE_TYPE ((GValue *) value) == GDA_TYPE_NULL));
471 (*wrapper->priv->real_class->real_set_value) (wrapper, value);
472 if (G_VALUE_TYPE ((GValue *) value) == GDA_TYPE_NULL)
473 wrapper->priv->null_forced = TRUE;
474 else
475 wrapper->priv->null_forced = FALSE;
476 }
477 else {
478 (*wrapper->priv->real_class->real_set_value) (wrapper, NULL);
479 wrapper->priv->null_forced = TRUE;
480 }
481 unblock_signals (wrapper);
482 wrapper->priv->default_forced = FALSE;
483 wrapper->priv->contents_has_changed = FALSE;
484
485 gdaui_entry_wrapper_emit_signal (wrapper);
486 }
487
488 static GValue *
gdaui_entry_wrapper_get_value(GdauiDataEntry * iface)489 gdaui_entry_wrapper_get_value (GdauiDataEntry *iface)
490 {
491 GValue *value = NULL;
492 GdauiEntryWrapper *wrapper;
493
494 g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), NULL);
495 wrapper = (GdauiEntryWrapper*) iface;
496
497 if (wrapper->priv->null_forced)
498 value = gda_value_new_null ();
499 else {
500 if (wrapper->priv->default_forced) {
501 if (G_VALUE_TYPE (wrapper->priv->value_default) == wrapper->priv->type)
502 value = gda_value_copy (wrapper->priv->value_default);
503 else
504 value = gda_value_new_null ();
505 }
506 else {
507 check_correct_init (wrapper);
508 value = (wrapper->priv->real_class->real_get_value) (wrapper);
509 }
510 }
511
512 return value;
513 }
514
515 static void
gdaui_entry_wrapper_set_ref_value(GdauiDataEntry * iface,const GValue * value)516 gdaui_entry_wrapper_set_ref_value (GdauiDataEntry *iface, const GValue *value)
517 {
518 GdauiEntryWrapper *wrapper;
519 gboolean changed = TRUE;
520 GValue *evalue;
521
522 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
523 wrapper = (GdauiEntryWrapper*) iface;
524 check_correct_init (wrapper);
525
526 /* compare existing value and the one provided as argument */
527 if (wrapper->priv->real_class->value_is_equal_to)
528 changed = ! wrapper->priv->real_class->value_is_equal_to (wrapper, value);
529 else {
530 evalue = gdaui_entry_wrapper_get_value (iface);
531 if ((!value || (G_VALUE_TYPE (value) == GDA_TYPE_NULL)) &&
532 (!evalue || (G_VALUE_TYPE (evalue) == GDA_TYPE_NULL)))
533 changed = FALSE;
534 else if (!gda_value_differ ((GValue *) value, evalue))
535 changed = FALSE;
536 if (evalue)
537 gda_value_free (evalue);
538 }
539
540 /* get rid on any existing orig value */
541 if (wrapper->priv->value_ref) {
542 gda_value_free (wrapper->priv->value_ref);
543 wrapper->priv->value_ref = NULL;
544 }
545
546 /* apply changes, if any */
547 if (changed) {
548 block_signals (wrapper);
549 gdaui_entry_wrapper_set_value (iface, value);
550 unblock_signals (wrapper);
551 }
552
553 if (value) {
554 g_return_if_fail ((G_VALUE_TYPE ((GValue *) value) == wrapper->priv->type) ||
555 (G_VALUE_TYPE ((GValue *) value) == GDA_TYPE_NULL));
556 wrapper->priv->value_ref = gda_value_copy ((GValue *) value);
557 }
558 else
559 wrapper->priv->value_ref = gda_value_new_null ();
560
561 /* signal changes if any */
562 if (changed)
563 gdaui_entry_wrapper_emit_signal (wrapper);
564 }
565
566 static const GValue *
gdaui_entry_wrapper_get_ref_value(GdauiDataEntry * iface)567 gdaui_entry_wrapper_get_ref_value (GdauiDataEntry *iface)
568 {
569 g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), NULL);
570 g_return_val_if_fail (GDAUI_ENTRY_WRAPPER (iface)->priv, NULL);
571
572 return GDAUI_ENTRY_WRAPPER (iface)->priv->value_ref;
573 }
574
575 static void
gdaui_entry_wrapper_set_value_default(GdauiDataEntry * iface,const GValue * value)576 gdaui_entry_wrapper_set_value_default (GdauiDataEntry *iface, const GValue *value)
577 {
578 GdauiEntryWrapper *wrapper;
579
580 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
581 wrapper = (GdauiEntryWrapper*) iface;
582
583 if (wrapper->priv->value_default)
584 gda_value_free (wrapper->priv->value_default);
585
586 if (value)
587 wrapper->priv->value_default = gda_value_copy ((GValue *) value);
588 else
589 wrapper->priv->value_default = gda_value_new_null ();
590
591 if (wrapper->priv->default_forced) {
592 if (G_VALUE_TYPE (wrapper->priv->value_default) == wrapper->priv->type) {
593 check_correct_init (wrapper);
594 block_signals (wrapper);
595 gdaui_entry_wrapper_set_value (iface, wrapper->priv->value_default);
596 unblock_signals (wrapper);
597 wrapper->priv->default_forced = TRUE;
598 gdaui_entry_wrapper_emit_signal (wrapper);
599 }
600 else {
601 check_correct_init (wrapper);
602 (*wrapper->priv->real_class->real_set_value) (wrapper, NULL);
603 gdaui_entry_wrapper_emit_signal (wrapper);
604 }
605 }
606 }
607
608 static void
gdaui_entry_wrapper_set_attributes(GdauiDataEntry * iface,GdaValueAttribute attrs,guint mask)609 gdaui_entry_wrapper_set_attributes (GdauiDataEntry *iface, GdaValueAttribute attrs, guint mask)
610 {
611 GdauiEntryWrapper *wrapper;
612 gboolean signal_contents_changed = FALSE;
613
614 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
615 wrapper = (GdauiEntryWrapper*) iface;
616 check_correct_init (wrapper);
617
618 /* Setting to NULL */
619 if (mask & GDA_VALUE_ATTR_IS_NULL) {
620 if ((mask & GDA_VALUE_ATTR_CAN_BE_NULL) &&
621 !(attrs & GDA_VALUE_ATTR_CAN_BE_NULL))
622 g_return_if_reached ();
623 if (attrs & GDA_VALUE_ATTR_IS_NULL) {
624 block_signals (wrapper);
625 gdaui_entry_wrapper_set_value (iface, NULL);
626 unblock_signals (wrapper);
627 wrapper->priv->null_forced = TRUE;
628
629 /* if default is set, see if we can keep it that way */
630 if (wrapper->priv->default_forced) {
631 if (G_VALUE_TYPE (wrapper->priv->value_default) !=
632 GDA_TYPE_NULL) {
633 wrapper->priv->default_forced = FALSE;
634 }
635 }
636 }
637 else
638 wrapper->priv->null_forced = FALSE;
639 signal_contents_changed = TRUE;
640 }
641
642 /* Can be NULL ? */
643 if (mask & GDA_VALUE_ATTR_CAN_BE_NULL)
644 wrapper->priv->null_possible = (attrs & GDA_VALUE_ATTR_CAN_BE_NULL) ? TRUE : FALSE;
645
646 /* Setting to DEFAULT */
647 guint current = gdaui_data_entry_get_attributes (iface);
648 if (mask & GDA_VALUE_ATTR_IS_DEFAULT) {
649 if (! (current & GDA_VALUE_ATTR_CAN_BE_DEFAULT))
650 g_warning ("Data entry does not have a default value");
651 if (attrs & GDA_VALUE_ATTR_IS_DEFAULT) {
652 block_signals (wrapper);
653 if (wrapper->priv->value_default) {
654 if (G_VALUE_TYPE (wrapper->priv->value_default) == wrapper->priv->type)
655 gdaui_entry_wrapper_set_value (iface, wrapper->priv->value_default);
656 else
657 (*wrapper->priv->real_class->real_set_value) (wrapper, NULL);
658 }
659 else
660 gdaui_entry_wrapper_set_value (iface, NULL);
661 unblock_signals (wrapper);
662
663 /* if NULL is set, see if we can keep it that way */
664 if (wrapper->priv->null_forced) {
665 if (G_VALUE_TYPE (wrapper->priv->value_default) !=
666 GDA_TYPE_NULL)
667 wrapper->priv->null_forced = FALSE;
668 }
669
670 wrapper->priv->default_forced = TRUE;
671 }
672 else
673 wrapper->priv->default_forced = FALSE;
674
675 signal_contents_changed = TRUE;
676 }
677
678 /* Can be DEFAULT ? */
679 if (mask & GDA_VALUE_ATTR_CAN_BE_DEFAULT)
680 wrapper->priv->default_possible = (attrs & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? TRUE : FALSE;
681
682 /* Modified ? */
683 if (mask & GDA_VALUE_ATTR_IS_UNCHANGED) {
684 if (attrs & GDA_VALUE_ATTR_IS_UNCHANGED) {
685 wrapper->priv->default_forced = FALSE;
686 block_signals (wrapper);
687 gdaui_entry_wrapper_set_value (iface, wrapper->priv->value_ref);
688 unblock_signals (wrapper);
689 signal_contents_changed = TRUE;
690 }
691 }
692
693 /* Actions buttons ? */
694 if (mask & GDA_VALUE_ATTR_ACTIONS_SHOWN) {
695 GValue *gval;
696 wrapper->priv->show_actions = (attrs & GDA_VALUE_ATTR_ACTIONS_SHOWN) ? TRUE : FALSE;
697
698 gval = g_new0 (GValue, 1);
699 g_value_init (gval, G_TYPE_BOOLEAN);
700 g_value_set_boolean (gval, wrapper->priv->show_actions);
701 g_object_set_property (G_OBJECT (wrapper), "actions", gval);
702 g_free (gval);
703 }
704
705 /* NON WRITABLE attributes */
706 if (mask & GDA_VALUE_ATTR_DATA_NON_VALID)
707 g_warning ("Can't force a GdauiDataEntry to be invalid!");
708
709 if (mask & GDA_VALUE_ATTR_HAS_VALUE_ORIG)
710 g_warning ("Having an original value is not a write attribute on GdauiDataEntry!");
711
712 current = gdaui_data_entry_get_attributes (iface);
713
714 if (signal_contents_changed) {
715 wrapper->priv->contents_has_changed = FALSE;
716 gdaui_entry_wrapper_emit_signal (wrapper);
717 }
718 g_signal_emit_by_name (G_OBJECT (wrapper), "status-changed");
719 }
720
721 static GdaValueAttribute
gdaui_entry_wrapper_get_attributes(GdauiDataEntry * iface)722 gdaui_entry_wrapper_get_attributes (GdauiDataEntry *iface)
723 {
724 GdaValueAttribute retval = 0;
725 GdauiEntryWrapper *wrapper;
726 GValue *value = NULL;
727 gboolean has_current_value;
728 gboolean value_is_null = FALSE;
729
730 g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), 0);
731 wrapper = (GdauiEntryWrapper*) iface;
732
733 check_correct_init (wrapper);
734 if (!wrapper->priv->real_class->value_is_equal_to ||
735 !wrapper->priv->real_class->value_is_null) {
736 value = gdaui_entry_wrapper_get_value (iface);
737 has_current_value = TRUE;
738 }
739 else
740 has_current_value = FALSE;
741
742 /* NULL? */
743 if (has_current_value) {
744 if ((value && (G_VALUE_TYPE (value) == GDA_TYPE_NULL)) || !value) {
745 if (wrapper->priv->default_forced) {
746 if (wrapper->priv->null_forced)
747 value_is_null = TRUE;
748 }
749 else
750 value_is_null = TRUE;
751 }
752 }
753 else {
754 if ((wrapper->priv->real_class->value_is_null) (wrapper))
755 value_is_null = TRUE;
756 }
757 if (value_is_null)
758 retval = retval | GDA_VALUE_ATTR_IS_NULL;
759
760 /* can be NULL? */
761 if (wrapper->priv->null_possible)
762 retval = retval | GDA_VALUE_ATTR_CAN_BE_NULL;
763
764 /* is default */
765 if (wrapper->priv->default_forced)
766 retval = retval | GDA_VALUE_ATTR_IS_DEFAULT;
767
768 /* can be default? */
769 if (wrapper->priv->default_possible)
770 retval = retval | GDA_VALUE_ATTR_CAN_BE_DEFAULT;
771
772 /* is unchanged */
773 if (has_current_value) {
774 if (wrapper->priv->value_ref &&
775 (G_VALUE_TYPE (value) == G_VALUE_TYPE (wrapper->priv->value_ref))) {
776 if (gda_value_is_null (value))
777 retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
778 else {
779 if (! gda_value_differ (value, wrapper->priv->value_ref))
780 retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
781 }
782 }
783 }
784 else if ((wrapper->priv->real_class->value_is_equal_to) (wrapper, wrapper->priv->value_ref))
785 retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
786
787 /* actions shown */
788 if (wrapper->priv->show_actions)
789 retval = retval | GDA_VALUE_ATTR_ACTIONS_SHOWN;
790
791 /* data valid? */
792 if (! (wrapper->priv->default_forced && wrapper->priv->default_possible)) {
793 if (/*(value_is_null && !wrapper->priv->null_forced) ||*/
794 (value_is_null && !wrapper->priv->null_possible))
795 retval = retval | GDA_VALUE_ATTR_DATA_NON_VALID;
796 }
797
798 /* has original value? */
799 if (wrapper->priv->value_ref)
800 retval = retval | GDA_VALUE_ATTR_HAS_VALUE_ORIG;
801
802 if (has_current_value)
803 gda_value_free (value);
804
805 if (!wrapper->priv->editable)
806 retval = retval | GDA_VALUE_ATTR_NO_MODIF;
807
808 return retval;
809 }
810
811
812 static GdaDataHandler *
gdaui_entry_wrapper_get_handler(GdauiDataEntry * iface)813 gdaui_entry_wrapper_get_handler (GdauiDataEntry *iface)
814 {
815 GdaDataHandler *dh;
816
817 g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), NULL);
818
819 g_object_get (G_OBJECT (iface), "handler", &dh, NULL);
820 if (dh) /* loose the reference before returning the object */
821 g_object_unref (dh);
822
823 return dh;
824 }
825
826 static void
gdaui_entry_wrapper_set_editable(GdauiDataEntry * iface,gboolean editable)827 gdaui_entry_wrapper_set_editable (GdauiDataEntry *iface, gboolean editable)
828 {
829 GdauiEntryWrapper *wrapper;
830
831 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
832 wrapper = (GdauiEntryWrapper*) iface;
833 check_correct_init (wrapper);
834
835 wrapper->priv->editable = editable;
836 if (wrapper->priv->real_class->set_editable)
837 (wrapper->priv->real_class->set_editable) (wrapper, editable);
838 else
839 gtk_widget_set_sensitive (GTK_WIDGET (iface), editable);
840 }
841
842 static gboolean
gdaui_entry_wrapper_get_editable(GdauiDataEntry * iface)843 gdaui_entry_wrapper_get_editable (GdauiDataEntry *iface)
844 {
845 GdauiEntryWrapper *wrapper;
846
847 g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), FALSE);
848 wrapper = (GdauiEntryWrapper*) iface;
849
850 return wrapper->priv->editable;
851 }
852
853 static void
gdaui_entry_wrapper_grab_focus(GdauiDataEntry * iface)854 gdaui_entry_wrapper_grab_focus (GdauiDataEntry *iface)
855 {
856 GdauiEntryWrapper *wrapper;
857
858 g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
859 wrapper = (GdauiEntryWrapper*) iface;
860 check_correct_init (wrapper);
861
862 if (wrapper->priv->real_class->grab_focus)
863 (wrapper->priv->real_class->grab_focus) (wrapper);
864 else if (wrapper->priv->entry) {
865 gboolean canfocus;
866 g_object_get ((GObject*) wrapper->priv->entry, "can-focus", &canfocus, NULL);
867 if (canfocus)
868 gtk_widget_grab_focus (wrapper->priv->entry);
869 }
870 }
871
872 static void
gdaui_entry_wrapper_set_unknown_color(GdauiDataEntry * de,gdouble red,gdouble green,gdouble blue,gdouble alpha)873 gdaui_entry_wrapper_set_unknown_color (GdauiDataEntry *de, gdouble red, gdouble green,
874 gdouble blue, gdouble alpha)
875 {
876 gdaui_entry_shell_set_ucolor (GDAUI_ENTRY_SHELL (de), red, green, blue, alpha);
877 }
878