2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2022 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>
29 #include <gdk/gdkkeysyms.h>
32 #include "mainwindow.h"
33 #include "alertpanel.h"
34 #include "manage_window.h"
38 #include "logwindow.h"
39 #include "prefs_common.h"
41 #define ALERT_PANEL_BUFSIZE 1024
43 static AlertValue value
;
44 static gboolean alertpanel_is_open
= FALSE
;
45 static GtkWidget
*window
;
47 static void alertpanel_show (void);
48 static void alertpanel_create (const gchar
*title
,
50 const gchar
*stock_icon1
,
51 const gchar
*button1_label
,
52 const gchar
*stock_icon2
,
53 const gchar
*button2_label
,
54 const gchar
*stock_icon3
,
55 const gchar
*button3_label
,
58 GtkWidget
*custom_widget
,
61 static void alertpanel_button_toggled (GtkToggleButton
*button
,
63 static void alertpanel_button_clicked (GtkWidget
*widget
,
65 static gint
alertpanel_deleted (GtkWidget
*widget
,
68 static gboolean
alertpanel_close (GtkWidget
*widget
,
72 AlertValue
alertpanel_with_widget(const gchar
*title
,
74 const gchar
*stock_icon1
,
75 const gchar
*button1_label
,
76 const gchar
*stock_icon2
,
77 const gchar
*button2_label
,
78 const gchar
*stock_icon3
,
79 const gchar
*button3_label
,
84 return alertpanel_full(title
, message
, NULL
, button1_label
,
85 NULL
, button2_label
, NULL
, button3_label
,
86 focus
, can_disable
, widget
, ALERT_QUESTION
);
89 AlertValue
alertpanel_full(const gchar
*title
, const gchar
*message
,
90 const gchar
*stock_icon1
,
91 const gchar
*button1_label
,
92 const gchar
*stock_icon2
,
93 const gchar
*button2_label
,
94 const gchar
*stock_icon3
,
95 const gchar
*button3_label
,
101 if (alertpanel_is_open
)
104 alertpanel_is_open
= TRUE
;
105 hooks_invoke(ALERTPANEL_OPENED_HOOKLIST
, &alertpanel_is_open
);
107 alertpanel_create(title
, message
, stock_icon1
, button1_label
, stock_icon2
,
108 button2_label
, stock_icon3
, button3_label
, focus
,
109 can_disable
, widget
, alert_type
);
112 debug_print("return value = %d\n", value
);
116 AlertValue
alertpanel(const gchar
*title
,
117 const gchar
*message
,
118 const gchar
*stock_icon1
,
119 const gchar
*button1_label
,
120 const gchar
*stock_icon2
,
121 const gchar
*button2_label
,
122 const gchar
*stock_icon3
,
123 const gchar
*button3_label
,
126 return alertpanel_full(title
, message
, stock_icon1
, button1_label
, stock_icon2
, button2_label
,
127 stock_icon3
, button3_label
, focus
, FALSE
, NULL
, ALERT_QUESTION
);
130 static void alertpanel_message(const gchar
*title
, const gchar
*message
, gint type
)
132 if (alertpanel_is_open
)
135 alertpanel_is_open
= TRUE
;
136 hooks_invoke(ALERTPANEL_OPENED_HOOKLIST
, &alertpanel_is_open
);
139 alertpanel_create(title
, message
, NULL
, _("_Close"), NULL
, NULL
, NULL
, NULL
,
140 ALERTFOCUS_FIRST
, FALSE
, NULL
, type
);
144 void alertpanel_notice(const gchar
*format
, ...)
147 gchar buf
[ALERT_PANEL_BUFSIZE
];
149 va_start(args
, format
);
150 g_vsnprintf(buf
, sizeof(buf
), format
, args
);
154 alertpanel_message(_("Notice"), buf
, ALERT_NOTICE
);
157 void alertpanel_warning(const gchar
*format
, ...)
160 gchar buf
[ALERT_PANEL_BUFSIZE
];
162 va_start(args
, format
);
163 g_vsnprintf(buf
, sizeof(buf
), format
, args
);
167 alertpanel_message(_("Warning"), buf
, ALERT_WARNING
);
170 void alertpanel_error(const gchar
*format
, ...)
173 gchar buf
[ALERT_PANEL_BUFSIZE
];
175 va_start(args
, format
);
176 g_vsnprintf(buf
, sizeof(buf
), format
, args
);
180 alertpanel_message(_("Error"), buf
, ALERT_ERROR
);
184 *\brief display an error with a View Log button
187 void alertpanel_error_log(const gchar
*format
, ...)
192 gchar buf
[ALERT_PANEL_BUFSIZE
];
194 va_start(args
, format
);
195 g_vsnprintf(buf
, sizeof(buf
), format
, args
);
199 mainwin
= mainwindow_get_mainwindow();
201 if (mainwin
&& mainwin
->logwin
) {
202 mainwindow_clear_error(mainwin
);
203 val
= alertpanel_full(_("Error"), buf
, NULL
, _("_Close"), NULL
,
204 _("_View log"), NULL
, NULL
, ALERTFOCUS_FIRST
,
205 FALSE
, NULL
, ALERT_ERROR
);
206 if (val
== G_ALERTALTERNATE
)
207 log_window_show(mainwin
->logwin
);
209 alertpanel_error("%s", buf
);
212 static void alertpanel_show(void)
217 gtk_window_set_modal(GTK_WINDOW(window
), TRUE
);
218 manage_window_set_transient(GTK_WINDOW(window
));
219 gtk_widget_show_all(window
);
222 display
= gdk_display_get_default();
223 seat
= gdk_display_get_default_seat(display
);
224 device
= gdk_seat_get_pointer(seat
);
226 if (gdk_display_device_is_grabbed(display
, device
))
227 gdk_seat_ungrab(seat
);
229 while ((value
& G_ALERT_VALUE_MASK
) == G_ALERTWAIT
)
230 gtk_main_iteration();
232 gtk_widget_destroy(window
);
235 alertpanel_is_open
= FALSE
;
236 hooks_invoke(ALERTPANEL_OPENED_HOOKLIST
, &alertpanel_is_open
);
241 static void alertpanel_create(const gchar
*title
,
242 const gchar
*message
,
243 const gchar
*stock_icon1
,
244 const gchar
*button1_label
,
245 const gchar
*stock_icon2
,
246 const gchar
*button2_label
,
247 const gchar
*stock_icon3
,
248 const gchar
*button3_label
,
250 gboolean can_disable
,
251 GtkWidget
*custom_widget
,
254 static PangoFontDescription
*font_desc
;
258 GtkWidget
*content_area
;
260 GtkWidget
*disable_checkbtn
;
261 GtkWidget
*confirm_area
;
265 GtkWidget
*focusbutton
;
268 gchar
*tmp
= title
?g_markup_printf_escaped("%s", title
)
270 gchar
*title_full
= g_strdup_printf("<span weight=\"bold\" "
271 "size=\"larger\">%s</span>",
274 debug_print("Creating alert panel window...\n");
276 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
277 manage_window_set_transient(GTK_WINDOW(window
));
278 gtk_window_set_title(GTK_WINDOW(window
), title
);
279 gtk_window_set_type_hint(GTK_WINDOW(window
), GDK_WINDOW_TYPE_HINT_DIALOG
);
280 gtk_window_set_modal(GTK_WINDOW(window
), TRUE
);
281 gtk_window_set_default_size (GTK_WINDOW(window
), 450, 200);
283 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
284 g_signal_connect(G_OBJECT(window
), "delete_event",
285 G_CALLBACK(alertpanel_deleted
),
286 (gpointer
)G_ALERTCANCEL
);
287 g_signal_connect(G_OBJECT(window
), "key_press_event",
288 G_CALLBACK(alertpanel_close
),
289 (gpointer
)G_ALERTCANCEL
);
291 content_area
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 12);
292 gtk_container_add (GTK_CONTAINER(window
), content_area
);
293 /* for title icon, label and message */
294 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 12);
295 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 12);
297 gtk_container_add (GTK_CONTAINER(content_area
), hbox
);
300 switch (alert_type
) {
302 image
= gtk_image_new_from_icon_name
303 ("dialog-question", GTK_ICON_SIZE_DIALOG
);
306 image
= gtk_image_new_from_icon_name
307 ("dialog-warning", GTK_ICON_SIZE_DIALOG
);
310 image
= gtk_image_new_from_icon_name
311 ("dialog-error", GTK_ICON_SIZE_DIALOG
);
315 image
= gtk_image_new_from_icon_name
316 ("dialog-information", GTK_ICON_SIZE_DIALOG
);
319 gtk_widget_set_halign(image
, GTK_ALIGN_CENTER
);
320 gtk_widget_set_valign(image
, GTK_ALIGN_START
);
321 gtk_box_pack_start(GTK_BOX(hbox
), image
, FALSE
, FALSE
, 0);
323 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 12);
325 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, TRUE
, TRUE
, 0);
326 gtk_widget_show (vbox
);
328 label
= gtk_label_new(title_full
);
329 gtk_label_set_xalign(GTK_LABEL(label
), 0.0);
330 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
331 gtk_label_set_use_markup(GTK_LABEL (label
), TRUE
);
332 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
333 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
337 size
= pango_font_description_get_size
338 (gtk_widget_get_style(label
)->font_desc
);
339 font_desc
= pango_font_description_new();
340 pango_font_description_set_weight
341 (font_desc
, PANGO_WEIGHT_BOLD
);
342 pango_font_description_set_size
343 (font_desc
, size
* PANGO_SCALE_LARGE
);
346 gtk_widget_override_font(label
, font_desc
);
349 label
= gtk_label_new(message
);
350 gtk_label_set_xalign(GTK_LABEL(label
), 0.0);
351 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
352 gtk_label_set_selectable(GTK_LABEL(label
), TRUE
);
353 gtk_label_set_use_markup(GTK_LABEL(label
), TRUE
);
354 gtk_widget_set_can_focus(label
, FALSE
);
355 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
356 gtk_label_set_line_wrap_mode(GTK_LABEL(label
), PANGO_WRAP_WORD_CHAR
);
357 gtk_box_pack_start(GTK_BOX(vbox
), label
, FALSE
, FALSE
, 0);
358 gtk_widget_show(label
);
360 /* Claws: custom widget */
362 gtk_box_pack_start(GTK_BOX(vbox
), custom_widget
, FALSE
,
367 hbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
368 gtk_box_pack_start(GTK_BOX(vbox
), hbox
,
371 disable_checkbtn
= gtk_check_button_new_with_label
372 (_("Show this message next time"));
373 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(disable_checkbtn
),
375 gtk_box_pack_start(GTK_BOX(hbox
), disable_checkbtn
,
378 g_signal_connect(G_OBJECT(disable_checkbtn
), "toggled",
379 G_CALLBACK(alertpanel_button_toggled
),
380 GUINT_TO_POINTER(G_ALERTDISABLE
));
385 button1_label
= _("_OK");
386 label2
= button2_label
;
387 label3
= button3_label
;
389 gtkut_stock_button_set_create(&confirm_area
,
390 &button1
, stock_icon1
, button1_label
,
391 button2_label
? &button2
: NULL
, stock_icon2
, label2
,
392 button3_label
? &button3
: NULL
, stock_icon3
, label3
);
394 gtk_box_pack_end(GTK_BOX(vbox
), confirm_area
, FALSE
, FALSE
, 0);
396 /* Set focus on correct button as requested. */
397 focusbutton
= button1
;
399 case ALERTFOCUS_SECOND
:
400 if (button2_label
!= NULL
)
401 focusbutton
= button2
;
403 case ALERTFOCUS_THIRD
:
404 if (button3_label
!= NULL
)
405 focusbutton
= button3
;
407 case ALERTFOCUS_FIRST
:
409 focusbutton
= button1
;
412 gtk_widget_grab_default(focusbutton
);
413 gtk_widget_grab_focus(focusbutton
);
415 g_signal_connect(G_OBJECT(button1
), "clicked",
416 G_CALLBACK(alertpanel_button_clicked
),
417 GUINT_TO_POINTER(G_ALERTDEFAULT
));
419 g_signal_connect(G_OBJECT(button2
), "clicked",
420 G_CALLBACK(alertpanel_button_clicked
),
421 GUINT_TO_POINTER(G_ALERTALTERNATE
));
423 g_signal_connect(G_OBJECT(button3
), "clicked",
424 G_CALLBACK(alertpanel_button_clicked
),
425 GUINT_TO_POINTER(G_ALERTOTHER
));
427 gtk_widget_show_all(window
);
430 static void alertpanel_button_toggled(GtkToggleButton
*button
,
433 if (gtk_toggle_button_get_active(button
))
434 value
&= ~GPOINTER_TO_UINT(data
);
436 value
|= GPOINTER_TO_UINT(data
);
439 static void alertpanel_button_clicked(GtkWidget
*widget
, gpointer data
)
441 value
= (value
& ~G_ALERT_VALUE_MASK
) | (AlertValue
)data
;
444 static gint
alertpanel_deleted(GtkWidget
*widget
, GdkEventAny
*event
,
447 value
= (value
& ~G_ALERT_VALUE_MASK
) | (AlertValue
)data
;
451 static gboolean
alertpanel_close(GtkWidget
*widget
, GdkEventAny
*event
,
454 if (event
->type
== GDK_KEY_PRESS
)
455 if (((GdkEventKey
*)event
)->keyval
!= GDK_KEY_Escape
)
458 value
= (value
& ~G_ALERT_VALUE_MASK
) | (AlertValue
)data
;