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/>.
27 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
36 #include "prefs_gtk.h"
37 #include "prefs_customheader.h"
38 #include "prefs_common.h"
39 #include "prefs_account.h"
40 #include "mainwindow.h"
41 #include "foldersel.h"
42 #include "manage_window.h"
43 #include "customheader.h"
47 #include "alertpanel.h"
52 CUSTHDR_STRING, /*!< display string managed by list store */
53 CUSTHDR_DATA, /*!< string managed by us */
57 static struct CustomHdr {
61 GtkWidget *cancel_btn;
69 /* widget creating functions */
70 static void prefs_custom_header_create (void);
72 static void prefs_custom_header_set_dialog (PrefsAccount *ac);
73 static void prefs_custom_header_set_list (PrefsAccount *ac);
74 static void prefs_custom_header_list_view_set_row (PrefsAccount *ac);
76 /* callback functions */
77 static void prefs_custom_header_add_cb (void);
78 static void prefs_custom_header_val_from_file_cb(void);
79 static void prefs_custom_header_delete_cb (void);
80 static void prefs_custom_header_up (void);
81 static void prefs_custom_header_down (void);
83 static gboolean prefs_custom_header_key_pressed (GtkWidget *widget,
86 static void prefs_custom_header_ok (void);
87 static void prefs_custom_header_cancel (void);
88 static gint prefs_custom_header_deleted (GtkWidget *widget,
92 static GtkListStore* prefs_custom_header_create_data_store (void);
94 static void prefs_custom_header_list_view_insert_header (GtkWidget *list_view,
95 GtkTreeIter *row_iter,
99 static GtkWidget *prefs_custom_header_list_view_create (void);
101 static void prefs_custom_header_create_list_view_columns (GtkWidget *list_view);
103 static gboolean prefs_custom_header_selected (GtkTreeSelection *selector,
106 gboolean currently_selected,
110 static PrefsAccount *cur_ac = NULL;
112 void prefs_custom_header_open(PrefsAccount *ac)
114 if (!customhdr.window) {
115 prefs_custom_header_create();
118 manage_window_set_transient(GTK_WINDOW(customhdr.window));
119 gtk_widget_grab_focus(customhdr.ok_btn);
121 prefs_custom_header_set_dialog(ac);
125 gtk_widget_show(customhdr.window);
128 static void prefs_custom_header_create(void)
134 GtkWidget *cancel_btn;
136 GtkWidget *confirm_area;
141 GtkWidget *hdr_label;
142 GtkWidget *hdr_combo;
143 GtkWidget *val_label;
144 GtkWidget *val_entry;
154 GtkWidget *ch_scrolledwin;
155 GtkWidget *list_view;
161 debug_print("Creating custom header setting window...\n");
163 window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_customheader");
164 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
165 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
166 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
167 gtk_window_set_resizable(GTK_WINDOW (window), TRUE);
169 vbox = gtk_vbox_new (FALSE, 6);
170 gtk_widget_show (vbox);
171 gtk_container_add (GTK_CONTAINER (window), vbox);
173 gtkut_stock_button_set_create(&confirm_area, &cancel_btn, GTK_STOCK_CANCEL,
174 &ok_btn, GTK_STOCK_OK,
176 gtk_widget_show (confirm_area);
177 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
178 gtk_widget_grab_default (ok_btn);
180 gtk_window_set_title (GTK_WINDOW(window), _("Custom header configuration"));
181 MANAGE_WINDOW_SIGNALS_CONNECT (window);
182 g_signal_connect (G_OBJECT(window), "delete_event",
183 G_CALLBACK(prefs_custom_header_deleted),
185 g_signal_connect (G_OBJECT(window), "key_press_event",
186 G_CALLBACK(prefs_custom_header_key_pressed),
188 g_signal_connect (G_OBJECT(ok_btn), "clicked",
189 G_CALLBACK(prefs_custom_header_ok), NULL);
190 g_signal_connect (G_OBJECT(cancel_btn), "clicked",
191 G_CALLBACK(prefs_custom_header_cancel), NULL);
193 vbox1 = gtk_vbox_new (FALSE, VSPACING);
194 gtk_widget_show (vbox1);
195 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
196 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
198 table1 = gtk_table_new (3, 2, FALSE);
199 gtk_widget_show (table1);
200 gtk_box_pack_start (GTK_BOX (vbox1), table1,
202 gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
203 gtk_table_set_col_spacings (GTK_TABLE (table1), 8);
205 hdr_label = gtk_label_new (_("Header"));
206 gtk_widget_show (hdr_label);
207 gtk_table_attach (GTK_TABLE (table1), hdr_label, 0, 1, 0, 1,
208 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
210 gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
212 hdr_combo = gtk_combo_new ();
213 gtk_widget_show (hdr_combo);
214 gtk_table_attach (GTK_TABLE (table1), hdr_combo, 0, 1, 1, 2,
215 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
217 gtk_widget_set_size_request (hdr_combo, 150, -1);
218 gtkut_combo_set_items (GTK_COMBO (hdr_combo),
219 "User-Agent", "Face", "X-Face", "X-Operating-System",
222 val_label = gtk_label_new (_("Value"));
223 gtk_widget_show (val_label);
224 gtk_table_attach (GTK_TABLE (table1), val_label, 1, 2, 0, 1,
225 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
227 gtk_misc_set_alignment (GTK_MISC (val_label), 0, 0.5);
229 val_entry = gtk_entry_new ();
230 gtk_widget_show (val_entry);
231 gtk_table_attach (GTK_TABLE (table1), val_entry, 1, 2, 1, 2,
232 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
234 gtk_widget_set_size_request (val_entry, 200, -1);
236 val_btn = gtk_button_new_with_label (_("From file..."));
237 gtk_widget_show (val_btn);
238 gtk_table_attach (GTK_TABLE (table1), val_btn, 2, 3, 1, 2,
239 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
241 g_signal_connect (G_OBJECT (val_btn), "clicked",
242 G_CALLBACK (prefs_custom_header_val_from_file_cb),
247 reg_hbox = gtk_hbox_new (FALSE, 4);
248 gtk_widget_show (reg_hbox);
249 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
251 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
252 gtk_widget_show (arrow);
253 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
254 gtk_widget_set_size_request (arrow, -1, 16);
256 btn_hbox = gtk_hbox_new (TRUE, 4);
257 gtk_widget_show (btn_hbox);
258 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
260 add_btn = gtk_button_new_from_stock (GTK_STOCK_ADD);
261 gtk_widget_show (add_btn);
262 gtk_box_pack_start (GTK_BOX (btn_hbox), add_btn, FALSE, TRUE, 0);
263 g_signal_connect (G_OBJECT (add_btn), "clicked",
264 G_CALLBACK (prefs_custom_header_add_cb),
267 del_btn = gtk_button_new_from_stock (GTK_STOCK_DELETE);
268 gtk_widget_show (del_btn);
269 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
270 g_signal_connect (G_OBJECT (del_btn), "clicked",
271 G_CALLBACK (prefs_custom_header_delete_cb),
275 ch_hbox = gtk_hbox_new (FALSE, 8);
276 gtk_widget_show (ch_hbox);
277 gtk_box_pack_start (GTK_BOX (vbox1), ch_hbox, TRUE, TRUE, 0);
279 ch_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
280 gtk_widget_set_size_request (ch_scrolledwin, -1, 200);
281 gtk_widget_show (ch_scrolledwin);
282 gtk_box_pack_start (GTK_BOX (ch_hbox), ch_scrolledwin, TRUE, TRUE, 0);
283 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ch_scrolledwin),
284 GTK_POLICY_AUTOMATIC,
285 GTK_POLICY_AUTOMATIC);
287 list_view = prefs_custom_header_list_view_create();
288 gtk_widget_show (list_view);
289 gtk_container_add (GTK_CONTAINER (ch_scrolledwin), list_view);
291 btn_vbox = gtk_vbox_new (FALSE, 8);
292 gtk_widget_show (btn_vbox);
293 gtk_box_pack_start (GTK_BOX (ch_hbox), btn_vbox, FALSE, FALSE, 0);
295 up_btn = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
296 gtk_widget_show (up_btn);
297 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
298 g_signal_connect (G_OBJECT (up_btn), "clicked",
299 G_CALLBACK (prefs_custom_header_up), NULL);
301 down_btn = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
302 gtk_widget_show (down_btn);
303 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
304 g_signal_connect (G_OBJECT (down_btn), "clicked",
305 G_CALLBACK (prefs_custom_header_down), NULL);
307 gtk_widget_show_all(window);
309 customhdr.window = window;
310 customhdr.ok_btn = ok_btn;
311 customhdr.cancel_btn = cancel_btn;
313 customhdr.hdr_combo = hdr_combo;
314 customhdr.hdr_entry = GTK_COMBO (hdr_combo)->entry;
315 customhdr.val_entry = val_entry;
317 customhdr.list_view = list_view;
320 void prefs_custom_header_read_config(PrefsAccount *ac)
324 gchar buf[PREFSBUFSIZE];
327 debug_print("Reading custom header configuration...\n");
329 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
330 CUSTOM_HEADER_RC, NULL);
331 if ((fp = g_fopen(rcpath, "rb")) == NULL) {
332 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
334 ac->customhdr_list = NULL;
339 /* remove all previous headers list */
340 while (ac->customhdr_list != NULL) {
341 ch = (CustomHeader *)ac->customhdr_list->data;
342 ac->customhdr_list = g_slist_remove(ac->customhdr_list, ch);
343 custom_header_free(ch);
346 while (fgets(buf, sizeof(buf), fp) != NULL) {
347 ch = custom_header_read_str(buf);
349 if (ch->account_id == ac->account_id) {
351 g_slist_append(ac->customhdr_list, ch);
353 custom_header_free(ch);
360 void prefs_custom_header_write_config(PrefsAccount *ac)
365 gchar buf[PREFSBUFSIZE];
369 GSList *all_hdrs = NULL;
371 debug_print("Writing custom header configuration...\n");
373 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
374 CUSTOM_HEADER_RC, NULL);
376 if ((fp = g_fopen(rcpath, "rb")) == NULL) {
377 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
381 while (fgets(buf, sizeof(buf), fp) != NULL) {
382 ch = custom_header_read_str(buf);
384 if (ch->account_id != ac->account_id)
386 g_slist_append(all_hdrs, ch);
388 custom_header_free(ch);
395 if ((pfile = prefs_write_open(rcpath)) == NULL) {
396 g_warning("failed to write configuration to file\n");
401 for (cur = all_hdrs; cur != NULL; cur = cur->next) {
402 CustomHeader *hdr = (CustomHeader *)cur->data;
405 chstr = custom_header_get_str(hdr);
406 if (fputs(chstr, pfile->fp) == EOF ||
407 fputc('\n', pfile->fp) == EOF) {
408 FILE_OP_ERROR(rcpath, "fputs || fputc");
409 prefs_file_close_revert(pfile);
417 for (cur = ac->customhdr_list; cur != NULL; cur = cur->next) {
418 CustomHeader *hdr = (CustomHeader *)cur->data;
421 chstr = custom_header_get_str(hdr);
422 if (fputs(chstr, pfile->fp) == EOF ||
423 fputc('\n', pfile->fp) == EOF) {
424 FILE_OP_ERROR(rcpath, "fputs || fputc");
425 prefs_file_close_revert(pfile);
435 while (all_hdrs != NULL) {
436 ch = (CustomHeader *)all_hdrs->data;
437 all_hdrs = g_slist_remove(all_hdrs, ch);
438 custom_header_free(ch);
441 if (prefs_file_close(pfile) < 0) {
442 g_warning("failed to write configuration to file\n");
447 static void prefs_custom_header_set_dialog(PrefsAccount *ac)
452 store = GTK_LIST_STORE(gtk_tree_view_get_model
453 (GTK_TREE_VIEW(customhdr.list_view)));
454 gtk_list_store_clear(store);
456 for (cur = ac->customhdr_list; cur != NULL; cur = cur->next) {
457 CustomHeader *ch = (CustomHeader *)cur->data;
460 ch_str = g_strdup_printf("%s: %s", ch->name,
461 ch->value ? ch->value : "");
463 prefs_custom_header_list_view_insert_header
464 (customhdr.list_view, NULL, ch_str, ch);
470 static void prefs_custom_header_set_list(PrefsAccount *ac)
476 g_slist_free(ac->customhdr_list);
477 ac->customhdr_list = NULL;
479 store = GTK_LIST_STORE(gtk_tree_view_get_model
480 (GTK_TREE_VIEW(customhdr.list_view)));
482 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter)) {
484 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
487 ac->customhdr_list = g_slist_append(ac->customhdr_list, ch);
488 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store),
493 static void prefs_custom_header_list_view_set_row(PrefsAccount *ac)
496 const gchar *entry_text;
500 store = GTK_LIST_STORE(gtk_tree_view_get_model
501 (GTK_TREE_VIEW(customhdr.list_view)));
503 entry_text = gtk_entry_get_text(GTK_ENTRY(customhdr.hdr_entry));
504 if (entry_text[0] == '\0') {
505 alertpanel_error(_("Header name is not set."));
509 while (*entry_text &&
510 (*entry_text == '\n' || *entry_text == '\r' ||
511 *entry_text == '\t' || *entry_text == ' '))
514 if (!custom_header_is_allowed(entry_text)) {
515 alertpanel_error(_("This Header name is not allowed as a custom header."));
519 ch = g_new0(CustomHeader, 1);
521 ch->account_id = ac->account_id;
523 ch->name = g_strdup(entry_text);
524 unfold_line(ch->name);
525 g_strstrip(ch->name);
526 gtk_entry_set_text(GTK_ENTRY(customhdr.hdr_entry), ch->name);
528 entry_text = gtk_entry_get_text(GTK_ENTRY(customhdr.val_entry));
529 while (*entry_text &&
530 (*entry_text == '\n' || *entry_text == '\r' ||
531 *entry_text == '\t' || *entry_text == ' '))
534 if (entry_text[0] != '\0') {
535 ch->value = g_strdup(entry_text);
536 unfold_line(ch->value);
537 g_strstrip(ch->value);
538 gtk_entry_set_text(GTK_ENTRY(customhdr.val_entry), ch->value);
541 ch_str = g_strdup_printf("%s: %s", ch->name,
542 ch->value ? ch->value : "");
544 prefs_custom_header_list_view_insert_header
545 (customhdr.list_view, NULL, ch_str, ch);
549 prefs_custom_header_set_list(cur_ac);
553 #define B64_LINE_SIZE 57
554 #define B64_BUFFSIZE 77
555 static void prefs_custom_header_val_from_file_cb(void)
557 gchar *filename = NULL;
558 gchar *contents = NULL;
559 const gchar *hdr = gtk_entry_get_text(GTK_ENTRY(customhdr.hdr_entry));
561 if (!strcmp(hdr, "Face"))
562 filename = filesel_select_file_open(_("Choose a png file"), NULL);
563 else if (!strcmp(hdr, "X-Face"))
564 filename = filesel_select_file_open(_("Choose an xbm file"), NULL);
566 filename = filesel_select_file_open(_("Choose a text file"), NULL);
568 if (!strcmp(hdr, "Face") || !strcmp(hdr, "X-Face")) {
569 if (filename && is_file_exist(filename)) {
572 gchar inbuf[B64_LINE_SIZE], outbuf[B64_BUFFSIZE];
575 GdkPixbufFormat *format = gdk_pixbuf_get_file_info(
578 if (format == NULL) {
579 alertpanel_error(_("This file isn't an image."));
583 if (w != 48 || h != 48) {
584 alertpanel_error(_("The chosen image isn't the correct size (48x48)."));
588 if (!strcmp(hdr, "Face")) {
589 if (get_file_size(filename) > 725) {
590 alertpanel_error(_("The image is too big; it must be maximum 725 bytes."));
594 if (g_ascii_strcasecmp("png", gdk_pixbuf_format_get_name(format))) {
595 alertpanel_error(_("The image isn't in the correct format (PNG)."));
596 printf("%s\n", gdk_pixbuf_format_get_name(format));
600 } else if (!strcmp(hdr, "X-Face")) {
601 gchar *tmp = NULL, *cmd = NULL;
603 if (g_ascii_strcasecmp("xbm", gdk_pixbuf_format_get_name(format))) {
604 alertpanel_error(_("The image isn't in the correct format (XBM)."));
605 printf("%s\n", gdk_pixbuf_format_get_name(format));
609 cmd = g_strdup_printf("compface %s", filename);
610 tmp = get_command_output(cmd);
612 if (tmp == NULL || strlen(tmp) == 0){
613 alertpanel_error(_("Couldn't call `compface`. Make sure it's in your $PATH."));
623 if (tmp[i] == '\r' || tmp[i] == '\n') {
627 contents = g_strdup_printf("%s%c",tmp2?tmp2:"", tmp[i]);
635 fp = g_fopen(filename, "rb");
641 while ((len = fread(inbuf, sizeof(gchar),
644 base64_encode(outbuf, inbuf, B64_LINE_SIZE);
647 contents = g_strconcat(tmp?tmp:"",outbuf, NULL);
650 if (len > 0 && feof(fp)) {
652 base64_encode(outbuf, inbuf, len);
653 contents = g_strconcat(tmp?tmp:"",outbuf, NULL);
662 contents = file_read_to_str(filename);
663 if (strchr(contents, '\n') || strchr(contents,'\r')) {
664 alertpanel_error(_("This file contains newlines."));
671 if (contents && strlen(contents))
672 gtk_entry_set_text(GTK_ENTRY(customhdr.val_entry), contents);
678 static void prefs_custom_header_add_cb(void)
680 prefs_custom_header_list_view_set_row(cur_ac);
683 static void prefs_custom_header_delete_cb(void)
689 if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection
690 (GTK_TREE_VIEW(customhdr.list_view)),
694 if (alertpanel(_("Delete header"),
695 _("Do you really want to delete this header?"),
696 GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL) != G_ALERTALTERNATE)
699 gtk_tree_model_get(model, &sel,
702 gtk_list_store_remove(GTK_LIST_STORE(model), &sel);
704 cur_ac->customhdr_list = g_slist_remove(cur_ac->customhdr_list, ch);
706 custom_header_free(ch);
709 static void prefs_custom_header_up(void)
711 GtkTreePath *prev, *sel;
713 GtkListStore *store = NULL;
714 GtkTreeModel *model = NULL;
717 if (!gtk_tree_selection_get_selected
718 (gtk_tree_view_get_selection
719 (GTK_TREE_VIEW(customhdr.list_view)),
723 store = (GtkListStore *)model;
724 sel = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &isel);
728 /* no move if we're at row 0... */
729 prev = gtk_tree_path_copy(sel);
730 if (!gtk_tree_path_prev(prev)) {
731 gtk_tree_path_free(prev);
732 gtk_tree_path_free(sel);
736 gtk_tree_model_get_iter(GTK_TREE_MODEL(store),
738 gtk_tree_path_free(sel);
739 gtk_tree_path_free(prev);
741 gtk_list_store_swap(store, &iprev, &isel);
742 prefs_custom_header_set_list(cur_ac);
745 static void prefs_custom_header_down(void)
747 GtkListStore *store = NULL;
748 GtkTreeModel *model = NULL;
749 GtkTreeIter next, sel;
751 if (!gtk_tree_selection_get_selected
752 (gtk_tree_view_get_selection
753 (GTK_TREE_VIEW(customhdr.list_view)),
757 store = (GtkListStore *)model;
759 if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &next))
762 gtk_list_store_swap(store, &next, &sel);
763 prefs_custom_header_set_list(cur_ac);
766 static gboolean prefs_custom_header_key_pressed(GtkWidget *widget,
770 if (event && event->keyval == GDK_Escape)
771 prefs_custom_header_cancel();
775 static void prefs_custom_header_ok(void)
777 prefs_custom_header_write_config(cur_ac);
778 gtk_widget_hide(customhdr.window);
781 static void prefs_custom_header_cancel(void)
783 prefs_custom_header_read_config(cur_ac);
784 gtk_widget_hide(customhdr.window);
787 static gint prefs_custom_header_deleted(GtkWidget *widget, GdkEventAny *event,
790 prefs_custom_header_cancel();
794 static GtkListStore* prefs_custom_header_create_data_store(void)
796 return gtk_list_store_new(N_CUSTHDR_COLUMNS,
802 static void prefs_custom_header_list_view_insert_header(GtkWidget *list_view,
803 GtkTreeIter *row_iter,
808 GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model
809 (GTK_TREE_VIEW(list_view)));
811 if (row_iter == NULL) {
813 gtk_list_store_append(list_store, &iter);
814 gtk_list_store_set(list_store, &iter,
815 CUSTHDR_STRING, header,
819 /* change existing */
820 CustomHeader *old_data;
822 gtk_tree_model_get(GTK_TREE_MODEL(list_store), row_iter,
823 CUSTHDR_DATA, &old_data,
826 custom_header_free(old_data);
828 gtk_list_store_set(list_store, row_iter,
829 CUSTHDR_STRING, header,
835 static GtkWidget *prefs_custom_header_list_view_create(void)
837 GtkTreeView *list_view;
838 GtkTreeSelection *selector;
841 model = GTK_TREE_MODEL(prefs_custom_header_create_data_store());
842 list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
843 g_object_unref(model);
845 gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
847 selector = gtk_tree_view_get_selection(list_view);
848 gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
849 gtk_tree_selection_set_select_function(selector, prefs_custom_header_selected,
852 /* create the columns */
853 prefs_custom_header_create_list_view_columns(GTK_WIDGET(list_view));
855 return GTK_WIDGET(list_view);
858 static void prefs_custom_header_create_list_view_columns(GtkWidget *list_view)
860 GtkTreeViewColumn *column;
861 GtkCellRenderer *renderer;
863 renderer = gtk_cell_renderer_text_new();
864 column = gtk_tree_view_column_new_with_attributes
865 (_("Current custom headers"),
867 "text", CUSTHDR_STRING,
869 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
872 #define ENTRY_SET_TEXT(entry, str) \
873 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
875 static gboolean prefs_custom_header_selected(GtkTreeSelection *selector,
878 gboolean currently_selected,
883 CustomHeader default_ch = { 0, "", NULL };
885 if (currently_selected)
888 if (!gtk_tree_model_get_iter(model, &iter, path))
891 gtk_tree_model_get(model, &iter,
895 if (!ch) ch = &default_ch;
897 ENTRY_SET_TEXT(customhdr.hdr_entry, ch->name);
898 ENTRY_SET_TEXT(customhdr.val_entry, ch->value);
903 #undef ENTRY_SET_TEXT