/*
* 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 <http://www.gnu.org/licenses/>
*
*
* Authors:
* Michael Zucchi <notzed@ximian.com>
* Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>
*
* 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 *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)) {
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_peek_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, FALSE);
gtk_window_set_title((GtkWindow *)self, title);
out = g_string_new ("");
primary = e_alert_get_primary_text (alert, TRUE);
if (primary) {
g_string_append_printf (out,
"<span weight=\"bold\" size=\"larger\">%s</span>\n\n",
primary);
}
secondary = e_alert_get_secondary_text (alert, TRUE);
if (secondary) {
g_string_append (out, 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);
}
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 #EAlertDialog
*
* 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;
}
/**
* e_alert_dialog_get_alert:
* @dialog: a #EAlertDialog
*
* Convenience API for getting the #EAlert associated with @dialog
*
* Return value: the #EAlert associated with @dialog. The alert should be
* unreffed when no longer needed.
*/
EAlert *
e_alert_dialog_get_alert (EAlertDialog *dialog)
{
EAlert *alert = NULL;
g_return_val_if_fail (dialog != NULL, NULL);
g_object_get (dialog, "alert", &alert,
NULL);
return alert;
}