Logo Search packages:      
Sourcecode: galeon version File versions

galeon-language-editor.c

/*
 *  Copyright (C) 2003  Tommi Komulainen
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation. 
 *
 *  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 "galeon-language-editor.h"

#include <glib/gi18n.h>
#include <glade/glade-xml.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkcelllayout.h>
#include <gtk/gtkstock.h>
#include <gtk/gtktreeselection.h>
#include <gtk/gtktreemodelsort.h>
#include <gtk/gtkcombobox.h>

#include "gul-glade.h"
#include "galeon-marshal.h"

#include <string.h>


enum {
      CHANGED,    /* indicate language selection changed */
      TITLE,            /* request a title for a custom value  */
      LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };


G_DEFINE_TYPE(GaleonLanguageEditor, galeon_language_editor, GTK_TYPE_DIALOG)

/**
 * galeon_language_editor_set_available:
 * @languages: an array of #GulGuiOption items
 * @n_languages: number of items in @languages
 *
 * Sets the available languages and their titles, the titles are expected to
 * already be translated.
 */
void
galeon_language_editor_set_available (GaleonLanguageEditor *self,
                                  const GulGuiOption   *languages,
                              guint                 n_languages)
{
      gul_gui_option_combobox_populate(GTK_COMBO_BOX(self->combobox),
                               languages, n_languages, TRUE, FALSE);

      /* 
       * Adding rows produces a warning if this is not done. *sigh*
       */
      gtk_widget_realize(self->combobox);
}

/**
 * galeon_language_editor_set_selected:
 * @values: list of strings
 */
void
galeon_language_editor_set_selected (GaleonLanguageEditor *self, GSList *values)
{
      GtkListStore *store;
      GSList       *l;

      store = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(self->treeview)));
      gtk_list_store_clear (store);

      for (l = values; l != NULL; l = l->next)
      {
            const char   *value = l->data;
            GtkTreeIter   iter;
            gboolean      found = FALSE;
            gboolean      valid = FALSE;
            gchar        *title = NULL;

            GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(self->combobox)); 

            valid = gtk_tree_model_get_iter_first(model, &iter);
            while (valid)
            {
                  gchar *iter_value, *iter_title;
                  gtk_tree_model_get(model, &iter,
                                 OPTION_COL_TITLE, &iter_title,
                                 OPTION_COL_VALUE, &iter_value,
                                 -1);
                  if (g_ascii_strcasecmp(value, iter_value) == 0)
                  {
                        found = TRUE;
                        title = iter_title;
                        g_free(iter_value);
                        break;
                  }
                  g_free(iter_title);
                  g_free(iter_value);
                  valid = gtk_tree_model_iter_next(model, &iter);
            }

            if (!found)
            {
                  g_signal_emit (G_OBJECT(self), signals[TITLE], 0, value, &title);

                  if (title != NULL)
                  {
                        GtkTreeIter new_iter;
                        GtkTreeModel *real_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model));

                        gtk_list_store_append(GTK_LIST_STORE(real_model), &new_iter);
                        gtk_list_store_set(GTK_LIST_STORE(real_model), &new_iter,
                                       OPTION_COL_TITLE, title,
                                       OPTION_COL_VALUE, value,
                                       -1);
                        found = TRUE;
                  }
            }

            if (found)
            {
                  GtkTreeIter sel_iter;
                  gtk_list_store_append (store, &sel_iter);
                  gtk_list_store_set (store, &sel_iter,
                              OPTION_COL_TITLE, title,
                              OPTION_COL_VALUE, value,
                              -1);
            }
      
            g_free(title);
      }
}

/** galeon_language_editor_get_selected:
 * @values: where to store the values or %NULL
 * @titles: where to store the titles or %NULL
 *
 * Get the currently selected list of languages.
 *
 * The lists and the strings in the lists must be freed by the caller.
 */
void
galeon_language_editor_get_selected (GaleonLanguageEditor *self,
                                 GSList **values, GSList **titles)
{
      GtkTreeModel *model;
      GtkTreeIter   iter;

      g_return_if_fail (values != NULL || titles != NULL);

      if (values) *values = NULL;
      if (titles) *titles = NULL;

      model = gtk_tree_view_get_model (GTK_TREE_VIEW(self->treeview));

      if (!gtk_tree_model_get_iter_first (model, &iter))
            return;

      do {
            gchar *title, *value;

            gtk_tree_model_get (model, &iter,
                        OPTION_COL_TITLE, &title,
                        OPTION_COL_VALUE, &value,
                        -1);

            if (values)
            {
                   *values = g_slist_prepend (*values, value);
            }
            else
            {
                  g_free(value);
            }

            if (titles)
            {
                  *titles = g_slist_prepend (*titles, title);
            }
            else
            {
                  g_free(title);
            }

      } while (gtk_tree_model_iter_next (model, &iter));

      if (values) *values = g_slist_reverse (*values);
      if (titles) *titles = g_slist_reverse (*titles);
}

static void
treeview_construct (GtkWidget *treeview)
{
      GtkListStore      *store;
      GtkTreeViewColumn *column;
      GtkCellRenderer   *renderer;

      g_return_if_fail (GTK_IS_TREE_VIEW(treeview));

      /* model */

      store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);

      /* view */

      column = gtk_tree_view_column_new ();

      renderer = gtk_cell_renderer_text_new ();
      gtk_tree_view_column_pack_start (column, renderer, TRUE);
      gtk_tree_view_column_add_attribute (column, renderer,
                                      "text", OPTION_COL_TITLE);

      gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);

      gtk_tree_view_set_model (GTK_TREE_VIEW(treeview),
                           GTK_TREE_MODEL(store));

      g_object_unref (store);
}

static void
on_selection_changed (GtkTreeSelection *selection, GaleonLanguageEditor *self)
{
      GtkTreeModel     *model;
      GtkTreeIter       iter;
      gboolean          can_up, can_down, can_remove;

      if (gtk_tree_selection_get_selected (selection, &model, &iter))
      {
            GtkTreePath *path;

            path = gtk_tree_model_get_path (model, &iter);

            can_up     = gtk_tree_path_prev (path);
            can_down   = gtk_tree_model_iter_next (model, &iter);
            can_remove = TRUE;

            gtk_tree_path_free (path);
      }
      else
      {
            can_up = can_down = can_remove = FALSE;
      }

      gtk_widget_set_sensitive (self->remove, can_remove);
      gtk_widget_set_sensitive (self->up,     can_up);
      gtk_widget_set_sensitive (self->down,   can_down);
}

static void
update_buttons_sensitivity (GaleonLanguageEditor *self)
{
      GtkTreeSelection *selection;

      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(self->treeview));
      on_selection_changed (selection, self);
}

static void
on_add_clicked (GtkWidget *button, GaleonLanguageEditor *self)
{
      GtkListStore *store;
      GtkTreeIter   iter;
      GtkTreeIter   combo_iter;
      gchar *title, *value;

      g_return_if_fail(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(self->combobox),
                                           &combo_iter));
      gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(self->combobox)), &combo_iter,
                     OPTION_COL_TITLE, &title,
                     OPTION_COL_VALUE, &value,
                     -1);

      store = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(self->treeview)));

      gtk_list_store_append (store, &iter);
      gtk_list_store_set (store, &iter,
                  OPTION_COL_TITLE, title,
                  OPTION_COL_VALUE, value,
                  -1);

      g_free(title);
      g_free(value);

      update_buttons_sensitivity (self);
      g_signal_emit (G_OBJECT(self), signals[CHANGED], 0);
}

static void
on_remove_clicked (GtkWidget *button, GaleonLanguageEditor *self)
{
      GtkTreeSelection *selection;
      GtkTreeModel     *model;
      GtkTreeIter       iter;

      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(self->treeview));

      g_return_if_fail (gtk_tree_selection_get_selected (selection, &model, &iter));
      g_return_if_fail (GTK_IS_LIST_STORE(model));

      gtk_list_store_remove (GTK_LIST_STORE(model), &iter);

      g_signal_emit (G_OBJECT(self), signals[CHANGED], 0);
}

static void
on_up_clicked (GtkWidget *button, GaleonLanguageEditor *self)
{
      GtkTreeSelection *selection;
      GtkTreeModel     *model;
      GtkTreeIter       iter;
      GtkTreePath      *path;
      GtkTreeIter       prev;

      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(self->treeview));

      g_return_if_fail (gtk_tree_selection_get_selected (selection, &model, &iter));
      g_return_if_fail (GTK_IS_LIST_STORE(model));

      path = gtk_tree_model_get_path (model, &iter);
      g_return_if_fail (path != NULL);
      gtk_tree_path_prev (path);
      gtk_tree_model_get_iter (model, &prev, path);
      gtk_tree_path_free (path);

      gtk_list_store_swap (GTK_LIST_STORE(model), &iter, &prev);

      g_signal_emit (G_OBJECT(self), signals[CHANGED], 0);
      update_buttons_sensitivity (self);
}

static void
on_down_clicked (GtkWidget *button, GaleonLanguageEditor *self)
{
      GtkTreeSelection *selection;
      GtkTreeModel     *model;
      GtkTreeIter       iter;
      GtkTreeIter      *next;

      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(self->treeview));

      g_return_if_fail (gtk_tree_selection_get_selected (selection, &model, &iter));
      g_return_if_fail (GTK_IS_LIST_STORE(model));

      next = gtk_tree_iter_copy (&iter);
      gtk_tree_model_iter_next (model, next);
      gtk_list_store_swap (GTK_LIST_STORE(model), &iter, next);
      gtk_tree_iter_free (next);

      g_signal_emit (G_OBJECT(self), signals[CHANGED], 0);
      update_buttons_sensitivity (self);
}

/* GObject boilerplate */

GtkWidget *
galeon_language_editor_new (void)
{
      GaleonLanguageEditor *self;

      self = GALEON_LANGUAGE_EDITOR(g_object_new (
                  GALEON_TYPE_LANGUAGE_EDITOR, 
                  "title",         _("Edit Languages"),
                  "has-separator", FALSE,
                  "resizable",     TRUE,
                  "border-width",  6,
                  NULL));
      gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(self)->vbox), 0);
      gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(self)->action_area), 6);

      gtk_dialog_add_buttons (GTK_DIALOG(self), 
                          /* FIXME need docs
                         * GTK_STOCK_HELP,  GTK_RESPONSE_HELP,
                         */
                          GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
                        NULL);

      return GTK_WIDGET(self);
}

static void
galeon_language_editor_init (GaleonLanguageEditor *self)
{
      GladeXML         *gxml;
      GtkWidget        *content, *glade_dialog;
      GtkTreeSelection *selection;

      gxml = gul_glade_widget_new ("prefs-dialog.glade", "language_dialog", NULL, self);
      g_return_if_fail (gxml != NULL);

      gul_glade_get_widgets (gxml,
                  "content_area",  &content,
                  "combobox",    &self->combobox,
                  "treeview",      &self->treeview,
                  "add_button",    &self->add,
                  "remove_button", &self->remove,
                  "up_button",     &self->up,
                  "down_button",   &self->down,
                  "language_dialog", &glade_dialog,
                  NULL);

      gtk_widget_reparent (content, GTK_DIALOG(self)->vbox);

      treeview_construct (self->treeview);

      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(self->treeview));
      g_signal_connect (G_OBJECT(selection), "changed", G_CALLBACK(on_selection_changed), self);
      on_selection_changed (selection, self);

      g_signal_connect (G_OBJECT(self->add),    "clicked", G_CALLBACK(on_add_clicked),    self);
      g_signal_connect (G_OBJECT(self->remove), "clicked", G_CALLBACK(on_remove_clicked), self);
      g_signal_connect (G_OBJECT(self->up),     "clicked", G_CALLBACK(on_up_clicked),     self);
      g_signal_connect (G_OBJECT(self->down),   "clicked", G_CALLBACK(on_down_clicked),   self);

      g_object_unref (gxml);
      gtk_widget_destroy (glade_dialog);
}

static void
galeon_language_editor_finalize (GObject *object)
{
      G_OBJECT_CLASS(galeon_language_editor_parent_class)->finalize (object);
}

static void
galeon_language_editor_class_init (GaleonLanguageEditorClass *klass)
{
      GObjectClass *object_class = G_OBJECT_CLASS(klass);


      object_class->finalize = galeon_language_editor_finalize;

      signals[CHANGED] = 
            g_signal_new ("changed",
                  G_OBJECT_CLASS_TYPE (klass),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GaleonLanguageEditorClass, changed),
                  NULL, NULL,
                  g_cclosure_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);

      signals[TITLE] =
            g_signal_new ("title",
                  G_OBJECT_CLASS_TYPE (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GaleonLanguageEditorClass, title),
                  NULL, NULL,
                  galeon_marshal_STRING__STRING,
                  G_TYPE_STRING, 1,
                  G_TYPE_STRING);
}


Generated by  Doxygen 1.6.0   Back to index