From 3b0699fc304d0f4aecb261d19869de221f5d6abf Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 7 Aug 2009 21:43:09 -0400 Subject: More refactoring of settings management. --- calendar/gui/e-timezone-entry.c | 450 ++++++++++++++++++++-------------------- 1 file changed, 230 insertions(+), 220 deletions(-) (limited to 'calendar/gui/e-timezone-entry.c') diff --git a/calendar/gui/e-timezone-entry.c b/calendar/gui/e-timezone-entry.c index f3e239aa63..53a8a4498b 100644 --- a/calendar/gui/e-timezone-entry.c +++ b/calendar/gui/e-timezone-entry.c @@ -33,12 +33,16 @@ #include #include "e-timezone-entry.h" +#define E_TIMEZONE_ENTRY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TIMEZONE_ENTRY, ETimezoneEntryPrivate)) + struct _ETimezoneEntryPrivate { /* The current timezone, set in e_timezone_entry_set_timezone() or from the timezone dialog. Note that we don't copy it or use a ref count - we assume it is never destroyed for the lifetime of this widget. */ - icaltimezone *zone; + icaltimezone *timezone; /* This can be set to the default timezone. If the current timezone setting in the ETimezoneEntry matches this, then the entry field @@ -50,314 +54,320 @@ struct _ETimezoneEntryPrivate { }; enum { - CHANGED, - LAST_SIGNAL + PROP_0, + PROP_TIMEZONE }; -static void e_timezone_entry_destroy (GtkObject *object); - -static gboolean e_timezone_entry_mnemonic_activate (GtkWidget *widget, - gboolean group_cycling); -static gboolean e_timezone_entry_focus (GtkWidget *widget, - GtkDirectionType direction); -static void on_entry_changed (GtkEntry *entry, - ETimezoneEntry *tentry); -static void on_button_clicked (GtkWidget *widget, - ETimezoneEntry *tentry); -static void add_relation (ETimezoneEntry *tentry, - GtkWidget *widget); - -static void e_timezone_entry_set_entry (ETimezoneEntry *tentry); +enum { + CHANGED, + LAST_SIGNAL +}; -static guint timezone_entry_signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL]; G_DEFINE_TYPE (ETimezoneEntry, e_timezone_entry, GTK_TYPE_HBOX) static void -e_timezone_entry_class_init (ETimezoneEntryClass *class) +timezone_entry_emit_changed (ETimezoneEntry *timezone_entry) { - GtkObjectClass *object_class = (GtkObjectClass *) class; - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); - - object_class = (GtkObjectClass*) class; - - widget_class->mnemonic_activate = e_timezone_entry_mnemonic_activate; - widget_class->focus = e_timezone_entry_focus; - timezone_entry_signals[CHANGED] = - g_signal_new ("changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ETimezoneEntryClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - object_class->destroy = e_timezone_entry_destroy; - - class->changed = NULL; + g_signal_emit (timezone_entry, signals[CHANGED], 0); } static void -e_timezone_entry_init (ETimezoneEntry *tentry) +timezone_entry_update_entry (ETimezoneEntry *timezone_entry) { - ETimezoneEntryPrivate *priv; - AtkObject *a11y; - - tentry->priv = priv = g_new0 (ETimezoneEntryPrivate, 1); + const gchar *display_name; + gchar *name_buffer; + icaltimezone *timezone; - priv->zone = NULL; - priv->default_zone = NULL; + timezone = e_timezone_entry_get_timezone (timezone_entry); - priv->entry = gtk_entry_new (); - gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE); - /*gtk_widget_set_usize (priv->date_entry, 90, 0);*/ - gtk_box_pack_start (GTK_BOX (tentry), priv->entry, TRUE, TRUE, 0); - gtk_widget_show (priv->entry); - g_signal_connect (priv->entry, "changed", G_CALLBACK (on_entry_changed), tentry); + if (timezone != NULL) { + display_name = icaltimezone_get_display_name (timezone); - priv->button = gtk_button_new_with_label (_("Select...")); - g_signal_connect (priv->button, "clicked", G_CALLBACK (on_button_clicked), tentry); - gtk_box_pack_start (GTK_BOX (tentry), priv->button, FALSE, FALSE, 6); - gtk_widget_show (priv->button); - a11y = gtk_widget_get_accessible (priv->button); - if (a11y != NULL) { - atk_object_set_name (a11y, _("Select Timezone")); - } -} + /* We check if it is one of our builtin timezone + names, in which case we call gettext to translate + it. If it isn't a builtin timezone name, we don't. */ + if (icaltimezone_get_builtin_timezone (display_name)) + display_name = _(display_name); + } else + display_name = ""; -/** - * e_timezone_entry_new: - * - * Description: Creates a new #ETimezoneEntry widget which can be used - * to provide an easy to use way for entering dates and times. - * - * Returns: a new #ETimezoneEntry widget. - */ -GtkWidget * -e_timezone_entry_new (void) -{ - ETimezoneEntry *tentry; + name_buffer = g_strdup (display_name); - tentry = g_object_new (e_timezone_entry_get_type (), NULL); + gtk_entry_set_text (GTK_ENTRY (timezone_entry->priv->entry), name_buffer); - GTK_WIDGET_SET_FLAGS (GTK_WIDGET(tentry), GTK_CAN_FOCUS); + /* XXX Do we need to hide the timezone entry at all? I know + * this overrules the previous case of hiding the timezone + * entry field when we select the default timezone. */ + gtk_widget_show (timezone_entry->priv->entry); - return GTK_WIDGET (tentry); + g_free (name_buffer); } - static void -e_timezone_entry_destroy (GtkObject *object) +timezone_entry_add_relation (ETimezoneEntry *timezone_entry) { - ETimezoneEntry *tentry; + AtkObject *a11y_timezone_entry; + AtkObject *a11y_widget; + AtkRelationSet *set; + AtkRelation *relation; + GtkWidget *widget; + GPtrArray *target; + gpointer target_object; - g_return_if_fail (E_IS_TIMEZONE_ENTRY (object)); + /* add a labelled_by relation for widget for accessibility */ - tentry = E_TIMEZONE_ENTRY (object); + widget = GTK_WIDGET (timezone_entry); + a11y_timezone_entry = gtk_widget_get_accessible (widget); - g_free (tentry->priv); - tentry->priv = NULL; + widget = timezone_entry->priv->entry; + a11y_widget = gtk_widget_get_accessible (widget); - if (GTK_OBJECT_CLASS (e_timezone_entry_parent_class)->destroy) - (* GTK_OBJECT_CLASS (e_timezone_entry_parent_class)->destroy) (object); + set = atk_object_ref_relation_set (a11y_widget); + if (set != NULL) { + relation = atk_relation_set_get_relation_by_type ( + set, ATK_RELATION_LABELLED_BY); + /* check whether has a labelled_by relation already */ + if (relation != NULL) + return; + } + + set = atk_object_ref_relation_set (a11y_timezone_entry); + if (!set) + return; + + relation = atk_relation_set_get_relation_by_type ( + set, ATK_RELATION_LABELLED_BY); + if (relation != NULL) { + target = atk_relation_get_target (relation); + target_object = g_ptr_array_index (target, 0); + if (ATK_IS_OBJECT (target_object)) { + atk_object_add_relationship ( + a11y_widget, + ATK_RELATION_LABELLED_BY, + ATK_OBJECT (target_object)); + } + } } /* The arrow button beside the date field has been clicked, so we show the popup with the ECalendar in. */ static void -on_button_clicked (GtkWidget *widget, - ETimezoneEntry *tentry) +timezone_entry_button_clicked_cb (ETimezoneEntry *timezone_entry) { - ETimezoneEntryPrivate *priv; ETimezoneDialog *timezone_dialog; GtkWidget *dialog; - - priv = tentry->priv; + icaltimezone *timezone; timezone_dialog = e_timezone_dialog_new (); - e_timezone_dialog_set_timezone (timezone_dialog, priv->zone); + timezone = e_timezone_entry_get_timezone (timezone_entry); + e_timezone_dialog_set_timezone (timezone_dialog, timezone); dialog = e_timezone_dialog_get_toplevel (timezone_dialog); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - priv->zone = e_timezone_dialog_get_timezone (timezone_dialog); - e_timezone_entry_set_entry (tentry); - } + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_ACCEPT) + goto exit; + timezone = e_timezone_dialog_get_timezone (timezone_dialog); + e_timezone_entry_set_timezone (timezone_entry, timezone); + timezone_entry_update_entry (timezone_entry); + +exit: g_object_unref (timezone_dialog); } static void -on_entry_changed (GtkEntry *entry, - ETimezoneEntry *tentry) +timezone_entry_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - g_signal_emit (GTK_OBJECT (tentry), timezone_entry_signals[CHANGED], 0); -} - -icaltimezone* -e_timezone_entry_get_timezone (ETimezoneEntry *tentry) -{ - ETimezoneEntryPrivate *priv; - - g_return_val_if_fail (E_IS_TIMEZONE_ENTRY (tentry), NULL); - - priv = tentry->priv; + switch (property_id) { + case PROP_TIMEZONE: + e_timezone_entry_set_timezone ( + E_TIMEZONE_ENTRY (object), + g_value_get_pointer (value)); + return; + } - return priv->zone; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -add_relation (ETimezoneEntry *tentry, - GtkWidget *widget) +timezone_entry_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - AtkObject *a11ytentry, *a11yWidget; - AtkRelationSet *set; - AtkRelation *relation; - GPtrArray *target; - gpointer target_object; - - /* add a labelled_by relation for widget for accessibility */ - - a11ytentry = gtk_widget_get_accessible (GTK_WIDGET (tentry)); - a11yWidget = gtk_widget_get_accessible (widget); - - set = atk_object_ref_relation_set (a11yWidget); - if (set != NULL) { - relation = atk_relation_set_get_relation_by_type (set, - ATK_RELATION_LABELLED_BY); - /* check whether has a labelled_by relation already */ - if (relation != NULL) + switch (property_id) { + case PROP_TIMEZONE: + g_value_set_pointer ( + value, e_timezone_entry_get_timezone ( + E_TIMEZONE_ENTRY (object))); return; } - set = atk_object_ref_relation_set (a11ytentry); - if (!set) - return; - - relation = atk_relation_set_get_relation_by_type (set, - ATK_RELATION_LABELLED_BY); - if (relation != NULL) { - target = atk_relation_get_target (relation); - target_object = g_ptr_array_index (target, 0); - if (ATK_IS_OBJECT (target_object)) { - atk_object_add_relationship (a11yWidget, - ATK_RELATION_LABELLED_BY, - ATK_OBJECT (target_object)); - } - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } -void -e_timezone_entry_set_timezone (ETimezoneEntry *tentry, - icaltimezone *zone) +static gboolean +timezone_entry_mnemonic_activate (GtkWidget *widget, + gboolean group_cycling) { ETimezoneEntryPrivate *priv; - g_return_if_fail (E_IS_TIMEZONE_ENTRY (tentry)); + priv = E_TIMEZONE_ENTRY_GET_PRIVATE (widget); - priv = tentry->priv; - - priv->zone = zone; - - e_timezone_entry_set_entry (tentry); + if (GTK_WIDGET_CAN_FOCUS (widget)) { + if (priv->button != NULL) + gtk_widget_grab_focus (priv->button); + } - add_relation (tentry, priv->entry); + return TRUE; } -/* Sets the default timezone. If the current timezone matches this, then the - entry field is hidden. This is useful since most people do not use timezones - so it makes the user interface simpler. */ -void -e_timezone_entry_set_default_timezone (ETimezoneEntry *tentry, - icaltimezone *zone) +static gboolean +timezone_entry_focus (GtkWidget *widget, + GtkDirectionType direction) { ETimezoneEntryPrivate *priv; - g_return_if_fail (E_IS_TIMEZONE_ENTRY (tentry)); + priv = E_TIMEZONE_ENTRY_GET_PRIVATE (widget); - priv = tentry->priv; + if (direction == GTK_DIR_TAB_FORWARD) { + if (GTK_WIDGET_HAS_FOCUS (priv->entry)) + gtk_widget_grab_focus (priv->button); + else if (GTK_WIDGET_HAS_FOCUS (priv->button)) + return FALSE; + else if (GTK_WIDGET_VISIBLE (priv->entry)) + gtk_widget_grab_focus (priv->entry); + else + gtk_widget_grab_focus (priv->button); - priv->default_zone = zone; + } else if (direction == GTK_DIR_TAB_BACKWARD) { + if (GTK_WIDGET_HAS_FOCUS (priv->entry)) + return FALSE; + else if (GTK_WIDGET_HAS_FOCUS (priv->button)) { + if (GTK_WIDGET_VISIBLE (priv->entry)) + gtk_widget_grab_focus (priv->entry); + else + return FALSE; + } else + gtk_widget_grab_focus (priv->button); + } else + return FALSE; - e_timezone_entry_set_entry (tentry); + return TRUE; } static void -e_timezone_entry_set_entry (ETimezoneEntry *tentry) +e_timezone_entry_class_init (ETimezoneEntryClass *class) { - ETimezoneEntryPrivate *priv; - const gchar *display_name; - gchar *name_buffer; + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + g_type_class_add_private (class, sizeof (ETimezoneEntryPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = timezone_entry_set_property; + object_class->get_property = timezone_entry_get_property; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->mnemonic_activate = timezone_entry_mnemonic_activate; + widget_class->focus = timezone_entry_focus; + + g_object_class_install_property ( + object_class, + PROP_TIMEZONE, + g_param_spec_pointer ( + "timezone", + "Timezone", + NULL, + G_PARAM_READWRITE)); + + signals[CHANGED] = g_signal_new ( + "changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETimezoneEntryClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} - priv = tentry->priv; +static void +e_timezone_entry_init (ETimezoneEntry *timezone_entry) +{ + AtkObject *a11y; + GtkWidget *widget; - if (priv->zone) { - display_name = icaltimezone_get_display_name (priv->zone); + timezone_entry->priv = E_TIMEZONE_ENTRY_GET_PRIVATE (timezone_entry); - /* We check if it is one of our builtin timezone - names, in which case we call gettext to translate - it. If it isn't a builtin timezone name, we - don't. */ - if (icaltimezone_get_builtin_timezone (display_name)) - display_name = _(display_name); - } else - display_name = ""; + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (timezone_entry), GTK_CAN_FOCUS); - name_buffer = g_strdup (display_name); + widget = gtk_entry_new (); + gtk_editable_set_editable (GTK_EDITABLE (widget), FALSE); + gtk_box_pack_start (GTK_BOX (timezone_entry), widget, TRUE, TRUE, 0); + timezone_entry->priv->entry = widget; + gtk_widget_show (widget); - gtk_entry_set_text (GTK_ENTRY (priv->entry), name_buffer); + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (timezone_entry_emit_changed), timezone_entry); - /* do we need to hide the timezone entry at all? i know this overrules the previous case of hiding the timezone - * entry field when we select the default timezone - */ - gtk_widget_show (priv->entry); + widget = gtk_button_new_with_label (_("Select...")); + gtk_box_pack_start (GTK_BOX (timezone_entry), widget, FALSE, FALSE, 6); + timezone_entry->priv->button = widget; + gtk_widget_show (widget); - g_free (name_buffer); + g_signal_connect_swapped ( + widget, "clicked", + G_CALLBACK (timezone_entry_button_clicked_cb), timezone_entry); + + a11y = gtk_widget_get_accessible (timezone_entry->priv->button); + if (a11y != NULL) + atk_object_set_name (a11y, _("Select Timezone")); } -static gboolean -e_timezone_entry_mnemonic_activate (GtkWidget *widget, - gboolean group_cycling) +GtkWidget * +e_timezone_entry_new (void) { - GtkButton *button = NULL; + return g_object_new (E_TYPE_TIMEZONE_ENTRY, NULL); +} - if (GTK_WIDGET_CAN_FOCUS (widget)) { - button = GTK_BUTTON (((ETimezoneEntryPrivate *) ((ETimezoneEntry *) widget)->priv)->button); - if (button != NULL) - gtk_widget_grab_focus (GTK_WIDGET (button)); - } +icaltimezone * +e_timezone_entry_get_timezone (ETimezoneEntry *timezone_entry) +{ + g_return_val_if_fail (E_IS_TIMEZONE_ENTRY (timezone_entry), NULL); - return TRUE; + return timezone_entry->priv->timezone; } -static gboolean -e_timezone_entry_focus (GtkWidget *widget, GtkDirectionType direction) +void +e_timezone_entry_set_timezone (ETimezoneEntry *timezone_entry, + icaltimezone *timezone) { - ETimezoneEntry *tentry; + g_return_if_fail (E_IS_TIMEZONE_ENTRY (timezone_entry)); - tentry = E_TIMEZONE_ENTRY (widget); + timezone_entry->priv->timezone = timezone; - if (direction == GTK_DIR_TAB_FORWARD) { - if (GTK_WIDGET_HAS_FOCUS (tentry->priv->entry)) - gtk_widget_grab_focus (tentry->priv->button); - else if (GTK_WIDGET_HAS_FOCUS (tentry->priv->button)) - return FALSE; - else if (GTK_WIDGET_VISIBLE (tentry->priv->entry)) - gtk_widget_grab_focus (tentry->priv->entry); - else - gtk_widget_grab_focus (tentry->priv->button); - } else if (direction == GTK_DIR_TAB_BACKWARD) { - if (GTK_WIDGET_HAS_FOCUS (tentry->priv->entry)) - return FALSE; - else if (GTK_WIDGET_HAS_FOCUS (tentry->priv->button)) { - if (GTK_WIDGET_VISIBLE (tentry->priv->entry)) - gtk_widget_grab_focus (tentry->priv->entry); - else - return FALSE; - } else - gtk_widget_grab_focus (tentry->priv->button); - } else - return FALSE; - return TRUE; + timezone_entry_update_entry (timezone_entry); + timezone_entry_add_relation (timezone_entry); + + g_object_notify (G_OBJECT (timezone_entry), "timezone"); } +/* Sets the default timezone. If the current timezone matches this, + * then the entry field is hidden. This is useful since most people + * do not use timezones so it makes the user interface simpler. */ +void +e_timezone_entry_set_default_timezone (ETimezoneEntry *timezone_entry, + icaltimezone *timezone) +{ + g_return_if_fail (E_IS_TIMEZONE_ENTRY (timezone_entry)); + + timezone_entry->priv->default_zone = timezone; + + timezone_entry_update_entry (timezone_entry); +} -- cgit v1.2.3