[libgda] Major rework of the data entries



commit 4a9f615d887def93ccfb109611d100d8ab7e0bd1
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sun Nov 29 14:44:13 2015 +0100

    Major rework of the data entries

 doc/C/libgda-sections.txt                          |    1 +
 libgda-ui/data-entries/common-bin.c                |  500 +++++++---
 libgda-ui/data-entries/common-bin.h                |   19 +-
 .../data-entries/gdaui-data-cell-renderer-bin.c    |   51 +-
 libgda-ui/data-entries/gdaui-entry-bin.c           |  207 ++---
 libgda-ui/data-entries/gdaui-entry-boolean.c       |   76 +-
 libgda-ui/data-entries/gdaui-entry-combo.c         |   56 +-
 libgda-ui/data-entries/gdaui-entry-common-time.c   | 1112 ++++++++------------
 libgda-ui/data-entries/gdaui-entry-integer.xml.in  |    4 +-
 libgda-ui/data-entries/gdaui-entry-none.c          |   13 +-
 libgda-ui/data-entries/gdaui-entry-number.c        |   30 +-
 libgda-ui/data-entries/gdaui-entry-number.xml.in   |    6 +-
 libgda-ui/data-entries/gdaui-entry-shell.c         |  603 +++++++----
 libgda-ui/data-entries/gdaui-entry-shell.h         |   17 +-
 libgda-ui/data-entries/gdaui-entry-string.c        |   37 +-
 libgda-ui/data-entries/gdaui-entry-string.xml.in   |    8 +-
 libgda-ui/data-entries/gdaui-entry-wrapper.c       |  288 +++---
 libgda-ui/data-entries/gdaui-entry.c               |   87 ++-
 libgda-ui/data-entries/gdaui-formatted-entry.c     |    2 +-
 libgda-ui/data-entries/gdaui-numeric-entry.c       |   34 +-
 libgda-ui/data-entries/plugins/gdaui-entry-cidr.c  |    6 +-
 .../data-entries/plugins/gdaui-entry-filesel.c     |   10 +-
 .../data-entries/plugins/gdaui-entry-format.c      |    6 +-
 .../data-entries/plugins/gdaui-entry-password.c    |   10 +-
 libgda-ui/data-entries/plugins/gdaui-entry-rt.c    |   10 +-
 libgda-ui/data-entries/plugins/gdaui-entry-text.c  |    9 +-
 libgda-ui/data/Makefile.am                         |    3 +-
 libgda-ui/data/bin-attachment-16x16.png            |  Bin 649 -> 0 bytes
 libgda-ui/data/mime-types-extensions               |  413 ++++++++
 libgda-ui/gdaui-basic-form.c                       |  254 ++---
 libgda-ui/gdaui-cloud.c                            |    3 +-
 libgda-ui/gdaui-data-entry.h                       |    4 +-
 libgda-ui/gdaui-enums.h                            |    8 +
 libgda-ui/gdaui-form.c                             |    3 +-
 libgda-ui/gdaui-raw-form.c                         |   14 -
 libgda-ui/gdaui.css                                |   12 -
 libgda-ui/gdaui.gresource.xml                      |    4 +-
 libgda-ui/internal/utility.c                       |    4 +-
 libgda-ui/libgda-ui.symbols                        |    3 +-
 libgda/gda-enums.h                                 |   17 +-
 libgda/gda-value.c                                 |   95 ++-
 libgda/gda-value.h                                 |    3 +-
 libgda/handlers/gda-handler-time.c                 |   62 ++-
 libgda/handlers/gda-handler-time.h                 |    2 +
 libgda/libgda.symbols                              |    2 +
 testing/gdaui-test-data-entries.c                  |  147 ++-
 testing/gdaui-test-errors.c                        |   11 +-
 testing/gdaui-test-widget-entry.c                  |   45 +-
 48 files changed, 2496 insertions(+), 1815 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index a9d17a0..64aa99b 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -943,6 +943,7 @@ gda_time_valid
 gda_time_change_timezone
 gda_value_get_time
 gda_value_set_time
+gda_value_new_time_from_timet
 <SUBSECTION>
 GdaTimestamp
 gda_timestamp_copy
diff --git a/libgda-ui/data-entries/common-bin.c b/libgda-ui/data-entries/common-bin.c
index 25e92d5..638d793 100644
--- a/libgda-ui/data-entries/common-bin.c
+++ b/libgda-ui/data-entries/common-bin.c
@@ -19,9 +19,9 @@
  * Boston, MA  02110-1301, USA.
  */
 
+#include <glib/gstdio.h>
 #include <libgda/gda-value.h>
 #include "common-bin.h"
-#include "../internal/popup-container.h"
 #include <string.h>
 #include <gtk/gtk.h>
 #include <glib/gi18n-lib.h>
@@ -32,11 +32,30 @@
 #endif
 
 static void
+show_and_clear_error (BinMenu *binmenu, const gchar *context, GError **error)
+{
+       if (!error)
+               return;
+
+       GtkWidget *msg, *relative_to;
+       relative_to = gtk_popover_get_relative_to (GTK_POPOVER (binmenu->popover));
+       msg = gtk_message_dialog_new_with_markup (relative_to ? GTK_WINDOW (gtk_widget_get_toplevel 
(relative_to)) : NULL,
+                                                 GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
+                                                 GTK_BUTTONS_CLOSE,
+                                                 "<b>%s:</b>\n%s: %s",
+                                                 _("Error"), context,
+                                                 *error && (*error)->message ? (*error)->message : _("No 
detail"));
+       gtk_dialog_run (GTK_DIALOG (msg));
+       gtk_widget_destroy (msg);
+       g_clear_error (error);
+}
+
+static void
 file_load_cb (GtkWidget *button, BinMenu *menu)
 {
        GtkWidget *dlg;
 
-       gtk_widget_hide (menu->popup);
+       gtk_widget_hide (menu->popover);
         dlg = gtk_file_chooser_dialog_new (_("Select file to load"),
                                            GTK_WINDOW (gtk_widget_get_toplevel (button)),
                                            GTK_FILE_CHOOSER_ACTION_OPEN,
@@ -71,22 +90,13 @@ file_load_cb (GtkWidget *button, BinMenu *menu)
                                menu->loaded_value_cb (menu->loaded_value_cb_data, nvalue);
                        }
                        else {
-                               GtkWidget *msg;
+                               gtk_widget_destroy (dlg);
+                               dlg = NULL;
+
                                gchar *tmp;
                                tmp = g_strdup_printf (_("Could not load the contents of '%s'"), filename);
-                               msg = gtk_message_dialog_new_with_markup (GTK_WINDOW (gtk_widget_get_toplevel 
(button)),
-                                                                         GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
-                                                                         GTK_BUTTONS_CLOSE,
-                                                                         "<b>%s:</b>\n%s: %s",
-                                                                         _("Error"), tmp,
-                                                                         error && error->message ? 
error->message : _("No detail"));
+                               show_and_clear_error (menu, tmp, &error);
                                g_free (tmp);
-                               g_clear_error (&error);
-                               gtk_widget_destroy (dlg);
-                               dlg = NULL;
-                               
-                               gtk_dialog_run (GTK_DIALOG (msg));
-                               gtk_widget_destroy (msg);
                        }
                }
                else
@@ -102,12 +112,51 @@ file_load_cb (GtkWidget *button, BinMenu *menu)
        }
 }
 
+static gboolean
+export_data (BinMenu *menu, const gchar *filename, GError **error)
+{
+       gboolean allok;
+       if (menu->entry_type == GDA_TYPE_BINARY) {
+               const GdaBinary *bin;
+               bin = gda_value_get_binary (menu->tmpvalue);
+               allok = g_file_set_contents (filename, (gchar *) bin->data,
+                                            bin->binary_length, error);
+       }
+       else if (menu->entry_type == GDA_TYPE_BLOB) {
+               GdaBlob *blob;
+               blob = (GdaBlob*) gda_value_get_blob (menu->tmpvalue);
+               if (blob->op) {
+                       GValue *dest_value;
+                       GdaBlob *dest_blob;
+
+                       dest_value = gda_value_new_blob_from_file (filename);
+                       dest_blob = (GdaBlob*) gda_value_get_blob (dest_value);
+                       allok = gda_blob_op_write_all (dest_blob->op, (GdaBlob*) blob);
+                       gda_value_free (dest_value);
+               }
+               else
+                       allok = g_file_set_contents (filename, (gchar *) ((GdaBinary*)blob)->data,
+                                                    ((GdaBinary*)blob)->binary_length, error);
+       }
+       else
+               g_assert_not_reached ();
+       if (allok) {
+#ifdef G_OS_WIN32
+               SetFileAttributes (filename, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
+                                  FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_TEMPORARY);
+#else
+               g_chmod (filename, 0400);
+#endif
+       }
+       return allok;
+}
+
 static void
 file_save_cb (GtkWidget *button, BinMenu *menu)
 {
        GtkWidget *dlg;
 
-       gtk_widget_hide (menu->popup);
+       gtk_widget_hide (menu->popover);
         dlg = gtk_file_chooser_dialog_new (_("Select a file to save data to"),
                                            GTK_WINDOW (gtk_widget_get_toplevel (button)),
                                            GTK_FILE_CHOOSER_ACTION_SAVE,
@@ -120,36 +169,10 @@ file_save_cb (GtkWidget *button, BinMenu *menu)
 
         if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_ACCEPT) {
                 char *filename;
-                gboolean allok = TRUE;
                 GError *error = NULL;
 
                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg));
-               if (menu->entry_type == GDA_TYPE_BINARY) {
-                       const GdaBinary *bin;
-                       bin = gda_value_get_binary (menu->tmpvalue);
-                       allok = g_file_set_contents (filename, (gchar *) bin->data,
-                                                    bin->binary_length, &error);
-               }
-               else if (menu->entry_type == GDA_TYPE_BLOB) {
-                       GdaBlob *blob;
-                       blob = (GdaBlob*) gda_value_get_blob (menu->tmpvalue);
-                       if (blob->op) {
-                              
-                               GValue *dest_value;
-                               GdaBlob *dest_blob;
-
-                               dest_value = gda_value_new_blob_from_file (filename);
-                               dest_blob = (GdaBlob*) gda_value_get_blob (dest_value);
-                               allok = gda_blob_op_write_all (dest_blob->op, (GdaBlob*) blob);
-                               gda_value_free (dest_value);
-                       }
-                       else
-                               allok = g_file_set_contents (filename, (gchar *) ((GdaBinary*)blob)->data,
-                                                            ((GdaBinary*)blob)->binary_length, &error);
-               }
-               else
-                       g_assert_not_reached ();
-                if (!allok) {
+                if (! export_data (menu, filename, &error)) {
                         GtkWidget *msg;
                        gchar *tmp;
                        tmp = g_strdup_printf (_("Could not save data to '%s'"), filename);
@@ -174,62 +197,73 @@ file_save_cb (GtkWidget *button, BinMenu *menu)
                g_free (menu->current_folder);
                menu->current_folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dlg));
                 gtk_widget_destroy (dlg);
-
        }
 }
 
+static void
+clear_data_cb (GtkWidget *button, BinMenu *menu)
+{
+       menu->loaded_value_cb (menu->loaded_value_cb_data, NULL);
+}
+
+#ifdef HAVE_GIO
+static void
+open_data_cb (GtkWidget *button, BinMenu *menu)
+{
+       g_return_if_fail (menu->open_menu);
+       gtk_menu_popup (GTK_MENU (menu->open_menu), NULL, NULL, NULL, NULL,
+                       0, gtk_get_current_event_time ());
+}
+#endif
+
 void
-common_bin_create_menu (BinMenu *binmenu, PopupContainerPositionFunc pos_func, GType entry_type,
+common_bin_create_menu (GtkWidget *relative_to, BinMenu *binmenu, GType entry_type,
                        BinCallback loaded_value_cb, gpointer loaded_value_cb_data)
 {
-       GtkWidget *popup, *vbox, *hbox, *bbox, *button, *label;
+       GtkWidget *vbox, *hbox, *bbox, *button, *label;
        gchar *str;
 
        binmenu->entry_type = entry_type;
        binmenu->loaded_value_cb = loaded_value_cb;
        binmenu->loaded_value_cb_data = loaded_value_cb_data;
        
-       popup = popup_container_new_with_func (pos_func);
-       binmenu->popup = popup;
-       
-       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-       gtk_container_add (GTK_CONTAINER (popup), vbox);
-
-       label = gtk_label_new ("");
-       str = g_strdup_printf ("<b>%s:</b>", _("Properties"));
-       gtk_label_set_markup (GTK_LABEL (label), str);
-       g_free (str);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
-       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
-
-       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); /* HIG */
-        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
-        gtk_widget_show (hbox);
-        label = gtk_label_new ("    ");
-        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-        gtk_widget_show (label);
-
-       label = gtk_label_new ("");
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
-       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-       binmenu->props_label = label;
+       binmenu->popover = gtk_popover_new (relative_to);
+       gtk_popover_set_modal (GTK_POPOVER (binmenu->popover), TRUE);
 
        bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
-       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
+       gtk_container_add (GTK_CONTAINER (binmenu->popover), bbox);
 
-       button = gtk_button_new_from_icon_name ("document-open", GTK_ICON_SIZE_BUTTON);
+       button = gtk_button_new_from_icon_name ("document-open-symbolic", GTK_ICON_SIZE_MENU);
+       gtk_widget_set_tooltip_text (button, _("Load data from file"));
        gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
        g_signal_connect (button, "clicked",
                          G_CALLBACK (file_load_cb), binmenu);
        binmenu->load_button = button;
 
-       button = gtk_button_new_from_icon_name ("document-save-as", GTK_ICON_SIZE_BUTTON);
+       button = gtk_button_new_from_icon_name ("document-save-as-symbolic", GTK_ICON_SIZE_MENU);
+       gtk_widget_set_tooltip_text (button, _("Save data to file"));
        gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
        g_signal_connect (button, "clicked",
                          G_CALLBACK (file_save_cb), binmenu);
        binmenu->save_button = button;
 
-       gtk_widget_show_all (vbox);
+       button = gtk_button_new_from_icon_name ("edit-clear-symbolic", GTK_ICON_SIZE_MENU);
+       gtk_widget_set_tooltip_text (button, _("Clear data"));
+       gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+       g_signal_connect (button, "clicked",
+                         G_CALLBACK (clear_data_cb), binmenu);
+       binmenu->clear_button = button;
+
+#ifdef HAVE_GIO
+       button = gtk_button_new_from_icon_name ("open-menu-symbolic", GTK_ICON_SIZE_MENU);
+       gtk_widget_set_tooltip_text (button, _("Open with..."));
+       gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+       g_signal_connect (button, "clicked",
+                         G_CALLBACK (open_data_cb), binmenu);
+       binmenu->open_button = button;
+#endif
+
+       gtk_widget_show_all (bbox);
 }
 
 static gchar *
@@ -245,39 +279,27 @@ format_size (gulong size)
                return g_strdup_printf ("%.1f Gio", (gfloat) (size / 1073741824));
 }
 
-/* 
- * adjust the sensitiveness of the menu items in the popup menu
+/**
+ * common_bin_get_description:
  */
-void
-common_bin_adjust_menu (BinMenu *binmenu, gboolean editable, const GValue *value)
+gchar *
+common_bin_get_description (BinMenu *binmenu)
 {
        gchar *size;
-       GString *string;
-#ifdef HAVE_GIO
-       gchar *ctype = NULL;
-#endif
+       GString *string = NULL;
 
-       if (!binmenu || !binmenu->popup)
-               return;
-
-       if (binmenu->tmpvalue) {
-               gda_value_free (binmenu->tmpvalue);
-               binmenu->tmpvalue = NULL;
-       }
-       string = g_string_new ("");
+       const GValue *value = binmenu->tmpvalue;
        if (value) {
-               binmenu->tmpvalue = gda_value_copy (value);
                if (G_VALUE_TYPE (value) == GDA_TYPE_NULL)
-                       g_string_append_printf (string, "<i>%s</i>", _("No data"));
-               else if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
+                       return NULL;
+
+               string = g_string_new ("");
+               if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
                        const GdaBinary *bin;
                        bin = gda_value_get_binary (value);
                        size = format_size (bin->binary_length);
-                       g_string_append_printf (string, "%s: %s", _("Data size"), size);
+                       g_string_append (string, size);
                        g_free (size);
-#ifdef HAVE_GIO
-                       ctype = g_content_type_guess (NULL, bin->data, (gsize) bin->binary_length, NULL);
-#endif
                }
                else if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
                        const GdaBlob *blob;
@@ -289,67 +311,276 @@ common_bin_adjust_menu (BinMenu *binmenu, gboolean editable, const GValue *value
                                len = gda_blob_op_get_length (blob->op);
                                if (len >= 0) {
                                        size = format_size (len);
-                                       g_string_append_printf (string, "%s: %s", _("Data size"), size);
+                                       g_string_append (string, size);
                                        g_free (size);
-#ifdef HAVE_GIO
-                                       GdaBlob *blob2;
-                                       blob2 = (GdaBlob*) gda_blob_copy ((gpointer) blob);
-                                       gda_blob_op_read (blob2->op, blob2, 0, 1024);
-                                       bin = (GdaBinary *) blob2;
-                                       ctype = g_content_type_guess (NULL, bin->data,
-                                                                     (gsize) bin->binary_length, NULL);
-                                       gda_blob_free ((gpointer) blob2);
-#endif
                                }
                                else
-                                       g_string_append_printf (string, "%s: %s", _("Data size"), 
_("Unknown"));
+                                       g_string_append (string, _("Unknown size"));
                        }
                        else {
                                size = format_size (bin->binary_length);
-                               g_string_append_printf (string, "%s: %s", _("Data size"), size);
+                               g_string_append (string, size);
                                g_free (size);
-#ifdef HAVE_GIO
-                               ctype = g_content_type_guess (NULL, bin->data, (gsize) bin->binary_length, 
NULL);
-#endif
                        }
                }
                else
                        g_assert_not_reached ();
        }
        else
-               g_string_append_printf (string, "<i>%s</i>", _("No data"));
+               return NULL;
 
 #ifdef HAVE_GIO
-       if (ctype) {
-               GList *list;
-               gchar *descr, *tmp;
-               descr = g_content_type_get_description (ctype);
-               tmp = g_markup_escape_text (descr, -1);
-               g_free (descr);
-               g_string_append_printf (string, "\n%s: %s", _("Data type"), tmp);
+       if (binmenu->ctype) {
+               gchar *tmp;
+               tmp = g_content_type_get_description (binmenu->ctype);
+               g_string_append_printf (string, " (%s)", tmp);
+               g_free (tmp);
+       }
+#endif
+       return g_string_free (string, FALSE);
+}
+
+#ifdef HAVE_GIO
+
+typedef struct {
+       gchar *dirname;
+       gchar *filename;
+} LaunchData;
+
+static gboolean
+launch_cleanups (LaunchData *data)
+{
+       g_assert (data);
+
+       if (data->filename) {
+#ifndef G_OS_WIN32
+               if (g_unlink (data->filename))
+                       g_warning ("Error removing temporary file %s", data->filename);
+#endif
+               g_free (data->filename);
+       }
+
+       if (data->dirname) {
+#ifndef G_OS_WIN32
+               if (g_rmdir (data->dirname))
+                       g_warning ("Error removing temporary directory %s", data->dirname);
+#endif
+               g_free (data->dirname);
+       }
+       g_free (data);
+
+       return G_SOURCE_REMOVE;
+}
+
+static gchar *
+get_file_extension_for_mime_type (const gchar *mime_type)
+{
+       g_return_val_if_fail (mime_type && *mime_type, NULL);
+       size_t length;
+       length = strlen (mime_type);
+       g_return_val_if_fail (length > 0, NULL);
+       GBytes *css_data;
+        css_data = g_resources_lookup_data ("/gdaui/data/mime-types-extensions",
+                                           G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+       if (css_data) {
+               gchar *ext = NULL;
+               const gchar *data;
+               const gchar *sol;
+               data = (gchar*) g_bytes_get_data (css_data, NULL);
+               for (sol = data; *sol; ) {
+                       const gchar *eol;
+                       for (eol = sol; *eol && (*eol != '\n'); eol++);
+                       if (((size_t) (eol - sol) > length) &&
+                           (sol[length] == '.') &&
+                           !strncmp (sol, mime_type, length)) {
+                               ext = g_strndup (sol + length + 1, eol - sol - length - 1);
+                               break;
+                       }
+                       sol = eol;
+                       if (*sol)
+                               sol++;
+               }
+               g_bytes_unref (css_data);
+               return ext;
+       }
+       else
+               return NULL;
+}
+
+static void
+open_activate_cb (GtkMenuItem *mitem, BinMenu *binmenu)
+{
+       GAppInfo *ai;
+       ai = g_object_get_data (G_OBJECT (mitem), "ai");
+       g_print ("OPENING With %s\n", g_app_info_get_name (ai));
+
+       GError *error = NULL;
+
+       /* Save data to a TMP file */
+       gchar *tmpdir;
+       tmpdir = g_dir_make_tmp (NULL, &error);
+       if (!tmpdir) {
+               show_and_clear_error (binmenu, _("Could not create temporary directory"), &error);
+               return;
+       }
+
+       /* filename */
+#define BASE_EXP_NAME "exported-data"
+       gchar *filename;
+       gchar *ext;
+       ext = get_file_extension_for_mime_type (binmenu->ctype);
+       if (ext) {
+               gchar *tmp;
+               tmp = g_strdup_printf ("%s.%s", BASE_EXP_NAME, ext);
+               filename = g_build_filename (tmpdir, tmp, NULL);
                g_free (tmp);
+               g_free (ext);
+       }
+       else
+               filename = g_build_filename (tmpdir, BASE_EXP_NAME, NULL);
+       g_print ("TMP file is: %s\n", filename);
+
+       LaunchData *data;
+       data = g_new (LaunchData, 1);
+       data->dirname = tmpdir;
+       data->filename = filename;
+
+       if (export_data (binmenu, filename, &error)) {
+               g_print ("Exported, now runinng opener program\n");
+               GList *files_list;
+               GFile *file;
+               file = g_file_new_for_path (filename);
+               files_list = g_list_append (NULL, file);
+
+               if (g_app_info_launch (ai, files_list, NULL, &error)) {
+                       g_print ("Ok, running...\n");
+                       g_timeout_add_seconds (30, (GSourceFunc) launch_cleanups, data);
+               }
+               else {
+                       show_and_clear_error (binmenu, _("Could not run selected application"), &error);
+                       launch_cleanups (data);
+               }
+               g_list_free (files_list);
+               g_object_unref (file);
+       }
+       else {
+               show_and_clear_error (binmenu, _("Could not export data"), &error);
+               launch_cleanups (data);
+       }
+}
+
+static void
+adjust_ctype (BinMenu *binmenu)
+{
+       g_free (binmenu->ctype);
+       binmenu->ctype = NULL;
+       if (binmenu->open_menu) {
+               gtk_widget_destroy (binmenu->open_menu);
+               binmenu->open_menu = NULL;
+       }
+       if (! binmenu->tmpvalue)
+               return;
+
+       const GValue *value = binmenu->tmpvalue;
+       if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
+               if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
+                       const GdaBinary *bin;
+                       bin = gda_value_get_binary (value);
+                       binmenu->ctype = g_content_type_guess (NULL, bin->data, (gsize) bin->binary_length, 
NULL);
+               }
+               else if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
+                       const GdaBlob *blob;
+                       GdaBinary *bin;
+                       blob = gda_value_get_blob (value);
+                       bin = (GdaBinary *) blob;
+                       if (blob->op) {
+                               glong len;
+                               len = gda_blob_op_get_length (blob->op);
+                               if (len >= 0) {
+                                       GdaBlob *blob2;
+                                       blob2 = (GdaBlob*) gda_blob_copy ((gpointer) blob);
+                                       gda_blob_op_read (blob2->op, blob2, 0, 1024);
+                                       bin = (GdaBinary *) blob2;
+                                       binmenu->ctype = g_content_type_guess (NULL, bin->data,
+                                                                     (gsize) bin->binary_length, NULL);
+                                       gda_blob_free ((gpointer) blob2);
+                               }
+                       }
+                       else
+                               binmenu->ctype = g_content_type_guess (NULL, bin->data,
+                                                                      (gsize) bin->binary_length, NULL);
+               }
+               else
+                       g_assert_not_reached ();
+       }
+       if (binmenu->ctype) {
+               GList *list;
+               list = g_app_info_get_all_for_type (binmenu->ctype);
+               for (; list; ) {
+                       GAppInfo *ai = (GAppInfo *) list->data;
+                       if (!binmenu->open_menu)
+                               binmenu->open_menu = gtk_menu_new ();
 
-               list = g_app_info_get_all_for_type (ctype);
-               for (; list; list = list->next) {
-                       GAppInfo *ai;
-                       ai = (GAppInfo*) list->data;
-                       g_print ("\t open with %s (%s)\n", g_app_info_get_name (ai),
-                                g_app_info_get_executable (ai));
+                       gchar *tmp;
+                       tmp = g_strdup_printf ("%s %s", _("Open with"), g_app_info_get_name (ai));
+                       GtkWidget *mitem;
+                       mitem = gtk_menu_item_new_with_label (tmp);
+                       g_free (tmp);
+                       g_object_set_data_full (G_OBJECT (mitem), "ai", ai, g_object_unref);
+                       g_signal_connect (mitem, "activate",
+                                         G_CALLBACK (open_activate_cb), binmenu);
+                       gtk_menu_shell_append (GTK_MENU_SHELL (binmenu->open_menu), mitem);
+                       gtk_widget_show (mitem);
+
+                       list = g_list_delete_link (list, list);
                }
-               g_free (ctype);
        }
+}
 #endif
 
+/*
+ * adjust the sensitiveness of the menu items in the popup menu
+ */
+void
+common_bin_adjust (BinMenu *binmenu, gboolean editable, const GValue *value)
+{
+       gchar *size;
+       GString *string;
 
-       gtk_label_set_markup (GTK_LABEL (binmenu->props_label), string->str);
-       g_string_free (string, TRUE);
+       if (!binmenu || !binmenu->popover)
+               return;
 
+       if (value != binmenu->tmpvalue) {
+               if (binmenu->tmpvalue) {
+                       gda_value_free (binmenu->tmpvalue);
+                       binmenu->tmpvalue = NULL;
+               }
+               if (value)
+                       binmenu->tmpvalue = gda_value_copy (value);
+       }
+#ifdef HAVE_GIO
+       adjust_ctype (binmenu);
+#endif
        gtk_widget_set_sensitive (binmenu->load_button, editable);
        gtk_widget_set_sensitive (binmenu->save_button, (value && !gda_value_is_null (value)) ? TRUE : FALSE);
+       gtk_widget_set_sensitive (binmenu->clear_button, (editable && value && !gda_value_is_null (value)) ? 
TRUE : FALSE);
+#ifdef HAVE_GIO
+       gtk_widget_set_sensitive (binmenu->open_button, binmenu->open_menu ? TRUE : FALSE);
+#endif
+}
+
+/*
+ * Initialize @binmenu's contents
+ */
+void
+common_bin_init (BinMenu *binmenu)
+{
+       g_assert (binmenu);
+       memset (binmenu, 0, sizeof (BinMenu));
 }
 
 /*
- * Reset @bonmenu's contents
+ * Reset @binmenu's contents
  */
 void
 common_bin_reset (BinMenu *binmenu)
@@ -358,9 +589,14 @@ common_bin_reset (BinMenu *binmenu)
                gda_value_free (binmenu->tmpvalue);
                binmenu->tmpvalue = NULL;
        }
-       if (binmenu->popup)
-               gtk_widget_destroy (binmenu->popup);
+       if (binmenu->popover)
+               gtk_widget_destroy (binmenu->popover);
        g_free (binmenu->current_folder);
+#ifdef HAVE_GIO
+       if (binmenu->open_menu)
+               gtk_widget_destroy (binmenu->open_menu);
+       g_free (binmenu->ctype);
+#endif 
 
        memset (binmenu, 0, sizeof (BinMenu));
 }
diff --git a/libgda-ui/data-entries/common-bin.h b/libgda-ui/data-entries/common-bin.h
index fbdb6c6..6b3c13a 100644
--- a/libgda-ui/data-entries/common-bin.h
+++ b/libgda-ui/data-entries/common-bin.h
@@ -25,15 +25,20 @@
 #define __COMMON_BIN_H__
 
 #include <gtk/gtk.h>
-#include "../internal/popup-container.h"
 
 typedef void (*BinCallback) (gpointer, GValue *);
 typedef struct {
-        GtkWidget    *popup; /* PopupContainer popup window */
+        GtkWidget    *popover; /* GtkPopover popup window */
         GtkWidget    *load_button;
         GtkWidget    *save_button;
+       GtkWidget    *clear_button;
+#ifdef HAVE_GIO
+       GtkWidget    *open_button;
+       gchar        *ctype;
+       GtkWidget    *open_menu;
+#endif
+
        gchar        *current_folder;
-       GtkWidget    *props_label;
 
        GType         entry_type;
        GValue       *tmpvalue;
@@ -43,9 +48,11 @@ typedef struct {
 } BinMenu;
 
 
-void         common_bin_create_menu (BinMenu *binmenu, PopupContainerPositionFunc pos_func, GType entry_type,
-                                    BinCallback loaded_value_cb, gpointer loaded_value_cb_data);
-void         common_bin_adjust_menu (BinMenu *binmenu, gboolean editable, const GValue *value);
+void         common_bin_init (BinMenu *binmenu);
 void         common_bin_reset (BinMenu *binmenu);
+gchar       *common_bin_get_description (BinMenu *binmenu);
+void         common_bin_create_menu (GtkWidget *relative_to, BinMenu *binmenu, GType entry_type,
+                                    BinCallback loaded_value_cb, gpointer loaded_value_cb_data);
+void         common_bin_adjust (BinMenu *binmenu, gboolean editable, const GValue *value);
 
 #endif
diff --git a/libgda-ui/data-entries/gdaui-data-cell-renderer-bin.c 
b/libgda-ui/data-entries/gdaui-data-cell-renderer-bin.c
index 5f2a4aa..be078c8 100644
--- a/libgda-ui/data-entries/gdaui-data-cell-renderer-bin.c
+++ b/libgda-ui/data-entries/gdaui-data-cell-renderer-bin.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2014 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  *
@@ -391,41 +391,6 @@ bin_data_changed_cb (GdauiDataCellRendererBin *bincell, GValue *value)
         gda_value_free (value);
 }
 
-static void
-popup_position (PopupContainer *container, gint *out_x, gint *out_y)
-{
-       GtkWidget *poswidget;
-       GdkEvent *event;
-       GdkRectangle *rect;
-       gint x, y;
-
-       poswidget = g_object_get_data (G_OBJECT (container), "__poswidget");
-       event = g_object_get_data (G_OBJECT (container), "__event");
-       rect = g_object_get_data (G_OBJECT (container), "__rect");
-
-       if (event && (event->type == GDK_BUTTON_PRESS)) {
-               GdkEventButton *rev = (GdkEventButton*) event;
-               gdk_window_get_origin (rev->window, &x, &y);
-               x += (gint) rev->x;
-               y += (gint) rev->y;
-       }
-       else {
-               g_assert (rect);
-               gdk_window_get_origin (gtk_tree_view_get_bin_window (GTK_TREE_VIEW (poswidget)), &x, &y);
-               x += rect->x;
-               y += rect->y;
-       }
-
-       if (x < 0)
-                x = 0;
-
-        if (y < 0)
-                y = 0;
-
-       *out_x = x;
-       *out_y = y;
-}
-
 static gboolean
 gdaui_data_cell_renderer_bin_activate  (GtkCellRenderer            *cell,
                                        GdkEvent                   *event,
@@ -443,11 +408,9 @@ gdaui_data_cell_renderer_bin_activate  (GtkCellRenderer            *cell,
         bincell = GDAUI_DATA_CELL_RENDERER_BIN (cell);
        
        g_object_set_data_full (G_OBJECT (bincell), "last-path", g_strdup (path), g_free);
-       if (!bincell->priv->menu.popup) {
-               common_bin_create_menu (&(bincell->priv->menu), popup_position, bincell->priv->type,
+       if (!bincell->priv->menu.popover)
+               common_bin_create_menu (widget, &(bincell->priv->menu), bincell->priv->type,
                                        (BinCallback) bin_data_changed_cb, bincell);
-               g_object_set_data (G_OBJECT (bincell->priv->menu.popup), "__poswidget", widget);
-       }
        
        model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
        tpath = gtk_tree_path_new_from_string (path);
@@ -459,11 +422,9 @@ gdaui_data_cell_renderer_bin_activate  (GtkCellRenderer            *cell,
 
                gtk_tree_model_get (model, &iter, 
                                    model_col, &value, -1);
-               common_bin_adjust_menu (&(bincell->priv->menu), bincell->priv->editable,
-                                       value);
-               g_object_set_data (G_OBJECT (bincell->priv->menu.popup), "__event", event);
-               g_object_set_data (G_OBJECT (bincell->priv->menu.popup), "__rect", (GdkRectangle*)cell_area);
-               gtk_widget_show (bincell->priv->menu.popup);
+               common_bin_adjust (&(bincell->priv->menu), bincell->priv->editable,
+                                  value);
+               gtk_widget_show (bincell->priv->menu.popover);
        }
        gtk_tree_path_free (tpath);
 
diff --git a/libgda-ui/data-entries/gdaui-entry-bin.c b/libgda-ui/data-entries/gdaui-entry-bin.c
index 5cea961..62de305 100644
--- a/libgda-ui/data-entries/gdaui-entry-bin.c
+++ b/libgda-ui/data-entries/gdaui-entry-bin.c
@@ -39,24 +39,17 @@ static void       connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb
 static void       set_editable (GdauiEntryWrapper *mgwrap, gboolean editable);
 static void       grab_focus (GdauiEntryWrapper *mgwrap);
 
-static void       show (GtkWidget *widget);
-
 /* get a pointer to the parents to be able to call their destructor */
 static GObjectClass  *parent_class = NULL;
-static GdkPixbuf *attach_pixbuf = NULL;
 
 /* private structure */
 struct _GdauiEntryBinPrivate
 {
-       GtkWidget *button;
-       GtkWidget *button_hbox;
-       GtkWidget *button_label; /* ref held! */
-       GtkWidget *button_image; /* ref held! */
+       GtkWidget *label;
 
-       BinMenu    menu;
+       BinMenu    commonbin;
+       GtkWidget *entry_widget;
        gboolean   editable;
-
-       GValue    *current_data;
 };
 
 
@@ -100,45 +93,15 @@ gdaui_entry_bin_class_init (GdauiEntryBinClass *class)
        GDAUI_ENTRY_WRAPPER_CLASS (class)->connect_signals = connect_signals;
        GDAUI_ENTRY_WRAPPER_CLASS (class)->set_editable = set_editable;
        GDAUI_ENTRY_WRAPPER_CLASS (class)->grab_focus = grab_focus;
-
-       GTK_WIDGET_CLASS (class)->show = show;
-
-       if (! attach_pixbuf) {
-               #define ICON_FILE "/gdaui/images/data/bin-attachment-16x16.png"
-               attach_pixbuf = gdk_pixbuf_new_from_resource (ICON_FILE, NULL);
-               if (!attach_pixbuf)
-                       g_warning ("Could not find icon file %s in resources please report error to "
-                                  "http://bugzilla.gnome.org/ for the \"libgda\" product", ICON_FILE);
-       }
 }
 
 static void
 gdaui_entry_bin_init (GdauiEntryBin * gdaui_entry_bin)
 {
        gdaui_entry_bin->priv = g_new0 (GdauiEntryBinPrivate, 1);
-       gdaui_entry_bin->priv->button = NULL;
-       gdaui_entry_bin->priv->current_data = NULL;
+       gdaui_entry_bin->priv->label = NULL;
        gdaui_entry_bin->priv->editable = TRUE;
-}
-
-static void
-show (GtkWidget *widget)
-{
-       GValue *value;
-       GdauiEntryBin *dbin;
-
-       ((GtkWidgetClass *)parent_class)->show (widget);
-
-       dbin = GDAUI_ENTRY_BIN (widget);
-       value = dbin->priv->current_data;
-       if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
-               gtk_widget_show (dbin->priv->button_image);
-               gtk_widget_hide (dbin->priv->button_label);
-       }
-       else {
-               gtk_widget_hide (dbin->priv->button_image);
-               gtk_widget_show (dbin->priv->button_label);
-       }
+       common_bin_init (&(gdaui_entry_bin->priv->commonbin));
 }
 
 /**
@@ -176,23 +139,8 @@ gdaui_entry_bin_dispose (GObject   * object)
        g_return_if_fail (GDAUI_IS_ENTRY_BIN (object));
 
        gdaui_entry_bin = GDAUI_ENTRY_BIN (object);
-       if (gdaui_entry_bin->priv) {
-               if (gdaui_entry_bin->priv->current_data) {
-                       gda_value_free (gdaui_entry_bin->priv->current_data);
-                       gdaui_entry_bin->priv->current_data = NULL;
-               }
-               common_bin_reset (&(gdaui_entry_bin->priv->menu));
-
-               if (gdaui_entry_bin->priv->button_label) {
-                       g_object_unref (gdaui_entry_bin->priv->button_label);
-                       gdaui_entry_bin->priv->button_label = NULL;
-               }
-
-               if (gdaui_entry_bin->priv->button_image) {
-                       g_object_unref (gdaui_entry_bin->priv->button_image);
-                       gdaui_entry_bin->priv->button_image = NULL;
-               }
-       }
+       if (gdaui_entry_bin->priv)
+               common_bin_reset (&(gdaui_entry_bin->priv->commonbin));
 
        /* parent class */
        parent_class->dispose (object);
@@ -208,7 +156,6 @@ gdaui_entry_bin_finalize (GObject   * object)
 
        gdaui_entry_bin = GDAUI_ENTRY_BIN (object);
        if (gdaui_entry_bin->priv) {
-
                g_free (gdaui_entry_bin->priv);
                gdaui_entry_bin->priv = NULL;
        }
@@ -217,10 +164,42 @@ gdaui_entry_bin_finalize (GObject   * object)
        parent_class->finalize (object);
 }
 
+/*
+ * Steals @value
+ *
+ * WARNING:
+ * Does NOT emit any signal 
+ */
+static void
+take_as_current_value (GdauiEntryBin *dbin, GValue *value)
+{
+       common_bin_adjust (&(dbin->priv->commonbin), dbin->priv->editable, value);
+
+       gchar *str;
+       str = common_bin_get_description (&(dbin->priv->commonbin));
+       gchar *markup;
+       if (str) {
+               markup = g_markup_printf_escaped ("<a href=''>%s</a>", str);
+               g_free (str);
+       }
+       else
+               markup = g_markup_printf_escaped ("<a href=''><i>%s</i></a>", _("No data"));
+       gtk_label_set_markup (GTK_LABEL (dbin->priv->label), markup);
+       g_free (markup);
+}
+
+static void
+event_after_cb (GtkWidget *widget, GdkEvent *event, GdauiEntryBin *dbin)
+{
+       /* don't "forward" event if popover is shown */ 
+       if (!dbin->priv->commonbin.popover || !gtk_widget_is_visible (dbin->priv->commonbin.popover))
+               g_signal_emit_by_name (dbin->priv->entry_widget, "event-after", event);
+}
+
 static GtkWidget *
 create_entry (GdauiEntryWrapper *mgwrap)
 {
-       GtkWidget *button, *arrow, *label, *img;
+       GtkWidget *label;
        GdauiEntryBin *dbin;
        GtkWidget *hbox;
 
@@ -228,56 +207,21 @@ create_entry (GdauiEntryWrapper *mgwrap)
        dbin = GDAUI_ENTRY_BIN (mgwrap);
        g_return_val_if_fail (dbin->priv, NULL);
 
-       button = gtk_button_new ();
-       dbin->priv->button = button;
-
        hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-        gtk_container_add (GTK_CONTAINER (button), hbox);
-       dbin->priv->button_hbox = hbox;
+       dbin->priv->entry_widget = hbox;
 
        label = gtk_label_new ("");
-       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-       dbin->priv->button_label = g_object_ref (G_OBJECT (label));
-
-       img = gtk_image_new_from_pixbuf (attach_pixbuf);
-       gtk_box_pack_start (GTK_BOX (hbox), img, FALSE, FALSE, 0);
-       dbin->priv->button_image = g_object_ref (G_OBJECT (img));
-
-       arrow = gtk_image_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_MENU);
-       gtk_widget_set_halign (arrow, GTK_ALIGN_START);
-       gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
+       gtk_widget_set_halign (label, GTK_ALIGN_START);
+       gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+       gtk_widget_show (label);
+       dbin->priv->label = label;
 
-        gtk_widget_show_all (hbox);
-       gtk_widget_hide (dbin->priv->button_label);
-
-       return button;
-}
-
-/*
- * WARNING:
- * Does NOT emit any signal 
- */
-static void
-take_current_value (GdauiEntryBin *dbin, GValue *value)
-{
-       /* clear previous situation */
-       if (dbin->priv->current_data) {
-               gda_value_free (dbin->priv->current_data);
-               dbin->priv->current_data = NULL;
-       }
+       g_signal_connect (label, "event-after",
+                         G_CALLBACK (event_after_cb), dbin);
 
-       /* new situation */
-       dbin->priv->current_data = value;
-       if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
-               gtk_widget_show (dbin->priv->button_image);
-               gtk_widget_hide (dbin->priv->button_label);
-       }
-       else {
-               gtk_widget_hide (dbin->priv->button_image);
-               gtk_widget_show (dbin->priv->button_label);
-       }
+       take_as_current_value (dbin, NULL);
 
-       common_bin_adjust_menu (&(dbin->priv->menu), dbin->priv->editable, value);
+       return hbox;
 }
 
 static void
@@ -289,7 +233,7 @@ real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
        dbin = GDAUI_ENTRY_BIN (mgwrap);
        g_return_if_fail (dbin->priv);
 
-       take_current_value (dbin, value ? gda_value_copy (value) : NULL);
+       take_as_current_value (dbin, value ? gda_value_copy (value) : NULL);
 }
 
 static GValue *
@@ -301,8 +245,8 @@ real_get_value (GdauiEntryWrapper *mgwrap)
        dbin = GDAUI_ENTRY_BIN (mgwrap);
        g_return_val_if_fail (dbin->priv, NULL);
 
-       if (dbin->priv->current_data)
-               return gda_value_copy (dbin->priv->current_data);
+       if (dbin->priv->commonbin.tmpvalue)
+               return gda_value_copy (dbin->priv->commonbin.tmpvalue);
        else
                return gda_value_new_null ();
 }
@@ -311,7 +255,7 @@ real_get_value (GdauiEntryWrapper *mgwrap)
 static void
 value_loaded_cb (GdauiEntryBin *dbin, GValue *new_value)
 {
-       take_current_value (dbin, new_value);
+       take_as_current_value (dbin, new_value);
 
        /* signal changes */
        gdaui_entry_wrapper_contents_changed (GDAUI_ENTRY_WRAPPER (dbin));
@@ -319,41 +263,15 @@ value_loaded_cb (GdauiEntryBin *dbin, GValue *new_value)
 }
 
 static void
-popup_position (PopupContainer *container, gint *out_x, gint *out_y)
-{
-       GtkWidget *poswidget;
-       poswidget = g_object_get_data (G_OBJECT (container), "__poswidget");
-
-       gint x, y;
-        gdk_window_get_origin (gtk_widget_get_window (poswidget), &x, &y);
-       GtkAllocation alloc;
-       gtk_widget_get_allocation (poswidget, &alloc);
-        x += alloc.x;
-        y += alloc.y;
-        y += alloc.height;
-
-        if (x < 0)
-                x = 0;
-
-        if (y < 0)
-                y = 0;
-
-       *out_x = x;
-       *out_y = y;
-}
-
-static void
-button_clicked_cb (GtkWidget *button, GdauiEntryBin *dbin)
+link_activated_cb (GdauiEntryBin *dbin, const gchar *uri, GtkWidget *label)
 {
-       if (!dbin->priv->menu.popup) {
-               common_bin_create_menu (&(dbin->priv->menu), popup_position,
+       if (!dbin->priv->commonbin.popover)
+               common_bin_create_menu (GTK_WIDGET (label), &(dbin->priv->commonbin),
                                        gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (dbin)),
                                        (BinCallback) value_loaded_cb, dbin);
-               g_object_set_data (G_OBJECT (dbin->priv->menu.popup), "__poswidget", button);
-       }
 
-       common_bin_adjust_menu (&(dbin->priv->menu), dbin->priv->editable, dbin->priv->current_data);
-       gtk_widget_show (dbin->priv->menu.popup);
+       common_bin_adjust (&(dbin->priv->commonbin), dbin->priv->editable, dbin->priv->commonbin.tmpvalue);
+       gtk_widget_show (dbin->priv->commonbin.popover);
 }
 
 static void
@@ -366,8 +284,9 @@ connect_signals (GdauiEntryWrapper *mgwrap, G_GNUC_UNUSED GCallback modify_cb,
        dbin = GDAUI_ENTRY_BIN (mgwrap);
        g_return_if_fail (dbin->priv);
 
-       g_signal_connect (G_OBJECT (dbin->priv->button), "clicked",
-                         G_CALLBACK (button_clicked_cb), dbin);
+       g_assert (dbin->priv->label);
+       g_signal_connect_swapped (G_OBJECT (dbin->priv->label), "activate-link",
+                                 G_CALLBACK (link_activated_cb), dbin);
 }
 
 static void
@@ -380,7 +299,7 @@ set_editable (GdauiEntryWrapper *mgwrap, gboolean editable)
        g_return_if_fail (dbin->priv);
 
        dbin->priv->editable = editable;
-       common_bin_adjust_menu (&(dbin->priv->menu), editable, dbin->priv->current_data);
+       common_bin_adjust (&(dbin->priv->commonbin), editable, dbin->priv->commonbin.tmpvalue);
 }
 
 static void
@@ -392,5 +311,5 @@ grab_focus (GdauiEntryWrapper *mgwrap)
        dbin = GDAUI_ENTRY_BIN (mgwrap);
        g_return_if_fail (dbin->priv);
 
-       gtk_widget_grab_focus (dbin->priv->button);
+       gtk_widget_grab_focus (dbin->priv->label);
 }
diff --git a/libgda-ui/data-entries/gdaui-entry-boolean.c b/libgda-ui/data-entries/gdaui-entry-boolean.c
index a15df78..2dc2c99 100644
--- a/libgda-ui/data-entries/gdaui-entry-boolean.c
+++ b/libgda-ui/data-entries/gdaui-entry-boolean.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2012 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  *
@@ -43,8 +43,7 @@ static GObjectClass  *parent_class = NULL;
 /* private structure */
 struct _GdauiEntryBooleanPrivate
 {
-       GtkWidget *hbox;
-       GtkWidget *check;
+       GtkWidget *switchw;
 };
 
 
@@ -94,8 +93,7 @@ static void
 gdaui_entry_boolean_init (GdauiEntryBoolean * gdaui_entry_boolean)
 {
        gdaui_entry_boolean->priv = g_new0 (GdauiEntryBooleanPrivate, 1);
-       gdaui_entry_boolean->priv->hbox = NULL;
-       gdaui_entry_boolean->priv->check = NULL;
+       gdaui_entry_boolean->priv->switchw = NULL;
 }
 
 /**
@@ -160,25 +158,31 @@ gdaui_entry_boolean_finalize (GObject   * object)
        parent_class->finalize (object);
 }
 
+static void
+event_after_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       g_signal_emit_by_name (widget, "event-after", event);
+}
+
 static GtkWidget *
 create_entry (GdauiEntryWrapper *mgwrap)
 {
-       GtkWidget *hbox, *cb;
        GdauiEntryBoolean *mgbool;
 
        g_return_val_if_fail (GDAUI_IS_ENTRY_BOOLEAN (mgwrap), NULL);
        mgbool = GDAUI_ENTRY_BOOLEAN (mgwrap);
        g_return_val_if_fail (mgbool->priv, NULL);
 
-       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
-       mgbool->priv->hbox = hbox;
-
-       cb = gtk_check_button_new ();
-       mgbool->priv->check = cb;
-       gtk_box_pack_start (GTK_BOX (hbox), cb, FALSE, FALSE, 0);
-       gtk_widget_show (cb);
+       GtkWidget *wid, *box;
+       box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+       wid = gtk_switch_new ();
+       gtk_box_pack_start (GTK_BOX (box), wid, FALSE, FALSE, 0);
+       gtk_widget_show (wid);
+       mgbool->priv->switchw = wid;
+       g_signal_connect_swapped (wid, "event-after",
+                                 G_CALLBACK (event_after_cb), box);
 
-       return hbox;
+       return box;
 }
 
 static void
@@ -191,22 +195,13 @@ real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
        g_return_if_fail (mgbool->priv);
 
        if (value) {
-               if (gda_value_is_null ((GValue *) value)) {
-                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mgbool->priv->check), FALSE);
-                       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (mgbool->priv->check), TRUE);
-               }
-               else {
-                       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (mgbool->priv->check), FALSE);
-                       if (g_value_get_boolean ((GValue *) value)) 
-                               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mgbool->priv->check), TRUE);
-                       else 
-                               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mgbool->priv->check), FALSE);
-               }
-       }
-       else {
-               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mgbool->priv->check), FALSE);
-               gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (mgbool->priv->check), TRUE);
+               if (gda_value_is_null ((GValue *) value))
+                       gtk_switch_set_active (GTK_SWITCH (mgbool->priv->switchw), FALSE);
+               else
+                       gtk_switch_set_active (GTK_SWITCH (mgbool->priv->switchw), g_value_get_boolean 
((GValue *) value));
        }
+       else
+               gtk_switch_set_active (GTK_SWITCH (mgbool->priv->switchw), FALSE);
 }
 
 static GValue *
@@ -222,7 +217,7 @@ real_get_value (GdauiEntryWrapper *mgwrap)
        g_return_val_if_fail (mgbool->priv, NULL);
 
        dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
-       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mgbool->priv->check)))
+       if (gtk_switch_get_active (GTK_SWITCH (mgbool->priv->switchw)))
                str = "TRUE";
        else
                str = "FALSE";
@@ -231,7 +226,6 @@ real_get_value (GdauiEntryWrapper *mgwrap)
        return value;
 }
 
-static void check_toggled_cb (GtkToggleButton *toggle, GdauiEntryBoolean *mgbool);
 static void
 connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb)
 {
@@ -241,18 +235,10 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
        mgbool = GDAUI_ENTRY_BOOLEAN (mgwrap);
        g_return_if_fail (mgbool->priv);
 
-       g_signal_connect (G_OBJECT (mgbool->priv->check), "toggled",
-                         modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgbool->priv->check), "toggled",
-                         activate_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgbool->priv->check), "toggled",
-                          G_CALLBACK (check_toggled_cb), mgwrap);
-}
-
-static void
-check_toggled_cb (GtkToggleButton *toggle, G_GNUC_UNUSED GdauiEntryBoolean *mgbool)
-{
-       gtk_toggle_button_set_inconsistent (toggle, FALSE);
+       g_signal_connect_swapped (G_OBJECT (mgbool->priv->switchw), "notify::active",
+                                 modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgbool->priv->switchw), "notify::active",
+                                 activate_cb, mgwrap);
 }
 
 static void
@@ -264,7 +250,7 @@ set_editable (GdauiEntryWrapper *mgwrap, gboolean editable)
        mgbool = GDAUI_ENTRY_BOOLEAN (mgwrap);
        g_return_if_fail (mgbool->priv);
 
-       gtk_widget_set_sensitive (mgbool->priv->check, editable);
+       gtk_widget_set_sensitive (mgbool->priv->switchw, editable);
 }
 
 static void
@@ -276,5 +262,5 @@ grab_focus (GdauiEntryWrapper *mgwrap)
        mgbool = GDAUI_ENTRY_BOOLEAN (mgwrap);
        g_return_if_fail (mgbool->priv);
 
-       gtk_widget_grab_focus (mgbool->priv->check);
+       gtk_widget_grab_focus (mgbool->priv->switchw);
 }
diff --git a/libgda-ui/data-entries/gdaui-entry-combo.c b/libgda-ui/data-entries/gdaui-entry-combo.c
index 309eceb..b2bcfd1 100644
--- a/libgda-ui/data-entries/gdaui-entry-combo.c
+++ b/libgda-ui/data-entries/gdaui-entry-combo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2013 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  * Copyright (C) 2013 Daniel Espinosa <esodan gmail com>
@@ -91,10 +91,10 @@ struct  _GdauiEntryComboPriv {
        gboolean                data_valid;
        gboolean                null_forced;
        gboolean                default_forced;
+       gboolean                invalid;
        gboolean                null_possible;
        gboolean                default_possible;
-       
-       gboolean                show_actions;
+
        gboolean                set_default_if_invalid; /* use first entry when provided value is not found ? 
*/
 };
 
@@ -185,13 +185,7 @@ real_combo_unblock_signals (GdauiEntryCombo *wid)
 static void
 gdaui_entry_combo_emit_signal (GdauiEntryCombo *combo)
 {
-#ifdef debug_signal
-       g_print (">> 'CONTENTS_MODIFIED' from %s\n", __FUNCTION__);
-#endif
        g_signal_emit_by_name (G_OBJECT (combo), "contents-modified");
-#ifdef debug_signal
-       g_print ("<< 'CONTENTS_MODIFIED' from %s\n", __FUNCTION__);
-#endif
 }
 
 static void
@@ -203,11 +197,11 @@ gdaui_entry_combo_init (GdauiEntryCombo *combo)
        combo->priv->set_default_if_invalid = FALSE;
        combo->priv->combo_entry = NULL;
        combo->priv->data_valid = FALSE;
+       combo->priv->invalid = FALSE;
        combo->priv->null_forced = FALSE;
        combo->priv->default_forced = FALSE;
        combo->priv->null_possible = TRUE;
        combo->priv->default_possible = FALSE;
-       combo->priv->show_actions = TRUE;
 
        combo->priv->paramlist = NULL;
        combo->priv->source = NULL;
@@ -909,22 +903,11 @@ gdaui_entry_combo_set_attributes (GdauiDataEntry *iface, guint attrs, guint mask
                }
        }
 
-       /* Actions buttons ? */
-       if (mask & GDA_VALUE_ATTR_ACTIONS_SHOWN) {
-               GValue *gval;
-               combo->priv->show_actions = (attrs & GDA_VALUE_ATTR_ACTIONS_SHOWN) ? TRUE : FALSE;
-               
-               gval = g_new0 (GValue, 1);
-               g_value_init (gval, G_TYPE_BOOLEAN);
-               g_value_set_boolean (gval, combo->priv->show_actions);
-               g_object_set_property (G_OBJECT (combo), "actions", gval);
-               g_free (gval);
-       }
+       /* invalid data */
+       if (mask & GDA_VALUE_ATTR_DATA_NON_VALID)
+               combo->priv->invalid = attrs & GDA_VALUE_ATTR_DATA_NON_VALID;
 
        /* NON WRITABLE attributes */
-       if (mask & GDA_VALUE_ATTR_DATA_NON_VALID) 
-               g_warning ("Can't force a GdauiDataEntry to be invalid!");
-
        if (mask & GDA_VALUE_ATTR_HAS_VALUE_ORIG)
                g_warning ("Having an original value is not a write attribute on GdauiDataEntry!");
 
@@ -980,31 +963,26 @@ gdaui_entry_combo_get_attributes (GdauiDataEntry *iface)
        }
 
        if (isunchanged)
-               retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
+               retval |= GDA_VALUE_ATTR_IS_UNCHANGED;
 
        if (isnull || combo->priv->null_forced)
-               retval = retval | GDA_VALUE_ATTR_IS_NULL;
+               retval |= GDA_VALUE_ATTR_IS_NULL;
 
        /* can be NULL? */
        if (combo->priv->null_possible) 
-               retval = retval | GDA_VALUE_ATTR_CAN_BE_NULL;
+               retval |= GDA_VALUE_ATTR_CAN_BE_NULL;
        
        /* is default */
        if (combo->priv->default_forced)
-               retval = retval | GDA_VALUE_ATTR_IS_DEFAULT;
+               retval |= GDA_VALUE_ATTR_IS_DEFAULT;
        
        /* can be default? */
        if (combo->priv->default_possible)
-               retval = retval | GDA_VALUE_ATTR_CAN_BE_DEFAULT;
+               retval |= GDA_VALUE_ATTR_CAN_BE_DEFAULT;
        
-
-       /* actions shown */
-       if (combo->priv->show_actions)
-               retval = retval | GDA_VALUE_ATTR_ACTIONS_SHOWN;
-
        /* data valid? */
-       if (! combo->priv->data_valid)
-               retval = retval | GDA_VALUE_ATTR_DATA_NON_VALID;
+       if ((! combo->priv->data_valid) || combo->priv->invalid)
+               retval |= GDA_VALUE_ATTR_DATA_NON_VALID;
        else {
                GSList *nodes;
                gboolean allnull = TRUE;
@@ -1021,13 +999,13 @@ gdaui_entry_combo_get_attributes (GdauiDataEntry *iface)
 
                if ((allnull && !combo->priv->null_possible) ||
                    (combo->priv->null_forced && !combo->priv->null_possible))
-                       retval = retval | GDA_VALUE_ATTR_DATA_NON_VALID;
+                       retval |= GDA_VALUE_ATTR_DATA_NON_VALID;
        }
 
        /* has original value? */
        list2 = gdaui_entry_combo_get_reference_values (combo);
        if (list2) {
-               retval = retval | GDA_VALUE_ATTR_HAS_VALUE_ORIG;
+               retval |= GDA_VALUE_ATTR_HAS_VALUE_ORIG;
                g_slist_free (list2);
        }
 
@@ -1051,5 +1029,5 @@ static void
 gdaui_entry_combo_set_unknown_color (GdauiDataEntry *de, gdouble red, gdouble green,
                                     gdouble blue, gdouble alpha)
 {
-       gdaui_entry_shell_set_ucolor (GDAUI_ENTRY_SHELL (de), red, green, blue, alpha);
+       gdaui_entry_shell_set_invalid_color (GDAUI_ENTRY_SHELL (de), red, green, blue, alpha);
 }
diff --git a/libgda-ui/data-entries/gdaui-entry-common-time.c 
b/libgda-ui/data-entries/gdaui-entry-common-time.c
index 90306b2..6a35ab7 100644
--- a/libgda-ui/data-entries/gdaui-entry-common-time.c
+++ b/libgda-ui/data-entries/gdaui-entry-common-time.c
@@ -25,9 +25,15 @@
 #include <gdk/gdkkeysyms.h>
 #include <string.h>
 #include "gdaui-formatted-entry.h"
+#include "gdaui-numeric-entry.h"
 #include <libgda/gda-debug-macros.h>
 
-/* 
+/*
+ * REM:
+ * Times are displayed relative to localtime
+ */
+
+/*
  * Main static functions 
  */
 static void gdaui_entry_common_time_class_init (GdauiEntryCommonTimeClass * class);
@@ -71,21 +77,14 @@ static GObjectClass  *parent_class = NULL;
 /* private structure */
 struct _GdauiEntryCommonTimePrivate
 {
-       /* for date */
-       GtkWidget *entry_date;
-       GtkWidget *date;
-        GtkWidget *window;
-        GtkWidget *date_button;
-       gboolean   editing_canceled;
-
-       /* for time */
-       GtkWidget *entry_time;
-
-       /* for timestamp */
-       GtkWidget *hbox;
+       GtkWidget *entry;
+       GtkWidget *cal_popover;
+       GtkWidget *calendar;
+       gulong     displayed_tz;
+       gulong     value_tz;
+       gulong     value_fraction;
 
-       /* Last value set */
-       GValue    *last_value_set;
+       gboolean   editing_canceled;
 };
 
 static void
@@ -162,19 +161,82 @@ key_press_event_cb (GdauiEntryCommonTime *mgtim, GdkEventKey *key_event, G_GNUC_
        return FALSE;
 }
 
+static glong
+compute_tz_offset (struct tm *gmttm, struct tm *loctm)
+{
+        if (! gmttm || !loctm)
+                return G_MAXLONG;
+
+        struct tm cgmttm, cloctm;
+        cgmttm = *gmttm;
+        cloctm = *loctm;
+
+        time_t lt, gt;
+        cgmttm.tm_isdst = 0;
+        cloctm.tm_isdst = 0;
+
+        lt = mktime (&cloctm);
+        if (lt == -1)
+                return G_MAXLONG;
+        gt = mktime (&cgmttm);
+        if (gt == -1)
+                return G_MAXLONG;
+        glong off;
+        off = lt - gt;
+
+        if ((off >= 24 * 3600) || (off <= - 24 * 3600))
+                return G_MAXLONG;
+        else
+                return off;
+}
+
+static gulong
+compute_localtime_tz (void)
+{
+       time_t val;
+       val = time (NULL);
+       glong tz = 0;
+
+#ifdef HAVE_LOCALTIME_R
+        struct tm gmttm, loctm;
+        tzset ();
+       localtime_r ((const time_t *) &val, &loctm);
+        tz = compute_tz_offset (gmtime_r ((const time_t *) &val, &gmttm), &loctm);
+#elif HAVE_LOCALTIME_S
+        struct tm gmttm, loctm;
+        if ((localtime_s (&loctm, (const time_t *) &val) == 0) &&
+            (gmtime_s (&gmttm, (const time_t *) &val) == 0)) {
+                tz = compute_tz_offset (&gmttm, &loctm);
+        }
+#else
+        struct tm gmttm, loctm;
+       struct tm *ltm;
+        ltm = gmtime ((const time_t *) &val);
+        if (ltm) {
+                gmttm = *ltm;
+                ltm = localtime ((const time_t *) &val);
+                if (ltm) {
+                        loctm = *ltm;
+                        tz = compute_tz_offset (&gmttm, &loctm);
+                }
+        }
+#endif
+       if (tz == G_MAXLONG)
+               tz = 0;
+       return tz;
+}
+
 static void
-gdaui_entry_common_time_init (GdauiEntryCommonTime *gdaui_entry_common_time)
+gdaui_entry_common_time_init (GdauiEntryCommonTime *mgtim)
 {
-       gdaui_entry_common_time->priv = g_new0 (GdauiEntryCommonTimePrivate, 1);
-       gdaui_entry_common_time->priv->entry_date = NULL;
-       gdaui_entry_common_time->priv->entry_time = NULL;
-       gdaui_entry_common_time->priv->date = NULL;
-       gdaui_entry_common_time->priv->window = NULL;
-       gdaui_entry_common_time->priv->date_button = NULL;
-       gdaui_entry_common_time->priv->hbox = NULL;
-       gdaui_entry_common_time->priv->last_value_set = NULL;
-       gdaui_entry_common_time->priv->editing_canceled = FALSE;
-       g_signal_connect (gdaui_entry_common_time, "key-press-event",
+       mgtim->priv = g_new0 (GdauiEntryCommonTimePrivate, 1);
+       mgtim->priv->entry = NULL;
+       mgtim->priv->calendar = NULL;
+       mgtim->priv->editing_canceled = FALSE;
+       mgtim->priv->value_tz = 0; /* safe init value */
+       mgtim->priv->value_fraction = 0; /* safe init value */
+       mgtim->priv->displayed_tz = compute_localtime_tz ();
+       g_signal_connect (mgtim, "key-press-event",
                          G_CALLBACK (key_press_event_cb), NULL);
 }
 
@@ -214,10 +276,6 @@ gdaui_entry_common_time_dispose (GObject   * object)
 
        gdaui_entry_common_time = GDAUI_ENTRY_COMMON_TIME (object);
        if (gdaui_entry_common_time->priv) {
-               if (gdaui_entry_common_time->priv->window) {
-                       gtk_widget_destroy (gdaui_entry_common_time->priv->window);
-                       gdaui_entry_common_time->priv->window = NULL;
-               }
        }
 
        /* parent class */
@@ -234,9 +292,6 @@ gdaui_entry_common_time_finalize (GObject   * object)
 
        gdaui_entry_common_time = GDAUI_ENTRY_COMMON_TIME (object);
        if (gdaui_entry_common_time->priv) {
-               if (gdaui_entry_common_time->priv->last_value_set) 
-                       gda_value_free (gdaui_entry_common_time->priv->last_value_set);
-
                g_free (gdaui_entry_common_time->priv);
                gdaui_entry_common_time->priv = NULL;
        }
@@ -293,33 +348,278 @@ gdaui_entry_common_time_get_property (GObject *object,
        }
 }
 
-static GtkWidget *create_entry_date (GdauiEntryCommonTime *mgtim);
-static GtkWidget *create_entry_time (GdauiEntryCommonTime *mgtim);
-static GtkWidget *create_entry_ts (GdauiEntryCommonTime *mgtim);
+static void date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
+static void date_day_selected_double_click (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
+
+static void
+icon_press_cb (GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEvent *event, GdauiEntryCommonTime *mgtim)
+{
+       if (icon_pos == GTK_ENTRY_ICON_PRIMARY) {
+               if (! mgtim->priv->cal_popover) {
+                       /* calendar */
+                       GtkWidget *wid;
+                       wid = gtk_calendar_new ();
+                       mgtim->priv->calendar = wid;
+                       gtk_widget_show (wid);
+                       g_signal_connect (G_OBJECT (wid), "day-selected",
+                                         G_CALLBACK (date_day_selected), mgtim);
+                       g_signal_connect (G_OBJECT (wid), "day-selected-double-click",
+                                         G_CALLBACK (date_day_selected_double_click), mgtim);
+
+                       /* popover */
+                       GtkWidget *popover;
+                       popover = gtk_popover_new (mgtim->priv->entry);
+                       gtk_container_add (GTK_CONTAINER (popover), mgtim->priv->calendar);
+                       mgtim->priv->cal_popover = popover;
+               }
+
+               /* set calendar to current value */
+               GValue *value;
+               guint year=0, month=0, day=0;
+               gboolean unset = TRUE;
+
+               /* setting the calendar to the displayed date */
+               value = gdaui_data_entry_get_value (GDAUI_DATA_ENTRY (mgtim));
+
+               if (value && !gda_value_is_null (value)) {
+                       GType type;
+                       type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
+                       if (type == G_TYPE_DATE) {
+                               const GDate *date;
+                               date = (GDate*) g_value_get_boxed (value);
+                               if (date) {
+                                       month = g_date_get_month (date);
+                                       year = g_date_get_year (date);
+                                       day = g_date_get_day (date);
+                                       if ((month != G_DATE_BAD_MONTH) && 
+                                           (day != G_DATE_BAD_DAY) &&
+                                           (year != G_DATE_BAD_YEAR)) {
+                                               month -= 1;
+                                               unset = FALSE;
+                                       }
+                               }
+                       }
+                       else if (type == GDA_TYPE_TIMESTAMP) {
+                               const GdaTimestamp *ts;
+                               ts = gda_value_get_timestamp (value);
+                               if (ts) {
+                                       year = ts->year;
+                                       month = ts->month - 1;
+                                       day = ts->day;
+                                       unset = FALSE;
+                               }
+                       }
+                       else
+                               g_assert_not_reached ();
+               }
+
+               if (unset) {
+                       time_t now;
+                       struct tm *stm;
+
+                       now = time (NULL);
+#ifdef HAVE_LOCALTIME_R
+                       struct tm tmpstm;
+                       stm = localtime_r (&now, &tmpstm);
+#elif HAVE_LOCALTIME_S
+                       struct tm tmpstm;
+                       g_assert (localtime_s (&tmpstm, &now) == 0);
+                       stm = &tmpstm;
+#else
+                       stm = localtime (&now);
+#endif
+                       year = stm->tm_year + 1900;
+                       month = stm->tm_mon;
+                       day = stm->tm_mday;
+               }
+
+               if (! unset) {
+                       g_signal_handlers_block_by_func (G_OBJECT (mgtim->priv->calendar),
+                                                        G_CALLBACK (date_day_selected), mgtim);
+                       g_signal_handlers_block_by_func (G_OBJECT (mgtim->priv->calendar),
+                                                        G_CALLBACK (date_day_selected_double_click), mgtim);
+               }
+               gtk_calendar_select_month (GTK_CALENDAR (mgtim->priv->calendar), month, year);
+               gtk_calendar_select_day (GTK_CALENDAR (mgtim->priv->calendar), day);
+               if (! unset) {
+                       g_signal_handlers_unblock_by_func (G_OBJECT (mgtim->priv->calendar),
+                                                          G_CALLBACK (date_day_selected), mgtim);
+                       g_signal_handlers_unblock_by_func (G_OBJECT (mgtim->priv->calendar),
+                                                          G_CALLBACK (date_day_selected_double_click), 
mgtim);
+               }
+
+               gtk_widget_show (mgtim->priv->cal_popover);
+       }
+}
+
+static void
+date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim)
+{
+       char buffer [256];
+        guint year, month, day;
+        struct tm mtm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+       GType type;
+       type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
+
+        gtk_calendar_get_date (calendar, &year, &month, &day);
+
+        mtm.tm_mday = day;
+        mtm.tm_mon = month;
+        if (year > 1900)
+                mtm.tm_year = year - 1900;
+        else
+                mtm.tm_year = year;
+
+       if (type == GDA_TYPE_TIMESTAMP) {
+               /* get the time part back from current value */
+               GValue *value = NULL;
+               gchar *tmpstr;
+               GdaDataHandler *dh;
+               dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgtim));
+               tmpstr = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry));
+               if (tmpstr) {
+                       value = gda_data_handler_get_value_from_str (dh, tmpstr, type);
+                       g_free (tmpstr);
+               }
+
+               if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
+                       /* copy the 'fraction' and 'timezone' parts, we have not modified */
+                       const GdaTimestamp *ets = gda_value_get_timestamp (value);
+                       mtm.tm_hour = ets->hour;
+                       mtm.tm_min = ets->minute;
+                       mtm.tm_sec = ets->second;
+               }
+               gda_value_free (value);
+       }
+
+       guint bufsize;
+       bufsize = sizeof (buffer) / sizeof (char);
+       if (strftime (buffer, bufsize, "%x", &mtm) == 0)
+               buffer [0] = 0;
+       else if (type == GDA_TYPE_TIMESTAMP) {
+               char buffer2 [128];
+               if (strftime (buffer2, bufsize, "%X", &mtm) == 0)
+                       buffer [0] = 0;
+               else {
+                       gchar *tmp;
+                       tmp = g_strdup_printf ("%s %s", buffer, buffer2);
+                       if (strlen (tmp) < bufsize)
+                               strcpy (buffer, tmp);
+                       else
+                               buffer [0] = 0;
+                       g_free (tmp);
+               }
+       }
+
+       g_print ("BUFFER:[%s]\n", buffer);
+
+       if (buffer [0]) {
+               char *str_utf8;
+               str_utf8 = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
+               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), str_utf8);
+               g_free (str_utf8);
+       }
+       else
+               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), "");
+}
+
+static void
+date_day_selected_double_click (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim)
+{
+       gtk_widget_hide (mgtim->priv->cal_popover);
+}
+
+static glong
+fit_tz (glong tz)
+{
+       tz = tz % 86400;
+       if (tz > 43200)
+               tz -= 86400;
+       else if (tz < -43200)
+               tz += 86400;
+       return tz;
+}
+
+static void entry_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, gpointer 
data);
+
+static void
+event_after_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+       g_signal_emit_by_name (widget, "event-after", event);
+}
+
 static GtkWidget *
 create_entry (GdauiEntryWrapper *mgwrap)
 {
        GdauiEntryCommonTime *mgtim;
-       GtkWidget *entry = NULL;
-       GType type;
-
-       g_return_val_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap), NULL);
+       g_return_val_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (mgwrap), NULL);
        mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
-       g_return_val_if_fail (mgtim->priv, NULL);
 
+       GtkWidget *wid, *hb;
+       GdaDataHandler *dh;
+       GType type;
        type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
-       if (type == G_TYPE_DATE)
-               entry = create_entry_date (mgtim);
-       else if (type == GDA_TYPE_TIME)
-               entry = create_entry_time (mgtim);
-       else if (type == GDA_TYPE_TIMESTAMP)
-               entry = create_entry_ts (mgtim);
+       
+       /* top widget */
+       hb = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
+
+       /* text entry */
+       dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgtim));
+       if (GDA_IS_HANDLER_TIME (dh)) {
+               gchar *str, *mask, *ptr;
+               str = gda_handler_time_get_format (GDA_HANDLER_TIME (dh), type);
+               mask = g_strdup (str);
+               for (ptr = mask; *ptr; ptr++) {
+                       if (*ptr == '0')
+                               *ptr = '-';
+               }
+               wid = gdaui_formatted_entry_new (str, mask);
+               gdaui_entry_set_suffix (GDAUI_ENTRY (wid), "");
+               g_free (str);
+               g_free (mask);
+
+               gchar *tmp;
+               gulong tz;
+               tz = mgtim->priv->displayed_tz;
+               if (tz == 0)
+                       tmp = g_strdup ("GMT");
+               else if ((tz % 3600) == 0)
+                       tmp = g_strdup_printf ("GMT %+03d", (gint) tz / 3600);
+               else if ((tz % 60) == 0)
+                       tmp = g_strdup_printf ("GMT %+02d min", (gint) tz / 60);
+               else
+                       tmp = g_strdup_printf ("GMT %+02d sec", (gint) tz);
+
+               gchar *hint;
+               gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_insert_func, mgtim);
+               str = gda_handler_time_get_hint (GDA_HANDLER_TIME (dh), type);
+               hint = g_strdup_printf (_("Expected format is %s\nTime is relative to local time (%s)"), str, 
tmp);
+               g_free (str);
+               g_free (tmp);
+               gtk_widget_set_tooltip_text (wid, hint);
+               g_free (hint);
+       }
        else
-               g_assert_not_reached ();
-               
-       return entry;
+               wid = gdaui_entry_new (NULL, NULL);
+       gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
+       gtk_widget_show (wid);
+       mgtim->priv->entry = wid;
+       g_signal_connect_swapped (wid, "event-after",
+                                 G_CALLBACK (event_after_cb), hb);
+
+       if ((type == G_TYPE_DATE) || (type == GDA_TYPE_TIMESTAMP))
+               gtk_entry_set_icon_from_icon_name (GTK_ENTRY (wid),
+                                                  GTK_ENTRY_ICON_PRIMARY, "x-office-calendar-symbolic");
+
+       g_signal_connect (wid, "icon-press",
+                         G_CALLBACK (icon_press_cb), mgtim);
+
+       return hb;
 }
 
+/*
+ * NB: the displayed value is relative to mgtim->priv->displayed_tz
+ */
 static void
 real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
 {
@@ -327,7 +627,7 @@ real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
        GType type;
        GdaDataHandler *dh;
 
-       g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
+       g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
        mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
        g_return_if_fail (mgtim->priv);
 
@@ -337,65 +637,84 @@ real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value)
        if (type == G_TYPE_DATE) {
                if (value) {
                        if (gda_value_is_null ((GValue *) value))
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
+                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), NULL);
                        else {
                                gchar *str;
                                
                                str = gda_data_handler_get_str_from_value (dh, value);
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), str);
+                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), str);
                                g_free (str);
                        }
                }
                else 
-                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
+                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), NULL);
        }
        else if (type == GDA_TYPE_TIME) {
                if (value) {
-                       if (gda_value_is_null ((GValue *) value))
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
+                       if (gda_value_is_null ((GValue *) value)) {
+                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), NULL);
+                               mgtim->priv->value_tz = mgtim->priv->displayed_tz;
+                               mgtim->priv->value_fraction = 0;
+                       }
                        else {
+                               const GdaTime *gtim;
+                               GdaTime copy;
+                               gtim = gda_value_get_time (value);
+                               mgtim->priv->value_tz = fit_tz (gtim->timezone);
+                               mgtim->priv->value_fraction = gtim->fraction;
+
+                               copy = *gtim;
+                               gda_time_change_timezone (&copy, mgtim->priv->displayed_tz);
+
+                               GValue *copy_value;
+                               copy_value = g_new0 (GValue, 1);
+                               gda_value_set_time (copy_value, &copy);
+
                                gchar *str;
-                               
-                               str = gda_data_handler_get_str_from_value (dh, value);
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), str);
+                               str = gda_data_handler_get_str_from_value (dh, copy_value);
+                               gda_value_free (copy_value);
+
+                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), str);
                                g_free (str);
                        }
                }
                else 
-                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
+                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), NULL);
        }
        else if (type == GDA_TYPE_TIMESTAMP) {
                if (value) {
                        if (gda_value_is_null ((GValue *) value)) {
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
+                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), NULL);
+                               mgtim->priv->value_tz = mgtim->priv->displayed_tz;
+                               mgtim->priv->value_fraction = 0;
                        }
                        else {
-                               gchar *str, *ptr;
-                               
-                               str = gda_data_handler_get_str_from_value (dh, value);
-                               ptr = strtok (str, " ");
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), ptr);
-                               ptr = strtok (NULL, " ");
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), ptr);
+                               const GdaTimestamp *gts;
+                               GdaTimestamp copy;
+                               gts = gda_value_get_timestamp (value);
+                               mgtim->priv->value_tz = fit_tz (gts->timezone);
+                               mgtim->priv->value_fraction = gts->fraction;
+
+                               copy = *gts;
+                               gda_timestamp_change_timezone (&copy, mgtim->priv->displayed_tz);
+
+                               GValue *copy_value;
+                               copy_value = g_new0 (GValue, 1);
+                               gda_value_set_timestamp (copy_value, &copy);
+
+                               gchar *str;
+                               str = gda_data_handler_get_str_from_value (dh, copy_value);
+                               gda_value_free (copy_value);
+
+                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), str);
                                g_free (str);
                        }
                }
-               else {
-                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), NULL);
-                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), NULL);
-               }
+               else
+                       gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), NULL);
        }
        else
                g_assert_not_reached ();
-
-       /* keep track of the last value set */
-       if (mgtim->priv->last_value_set) {
-               gda_value_free (mgtim->priv->last_value_set);
-               mgtim->priv->last_value_set = NULL;
-       }
-       if (value)
-               mgtim->priv->last_value_set = gda_value_copy ((GValue *) value);
 }
 
 static GValue *
@@ -415,52 +734,44 @@ real_get_value (GdauiEntryWrapper *mgwrap)
        dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap));
 
        if (type == G_TYPE_DATE) {
-               str2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_date));
+               str2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry));
                if (str2) {
                        value = gda_data_handler_get_value_from_str (dh, str2, type);
                        g_free (str2);
                }
        }
        else if (type == GDA_TYPE_TIME) {
-               str2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_time));
+               str2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry));
                if (str2) {
                        value = gda_data_handler_get_value_from_str (dh, str2, type);
                        g_free (str2);
                }
 
-               if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL) &&
-                   mgtim->priv->last_value_set && 
-                   gda_value_isa (mgtim->priv->last_value_set, GDA_TYPE_TIME)) {
-                       /* copy the 'timezone' part, we we have not modified */
-                       const GdaTime *dgatime_set = gda_value_get_time (mgtim->priv->last_value_set);
+               if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
                        GdaTime *gdatime = g_new (GdaTime, 1);
                        *gdatime = *(gda_value_get_time (value));
-                       gdatime->timezone = dgatime_set->timezone;
+                       gdatime->timezone = mgtim->priv->displayed_tz;
+                       gda_time_change_timezone (gdatime, mgtim->priv->value_tz);
                        gda_value_set_time (value, gdatime);
                        g_free (gdatime);
                }
        }
        else if (type == GDA_TYPE_TIMESTAMP) {
-               gchar *tmpstr, *tmpstr2;
+               gchar *tmpstr;
 
-               tmpstr = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_time));
-               tmpstr2 = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry_date));
-               if (tmpstr && tmpstr2) {
-                       str2 = g_strdup_printf ("%s %s", tmpstr2, tmpstr);
-                       value = gda_data_handler_get_value_from_str (dh, str2, type);
-                       g_free (str2);
+               tmpstr = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry));
+               if (tmpstr) {
+                       value = gda_data_handler_get_value_from_str (dh, tmpstr, type);
+                       g_free (tmpstr);
                }
-               g_free (tmpstr);
-               g_free (tmpstr2);
-               if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL) &&
-                   mgtim->priv->last_value_set && 
-                   gda_value_isa (mgtim->priv->last_value_set, GDA_TYPE_TIMESTAMP)) {
-                       /* copy the 'fraction' and 'timezone' parts, we have not modified */
-                       const GdaTimestamp *dgatime_set = gda_value_get_timestamp 
(mgtim->priv->last_value_set);
+
+               if (value && (G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
+                       /* copy the 'fraction' part, we have not modified */
                        GdaTimestamp *gdatime = g_new (GdaTimestamp, 1);
                        *gdatime = *(gda_value_get_timestamp (value));
-                       gdatime->fraction = dgatime_set->fraction;
-                       gdatime->timezone = dgatime_set->timezone;
+                       gdatime->fraction = mgtim->priv->value_fraction;
+                       gdatime->timezone = mgtim->priv->displayed_tz;
+                       gda_timestamp_change_timezone (gdatime, mgtim->priv->value_tz);
                        gda_value_set_timestamp (value, gdatime);
                        g_free (gdatime);
                }
@@ -481,27 +792,13 @@ static void
 connect_signals (GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activate_cb)
 {
        GdauiEntryCommonTime *mgtim;
-       GType type;
-
-       g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
+       g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
        mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
-       g_return_if_fail (mgtim->priv);
-
-       type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
 
-       if ((type == G_TYPE_DATE) || (type == GDA_TYPE_TIMESTAMP)) {
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "changed",
+       g_signal_connect_swapped (G_OBJECT (mgtim->priv->entry), "changed",
                                  modify_cb, mgwrap);
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "activate",
+       g_signal_connect_swapped (G_OBJECT (mgtim->priv->entry), "activate",
                                  activate_cb, mgwrap);
-       }
-
-       if ((type == GDA_TYPE_TIME) || (type == GDA_TYPE_TIMESTAMP)) {
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "changed",
-                                 modify_cb, mgwrap);
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "activate",
-                                 activate_cb, mgwrap);
-       }
 }
 
 static void
@@ -509,16 +806,14 @@ set_editable (GdauiEntryWrapper *mgwrap, gboolean editable)
 {
        GdauiEntryCommonTime *mgtim;
 
-       g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
+       g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
        mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
-       g_return_if_fail (mgtim->priv);
 
-       if (mgtim->priv->entry_date)
-               gtk_editable_set_editable (GTK_EDITABLE (mgtim->priv->entry_date), editable);
-       if (mgtim->priv->entry_time)
-               gtk_editable_set_editable (GTK_EDITABLE (mgtim->priv->entry_time), editable);
-       if (mgtim->priv->date_button)
-               gtk_widget_set_sensitive (mgtim->priv->date_button, editable);
+       if (mgtim->priv->entry)
+               gtk_editable_set_editable (GTK_EDITABLE (mgtim->priv->entry), editable);
+
+       gtk_entry_set_icon_sensitive (GTK_ENTRY (mgtim->priv->entry), GTK_ENTRY_ICON_PRIMARY, editable);
+       gtk_entry_set_icon_sensitive (GTK_ENTRY (mgtim->priv->entry), GTK_ENTRY_ICON_SECONDARY, editable);
 }
 
 static void
@@ -526,105 +821,15 @@ grab_focus (GdauiEntryWrapper *mgwrap)
 {
        GdauiEntryCommonTime *mgtim;
 
-       g_return_if_fail (mgwrap && GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
+       g_return_if_fail (GDAUI_IS_ENTRY_COMMON_TIME (mgwrap));
        mgtim = GDAUI_ENTRY_COMMON_TIME (mgwrap);
-       g_return_if_fail (mgtim->priv);
-
-       if (mgtim->priv->entry_date)
-               gtk_widget_grab_focus (mgtim->priv->entry_date);
-       if (mgtim->priv->entry_time)
-               gtk_widget_grab_focus (mgtim->priv->entry_time);
-}
-
-
-
-/*
- * callbacks for the date 
- */
-static gint date_delete_popup (GtkWidget *widget, GdauiEntryCommonTime *mgtim);
-static gint date_key_press_popup (GtkWidget *widget, GdkEventKey *event, GdauiEntryCommonTime *mgtim);
-static gint date_button_press_popup (GtkWidget *widget, GdkEventButton *event, GdauiEntryCommonTime *mgtim);
-static void date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
-static void date_day_selected_double_click (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim);
-static void date_calendar_choose_cb (GtkWidget *button, GdauiEntryCommonTime *mgtim);
-
-static void entry_date_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, 
gpointer data);
-
-static GtkWidget *
-create_entry_date (GdauiEntryCommonTime *mgtim)
-{
-       GtkWidget *wid, *hb, *window, *arrow;
-       GdaDataHandler *dh;
-
-       /* top widget */
-       hb = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
-
-       /* text entry */
-       dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgtim));
-       if (GDA_IS_HANDLER_TIME (dh)) {
-               gchar *str, *mask, *ptr;
-               str = gda_handler_time_get_format (GDA_HANDLER_TIME (dh), G_TYPE_DATE);
-               mask = g_strdup (str);
-               for (ptr = mask; *ptr; ptr++) {
-                       if (*ptr == '0')
-                               *ptr = '-';
-               }
-               wid = gdaui_formatted_entry_new (str, mask);
-               g_free (str);
-               g_free (mask);
 
-               gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_date_insert_func,
-                                                      mgtim);
-       }
-       else
-               wid = gdaui_entry_new (NULL, NULL);
-       gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
-       gtk_widget_show (wid);
-       mgtim->priv->entry_date = wid;
-       
-       /* window to hold the calendar popup */
-       window = gtk_window_new (GTK_WINDOW_POPUP);
-       gtk_widget_set_events (window, gtk_widget_get_events (window) | GDK_KEY_PRESS_MASK);
-       gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
-       g_signal_connect (G_OBJECT (window), "delete-event",
-                         G_CALLBACK (date_delete_popup), mgtim);
-       g_signal_connect (G_OBJECT (window), "key-press-event",
-                         G_CALLBACK (date_key_press_popup), mgtim);
-       g_signal_connect (G_OBJECT (window), "button-press-event",
-                         G_CALLBACK (date_button_press_popup), mgtim);
-       mgtim->priv->window = window;
-       
-       /* calendar */
-       wid = gtk_calendar_new ();
-       mgtim->priv->date = wid;
-       gtk_container_add (GTK_CONTAINER (window), wid);
-       gtk_widget_show (wid);
-       g_signal_connect (G_OBJECT (wid), "day-selected",
-                         G_CALLBACK (date_day_selected), mgtim);
-       g_signal_connect (G_OBJECT (wid), "day-selected-double-click",
-                         G_CALLBACK (date_day_selected_double_click), mgtim);
-       
-       /* button to pop up the calendar */
-       wid = gtk_button_new ();
-       arrow = gtk_image_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_MENU);
-       gtk_container_add (GTK_CONTAINER (wid), arrow);
-       gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
-       gtk_widget_show_all (wid);
-       g_signal_connect (G_OBJECT (wid), "clicked",
-                         G_CALLBACK (date_calendar_choose_cb), mgtim);
-       mgtim->priv->date_button = wid;
-
-       /* padding */
-       wid = gtk_label_new ("");
-       gtk_box_pack_start (GTK_BOX (hb), wid, TRUE, TRUE, 0);
-       gtk_widget_show (wid);
-
-       return hb;
+       gtk_widget_grab_focus (mgtim->priv->entry);
 }
 
 static void
-entry_date_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar insert_char,
-                       G_GNUC_UNUSED gint virt_pos, gpointer data)
+entry_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar insert_char,
+                  G_GNUC_UNUSED gint virt_pos, gpointer data)
 {
        GValue *value;
        GType type;
@@ -634,31 +839,42 @@ entry_date_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar inse
        if (!value)
                return;
 
-       if (G_VALUE_TYPE (value) == GDA_TYPE_NULL) {
+        /* current value is NULL and we are not entering a digit */
+       if ((G_VALUE_TYPE (value) == GDA_TYPE_NULL) && (insert_char == g_utf8_get_char (" "))) {
+               gda_value_reset_with_type (value, type);
                if (type == G_TYPE_DATE) {
-                       /* set current date, whatever @insert_char is */
+                       /* set current date */
                        GDate *ndate;
                        ndate = g_new0 (GDate, 1);
                        g_date_set_time_t (ndate, time (NULL));
 
-                       gda_value_reset_with_type (value, type);
                        g_value_take_boxed (value, ndate);
                        real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
                }
+               else if (type == GDA_TYPE_TIME) {
+                       /* set current time */
+                       GValue *timvalue;
+                       GdauiEntryCommonTime *mgtim = GDAUI_ENTRY_COMMON_TIME (data);
+                       timvalue = gda_value_new_time_from_timet (time (NULL));
+                       real_set_value (GDAUI_ENTRY_WRAPPER (data), timvalue);
+                       gda_value_free (timvalue);
+               }
                else if (type == GDA_TYPE_TIMESTAMP) {
+                       /* set current date and time */
                        GValue *tsvalue;
-                       gchar *str;
+                       //gchar *str;
                        GdauiEntryCommonTime *mgtim = GDAUI_ENTRY_COMMON_TIME (data);
-                       str = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY 
(mgtim->priv->entry_time));
+                       //str = gdaui_formatted_entry_get_text (GDAUI_FORMATTED_ENTRY (mgtim->priv->entry));
                        tsvalue = gda_value_new_timestamp_from_timet (time (NULL));
                        real_set_value (GDAUI_ENTRY_WRAPPER (data), tsvalue);
                        gda_value_free (tsvalue);
-                       if (str && g_ascii_isdigit (*str))
-                               gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_time), str);
-                       g_free (str);
+                       //if (str && g_ascii_isdigit (*str))
+                       //      gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry), str);
+                       //g_free (str);
                }
        }
-       else {
+       else if ((G_VALUE_TYPE (value) != GDA_TYPE_NULL)) {
+               /* REM: if (type == GDA_TYPE_TIME) we have nothing to do  */
                GDate *date = NULL;
                if (type == G_TYPE_DATE) {
                        date = (GDate*) g_value_get_boxed (value);
@@ -708,399 +924,6 @@ entry_date_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar inse
        gda_value_free (value);
 }
 
-static void
-hide_popup (GdauiEntryCommonTime *mgtim)
-{
-        gtk_widget_hide (mgtim->priv->window);
-        gtk_grab_remove (mgtim->priv->window);
-}
-
-static gint
-date_delete_popup (G_GNUC_UNUSED GtkWidget *widget, GdauiEntryCommonTime *mgtim)
-{
-       hide_popup (mgtim);
-       return TRUE;
-}
-
-static gint
-date_key_press_popup (GtkWidget *widget, GdkEventKey *event, GdauiEntryCommonTime *mgtim)
-{
-       if (event->keyval != GDK_KEY_Escape)
-                return FALSE;
-
-        g_signal_stop_emission_by_name (widget, "key-press-event");
-        hide_popup (mgtim);
-
-        return TRUE;
-}
-
-static gint
-date_button_press_popup (GtkWidget *widget, GdkEventButton *event, GdauiEntryCommonTime *mgtim)
-{
-       GtkWidget *child;
-
-        child = gtk_get_event_widget ((GdkEvent *) event);
-
-        /* We don't ask for button press events on the grab widget, so
-         *  if an event is reported directly to the grab widget, it must
-         *  be on a window outside the application (and thus we remove
-         *  the popup window). Otherwise, we check if the widget is a child
-         *  of the grab widget, and only remove the popup window if it
-         *  is not.
-         */
-        if (child != widget) {
-                while (child) {
-                        if (child == widget)
-                                return FALSE;
-                        child = gtk_widget_get_parent (child);
-                }
-        }
-
-        hide_popup (mgtim);
-
-        return TRUE;
-}
-
-static void
-date_day_selected (GtkCalendar *calendar, GdauiEntryCommonTime *mgtim)
-{
-       char buffer [256];
-        guint year, month, day;
-        struct tm mtm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-        char *str_utf8;
-
-        gtk_calendar_get_date (calendar, &year, &month, &day);
-
-        mtm.tm_mday = day;
-        mtm.tm_mon = month;
-        if (year > 1900)
-                mtm.tm_year = year - 1900;
-        else
-                mtm.tm_year = year;
-
-        if (strftime (buffer, sizeof (buffer), "%x", &mtm) == 0)
-                strcpy (buffer, "???");
-        buffer[sizeof(buffer)-1] = '\0';
-
-        str_utf8 = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
-        gdaui_entry_set_text (GDAUI_ENTRY (mgtim->priv->entry_date), str_utf8);
-        g_free (str_utf8);
-}
-
-static void
-date_day_selected_double_click (G_GNUC_UNUSED GtkCalendar *calendar, GdauiEntryCommonTime *mgtim)
-{
-       hide_popup (mgtim);
-}
-
-
-static gboolean popup_grab_on_window (GtkWidget *widget, guint32 activate_time);
-static void position_popup (GdauiEntryCommonTime *mgtim);
-static void
-date_calendar_choose_cb (GtkWidget *button, GdauiEntryCommonTime *mgtim)
-{
-       GValue *value;
-        guint year=0, month=0, day=0;
-       gboolean unset = TRUE;
-
-        /* setting the calendar to the latest displayed date */
-       value = gdaui_data_entry_get_value (GDAUI_DATA_ENTRY (mgtim));
-       
-        if (value && !gda_value_is_null (value)) {
-               const GDate *date;
-               const GdaTimestamp *ts;
-               GType type;
-
-               type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (mgtim));
-               if (type == G_TYPE_DATE) {
-                       date = (GDate*) g_value_get_boxed (value);
-                       if (date) {
-                               month = g_date_get_month (date);
-                               year = g_date_get_year (date);
-                               day = g_date_get_day (date);
-                               if ((month != G_DATE_BAD_MONTH) && 
-                                   (day != G_DATE_BAD_DAY) &&
-                                   (year != G_DATE_BAD_YEAR)) {
-                                       month -= 1;
-                                       unset = FALSE;
-                               }
-                       }
-               }
-               else if (type == GDA_TYPE_TIMESTAMP) {
-                       ts = gda_value_get_timestamp (value);
-                       if (ts) {
-                               year = ts->year;
-                               month = ts->month - 1;
-                               day = ts->day;
-                               unset = FALSE;
-                       }
-               }
-               else
-                       g_assert_not_reached ();
-        }
-
-       if (unset) {
-                time_t now;
-                struct tm *stm;
-
-                now = time (NULL);
-#ifdef HAVE_LOCALTIME_R
-               struct tm tmpstm;
-               stm = localtime_r (&now, &tmpstm);
-#elif HAVE_LOCALTIME_S
-               struct tm tmpstm;
-               g_assert (localtime_s (&tmpstm, &now) == 0);
-               stm = &tmpstm;
-#else
-                stm = localtime (&now);
-#endif
-                year = stm->tm_year + 1900;
-                month = stm->tm_mon;
-                day = stm->tm_mday;
-        }
-
-        gtk_calendar_select_month (GTK_CALENDAR (mgtim->priv->date), month, year);
-        gtk_calendar_select_day (GTK_CALENDAR (mgtim->priv->date), day);
-
-        /* popup window */
-        /* Temporarily grab pointer and keyboard, copied from GnomeDateEdit */
-        if (!popup_grab_on_window (button, gtk_get_current_event_time ()))
-                return;
-
-        position_popup (mgtim);
-        gtk_widget_show (mgtim->priv->window);
-        gtk_grab_add (mgtim->priv->window);
-
-       GdkScreen *screen;
-       gint swidth, sheight;
-       gint root_x, root_y;
-       gint wwidth, wheight;
-       gboolean do_move = FALSE;
-       screen = gtk_window_get_screen (GTK_WINDOW (mgtim->priv->window));
-       if (screen) {
-               swidth = gdk_screen_get_width (screen);
-               sheight = gdk_screen_get_height (screen);
-       }
-       else {
-               swidth = gdk_screen_width ();
-               sheight = gdk_screen_height ();
-       }
-       gtk_window_get_position (GTK_WINDOW (mgtim->priv->window), &root_x, &root_y);
-       gtk_window_get_size (GTK_WINDOW (mgtim->priv->window), &wwidth, &wheight);
-       if (root_x + wwidth > swidth) {
-               do_move = TRUE;
-               root_x = swidth - wwidth;
-       }
-       else if (root_x < 0) {
-               do_move = TRUE;
-               root_x = 0;
-       }
-       if (root_y + wheight > sheight) {
-               do_move = TRUE;
-               root_y = sheight - wheight;
-       }
-       else if (root_y < 0) {
-               do_move = TRUE;
-               root_y = 0;
-       }
-       if (do_move)
-               gtk_window_move (GTK_WINDOW (mgtim->priv->window), root_x, root_y);
-
-        gtk_widget_grab_focus (mgtim->priv->date);
-        popup_grab_on_window (mgtim->priv->window,
-                              gtk_get_current_event_time ());
-}
-
-static gboolean
-popup_grab_on_window (GtkWidget *widget, guint32 activate_time)
-{
-       GdkDeviceManager *manager;
-       GdkDevice *pointer;
-       GdkWindow *window;
-       window = gtk_widget_get_window (widget);
-       manager = gdk_display_get_device_manager (gtk_widget_get_display (widget));
-       pointer = gdk_device_manager_get_client_pointer (manager);
-        if (gdk_device_grab (pointer, window, GDK_OWNERSHIP_WINDOW, TRUE,
-                            GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-                            GDK_POINTER_MOTION_MASK,
-                            NULL, activate_time) == GDK_GRAB_SUCCESS) {
-               GdkDevice *keyb;
-               keyb = gdk_device_get_associated_device (pointer);
-                if (gdk_device_grab (keyb, window, GDK_OWNERSHIP_WINDOW, TRUE,
-                                    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, activate_time) ==
-                   GDK_GRAB_SUCCESS)
-                        return TRUE;
-                else {
-                        gdk_device_ungrab (pointer, activate_time);
-                        return FALSE;
-                }
-        }
-        return FALSE;
-}
-
-static void
-position_popup (GdauiEntryCommonTime *mgtim)
-{
-        gint x, y;
-        gint bwidth, bheight;
-        GtkRequisition req_minimum, req_natural;
-
-        gtk_widget_get_preferred_size (mgtim->priv->window, &req_minimum,
-                                      &req_natural);
-
-        gdk_window_get_origin (gtk_widget_get_window (mgtim->priv->date_button), &x, &y);
-       GtkAllocation alloc;
-       gtk_widget_get_allocation (mgtim->priv->date_button, &alloc);
-        x += alloc.x;
-        y += alloc.y;
-        bwidth = alloc.width;
-        bheight = alloc.height;
-
-        x += bwidth - req_natural.width;
-        y += bheight;
-
-        if (x < 0)
-                x = 0;
-
-        if (y < 0)
-                y = 0;
-
-        gtk_window_move (GTK_WINDOW (mgtim->priv->window), x, y);
-}
-
-
-
-
-/*
- * callbacks for the time
- */
-static void entry_time_insert_func (GdauiFormattedEntry *fentry, gunichar insert_char, gint virt_pos, 
gpointer data);
-
-static GtkWidget *
-create_entry_time (GdauiEntryCommonTime *mgtim)
-{
-       GtkWidget *wid;
-       GdaDataHandler *dh;
-
-       /* text entry */
-       dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgtim));
-       if (GDA_IS_HANDLER_TIME (dh)) {
-               gchar *str, *mask, *ptr;
-               str = gda_handler_time_get_format (GDA_HANDLER_TIME (dh), GDA_TYPE_TIME);
-               mask = g_strdup (str);
-               for (ptr = mask; *ptr; ptr++) {
-                       if (*ptr == '0')
-                               *ptr = '-';
-               }
-               wid = gdaui_formatted_entry_new (str, mask);
-               g_free (str);
-               g_free (mask);
-
-               gdaui_formatted_entry_set_insert_func (GDAUI_FORMATTED_ENTRY (wid), entry_time_insert_func,
-                                                      mgtim);
-       }
-       else
-               wid = gdaui_entry_new (NULL, NULL);
-        mgtim->priv->entry_time = wid;
-
-        /* format tooltip */
-       gtk_widget_set_tooltip_text (wid, _("Format is hh:mm:ss"));
-
-        return wid;
-}
-
-static void
-entry_time_insert_func (G_GNUC_UNUSED GdauiFormattedEntry *fentry, gunichar insert_char,
-                       G_GNUC_UNUSED gint virt_pos, gpointer data)
-{
-       GValue *value;
-       GType type;
-
-       type = gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY (data));
-       value = real_get_value (GDAUI_ENTRY_WRAPPER (data));
-       if (!value)
-               return;
-
-       if (insert_char != g_utf8_get_char (" "))
-               return;
-
-       if (type == GDA_TYPE_TIME) {
-               /* set current time */
-               gda_value_reset_with_type (value, type);
-               struct tm *ltm;
-               time_t val;
-               
-               val = time (NULL);
-               ltm = localtime ((const time_t *) &val);
-               if (ltm) {
-                       GdaTime tim;
-                       memset (&tim, 0, sizeof (GdaTime));
-                       tim.hour = ltm->tm_hour;
-                       tim.minute = ltm->tm_min;
-                       tim.second = ltm->tm_sec;
-                       tim.fraction = 0;
-                       tim.timezone = GDA_TIMEZONE_INVALID;
-                       gda_value_set_time (value, (const GdaTime *) &tim);
-                       real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
-               }
-       }
-       else if (type == GDA_TYPE_TIMESTAMP && (G_VALUE_TYPE (value) == GDA_TYPE_TIMESTAMP)) {
-               const GdaTimestamp *ts;
-               ts = gda_value_get_timestamp (value);
-               if (ts) {
-                       struct tm *ltm;
-                       time_t val;
-               
-                       val = time (NULL);
-                       ltm = localtime ((const time_t *) &val);
-                       if (ltm) {
-                               GdaTimestamp tim;
-                               tim = *ts;
-                               tim.hour = ltm->tm_hour;
-                               tim.minute = ltm->tm_min;
-                               tim.second = ltm->tm_sec;
-                               tim.fraction = 0;
-                               tim.timezone = GDA_TIMEZONE_INVALID;
-                               gda_value_set_timestamp (value, (const GdaTimestamp *) &tim);
-                               real_set_value (GDAUI_ENTRY_WRAPPER (data), value);
-                       }
-               }
-       }
-       else if (type == GDA_TYPE_TIMESTAMP) {
-               /* value is GDA_TYPE_NULL */
-               entry_date_insert_func (NULL, insert_char, 0, data);
-       }
-       
-       gda_value_free (value);
-}
-
-/*
- * callbacks for the timestamp
- */
-static GtkWidget *
-create_entry_ts (GdauiEntryCommonTime *mgtim)
-{
-       GtkWidget *hb, *wid;
-
-       hb = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-       
-       /* date part */
-       wid = create_entry_date (mgtim);
-       gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
-       gtk_widget_show (wid);
-
-       /* time part */
-       wid = create_entry_time (mgtim);
-       gtk_box_pack_start (GTK_BOX (hb), wid, FALSE, FALSE, 0);
-       gtk_widget_show (wid);
-
-       mgtim->priv->hbox = hb;
-       
-       return hb;
-}
-
-
-
 /*
  * GtkCellEditable interface
  */
@@ -1126,39 +949,16 @@ gdaui_entry_common_time_start_editing (GtkCellEditable *iface, GdkEvent *event)
        g_return_if_fail (mgtim->priv);
 
        mgtim->priv->editing_canceled = FALSE;
-       if (mgtim->priv->date_button) {
-               gtk_widget_destroy (mgtim->priv->date_button);
-               mgtim->priv->date_button = NULL;
-       }
-
-       if (mgtim->priv->hbox) {
-               gtk_box_set_spacing (GTK_BOX (mgtim->priv->hbox), 0);
-               gtk_container_set_border_width (GTK_CONTAINER (mgtim->priv->hbox), 0);
-       }
 
-       if (mgtim->priv->entry_date) {
-               g_object_set (G_OBJECT (mgtim->priv->entry_date), "has-frame", FALSE, NULL);
-               gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (mgtim->priv->entry_date), event);
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "editing-done",
+       if (mgtim->priv->entry) {
+               g_object_set (G_OBJECT (mgtim->priv->entry), "has-frame", FALSE, NULL);
+               gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (mgtim->priv->entry), event);
+               g_signal_connect (G_OBJECT (mgtim->priv->entry), "editing-done",
                                  G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgtim);
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_date), "remove-widget",
+               g_signal_connect (G_OBJECT (mgtim->priv->entry), "remove-widget",
                                  G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgtim);
        }
 
-       if (mgtim->priv->entry_time) {
-               g_object_set (G_OBJECT (mgtim->priv->entry_time), "has-frame", FALSE, NULL);
-               gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (mgtim->priv->entry_time), event);
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "editing-done",
-                                 G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgtim);
-               g_signal_connect (G_OBJECT (mgtim->priv->entry_time), "remove-widget",
-                                 G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgtim);
-       }
-
-       gdaui_entry_shell_refresh (GDAUI_ENTRY_SHELL (mgtim));
-
-       if (mgtim->priv->entry_date)
-               gtk_widget_grab_focus (mgtim->priv->entry_date);
-       else
-               gtk_widget_grab_focus (mgtim->priv->entry_time);
-       gtk_widget_queue_draw (GTK_WIDGET (mgtim));
+       gtk_widget_grab_focus (mgtim->priv->entry);
+       //gtk_widget_queue_draw (GTK_WIDGET (mgtim)); useful ?
 }
diff --git a/libgda-ui/data-entries/gdaui-entry-integer.xml.in 
b/libgda-ui/data-entries/gdaui-entry-integer.xml.in
index f46ff21..04d7a01 100644
--- a/libgda-ui/data-entries/gdaui-entry-integer.xml.in
+++ b/libgda-ui/data-entries/gdaui-entry-integer.xml.in
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
 <data-set-spec>
   <parameters>
-    <parameter id="THOUSAND_SEP" _name="Use 1000s separators" _descr="Use thousands separator as specified 
by current locale" gdatype="gboolean">
+    <parameter id="THOUSAND_SEP" _name="Use 1000s separators" _descr="Use thousands separator as specified 
by current locale" gdatype="gboolean" nullok="TRUE">
       <gda_value>FALSE</gda_value>
     </parameter>
-    <parameter id="CURRENCY" _name="Currency symbol" _descr="A currency symbol" source="currencies:0" 
gdatype="gchararray"/>
+    <parameter id="CURRENCY" _name="Currency symbol" _descr="A currency symbol" source="currencies:0" 
gdatype="gchararray" nullok="TRUE"/>
   </parameters>
   <sources>
     <gda_array name="currencies">
diff --git a/libgda-ui/data-entries/gdaui-entry-none.c b/libgda-ui/data-entries/gdaui-entry-none.c
index bbf7834..aa05b89 100644
--- a/libgda-ui/data-entries/gdaui-entry-none.c
+++ b/libgda-ui/data-entries/gdaui-entry-none.c
@@ -156,23 +156,24 @@ gdaui_entry_none_finalize (GObject   * object)
 static GtkWidget *
 create_entry (GdauiEntryWrapper *mgwrap)
 {
-       GtkWidget *frame, *label;
+       GtkWidget *evbox, *label;
        GdauiEntryNone *entry;
 
        g_return_val_if_fail (mgwrap && GDAUI_IS_ENTRY_NONE (mgwrap), NULL);
        entry = GDAUI_ENTRY_NONE (mgwrap);
        g_return_val_if_fail (entry->priv, NULL);
 
-       frame = gtk_frame_new (NULL);
-       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
-       
+       evbox = gtk_event_box_new ();
+       gtk_widget_add_events (evbox, GDK_FOCUS_CHANGE_MASK);
+       gtk_widget_set_can_focus (evbox, TRUE);
        label = gtk_label_new ("");
+       gtk_widget_set_name (label, "invalid-label");
        gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
 
-       gtk_container_add (GTK_CONTAINER (frame), label);
+       gtk_container_add (GTK_CONTAINER (evbox), label);
        gtk_widget_show (label);
 
-       return frame;
+       return evbox;
 }
 
 static void
diff --git a/libgda-ui/data-entries/gdaui-entry-number.c b/libgda-ui/data-entries/gdaui-entry-number.c
index 84f6564..b0383be 100644
--- a/libgda-ui/data-entries/gdaui-entry-number.c
+++ b/libgda-ui/data-entries/gdaui-entry-number.c
@@ -78,8 +78,6 @@ struct _GdauiEntryNumberPrivate
        guchar         thousand_sep;
        guint16        nb_decimals;
        gchar         *currency;
-
-       gulong         entry_change_sig;
 };
 
 static void
@@ -165,8 +163,6 @@ gdaui_entry_number_init (GdauiEntryNumber *mgstr)
        mgstr->priv->nb_decimals = G_MAXUINT16; /* unlimited number of decimals */
        mgstr->priv->currency = NULL;
 
-       mgstr->priv->entry_change_sig = 0;
-
        g_signal_connect (mgstr, "key-press-event",
                          G_CALLBACK (key_press_event_cb), NULL);
 }
@@ -187,8 +183,9 @@ gdaui_entry_number_is_type_numeric (GType type)
  * gdaui_entry_number_new:
  * @dh: the data handler to be used by the new widget
  * @type: the requested data type (compatible with @dh)
+ * @options: (allow-none): some options formatting the new entry, or %NULL
  *
- * Creates a new data entry widget
+ * Creates a new data entry widget. Known options are: THOUSAND_SEP, NB_DECIMALS and CURRENCY
  *
  * Returns: (transfer full): the new widget
  */
@@ -293,18 +290,30 @@ gdaui_entry_number_get_property (GObject *object,
        }
 }
 
+static void
+event_after_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+        g_signal_emit_by_name (widget, "event-after", event);
+}
+
 static GtkWidget *
 create_entry (GdauiEntryWrapper *mgwrap)
 {
+       GtkWidget *hb;
        GdauiEntryNumber *mgstr;
 
        g_return_val_if_fail (GDAUI_IS_ENTRY_NUMBER (mgwrap), NULL);
        mgstr = GDAUI_ENTRY_NUMBER (mgwrap);
 
+       hb = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        mgstr->priv->entry = gdaui_numeric_entry_new (gdaui_data_entry_get_value_type (GDAUI_DATA_ENTRY 
(mgwrap)));
        sync_entry_options (mgstr);
 
-       return mgstr->priv->entry;
+       gtk_container_add (GTK_CONTAINER (hb), mgstr->priv->entry);
+       gtk_widget_show (mgstr->priv->entry);
+       g_signal_connect_swapped (mgstr->priv->entry, "event-after",
+                                  G_CALLBACK (event_after_cb), hb);
+       return hb;
 }
 
 static void
@@ -361,10 +370,10 @@ connect_signals (GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activ
        mgstr = GDAUI_ENTRY_NUMBER (mgwrap);
        g_return_if_fail (mgstr->priv);
 
-       mgstr->priv->entry_change_sig = g_signal_connect (G_OBJECT (mgstr->priv->entry), "changed",
-                                                         modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgstr->priv->entry), "activate",
-                         activate_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgstr->priv->entry), "changed",
+                                 modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgstr->priv->entry), "activate",
+                                 activate_cb, mgwrap);
 }
 
 static void
@@ -420,7 +429,6 @@ gdaui_entry_number_start_editing (GtkCellEditable *iface, GdkEvent *event)
                          G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgstr);
        g_signal_connect (G_OBJECT (mgstr->priv->entry), "remove-widget",
                          G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgstr);
-       gdaui_entry_shell_refresh (GDAUI_ENTRY_SHELL (mgstr));
 
        gtk_widget_grab_focus (mgstr->priv->entry);
        gtk_widget_queue_draw (GTK_WIDGET (mgstr));
diff --git a/libgda-ui/data-entries/gdaui-entry-number.xml.in 
b/libgda-ui/data-entries/gdaui-entry-number.xml.in
index 4dcdeba..dc86769 100644
--- a/libgda-ui/data-entries/gdaui-entry-number.xml.in
+++ b/libgda-ui/data-entries/gdaui-entry-number.xml.in
@@ -1,13 +1,13 @@
 <?xml version="1.0"?>
 <data-set-spec>
   <parameters>
-    <parameter id="THOUSAND_SEP" _name="Use 1000s separators" _descr="Use thousands separator as specified 
by current locale" gdatype="gboolean">
+    <parameter id="THOUSAND_SEP" _name="Use 1000s separators" _descr="Use thousands separator as specified 
by current locale" gdatype="gboolean" nullok="TRUE">
       <gda_value>FALSE</gda_value>
     </parameter>
-    <parameter id="NB_DECIMALS" _name="Decimals" _descr="Number of decimals" gdatype="guint">
+    <parameter id="NB_DECIMALS" _name="Decimals" _descr="Number of decimals" gdatype="guint" nullok="TRUE">
       <gda_value>2</gda_value>
     </parameter>
-    <parameter id="CURRENCY" _name="Currency symbol" _descr="A currency symbol" source="currencies:0" 
gdatype="gchararray"/>
+    <parameter id="CURRENCY" _name="Currency symbol" _descr="A currency symbol" source="currencies:0" 
gdatype="gchararray" nullok="TRUE"/>
   </parameters>
   <sources>
     <gda_array name="currencies">
diff --git a/libgda-ui/data-entries/gdaui-entry-shell.c b/libgda-ui/data-entries/gdaui-entry-shell.c
index ccee60b..2ac2b00 100644
--- a/libgda-ui/data-entries/gdaui-entry-shell.c
+++ b/libgda-ui/data-entries/gdaui-entry-shell.c
@@ -19,13 +19,16 @@
  * Boston, MA  02110-1301, USA.
  */
 
-#include <gdk/gdkkeysyms.h>
+#include <gdk/gdk.h>
 #include "gdaui-entry-shell.h"
 #include "gdaui-entry-none.h"
 #include <libgda/gda-data-handler.h>
 #include <libgda-ui/internal/utility.h>
 #include <glib/gi18n-lib.h>
-#include "widget-embedder.h"
+#include <libgda/gda-debug-macros.h>
+
+/*#define DEBUG*/
+
 static void gdaui_entry_shell_class_init (GdauiEntryShellClass *class);
 static void gdaui_entry_shell_init (GdauiEntryShell *wid);
 static void gdaui_entry_shell_dispose (GObject *object);
@@ -38,36 +41,72 @@ static void gdaui_entry_shell_get_property (GObject *object,
                                            guint param_id,
                                            GValue *value,
                                            GParamSpec *pspec);
+/*
+ * This widget displays a GValue and its attributes (GValueAttribute) in the following way:
+ * - if GDA_VALUE_ATTR_DATA_NON_VALID, then:
+ *      - if GDA_VALUE_ATTR_READ_ONLY: then a "Invalid" label is shown, and no action is possible
+ *    else
+ *      - an entry widget is shown
+ *      NB: in both cases, the widget is outlined (or colored) in the "invalid color", which can be changed
+ *          using gdaui_entry_shell_set_invalid_color()
+ * else
+ * - if GDA_VALUE_ATTR_IS_NULL or GDA_VALUE_ATTR_IS_DEFAULT then
+ *      - a "value is NULL" or "value is default" or "Value is default (NULL)" is shown.
+ *        If not GDA_VALUE_ATTR_READ_ONLY, then an "edit" action is possible, which (at least up to when
+ *        the focus is lost), displays an entry widget
+ *    else
+ *      - an entry widget is shown. If not GDA_VALUE_ATTR_READ_ONLY then, depending on
+ *        GDA_VALUE_ATTR_CAN_BE_NULL, GDA_VALUE_ATTR_CAN_BE_DEFAULT, or GDA_VALUE_ATTR_HAS_VALUE_ORIG, the
+ *        following respective actions are possible: "set to NULL", "set to default" and "reset" (this last 
one
+ *        if not GDA_VALUE_ATTR_IS_UNCHANGED)
+ */
 
+#define PAGE_LABEL "L"
+#define PAGE_ENTRY "E"
+
+typedef enum {
+       MESSAGE_NONE,
+       MESSAGE_NULL,
+       MESSAGE_DEFAULT,
+       MESSAGE_DEFAULT_AND_NULL,
+       MESSAGE_INVALID
+} MessageType;
+
+static const gchar *raw_messages[] = {
+       "",
+       N_("NULL value"),
+       N_("Default value"),
+       N_("Default value (NULL)"),
+       N_("Invalid value"),
+};
 
-static gint event_cb (GtkWidget *widget, GdkEvent *event, GdauiEntryShell *shell);
-static void show_all (GtkWidget *widget);
-static void contents_modified_cb (GdauiEntryShell *shell, gpointer unused);
-static void gdaui_entry_shell_refresh_status_display (GdauiEntryShell *shell);
+static gchar **messages = NULL;
 
 /* properties */
 enum {
        PROP_0,
        PROP_HANDLER,
-       PROP_ACTIONS,
        PROP_IS_CELL_RENDERER
 };
 
+#define value_is_null(attr) ((attr) & GDA_VALUE_ATTR_IS_NULL)
+#define value_is_modified(attr) (!((attr) & GDA_VALUE_ATTR_IS_UNCHANGED))
+#define value_is_default(attr) ((attr) & GDA_VALUE_ATTR_IS_DEFAULT)
+#define value_is_valid(attr) (!((attr) & GDA_VALUE_ATTR_DATA_NON_VALID))
 struct  _GdauiEntryShellPriv {
-        GtkWidget           *embedder;
-       GtkWidget           *hbox;
-        GtkWidget           *button;
-        GdaDataHandler      *data_handler;
+       GtkWidget           *stack;
+       GtkWidget           *button; /* "..." button */
+       GtkWidget           *label;
+        GdaDataHandler      *data_handler; /* FIXME: to remove if unused elsewhere */
        gboolean             show_actions;
-
-       gboolean             value_is_null;
-       gboolean             value_is_modified;
-       gboolean             value_is_default;
-       gboolean             value_is_non_valid;
-
        gboolean             is_cell_renderer;
+       gboolean             editable;
+       gboolean             being_edited;
 };
 
+static void show_or_hide_actions_button (GdauiEntryShell *shell, GdaValueAttribute attr);
+static guint compute_nb_possible_actions (GdauiEntryShell *shell, GdaValueAttribute attr);
+
 /* get a pointer to the parents to be able to call their destructor */
 static GObjectClass *parent_class = NULL;
 
@@ -97,7 +136,7 @@ gdaui_entry_shell_get_type (void)
                        0
                };
 
-               type = g_type_register_static (GTK_TYPE_VIEWPORT, "GdauiEntryShell", &info, 0);
+               type = g_type_register_static (GTK_TYPE_BOX, "GdauiEntryShell", &info, 0);
        }
        return type;
 }
@@ -112,7 +151,6 @@ gdaui_entry_shell_class_init (GdauiEntryShellClass * class)
        parent_class = g_type_class_peek_parent (class);
 
        object_class->dispose = gdaui_entry_shell_dispose;
-       widget_class->show_all = show_all;
 
        /* Properties */
        object_class->set_property = gdaui_entry_shell_set_property;
@@ -120,9 +158,6 @@ gdaui_entry_shell_class_init (GdauiEntryShellClass * class)
        g_object_class_install_property (object_class, PROP_HANDLER,
                                         g_param_spec_object ("handler", NULL, NULL, GDA_TYPE_DATA_HANDLER,
                                                              (G_PARAM_READABLE | G_PARAM_WRITABLE)));
-       g_object_class_install_property (object_class, PROP_ACTIONS,
-                                        g_param_spec_boolean ("actions", NULL, NULL, TRUE,
-                                                              (G_PARAM_READABLE | G_PARAM_WRITABLE)));
 
        g_object_class_install_property (object_class, PROP_IS_CELL_RENDERER,
                                         g_param_spec_boolean ("is-cell-renderer", NULL, NULL, TRUE,
@@ -130,65 +165,233 @@ gdaui_entry_shell_class_init (GdauiEntryShellClass * class)
 }
 
 static void
-show_all (GtkWidget *widget)
+destroy_popover (GtkWidget *child)
+{
+       /* destroy GtkPopover in which @child is */
+       GtkWidget *pop;
+       pop = gtk_widget_get_ancestor (GTK_WIDGET (child), GTK_TYPE_POPOVER);
+       if (pop)
+               gtk_widget_destroy (pop);
+}
+
+static void
+action_edit_value_cb (GtkButton *button, GdauiEntryShell *shell)
+{
+       GdaValueAttribute attr;
+       attr = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
+       if (! (attr & GDA_VALUE_ATTR_READ_ONLY)) {
+               gtk_stack_set_visible_child_name (GTK_STACK (shell->priv->stack), PAGE_ENTRY);
+               gdaui_data_entry_grab_focus (GDAUI_DATA_ENTRY (shell));
+               show_or_hide_actions_button (shell, attr);
+               shell->priv->being_edited = TRUE;
+       }
+       if (button)
+               destroy_popover (GTK_WIDGET (button));
+}
+
+static void
+action_set_value_to_null_cb (GtkButton *button, GdauiEntryShell *shell)
+{
+       GdaValueAttribute attr;
+       attr = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
+       if (attr & GDA_VALUE_ATTR_CAN_BE_NULL) {
+               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (shell),
+                                                GDA_VALUE_ATTR_IS_NULL, GDA_VALUE_ATTR_IS_NULL);
+               show_or_hide_actions_button (shell, attr);
+               shell->priv->being_edited = FALSE;
+       }
+       destroy_popover (GTK_WIDGET (button));
+}
+
+static void
+action_set_value_to_default_cb (GtkButton *button, GdauiEntryShell *shell)
+{
+       GdaValueAttribute attr;
+       attr = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
+       if (attr & GDA_VALUE_ATTR_CAN_BE_DEFAULT) {
+               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (shell),
+                                                GDA_VALUE_ATTR_IS_DEFAULT, GDA_VALUE_ATTR_IS_DEFAULT);
+               show_or_hide_actions_button (shell, attr);
+               shell->priv->being_edited = FALSE;
+       }
+       destroy_popover (GTK_WIDGET (button));
+}
+
+static void
+action_reset_value_cb (GtkButton *button, GdauiEntryShell *shell)
 {
-       if (((GdauiEntryShell*) widget)->priv->show_actions)
-               gtk_widget_show (((GdauiEntryShell*) widget)->priv->button);
+       GdaValueAttribute attr;
+       attr = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
+       if (attr & GDA_VALUE_ATTR_HAS_VALUE_ORIG) {
+               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (shell),
+                                                GDA_VALUE_ATTR_IS_UNCHANGED, GDA_VALUE_ATTR_IS_UNCHANGED);
+               shell->priv->being_edited = FALSE;
+       }
+       destroy_popover (GTK_WIDGET (button));
+}
+
+static void
+show_or_hide_actions_button (GdauiEntryShell *shell, GdaValueAttribute attr)
+{
+       gboolean visible = FALSE;
+       if (shell->priv->editable) {
+               guint nb;
+               nb = compute_nb_possible_actions (shell, attr);
+               if (nb > 0)
+                       visible = TRUE;
+       }
+       gtk_widget_set_visible (shell->priv->button, visible);
+}
+
+static guint
+compute_nb_possible_actions (GdauiEntryShell *shell, GdaValueAttribute attr)
+{
+       guint nb = 0;
+
+       if (attr & GDA_VALUE_ATTR_READ_ONLY)
+               return 0; /* no action possible */
+
+       if (!strcmp (gtk_stack_get_visible_child_name (GTK_STACK (shell->priv->stack)), PAGE_LABEL))
+               nb ++; /* "edit value" action */
+
+       if ((attr & GDA_VALUE_ATTR_CAN_BE_NULL) && !(attr & GDA_VALUE_ATTR_IS_NULL))
+               nb++;
+       if ((attr & GDA_VALUE_ATTR_CAN_BE_DEFAULT) && !(attr & GDA_VALUE_ATTR_IS_DEFAULT))
+               nb++;
+       if ((attr & GDA_VALUE_ATTR_HAS_VALUE_ORIG) && ! (attr & GDA_VALUE_ATTR_IS_UNCHANGED))
+               nb ++;
+       return nb;
+}
+
+static void
+actions_button_clicked_cb (G_GNUC_UNUSED GtkButton *button, GdauiEntryShell *shell)
+{
+       GdaValueAttribute attr;
+       attr = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
+
+       if (attr & GDA_VALUE_ATTR_READ_ONLY)
+               g_assert_not_reached ();
+
+       shell->priv->being_edited = FALSE;
+       g_assert (compute_nb_possible_actions (shell, attr) != 0);
+
+       GtkWidget *pop;
+       pop = gtk_popover_new (GTK_WIDGET (button));
+       GtkWidget *box;
+       box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       gtk_container_add (GTK_CONTAINER (pop), box);
+
+       GtkWidget *action_button;
+       if (!strcmp (gtk_stack_get_visible_child_name (GTK_STACK (shell->priv->stack)), PAGE_LABEL)) {
+               action_button = gtk_button_new_with_label (_("Edit value"));
+               g_signal_connect (action_button, "clicked",
+                                 G_CALLBACK (action_edit_value_cb), shell);
+               gtk_box_pack_start (GTK_BOX (box), action_button, FALSE, FALSE, 0);
+       }
+
+       if ((attr & GDA_VALUE_ATTR_CAN_BE_NULL) && !(attr & GDA_VALUE_ATTR_IS_NULL)) {
+               action_button = gtk_button_new_with_label (_("Set value to NULL"));
+               g_signal_connect (action_button, "clicked",
+                                 G_CALLBACK (action_set_value_to_null_cb), shell);
+               gtk_box_pack_start (GTK_BOX (box), action_button, FALSE, FALSE, 0);
+       }
+
+       if ((attr & GDA_VALUE_ATTR_CAN_BE_DEFAULT) && !(attr & GDA_VALUE_ATTR_IS_DEFAULT)) {
+               action_button = gtk_button_new_with_label (_("Set value to default"));
+               g_signal_connect (action_button, "clicked",
+                                 G_CALLBACK (action_set_value_to_default_cb), shell);
+               gtk_box_pack_start (GTK_BOX (box), action_button, FALSE, FALSE, 0);
+       }
+
+       if ((attr & GDA_VALUE_ATTR_HAS_VALUE_ORIG) && ! (attr & GDA_VALUE_ATTR_IS_UNCHANGED)) {
+               action_button = gtk_button_new_with_label (_("Reset value"));
+               g_signal_connect (action_button, "clicked",
+                                 G_CALLBACK (action_reset_value_cb), shell);
+                       gtk_box_pack_start (GTK_BOX (box), action_button, FALSE, FALSE, 0);
+       }
+
+       g_signal_connect (pop, "closed", G_CALLBACK (gtk_widget_destroy), NULL);
+       gtk_widget_show_all (pop);
+}
+
+static void
+event_after_cb (GtkWidget *widget, GdkEvent *event, GdauiEntryShell *shell)
+{
+       if (((event->type == GDK_KEY_RELEASE) && (((GdkEventKey*) event)->keyval == GDK_KEY_Escape)) ||
+           ((event->type == GDK_FOCUS_CHANGE) && (((GdkEventFocus*) event)->in == FALSE))) {
+               shell->priv->being_edited = FALSE;
+#ifdef DEBUG
+               g_print ("EVENT AFTER: %s!\n", event->type == GDK_FOCUS_CHANGE ? "FOCUS" : "KEY RELEASE");
+#endif
+               if (!strcmp (gtk_stack_get_visible_child_name (GTK_STACK (shell->priv->stack)), PAGE_ENTRY)) {
+                       GdaValueAttribute attr;
+                       attr = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
+                       _gdaui_entry_shell_attrs_changed (shell, attr);
+               }
+       }
+}
+
+static gboolean
+label_event_cb (GtkWidget *widget, GdkEvent *event, GdauiEntryShell *shell)
+{
+       action_edit_value_cb (NULL, shell);
+       return FALSE;
 }
 
 static void
 gdaui_entry_shell_init (GdauiEntryShell *shell)
 {
-       GtkWidget *button, *hbox, *arrow;
        GValue *gval;
 
+       gtk_orientable_set_orientation (GTK_ORIENTABLE (shell), GTK_ORIENTATION_HORIZONTAL);
+
        /* Private structure */
        shell->priv = g_new0 (GdauiEntryShellPriv, 1);
-       shell->priv->embedder = NULL;
-       shell->priv->button = NULL;
        shell->priv->show_actions = TRUE;
        shell->priv->data_handler = NULL;
-
-       shell->priv->value_is_null = FALSE;
-       shell->priv->value_is_modified = FALSE;
-       shell->priv->value_is_default = FALSE;
-       shell->priv->value_is_non_valid = FALSE;
+       shell->priv->editable = TRUE;
+       shell->priv->being_edited = FALSE;
 
        shell->priv->is_cell_renderer = FALSE;
 
        /* Setting the initial layout */
-       gtk_viewport_set_shadow_type (GTK_VIEWPORT (shell), GTK_SHADOW_NONE);
+       shell->priv->stack = gtk_stack_new ();
+       gtk_box_pack_start (GTK_BOX (shell), shell->priv->stack, TRUE, TRUE, 0);
+       gtk_widget_show (shell->priv->stack);
        gtk_container_set_border_width (GTK_CONTAINER (shell), 0);
 
-       /* hbox */
-       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-       gtk_container_add (GTK_CONTAINER (shell), hbox);
-       gtk_widget_show (hbox);
-       shell->priv->hbox = hbox;
-
-       /* vbox to insert the real widget to edit data */
-       shell->priv->embedder = widget_embedder_new ();
-       gtk_box_pack_start (GTK_BOX (hbox), shell->priv->embedder, TRUE, TRUE, 0);
-       gtk_widget_show (shell->priv->embedder);
-
-       /* button to change the entry's state and to display that state */
-       arrow = gtk_image_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_MENU);
-       button = gtk_button_new ();
-       gtk_style_context_add_class (gtk_widget_get_style_context (button), "action-entry");
-       gtk_container_add (GTK_CONTAINER (button), arrow);
-       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
-       shell->priv->button = button;
-       gtk_widget_show_all (button);
-
-       g_signal_connect (G_OBJECT (button), "event",
-                         G_CALLBACK (event_cb), shell);
-
-       /* focus */
-       gval = g_new0 (GValue, 1);
-       g_value_init (gval, G_TYPE_BOOLEAN);
-       g_value_set_boolean (gval, TRUE);
-       g_object_set_property (G_OBJECT (button), "can-focus", gval);
-       g_free (gval);
+       /* button */
+       shell->priv->button = gtk_button_new_with_label ("...");
+       gtk_button_set_relief (GTK_BUTTON (shell->priv->button), GTK_RELIEF_NONE);
+       gtk_style_context_add_class (gtk_widget_get_style_context (shell->priv->button), "action-entry");
+       g_object_set (G_OBJECT (shell->priv->button), "no-show-all", TRUE, NULL);
+       gtk_box_pack_start (GTK_BOX (shell), shell->priv->button, FALSE, FALSE, 0);
+       gtk_widget_show (shell->priv->button);
+       g_signal_connect (shell->priv->button, "clicked",
+                         G_CALLBACK (actions_button_clicked_cb), shell);
+
+       /* label */
+       if (!messages) {
+               guint size, i;
+               size = G_N_ELEMENTS (raw_messages);
+               messages = g_new (gchar *, size);
+               for (i = 0; i < size; i++)
+                       messages[i] = g_markup_printf_escaped ("<i>%s</i>", raw_messages[i]);
+       }
+       shell->priv->label = gtk_label_new ("");
+       gtk_widget_set_name (shell->priv->label, "invalid-label");
+       gtk_label_set_markup (GTK_LABEL (shell->priv->label), messages[MESSAGE_INVALID]);
+       gtk_widget_set_halign (shell->priv->label, GTK_ALIGN_START);
+       GtkWidget *evbox;
+       evbox = gtk_event_box_new ();
+       gtk_container_add (GTK_CONTAINER (evbox), shell->priv->label);
+       gtk_widget_show_all (evbox);
+       gtk_stack_add_named (GTK_STACK (shell->priv->stack), evbox, PAGE_LABEL);
+
+       gdaui_entry_shell_set_invalid_color (shell, 1.0, 0., 0., 0.9);
+
+       g_signal_connect (evbox, "button-press-event",
+                         G_CALLBACK (label_event_cb), shell);
 }
 
 static void
@@ -240,13 +443,6 @@ gdaui_entry_shell_set_property (GObject *object,
                                             "(to be set using the 'handler' property) expect some 
mis-behaviours"),
                                           G_OBJECT_TYPE_NAME (object));
                        break;
-               case PROP_ACTIONS:
-                       shell->priv->show_actions = g_value_get_boolean (value);
-                       if (shell->priv->show_actions)
-                               gtk_widget_show (shell->priv->button);
-                       else
-                               gtk_widget_hide (shell->priv->button);
-                       break;
                case PROP_IS_CELL_RENDERER:
                        if (GTK_IS_CELL_EDITABLE (shell) &&
                            (g_value_get_boolean (value) != shell->priv->is_cell_renderer)) {
@@ -274,9 +470,6 @@ gdaui_entry_shell_get_property (GObject *object,
                case PROP_HANDLER:
                        g_value_set_object (value, shell->priv->data_handler);
                        break;
-               case PROP_ACTIONS:
-                       g_value_set_boolean (value, shell->priv->show_actions);
-                       break;
                case PROP_IS_CELL_RENDERER:
                        g_value_set_boolean (value, shell->priv->is_cell_renderer);
                        break;
@@ -287,177 +480,34 @@ gdaui_entry_shell_get_property (GObject *object,
        }
 }
 
-
 /**
  * gdaui_entry_shell_pack_entry:
  * @shell: a #GdauiEntryShell object
- * @main_widget: a #GtkWidget to pack into @shell
+ * @entry: a #GtkWidget to pack into @shell
  *
- * Packs a #GTkWidget widget into the GdauiEntryShell.
+ * Packs a #GtkWidget widget into the @shell.
  */
 void
-gdaui_entry_shell_pack_entry (GdauiEntryShell *shell, GtkWidget *main_widget)
+gdaui_entry_shell_pack_entry (GdauiEntryShell *shell, GtkWidget *entry)
 {
        g_return_if_fail (GDAUI_IS_ENTRY_SHELL (shell));
-       g_return_if_fail (main_widget && GTK_IS_WIDGET (main_widget));
-       gtk_container_add (GTK_CONTAINER (shell->priv->embedder), main_widget);
+       g_return_if_fail (GTK_IS_WIDGET (entry));
 
-       /* signals */
-       g_signal_connect (G_OBJECT (shell), "contents-modified",
-                         G_CALLBACK (contents_modified_cb), NULL);
-
-       g_signal_connect (G_OBJECT (shell), "status-changed",
-                         G_CALLBACK (contents_modified_cb), NULL);
-}
-
-static void
-contents_modified_cb (GdauiEntryShell *shell, G_GNUC_UNUSED gpointer unused)
-{
-       gdaui_entry_shell_refresh (shell);
-}
-
-static void mitem_activated_cb (GtkWidget *mitem, GdauiEntryShell *shell);
-static GdaValueAttribute gdaui_entry_shell_refresh_attributes (GdauiEntryShell *shell);
-static gint
-event_cb (G_GNUC_UNUSED GtkWidget *widget, GdkEvent *event, GdauiEntryShell *shell)
-{
-       gboolean done = FALSE;
-
-       if (!shell->priv->show_actions)
-               return done;
-
-       if (event->type == GDK_BUTTON_PRESS) {
-               GdkEventButton *bevent = (GdkEventButton *) event;
-               if ((bevent->button == 1) || (bevent->button == 3)) {
-                       GtkWidget *menu;
-                       guint attributes;
-
-                       attributes = gdaui_entry_shell_refresh_attributes (shell);
-                       menu = _gdaui_utility_entry_build_actions_menu (G_OBJECT (shell), attributes,
-                                                                       G_CALLBACK (mitem_activated_cb));
-                       gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
-                                       bevent->button, bevent->time);
-                       done = TRUE;
-               }
+       /* real packing */
+       if (gtk_stack_get_child_by_name (GTK_STACK (shell->priv->stack), PAGE_ENTRY)) {
+               g_warning ("Implementation error: %s() has already been called for this GdauiEntryShell.",
+                          __FUNCTION__);
+               return;
        }
+       gtk_stack_add_named (GTK_STACK (shell->priv->stack), entry, PAGE_ENTRY);
 
-       if (event->type == GDK_KEY_PRESS) {
-               GtkWidget *menu;
-               GdkEventKey *kevent = (GdkEventKey *) event;
-
-               if (kevent->keyval == GDK_KEY_space) {
-                       guint attributes;
-
-                       attributes = gdaui_entry_shell_refresh_attributes (shell);
-                       menu = _gdaui_utility_entry_build_actions_menu (G_OBJECT (shell), attributes,
-                                                                       G_CALLBACK (mitem_activated_cb));
-
-                       gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
-                                       0, kevent->time);
-                       done = TRUE;
-               }
-               else {
-                       if (kevent->keyval == GDK_KEY_Tab)
-                               done = FALSE;
-                       else
-                               done = TRUE;
-               }
-       }
-
-       return done;
-}
-
-static void
-mitem_activated_cb (GtkWidget *mitem, GdauiEntryShell *shell)
-{
-       guint action;
-
-       action = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (mitem), "action"));
-       gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (shell), action, action);
-}
-
-static void
-gdaui_entry_shell_refresh_status_display (GdauiEntryShell *shell)
-{
-       static GdkRGBA **colors = NULL;
-       GdkRGBA *normal = NULL, *prelight = NULL;
-
-       g_return_if_fail (GDAUI_IS_ENTRY_SHELL (shell));
-
-       if (!colors)
-               colors = _gdaui_utility_entry_build_info_colors_array_a ();
-
-       gtk_widget_set_tooltip_text (shell->priv->button, NULL);
-
-       if (shell->priv->value_is_null) {
-               normal = colors[0];
-               prelight = colors[1];
-               gtk_widget_set_tooltip_text (shell->priv->button, _("Value is NULL"));
-       }
-
-       if (shell->priv->value_is_default) {
-               normal = colors[2];
-               prelight = colors[3];
-               gtk_widget_set_tooltip_text (shell->priv->button, _("Value will be determined by default"));
-       }
-
-       if (shell->priv->value_is_non_valid) {
-               normal = colors[4];
-               prelight = colors[5];
-               gtk_widget_set_tooltip_text (shell->priv->button, _("Value is invalid"));
-       }
-
-       gtk_widget_override_background_color (shell->priv->button, GTK_STATE_FLAG_NORMAL, normal);
-       gtk_widget_override_background_color (shell->priv->button, GTK_STATE_FLAG_ACTIVE, normal);
-       gtk_widget_override_background_color (shell->priv->button, GTK_STATE_FLAG_PRELIGHT, prelight);
-}
-
-static GdaValueAttribute
-gdaui_entry_shell_refresh_attributes (GdauiEntryShell *shell)
-{
-       GdaValueAttribute attrs;
-
-       attrs = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell));
-       shell->priv->value_is_null = attrs & GDA_VALUE_ATTR_IS_NULL;
-       shell->priv->value_is_modified = ! (attrs & GDA_VALUE_ATTR_IS_UNCHANGED);
-       shell->priv->value_is_default = attrs & GDA_VALUE_ATTR_IS_DEFAULT;
-       shell->priv->value_is_non_valid = attrs & GDA_VALUE_ATTR_DATA_NON_VALID;
-
-       return attrs;
-}
-
-/**
- * gdaui_entry_shell_refresh:
- * @shell: the GdauiEntryShell widget to refresh
- *
- * Forces the shell to refresh its display (mainly the color of the
- * button).
- */
-void
-gdaui_entry_shell_refresh (GdauiEntryShell *shell)
-{
-       g_return_if_fail (GDAUI_IS_ENTRY_SHELL (shell));
-       gdaui_entry_shell_refresh_attributes (shell);
-       gdaui_entry_shell_refresh_status_display (shell);
-}
-
-/**
- * gdaui_entry_shell_set_unknown:
- * @shell: the #GdauiEntryShell widget to refresh
- * @unknown: set to %TRUE if @shell's contents is unavailable and should not be modified
- *
- * Defines if @shell's contents is in an undefined state (shows or hides @shell's contents)
- */
-void
-gdaui_entry_shell_set_unknown (GdauiEntryShell *shell, gboolean unknown)
-{
-       g_return_if_fail (GDAUI_IS_ENTRY_SHELL (shell));
-
-       widget_embedder_set_valid ((WidgetEmbedder*) shell->priv->embedder, !unknown);
+       /* signals */
+       g_signal_connect_after (G_OBJECT (entry), "event-after",
+                               G_CALLBACK (event_after_cb), shell);
 }
 
 /**
- * gdaui_entry_shell_set_ucolor:
+ * gdaui_entry_shell_set_invalid_color:
  * @shell: a #GdauiEntryShell
  * @red: the red component of a color
  * @green: the green component of a color
@@ -470,9 +520,96 @@ gdaui_entry_shell_set_unknown (GdauiEntryShell *shell, gboolean unknown)
  * Since: 5.0.3
  */
 void
-gdaui_entry_shell_set_ucolor (GdauiEntryShell *shell, gdouble red, gdouble green,
-                             gdouble blue, gdouble alpha)
+gdaui_entry_shell_set_invalid_color (GdauiEntryShell *shell, gdouble red, gdouble green,
+                                    gdouble blue, gdouble alpha)
 {
        g_return_if_fail (GDAUI_IS_ENTRY_SHELL (shell));
-       widget_embedder_set_ucolor ((WidgetEmbedder*) shell->priv->embedder, red, green, blue, alpha);
+       g_return_if_fail ((red >= 0.) && (red <= 1.));
+       g_return_if_fail ((green >= 0.) && (green <= 1.));
+       g_return_if_fail ((blue >= 0.) && (blue <= 1.));
+       g_return_if_fail ((alpha >= 0.) && (alpha <= 1.));
+
+       static GtkCssProvider *prov = NULL;
+       if (!prov) {
+               prov = gtk_css_provider_new ();
+               gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                                          GTK_STYLE_PROVIDER (prov),
+                                                          GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+       }
+
+#define BASE_CSS_FORMAT "@define-color gdaui_inv_color lighter (rgba (%u,%u,%u,0.%d));" \
+               ".invalid-entry #invalid-label {"                       \
+               "color: darker (@selected_fg_color);"                   \
+               "background-color: @gdaui_inv_color;"                   \
+               "border-width:1px;"                                     \
+               "border-style:solid;"                                   \
+               "border-radius:3px;"                                    \
+               "border-color: @gdaui_inv_color;"                       \
+               "}"                                                     \
+               ".invalid-entry GtkEntry, .invalid-entry GtkButton, .invalid-entry GtkScrolledWindow, 
.invalid-entry GtkSwitch {"       \
+               "border-radius:3px;"                                    \
+               "border-color: @gdaui_inv_color;"                       \
+               "border-width:1px;"                                     \
+               "border-style:solid;"                                   \
+               "}"                                                     \
+               ".invalid-entry GtkLabel {"                             \
+               "color: @gdaui_inv_color;"                                                      \
+               "}"
+
+       gchar *css;
+       css = g_strdup_printf (BASE_CSS_FORMAT, (guint) (red * 255), (guint) (green * 255),
+                              (guint) (blue * 255), (gint) (alpha * 100));
+       gtk_css_provider_load_from_data (prov, css, -1, NULL);
+       g_free (css);
+}
+
+void
+_gdaui_entry_shell_mark_editable (GdauiEntryShell *shell, gboolean editable)
+{
+       
+       if (editable != shell->priv->editable) {
+               shell->priv->editable = editable;
+               _gdaui_entry_shell_attrs_changed (shell,
+                                                 gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (shell)));
+       }
+}
+
+/*
+ * Call this function to inform @shell that it may need to refresh its UI settings.
+ */
+void
+_gdaui_entry_shell_attrs_changed (GdauiEntryShell *shell, GdaValueAttribute attr)
+{
+
+       MessageType msg = MESSAGE_NONE;
+       if (value_is_valid (attr)) {
+               if (value_is_null (attr)) {
+                       if (value_is_default (attr))
+                               msg = MESSAGE_DEFAULT_AND_NULL;
+                       else
+                               msg = MESSAGE_NULL;
+               }
+               else if (value_is_default (attr))
+                       msg = MESSAGE_DEFAULT;
+       }
+       else
+               msg = MESSAGE_INVALID;
+
+       if (! shell->priv->being_edited) {
+               gtk_label_set_markup (GTK_LABEL (shell->priv->label), messages[msg]);
+               if ((msg == MESSAGE_NONE) ||
+                   ((msg == MESSAGE_INVALID) && ! (attr & GDA_VALUE_ATTR_READ_ONLY)))
+                       gtk_stack_set_visible_child_name (GTK_STACK (shell->priv->stack), PAGE_ENTRY);
+               else
+                       gtk_stack_set_visible_child_name (GTK_STACK (shell->priv->stack), PAGE_LABEL);
+       }
+
+       if (msg == MESSAGE_INVALID)
+               gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (shell)),
+                                            "invalid-entry");
+       else
+               gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (shell)),
+                                               "invalid-entry");
+
+       show_or_hide_actions_button (shell, attr);
 }
diff --git a/libgda-ui/data-entries/gdaui-entry-shell.h b/libgda-ui/data-entries/gdaui-entry-shell.h
index 92cea9e..38488a3 100644
--- a/libgda-ui/data-entries/gdaui-entry-shell.h
+++ b/libgda-ui/data-entries/gdaui-entry-shell.h
@@ -42,7 +42,7 @@ typedef struct _GdauiEntryShellPriv  GdauiEntryShellPriv;
 /* struct for the object's data */
 struct _GdauiEntryShell
 {
-       GtkViewport         object;
+       GtkBox                object;
 
        GdauiEntryShellPriv  *priv;
 };
@@ -50,17 +50,18 @@ struct _GdauiEntryShell
 /* struct for the object's class */
 struct _GdauiEntryShellClass
 {
-       GtkViewportClass    parent_class;
+       GtkBoxClass           parent_class;
 };
 
 
-GType           gdaui_entry_shell_get_type      (void) G_GNUC_CONST;
-void            gdaui_entry_shell_pack_entry    (GdauiEntryShell *shell, GtkWidget *main_widget);
-void            gdaui_entry_shell_refresh       (GdauiEntryShell *shell);
-void            gdaui_entry_shell_set_unknown   (GdauiEntryShell *shell, gboolean unknown);
-void            gdaui_entry_shell_set_ucolor    (GdauiEntryShell *shell, gdouble red, gdouble green,
-                                                gdouble blue, gdouble alpha);
+GType           gdaui_entry_shell_get_type          (void) G_GNUC_CONST;
+void            gdaui_entry_shell_pack_entry        (GdauiEntryShell *shell, GtkWidget *entry);
+void            gdaui_entry_shell_set_invalid_color (GdauiEntryShell *shell, gdouble red, gdouble green,
+                                                    gdouble blue, gdouble alpha);
 
+/* private */
+void           _gdaui_entry_shell_mark_editable     (GdauiEntryShell *shell, gboolean editable);
+void           _gdaui_entry_shell_attrs_changed     (GdauiEntryShell *shell, GdaValueAttribute attr);
 
 G_END_DECLS
 
diff --git a/libgda-ui/data-entries/gdaui-entry-string.c b/libgda-ui/data-entries/gdaui-entry-string.c
index 8935963..2eecf00 100644
--- a/libgda-ui/data-entries/gdaui-entry-string.c
+++ b/libgda-ui/data-entries/gdaui-entry-string.c
@@ -87,8 +87,6 @@ struct _GdauiEntryStringPrivate
        GtkWidget     *view;
 
        gint           maxsize;
-
-       gulong         entry_change_sig;
 };
 
 static void
@@ -182,8 +180,6 @@ gdaui_entry_string_init (GdauiEntryString *mgstr)
 
        mgstr->priv->maxsize = 65535; /* eg. unlimited for GtkEntry */
 
-       mgstr->priv->entry_change_sig = 0;
-
        g_signal_connect (mgstr, "key-press-event",
                          G_CALLBACK (key_press_event_cb), NULL);
 }
@@ -192,8 +188,9 @@ gdaui_entry_string_init (GdauiEntryString *mgstr)
  * gdaui_entry_string_new:
  * @dh: the data handler to be used by the new widget
  * @type: the requested data type (compatible with @dh)
+ * @options: (allow-none): some options formatting the new entry, or %NULL
  *
- * Creates a new data entry widget
+ * Creates a new data entry widget. Known options are: MAX_SIZE, MULTILINE, and HIDDEN
  *
  * Returns: (transfer full): the new widget
  */
@@ -320,6 +317,13 @@ gdaui_entry_string_get_property (GObject *object,
 }
 
 static void widget_shown_cb (GtkWidget *wid, GdauiEntryString *mgstr);
+static void
+ev_cb (GtkWidget *wid, GdkEvent *event, GObject *obj)
+{
+       /* see /usr/include/gtk-3.0/gdk/gdkevents.h */
+        if ((event->type == GDK_FOCUS_CHANGE) && !((GdkEventFocus*)event)->in)
+               g_signal_emit_by_name (obj, "event-after", event);
+}
 
 static GtkWidget *
 create_entry (GdauiEntryWrapper *mgwrap)
@@ -332,7 +336,9 @@ create_entry (GdauiEntryWrapper *mgwrap)
        g_return_val_if_fail (mgstr->priv, NULL);
 
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       gtk_widget_set_hexpand (GTK_WIDGET (mgwrap), TRUE);
        mgstr->priv->vbox = vbox;
+       gtk_widget_add_events (vbox, GDK_FOCUS_CHANGE_MASK);
 
        /* one line entry */
        mgstr->priv->entry = gdaui_entry_new (NULL, NULL);
@@ -343,6 +349,7 @@ create_entry (GdauiEntryWrapper *mgwrap)
 
        /* multiline entry */
        mgstr->priv->view = gtk_text_view_new ();
+       gtk_widget_set_vexpand (mgstr->priv->view, TRUE);
        mgstr->priv->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (mgstr->priv->view));
        mgstr->priv->sw = gtk_scrolled_window_new (NULL, NULL);
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (mgstr->priv->sw), GTK_SHADOW_IN);
@@ -355,11 +362,14 @@ create_entry (GdauiEntryWrapper *mgwrap)
        g_signal_connect_after (G_OBJECT (mgstr->priv->sw), "show", 
                                G_CALLBACK (widget_shown_cb), mgstr);
 
-
-       /* show widgets if they need to be shown */
+       /* mark both widgets to be shown */
        gtk_widget_show (mgstr->priv->entry);
        gtk_widget_show (mgstr->priv->sw);
 
+       g_signal_connect (mgstr->priv->entry, "event-after",
+                          G_CALLBACK (ev_cb), vbox);
+       g_signal_connect (mgstr->priv->view, "event-after",
+                          G_CALLBACK (ev_cb), vbox);
        return vbox;
 }
 
@@ -465,13 +475,13 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
        mgstr = GDAUI_ENTRY_STRING (mgwrap);
        g_return_if_fail (mgstr->priv);
 
-       mgstr->priv->entry_change_sig = g_signal_connect (G_OBJECT (mgstr->priv->entry), "changed",
-                                                         modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgstr->priv->entry), "activate",
-                         activate_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgstr->priv->entry), "changed",
+                                 modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgstr->priv->entry), "activate",
+                                 activate_cb, mgwrap);
 
-       g_signal_connect (G_OBJECT (mgstr->priv->buffer), "changed",
-                         modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgstr->priv->buffer), "changed",
+                                 modify_cb, mgwrap);
        /* FIXME: how does the user "activates" the GtkTextView widget ? */
 }
 
@@ -541,7 +551,6 @@ gdaui_entry_string_start_editing (GtkCellEditable *iface, GdkEvent *event)
                          G_CALLBACK (gtk_cell_editable_entry_editing_done_cb), mgstr);
        g_signal_connect (mgstr->priv->entry, "remove-widget",
                          G_CALLBACK (gtk_cell_editable_entry_remove_widget_cb), mgstr);
-       gdaui_entry_shell_refresh (GDAUI_ENTRY_SHELL (mgstr));
        
        gtk_widget_grab_focus (mgstr->priv->entry);
        gtk_widget_queue_draw (GTK_WIDGET (mgstr));
diff --git a/libgda-ui/data-entries/gdaui-entry-string.xml.in 
b/libgda-ui/data-entries/gdaui-entry-string.xml.in
index 640bc0e..19d7a4a 100644
--- a/libgda-ui/data-entries/gdaui-entry-string.xml.in
+++ b/libgda-ui/data-entries/gdaui-entry-string.xml.in
@@ -1,8 +1,10 @@
 <?xml version="1.0"?>
 <data-set-spec>
   <parameters>
-    <parameter id="MAX_SIZE" _name="Maximum length" _descr="Maximum acceptable length of the text" 
gdatype="gint"/>
-    <parameter id="MULTILINE" _name="Multiline" _descr="Display only one line, or a complete text editor" 
gdatype="gboolean"/>
-    <parameter id="HIDDEN" _name="Hidden" _descr="If set to TRUE, characters are all displayed using a 
single 'invisible' character, suitable to enter passwords" gdatype="gboolean"/>
+    <parameter id="MAX_SIZE" _name="Maximum length" _descr="Maximum acceptable length of the text" 
gdatype="gint" nullok="TRUE"/>
+    <parameter id="MULTILINE" _name="Multiline" _descr="Display only one line, or a complete text editor" 
gdatype="gboolean" nullok="TRUE"/>
+    <parameter id="HIDDEN" _name="Hidden" _descr="If set to TRUE, characters are all displayed using a 
single 'invisible' character, suitable to enter passwords" gdatype="gboolean" nullok="TRUE">
+      <gda_value>FALSE</gda_value>
+    </parameter>
   </parameters>
 </data-set-spec>
diff --git a/libgda-ui/data-entries/gdaui-entry-wrapper.c b/libgda-ui/data-entries/gdaui-entry-wrapper.c
index 8090f13..a744fbb 100644
--- a/libgda-ui/data-entries/gdaui-entry-wrapper.c
+++ b/libgda-ui/data-entries/gdaui-entry-wrapper.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2012 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  *
@@ -23,6 +23,8 @@
 #include <libgda/gda-data-handler.h>
 #include <libgda/gda-enums.h>
 
+/*#define DEBUG*/
+
 static void gdaui_entry_wrapper_class_init (GdauiEntryWrapperClass *klass);
 static void gdaui_entry_wrapper_init (GdauiEntryWrapper *wid);
 static void gdaui_entry_wrapper_dispose (GObject *object);
@@ -36,8 +38,8 @@ static void gdaui_entry_wrapper_get_property (GObject *object,
                                              GValue *value,
                                              GParamSpec *pspec);
 
-static void contents_changed_cb (GtkWidget *entry, GdauiEntryWrapper *wrapper);
-static void contents_activated_cb (GtkWidget *entry, GdauiEntryWrapper *wrapper);
+static void contents_changed_cb (GdauiEntryWrapper *wrapper);
+static void contents_activated_cb (GdauiEntryWrapper *wrapper);
 static void check_correct_init (GdauiEntryWrapper *wid);
 static void block_signals (GdauiEntryWrapper *wid);
 static void unblock_signals (GdauiEntryWrapper *wid);
@@ -79,9 +81,9 @@ struct  _GdauiEntryWrapperPriv {
        gboolean                  null_forced;
        gboolean                  default_forced;
 
+       gboolean                  invalid;
        gboolean                  null_possible;
        gboolean                  default_possible;
-       gboolean                  show_actions;
        gboolean                  editable;
        gboolean                  contents_has_changed; /* since this variable was reset */
 
@@ -175,22 +177,28 @@ check_correct_init (GdauiEntryWrapper *wrapper)
 
                klass = GDAUI_ENTRY_WRAPPER_CLASS (G_OBJECT_GET_CLASS (wrapper));
                if (! klass->create_entry) {
-                       g_warning ("create_entry () virtual function not implemented for object class %s\n",
+                       g_warning ("create_entry () virtual function not implemented for object class %s",
                                   G_OBJECT_TYPE_NAME (wrapper));
                        class_impl_error = TRUE;
                }
                if (! klass->real_set_value) {
-                       g_warning ("real_set_value () virtual function not implemented for object class %s\n",
+                       g_warning ("real_set_value () virtual function not implemented for object class %s",
                                   G_OBJECT_TYPE_NAME (wrapper));
                        class_impl_error = TRUE;
                }
                if (! klass->real_get_value) {
-                       g_warning ("real_get_value () virtual function not implemented for object class %s\n",
+                       g_warning ("real_get_value () virtual function not implemented for object class %s",
                                   G_OBJECT_TYPE_NAME (wrapper));
                        class_impl_error = TRUE;
                }
                if (! klass->connect_signals) {
-                       g_warning ("connect_signals () virtual function not implemented for object class 
%s\n",
+                       g_warning ("connect_signals () virtual function not implemented for object class %s",
+                                  G_OBJECT_TYPE_NAME (wrapper));
+                       class_impl_error = TRUE;
+               }
+               if ((klass->value_is_null && !klass->value_is_equal_to) ||
+                   (!klass->value_is_null && klass->value_is_equal_to)) {
+                       g_warning ("value_is_null() and value_is_equal_to() virtuals functions must eithe 
both be implemented for object class %s, or none must be implemented",
                                   G_OBJECT_TYPE_NAME (wrapper));
                        class_impl_error = TRUE;
                }
@@ -205,7 +213,7 @@ check_correct_init (GdauiEntryWrapper *wrapper)
                        wrapper->priv->entry = entry;
 
                        (*wrapper->priv->real_class->connect_signals) (wrapper, G_CALLBACK 
(contents_changed_cb),
-                                                                     G_CALLBACK (contents_activated_cb));
+                                                                      G_CALLBACK (contents_activated_cb));
                }
                else {
                        /* we need to exit because the program WILL BE unstable and WILL crash */
@@ -244,9 +252,9 @@ gdaui_entry_wrapper_init (GdauiEntryWrapper *wrapper)
        wrapper->priv->null_forced = FALSE;
        wrapper->priv->default_forced = FALSE;
 
+       wrapper->priv->invalid = FALSE;
        wrapper->priv->null_possible = TRUE;
        wrapper->priv->default_possible = FALSE;
-       wrapper->priv->show_actions = TRUE;
        wrapper->priv->editable = TRUE;
        wrapper->priv->contents_has_changed = FALSE;
 
@@ -347,7 +355,7 @@ gdaui_entry_wrapper_contents_changed (GdauiEntryWrapper *wrapper)
 {
        g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (wrapper));
 
-       contents_changed_cb (NULL, wrapper);
+       contents_changed_cb (wrapper);
 }
 
 /**
@@ -362,15 +370,17 @@ gdaui_entry_wrapper_contents_activated (GdauiEntryWrapper *wrapper)
 {
        g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (wrapper));
 
-       contents_activated_cb (NULL, wrapper);
+       contents_activated_cb (wrapper);
 }
 
 
 static void gdaui_entry_wrapper_emit_signal (GdauiEntryWrapper *wrapper);
 static void
-contents_changed_cb (G_GNUC_UNUSED GtkWidget *entry, GdauiEntryWrapper *wrapper)
+contents_changed_cb (GdauiEntryWrapper *wrapper)
 {
-       /* @entry is not used */
+#ifdef DEBUG
+       g_print ("%s(%p)\n", __FUNCTION__, wrapper);
+#endif
        if (! wrapper->priv->signals_blocked) {
                wrapper->priv->null_forced = FALSE;
                wrapper->priv->default_forced = FALSE;
@@ -380,34 +390,25 @@ contents_changed_cb (G_GNUC_UNUSED GtkWidget *entry, GdauiEntryWrapper *wrapper)
 }
 
 static void
-contents_activated_cb (G_GNUC_UNUSED GtkWidget *entry, GdauiEntryWrapper *wrapper)
+contents_activated_cb (GdauiEntryWrapper *wrapper)
 {
-       /* @entry is not used */
+#ifdef DEBUG
+       g_print ("%s(%p)\n", __FUNCTION__, wrapper);
+#endif
        if (! wrapper->priv->signals_blocked) {
                wrapper->priv->null_forced = FALSE;
                wrapper->priv->default_forced = FALSE;
-#ifdef debug_signal
-               g_print (">> 'CONTENTS_ACTIVATED' from %s\n", __FUNCTION__);
-#endif
                g_signal_emit_by_name (G_OBJECT (wrapper), "contents-activated");
-#ifdef debug_signal
-               g_print ("<< 'CONTENTS_ACTIVATED' from %s\n", __FUNCTION__);
-#endif
        }
 }
 
 static void
 gdaui_entry_wrapper_emit_signal (GdauiEntryWrapper *wrapper)
 {
-       if (! wrapper->priv->signals_blocked) {
-#ifdef debug_signal
-               g_print (">> 'CONTENTS_MODIFIED' from %s\n", __FUNCTION__);
-#endif
+       if (! wrapper->priv->signals_blocked)
                g_signal_emit_by_name (G_OBJECT (wrapper), "contents-modified");
-#ifdef debug_signal
-               g_print ("<< 'CONTENTS_MODIFIED' from %s\n", __FUNCTION__);
-#endif
-       }
+       _gdaui_entry_shell_attrs_changed (GDAUI_ENTRY_SHELL (wrapper),
+                                         gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (wrapper)));
 }
 
 
@@ -528,13 +529,13 @@ gdaui_entry_wrapper_set_ref_value (GdauiDataEntry *iface, const GValue *value)
                changed = ! wrapper->priv->real_class->value_is_equal_to (wrapper, value);
        else {
                evalue = gdaui_entry_wrapper_get_value (iface);
+               g_assert (evalue);
                if ((!value || (G_VALUE_TYPE (value) == GDA_TYPE_NULL)) &&
-                   (!evalue || (G_VALUE_TYPE (evalue) == GDA_TYPE_NULL)))
+                   (G_VALUE_TYPE (evalue) == GDA_TYPE_NULL))
                        changed = FALSE;
                else if (!gda_value_differ ((GValue *) value, evalue))
                        changed = FALSE;
-               if (evalue)
-                       gda_value_free (evalue);
+               gda_value_free (evalue);
        }
 
        /* get rid on any existing orig value */
@@ -595,13 +596,12 @@ gdaui_entry_wrapper_set_value_default (GdauiDataEntry *iface, const GValue *valu
                        gdaui_entry_wrapper_set_value (iface, wrapper->priv->value_default);
                        unblock_signals (wrapper);
                        wrapper->priv->default_forced = TRUE;
-                       gdaui_entry_wrapper_emit_signal (wrapper);
                }
                else {
                        check_correct_init (wrapper);
                        (*wrapper->priv->real_class->real_set_value) (wrapper, NULL);
-                       gdaui_entry_wrapper_emit_signal (wrapper);
                }
+               gdaui_entry_wrapper_emit_signal (wrapper);
        }
 }
 
@@ -609,17 +609,42 @@ static void
 gdaui_entry_wrapper_set_attributes (GdauiDataEntry *iface, GdaValueAttribute attrs, guint mask)
 {
        GdauiEntryWrapper *wrapper;
-       gboolean signal_contents_changed = FALSE;
+       gboolean do_signal = FALSE;
 
        g_return_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface));
        wrapper = (GdauiEntryWrapper*) iface;
        check_correct_init (wrapper);
 
+#ifdef DEBUG
+       g_print ("%s (%p): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", __FUNCTION__, iface,
+                (mask & GDA_VALUE_ATTR_IS_NULL) ? "IS_NULL:" : "",
+                (mask & GDA_VALUE_ATTR_IS_NULL) ? ((attrs & GDA_VALUE_ATTR_IS_NULL) ? "X" : ".") : "",
+                (mask & GDA_VALUE_ATTR_CAN_BE_NULL) ? "CAN_BE_NULL:" : "",
+                (mask & GDA_VALUE_ATTR_CAN_BE_NULL) ? ((attrs & GDA_VALUE_ATTR_CAN_BE_NULL) ? "X" : ".") : 
"",
+                (mask & GDA_VALUE_ATTR_IS_DEFAULT) ? "IS_DEFAULT:" : "",
+                (mask & GDA_VALUE_ATTR_IS_DEFAULT) ? ((attrs & GDA_VALUE_ATTR_IS_DEFAULT) ? "X" : ".") : "",
+                (mask & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? "CAN_BE_DEFAULT:" : "",
+                (mask & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? ((attrs & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? "X" : 
".") : "",
+                (mask & GDA_VALUE_ATTR_IS_UNCHANGED) ? "IS_UNCHANGED:" : "",
+                (mask & GDA_VALUE_ATTR_IS_UNCHANGED) ? ((attrs & GDA_VALUE_ATTR_IS_UNCHANGED) ? "X" : ".") : 
"",
+                (mask & GDA_VALUE_ATTR_DATA_NON_VALID) ? "NON_VALID:" : "",
+                (mask & GDA_VALUE_ATTR_DATA_NON_VALID) ? ((attrs & GDA_VALUE_ATTR_DATA_NON_VALID) ? "X" : 
".") : "",
+                (mask & GDA_VALUE_ATTR_READ_ONLY) ? "READ_ONLY:" : "",
+                (mask & GDA_VALUE_ATTR_READ_ONLY) ? ((attrs & GDA_VALUE_ATTR_READ_ONLY) ? "X" : ".") : "",
+                (mask & GDA_VALUE_ATTR_HAS_VALUE_ORIG) ? "HAS_VALUE_ORIG:" : "",
+                (mask & GDA_VALUE_ATTR_HAS_VALUE_ORIG) ? ((attrs & GDA_VALUE_ATTR_HAS_VALUE_ORIG) ? "X" : 
".") : "");
+#endif
+
+       /* Can be NULL ? */
+       if (mask & GDA_VALUE_ATTR_CAN_BE_NULL)
+               wrapper->priv->null_possible = (attrs & GDA_VALUE_ATTR_CAN_BE_NULL) ? TRUE : FALSE;
+
+       /* Can be DEFAULT ? */
+       if (mask & GDA_VALUE_ATTR_CAN_BE_DEFAULT)
+               wrapper->priv->default_possible = (attrs & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? TRUE : FALSE;
+
        /* Setting to NULL */
        if (mask & GDA_VALUE_ATTR_IS_NULL) {
-               if ((mask & GDA_VALUE_ATTR_CAN_BE_NULL) &&
-                   !(attrs & GDA_VALUE_ATTR_CAN_BE_NULL))
-                       g_return_if_reached ();
                if (attrs & GDA_VALUE_ATTR_IS_NULL) {
                        block_signals (wrapper);
                        gdaui_entry_wrapper_set_value (iface, NULL);
@@ -627,91 +652,74 @@ gdaui_entry_wrapper_set_attributes (GdauiDataEntry *iface, GdaValueAttribute att
                        wrapper->priv->null_forced = TRUE;
 
                        /* if default is set, see if we can keep it that way */
-                       if (wrapper->priv->default_forced) {
-                               if (G_VALUE_TYPE (wrapper->priv->value_default) !=
-                                   GDA_TYPE_NULL) {
+                       if (wrapper->priv->default_forced &&
+                           (G_VALUE_TYPE (wrapper->priv->value_default) != GDA_TYPE_NULL))
                                        wrapper->priv->default_forced = FALSE;
-                               }
-                       }
                }
                else
                        wrapper->priv->null_forced = FALSE;
-               signal_contents_changed = TRUE;
+               do_signal = TRUE;
        }
 
-       /* Can be NULL ? */
-       if (mask & GDA_VALUE_ATTR_CAN_BE_NULL)
-               wrapper->priv->null_possible = (attrs & GDA_VALUE_ATTR_CAN_BE_NULL) ? TRUE : FALSE;
-
        /* Setting to DEFAULT */
-       guint current = gdaui_data_entry_get_attributes (iface);
        if (mask & GDA_VALUE_ATTR_IS_DEFAULT) {
-               if (! (current & GDA_VALUE_ATTR_CAN_BE_DEFAULT))
-                       g_warning ("Data entry does not have a default value");
                if (attrs & GDA_VALUE_ATTR_IS_DEFAULT) {
-                       block_signals (wrapper);
-                       if (wrapper->priv->value_default) {
-                               if (G_VALUE_TYPE (wrapper->priv->value_default) == wrapper->priv->type)
-                                       gdaui_entry_wrapper_set_value (iface, wrapper->priv->value_default);
-                               else
-                                       (*wrapper->priv->real_class->real_set_value) (wrapper, NULL);
+                       if (! wrapper->priv->default_possible) {
+                               g_warning ("Data entry does not have a default value");
+                               wrapper->priv->default_forced = FALSE;
                        }
-                       else
-                               gdaui_entry_wrapper_set_value (iface, NULL);
-                       unblock_signals (wrapper);
+                       else {
+                               block_signals (wrapper);
+                               if (wrapper->priv->value_default) {
+                                       if (G_VALUE_TYPE (wrapper->priv->value_default) == 
wrapper->priv->type)
+                                               gdaui_entry_wrapper_set_value (iface, 
wrapper->priv->value_default);
+                                       else
+                                               (*wrapper->priv->real_class->real_set_value) (wrapper, NULL);
+                               }
+                               else
+                                       gdaui_entry_wrapper_set_value (iface, NULL);
+                               unblock_signals (wrapper);
 
-                       /* if NULL is set, see if we can keep it that way */
-                       if (wrapper->priv->null_forced) {
-                               if (G_VALUE_TYPE (wrapper->priv->value_default) !=
-                                   GDA_TYPE_NULL)
+                               /* if NULL is set, see if we can keep it that way */
+                               if (wrapper->priv->null_forced &&
+                                   (G_VALUE_TYPE (wrapper->priv->value_default) != GDA_TYPE_NULL))
                                        wrapper->priv->null_forced = FALSE;
+                               wrapper->priv->default_forced = TRUE;
                        }
-
-                       wrapper->priv->default_forced = TRUE;
                }
                else
                        wrapper->priv->default_forced = FALSE;
 
-               signal_contents_changed = TRUE;
+               do_signal = TRUE;
        }
 
-       /* Can be DEFAULT ? */
-       if (mask & GDA_VALUE_ATTR_CAN_BE_DEFAULT)
-               wrapper->priv->default_possible = (attrs & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? TRUE : FALSE;
-
-       /* Modified ? */
+       /* Reset value to original */
        if (mask & GDA_VALUE_ATTR_IS_UNCHANGED) {
                if (attrs & GDA_VALUE_ATTR_IS_UNCHANGED) {
                        wrapper->priv->default_forced = FALSE;
                        block_signals (wrapper);
                        gdaui_entry_wrapper_set_value (iface, wrapper->priv->value_ref);
                        unblock_signals (wrapper);
-                       signal_contents_changed = TRUE;
+                       do_signal = TRUE;
                }
        }
 
-       /* Actions buttons ? */
-       if (mask & GDA_VALUE_ATTR_ACTIONS_SHOWN) {
-               GValue *gval;
-               wrapper->priv->show_actions = (attrs & GDA_VALUE_ATTR_ACTIONS_SHOWN) ? TRUE : FALSE;
+       /* invalid data */
+       if (mask & GDA_VALUE_ATTR_DATA_NON_VALID)
+               wrapper->priv->invalid = attrs & GDA_VALUE_ATTR_DATA_NON_VALID;
 
-               gval = g_new0 (GValue, 1);
-               g_value_init (gval, G_TYPE_BOOLEAN);
-               g_value_set_boolean (gval, wrapper->priv->show_actions);
-               g_object_set_property (G_OBJECT (wrapper), "actions", gval);
-               g_free (gval);
-       }
+       /* editable */
+       if (mask & GDA_VALUE_ATTR_READ_ONLY)
+               gdaui_entry_wrapper_set_editable (GDAUI_DATA_ENTRY (wrapper), attrs & 
GDA_VALUE_ATTR_READ_ONLY);
 
        /* NON WRITABLE attributes */
-       if (mask & GDA_VALUE_ATTR_DATA_NON_VALID)
-               g_warning ("Can't force a GdauiDataEntry to be invalid!");
-
        if (mask & GDA_VALUE_ATTR_HAS_VALUE_ORIG)
-               g_warning ("Having an original value is not a write attribute on GdauiDataEntry!");
+               g_warning ("Use gdaui_entry_wrapper_set_value_default() instead of 
GDA_VALUE_ATTR_HAS_VALUE_ORIG");
 
-       current = gdaui_data_entry_get_attributes (iface);
+       _gdaui_entry_shell_attrs_changed (GDAUI_ENTRY_SHELL (wrapper),
+                                         gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (wrapper)));
 
-       if (signal_contents_changed) {
+       if (do_signal) {
                wrapper->priv->contents_has_changed = FALSE;
                gdaui_entry_wrapper_emit_signal (wrapper);
        }
@@ -724,24 +732,36 @@ gdaui_entry_wrapper_get_attributes (GdauiDataEntry *iface)
        GdaValueAttribute retval = 0;
        GdauiEntryWrapper *wrapper;
        GValue *value = NULL;
-       gboolean has_current_value;
-       gboolean value_is_null = FALSE;
 
        g_return_val_if_fail (GDAUI_IS_ENTRY_WRAPPER (iface), 0);
        wrapper = (GdauiEntryWrapper*) iface;
 
        check_correct_init (wrapper);
+
+       gboolean specific_impl = TRUE;
        if (!wrapper->priv->real_class->value_is_equal_to ||
            !wrapper->priv->real_class->value_is_null) {
-               value = gdaui_entry_wrapper_get_value (iface);
-               has_current_value = TRUE;
+               value = gdaui_entry_wrapper_get_value (iface); /* @value may NOT be @NULL ! */
+               g_assert (value);
+               specific_impl = FALSE;
        }
-       else
-               has_current_value = FALSE;
+
+       /* can be NULL? */
+       if (wrapper->priv->null_possible)
+               retval |= GDA_VALUE_ATTR_CAN_BE_NULL;
+
+       /* can be default? */
+       if (wrapper->priv->default_possible)
+               retval |= GDA_VALUE_ATTR_CAN_BE_DEFAULT;
 
        /* NULL? */
-       if (has_current_value) {
-               if ((value && (G_VALUE_TYPE (value) == GDA_TYPE_NULL)) || !value) {
+       gboolean value_is_null = FALSE;
+       if (specific_impl) {
+               if ((wrapper->priv->real_class->value_is_null) (wrapper))
+                       value_is_null = TRUE;
+       }
+       else {
+               if (G_VALUE_TYPE (value) == GDA_TYPE_NULL) {
                        if (wrapper->priv->default_forced) {
                                if (wrapper->priv->null_forced)
                                        value_is_null = TRUE;
@@ -750,61 +770,52 @@ gdaui_entry_wrapper_get_attributes (GdauiDataEntry *iface)
                                value_is_null = TRUE;
                }
        }
-       else {
-               if ((wrapper->priv->real_class->value_is_null) (wrapper))
-                       value_is_null = TRUE;
-       }
        if (value_is_null)
-               retval = retval | GDA_VALUE_ATTR_IS_NULL;
-
-       /* can be NULL? */
-       if (wrapper->priv->null_possible)
-               retval = retval | GDA_VALUE_ATTR_CAN_BE_NULL;
+               retval |= GDA_VALUE_ATTR_IS_NULL;
 
        /* is default */
        if (wrapper->priv->default_forced)
-               retval = retval | GDA_VALUE_ATTR_IS_DEFAULT;
-
-       /* can be default? */
-       if (wrapper->priv->default_possible)
-               retval = retval | GDA_VALUE_ATTR_CAN_BE_DEFAULT;
-
-       /* is unchanged */
-       if (has_current_value) {
-               if (wrapper->priv->value_ref &&
-                   (G_VALUE_TYPE (value) == G_VALUE_TYPE (wrapper->priv->value_ref))) {
-                       if (gda_value_is_null (value))
-                               retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
-                       else {
+               retval |= GDA_VALUE_ATTR_IS_DEFAULT;
+       else {
+               /* is unchanged */
+               if (wrapper->priv->value_ref) {
+                       if (specific_impl) {
+                               if ((wrapper->priv->real_class->value_is_equal_to) (wrapper, 
wrapper->priv->value_ref))
+                                       retval |= GDA_VALUE_ATTR_IS_UNCHANGED;
+                       }
+                       else if (G_VALUE_TYPE (value) == G_VALUE_TYPE (wrapper->priv->value_ref)) {
                                if (! gda_value_differ (value, wrapper->priv->value_ref))
-                                       retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
+                                       retval |= GDA_VALUE_ATTR_IS_UNCHANGED;
                        }
                }
        }
-       else if ((wrapper->priv->real_class->value_is_equal_to) (wrapper, wrapper->priv->value_ref))
-               retval = retval | GDA_VALUE_ATTR_IS_UNCHANGED;
-
-       /* actions shown */
-       if (wrapper->priv->show_actions)
-               retval = retval | GDA_VALUE_ATTR_ACTIONS_SHOWN;
 
        /* data valid? */
-       if (! (wrapper->priv->default_forced && wrapper->priv->default_possible)) {
-               if (/*(value_is_null && !wrapper->priv->null_forced) ||*/
-                   (value_is_null && !wrapper->priv->null_possible))
-                       retval = retval | GDA_VALUE_ATTR_DATA_NON_VALID;
-       }
+       if (wrapper->priv->invalid ||
+           (value_is_null && !wrapper->priv->null_possible))
+               retval |= GDA_VALUE_ATTR_DATA_NON_VALID;
 
        /* has original value? */
        if (wrapper->priv->value_ref)
-               retval = retval | GDA_VALUE_ATTR_HAS_VALUE_ORIG;
+               retval |= GDA_VALUE_ATTR_HAS_VALUE_ORIG;
 
-       if (has_current_value)
-               gda_value_free (value);
+       gda_value_free (value);
 
+       /* editable ? */
        if (!wrapper->priv->editable)
-               retval = retval | GDA_VALUE_ATTR_NO_MODIF;
-
+               retval |= GDA_VALUE_ATTR_READ_ONLY;
+
+#ifdef DEBUG
+       g_print ("%s (%p): %s%s%s%s%s%s%s%s\n", __FUNCTION__, iface,
+                (retval & GDA_VALUE_ATTR_IS_NULL) ? "IS_NULL " : "        ",
+                (retval & GDA_VALUE_ATTR_CAN_BE_NULL) ? "CAN_BE_NULL " : "            ",
+                (retval & GDA_VALUE_ATTR_IS_DEFAULT) ? "IS_DEFAULT " : "           ",
+                (retval & GDA_VALUE_ATTR_CAN_BE_DEFAULT) ? "CAN_BE_DEFAULT " : "               ",
+                (retval & GDA_VALUE_ATTR_IS_UNCHANGED) ? "IS_UNCHANGED " : "             ",
+                (retval & GDA_VALUE_ATTR_DATA_NON_VALID) ? "NON_VALID " : "          ",
+                (retval & GDA_VALUE_ATTR_READ_ONLY) ? "READ_ONLY " : "          ",
+                (retval & GDA_VALUE_ATTR_HAS_VALUE_ORIG) ? "HAS_VALUE_ORIG " : "               ");
+#endif
        return retval;
 }
 
@@ -837,6 +848,7 @@ gdaui_entry_wrapper_set_editable (GdauiDataEntry *iface, gboolean editable)
                (wrapper->priv->real_class->set_editable) (wrapper, editable);
        else
                gtk_widget_set_sensitive (GTK_WIDGET (iface), editable);
+       _gdaui_entry_shell_mark_editable (GDAUI_ENTRY_SHELL (wrapper), editable);
 }
 
 static gboolean
@@ -873,5 +885,5 @@ static void
 gdaui_entry_wrapper_set_unknown_color (GdauiDataEntry *de, gdouble red, gdouble green,
                                       gdouble blue, gdouble alpha)
 {
-       gdaui_entry_shell_set_ucolor (GDAUI_ENTRY_SHELL (de), red, green, blue, alpha);
+       gdaui_entry_shell_set_invalid_color (GDAUI_ENTRY_SHELL (de), red, green, blue, alpha);
 }
diff --git a/libgda-ui/data-entries/gdaui-entry.c b/libgda-ui/data-entries/gdaui-entry.c
index ccd9abb..9db3196 100644
--- a/libgda-ui/data-entries/gdaui-entry.c
+++ b/libgda-ui/data-entries/gdaui-entry.c
@@ -35,6 +35,7 @@ struct _GdauiEntryPrivate {
        gint     maxlen; /* UTF8 len */
        gboolean isnull;
        guchar   internal_changes;
+       gint     max_width;
 };
 
 #define ENTER_INTERNAL_CHANGES(entry) (entry)->priv->internal_changes ++
@@ -83,6 +84,8 @@ static void signal_handlers_unblock (GdauiEntry *entry);
 static void changed_cb (GtkEditable *editable, gpointer data);
 static void delete_text_cb (GtkEditable *editable, gint start_pos, gint end_pos, gpointer data);
 static void insert_text_cb (GtkEditable *editable, const gchar *text, gint length, gint *position, gpointer 
data);
+static void internal_insert_text (GtkEditable *editable, const gchar *text, gint text_length, gint *position,
+                                 gboolean handle_default_insert);
 
 
 static GObjectClass *parent_class = NULL;
@@ -146,6 +149,7 @@ gdaui_entry_init (GdauiEntry *entry)
        entry->priv->maxlen = 65535; /* eg. unlimited for GtkEntry */
        entry->priv->isnull = TRUE;
        entry->priv->internal_changes = 0;
+       entry->priv->max_width = -1;
 
        g_signal_connect (G_OBJECT (entry), "delete-text",
                          G_CALLBACK (delete_text_cb), NULL);
@@ -208,6 +212,7 @@ gdaui_entry_set_property (GObject *object,
                        }
                        adjust_display (entry, otext);
                        g_free (otext);
+                       gdaui_entry_set_width_chars (entry, entry->priv->max_width);
                         break;
                 case PROP_SUFFIX:
                        otext = gdaui_entry_get_text (entry);
@@ -227,18 +232,20 @@ gdaui_entry_set_property (GObject *object,
                        }
                        adjust_display (entry, otext);
                        g_free (otext);
+                       gdaui_entry_set_width_chars (entry, entry->priv->max_width);
                         break;
                case PROP_MAXLEN:
                        entry->priv->maxlen = g_value_get_int (value);
                        otext = gdaui_entry_get_text (entry);
                        adjust_display (entry, otext);
                        g_free (otext);
+                       gdaui_entry_set_width_chars (entry, entry->priv->max_width);
                        break;
                 default:
                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                         break;
                 }
-        }      
+        }
 }
 
 static void
@@ -435,18 +442,28 @@ gdaui_entry_set_text (GdauiEntry *entry, const gchar *text)
                gtk_entry_set_text (GTK_ENTRY (entry), "");
                signal_handlers_unblock (entry);
                ENTER_INTERNAL_CHANGES(entry);
-               gtk_entry_set_text (GTK_ENTRY (entry), text); /* emits the "insert-text" signal which is 
treated */
+
+               if (entry->priv->internal_changes ==  1) {
+                       /* function has been called by "external" programmer,
+                        * emits the "insert-text" signal which is treated */
+                       gtk_entry_set_text (GTK_ENTRY (entry), text);
+               }
+               else {
+                       /* function has been called by a subsequent call of one of
+                        * the descendant's implementation */
+                       gint pos = 0;
+                       internal_insert_text (GTK_EDITABLE (entry), text, g_utf8_strlen (text, -1), &pos, 
TRUE);
+               }
                entry->priv->isnull = FALSE; /* in case it has not been set */
                LEAVE_INTERNAL_CHANGES(entry);
-               g_signal_emit_by_name (entry, "changed");
        }
        else {
                entry->priv->isnull = TRUE;
                signal_handlers_block (entry);
                gtk_entry_set_text (GTK_ENTRY (entry), "");
                signal_handlers_unblock (entry);
-               g_signal_emit_by_name (entry, "changed");
        }
+       g_signal_emit_by_name (entry, "changed");
 }
 
 /**
@@ -487,7 +504,7 @@ gdaui_entry_set_suffix (GdauiEntry *entry, const gchar *suffix)
  * @entry: a #GdauiEntry widget
  * @max_width: maximum width, or -1
  *
- * Sets @entry's maximum width in characters, without taking into account
+ * Sets @entry's width in characters, without taking into account
  * any prefix or suffix (which will automatically be handled). If you want to take
  * a prefix or suffix into account direclty, then use gtk_entry_set_width_chars()
  */
@@ -495,12 +512,17 @@ void
 gdaui_entry_set_width_chars (GdauiEntry *entry, gint max_width)
 {
        g_return_if_fail (GDAUI_IS_ENTRY (entry));
-       if (max_width < 0)
+       entry->priv->max_width = max_width;
+       if (max_width < 0) {
                gtk_entry_set_width_chars (GTK_ENTRY (entry), -1);
+               gtk_widget_set_hexpand (GTK_WIDGET (entry), TRUE);
+       }
        else {
-               max_width += entry->priv->prefix_clen;
-               max_width += entry->priv->suffix_clen;
+               max_width += (entry->priv->prefix_clen > 0 ? entry->priv->prefix_clen + 1 : 0);
+               max_width += (entry->priv->suffix_clen > 0 ? entry->priv->suffix_clen + 1 : 0);
                gtk_entry_set_width_chars (GTK_ENTRY (entry), max_width);
+               gtk_entry_set_max_width_chars (GTK_ENTRY (entry), max_width);
+               gtk_widget_set_hexpand (GTK_WIDGET (entry), FALSE);
        }
 }
 
@@ -578,11 +600,11 @@ delete_text_cb (GtkEditable *editable, gint start_pos, gint end_pos, G_GNUC_UNUS
        g_signal_emit_by_name (entry, "changed");
 }
 
-
 static void
-insert_text_cb (GtkEditable *editable, const gchar *text, gint text_length, gint *position,
-               G_GNUC_UNUSED gpointer data)
+internal_insert_text (GtkEditable *editable, const gchar *text, gint text_length, gint *position,
+                     gboolean handle_default_insert)
 {
+       /*g_print ("%s ([%s] @ %d)\n", __FUNCTION__, text, *position);*/
        const gchar *otext;
        gint clen;
        GdauiEntry *entry = GDAUI_ENTRY (editable);
@@ -618,7 +640,19 @@ insert_text_cb (GtkEditable *editable, const gchar *text, gint text_length, gint
 
        /* test if the whole insertion is Ok */
        text_clen = g_utf8_strlen (text, text_length);
-       if (clen - entry->priv->prefix_clen - entry->priv->suffix_clen + text_clen > entry->priv->maxlen) {
+       if (GDAUI_ENTRY_GET_CLASS (editable)->assume_insert) {
+               /* Subclass assumes text insert */
+               gint pos = *position - entry->priv->prefix_clen;
+               GDAUI_ENTRY_GET_CLASS (editable)->assume_insert (entry, text, text_length,
+                                                                &pos, entry->priv->prefix_clen);
+               *position = pos + entry->priv->prefix_clen;
+
+               g_signal_stop_emission_by_name (editable, "insert-text");
+               signal_handlers_unblock (entry);
+               g_signal_emit_by_name (entry, "changed");
+       }
+       else if (clen - entry->priv->prefix_clen - entry->priv->suffix_clen + text_clen > 
entry->priv->maxlen) {
+               /* text to insert is too long and needs to be truncated */
                gchar *itext;
                gint nallowed;
                nallowed = entry->priv->maxlen - (clen - entry->priv->prefix_clen - entry->priv->suffix_clen);
@@ -633,17 +667,22 @@ insert_text_cb (GtkEditable *editable, const gchar *text, gint text_length, gint
                signal_handlers_unblock (entry);
                g_signal_emit_by_name (entry, "changed");
        }
-       else if (GDAUI_ENTRY_GET_CLASS (editable)->assume_insert) {
-               g_signal_stop_emission_by_name (editable, "insert-text");
-               //g_print ("Subclass assumes text insert\n");
-               gint pos = *position - entry->priv->prefix_clen;
-               GDAUI_ENTRY_GET_CLASS (editable)->assume_insert (entry, text, text_length,
-                                                                &pos, entry->priv->prefix_clen);
-               *position = pos + entry->priv->prefix_clen;
-
-               signal_handlers_unblock (entry);
-               g_signal_emit_by_name (entry, "changed");
+       else {
+               if (handle_default_insert) {
+                       ENTER_INTERNAL_CHANGES(entry);
+                       gtk_editable_insert_text (editable, text, text_length, position);
+                       LEAVE_INTERNAL_CHANGES(entry);
+                       signal_handlers_unblock (entry);
+                       g_signal_emit_by_name (entry, "changed");
+               }
+               else
+                       signal_handlers_unblock (entry);
        }
-       else
-               signal_handlers_unblock (entry);
+}
+
+static void
+insert_text_cb (GtkEditable *editable, const gchar *text, gint text_length, gint *position,
+               G_GNUC_UNUSED gpointer data)
+{
+       internal_insert_text (editable, text, text_length, position, FALSE);
 }
diff --git a/libgda-ui/data-entries/gdaui-formatted-entry.c b/libgda-ui/data-entries/gdaui-formatted-entry.c
index 14e9ce1..d0d7c21 100644
--- a/libgda-ui/data-entries/gdaui-formatted-entry.c
+++ b/libgda-ui/data-entries/gdaui-formatted-entry.c
@@ -394,7 +394,7 @@ gdaui_formatted_entry_assume_delete (GdauiEntry *entry, gint virt_start_pos, gin
 #endif
 
        g_assert (virt_end_pos <= fentry->priv->format_clen);
-       
+
        /* move fptr to the @virt_start_pos in fentry->priv->format */
        for (fptr = fentry->priv->format, i = 0;
             (i < virt_start_pos) && *fptr;
diff --git a/libgda-ui/data-entries/gdaui-numeric-entry.c b/libgda-ui/data-entries/gdaui-numeric-entry.c
index 77ecaa7..bd9ea08 100644
--- a/libgda-ui/data-entries/gdaui-numeric-entry.c
+++ b/libgda-ui/data-entries/gdaui-numeric-entry.c
@@ -37,6 +37,7 @@ typedef struct {
         gdouble   fmax;
         gboolean  is_int;
         gboolean  is_signed;
+       guint8    max_nchars;
 } NumAttr;
 
 struct _GdauiNumericEntryPrivate {
@@ -142,6 +143,7 @@ compute_numeric_attributes (GType type, NumAttr *attr)
         attr->is_int = FALSE;
         attr->is_signed = TRUE;
         attr->is_numerical = TRUE;
+       attr->max_nchars = 0;
 
         if (type == G_TYPE_INT64) {
                 attr->imax = G_MAXINT64;
@@ -189,6 +191,7 @@ compute_numeric_attributes (GType type, NumAttr *attr)
                 attr->fmax = G_MAXDOUBLE;
         }
         else if (type == GDA_TYPE_NUMERIC) {
+               attr->max_nchars = 30;
         }
         else if (type == GDA_TYPE_SHORT) {
                 attr->imax = G_MAXSHORT;
@@ -203,6 +206,21 @@ compute_numeric_attributes (GType type, NumAttr *attr)
         else {
                 attr->is_numerical = FALSE;
         }
+
+       if (attr->is_numerical && attr->is_int) {
+               guint64 number;
+               if (attr->is_signed) {
+                       number = (guint64) attr->imax;
+                       attr->max_nchars = 1; /* for the sign */
+               }
+               else
+                       number = attr->uimax;
+
+               do {
+                       number /= 10;
+                       attr->max_nchars ++;
+               } while (number != 0);
+       }
 }
 
 static gchar
@@ -227,7 +245,6 @@ gdaui_numeric_entry_init (GdauiNumericEntry *entry)
        entry->priv->decimal_sep = get_default_decimal_sep ();
        entry->priv->thousands_sep = 0;
        entry->priv->nb_decimals = G_MAXUINT16;
-       gtk_entry_set_width_chars (GTK_ENTRY (entry), 3);
 }
 
 static void 
@@ -302,6 +319,21 @@ gdaui_numeric_entry_set_property (GObject *object,
         }
        gdaui_entry_set_text (GDAUI_ENTRY (entry), otext);
        g_free (otext);
+
+       gint msize;
+       if (entry->priv->num_attr.max_nchars == 0)
+               msize = -1;
+       else {
+               msize = (gint) entry->priv->num_attr.max_nchars;
+               if (entry->priv->thousands_sep)
+                       msize += entry->priv->num_attr.max_nchars / 3;
+               if (! entry->priv->num_attr.is_int)
+                       msize += 1;
+               if (entry->priv->nb_decimals != G_MAXUINT16)
+                       msize += entry->priv->nb_decimals;
+       }
+       /*g_print ("GdauiNumericEntry: type %s => msize = %d\n", g_type_name (entry->priv->type), msize);*/
+       gdaui_entry_set_width_chars (GDAUI_ENTRY (entry), msize);
 }
 
 static void
diff --git a/libgda-ui/data-entries/plugins/gdaui-entry-cidr.c 
b/libgda-ui/data-entries/plugins/gdaui-entry-cidr.c
index 5796a35..e7593b0 100644
--- a/libgda-ui/data-entries/plugins/gdaui-entry-cidr.c
+++ b/libgda-ui/data-entries/plugins/gdaui-entry-cidr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2012 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  *
  * This library is free software; you can redistribute it and/or
@@ -585,8 +585,8 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
        mgcidr = GDAUI_ENTRY_CIDR (mgwrap);
        g_return_if_fail (mgcidr->priv);
 
-       g_signal_connect (G_OBJECT (mgcidr->priv->entry), "changed", modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgcidr->priv->entry), "activate", activate_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgcidr->priv->entry), "changed", modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgcidr->priv->entry), "activate", activate_cb, mgwrap);
 }
 
 static SplitValues *
diff --git a/libgda-ui/data-entries/plugins/gdaui-entry-filesel.c 
b/libgda-ui/data-entries/plugins/gdaui-entry-filesel.c
index f6591a5..c8ce8b9 100644
--- a/libgda-ui/data-entries/plugins/gdaui-entry-filesel.c
+++ b/libgda-ui/data-entries/plugins/gdaui-entry-filesel.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2014 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  *
@@ -310,10 +310,10 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
        filesel = GDAUI_ENTRY_FILESEL (mgwrap);
        g_return_if_fail (filesel->priv);
 
-       g_signal_connect (G_OBJECT (filesel->priv->entry), "changed",
-                         modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (filesel->priv->entry), "activate",
-                         activate_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (filesel->priv->entry), "changed",
+                                 modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (filesel->priv->entry), "activate",
+                                 activate_cb, mgwrap);
 }
 
 static void
diff --git a/libgda-ui/data-entries/plugins/gdaui-entry-format.c 
b/libgda-ui/data-entries/plugins/gdaui-entry-format.c
index b9a840a..62fb5af 100644
--- a/libgda-ui/data-entries/plugins/gdaui-entry-format.c
+++ b/libgda-ui/data-entries/plugins/gdaui-entry-format.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2012 - 2015 Vivien Malerba <malerba gnome-db org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -250,6 +250,6 @@ connect_signals (GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activ
        mgformat = GDAUI_ENTRY_FORMAT (mgwrap);
        g_return_if_fail (mgformat->priv);
 
-       g_signal_connect (G_OBJECT (mgformat->priv->entry), "changed", modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgformat->priv->entry), "activate", activate_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgformat->priv->entry), "changed", modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgformat->priv->entry), "activate", activate_cb, mgwrap);
 }
diff --git a/libgda-ui/data-entries/plugins/gdaui-entry-password.c 
b/libgda-ui/data-entries/plugins/gdaui-entry-password.c
index 352eed5..08a926e 100644
--- a/libgda-ui/data-entries/plugins/gdaui-entry-password.c
+++ b/libgda-ui/data-entries/plugins/gdaui-entry-password.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2012 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  *
  * This library is free software; you can redistribute it and/or
@@ -289,10 +289,10 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
         g_signal_connect (G_OBJECT (mgstr->priv->entry), "insert-text",
                           G_CALLBACK (entry_insert_text_cb), mgwrap);
 
-        g_signal_connect (G_OBJECT (mgstr->priv->entry), "changed",
-                          modify_cb, mgwrap);
-        g_signal_connect (G_OBJECT (mgstr->priv->entry), "activate",
-                          activate_cb, mgwrap);
+        g_signal_connect_swapped (G_OBJECT (mgstr->priv->entry), "changed",
+                               modify_cb, mgwrap);
+        g_signal_connect_swapped (G_OBJECT (mgstr->priv->entry), "activate",
+                                 activate_cb, mgwrap);
 }
 
 static void 
diff --git a/libgda-ui/data-entries/plugins/gdaui-entry-rt.c b/libgda-ui/data-entries/plugins/gdaui-entry-rt.c
index 28f63f1..7739bb3 100644
--- a/libgda-ui/data-entries/plugins/gdaui-entry-rt.c
+++ b/libgda-ui/data-entries/plugins/gdaui-entry-rt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 - 2012 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2010 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  *
  * This library is free software; you can redistribute it and/or
@@ -274,10 +274,10 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
        g_return_if_fail (mgtxt->priv);
 
        g_object_set_data (G_OBJECT (mgtxt->priv->view), "_activate_cb", activate_cb);
-       g_signal_connect (G_OBJECT (GDAUI_RT_EDITOR (mgtxt->priv->view)), "changed",
-                         modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgtxt->priv->view), "focus-out-event",
-                         G_CALLBACK (focus_out_cb), mgtxt);
+       g_signal_connect_swapped (G_OBJECT (GDAUI_RT_EDITOR (mgtxt->priv->view)), "changed",
+                                 modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgtxt->priv->view), "focus-out-event",
+                                 G_CALLBACK (focus_out_cb), mgtxt);
        /* FIXME: how does the user "activates" the GtkRtView widget ? */
 }
 
diff --git a/libgda-ui/data-entries/plugins/gdaui-entry-text.c 
b/libgda-ui/data-entries/plugins/gdaui-entry-text.c
index 1f634bd..e447b19 100644
--- a/libgda-ui/data-entries/plugins/gdaui-entry-text.c
+++ b/libgda-ui/data-entries/plugins/gdaui-entry-text.c
@@ -114,6 +114,7 @@ gdaui_entry_text_init (GdauiEntryText *gdaui_entry_text)
        gdaui_entry_text->priv->view = NULL;
        gdaui_entry_text->priv->wrapmode = GTK_WRAP_NONE;
        gtk_widget_set_vexpand (GTK_WIDGET (gdaui_entry_text), TRUE);
+       gtk_widget_set_hexpand (GTK_WIDGET (gdaui_entry_text), TRUE);
 }
 
 /**
@@ -402,10 +403,10 @@ connect_signals(GdauiEntryWrapper *mgwrap, GCallback modify_cb, GCallback activa
        g_return_if_fail (mgtxt->priv);
 
        g_object_set_data (G_OBJECT (mgtxt->priv->view), "_activate_cb", activate_cb);
-       g_signal_connect (G_OBJECT (mgtxt->priv->buffer), "changed",
-                         modify_cb, mgwrap);
-       g_signal_connect (G_OBJECT (mgtxt->priv->view), "focus-out-event",
-                         G_CALLBACK (focus_out_cb), mgtxt);
+       g_signal_connect_swapped (G_OBJECT (mgtxt->priv->buffer), "changed",
+                                 modify_cb, mgwrap);
+       g_signal_connect_swapped (G_OBJECT (mgtxt->priv->view), "focus-out-event",
+                                 G_CALLBACK (focus_out_cb), mgtxt);
        /* FIXME: how does the user "activates" the GtkTextView widget ? */
 }
 
diff --git a/libgda-ui/data/Makefile.am b/libgda-ui/data/Makefile.am
index 0e4f3af..0a6e92e 100644
--- a/libgda-ui/data/Makefile.am
+++ b/libgda-ui/data/Makefile.am
@@ -1,8 +1,7 @@
 # icons
 iconsdir=$(datadir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/pixmaps
 icons_DATA= \
-       gdaui-generic.png \
-       bin-attachment-16x16.png
+       gdaui-generic.png
 
 # other
 xmldir = $(datadir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)
diff --git a/libgda-ui/data/mime-types-extensions b/libgda-ui/data/mime-types-extensions
new file mode 100644
index 0000000..6f9870a
--- /dev/null
+++ b/libgda-ui/data/mime-types-extensions
@@ -0,0 +1,413 @@
+# Manually generated using:
+# cat /etc/mime.types | grep -v '^#' | awk '{if ($2 != "") print $1 "." $2}'
+application/andrew-inset.ez
+application/annodex.anx
+application/atom+xml.atom
+application/atomcat+xml.atomcat
+application/atomserv+xml.atomsrv
+application/bbolin.lin
+application/cu-seeme.cu
+application/davmount+xml.davmount
+application/dicom.dcm
+application/dsptype.tsp
+application/ecmascript.es
+application/font-sfnt.otf
+application/font-tdpfr.pfr
+application/font-woff.woff
+application/futuresplash.spl
+application/gzip.gz
+application/hta.hta
+application/java-archive.jar
+application/java-serialized-object.ser
+application/java-vm.class
+application/javascript.js
+application/json.json
+application/m3g.m3g
+application/mac-binhex40.hqx
+application/mac-compactpro.cpt
+application/mathematica.nb
+application/mbox.mbox
+application/msaccess.mdb
+application/msword.doc
+application/mxf.mxf
+application/octet-stream.bin
+application/oda.oda
+application/oebps-package+xml.opf
+application/ogg.ogx
+application/onenote.one
+application/pdf.pdf
+application/pgp-encrypted.pgp
+application/pgp-keys.key
+application/pgp-signature.sig
+application/pics-rules.prf
+application/postscript.ps
+application/rar.rar
+application/rdf+xml.rdf
+application/rtf.rtf
+application/sla.stl
+application/smil+xml.smi
+application/xhtml+xml.xhtml
+application/xml.xml
+application/xslt+xml.xsl
+application/xspf+xml.xspf
+application/zip.zip
+application/vnd.android.package-archive.apk
+application/vnd.cinderella.cdy
+application/vnd.debian.binary-package.deb
+application/vnd.font-fontforge-sfd.sfd
+application/vnd.google-earth.kml+xml.kml
+application/vnd.google-earth.kmz.kmz
+application/vnd.mozilla.xul+xml.xul
+application/vnd.ms-excel.xls
+application/vnd.ms-excel.addin.macroEnabled.12.xlam
+application/vnd.ms-excel.sheet.binary.macroEnabled.12.xlsb
+application/vnd.ms-excel.sheet.macroEnabled.12.xlsm
+application/vnd.ms-excel.template.macroEnabled.12.xltm
+application/vnd.ms-fontobject.eot
+application/vnd.ms-officetheme.thmx
+application/vnd.ms-pki.seccat.cat
+application/vnd.ms-powerpoint.ppt
+application/vnd.ms-powerpoint.addin.macroEnabled.12.ppam
+application/vnd.ms-powerpoint.presentation.macroEnabled.12.pptm
+application/vnd.ms-powerpoint.slide.macroEnabled.12.sldm
+application/vnd.ms-powerpoint.slideshow.macroEnabled.12.ppsm
+application/vnd.ms-powerpoint.template.macroEnabled.12.potm
+application/vnd.ms-word.document.macroEnabled.12.docm
+application/vnd.ms-word.template.macroEnabled.12.dotm
+application/vnd.oasis.opendocument.chart.odc
+application/vnd.oasis.opendocument.database.odb
+application/vnd.oasis.opendocument.formula.odf
+application/vnd.oasis.opendocument.graphics.odg
+application/vnd.oasis.opendocument.graphics-template.otg
+application/vnd.oasis.opendocument.image.odi
+application/vnd.oasis.opendocument.presentation.odp
+application/vnd.oasis.opendocument.presentation-template.otp
+application/vnd.oasis.opendocument.spreadsheet.ods
+application/vnd.oasis.opendocument.spreadsheet-template.ots
+application/vnd.oasis.opendocument.text.odt
+application/vnd.oasis.opendocument.text-master.odm
+application/vnd.oasis.opendocument.text-template.ott
+application/vnd.oasis.opendocument.text-web.oth
+application/vnd.openxmlformats-officedocument.presentationml.presentation.pptx
+application/vnd.openxmlformats-officedocument.presentationml.slide.sldx
+application/vnd.openxmlformats-officedocument.presentationml.slideshow.ppsx
+application/vnd.openxmlformats-officedocument.presentationml.template.potx
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.xlsx
+application/vnd.openxmlformats-officedocument.spreadsheetml.template.xltx
+application/vnd.openxmlformats-officedocument.wordprocessingml.document.docx
+application/vnd.openxmlformats-officedocument.wordprocessingml.template.dotx
+application/vnd.rim.cod.cod
+application/vnd.smaf.mmf
+application/vnd.stardivision.calc.sdc
+application/vnd.stardivision.chart.sds
+application/vnd.stardivision.draw.sda
+application/vnd.stardivision.impress.sdd
+application/vnd.stardivision.math.sdf
+application/vnd.stardivision.writer.sdw
+application/vnd.stardivision.writer-global.sgl
+application/vnd.sun.xml.calc.sxc
+application/vnd.sun.xml.calc.template.stc
+application/vnd.sun.xml.draw.sxd
+application/vnd.sun.xml.draw.template.std
+application/vnd.sun.xml.impress.sxi
+application/vnd.sun.xml.impress.template.sti
+application/vnd.sun.xml.math.sxm
+application/vnd.sun.xml.writer.sxw
+application/vnd.sun.xml.writer.global.sxg
+application/vnd.sun.xml.writer.template.stw
+application/vnd.symbian.install.sis
+application/vnd.tcpdump.pcap.cap
+application/vnd.visio.vsd
+application/vnd.wap.wbxml.wbxml
+application/vnd.wap.wmlc.wmlc
+application/vnd.wap.wmlscriptc.wmlsc
+application/vnd.wordperfect.wpd
+application/vnd.wordperfect5.1.wp5
+application/x-123.wk
+application/x-7z-compressed.7z
+application/x-abiword.abw
+application/x-apple-diskimage.dmg
+application/x-bcpio.bcpio
+application/x-bittorrent.torrent
+application/x-cab.cab
+application/x-cbr.cbr
+application/x-cbz.cbz
+application/x-cdf.cdf
+application/x-cdlink.vcd
+application/x-chess-pgn.pgn
+application/x-comsol.mph
+application/x-cpio.cpio
+application/x-csh.csh
+application/x-debian-package.deb
+application/x-director.dcr
+application/x-dms.dms
+application/x-doom.wad
+application/x-dvi.dvi
+application/x-font.pfa
+application/x-font-pcf.pcf
+application/x-freemind.mm
+application/x-futuresplash.spl
+application/x-ganttproject.gan
+application/x-gnumeric.gnumeric
+application/x-go-sgf.sgf
+application/x-graphing-calculator.gcf
+application/x-gtar.gtar
+application/x-gtar-compressed.tgz
+application/x-hdf.hdf
+application/x-hwp.hwp
+application/x-ica.ica
+application/x-info.info
+application/x-internet-signup.ins
+application/x-iphone.iii
+application/x-iso9660-image.iso
+application/x-jam.jam
+application/x-java-jnlp-file.jnlp
+application/x-jmol.jmz
+application/x-kchart.chrt
+application/x-killustrator.kil
+application/x-koan.skp
+application/x-kpresenter.kpr
+application/x-kspread.ksp
+application/x-kword.kwd
+application/x-latex.latex
+application/x-lha.lha
+application/x-lyx.lyx
+application/x-lzh.lzh
+application/x-lzx.lzx
+application/x-maker.frm
+application/x-mif.mif
+application/x-mpegURL.m3u8
+application/x-ms-wmd.wmd
+application/x-ms-wmz.wmz
+application/x-msdos-program.com
+application/x-msi.msi
+application/x-netcdf.nc
+application/x-ns-proxy-autoconfig.pac
+application/x-nwc.nwc
+application/x-object.o
+application/x-oz-application.oza
+application/x-pkcs7-certreqresp.p7r
+application/x-pkcs7-crl.crl
+application/x-python-code.pyc
+application/x-qgis.qgs
+application/x-quicktimeplayer.qtl
+application/x-rdp.rdp
+application/x-redhat-package-manager.rpm
+application/x-rss+xml.rss
+application/x-ruby.rb
+application/x-scilab.sci
+application/x-scilab-xcos.xcos
+application/x-sh.sh
+application/x-shar.shar
+application/x-shockwave-flash.swf
+application/x-silverlight.scr
+application/x-sql.sql
+application/x-stuffit.sit
+application/x-sv4cpio.sv4cpio
+application/x-sv4crc.sv4crc
+application/x-tar.tar
+application/x-tcl.tcl
+application/x-tex-gf.gf
+application/x-tex-pk.pk
+application/x-texinfo.texinfo
+application/x-trash.~
+application/x-troff.t
+application/x-troff-man.man
+application/x-troff-me.me
+application/x-troff-ms.ms
+application/x-ustar.ustar
+application/x-wais-source.src
+application/x-wingz.wz
+application/x-x509-ca-cert.crt
+application/x-xcf.xcf
+application/x-xfig.fig
+application/x-xpinstall.xpi
+application/x-xz.xz
+audio/amr.amr
+audio/amr-wb.awb
+audio/annodex.axa
+audio/basic.au
+audio/csound.csd
+audio/flac.flac
+audio/midi.mid
+audio/mpeg.mpga
+audio/mpegurl.m3u
+audio/ogg.oga
+audio/prs.sid.sid
+audio/x-aiff.aif
+audio/x-gsm.gsm
+audio/x-mpegurl.m3u
+audio/x-ms-wma.wma
+audio/x-ms-wax.wax
+audio/x-pn-realaudio.ra
+audio/x-realaudio.ra
+audio/x-scpls.pls
+audio/x-sd2.sd2
+audio/x-wav.wav
+chemical/x-alchemy.alc
+chemical/x-cache.cac
+chemical/x-cache-csf.csf
+chemical/x-cactvs-binary.cbin
+chemical/x-cdx.cdx
+chemical/x-cerius.cer
+chemical/x-chem3d.c3d
+chemical/x-chemdraw.chm
+chemical/x-cif.cif
+chemical/x-cmdf.cmdf
+chemical/x-cml.cml
+chemical/x-compass.cpa
+chemical/x-crossfire.bsd
+chemical/x-csml.csml
+chemical/x-ctx.ctx
+chemical/x-cxf.cxf
+chemical/x-embl-dl-nucleotide.emb
+chemical/x-galactic-spc.spc
+chemical/x-gamess-input.inp
+chemical/x-gaussian-checkpoint.fch
+chemical/x-gaussian-cube.cub
+chemical/x-gaussian-input.gau
+chemical/x-gaussian-log.gal
+chemical/x-gcg8-sequence.gcg
+chemical/x-genbank.gen
+chemical/x-hin.hin
+chemical/x-isostar.istr
+chemical/x-jcamp-dx.jdx
+chemical/x-kinemage.kin
+chemical/x-macmolecule.mcm
+chemical/x-macromodel-input.mmd
+chemical/x-mdl-molfile.mol
+chemical/x-mdl-rdfile.rd
+chemical/x-mdl-rxnfile.rxn
+chemical/x-mdl-sdfile.sd
+chemical/x-mdl-tgf.tgf
+chemical/x-mmcif.mcif
+chemical/x-mol2.mol2
+chemical/x-molconn-Z.b
+chemical/x-mopac-graph.gpt
+chemical/x-mopac-input.mop
+chemical/x-mopac-out.moo
+chemical/x-mopac-vib.mvb
+chemical/x-ncbi-asn1.asn
+chemical/x-ncbi-asn1-ascii.prt
+chemical/x-ncbi-asn1-binary.val
+chemical/x-ncbi-asn1-spec.asn
+chemical/x-pdb.pdb
+chemical/x-rosdal.ros
+chemical/x-swissprot.sw
+chemical/x-vamas-iso14976.vms
+chemical/x-vmd.vmd
+chemical/x-xtel.xtel
+chemical/x-xyz.xyz
+image/gif.gif
+image/ief.ief
+image/jp2.jp2
+image/jpeg.jpeg
+image/jpm.jpm
+image/jpx.jpx
+image/pcx.pcx
+image/png.png
+image/svg+xml.svg
+image/tiff.tiff
+image/vnd.djvu.djvu
+image/vnd.microsoft.icon.ico
+image/vnd.wap.wbmp.wbmp
+image/x-canon-cr2.cr2
+image/x-canon-crw.crw
+image/x-cmu-raster.ras
+image/x-coreldraw.cdr
+image/x-coreldrawpattern.pat
+image/x-coreldrawtemplate.cdt
+image/x-corelphotopaint.cpt
+image/x-epson-erf.erf
+image/x-jg.art
+image/x-jng.jng
+image/x-ms-bmp.bmp
+image/x-nikon-nef.nef
+image/x-olympus-orf.orf
+image/x-photoshop.psd
+image/x-portable-anymap.pnm
+image/x-portable-bitmap.pbm
+image/x-portable-graymap.pgm
+image/x-portable-pixmap.ppm
+image/x-rgb.rgb
+image/x-xbitmap.xbm
+image/x-xpixmap.xpm
+image/x-xwindowdump.xwd
+message/rfc822.eml
+model/iges.igs
+model/mesh.msh
+model/vrml.wrl
+model/x3d+vrml.x3dv
+model/x3d+xml.x3d
+model/x3d+binary.x3db
+text/cache-manifest.appcache
+text/calendar.ics
+text/css.css
+text/csv.csv
+text/h323.323
+text/html.html
+text/iuls.uls
+text/mathml.mml
+text/plain.asc
+text/richtext.rtx
+text/scriptlet.sct
+text/texmacs.tm
+text/tab-separated-values.tsv
+text/turtle.ttl
+text/vcard.vcf
+text/vnd.sun.j2me.app-descriptor.jad
+text/vnd.wap.wml.wml
+text/vnd.wap.wmlscript.wmls
+text/x-bibtex.bib
+text/x-boo.boo
+text/x-c++hdr.h++
+text/x-c++src.c++
+text/x-chdr.h
+text/x-component.htc
+text/x-csh.csh
+text/x-csrc.c
+text/x-dsrc.d
+text/x-diff.diff
+text/x-haskell.hs
+text/x-java.java
+text/x-lilypond.ly
+text/x-literate-haskell.lhs
+text/x-moc.moc
+text/x-pascal.p
+text/x-pcs-gcd.gcd
+text/x-perl.pl
+text/x-python.py
+text/x-scala.scala
+text/x-setext.etx
+text/x-sfv.sfv
+text/x-sh.sh
+text/x-tcl.tcl
+text/x-tex.tex
+text/x-vcalendar.vcs
+video/3gpp.3gp
+video/annodex.axv
+video/dl.dl
+video/dv.dif
+video/fli.fli
+video/gl.gl
+video/mpeg.mpeg
+video/MP2T.ts
+video/mp4.mp4
+video/quicktime.qt
+video/ogg.ogv
+video/webm.webm
+video/vnd.mpegurl.mxu
+video/x-flv.flv
+video/x-la-asf.lsf
+video/x-mng.mng
+video/x-ms-asf.asf
+video/x-ms-wm.wm
+video/x-ms-wmv.wmv
+video/x-ms-wmx.wmx
+video/x-ms-wvx.wvx
+video/x-msvideo.avi
+video/x-sgi-movie.movie
+video/x-matroska.mpv
+x-conference/x-cooltalk.ice
+x-epoc/x-sisx-app.sisx
+x-world/x-vrml.vrm
diff --git a/libgda-ui/gdaui-basic-form.c b/libgda-ui/gdaui-basic-form.c
index b1f9221..67774a7 100644
--- a/libgda-ui/gdaui-basic-form.c
+++ b/libgda-ui/gdaui-basic-form.c
@@ -35,7 +35,6 @@
 #include <libgda-ui/gdaui-easy.h>
 #include <libgda/gda-debug-macros.h>
 
-#define SPACING 3
 static void gdaui_basic_form_class_init (GdauiBasicFormClass * class);
 static void gdaui_basic_form_init (GdauiBasicForm *wid);
 static void gdaui_basic_form_dispose (GObject *object);
@@ -106,7 +105,6 @@ static void unpack_entries (GdauiBasicForm *form);
 static void destroy_entries (GdauiBasicForm *form);
 static gchar *create_text_label_for_sentry (SingleEntry *sentry, gchar **out_title);
 
-static void gdaui_basic_form_show_entry_actions (GdauiBasicForm *form, gboolean show_actions);
 static void gdaui_basic_form_set_entries_auto_default (GdauiBasicForm *form, gboolean auto_default);
 
 static void get_rid_of_set (GdaSet *paramlist, GdauiBasicForm *form);
@@ -118,6 +116,7 @@ static void paramlist_holder_type_set_cb (GdaSet *paramlist, GdaHolder *param,
 
 static void entry_contents_modified (GdauiDataEntry *entry, SingleEntry *sentry);
 static void entry_contents_activated (GdauiDataEntry *entry, GdauiBasicForm *form);
+static void sync_entry_attributes (GdaHolder *param, SingleEntry *sentry);
 static void parameter_changed_cb (GdaHolder *param, SingleEntry *sentry);
 
 static void mark_not_null_entry_labels (GdauiBasicForm *form, gboolean show_mark);
@@ -135,7 +134,6 @@ enum {
        PROP_XML_LAYOUT,
        PROP_PARAMLIST,
        PROP_HEADERS_SENSITIVE,
-       PROP_SHOW_ACTIONS,
        PROP_ENTRIES_AUTO_DEFAULT,
        PROP_CAN_VEXPAND
 };
@@ -160,7 +158,6 @@ struct _GdauiBasicFormPriv
 
        GtkWidget  *top_container;
 
-       gboolean    show_actions;
        gboolean    entries_auto_default;
 
        GSList     *size_groups; /* list of SizeGroup pointers */
@@ -304,11 +301,6 @@ gdaui_basic_form_class_init (GdauiBasicFormClass *klass)
                                                               "",
                                                               NULL, FALSE,
                                                               G_PARAM_READABLE | G_PARAM_WRITABLE));
-       g_object_class_install_property (object_class, PROP_SHOW_ACTIONS,
-                                        g_param_spec_boolean ("show-actions",
-                                                              _("Show Entry actions"),
-                                                              NULL, FALSE,
-                                                              G_PARAM_READABLE | G_PARAM_WRITABLE));
        g_object_class_install_property (object_class, PROP_ENTRIES_AUTO_DEFAULT,
                                         g_param_spec_boolean ("entries-auto-default",
                                                               _("Entries Auto-default"),
@@ -406,7 +398,6 @@ gdaui_basic_form_init (GdauiBasicForm *wid)
        wid->priv->place_holders = NULL;
        wid->priv->top_container = NULL;
 
-       wid->priv->show_actions = FALSE;
        wid->priv->entries_auto_default = FALSE;
 
        gtk_orientable_set_orientation (GTK_ORIENTABLE (wid), GTK_ORIENTATION_VERTICAL);
@@ -425,10 +416,10 @@ gdaui_basic_form_init (GdauiBasicForm *wid)
        g_signal_connect (evbox, "button-press-event",
                          G_CALLBACK (button_press_event_cb), wid);
 
-       wid->priv->red = .98;
-       wid->priv->green = .93;
-       wid->priv->blue = .25;
-       wid->priv->alpha = .50;
+       wid->priv->red = 0.;
+       wid->priv->green = 0.;
+       wid->priv->blue = 0.;
+       wid->priv->alpha = 0.;
 }
 
 /**
@@ -472,7 +463,6 @@ get_rid_of_set (GdaSet *paramlist, GdauiBasicForm *form)
        /* unref the paramlist */
        g_signal_handlers_disconnect_by_func (form->priv->set_info,
                                              G_CALLBACK (paramlist_public_data_changed_cb), form);
-
        g_signal_handlers_disconnect_by_func (paramlist,
                                              G_CALLBACK (paramlist_param_attr_changed_cb), form);
        g_signal_handlers_disconnect_by_func (paramlist,
@@ -500,9 +490,6 @@ paramlist_holder_type_set_cb (G_GNUC_UNUSED GdaSet *paramlist, GdaHolder *param,
        sentry = get_single_entry_for_holder (form, param);
        if (sentry) {
                create_entry_widget (sentry);
-               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (sentry->entry),
-                                                form->priv->show_actions ? GDA_VALUE_ATTR_ACTIONS_SHOWN : 0,
-                                                GDA_VALUE_ATTR_ACTIONS_SHOWN);
                pack_entry_widget (sentry);
                gdaui_basic_form_entry_set_visible (form, param, !sentry->hidden);
        }
@@ -563,9 +550,6 @@ paramlist_param_attr_changed_cb (G_GNUC_UNUSED GdaSet *paramlist, GdaHolder *par
                if (sentry) {
                        /* recreate an entry widget */
                        create_entry_widget (sentry);
-                       gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (sentry->entry),
-                                                        form->priv->show_actions ? 
GDA_VALUE_ATTR_ACTIONS_SHOWN : 0,
-                                                        GDA_VALUE_ATTR_ACTIONS_SHOWN);
                        pack_entry_widget (sentry);
                        gdaui_basic_form_entry_set_visible (form, param, !sentry->hidden);
                }
@@ -685,9 +669,6 @@ gdaui_basic_form_set_property (GObject *object,
                        break;
                case PROP_HEADERS_SENSITIVE:
                        break;
-               case PROP_SHOW_ACTIONS:
-                       gdaui_basic_form_show_entry_actions (form, g_value_get_boolean (value));
-                       break;
                case PROP_ENTRIES_AUTO_DEFAULT:
                        gdaui_basic_form_set_entries_auto_default (form, g_value_get_boolean (value));
                        break;
@@ -714,9 +695,6 @@ gdaui_basic_form_get_property (GObject *object,
                        break;
                case PROP_HEADERS_SENSITIVE:
                        break;
-               case PROP_SHOW_ACTIONS:
-                       g_value_set_boolean (value, form->priv->show_actions);
-                       break;
                case PROP_ENTRIES_AUTO_DEFAULT:
                        g_value_set_boolean (value, form->priv->entries_auto_default);
                        break;
@@ -959,6 +937,7 @@ create_entry_widget (SingleEntry *sentry)
                                           GDAUI_ATTRIBUTE_PLUGIN);
                }
                entry = GTK_WIDGET (gdaui_new_data_entry (type, plugin));
+               sentry->entry = GDAUI_DATA_ENTRY (entry);
 
                /* set current value */
                if (gda_holder_is_valid (param))
@@ -975,20 +954,8 @@ create_entry_widget (SingleEntry *sentry)
                          (G_VALUE_TYPE ((GValue *) value) != GDA_TYPE_NULL)))
                        gdaui_data_entry_set_reference_value (GDAUI_DATA_ENTRY (entry), value);
 
-               if (default_val) {
+               if (default_val)
                        gdaui_data_entry_set_default_value (GDAUI_DATA_ENTRY (entry), default_val);
-                       gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (entry),
-                                                        GDA_VALUE_ATTR_CAN_BE_DEFAULT,
-                                                        GDA_VALUE_ATTR_CAN_BE_DEFAULT);
-                       if (gda_holder_value_is_default (param))
-                               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (entry),
-                                                        GDA_VALUE_ATTR_IS_DEFAULT,
-                                                        GDA_VALUE_ATTR_IS_DEFAULT);
-               }
-
-               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (entry),
-                                                nnul ? 0 : GDA_VALUE_ATTR_CAN_BE_NULL,
-                                                GDA_VALUE_ATTR_CAN_BE_NULL);
 
                /* connect to the parameter's changes */
                sentry->single_signal.holder = g_object_ref (param);
@@ -1010,6 +977,9 @@ create_entry_widget (SingleEntry *sentry)
                if (title && *title)
                        gtk_widget_set_tooltip_text (sentry->label, title);
                g_free (title);
+
+               /* set up the data entry's attributes */
+               sync_entry_attributes (param, sentry);
        }
        else {
                /* several parameters depending on the values of a GdaDataModel object */
@@ -1017,6 +987,7 @@ create_entry_widget (SingleEntry *sentry)
                gboolean nullok = TRUE;
                        
                entry = gdaui_entry_combo_new (sentry->form->priv->set_info, gdaui_set_group_get_source 
(group));
+               sentry->entry = GDAUI_DATA_ENTRY (entry);
 
                /* connect to the parameter's changes */
                sentry->group_signals = g_array_new (FALSE, FALSE, sizeof (SignalData));
@@ -1024,7 +995,7 @@ create_entry_widget (SingleEntry *sentry)
                        GdaHolder *param;
 
                        param = gda_set_node_get_holder (GDA_SET_NODE (plist->data));
-                       if (gda_holder_get_not_null (param))
+                       if (nullok && gda_holder_get_not_null (param))
                                nullok = FALSE;
 
                        SignalData sd;
@@ -1034,9 +1005,6 @@ create_entry_widget (SingleEntry *sentry)
                                                         sentry);
                        g_array_append_val (sentry->group_signals, sd);
                }
-               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (entry),
-                                                nullok ? GDA_VALUE_ATTR_CAN_BE_NULL : 0,
-                                                GDA_VALUE_ATTR_CAN_BE_NULL);
                sentry->not_null = !nullok;
 
                /* label */
@@ -1055,16 +1023,20 @@ create_entry_widget (SingleEntry *sentry)
                if (title && *title)
                        gtk_widget_set_tooltip_text (sentry->label, title);
 
+               /* set up the data entry's attributes using the 1st parameter */
+               plist = gda_set_group_get_nodes (gdaui_set_group_get_group (group));
+               sync_entry_attributes (gda_set_node_get_holder (GDA_SET_NODE (plist->data)), sentry);
        }
-       gtk_widget_set_halign (sentry->label, GTK_ALIGN_START);
-       gtk_widget_set_hexpand (sentry->label, FALSE);
-       g_object_set (G_OBJECT (sentry->label), "xalign", 0., NULL);
-       sentry->entry = GDAUI_DATA_ENTRY (entry);
        g_object_ref_sink (sentry->entry);
+
+       gtk_widget_set_halign (sentry->label, GTK_ALIGN_END);
+       gtk_widget_set_hexpand (sentry->label, FALSE);
+       g_object_set (G_OBJECT (sentry->label), "xalign", 1., NULL);
        gdaui_data_entry_set_editable (sentry->entry, editable);
-       gdaui_data_entry_set_unknown_color (sentry->entry, sentry->form->priv->red,
-                                           sentry->form->priv->green, sentry->form->priv->blue,
-                                           sentry->form->priv->alpha);
+       if (sentry->form->priv->alpha > 0.)
+               gdaui_data_entry_set_unknown_color (sentry->entry, sentry->form->priv->red,
+                                                   sentry->form->priv->green, sentry->form->priv->blue,
+                                                   sentry->form->priv->alpha);
 
        GSList *list;
        for (list = sentry->form->priv->size_groups; list; list = list->next) {
@@ -1119,8 +1091,6 @@ create_entries (GdauiBasicForm *form)
                create_entry_widget (sentry);
        }
  
-       /* Set the Show actions in the entries */
-       gdaui_basic_form_show_entry_actions (form, form->priv->show_actions);
        /* Set the Auto entries default in the entries */
        gdaui_basic_form_set_entries_auto_default (form, form->priv->entries_auto_default);
 
@@ -1182,10 +1152,16 @@ pack_entries_in_table (GdauiBasicForm *form)
 
        /* creating a table for all the entries */
        grid = gtk_grid_new ();
-       gtk_grid_set_row_spacing (GTK_GRID (grid), SPACING);
-       gtk_grid_set_column_spacing (GTK_GRID (grid), SPACING);
+       gtk_grid_set_row_spacing (GTK_GRID (grid), GDAUI_HIG_FORM_VSPACE);
+       gtk_grid_set_column_spacing (GTK_GRID (grid), GDAUI_HIG_FORM_HSPACE);
        form->priv->top_container = grid;
        gtk_box_pack_start (GTK_BOX (form->priv->mainbox), grid, TRUE, TRUE, 0);
+       g_object_set (G_OBJECT (grid),
+                     "margin-top", GDAUI_HIG_FORM_VBORDER,
+                     "margin-bottom", GDAUI_HIG_FORM_VBORDER,
+                     "margin-start", GDAUI_HIG_FORM_HBORDER,
+                     "margin-end", GDAUI_HIG_FORM_HBORDER, NULL);
+                     
        for (list = form->priv->s_entries, i = 0;
             list;
             list = list->next, i++) {
@@ -1285,7 +1261,7 @@ load_xml_layout_children (GdauiBasicForm *form, xmlNodePtr parent_node)
                if (wid) {
                        switch (ctype) {
                        case TOP_BOX:
-                               gtk_box_pack_start (GTK_BOX (top), wid, TRUE, TRUE, SPACING);
+                               gtk_box_pack_start (GTK_BOX (top), wid, TRUE, TRUE, GDAUI_HIG_FORM_VSPACE);
                                break;
                        case TOP_PANED:
                                if (pos == 0)
@@ -1351,9 +1327,9 @@ load_xml_layout_column (GdauiBasicForm *form, xmlNodePtr box_node)
                                                }
                                                sentry->label = gtk_label_new ((gchar*) label);
                                                g_object_ref_sink (sentry->label);
-                                               gtk_widget_set_halign (sentry->label, GTK_ALIGN_START);
+                                               gtk_widget_set_halign (sentry->label, GTK_ALIGN_END);
                                                gtk_widget_set_hexpand (sentry->label, FALSE);
-                                               g_object_set (G_OBJECT (sentry->label), "xalign", 0., NULL);
+                                               g_object_set (G_OBJECT (sentry->label), "xalign", 1., NULL);
 
                                                xmlFree (label);
                                        }
@@ -1395,8 +1371,8 @@ load_xml_layout_column (GdauiBasicForm *form, xmlNodePtr box_node)
                        g_warning ("Unknown node type '%s', ignoring", (gchar*) child->name);   
        }
 
-       gtk_grid_set_row_spacing (GTK_GRID (grid), SPACING);
-       gtk_grid_set_column_spacing (GTK_GRID (grid), SPACING);
+       gtk_grid_set_row_spacing (GTK_GRID (grid), GDAUI_HIG_FORM_VSPACE);
+       gtk_grid_set_column_spacing (GTK_GRID (grid), GDAUI_HIG_FORM_HSPACE);
        return grid;
 }
 
@@ -1416,9 +1392,9 @@ load_xml_layout_section (GdauiBasicForm *form, xmlNodePtr section_node)
                label = gtk_label_new ("");
                gtk_label_set_markup (GTK_LABEL (label), str);
                g_free (str);
-               gtk_widget_set_halign (label, GTK_ALIGN_START);
+               gtk_widget_set_halign (label, GTK_ALIGN_END);
                gtk_widget_set_hexpand (label, FALSE);
-               g_object_set (G_OBJECT (label), "xalign", 0., NULL);
+               g_object_set (G_OBJECT (label), "xalign", 1., NULL);
 
                GtkWidget *vbox;
                vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
@@ -1566,6 +1542,64 @@ entry_contents_modified (GdauiDataEntry *entry, SingleEntry *sentry)
        }
 }
 
+static void
+sync_entry_attributes (GdaHolder *param, SingleEntry *sentry)
+{
+       const GValue *value = gda_holder_get_value (param);
+       GdauiDataEntry *entry;
+       gboolean param_valid;
+       param_valid = gda_holder_is_valid (param);
+
+       entry = sentry->entry;
+       if (sentry->single_param) {
+               gdaui_data_entry_set_value (entry, param_valid ? value : NULL);
+               sentry->not_null = gda_holder_get_not_null (param);
+       }
+       else {
+               GSList *values = NULL;
+               GSList *list;
+               gboolean allnull = TRUE;
+               gboolean nullok = TRUE;
+
+               for (list = gda_set_group_get_nodes (gdaui_set_group_get_group (sentry->group));
+                    list; list = list->next) {
+                       const GValue *pvalue;
+                       pvalue = gda_holder_get_value (gda_set_node_get_holder (GDA_SET_NODE (list->data)));
+                       param_valid = param_valid && gda_holder_is_valid (param);
+                       values = g_slist_append (values, (GValue *) pvalue);
+                       if (allnull && pvalue &&
+                           (G_VALUE_TYPE ((GValue *) pvalue) != GDA_TYPE_NULL))
+                               allnull = FALSE;
+                       if (nullok && gda_holder_get_not_null (param))
+                               nullok = FALSE;
+               }
+
+               if (!allnull)
+                       gdaui_entry_combo_set_values (GDAUI_ENTRY_COMBO (entry), values);
+               else
+                       gdaui_entry_combo_set_values (GDAUI_ENTRY_COMBO (entry), NULL);
+
+               g_slist_free (values);
+               sentry->not_null = !nullok;
+       }
+
+       g_signal_emit (G_OBJECT (sentry->form), gdaui_basic_form_signals[HOLDER_CHANGED], 0,
+                      param, FALSE);
+
+       /* correctly update the NULLOK status */
+       GdaValueAttribute attr;
+       gboolean nullok;
+       attr = gdaui_data_entry_get_attributes (entry);
+       nullok = !sentry->not_null;
+       if (((attr & GDA_VALUE_ATTR_CAN_BE_NULL) && !nullok) ||
+           (! (attr & GDA_VALUE_ATTR_CAN_BE_NULL) && nullok))
+               gdaui_data_entry_set_attributes (entry, nullok ? GDA_VALUE_ATTR_CAN_BE_NULL : 0,
+                                                GDA_VALUE_ATTR_CAN_BE_NULL);
+
+       /* update the VALID atttibute */
+       gdaui_data_entry_set_attributes (entry, (!param_valid) ? GDA_VALUE_ATTR_DATA_NON_VALID : 0,
+                                        GDA_VALUE_ATTR_DATA_NON_VALID);
+}
 
 /*
  * Called when a parameter changes
@@ -1575,22 +1609,20 @@ entry_contents_modified (GdauiDataEntry *entry, SingleEntry *sentry)
 static void
 parameter_changed_cb (GdaHolder *param, SingleEntry *sentry)
 {
-       const GValue *value = gda_holder_get_value (param);
        GdauiDataEntry *entry;
-
        entry = sentry->entry;
        if (sentry->forward_param_updates) {
-               gboolean param_valid;
                gboolean default_if_invalid = FALSE;
+               gboolean param_valid;
+               param_valid = gda_holder_is_valid (param);
 
                /* There can be a feedback from the entry if the param is invalid and "set-default-if-invalid"
                   exists and is TRUE */
-               param_valid = gda_holder_is_valid (param);
                if (!param_valid)
                        if (g_object_class_find_property (G_OBJECT_GET_CLASS (entry),
                                                          "set-default-if-invalid"))
                                g_object_get (G_OBJECT (entry),
-                                             "set-default-if-invalid", &default_if_invalid, NULL);
+                               "set-default-if-invalid", &default_if_invalid, NULL);
 
                /* updating the corresponding entry */
                if (! default_if_invalid) {
@@ -1599,58 +1631,14 @@ parameter_changed_cb (GdaHolder *param, SingleEntry *sentry)
                        g_signal_handler_block (G_OBJECT (entry),
                                                sentry->entry_contents_activated_id);
                }
-
-               if (sentry->single_param)
-                       gdaui_data_entry_set_value (entry, param_valid ? value : NULL);
-               else {
-                       GSList *values = NULL;
-                       GSList *list;
-                       gboolean allnull = TRUE;
-
-                       for (list = gda_set_group_get_nodes (gdaui_set_group_get_group (sentry->group));
-                            list; list = list->next) {
-                               const GValue *pvalue;
-                               pvalue = gda_holder_get_value (gda_set_node_get_holder (GDA_SET_NODE 
(list->data)));
-                               values = g_slist_append (values, (GValue *) pvalue);
-                               if (allnull && pvalue &&
-                                   (G_VALUE_TYPE ((GValue *) pvalue) != GDA_TYPE_NULL))
-                                       allnull = FALSE;
-                       }
-
-                       if (!allnull)
-                               gdaui_entry_combo_set_values (GDAUI_ENTRY_COMBO (entry), values);
-                       else
-                               gdaui_entry_combo_set_values (GDAUI_ENTRY_COMBO (entry), NULL);
-
-                       g_slist_free (values);
-               }
-
+               sync_entry_attributes (param, sentry);
                if (! default_if_invalid) {
                        g_signal_handler_unblock (G_OBJECT (entry),
                                                  sentry->entry_contents_modified_id);
                        g_signal_handler_unblock (G_OBJECT (entry),
                                                  sentry->entry_contents_activated_id);
-               }               
-
-               gdaui_entry_shell_set_unknown (GDAUI_ENTRY_SHELL (entry),
-                                              !gda_holder_is_valid (param));
-
-               g_signal_emit (G_OBJECT (sentry->form), gdaui_basic_form_signals[HOLDER_CHANGED], 0,
-                              param, FALSE);
+               }
        }
-       else
-               gdaui_entry_shell_set_unknown (GDAUI_ENTRY_SHELL (entry),
-                                              !gda_holder_is_valid (param));
-
-       /* correctly update the NULLOK status */
-       GdaValueAttribute attr;
-       gboolean nullok;
-       attr = gdaui_data_entry_get_attributes (entry);
-       nullok = !gda_holder_get_not_null (param);
-       if (((attr & GDA_VALUE_ATTR_CAN_BE_NULL) && !nullok) ||
-           (! (attr & GDA_VALUE_ATTR_CAN_BE_NULL) && nullok))
-               gdaui_data_entry_set_attributes (entry, nullok ? GDA_VALUE_ATTR_CAN_BE_NULL : 0,
-                                                GDA_VALUE_ATTR_CAN_BE_NULL);
 }
 
 /**
@@ -1775,33 +1763,6 @@ gdaui_basic_form_has_changed (GdauiBasicForm *form)
        return FALSE;
 }
 
-/*
- * gdaui_basic_form_show_entry_actions
- * @form: a #GdauiBasicForm widget
- * @show_actions: a boolean
- *
- * Show or hide the actions button available at the end of each data entry
- * in the form
- */
-static void
-gdaui_basic_form_show_entry_actions (GdauiBasicForm *form, gboolean show_actions)
-{
-       GSList *list;
-       guint show;
-
-       g_return_if_fail (GDAUI_IS_BASIC_FORM (form));
-
-       show = show_actions ? GDA_VALUE_ATTR_ACTIONS_SHOWN : 0;
-       form->priv->show_actions = show_actions;
-
-       for (list = form->priv->s_entries; list; list = list->next) {
-               SingleEntry *sentry = (SingleEntry*) list->data;
-               gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (sentry->entry), show,
-                                                GDA_VALUE_ATTR_ACTIONS_SHOWN);
-               /* mark_not_null_entry_labels (form, show_actions); */
-       }
-}
-
 /**
  * gdaui_basic_form_reset:
  * @form: a #GdauiBasicForm widget
@@ -2169,14 +2130,14 @@ gdaui_basic_form_new_in_dialog (GdaSet *data_set, GtkWindow *parent,
                gchar *str;
 
                label = gtk_label_new (NULL);
-               gtk_widget_set_halign (label, GTK_ALIGN_START);
+               gtk_widget_set_halign (label, GTK_ALIGN_END);
                gtk_widget_set_hexpand (label, FALSE);
-               g_object_set (G_OBJECT (label), "xalign", 0., NULL);
+               g_object_set (G_OBJECT (label), "xalign", 1., NULL);
                str = g_markup_printf_escaped ("<b>%s:</b>", header);
                gtk_label_set_markup (GTK_LABEL (label), str);
                g_free (str);
                gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
-                                   label, FALSE, FALSE, SPACING);
+                                   label, FALSE, FALSE, GDAUI_HIG_FORM_VSEP);
                gtk_widget_show (label);
        }
 
@@ -2184,7 +2145,7 @@ gdaui_basic_form_new_in_dialog (GdaSet *data_set, GtkWindow *parent,
        can_expand = gtk_widget_compute_expand (GTK_WIDGET (form), GTK_ORIENTATION_VERTICAL);
        gtk_container_set_border_width (GTK_CONTAINER (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG 
(dlg)))), 4);
        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), form,
-                           can_expand, can_expand, 10);
+                           can_expand, can_expand, 0);
 
        g_signal_connect (G_OBJECT (form), "holder-changed",
                          G_CALLBACK (form_holder_changed), dlg);
@@ -2416,6 +2377,11 @@ gdaui_basic_form_set_unknown_color (GdauiBasicForm *form, gdouble red, gdouble g
                                    gdouble blue, gdouble alpha)
 {
        g_return_if_fail (GDAUI_IS_BASIC_FORM (form));
+       g_return_if_fail ((red >= 0.) && (red <= 1.));
+       g_return_if_fail ((green >= 0.) && (green <= 1.));
+       g_return_if_fail ((blue >= 0.) && (blue <= 1.));
+       g_return_if_fail ((alpha >= 0.) && (alpha <= 1.));
+
        form->priv->red = red;
        form->priv->green = green;
        form->priv->blue = blue;
diff --git a/libgda-ui/gdaui-cloud.c b/libgda-ui/gdaui-cloud.c
index 3384d14..3daa0e1 100644
--- a/libgda-ui/gdaui-cloud.c
+++ b/libgda-ui/gdaui-cloud.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2013 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2010 David King <davidk openismus com>
  * Copyright (C) 2011 Murray Cumming <murrayc murrayc com>
  *
@@ -24,7 +24,6 @@
 #include <libgda/libgda.h>
 #include "gdaui-cloud.h"
 #include <gdk/gdkkeysyms.h>
-#include "internal/popup-container.h"
 #include "gdaui-data-selector.h"
 #include <libgda/gda-debug-macros.h>
 
diff --git a/libgda-ui/gdaui-data-entry.h b/libgda-ui/gdaui-data-entry.h
index 6454045..cfd3b40 100644
--- a/libgda-ui/gdaui-data-entry.h
+++ b/libgda-ui/gdaui-data-entry.h
@@ -68,7 +68,7 @@ struct _GdauiDataEntryIface
        void            (*set_attributes)        (GdauiDataEntry *de, GdaValueAttribute attrs, 
GdaValueAttribute mask);
        GdaValueAttribute (*get_attributes)      (GdauiDataEntry *de);
        GdaDataHandler *(*get_handler)           (GdauiDataEntry *de);
-       gboolean        (*can_expand)            (GdauiDataEntry *de, gboolean horiz); /* not used anymore */
+       gboolean        (*can_expand)            (GdauiDataEntry *de, gboolean horiz); /* FIXME: not used 
anymore */
        void            (*set_editable)          (GdauiDataEntry *de, gboolean editable);
        gboolean        (*get_editable)          (GdauiDataEntry *de);
        void            (*grab_focus)            (GdauiDataEntry *de);
@@ -126,7 +126,7 @@ GType           gdaui_data_entry_get_value_type         (GdauiDataEntry *de);
 void            gdaui_data_entry_set_value              (GdauiDataEntry *de, const GValue *value);
 GValue         *gdaui_data_entry_get_value              (GdauiDataEntry *de);
 gboolean        gdaui_data_entry_content_is_valid       (GdauiDataEntry *de, GError **error);
-gboolean        gdaui_data_entry_validate                                      (GdauiDataEntry *de, GError 
**error);
+gboolean        gdaui_data_entry_validate              (GdauiDataEntry *de, GError **error);
 void            gdaui_data_entry_set_reference_value    (GdauiDataEntry *de, const GValue *value);
 const GValue   *gdaui_data_entry_get_reference_value    (GdauiDataEntry *de);
 void            gdaui_data_entry_set_reference_current  (GdauiDataEntry *de);
diff --git a/libgda-ui/gdaui-enums.h b/libgda-ui/gdaui-enums.h
index e3e1e90..e3a5197 100644
--- a/libgda-ui/gdaui-enums.h
+++ b/libgda-ui/gdaui-enums.h
@@ -58,6 +58,14 @@ typedef enum {
 /* possible predefined attribute names for gda_holder_get_attribute() or gda_column_get_attribute() */
 #define GDAUI_ATTRIBUTE_PLUGIN "__gdaui_attr_plugin" /* G_TYPE_STRING expected */
 
+/* issued from HIG 3 */
+#define GDAUI_HIG_FORM_HBORDER 18
+#define GDAUI_HIG_FORM_HSPACE 12
+
+#define GDAUI_HIG_FORM_VBORDER 18
+#define GDAUI_HIG_FORM_VSPACE 6
+#define GDAUI_HIG_FORM_VSEP 18
+
 #endif
 
 
diff --git a/libgda-ui/gdaui-form.c b/libgda-ui/gdaui-form.c
index 5aee348..2a613b8 100644
--- a/libgda-ui/gdaui-form.c
+++ b/libgda-ui/gdaui-form.c
@@ -202,12 +202,11 @@ gdaui_form_init (GdauiForm *form)
        GtkWidget *frame;
        frame = gtk_frame_new (NULL);
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-       gtk_box_pack_start (GTK_BOX (form), frame, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (form), frame, TRUE, TRUE, 0);
        gtk_widget_show (frame);
 
        form->priv->raw_form = gdaui_raw_form_new (NULL);
        gtk_container_add (GTK_CONTAINER (frame), form->priv->raw_form);
-       gtk_container_set_border_width (GTK_CONTAINER (form->priv->raw_form), 6);
 
        gtk_widget_show (form->priv->raw_form);
        g_signal_connect (form->priv->raw_form, "layout-changed",
diff --git a/libgda-ui/gdaui-raw-form.c b/libgda-ui/gdaui-raw-form.c
index 0469844..ad9d171 100644
--- a/libgda-ui/gdaui-raw-form.c
+++ b/libgda-ui/gdaui-raw-form.c
@@ -453,9 +453,6 @@ gdaui_raw_form_init (GdauiRawForm *wid)
                          G_CALLBACK (form_activated_cb), NULL);
        g_signal_connect (G_OBJECT (wid), "holder-changed",
                          G_CALLBACK (form_holder_changed_cb), NULL);
-
-       /* raw forms' default unknown color */
-       gdaui_basic_form_set_unknown_color ((GdauiBasicForm*) wid, -1., -1., -1., -1.);
 }
 
 /**
@@ -561,17 +558,6 @@ gdaui_raw_form_set_property (GObject *object,
                                /* we don't want chuncking */
                                gda_data_proxy_set_sample_size (form->priv->proxy, 0);
 
-                               /* handle invalid iterators' GdaHolder */
-                               GSList *list;
-                               for (list = GDA_SET (form->priv->iter)->holders; list; list = list->next) {
-                                       GtkWidget *entry;
-                                       entry = gdaui_basic_form_get_entry_widget (GDAUI_BASIC_FORM (form),
-                                                                                  (GdaHolder*) list->data);
-                                       if (entry)
-                                               gdaui_entry_shell_set_unknown ((GdauiEntryShell*) entry,
-                                                                              !gda_holder_is_valid 
((GdaHolder*) list->data));
-                               }
-
                                iter_row_changed_cb (form->priv->iter,
                                                     gda_data_model_iter_get_row (form->priv->iter), form);
 
diff --git a/libgda-ui/gdaui.css b/libgda-ui/gdaui.css
index 2397273..5cef693 100644
--- a/libgda-ui/gdaui.css
+++ b/libgda-ui/gdaui.css
@@ -2,18 +2,6 @@
     background-color : transparent;
 }
 
-GdauiEntryShell {
-    -GtkArrow-arrow-scaling: 0.4;
-    margin: 0;
-    padding: 0;
-    border-style: none;
-    border-width: 0;
-    -GtkButton-default-border: 0;
-    -GtkButton-default-outside-border: 0;
-    -GtkButton-inner-border: 0;
-    background-color : transparent;
-}
-
 GdauiCombo.gdaui-combo-as-list {
     -GtkComboBox-appears-as-list : true;
 }
diff --git a/libgda-ui/gdaui.gresource.xml b/libgda-ui/gdaui.gresource.xml
index bb9b463..ce94b37 100644
--- a/libgda-ui/gdaui.gresource.xml
+++ b/libgda-ui/gdaui.gresource.xml
@@ -9,8 +9,8 @@
   <gresource prefix="/gdaui/images">
     <file compressed="no">data/gdaui-generic.png</file>
   </gresource>
-  <gresource prefix="/gdaui/images">
-    <file compressed="no">data/bin-attachment-16x16.png</file>
+  <gresource prefix="/gdaui">
+    <file compressed="true">data/mime-types-extensions</file>
   </gresource>
   <gresource prefix="/gdaui">
     <file compressed="true">data-entries/gdaui-entry-string.xml</file>
diff --git a/libgda-ui/internal/utility.c b/libgda-ui/internal/utility.c
index aa5173b..e61d79f 100644
--- a/libgda-ui/internal/utility.c
+++ b/libgda-ui/internal/utility.c
@@ -180,9 +180,9 @@ gchar *
 _gdaui_utility_markup_title (const gchar *title, gboolean optional)
 {
        if (!optional)
-               return g_strdup_printf ("%s <span foreground='red' weight='bold'>*</span>:", title);
+               return g_markup_printf_escaped ("%s <span foreground='red' weight='bold'>*</span>:", title);
        else
-               return g_strdup_printf ("%s:", title);
+               return g_markup_printf_escaped ("%s:", title);
 }
 
 /*
diff --git a/libgda-ui/libgda-ui.symbols b/libgda-ui/libgda-ui.symbols
index 1d26742..a05e60e 100644
--- a/libgda-ui/libgda-ui.symbols
+++ b/libgda-ui/libgda-ui.symbols
@@ -123,8 +123,7 @@
        gdaui_entry_set_width_chars
        gdaui_entry_shell_get_type
        gdaui_entry_shell_pack_entry
-       gdaui_entry_shell_refresh
-       gdaui_entry_shell_set_ucolor
+       gdaui_entry_shell_set_invalid_color
        gdaui_entry_string_get_type
        gdaui_entry_string_new
        gdaui_entry_time_get_type
diff --git a/libgda/gda-enums.h b/libgda/gda-enums.h
index 973a551..f8072ec 100644
--- a/libgda/gda-enums.h
+++ b/libgda/gda-enums.h
@@ -41,7 +41,20 @@ typedef enum {
 
 #define GDA_TRANSACTION_ISOLATION_UNKNOWN GDA_TRANSACTION_ISOLATION_SERVER_DEFAULT
 
-/* status of a value */
+/**
+ * GdaValueAttribute:
+ * @GDA_VALUE_ATTR_NONE: no specific attribute
+ * @GDA_VALUE_ATTR_IS_NULL: value is NULL (in the SQL sense)
+ * @GDA_VALUE_ATTR_CAN_BE_NULL: value can be set to NULL (in the SQL sense)
+ * @GDA_VALUE_ATTR_IS_DEFAULT: value is defined as the default value (the value itself is not specified)
+ * @GDA_VALUE_ATTR_CAN_BE_DEFAULT: a default value (not specified) exists for the value
+ * @GDA_VALUE_ATTR_IS_UNCHANGED: the value has not been changed (in the context of the attribute usage)
+ * @GDA_VALUE_ATTR_DATA_NON_VALID: the value is not valid (with regards to the context)
+ * @GDA_VALUE_ATTR_HAS_VALUE_ORIG: the value can be resetted to its "original" value (i.e. before it was 
modified)
+ * @GDA_VALUE_ATTR_READ_ONLY: the value can't be modified
+ *
+ * Attributes of a value, used internally by Libgda in different contexts. Values can be OR'ed.
+ */
 typedef enum  {
        GDA_VALUE_ATTR_NONE           = 0,
         GDA_VALUE_ATTR_IS_NULL        = 1 << 0,
@@ -49,10 +62,10 @@ typedef enum  {
         GDA_VALUE_ATTR_IS_DEFAULT     = 1 << 2,
         GDA_VALUE_ATTR_CAN_BE_DEFAULT = 1 << 3,
         GDA_VALUE_ATTR_IS_UNCHANGED   = 1 << 4,
-        GDA_VALUE_ATTR_ACTIONS_SHOWN  = 1 << 5,
         GDA_VALUE_ATTR_DATA_NON_VALID = 1 << 6,
         GDA_VALUE_ATTR_HAS_VALUE_ORIG = 1 << 7,
        GDA_VALUE_ATTR_NO_MODIF       = 1 << 8,
+       GDA_VALUE_ATTR_READ_ONLY      = 1 << 8, /* same as GDA_VALUE_ATTR_NO_MODIF */
 } GdaValueAttribute;
 
 /* how SQL identifiers are represented */
diff --git a/libgda/gda-value.c b/libgda/gda-value.c
index 43c7825..4c2367f 100644
--- a/libgda/gda-value.c
+++ b/libgda/gda-value.c
@@ -1628,29 +1628,35 @@ gda_value_new_blob_from_file (const gchar *filename)
 }
 
 /*
- * Warning: modifies @gmttm and loctm
+ * Warning: DOES NOT modify @gmttm and loctm
  *
  * Returns: the offset, or G_MAXLONG in case of error
  */
 static glong
 compute_tz_offset (struct tm *gmttm, struct tm *loctm)
 {
-       time_t lt, gt;
        if (! gmttm || !loctm)
                return G_MAXLONG;
 
-       gmttm->tm_isdst = 0;
-       loctm->tm_isdst = 0;
+       struct tm cgmttm, cloctm;
+       cgmttm = *gmttm;
+       cloctm = *loctm;
+
+       time_t lt, gt;
+       cgmttm.tm_isdst = 0;
+       cloctm.tm_isdst = 0;
 
-       lt = mktime (loctm);
+       lt = mktime (&cloctm);
        if (lt == -1)
                return G_MAXLONG;
-       gt = mktime (gmttm);
+       gt = mktime (&cgmttm);
        if (gt == -1)
                return G_MAXLONG;
-
        glong off;
        off = lt - gt;
+       g_print ("%s(): %02d:%02d:%02d %d\n", __FUNCTION__,
+                loctm->tm_hour, loctm->tm_min, loctm->tm_sec, (gint) (off / 3600));
+
        if ((off >= 24 * 3600) || (off <= - 24 * 3600))
                return G_MAXLONG;
        else
@@ -1658,7 +1664,7 @@ compute_tz_offset (struct tm *gmttm, struct tm *loctm)
 }
 
 /**
- * gda_value_new_timestamp_from_timet: (skip)
+ * gda_value_new_timestamp_from_timet:
  * @val: value to set for the new #GValue.
  *
  * Makes a new #GValue of type #GDA_TYPE_TIMESTAMP with value @val
@@ -1732,6 +1738,79 @@ gda_value_new_timestamp_from_timet (time_t val)
 }
 
 /**
+ * gda_value_new_time_from_timet:
+ * @val: value to set for the new #GValue.
+ *
+ * Makes a new #GValue of type #GDA_TYPE_TIME with value @val
+ * (of type time_t). The returned times's value is relative to the current
+ * timezone (i.e. is localtime).
+ *
+ * For example, to get a time representing the current time, use:
+ *
+ * <code>
+ * ts = gda_value_new_time_from_timet (time (NULL));
+ * </code>
+ *
+ * Returns: (transfer full): the newly created #GValue, or %NULL in case of error
+ *
+ * Free-function: gda_value_free
+ *
+ * Since: 6.0
+ */
+GValue *
+gda_value_new_time_from_timet (time_t val)
+{
+       GValue *value = NULL;
+       struct tm *ltm = NULL;
+       glong tz = 0;
+
+#ifdef HAVE_LOCALTIME_R
+       struct tm gmttm, loctm;
+       tzset ();
+       ltm = localtime_r ((const time_t *) &val, &loctm);
+       tz = compute_tz_offset (gmtime_r ((const time_t *) &val, &gmttm), &loctm);
+       if (tz == G_MAXLONG)
+               ltm = NULL;
+#elif HAVE_LOCALTIME_S
+       struct tm gmttm, loctm;
+       if ((localtime_s (&loctm, (const time_t *) &val) == 0) &&
+           (gmtime_s (&gmttm, (const time_t *) &val) == 0)) {
+               tz = compute_tz_offset (&gmttm, &loctm);
+               if (tz != G_MAXLONG)
+                       ltm = &loctm;
+       }
+#else
+       struct tm gmttm, loctm;
+       ltm = gmtime ((const time_t *) &val);
+       if (ltm) {
+               gmttm = *ltm;
+               ltm = localtime ((const time_t *) &val);
+               if (ltm) {
+                       loctm = *ltm;
+                       tz = compute_tz_offset (&gmttm, &loctm);
+                       if (tz == G_MAXLONG)
+                               ltm = NULL;
+               }
+       }
+       
+#endif
+
+        if (ltm) {
+                GdaTime tim;
+                tim.hour = ltm->tm_hour;
+                tim.minute = ltm->tm_min;
+                tim.second = ltm->tm_sec;
+                tim.fraction = 0;
+                tim.timezone = tz;
+
+               value = g_new0 (GValue, 1);
+                gda_value_set_time (value, (const GdaTime *) &tim);
+        }
+
+        return value;
+}
+
+/**
  * gda_value_new_from_string: (skip)
  * @as_string: stringified representation of the value.
  * @type: the new value type.
diff --git a/libgda/gda-value.h b/libgda/gda-value.h
index 7ac4629..1037aaf 100644
--- a/libgda/gda-value.h
+++ b/libgda/gda-value.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001 - 2003 Rodrigo Moya <rodrigo gnome-db org>
  * Copyright (C) 2002 - 2003 Gonzalo Paniagua Javier <gonzalo gnome-db org>
- * Copyright (C) 2002 - 2013 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2002 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2003 Akira TAGOH <tagoh gnome-db org>
  * Copyright (C) 2003 Danilo Schoeneberg <dschoene src gnome org>
  * Copyright (C) 2003 Laurent Sansonetti <laurent datarescue be>
@@ -203,6 +203,7 @@ GValue                           *gda_value_new_default (const gchar *default_va
 GValue                           *gda_value_new_binary (const guchar *val, glong size);
 GValue                           *gda_value_new_blob (const guchar *val, glong size);
 GValue                           *gda_value_new_blob_from_file (const gchar *filename);
+GValue                           *gda_value_new_time_from_timet (time_t val);
 GValue                           *gda_value_new_timestamp_from_timet (time_t val);
 
 GValue                           *gda_value_new_from_string (const gchar *as_string, GType type);
diff --git a/libgda/handlers/gda-handler-time.c b/libgda/handlers/gda-handler-time.c
index b4b7632..5c4385a 100644
--- a/libgda/handlers/gda-handler-time.c
+++ b/libgda/handlers/gda-handler-time.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 - 2013 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2006 - 2015 Vivien Malerba <malerba gnome-db org>
  * Copyright (C) 2007 Murray Cumming <murrayc murrayc com>
  * Copyright (C) 2009 Bas Driessen <bas driessen xobas com>
  * Copyright (C) 2010 David King <davidk openismus com>
@@ -597,6 +597,66 @@ gda_handler_time_get_format (GdaHandlerTime *dh, GType type)
        return str;
 }
 
+/**
+ * gda_handler_time_get_hint:
+ * @dh: a #GdaHandlerTime object
+ * @type: the type of data being handled
+ *
+ * Get a string giving the user a hint about the locale-dependent requested format.
+ *
+ * Returns: a new string
+ *
+ * Since: 6.0
+ */
+gchar *
+gda_handler_time_get_hint (GdaHandlerTime *dh, GType type)
+{
+       gchar *str;
+       GString *string;
+       gint i;
+
+       g_return_val_if_fail (GDA_IS_HANDLER_TIME (dh), NULL);
+
+       string = g_string_new ("");
+       if ((type == G_TYPE_DATE) || (type == GDA_TYPE_TIMESTAMP) || (type == G_TYPE_DATE_TIME)) {
+               for (i=0; i<3; i++) {
+                       if (i > 0)
+                               g_string_append_c (string, dh->priv->str_locale->separator);
+                       switch (dh->priv->str_locale->dmy_order[i]) {
+                       case G_DATE_DAY:
+                               /* To translators: DD represents a place holder in a date string. For example 
in the "YYYY-MM-DD" format, one knows that she has to replace DD by a day number */
+                               g_string_append (string, _("DD"));
+                               break;
+                       case G_DATE_MONTH:
+                               /* To translators: MM represents a place holder in a date string. For example 
in the "YYYY-MM-DD" format, one knows that she has to replace MM by a month number */
+                               g_string_append (string, _("MM"));
+                               break;
+                       case G_DATE_YEAR:
+                               if (dh->priv->str_locale->twodigit_years)
+                                       /* To translators: YY represents a place holder in a date string. For 
example in the "YY-MM-DD" format, one knows that she has to replace YY by a year number, on 2 digits */
+                                       g_string_append (string, _("YY"));
+                               else
+                                       /* To translators: YYYY represents a place holder in a date string. 
For example in the "YYYY-MM-DD" format, one knows that she has to replace YYYY by a year number, on 4 digits 
*/
+                                       g_string_append (string, _("YYYY"));
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                               break;
+                       }
+               }
+       }
+       if (type == GDA_TYPE_TIMESTAMP)
+               g_string_append_c (string, ' ');
+
+       if ((type == GDA_TYPE_TIME) || (type == GDA_TYPE_TIMESTAMP) || (type == G_TYPE_DATE_TIME))
+               /* To translators: HH:MM:SS represents a time format. For example in the "HH:MM:SS" format, 
one knows that she has to replace HH by a number of hours, and so on */
+               g_string_append (string, "HH:MM:SS");
+
+       str = string->str;
+       g_string_free (string, FALSE);
+       return str;
+}
+
 /* Interface implementation */
 
 /* REM: SQL date format is always returned using the MM-DD-YYY format, it's up to the
diff --git a/libgda/handlers/gda-handler-time.h b/libgda/handlers/gda-handler-time.h
index 834410d..c1e2124 100644
--- a/libgda/handlers/gda-handler-time.h
+++ b/libgda/handlers/gda-handler-time.h
@@ -74,6 +74,8 @@ void            gda_handler_time_set_str_spec  (GdaHandlerTime *dh, GDateDMY fir
 gchar          *gda_handler_time_get_no_locale_str_from_value (GdaHandlerTime *dh, const GValue *value);
 
 gchar          *gda_handler_time_get_format    (GdaHandlerTime *dh, GType type);
+gchar          *gda_handler_time_get_hint      (GdaHandlerTime *dh, GType type);
+
 G_END_DECLS
 
 #endif
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index 851ea6a..93f0b24 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -372,6 +372,7 @@
        gda_handler_string_new_with_provider
        gda_handler_time_get_format
        gda_handler_time_get_no_locale_str_from_value
+       gda_handler_time_get_hint
        gda_handler_time_get_type
        gda_handler_time_new
        gda_handler_time_new_no_locale
@@ -949,6 +950,7 @@
        gda_value_new_from_string
        gda_value_new_from_xml
        gda_value_new_null
+       gda_value_new_time_from_timet
        gda_value_new_timestamp_from_timet
        gda_value_reset_with_type
        gda_value_set_binary
diff --git a/testing/gdaui-test-data-entries.c b/testing/gdaui-test-data-entries.c
index cc4bcb4..b8bd831 100644
--- a/testing/gdaui-test-data-entries.c
+++ b/testing/gdaui-test-data-entries.c
@@ -144,10 +144,11 @@ main (int argc, char **argv)
        gdaui_init ();
 
        /* init main conf */
-       GType tested_gtypes [] = {G_TYPE_INT64, G_TYPE_UINT64, GDA_TYPE_BINARY, G_TYPE_BOOLEAN, GDA_TYPE_BLOB,
+       GType tested_gtypes [] = {G_TYPE_STRING,
+                                 G_TYPE_INT64, G_TYPE_UINT64, GDA_TYPE_BINARY, G_TYPE_BOOLEAN, GDA_TYPE_BLOB,
                                  G_TYPE_DATE, G_TYPE_DOUBLE,
                                  GDA_TYPE_GEOMETRIC_POINT, G_TYPE_OBJECT, G_TYPE_INT, 
-                                 GDA_TYPE_NUMERIC, G_TYPE_FLOAT, GDA_TYPE_SHORT, GDA_TYPE_USHORT, 
G_TYPE_STRING, 
+                                 GDA_TYPE_NUMERIC, G_TYPE_FLOAT, GDA_TYPE_SHORT, GDA_TYPE_USHORT,
                                  GDA_TYPE_TIME, GDA_TYPE_TIMESTAMP, G_TYPE_CHAR, G_TYPE_UCHAR, G_TYPE_UINT};
        mainconf.test_type = TESTED_BASIC;
        if (test_type) {
@@ -197,6 +198,8 @@ main (int argc, char **argv)
                              "them in pages of a notebook. Each page presents the default "
                              "data entry for the corresponding data type.");
        gtk_widget_set_halign (label, GTK_ALIGN_START);
+       gtk_widget_set_margin_start (label, 10);
+       gtk_widget_set_margin_end (label, 10);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5);
        gtk_widget_show (label);
 
@@ -221,6 +224,8 @@ main (int argc, char **argv)
                              "them in pages of a notebook. Each page tests a plugin for a given "
                              "data type");
        gtk_widget_set_halign (label, GTK_ALIGN_START);
+       gtk_widget_set_margin_start (label, 10);
+       gtk_widget_set_margin_end (label, 10);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 5);
        gtk_widget_show (label);
 
@@ -404,6 +409,8 @@ build_test_for_plugin_struct (GdauiPlugin *plugin)
        g_assert (plugin);
 
        grid = gtk_grid_new ();
+       gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+       gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
 
        /* explain top label */
        if (plugin->plugin_file)
@@ -459,12 +466,17 @@ build_test_for_plugin_struct (GdauiPlugin *plugin)
                        g_error_free (error);
                }
                else {
-                       GtkWidget *form;
-
+                       GtkWidget *form, *frame;
+                       frame = gtk_frame_new ("");
                        form = gdaui_basic_form_new (plist);
                        g_object_unref (plist);
-                       gtk_grid_attach (GTK_GRID (grid), form, 1, 2, 1, 1);
-                       gtk_widget_show (form);
+                       gtk_widget_set_margin_top (form, 10);
+                       gtk_widget_set_margin_bottom (form, 10);
+                       gtk_widget_set_margin_start (form, 10);
+                       gtk_widget_set_margin_end (form, 10);
+                       gtk_grid_attach (GTK_GRID (grid), frame, 1, 2, 1, 1);
+                       gtk_container_add (GTK_CONTAINER (frame), form);
+                       gtk_widget_show_all (frame);
                        g_object_set_data (G_OBJECT (grid), "options", form);
                        g_signal_connect (G_OBJECT (form), "holder-changed",
                                          G_CALLBACK (options_form_holder_changed_cb), grid);
@@ -494,9 +506,14 @@ create_plugin_nb (GtkWidget *grid, GdauiPlugin *plugin)
        GType type;
        GdaDataHandler *dh;
 
+       label = gtk_label_new ("");
+       gtk_label_set_markup (GTK_LABEL (label), "<b>Handled GTypes:</b>");
+       gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
+       gtk_widget_show (label);
+
        nb = gtk_notebook_new ();
        gtk_notebook_set_tab_pos (GTK_NOTEBOOK (nb), GTK_POS_LEFT);
-       gtk_grid_attach (GTK_GRID (grid), nb, 0, 1, 2, 1);
+       gtk_grid_attach (GTK_GRID (grid), nb, 1, 3, 1, 1);
        gtk_widget_show (nb);
        g_signal_connect (G_OBJECT (nb), "switch-page",
                          G_CALLBACK (plugin_nb_page_changed_cb), grid);
@@ -667,7 +684,7 @@ options_form_holder_changed_cb (G_GNUC_UNUSED GdauiBasicForm *form, G_GNUC_UNUSE
 /*
  * Basic test (individual GdauiDataEntry widget being tested)
  */
-void entry_contents_modified (GtkWidget *entry, gpointer data);
+void entry_contents_or_attrs_changed (GtkWidget *entry, gpointer data);
 void null_toggled_cb (GtkToggleButton *button, GtkWidget *entry);
 void default_toggled_cb (GtkToggleButton *button, GtkWidget *entry);
 void actions_toggled_cb (GtkToggleButton *button, GtkWidget *entry);
@@ -703,11 +720,22 @@ build_basic_test_for_gtype (GdaDataHandler *dh, GType type, const gchar *plugin_
        gtk_widget_show (label);
 
        /* widget being tested */
+       label = gtk_label_new ("Data entry widget: ");
+       gtk_widget_set_halign (label, GTK_ALIGN_START);
+       gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+       gtk_widget_show (label);
+
+       GtkWidget *frame;
+       frame = gtk_frame_new ("");
+       gtk_grid_attach (GTK_GRID (grid), frame, 1, 1, 2, 1);
        wid = GTK_WIDGET (gdaui_new_data_entry (type, plugin_name));
+       gtk_widget_set_margin_top (wid, 10);
+       gtk_widget_set_margin_bottom (wid, 10);
+       gtk_widget_set_margin_start (wid, 10);
+       gtk_widget_set_margin_end (wid, 10);
        g_object_set (G_OBJECT (wid), "handler", dh, NULL);
-
-       gtk_grid_attach (GTK_GRID (grid), wid, 0, 1, 3, 1);
-       gtk_widget_show (wid);
+       gtk_container_add (GTK_CONTAINER (frame), wid);
+       gtk_widget_show_all (frame);
 
        /* Other widgets */
        label = gtk_label_new ("Current flags: ");
@@ -731,13 +759,15 @@ build_basic_test_for_gtype (GdaDataHandler *dh, GType type, const gchar *plugin_
        gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
        g_object_set_data (G_OBJECT (wid), "value", label);
        g_signal_connect (G_OBJECT (wid), "contents-modified",
-                         G_CALLBACK (entry_contents_modified), NULL);
+                         G_CALLBACK (entry_contents_or_attrs_changed), NULL);
+       g_signal_connect (G_OBJECT (wid), "status-changed",
+                         G_CALLBACK (entry_contents_or_attrs_changed), NULL);
+       entry_contents_or_attrs_changed (wid, GTK_LABEL (label));
        gtk_widget_show (label);
 
-       entry_contents_modified (wid, GTK_LABEL (label));
-
        bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
-       gtk_grid_attach (GTK_GRID (grid), bbox, 0, 4, 3, 1);
+       gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
+       gtk_grid_attach (GTK_GRID (grid), bbox, 0, 4, 2, 1);
                
        button = gtk_toggle_button_new_with_label ("NULL ok");
        g_signal_connect (G_OBJECT (button), "toggled",
@@ -755,31 +785,28 @@ build_basic_test_for_gtype (GdaDataHandler *dh, GType type, const gchar *plugin_
                                      gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (wid)) & 
                                      GDA_VALUE_ATTR_CAN_BE_DEFAULT);
 
-       button = gtk_toggle_button_new_with_label ("Actions?");
-       g_signal_connect (G_OBJECT (button), "toggled",
-                         G_CALLBACK (actions_toggled_cb), wid);
-       gtk_container_add (GTK_CONTAINER (bbox), button);
-       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
-                                     gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (wid)) & 
-                                     GDA_VALUE_ATTR_ACTIONS_SHOWN);
-
        button = gtk_toggle_button_new_with_label ("Editable?");
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
        g_signal_connect (G_OBJECT (button), "toggled",
                          G_CALLBACK (editable_toggled_cb), wid);
        gtk_container_add (GTK_CONTAINER (bbox), button);
-                             
+
+       entry = gtk_entry_new ();
+       gtk_entry_set_placeholder_text (GTK_ENTRY (entry), "Grab focus here!");
+       gtk_widget_set_can_focus (entry, TRUE);
+       gtk_container_add (GTK_CONTAINER (bbox), entry);
+
        gtk_widget_show_all (bbox);
 
        /* to set the original value */
        entry = GTK_WIDGET (gdaui_new_data_entry (type, plugin_name));
        g_object_set (G_OBJECT (entry), "handler", dh, NULL);
 
-       gtk_grid_attach (GTK_GRID (grid), entry, 0, 5, 2, 1);
+       gtk_grid_attach (GTK_GRID (grid), entry, 1, 5, 1, 1);
        gtk_widget_show (entry);
        button = gtk_button_new_with_label ("Set as original");
        g_object_set_data (G_OBJECT (button), "entry", entry);
-       gtk_grid_attach (GTK_GRID (grid), button, 2, 5, 1, 1);
+       gtk_grid_attach (GTK_GRID (grid), button, 0, 5, 1, 1);
        gtk_widget_show (button);
        g_signal_connect (G_OBJECT (button), "clicked",
                          G_CALLBACK (orig_clicked_cb), wid);
@@ -788,11 +815,11 @@ build_basic_test_for_gtype (GdaDataHandler *dh, GType type, const gchar *plugin_
        entry = GTK_WIDGET (gdaui_new_data_entry (type, plugin_name));
        g_object_set (G_OBJECT (entry), "handler", dh, NULL);
 
-       gtk_grid_attach (GTK_GRID (grid), entry, 0, 6, 2, 1);
+       gtk_grid_attach (GTK_GRID (grid), entry, 1, 6, 1, 1);
        gtk_widget_show (entry);
        button = gtk_button_new_with_label ("Set as default");
        g_object_set_data (G_OBJECT (button), "entry", entry);
-       gtk_grid_attach (GTK_GRID (grid), button, 2, 6, 1, 1);
+       gtk_grid_attach (GTK_GRID (grid), button, 0, 6, 1, 1);
        gtk_widget_show (button);
        g_signal_connect (G_OBJECT (button), "clicked",
                          G_CALLBACK (default_clicked_cb), wid);
@@ -832,20 +859,6 @@ default_toggled_cb (GtkToggleButton *button, GtkWidget *entry)
 }
 
 void
-actions_toggled_cb (GtkToggleButton *button, GtkWidget *entry)
-{
-       guint action = 0;
-       if (gtk_toggle_button_get_active (button))
-               action = GDA_VALUE_ATTR_ACTIONS_SHOWN;
-
-       gdaui_data_entry_set_attributes (GDAUI_DATA_ENTRY (entry),
-                                     action, GDA_VALUE_ATTR_ACTIONS_SHOWN);
-       gtk_toggle_button_set_active (button,
-                                     gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (entry)) & 
-                                     GDA_VALUE_ATTR_ACTIONS_SHOWN);
-}
-
-void
 editable_toggled_cb (GtkToggleButton *button, GtkWidget *entry)
 {
        gboolean editable;
@@ -855,27 +868,51 @@ editable_toggled_cb (GtkToggleButton *button, GtkWidget *entry)
 }
 
 void 
-entry_contents_modified (GtkWidget *entry, G_GNUC_UNUSED gpointer data)
+entry_contents_or_attrs_changed (GtkWidget *entry, G_GNUC_UNUSED gpointer data)
 {
        guint attrs;
        GtkLabel *label;
-       GString *str = g_string_new ("");
+       GString *str = NULL;
        GValue *value;
        GdaDataHandler *dh;
 
        /* flags */
        label = g_object_get_data (G_OBJECT (entry), "flags");
        attrs = gdaui_data_entry_get_attributes (GDAUI_DATA_ENTRY (entry));
-       if (attrs & GDA_VALUE_ATTR_IS_NULL)
-               g_string_append (str, "N ");
-       if (attrs & GDA_VALUE_ATTR_IS_DEFAULT)
-               g_string_append (str, "D ");
-       if (!(attrs & GDA_VALUE_ATTR_IS_UNCHANGED))
-               g_string_append (str, "M ");
-       if (attrs & GDA_VALUE_ATTR_DATA_NON_VALID)
-               g_string_append (str, "U ");
-
-       gtk_label_set_text (label, str->str);
+       if (attrs & GDA_VALUE_ATTR_IS_NULL) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "IS_NULL");
+       }
+       if (attrs & GDA_VALUE_ATTR_CAN_BE_NULL) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "CAN_BE_NULL");
+       }
+       if (attrs & GDA_VALUE_ATTR_IS_DEFAULT) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "IS_DEFAULT");
+       }
+       if (attrs & GDA_VALUE_ATTR_CAN_BE_DEFAULT) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "CAN_BE_DEFAULT");
+       }
+       if (attrs & GDA_VALUE_ATTR_IS_UNCHANGED) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "IS_UNCHANGED");
+       }
+       if (attrs & GDA_VALUE_ATTR_DATA_NON_VALID) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "NON_VALID");
+       }
+       if (attrs & GDA_VALUE_ATTR_READ_ONLY) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "READ_ONLY");
+       }
+       if (attrs & GDA_VALUE_ATTR_HAS_VALUE_ORIG) {
+               if (!str) str = g_string_new (""); else g_string_append (str, ", ");
+               g_string_append (str, "HAS_VALUE_ORIG");
+       }
+
+       gtk_label_set_text (label, str ? str->str : "");
        g_string_free (str, TRUE);
 
        /* value */
@@ -894,7 +931,6 @@ entry_contents_modified (GtkWidget *entry, G_GNUC_UNUSED gpointer data)
                        blob = gda_value_get_blob (value);
                        strval = g_strdup_printf ("Blob data, size=%ld", ((GdaBinary*) blob)->binary_length);
                }
-
                else
                        strval = gda_data_handler_get_sql_from_value (dh, value);
                gda_value_free (value);
@@ -924,7 +960,6 @@ orig_clicked_cb (GtkButton *button, GtkWidget *entry)
        
        gdaui_data_entry_set_reference_value (GDAUI_DATA_ENTRY (entry), value);
        gda_value_free (value);
-       entry_contents_modified (entry, NULL);
 }
 
 void
diff --git a/testing/gdaui-test-errors.c b/testing/gdaui-test-errors.c
index a1320f3..0f561e8 100644
--- a/testing/gdaui-test-errors.c
+++ b/testing/gdaui-test-errors.c
@@ -27,14 +27,21 @@ static void destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer dat
 
 static gboolean change_unknow_color (GdauiBasicForm *form)
 {
+       static gdouble sign = 1.;
        static gdouble red = .3;
        static gdouble green = .1;
        static gdouble blue = .1;
        static gdouble alpha = .5;
 
-       red += .075;
-       if (red >= 1.)
+       red += .075 * sign;
+       if (red >= 1.) {
+               sign = -1.;
+               red = 1.;
+       }
+       else if (red <= .3) {
+               sign = 1.;
                red = .3;
+       }
        gdaui_basic_form_set_unknown_color (form, red, green, blue, alpha);
        return TRUE; /* keep timer */
 }
diff --git a/testing/gdaui-test-widget-entry.c b/testing/gdaui-test-widget-entry.c
index 85e70ad..1e52039 100644
--- a/testing/gdaui-test-widget-entry.c
+++ b/testing/gdaui-test-widget-entry.c
@@ -144,9 +144,8 @@ main (int argc, char* argv[])
 #define HAVE_NORMAL
 #ifdef HAVE_NORMAL
        /* #0 */
-       tmp = g_strdup_printf ("#%d", index);
-       label = gtk_label_new (tmp);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
+#define L0 "NULL, NULL"
+       label = make_label (0, L0);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        entry = gdaui_entry_new (NULL, NULL);
@@ -154,11 +153,11 @@ main (int argc, char* argv[])
        index++;
        gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
        g_signal_connect (entry, "changed",
-                         G_CALLBACK (entry_changed_cb), tmp);
+                         G_CALLBACK (entry_changed_cb), L0);
+
        /* #1 */
-       tmp = g_strdup_printf ("#%d", index);
-       label = gtk_label_new (tmp);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
+#define L1 "\"€ \", NULL"
+       label = make_label (1, L1);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        entry = gdaui_entry_new ("€ ", NULL);
@@ -166,12 +165,11 @@ main (int argc, char* argv[])
        index++;
        gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
        g_signal_connect (entry, "changed",
-                         G_CALLBACK (entry_changed_cb), tmp);
+                         G_CALLBACK (entry_changed_cb), L1);
 
        /* #2 */
-       tmp = g_strdup_printf ("#%d", index);
-       label = gtk_label_new (tmp);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
+#define L2 "NULL, \"  Ê\""
+       label = make_label (2, L2);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        entry = gdaui_entry_new (NULL, " Ê");
@@ -179,12 +177,11 @@ main (int argc, char* argv[])
        index++;
        gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
        g_signal_connect (entry, "changed",
-                         G_CALLBACK (entry_changed_cb), tmp);
+                         G_CALLBACK (entry_changed_cb), L2);
 
        /* #3 */
-       tmp = g_strdup_printf ("#%d", index);
-       label = gtk_label_new (tmp);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
+#define L3 "\"€€ \", \" êê\""
+       label = make_label (3, L3);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        entry = gdaui_entry_new ("€€ ", " êê");
@@ -192,7 +189,7 @@ main (int argc, char* argv[])
        index++;
        gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
        g_signal_connect (entry, "changed",
-                         G_CALLBACK (entry_changed_cb), tmp);
+                         G_CALLBACK (entry_changed_cb), L3);
 #endif
 
 #define HAVE_FORMATTED
@@ -208,9 +205,8 @@ main (int argc, char* argv[])
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        /* #4 */
-       tmp = g_strdup_printf ("#%d", index);
-       label = gtk_label_new (tmp);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
+#define L4 "\"TIME=00:00:00\", NULL"
+       label = make_label (4, L4);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        entry = gdaui_formatted_entry_new ("TIME=00:00:00", NULL);
@@ -218,21 +214,20 @@ main (int argc, char* argv[])
        index++;
        gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
        g_signal_connect (entry, "changed",
-                         G_CALLBACK (entry_changed_cb), tmp);
+                         G_CALLBACK (entry_changed_cb), L4);
 
        /* #5 */
-       tmp = g_strdup_printf ("#%d", index);
-       label = gtk_label_new (tmp);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
+#define L5 "\"TIME=00€00:00\", \"------- --   \""
+       label = make_label (5, L5);
        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
 
        entry = gdaui_formatted_entry_new ("TIME=00€00:00",
-                                          "------- --   ");
+               "------- --   ");
        entries[index] = entry;
        index++;
        gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
        g_signal_connect (entry, "changed",
-                         G_CALLBACK (entry_changed_cb), tmp);
+                         G_CALLBACK (entry_changed_cb), L5);
 #endif
 
 #define HAVE_NUMERIC


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]