[libgda] Control center: modifications to get rid of deprecated API and improvements



commit 0764e0022227abe864395b298582f14575f0c8c7
Author: Vivien Malerba <malerba gnome-db org>
Date:   Wed Jul 8 15:23:43 2015 +0200

    Control center: modifications to get rid of deprecated API and improvements

 control-center/Makefile.am                         |    4 +-
 control-center/dsn-config.c                        |  283 +++++++++---
 control-center/dsn-config.h                        |    3 +-
 control-center/dsn-properties-dialog.c             |  284 -----------
 control-center/gdaui-bar.c                         |    5 +-
 control-center/gdaui-dsn-assistant.c               |   17 +-
 control-center/gdaui-dsn-editor.c                  |  499 ++++++++++++++++----
 control-center/gdaui-dsn-editor.h                  |   13 +-
 control-center/main.c                              |   81 +---
 control-center/menus.ui                            |   11 +-
 control-center/provider-config.c                   |   19 +-
 control-center/support.c                           |   52 ++
 .../{dsn-properties-dialog.h => support.h}         |   14 +-
 13 files changed, 749 insertions(+), 536 deletions(-)
---
diff --git a/control-center/Makefile.am b/control-center/Makefile.am
index 70b186b..ca11f68 100644
--- a/control-center/Makefile.am
+++ b/control-center/Makefile.am
@@ -27,11 +27,11 @@ gda_control_center_6_0_SOURCES=\
        gdaui-dsn-assistant.h \
        gdaui-dsn-editor.c \
        gdaui-dsn-editor.h \
-       dsn-properties-dialog.c \
-       dsn-properties-dialog.h \
        main.c \
        provider-config.c \
        provider-config.h \
+       support.h \
+       support.c \
        control-center.gresources.c
 
 # resources
diff --git a/control-center/dsn-config.c b/control-center/dsn-config.c
index abfeb97..76b7b27 100644
--- a/control-center/dsn-config.c
+++ b/control-center/dsn-config.c
@@ -24,38 +24,32 @@
 #include <libgda/gda-data-model-array.h>
 #include <libgda-ui/libgda-ui.h>
 #include "dsn-config.h"
-#include "dsn-properties-dialog.h"
 #include "gdaui-bar.h"
+#include "gdaui-dsn-editor.h"
+#include <libgda-ui/internal/utility.h>
 
 #define DSN_CONFIG_DATA "DSN_ConfigData"
+#define ST_NOPROP "noprop"
+#define ST_PROP "prop"
 
 typedef struct {
        GtkWidget *title;
        GtkWidget *dsn_list;
        GtkWidget *dialog;
+       GtkWidget *stack;
+       GdauiDsnEditor *dsn_editor;
+       GtkToggleButton *view_buttons[GDAUI_DSN_EDITOR_PANE_AUTH + 1];
+       GtkWidget *commit_button;
 } DsnConfigPrivate;
 
 static void
 free_private_data (gpointer data)
 {
        DsnConfigPrivate *priv = (DsnConfigPrivate *) data;
-
        g_free (priv);
 }
 
 static void
-list_double_clicked_cb (G_GNUC_UNUSED GdauiGrid *grid, G_GNUC_UNUSED gint row, gpointer user_data)
-{
-       dsn_config_edit_properties (GTK_WIDGET (user_data));
-}
-
-static void
-list_popup_properties_cb (G_GNUC_UNUSED GtkWidget *menu, gpointer user_data)
-{
-       dsn_config_edit_properties (GTK_WIDGET (user_data));
-}
-
-static void
 list_popup_delete_cb (G_GNUC_UNUSED GtkWidget *menu, gpointer user_data)
 {
        dsn_config_delete (GTK_WIDGET (user_data));
@@ -78,40 +72,100 @@ new_menu_item (const gchar *label,
 static void
 list_popup_cb (GdauiRawGrid *grid, GtkMenu *menu, gpointer user_data)
 {
-       GtkWidget *item_delete, *item_properties;
+       GtkWidget *item_delete;
        gboolean ok;
        GArray *selection;
 
        item_delete = new_menu_item (_("_Delete"),
                                     G_CALLBACK (list_popup_delete_cb),
                                     user_data);
-       item_properties = new_menu_item (_("_Properties"),
-                                        G_CALLBACK (list_popup_properties_cb),
-                                        user_data);
 
        selection = gdaui_data_selector_get_selected_rows (GDAUI_DATA_SELECTOR (grid));
        ok = (selection != NULL);
        if (selection)
                g_array_free (selection, TRUE);
        gtk_widget_set_sensitive (item_delete, ok);
-       gtk_widget_set_sensitive (item_properties, ok);
 
        gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
        gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item_delete);
-       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
-       gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item_properties);
+}
+
+static void
+list_selection_changed_cb (GdauiRawGrid *grid, gpointer user_data)
+{
+       DsnConfigPrivate *priv;
+       GdaDataModel *model;
+       GArray *selection;
+       gchar *str;
+       const GValue *cvalue;
+       GApplication *app;
+       GtkWidget *win = gtk_widget_get_toplevel (GTK_WIDGET (grid));
+       if (gtk_widget_is_toplevel (win)) {
+               g_simple_action_set_enabled (G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP (win),
+                                                                                         
"DatasourceDelete")), FALSE);
+       }
+
+       priv = g_object_get_data (G_OBJECT (user_data), DSN_CONFIG_DATA);
+
+       selection = gdaui_data_selector_get_selected_rows (GDAUI_DATA_SELECTOR (priv->dsn_list));
+       if (!selection) {
+               gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), ST_NOPROP);
+               return;
+       }
+
+       model = gdaui_data_selector_get_model (GDAUI_DATA_SELECTOR (priv->dsn_list));
+       if (!GDA_IS_DATA_MODEL (model)) {
+               g_array_free (selection, TRUE);
+               gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), ST_NOPROP);
+               return;
+       }
+
+       cvalue = gda_data_model_get_value_at (model, 0, g_array_index (selection, gint, 0), NULL);
+       g_array_free (selection, TRUE);
+       if (!cvalue) {
+               gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), ST_NOPROP);
+               return;
+       }
+
+       str = gda_value_stringify ((GValue *) cvalue);
+       g_print ("==> %s\n", str);
+
+       GdaDsnInfo *dsn_info;
+       dsn_info = gda_config_get_dsn_info (str);
+       g_free (str);
+       if (!dsn_info) {
+               /* something went wrong here... */
+               gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), ST_NOPROP);
+               return;
+       }
+
+       gdaui_dsn_editor_set_dsn (priv->dsn_editor, dsn_info);
+
+       if (gdaui_dsn_editor_need_authentication (priv->dsn_editor))
+               gtk_widget_show (GTK_WIDGET (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH]));
+       else
+               gtk_widget_hide (GTK_WIDGET (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH]));
+       gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_DEFINITION], TRUE);
+
+       gtk_stack_set_visible_child_name (GTK_STACK (priv->stack), ST_PROP);
+       if (gtk_widget_is_toplevel (win)) {
+               g_simple_action_set_enabled (G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP (win),
+                                                                                         
"DatasourceDelete")), TRUE);
+       }
 }
 
 /*
  * Public functions
  */
+static void dsn_editor_changed_cb (G_GNUC_UNUSED GdauiDsnEditor *editor, GtkWidget *dsn);
+static void view_toggled_cb (GtkToggleButton *button, GtkWidget *dsn);
+static void save_cb (GtkButton *button, GtkWidget *dsn);
 
 GtkWidget *
 dsn_config_new (void)
 {
        DsnConfigPrivate *priv;
        GtkWidget *dsn;
-       GtkWidget *box;
        GtkWidget *image;
        GtkWidget *label;
        GtkWidget *sw;
@@ -140,12 +194,24 @@ dsn_config_new (void)
        gtk_box_pack_start (GTK_BOX (dsn), priv->title, FALSE, FALSE, 0);
        gtk_widget_show (priv->title);
 
+       /* horizontal box for the provider list and its properties */
+       GtkWidget *hbox;
+       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+       gtk_box_pack_start (GTK_BOX (dsn), hbox, TRUE, TRUE, 0);
+
+       /* left part */
+       GtkWidget *vbox;
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       gtk_widget_set_size_request (vbox, 150, -1);
+       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
+
        /* create the data source list */
        sw = gtk_scrolled_window_new (NULL, NULL);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC,
                                        GTK_POLICY_AUTOMATIC);
-       gtk_box_pack_start (GTK_BOX (dsn), sw, TRUE, TRUE, 0);
-       
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
+       gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
+
        model = gda_config_list_dsn ();
        priv->dsn_list = gdaui_raw_grid_new (model);
        gtk_tree_view_move_column_after (GTK_TREE_VIEW (priv->dsn_list),
@@ -154,52 +220,159 @@ dsn_config_new (void)
 
        g_object_unref (model);
        g_object_set_data (G_OBJECT (dsn), "grid", priv->dsn_list);
-       gdaui_data_proxy_column_set_editable (GDAUI_DATA_PROXY (priv->dsn_list), 0, FALSE);
-       gdaui_data_selector_set_column_visible (GDAUI_DATA_SELECTOR (priv->dsn_list), 3, FALSE);
-       gdaui_data_selector_set_column_visible (GDAUI_DATA_SELECTOR (priv->dsn_list), 4, FALSE);
+       gdaui_data_proxy_column_set_editable (GDAUI_DATA_PROXY (priv->dsn_list), 0, FALSE);
+       gdaui_data_selector_set_column_visible (GDAUI_DATA_SELECTOR (priv->dsn_list), -1, FALSE);
+       gdaui_data_selector_set_column_visible (GDAUI_DATA_SELECTOR (priv->dsn_list), 0, TRUE);
+       gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->dsn_list), FALSE);
        g_object_set (priv->dsn_list, "info-cell-visible", FALSE, NULL);
 
        gtk_container_add (GTK_CONTAINER (sw), priv->dsn_list);
-       
-       gtk_widget_show_all (sw);
-       g_signal_connect (priv->dsn_list, "double-clicked",
-                         G_CALLBACK (list_double_clicked_cb), dsn);
+
+       g_signal_connect (priv->dsn_list, "selection-changed",
+                         G_CALLBACK (list_selection_changed_cb), dsn);
        g_signal_connect (priv->dsn_list, "populate-popup",
                          G_CALLBACK (list_popup_cb), dsn);
 
+       /* add/delete buttons */
+       GtkWidget *toolbar;
+       toolbar = gtk_toolbar_new ();
+       gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_SMALL_TOOLBAR);
+       gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), "inline-toolbar");
+       gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
+       GtkToolItem *titem;
+       titem = gtk_tool_button_new (NULL, NULL);
+       gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (titem), "list-add-symbolic");
+       gtk_actionable_set_action_name (GTK_ACTIONABLE (titem), "win.DatasourceNew");
+       gtk_toolbar_insert (GTK_TOOLBAR (toolbar), titem, -1);
+       titem = gtk_tool_button_new (NULL, NULL);
+       gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (titem), "list-remove-symbolic");
+       gtk_actionable_set_action_name (GTK_ACTIONABLE (titem), "win.DatasourceDelete");
+       gtk_toolbar_insert (GTK_TOOLBAR (toolbar), titem, -1);
+
+       /* create the data source's properties */
+       GtkWidget *stack;
+       stack = gtk_stack_new ();
+       priv->stack = stack;
+       gtk_box_pack_start (GTK_BOX (hbox), stack, TRUE, TRUE, 10);
+
+       label = gtk_label_new (_("No data source selected."));
+       gtk_stack_add_named (GTK_STACK (stack), label, ST_NOPROP);
+
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       gtk_stack_add_named (GTK_STACK (stack), vbox, ST_PROP);
+
+       GtkWidget *form;
+       form = gdaui_dsn_editor_new ();
+       priv->dsn_editor = GDAUI_DSN_EDITOR (form);
+       gtk_box_pack_start (GTK_BOX (vbox), form, TRUE, TRUE, 0);
+       g_signal_connect (priv->dsn_editor, "changed",
+                         G_CALLBACK (dsn_editor_changed_cb), dsn);
+
+       /* action buttons */
+       GtkWidget *hbox2;
+       hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+       gtk_box_pack_start (GTK_BOX (vbox), hbox2, FALSE, FALSE, 6);
+
+       GtkWidget *bbox;
+       bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+       gtk_widget_set_hexpand (bbox, TRUE);
+       gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_CENTER);
+       gtk_box_pack_start (GTK_BOX (hbox2), bbox, FALSE, FALSE, 6);
+
+       GtkWidget *button;
+       button = gtk_toggle_button_new_with_label (_("Definition"));
+       gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+       priv->view_buttons [GDAUI_DSN_EDITOR_PANE_DEFINITION] = GTK_TOGGLE_BUTTON (button);
+       g_signal_connect (button, "toggled",
+                         G_CALLBACK (view_toggled_cb), dsn);
+
+       button = gtk_toggle_button_new_with_label (_("Parameters"));
+       gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+       priv->view_buttons [GDAUI_DSN_EDITOR_PANE_PARAMS] = GTK_TOGGLE_BUTTON (button);
+       g_signal_connect (button, "toggled",
+                         G_CALLBACK (view_toggled_cb), dsn);
+
+       button = gtk_toggle_button_new_with_label (_("Authentication"));
+       gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+       priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH] = GTK_TOGGLE_BUTTON (button);
+       g_signal_connect (button, "toggled",
+                         G_CALLBACK (view_toggled_cb), dsn);
+
+       button = gtk_button_new_from_icon_name ("document-save-symbolic", GTK_ICON_SIZE_BUTTON);
+       gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE, FALSE, 0);
+       priv->commit_button = button;
+       gtk_widget_set_sensitive (button, FALSE);
+       gtk_widget_set_tooltip_text (button, _("Write changes made to the DSN"));
+       g_signal_connect (button, "clicked",
+                         G_CALLBACK (save_cb), dsn);
+
+       gtk_widget_show_all (hbox);
        return dsn;
 }
 
-void
-dsn_config_edit_properties (GtkWidget *dsn)
+static void
+view_toggled_cb (GtkToggleButton *button, GtkWidget *dsn)
 {
+       if (! gtk_toggle_button_get_active (button))
+               return;
+
        DsnConfigPrivate *priv;
-       GdaDataModel *model;
-       GArray *selection;
-       gchar *str;
-       const GValue *cvalue;
+       priv = g_object_get_data (G_OBJECT (dsn), DSN_CONFIG_DATA);
+       if (button == priv->view_buttons [GDAUI_DSN_EDITOR_PANE_DEFINITION]) {
+               gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_PARAMS], FALSE);
+               gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH], FALSE);
+               gdaui_dsn_editor_show_pane (priv->dsn_editor, GDAUI_DSN_EDITOR_PANE_DEFINITION);
+       }
+       else if (button == priv->view_buttons [GDAUI_DSN_EDITOR_PANE_PARAMS]) {
+               gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_DEFINITION], FALSE);
+               gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH], FALSE);
+               gdaui_dsn_editor_show_pane (priv->dsn_editor, GDAUI_DSN_EDITOR_PANE_PARAMS);
+       }
+       else if (button == priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH]) {
+               gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_DEFINITION], FALSE);
+               gtk_toggle_button_set_active (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_PARAMS], FALSE);
+               gdaui_dsn_editor_show_pane (priv->dsn_editor, GDAUI_DSN_EDITOR_PANE_AUTH);
+       }
+       else
+               g_assert_not_reached ();
+}
 
+static void
+dsn_editor_changed_cb (GdauiDsnEditor *editor, GtkWidget *dsn)
+{
+       DsnConfigPrivate *priv;
        priv = g_object_get_data (G_OBJECT (dsn), DSN_CONFIG_DATA);
-       
-       selection = gdaui_data_selector_get_selected_rows (GDAUI_DATA_SELECTOR (priv->dsn_list));
-       if (!selection)
-               return;
 
-       model = gdaui_data_selector_get_model (GDAUI_DATA_SELECTOR (priv->dsn_list));
-       if (!GDA_IS_DATA_MODEL (model)) {
-               g_array_free (selection, TRUE);
-               return;
-       }
+       gboolean can_save = FALSE;
+       can_save = gdaui_dsn_editor_has_been_changed (editor);
 
-       cvalue = gda_data_model_get_value_at (model, 0, g_array_index (selection, gint, 0), NULL);
-       g_array_free (selection, TRUE);
-       if (!cvalue) 
-               return;
+       gtk_widget_set_sensitive (priv->commit_button, can_save);
 
-       str = gda_value_stringify ((GValue *) cvalue);
-       dsn_properties_dialog (GTK_WINDOW (gtk_widget_get_toplevel (dsn)), str);
+       if (gdaui_dsn_editor_need_authentication (priv->dsn_editor))
+               gtk_widget_show (GTK_WIDGET (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH]));
+       else
+               gtk_widget_hide (GTK_WIDGET (priv->view_buttons [GDAUI_DSN_EDITOR_PANE_AUTH]));
+}
 
-       g_free (str);
+static void
+save_cb (GtkButton *button, GtkWidget *dsn)
+{
+       DsnConfigPrivate *priv;
+       priv = g_object_get_data (G_OBJECT (dsn), DSN_CONFIG_DATA);
+
+       const GdaDsnInfo *newdsn;
+       newdsn = gdaui_dsn_editor_get_dsn (priv->dsn_editor);
+
+       GError *error = NULL;
+       if (! gda_config_define_dsn (newdsn, &error)) {
+               _gdaui_utility_show_error (NULL, _("Could not save DSN definition: %s"), error ? 
error->message : _("No detail"));
+               g_clear_error (&error);
+       }
+
+       /* update reference DSN and UI */
+       GdaDsnInfo *dsn_info;
+       dsn_info = gda_config_get_dsn_info (newdsn->name);
+       gdaui_dsn_editor_set_dsn (priv->dsn_editor, dsn_info);
 }
 
 void
@@ -244,8 +417,8 @@ dsn_config_delete (GtkWidget *dsn)
                dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gtk_widget_get_toplevel 
(priv->dsn_list)),
                                                             GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
                                                             GTK_BUTTONS_YES_NO, 
-                                                            "<b>%s:</b>\n\n%s", _("Data source removal 
confirmation"),
-                                                            str);
+                                                            "<b>%s:</b>\n\n%s",
+                                                            _("Data source removal confirmation"), str);
                g_free (str);
                gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
                gtk_widget_show (dialog);
diff --git a/control-center/dsn-config.h b/control-center/dsn-config.h
index 3f9c3eb..ae2c83e 100644
--- a/control-center/dsn-config.h
+++ b/control-center/dsn-config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2011 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2009 - 2015 Vivien Malerba <malerba gnome-db org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,7 +22,6 @@
 #include <gtk/gtk.h>
 
 GtkWidget *dsn_config_new             (void);
-void       dsn_config_edit_properties (GtkWidget *dsn);
 void       dsn_config_delete          (GtkWidget *dsn);
 
 #endif
diff --git a/control-center/gdaui-bar.c b/control-center/gdaui-bar.c
index 60574ad..a59cd05 100644
--- a/control-center/gdaui-bar.c
+++ b/control-center/gdaui-bar.c
@@ -161,7 +161,7 @@ gdaui_bar_init (GdauiBar *bar)
        GtkStyleContext *context;
        if (!css_provider) {
 #define CSS ".gdauibar {\n"                            \
-                       "background-color: #b3b3b3;\n"  \
+                       "border-radius: 3px;\n"         \
                        "padding: 5px;\n"               \
                        "}"                             \
                        ".gdauibar_button {\n"                  \
@@ -181,7 +181,7 @@ gdaui_bar_init (GdauiBar *bar)
                        "-GtkButtonBox-child-internal-pad-x : 1px;\n"   \
                        "-GtkButtonBox-child-min-width : 0px;\n"        \
                        "border-style: solid;\n"                        \
-                       "border-radius: 5px;\n"                         \
+                       "border-radius: 3px;\n"                         \
                        "}"
                css_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
                gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (css_provider), CSS, -1, NULL);
@@ -189,6 +189,7 @@ gdaui_bar_init (GdauiBar *bar)
        context = gtk_widget_get_style_context (GTK_WIDGET (bar));
        gtk_style_context_add_provider (context, css_provider, G_MAXUINT);
        gtk_style_context_add_class (context, "gdauibar");
+       gtk_style_context_add_class (context, "inline-toolbar");
 }
 
 static void
diff --git a/control-center/gdaui-dsn-assistant.c b/control-center/gdaui-dsn-assistant.c
index d31e1ab..677a08e 100644
--- a/control-center/gdaui-dsn-assistant.c
+++ b/control-center/gdaui-dsn-assistant.c
@@ -83,16 +83,6 @@ enum {
 static guint config_assistant_signals[LAST_SIGNAL] = { 0, };
 static GObjectClass *parent_class = NULL;
 
-static void 
-data_source_info_free (GdaDsnInfo *info)
-{
-       g_free (info->provider); 
-       g_free (info->cnc_string); 
-       g_free (info->description);
-       g_free (info->auth_string);
-       g_free (info);
-}
-
 /*
  * Callbacks
  */
@@ -116,7 +106,7 @@ assistant_applied_cb (GtkAssistant *assist, G_GNUC_UNUSED gpointer data)
 
        /* clear the internal dsn_info */
        if (assistant->priv->dsn_info) {
-               data_source_info_free (assistant->priv->dsn_info);
+               gda_dsn_info_free (assistant->priv->dsn_info);
                assistant->priv->dsn_info = NULL;
        }
 
@@ -177,7 +167,7 @@ assistant_applied_cb (GtkAssistant *assist, G_GNUC_UNUSED gpointer data)
 
        /* Data source declaration */
        if (allok) {
-               assistant->priv->dsn_info = g_new0 (GdaDsnInfo, 1);
+               assistant->priv->dsn_info = gda_dsn_info_new ();
                assistant->priv->dsn_info->name = g_strdup (gtk_entry_get_text (GTK_ENTRY 
(assistant->priv->general_name)));
                assistant->priv->dsn_info->provider = g_strdup (
                                         gdaui_provider_selector_get_provider (
@@ -669,8 +659,7 @@ gdaui_dsn_assistant_finalize (GObject *object)
        g_return_if_fail (GDAUI_IS_DSN_ASSISTANT (assistant));
 
        /* free memory */
-       if (assistant->priv->dsn_info)
-               data_source_info_free (assistant->priv->dsn_info);
+       gda_dsn_info_free (assistant->priv->dsn_info);
 
        if (assistant->priv->create_db_op)
                g_object_unref (assistant->priv->create_db_op);
diff --git a/control-center/gdaui-dsn-editor.c b/control-center/gdaui-dsn-editor.c
index 2b2bcae..0e7785a 100644
--- a/control-center/gdaui-dsn-editor.c
+++ b/control-center/gdaui-dsn-editor.c
@@ -22,25 +22,28 @@
 #include <libgda/libgda.h>
 #include "gdaui-dsn-editor.h"
 #include <libgda-ui/gdaui-provider-selector.h>
-#include <libgda-ui/gdaui-basic-form.h>
 #include <glib/gi18n-lib.h>
 #include <libgda-ui/internal/gdaui-provider-spec-editor.h>
 #include <libgda-ui/internal/gdaui-provider-auth-editor.h>
+#include "support.h"
+#include "gdaui-login-dialog.h"
+#include <libgda-ui/internal/utility.h>
 
 struct _GdauiDsnEditorPrivate {
+       gchar     *name;
+       GtkWidget *icon;
        GtkWidget *wname;
        GtkWidget *wprovider;
        GtkWidget *wdesc;
        GtkWidget *is_system;
        GtkWidget *warning;
 
-       GtkWidget *dsn_spec_expander;
+       GtkWidget *stack;
        GtkWidget *dsn_spec;
-
-       GtkWidget *dsn_auth_expander;
        GtkWidget *dsn_auth;    
 
        GdaDsnInfo *dsn_info;
+       gboolean    no_change_signal; /* set to %TRUE when we don't want to emit the "changed" signal */
 };
 
 static void gdaui_dsn_editor_class_init (GdauiDsnEditorClass *klass);
@@ -59,6 +62,17 @@ static GObjectClass *parent_class = NULL;
 /*
  * GdauiDsnEditor class implementation
  */
+static void
+_changed_cb (GdauiDsnEditor *config)
+{
+       gboolean can_save = FALSE;
+       can_save = gdaui_dsn_editor_has_been_changed (config);
+       GtkWindow *win;
+       win = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ()));
+       GAction *action;
+       action = g_action_map_lookup_action (G_ACTION_MAP (win), "DSNReset");
+       g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_save);
+}
 
 static void
 gdaui_dsn_editor_class_init (GdauiDsnEditorClass *klass)
@@ -68,7 +82,7 @@ gdaui_dsn_editor_class_init (GdauiDsnEditorClass *klass)
        parent_class = g_type_class_peek_parent (klass);
 
        object_class->finalize = gdaui_dsn_editor_finalize;
-       klass->changed = NULL;
+       klass->changed = _changed_cb;
 
        /* add class signals */
        gdaui_dsn_editor_signals[CHANGED] =
@@ -84,21 +98,58 @@ gdaui_dsn_editor_class_init (GdauiDsnEditorClass *klass)
 static void
 field_changed_cb (GtkWidget *widget, GdauiDsnEditor *config)
 {
-       if (widget == config->priv->wprovider) 
+       if (widget == config->priv->wprovider) {
                /* replace the expander's contents */
+               const gchar *pname;
+               pname = gdaui_provider_selector_get_provider (GDAUI_PROVIDER_SELECTOR 
(config->priv->wprovider));
                _gdaui_provider_spec_editor_set_provider (GDAUI_PROVIDER_SPEC_EDITOR (config->priv->dsn_spec),
-                                               gdaui_provider_selector_get_provider 
-                                               (GDAUI_PROVIDER_SELECTOR (config->priv->wprovider)));
+                                                         pname);
+               _gdaui_provider_auth_editor_set_provider (GDAUI_PROVIDER_AUTH_EDITOR (config->priv->dsn_auth),
+                                                         pname);
+
+               GdaProviderInfo *pinfo;
+               pinfo = gda_config_get_provider_info (pname);
+
+               GdkPixbuf *pix;
+               pix = support_create_pixbuf_for_provider (pinfo);
+               if (pix) {
+                       gtk_image_set_from_pixbuf (GTK_IMAGE (config->priv->icon), pix);
+                       g_object_unref (pix);
+               }
+               else
+                       gtk_image_clear (GTK_IMAGE (config->priv->icon));
 
-       g_signal_emit (config, gdaui_dsn_editor_signals[CHANGED], 0, NULL);
+               if (pinfo)
+                       gtk_widget_hide (config->priv->warning);
+               else
+                       gtk_widget_show (config->priv->warning);
+       }
+
+       if (! config->priv->no_change_signal)
+               g_signal_emit (config, gdaui_dsn_editor_signals[CHANGED], 0, NULL);
 }
 
 static void
 field_toggled_cb (G_GNUC_UNUSED GtkWidget *widget, GdauiDsnEditor *config)
 {
-       g_signal_emit (config, gdaui_dsn_editor_signals[CHANGED], 0, NULL);
+       if (! config->priv->no_change_signal)
+               g_signal_emit (config, gdaui_dsn_editor_signals[CHANGED], 0, NULL);
 }
 
+#define PANE_DEFINITION "PANE_DEF"
+#define PANE_PARAMS "PANE_PARAMS"
+#define PANE_AUTH "PANE_AUTH"
+
+static void dsn_test_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *state, gpointer data);
+static void dsn_reset_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *state, gpointer data);
+static void dsn_copy_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *state, gpointer data);
+
+static GActionEntry win_entries[] = {
+        { "DSNTest", dsn_test_cb, NULL, NULL, NULL },
+       { "DSNReset", dsn_reset_cb, NULL, NULL, NULL },
+       { "DSNCopy", dsn_copy_cb, NULL, NULL, NULL },
+};
+
 static void
 gdaui_dsn_editor_init (GdauiDsnEditor *config, G_GNUC_UNUSED GdauiDsnEditorClass *klass)
 {
@@ -106,7 +157,6 @@ gdaui_dsn_editor_init (GdauiDsnEditor *config, G_GNUC_UNUSED GdauiDsnEditorClass
        GtkWidget *label;
        GtkWidget *exp;
        gchar *str;
-       GtkSizeGroup *labels_size_group;
 
        g_return_if_fail (GDAUI_IS_DSN_EDITOR (config));
 
@@ -115,41 +165,64 @@ gdaui_dsn_editor_init (GdauiDsnEditor *config, G_GNUC_UNUSED GdauiDsnEditorClass
        /* allocate private structure */
        config->priv = g_new0 (GdauiDsnEditorPrivate, 1);
        config->priv->dsn_info = g_new0 (GdaDsnInfo, 1);
-
-       /* size group */
-       labels_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
-
+       config->priv->no_change_signal = TRUE;
+
+       /* data source's name and icon */
+       GtkWidget *hbox_header;
+       hbox_header = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+       gtk_box_pack_start (GTK_BOX (config), hbox_header, FALSE, FALSE, 6);
+       config->priv->icon = gtk_image_new ();
+       gtk_widget_set_size_request (config->priv->icon, -1, SUPPORT_ICON_SIZE);
+       gtk_box_pack_start (GTK_BOX (hbox_header), config->priv->icon, FALSE, FALSE, 0);
+       config->priv->wname = gtk_label_new ("");
+       gtk_box_pack_start (GTK_BOX (hbox_header), config->priv->wname, FALSE, FALSE, 10);
+
+       GtkWidget *menu_button;
+       menu_button = gtk_menu_button_new ();
+       gtk_box_pack_end (GTK_BOX (hbox_header), menu_button, FALSE, FALSE, 0);
+
+       GtkWidget *menu_icon;
+        menu_icon = gtk_image_new_from_icon_name ("open-menu-symbolic", GTK_ICON_SIZE_MENU);
+        gtk_button_set_image (GTK_BUTTON (menu_button), menu_icon);
+
+       GMenu *smenu;
+        smenu = g_menu_new ();
+        gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (menu_button), G_MENU_MODEL (smenu));
+
+       GMenuItem *mitem;
+        mitem = g_menu_item_new ("Test data source", "win.DSNTest");
+        g_menu_insert_item (smenu, -1, mitem);
+        mitem = g_menu_item_new ("Reset data source's changes", "win.DSNReset");
+        g_menu_insert_item (smenu, -1, mitem);
+        mitem = g_menu_item_new ("Duplicate data source", "win.DSNCopy");
+        g_menu_insert_item (smenu, -1, mitem);
+
+       GtkWindow *win;
+       win = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ()));
+       g_action_map_add_action_entries (G_ACTION_MAP (win), win_entries, G_N_ELEMENTS (win_entries), config);
+
+       /* stack in a scrolled window */
+       GtkWidget *sw;
+       sw = gtk_scrolled_window_new (NULL, NULL);
+       gtk_widget_set_vexpand (sw, TRUE);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_NONE);
+       gtk_box_pack_start (GTK_BOX (config), sw, TRUE, TRUE, 6);
+
+       /* Stack */
+       config->priv->stack = gtk_stack_new ();
+       gtk_stack_set_transition_type (GTK_STACK (config->priv->stack), 
GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
+       gtk_container_add (GTK_CONTAINER (sw), config->priv->stack);
+       
        /* set up widgets */
        grid = gtk_grid_new ();
        gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
        gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
        gtk_widget_show (grid);
-       gtk_box_pack_start (GTK_BOX (config), grid, TRUE, TRUE, 0);
-
-       str = g_strdup_printf ("%s <span foreground='red' weight='bold'>*</span>", _("Data source _name:"));
-       label = gtk_label_new ("");
-       gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str);
-       g_free (str);
-       gtk_widget_set_halign (label, GTK_ALIGN_START);
-       gtk_size_group_add_widget (labels_size_group, label);
-       gtk_widget_show (label);
-
-       gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
-       config->priv->wname = gtk_entry_new ();
-        gtk_editable_set_editable (GTK_EDITABLE (config->priv->wname), FALSE);
-       g_object_set (G_OBJECT (config->priv->wname), "can-focus", FALSE, NULL);
-
-        gtk_widget_show (config->priv->wname);
-       gtk_label_set_mnemonic_widget (GTK_LABEL (label), config->priv->wname);
-       gtk_widget_show (config->priv->wname);
-       gtk_editable_set_editable (GTK_EDITABLE (config->priv->wname), FALSE);
-       g_signal_connect (G_OBJECT (config->priv->wname), "changed",
-                         G_CALLBACK (field_changed_cb), config);
-       gtk_grid_attach (GTK_GRID (grid), config->priv->wname, 1, 0, 1, 1);
 
        label = gtk_label_new_with_mnemonic (_("_System wide data source:"));
        gtk_widget_set_halign (label, GTK_ALIGN_START);
-       gtk_size_group_add_widget (labels_size_group, label);
+       gtk_widget_set_hexpand (label, FALSE);
+       g_object_set (G_OBJECT (label), "xalign", 0., NULL);
        gtk_widget_show (label);
        gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
        config->priv->is_system = gtk_check_button_new ();
@@ -163,10 +236,12 @@ gdaui_dsn_editor_init (GdauiDsnEditor *config, G_GNUC_UNUSED GdauiDsnEditorClass
        gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), str);
        g_free (str);
        gtk_widget_set_halign (label, GTK_ALIGN_START);
-       gtk_size_group_add_widget (labels_size_group, label);
+       gtk_widget_set_hexpand (label, FALSE);
+       g_object_set (G_OBJECT (label), "xalign", 0., NULL);
        gtk_widget_show (label);
        gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
        config->priv->wprovider = gdaui_provider_selector_new ();
+       gtk_widget_set_hexpand (config->priv->wprovider, TRUE);
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), config->priv->wprovider);
        gtk_widget_show (config->priv->wprovider);
        g_signal_connect (G_OBJECT (config->priv->wprovider), "changed",
@@ -175,56 +250,226 @@ gdaui_dsn_editor_init (GdauiDsnEditor *config, G_GNUC_UNUSED GdauiDsnEditorClass
 
        label = gtk_label_new_with_mnemonic (_("_Description:"));
        gtk_widget_set_halign (label, GTK_ALIGN_START);
-       gtk_size_group_add_widget (labels_size_group, label);
+       gtk_widget_set_hexpand (label, FALSE);
+       g_object_set (G_OBJECT (label), "xalign", 0., NULL);
        gtk_widget_show (label);
        gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
-       config->priv->wdesc = gtk_entry_new ();
-        gtk_editable_set_editable (GTK_EDITABLE (config->priv->wdesc), TRUE);
-        gtk_widget_show (config->priv->wdesc);
+
+       sw = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
+       config->priv->wdesc = gtk_text_view_new ();
+       gtk_container_add (GTK_CONTAINER (sw), config->priv->wdesc);
+       gtk_text_view_set_editable (GTK_TEXT_VIEW (config->priv->wdesc), TRUE);
+       gtk_widget_set_vexpand (config->priv->wdesc, TRUE);
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), config->priv->wdesc);
-       gtk_widget_show (config->priv->wdesc);
-       g_signal_connect (G_OBJECT (config->priv->wdesc), "changed",
+       g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (config->priv->wdesc)), "changed",
                          G_CALLBACK (field_changed_cb), config);
-       gtk_grid_attach (GTK_GRID (grid), config->priv->wdesc, 1, 3, 1, 1);
+       gtk_grid_attach (GTK_GRID (grid), sw, 1, 3, 1, 1);
 
        config->priv->warning = gtk_label_new (NULL);
        gtk_label_set_markup (GTK_LABEL (config->priv->warning),
                              _("<span foreground='red'>The database provider used by this data source is not 
available,\n"
                                "editing the data source's attributes is disabled</span>"));
-       gtk_widget_set_halign (config->priv->warning, GTK_ALIGN_START);
+       gtk_widget_set_halign (config->priv->warning, GTK_ALIGN_CENTER);
+       gtk_widget_set_hexpand (config->priv->warning, TRUE);
+       g_object_set (G_OBJECT (config->priv->warning), "xalign", 0.5, NULL);
        gtk_label_set_justify (GTK_LABEL (config->priv->warning), GTK_JUSTIFY_CENTER);
        gtk_label_set_line_wrap (GTK_LABEL (config->priv->warning), TRUE);
        gtk_grid_attach (GTK_GRID (grid), config->priv->warning, 0, 8, 2, 1);
+       gtk_stack_add_named (GTK_STACK (config->priv->stack), grid, PANE_DEFINITION);
 
        /* connection's spec */
-       exp = gtk_expander_new (_("Connection's parameters"));
-       config->priv->dsn_spec_expander = exp;
-       gtk_widget_show (exp);
-       gtk_grid_attach (GTK_GRID (grid), config->priv->dsn_spec_expander, 0, 6, 2, 1);
        config->priv->dsn_spec = _gdaui_provider_spec_editor_new (gdaui_provider_selector_get_provider 
                                                                 (GDAUI_PROVIDER_SELECTOR 
(config->priv->wprovider)));
        g_signal_connect (G_OBJECT (config->priv->dsn_spec), "changed",
                          G_CALLBACK (field_changed_cb), config);
-       gtk_container_add (GTK_CONTAINER (config->priv->dsn_spec_expander), config->priv->dsn_spec);
-       _gdaui_provider_spec_editor_add_to_size_group (GDAUI_PROVIDER_SPEC_EDITOR (config->priv->dsn_spec), 
labels_size_group,
-                                                      GDAUI_BASIC_FORM_LABELS);
        gtk_widget_show (config->priv->dsn_spec);
+       gtk_stack_add_named (GTK_STACK (config->priv->stack), config->priv->dsn_spec, PANE_PARAMS);
 
        /* connection's authentication */
-       exp = gtk_expander_new (_("Authentication"));
-       config->priv->dsn_auth_expander = exp;
-       gtk_widget_show (exp);
-       gtk_grid_attach (GTK_GRID (grid), config->priv->dsn_auth_expander, 0, 7, 2, 1);
        config->priv->dsn_auth = _gdaui_provider_auth_editor_new (gdaui_provider_selector_get_provider 
                                                                 (GDAUI_PROVIDER_SELECTOR 
(config->priv->wprovider)));
        g_signal_connect (G_OBJECT (config->priv->dsn_auth), "changed",
                          G_CALLBACK (field_changed_cb), config);
-       gtk_container_add (GTK_CONTAINER (config->priv->dsn_auth_expander), config->priv->dsn_auth);
-       _gdaui_provider_auth_editor_add_to_size_group (GDAUI_PROVIDER_AUTH_EDITOR (config->priv->dsn_auth), 
labels_size_group,
-                                                      GDAUI_BASIC_FORM_LABELS);
        gtk_widget_show (config->priv->dsn_auth);
+       gtk_stack_add_named (GTK_STACK (config->priv->stack), config->priv->dsn_auth, PANE_AUTH);
+
+       config->priv->no_change_signal = FALSE;
+}
+
+static void
+dsn_test_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *state, gpointer data)
+{
+       GdauiDsnEditor *editor;
+       editor = GDAUI_DSN_EDITOR (data);
+
+       GtkWidget *test_dialog = NULL;
+       GdauiLogin* login = NULL;
+       GdaConnection *cnc = NULL;
+       gboolean auth_needed = gdaui_dsn_editor_need_authentication (editor);
+
+       GtkWindow *parent = NULL;
+       parent = (GtkWindow*) gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW);
+
+       const gchar *dsn;
+       dsn = editor->priv->name;
+       if (auth_needed) {
+               gchar *title;
+               title = g_strdup_printf (_("Login for %s"), dsn);
+               test_dialog = gdaui_login_dialog_new (title, parent);
+               g_free (title);
+               login = gdaui_login_dialog_get_login_widget (GDAUI_LOGIN_DIALOG (test_dialog));
+               g_object_set (G_OBJECT (login), "dsn", dsn, NULL);
+       }
+
+       if (!auth_needed || gdaui_login_dialog_run (GDAUI_LOGIN_DIALOG (test_dialog))) {
+               if (test_dialog)
+                       parent = GTK_WINDOW (test_dialog);
+
+               GtkWidget *msgdialog;
+               GError *error = NULL;
+               const GdaDsnInfo *cinfo = NULL;
+
+               if (login)
+                       cinfo = gdaui_login_get_connection_information (login);
+               cnc = gda_connection_open_from_dsn (dsn,
+                                                   cinfo ? cinfo->auth_string : NULL,
+                                                   GDA_CONNECTION_OPTIONS_NONE, &error);
+               if (cnc) {
+                       msgdialog = gtk_message_dialog_new_with_markup (parent,
+                                                                       GTK_DIALOG_MODAL,
+                                                                       GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
+                                                                       "<b>%s</b>",
+                                                                       _("Connection successfully opened!"));
+                       gda_connection_close (cnc, NULL);
+               }
+               else {
+                       msgdialog = gtk_message_dialog_new_with_markup (parent,
+                                                                       GTK_DIALOG_MODAL,
+                                                                       GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+                                                                       "<b>%s:</b>\n%s",
+                                                                       _("Could not open connection"),
+                                                                       error->message ? error->message : 
_("No detail"));
+                       if (error)
+                               g_error_free (error);
+               }
+
+               gtk_dialog_run (GTK_DIALOG (msgdialog));
+               gtk_widget_destroy (msgdialog);
+       }
+       if (test_dialog)
+               gtk_widget_destroy (test_dialog);
+}
 
-       g_object_unref (labels_size_group);
+static void
+dsn_reset_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *state, gpointer data)
+{
+       GdauiDsnEditor *editor;
+       editor = GDAUI_DSN_EDITOR (data);
+       GdaDsnInfo *orig;
+       orig = gda_config_get_dsn_info (editor->priv->name);
+       gdaui_dsn_editor_set_dsn (editor, orig);
+}
+
+static void
+copy_dlg_entry_changed_cb (GtkEntry *entry, GtkDialog *dlg)
+{
+       gboolean can_create = FALSE;
+       const gchar *name;
+       name = gtk_entry_get_text (entry);
+       if (name && *name && !gda_config_get_dsn_info (name))
+               can_create = TRUE;
+
+       GtkWidget *resp;
+       resp = gtk_dialog_get_widget_for_response (dlg, GTK_RESPONSE_ACCEPT);
+       gtk_widget_set_sensitive (resp, can_create);
+}
+
+static void
+dsn_copy_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *state, gpointer data)
+{
+       GdauiDsnEditor *editor;
+       editor = GDAUI_DSN_EDITOR (data);
+
+       GtkWindow *parent = NULL;
+       parent = (GtkWindow*) gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW);
+
+       GtkWidget *dialog = NULL;
+       dialog = gtk_dialog_new_with_buttons (_("Data source copy"), parent,
+                                             GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                             _("Create data source"), GTK_RESPONSE_ACCEPT,
+                                             _("_Cancel"), GTK_RESPONSE_REJECT,
+                                             NULL);
+       gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
+
+       GtkWidget *grid, *dlg_box, *label, *entry;
+       dlg_box = gtk_dialog_get_content_area (GTK_DIALOG (dialog));    
+
+       grid = gtk_grid_new ();
+       gtk_box_pack_start (GTK_BOX (dlg_box), grid, TRUE, TRUE, 6);
+        gtk_container_set_border_width (GTK_CONTAINER (grid), 0);
+        gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+        gtk_grid_set_column_spacing (GTK_GRID (grid), 5);
+
+       gchar *str;
+       str = g_strdup_printf (_("Define the named of the new data source which will be created as a copy "
+                                "of '%s':"), editor->priv->name); 
+        label = gtk_label_new (str);
+       g_free (str);       
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 2, 1);
+
+        str = _gdaui_utility_markup_title (_("Data source name"), FALSE);
+        label = gtk_label_new ("");
+        gtk_label_set_markup (GTK_LABEL (label), str);
+        g_free (str);
+        gtk_widget_set_halign (label, GTK_ALIGN_START);
+        gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+
+        entry = gtk_entry_new ();
+       guint i;
+       for (i = 1; ; i++) {
+               str = g_strdup_printf ("%s_%u", editor->priv->name, i);
+               if (! gda_config_get_dsn_info (str)) {
+                       gtk_entry_set_text (GTK_ENTRY (entry), str);
+                       g_free (str);
+                       break;
+               }
+               g_free (str);
+       }
+        gtk_editable_set_editable (GTK_EDITABLE (entry), TRUE);
+       g_signal_connect (entry, "changed",
+                         G_CALLBACK (copy_dlg_entry_changed_cb), dialog);
+       gtk_widget_set_hexpand (entry, TRUE);
+        gtk_grid_attach (GTK_GRID (grid), entry, 1, 1, 1, 1);
+
+       gtk_widget_show_all (grid);
+       if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+               const gchar *name;
+               name = gtk_entry_get_text (GTK_ENTRY (entry));
+
+               GdaDsnInfo *dsn_info = NULL;
+               GError *error = NULL;
+               dsn_info = gda_config_get_dsn_info (editor->priv->name);
+               if (dsn_info) {
+                       dsn_info = gda_dsn_info_copy (dsn_info);
+                       g_free (dsn_info->name);
+                       dsn_info->name = g_strdup (name);
+                       gda_config_define_dsn (dsn_info, &error);
+                       gda_dsn_info_free (dsn_info);
+               }
+               else
+                       g_set_error (&error, GDA_CONFIG_ERROR, GDA_CONFIG_DSN_NOT_FOUND_ERROR,
+                                    ("DSN '%s' does not exist anymore"), editor->priv->name);
+
+               if (error) {
+                       _gdaui_utility_show_error (GTK_WINDOW (dialog), _("Could not create data source: %s"),
+                                                  error->message);
+                       g_clear_error (&error);
+               }
+       }
+       gtk_widget_destroy (dialog);
 }
 
 static void
@@ -235,6 +480,7 @@ gdaui_dsn_editor_finalize (GObject *object)
        g_return_if_fail (GDAUI_IS_DSN_EDITOR (config));
 
        /* free memory */
+       g_free (config->priv->name); 
        g_free (config->priv->dsn_info->provider); 
        g_free (config->priv->dsn_info->cnc_string); 
        g_free (config->priv->dsn_info->description);
@@ -306,11 +552,17 @@ gdaui_dsn_editor_get_dsn (GdauiDsnEditor *config)
        g_free (dsn_info->cnc_string); dsn_info->cnc_string = NULL;
        g_free (dsn_info->description); dsn_info->description = NULL;
        g_free (dsn_info->auth_string); dsn_info->auth_string = NULL;
-       dsn_info->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (config->priv->wname)));
+       g_free (dsn_info->name); dsn_info->name = NULL;
+       dsn_info->name = g_strdup (config->priv->name);
        dsn_info->provider = g_strdup (gdaui_provider_selector_get_provider 
                                       (GDAUI_PROVIDER_SELECTOR (config->priv->wprovider)));
        dsn_info->cnc_string = _gdaui_provider_spec_editor_get_specs (GDAUI_PROVIDER_SPEC_EDITOR 
(config->priv->dsn_spec));
-       dsn_info->description = g_strdup (gtk_entry_get_text (GTK_ENTRY (config->priv->wdesc)));
+       GtkTextBuffer *buf;
+       GtkTextIter start, end;
+       buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (config->priv->wdesc));
+       gtk_text_buffer_get_start_iter (buf, &start);
+       gtk_text_buffer_get_end_iter (buf, &end);
+       dsn_info->description = gtk_text_buffer_get_text (buf, &start, &end, FALSE);
        dsn_info->auth_string = _gdaui_provider_auth_editor_get_auth (GDAUI_PROVIDER_AUTH_EDITOR 
(config->priv->dsn_auth));
        dsn_info->is_system = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (config->priv->is_system));
 
@@ -329,21 +581,41 @@ void
 gdaui_dsn_editor_set_dsn (GdauiDsnEditor *editor, const GdaDsnInfo *dsn_info)
 {
        g_return_if_fail (GDAUI_IS_DSN_EDITOR (editor));
+       editor->priv->no_change_signal = TRUE;
 
        if (dsn_info) {
                GdaProviderInfo *pinfo;
-
                pinfo = gda_config_get_provider_info (dsn_info->provider);
-               
-               gtk_entry_set_text (GTK_ENTRY (editor->priv->wname), dsn_info->name);
+
+               GdkPixbuf *pix;
+               pix = support_create_pixbuf_for_provider (pinfo);
+               if (pix) {
+                       gtk_image_set_from_pixbuf (GTK_IMAGE (editor->priv->icon), pix);
+                       g_object_unref (pix);
+               }
+               else
+                       gtk_image_clear (GTK_IMAGE (editor->priv->icon));
+
+               if (pinfo)
+                       gtk_widget_hide (editor->priv->warning);
+               else
+                       gtk_widget_show (editor->priv->warning);
+
+               gchar *tmp;
+               tmp = g_markup_printf_escaped ("<big><b>%s</b></big>", dsn_info->name);
+               gtk_label_set_markup (GTK_LABEL (editor->priv->wname), tmp);
+               g_free (tmp);
+
+               g_free (editor->priv->name);
+               editor->priv->name = g_strdup (dsn_info->name);
                gdaui_provider_selector_set_provider (GDAUI_PROVIDER_SELECTOR (editor->priv->wprovider), 
                                                      dsn_info->provider);
                _gdaui_provider_spec_editor_set_provider (GDAUI_PROVIDER_SPEC_EDITOR (editor->priv->dsn_spec),
                                                         dsn_info->provider);
                _gdaui_provider_spec_editor_set_specs (GDAUI_PROVIDER_SPEC_EDITOR (editor->priv->dsn_spec),
                                                      dsn_info->cnc_string);
-               gtk_entry_set_text (GTK_ENTRY (editor->priv->wdesc),
-                                   dsn_info->description ? dsn_info->description : "");
+               gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->wdesc)),
+                                         dsn_info->description ? dsn_info->description : "", -1);
                _gdaui_provider_auth_editor_set_provider (GDAUI_PROVIDER_AUTH_EDITOR (editor->priv->dsn_auth),
                                                         dsn_info->provider);
                _gdaui_provider_auth_editor_set_auth (GDAUI_PROVIDER_AUTH_EDITOR (editor->priv->dsn_auth),
@@ -351,52 +623,93 @@ gdaui_dsn_editor_set_dsn (GdauiDsnEditor *editor, const GdaDsnInfo *dsn_info)
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->is_system), 
dsn_info->is_system);
                
                if (dsn_info->is_system && !gda_config_can_modify_system_config ()) {
-                       gtk_editable_set_editable (GTK_EDITABLE (editor->priv->wname), FALSE);
                        gtk_widget_set_sensitive (editor->priv->wprovider, FALSE);
-                       gtk_editable_set_editable (GTK_EDITABLE (editor->priv->wdesc), pinfo ? TRUE : FALSE);
+                       gtk_text_view_set_editable (GTK_TEXT_VIEW (editor->priv->wdesc), pinfo ? TRUE : 
FALSE);
                        gtk_widget_set_sensitive (editor->priv->dsn_spec, FALSE);
                        gtk_widget_set_sensitive (editor->priv->dsn_auth, FALSE);
                        gtk_widget_set_sensitive (editor->priv->is_system, FALSE);
                }
                else {
-                       gtk_editable_set_editable (GTK_EDITABLE (editor->priv->wname), FALSE);
                        gtk_widget_set_sensitive (editor->priv->wprovider, pinfo ? TRUE : FALSE);
-                       gtk_editable_set_editable (GTK_EDITABLE (editor->priv->wdesc), pinfo ? TRUE : FALSE);
+                       gtk_text_view_set_editable (GTK_TEXT_VIEW (editor->priv->wdesc), pinfo ? TRUE : 
FALSE);
                        gtk_widget_set_sensitive (editor->priv->dsn_spec, TRUE);
                        gtk_widget_set_sensitive (editor->priv->dsn_auth, TRUE);
                        gtk_widget_set_sensitive (editor->priv->is_system,
                                                  pinfo && gda_config_can_modify_system_config () ? TRUE : 
FALSE);
                }
-               if (pinfo) {
-                       gtk_widget_hide (editor->priv->warning);
-                       gtk_widget_show (editor->priv->dsn_spec_expander);
-               }
-               else {
-                       gtk_widget_show (editor->priv->warning);
-                       gtk_widget_hide (editor->priv->dsn_spec_expander);
-               }
-
-               if (pinfo && gda_config_dsn_needs_authentication (dsn_info->name))
-                       gtk_widget_show (editor->priv->dsn_auth_expander);
-               else
-                       gtk_widget_hide (editor->priv->dsn_auth_expander);
        }
        else {
-               gtk_entry_set_text (GTK_ENTRY (editor->priv->wname), "");
+               gtk_image_clear (GTK_IMAGE (editor->priv->icon));
+               gtk_label_set_text (GTK_LABEL (editor->priv->wname), "");
                gdaui_provider_selector_set_provider (GDAUI_PROVIDER_SELECTOR (editor->priv->wprovider), 
NULL);
                _gdaui_provider_spec_editor_set_provider (GDAUI_PROVIDER_SPEC_EDITOR 
(editor->priv->dsn_spec), NULL);
-               gtk_entry_set_text (GTK_ENTRY (editor->priv->wdesc), "");
+               gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->wdesc)), "", 
-1);
                _gdaui_provider_auth_editor_set_provider (GDAUI_PROVIDER_AUTH_EDITOR 
(editor->priv->dsn_auth), NULL);
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editor->priv->is_system), FALSE);
-               
-               gtk_editable_set_editable (GTK_EDITABLE (editor->priv->wname), FALSE);
+
                gtk_widget_set_sensitive (editor->priv->wprovider, FALSE);
-               gtk_editable_set_editable (GTK_EDITABLE (editor->priv->wdesc), FALSE);
+               gtk_text_view_set_editable (GTK_TEXT_VIEW (editor->priv->wdesc), FALSE);
                gtk_widget_set_sensitive (editor->priv->dsn_spec, FALSE);
                gtk_widget_set_sensitive (editor->priv->dsn_auth, FALSE);
                gtk_widget_set_sensitive (editor->priv->is_system, FALSE);
+       }
+
+       editor->priv->no_change_signal = FALSE;
+       g_signal_emit (editor, gdaui_dsn_editor_signals[CHANGED], 0, NULL);
+}
+
+/**
+ * gdaui_dsn_editor_has_been_changed:
+ * @config: a #GdauiDsnEditor
+ *
+ * Tells if the user has some changes to the DSN being edited, which can be comitted
+ *
+ * Returns: %TRUE if some changes can be comitted
+ */
+gboolean
+gdaui_dsn_editor_has_been_changed (GdauiDsnEditor *config)
+{
+       g_return_val_if_fail (GDAUI_IS_DSN_EDITOR (config), FALSE);
+       GdaDsnInfo *orig;
+       orig = gda_config_get_dsn_info (config->priv->name);
+
+       return ! gda_dsn_info_equal (gdaui_dsn_editor_get_dsn (config), orig);
+}
 
-               gtk_widget_hide (editor->priv->dsn_spec_expander);
-               gtk_widget_hide (editor->priv->dsn_auth_expander);
+/**
+ * gdaui_dsn_editor_show_pane:
+ */
+void
+gdaui_dsn_editor_show_pane (GdauiDsnEditor *config, GdauiDsnEditorPaneType type)
+{
+       switch (type) {
+       case GDAUI_DSN_EDITOR_PANE_DEFINITION:
+               gtk_stack_set_visible_child_name (GTK_STACK (config->priv->stack), PANE_DEFINITION);
+               break;
+       case GDAUI_DSN_EDITOR_PANE_PARAMS:
+               gtk_stack_set_visible_child_name (GTK_STACK (config->priv->stack), PANE_PARAMS);
+               break;
+       case GDAUI_DSN_EDITOR_PANE_AUTH:
+               gtk_stack_set_visible_child_name (GTK_STACK (config->priv->stack), PANE_AUTH);
+               break;
+       default:
+               g_assert_not_reached ();
        }
 }
+
+/**
+ * gdaui_dsn_editor_need_authentication:
+ */
+gboolean
+gdaui_dsn_editor_need_authentication (GdauiDsnEditor *config)
+{
+       const GdaDsnInfo *dsn_info;
+       dsn_info = gdaui_dsn_editor_get_dsn (config);
+
+       GdaProviderInfo *pinfo;
+       pinfo = gda_config_get_provider_info (dsn_info->provider);
+       if (pinfo && pinfo->auth_params && pinfo->auth_params->holders)
+               return TRUE;
+       else
+               return FALSE;
+}
diff --git a/control-center/gdaui-dsn-editor.h b/control-center/gdaui-dsn-editor.h
index c0b417f..07911a4 100644
--- a/control-center/gdaui-dsn-editor.h
+++ b/control-center/gdaui-dsn-editor.h
@@ -46,12 +46,21 @@ struct _GdauiDsnEditorClass {
        void (* changed) (GdauiDsnEditor *config);
 };
 
+typedef enum {
+       GDAUI_DSN_EDITOR_PANE_DEFINITION,
+       GDAUI_DSN_EDITOR_PANE_PARAMS,
+       GDAUI_DSN_EDITOR_PANE_AUTH
+} GdauiDsnEditorPaneType;
+
 GType                    gdaui_dsn_editor_get_type (void) G_GNUC_CONST;
 GtkWidget               *gdaui_dsn_editor_new (void);
+gboolean                 gdaui_dsn_editor_has_been_changed (GdauiDsnEditor *config);
 
 const GdaDsnInfo        *gdaui_dsn_editor_get_dsn (GdauiDsnEditor *config);
-void                     gdaui_dsn_editor_set_dsn (GdauiDsnEditor *config,
-                                                  const GdaDsnInfo *dsn_info);
+void                     gdaui_dsn_editor_set_dsn (GdauiDsnEditor *config, const GdaDsnInfo *dsn_info);
+
+void                     gdaui_dsn_editor_show_pane (GdauiDsnEditor *config, GdauiDsnEditorPaneType type);
+gboolean                 gdaui_dsn_editor_need_authentication (GdauiDsnEditor *config);
 
 G_END_DECLS
 
diff --git a/control-center/main.c b/control-center/main.c
index cd05a51..db99f99 100644
--- a/control-center/main.c
+++ b/control-center/main.c
@@ -26,6 +26,7 @@
 #include "dsn-config.h"
 #include "provider-config.h"
 #include "gdaui-dsn-assistant.h"
+#include <libgda-ui/internal/utility.h>
 
 GtkApplication *app;
 GtkWindow *main_window;
@@ -36,38 +37,6 @@ GtkWindow *main_window;
 static GtkWidget *create_main_stack (GtkApplicationWindow *app_window);
 
 static void
-show_error (GtkWindow *parent, const gchar *format, ...)
-{
-        va_list args;
-        gchar sz[2048];
-        GtkWidget *dialog;
-
-        /* build the message string */
-        va_start (args, format);
-        vsnprintf (sz, sizeof sz, format, args);
-        va_end (args);
-
-        /* create the error message dialog */
-       gchar *str;
-       str = g_strconcat ("<span weight=\"bold\">",
-                           _("Error:"),
-                           "</span>\n",
-                           sz,
-                           NULL);
-
-       dialog = gtk_message_dialog_new_with_markup (parent,
-                                                     GTK_DIALOG_DESTROY_WITH_PARENT |
-                                                     GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
-                                                     GTK_BUTTONS_CLOSE, "%s", str);
-        gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
-                                      gtk_button_new_with_mnemonic (_("_Ok")),
-                                      GTK_RESPONSE_OK);
-        gtk_widget_show_all (dialog);
-        gtk_dialog_run (GTK_DIALOG (dialog));
-        gtk_widget_destroy (dialog);
-}
-
-static void
 assistant_finished_cb (GdauiDsnAssistant *assistant, gboolean error, G_GNUC_UNUSED gpointer user_data)
 {
        const GdaDsnInfo *dsn_info;
@@ -76,10 +45,10 @@ assistant_finished_cb (GdauiDsnAssistant *assistant, gboolean error, G_GNUC_UNUS
                dsn_info = gdaui_dsn_assistant_get_dsn (assistant);
                if (dsn_info) {
                        if (! gda_config_define_dsn (dsn_info, NULL)) 
-                               show_error (NULL, _("Could not declare new data source"));
+                               _gdaui_utility_show_error (NULL, _("Could not declare new data source"));
                }
                else
-                       show_error (NULL, _("No valid data source info was created"));
+                       _gdaui_utility_show_error (NULL, _("No valid data source info was created"));
        }
 }
 
@@ -103,41 +72,19 @@ file_new_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *parameter, G_GNUC_UN
 }
 
 static void
-file_properties_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *parameter, gpointer user_data)
-{
-       GtkWidget *app_window = GTK_WIDGET (user_data);
-       GtkWidget *nb, *dsn, *current_widget;
-       gint current;
-
-       dsn = g_object_get_data (G_OBJECT (app_window), DSN_PAGE);
-       nb = g_object_get_data (G_OBJECT (app_window), STACK);
-
-       current = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
-       if (current == -1)
-               return;
-
-       current_widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), current);
-       if (current_widget == dsn)
-               dsn_config_edit_properties (dsn);
-}
-
-static void
 file_delete_cb (G_GNUC_UNUSED GSimpleAction *action, GVariant *parameter, gpointer user_data)
 {
        GtkWidget *app_window = GTK_WIDGET (user_data);
-       GtkWidget *nb, *dsn, *current_widget;
+       GtkWidget *stack, *dsn, *current_widget;
        gint current;
 
        dsn = g_object_get_data (G_OBJECT (app_window), DSN_PAGE);
-       nb = g_object_get_data (G_OBJECT (app_window), STACK);
-
-       current = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
-       if (current == -1)
-               return;
+       stack = g_object_get_data (G_OBJECT (app_window), STACK);
 
-       current_widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (nb), current);
-       if (current_widget == dsn)
-               dsn_config_delete (dsn);
+       const gchar *visible;
+       visible = gtk_stack_get_visible_child_name (GTK_STACK (stack));
+       if (visible && !strcmp (visible, DSN_PAGE))
+               dsn_config_delete (dsn);        
 }
 
 static void
@@ -230,7 +177,6 @@ static GActionEntry app_entries[] = {
 static GActionEntry win_entries[] = {
        { "DatasourceNew", file_new_cb, NULL, NULL, NULL },
        { "DatasourceDelete", file_delete_cb, NULL, NULL, NULL },
-       { "DatasourceProperties", file_properties_cb, NULL, NULL, NULL },
        { "ShowDatasources", show_datasources_cb, NULL, NULL, NULL },
        { "ShowProviders", show_providers_cb, NULL, NULL, NULL },
 };
@@ -279,7 +225,7 @@ activate (GApplication *app)
 
        gtk_window_set_titlebar (GTK_WINDOW (window), header);
        gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
-       gtk_window_set_default_size (GTK_WINDOW (window), 780, 500);
+       gtk_window_set_default_size (GTK_WINDOW (window), 780, 600);
 
        GtkWidget *menu_button;
        menu_button = gtk_menu_button_new ();
@@ -313,6 +259,8 @@ activate (GApplication *app)
        g_action_map_add_action_entries (G_ACTION_MAP (window),
                                         win_entries, G_N_ELEMENTS (win_entries),
                                         window);
+       g_simple_action_set_enabled (G_SIMPLE_ACTION (g_action_map_lookup_action (G_ACTION_MAP (window),
+                                                                                 "DatasourceDelete")), 
FALSE);
 
        GtkBuilder *builder;
        GMenuModel *menubar;
@@ -356,9 +304,6 @@ dsn_selection_changed_cb (GdauiRawGrid *dbrawgrid, GtkApplicationWindow *main_wi
        selection = gdaui_data_selector_get_selected_rows (GDAUI_DATA_SELECTOR (dbrawgrid));
 
        GAction *action;
-       action = g_action_map_lookup_action (G_ACTION_MAP (main_window), "DatasourceProperties");
-       g_simple_action_set_enabled (G_SIMPLE_ACTION (action), selection ? TRUE : FALSE);
-
        action = g_action_map_lookup_action (G_ACTION_MAP (main_window), "DatasourceDelete");
        g_simple_action_set_enabled (G_SIMPLE_ACTION (action), selection ? TRUE : FALSE);
        if (selection)
@@ -376,7 +321,7 @@ create_main_stack (GtkApplicationWindow *app_window)
        stack = gtk_stack_new ();
        g_object_set_data (G_OBJECT (app_window), STACK, stack);
         gtk_widget_show (stack);
-       gtk_stack_set_transition_type (GTK_STACK (stack), GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
+       gtk_stack_set_transition_type (GTK_STACK (stack), GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
 
        /* data source configuration page */
        dsn = dsn_config_new ();
diff --git a/control-center/menus.ui b/control-center/menus.ui
index af6062a..558a3ae 100644
--- a/control-center/menus.ui
+++ b/control-center/menus.ui
@@ -16,17 +16,24 @@
   </menu>
   <menu id="menubar">
     <section>
-      <attribute name="display-hint">horizontal-buttons</attribute>
+      <attribute name="display-hint">vertical-buttons</attribute>
       <item>
         <attribute name="label" translatable="yes">_Data sources</attribute>
         <attribute name="action">win.ShowDatasources</attribute>
         <attribute name="accel">&lt;Primary&gt;D</attribute>
       </item>
       <item>
-        <attribute name="label" translatable="yes">_Providers</attribute>
+        <attribute name="label" translatable="yes">_Databases' providers</attribute>
         <attribute name="action">win.ShowProviders</attribute>
         <attribute name="accel">&lt;Primary&gt;P</attribute>
       </item>
     </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">New data source</attribute>
+        <attribute name="action">win.DatasourceNew</attribute>
+        <attribute name="accel">&lt;Primary&gt;N</attribute>
+      </item>
+    </section>
   </menu>
 </interface>
diff --git a/control-center/provider-config.c b/control-center/provider-config.c
index bdafa6f..29f7662 100644
--- a/control-center/provider-config.c
+++ b/control-center/provider-config.c
@@ -25,6 +25,7 @@
 #include <libgda-ui/libgda-ui.h>
 #include "provider-config.h"
 #include "gdaui-bar.h"
+#include "support.h"
 
 #define PROVIDER_CONFIG_DATA "Provider_ConfigData"
 
@@ -46,15 +47,13 @@ provider_selection_changed_cb (GtkTreeSelection *selection, ProviderConfigPrivat
        GdaDataModelIter *sel_iter;
        sel_iter = gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (priv->provider_list));
        GdkPixbuf *pix = NULL;
-       if (sel_iter) {
-               const GValue *cvalue;
+       const GValue *cvalue = NULL;
+       if (sel_iter)
                cvalue = gda_data_model_iter_get_value_at (sel_iter, 0);
-               g_print ("Provider: %s\n", gda_value_stringify (cvalue));
-
+       if (cvalue) {
                GdaProviderInfo *pinfo;
                pinfo = gda_config_get_provider_info (g_value_get_string (cvalue));
-               g_assert (pinfo);
-               pix = gdaui_get_icon_for_db_engine (pinfo->icon_id);
+               pix = support_create_pixbuf_for_provider (pinfo);
 
                gchar *tmp, *tmp1, *tmp2;
                tmp1 = g_markup_printf_escaped ("%s", pinfo->id);
@@ -144,7 +143,12 @@ provider_selection_changed_cb (GtkTreeSelection *selection, ProviderConfigPrivat
                gtk_label_set_markup (GTK_LABEL (priv->prov_loc), string->str);
                g_string_free (string, TRUE);
        }
-       gtk_image_set_from_pixbuf (GTK_IMAGE (priv->prov_image), pix);
+       if (pix) {
+               gtk_image_set_from_pixbuf (GTK_IMAGE (priv->prov_image), pix);
+               g_object_unref (pix);
+       }
+       else
+               gtk_image_clear (GTK_IMAGE (priv->prov_image));
        gtk_widget_grab_focus (priv->provider_list);
 }
 
@@ -216,7 +220,6 @@ provider_config_new (void)
 
        GtkWidget *grid;
        grid = gtk_grid_new ();
-       gtk_paned_add2 (GTK_PANED (paned), grid);
        g_object_set (grid, "margin-top", 20, NULL);
        gtk_container_add (GTK_CONTAINER (sw), grid);
        gtk_widget_show (sw);
diff --git a/control-center/support.c b/control-center/support.c
new file mode 100644
index 0000000..e97348f
--- /dev/null
+++ b/control-center/support.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "support.h"
+#include <libgda-ui/libgda-ui.h>
+
+/**
+ * support_create_pixbuf_for_provider:
+ * @pinfo: (allow-none): a #GdaProviderInfo, or %NULL
+ *
+ * Creates a new #GdkPixbuf using @pinfo's icon. The new pixbuf will at most be SUPPORT_ICON_SIZE pixels 
high.
+ *
+ * Returns: (transfer full): a new #GdkPixbuf
+ */
+GdkPixbuf *
+support_create_pixbuf_for_provider (GdaProviderInfo *pinfo)
+{
+       if (!pinfo)
+               return NULL;
+
+       GdkPixbuf *pix, *pix2;
+
+       pix = gdaui_get_icon_for_db_engine (pinfo->icon_id);
+       if (pix) {
+               gfloat scale;
+               scale = (gfloat) SUPPORT_ICON_SIZE / (gfloat) gdk_pixbuf_get_height (pix);
+               if (scale > 1.)
+                       scale = 1.;
+               pix2 = gdk_pixbuf_scale_simple (pix, scale * gdk_pixbuf_get_width (pix),
+                                               scale * gdk_pixbuf_get_height (pix),
+                                               GDK_INTERP_HYPER);
+               return pix2;
+       }
+       else
+               return NULL;
+}
+
diff --git a/control-center/dsn-properties-dialog.h b/control-center/support.h
similarity index 74%
rename from control-center/dsn-properties-dialog.h
rename to control-center/support.h
index 07aa6be..3fbe68e 100644
--- a/control-center/dsn-properties-dialog.h
+++ b/control-center/support.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 - 2011 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2015 Vivien Malerba <malerba gnome-db org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -16,11 +16,17 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#ifndef __DSN_PROPERTIES_DIALOG_H__
-#define __DSN_PROPERTIES_DIALOG_H__
+#ifndef __SUPPORT_H__
+#define __SUPPORT_H__
 
 #include <gtk/gtk.h>
+#include <libgda/libgda.h>
 
-void dsn_properties_dialog (GtkWindow *parent, const gchar *dsn);
+G_BEGIN_DECLS
+
+#define SUPPORT_ICON_SIZE 48
+GdkPixbuf *support_create_pixbuf_for_provider (GdaProviderInfo *pinfo);
+
+G_END_DECLS
 
 #endif


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