prefs_toolbar.c (44741B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 2002-2025 the Claws Mail team 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 28 #include "stock_pixmap.h" 29 #include "manage_window.h" 30 #include "combobox.h" 31 #include "gtkutils.h" 32 #include "mainwindow.h" 33 #include "alertpanel.h" 34 #include "prefs_common.h" 35 #include "prefs_actions.h" 36 37 #include "utils.h" 38 39 #include "toolbar.h" 40 #include "prefs_toolbar.h" 41 #include "prefswindow.h" 42 #include "prefs_gtk.h" 43 #include "messageview.h" 44 45 enum 46 { 47 SET_ICON = 0, 48 SET_FILENAME = 1, 49 SET_TEXT = 2, 50 SET_EVENT = 3, 51 SET_ICON_TEXT = 4, /*!< "icon" text (separator) */ 52 SET_ICON_IS_TEXT = 5, /*!< icon is text representation */ 53 N_SET_COLUMNS 54 }; 55 56 enum 57 { 58 ITEM_FUNCTION = 0, 59 ITEM_USER_ACTION = 1, 60 ITEM_SEPARATOR = 3, 61 }; 62 63 static const gint ToolbarIcons[] = 64 { 65 STOCK_PIXMAP_ADDRESS_BOOK, 66 STOCK_PIXMAP_ADDRESS_SEARCH, 67 STOCK_PIXMAP_BOOK, 68 STOCK_PIXMAP_CATEGORY, 69 STOCK_PIXMAP_CHECK_SPELLING, 70 STOCK_PIXMAP_CLOSE, 71 STOCK_PIXMAP_DOWN_ARROW, 72 STOCK_PIXMAP_UP_ARROW, 73 STOCK_PIXMAP_EDIT_EXTERN, 74 STOCK_PIXMAP_ERROR, 75 STOCK_PIXMAP_EXEC, 76 STOCK_PIXMAP_GROUP, 77 STOCK_PIXMAP_INSERT_FILE, 78 STOCK_PIXMAP_INTERFACE, 79 STOCK_PIXMAP_LINEWRAP_CURRENT, 80 STOCK_PIXMAP_LINEWRAP_ALL, 81 STOCK_PIXMAP_MAIL_DRAFT, 82 STOCK_PIXMAP_MAIL_ATTACH, 83 STOCK_PIXMAP_MAIL_COMPOSE, 84 STOCK_PIXMAP_MAIL_FORWARD, 85 STOCK_PIXMAP_MAIL_RECEIVE, 86 STOCK_PIXMAP_MAIL_RECEIVE_ALL, 87 STOCK_PIXMAP_MAIL_REPLY, 88 STOCK_PIXMAP_MAIL_REPLY_TO_ALL, 89 STOCK_PIXMAP_MAIL_REPLY_TO_AUTHOR, 90 STOCK_PIXMAP_MAIL_REPLY_TO_LIST, 91 STOCK_PIXMAP_MAIL_SEND, 92 STOCK_PIXMAP_MAIL_SEND_QUEUE, 93 STOCK_PIXMAP_MAIL_SIGN, 94 STOCK_PIXMAP_OPEN_MAIL, 95 STOCK_PIXMAP_NEWS_COMPOSE, 96 STOCK_PIXMAP_PASTE, 97 STOCK_PIXMAP_PREFERENCES, 98 STOCK_PIXMAP_PROPERTIES, 99 STOCK_PIXMAP_ONLINE, 100 STOCK_PIXMAP_OFFLINE, 101 STOCK_PIXMAP_NOTICE_WARN, /* small warning */ 102 STOCK_PIXMAP_NOTICE_ERROR, /* small error */ 103 STOCK_PIXMAP_NOTICE_NOTE, /* small message */ 104 STOCK_PIXMAP_GO_FOLDERS, 105 STOCK_PIXMAP_MIME_TEXT_PLAIN, 106 STOCK_PIXMAP_MIME_TEXT_HTML, 107 STOCK_PIXMAP_MIME_TEXT_PATCH, 108 STOCK_PIXMAP_MIME_APPLICATION, 109 STOCK_PIXMAP_MIME_IMAGE, 110 STOCK_PIXMAP_MIME_AUDIO, 111 STOCK_PIXMAP_MIME_TEXT_ENRICHED, 112 STOCK_PIXMAP_MIME_UNKNOWN, 113 STOCK_PIXMAP_MIME_PDF, 114 STOCK_PIXMAP_MIME_PS, 115 STOCK_PIXMAP_MIME_TEXT_CALENDAR, 116 STOCK_PIXMAP_MIME_PGP_SIG, 117 STOCK_PIXMAP_PRINTER_BTN, 118 STOCK_PIXMAP_PRIVACY_SIGNED, 119 STOCK_PIXMAP_PRIVACY_PASSED, 120 STOCK_PIXMAP_PRIVACY_FAILED, 121 STOCK_PIXMAP_PRIVACY_UNKNOWN, 122 STOCK_PIXMAP_PRIVACY_EXPIRED, 123 STOCK_PIXMAP_PRIVACY_WARN, 124 STOCK_PIXMAP_PRIVACY_EMBLEM_SIGNED, 125 STOCK_PIXMAP_PRIVACY_EMBLEM_PASSED, 126 STOCK_PIXMAP_PRIVACY_EMBLEM_FAILED, 127 STOCK_PIXMAP_PRIVACY_EMBLEM_WARN, 128 STOCK_PIXMAP_MIME_MESSAGE, 129 STOCK_PIXMAP_SPAM_BTN, 130 STOCK_PIXMAP_HAM_BTN, 131 STOCK_PIXMAP_TRASH, 132 STOCK_PIXMAP_DELETE, 133 STOCK_PIXMAP_DELETE_DUP, 134 STOCK_PIXMAP_CANCEL, 135 STOCK_PIXMAP_MARK_IGNORETHREAD, 136 STOCK_PIXMAP_MARK_WATCHTHREAD, 137 STOCK_PIXMAP_MARK_MARK, 138 STOCK_PIXMAP_MARK_UNMARK, 139 STOCK_PIXMAP_MARK_LOCKED, 140 STOCK_PIXMAP_MARK_UNLOCKED, 141 STOCK_PIXMAP_MARK_ALLREAD, 142 STOCK_PIXMAP_MARK_ALLUNREAD, 143 STOCK_PIXMAP_MARK_READ, 144 STOCK_PIXMAP_MARK_UNREAD, 145 STOCK_PIXMAP_DIR_OPEN, 146 STOCK_PIXMAP_EMPTY, /* last entry */ 147 }; 148 149 typedef struct _ToolbarPage 150 { 151 PrefsPage page; 152 153 GtkWidget *window; /* do not modify */ 154 155 ToolbarType source; 156 GList *combo_action_list; /* list of internal functions */ 157 158 GtkWidget *list_view_set; /* toolbar items treeview */ 159 GtkWidget *item_text_entry; /* item name */ 160 GtkWidget *item_type_combo; /* item type selection widget */ 161 GtkWidget *item_func_combo; /* item internal function widget */ 162 GtkWidget *item_action_combo; /* item user action widget */ 163 GtkWidget *icon_button; /* item icon chooser widget */ 164 165 GtkWidget *icon_chooser_win; 166 GtkWidget *icon_chooser_view; 167 168 gchar *item_icon_file; /* item icon file */ 169 170 } ToolbarPage; 171 172 #define ERROR_MSG _("Selected Action already set.\nPlease choose another Action from List") 173 #define ERROR_MSG_NO_ICON _("Item has no icon defined.") 174 #define ERROR_MSG_NO_TEXT _("Item has no text defined.") 175 176 static void prefs_toolbar_populate (ToolbarPage *prefs_toolbar); 177 178 static void get_action_name (const gchar *entry, 179 gchar **menu); 180 181 static gboolean is_duplicate (ToolbarPage *prefs_toolbar, 182 gchar *chosen_action); 183 static void prefs_toolbar_save (PrefsPage *_page); 184 185 static void prefs_toolbar_register (GtkButton *button, 186 ToolbarPage *prefs_toolbar); 187 static void prefs_toolbar_substitute (GtkButton *button, 188 ToolbarPage *prefs_toolbar); 189 static void prefs_toolbar_delete (GtkButton *button, 190 ToolbarPage *prefs_toolbar); 191 192 static void prefs_toolbar_up (GtkButton *button, 193 ToolbarPage *prefs_toolbar); 194 195 static void prefs_toolbar_down (GtkButton *button, 196 ToolbarPage *prefs_toolbar); 197 198 static void action_selection_changed (GtkComboBox *action_combo, 199 ToolbarPage *prefs_toolbar); 200 201 static void func_selection_changed (GtkComboBox *action_combo, 202 ToolbarPage *prefs_toolbar); 203 204 static void prefs_toolbar_create (ToolbarPage *prefs_toolbar); 205 206 static GtkWidget *create_set_list_view (ToolbarPage *prefs_toolbar); 207 208 static gboolean set_list_selected (GtkTreeSelection *selector, 209 GtkTreeModel *model, 210 GtkTreePath *path, 211 gboolean currently_selected, 212 ToolbarPage *prefs_toolbar); 213 214 static void icon_chooser_create (GtkButton *button, 215 ToolbarPage *prefs_toolbar); 216 217 static void prefs_toolbar_create_widget(PrefsPage *_page, GtkWindow *window, gpointer data) 218 { 219 ToolbarPage *prefs_toolbar = (ToolbarPage *) _page; 220 221 prefs_toolbar->window = GTK_WIDGET(window); 222 223 toolbar_read_config_file(prefs_toolbar->source); 224 225 prefs_toolbar_create(prefs_toolbar); 226 prefs_toolbar_populate(prefs_toolbar); 227 } 228 229 static void prefs_toolbar_save(PrefsPage *_page) 230 { 231 ToolbarPage *prefs_toolbar = (ToolbarPage *) _page; 232 GtkTreeView *list_view = GTK_TREE_VIEW(prefs_toolbar->list_view_set); 233 GtkTreeModel *model = gtk_tree_view_get_model(list_view); 234 GtkTreeIter iter; 235 236 toolbar_clear_list(prefs_toolbar->source); 237 238 if (!gtk_tree_model_iter_n_children(model, NULL) 239 || !gtk_tree_model_get_iter_first(model, &iter)) 240 toolbar_set_default(prefs_toolbar->source); 241 else { 242 do { 243 ToolbarItem *item; 244 gchar *fname, *text, *event; 245 246 item = g_new0(ToolbarItem, 1); 247 248 gtk_tree_model_get(model, &iter, 249 SET_FILENAME, &fname, 250 SET_TEXT, &text, 251 SET_EVENT, &event, 252 -1); 253 254 /* XXX: remember that G_TYPE_STRING returned by model 255 * is owned by caller of gtk_tree_model_get() */ 256 item->file = fname; 257 item->text = text; 258 item->index = toolbar_ret_val_from_descr(event); 259 g_free(event); 260 261 toolbar_set_list_item(item, prefs_toolbar->source); 262 263 g_free(item->file); 264 g_free(item->text); 265 g_free(item); 266 } while (gtk_tree_model_iter_next(model, &iter)); 267 } 268 269 toolbar_save_config_file(prefs_toolbar->source); 270 271 if (prefs_toolbar->source == TOOLBAR_MAIN) 272 toolbar_update(TOOLBAR_MAIN, mainwindow_get_mainwindow()); 273 else if (prefs_toolbar->source == TOOLBAR_COMPOSE) 274 compose_reflect_prefs_pixmap_theme(); 275 else if (prefs_toolbar->source == TOOLBAR_MSGVIEW) 276 messageview_reflect_prefs_pixmap_theme(); 277 } 278 279 static void prefs_toolbar_destroy_widget(PrefsPage *_page) 280 { 281 ToolbarPage *prefs_toolbar = (ToolbarPage *) _page; 282 283 g_list_free(prefs_toolbar->combo_action_list); 284 prefs_toolbar->combo_action_list = NULL; 285 } 286 287 static void prefs_toolbar_set_displayed(ToolbarPage *prefs_toolbar) 288 { 289 GSList *cur; 290 GtkTreeView *list_view_set = GTK_TREE_VIEW(prefs_toolbar->list_view_set); 291 GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model 292 (list_view_set)); 293 GSList *toolbar_list = toolbar_get_list(prefs_toolbar->source); 294 GtkTreeIter iter; 295 296 gtk_list_store_clear(store); 297 298 /* set currently active toolbar entries */ 299 for (cur = toolbar_list; cur != NULL; cur = cur->next) { 300 ToolbarItem *item = (ToolbarItem*) cur->data; 301 302 gtk_list_store_append(store, &iter); 303 304 if (item->index != A_SEPARATOR) { 305 GdkPixbuf *pix; 306 StockPixmap icon = stock_pixmap_get_icon(item->file); 307 308 stock_pixbuf_gdk(icon, &pix); 309 310 gtk_list_store_set(store, &iter, 311 SET_ICON, pix, 312 SET_FILENAME, item->file, 313 SET_TEXT, item->text, 314 SET_EVENT, toolbar_ret_descr_from_val(item->index), 315 SET_ICON_TEXT, NULL, 316 SET_ICON_IS_TEXT, FALSE, 317 -1); 318 } else { 319 gtk_list_store_set(store, &iter, 320 SET_ICON, NULL, 321 SET_FILENAME, toolbar_ret_descr_from_val(A_SEPARATOR), 322 SET_TEXT, (const gchar *) "", 323 SET_EVENT, toolbar_ret_descr_from_val(A_SEPARATOR), 324 SET_ICON_TEXT, (const gchar *) SEPARATOR_PIXMAP, 325 SET_ICON_IS_TEXT, TRUE, 326 -1); 327 } 328 } 329 330 /* select first */ 331 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) { 332 gtk_tree_selection_select_iter(gtk_tree_view_get_selection 333 (list_view_set), 334 &iter); 335 } 336 } 337 338 static void prefs_toolbar_populate(ToolbarPage *prefs_toolbar) 339 { 340 GSList *cur; 341 gchar *act, *act_name; 342 343 prefs_toolbar->combo_action_list = toolbar_get_action_items(prefs_toolbar->source); 344 combobox_set_popdown_strings(GTK_COMBO_BOX_TEXT(prefs_toolbar->item_func_combo), 345 prefs_toolbar->combo_action_list); 346 347 /* get currently defined actions */ 348 if (prefs_common.actions_list != NULL) { 349 for (cur = prefs_common.actions_list; cur != NULL; cur = cur->next) { 350 act = (gchar *)cur->data; 351 get_action_name(act, &act_name); 352 353 gtk_combo_box_text_append_text( 354 GTK_COMBO_BOX_TEXT(prefs_toolbar->item_action_combo), 355 act_name); 356 357 g_free(act_name); 358 } 359 360 } else 361 combobox_set_sensitive(GTK_COMBO_BOX(prefs_toolbar->item_type_combo), 362 ITEM_USER_ACTION, FALSE); 363 364 gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_func_combo), 0); 365 gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_action_combo), 0); 366 367 prefs_toolbar_set_displayed(prefs_toolbar); 368 369 toolbar_clear_list(prefs_toolbar->source); 370 } 371 372 static gboolean is_duplicate(ToolbarPage *prefs_toolbar, gchar *chosen_action) 373 { 374 GtkTreeView *list_view_set = GTK_TREE_VIEW 375 (prefs_toolbar->list_view_set); 376 GtkTreeModel *model_set = gtk_tree_view_get_model(list_view_set); 377 gchar *entry; 378 GtkTreeIter iter; 379 gboolean result; 380 381 cm_return_val_if_fail(chosen_action != NULL, TRUE); 382 383 if (!gtk_tree_model_iter_n_children(model_set, NULL)) 384 return FALSE; 385 386 if (!gtk_tree_model_get_iter_first(model_set, &iter)) 387 return FALSE; 388 389 result = FALSE; 390 do { 391 gtk_tree_model_get(model_set, &iter, 392 SET_EVENT, &entry, 393 -1); 394 if (g_utf8_collate(chosen_action, entry) == 0) 395 result = TRUE; 396 g_free(entry); 397 } while (!result && gtk_tree_model_iter_next(model_set, &iter)); 398 399 return result; 400 } 401 402 static void prefs_toolbar_default(GtkButton *button, ToolbarPage *prefs_toolbar) 403 { 404 toolbar_clear_list(prefs_toolbar->source); 405 toolbar_set_default(prefs_toolbar->source); 406 prefs_toolbar_set_displayed(prefs_toolbar); 407 } 408 409 /*! 410 *\return String that should be freed by caller. 411 */ 412 static void get_action_name(const gchar *entry, gchar **menu) 413 { 414 gchar *act, *act_p; 415 416 *menu = NULL; 417 418 if (prefs_common.actions_list != NULL) { 419 420 act = g_strdup(entry); 421 act_p = strstr(act, ": "); 422 if (act_p != NULL) 423 act_p[0] = 0x00; 424 /* freed by calling func */ 425 *menu = act; 426 } 427 } 428 429 static void prefs_toolbar_register(GtkButton *button, ToolbarPage *prefs_toolbar) 430 { 431 GtkTreeView *list_view_set = GTK_TREE_VIEW(prefs_toolbar->list_view_set); 432 gint item_type = gtk_combo_box_get_active(GTK_COMBO_BOX(prefs_toolbar->item_type_combo)); 433 GtkListStore *store_set; 434 GtkTreeIter iter; 435 436 store_set = GTK_LIST_STORE(gtk_tree_view_get_model(list_view_set)); 437 438 /* SEPARATOR or other ? */ 439 if (item_type == ITEM_SEPARATOR) { 440 gtk_list_store_append(store_set, &iter); 441 gtk_list_store_set(store_set, &iter, 442 SET_ICON, NULL, 443 SET_FILENAME, prefs_toolbar->item_icon_file, 444 SET_TEXT, NULL, 445 SET_EVENT, toolbar_ret_descr_from_val(A_SEPARATOR), 446 SET_ICON_TEXT, (const gchar *) SEPARATOR_PIXMAP, 447 SET_ICON_IS_TEXT, TRUE, 448 -1); 449 } else { 450 GdkPixbuf *pixbuf; 451 gchar *event, *text; 452 453 if (prefs_toolbar->item_icon_file == NULL) { 454 alertpanel_error(ERROR_MSG_NO_ICON); 455 return; 456 } 457 stock_pixbuf_gdk( 458 stock_pixmap_get_icon(prefs_toolbar->item_icon_file), 459 &pixbuf); 460 if(pixbuf == NULL) { 461 alertpanel_error(ERROR_MSG_NO_ICON); 462 return; 463 } 464 465 if (item_type == ITEM_FUNCTION) { 466 event = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT( 467 prefs_toolbar->item_func_combo)); 468 469 if (is_duplicate(prefs_toolbar, event)) { 470 alertpanel_error(ERROR_MSG); 471 g_free(event); 472 return; 473 } 474 } 475 else 476 event = toolbar_ret_descr_from_val(A_CLAWS_ACTIONS); 477 478 text = gtk_editable_get_chars( 479 GTK_EDITABLE(prefs_toolbar->item_text_entry), 0 , -1); 480 481 if (text != NULL) { 482 gtk_list_store_append(store_set, &iter); 483 gtk_list_store_set(store_set, &iter, 484 SET_ICON, pixbuf, 485 SET_FILENAME, prefs_toolbar->item_icon_file, 486 SET_TEXT, text, 487 SET_EVENT, event, 488 SET_ICON_TEXT, NULL, 489 SET_ICON_IS_TEXT, FALSE, 490 -1); 491 } else { 492 alertpanel_error(ERROR_MSG_NO_TEXT); 493 return; 494 } 495 496 g_free(text); 497 if(item_type != ITEM_USER_ACTION) 498 g_free(event); 499 } 500 501 gtk_tree_selection_select_iter(gtk_tree_view_get_selection 502 (list_view_set), 503 &iter); 504 } 505 506 static void prefs_toolbar_substitute(GtkButton *button, ToolbarPage *prefs_toolbar) 507 { 508 GtkTreeView *list_view_set = GTK_TREE_VIEW(prefs_toolbar->list_view_set); 509 GtkListStore *store_set = GTK_LIST_STORE(gtk_tree_view_get_model(list_view_set)); 510 gint item_type = gtk_combo_box_get_active(GTK_COMBO_BOX(prefs_toolbar->item_type_combo)); 511 GtkTreeSelection *sel_set; 512 GtkTreeIter iter_set; 513 514 if (!gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_set), NULL)) 515 return; 516 517 sel_set = gtk_tree_view_get_selection(list_view_set); 518 if (!gtk_tree_selection_get_selected(sel_set, NULL, &iter_set)) 519 return; 520 521 if (item_type == ITEM_SEPARATOR) { 522 gtk_list_store_set(store_set, &iter_set, 523 SET_ICON, NULL, 524 SET_TEXT, NULL, 525 SET_EVENT, toolbar_ret_descr_from_val(A_SEPARATOR), 526 SET_FILENAME, prefs_toolbar->item_icon_file, 527 SET_ICON_TEXT, (const gchar *) SEPARATOR_PIXMAP, 528 SET_ICON_IS_TEXT, TRUE, 529 -1); 530 } else { 531 GdkPixbuf *pixbuf; 532 gchar *icon_event, *set_event, *text; 533 534 if (prefs_toolbar->item_icon_file == NULL) { 535 alertpanel_error(ERROR_MSG_NO_ICON); 536 return; 537 } 538 stock_pixbuf_gdk( 539 stock_pixmap_get_icon(prefs_toolbar->item_icon_file), 540 &pixbuf); 541 if(pixbuf == NULL) { 542 alertpanel_error(ERROR_MSG_NO_ICON); 543 return; 544 } 545 546 gtk_tree_model_get(GTK_TREE_MODEL(store_set), &iter_set, 547 SET_EVENT, &set_event, 548 -1); 549 550 if (item_type == ITEM_FUNCTION) { 551 icon_event = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT( 552 prefs_toolbar->item_func_combo)); 553 554 if (is_duplicate(prefs_toolbar, icon_event) 555 && g_utf8_collate(icon_event, set_event) != 0){ 556 alertpanel_error(ERROR_MSG); 557 g_free(icon_event); 558 g_free(set_event); 559 return; 560 } 561 } 562 else 563 icon_event = toolbar_ret_descr_from_val(A_CLAWS_ACTIONS); 564 565 text = gtk_editable_get_chars( 566 GTK_EDITABLE(prefs_toolbar->item_text_entry), 0 , -1); 567 568 /* change the row */ 569 if (text != NULL) { 570 gtk_list_store_set(store_set, &iter_set, 571 SET_ICON, pixbuf, 572 SET_FILENAME, prefs_toolbar->item_icon_file, 573 SET_TEXT, text, 574 SET_EVENT, icon_event, 575 SET_ICON_TEXT, NULL, 576 SET_ICON_IS_TEXT, FALSE, 577 -1); 578 } else 579 alertpanel_error(ERROR_MSG_NO_TEXT); 580 581 g_free(text); 582 g_free(set_event); 583 if(item_type != ITEM_USER_ACTION) 584 g_free(icon_event); 585 } 586 } 587 588 static void prefs_toolbar_delete(GtkButton *button, ToolbarPage *prefs_toolbar) 589 { 590 GtkTreeView *list_view_set = GTK_TREE_VIEW(prefs_toolbar->list_view_set); 591 GtkTreeModel *store_set = gtk_tree_view_get_model(list_view_set); 592 GtkTreeIter iter_set; 593 GtkTreePath *path; 594 595 if (!gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_set), NULL)) 596 return; 597 598 if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection 599 (list_view_set), 600 NULL, 601 &iter_set)) 602 return; 603 604 /* select prev list item, if deleted was first select next */ 605 path = gtk_tree_model_get_path(store_set, &iter_set); 606 gtk_tree_path_prev(path); 607 608 gtk_list_store_remove(GTK_LIST_STORE(store_set), &iter_set); 609 610 gtk_tree_selection_select_path( 611 gtk_tree_view_get_selection(list_view_set), 612 path); 613 614 gtk_tree_path_free(path); 615 } 616 617 static void prefs_toolbar_up(GtkButton *button, ToolbarPage *prefs_toolbar) 618 { 619 GtkTreePath *prev, *sel; 620 GtkTreeIter isel; 621 GtkListStore *store = NULL; 622 GtkTreeModel *model = NULL; 623 GtkTreeIter iprev; 624 625 if (!gtk_tree_selection_get_selected 626 (gtk_tree_view_get_selection 627 (GTK_TREE_VIEW(prefs_toolbar->list_view_set)), 628 &model, 629 &isel)) 630 return; 631 store = (GtkListStore *)model; 632 633 sel = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &isel); 634 if (!sel) 635 return; 636 637 /* no move if we're at row 0... */ 638 prev = gtk_tree_path_copy(sel); 639 if (!gtk_tree_path_prev(prev)) { 640 gtk_tree_path_free(prev); 641 gtk_tree_path_free(sel); 642 return; 643 } 644 645 gtk_tree_model_get_iter(GTK_TREE_MODEL(store), 646 &iprev, prev); 647 gtk_tree_path_free(sel); 648 gtk_tree_path_free(prev); 649 650 gtk_list_store_swap(store, &iprev, &isel); 651 } 652 653 static void prefs_toolbar_down(GtkButton *button, ToolbarPage *prefs_toolbar) 654 { 655 GtkListStore *store = NULL; 656 GtkTreeModel *model = NULL; 657 GtkTreeIter next, sel; 658 659 if (!gtk_tree_selection_get_selected 660 (gtk_tree_view_get_selection 661 (GTK_TREE_VIEW(prefs_toolbar->list_view_set)), 662 &model, 663 &sel)) 664 return; 665 666 store = (GtkListStore *)model; 667 next = sel; 668 if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &next)) 669 return; 670 671 gtk_list_store_swap(store, &next, &sel); 672 } 673 674 static void item_type_changed(GtkComboBox *item_type_combo, 675 ToolbarPage *prefs_toolbar) 676 { 677 gint active = gtk_combo_box_get_active(item_type_combo); 678 679 switch(active) { 680 case ITEM_FUNCTION: 681 gtk_widget_show(prefs_toolbar->item_func_combo); 682 gtk_widget_hide(prefs_toolbar->item_action_combo); 683 gtk_combo_box_set_active( 684 GTK_COMBO_BOX(prefs_toolbar->item_func_combo), 0); 685 gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), ""); 686 gtk_widget_set_sensitive(prefs_toolbar->item_text_entry, TRUE); 687 gtk_widget_set_sensitive(prefs_toolbar->item_func_combo, TRUE); 688 gtk_widget_set_sensitive(prefs_toolbar->icon_button, TRUE); 689 690 func_selection_changed(GTK_COMBO_BOX(prefs_toolbar->item_func_combo), 691 prefs_toolbar); 692 break; 693 case ITEM_USER_ACTION: 694 gtk_widget_show(prefs_toolbar->item_action_combo); 695 gtk_widget_hide(prefs_toolbar->item_func_combo); 696 gtk_combo_box_set_active( 697 GTK_COMBO_BOX(prefs_toolbar->item_action_combo), 0); 698 gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), ""); 699 gtk_widget_set_sensitive(prefs_toolbar->item_text_entry, FALSE); 700 gtk_widget_set_sensitive(prefs_toolbar->item_action_combo, TRUE); 701 gtk_widget_set_sensitive(prefs_toolbar->icon_button, TRUE); 702 703 action_selection_changed(GTK_COMBO_BOX(prefs_toolbar->item_action_combo), 704 prefs_toolbar); 705 break; 706 case ITEM_SEPARATOR: 707 gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), _("None")); 708 gtk_button_set_image(GTK_BUTTON(prefs_toolbar->icon_button), NULL); 709 g_free(prefs_toolbar->item_icon_file); 710 prefs_toolbar->item_icon_file = NULL; 711 gtk_combo_box_set_active( 712 GTK_COMBO_BOX(prefs_toolbar->item_func_combo), -1); 713 gtk_combo_box_set_active( 714 GTK_COMBO_BOX(prefs_toolbar->item_action_combo), -1); 715 gtk_entry_set_text(GTK_ENTRY(prefs_toolbar->item_text_entry), ""); 716 gtk_widget_set_sensitive(prefs_toolbar->item_action_combo, FALSE); 717 gtk_widget_set_sensitive(prefs_toolbar->item_text_entry, FALSE); 718 gtk_widget_set_sensitive(prefs_toolbar->item_func_combo, FALSE); 719 gtk_widget_set_sensitive(prefs_toolbar->icon_button, FALSE); 720 break; 721 } 722 723 } 724 725 static void action_selection_changed(GtkComboBox *action_combo, 726 ToolbarPage *prefs_toolbar) 727 { 728 gchar *text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT( 729 prefs_toolbar->item_action_combo)); 730 731 if(text != NULL) { /* action */ 732 gtk_entry_set_text(GTK_ENTRY(prefs_toolbar->item_text_entry), text); 733 g_free(text); 734 } 735 } 736 737 static void func_selection_changed(GtkComboBox *action_combo, 738 ToolbarPage *prefs_toolbar) 739 { 740 gchar *text = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT( 741 prefs_toolbar->item_func_combo)); 742 743 if(text != NULL) { /* action */ 744 int action; 745 746 action = toolbar_ret_val_from_descr(text); 747 g_free(text); 748 if (action > -1) { 749 gint icon; 750 751 gtk_entry_set_text(GTK_ENTRY(prefs_toolbar->item_text_entry), 752 toolbar_get_short_text(action)); 753 icon = toolbar_get_icon(action); 754 if (icon > -1) { 755 StockPixmap stockp = (StockPixmap)icon; 756 g_free(prefs_toolbar->item_icon_file); 757 prefs_toolbar->item_icon_file = g_strdup(stock_pixmap_get_name(stockp)); 758 759 gtk_button_set_image(GTK_BUTTON(prefs_toolbar->icon_button), 760 stock_pixmap_widget(stockp)); 761 } 762 } 763 } 764 } 765 766 static void prefs_toolbar_create(ToolbarPage *prefs_toolbar) 767 { 768 GtkWidget *main_vbox; 769 GtkWidget *toolbar_item_hbox; 770 GtkWidget *icon_vbox; 771 GtkWidget *icon_label; 772 GtkWidget *icon_button; 773 GtkWidget *icon_hbox; 774 GtkWidget *item_type_combo; 775 GtkListStore *item_type_model; 776 GtkTreeIter iter; 777 GtkWidget *item_action_combo; 778 GtkWidget *item_func_combo; 779 GtkWidget *reg_hbox; 780 GtkWidget *arrow; 781 GtkWidget *btn_hbox; 782 GtkWidget *reg_btn; 783 GtkWidget *subst_btn; 784 GtkWidget *del_btn; 785 GtkWidget *default_btn; 786 GtkWidget *vbox_frame; 787 GtkWidget *table; 788 GtkWidget *label_icon_text; 789 GtkWidget *item_text_entry; 790 GtkWidget *vbox_toolbar_items; 791 GtkWidget *hbox_bottom; 792 GtkWidget *scrolledwindow_list_view_set; 793 GtkWidget *list_view_set; 794 GtkWidget *label; 795 796 GtkWidget *btn_vbox; 797 GtkWidget *up_btn; 798 GtkWidget *down_btn; 799 800 debug_print("Creating custom toolbar window...\n"); 801 802 main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); 803 gtk_widget_show(main_vbox); 804 805 PACK_FRAME (main_vbox, vbox_frame, _("Toolbar item")) 806 gtk_container_set_border_width(GTK_CONTAINER(vbox_frame), 8); 807 gtk_widget_show(vbox_frame); 808 809 toolbar_item_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); 810 gtk_widget_show(toolbar_item_hbox); 811 gtk_container_add(GTK_CONTAINER (vbox_frame), toolbar_item_hbox); 812 813 table = gtk_grid_new(); 814 gtk_container_set_border_width (GTK_CONTAINER (table), 8); 815 gtk_grid_set_row_spacing(GTK_GRID(table), 8); 816 gtk_grid_set_column_spacing(GTK_GRID(table), 8); 817 818 gtk_box_pack_start(GTK_BOX(toolbar_item_hbox), table, 819 TRUE, TRUE, 0); 820 821 /* toolbar item type */ 822 label = gtk_label_new(_("Item type")); 823 gtk_label_set_xalign(GTK_LABEL(label), 0.0); 824 gtk_widget_show(label); 825 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1); 826 827 item_type_combo = gtkut_sc_combobox_create(NULL, TRUE); 828 item_type_model = GTK_LIST_STORE(gtk_combo_box_get_model( 829 GTK_COMBO_BOX(item_type_combo))); 830 COMBOBOX_ADD(item_type_model, _("Internal Function"), ITEM_FUNCTION); 831 COMBOBOX_ADD(item_type_model, _("User Action"), ITEM_USER_ACTION); 832 COMBOBOX_ADD(item_type_model, _("Separator"), ITEM_SEPARATOR); 833 gtk_widget_set_size_request(item_type_combo, 200, -1); 834 gtk_grid_attach(GTK_GRID(table), item_type_combo, 1, 0, 1, 1); 835 836 /* available actions */ 837 label = gtk_label_new(_("Event executed on click")); 838 gtk_label_set_xalign(GTK_LABEL(label), 0.0); 839 gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1); 840 841 item_action_combo = gtk_combo_box_text_new(); 842 gtk_widget_set_size_request(item_action_combo, 200, -1); 843 gtk_grid_attach(GTK_GRID(table), item_action_combo, 1, 1, 1, 1); 844 845 /* available internal functions */ 846 item_func_combo = gtk_combo_box_text_new(); 847 gtk_widget_set_size_request(item_func_combo, 200, -1); 848 gtk_grid_attach(GTK_GRID(table), item_func_combo, 1, 1, 1, 1); 849 850 /* toolbar item description */ 851 label_icon_text = gtk_label_new(_("Toolbar text")); 852 gtk_label_set_xalign(GTK_LABEL(label_icon_text), 0.0); 853 gtk_widget_show (label_icon_text); 854 gtk_grid_attach(GTK_GRID(table), label_icon_text, 0, 2, 1, 1); 855 856 item_text_entry = gtk_entry_new(); 857 gtk_grid_attach(GTK_GRID(table), item_text_entry, 1, 2, 1, 1); 858 gtk_widget_set_hexpand(item_text_entry, TRUE); 859 gtk_widget_set_halign(item_text_entry, GTK_ALIGN_FILL); 860 861 icon_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, VBOX_BORDER); 862 gtk_widget_show(icon_vbox); 863 864 icon_label = gtk_label_new(_("Icon")); 865 gtk_widget_set_size_request(icon_label, 100, -1); 866 gtk_box_pack_start(GTK_BOX(icon_vbox), icon_label, FALSE, FALSE, 0); 867 868 icon_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); 869 gtk_widget_show(icon_hbox); 870 871 label = gtk_label_new(""); 872 gtk_box_pack_start(GTK_BOX(icon_hbox), label, TRUE, TRUE, 0); 873 874 icon_button = gtk_button_new(); 875 gtk_widget_show(icon_button); 876 gtk_widget_set_size_request(icon_button, 50, 50); 877 g_signal_connect(G_OBJECT(icon_button), "clicked", 878 G_CALLBACK(icon_chooser_create), prefs_toolbar); 879 gtk_box_pack_start(GTK_BOX(icon_hbox), icon_button, FALSE, FALSE, 8); 880 881 label = gtk_label_new(""); 882 gtk_box_pack_start(GTK_BOX(icon_hbox), label, TRUE, TRUE, 0); 883 884 gtk_box_pack_start(GTK_BOX(icon_vbox), icon_hbox, FALSE, FALSE, 0); 885 886 gtk_box_pack_start(GTK_BOX(toolbar_item_hbox), icon_vbox, FALSE, FALSE, 0); 887 888 /* register / substitute / delete */ 889 reg_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); 890 gtk_box_pack_start(GTK_BOX(main_vbox), reg_hbox, FALSE, FALSE, 0); 891 gtk_container_set_border_width(GTK_CONTAINER(reg_hbox), 10); 892 893 arrow = gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_MENU); 894 gtk_box_pack_start(GTK_BOX(reg_hbox), arrow, FALSE, FALSE, 0); 895 gtk_widget_set_size_request(arrow, -1, 16); 896 897 btn_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); 898 gtk_box_pack_start(GTK_BOX(reg_hbox), btn_hbox, FALSE, FALSE, 0); 899 900 reg_btn = gtkut_stock_button("list-add", _("_Add")); 901 gtk_box_pack_start(GTK_BOX(btn_hbox), reg_btn, FALSE, TRUE, 0); 902 g_signal_connect(G_OBJECT(reg_btn), "clicked", 903 G_CALLBACK(prefs_toolbar_register), 904 prefs_toolbar); 905 906 subst_btn = gtkut_get_replace_btn(_("_Replace")); 907 gtk_box_pack_start(GTK_BOX(btn_hbox), subst_btn, FALSE, TRUE, 0); 908 g_signal_connect(G_OBJECT(subst_btn), "clicked", 909 G_CALLBACK(prefs_toolbar_substitute), 910 prefs_toolbar); 911 912 del_btn = gtkut_stock_button("edit-delete", _("D_elete")); 913 gtk_box_pack_start(GTK_BOX(btn_hbox), del_btn, FALSE, TRUE, 0); 914 g_signal_connect(G_OBJECT(del_btn), "clicked", 915 G_CALLBACK(prefs_toolbar_delete), 916 prefs_toolbar); 917 918 default_btn = gtk_button_new_with_label(_(" Use default ")); 919 gtk_box_pack_end(GTK_BOX(reg_hbox), default_btn, FALSE, TRUE, 0); 920 g_signal_connect(G_OBJECT(default_btn), "clicked", 921 G_CALLBACK(prefs_toolbar_default), 922 prefs_toolbar); 923 924 /* currently active toolbar items */ 925 vbox_toolbar_items = gtk_box_new(GTK_ORIENTATION_VERTICAL, VBOX_BORDER); 926 gtk_box_pack_start(GTK_BOX(main_vbox), vbox_toolbar_items, TRUE, TRUE, 0); 927 928 hbox_bottom = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); 929 gtk_container_add(GTK_CONTAINER(vbox_toolbar_items), hbox_bottom); 930 931 scrolledwindow_list_view_set = gtk_scrolled_window_new(NULL, NULL); 932 gtk_box_pack_start(GTK_BOX(hbox_bottom), scrolledwindow_list_view_set, TRUE, TRUE, 0); 933 gtk_container_set_border_width(GTK_CONTAINER(scrolledwindow_list_view_set), 8); 934 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow_list_view_set), 935 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 936 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow_list_view_set), 937 GTK_SHADOW_IN); 938 gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scrolledwindow_list_view_set), TRUE); 939 940 list_view_set = create_set_list_view(prefs_toolbar); 941 gtk_widget_show(list_view_set); 942 gtk_container_add(GTK_CONTAINER(scrolledwindow_list_view_set), list_view_set); 943 gtk_widget_set_vexpand(list_view_set, TRUE); 944 gtk_widget_set_hexpand(list_view_set, TRUE); 945 946 btn_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); 947 gtk_widget_show(btn_vbox); 948 gtk_box_pack_start(GTK_BOX(hbox_bottom), btn_vbox, FALSE, FALSE, 0); 949 950 up_btn = gtkut_stock_button("go-up", _("_Up")); 951 gtk_widget_show(up_btn); 952 gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, FALSE, 4); 953 954 down_btn = gtkut_stock_button("go-down", _("_Down")); 955 gtk_widget_show(down_btn); 956 gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, FALSE, 0); 957 gtk_container_set_border_width(GTK_CONTAINER(btn_vbox), 8); 958 959 g_signal_connect(G_OBJECT(item_type_combo), "changed", 960 G_CALLBACK(item_type_changed), prefs_toolbar); 961 g_signal_connect(G_OBJECT(item_action_combo), "changed", 962 G_CALLBACK(action_selection_changed), prefs_toolbar); 963 g_signal_connect(G_OBJECT(item_func_combo), "changed", 964 G_CALLBACK(func_selection_changed), prefs_toolbar); 965 g_signal_connect(G_OBJECT(up_btn), "clicked", 966 G_CALLBACK(prefs_toolbar_up), prefs_toolbar); 967 g_signal_connect(G_OBJECT(down_btn), "clicked", 968 G_CALLBACK(prefs_toolbar_down), prefs_toolbar); 969 970 gtk_widget_show_all(main_vbox); 971 972 prefs_toolbar->list_view_set = list_view_set; 973 prefs_toolbar->item_text_entry = item_text_entry; 974 prefs_toolbar->item_type_combo = item_type_combo; 975 prefs_toolbar->item_func_combo = item_func_combo; 976 prefs_toolbar->item_action_combo= item_action_combo; 977 prefs_toolbar->icon_button = icon_button; 978 prefs_toolbar->item_icon_file = NULL; 979 980 prefs_toolbar->page.widget = main_vbox; 981 } 982 983 ToolbarPage *prefs_toolbar_mainwindow; 984 ToolbarPage *prefs_toolbar_composewindow; 985 ToolbarPage *prefs_toolbar_messageview; 986 987 void prefs_toolbar_init(void) 988 { 989 ToolbarPage *page; 990 static gchar *mainpath[3], *messagepath[3], *composepath[3]; 991 992 mainpath[0] = _("Toolbars"); 993 mainpath[1] = _("Main Window"); 994 mainpath[2] = NULL; 995 996 page = g_new0(ToolbarPage, 1); 997 page->page.path = mainpath; 998 page->page.create_widget = prefs_toolbar_create_widget; 999 page->page.destroy_widget = prefs_toolbar_destroy_widget; 1000 page->page.save_page = prefs_toolbar_save; 1001 page->source = TOOLBAR_MAIN; 1002 page->page.weight = 50.0; 1003 prefs_gtk_register_page((PrefsPage *) page); 1004 prefs_toolbar_mainwindow = page; 1005 1006 messagepath[0] = _("Toolbars"); 1007 messagepath[1] = _("Message Window"); 1008 messagepath[2] = NULL; 1009 1010 page = g_new0(ToolbarPage, 1); 1011 page->page.path = messagepath; 1012 page->page.create_widget = prefs_toolbar_create_widget; 1013 page->page.destroy_widget = prefs_toolbar_destroy_widget; 1014 page->page.save_page = prefs_toolbar_save; 1015 page->source = TOOLBAR_MSGVIEW; 1016 page->page.weight = 45.0; 1017 prefs_gtk_register_page((PrefsPage *) page); 1018 prefs_toolbar_messageview = page; 1019 1020 composepath[0] = _("Toolbars"); 1021 composepath[1] = _("Write Window"); 1022 composepath[2] = NULL; 1023 1024 page = g_new0(ToolbarPage, 1); 1025 page->page.path = composepath; 1026 page->page.create_widget = prefs_toolbar_create_widget; 1027 page->page.destroy_widget = prefs_toolbar_destroy_widget; 1028 page->page.save_page = prefs_toolbar_save; 1029 page->source = TOOLBAR_COMPOSE; 1030 page->page.weight = 40.0; 1031 prefs_gtk_register_page((PrefsPage *) page); 1032 prefs_toolbar_composewindow = page; 1033 } 1034 1035 void prefs_toolbar_done(void) 1036 { 1037 prefs_gtk_unregister_page((PrefsPage *) prefs_toolbar_mainwindow); 1038 g_free(prefs_toolbar_mainwindow->item_icon_file); 1039 g_free(prefs_toolbar_mainwindow); 1040 prefs_gtk_unregister_page((PrefsPage *) prefs_toolbar_composewindow); 1041 g_free(prefs_toolbar_composewindow->item_icon_file); 1042 g_free(prefs_toolbar_composewindow); 1043 prefs_gtk_unregister_page((PrefsPage *) prefs_toolbar_messageview); 1044 g_free(prefs_toolbar_messageview->item_icon_file); 1045 g_free(prefs_toolbar_messageview); 1046 } 1047 1048 void prefs_toolbar_update_action_btns(void) 1049 { 1050 if (toolbar_check_action_btns(TOOLBAR_MAIN)) { 1051 toolbar_save_config_file(TOOLBAR_MAIN); 1052 toolbar_update(TOOLBAR_MAIN, mainwindow_get_mainwindow()); 1053 } 1054 1055 if (toolbar_check_action_btns(TOOLBAR_COMPOSE)) { 1056 toolbar_save_config_file(TOOLBAR_COMPOSE); 1057 compose_reflect_prefs_pixmap_theme(); 1058 } 1059 1060 if (toolbar_check_action_btns(TOOLBAR_MSGVIEW)) { 1061 toolbar_save_config_file(TOOLBAR_MSGVIEW); 1062 messageview_reflect_prefs_pixmap_theme(); 1063 } 1064 } 1065 1066 static void set_visible_if_not_text(GtkTreeViewColumn *col, 1067 GtkCellRenderer *renderer, 1068 GtkTreeModel *model, 1069 GtkTreeIter *iter, 1070 gpointer user_data) 1071 { 1072 gboolean is_text; 1073 GdkPixbuf *pixbuf; 1074 1075 gtk_tree_model_get(model, iter, SET_ICON_IS_TEXT, &is_text, -1); 1076 if (is_text) { 1077 g_object_set(renderer, "visible", FALSE, NULL); 1078 } else { 1079 pixbuf = NULL; 1080 gtk_tree_model_get(model, iter, 1081 SET_ICON, &pixbuf, 1082 -1); 1083 /* note: getting a pixbuf from a tree model increases 1084 * its refcount ... */ 1085 1086 g_object_set(renderer, "visible", TRUE, NULL); 1087 g_object_set(renderer, "pixbuf", pixbuf, NULL); 1088 1089 if (pixbuf != NULL) 1090 g_object_unref(pixbuf); 1091 } 1092 } 1093 1094 static GtkWidget *create_set_list_view(ToolbarPage *prefs_toolbar) 1095 { 1096 GtkTreeView *list_view; 1097 GtkListStore *store; 1098 GtkCellRenderer *renderer; 1099 GtkTreeViewColumn *column; 1100 GtkTreeSelection *selector; 1101 1102 store = gtk_list_store_new(N_SET_COLUMNS, 1103 GDK_TYPE_PIXBUF, 1104 G_TYPE_STRING, 1105 G_TYPE_STRING, 1106 G_TYPE_STRING, 1107 G_TYPE_STRING, 1108 G_TYPE_BOOLEAN, 1109 -1); 1110 list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store))); 1111 g_object_unref(G_OBJECT(store)); 1112 1113 column = gtk_tree_view_column_new(); 1114 gtk_tree_view_column_set_title(column, _("Icon")); 1115 renderer = gtk_cell_renderer_pixbuf_new(); 1116 gtk_tree_view_column_pack_start(column, renderer, FALSE); 1117 gtk_tree_view_set_reorderable(list_view, TRUE); 1118 /* tell pixbuf renderer it is only visible if 1119 * the icon is not represented by text */ 1120 gtk_tree_view_column_set_cell_data_func(column, renderer, 1121 set_visible_if_not_text, 1122 NULL, NULL); 1123 1124 renderer = gtk_cell_renderer_text_new(); 1125 gtk_tree_view_column_pack_start(column, renderer, FALSE); 1126 1127 /* tell the text renderer it is only visible if the icon 1128 * is represented by an image */ 1129 gtk_tree_view_column_set_attributes(column, renderer, 1130 "visible", SET_ICON_IS_TEXT, 1131 "text", SET_ICON_TEXT, 1132 NULL); 1133 1134 gtk_tree_view_append_column(list_view, column); 1135 1136 column = gtk_tree_view_column_new(); 1137 gtk_tree_view_column_set_title(column, _("Icon text")); 1138 renderer = gtk_cell_renderer_text_new(); 1139 gtk_tree_view_column_pack_start(column, renderer, FALSE); 1140 gtk_tree_view_column_set_attributes(column, renderer, 1141 "text", SET_TEXT, 1142 NULL); 1143 gtk_tree_view_append_column(list_view, column); 1144 1145 column = gtk_tree_view_column_new(); 1146 gtk_tree_view_column_set_title(column, _("Mapped event")); 1147 renderer = gtk_cell_renderer_text_new(); 1148 gtk_tree_view_column_pack_start(column, renderer, FALSE); 1149 gtk_tree_view_column_set_attributes(column, renderer, 1150 "text", SET_EVENT, 1151 NULL); 1152 gtk_tree_view_append_column(list_view, column); 1153 1154 /* various other tree view attributes */ 1155 selector = gtk_tree_view_get_selection(list_view); 1156 gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE); 1157 gtk_tree_selection_set_select_function 1158 (selector, (GtkTreeSelectionFunc) set_list_selected, 1159 prefs_toolbar, NULL); 1160 1161 return GTK_WIDGET(list_view); 1162 1163 } 1164 1165 static gboolean set_list_selected(GtkTreeSelection *selector, 1166 GtkTreeModel *model, 1167 GtkTreePath *path, 1168 gboolean currently_selected, 1169 ToolbarPage *prefs_toolbar) 1170 { 1171 1172 GtkTreeIter iter; 1173 gchar *icon_text, *icon_file, *descr; 1174 GList *cur; 1175 GSList *cur2; 1176 gint item_num; 1177 GdkPixbuf *pix; 1178 1179 if (currently_selected || !gtk_tree_model_get_iter(model, &iter, path)) 1180 return TRUE; 1181 1182 gtk_tree_model_get(model, &iter, 1183 SET_ICON, &pix, 1184 SET_TEXT, &icon_text, 1185 SET_EVENT, &descr, 1186 SET_FILENAME, &icon_file, 1187 -1); 1188 1189 g_free(prefs_toolbar->item_icon_file); 1190 prefs_toolbar->item_icon_file = icon_file; 1191 gtk_button_set_image(GTK_BUTTON(prefs_toolbar->icon_button), 1192 gtk_image_new_from_pixbuf(pix)); 1193 gtk_button_set_always_show_image(GTK_BUTTON(prefs_toolbar->icon_button), TRUE); 1194 1195 if (g_utf8_collate(toolbar_ret_descr_from_val(A_SEPARATOR), descr) == 0) { 1196 gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), 1197 _("None")); 1198 g_free(prefs_toolbar->item_icon_file); 1199 prefs_toolbar->item_icon_file = NULL; 1200 gtk_combo_box_set_active(GTK_COMBO_BOX(prefs_toolbar->item_type_combo), 1201 ITEM_SEPARATOR); 1202 g_free(icon_text); 1203 g_free(descr); 1204 if (pix != NULL) 1205 g_object_unref(pix); 1206 1207 return TRUE; 1208 } 1209 1210 gtk_button_set_label(GTK_BUTTON(prefs_toolbar->icon_button), ""); 1211 gtk_entry_set_text(GTK_ENTRY(prefs_toolbar->item_text_entry), 1212 icon_text); 1213 1214 if (g_utf8_collate(toolbar_ret_descr_from_val(A_CLAWS_ACTIONS), descr) == 0) { 1215 gtk_combo_box_set_active(GTK_COMBO_BOX( 1216 prefs_toolbar->item_type_combo), ITEM_USER_ACTION); 1217 1218 for(cur2 = prefs_common.actions_list, item_num = 0; cur2 != NULL; 1219 cur2 = cur2->next) { 1220 gchar *item_string; 1221 get_action_name((gchar *)cur2->data, &item_string); 1222 1223 if(g_utf8_collate(item_string, icon_text) == 0) { 1224 gtk_combo_box_set_active( 1225 GTK_COMBO_BOX(prefs_toolbar->item_action_combo), 1226 item_num); 1227 g_free(item_string); 1228 break; 1229 } 1230 else { 1231 item_num++; 1232 g_free(item_string); 1233 } 1234 } 1235 1236 gtk_widget_show(prefs_toolbar->item_action_combo); 1237 gtk_widget_hide(prefs_toolbar->item_func_combo); 1238 1239 g_free(icon_text); 1240 g_free(descr); 1241 if (pix != NULL) 1242 g_object_unref(pix); 1243 1244 return TRUE; 1245 } 1246 1247 /* scan combo list for selected description an set combo item accordingly */ 1248 for (cur = prefs_toolbar->combo_action_list, item_num = 0; cur != NULL; 1249 cur = cur->next) { 1250 gchar *item_str = (gchar*)cur->data; 1251 if (g_utf8_collate(item_str, descr) == 0) { 1252 gtk_combo_box_set_active( 1253 GTK_COMBO_BOX(prefs_toolbar->item_func_combo), 1254 item_num); 1255 1256 break; 1257 } 1258 else 1259 item_num++; 1260 } 1261 1262 gtk_combo_box_set_active(GTK_COMBO_BOX( 1263 prefs_toolbar->item_type_combo),ITEM_FUNCTION); 1264 gtk_widget_hide(prefs_toolbar->item_action_combo); 1265 gtk_widget_show(prefs_toolbar->item_func_combo); 1266 1267 g_free(icon_text); 1268 g_free(descr); 1269 if (pix != NULL) 1270 g_object_unref(pix); 1271 1272 return TRUE; 1273 } 1274 1275 static void icon_chooser_ok_clicked(GtkButton *button, 1276 ToolbarPage *prefs_toolbar) 1277 { 1278 GtkTreeModel *model; 1279 GtkTreeIter iter; 1280 GList *list; 1281 GdkPixbuf *pix; 1282 gchar *icon_file; 1283 1284 cm_return_if_fail(prefs_toolbar != NULL); 1285 1286 model = gtk_icon_view_get_model(GTK_ICON_VIEW(prefs_toolbar->icon_chooser_view)); 1287 list = gtk_icon_view_get_selected_items(GTK_ICON_VIEW(prefs_toolbar->icon_chooser_view)); 1288 if(list == NULL) 1289 return; 1290 1291 if(!gtk_tree_model_get_iter(model, &iter, (GtkTreePath *)list->data)) { 1292 gtk_tree_path_free(list->data); 1293 g_list_free(list); 1294 return; 1295 } 1296 1297 gtk_tree_model_get(model, &iter, 1298 SET_ICON, &pix, 1299 SET_FILENAME, &icon_file, 1300 -1); 1301 1302 g_free(prefs_toolbar->item_icon_file); 1303 prefs_toolbar->item_icon_file = icon_file; 1304 gtk_button_set_image(GTK_BUTTON(prefs_toolbar->icon_button), 1305 gtk_image_new_from_pixbuf(pix)); 1306 if (pix != NULL) 1307 g_object_unref(pix); 1308 1309 gtk_widget_destroy(prefs_toolbar->icon_chooser_win); 1310 prefs_toolbar->icon_chooser_win = NULL; 1311 prefs_toolbar->icon_chooser_view = NULL; 1312 1313 gtk_tree_path_free(list->data); 1314 g_list_free(list); 1315 } 1316 1317 static void icon_chooser_cancel_clicked(GtkButton *button, 1318 ToolbarPage *prefs_toolbar) 1319 { 1320 cm_return_if_fail(prefs_toolbar != NULL); 1321 1322 gtk_widget_destroy(prefs_toolbar->icon_chooser_win); 1323 prefs_toolbar->icon_chooser_win = NULL; 1324 prefs_toolbar->icon_chooser_view = NULL; 1325 } 1326 1327 static gboolean icon_list_key_pressed(GtkWidget *widget, GdkEventKey *event, 1328 ToolbarPage *prefs_toolbar) 1329 { 1330 if (event) { 1331 if (event->keyval == GDK_KEY_KP_Enter || 1332 event->keyval == GDK_KEY_Return || 1333 event->keyval == GDK_KEY_space) { 1334 icon_chooser_ok_clicked(NULL, prefs_toolbar); 1335 return TRUE; 1336 } 1337 } 1338 return FALSE; 1339 } 1340 1341 static gboolean ok_cb(gpointer data) 1342 { 1343 ToolbarPage *prefs_toolbar = (ToolbarPage *)data; 1344 icon_chooser_ok_clicked(NULL, prefs_toolbar); 1345 return FALSE; 1346 } 1347 1348 static gboolean icon_list_button_release(GtkWidget *widget, 1349 GdkEventButton *event, 1350 ToolbarPage *prefs_toolbar ) 1351 { 1352 static guint id = 0; 1353 if (id > 0) { 1354 g_source_remove(id); 1355 id = 0; 1356 } 1357 id = g_timeout_add(100, ok_cb, prefs_toolbar); 1358 return FALSE; 1359 } 1360 1361 static gboolean icon_window_button_press(GtkWidget *widget, 1362 GdkEventButton *event, 1363 ToolbarPage *prefs_toolbar ) 1364 { 1365 GtkWidget *event_widget; 1366 gboolean restore = TRUE; 1367 1368 /* Test where mouse was clicked */ 1369 event_widget = gtk_get_event_widget((GdkEvent *)event); 1370 if (event_widget != widget) { 1371 while (event_widget) { 1372 if (event_widget == widget) 1373 return FALSE; 1374 else if (event_widget == prefs_toolbar->icon_chooser_win) { 1375 restore = FALSE; 1376 break; 1377 } 1378 event_widget = gtk_widget_get_parent(event_widget); 1379 } 1380 } 1381 1382 if (restore) { 1383 icon_chooser_cancel_clicked(NULL, prefs_toolbar); 1384 return TRUE; 1385 } 1386 return FALSE; 1387 } 1388 1389 static void icon_chooser_activated(GtkTreeView *treeview, GtkTreePath *path, 1390 ToolbarPage *prefs_toolbar) 1391 { 1392 icon_chooser_ok_clicked(NULL, prefs_toolbar); 1393 } 1394 1395 static void icon_chooser_create(GtkButton *button, ToolbarPage *prefs_toolbar) 1396 { 1397 GtkAllocation allocation; 1398 GtkWidget *icon_chooser_win; 1399 GtkWidget *scrollwin; 1400 GtkWidget *icon_view; 1401 GtkListStore *store; 1402 GtkTreeIter iter; 1403 gint i, x, y; 1404 1405 store = gtk_list_store_new(2, 1406 GDK_TYPE_PIXBUF, 1407 G_TYPE_STRING, 1408 -1); 1409 1410 gtk_list_store_clear(store); 1411 1412 for (i = 0; ToolbarIcons[i] != STOCK_PIXMAP_EMPTY; i++) { 1413 GdkPixbuf *pixbuf; 1414 stock_pixbuf_gdk(ToolbarIcons[i], &pixbuf); 1415 1416 gtk_list_store_append(store, &iter); 1417 gtk_list_store_set(store, &iter, 1418 SET_ICON, pixbuf, 1419 SET_FILENAME, stock_pixmap_get_name((StockPixmap) ToolbarIcons[i]), 1420 -1); 1421 } 1422 1423 icon_chooser_win = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_toolbar"); 1424 gtk_window_set_title(GTK_WINDOW(icon_chooser_win), _("Toolbar item icon")); 1425 gtk_window_set_decorated(GTK_WINDOW(icon_chooser_win), FALSE); 1426 gdk_window_get_origin(gtk_widget_get_window( 1427 GTK_WIDGET(prefs_toolbar->icon_button)), 1428 &x, &y); 1429 gtk_widget_get_allocation(GTK_WIDGET(prefs_toolbar->icon_button), &allocation); 1430 x += allocation.x; 1431 y += allocation.y; 1432 y += 50; 1433 x -= 300-50; 1434 gtk_window_move(GTK_WINDOW(icon_chooser_win), x, y); 1435 gtk_window_set_resizable(GTK_WINDOW(icon_chooser_win), FALSE); 1436 gtk_window_set_type_hint(GTK_WINDOW(icon_chooser_win), GDK_WINDOW_TYPE_HINT_DIALOG); 1437 gtk_widget_set_size_request(icon_chooser_win, 300, 320); 1438 1439 scrollwin = gtk_scrolled_window_new(NULL, NULL); 1440 gtk_container_add(GTK_CONTAINER(icon_chooser_win), scrollwin); 1441 gtk_widget_show(scrollwin); 1442 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), 1443 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); 1444 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), 1445 GTK_SHADOW_OUT); 1446 gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scrollwin), TRUE); 1447 1448 icon_view = gtk_icon_view_new_with_model(GTK_TREE_MODEL(store)); 1449 gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(icon_view), GTK_SELECTION_SINGLE); 1450 gtk_icon_view_set_pixbuf_column(GTK_ICON_VIEW(icon_view), SET_ICON); 1451 gtk_container_add(GTK_CONTAINER(scrollwin), GTK_WIDGET(icon_view)); 1452 1453 g_signal_connect(G_OBJECT(icon_view), "item-activated", 1454 G_CALLBACK(icon_chooser_activated), prefs_toolbar); 1455 g_signal_connect(G_OBJECT(icon_chooser_win), 1456 "button-press-event", 1457 G_CALLBACK(icon_window_button_press), 1458 prefs_toolbar ); 1459 g_signal_connect(G_OBJECT(icon_view), 1460 "button-release-event", 1461 G_CALLBACK(icon_list_button_release), 1462 prefs_toolbar ); 1463 g_signal_connect(G_OBJECT(icon_view), "key_press_event", 1464 G_CALLBACK(icon_list_key_pressed), prefs_toolbar); 1465 1466 gtk_widget_show_all(icon_chooser_win); 1467 gtk_widget_grab_focus(GTK_WIDGET(icon_view)); 1468 manage_window_set_transient(GTK_WINDOW(icon_chooser_win)); 1469 gtk_window_set_modal(GTK_WINDOW(icon_chooser_win), TRUE); 1470 1471 prefs_toolbar->icon_chooser_win = icon_chooser_win; 1472 prefs_toolbar->icon_chooser_view = icon_view; 1473 }