From 0d6061a4ebf34cbe4f640e755372c38bd698ed25 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sun, 12 Jul 2009 12:55:10 -0400 Subject: Add a "quit-requested" signal to the shutdown protocol. The contact and contact-list editors now demonstrate this part of the shutdown protocol. They listen for the "quit-requested" signal from the shell and prompt to save changes, discard changes or cancel. If the user cancels, the editor calls e_shell_cancel_quit() to do just that. --- addressbook/gui/contact-editor/eab-editor.c | 352 ++++++++++++++++------------ 1 file changed, 204 insertions(+), 148 deletions(-) (limited to 'addressbook/gui/contact-editor/eab-editor.c') diff --git a/addressbook/gui/contact-editor/eab-editor.c b/addressbook/gui/contact-editor/eab-editor.c index b5a4683540..554db9aa7b 100644 --- a/addressbook/gui/contact-editor/eab-editor.c +++ b/addressbook/gui/contact-editor/eab-editor.c @@ -31,13 +31,19 @@ #include "e-util/e-util.h" #include "addressbook/gui/widgets/eab-gui-util.h" -static void eab_editor_default_show (EABEditor *editor); -static void eab_editor_default_raise (EABEditor *editor); -static void eab_editor_default_close (EABEditor *editor); -static void eab_editor_class_init (EABEditorClass *klass); -static void eab_editor_init (EABEditor *editor); +#define EAB_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EAB_TYPE_EDITOR, EABEditorPrivate)) + +struct _EABEditorPrivate { + EShell *shell; +}; + +enum { + PROP_0, + PROP_SHELL +}; -/* Signal IDs */ enum { CONTACT_ADDED, CONTACT_MODIFIED, @@ -46,97 +52,125 @@ enum { LAST_SIGNAL }; -static GSList *all_editors = NULL; - -static GtkObjectClass *parent_class = NULL; - -static guint editor_signals[LAST_SIGNAL]; +static GSList *all_editors; +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; -GType -eab_editor_get_type (void) +static void +eab_editor_quit_requested_cb (EABEditor *editor, + EShell *shell) { - static GType editor_type = 0; - - if (!editor_type) { - static const GTypeInfo editor_info = { - sizeof (EABEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) eab_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EABEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) eab_editor_init, - }; + GtkWindow *window; - editor_type = g_type_register_static (G_TYPE_OBJECT, "EABEditor", &editor_info, 0); - } + window = eab_editor_get_window (editor); - return editor_type; + eab_editor_raise (editor); + if (!eab_editor_prompt_to_save_changes (editor, window)) + e_shell_cancel_quit (shell); } static void -eab_editor_default_show (EABEditor *editor) +eab_editor_set_shell (EABEditor *editor, + EShell *shell) { - g_warning ("abstract eab_editor_show called"); + g_return_if_fail (editor->priv->shell == NULL); + g_return_if_fail (E_IS_SHELL (shell)); + + editor->priv->shell = g_object_ref (shell); + + g_signal_connect_swapped ( + shell, "quit-requested", + G_CALLBACK (eab_editor_quit_requested_cb), editor); } static void -eab_editor_default_close (EABEditor *editor) +eab_editor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - g_warning ("abstract eab_editor_close called"); + switch (property_id) { + case PROP_SHELL: + eab_editor_set_shell ( + EAB_EDITOR (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -eab_editor_default_raise (EABEditor *editor) +eab_editor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - g_warning ("abstract eab_editor_raise called"); + switch (property_id) { + case PROP_SHELL: + g_value_set_object ( + value, eab_editor_get_shell ( + EAB_EDITOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -eab_editor_default_save_contact (EABEditor *editor, gboolean should_close) +eab_editor_dispose (GObject *object) { - g_warning ("abstract eab_editor_save_contact called"); -} + EABEditorPrivate *priv; -static gboolean -eab_editor_default_is_valid (EABEditor *editor) -{ - g_warning ("abstract eab_editor_is_valid called"); - return FALSE; -} + priv = EAB_EDITOR_GET_PRIVATE (object); -static gboolean -eab_editor_default_is_changed (EABEditor *editor) -{ - g_warning ("abstract eab_editor_is_changed called"); - return FALSE; -} + if (priv->shell != NULL) { + g_signal_handlers_disconnect_matched ( + priv->shell, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, object); + g_object_unref (priv->shell); + priv->shell = NULL; + } -static GtkWindow* -eab_editor_default_get_window (EABEditor *editor) -{ - g_warning ("abstract eab_editor_get_window called"); - return NULL; + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -eab_editor_class_init (EABEditorClass *klass) +eab_editor_finalize (GObject *object) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + all_editors = g_slist_remove (all_editors, object); - parent_class = g_type_class_ref (G_TYPE_OBJECT); - - klass->show = eab_editor_default_show; - klass->close = eab_editor_default_close; - klass->raise = eab_editor_default_raise; - klass->save_contact = eab_editor_default_save_contact; - klass->is_valid = eab_editor_default_is_valid; - klass->is_changed = eab_editor_default_is_changed; - klass->get_window = eab_editor_default_get_window; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} - editor_signals[CONTACT_ADDED] = +static void +eab_editor_class_init (EABEditorClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EABEditorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = eab_editor_set_property; + object_class->get_property = eab_editor_get_property; + object_class->dispose = eab_editor_dispose; + object_class->finalize = eab_editor_finalize; + + g_object_class_install_property ( + object_class, + PROP_SHELL, + g_param_spec_object ( + "shell", + _("Shell"), + _("The EShell singleton"), + E_TYPE_SHELL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + signals[CONTACT_ADDED] = g_signal_new ("contact_added", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -146,7 +180,7 @@ eab_editor_class_init (EABEditorClass *klass) G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_OBJECT); - editor_signals[CONTACT_MODIFIED] = + signals[CONTACT_MODIFIED] = g_signal_new ("contact_modified", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -156,7 +190,7 @@ eab_editor_class_init (EABEditorClass *klass) G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_OBJECT); - editor_signals[CONTACT_DELETED] = + signals[CONTACT_DELETED] = g_signal_new ("contact_deleted", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -166,7 +200,7 @@ eab_editor_class_init (EABEditorClass *klass) G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_OBJECT); - editor_signals[EDITOR_CLOSED] = + signals[EDITOR_CLOSED] = g_signal_new ("editor_closed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, @@ -179,78 +213,143 @@ eab_editor_class_init (EABEditorClass *klass) static void eab_editor_init (EABEditor *editor) { + editor->priv = EAB_EDITOR_GET_PRIVATE (editor); + + all_editors = g_slist_prepend (all_editors, editor); +} + +GType +eab_editor_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EABEditorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) eab_editor_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EABEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) eab_editor_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + G_TYPE_OBJECT, "EABEditor", &type_info, + G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +EShell * +eab_editor_get_shell (EABEditor *editor) +{ + g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL); + + return E_SHELL (editor->priv->shell); } - +GSList * +eab_editor_get_all_editors (void) +{ + return all_editors; +} void eab_editor_show (EABEditor *editor) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->show) - EAB_EDITOR_GET_CLASS(editor)->show (editor); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->show != NULL); + + class->show (editor); } void eab_editor_close (EABEditor *editor) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->close) - EAB_EDITOR_GET_CLASS(editor)->close (editor); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->close != NULL); + + class->close (editor); } void eab_editor_raise (EABEditor *editor) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->raise) - EAB_EDITOR_GET_CLASS(editor)->raise (editor); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->raise != NULL); + + class->raise (editor); } void eab_editor_save_contact (EABEditor *editor, gboolean should_close) { + EABEditorClass *class; + g_return_if_fail (EAB_IS_EDITOR (editor)); - if (EAB_EDITOR_GET_CLASS(editor)->save_contact) - EAB_EDITOR_GET_CLASS(editor)->save_contact (editor, should_close); + class = EAB_EDITOR_GET_CLASS (editor); + g_return_if_fail (class->save_contact != NULL); + + class->save_contact (editor, should_close); } gboolean eab_editor_is_changed (EABEditor *editor) { + EABEditorClass *class; + g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE); - if (EAB_EDITOR_GET_CLASS(editor)->is_changed) - return EAB_EDITOR_GET_CLASS(editor)->is_changed (editor); - else - return FALSE; + class = EAB_EDITOR_GET_CLASS (editor); + g_return_val_if_fail (class->is_changed != NULL, FALSE); + + return class->is_changed (editor); } gboolean eab_editor_is_valid (EABEditor *editor) { + EABEditorClass *class; + g_return_val_if_fail (EAB_IS_EDITOR (editor), FALSE); - if (EAB_EDITOR_GET_CLASS(editor)->is_valid) - return EAB_EDITOR_GET_CLASS(editor)->is_valid (editor); - else - return FALSE; + class = EAB_EDITOR_GET_CLASS (editor); + g_return_val_if_fail (class->is_valid != NULL, FALSE); + + return class->is_valid (editor); } GtkWindow* eab_editor_get_window (EABEditor *editor) { + EABEditorClass *class; + g_return_val_if_fail (EAB_IS_EDITOR (editor), NULL); - if (EAB_EDITOR_GET_CLASS(editor)->get_window) - return EAB_EDITOR_GET_CLASS(editor)->get_window (editor); - else - return NULL; + class = EAB_EDITOR_GET_CLASS (editor); + g_return_val_if_fail (class->get_window != NULL, NULL); + + return class->get_window (editor); } + /* This function prompts for saving if editor conents are in changed state and save or discards or cancels(just returns with out doing anything) according to user input. Editor gets destoryed in case of save and discard case. @@ -280,64 +379,37 @@ eab_editor_prompt_to_save_changes (EABEditor *editor, GtkWindow *window) } } -gboolean -eab_editor_request_close_all (void) -{ - GSList *p; - GSList *pnext; - gboolean retval; - - retval = TRUE; - for (p = all_editors; p != NULL; p = pnext) { - EABEditor *editor = EAB_EDITOR (p->data); - GtkWindow *window = eab_editor_get_window (editor); - - pnext = p->next; - - eab_editor_raise (editor); - if (! eab_editor_prompt_to_save_changes (editor, window)) { - retval = FALSE; - break; - } - } - - return retval; -} - -const GSList* -eab_editor_get_all_editors (void) -{ - return all_editors; -} - void -eab_editor_contact_added (EABEditor *editor, EBookStatus status, EContact *contact) +eab_editor_contact_added (EABEditor *editor, + EBookStatus status, + EContact *contact) { g_return_if_fail (EAB_IS_EDITOR (editor)); g_return_if_fail (E_IS_CONTACT (contact)); - g_signal_emit (editor, editor_signals[CONTACT_ADDED], 0, - status, contact); + g_signal_emit (editor, signals[CONTACT_ADDED], 0, status, contact); } void -eab_editor_contact_modified (EABEditor *editor, EBookStatus status, EContact *contact) +eab_editor_contact_modified (EABEditor *editor, + EBookStatus status, + EContact *contact) { g_return_if_fail (EAB_IS_EDITOR (editor)); g_return_if_fail (E_IS_CONTACT (contact)); - g_signal_emit (editor, editor_signals[CONTACT_MODIFIED], 0, - status, contact); + g_signal_emit (editor, signals[CONTACT_MODIFIED], 0, status, contact); } void -eab_editor_contact_deleted (EABEditor *editor, EBookStatus status, EContact *contact) +eab_editor_contact_deleted (EABEditor *editor, + EBookStatus status, + EContact *contact) { g_return_if_fail (EAB_IS_EDITOR (editor)); g_return_if_fail (E_IS_CONTACT (contact)); - g_signal_emit (editor, editor_signals[CONTACT_DELETED], 0, - status, contact); + g_signal_emit (editor, signals[CONTACT_DELETED], 0, status, contact); } void @@ -345,21 +417,5 @@ eab_editor_closed (EABEditor *editor) { g_return_if_fail (EAB_IS_EDITOR (editor)); - g_signal_emit (editor, editor_signals[EDITOR_CLOSED], 0); -} - -void -eab_editor_add (EABEditor *editor) -{ - g_return_if_fail (EAB_IS_EDITOR (editor)); - - all_editors = g_slist_prepend (all_editors, editor); -} - -void -eab_editor_remove (EABEditor *editor) -{ - g_return_if_fail (EAB_IS_EDITOR (editor)); - - all_editors = g_slist_remove (all_editors, editor); + g_signal_emit (editor, signals[EDITOR_CLOSED], 0); } -- cgit v1.2.3