/* OGMRip - A DVD Encoder for GNOME
 * Copyright (C) 2004-2012 Olivier Rolland <billl@users.sourceforge.net>
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "ogmrip.h"

#include "ogmrip-gconf.h"
#include "ogmrip-helper.h"
#include "ogmrip-marshal.h"
#include "ogmrip-profiles.h"
#include "ogmrip-profile-editor.h"
#include "ogmrip-profiles-dialog.h"

#include <libxml/parser.h>
#include <gconf/gconf-client.h>

#include <glib/gi18n.h>
#include <glade/glade.h>

#include <string.h>

#define OGMRIP_GLADE_FILE "ogmrip" G_DIR_SEPARATOR_S "ogmrip-profiles.glade"
#define OGMRIP_GLADE_ROOT "root"

#define OGMRIP_PROFILES_DIALOG_GET_PRIVATE(o) \
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), OGMRIP_TYPE_PROFILES_DIALOG, OGMRipProfilesDialogPriv))

enum
{
  COL_NAME,
  COL_SECTION,
  COL_DLG,
  COL_LAST
};

struct _OGMRipProfilesDialogPriv
{
  GtkWidget *list;
  GtkWidget *new_button;
  GtkWidget *copy_button;
  GtkWidget *edit_button;
  GtkWidget *remove_button;
  GtkWidget *rename_button;
  GtkWidget *export_button;
};

enum
{
  NEW,
  REMOVE,
  RENAME,
  LAST_SIGNAL
};

static int signals[LAST_SIGNAL] = { 0 };

extern OGMRipSettings *settings;

/*
 * Dialog
 */

static gint
ogmrip_profiles_dialog_compare_profiles (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, OGMRipProfilesDialog *dialog)
{
  gchar *aname, *bname;
  gint ret;

  gtk_tree_model_get (model, a, COL_NAME, &aname, -1);
  gtk_tree_model_get (model, b, COL_NAME, &bname, -1);

  ret = g_utf8_collate (aname, bname);

  g_free (aname);
  g_free (bname);

  return ret;
}

static void
ogmrip_profiles_dialog_construct_profiles (OGMRipProfilesDialog *dialog)
{
  GtkListStore *store;
  GtkCellRenderer *cell;
  GtkTreeViewColumn *column;

  store = gtk_list_store_new (COL_LAST, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
  gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->list), GTK_TREE_MODEL (store));
  g_object_unref (store);

  column = gtk_tree_view_column_new ();
  gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->priv->list), column);

  cell = gtk_cell_renderer_text_new ();
  gtk_tree_view_column_pack_start (column, cell, TRUE);
  gtk_tree_view_column_set_attributes (column, cell, "markup", COL_NAME, NULL);

  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), COL_NAME,
      (GtkTreeIterCompareFunc) ogmrip_profiles_dialog_compare_profiles, dialog, NULL);
  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
      COL_NAME, GTK_SORT_ASCENDING);
}

static gboolean
ogmrip_profiles_dialog_find_profile (GtkTreeModel *model, GtkTreeIter *iter, const gchar *section)
{
  gboolean retval = FALSE;

  if (gtk_tree_model_get_iter_first (model, iter))
  {
    gchar *str;

    do
    {
      gtk_tree_model_get (model, iter, COL_SECTION, &str, -1);
      retval = g_str_equal (str, section);
      g_free (str);
    }
    while (!retval && gtk_tree_model_iter_next (model, iter));
  }

  return retval;
}

static void
ogmrip_profiles_dialog_add_profiles (OGMRipProfilesDialog *dialog, gboolean reload)
{
  GtkTreeModel *model;
  GtkTreeIter iter;

  GSList *sections, *section;
  gchar *name;

  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->list));
  sections = ogmrip_settings_get_subsections (settings, OGMRIP_GCONF_PROFILES);

  for (section = sections; section; section = section->next)
  {
    if (ogmrip_profiles_check_profile (section->data, NULL))
    {
      if (!reload || !ogmrip_profiles_dialog_find_profile (model, &iter, section->data))
      {
        ogmrip_settings_get (settings, section->data, OGMRIP_GCONF_PROFILE_NAME, &name, NULL);

        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
        gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_NAME, name, COL_SECTION, section->data, COL_DLG, NULL, -1);

        if (reload)
          g_signal_emit (dialog, signals[NEW], 0, section->data, name);

        g_free (name);
      }
    }
    g_free (section->data);
  }
  g_slist_free (sections);
}

static void
ogmrip_profiles_dialog_profile_name_changed (GtkTextBuffer *buffer, GtkWidget *dialog)
{
  GtkTextIter start, end;
  gchar *text;

  gtk_text_buffer_get_bounds (buffer, &start, &end);
  text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);

  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
      GTK_RESPONSE_ACCEPT, text != NULL && text[0] != '\0');

  g_free (text);
}

static gchar *
ogmrip_profiles_dialog_run_profile_dialog (GtkWindow *parent, const gchar *old_name)
{
  GtkWidget *dialog, *area, *vbox, *label, *frame, *entry;
  GtkTextBuffer *buffer;

  gchar *new_name = NULL;

  dialog = gtk_dialog_new_with_buttons (old_name ? _("Rename profile") : _("New profile"), NULL,
      GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL);

  gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT, FALSE);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);

  gtk_window_set_default_size (GTK_WINDOW (dialog), 250, 125);
  gtk_window_set_icon_from_stock (GTK_WINDOW (dialog), GTK_STOCK_PREFERENCES);
  gtk_window_set_parent (GTK_WINDOW (dialog), parent);

  area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

  vbox = gtk_vbox_new (FALSE, 6);
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  gtk_container_add (GTK_CONTAINER (area), vbox);
  gtk_widget_show (vbox);

  label = gtk_label_new (_("_Profile name:"));
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
  gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  gtk_widget_show (label);

  frame = gtk_frame_new (NULL);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
  gtk_widget_show (frame);

  entry = gtk_text_view_new ();
  gtk_text_view_set_accepts_tab (GTK_TEXT_VIEW (entry), FALSE);
  gtk_container_add (GTK_CONTAINER (frame), entry);
  gtk_widget_show (entry);

  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (entry));

  if (old_name)
    gtk_text_buffer_set_text (buffer, old_name, -1);

  g_signal_connect (buffer, "changed",
      G_CALLBACK (ogmrip_profiles_dialog_profile_name_changed), dialog);

  gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);

  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
  {
    GtkTextIter start, end;

    gtk_text_buffer_get_bounds (buffer, &start, &end);
    new_name = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
  }
  gtk_widget_destroy (dialog);

  return new_name;
}

static void
ogmrip_profiles_dialog_new_button_clicked (OGMRipProfilesDialog *parent)
{
  gchar *name;

  name = ogmrip_profiles_dialog_run_profile_dialog (GTK_WINDOW (parent), NULL);
  if (name)
  {
    GtkTreeSelection *selection;
    GtkTreeModel *model;
    GtkTreeIter iter;

    gchar *profile, *section;

    profile = gconf_unique_key ();
    section = ogmrip_settings_build_section (settings, OGMRIP_GCONF_PROFILES, profile, NULL);
    g_free (profile);

    model = gtk_tree_view_get_model (GTK_TREE_VIEW (parent->priv->list));
    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
    gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_NAME, name, COL_SECTION, section, -1);

    ogmrip_settings_set (settings, section, "name", name, NULL);

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (parent->priv->list));
    gtk_tree_selection_select_iter (selection, &iter);

    g_signal_emit (parent, signals[NEW], 0, section, name);

    g_free (section);
    g_free (name);
  }
}

static void
ogmrip_profiles_dialog_profile_dialog_destroyed (GtkWidget *dialog, GtkTreeRowReference *ref)
{
  if (gtk_tree_row_reference_valid (ref))
  {
    GtkTreePath *path;

    path = gtk_tree_row_reference_get_path (ref);
    if (path)
    {
      GtkTreeModel *model;
      GtkTreeIter iter;

      model = gtk_tree_row_reference_get_model (ref);
      if (gtk_tree_model_get_iter (model, &iter, path))
        gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_DLG, NULL, -1);

      gtk_tree_path_free (path);
    }
  }

  gtk_tree_row_reference_free (ref);
}

static gboolean
ogmrip_profiles_dialog_selection_changed (OGMRipProfilesDialog *dialog, GtkTreeSelection *selection)
{
  GtkTreeIter iter;
  gboolean sensitive;

  sensitive = gtk_tree_selection_get_selected (selection, NULL, &iter);

  gtk_widget_set_sensitive (dialog->priv->copy_button, sensitive);
  gtk_widget_set_sensitive (dialog->priv->edit_button, sensitive);
  gtk_widget_set_sensitive (dialog->priv->remove_button, sensitive);
  gtk_widget_set_sensitive (dialog->priv->rename_button, sensitive);
  gtk_widget_set_sensitive (dialog->priv->export_button, sensitive);

  return TRUE;
}

static gchar *
get_profile_title (const gchar *name)
{
  gchar *str1, *str2;
  gint i;

  for (i = 0; name[i] != '\0'; i++)
    if (name[i] == '\n' || name[i] == '\r')
      break;

  str1 = g_strndup (name, i);

  if (!pango_parse_markup (str1, -1, 0, NULL, &str2, NULL, NULL))
    str2 = g_strdup (name);

  g_free (str1);

  str1 = g_strdup_printf (_("Editing profile \"%s\""), str2);
  g_free (str2);

  return str1;
}

static void
ogmrip_profiles_copy_entry (gchar *key, const gchar *section[])
{
  if (ogmrip_settings_find_key (settings, key))
  {
    GValue value = {0};

    ogmrip_settings_get_value (settings, section[0], key, &value); 
    if (G_IS_VALUE (&value))
      ogmrip_settings_set_value (settings, section[1], key, &value);

    g_free (key);
  }
}

static void
ogmrip_profiles_dialog_copy_button_clicked (OGMRipProfilesDialog *parent)
{
  GtkTreeSelection *selection;
  GtkTreeModel *model;
  GtkTreeIter iter;
  GSList *entries;

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (parent->priv->list));
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
  {
    gchar *profile, *name[2], *section[2];

    profile = gconf_unique_key ();
    section[1] = ogmrip_settings_build_section (settings, OGMRIP_GCONF_PROFILES, profile, NULL);
    g_free (profile);

    gtk_tree_model_get (model, &iter, COL_NAME, &(name[0]), COL_SECTION, &(section[0]), -1);
    name[1] = g_strconcat (_("Copy of"), " ", name[0], NULL);
    g_free (name[0]);

    entries = ogmrip_settings_get_keys (settings, section[0], TRUE);
    g_slist_foreach (entries, (GFunc) ogmrip_profiles_copy_entry, section);
    g_slist_free (entries);

    g_free (section[0]);

    gtk_list_store_append (GTK_LIST_STORE (model), &iter);
    gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_NAME, name[1], COL_SECTION, section[1], -1);

    ogmrip_settings_set (settings, section[1], "name", name[1], NULL);

    gtk_tree_selection_select_iter (selection, &iter);

    g_signal_emit (parent, signals[NEW], 0, section[1], name[1]);

    g_free (name[1]);
    g_free (section[1]);
  }
}

static void
ogmrip_profiles_dialog_edit_button_clicked (OGMRipProfilesDialog *parent)
{
  GtkTreeSelection *selection;
  GtkTreeModel *model;
  GtkTreeIter iter;

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (parent->priv->list));
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
  {
    GtkWidget *dialog;
    gchar *name, *section;

    gtk_tree_model_get (model, &iter, COL_NAME, &name, COL_SECTION, &section, COL_DLG, &dialog, -1);
    if (!dialog)
    {
      GtkTreePath *path;
      GtkTreeRowReference *ref;
      gchar *title;

      dialog = ogmrip_profile_editor_dialog_new (section);

      gtk_window_set_parent (GTK_WINDOW (dialog), GTK_WINDOW (parent));
      gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), FALSE);

      title = get_profile_title (name);
      gtk_window_set_title (GTK_WINDOW (dialog), title);
      g_free (title);

      g_signal_connect (dialog, "delete-event", G_CALLBACK (gtk_true), NULL);
      g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);

      path = gtk_tree_model_get_path (model, &iter);
      ref = gtk_tree_row_reference_new (model, path);
      gtk_tree_path_free (path);

      g_signal_connect (dialog, "destroy", G_CALLBACK (ogmrip_profiles_dialog_profile_dialog_destroyed), ref);

      gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_DLG, dialog, -1);
    }
    g_free (name);
    g_free (section);

    gtk_window_present (GTK_WINDOW (dialog));
  }
}

static void
ogmrip_profiles_dialog_remove_button_clicked (OGMRipProfilesDialog *parent)
{
  GtkTreeIter iter;
  GtkTreeSelection *selection;
  GtkTreeModel *model;

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (parent->priv->list));
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
  {
    GtkWidget *dialog;
    gchar *section, *name;

    gtk_tree_model_get (model, &iter, COL_NAME, &name, COL_SECTION, &section, COL_DLG, &dialog, -1);

    if (dialog)
    {
      dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
          GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Cannot remove profile"));
      gtk_window_set_title (GTK_WINDOW (dialog), _("Cannot remove profile"));

      gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", name);

      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
      gtk_window_set_parent (GTK_WINDOW (dialog), GTK_WINDOW (parent));

      gtk_dialog_run (GTK_DIALOG (dialog));
      gtk_widget_destroy (dialog);
    }
    else
    {
      dialog = gtk_message_dialog_new_with_markup (NULL, GTK_DIALOG_MODAL,
          GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, _("Delete profile ?"));
      gtk_window_set_title (GTK_WINDOW (dialog), _("Delete profile ?"));

      gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", name);

      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
      gtk_window_set_parent (GTK_WINDOW (dialog), GTK_WINDOW (parent));

      if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
      {
        gchar *default_section;

        default_section = ogmrip_settings_build_section (settings, OGMRIP_GCONF_PROFILES, OGMRIP_DEFAULT_PROFILE, NULL);
        if (!g_str_equal (section, default_section))
          ogmrip_settings_remove_section (settings, section);
        g_free (default_section);

        gtk_list_store_remove (GTK_LIST_STORE (model), &iter);

        if (!gtk_tree_model_iter_n_children (model, NULL))
          ogmrip_settings_set (settings, OGMRIP_GCONF_GENERAL, OGMRIP_GCONF_PROFILE, OGMRIP_DEFAULT_PROFILE, NULL);

        g_signal_emit (parent, signals[REMOVE], 0, section, name);

        if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
          gtk_tree_selection_select_iter (selection, &iter);
      }
      gtk_widget_destroy (dialog);
    }

    g_free (name);
    g_free (section);
  }
}

static void
ogmrip_profiles_dialog_rename_button_clicked (OGMRipProfilesDialog *parent)
{
  GtkTreeModel *model;
  GtkTreeSelection *selection;
  GtkTreeIter iter;

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (parent->priv->list));
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
  {
    gchar *old_name, *new_name, *section;

    gtk_tree_model_get (model, &iter, COL_NAME, &old_name, COL_SECTION, &section, -1);
    new_name = ogmrip_profiles_dialog_run_profile_dialog (GTK_WINDOW (parent), old_name);
  
    if (new_name && !g_str_equal (new_name, old_name))
    {
      ogmrip_settings_set (settings, section, "name", new_name, NULL);
      gtk_list_store_set (GTK_LIST_STORE (model), &iter, COL_NAME, new_name, -1);
      g_signal_emit (parent, signals[RENAME], 0, section, new_name);
    }

    g_free (new_name);
    g_free (old_name);
    g_free (section);
  }
}

static void
ogmrip_profiles_dialog_export_button_clicked (OGMRipProfilesDialog *parent)
{
  GtkTreeModel *model;
  GtkTreeSelection *selection;
  GtkTreeIter iter;

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (parent->priv->list));
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
  {
    GtkWidget *dialog;

    dialog = gtk_file_chooser_dialog_new (_("Export profile as"),
        GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_SAVE,
        GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
        NULL);
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
    {
      gchar *filename, *section;

      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
      gtk_tree_model_get (model, &iter, COL_SECTION, &section, -1);

      ogmrip_settings_export (settings, section, filename, NULL);

      g_free (filename);
      g_free (section);
    }
    gtk_widget_destroy (dialog);
  }
}

static void
ogmrip_profiles_dialog_import_button_clicked (OGMRipProfilesDialog *parent)
{
  GtkWidget *dialog;

  dialog = gtk_file_chooser_dialog_new (_("Select profile to import"),
      GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_OPEN,
      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
      NULL);

  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
  {
    GError *error = NULL;
    gchar *filename;

    gtk_widget_hide (dialog);

    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
    if (ogmrip_profiles_import (filename, &error))
      ogmrip_profiles_dialog_add_profiles (parent, TRUE);
    else
    {
      gtk_widget_destroy (dialog);
      dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
          GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Cannot load profile"));
      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), 
          "%s", error ? error->message : _("Unknown error"));
      g_error_free (error);

      gtk_dialog_run (GTK_DIALOG (dialog));
    }
    g_free (filename);
  }
  gtk_widget_destroy (dialog);
}

G_DEFINE_TYPE (OGMRipProfilesDialog, ogmrip_profiles_dialog, GTK_TYPE_DIALOG)

static void
ogmrip_profiles_dialog_class_init (OGMRipProfilesDialogClass *klass)
{
  g_type_class_add_private (klass, sizeof (OGMRipProfilesDialogPriv));

  signals[NEW] = g_signal_new ("new-profile", G_TYPE_FROM_CLASS (klass), 
      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
      G_STRUCT_OFFSET (OGMRipProfilesDialogClass, new_profile), NULL, NULL,
      ogmrip_cclosure_marshal_VOID__STRING_STRING,
      G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);

  signals[REMOVE] = g_signal_new ("remove-profile", G_TYPE_FROM_CLASS (klass), 
      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
      G_STRUCT_OFFSET (OGMRipProfilesDialogClass, remove_profile), NULL, NULL,
      ogmrip_cclosure_marshal_VOID__STRING_STRING,
      G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);

  signals[RENAME] = g_signal_new ("rename-profile", G_TYPE_FROM_CLASS (klass), 
      G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
      G_STRUCT_OFFSET (OGMRipProfilesDialogClass, rename_profile), NULL, NULL,
      ogmrip_cclosure_marshal_VOID__STRING_STRING,
      G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
}

static void
ogmrip_profiles_dialog_init (OGMRipProfilesDialog *dialog)
{
  GtkWidget *area, *widget, *image;
  GtkTreeSelection *selection;
  GladeXML *xml;

  dialog->priv = OGMRIP_PROFILES_DIALOG_GET_PRIVATE (dialog);

  xml = glade_xml_new (OGMRIP_DATA_DIR G_DIR_SEPARATOR_S OGMRIP_GLADE_FILE, OGMRIP_GLADE_ROOT, NULL);
  if (!xml)
  {
    g_warning ("Could not find " OGMRIP_GLADE_FILE);
    return;
  }

  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
      NULL);
#if !GTK_CHECK_VERSION(2,22,0)
  gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
#endif
  gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
  gtk_window_set_default_size (GTK_WINDOW (dialog), 450, -1);
  gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Profiles"));
  gtk_window_set_icon_from_stock (GTK_WINDOW (dialog), GTK_STOCK_PREFERENCES);

  area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

  widget = glade_xml_get_widget (xml, OGMRIP_GLADE_ROOT);
  gtk_container_add (GTK_CONTAINER (area), widget);
  gtk_widget_show (widget);

  dialog->priv->edit_button = glade_xml_get_widget (xml, "edit-button");
  gtk_widget_set_sensitive (dialog->priv->edit_button, FALSE);
  g_signal_connect_swapped (dialog->priv->edit_button, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_edit_button_clicked), dialog);

  dialog->priv->new_button = glade_xml_get_widget (xml, "new-button");
  g_signal_connect_swapped (dialog->priv->new_button, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_new_button_clicked), dialog);

  dialog->priv->remove_button = glade_xml_get_widget (xml, "delete-button");
  gtk_widget_set_sensitive (dialog->priv->remove_button, FALSE);
  g_signal_connect_swapped (dialog->priv->remove_button, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_remove_button_clicked), dialog);

  dialog->priv->copy_button = glade_xml_get_widget (xml, "copy-button");
  gtk_widget_set_sensitive (dialog->priv->copy_button, FALSE);
  g_signal_connect_swapped (dialog->priv->copy_button, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_copy_button_clicked), dialog);

  dialog->priv->rename_button = glade_xml_get_widget (xml, "rename-button");
  gtk_widget_set_sensitive (dialog->priv->rename_button, FALSE);
  g_signal_connect_swapped (dialog->priv->rename_button, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_rename_button_clicked), dialog);

  image = gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_BUTTON);
  gtk_button_set_image (GTK_BUTTON (dialog->priv->rename_button), image);

  dialog->priv->export_button = glade_xml_get_widget (xml, "export-button");
  gtk_widget_set_sensitive (dialog->priv->export_button, FALSE);
  g_signal_connect_swapped (dialog->priv->export_button, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_export_button_clicked), dialog);

  image = gtk_image_new_from_stock (GTK_STOCK_SAVE, GTK_ICON_SIZE_BUTTON);
  gtk_button_set_image (GTK_BUTTON (dialog->priv->export_button), image);

  widget = glade_xml_get_widget (xml, "import-button");
  g_signal_connect_swapped (widget, "clicked",
      G_CALLBACK (ogmrip_profiles_dialog_import_button_clicked), dialog);

  image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
  gtk_button_set_image (GTK_BUTTON (widget), image);

  dialog->priv->list = glade_xml_get_widget (xml, "treeview");
  ogmrip_profiles_dialog_construct_profiles (dialog);

  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->list));
  g_signal_connect_swapped (selection, "changed",
      G_CALLBACK (ogmrip_profiles_dialog_selection_changed), dialog);

  ogmrip_profiles_dialog_add_profiles (dialog, FALSE);

  g_object_unref (xml);
}

GtkWidget *
ogmrip_profiles_dialog_new (void)
{
  return g_object_new (OGMRIP_TYPE_PROFILES_DIALOG, NULL);
}

void
ogmrip_profiles_dialog_set_active (OGMRipProfilesDialog *dialog, const gchar *profile)
{
  GtkTreeModel *model;
  GtkTreeIter iter;

  g_return_if_fail (OGMRIP_IS_PROFILES_DIALOG (dialog));

  model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->list));

  if (ogmrip_profiles_dialog_find_profile (model, &iter, profile) ||
      gtk_tree_model_get_iter_first (model, &iter))
  {
    GtkTreeSelection *selection;

    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->list));
    gtk_tree_selection_select_iter (selection, &iter);
  }
}

