No issues found
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /* rb-alert-dialog.c: An HIG compliant alert dialog.
4
5 The Gnome Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The Gnome Library 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 GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the Gnome Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20 */
21
22 /* this was originally nautilus/eel/eel-alert-dialog.c */
23
24 #include <config.h>
25
26 #include "rb-alert-dialog.h"
27 #include <glib/gi18n.h>
28 #include <gtk/gtk.h>
29 #include <string.h>
30
31 enum {
32 PROP_0,
33 PROP_ALERT_TYPE,
34 PROP_BUTTONS
35 };
36
37 struct _RBAlertDialogDetails {
38 GtkWidget *image;
39 GtkWidget *primary_label;
40 GtkWidget *secondary_label;
41 GtkWidget *details_expander;
42 GtkWidget *details_label;
43 GtkMessageType type;
44 };
45
46
47 static gpointer parent_class;
48
49 static void rb_alert_dialog_finalize (GObject *object);
50 static void rb_alert_dialog_class_init (RBAlertDialogClass *klass);
51 static void rb_alert_dialog_init (RBAlertDialog *dialog);
52 static void rb_alert_dialog_style_set (GtkWidget *widget,
53 GtkStyle *prev_style);
54 static void rb_alert_dialog_set_property (GObject *object,
55 guint prop_id,
56 const GValue *value,
57 GParamSpec *pspec);
58 static void rb_alert_dialog_get_property (GObject *object,
59 guint prop_id,
60 GValue *value,
61 GParamSpec *pspec);
62 static void rb_alert_dialog_add_buttons (RBAlertDialog *alert_dialog,
63 GtkButtonsType buttons);
64
65 G_DEFINE_TYPE (RBAlertDialog, rb_alert_dialog, GTK_TYPE_DIALOG)
66
67 static void
68 rb_alert_dialog_class_init (RBAlertDialogClass *class)
69 {
70 GtkWidgetClass *widget_class;
71 GObjectClass *gobject_class;
72
73 widget_class = GTK_WIDGET_CLASS (class);
74 gobject_class = G_OBJECT_CLASS (class);
75
76 parent_class = g_type_class_peek_parent (class);
77
78 G_OBJECT_CLASS (class)->finalize = rb_alert_dialog_finalize;
79
80 widget_class->style_set = rb_alert_dialog_style_set;
81
82 gobject_class->set_property = rb_alert_dialog_set_property;
83 gobject_class->get_property = rb_alert_dialog_get_property;
84
85 gtk_widget_class_install_style_property (widget_class,
86 g_param_spec_int ("alert_border",
87 _("Image/label border"),
88 _("Width of border around the label and image in the alert dialog"),
89 0,
90 G_MAXINT,
91 5,
92 G_PARAM_READABLE));
93
94 g_object_class_install_property (gobject_class,
95 PROP_ALERT_TYPE,
96 g_param_spec_enum ("alert_type",
97 _("Alert Type"),
98 _("The type of alert"),
99 GTK_TYPE_MESSAGE_TYPE,
100 GTK_MESSAGE_INFO,
101 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
102
103 g_object_class_install_property (gobject_class,
104 PROP_BUTTONS,
105 g_param_spec_enum ("buttons",
106 _("Alert Buttons"),
107 _("The buttons shown in the alert dialog"),
108 GTK_TYPE_BUTTONS_TYPE,
109 GTK_BUTTONS_NONE,
110 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
111 }
112
113 static void
114 rb_alert_dialog_finalize (GObject *object)
115 {
116 RBAlertDialog *dialog;
117
118 dialog = RB_ALERT_DIALOG (object);
119
120 g_free (dialog->details);
121
122 G_OBJECT_CLASS (rb_alert_dialog_parent_class)->finalize (object);
123 }
124
125
126 static void
127 rb_alert_dialog_init (RBAlertDialog *dialog)
128 {
129 GtkWidget *hbox;
130 GtkWidget *vbox;
131 GtkWidget *expander;
132 GtkWidget *content;
133
134 dialog->details = g_new0 (RBAlertDialogDetails, 1);
135
136 dialog->details->primary_label = gtk_label_new (NULL);
137 dialog->details->secondary_label = gtk_label_new (NULL);
138 dialog->details->details_label = gtk_label_new (NULL);
139 dialog->details->image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG);
140 gtk_misc_set_alignment (GTK_MISC (dialog->details->image), 0.5, 0.0);
141
142 gtk_label_set_line_wrap (GTK_LABEL (dialog->details->primary_label), TRUE);
143 gtk_label_set_selectable (GTK_LABEL (dialog->details->primary_label), TRUE);
144 gtk_label_set_use_markup (GTK_LABEL (dialog->details->primary_label), TRUE);
145 gtk_misc_set_alignment (GTK_MISC (dialog->details->primary_label), 0.0, 0.5);
146
147 gtk_label_set_line_wrap (GTK_LABEL (dialog->details->secondary_label), TRUE);
148 gtk_label_set_selectable (GTK_LABEL (dialog->details->secondary_label), TRUE);
149 gtk_misc_set_alignment (GTK_MISC (dialog->details->secondary_label), 0.0, 0.5);
150
151 gtk_label_set_line_wrap (GTK_LABEL (dialog->details->details_label), TRUE);
152 gtk_label_set_selectable (GTK_LABEL (dialog->details->details_label), TRUE);
153 gtk_misc_set_alignment (GTK_MISC (dialog->details->details_label), 0.0, 0.5);
154
155 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
156 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
157
158 gtk_box_pack_start (GTK_BOX (hbox), dialog->details->image,
159 FALSE, FALSE, 0);
160
161 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
162
163 gtk_box_pack_start (GTK_BOX (hbox), vbox,
164 FALSE, FALSE, 0);
165
166 gtk_box_pack_start (GTK_BOX (vbox), dialog->details->primary_label,
167 FALSE, FALSE, 0);
168
169 gtk_box_pack_start (GTK_BOX (vbox), dialog->details->secondary_label,
170 FALSE, FALSE, 0);
171
172 expander = gtk_expander_new_with_mnemonic (_("Show more _details"));
173 dialog->details->details_expander = expander;
174 gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
175 gtk_container_add (GTK_CONTAINER (expander), dialog->details->details_label);
176
177 gtk_box_pack_start (GTK_BOX (vbox), expander,
178 FALSE, FALSE, 0);
179
180 content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
181 gtk_box_pack_start (GTK_BOX (content), hbox, FALSE, FALSE, 0);
182
183 gtk_widget_show_all (hbox);
184 gtk_widget_hide (expander);
185
186 }
187
188 static void
189 setup_type (RBAlertDialog *dialog,
190 GtkMessageType type)
191 {
192 const gchar *stock_id = NULL;
193 GtkStockItem item;
194
195 switch (type) {
196 case GTK_MESSAGE_INFO:
197 stock_id = GTK_STOCK_DIALOG_INFO;
198 break;
199 case GTK_MESSAGE_QUESTION:
200 stock_id = GTK_STOCK_DIALOG_QUESTION;
201 break;
202 case GTK_MESSAGE_WARNING:
203 stock_id = GTK_STOCK_DIALOG_WARNING;
204 break;
205 case GTK_MESSAGE_ERROR:
206 stock_id = GTK_STOCK_DIALOG_ERROR;
207 break;
208 default:
209 g_warning ("Unknown GtkMessageType %d", type);
210 break;
211 }
212
213 if (stock_id == NULL) {
214 stock_id = GTK_STOCK_DIALOG_INFO;
215 }
216
217 if (gtk_stock_lookup (stock_id, &item)) {
218 gtk_image_set_from_stock (GTK_IMAGE (dialog->details->image), stock_id,
219 GTK_ICON_SIZE_DIALOG);
220 } else {
221 g_warning ("Stock dialog ID doesn't exist?");
222 }
223 }
224
225 static void
226 rb_alert_dialog_set_property (GObject *object,
227 guint prop_id,
228 const GValue *value,
229 GParamSpec *pspec)
230 {
231 RBAlertDialog *dialog;
232
233 dialog = RB_ALERT_DIALOG (object);
234
235 switch (prop_id) {
236 case PROP_ALERT_TYPE:
237 dialog->details->type = g_value_get_enum (value);
238 setup_type (dialog, dialog->details->type);
239 break;
240 case PROP_BUTTONS:
241 rb_alert_dialog_add_buttons (dialog, g_value_get_enum (value));
242 break;
243 default:
244 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
245 break;
246 }
247 }
248
249 static void
250 rb_alert_dialog_get_property (GObject *object,
251 guint prop_id,
252 GValue *value,
253 GParamSpec *pspec)
254 {
255 RBAlertDialog *dialog;
256
257 dialog = RB_ALERT_DIALOG (object);
258
259 switch (prop_id) {
260 case PROP_ALERT_TYPE:
261 g_value_set_enum (value, dialog->details->type);
262 break;
263 default:
264 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
265 break;
266 }
267 }
268
269 void
270 rb_alert_dialog_set_primary_label (RBAlertDialog *dialog,
271 const gchar *message)
272 {
273 gchar *markup_str;
274 char *escaped_message;
275
276 if (message != NULL) {
277 escaped_message = g_markup_escape_text (message, -1);
278 markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", escaped_message, "</span>", NULL);
279 gtk_label_set_markup (GTK_LABEL (RB_ALERT_DIALOG (dialog)->details->primary_label),
280 markup_str);
281 g_free (markup_str);
282 g_free (escaped_message);
283 }
284 }
285
286 void
287 rb_alert_dialog_set_secondary_label (RBAlertDialog *dialog,
288 const gchar *message)
289 {
290 if (message != NULL) {
291 gtk_label_set_text (GTK_LABEL (RB_ALERT_DIALOG (dialog)->details->secondary_label),
292 message);
293 } else {
294 gtk_widget_hide (RB_ALERT_DIALOG (dialog)->details->secondary_label);
295 }
296 }
297
298 void
299 rb_alert_dialog_set_details_label (RBAlertDialog *dialog,
300 const gchar *message)
301 {
302 if (message != NULL) {
303 gtk_widget_show (dialog->details->details_expander);
304 gtk_label_set_text (GTK_LABEL (dialog->details->details_label), message);
305 } else {
306 gtk_widget_hide (dialog->details->details_expander);
307 }
308 }
309
310
311 GtkWidget*
312 rb_alert_dialog_new (GtkWindow *parent,
313 GtkDialogFlags flags,
314 GtkMessageType type,
315 GtkButtonsType buttons,
316 const gchar *primary_message,
317 const gchar *secondary_message)
318 {
319 GtkWidget *widget;
320 GtkDialog *dialog;
321 GtkWidget *content;
322
323 g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
324
325 widget = g_object_new (RB_TYPE_ALERT_DIALOG,
326 "alert_type", type,
327 "buttons", buttons,
328 NULL);
329 atk_object_set_role (gtk_widget_get_accessible (widget), ATK_ROLE_ALERT);
330
331 dialog = GTK_DIALOG (widget);
332
333 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
334 content = gtk_dialog_get_content_area (dialog);
335 gtk_box_set_spacing (GTK_BOX (content), 14);
336 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
337
338 /* Make sure we don't get a window title.
339 * HIG says that alert dialogs should not have window title
340 */
341 gtk_window_set_title (GTK_WINDOW (dialog), "");
342 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
343
344 rb_alert_dialog_set_primary_label (RB_ALERT_DIALOG (dialog),
345 primary_message);
346
347 rb_alert_dialog_set_secondary_label (RB_ALERT_DIALOG (dialog),
348 secondary_message);
349
350 if (parent != NULL) {
351 gtk_window_set_transient_for (GTK_WINDOW (widget),
352 GTK_WINDOW (parent));
353 }
354
355 if (flags & GTK_DIALOG_MODAL) {
356 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
357 }
358
359 if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) {
360 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
361 }
362 return widget;
363 }
364
365 static void
366 rb_alert_dialog_add_buttons (RBAlertDialog* alert_dialog,
367 GtkButtonsType buttons)
368 {
369 GtkDialog* dialog;
370
371 dialog = GTK_DIALOG (alert_dialog);
372
373 switch (buttons) {
374 case GTK_BUTTONS_NONE:
375 break;
376 case GTK_BUTTONS_OK:
377 gtk_dialog_add_button (dialog,
378 GTK_STOCK_OK,
379 GTK_RESPONSE_OK);
380 gtk_dialog_set_default_response (dialog,
381 GTK_RESPONSE_OK);
382 break;
383 case GTK_BUTTONS_CLOSE:
384 gtk_dialog_add_button (dialog,
385 GTK_STOCK_CLOSE,
386 GTK_RESPONSE_CLOSE);
387 gtk_dialog_set_default_response (dialog,
388 GTK_RESPONSE_CLOSE);
389 break;
390 case GTK_BUTTONS_CANCEL:
391 gtk_dialog_add_button (dialog,
392 GTK_STOCK_CANCEL,
393 GTK_RESPONSE_CANCEL);
394 gtk_dialog_set_default_response (dialog,
395 GTK_RESPONSE_CANCEL);
396 break;
397 case GTK_BUTTONS_YES_NO:
398 gtk_dialog_add_button (dialog,
399 GTK_STOCK_NO,
400 GTK_RESPONSE_NO);
401 gtk_dialog_add_button (dialog,
402 GTK_STOCK_YES,
403 GTK_RESPONSE_YES);
404 gtk_dialog_set_default_response (dialog,
405 GTK_RESPONSE_YES);
406 break;
407 case GTK_BUTTONS_OK_CANCEL:
408 gtk_dialog_add_button (dialog,
409 GTK_STOCK_CANCEL,
410 GTK_RESPONSE_CANCEL);
411 gtk_dialog_add_button (dialog,
412 GTK_STOCK_OK,
413 GTK_RESPONSE_OK);
414 gtk_dialog_set_default_response (dialog,
415 GTK_RESPONSE_OK);
416 break;
417 default:
418 g_warning ("Unknown GtkButtonsType");
419 break;
420 }
421 g_object_notify (G_OBJECT (alert_dialog), "buttons");
422 }
423
424 static void
425 rb_alert_dialog_style_set (GtkWidget *widget,
426 GtkStyle *prev_style)
427 {
428 GtkWidget *parent;
429 gint border_width;
430
431 border_width = 0;
432
433 parent = gtk_widget_get_parent (RB_ALERT_DIALOG (widget)->details->image);
434
435 if (parent != NULL) {
436 gtk_widget_style_get (widget, "alert_border",
437 &border_width, NULL);
438
439 gtk_container_set_border_width (GTK_CONTAINER (parent),
440 border_width);
441 }
442
443 if (GTK_WIDGET_CLASS (parent_class)->style_set) {
444 (GTK_WIDGET_CLASS (parent_class)->style_set) (widget, prev_style);
445 }
446 }