2005-08-06 [paul] 1.9.13cvs18
[claws.git] / src / prefs_summary_column.c
index 3bb6a9ab57dabc0dbf171177d4b5791fb6a48aa5..159b86ce41ecfcea3f882a699ab83ca1dda68d3c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2001 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
  *
  * 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
 #include "defs.h"
 
 #include <glib.h>
+#include <glib/gi18n.h>
 #include <gtk/gtkmain.h>
 #include <gtk/gtkwindow.h>
 #include <gtk/gtkvbox.h>
 #include <gtk/gtkhbox.h>
-#include <gtk/gtkclist.h>
 #include <gtk/gtkbutton.h>
 #include <gdk/gdkkeysyms.h>
 
-#include "intl.h"
-#include "prefs.h"
+#include "prefs_gtk.h"
 #include "prefs_common.h"
 #include "prefs_summary_column.h"
 #include "manage_window.h"
 #include "gtkutils.h"
 #include "utils.h"
 
+enum {
+       SUMCOL_NAME,
+       SUMCOL_TYPE,
+       N_SUMCOL_COLUMNS
+};
+
+#define TARGET_INFO_SUMCOL  (0xFEEDBABE)
+
+static const GtkTargetEntry row_targets[] = {
+       { "PREFS_SUM_COL_MODEL_ROW", GTK_TARGET_SAME_APP, TARGET_INFO_SUMCOL }
+};
+
+
 static struct _SummaryColumnDialog
 {
        GtkWidget *window;
 
-       GtkWidget *stock_clist;
-       GtkWidget *shown_clist;
+       GtkWidget *stock_list_view;
+       GtkWidget *shown_list_view;
 
        GtkWidget *add_btn;
        GtkWidget *remove_btn;
@@ -65,26 +77,30 @@ static struct _SummaryColumnDialog
 
 static const gchar *const col_name[N_SUMMARY_COLS] = {
        N_("Mark"),             /* S_COL_MARK    */
-       N_("Unread"),           /* S_COL_UNREAD  */
+       N_("Status"),           /* S_COL_STATUS  */
        N_("Attachment"),       /* S_COL_MIME    */
        N_("Subject"),          /* S_COL_SUBJECT */
        N_("From"),             /* S_COL_FROM    */
+       N_("To"),               /* S_COL_TO      */
        N_("Date"),             /* S_COL_DATE    */
        N_("Size"),             /* S_COL_SIZE    */
        N_("Number"),           /* S_COL_NUMBER  */
-        N_("Score")            /* S_COL_SCORE   */
+        N_("Score"),           /* S_COL_SCORE   */
+       N_("Locked"),           /* S_COL_LOCKED  */
 };
 
 static SummaryColumnState default_state[N_SUMMARY_COLS] = {
        { S_COL_MARK   , TRUE  },
-       { S_COL_UNREAD , TRUE  },
+       { S_COL_STATUS , TRUE  },
        { S_COL_MIME   , TRUE  },
        { S_COL_SUBJECT, TRUE  },
        { S_COL_FROM   , TRUE  },
+       { S_COL_TO     , FALSE },
        { S_COL_DATE   , TRUE  },
        { S_COL_SIZE   , TRUE  },
        { S_COL_NUMBER , FALSE },
-        { S_COL_SCORE  , FALSE }
+        { S_COL_SCORE  , FALSE },
+       { S_COL_LOCKED , FALSE },
 };
 
 static void prefs_summary_column_create        (void);
@@ -107,10 +123,40 @@ static void prefs_summary_column_cancel   (void);
 static gint prefs_summary_column_delete_event  (GtkWidget      *widget,
                                                 GdkEventAny    *event,
                                                 gpointer        data);
-static void prefs_summary_column_key_pressed   (GtkWidget      *widget,
+static gboolean prefs_summary_column_key_pressed(GtkWidget     *widget,
                                                 GdkEventKey    *event,
                                                 gpointer        data);
 
+static GtkListStore *prefs_summary_column_create_store (void);
+
+static void prefs_summary_column_insert_column (GtkListStore *store,
+                                                gint row,
+                                                const gchar *name,
+                                                SummaryColumnType type);
+                                              
+static SummaryColumnType prefs_summary_column_get_column       (GtkWidget *list, 
+                                                                gint row);
+
+static GtkWidget *prefs_summary_column_list_view_create        (const gchar *name);
+
+static void prefs_filtering_create_list_view_columns   (GtkWidget *list_view, 
+                                                        const gchar *name);
+
+static void drag_data_get      (GtkTreeView *tree_view, 
+                                GdkDragContext *context, 
+                                GtkSelectionData *data, 
+                                guint info, 
+                                guint time, 
+                                GtkTreeModel *model);
+                         
+static void drag_data_received (GtkTreeView *tree_view, 
+                                GdkDragContext *context,
+                                gint x, gint y, 
+                                GtkSelectionData *data,
+                                guint info, 
+                                guint time, 
+                                GtkTreeModel *model);
+
 void prefs_summary_column_open(void)
 {
        inc_lock();
@@ -147,11 +193,10 @@ static void prefs_summary_column_create(void)
        GtkWidget *hbox1;
        GtkWidget *clist_hbox;
        GtkWidget *scrolledwin;
-       GtkWidget *stock_clist;
-       GtkWidget *shown_clist;
+       GtkWidget *stock_list_view;
+       GtkWidget *shown_list_view;
 
        GtkWidget *btn_vbox;
-       GtkWidget *btn_vbox1;
        GtkWidget *add_btn;
        GtkWidget *remove_btn;
        GtkWidget *up_btn;
@@ -163,23 +208,21 @@ static void prefs_summary_column_create(void)
        GtkWidget *ok_btn;
        GtkWidget *cancel_btn;
 
-       gchar *title[1];
+       debug_print("Creating summary column setting window...\n");
 
-       debug_print(_("Creating summary column setting window...\n"));
-
-       window = gtk_window_new(GTK_WINDOW_DIALOG);
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
-       gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
-       gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
+       gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
        gtk_window_set_title(GTK_WINDOW(window),
-                            _("Summary display item setting"));
-       gtk_signal_connect(GTK_OBJECT(window), "delete_event",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_delete_event),
-                          NULL);
-       gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_key_pressed),
-                          NULL);
+                            _("Message list columns configuration"));
+       g_signal_connect(G_OBJECT(window), "delete_event",
+                        G_CALLBACK(prefs_summary_column_delete_event),
+                        NULL);
+       g_signal_connect(G_OBJECT(window), "key_press_event",
+                        G_CALLBACK(prefs_summary_column_key_pressed),
+                        NULL);
 
        vbox = gtk_vbox_new(FALSE, 6);
        gtk_widget_show(vbox);
@@ -190,8 +233,8 @@ static void prefs_summary_column_create(void)
        gtk_box_pack_start(GTK_BOX(vbox), label_hbox, FALSE, FALSE, 4);
 
        label = gtk_label_new
-               (_("Select items to be displayed on the summary view. You can modify\n"
-                  "the order by using the Up / Down button, or dragging the items."));
+               (_("Select columns to be displayed in the message list. You can modify\n"
+                  "the order by using the Up / Down buttons or by dragging the items."));
        gtk_widget_show(label);
        gtk_box_pack_start(GTK_BOX(label_hbox), label, FALSE, FALSE, 4);
        gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
@@ -210,88 +253,71 @@ static void prefs_summary_column_create(void)
        gtk_box_pack_start(GTK_BOX(hbox1), clist_hbox, TRUE, TRUE, 0);
 
        scrolledwin = gtk_scrolled_window_new(NULL, NULL);
-       gtk_widget_set_usize(scrolledwin, 180, 210);
+       gtk_widget_set_size_request(scrolledwin, 180, 210);
        gtk_widget_show(scrolledwin);
        gtk_box_pack_start(GTK_BOX(clist_hbox), scrolledwin, TRUE, TRUE, 0);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
 
-       title[0] = _("Available items");
-       stock_clist = gtk_clist_new_with_titles(1, title);
-       gtk_widget_show(stock_clist);
-       gtk_container_add(GTK_CONTAINER(scrolledwin), stock_clist);
-       gtk_clist_set_selection_mode(GTK_CLIST(stock_clist),
-                                    GTK_SELECTION_BROWSE);
-       GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(stock_clist)->column[0].button,
-                              GTK_CAN_FOCUS);
+                                      
+       stock_list_view = prefs_summary_column_list_view_create
+                               (_("Hidden columns"));
+       gtk_widget_show(stock_list_view);
+       gtk_container_add(GTK_CONTAINER(scrolledwin), stock_list_view);
 
        /* add/remove button */
-       btn_vbox = gtk_vbox_new(FALSE, 0);
+       btn_vbox = gtk_vbox_new(FALSE, 8);
        gtk_widget_show(btn_vbox);
        gtk_box_pack_start(GTK_BOX(hbox1), btn_vbox, FALSE, FALSE, 0);
 
-       btn_vbox1 = gtk_vbox_new(FALSE, 8);
-       gtk_widget_show(btn_vbox1);
-       gtk_box_pack_start(GTK_BOX(btn_vbox), btn_vbox1, TRUE, FALSE, 0);
-
-       add_btn = gtk_button_new_with_label(_("  ->  "));
+       add_btn = gtk_button_new_from_stock(GTK_STOCK_ADD);
        gtk_widget_show(add_btn);
-       gtk_box_pack_start(GTK_BOX(btn_vbox1), add_btn, FALSE, FALSE, 0);
-
-       remove_btn = gtk_button_new_with_label(_("  <-  "));
-       gtk_widget_show(remove_btn);
-       gtk_box_pack_start(GTK_BOX(btn_vbox1), remove_btn, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(btn_vbox), add_btn, FALSE, TRUE, 0);
 
-       gtk_signal_connect(GTK_OBJECT(add_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_add), NULL);
-       gtk_signal_connect(GTK_OBJECT(remove_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_remove), NULL);
+       g_signal_connect(G_OBJECT(add_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_add), NULL);
 
        clist_hbox = gtk_hbox_new(FALSE, 8);
        gtk_widget_show(clist_hbox);
        gtk_box_pack_start(GTK_BOX(hbox1), clist_hbox, TRUE, TRUE, 0);
 
        scrolledwin = gtk_scrolled_window_new(NULL, NULL);
-       gtk_widget_set_usize(scrolledwin, 180, 210);
+       gtk_widget_set_size_request(scrolledwin, 180, 210);
        gtk_widget_show(scrolledwin);
        gtk_box_pack_start(GTK_BOX(clist_hbox), scrolledwin, TRUE, TRUE, 0);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
 
-       title[0] = _("Displayed items");
-       shown_clist = gtk_clist_new_with_titles(1, title);
-       gtk_widget_show(shown_clist);
-       gtk_container_add(GTK_CONTAINER(scrolledwin), shown_clist);
-       gtk_clist_set_selection_mode(GTK_CLIST(shown_clist),
-                                    GTK_SELECTION_BROWSE);
-       gtk_clist_set_reorderable(GTK_CLIST(shown_clist), TRUE);
-       gtk_clist_set_use_drag_icons(GTK_CLIST(shown_clist), FALSE);
-       GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(shown_clist)->column[0].button,
-                              GTK_CAN_FOCUS);
+       shown_list_view = prefs_summary_column_list_view_create
+                               (_("Displayed columns"));
+       gtk_widget_show(shown_list_view);
+       gtk_container_add(GTK_CONTAINER(scrolledwin), shown_list_view);
 
        /* up/down button */
-       btn_vbox = gtk_vbox_new(FALSE, 0);
+       btn_vbox = gtk_vbox_new(FALSE, 8);
        gtk_widget_show(btn_vbox);
        gtk_box_pack_start(GTK_BOX(hbox1), btn_vbox, FALSE, FALSE, 0);
 
-       btn_vbox1 = gtk_vbox_new(FALSE, 8);
-       gtk_widget_show(btn_vbox1);
-       gtk_box_pack_start(GTK_BOX(btn_vbox), btn_vbox1, TRUE, FALSE, 0);
+       remove_btn = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
+       gtk_widget_show(remove_btn);
+       gtk_box_pack_start(GTK_BOX(btn_vbox), remove_btn, FALSE, TRUE, 0);
 
-       up_btn = gtk_button_new_with_label(_("Up"));
+       up_btn = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
        gtk_widget_show(up_btn);
-       gtk_box_pack_start(GTK_BOX(btn_vbox1), up_btn, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, TRUE, 0);
 
-       down_btn = gtk_button_new_with_label(_("Down"));
+       down_btn = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
        gtk_widget_show(down_btn);
-       gtk_box_pack_start(GTK_BOX(btn_vbox1), down_btn, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, TRUE, 0);
 
-       gtk_signal_connect(GTK_OBJECT(up_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_up), NULL);
-       gtk_signal_connect(GTK_OBJECT(down_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_down), NULL);
+       g_signal_connect(G_OBJECT(remove_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_remove), NULL);
+       g_signal_connect(G_OBJECT(up_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_up), NULL);
+       g_signal_connect(G_OBJECT(down_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_down), NULL);
 
        btn_hbox = gtk_hbox_new(FALSE, 8);
        gtk_widget_show(btn_hbox);
@@ -301,33 +327,35 @@ static void prefs_summary_column_create(void)
        gtk_widget_show(btn_vbox);
        gtk_box_pack_start(GTK_BOX(btn_hbox), btn_vbox, FALSE, FALSE, 0);
 
-       default_btn = gtk_button_new_with_label(_(" Revert to default "));
+       default_btn = gtk_button_new_with_label(_(" Use default "));
        gtk_widget_show(default_btn);
        gtk_box_pack_start(GTK_BOX(btn_vbox), default_btn, TRUE, FALSE, 0);
-       gtk_signal_connect(GTK_OBJECT(default_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_set_to_default),
-                          NULL);
+       g_signal_connect(G_OBJECT(default_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_set_to_default),
+                        NULL);
 
-       gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
-                               &cancel_btn, _("Cancel"), NULL, NULL);
+       gtkut_stock_button_set_create(&confirm_area, &ok_btn, GTK_STOCK_OK,
+                                     &cancel_btn, GTK_STOCK_CANCEL,
+                                     NULL, NULL);
        gtk_widget_show(confirm_area);
        gtk_box_pack_end(GTK_BOX(btn_hbox), confirm_area, FALSE, FALSE, 0);
        gtk_widget_grab_default(ok_btn);
 
-       gtk_signal_connect(GTK_OBJECT(ok_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_ok), NULL);
-       gtk_signal_connect(GTK_OBJECT(cancel_btn), "clicked",
-                          GTK_SIGNAL_FUNC(prefs_summary_column_cancel), NULL);
+       g_signal_connect(G_OBJECT(ok_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_ok), NULL);
+       g_signal_connect(G_OBJECT(cancel_btn), "clicked",
+                        G_CALLBACK(prefs_summary_column_cancel), NULL);
+
 
        summary_col.window      = window;
-       summary_col.stock_clist = stock_clist;
-       summary_col.shown_clist = shown_clist;
        summary_col.add_btn     = add_btn;
        summary_col.remove_btn  = remove_btn;
        summary_col.up_btn      = up_btn;
        summary_col.down_btn    = down_btn;
        summary_col.ok_btn      = ok_btn;
        summary_col.cancel_btn  = cancel_btn;
+       summary_col.stock_list_view = stock_list_view;
+       summary_col.shown_list_view = shown_list_view;
 }
 
 SummaryColumnState *prefs_summary_column_get_config(void)
@@ -369,57 +397,65 @@ void prefs_summary_column_set_config(SummaryColumnState *state)
 
 static void prefs_summary_column_set_dialog(SummaryColumnState *state)
 {
-       GtkCList *stock_clist = GTK_CLIST(summary_col.stock_clist);
-       GtkCList *shown_clist = GTK_CLIST(summary_col.shown_clist);
+       GtkListStore *stock_store, *shown_store;
        gint pos;
        SummaryColumnType type;
        gchar *name;
 
-       gtk_clist_clear(stock_clist);
-       gtk_clist_clear(shown_clist);
+       stock_store = GTK_LIST_STORE(gtk_tree_view_get_model
+                       (GTK_TREE_VIEW(summary_col.stock_list_view)));
+       shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
+                       (GTK_TREE_VIEW(summary_col.shown_list_view)));
+
+       gtk_list_store_clear(stock_store);
+       gtk_list_store_clear(shown_store);
 
        if (!state)
                state = prefs_summary_column_get_config();
 
        for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
-               gint row;
                type = state[pos].type;
                name = gettext(col_name[type]);
 
-               if (state[pos].visible) {
-                       row = gtk_clist_append(shown_clist, (gchar **)&name);
-                       gtk_clist_set_row_data(shown_clist, row,
-                                              GINT_TO_POINTER(type));
-               } else {
-                       row = gtk_clist_append(stock_clist, (gchar **)&name);
-                       gtk_clist_set_row_data(stock_clist, row,
-                                              GINT_TO_POINTER(type));
-               }
+               if (state[pos].visible)
+                       prefs_summary_column_insert_column(shown_store,
+                                                          -1, name,
+                                                          type);
+               else
+                       prefs_summary_column_insert_column(stock_store,
+                                                           -1, name,
+                                                           type);
        }
 }
 
 static void prefs_summary_column_set_view(void)
 {
-       GtkCList *stock_clist = GTK_CLIST(summary_col.stock_clist);
-       GtkCList *shown_clist = GTK_CLIST(summary_col.shown_clist);
+       gint stock_n_rows, shown_n_rows;
        SummaryColumnState state[N_SUMMARY_COLS];
        SummaryColumnType type;
        gint row, pos = 0;
 
+       stock_n_rows = gtk_tree_model_iter_n_children
+               (gtk_tree_view_get_model(GTK_TREE_VIEW
+                       (summary_col.stock_list_view)), NULL);
+       shown_n_rows = gtk_tree_model_iter_n_children
+               (gtk_tree_view_get_model(GTK_TREE_VIEW
+                       (summary_col.shown_list_view)), NULL);
+
        g_return_if_fail
-               (stock_clist->rows + shown_clist->rows == N_SUMMARY_COLS);
+               (stock_n_rows + shown_n_rows == N_SUMMARY_COLS);
 
-       for (row = 0; row < stock_clist->rows; row++) {
-               type = GPOINTER_TO_INT
-                       (gtk_clist_get_row_data(stock_clist, row));
+       for (row = 0; row < stock_n_rows; row++) {
+               type = prefs_summary_column_get_column
+                       (summary_col.stock_list_view, row);
                state[row].type = type;
                state[row].visible = FALSE;
        }
 
        pos = row;
-       for (row = 0; row < shown_clist->rows; row++) {
-               type = GPOINTER_TO_INT
-                       (gtk_clist_get_row_data(shown_clist, row));
+       for (row = 0; row < shown_n_rows; row++) {
+               type = prefs_summary_column_get_column
+                       (summary_col.shown_list_view, row);
                state[pos + row].type = type;
                state[pos + row].visible = TRUE;
        }
@@ -430,80 +466,155 @@ static void prefs_summary_column_set_view(void)
 
 static void prefs_summary_column_add(void)
 {
-       GtkCList *stock_clist = GTK_CLIST(summary_col.stock_clist);
-       GtkCList *shown_clist = GTK_CLIST(summary_col.shown_clist);
-       gint row;
-       SummaryColumnType type;
+       GtkListStore *stock_store, *shown_store;
+       GtkTreeIter stock_sel, shown_sel, shown_add;
+       gboolean shown_sel_valid;
        gchar *name;
-
-       if (!stock_clist->selection) return;
-
-       row = GPOINTER_TO_INT(stock_clist->selection->data);
-       type = GPOINTER_TO_INT(gtk_clist_get_row_data(stock_clist, row));
-       gtk_clist_remove(stock_clist, row);
-       if (stock_clist->rows == row)
-               gtk_clist_select_row(stock_clist, row - 1, -1);
-
-       if (!shown_clist->selection)
-               row = 0;
-       else
-               row = GPOINTER_TO_INT(shown_clist->selection->data) + 1;
-
-       name = gettext(col_name[type]);
-       row = gtk_clist_insert(shown_clist, row, (gchar **)&name);
-       gtk_clist_set_row_data(shown_clist, row, GINT_TO_POINTER(type));
-       gtk_clist_select_row(shown_clist, row, -1);
+       SummaryColumnType type;
+       
+       stock_store = GTK_LIST_STORE(gtk_tree_view_get_model
+               (GTK_TREE_VIEW(summary_col.stock_list_view)));
+       shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
+               (GTK_TREE_VIEW(summary_col.shown_list_view)));
+       
+       if (!gtk_tree_selection_get_selected
+               (gtk_tree_view_get_selection
+                       (GTK_TREE_VIEW(summary_col.stock_list_view)),
+                NULL,
+                &stock_sel))
+               return;
+
+       shown_sel_valid = gtk_tree_selection_get_selected
+               (gtk_tree_view_get_selection
+                       (GTK_TREE_VIEW(summary_col.shown_list_view)),
+                NULL,
+                &shown_sel);
+                        
+       gtk_tree_model_get(GTK_TREE_MODEL(stock_store), &stock_sel,
+                          SUMCOL_TYPE, &type,
+                          -1);
+                       
+       gtk_list_store_remove(stock_store, &stock_sel);
+
+       gtk_list_store_insert_after(shown_store, &shown_add, 
+                                   shown_sel_valid ? &shown_sel : NULL);
+
+       name = gettext(col_name[type]);                             
+                                   
+       gtk_list_store_set(shown_store, &shown_add,
+                          SUMCOL_NAME, name,
+                          SUMCOL_TYPE, type,
+                          -1);
+       
+       gtk_tree_selection_select_iter(gtk_tree_view_get_selection
+               (GTK_TREE_VIEW(summary_col.shown_list_view)),
+                &shown_add);
 }
 
 static void prefs_summary_column_remove(void)
 {
-       GtkCList *stock_clist = GTK_CLIST(summary_col.stock_clist);
-       GtkCList *shown_clist = GTK_CLIST(summary_col.shown_clist);
-       gint row;
-       SummaryColumnType type;
+       GtkListStore *stock_store, *shown_store;
+       GtkTreeIter shown_sel, stock_sel, stock_add;
+       gboolean stock_sel_valid;
        gchar *name;
-
-       if (!shown_clist->selection) return;
-
-       row = GPOINTER_TO_INT(shown_clist->selection->data);
-       type = GPOINTER_TO_INT(gtk_clist_get_row_data(shown_clist, row));
-       gtk_clist_remove(shown_clist, row);
-       if (shown_clist->rows == row)
-               gtk_clist_select_row(shown_clist, row - 1, -1);
-
-       if (!stock_clist->selection)
-               row = 0;
-       else
-               row = GPOINTER_TO_INT(stock_clist->selection->data) + 1;
-
-       name = gettext(col_name[type]);
-       row = gtk_clist_insert(stock_clist, row, (gchar **)&name);
-       gtk_clist_set_row_data(stock_clist, row, GINT_TO_POINTER(type));
-       gtk_clist_select_row(stock_clist, row, -1);
+       SummaryColumnType type;
+       
+       stock_store = GTK_LIST_STORE(gtk_tree_view_get_model
+               (GTK_TREE_VIEW(summary_col.stock_list_view)));
+       shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
+               (GTK_TREE_VIEW(summary_col.shown_list_view)));
+               
+       if (!gtk_tree_selection_get_selected
+               (gtk_tree_view_get_selection
+                       (GTK_TREE_VIEW(summary_col.shown_list_view)),
+                NULL,
+                &shown_sel))
+               return;
+
+       stock_sel_valid = gtk_tree_selection_get_selected
+               (gtk_tree_view_get_selection
+                       (GTK_TREE_VIEW(summary_col.stock_list_view)),
+                NULL,
+                &stock_sel);
+       
+       gtk_tree_model_get(GTK_TREE_MODEL(shown_store), &shown_sel,
+                          SUMCOL_TYPE, &type,
+                          -1);
+                       
+       gtk_list_store_remove(shown_store, &shown_sel);
+
+       gtk_list_store_insert_after(stock_store, &stock_add, 
+                                   stock_sel_valid ? &stock_sel : NULL);
+
+       name = gettext(col_name[type]);                             
+                                   
+       gtk_list_store_set(stock_store, &stock_add,
+                          SUMCOL_NAME, name,
+                          SUMCOL_TYPE, type,
+                          -1);
+       
+       gtk_tree_selection_select_iter(gtk_tree_view_get_selection
+               (GTK_TREE_VIEW(summary_col.stock_list_view)),
+               &stock_add);
 }
 
 static void prefs_summary_column_up(void)
 {
-       GtkCList *clist = GTK_CLIST(summary_col.shown_clist);
-       gint row;
+       GtkTreePath *prev, *sel;
+       GtkTreeIter isel;
+       GtkListStore *shown_store;
+       GtkTreeIter iprev;
+       
+       if (!gtk_tree_selection_get_selected
+               (gtk_tree_view_get_selection
+                       (GTK_TREE_VIEW(summary_col.shown_list_view)),
+                NULL,
+                &isel))
+               return;
+
+       shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
+               (GTK_TREE_VIEW(summary_col.shown_list_view)));
+
+       sel = gtk_tree_model_get_path(GTK_TREE_MODEL(shown_store), 
+                                     &isel);
+       if (!sel)
+               return;
+
+       prev = gtk_tree_path_copy(sel);         
+       if (!gtk_tree_path_prev(prev)) {
+               gtk_tree_path_free(prev);
+               gtk_tree_path_free(sel);
+               return;
+       }
 
-       if (!clist->selection) return;
+       gtk_tree_model_get_iter(GTK_TREE_MODEL(shown_store),
+                               &iprev, prev);
+       gtk_tree_path_free(sel);
+       gtk_tree_path_free(prev);
 
-       row = GPOINTER_TO_INT(clist->selection->data);
-       if (row > 0)
-               gtk_clist_row_move(clist, row, row - 1);
+       gtk_list_store_swap(shown_store, &iprev, &isel);
 }
 
 static void prefs_summary_column_down(void)
 {
-       GtkCList *clist = GTK_CLIST(summary_col.shown_clist);
-       gint row;
-
-       if (!clist->selection) return;
-
-       row = GPOINTER_TO_INT(clist->selection->data);
-       if (row >= 0 && row < clist->rows - 1)
-               gtk_clist_row_move(clist, row, row + 1);
+       GtkListStore *shown_store;
+       GtkTreeIter next, sel;
+       
+       if (!gtk_tree_selection_get_selected
+               (gtk_tree_view_get_selection
+                       (GTK_TREE_VIEW(summary_col.shown_list_view)),
+                NULL,
+                &sel))
+               return;
+
+       shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
+               (GTK_TREE_VIEW(summary_col.shown_list_view)));
+
+       next = sel;
+       if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(shown_store), &next)) 
+               return;
+
+       gtk_list_store_swap(shown_store, &next, &sel);
 }
 
 static void prefs_summary_column_set_to_default(void)
@@ -532,10 +643,248 @@ static gint prefs_summary_column_delete_event(GtkWidget *widget,
        return TRUE;
 }
 
-static void prefs_summary_column_key_pressed(GtkWidget *widget,
-                                            GdkEventKey *event,
-                                            gpointer data)
+static gboolean prefs_summary_column_key_pressed(GtkWidget *widget,
+                                                GdkEventKey *event,
+                                                gpointer data)
 {
        if (event && event->keyval == GDK_Escape)
                summary_col.finished = TRUE;
+       return FALSE;
 }
+
+static GtkListStore *prefs_summary_column_create_store(void)
+{
+       return gtk_list_store_new(N_SUMCOL_COLUMNS,
+                                 G_TYPE_STRING,
+                                 G_TYPE_INT,
+                                 -1);
+}
+
+static void prefs_summary_column_insert_column(GtkListStore *store,
+                                              gint row,
+                                              const gchar *name,
+                                              SummaryColumnType type)
+{
+       GtkTreeIter iter;
+
+       if (row >= 0) {
+               if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store),
+                                                  &iter, NULL, row))
+                       row = -1;                                                  
+       }
+       if (row < 0) {
+               /* add new */
+               gtk_list_store_append(store, &iter);
+               gtk_list_store_set(store, &iter,
+                                  SUMCOL_NAME, name,
+                                  SUMCOL_TYPE, type,
+                                  -1);
+               return;
+       } else {
+               /* change existing */
+               gtk_list_store_set(store, &iter, 
+                                  SUMCOL_NAME, name,
+                                  SUMCOL_TYPE, type,
+                                  -1);
+       }
+}
+
+/*!
+ *\brief       Return the columnn type for a row
+ */
+static SummaryColumnType prefs_summary_column_get_column(GtkWidget *list, gint row)
+{      
+       GtkTreeView *list_view = GTK_TREE_VIEW(list);
+       GtkTreeModel *model = gtk_tree_view_get_model(list_view);
+       GtkTreeIter iter;
+       SummaryColumnType result;
+
+       if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row))
+               return -1;
+       
+       gtk_tree_model_get(model, &iter, 
+                          SUMCOL_TYPE, &result,
+                          -1);
+       
+       return result;
+}
+
+static GtkWidget *prefs_summary_column_list_view_create(const gchar *name)
+{
+       GtkWidget *list_view;
+       GtkTreeSelection *selector;
+       GtkTreeModel *model;
+
+       model = GTK_TREE_MODEL(prefs_summary_column_create_store());
+       list_view = gtk_tree_view_new_with_model(model);
+       g_object_unref(G_OBJECT(model));
+       
+       gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list_view),
+                                    prefs_common.enable_rules_hint);
+       
+       selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view));
+       gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
+
+       prefs_filtering_create_list_view_columns(GTK_WIDGET(list_view), name);
+
+       gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(list_view),
+                                              GDK_BUTTON1_MASK,
+                                              row_targets,
+                                              G_N_ELEMENTS(row_targets), 
+                                              GDK_ACTION_MOVE);
+                                           
+       gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(list_view), 
+                                            row_targets, 
+                                            G_N_ELEMENTS(row_targets), 
+                                            GDK_ACTION_MOVE);
+               
+       g_signal_connect(G_OBJECT(list_view), "drag_data_get",
+                        G_CALLBACK(drag_data_get),
+                        model);
+
+       g_signal_connect(G_OBJECT(list_view), "drag_data_received",
+                        G_CALLBACK(drag_data_received),
+                        model);
+
+       return list_view;
+}
+
+static void prefs_filtering_create_list_view_columns(GtkWidget *list_view, 
+                                                    const gchar *name)
+{
+       GtkTreeViewColumn *column;
+       GtkCellRenderer *renderer;
+
+       renderer = gtk_cell_renderer_text_new();
+       column = gtk_tree_view_column_new_with_attributes
+               (name, renderer, "text", SUMCOL_NAME, NULL);
+       gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
+}
+
+static void drag_data_get(GtkTreeView *tree_view, GdkDragContext *context, 
+                         GtkSelectionData *data, guint info, 
+                         guint time, GtkTreeModel *model)
+{
+       GtkTreeIter iter;
+       SummaryColumnType type;
+       GtkTreeModel *source_model;
+
+       if (info != TARGET_INFO_SUMCOL) 
+               return;
+
+       if (!gtk_tree_selection_get_selected
+                       (gtk_tree_view_get_selection(tree_view),
+                        &source_model, &iter)) 
+               return;                  
+       
+       gtk_tree_model_get(source_model, &iter, 
+                          SUMCOL_TYPE, &type,
+                          -1);
+
+       /* send the type */
+       gtk_selection_data_set(data, data->target, 8, (gchar *) &type, sizeof type);
+}
+
+static void drag_data_received(GtkTreeView *tree_view, GdkDragContext *context,
+                              gint x, gint y, GtkSelectionData *data,
+                              guint info, guint time, GtkTreeModel *model)
+{
+       GtkWidget *source;
+       GtkTreePath *dst = NULL, *sel = NULL;
+       GtkTreeIter isel, idst;
+       GtkTreeViewDropPosition pos;
+       SummaryColumnType type;
+       GtkTreeModel *sel_model;
+       gchar *name;
+       
+       source = gtk_drag_get_source_widget(context);
+       
+       if (source == GTK_WIDGET(tree_view)) {
+       
+               /*
+                * Same widget: re-order
+                */
+                
+               gtk_tree_selection_get_selected(gtk_tree_view_get_selection(tree_view),
+                                          NULL, &isel);
+               sel = gtk_tree_model_get_path(model, &isel);
+               gtk_tree_view_get_dest_row_at_pos(tree_view, x, y,
+                                                 &dst, &pos);
+
+               /* NOTE: dst is invalid if selection beyond last row, in that
+                * case move beyond last one (XXX_move_before(..., NULL)) */                                              
+
+               if (dst)                                                  
+                       gtk_tree_model_get_iter(model, &idst, dst);
+               else 
+                       gtk_list_store_move_before(GTK_LIST_STORE(model),
+                                                  &isel,
+                                                  NULL);
+
+               /* we do not drag if no valid dst and sel, and when
+                * dst and sel are the same (moving after or before
+                * itself doesn't change order...) */
+               if ((dst && sel) && gtk_tree_path_compare(sel, dst) != 0) {
+                       if (pos == GTK_TREE_VIEW_DROP_BEFORE
+                       ||  pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
+                               gtk_list_store_move_before(GTK_LIST_STORE(model),
+                                                          &isel,
+                                                          &idst);
+                       else
+                               gtk_list_store_move_after(GTK_LIST_STORE(model),
+                                                         &isel,
+                                                         &idst);
+                       
+               } 
+               gtk_tree_path_free(dst);                                          
+               gtk_tree_path_free(sel);
+               gtk_drag_finish(context, TRUE, FALSE, time);
+               
+       } else if (source == summary_col.stock_list_view 
+       ||         source == summary_col.shown_list_view) {
+       
+               /*
+                * Other widget: change and update
+                */
+
+               
+               /* get source information and remove */
+               gtk_tree_selection_get_selected(gtk_tree_view_get_selection(
+                                               GTK_TREE_VIEW(source)),
+                                               &sel_model, &isel);
+               type = *((gint *) data->data);
+               name = gettext(col_name[type]);
+               gtk_list_store_remove(GTK_LIST_STORE(sel_model), &isel);
+
+               /* get insertion position */
+               gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &dst, &pos);
+
+               /* NOTE: dst is invalid if insertion point beyond last row, 
+                * just append to list in that case (XXX_store_append()) */
+
+               if (dst) {
+                       gtk_tree_model_get_iter(model, &idst, dst);
+
+                       if (pos == GTK_TREE_VIEW_DROP_BEFORE
+                       ||  pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
+                               gtk_list_store_insert_before(GTK_LIST_STORE(model),
+                                                            &isel,
+                                                            &idst);
+                       else
+                               gtk_list_store_insert_after(GTK_LIST_STORE(model),
+                                                           &isel,
+                                                           &idst);
+               } else
+                       gtk_list_store_append(GTK_LIST_STORE(model),
+                                             &isel);
+               
+               gtk_list_store_set(GTK_LIST_STORE(model), &isel,
+                                  SUMCOL_NAME, name,
+                                  SUMCOL_TYPE, type, -1);
+               gtk_tree_path_free(dst);
+               gtk_drag_finish(context, TRUE, FALSE, time);
+       }
+
+       /* XXXX: should we call gtk_drag_finish() for other code paths? */
+}
+