2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2020 the Claws Mail team and Hiroyuki Yamamoto
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/>.
21 #include "claws-features.h"
27 #include <glib/gi18n.h>
33 #include <gdk-pixbuf/gdk-pixbuf.h>
35 #include "headerview.h"
36 #include "prefs_common.h"
41 #include "addrindex.h"
45 static gint
headerview_show_avatar (HeaderView
*headerview
,
47 static gint
headerview_show_contact_pic (HeaderView
*headerview
,
49 static void headerview_save_contact_pic (HeaderView
*headerview
,
52 HeaderView
*headerview_create(void)
54 HeaderView
*headerview
;
60 GtkWidget
*from_header_label
;
61 GtkWidget
*from_body_label
;
62 GtkWidget
*to_header_label
;
63 GtkWidget
*to_body_label
;
64 GtkWidget
*ng_header_label
;
65 GtkWidget
*ng_body_label
;
66 GtkWidget
*subject_header_label
;
67 GtkWidget
*subject_body_label
;
68 GtkWidget
*tags_header_label
;
69 GtkWidget
*tags_body_label
;
71 debug_print("Creating header view...\n");
72 headerview
= g_new0(HeaderView
, 1);
74 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
75 gtk_widget_set_name(GTK_WIDGET(hbox
), "headerview");
76 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 2);
77 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 2);
78 gtk_box_pack_start(GTK_BOX(hbox
), vbox
, TRUE
, TRUE
, 0);
80 hbox1
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 4);
81 gtk_box_pack_start(GTK_BOX(vbox
), hbox1
, FALSE
, FALSE
, 0);
82 hbox2
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 4);
83 gtk_box_pack_start(GTK_BOX(vbox
), hbox2
, FALSE
, FALSE
, 0);
84 hbox3
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 4);
85 gtk_box_pack_start(GTK_BOX(vbox
), hbox3
, FALSE
, FALSE
, 0);
87 from_header_label
= gtk_label_new(prefs_common_translated_header_name("From:"));
88 from_body_label
= gtk_label_new("");
89 to_header_label
= gtk_label_new(prefs_common_translated_header_name("To:"));
90 to_body_label
= gtk_label_new("");
91 ng_header_label
= gtk_label_new(prefs_common_translated_header_name("Newsgroups:"));
92 ng_body_label
= gtk_label_new("");
93 subject_header_label
= gtk_label_new(prefs_common_translated_header_name("Subject:"));
94 subject_body_label
= gtk_label_new("");
95 tags_header_label
= gtk_label_new(_("Tags:"));
96 tags_body_label
= gtk_label_new("");
98 gtk_label_set_selectable(GTK_LABEL(from_body_label
), TRUE
);
99 gtk_label_set_selectable(GTK_LABEL(to_body_label
), TRUE
);
100 gtk_label_set_selectable(GTK_LABEL(ng_body_label
), TRUE
);
101 gtk_label_set_selectable(GTK_LABEL(subject_body_label
), TRUE
);
102 gtk_label_set_selectable(GTK_LABEL(tags_body_label
), TRUE
);
104 gtk_widget_set_can_focus(from_body_label
, FALSE
);
105 gtk_widget_set_can_focus(to_body_label
, FALSE
);
106 gtk_widget_set_can_focus(ng_body_label
, FALSE
);
107 gtk_widget_set_can_focus(subject_body_label
, FALSE
);
108 gtk_widget_set_can_focus(tags_body_label
, FALSE
);
110 gtk_box_pack_start(GTK_BOX(hbox1
), from_header_label
, FALSE
, FALSE
, 0);
111 gtk_box_pack_start(GTK_BOX(hbox1
), from_body_label
, FALSE
, FALSE
, 0);
112 gtk_box_pack_start(GTK_BOX(hbox1
), to_header_label
, FALSE
, FALSE
, 0);
113 gtk_box_pack_start(GTK_BOX(hbox1
), to_body_label
, TRUE
, TRUE
, 0);
114 gtk_box_pack_start(GTK_BOX(hbox1
), ng_header_label
, FALSE
, FALSE
, 0);
115 gtk_box_pack_start(GTK_BOX(hbox1
), ng_body_label
, TRUE
, TRUE
, 0);
116 gtk_box_pack_start(GTK_BOX(hbox2
), subject_header_label
, FALSE
, FALSE
, 0);
117 gtk_box_pack_start(GTK_BOX(hbox2
), subject_body_label
, TRUE
, TRUE
, 0);
118 gtk_box_pack_start(GTK_BOX(hbox3
), tags_header_label
, FALSE
, FALSE
, 0);
119 gtk_box_pack_start(GTK_BOX(hbox3
), tags_body_label
, TRUE
, TRUE
, 0);
121 gtk_label_set_xalign(GTK_LABEL(to_body_label
), 0.0);
122 gtk_label_set_xalign(GTK_LABEL(ng_body_label
), 0.0);
123 gtk_label_set_xalign(GTK_LABEL(subject_body_label
), 0.0);
124 gtk_label_set_xalign(GTK_LABEL(tags_body_label
), 0.0);
125 gtk_label_set_ellipsize(GTK_LABEL(to_body_label
), PANGO_ELLIPSIZE_END
);
126 gtk_label_set_ellipsize(GTK_LABEL(ng_body_label
), PANGO_ELLIPSIZE_END
);
127 gtk_label_set_ellipsize(GTK_LABEL(subject_body_label
), PANGO_ELLIPSIZE_END
);
128 gtk_label_set_ellipsize(GTK_LABEL(tags_body_label
), PANGO_ELLIPSIZE_END
);
130 headerview
->hbox
= hbox
;
131 headerview
->from_header_label
= from_header_label
;
132 headerview
->from_body_label
= from_body_label
;
133 headerview
->to_header_label
= to_header_label
;
134 headerview
->to_body_label
= to_body_label
;
135 headerview
->ng_header_label
= ng_header_label
;
136 headerview
->ng_body_label
= ng_body_label
;
137 headerview
->subject_header_label
= subject_header_label
;
138 headerview
->subject_body_label
= subject_body_label
;
139 headerview
->tags_header_label
= tags_header_label
;
140 headerview
->tags_body_label
= tags_body_label
;
141 headerview
->image
= NULL
;
143 gtk_widget_show_all(hbox
);
148 void headerview_set_font(HeaderView
*headerview
)
150 PangoFontDescription
*boldfont
= NULL
;
151 PangoFontDescription
*normalfont
= NULL
;
153 normalfont
= pango_font_description_from_string(NORMAL_FONT
);
155 gtk_widget_override_font(headerview
->from_body_label
, normalfont
);
156 gtk_widget_override_font(headerview
->to_body_label
, normalfont
);
157 gtk_widget_override_font(headerview
->ng_body_label
, normalfont
);
158 gtk_widget_override_font(headerview
->subject_body_label
, normalfont
);
159 gtk_widget_override_font(headerview
->tags_body_label
, normalfont
);
160 pango_font_description_free(normalfont
);
163 if (prefs_common
.derive_from_normal_font
|| !BOLD_FONT
) {
164 boldfont
= pango_font_description_from_string(NORMAL_FONT
);
165 pango_font_description_set_weight(boldfont
, PANGO_WEIGHT_BOLD
);
167 boldfont
= pango_font_description_from_string(BOLD_FONT
);
170 gtk_widget_override_font(headerview
->from_header_label
, boldfont
);
171 gtk_widget_override_font(headerview
->to_header_label
, boldfont
);
172 gtk_widget_override_font(headerview
->ng_header_label
, boldfont
);
173 gtk_widget_override_font(headerview
->subject_header_label
, boldfont
);
174 gtk_widget_override_font(headerview
->tags_header_label
, boldfont
);
175 pango_font_description_free(boldfont
);
179 void headerview_init(HeaderView
*headerview
)
181 headerview_set_font(headerview
);
182 headerview_clear(headerview
);
183 headerview_set_visibility(headerview
, prefs_common
.display_header_pane
);
186 void headerview_show(HeaderView
*headerview
, MsgInfo
*msginfo
)
188 gchar
*tags
= procmsg_msginfo_get_tags_str(msginfo
);
190 headerview_clear(headerview
);
192 gtk_label_set_text(GTK_LABEL(headerview
->from_body_label
),
193 msginfo
->from
? msginfo
->from
: _("(No From)"));
195 gtk_label_set_text(GTK_LABEL(headerview
->to_body_label
),
197 gtk_widget_show(headerview
->to_header_label
);
198 gtk_widget_show(headerview
->to_body_label
);
200 if (msginfo
->newsgroups
) {
201 gtk_label_set_text(GTK_LABEL(headerview
->ng_body_label
),
202 msginfo
->newsgroups
);
203 gtk_widget_show(headerview
->ng_header_label
);
204 gtk_widget_show(headerview
->ng_body_label
);
206 gtk_label_set_text(GTK_LABEL(headerview
->subject_body_label
),
207 msginfo
->subject
? msginfo
->subject
:
210 gtk_label_set_text(GTK_LABEL(headerview
->tags_body_label
),
212 gtk_widget_show(headerview
->tags_header_label
);
213 gtk_widget_show(headerview
->tags_body_label
);
216 if (!headerview_show_avatar(headerview
, msginfo
))
219 if (!headerview_show_contact_pic(headerview
, msginfo
))
224 static gint
headerview_show_avatar (HeaderView
*headerview
, MsgInfo
*msginfo
)
226 AvatarRender
*avatarr
= avatars_avatarrender_new(msginfo
);
227 GtkWidget
*hbox
= headerview
->hbox
;
229 hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST
, avatarr
);
231 if (!avatarr
->image
) {
232 if (headerview
->image
233 && gtk_widget_get_visible(headerview
->image
)) {
234 gtk_widget_hide(headerview
->image
);
235 gtk_widget_queue_resize(hbox
);
237 avatars_avatarrender_free(avatarr
);
240 if (!gtk_widget_get_visible(hbox
)) {
241 avatars_avatarrender_free(avatarr
);
245 if (headerview
->image
) {
246 gtk_widget_destroy(headerview
->image
);
247 headerview
->image
= NULL
;
250 gtk_box_pack_start(GTK_BOX(hbox
), avatarr
->image
, FALSE
, FALSE
, 0);
251 gtk_widget_show(avatarr
->image
);
253 headerview
->image
= avatarr
->image
;
254 avatarr
->image
= NULL
; /* avoid destroying */
255 avatars_avatarrender_free(avatarr
);
257 if (prefs_common
.save_xface
)
258 headerview_save_contact_pic(headerview
, msginfo
);
262 static void headerview_save_contact_pic (HeaderView
*headerview
, MsgInfo
*msginfo
)
264 #ifndef USE_ALT_ADDRBOOK
265 gchar
*filename
= NULL
;
266 GError
*error
= NULL
;
267 GdkPixbuf
*picture
= NULL
;
269 if (!gtk_widget_get_visible(headerview
->hbox
)) return;
271 if (headerview
->image
) {
272 picture
= gtk_image_get_pixbuf(GTK_IMAGE(headerview
->image
));
275 filename
= addrindex_get_picture_file(msginfo
->from
);
278 if (!is_file_exist(filename
)) {
279 gdk_pixbuf_save(picture
, filename
, "png", &error
, NULL
);
281 g_warning("failed to save image: %s",
288 /* new address book */
292 static gint
headerview_show_contact_pic (HeaderView
*headerview
, MsgInfo
*msginfo
)
294 #ifndef USE_ALT_ADDRBOOK
295 GtkWidget
*hbox
= headerview
->hbox
;
297 gchar
*filename
= NULL
;
298 GError
*error
= NULL
;
299 GdkPixbuf
*picture
= NULL
;
302 if (!gtk_widget_get_visible(headerview
->hbox
)) return -1;
304 if (headerview
->image
) {
305 gtk_widget_destroy(headerview
->image
);
306 headerview
->image
= NULL
;
309 filename
= addrindex_get_picture_file(msginfo
->from
);
313 if (!is_file_exist(filename
)) {
317 gdk_pixbuf_get_file_info(filename
, &w
, &h
);
319 if (w
> 48 || h
> 48)
320 picture
= gdk_pixbuf_new_from_file_at_scale(filename
,
321 48, 48, TRUE
, &error
);
323 picture
= gdk_pixbuf_new_from_file(filename
, &error
);
327 debug_print("Failed to import image: %s\n",
333 image
= gtk_image_new_from_pixbuf(picture
);
337 g_object_unref(picture
);
339 gtk_box_pack_start(GTK_BOX(hbox
), image
, FALSE
, FALSE
, 0);
340 gtk_widget_show(image
);
343 headerview
->image
= image
;
349 /* new address book */
354 void headerview_clear(HeaderView
*headerview
)
356 if (headerview
== NULL
)
359 gtk_label_set_text(GTK_LABEL(headerview
->from_body_label
), "");
360 gtk_label_set_text(GTK_LABEL(headerview
->to_body_label
), "");
361 gtk_label_set_text(GTK_LABEL(headerview
->ng_body_label
), "");
362 gtk_label_set_text(GTK_LABEL(headerview
->subject_body_label
), "");
363 gtk_label_set_text(GTK_LABEL(headerview
->tags_body_label
), "");
364 gtk_widget_hide(headerview
->to_header_label
);
365 gtk_widget_hide(headerview
->to_body_label
);
366 gtk_widget_hide(headerview
->ng_header_label
);
367 gtk_widget_hide(headerview
->ng_body_label
);
368 gtk_widget_hide(headerview
->tags_header_label
);
369 gtk_widget_hide(headerview
->tags_body_label
);
371 if (headerview
->image
&& gtk_widget_get_visible(headerview
->image
)) {
372 gtk_widget_hide(headerview
->image
);
373 gtk_widget_queue_resize(headerview
->hbox
);
377 void headerview_set_visibility(HeaderView
*headerview
, gboolean visibility
)
380 gtk_widget_show(headerview
->hbox
);
382 gtk_widget_hide(headerview
->hbox
);
385 void headerview_destroy(HeaderView
*headerview
)