2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 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/>.
22 #include "claws-features.h"
28 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
37 #include "prefs_gtk.h"
38 #include "prefs_customheader.h"
39 #include "prefs_common.h"
40 #include "prefs_account.h"
41 #include "mainwindow.h"
42 #include "foldersel.h"
43 #include "manage_window.h"
44 #include "customheader.h"
48 #include "alertpanel.h"
53 CUSTHDR_STRING
, /*!< display string managed by list store */
54 CUSTHDR_DATA
, /*!< string managed by us */
58 static struct CustomHdr
{
62 GtkWidget
*cancel_btn
;
71 /* widget creating functions */
72 static void prefs_custom_header_create (void);
74 static void prefs_custom_header_set_dialog (PrefsAccount
*ac
);
75 static void prefs_custom_header_set_list (PrefsAccount
*ac
);
76 static void prefs_custom_header_list_view_set_row (PrefsAccount
*ac
);
78 /* callback functions */
79 static void prefs_custom_header_add_cb (void);
80 static void prefs_custom_header_val_from_file_cb(void);
81 static void prefs_custom_header_delete_cb (void);
82 static void prefs_custom_header_up (void);
83 static void prefs_custom_header_down (void);
85 static gboolean
prefs_custom_header_key_pressed (GtkWidget
*widget
,
88 static void prefs_custom_header_ok (void);
89 static void prefs_custom_header_cancel (void);
90 static gint
prefs_custom_header_deleted (GtkWidget
*widget
,
94 static GtkListStore
* prefs_custom_header_create_data_store (void);
96 static void prefs_custom_header_list_view_insert_header (GtkWidget
*list_view
,
97 GtkTreeIter
*row_iter
,
101 static GtkWidget
*prefs_custom_header_list_view_create (void);
103 static void prefs_custom_header_create_list_view_columns (GtkWidget
*list_view
);
105 static gboolean
prefs_custom_header_selected (GtkTreeSelection
*selector
,
108 gboolean currently_selected
,
112 static PrefsAccount
*cur_ac
= NULL
;
114 void prefs_custom_header_open(PrefsAccount
*ac
)
116 if (!customhdr
.window
) {
117 prefs_custom_header_create();
120 manage_window_set_transient(GTK_WINDOW(customhdr
.window
));
121 gtk_widget_grab_focus(customhdr
.ok_btn
);
123 prefs_custom_header_set_dialog(ac
);
127 gtk_widget_show(customhdr
.window
);
128 gtk_window_set_modal(GTK_WINDOW(customhdr
.window
), TRUE
);
131 static void prefs_custom_header_create(void)
137 GtkWidget
*cancel_btn
;
139 GtkWidget
*confirm_area
;
144 GtkWidget
*hdr_label
;
145 GtkWidget
*hdr_combo
;
146 GtkWidget
*val_label
;
147 GtkWidget
*val_entry
;
158 GtkWidget
*ch_scrolledwin
;
159 GtkWidget
*list_view
;
165 debug_print("Creating custom header setting window...\n");
167 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_customheader");
168 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
169 gtk_window_set_position (GTK_WINDOW (window
), GTK_WIN_POS_CENTER
);
170 gtk_window_set_resizable(GTK_WINDOW (window
), TRUE
);
172 vbox
= gtk_vbox_new (FALSE
, 6);
173 gtk_widget_show (vbox
);
174 gtk_container_add (GTK_CONTAINER (window
), vbox
);
176 gtkut_stock_button_set_create(&confirm_area
, &cancel_btn
, GTK_STOCK_CANCEL
,
177 &ok_btn
, GTK_STOCK_OK
,
179 gtk_widget_show (confirm_area
);
180 gtk_box_pack_end (GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
181 gtk_widget_grab_default (ok_btn
);
183 gtk_window_set_title (GTK_WINDOW(window
), _("Custom header configuration"));
184 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
185 g_signal_connect (G_OBJECT(window
), "delete_event",
186 G_CALLBACK(prefs_custom_header_deleted
),
188 g_signal_connect (G_OBJECT(window
), "key_press_event",
189 G_CALLBACK(prefs_custom_header_key_pressed
),
191 g_signal_connect (G_OBJECT(ok_btn
), "clicked",
192 G_CALLBACK(prefs_custom_header_ok
), NULL
);
193 g_signal_connect (G_OBJECT(cancel_btn
), "clicked",
194 G_CALLBACK(prefs_custom_header_cancel
), NULL
);
196 vbox1
= gtk_vbox_new (FALSE
, VSPACING
);
197 gtk_widget_show (vbox1
);
198 gtk_box_pack_start (GTK_BOX (vbox
), vbox1
, TRUE
, TRUE
, 0);
199 gtk_container_set_border_width (GTK_CONTAINER (vbox1
), 2);
201 table1
= gtk_table_new (3, 2, FALSE
);
202 gtk_widget_show (table1
);
203 gtk_box_pack_start (GTK_BOX (vbox1
), table1
,
205 gtk_table_set_row_spacings (GTK_TABLE (table1
), 8);
206 gtk_table_set_col_spacings (GTK_TABLE (table1
), 8);
208 hdr_label
= gtk_label_new (_("Header"));
209 gtk_widget_show (hdr_label
);
210 gtk_table_attach (GTK_TABLE (table1
), hdr_label
, 0, 1, 0, 1,
211 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
213 gtk_misc_set_alignment (GTK_MISC (hdr_label
), 0, 0.5);
215 hdr_combo
= combobox_text_new(TRUE
, "User-Agent", "Face", "X-Face",
216 "X-Operating-System", NULL
);
217 gtk_table_attach (GTK_TABLE (table1
), hdr_combo
, 0, 1, 1, 2,
218 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
220 gtk_widget_set_size_request (hdr_combo
, 150, -1);
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
= gtkut_get_browse_file_btn(_("Bro_wse"));
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 preview
= gtk_image_new ();
308 gtk_widget_show (preview
);
309 gtk_box_pack_start (GTK_BOX (btn_vbox
), preview
, FALSE
, FALSE
, 0);
311 gtk_widget_show_all(window
);
313 customhdr
.window
= window
;
314 customhdr
.ok_btn
= ok_btn
;
315 customhdr
.cancel_btn
= cancel_btn
;
316 customhdr
.preview
= preview
;
318 customhdr
.hdr_combo
= hdr_combo
;
319 customhdr
.hdr_entry
= gtk_bin_get_child(GTK_BIN((hdr_combo
)));
320 customhdr
.val_entry
= val_entry
;
322 customhdr
.list_view
= list_view
;
325 void prefs_custom_header_read_config(PrefsAccount
*ac
)
329 gchar buf
[PREFSBUFSIZE
];
332 debug_print("Reading custom header configuration...\n");
334 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
335 CUSTOM_HEADER_RC
, NULL
);
336 if ((fp
= g_fopen(rcpath
, "rb")) == NULL
) {
337 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "fopen");
339 ac
->customhdr_list
= NULL
;
344 /* remove all previous headers list */
345 while (ac
->customhdr_list
!= NULL
) {
346 ch
= (CustomHeader
*)ac
->customhdr_list
->data
;
347 ac
->customhdr_list
= g_slist_remove(ac
->customhdr_list
, ch
);
348 custom_header_free(ch
);
351 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
352 ch
= custom_header_read_str(buf
);
354 if (ch
->account_id
== ac
->account_id
) {
356 g_slist_append(ac
->customhdr_list
, ch
);
358 custom_header_free(ch
);
365 static void prefs_custom_header_write_config(PrefsAccount
*ac
)
370 gchar buf
[PREFSBUFSIZE
];
374 GSList
*all_hdrs
= NULL
;
376 debug_print("Writing custom header configuration...\n");
378 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
379 CUSTOM_HEADER_RC
, NULL
);
381 if ((fp
= g_fopen(rcpath
, "rb")) == NULL
) {
382 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "fopen");
386 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
387 ch
= custom_header_read_str(buf
);
389 if (ch
->account_id
!= ac
->account_id
)
391 g_slist_append(all_hdrs
, ch
);
393 custom_header_free(ch
);
400 if ((pfile
= prefs_write_open(rcpath
)) == NULL
) {
401 g_warning("failed to write configuration to file");
406 for (cur
= all_hdrs
; cur
!= NULL
; cur
= cur
->next
) {
407 CustomHeader
*hdr
= (CustomHeader
*)cur
->data
;
410 chstr
= custom_header_get_str(hdr
);
411 if (fputs(chstr
, pfile
->fp
) == EOF
||
412 fputc('\n', pfile
->fp
) == EOF
) {
413 FILE_OP_ERROR(rcpath
, "fputs || fputc");
414 prefs_file_close_revert(pfile
);
422 for (cur
= ac
->customhdr_list
; cur
!= NULL
; cur
= cur
->next
) {
423 CustomHeader
*hdr
= (CustomHeader
*)cur
->data
;
426 chstr
= custom_header_get_str(hdr
);
427 if (fputs(chstr
, pfile
->fp
) == EOF
||
428 fputc('\n', pfile
->fp
) == EOF
) {
429 FILE_OP_ERROR(rcpath
, "fputs || fputc");
430 prefs_file_close_revert(pfile
);
440 while (all_hdrs
!= NULL
) {
441 ch
= (CustomHeader
*)all_hdrs
->data
;
442 all_hdrs
= g_slist_remove(all_hdrs
, ch
);
443 custom_header_free(ch
);
446 if (prefs_file_close(pfile
) < 0) {
447 g_warning("failed to write configuration to file");
452 static void prefs_custom_header_set_dialog(PrefsAccount
*ac
)
457 store
= GTK_LIST_STORE(gtk_tree_view_get_model
458 (GTK_TREE_VIEW(customhdr
.list_view
)));
459 gtk_list_store_clear(store
);
461 for (cur
= ac
->customhdr_list
; cur
!= NULL
; cur
= cur
->next
) {
462 CustomHeader
*ch
= (CustomHeader
*)cur
->data
;
465 ch_str
= g_strdup_printf("%s: %s", ch
->name
,
466 ch
->value
? ch
->value
: "");
468 prefs_custom_header_list_view_insert_header
469 (customhdr
.list_view
, NULL
, ch_str
, ch
);
475 static void prefs_custom_header_set_list(PrefsAccount
*ac
)
481 g_slist_free(ac
->customhdr_list
);
482 ac
->customhdr_list
= NULL
;
484 store
= GTK_LIST_STORE(gtk_tree_view_get_model
485 (GTK_TREE_VIEW(customhdr
.list_view
)));
487 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store
), &iter
)) {
489 gtk_tree_model_get(GTK_TREE_MODEL(store
), &iter
,
492 ac
->customhdr_list
= g_slist_append(ac
->customhdr_list
, ch
);
493 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store
),
498 static void prefs_custom_header_list_view_set_row(PrefsAccount
*ac
)
501 const gchar
*entry_text
;
504 entry_text
= gtk_entry_get_text(GTK_ENTRY(customhdr
.hdr_entry
));
505 if (entry_text
[0] == '\0') {
506 alertpanel_error(_("Header name is not set."));
510 while (*entry_text
&&
511 (*entry_text
== '\n' || *entry_text
== '\r' ||
512 *entry_text
== '\t' || *entry_text
== ' '))
515 if (!custom_header_is_allowed(entry_text
)) {
516 alertpanel_error(_("This Header name is not allowed as a custom header."));
520 ch
= g_new0(CustomHeader
, 1);
522 ch
->account_id
= ac
->account_id
;
524 ch
->name
= g_strdup(entry_text
);
525 unfold_line(ch
->name
);
526 g_strstrip(ch
->name
);
527 gtk_entry_set_text(GTK_ENTRY(customhdr
.hdr_entry
), ch
->name
);
529 entry_text
= gtk_entry_get_text(GTK_ENTRY(customhdr
.val_entry
));
530 while (*entry_text
&&
531 (*entry_text
== '\n' || *entry_text
== '\r' ||
532 *entry_text
== '\t' || *entry_text
== ' '))
535 if (entry_text
[0] != '\0') {
536 ch
->value
= g_strdup(entry_text
);
537 unfold_line(ch
->value
);
538 g_strstrip(ch
->value
);
539 gtk_entry_set_text(GTK_ENTRY(customhdr
.val_entry
), ch
->value
);
542 ch_str
= g_strdup_printf("%s: %s", ch
->name
,
543 ch
->value
? ch
->value
: "");
545 prefs_custom_header_list_view_insert_header
546 (customhdr
.list_view
, NULL
, ch_str
, ch
);
550 prefs_custom_header_set_list(cur_ac
);
554 #define B64_LINE_SIZE 57
555 #define B64_BUFFSIZE 77
556 static void prefs_custom_header_val_from_file_cb(void)
558 gchar
*filename
= NULL
;
559 gchar
*contents
= NULL
;
560 const gchar
*hdr
= gtk_entry_get_text(GTK_ENTRY(customhdr
.hdr_entry
));
562 if (!strcmp(hdr
, "Face"))
563 filename
= filesel_select_file_open(_("Choose a PNG file"), NULL
);
564 else if (!strcmp(hdr
, "X-Face"))
565 filename
= filesel_select_file_open(_("Choose an XBM file"), NULL
);
567 filename
= filesel_select_file_open(_("Choose a text file"), NULL
);
569 if (!strcmp(hdr
, "Face") || !strcmp(hdr
, "X-Face")) {
570 if (filename
&& is_file_exist(filename
)) {
573 gchar inbuf
[B64_LINE_SIZE
], *outbuf
;
576 GdkPixbufFormat
*format
= gdk_pixbuf_get_file_info(
579 if (format
== NULL
) {
580 alertpanel_error(_("This file isn't an image."));
584 if (w
!= 48 || h
!= 48) {
585 alertpanel_error(_("The chosen image isn't the correct size (48x48)."));
589 if (!strcmp(hdr
, "Face")) {
590 if (get_file_size(filename
) > 725) {
591 alertpanel_error(_("The image is too big; it must be maximum 725 bytes."));
595 if (g_ascii_strcasecmp("png", gdk_pixbuf_format_get_name(format
))) {
596 alertpanel_error(_("The image isn't in the correct format (PNG)."));
597 g_print("%s\n", gdk_pixbuf_format_get_name(format
));
601 } else if (!strcmp(hdr
, "X-Face")) {
602 gchar
*tmp
= NULL
, *cmd
= NULL
;
604 if (g_ascii_strcasecmp("xbm", gdk_pixbuf_format_get_name(format
))) {
605 alertpanel_error(_("The image isn't in the correct format (XBM)."));
606 g_print("%s\n", gdk_pixbuf_format_get_name(format
));
610 cmd
= g_strdup_printf("compface %s", filename
);
611 tmp
= get_command_output(cmd
);
613 if (tmp
== NULL
|| *tmp
== '\0') {
614 alertpanel_error(_("Couldn't call `compface`. Make sure it's in your $PATH."));
619 if (strstr(tmp
, "compface:")) {
620 alertpanel_error(_("Compface error: %s"), tmp
);
630 if (tmp
[i
] == '\r' || tmp
[i
] == '\n') {
634 contents
= g_strdup_printf("%s%c",tmp2
?tmp2
:"", tmp
[i
]);
642 fp
= g_fopen(filename
, "rb");
648 while ((len
= fread(inbuf
, sizeof(gchar
),
651 outbuf
= g_base64_encode(inbuf
, B64_LINE_SIZE
);
654 contents
= g_strconcat(tmp
?tmp
:"",outbuf
, NULL
);
658 if (len
> 0 && feof(fp
)) {
660 outbuf
= g_base64_encode(inbuf
, len
);
661 contents
= g_strconcat(tmp
?tmp
:"",outbuf
, NULL
);
671 contents
= file_read_to_str(filename
);
672 if (strchr(contents
, '\n') || strchr(contents
,'\r')) {
673 alertpanel_error(_("This file contains newlines."));
680 if (contents
&& strlen(contents
))
681 gtk_entry_set_text(GTK_ENTRY(customhdr
.val_entry
), contents
);
687 static void prefs_custom_header_add_cb(void)
689 prefs_custom_header_list_view_set_row(cur_ac
);
692 static void prefs_custom_header_delete_cb(void)
698 if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection
699 (GTK_TREE_VIEW(customhdr
.list_view
)),
703 if (alertpanel(_("Delete header"),
704 _("Do you really want to delete this header?"),
705 GTK_STOCK_CANCEL
, GTK_STOCK_DELETE
, NULL
) != G_ALERTALTERNATE
)
708 gtk_tree_model_get(model
, &sel
,
711 gtk_list_store_remove(GTK_LIST_STORE(model
), &sel
);
713 cur_ac
->customhdr_list
= g_slist_remove(cur_ac
->customhdr_list
, ch
);
715 custom_header_free(ch
);
718 static void prefs_custom_header_up(void)
720 GtkTreePath
*prev
, *sel
;
722 GtkListStore
*store
= NULL
;
723 GtkTreeModel
*model
= NULL
;
726 if (!gtk_tree_selection_get_selected
727 (gtk_tree_view_get_selection
728 (GTK_TREE_VIEW(customhdr
.list_view
)),
732 store
= (GtkListStore
*)model
;
733 sel
= gtk_tree_model_get_path(GTK_TREE_MODEL(store
), &isel
);
737 /* no move if we're at row 0... */
738 prev
= gtk_tree_path_copy(sel
);
739 if (!gtk_tree_path_prev(prev
)) {
740 gtk_tree_path_free(prev
);
741 gtk_tree_path_free(sel
);
745 gtk_tree_model_get_iter(GTK_TREE_MODEL(store
),
747 gtk_tree_path_free(sel
);
748 gtk_tree_path_free(prev
);
750 gtk_list_store_swap(store
, &iprev
, &isel
);
751 prefs_custom_header_set_list(cur_ac
);
754 static void prefs_custom_header_down(void)
756 GtkListStore
*store
= NULL
;
757 GtkTreeModel
*model
= NULL
;
758 GtkTreeIter next
, sel
;
760 if (!gtk_tree_selection_get_selected
761 (gtk_tree_view_get_selection
762 (GTK_TREE_VIEW(customhdr
.list_view
)),
766 store
= (GtkListStore
*)model
;
768 if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(store
), &next
))
771 gtk_list_store_swap(store
, &next
, &sel
);
772 prefs_custom_header_set_list(cur_ac
);
775 static gboolean
prefs_custom_header_key_pressed(GtkWidget
*widget
,
779 if (event
&& event
->keyval
== GDK_KEY_Escape
)
780 prefs_custom_header_cancel();
784 static void prefs_custom_header_ok(void)
786 prefs_custom_header_write_config(cur_ac
);
787 gtk_widget_hide(customhdr
.window
);
788 gtk_window_set_modal(GTK_WINDOW(customhdr
.window
), FALSE
);
791 static void prefs_custom_header_cancel(void)
793 prefs_custom_header_read_config(cur_ac
);
794 gtk_widget_hide(customhdr
.window
);
795 gtk_window_set_modal(GTK_WINDOW(customhdr
.window
), FALSE
);
798 static gint
prefs_custom_header_deleted(GtkWidget
*widget
, GdkEventAny
*event
,
801 prefs_custom_header_cancel();
805 static GtkListStore
* prefs_custom_header_create_data_store(void)
807 return gtk_list_store_new(N_CUSTHDR_COLUMNS
,
813 static void prefs_custom_header_list_view_insert_header(GtkWidget
*list_view
,
814 GtkTreeIter
*row_iter
,
819 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model
820 (GTK_TREE_VIEW(list_view
)));
822 if (row_iter
== NULL
) {
824 gtk_list_store_append(list_store
, &iter
);
825 gtk_list_store_set(list_store
, &iter
,
826 CUSTHDR_STRING
, header
,
830 /* change existing */
831 CustomHeader
*old_data
;
833 gtk_tree_model_get(GTK_TREE_MODEL(list_store
), row_iter
,
834 CUSTHDR_DATA
, &old_data
,
837 custom_header_free(old_data
);
839 gtk_list_store_set(list_store
, row_iter
,
840 CUSTHDR_STRING
, header
,
846 static GtkWidget
*prefs_custom_header_list_view_create(void)
848 GtkTreeView
*list_view
;
849 GtkTreeSelection
*selector
;
852 model
= GTK_TREE_MODEL(prefs_custom_header_create_data_store());
853 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
854 g_object_unref(model
);
856 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
857 gtk_tree_view_set_reorderable(list_view
, TRUE
);
859 selector
= gtk_tree_view_get_selection(list_view
);
860 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
861 gtk_tree_selection_set_select_function(selector
, prefs_custom_header_selected
,
864 /* create the columns */
865 prefs_custom_header_create_list_view_columns(GTK_WIDGET(list_view
));
867 return GTK_WIDGET(list_view
);
870 static void prefs_custom_header_create_list_view_columns(GtkWidget
*list_view
)
872 GtkTreeViewColumn
*column
;
873 GtkCellRenderer
*renderer
;
875 renderer
= gtk_cell_renderer_text_new();
876 column
= gtk_tree_view_column_new_with_attributes
877 (_("Current custom headers"),
879 "text", CUSTHDR_STRING
,
881 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
884 #define ENTRY_SET_TEXT(entry, str) \
885 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
887 static gboolean
prefs_custom_header_selected(GtkTreeSelection
*selector
,
890 gboolean currently_selected
,
897 CustomHeader default_ch
= { 0, "", NULL
};
899 if (currently_selected
)
902 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
905 gtk_tree_model_get(model
, &iter
,
909 if (!ch
) ch
= &default_ch
;
911 ENTRY_SET_TEXT(customhdr
.hdr_entry
, ch
->name
);
912 ENTRY_SET_TEXT(customhdr
.val_entry
, ch
->value
);
913 if (!strcmp2("Face",ch
->name
)) {
914 preview
= GTK_IMAGE(face_get_from_header (ch
->value
));
915 pixbuf
= gtk_image_get_pixbuf(preview
);
916 gtk_image_set_from_pixbuf (GTK_IMAGE(customhdr
.preview
), pixbuf
);
917 gtk_widget_show(customhdr
.preview
);
918 g_object_ref_sink (G_OBJECT(preview
));
921 else if (!strcmp2("X-Face", ch
->name
)) {
922 preview
= GTK_IMAGE(xface_get_from_header(ch
->value
));
923 pixbuf
= gtk_image_get_pixbuf(preview
);
924 gtk_image_set_from_pixbuf (GTK_IMAGE(customhdr
.preview
), pixbuf
);
925 gtk_widget_show(customhdr
.preview
);
926 g_object_ref_sink (G_OBJECT(preview
));
930 gtk_widget_hide(customhdr
.preview
);
935 #undef ENTRY_SET_TEXT