2007-08-27 [colin] 2.10.0cvs179
[claws.git] / src / prefs_summary_column.c
blobd59f084bc258a64b7b17b75c777c65a536f8a86b
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include "defs.h"
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gtk/gtkmain.h>
29 #include <gtk/gtkwindow.h>
30 #include <gtk/gtkvbox.h>
31 #include <gtk/gtkhbox.h>
32 #include <gtk/gtkbutton.h>
33 #include <gdk/gdkkeysyms.h>
35 #include "prefs_gtk.h"
36 #include "prefs_common.h"
37 #include "prefs_summary_column.h"
38 #include "manage_window.h"
39 #include "summaryview.h"
40 #include "mainwindow.h"
41 #include "inc.h"
42 #include "gtkutils.h"
43 #include "utils.h"
45 enum {
46 SUMCOL_NAME,
47 SUMCOL_TYPE,
48 N_SUMCOL_COLUMNS
51 #define TARGET_INFO_SUMCOL (0xFEEDBABE)
53 static const GtkTargetEntry row_targets[] = {
54 { "PREFS_SUM_COL_MODEL_ROW", GTK_TARGET_SAME_APP, TARGET_INFO_SUMCOL }
58 static struct _SummaryColumnDialog
60 GtkWidget *window;
62 GtkWidget *stock_list_view;
63 GtkWidget *shown_list_view;
65 GtkWidget *add_btn;
66 GtkWidget *remove_btn;
67 GtkWidget *up_btn;
68 GtkWidget *down_btn;
70 GtkWidget *default_btn;
72 GtkWidget *ok_btn;
73 GtkWidget *cancel_btn;
75 gboolean finished;
76 } summary_col;
78 static const gchar *const col_name[N_SUMMARY_COLS] = {
79 N_("Mark"), /* S_COL_MARK */
80 N_("Status"), /* S_COL_STATUS */
81 N_("Attachment"), /* S_COL_MIME */
82 N_("Subject"), /* S_COL_SUBJECT */
83 N_("From"), /* S_COL_FROM */
84 N_("To"), /* S_COL_TO */
85 N_("Date"), /* S_COL_DATE */
86 N_("Size"), /* S_COL_SIZE */
87 N_("Number"), /* S_COL_NUMBER */
88 N_("Score"), /* S_COL_SCORE */
89 N_("Locked"), /* S_COL_LOCKED */
90 N_("Tags"), /* S_COL_TAGS */
93 static SummaryColumnState default_state[N_SUMMARY_COLS] = {
94 { S_COL_MARK , TRUE },
95 { S_COL_STATUS , TRUE },
96 { S_COL_MIME , TRUE },
97 { S_COL_SUBJECT, TRUE },
98 { S_COL_FROM , TRUE },
99 { S_COL_TO , FALSE },
100 { S_COL_DATE , TRUE },
101 { S_COL_SIZE , TRUE },
102 { S_COL_NUMBER , FALSE },
103 { S_COL_SCORE , FALSE },
104 { S_COL_LOCKED , FALSE },
105 { S_COL_TAGS , FALSE },
108 static void prefs_summary_column_create (void);
110 static void prefs_summary_column_set_dialog (SummaryColumnState *state);
111 static void prefs_summary_column_set_view (void);
113 /* callback functions */
114 static void prefs_summary_column_add (void);
115 static void prefs_summary_column_remove (void);
117 static void prefs_summary_column_up (void);
118 static void prefs_summary_column_down (void);
120 static void prefs_summary_column_set_to_default (void);
122 static void prefs_summary_column_ok (void);
123 static void prefs_summary_column_cancel (void);
125 static gint prefs_summary_column_delete_event (GtkWidget *widget,
126 GdkEventAny *event,
127 gpointer data);
128 static gboolean prefs_summary_column_key_pressed(GtkWidget *widget,
129 GdkEventKey *event,
130 gpointer data);
132 static GtkListStore *prefs_summary_column_create_store (void);
134 static void prefs_summary_column_insert_column (GtkListStore *store,
135 gint row,
136 const gchar *name,
137 SummaryColumnType type);
139 static SummaryColumnType prefs_summary_column_get_column (GtkWidget *list,
140 gint row);
142 static GtkWidget *prefs_summary_column_list_view_create (const gchar *name);
144 static void prefs_filtering_create_list_view_columns (GtkWidget *list_view,
145 const gchar *name);
147 static void drag_data_get (GtkTreeView *tree_view,
148 GdkDragContext *context,
149 GtkSelectionData *data,
150 guint info,
151 guint time,
152 GtkTreeModel *model);
154 static void drag_data_received (GtkTreeView *tree_view,
155 GdkDragContext *context,
156 gint x, gint y,
157 GtkSelectionData *data,
158 guint info,
159 guint time,
160 GtkTreeModel *model);
162 void prefs_summary_column_open(void)
164 inc_lock();
166 if (!summary_col.window)
167 prefs_summary_column_create();
169 manage_window_set_transient(GTK_WINDOW(summary_col.window));
170 gtk_widget_grab_focus(summary_col.ok_btn);
172 prefs_summary_column_set_dialog(NULL);
174 gtk_widget_show(summary_col.window);
176 summary_col.finished = FALSE;
177 while (summary_col.finished == FALSE)
178 gtk_main_iteration();
180 gtk_widget_hide(summary_col.window);
182 inc_unlock();
185 static void prefs_summary_column_create(void)
187 GtkWidget *window;
188 GtkWidget *vbox;
190 GtkWidget *label_hbox;
191 GtkWidget *label;
193 GtkWidget *vbox1;
195 GtkWidget *hbox1;
196 GtkWidget *clist_hbox;
197 GtkWidget *scrolledwin;
198 GtkWidget *stock_list_view;
199 GtkWidget *shown_list_view;
201 GtkWidget *btn_vbox;
202 GtkWidget *add_btn;
203 GtkWidget *remove_btn;
204 GtkWidget *up_btn;
205 GtkWidget *down_btn;
207 GtkWidget *btn_hbox;
208 GtkWidget *default_btn;
209 GtkWidget *confirm_area;
210 GtkWidget *ok_btn;
211 GtkWidget *cancel_btn;
213 debug_print("Creating summary column setting window...\n");
215 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_summary_column");
216 gtk_container_set_border_width(GTK_CONTAINER(window), 8);
217 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
218 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
219 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
220 gtk_window_set_title(GTK_WINDOW(window),
221 _("Message list columns configuration"));
222 g_signal_connect(G_OBJECT(window), "delete_event",
223 G_CALLBACK(prefs_summary_column_delete_event),
224 NULL);
225 g_signal_connect(G_OBJECT(window), "key_press_event",
226 G_CALLBACK(prefs_summary_column_key_pressed),
227 NULL);
229 vbox = gtk_vbox_new(FALSE, 6);
230 gtk_widget_show(vbox);
231 gtk_container_add(GTK_CONTAINER(window), vbox);
233 label_hbox = gtk_hbox_new(FALSE, 0);
234 gtk_widget_show(label_hbox);
235 gtk_box_pack_start(GTK_BOX(vbox), label_hbox, FALSE, FALSE, 4);
237 label = gtk_label_new
238 (_("Select columns to be displayed in the message list. You can modify\n"
239 "the order by using the Up / Down buttons or by dragging the items."));
240 gtk_widget_show(label);
241 gtk_box_pack_start(GTK_BOX(label_hbox), label, FALSE, FALSE, 4);
242 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
244 vbox1 = gtk_vbox_new(FALSE, VSPACING);
245 gtk_widget_show(vbox1);
246 gtk_box_pack_start(GTK_BOX(vbox), vbox1, TRUE, TRUE, 0);
247 gtk_container_set_border_width(GTK_CONTAINER(vbox1), 2);
249 hbox1 = gtk_hbox_new(FALSE, 8);
250 gtk_widget_show(hbox1);
251 gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, TRUE, 0);
253 clist_hbox = gtk_hbox_new(FALSE, 8);
254 gtk_widget_show(clist_hbox);
255 gtk_box_pack_start(GTK_BOX(hbox1), clist_hbox, TRUE, TRUE, 0);
257 scrolledwin = gtk_scrolled_window_new(NULL, NULL);
258 gtk_widget_set_size_request(scrolledwin, 180, 210);
259 gtk_widget_show(scrolledwin);
260 gtk_box_pack_start(GTK_BOX(clist_hbox), scrolledwin, TRUE, TRUE, 0);
261 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
262 GTK_POLICY_AUTOMATIC,
263 GTK_POLICY_AUTOMATIC);
266 stock_list_view = prefs_summary_column_list_view_create
267 (_("Hidden columns"));
268 gtk_widget_show(stock_list_view);
269 gtk_container_add(GTK_CONTAINER(scrolledwin), stock_list_view);
271 /* add/remove button */
272 btn_vbox = gtk_vbox_new(FALSE, 8);
273 gtk_widget_show(btn_vbox);
274 gtk_box_pack_start(GTK_BOX(hbox1), btn_vbox, FALSE, FALSE, 0);
276 add_btn = gtk_button_new_from_stock(GTK_STOCK_ADD);
277 gtk_widget_show(add_btn);
278 gtk_box_pack_start(GTK_BOX(btn_vbox), add_btn, FALSE, TRUE, 0);
280 g_signal_connect(G_OBJECT(add_btn), "clicked",
281 G_CALLBACK(prefs_summary_column_add), NULL);
283 clist_hbox = gtk_hbox_new(FALSE, 8);
284 gtk_widget_show(clist_hbox);
285 gtk_box_pack_start(GTK_BOX(hbox1), clist_hbox, TRUE, TRUE, 0);
287 scrolledwin = gtk_scrolled_window_new(NULL, NULL);
288 gtk_widget_set_size_request(scrolledwin, 180, 210);
289 gtk_widget_show(scrolledwin);
290 gtk_box_pack_start(GTK_BOX(clist_hbox), scrolledwin, TRUE, TRUE, 0);
291 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
292 GTK_POLICY_AUTOMATIC,
293 GTK_POLICY_AUTOMATIC);
295 shown_list_view = prefs_summary_column_list_view_create
296 (_("Displayed columns"));
297 gtk_widget_show(shown_list_view);
298 gtk_container_add(GTK_CONTAINER(scrolledwin), shown_list_view);
300 /* up/down button */
301 btn_vbox = gtk_vbox_new(FALSE, 8);
302 gtk_widget_show(btn_vbox);
303 gtk_box_pack_start(GTK_BOX(hbox1), btn_vbox, FALSE, FALSE, 0);
305 remove_btn = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
306 gtk_widget_show(remove_btn);
307 gtk_box_pack_start(GTK_BOX(btn_vbox), remove_btn, FALSE, TRUE, 0);
309 up_btn = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
310 gtk_widget_show(up_btn);
311 gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, TRUE, 0);
313 down_btn = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
314 gtk_widget_show(down_btn);
315 gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, TRUE, 0);
317 g_signal_connect(G_OBJECT(remove_btn), "clicked",
318 G_CALLBACK(prefs_summary_column_remove), NULL);
319 g_signal_connect(G_OBJECT(up_btn), "clicked",
320 G_CALLBACK(prefs_summary_column_up), NULL);
321 g_signal_connect(G_OBJECT(down_btn), "clicked",
322 G_CALLBACK(prefs_summary_column_down), NULL);
324 btn_hbox = gtk_hbox_new(FALSE, 8);
325 gtk_widget_show(btn_hbox);
326 gtk_box_pack_end(GTK_BOX(vbox), btn_hbox, FALSE, FALSE, 0);
328 btn_vbox = gtk_vbox_new(FALSE, 0);
329 gtk_widget_show(btn_vbox);
330 gtk_box_pack_start(GTK_BOX(btn_hbox), btn_vbox, FALSE, FALSE, 0);
332 default_btn = gtk_button_new_with_label(_(" Use default "));
333 gtk_widget_show(default_btn);
334 gtk_box_pack_start(GTK_BOX(btn_vbox), default_btn, TRUE, FALSE, 0);
335 g_signal_connect(G_OBJECT(default_btn), "clicked",
336 G_CALLBACK(prefs_summary_column_set_to_default),
337 NULL);
339 gtkut_stock_button_set_create(&confirm_area,
340 &cancel_btn, GTK_STOCK_CANCEL,
341 &ok_btn, GTK_STOCK_OK,
342 NULL, NULL);
343 gtk_widget_show(confirm_area);
344 gtk_box_pack_end(GTK_BOX(btn_hbox), confirm_area, FALSE, FALSE, 0);
345 gtk_widget_grab_default(ok_btn);
347 g_signal_connect(G_OBJECT(ok_btn), "clicked",
348 G_CALLBACK(prefs_summary_column_ok), NULL);
349 g_signal_connect(G_OBJECT(cancel_btn), "clicked",
350 G_CALLBACK(prefs_summary_column_cancel), NULL);
353 summary_col.window = window;
354 summary_col.add_btn = add_btn;
355 summary_col.remove_btn = remove_btn;
356 summary_col.up_btn = up_btn;
357 summary_col.down_btn = down_btn;
358 summary_col.ok_btn = ok_btn;
359 summary_col.cancel_btn = cancel_btn;
360 summary_col.stock_list_view = stock_list_view;
361 summary_col.shown_list_view = shown_list_view;
364 SummaryColumnState *prefs_summary_column_get_config(void)
366 static SummaryColumnState state[N_SUMMARY_COLS];
367 SummaryColumnType type;
368 gint pos;
370 for (pos = 0; pos < N_SUMMARY_COLS; pos++)
371 state[pos].type = -1;
373 for (type = 0; type < N_SUMMARY_COLS; type++) {
374 pos = prefs_common.summary_col_pos[type];
375 if (pos < 0 || pos >= N_SUMMARY_COLS ||
376 state[pos].type != -1) {
377 g_warning("Wrong column position\n");
378 prefs_summary_column_set_config(default_state);
379 return default_state;
382 state[pos].type = type;
383 state[pos].visible = prefs_common.summary_col_visible[type];
386 return state;
389 void prefs_summary_column_set_config(SummaryColumnState *state)
391 SummaryColumnType type;
392 gint pos;
394 for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
395 type = state[pos].type;
396 prefs_common.summary_col_visible[type] = state[pos].visible;
397 prefs_common.summary_col_pos[type] = pos;
401 static void prefs_summary_column_set_dialog(SummaryColumnState *state)
403 GtkListStore *stock_store, *shown_store;
404 gint pos;
405 SummaryColumnType type;
406 gchar *name;
408 stock_store = GTK_LIST_STORE(gtk_tree_view_get_model
409 (GTK_TREE_VIEW(summary_col.stock_list_view)));
410 shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
411 (GTK_TREE_VIEW(summary_col.shown_list_view)));
413 gtk_list_store_clear(stock_store);
414 gtk_list_store_clear(shown_store);
416 if (!state)
417 state = prefs_summary_column_get_config();
419 for (pos = 0; pos < N_SUMMARY_COLS; pos++) {
420 type = state[pos].type;
421 name = gettext(col_name[type]);
423 if (state[pos].visible)
424 prefs_summary_column_insert_column(shown_store,
425 -1, name,
426 type);
427 else
428 prefs_summary_column_insert_column(stock_store,
429 -1, name,
430 type);
434 static void prefs_summary_column_set_view(void)
436 gint stock_n_rows, shown_n_rows;
437 SummaryColumnState state[N_SUMMARY_COLS];
438 SummaryColumnType type;
439 gint row, pos = 0;
441 stock_n_rows = gtk_tree_model_iter_n_children
442 (gtk_tree_view_get_model(GTK_TREE_VIEW
443 (summary_col.stock_list_view)), NULL);
444 shown_n_rows = gtk_tree_model_iter_n_children
445 (gtk_tree_view_get_model(GTK_TREE_VIEW
446 (summary_col.shown_list_view)), NULL);
448 g_return_if_fail
449 (stock_n_rows + shown_n_rows == N_SUMMARY_COLS);
451 for (row = 0; row < stock_n_rows; row++) {
452 type = prefs_summary_column_get_column
453 (summary_col.stock_list_view, row);
454 state[row].type = type;
455 state[row].visible = FALSE;
458 pos = row;
459 for (row = 0; row < shown_n_rows; row++) {
460 type = prefs_summary_column_get_column
461 (summary_col.shown_list_view, row);
462 state[pos + row].type = type;
463 state[pos + row].visible = TRUE;
466 prefs_summary_column_set_config(state);
467 main_window_set_summary_column();
470 static void prefs_summary_column_add(void)
472 GtkListStore *stock_store, *shown_store;
473 GtkTreeIter stock_sel, shown_sel, shown_add;
474 gboolean shown_sel_valid;
475 gchar *name;
476 SummaryColumnType type;
478 stock_store = GTK_LIST_STORE(gtk_tree_view_get_model
479 (GTK_TREE_VIEW(summary_col.stock_list_view)));
480 shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
481 (GTK_TREE_VIEW(summary_col.shown_list_view)));
483 if (!gtk_tree_selection_get_selected
484 (gtk_tree_view_get_selection
485 (GTK_TREE_VIEW(summary_col.stock_list_view)),
486 NULL,
487 &stock_sel))
488 return;
490 shown_sel_valid = gtk_tree_selection_get_selected
491 (gtk_tree_view_get_selection
492 (GTK_TREE_VIEW(summary_col.shown_list_view)),
493 NULL,
494 &shown_sel);
496 gtk_tree_model_get(GTK_TREE_MODEL(stock_store), &stock_sel,
497 SUMCOL_TYPE, &type,
498 -1);
500 gtk_list_store_remove(stock_store, &stock_sel);
502 gtk_list_store_insert_after(shown_store, &shown_add,
503 shown_sel_valid ? &shown_sel : NULL);
505 name = gettext(col_name[type]);
507 gtk_list_store_set(shown_store, &shown_add,
508 SUMCOL_NAME, name,
509 SUMCOL_TYPE, type,
510 -1);
512 gtk_tree_selection_select_iter(gtk_tree_view_get_selection
513 (GTK_TREE_VIEW(summary_col.shown_list_view)),
514 &shown_add);
517 static void prefs_summary_column_remove(void)
519 GtkListStore *stock_store, *shown_store;
520 GtkTreeIter shown_sel, stock_sel, stock_add;
521 gboolean stock_sel_valid;
522 gchar *name;
523 SummaryColumnType type;
525 stock_store = GTK_LIST_STORE(gtk_tree_view_get_model
526 (GTK_TREE_VIEW(summary_col.stock_list_view)));
527 shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
528 (GTK_TREE_VIEW(summary_col.shown_list_view)));
530 if (!gtk_tree_selection_get_selected
531 (gtk_tree_view_get_selection
532 (GTK_TREE_VIEW(summary_col.shown_list_view)),
533 NULL,
534 &shown_sel))
535 return;
537 stock_sel_valid = gtk_tree_selection_get_selected
538 (gtk_tree_view_get_selection
539 (GTK_TREE_VIEW(summary_col.stock_list_view)),
540 NULL,
541 &stock_sel);
543 gtk_tree_model_get(GTK_TREE_MODEL(shown_store), &shown_sel,
544 SUMCOL_TYPE, &type,
545 -1);
547 gtk_list_store_remove(shown_store, &shown_sel);
549 gtk_list_store_insert_after(stock_store, &stock_add,
550 stock_sel_valid ? &stock_sel : NULL);
552 name = gettext(col_name[type]);
554 gtk_list_store_set(stock_store, &stock_add,
555 SUMCOL_NAME, name,
556 SUMCOL_TYPE, type,
557 -1);
559 gtk_tree_selection_select_iter(gtk_tree_view_get_selection
560 (GTK_TREE_VIEW(summary_col.stock_list_view)),
561 &stock_add);
564 static void prefs_summary_column_up(void)
566 GtkTreePath *prev, *sel;
567 GtkTreeIter isel;
568 GtkListStore *shown_store;
569 GtkTreeIter iprev;
571 if (!gtk_tree_selection_get_selected
572 (gtk_tree_view_get_selection
573 (GTK_TREE_VIEW(summary_col.shown_list_view)),
574 NULL,
575 &isel))
576 return;
578 shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
579 (GTK_TREE_VIEW(summary_col.shown_list_view)));
581 sel = gtk_tree_model_get_path(GTK_TREE_MODEL(shown_store),
582 &isel);
583 if (!sel)
584 return;
586 prev = gtk_tree_path_copy(sel);
587 if (!gtk_tree_path_prev(prev)) {
588 gtk_tree_path_free(prev);
589 gtk_tree_path_free(sel);
590 return;
593 gtk_tree_model_get_iter(GTK_TREE_MODEL(shown_store),
594 &iprev, prev);
595 gtk_tree_path_free(sel);
596 gtk_tree_path_free(prev);
598 gtk_list_store_swap(shown_store, &iprev, &isel);
601 static void prefs_summary_column_down(void)
603 GtkListStore *shown_store;
604 GtkTreeIter next, sel;
606 if (!gtk_tree_selection_get_selected
607 (gtk_tree_view_get_selection
608 (GTK_TREE_VIEW(summary_col.shown_list_view)),
609 NULL,
610 &sel))
611 return;
613 shown_store = GTK_LIST_STORE(gtk_tree_view_get_model
614 (GTK_TREE_VIEW(summary_col.shown_list_view)));
616 next = sel;
617 if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(shown_store), &next))
618 return;
620 gtk_list_store_swap(shown_store, &next, &sel);
623 static void prefs_summary_column_set_to_default(void)
625 prefs_summary_column_set_dialog(default_state);
628 static void prefs_summary_column_ok(void)
630 if (!summary_col.finished) {
631 summary_col.finished = TRUE;
632 prefs_summary_column_set_view();
636 static void prefs_summary_column_cancel(void)
638 summary_col.finished = TRUE;
641 static gint prefs_summary_column_delete_event(GtkWidget *widget,
642 GdkEventAny *event,
643 gpointer data)
645 summary_col.finished = TRUE;
646 return TRUE;
649 static gboolean prefs_summary_column_key_pressed(GtkWidget *widget,
650 GdkEventKey *event,
651 gpointer data)
653 if (event && event->keyval == GDK_Escape)
654 summary_col.finished = TRUE;
655 return FALSE;
658 static GtkListStore *prefs_summary_column_create_store(void)
660 return gtk_list_store_new(N_SUMCOL_COLUMNS,
661 G_TYPE_STRING,
662 G_TYPE_INT,
663 -1);
666 static void prefs_summary_column_insert_column(GtkListStore *store,
667 gint row,
668 const gchar *name,
669 SummaryColumnType type)
671 GtkTreeIter iter;
673 if (row >= 0) {
674 if (!gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store),
675 &iter, NULL, row))
676 row = -1;
678 if (row < 0) {
679 /* add new */
680 gtk_list_store_append(store, &iter);
681 gtk_list_store_set(store, &iter,
682 SUMCOL_NAME, name,
683 SUMCOL_TYPE, type,
684 -1);
685 return;
686 } else {
687 /* change existing */
688 gtk_list_store_set(store, &iter,
689 SUMCOL_NAME, name,
690 SUMCOL_TYPE, type,
691 -1);
696 *\brief Return the columnn type for a row
698 static SummaryColumnType prefs_summary_column_get_column(GtkWidget *list, gint row)
700 GtkTreeView *list_view = GTK_TREE_VIEW(list);
701 GtkTreeModel *model = gtk_tree_view_get_model(list_view);
702 GtkTreeIter iter;
703 SummaryColumnType result;
705 if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row))
706 return -1;
708 gtk_tree_model_get(model, &iter,
709 SUMCOL_TYPE, &result,
710 -1);
712 return result;
715 static GtkWidget *prefs_summary_column_list_view_create(const gchar *name)
717 GtkWidget *list_view;
718 GtkTreeSelection *selector;
719 GtkTreeModel *model;
721 model = GTK_TREE_MODEL(prefs_summary_column_create_store());
722 list_view = gtk_tree_view_new_with_model(model);
723 g_object_unref(G_OBJECT(model));
725 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list_view),
726 prefs_common.use_stripes_everywhere);
728 selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view));
729 gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
731 prefs_filtering_create_list_view_columns(GTK_WIDGET(list_view), name);
733 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(list_view),
734 GDK_BUTTON1_MASK,
735 row_targets,
736 G_N_ELEMENTS(row_targets),
737 GDK_ACTION_MOVE);
739 gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(list_view),
740 row_targets,
741 G_N_ELEMENTS(row_targets),
742 GDK_ACTION_MOVE);
744 g_signal_connect(G_OBJECT(list_view), "drag_data_get",
745 G_CALLBACK(drag_data_get),
746 model);
748 g_signal_connect(G_OBJECT(list_view), "drag_data_received",
749 G_CALLBACK(drag_data_received),
750 model);
752 return list_view;
755 static void prefs_filtering_create_list_view_columns(GtkWidget *list_view,
756 const gchar *name)
758 GtkTreeViewColumn *column;
759 GtkCellRenderer *renderer;
761 renderer = gtk_cell_renderer_text_new();
762 column = gtk_tree_view_column_new_with_attributes
763 (name, renderer, "text", SUMCOL_NAME, NULL);
764 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
767 static void drag_data_get(GtkTreeView *tree_view, GdkDragContext *context,
768 GtkSelectionData *data, guint info,
769 guint time, GtkTreeModel *model)
771 GtkTreeIter iter;
772 SummaryColumnType type;
773 GtkTreeModel *source_model;
775 if (info != TARGET_INFO_SUMCOL)
776 return;
778 if (!gtk_tree_selection_get_selected
779 (gtk_tree_view_get_selection(tree_view),
780 &source_model, &iter))
781 return;
783 gtk_tree_model_get(source_model, &iter,
784 SUMCOL_TYPE, &type,
785 -1);
787 /* send the type */
788 gtk_selection_data_set(data, data->target, 8, (gchar *) &type, sizeof type);
791 static void drag_data_received(GtkTreeView *tree_view, GdkDragContext *context,
792 gint x, gint y, GtkSelectionData *data,
793 guint info, guint time, GtkTreeModel *model)
795 GtkWidget *source;
796 GtkTreePath *dst = NULL, *sel = NULL;
797 GtkTreeIter isel, idst;
798 GtkTreeViewDropPosition pos;
799 SummaryColumnType type;
800 GtkTreeModel *sel_model;
801 gchar *name;
803 source = gtk_drag_get_source_widget(context);
805 if (source == GTK_WIDGET(tree_view)) {
808 * Same widget: re-order
811 gtk_tree_selection_get_selected(gtk_tree_view_get_selection(tree_view),
812 NULL, &isel);
813 sel = gtk_tree_model_get_path(model, &isel);
814 gtk_tree_view_get_dest_row_at_pos(tree_view, x, y,
815 &dst, &pos);
817 /* NOTE: dst is invalid if selection beyond last row, in that
818 * case move beyond last one (XXX_move_before(..., NULL)) */
820 if (dst)
821 gtk_tree_model_get_iter(model, &idst, dst);
822 else
823 gtk_list_store_move_before(GTK_LIST_STORE(model),
824 &isel,
825 NULL);
827 /* we do not drag if no valid dst and sel, and when
828 * dst and sel are the same (moving after or before
829 * itself doesn't change order...) */
830 if ((dst && sel) && gtk_tree_path_compare(sel, dst) != 0) {
831 if (pos == GTK_TREE_VIEW_DROP_BEFORE
832 || pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
833 gtk_list_store_move_before(GTK_LIST_STORE(model),
834 &isel,
835 &idst);
836 else
837 gtk_list_store_move_after(GTK_LIST_STORE(model),
838 &isel,
839 &idst);
842 gtk_tree_path_free(dst);
843 gtk_tree_path_free(sel);
844 gtk_drag_finish(context, TRUE, FALSE, time);
846 } else if (source == summary_col.stock_list_view
847 || source == summary_col.shown_list_view) {
850 * Other widget: change and update
854 /* get source information and remove */
855 gtk_tree_selection_get_selected(gtk_tree_view_get_selection(
856 GTK_TREE_VIEW(source)),
857 &sel_model, &isel);
858 type = *((gint *) data->data);
859 name = gettext(col_name[type]);
860 gtk_list_store_remove(GTK_LIST_STORE(sel_model), &isel);
862 /* get insertion position */
863 gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &dst, &pos);
865 /* NOTE: dst is invalid if insertion point beyond last row,
866 * just append to list in that case (XXX_store_append()) */
868 if (dst) {
869 gtk_tree_model_get_iter(model, &idst, dst);
871 if (pos == GTK_TREE_VIEW_DROP_BEFORE
872 || pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)
873 gtk_list_store_insert_before(GTK_LIST_STORE(model),
874 &isel,
875 &idst);
876 else
877 gtk_list_store_insert_after(GTK_LIST_STORE(model),
878 &isel,
879 &idst);
880 } else
881 gtk_list_store_append(GTK_LIST_STORE(model),
882 &isel);
884 gtk_list_store_set(GTK_LIST_STORE(model), &isel,
885 SUMCOL_NAME, name,
886 SUMCOL_TYPE, type, -1);
887 gtk_tree_path_free(dst);
888 gtk_drag_finish(context, TRUE, FALSE, time);
891 /* XXXX: should we call gtk_drag_finish() for other code paths? */