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 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 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 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 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 218 block_signals (GdauiEntryWrapper *wrapper) 219 { 220 wrapper->priv->signals_blocked ++; 221 } 222 223 static void 224 unblock_signals (GdauiEntryWrapper *wrapper) 225 { 226 wrapper->priv->signals_blocked --; 227 } 228 229 230 static void 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 * 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 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 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 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 * 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 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 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 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 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