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"
51 #include "file-utils.h"
54 CUSTHDR_STRING
, /*!< display string managed by list store */
55 CUSTHDR_DATA
, /*!< string managed by us */
59 static struct CustomHdr
{
63 GtkWidget
*cancel_btn
;
72 /* widget creating functions */
73 static void prefs_custom_header_create (void);
75 static void prefs_custom_header_set_dialog (PrefsAccount
*ac
);
76 static void prefs_custom_header_set_list (PrefsAccount
*ac
);
77 static void prefs_custom_header_list_view_set_row (PrefsAccount
*ac
);
79 /* callback functions */
80 static void prefs_custom_header_add_cb (void);
81 static void prefs_custom_header_val_from_file_cb(void);
82 static void prefs_custom_header_delete_cb (void);
83 static void prefs_custom_header_up (void);
84 static void prefs_custom_header_down (void);
86 static gboolean
prefs_custom_header_key_pressed (GtkWidget
*widget
,
89 static void prefs_custom_header_ok (void);
90 static void prefs_custom_header_cancel (void);
91 static gint
prefs_custom_header_deleted (GtkWidget
*widget
,
95 static GtkListStore
* prefs_custom_header_create_data_store (void);
97 static void prefs_custom_header_list_view_insert_header (GtkWidget
*list_view
,
98 GtkTreeIter
*row_iter
,
102 static GtkWidget
*prefs_custom_header_list_view_create (void);
104 static void prefs_custom_header_create_list_view_columns (GtkWidget
*list_view
);
106 static gboolean
prefs_custom_header_selected (GtkTreeSelection
*selector
,
109 gboolean currently_selected
,
113 static PrefsAccount
*cur_ac
= NULL
;
115 void prefs_custom_header_open(PrefsAccount
*ac
)
117 if (!customhdr
.window
) {
118 prefs_custom_header_create();
121 manage_window_set_transient(GTK_WINDOW(customhdr
.window
));
122 gtk_widget_grab_focus(customhdr
.ok_btn
);
124 prefs_custom_header_set_dialog(ac
);
128 gtk_widget_show(customhdr
.window
);
129 gtk_window_set_modal(GTK_WINDOW(customhdr
.window
), TRUE
);
132 static void prefs_custom_header_create(void)
138 GtkWidget
*cancel_btn
;
140 GtkWidget
*confirm_area
;
145 GtkWidget
*hdr_label
;
146 GtkWidget
*hdr_combo
;
147 GtkWidget
*val_label
;
148 GtkWidget
*val_entry
;
159 GtkWidget
*ch_scrolledwin
;
160 GtkWidget
*list_view
;
166 debug_print("Creating custom header setting window...\n");
168 window
= gtkut_window_new(GTK_WINDOW_TOPLEVEL
, "prefs_customheader");
169 gtk_container_set_border_width (GTK_CONTAINER (window
), 8);
170 gtk_window_set_position (GTK_WINDOW (window
), GTK_WIN_POS_CENTER
);
171 gtk_window_set_resizable(GTK_WINDOW (window
), TRUE
);
172 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
174 vbox
= gtk_vbox_new (FALSE
, 6);
175 gtk_widget_show (vbox
);
176 gtk_container_add (GTK_CONTAINER (window
), vbox
);
178 gtkut_stock_button_set_create(&confirm_area
, &cancel_btn
, GTK_STOCK_CANCEL
,
179 &ok_btn
, GTK_STOCK_OK
,
181 gtk_widget_show (confirm_area
);
182 gtk_box_pack_end (GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
183 gtk_widget_grab_default (ok_btn
);
185 gtk_window_set_title (GTK_WINDOW(window
), _("Custom header configuration"));
186 MANAGE_WINDOW_SIGNALS_CONNECT (window
);
187 g_signal_connect (G_OBJECT(window
), "delete_event",
188 G_CALLBACK(prefs_custom_header_deleted
),
190 g_signal_connect (G_OBJECT(window
), "key_press_event",
191 G_CALLBACK(prefs_custom_header_key_pressed
),
193 g_signal_connect (G_OBJECT(ok_btn
), "clicked",
194 G_CALLBACK(prefs_custom_header_ok
), NULL
);
195 g_signal_connect (G_OBJECT(cancel_btn
), "clicked",
196 G_CALLBACK(prefs_custom_header_cancel
), NULL
);
198 vbox1
= gtk_vbox_new (FALSE
, VSPACING
);
199 gtk_widget_show (vbox1
);
200 gtk_box_pack_start (GTK_BOX (vbox
), vbox1
, TRUE
, TRUE
, 0);
201 gtk_container_set_border_width (GTK_CONTAINER (vbox1
), 2);
203 table1
= gtk_table_new (3, 2, FALSE
);
204 gtk_widget_show (table1
);
205 gtk_box_pack_start (GTK_BOX (vbox1
), table1
,
207 gtk_table_set_row_spacings (GTK_TABLE (table1
), 8);
208 gtk_table_set_col_spacings (GTK_TABLE (table1
), 8);
210 hdr_label
= gtk_label_new (_("Header"));
211 gtk_widget_show (hdr_label
);
212 gtk_table_attach (GTK_TABLE (table1
), hdr_label
, 0, 1, 0, 1,
213 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
215 gtk_misc_set_alignment (GTK_MISC (hdr_label
), 0, 0.5);
217 hdr_combo
= combobox_text_new(TRUE
, "User-Agent", "Face", "X-Face",
218 "X-Operating-System", NULL
);
219 gtk_table_attach (GTK_TABLE (table1
), hdr_combo
, 0, 1, 1, 2,
220 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
223 val_label
= gtk_label_new (_("Value"));
224 gtk_widget_show (val_label
);
225 gtk_table_attach (GTK_TABLE (table1
), val_label
, 1, 2, 0, 1,
226 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
228 gtk_misc_set_alignment (GTK_MISC (val_label
), 0, 0.5);
230 val_entry
= gtk_entry_new ();
231 gtk_widget_show (val_entry
);
232 gtk_table_attach (GTK_TABLE (table1
), val_entry
, 1, 2, 1, 2,
233 GTK_EXPAND
| GTK_SHRINK
| GTK_FILL
,
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);
255 btn_hbox
= gtk_hbox_new (TRUE
, 4);
256 gtk_widget_show (btn_hbox
);
257 gtk_box_pack_start (GTK_BOX (reg_hbox
), btn_hbox
, FALSE
, FALSE
, 0);
259 add_btn
= gtk_button_new_from_stock (GTK_STOCK_ADD
);
260 gtk_widget_show (add_btn
);
261 gtk_box_pack_start (GTK_BOX (btn_hbox
), add_btn
, FALSE
, TRUE
, 0);
262 g_signal_connect (G_OBJECT (add_btn
), "clicked",
263 G_CALLBACK (prefs_custom_header_add_cb
),
266 del_btn
= gtk_button_new_from_stock (GTK_STOCK_DELETE
);
267 gtk_widget_show (del_btn
);
268 gtk_box_pack_start (GTK_BOX (btn_hbox
), del_btn
, FALSE
, TRUE
, 0);
269 g_signal_connect (G_OBJECT (del_btn
), "clicked",
270 G_CALLBACK (prefs_custom_header_delete_cb
),
274 ch_hbox
= gtk_hbox_new (FALSE
, 8);
275 gtk_widget_show (ch_hbox
);
276 gtk_box_pack_start (GTK_BOX (vbox1
), ch_hbox
, TRUE
, TRUE
, 0);
278 ch_scrolledwin
= gtk_scrolled_window_new (NULL
, NULL
);
279 gtk_widget_show (ch_scrolledwin
);
280 gtk_box_pack_start (GTK_BOX (ch_hbox
), ch_scrolledwin
, TRUE
, TRUE
, 0);
281 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ch_scrolledwin
),
282 GTK_POLICY_AUTOMATIC
,
283 GTK_POLICY_AUTOMATIC
);
285 list_view
= prefs_custom_header_list_view_create();
286 gtk_widget_show (list_view
);
287 gtk_container_add (GTK_CONTAINER (ch_scrolledwin
), list_view
);
289 btn_vbox
= gtk_vbox_new (FALSE
, 8);
290 gtk_widget_show (btn_vbox
);
291 gtk_box_pack_start (GTK_BOX (ch_hbox
), btn_vbox
, FALSE
, FALSE
, 0);
293 up_btn
= gtk_button_new_from_stock (GTK_STOCK_GO_UP
);
294 gtk_widget_show (up_btn
);
295 gtk_box_pack_start (GTK_BOX (btn_vbox
), up_btn
, FALSE
, FALSE
, 0);
296 g_signal_connect (G_OBJECT (up_btn
), "clicked",
297 G_CALLBACK (prefs_custom_header_up
), NULL
);
299 down_btn
= gtk_button_new_from_stock (GTK_STOCK_GO_DOWN
);
300 gtk_widget_show (down_btn
);
301 gtk_box_pack_start (GTK_BOX (btn_vbox
), down_btn
, FALSE
, FALSE
, 0);
302 g_signal_connect (G_OBJECT (down_btn
), "clicked",
303 G_CALLBACK (prefs_custom_header_down
), NULL
);
305 preview
= gtk_image_new ();
306 gtk_widget_show (preview
);
307 gtk_box_pack_start (GTK_BOX (btn_vbox
), preview
, FALSE
, FALSE
, 0);
309 gtk_widget_show_all(window
);
311 customhdr
.window
= window
;
312 customhdr
.ok_btn
= ok_btn
;
313 customhdr
.cancel_btn
= cancel_btn
;
314 customhdr
.preview
= preview
;
316 customhdr
.hdr_combo
= hdr_combo
;
317 customhdr
.hdr_entry
= gtk_bin_get_child(GTK_BIN((hdr_combo
)));
318 customhdr
.val_entry
= val_entry
;
320 customhdr
.list_view
= list_view
;
323 void prefs_custom_header_read_config(PrefsAccount
*ac
)
327 gchar buf
[PREFSBUFSIZE
];
330 debug_print("Reading custom header configuration...\n");
332 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
333 CUSTOM_HEADER_RC
, NULL
);
334 if ((fp
= claws_fopen(rcpath
, "rb")) == NULL
) {
335 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "claws_fopen");
337 ac
->customhdr_list
= NULL
;
342 /* remove all previous headers list */
343 while (ac
->customhdr_list
!= NULL
) {
344 ch
= (CustomHeader
*)ac
->customhdr_list
->data
;
345 ac
->customhdr_list
= g_slist_remove(ac
->customhdr_list
, ch
);
346 custom_header_free(ch
);
349 while (claws_fgets(buf
, sizeof(buf
), fp
) != NULL
) {
350 ch
= custom_header_read_str(buf
);
352 if (ch
->account_id
== ac
->account_id
) {
354 g_slist_append(ac
->customhdr_list
, ch
);
356 custom_header_free(ch
);
363 static void prefs_custom_header_write_config(PrefsAccount
*ac
)
368 gchar buf
[PREFSBUFSIZE
];
372 GSList
*all_hdrs
= NULL
;
374 debug_print("Writing custom header configuration...\n");
376 rcpath
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
377 CUSTOM_HEADER_RC
, NULL
);
379 if ((fp
= claws_fopen(rcpath
, "rb")) == NULL
) {
380 if (ENOENT
!= errno
) FILE_OP_ERROR(rcpath
, "claws_fopen");
384 while (claws_fgets(buf
, sizeof(buf
), fp
) != NULL
) {
385 ch
= custom_header_read_str(buf
);
387 if (ch
->account_id
!= ac
->account_id
)
389 g_slist_append(all_hdrs
, ch
);
391 custom_header_free(ch
);
398 if ((pfile
= prefs_write_open(rcpath
)) == NULL
) {
399 g_warning("failed to write configuration to file");
404 for (cur
= all_hdrs
; cur
!= NULL
; cur
= cur
->next
) {
405 CustomHeader
*hdr
= (CustomHeader
*)cur
->data
;
408 chstr
= custom_header_get_str(hdr
);
409 if (claws_fputs(chstr
, pfile
->fp
) == EOF
||
410 claws_fputc('\n', pfile
->fp
) == EOF
) {
411 FILE_OP_ERROR(rcpath
, "claws_fputs || claws_fputc");
412 prefs_file_close_revert(pfile
);
420 for (cur
= ac
->customhdr_list
; cur
!= NULL
; cur
= cur
->next
) {
421 CustomHeader
*hdr
= (CustomHeader
*)cur
->data
;
424 chstr
= custom_header_get_str(hdr
);
425 if (claws_fputs(chstr
, pfile
->fp
) == EOF
||
426 claws_fputc('\n', pfile
->fp
) == EOF
) {
427 FILE_OP_ERROR(rcpath
, "claws_fputs || claws_fputc");
428 prefs_file_close_revert(pfile
);
438 while (all_hdrs
!= NULL
) {
439 ch
= (CustomHeader
*)all_hdrs
->data
;
440 all_hdrs
= g_slist_remove(all_hdrs
, ch
);
441 custom_header_free(ch
);
444 if (prefs_file_close(pfile
) < 0) {
445 g_warning("failed to write configuration to file");
450 static void prefs_custom_header_set_dialog(PrefsAccount
*ac
)
455 store
= GTK_LIST_STORE(gtk_tree_view_get_model
456 (GTK_TREE_VIEW(customhdr
.list_view
)));
457 gtk_list_store_clear(store
);
459 for (cur
= ac
->customhdr_list
; cur
!= NULL
; cur
= cur
->next
) {
460 CustomHeader
*ch
= (CustomHeader
*)cur
->data
;
463 ch_str
= g_strdup_printf("%s: %s", ch
->name
,
464 ch
->value
? ch
->value
: "");
466 prefs_custom_header_list_view_insert_header
467 (customhdr
.list_view
, NULL
, ch_str
, ch
);
473 static void prefs_custom_header_set_list(PrefsAccount
*ac
)
479 g_slist_free(ac
->customhdr_list
);
480 ac
->customhdr_list
= NULL
;
482 store
= GTK_LIST_STORE(gtk_tree_view_get_model
483 (GTK_TREE_VIEW(customhdr
.list_view
)));
485 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store
), &iter
)) {
487 gtk_tree_model_get(GTK_TREE_MODEL(store
), &iter
,
490 ac
->customhdr_list
= g_slist_append(ac
->customhdr_list
, ch
);
491 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store
),
496 static void prefs_custom_header_list_view_set_row(PrefsAccount
*ac
)
499 const gchar
*entry_text
;
502 entry_text
= gtk_entry_get_text(GTK_ENTRY(customhdr
.hdr_entry
));
503 if (entry_text
[0] == '\0') {
504 alertpanel_error(_("Header name is not set."));
508 while (*entry_text
&&
509 (*entry_text
== '\n' || *entry_text
== '\r' ||
510 *entry_text
== '\t' || *entry_text
== ' '))
513 if (!custom_header_is_allowed(entry_text
)) {
514 alertpanel_error(_("This Header name is not allowed as a custom header."));
518 ch
= g_new0(CustomHeader
, 1);
520 ch
->account_id
= ac
->account_id
;
522 ch
->name
= g_strdup(entry_text
);
523 unfold_line(ch
->name
);
524 g_strstrip(ch
->name
);
525 gtk_entry_set_text(GTK_ENTRY(customhdr
.hdr_entry
), ch
->name
);
527 entry_text
= gtk_entry_get_text(GTK_ENTRY(customhdr
.val_entry
));
528 while (*entry_text
&&
529 (*entry_text
== '\n' || *entry_text
== '\r' ||
530 *entry_text
== '\t' || *entry_text
== ' '))
533 if (entry_text
[0] != '\0') {
534 ch
->value
= g_strdup(entry_text
);
535 unfold_line(ch
->value
);
536 g_strstrip(ch
->value
);
537 gtk_entry_set_text(GTK_ENTRY(customhdr
.val_entry
), ch
->value
);
540 ch_str
= g_strdup_printf("%s: %s", ch
->name
,
541 ch
->value
? ch
->value
: "");
543 prefs_custom_header_list_view_insert_header
544 (customhdr
.list_view
, NULL
, ch_str
, ch
);
548 prefs_custom_header_set_list(cur_ac
);
552 #define B64_LINE_SIZE 57
553 #define B64_BUFFSIZE 77
554 static void prefs_custom_header_val_from_file_cb(void)
556 gchar
*filename
= NULL
;
557 gchar
*contents
= NULL
;
558 const gchar
*hdr
= gtk_entry_get_text(GTK_ENTRY(customhdr
.hdr_entry
));
560 if (!strcmp(hdr
, "Face"))
561 filename
= filesel_select_file_open(_("Choose a PNG file"), NULL
);
562 else if (!strcmp(hdr
, "X-Face"))
563 filename
= filesel_select_file_open(_("Choose an XBM file"), NULL
);
565 filename
= filesel_select_file_open(_("Choose a text file"), NULL
);
567 if (!strcmp(hdr
, "Face") || !strcmp(hdr
, "X-Face")) {
568 if (filename
&& is_file_exist(filename
)) {
571 gchar inbuf
[B64_LINE_SIZE
], *outbuf
;
574 GdkPixbufFormat
*format
= gdk_pixbuf_get_file_info(
577 if (format
== NULL
) {
578 alertpanel_error(_("This file isn't an image."));
582 if (w
!= 48 || h
!= 48) {
583 alertpanel_error(_("The chosen image isn't the correct size (48x48)."));
587 if (!strcmp(hdr
, "Face")) {
588 if (get_file_size(filename
) > 725) {
589 alertpanel_error(_("The image is too big; it must be maximum 725 bytes."));
593 if (g_ascii_strcasecmp("png", gdk_pixbuf_format_get_name(format
))) {
594 alertpanel_error(_("The image isn't in the correct format (PNG)."));
595 g_print("%s\n", gdk_pixbuf_format_get_name(format
));
599 } else if (!strcmp(hdr
, "X-Face")) {
600 gchar
*tmp
= NULL
, *cmd
= NULL
;
602 if (g_ascii_strcasecmp("xbm", gdk_pixbuf_format_get_name(format
))) {
603 alertpanel_error(_("The image isn't in the correct format (XBM)."));
604 g_print("%s\n", gdk_pixbuf_format_get_name(format
));
608 cmd
= g_strdup_printf("compface %s", filename
);
609 tmp
= get_command_output(cmd
);
611 if (tmp
== NULL
|| *tmp
== '\0') {
612 alertpanel_error(_("Couldn't call `compface`. Make sure it's in your $PATH."));
617 if (strstr(tmp
, "compface:")) {
618 alertpanel_error(_("Compface error: %s"), tmp
);
628 if (tmp
[i
] == '\r' || tmp
[i
] == '\n') {
632 contents
= g_strdup_printf("%s%c",tmp2
?tmp2
:"", tmp
[i
]);
640 fp
= claws_fopen(filename
, "rb");
646 while ((len
= claws_fread(inbuf
, sizeof(gchar
),
649 outbuf
= g_base64_encode(inbuf
, B64_LINE_SIZE
);
652 contents
= g_strconcat(tmp
?tmp
:"",outbuf
, NULL
);
656 if (len
> 0 && claws_feof(fp
)) {
658 outbuf
= g_base64_encode(inbuf
, len
);
659 contents
= g_strconcat(tmp
?tmp
:"",outbuf
, NULL
);
669 contents
= file_read_to_str(filename
);
670 if (strchr(contents
, '\n') || strchr(contents
,'\r')) {
671 alertpanel_error(_("This file contains newlines."));
678 if (contents
&& strlen(contents
))
679 gtk_entry_set_text(GTK_ENTRY(customhdr
.val_entry
), contents
);
685 static void prefs_custom_header_add_cb(void)
687 prefs_custom_header_list_view_set_row(cur_ac
);
690 static void prefs_custom_header_delete_cb(void)
696 if (!gtk_tree_selection_get_selected(gtk_tree_view_get_selection
697 (GTK_TREE_VIEW(customhdr
.list_view
)),
701 if (alertpanel(_("Delete header"),
702 _("Do you really want to delete this header?"),
703 GTK_STOCK_CANCEL
, GTK_STOCK_DELETE
, NULL
, ALERTFOCUS_FIRST
) != G_ALERTALTERNATE
)
706 gtk_tree_model_get(model
, &sel
,
709 gtk_list_store_remove(GTK_LIST_STORE(model
), &sel
);
711 cur_ac
->customhdr_list
= g_slist_remove(cur_ac
->customhdr_list
, ch
);
713 custom_header_free(ch
);
716 static void prefs_custom_header_up(void)
718 GtkTreePath
*prev
, *sel
;
720 GtkListStore
*store
= NULL
;
721 GtkTreeModel
*model
= NULL
;
724 if (!gtk_tree_selection_get_selected
725 (gtk_tree_view_get_selection
726 (GTK_TREE_VIEW(customhdr
.list_view
)),
730 store
= (GtkListStore
*)model
;
731 sel
= gtk_tree_model_get_path(GTK_TREE_MODEL(store
), &isel
);
735 /* no move if we're at row 0... */
736 prev
= gtk_tree_path_copy(sel
);
737 if (!gtk_tree_path_prev(prev
)) {
738 gtk_tree_path_free(prev
);
739 gtk_tree_path_free(sel
);
743 gtk_tree_model_get_iter(GTK_TREE_MODEL(store
),
745 gtk_tree_path_free(sel
);
746 gtk_tree_path_free(prev
);
748 gtk_list_store_swap(store
, &iprev
, &isel
);
749 prefs_custom_header_set_list(cur_ac
);
752 static void prefs_custom_header_down(void)
754 GtkListStore
*store
= NULL
;
755 GtkTreeModel
*model
= NULL
;
756 GtkTreeIter next
, sel
;
758 if (!gtk_tree_selection_get_selected
759 (gtk_tree_view_get_selection
760 (GTK_TREE_VIEW(customhdr
.list_view
)),
764 store
= (GtkListStore
*)model
;
766 if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(store
), &next
))
769 gtk_list_store_swap(store
, &next
, &sel
);
770 prefs_custom_header_set_list(cur_ac
);
773 static gboolean
prefs_custom_header_key_pressed(GtkWidget
*widget
,
777 if (event
&& event
->keyval
== GDK_KEY_Escape
)
778 prefs_custom_header_cancel();
782 static void prefs_custom_header_ok(void)
784 prefs_custom_header_write_config(cur_ac
);
785 gtk_widget_hide(customhdr
.window
);
786 gtk_window_set_modal(GTK_WINDOW(customhdr
.window
), FALSE
);
789 static void prefs_custom_header_cancel(void)
791 prefs_custom_header_read_config(cur_ac
);
792 gtk_widget_hide(customhdr
.window
);
793 gtk_window_set_modal(GTK_WINDOW(customhdr
.window
), FALSE
);
796 static gint
prefs_custom_header_deleted(GtkWidget
*widget
, GdkEventAny
*event
,
799 prefs_custom_header_cancel();
803 static GtkListStore
* prefs_custom_header_create_data_store(void)
805 return gtk_list_store_new(N_CUSTHDR_COLUMNS
,
811 static void prefs_custom_header_list_view_insert_header(GtkWidget
*list_view
,
812 GtkTreeIter
*row_iter
,
817 GtkListStore
*list_store
= GTK_LIST_STORE(gtk_tree_view_get_model
818 (GTK_TREE_VIEW(list_view
)));
820 if (row_iter
== NULL
) {
822 gtk_list_store_append(list_store
, &iter
);
823 gtk_list_store_set(list_store
, &iter
,
824 CUSTHDR_STRING
, header
,
828 /* change existing */
829 CustomHeader
*old_data
;
831 gtk_tree_model_get(GTK_TREE_MODEL(list_store
), row_iter
,
832 CUSTHDR_DATA
, &old_data
,
835 custom_header_free(old_data
);
837 gtk_list_store_set(list_store
, row_iter
,
838 CUSTHDR_STRING
, header
,
844 static GtkWidget
*prefs_custom_header_list_view_create(void)
846 GtkTreeView
*list_view
;
847 GtkTreeSelection
*selector
;
850 model
= GTK_TREE_MODEL(prefs_custom_header_create_data_store());
851 list_view
= GTK_TREE_VIEW(gtk_tree_view_new_with_model(model
));
852 g_object_unref(model
);
854 gtk_tree_view_set_rules_hint(list_view
, prefs_common
.use_stripes_everywhere
);
855 gtk_tree_view_set_reorderable(list_view
, TRUE
);
857 selector
= gtk_tree_view_get_selection(list_view
);
858 gtk_tree_selection_set_mode(selector
, GTK_SELECTION_BROWSE
);
859 gtk_tree_selection_set_select_function(selector
, prefs_custom_header_selected
,
862 /* create the columns */
863 prefs_custom_header_create_list_view_columns(GTK_WIDGET(list_view
));
865 return GTK_WIDGET(list_view
);
868 static void prefs_custom_header_create_list_view_columns(GtkWidget
*list_view
)
870 GtkTreeViewColumn
*column
;
871 GtkCellRenderer
*renderer
;
873 renderer
= gtk_cell_renderer_text_new();
874 column
= gtk_tree_view_column_new_with_attributes
875 (_("Current custom headers"),
877 "text", CUSTHDR_STRING
,
879 gtk_tree_view_append_column(GTK_TREE_VIEW(list_view
), column
);
882 #define ENTRY_SET_TEXT(entry, str) \
883 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
885 static gboolean
prefs_custom_header_selected(GtkTreeSelection
*selector
,
888 gboolean currently_selected
,
895 CustomHeader default_ch
= { 0, "", NULL
};
897 if (currently_selected
)
900 if (!gtk_tree_model_get_iter(model
, &iter
, path
))
903 gtk_tree_model_get(model
, &iter
,
907 if (!ch
) ch
= &default_ch
;
909 ENTRY_SET_TEXT(customhdr
.hdr_entry
, ch
->name
);
910 ENTRY_SET_TEXT(customhdr
.val_entry
, ch
->value
);
911 if (!g_strcmp0("Face",ch
->name
) && ch
->value
!= NULL
) {
912 preview
= GTK_IMAGE(face_get_from_header (ch
->value
));
913 pixbuf
= gtk_image_get_pixbuf(preview
);
914 gtk_image_set_from_pixbuf (GTK_IMAGE(customhdr
.preview
), pixbuf
);
915 gtk_widget_show(customhdr
.preview
);
916 g_object_ref_sink (G_OBJECT(preview
));
919 else if (!g_strcmp0("X-Face", ch
->name
) && ch
->value
!= NULL
) {
920 preview
= GTK_IMAGE(xface_get_from_header(ch
->value
));
921 pixbuf
= gtk_image_get_pixbuf(preview
);
922 gtk_image_set_from_pixbuf (GTK_IMAGE(customhdr
.preview
), pixbuf
);
923 gtk_widget_show(customhdr
.preview
);
924 g_object_ref_sink (G_OBJECT(preview
));
928 gtk_widget_hide(customhdr
.preview
);
933 #undef ENTRY_SET_TEXT