From f20528381a13299e8d160195d4b731e10b7ed437 Mon Sep 17 00:00:00 2001 From: Jonathon Jongsma Date: Fri, 4 Dec 2009 15:53:29 -0600 Subject: Add EAlertDialog This is a proper implementation of the various alert dialog helper functions. It is a proper subclass of GtkDialog, etc. --- e-util/Makefile.am | 6 +- e-util/e-alert-dialog.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ e-util/e-alert-dialog.h | 82 +++++++++++ 3 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 e-util/e-alert-dialog.c create mode 100644 e-util/e-alert-dialog.h diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 51fa43428e..7ca0aa6ff0 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -12,7 +12,9 @@ privsolib_LTLIBRARIES = libeutil.la libeconduit.la eutilinclude_HEADERS = \ e-account-utils.h \ e-activity.h \ + e-alert.h \ e-alert-activity.h \ + e-alert-dialog.h \ e-bconf-map.h \ e-binding.h \ e-bit-array.h \ @@ -22,7 +24,6 @@ eutilinclude_HEADERS = \ e-datetime-format.h \ e-dialog-utils.h \ e-dialog-widgets.h \ - e-alert.h \ e-event.h \ e-file-utils.h \ e-folder-map.h \ @@ -85,7 +86,9 @@ libeutil_la_SOURCES = \ $(eutilinclude_HEADERS) \ e-account-utils.c \ e-activity.c \ + e-alert.c \ e-alert-activity.c \ + e-alert-dialog.c \ e-bconf-map.c \ e-binding.c \ e-bit-array.c \ @@ -95,7 +98,6 @@ libeutil_la_SOURCES = \ e-datetime-format.c \ e-dialog-utils.c \ e-dialog-widgets.c \ - e-alert.c \ e-event.c \ e-file-utils.c \ e-folder-map.c \ diff --git a/e-util/e-alert-dialog.c b/e-util/e-alert-dialog.c new file mode 100644 index 0000000000..eb89e68fe6 --- /dev/null +++ b/e-util/e-alert-dialog.c @@ -0,0 +1,362 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Michael Zucchi + * Jonathon Jongsma + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2009 Intel Corporation + */ + +#include "e-alert-dialog.h" +#include "e-util.h" + +G_DEFINE_TYPE (EAlertDialog, e_alert_dialog, GTK_TYPE_DIALOG) + +#define ALERT_DIALOG_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_ALERT_DIALOG, EAlertDialogPrivate)) + +struct _EAlertDialogPrivate +{ + GtkWindow *parent; + EAlert *alert; +}; + +enum +{ + PROP_0, + PROP_PARENT, + PROP_ALERT +}; + +static void +e_alert_dialog_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + EAlertDialog *dialog = (EAlertDialog*) object; + + switch (property_id) + { + case PROP_PARENT: + dialog->priv->parent = g_value_dup_object (value); + break; + case PROP_ALERT: + dialog->priv->alert = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +e_alert_dialog_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + EAlertDialog *dialog = (EAlertDialog*) object; + + switch (property_id) + { + case PROP_PARENT: + g_value_set_object (value, dialog->priv->parent); + break; + case PROP_ALERT: + g_value_set_object (value, dialog->priv->alert); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +e_alert_dialog_dispose (GObject *object) +{ + EAlertDialog *dialog = (EAlertDialog*) object; + + if (dialog->priv->parent) { + g_object_unref (dialog->priv->parent); + dialog->priv->parent = NULL; + } + + if (dialog->priv->alert) { + g_object_unref (dialog->priv->alert); + dialog->priv->alert = NULL; + } + + G_OBJECT_CLASS (e_alert_dialog_parent_class)->dispose (object); +} + +static void +dialog_response_cb(GtkWidget *w, guint button, gpointer user_data) +{ + EAlertDialogPrivate *priv = ALERT_DIALOG_PRIVATE (w); + + if (button == GTK_RESPONSE_HELP) { + g_signal_stop_emission_by_name(w, "response"); + e_display_help (GTK_WINDOW (w), e_alert_peek_help_uri (priv->alert)); + } +} + +static void +e_alert_dialog_init (EAlertDialog *self) +{ + self->priv = ALERT_DIALOG_PRIVATE (self); +} + +static void +e_alert_dialog_constructed (GObject *obj) +{ + EAlertDialog *self = (EAlertDialog*) obj; + EAlert *alert; + struct _e_alert_button *b; + GtkWidget *hbox, *w, *scroll=NULL; + GtkWidget *action_area; + GtkWidget *content_area; + GString *out; + gchar *perr=NULL, *serr=NULL; + gchar *title, *primary, *secondary; + + g_return_if_fail (self != NULL); + + self->priv = ALERT_DIALOG_PRIVATE (self); + alert = self->priv->alert; + + action_area = gtk_dialog_get_action_area ((GtkDialog*) self); + content_area = gtk_dialog_get_content_area ((GtkDialog*) self); + + gtk_dialog_set_has_separator((GtkDialog*) self, FALSE); + + gtk_widget_ensure_style ((GtkWidget *)self); + gtk_container_set_border_width (GTK_CONTAINER (action_area), 12); + gtk_container_set_border_width (GTK_CONTAINER (content_area), 0); + + if (self->priv->parent) + gtk_window_set_transient_for ((GtkWindow *)self, self->priv->parent); + else + g_warning ( + "Something called %s() with a NULL parent window. " + "This is no longer legal, please fix it.", G_STRFUNC); + + if (e_alert_get_flags (alert) & GTK_DIALOG_MODAL) + gtk_window_set_modal((GtkWindow *)self, TRUE); + gtk_window_set_destroy_with_parent((GtkWindow *)self, TRUE); + + if (e_alert_peek_help_uri (alert)) { + w = gtk_dialog_add_button((GtkDialog*) self, GTK_STOCK_HELP, GTK_RESPONSE_HELP); + g_signal_connect(self, "response", G_CALLBACK(dialog_response_cb), NULL); + } + + b = e_alert_get_buttons (alert); + if (b == NULL) { + gtk_dialog_add_button((GtkDialog*) self, GTK_STOCK_OK, GTK_RESPONSE_OK); + } else { + for (; b; b=b->next) { + if (b->stock) { + if (b->label) { +#if 0 + /* FIXME: So although this looks like it will work, it wont. + Need to do it the hard way ... it also breaks the + default_response stuff */ + w = gtk_button_new_from_stock(b->stock); + gtk_button_set_label((GtkButton *)w, b->label); + gtk_widget_show(w); + gtk_dialog_add_action_widget(self, w, b->response); +#endif + gtk_dialog_add_button((GtkDialog*) self, b->label, b->response); + } else + gtk_dialog_add_button((GtkDialog*) self, b->stock, b->response); + } else + gtk_dialog_add_button((GtkDialog*) self, b->label, b->response); + } + } + + if (e_alert_get_default_response (alert)) + gtk_dialog_set_default_response((GtkDialog*) self, + e_alert_get_default_response (alert)); + + hbox = gtk_hbox_new(FALSE, 0); + gtk_container_set_border_width((GtkContainer *)hbox, 12); + + w = gtk_image_new_from_stock + (e_alert_peek_stock_image (alert), GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.0); + gtk_box_pack_start((GtkBox *)hbox, w, FALSE, FALSE, 12); + + title = e_alert_get_title (alert); + gtk_window_set_title((GtkWindow *)self, title); + + out = g_string_new (""); + primary = e_alert_get_primary_text (alert); + if (primary) { + g_string_append_printf (out, + "%s", + primary); + /* FIXME: What is this used for? */ + perr = g_strdup (primary); + } else + perr = g_strdup (title); /* XXX: why? */ + + secondary = e_alert_get_secondary_text (alert); + if (secondary) { + g_string_append (out, secondary); + serr = g_strdup (secondary); + } + + g_free (secondary); + g_free (title); + g_free (primary); + + if (e_alert_get_scroll (alert)) { + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy ((GtkScrolledWindow *)scroll, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + } + w = gtk_label_new(NULL); + gtk_label_set_selectable((GtkLabel *)w, TRUE); + gtk_label_set_line_wrap((GtkLabel *)w, TRUE); + gtk_label_set_markup((GtkLabel *)w, out->str); + GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_FOCUS); + g_string_free(out, TRUE); + if (e_alert_get_scroll (alert)) { + gtk_scrolled_window_add_with_viewport ((GtkScrolledWindow *)scroll, w); + gtk_box_pack_start((GtkBox *)hbox, scroll, FALSE, FALSE, 0); + gtk_window_set_default_size ((GtkWindow *)self, 360, 180); + } else + gtk_box_pack_start((GtkBox *)hbox, w, TRUE, TRUE, 0); + + gtk_widget_show_all(hbox); + + gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0); + /* FIXME: What is this used for? */ + g_object_set_data_full ((GObject *) self, "primary", perr, g_free); + g_object_set_data_full ((GObject *) self, "secondary", serr, g_free); +} + +static void +e_alert_dialog_class_init (EAlertDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (EAlertDialogPrivate)); + + object_class->dispose = e_alert_dialog_dispose; + object_class->get_property = e_alert_dialog_get_property; + object_class->set_property = e_alert_dialog_set_property; + object_class->constructed = e_alert_dialog_constructed; + + g_object_class_install_property (object_class, + PROP_PARENT, + g_param_spec_object ("parent", + "parent window", + "A parent window to be transient for", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_ALERT, + g_param_spec_object ("alert", + "alert", + "EAlert to be displayed", + E_TYPE_ALERT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + + +GtkWidget* +e_alert_dialog_new (GtkWindow *parent, EAlert *alert) +{ + return (GtkWidget*) g_object_new (E_TYPE_ALERT_DIALOG, "parent", parent, "alert", alert, NULL); +} + +GtkWidget* +e_alert_dialog_new_for_args (GtkWindow *parent, const gchar *tag, const gchar *arg0, ...) +{ + GtkWidget *d; + EAlert *e; + va_list ap; + + va_start(ap, arg0); + e = e_alert_new_valist(tag, arg0, ap); + va_end(ap); + + d = e_alert_dialog_new (parent, e); + g_object_unref (e); + + return d; +} + + +gint +e_alert_run_dialog(GtkWindow *parent, EAlert *alert) +{ + GtkWidget *dialog; + gint res; + + dialog = e_alert_dialog_new (parent, alert); + + res = gtk_dialog_run((GtkDialog *)dialog); + gtk_widget_destroy(dialog); + + return res; +} + +gint +e_alert_run_dialog_for_args (GtkWindow *parent, const gchar *tag, const gchar *arg0, ...) +{ + EAlert *e; + va_list ap; + gint response; + + va_start(ap, arg0); + e = e_alert_new_valist(tag, arg0, ap); + va_end(ap); + + response = e_alert_run_dialog (parent, e); + g_object_unref (e); + + return response; +} + +/** + * e_alert_dialog_count_buttons: + * @dialog: a #GtkDialog + * + * Counts the number of buttons in @dialog's action area. + * + * Returns: number of action area buttons + **/ +guint +e_alert_dialog_count_buttons (EAlertDialog *dialog) +{ + GtkWidget *container; + GList *children, *iter; + guint n_buttons = 0; + + g_return_val_if_fail (E_IS_ALERT_DIALOG (dialog), 0); + + container = gtk_dialog_get_action_area ((GtkDialog*) dialog); + children = gtk_container_get_children (GTK_CONTAINER (container)); + + /* Iterate over the children looking for buttons. */ + for (iter = children; iter != NULL; iter = iter->next) + if (GTK_IS_BUTTON (iter->data)) + n_buttons++; + + g_list_free (children); + + return n_buttons; +} diff --git a/e-util/e-alert-dialog.h b/e-util/e-alert-dialog.h new file mode 100644 index 0000000000..d70a76a951 --- /dev/null +++ b/e-util/e-alert-dialog.h @@ -0,0 +1,82 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + * + * Authors: + * Michael Zucchi + * Jonathon Jongsma + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2009 Intel Corporation + */ + +#ifndef _E_ALERT_DIALOG_H +#define _E_ALERT_DIALOG_H + +#include +#include + +G_BEGIN_DECLS + +#define E_TYPE_ALERT_DIALOG e_alert_dialog_get_type() + +#define E_ALERT_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + E_TYPE_ALERT_DIALOG, EAlertDialog)) + +#define E_ALERT_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + E_TYPE_ALERT_DIALOG, EAlertDialogClass)) + +#define E_IS_ALERT_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + E_TYPE_ALERT_DIALOG)) + +#define E_IS_ALERT_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + E_TYPE_ALERT_DIALOG)) + +#define E_ALERT_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + E_TYPE_ALERT_DIALOG, EAlertDialogClass)) + +typedef struct _EAlertDialog EAlertDialog; +typedef struct _EAlertDialogClass EAlertDialogClass; +typedef struct _EAlertDialogPrivate EAlertDialogPrivate; + +struct _EAlertDialog +{ + GtkDialog parent; + EAlertDialogPrivate *priv; +}; + +struct _EAlertDialogClass +{ + GtkDialogClass parent_class; +}; + +GType e_alert_dialog_get_type (void); + +GtkWidget* e_alert_dialog_new (GtkWindow* parent, EAlert *alert); +GtkWidget* e_alert_dialog_new_for_args (GtkWindow* parent, const gchar *tag, const gchar *arg0, ...); + +/* Convenience functions for displaying the alert in a GtkDialog */ +gint e_alert_run_dialog(GtkWindow *parent, EAlert *alert); +gint e_alert_run_dialog_for_args (GtkWindow *parent, const gchar *tag, const gchar *arg0, ...); + +guint e_alert_dialog_count_buttons (EAlertDialog *dialog); + +G_END_DECLS + +#endif /* _E_ALERT_DIALOG_H */ -- cgit v1.2.3