prefs_summary_open.c (19846B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2024 the Claws Mail team and Hiroyuki Yamamoto 4 * 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. 9 * 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. 14 * 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/>. 17 */ 18 19 #include "defs.h" 20 21 #include <glib.h> 22 #include <glib/gi18n.h> 23 #include <gtk/gtk.h> 24 #include <gdk/gdkkeysyms.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <errno.h> 29 30 #include "prefs_gtk.h" 31 #include "prefs_summary_open.h" 32 #include "prefs_common.h" 33 #include "manage_window.h" 34 #include "alertpanel.h" 35 #include "displayheader.h" 36 #include "utils.h" 37 #include "gtkutils.h" 38 39 enum { 40 PREFS_SUMMARY_OPEN_HEADER, 41 PREFS_SUMMARY_OPEN_DATA, 42 N_PREFS_SUMMARY_OPEN_COLUMNS 43 }; 44 45 static struct SummaryOpen { 46 GtkWidget *window; 47 48 GtkWidget *ok_btn; 49 GtkWidget *cancel_btn; 50 51 GtkWidget *possible_actions_list_view; 52 GtkWidget *actions_list_view; 53 } summaryopen; 54 55 /* widget creating functions */ 56 static void prefs_summary_open_create (void); 57 58 static void prefs_summary_open_set_dialog (void); 59 static void prefs_summary_open_set_list (void); 60 61 /* callback functions */ 62 static void prefs_summary_open_register_cb (GtkButton *btn, 63 gpointer hidden_data); 64 static void prefs_summary_open_delete_cb (GtkButton *btn, 65 gpointer list_view_data); 66 static void prefs_summary_open_up (void); 67 static void prefs_summary_open_down (void); 68 69 static void prefs_summary_open_ok (void); 70 static void prefs_summary_open_cancel (void); 71 static gint prefs_summary_open_deleted (GtkWidget *widget, 72 GdkEventAny *event, 73 gpointer data); 74 75 76 static GtkListStore *prefs_summary_open_create_store (void); 77 static void prefs_summary_open_insert_action (GtkListStore *store, 78 gchar *name, 79 gint act); 80 static GtkWidget *prefs_summary_open_list_view_create (const gchar *name); 81 static void prefs_summary_open_create_list_view_columns (GtkWidget *list_view, 82 const gchar *name); 83 static void actions_list_model_row_changed (GtkTreeModel *model, 84 GtkTreePath *path, 85 GtkTreeIter *iter, 86 GtkTreeView *list_view); 87 88 static void drag_begin (GtkTreeView *list_view, 89 GdkDragContext *context, 90 gpointer data); 91 92 static void drag_end (GtkTreeView *list_view, 93 GdkDragContext *context, 94 gpointer data); 95 96 static EntryAction saved_summary_select_prio[SUMMARY_OPEN_ACTIONS-1]; 97 98 static gchar *action_name[SUMMARY_OPEN_ACTIONS] = 99 { ("UNSET (!)"), 100 N_("oldest marked email"), 101 N_("oldest new email"), 102 N_("oldest unread email"), 103 N_("last opened email"), 104 N_("newest email in the list"), 105 N_("none"), 106 N_("oldest email in the list"), 107 N_("newest marked email"), 108 N_("newest new email"), 109 N_("newest unread email") 110 }; 111 112 void prefs_summary_open_open(void) 113 { 114 int i; 115 if (!summaryopen.window) { 116 prefs_summary_open_create(); 117 } 118 119 manage_window_set_transient(GTK_WINDOW(summaryopen.window)); 120 gtk_widget_grab_focus(summaryopen.ok_btn); 121 122 prefs_summary_open_set_dialog(); 123 124 for (i = 0; i < SUMMARY_OPEN_ACTIONS-1; i++) 125 saved_summary_select_prio[i] = prefs_common.summary_select_prio[i]; 126 127 gtk_widget_show(summaryopen.window); 128 gtk_window_set_modal(GTK_WINDOW(summaryopen.window), TRUE); 129 } 130 131 static void prefs_summary_open_create(void) 132 { 133 GtkWidget *window; 134 GtkWidget *vbox; 135 GtkWidget *btn_hbox; 136 GtkWidget *ok_btn; 137 GtkWidget *cancel_btn; 138 GtkWidget *confirm_area; 139 140 GtkWidget *vbox1; 141 142 GtkWidget *hbox1; 143 144 GtkWidget *btn_vbox; 145 GtkWidget *reg_btn; 146 GtkWidget *del_btn; 147 GtkWidget *up_btn; 148 GtkWidget *down_btn; 149 150 GtkWidget *list_view_hbox; 151 GtkWidget *list_view_hbox1; 152 GtkWidget *list_view_hbox2; 153 GtkWidget *list_view_scrolledwin; 154 GtkWidget *possible_actions_list_view; 155 GtkWidget *actions_list_view; 156 157 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_summary_open"); 158 gtk_container_set_border_width (GTK_CONTAINER (window), 8); 159 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER); 160 gtk_window_set_resizable(GTK_WINDOW (window), TRUE); 161 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); 162 gtk_widget_set_size_request (GTK_WIDGET (window), 610, 310); 163 164 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); 165 gtk_widget_show (vbox); 166 gtk_container_add (GTK_CONTAINER (window), vbox); 167 168 btn_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); 169 gtk_widget_show (btn_hbox); 170 gtk_box_pack_end (GTK_BOX (vbox), btn_hbox, FALSE, FALSE, 0); 171 172 gtkut_stock_button_set_create(&confirm_area, &cancel_btn, NULL, _("_Cancel"), 173 &ok_btn, NULL, _("_OK"), NULL, NULL, NULL); 174 gtk_widget_show (confirm_area); 175 gtk_box_pack_end (GTK_BOX(btn_hbox), confirm_area, FALSE, FALSE, 0); 176 gtk_widget_grab_default (ok_btn); 177 178 gtk_window_set_title (GTK_WINDOW(window), 179 _("Message selection when entering a folder")); 180 MANAGE_WINDOW_SIGNALS_CONNECT(window); 181 g_signal_connect (G_OBJECT(window), "delete_event", 182 G_CALLBACK(prefs_summary_open_deleted), 183 NULL); 184 g_signal_connect (G_OBJECT(ok_btn), "clicked", 185 G_CALLBACK(prefs_summary_open_ok), 186 NULL); 187 g_signal_connect (G_OBJECT(cancel_btn), "clicked", 188 G_CALLBACK(prefs_summary_open_cancel), 189 NULL); 190 191 vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, VSPACING); 192 gtk_widget_show (vbox1); 193 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0); 194 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2); 195 196 hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); 197 gtk_widget_show (hbox1); 198 gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, TRUE, 0); 199 200 /* display headers list */ 201 202 list_view_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10); 203 gtk_widget_show (list_view_hbox); 204 gtk_box_pack_start (GTK_BOX (vbox1), list_view_hbox, TRUE, TRUE, 0); 205 206 list_view_hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); 207 gtk_widget_show (list_view_hbox1); 208 gtk_box_pack_start (GTK_BOX (list_view_hbox), list_view_hbox1, TRUE, TRUE, 0); 209 210 list_view_scrolledwin = gtk_scrolled_window_new (NULL, NULL); 211 gtk_widget_show (list_view_scrolledwin); 212 gtk_box_pack_start (GTK_BOX (list_view_hbox1), list_view_scrolledwin, 213 TRUE, TRUE, 0); 214 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_view_scrolledwin), 215 GTK_POLICY_AUTOMATIC, 216 GTK_POLICY_AUTOMATIC); 217 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(list_view_scrolledwin), 218 GTK_SHADOW_IN); 219 220 possible_actions_list_view = prefs_summary_open_list_view_create 221 (_("Available selections")); 222 gtk_widget_show (possible_actions_list_view); 223 gtk_container_add(GTK_CONTAINER(list_view_scrolledwin), possible_actions_list_view); 224 225 btn_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); 226 gtk_widget_show (btn_vbox); 227 gtk_box_pack_start (GTK_BOX (list_view_hbox1), btn_vbox, FALSE, FALSE, 0); 228 229 reg_btn = gtkut_stock_button("list-add", _("_Add")); 230 gtk_widget_show (reg_btn); 231 gtk_box_pack_start (GTK_BOX (btn_vbox), reg_btn, FALSE, TRUE, 0); 232 g_signal_connect (G_OBJECT (reg_btn), "clicked", 233 G_CALLBACK (prefs_summary_open_register_cb), 234 possible_actions_list_view); 235 del_btn = gtkut_stock_button("list-remove", _("_Remove")); 236 gtk_widget_show (del_btn); 237 gtk_box_pack_start (GTK_BOX (btn_vbox), del_btn, FALSE, TRUE, 0); 238 239 /* actions list */ 240 241 list_view_hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); 242 gtk_widget_show (list_view_hbox2); 243 gtk_box_pack_start (GTK_BOX (list_view_hbox), list_view_hbox2, TRUE, TRUE, 0); 244 245 list_view_scrolledwin = gtk_scrolled_window_new (NULL, NULL); 246 gtk_widget_show (list_view_scrolledwin); 247 gtk_box_pack_start (GTK_BOX (list_view_hbox2), list_view_scrolledwin, 248 TRUE, TRUE, 0); 249 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_view_scrolledwin), 250 GTK_POLICY_AUTOMATIC, 251 GTK_POLICY_AUTOMATIC); 252 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(list_view_scrolledwin), 253 GTK_SHADOW_IN); 254 255 actions_list_view = prefs_summary_open_list_view_create 256 (_("Current selections")); 257 g_signal_connect (G_OBJECT (del_btn), "clicked", 258 G_CALLBACK (prefs_summary_open_delete_cb), 259 actions_list_view); 260 gtk_widget_show (actions_list_view); 261 gtk_container_add (GTK_CONTAINER (list_view_scrolledwin), 262 actions_list_view); 263 264 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(actions_list_view), TRUE); 265 g_signal_connect(G_OBJECT(actions_list_view), "drag_begin", 266 G_CALLBACK(drag_begin), 267 actions_list_view); 268 269 g_signal_connect(G_OBJECT(actions_list_view), "drag_end", 270 G_CALLBACK(drag_end), 271 actions_list_view); 272 273 btn_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); 274 gtk_widget_show (btn_vbox); 275 gtk_box_pack_start (GTK_BOX (list_view_hbox2), btn_vbox, FALSE, FALSE, 0); 276 277 up_btn = gtkut_stock_button("go-up", _("_Up")); 278 gtk_widget_show (up_btn); 279 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0); 280 g_signal_connect (G_OBJECT (up_btn), "clicked", 281 G_CALLBACK (prefs_summary_open_up), NULL); 282 283 down_btn = gtkut_stock_button("go-down", _("_Down")); 284 gtk_widget_show (down_btn); 285 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0); 286 g_signal_connect (G_OBJECT (down_btn), "clicked", 287 G_CALLBACK (prefs_summary_open_down), NULL); 288 289 gtk_widget_show_all(window); 290 291 summaryopen.window = window; 292 summaryopen.ok_btn = ok_btn; 293 summaryopen.cancel_btn = cancel_btn; 294 295 summaryopen.possible_actions_list_view = possible_actions_list_view; 296 summaryopen.actions_list_view = actions_list_view; 297 } 298 299 /* do it SUMMARY_OPEN_ACTIONS-1 times */ 300 #define SET_PRIO(p_one,p_two,p_three,p_four) { \ 301 prefs_common.summary_select_prio[0] = p_one; \ 302 prefs_common.summary_select_prio[1] = p_two; \ 303 prefs_common.summary_select_prio[2] = p_three; \ 304 prefs_common.summary_select_prio[3] = p_four; \ 305 prefs_common.summary_select_prio[4] = ACTION_UNSET; \ 306 prefs_common.summary_select_prio[5] = ACTION_UNSET; \ 307 prefs_common.summary_select_prio[6] = ACTION_UNSET; \ 308 prefs_common.summary_select_prio[7] = ACTION_UNSET; \ 309 prefs_common.summary_select_prio[8] = ACTION_UNSET; \ 310 prefs_common.summary_select_prio[9] = ACTION_UNSET; \ 311 } 312 313 void prefs_summary_open_set_defaults(void) 314 { 315 switch (prefs_common.select_on_entry) { 316 case SELECTONENTRY_MNU: 317 SET_PRIO(ACTION_OLDEST_MARKED, ACTION_OLDEST_NEW, ACTION_OLDEST_UNREAD, ACTION_NEWEST_LIST); break; 318 case SELECTONENTRY_MUN: 319 SET_PRIO(ACTION_OLDEST_MARKED, ACTION_OLDEST_UNREAD, ACTION_OLDEST_NEW, ACTION_NEWEST_LIST); break; 320 case SELECTONENTRY_NMU: 321 SET_PRIO(ACTION_OLDEST_NEW, ACTION_OLDEST_MARKED, ACTION_OLDEST_UNREAD, ACTION_NEWEST_LIST); break; 322 case SELECTONENTRY_NUM: 323 SET_PRIO(ACTION_OLDEST_NEW, ACTION_OLDEST_UNREAD, ACTION_OLDEST_MARKED, ACTION_NEWEST_LIST); break; 324 case SELECTONENTRY_UNM: 325 SET_PRIO(ACTION_OLDEST_UNREAD, ACTION_OLDEST_NEW, ACTION_OLDEST_MARKED, ACTION_NEWEST_LIST); break; 326 case SELECTONENTRY_UMN: 327 SET_PRIO(ACTION_OLDEST_UNREAD, ACTION_OLDEST_MARKED, ACTION_OLDEST_NEW, ACTION_NEWEST_LIST); break; 328 case SELECTONENTRY_LAST: 329 SET_PRIO(ACTION_LAST_OPENED, ACTION_NEWEST_LIST, ACTION_UNSET, ACTION_UNSET); break; 330 case SELECTONENTRY_NOTHING: 331 SET_PRIO(ACTION_NEWEST_LIST, ACTION_UNSET, ACTION_UNSET, ACTION_UNSET); break; 332 default: 333 break; 334 } 335 } 336 static void prefs_summary_open_set_dialog(void) 337 { 338 GtkTreeView *possible_list_view = GTK_TREE_VIEW(summaryopen.possible_actions_list_view); 339 GtkTreeView *actions_list_view = GTK_TREE_VIEW(summaryopen.actions_list_view); 340 GtkTreeModel *model_poss, *model_act; 341 int i; 342 gboolean set = FALSE; 343 gboolean used[SUMMARY_OPEN_ACTIONS-1] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; 344 345 model_poss = gtk_tree_view_get_model(possible_list_view); 346 model_act = gtk_tree_view_get_model(actions_list_view); 347 348 gtk_list_store_clear(GTK_LIST_STORE(model_poss)); 349 gtk_list_store_clear(GTK_LIST_STORE(model_act)); 350 351 fill: 352 for (i = 0; i < SUMMARY_OPEN_ACTIONS-1; i++) { 353 EntryAction act = prefs_common.summary_select_prio[i]; 354 355 if (act == ACTION_UNSET) 356 continue; 357 358 set = TRUE; 359 used[act-1] = TRUE; 360 prefs_summary_open_insert_action(GTK_LIST_STORE 361 (model_act), action_name[act], act); 362 } 363 if (!set) { 364 /* backward compat */ 365 prefs_summary_open_set_defaults(); 366 goto fill; 367 } 368 369 for (i = 1; i < SUMMARY_OPEN_ACTIONS; i++) { 370 if (!used[i-1]) { 371 prefs_summary_open_insert_action(GTK_LIST_STORE 372 (model_poss), action_name[i], i); 373 } 374 } 375 } 376 377 static void prefs_summary_open_set_list(void) 378 { 379 gint row = 0; 380 gpointer data; 381 GtkTreeModel *model; 382 GtkTreeIter iter; 383 384 model = gtk_tree_view_get_model(GTK_TREE_VIEW(summaryopen.actions_list_view)); 385 while (gtk_tree_model_iter_nth_child(model, &iter, NULL, row)) { 386 gtk_tree_model_get(model, &iter, PREFS_SUMMARY_OPEN_DATA, &data, -1); 387 prefs_common.summary_select_prio[row] = GPOINTER_TO_INT(data); 388 row++; 389 } 390 for (; row < SUMMARY_OPEN_ACTIONS-1; row++) { 391 prefs_common.summary_select_prio[row] = ACTION_UNSET; 392 } 393 } 394 395 static void prefs_summary_open_delete_cb(GtkButton *btn, gpointer list_view_data) 396 { 397 GtkTreeView *list_view = GTK_TREE_VIEW(list_view_data); 398 gpointer data; 399 GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(list_view)); 400 GtkTreeSelection *selection = gtk_tree_view_get_selection(list_view); 401 GtkTreeIter iter; 402 GtkTreeView *possible_list_view = GTK_TREE_VIEW(summaryopen.possible_actions_list_view); 403 GtkTreeModel *model, *model_poss; 404 gint i; 405 406 model = gtk_tree_view_get_model(list_view); 407 model_poss = gtk_tree_view_get_model(possible_list_view); 408 409 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) 410 return; 411 412 gtk_tree_model_get(model, &iter, PREFS_SUMMARY_OPEN_DATA, &data, -1); 413 if (!data) 414 return; 415 416 gtk_list_store_remove(store, &iter); 417 418 i = GPOINTER_TO_INT(data); 419 prefs_summary_open_insert_action(GTK_LIST_STORE 420 (model_poss), action_name[i], i); 421 422 prefs_summary_open_set_list(); 423 } 424 425 static void prefs_summary_open_register_cb(GtkButton *btn, gpointer list_view_data) 426 { 427 GtkTreeView *possible_list_view = GTK_TREE_VIEW(list_view_data); 428 GtkTreeView *list_view = GTK_TREE_VIEW(summaryopen.actions_list_view); 429 gpointer data; 430 GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(possible_list_view)); 431 GtkTreeSelection *selection = gtk_tree_view_get_selection(possible_list_view); 432 GtkTreeIter iter; 433 GtkTreeModel *model, *model_poss; 434 gint i; 435 436 model = gtk_tree_view_get_model(list_view); 437 model_poss = gtk_tree_view_get_model(possible_list_view); 438 439 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) 440 return; 441 442 gtk_tree_model_get(model_poss, &iter, PREFS_SUMMARY_OPEN_DATA, &data, -1); 443 if (!data) 444 return; 445 446 gtk_list_store_remove(store, &iter); 447 448 i = GPOINTER_TO_INT(data); 449 prefs_summary_open_insert_action(GTK_LIST_STORE 450 (model), action_name[i], i); 451 452 prefs_summary_open_set_list(); 453 } 454 455 static void prefs_summary_open_up(void) 456 { 457 GtkTreePath *prev, *sel, *try; 458 GtkTreeIter isel; 459 GtkListStore *store = NULL; 460 GtkTreeModel *model = NULL; 461 GtkTreeIter iprev; 462 463 if (!gtk_tree_selection_get_selected 464 (gtk_tree_view_get_selection 465 (GTK_TREE_VIEW(summaryopen.actions_list_view)), 466 &model, 467 &isel)) 468 return; 469 store = (GtkListStore *)model; 470 sel = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &isel); 471 if (!sel) 472 return; 473 474 /* no move if we're at row 0... */ 475 try = gtk_tree_path_copy(sel); 476 if (!gtk_tree_path_prev(try)) { 477 gtk_tree_path_free(try); 478 gtk_tree_path_free(sel); 479 return; 480 } 481 482 prev = try; 483 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), 484 &iprev, prev); 485 gtk_list_store_swap(store, &iprev, &isel); 486 487 gtk_tree_path_free(sel); 488 gtk_tree_path_free(prev); 489 prefs_summary_open_set_list(); 490 } 491 492 static void prefs_summary_open_down(void) 493 { 494 GtkListStore *store = NULL; 495 GtkTreeModel *model = NULL; 496 GtkTreeIter next, sel; 497 GtkTreePath *try; 498 499 if (!gtk_tree_selection_get_selected 500 (gtk_tree_view_get_selection 501 (GTK_TREE_VIEW(summaryopen.actions_list_view)), 502 &model, 503 &sel)) 504 return; 505 store = (GtkListStore *)model; 506 try = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &sel); 507 if (!try) 508 return; 509 510 next = sel; 511 if (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &next)) 512 gtk_list_store_swap(store, &next, &sel); 513 514 gtk_tree_path_free(try); 515 prefs_summary_open_set_list(); 516 } 517 518 static void prefs_summary_open_ok(void) 519 { 520 int i; 521 522 /* force an empty list to be at least ACTION_NONE */ 523 if (prefs_common.summary_select_prio[0] == ACTION_UNSET) 524 prefs_common.summary_select_prio[0] = ACTION_NOTHING; 525 526 for (i = 0; i < SUMMARY_OPEN_ACTIONS-1; i++) 527 saved_summary_select_prio[i] = prefs_common.summary_select_prio[i]; 528 529 gtk_widget_hide(summaryopen.window); 530 gtk_window_set_modal(GTK_WINDOW(summaryopen.window), FALSE); 531 } 532 533 static void prefs_summary_open_cancel(void) 534 { 535 int i; 536 for (i = 0; i < SUMMARY_OPEN_ACTIONS-1; i++) 537 prefs_common.summary_select_prio[i] = saved_summary_select_prio[i]; 538 539 gtk_widget_hide(summaryopen.window); 540 } 541 542 static gint prefs_summary_open_deleted(GtkWidget *widget, GdkEventAny *event, 543 gpointer data) 544 { 545 prefs_summary_open_cancel(); 546 return TRUE; 547 } 548 549 static GtkListStore *prefs_summary_open_create_store(void) 550 { 551 return gtk_list_store_new(N_PREFS_SUMMARY_OPEN_COLUMNS, 552 G_TYPE_STRING, 553 G_TYPE_POINTER, 554 -1); 555 } 556 557 static void prefs_summary_open_insert_action(GtkListStore *store, 558 gchar *name, 559 gint dp) 560 { 561 GtkTreeIter iter; 562 563 /* add new */ 564 gtk_list_store_append(store, &iter); 565 gtk_list_store_set(store, &iter, 566 PREFS_SUMMARY_OPEN_HEADER, 567 name, 568 PREFS_SUMMARY_OPEN_DATA, GINT_TO_POINTER(dp), 569 -1); 570 } 571 572 static GtkWidget *prefs_summary_open_list_view_create(const gchar *name) 573 { 574 GtkWidget *list_view; 575 GtkTreeSelection *selector; 576 GtkTreeModel *model; 577 578 model = GTK_TREE_MODEL(prefs_summary_open_create_store()); 579 list_view = gtk_tree_view_new_with_model(model); 580 g_object_unref(G_OBJECT(model)); 581 582 selector = gtk_tree_view_get_selection(GTK_TREE_VIEW(list_view)); 583 gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE); 584 585 prefs_summary_open_create_list_view_columns(GTK_WIDGET(list_view), name); 586 587 return list_view; 588 } 589 590 static void prefs_summary_open_create_list_view_columns(GtkWidget *list_view, 591 const gchar *name) 592 { 593 GtkTreeViewColumn *column; 594 GtkCellRenderer *renderer; 595 596 renderer = gtk_cell_renderer_text_new(); 597 column = gtk_tree_view_column_new_with_attributes 598 (name, renderer, "text", PREFS_SUMMARY_OPEN_HEADER, NULL); 599 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column); 600 } 601 602 /*! 603 *\brief Called as a result of a drag & drop 604 */ 605 static void actions_list_model_row_changed(GtkTreeModel *model, 606 GtkTreePath *path, 607 GtkTreeIter *iter, 608 GtkTreeView *list_view) 609 { 610 } 611 612 /*! 613 *\brief Called as a result of a gtk_list_store_swap() 614 */ 615 static void drag_begin(GtkTreeView *list_view, 616 GdkDragContext *context, 617 gpointer data) 618 { 619 /* XXX unfortunately a completed drag & drop does not emit 620 * a "rows_reordered" signal, but a "row_changed" signal. 621 * So during drag and drop, listen to "row_changed", and 622 * update the account list accordingly */ 623 624 GtkTreeModel *model = gtk_tree_view_get_model(list_view); 625 g_signal_connect(G_OBJECT(model), "row_changed", 626 G_CALLBACK(actions_list_model_row_changed), 627 list_view); 628 } 629 630 static void drag_end(GtkTreeView *list_view, 631 GdkDragContext *context, 632 gpointer data) 633 { 634 GtkTreeModel *model = gtk_tree_view_get_model(list_view); 635 g_signal_handlers_disconnect_by_func(G_OBJECT(model), 636 G_CALLBACK(actions_list_model_row_changed), 637 list_view); 638 prefs_summary_open_set_list(); 639 } 640