From f5bed9bf7b143fff9bd258ea31fdac192e00a0d9 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 27 Nov 2007 20:24:44 +0000 Subject: ** Fixes bug #495123 2007-11-27 Matthew Barnes ** Fixes bug #495123 * composer/Makefile.am: Add a bunch of files for managing composer headers. * composer/e-msg-composer.c (build_message), (from_changed_cb), (set_editor_signature), (e_msg_composer_set_body), (e_msg_composer_get_preferred_account): * plugins/exchange-operations/exchange-mail-send-options.c (append_to_header): Use e_msg_composer_hdrs_get_from_account() to obtain the EAccount. * composer/e-msg-composer-hdrs.c: * composer/e-msg-composer-hdrs.h: Massive refactoring to use new EComposerHeader classes. * composer/e-composer-header.c: * composer/e-composer-header.h: * composer/e-composer-from-header.c: * composer/e-composer-from-header.h: * composer/e-composer-name-header.c: * composer/e-composer-name-header.h: * composer/e-composer-post-header.c: * composer/e-composer-post-header.h: * composer/e-composer-text-header.c: * composer/e-composer-text-header.h: New GObject classes manage different types of composer headers. See bug #495123 for a more detailed description of each class. * mail/mail-session.c (mail_session_init): Pass the CamelSession to the EAccountComboBox class (ugly hack). * widgets/misc/Makefile.am: Add e-account-combo-box.[ch]. * widgets/misc/e-account-combo-box.c: * widgets/misc/e-account-combo-box.h: New widget renders an EAccountList as a combo box. Also listens for changes to the EAccountList and updates itself accordingly. svn path=/trunk/; revision=34600 --- composer/e-composer-header.c | 310 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 composer/e-composer-header.c (limited to 'composer/e-composer-header.c') diff --git a/composer/e-composer-header.c b/composer/e-composer-header.c new file mode 100644 index 0000000000..a7c10997cc --- /dev/null +++ b/composer/e-composer-header.c @@ -0,0 +1,310 @@ +#include "e-composer-header.h" + +#define E_COMPOSER_HEADER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderPrivate)) + +enum { + PROP_0, + PROP_BUTTON, + PROP_LABEL, + PROP_VISIBLE +}; + +enum { + CHANGED, + CLICKED, + LAST_SIGNAL +}; + +struct _EComposerHeaderPrivate { + gchar *label; + gboolean button; +}; + +static gpointer parent_class; +static guint signal_ids[LAST_SIGNAL]; + +static void +composer_header_button_clicked_cb (GtkButton *button, + EComposerHeader *header) +{ + gtk_widget_grab_focus (header->input_widget); + g_signal_emit (header, signal_ids[CLICKED], 0); +} + +static GObject * +composer_header_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *object; + GtkWidget *widget; + EComposerHeader *header; + + /* Chain up to parent's constructor() method. */ + object = G_OBJECT_CLASS (parent_class)->constructor ( + type, n_construct_properties, construct_properties); + + header = E_COMPOSER_HEADER (object); + + if (header->priv->button) { + widget = gtk_button_new_with_mnemonic (header->priv->label); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); + g_signal_connect ( + widget, "clicked", + G_CALLBACK (composer_header_button_clicked_cb), + header); + } else { + widget = gtk_label_new_with_mnemonic (header->priv->label); + + /* The subclass may not have initialized 'input_widget' yet, + * in which case the subclass will have to do this. */ + if (header->input_widget != NULL) + gtk_label_set_mnemonic_widget ( + GTK_LABEL (widget), header->input_widget); + } + header->title_widget = g_object_ref_sink (widget); + + g_free (header->priv->label); + header->priv->label = NULL; + + return object; +} + +static void +composer_header_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EComposerHeaderPrivate *priv; + + priv = E_COMPOSER_HEADER_GET_PRIVATE (object); + + switch (property_id) { + case PROP_BUTTON: /* construct only */ + priv->button = g_value_get_boolean (value); + return; + + case PROP_LABEL: /* construct only */ + priv->label = g_value_dup_string (value); + return; + + case PROP_VISIBLE: + e_composer_header_set_visible ( + E_COMPOSER_HEADER (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +composer_header_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EComposerHeaderPrivate *priv; + + priv = E_COMPOSER_HEADER_GET_PRIVATE (object); + + switch (property_id) { + case PROP_BUTTON: /* construct only */ + g_value_set_boolean (value, priv->button); + return; + + case PROP_LABEL: /* construct only */ + g_value_take_string ( + value, e_composer_header_get_label ( + E_COMPOSER_HEADER (object))); + return; + + case PROP_VISIBLE: + g_value_set_boolean ( + value, e_composer_header_get_visible ( + E_COMPOSER_HEADER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +composer_header_dispose (GObject *object) +{ + EComposerHeader *header = E_COMPOSER_HEADER (object); + + if (header->title_widget != NULL) { + g_object_unref (header->title_widget); + header->title_widget = NULL; + } + + if (header->input_widget != NULL) { + g_object_unref (header->input_widget); + header->input_widget = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +composer_header_class_init (EComposerHeaderClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EComposerHeaderPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructor = composer_header_constructor; + object_class->set_property = composer_header_set_property; + object_class->get_property = composer_header_get_property; + object_class->dispose = composer_header_dispose; + + g_object_class_install_property ( + object_class, + PROP_BUTTON, + g_param_spec_boolean ( + "button", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_LABEL, + g_param_spec_string ( + "label", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_VISIBLE, + g_param_spec_boolean ( + "visible", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE)); + + signal_ids[CHANGED] = g_signal_new ( + "changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signal_ids[CLICKED] = g_signal_new ( + "clicked", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +composer_header_init (EComposerHeader *header) +{ + header->priv = E_COMPOSER_HEADER_GET_PRIVATE (header); +} + +GType +e_composer_header_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EComposerHeaderClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) composer_header_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EComposerHeader), + 0, /* n_preallocs */ + (GInstanceInitFunc) composer_header_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EComposerHeader", + &type_info, G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +gchar * +e_composer_header_get_label (EComposerHeader *header) +{ + gchar *label; + + g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), NULL); + + /* GtkButton and GtkLabel both have a "label" property. */ + g_object_get (header->title_widget, "label", &label, NULL); + + return label; +} + +gboolean +e_composer_header_get_visible (EComposerHeader *header) +{ + gboolean visible; + + g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE); + + visible = GTK_WIDGET_VISIBLE (header->title_widget); + if (GTK_WIDGET_VISIBLE (header->input_widget) != visible) + g_warning ("%s: Visibility is out of sync", G_STRFUNC); + + return visible; +} + +void +e_composer_header_set_visible (EComposerHeader *header, + gboolean visible) +{ + g_return_if_fail (E_IS_COMPOSER_HEADER (header)); + + if (visible) { + gtk_widget_show (header->title_widget); + gtk_widget_show (header->input_widget); + } else { + gtk_widget_hide (header->title_widget); + gtk_widget_hide (header->input_widget); + } + + g_object_notify (G_OBJECT (header), "visible"); +} + +void +e_composer_header_set_title_tooltip (EComposerHeader *header, + const gchar *tooltip) +{ + g_return_if_fail (E_IS_COMPOSER_HEADER (header)); + + gtk_widget_set_tooltip_text (header->title_widget, tooltip); +} + +void +e_composer_header_set_input_tooltip (EComposerHeader *header, + const gchar *tooltip) +{ + g_return_if_fail (E_IS_COMPOSER_HEADER (header)); + + gtk_widget_set_tooltip_text (header->input_widget, tooltip); +} -- cgit v1.2.3