static void
gdict_source_dialog_response_cb (GtkDialog *dialog,
                                 gint       response_id,
                                 gpointer   user_data)
{
    GError *err = NULL;

    switch (response_id)
    {
    case GTK_RESPONSE_ACCEPT:
        build_new_source (GDICT_SOURCE_DIALOG (dialog));
        break;
    case GTK_RESPONSE_HELP:
        gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (dialog)),
                      "help:mate-dictionary/mate-dictionary-add-source",
                      gtk_get_current_event_time (), &err);
        if (err)
        {
            gdict_show_gerror_dialog (GTK_WINDOW (dialog),
                                      _("There was an error while displaying help"),
                                      err);
        }

        /* we don't want the dialog to close itself */
        g_signal_stop_emission_by_name (dialog, "response");
        break;
    case GTK_RESPONSE_CLOSE:
        save_source (GDICT_SOURCE_DIALOG (dialog));
        break;
    case GTK_RESPONSE_CANCEL:
        break;
    default:
        break;
    }
}
static void
transport_combo_changed_cb (GtkWidget *widget,
			    gpointer   user_data)
{
  GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (user_data);
  gint transport;

  transport = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
  if (transport == dialog->transport)
    return;

  if (transport == GDICT_SOURCE_TRANSPORT_DICTD)
    {
      gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "hostname_label")));
      gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "hostname_entry")));
      gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "port_label")));
      gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "port_entry")));
      
      if (dialog->action == GDICT_SOURCE_DIALOG_CREATE)
        {
          gtk_widget_set_sensitive (dialog->add_button, TRUE);
          
          dialog->transport = GDICT_SOURCE_TRANSPORT_DICTD;
        }
    }
  else
    {
      gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "hostname_label")));
      gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "hostname_entry")));
      gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "port_label")));
      gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (dialog->builder, "port_entry")));

      if (dialog->action == GDICT_SOURCE_DIALOG_CREATE)
        {
          gtk_widget_set_sensitive (dialog->add_button, FALSE);
          
          dialog->transport = GDICT_SOURCE_TRANSPORT_INVALID;
        }
    }
}
static void
gdict_source_dialog_finalize (GObject *object)
{
  GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (object);

  if (dialog->gconf_client)
    g_object_unref (dialog->gconf_client);
  
  if (dialog->builder)
    g_object_unref (dialog->builder);

  if (dialog->source_name)
    g_free (dialog->source_name);

  if (dialog->source)
    g_object_unref (dialog->source);
  
  if (dialog->loader)
    g_object_unref (dialog->loader);
  
  G_OBJECT_CLASS (gdict_source_dialog_parent_class)->finalize (object);
}
static void
gdict_source_dialog_get_property (GObject    *object,
				  guint       prop_id,
				  GValue     *value,
				  GParamSpec *pspec)
{
  GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (object);
  
  switch (prop_id)
    {
    case PROP_SOURCE_LOADER:
      g_value_set_object (value, dialog->loader);
      break;
    case PROP_SOURCE_NAME:
      g_value_set_string (value, dialog->source_name);
      break;
    case PROP_ACTION:
      g_value_set_int (value, dialog->action);
      break;
    default:
      break;
    }
}
static void
gdict_source_dialog_set_property (GObject      *object,
				  guint         prop_id,
				  const GValue *value,
				  GParamSpec   *pspec)
{
  GdictSourceDialog *dialog = GDICT_SOURCE_DIALOG (object);
  
  switch (prop_id)
    {
    case PROP_SOURCE_LOADER:
      set_source_loader (dialog, g_value_get_object (value));
      break;
    case PROP_SOURCE_NAME:
      g_free (dialog->source_name);
      dialog->source_name = g_strdup (g_value_get_string (value));
      break;
    case PROP_ACTION:
      dialog->action = (GdictSourceDialogAction) g_value_get_int (value);
      break;
    default:
      break;
    }
}
static GObject *
gdict_source_dialog_constructor (GType                  type,
				 guint                  n_construct_properties,
				 GObjectConstructParam *construct_params)
{
  GObject *object;
  GdictSourceDialog *dialog;
  GtkWidget *vbox;
  GError *error = NULL;

  object = G_OBJECT_CLASS (gdict_source_dialog_parent_class)->constructor (type,
									   n_construct_properties,
									   construct_params);
  dialog = GDICT_SOURCE_DIALOG (object);

  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
  gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
  
  gtk_widget_push_composite_child ();

  /* get the UI from the GtkBuilder file */
  dialog->builder = gtk_builder_new ();
  gtk_builder_add_from_file (dialog->builder, GDICT_SOURCE_UI, &error);

  if (error) {
    g_critical ("Unable to load the user interface definition file: %s",
                error->message);
    g_error_free (error);
    g_assert_not_reached ();
  }
  
  /* the main widget */
  gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
                     GTK_WIDGET (gtk_builder_get_object (dialog->builder, "source_root")));

  /* the transport combo changes the UI by changing the visible widgets
   * bound to the transport's own options.
   */
  dialog->transport_combo = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "transport_combo"));
  g_signal_connect (dialog->transport_combo, "changed",
  		    G_CALLBACK (transport_combo_changed_cb),
  		    dialog);

  /* the help button is always visible */
  dialog->help_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
  					       GTK_STOCK_HELP,
					       GTK_RESPONSE_HELP);
  
  vbox = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "db-vbox"));
  dialog->db_chooser = gdict_database_chooser_new ();
  gtk_box_pack_start (GTK_BOX (vbox), dialog->db_chooser, TRUE, TRUE, 0);
  gtk_widget_show (dialog->db_chooser);

  vbox = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "strat-vbox"));
  dialog->strat_chooser = gdict_strategy_chooser_new ();
  gtk_box_pack_start (GTK_BOX (vbox), dialog->strat_chooser, TRUE, TRUE, 0);
  gtk_widget_show (dialog->strat_chooser);

  /* the UI changes depending on the action that the source dialog
   * should perform
   */
  switch (dialog->action)
    {
    case GDICT_SOURCE_DIALOG_VIEW:
      /* disable every editable widget */
      gtk_editable_set_editable (GTK_EDITABLE (gtk_builder_get_object (dialog->builder, "name_entry")), FALSE);
      gtk_editable_set_editable (GTK_EDITABLE (gtk_builder_get_object (dialog->builder, "description_entry")), FALSE);
      gtk_editable_set_editable (GTK_EDITABLE (gtk_builder_get_object (dialog->builder, "hostname_entry")), FALSE);
      gtk_editable_set_editable (GTK_EDITABLE (gtk_builder_get_object (dialog->builder, "port_entry")), FALSE);
      
      gtk_widget_set_sensitive (dialog->transport_combo, FALSE);

      /* we just allow closing the dialog */
      dialog->close_button  = gtk_dialog_add_button (GTK_DIALOG (dialog),
      						     GTK_STOCK_CLOSE,
      						     GTK_RESPONSE_CLOSE);
      break;
    case GDICT_SOURCE_DIALOG_CREATE:
      dialog->cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
      						     GTK_STOCK_CANCEL,
      						     GTK_RESPONSE_CANCEL);
      dialog->add_button    = gtk_dialog_add_button (GTK_DIALOG (dialog),
      						     GTK_STOCK_ADD,
      						     GTK_RESPONSE_ACCEPT);
      /* the "add" button sensitivity is controlled by the transport_combo
       * since it's the only setting that makes a source usable.
       */
      gtk_widget_set_sensitive (dialog->add_button, FALSE);
      break;
    case GDICT_SOURCE_DIALOG_EDIT:
      dialog->cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
      						     GTK_STOCK_CANCEL,
      						     GTK_RESPONSE_CANCEL);
      dialog->close_button  = gtk_dialog_add_button (GTK_DIALOG (dialog),
		      	 			     GTK_STOCK_CLOSE,
						     GTK_RESPONSE_CLOSE);
      break;
    default:
      g_assert_not_reached ();
      break;
    }
  
  /* this will take care of updating the contents of the dialog
   * based on the action
   */
  update_dialog_ui (dialog);
  
  gtk_widget_pop_composite_child ();
  
  return object;
}