Logo Search packages:      
Sourcecode: kazehakase version File versions

kz-dlist.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 * kz_dlist.c - Pair of reorderable stack list widget.
 * Copyright (C) 2001-2002 Takuro Ashie
 *
 * 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 3S30, Boston, MA 02111-1307, USA.
 *
 * $Id: kz-dlist.c,v 1.5 2005/02/13 13:20:37 ikezoe Exp $
 */

#include "kz-dlist.h"

#include <string.h>
#include <stdlib.h>
#include <glib/gi18n.h>

#include "gobject-utils.h"
#include "gtk-utils.h"

enum {
      AVAILABLE_LIST_UPDATED_SIGNAL,
      ENABLED_LIST_UPDATED_SIGNAL,
      LAST_SIGNAL
};

enum {
      PROP_0,
      PROP_TITLE1,
      PROP_TITLE2
};

enum {
      COLUMN_TERMINATOR = -1,
      COLUMN_LABEL,
      COLUMN_ID,
      COLUMN_INDEX
};

#define GET_ROW_NUM(widget) \
      (gtk_tree_model_iter_n_children(gtk_tree_view_get_model(GTK_TREE_VIEW(widget)), NULL))


static void       kz_dlist_init                     (KzDList *dlist);
static void       kz_dlist_class_init               (KzDListClass *klass);

/* object class functions */
static void       kz_dlist_dispose                  (GObject      *object);
/* static void       kz_dlist_finalize                 (GObject *object); */
static void       kz_dlist_set_property             (GObject      *object,
                                         guint         prop_id,
                                         const GValue *value,
                                         GParamSpec   *pspec);
static void       kz_dlist_get_property             (GObject      *object,
                                         guint         prop_id,
                                         GValue       *value,
                                         GParamSpec   *pspec);

/* private functions */
static void       kz_dlist_available_list_updated   (KzDList   *dlist);
static void       kz_dlist_enabled_list_updated     (KzDList   *dlist);
static void       kz_dlist_set_sensitive            (KzDList   *dlist);
static GtkWidget *kz_dlist_create_list_widget       (KzDList   *dlist,
                                                     gboolean   reorderble);
static void       cb_add_button_pressed             (GtkButton *button,
                                         gpointer   data);
static void       cb_del_button_pressed             (GtkButton *button,
                                         gpointer   data);
static void       cb_up_button_pressed              (GtkButton *button,
                                         gpointer   data);
static void       cb_down_button_pressed            (GtkButton *button,
                                         gpointer   data);


static GtkHBoxClass *parent_class = NULL;
static gint kz_dlist_signals[LAST_SIGNAL] = {0};


KZ_OBJECT_GET_TYPE(kz_dlist, "KzDList", KzDList,
                   kz_dlist_class_init, kz_dlist_init,
                   GTK_TYPE_HBOX)


static void
kz_dlist_class_init (KzDListClass *klass)
{
      GObjectClass *gobject_class;

      gobject_class = (GObjectClass *) klass;
      parent_class = gtk_type_class (gtk_hbox_get_type ());

      gobject_class->dispose = kz_dlist_dispose;
      /* gobject_class->finalize = kz_dlist_finalize; */
      gobject_class->set_property = kz_dlist_set_property;
      gobject_class->get_property = kz_dlist_get_property;

      g_object_class_install_property(
            gobject_class,
            PROP_TITLE1,
            g_param_spec_string(
                  "title1",
                  _("Title1"),
                  _("The title used for left side tree view"),
                  NULL,
                  G_PARAM_READWRITE));

      g_object_class_install_property(
            gobject_class,
            PROP_TITLE2,
            g_param_spec_string(
                  "title2",
                  _("Title2"),
                  _("The title used for right side tree view"),
                  NULL,
                  G_PARAM_READWRITE));

      kz_dlist_signals[AVAILABLE_LIST_UPDATED_SIGNAL]
            = g_signal_new("available-list-updated",
                         G_TYPE_FROM_CLASS(klass),
                         G_SIGNAL_RUN_FIRST,
                         G_STRUCT_OFFSET (KzDListClass, available_list_updated),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__VOID,
                         G_TYPE_NONE, 0);

      kz_dlist_signals[ENABLED_LIST_UPDATED_SIGNAL]
            = g_signal_new("enabled-list-updated",
                         G_TYPE_FROM_CLASS(klass),
                         G_SIGNAL_RUN_FIRST,
                         G_STRUCT_OFFSET (KzDListClass, enabled_list_updated),
                         NULL, NULL,
                         g_cclosure_marshal_VOID__VOID,
                         G_TYPE_NONE, 0);
}


static void
kz_dlist_init (KzDList *dlist)
{
      GtkWidget *hbox = GTK_WIDGET(dlist);
      GtkWidget *vbox, *vbox1, *vbox2, *vbox3, *hseparator;
      GtkWidget *label, *scrollwin1, *scrollwin2, *clist, *button, *arrow;

      dlist->label1          = NULL;
      dlist->label2          = NULL;
      dlist->clist1          = NULL;
      dlist->clist2          = NULL;
      dlist->add_button      = NULL;
      dlist->del_button      = NULL;
      dlist->up_button       = NULL;
      dlist->down_button     = NULL;

      dlist->available_list  = NULL;

      /* possible columns */
      vbox1 = gtk_vbox_new(FALSE, 0);
      gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
      gtk_widget_show(vbox1);

      label = gtk_label_new(NULL);
      dlist->label1 = label;
      gtk_box_pack_start(GTK_BOX(vbox1), label, FALSE, FALSE, 0);
      gtk_widget_show(label);

      scrollwin1 = gtk_scrolled_window_new(NULL, NULL);
      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin1),
                               GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin1),
                                  GTK_SHADOW_IN);
      gtk_container_set_border_width(GTK_CONTAINER(scrollwin1), 5);
      gtk_box_pack_start(GTK_BOX(vbox1), scrollwin1, TRUE, TRUE, 0);
      gtk_widget_show(scrollwin1);

      clist = dlist->clist1 = kz_dlist_create_list_widget(dlist, FALSE);
      gtk_container_add(GTK_CONTAINER(scrollwin1), clist);
      gtk_widget_show(clist);


      /* add/delete buttons */
      vbox3 = gtk_vbox_new(TRUE, 0);
      gtk_box_pack_start(GTK_BOX(hbox), vbox3, FALSE, FALSE, 0);
      gtk_widget_show(vbox3);

      vbox = gtk_vbox_new(TRUE, 0);
      gtk_box_pack_start (GTK_BOX(vbox3), vbox, FALSE, FALSE, 0);
      gtk_widget_show(vbox);

      button = dlist->add_button = gtk_button_new();
      arrow = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 2);
      gtk_widget_show(button);

      button = dlist->del_button = gtk_button_new();
      arrow = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 2);
      gtk_widget_show(button);

      hseparator = gtk_hseparator_new();
      gtk_box_pack_start(GTK_BOX (vbox), hseparator, FALSE, FALSE, 2);
      gtk_widget_show(hseparator);


      /* move buttons */
      button = dlist->up_button = gtk_button_new();
      arrow = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 2);
      gtk_widget_show(button);

      button = dlist->down_button = gtk_button_new();
      arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
      gtk_container_add(GTK_CONTAINER(button), arrow);
      gtk_widget_show(arrow);
      gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 2);
      gtk_widget_show(button);


      /* Use list */
      vbox2 = gtk_vbox_new(FALSE, 0);
      gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
      gtk_widget_show(vbox2);

      label = gtk_label_new(NULL);
      dlist->label2 = label;
      gtk_box_pack_start (GTK_BOX(vbox2), label, FALSE, FALSE, 0);
      gtk_widget_show(label);

      scrollwin2 = gtk_scrolled_window_new (NULL, NULL);
      gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollwin2),
                              GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin2),
                                  GTK_SHADOW_IN);
      gtk_container_set_border_width(GTK_CONTAINER(scrollwin2), 5);
      gtk_box_pack_start(GTK_BOX(vbox2), scrollwin2, TRUE, TRUE, 0);
      gtk_widget_show(scrollwin2);

      clist = dlist->clist2 = kz_dlist_create_list_widget(dlist, TRUE);
      gtk_container_add(GTK_CONTAINER(scrollwin2), clist);
      gtk_widget_show(clist);

      gtk_widget_set_size_request(dlist->add_button,  20, 20);
      gtk_widget_set_size_request(dlist->del_button,  20, 20);
      gtk_widget_set_size_request(dlist->up_button,   20, 20);
      gtk_widget_set_size_request(dlist->down_button, 20, 20);

      g_signal_connect(dlist->add_button, "clicked",
                   G_CALLBACK(cb_add_button_pressed),
                   dlist);
      g_signal_connect(dlist->del_button, "clicked",
                   G_CALLBACK(cb_del_button_pressed),
                   dlist);
      g_signal_connect(dlist->up_button, "clicked",
                   G_CALLBACK(cb_up_button_pressed),
                   dlist);
      g_signal_connect(dlist->down_button, "clicked",
                   G_CALLBACK(cb_down_button_pressed),
                   dlist);

      kz_dlist_set_sensitive(dlist);
}


static void
kz_dlist_dispose (GObject *object)
{
      KzDList *dlist = KZ_DLIST(object);

      g_list_foreach(dlist->available_list, (GFunc) g_free, NULL);
      g_list_free(dlist->available_list);
      dlist->available_list = NULL;

      if (G_OBJECT_CLASS(parent_class)->dispose)
            G_OBJECT_CLASS(parent_class)->dispose(object);
}


/* KZ_OBJECT_FINALIZE(kz_dlist, KzDList) */


static void
kz_dlist_set_property (GObject *object,
                   guint prop_id,
                   const GValue *value,
                   GParamSpec *pspec)
{
      KzDList *dlist = KZ_DLIST(object);

      switch (prop_id)
      {
      case PROP_TITLE1:
            gtk_label_set_text(GTK_LABEL(dlist->label1),
                           g_value_get_string(value));
            break;
      case PROP_TITLE2:
            gtk_label_set_text(GTK_LABEL(dlist->label2),
                           g_value_get_string(value));
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
            break;
      }
}


static void
kz_dlist_get_property (GObject *object,
                   guint prop_id,
                   GValue *value,
                   GParamSpec *pspec)
{
      KzDList *dlist = KZ_DLIST(object);
      const gchar *text;

      switch (prop_id)
      {
      case PROP_TITLE1:
            text = gtk_label_get_text(GTK_LABEL(dlist->label1));
            g_value_set_string(value, text);
            break;
      case PROP_TITLE2:
            text = gtk_label_get_text(GTK_LABEL(dlist->label2));
            g_value_set_string(value, text);
            break;
      default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
            break;
      }
}


GtkWidget *
kz_dlist_new (const gchar *title1,
            const gchar *title2)
{
      KzDList *dlist = g_object_new (KZ_TYPE_DLIST,
                               "title1", title1,
                               "title2", title2,
                               NULL);

      return GTK_WIDGET(dlist);
}


gint
kz_dlist_append_available_item (KzDList *dlist, const gchar *label, const gchar *id)
{
      GtkWidget *clist = dlist->clist1;
      GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(clist));
      GtkListStore *store = GTK_LIST_STORE(model);
      GtkTreeIter iter;
      gchar *text;
      gint idx;

      g_return_val_if_fail(KZ_IS_DLIST(dlist), -1);
      g_return_val_if_fail(label, -1);

      if (id)
            text = g_strdup(id);
      else
            text = g_strdup(label);

      dlist->available_list = g_list_append(dlist->available_list, text);
      idx = g_list_index(dlist->available_list, text);

      gtk_list_store_append(store, &iter);
      gtk_list_store_set(store, &iter,
                     COLUMN_LABEL, label,
                     COLUMN_ID,    id,
                     COLUMN_INDEX, idx,
                     COLUMN_TERMINATOR);

      kz_dlist_set_sensitive(dlist);

      return idx;
}


void
kz_dlist_column_add (KzDList *dlist, gint idx)
{
      GtkTreeView *treeview1 = GTK_TREE_VIEW(dlist->clist1);
      GtkTreeView *treeview2 = GTK_TREE_VIEW(dlist->clist2);
      GtkTreeModel *model1 = gtk_tree_view_get_model(treeview1);
      GtkTreeModel *model2 = gtk_tree_view_get_model(treeview2);
      GtkTreeIter iter1, iter2, next;
      gboolean go_next;
      gchar *label = NULL, *id = NULL;
      gchar *text;
      GList *list;

      list = g_list_nth(dlist->available_list, idx);
      g_return_if_fail(list);
      text = list->data;
      g_return_if_fail(text);

      /* find row from clist1 */
      go_next = gtk_tree_model_get_iter_first(model1, &iter1);
      for (; go_next; go_next = gtk_tree_model_iter_next(model1, &iter1))
      {
            gtk_tree_model_get(model1, &iter1,
                           COLUMN_LABEL, &label,
                           COLUMN_ID,    &id,
                           COLUMN_TERMINATOR);
            if (id && !strcmp(text, id)) break;
            g_free(label);
            g_free(id);
            label = NULL;
            id    = NULL;
      }
      if (!id)
      {
            g_free(label);
            return;
      }

      /* append to clist2 */
      gtk_list_store_append(GTK_LIST_STORE(model2), &iter2);
      gtk_list_store_set(GTK_LIST_STORE(model2), &iter2,
                     COLUMN_LABEL, label,
                     COLUMN_ID,    id,
                     COLUMN_INDEX, idx,
                     COLUMN_TERMINATOR);

      /* set cursor of clist1 */
      next = iter1;
      if (gtk_tree_model_iter_next(model1, &next))
      {
            GtkTreePath *path = gtk_tree_model_get_path(model1, &next);
            gtk_tree_view_set_cursor(treeview1, path, NULL, FALSE);
            gtk_tree_path_free(path);
      }
      else
      {
            GtkTreePath *path = gtk_tree_model_get_path(model1, &iter1);
            if (gtk_tree_path_prev(path))
                  gtk_tree_view_set_cursor(treeview1, path, NULL, FALSE);
            gtk_tree_path_free(path);
      }

      /* remove from clist1 */
      gtk_list_store_remove(GTK_LIST_STORE(model1), &iter1);

      /* clean :-) */
      g_free (label);
      g_free (id);

      g_signal_emit_by_name(treeview1, "cursor-changed");

      kz_dlist_available_list_updated(dlist);
      kz_dlist_enabled_list_updated(dlist);
}


void
kz_dlist_column_del (KzDList *dlist, gint idx)
{
      GtkTreeView *treeview1 = GTK_TREE_VIEW(dlist->clist1);
      GtkTreeView *treeview2 = GTK_TREE_VIEW(dlist->clist2);
      GtkTreeModel *model1 = gtk_tree_view_get_model(treeview1);
      GtkTreeModel *model2 = gtk_tree_view_get_model(treeview2);
      GtkTreeIter iter, iter1, iter2, next;
      gboolean go_next;
      gchar *label = NULL, *id = NULL;
      gchar *text;
      GList *list;

      list = g_list_nth(dlist->available_list, idx);
      g_return_if_fail(list);
      text = list->data;
      g_return_if_fail(text);

      /* find row from clist2 */
      go_next = gtk_tree_model_get_iter_first(model2, &iter2);
      for (; go_next; go_next = gtk_tree_model_iter_next(model2, &iter2))
      {
            gtk_tree_model_get(model2, &iter2,
                           COLUMN_LABEL, &label,
                           COLUMN_ID,    &id,
                           COLUMN_TERMINATOR);
            if (id && !strcmp(text, id)) break;
            g_free(label);
            g_free(id);
            label = NULL;
            id    = NULL;
      }
      if (!id)
      {
            g_free(label);
            return;
      }

      /* append to clist1 */
      go_next = gtk_tree_model_get_iter_first(model1, &iter1);
      for (; go_next; go_next = gtk_tree_model_iter_next(model1, &iter1))
      {
            gint idx1;
            gtk_tree_model_get(model1, &iter1,
                           COLUMN_INDEX, &idx1,
                           COLUMN_TERMINATOR);
            if (idx < idx1) break;
      }

      if (go_next)
            gtk_list_store_insert_before(GTK_LIST_STORE(model1), &iter, &iter1);
      else
            gtk_list_store_append(GTK_LIST_STORE(model1), &iter);

      gtk_list_store_set(GTK_LIST_STORE(model1), &iter,
                     COLUMN_LABEL, label,
                     COLUMN_ID,    id,
                     COLUMN_INDEX, idx,
                     COLUMN_TERMINATOR);

      /* set cursor of clist2 */
      next = iter2;
      if (gtk_tree_model_iter_next(model2, &next))
      {
            GtkTreePath *path = gtk_tree_model_get_path(model2, &next);
            gtk_tree_view_set_cursor(treeview2, path, NULL, FALSE);
            gtk_tree_path_free(path);
      }
      else
      {
            GtkTreePath *path = gtk_tree_model_get_path(model2, &iter2);
            if (gtk_tree_path_prev(path))
                  gtk_tree_view_set_cursor(treeview2, path, NULL, FALSE);
            gtk_tree_path_free(path);
      }

      /* remove from clist2 */
      gtk_list_store_remove(GTK_LIST_STORE(model2), &iter2);

      /* clean :-) */
      g_free(label);
      g_free(id);

      g_signal_emit_by_name(treeview2, "cursor-changed");

      kz_dlist_available_list_updated(dlist);
      kz_dlist_enabled_list_updated(dlist);
}


void
kz_dlist_column_add_by_id (KzDList *dlist, const gchar *label)
{
      GList *list;
      gint j, idx = -1;

      g_return_if_fail(KZ_IS_DLIST (dlist));
      g_return_if_fail(label && *label);

      list = dlist->available_list;
      for (j = 0; list; j++, list = g_list_next (list))
      {
            if (!strcmp (label, (gchar *)list->data))
            {
                  idx = j;
                  break;
            }
      }
      if (idx >= 0)
            kz_dlist_column_add(dlist, idx);

      kz_dlist_set_sensitive(dlist);
}


gint
kz_dlist_get_n_available_items (KzDList  *dlist)
{
      g_return_val_if_fail(KZ_IS_DLIST(dlist), 0);
      return GET_ROW_NUM(dlist->clist1);
}


gint
kz_dlist_get_n_enabled_items (KzDList  *dlist)
{
      g_return_val_if_fail(KZ_IS_DLIST(dlist), 0);
      return GET_ROW_NUM(dlist->clist2);
}


static gchar *
kz_dlist_get_row (KzDList *dlist, gint row,
              gboolean is_available, gboolean is_label)
{
      GtkTreeView *treeview;
      GtkTreeModel *model;
      GtkTreeIter iter;
      gboolean success;
      gchar *text;
      gint col = is_label ? COLUMN_LABEL : COLUMN_ID;

      g_return_val_if_fail(KZ_IS_DLIST(dlist), NULL);

      treeview = GTK_TREE_VIEW(is_available ? dlist->clist1 : dlist->clist2);
      model = gtk_tree_view_get_model(treeview);

      if (row < 0 && row >= GET_ROW_NUM(treeview)) return NULL;

      success = gtk_tree_model_iter_nth_child(model, &iter, NULL, row);
      if (!success) return NULL;

      gtk_tree_model_get(model, &iter,
                     col, &text,
                     COLUMN_TERMINATOR);

      return text;
}


gchar *
kz_dlist_get_available_id (KzDList *dlist, gint row)
{
      return kz_dlist_get_row(dlist, row, TRUE, FALSE);
}


gchar *
kz_dlist_get_available_label (KzDList *dlist, gint row)
{
      return kz_dlist_get_row(dlist, row, TRUE, TRUE);
}


gchar *
kz_dlist_get_enabled_id (KzDList *dlist, gint row)
{
      return kz_dlist_get_row(dlist, row, FALSE, FALSE);
}


gchar *
kz_dlist_get_enabled_label (KzDList *dlist, gint row)
{
      return kz_dlist_get_row(dlist, row, FALSE, TRUE);
}



/*******************************************************************************
 *
 *  Callback functions for child widget.
 *
 *******************************************************************************/
static void
cb_cursor_changed (GtkTreeView *treeview, gpointer data)
{
      KzDList *dlist = data;

      g_return_if_fail(treeview);
      g_return_if_fail(dlist);

      kz_dlist_set_sensitive(dlist);
}


static void
cb_row_changed (GtkTreeModel *model,
            GtkTreePath *treepath,
            GtkTreeIter *iter,
            gpointer data)
{
      KzDList *dlist = data;

      kz_dlist_enabled_list_updated(dlist);

      kz_dlist_set_sensitive(dlist);
}


static void
cb_row_deleted (GtkTreeModel *model,
            GtkTreePath *treepath,
            gpointer data)
{
      KzDList *dlist = data;

      kz_dlist_enabled_list_updated(dlist);
      kz_dlist_set_sensitive(dlist);
}


static void
cb_add_button_pressed (GtkButton *button, gpointer data)
{
      KzDList *dlist = data;
      GtkTreeView *treeview = GTK_TREE_VIEW(dlist->clist1);
      GtkTreeModel *model = gtk_tree_view_get_model(treeview);
      GtkTreeSelection *selection;
      GtkTreeIter iter;
      gboolean success;
      gint idx;

      selection = gtk_tree_view_get_selection(treeview);
      success = gtk_tree_selection_get_selected(selection, &model, &iter);
      if (!success) return;

      gtk_tree_model_get(model, &iter,
                     COLUMN_INDEX, &idx,
                     COLUMN_TERMINATOR);

      kz_dlist_column_add(dlist, idx);
}


static void
cb_del_button_pressed (GtkButton *button, gpointer data)
{
      KzDList *dlist = data;
      GtkTreeView *treeview = GTK_TREE_VIEW(dlist->clist2);
      GtkTreeModel *model = gtk_tree_view_get_model(treeview);
      GtkTreeSelection *selection;
      GtkTreeIter iter;
      gboolean success;
      gint idx;

      selection = gtk_tree_view_get_selection(treeview);
      success = gtk_tree_selection_get_selected(selection, &model, &iter);
      if (!success) return;

      gtk_tree_model_get(model, &iter,
                     COLUMN_INDEX, &idx,
                     COLUMN_TERMINATOR);

      kz_dlist_column_del(dlist, idx);
}


static void
cb_up_button_pressed (GtkButton *button, gpointer data)
{
      KzDList *dlist = data;
      GtkTreeView *treeview = GTK_TREE_VIEW(dlist->clist2);
      GtkTreeModel *model = gtk_tree_view_get_model(treeview);
      GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
      GtkTreeIter iter, prev_iter;
      GtkTreePath *treepath;
      gboolean success;

      /* get src row */
      selection = gtk_tree_view_get_selection(treeview);
      success = gtk_tree_selection_get_selected(selection, &model, &iter);
      if (!success) return;
      treepath = gtk_tree_model_get_path(model, &iter);

      /* get prev row */
      success = gtk_tree_path_prev(treepath);
      if (!success)
      {
            gtk_tree_path_free(treepath);
            return;
      }
      gtk_tree_model_get_iter(model, &prev_iter, treepath);
      gtk_tree_path_free(treepath);

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

      kz_dlist_enabled_list_updated(dlist);
}


static void
cb_down_button_pressed (GtkButton *button, gpointer data)
{
      KzDList *dlist = data;
      GtkTreeView *treeview = GTK_TREE_VIEW(dlist->clist2);
      GtkTreeModel *model = gtk_tree_view_get_model(treeview);
      GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
      GtkTreeIter iter, next_iter;
      gboolean success;

      /* get src row */
      selection = gtk_tree_view_get_selection(treeview);
      success = gtk_tree_selection_get_selected(selection, &model, &iter);
      if (!success) return;

      /* get next row */
      next_iter = iter;
      success = gtk_tree_model_iter_next(model, &next_iter);
      if (!success) return;

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

      kz_dlist_enabled_list_updated(dlist);
}



/*******************************************************************************
 *
 *  Private functions.
 *
 *******************************************************************************/
static void
kz_dlist_available_list_updated (KzDList *dlist)
{
      g_return_if_fail(KZ_IS_DLIST(dlist));

      g_signal_emit(dlist,
                  kz_dlist_signals[AVAILABLE_LIST_UPDATED_SIGNAL], 0);

      kz_dlist_set_sensitive(dlist);
}


static void
kz_dlist_enabled_list_updated (KzDList *dlist)
{
      g_return_if_fail(KZ_IS_DLIST(dlist));

      g_signal_emit(dlist,
                  kz_dlist_signals[ENABLED_LIST_UPDATED_SIGNAL], 0);

      kz_dlist_set_sensitive(dlist);
}


static gint
get_selected_row (GtkTreeView *treeview)
{
      GtkTreeSelection *selection;
      GtkTreeIter iter;
      GtkTreeModel *model;
      gboolean success;

      selection = gtk_tree_view_get_selection(treeview);
      success = gtk_tree_selection_get_selected(selection, &model, &iter);
      if (success)
      {
            GtkTreePath *treepath = gtk_tree_model_get_path(model, &iter);
            gchar *path = gtk_tree_path_to_string(treepath);
            gint selected;

            selected = atoi(path);
            gtk_tree_path_free(treepath);
            g_free(path);

            return selected;
      }

      return -1;
}


static void
kz_dlist_set_sensitive (KzDList *dlist)
{
      gint selected1 = get_selected_row(GTK_TREE_VIEW(dlist->clist1));
      gint selected2 = get_selected_row(GTK_TREE_VIEW(dlist->clist2));

      /* add button */
      if (selected1 < 0 || selected1 >= GET_ROW_NUM(dlist->clist1))
            gtk_widget_set_sensitive(dlist->add_button, FALSE);
      else
            gtk_widget_set_sensitive(dlist->add_button, TRUE);

      /* delete button */
      if (selected2 < 0 || selected2 >= GET_ROW_NUM(dlist->clist2))
            gtk_widget_set_sensitive(dlist->del_button, FALSE);
      else
            gtk_widget_set_sensitive(dlist->del_button, TRUE);

      /* up button */
      if (selected2 > 0 && selected2 < GET_ROW_NUM(dlist->clist2))
            gtk_widget_set_sensitive(dlist->up_button, TRUE);
      else
            gtk_widget_set_sensitive(dlist->up_button, FALSE);

      /* down button */
      if (selected2 >= 0 && selected2 < GET_ROW_NUM(dlist->clist2) - 1)
            gtk_widget_set_sensitive(dlist->down_button, TRUE);
      else
            gtk_widget_set_sensitive(dlist->down_button, FALSE);
}


static GtkWidget *
kz_dlist_create_list_widget (KzDList *dlist, gboolean reorderble)
{
      GtkWidget *clist;

      GtkListStore *store;
      GtkTreeViewColumn *col;
      GtkCellRenderer *render;

      store = gtk_list_store_new(3,
                           G_TYPE_STRING,
                           G_TYPE_STRING,
                           G_TYPE_INT);
      clist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
      dlist->clist2 = clist;
      gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(clist), TRUE);
      gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(clist), FALSE);

      if (reorderble)
            gtk_tree_view_set_reorderable(GTK_TREE_VIEW(clist), TRUE);

      g_signal_connect(store, "row_changed",
                   G_CALLBACK(cb_row_changed),
                   dlist);
      g_signal_connect(store, "row_deleted",
                   G_CALLBACK(cb_row_deleted),
                   dlist);
      g_signal_connect(clist,"cursor_changed",
                   G_CALLBACK(cb_cursor_changed),
                   dlist);

      /* set column */
      col = gtk_tree_view_column_new();
      render = gtk_cell_renderer_text_new();
      gtk_tree_view_column_pack_start(col, render, TRUE);
      gtk_tree_view_column_add_attribute(col, render, "text", 0);
      gtk_tree_view_append_column(GTK_TREE_VIEW(clist), col);

      g_object_unref(store);
      return clist;
}

Generated by  Doxygen 1.6.0   Back to index