[gnome-initial-setup] assistant: Add async mechanism for applying page changes
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-initial-setup] assistant: Add async mechanism for applying page changes
- Date: Mon, 27 May 2013 16:29:33 +0000 (UTC)
commit f5decfa6c1030336508e81aa545c3f08ef55e1ef
Author: Stef Walter <stefw redhat com>
Date: Sun May 26 13:33:44 2013 +0200
assistant: Add async mechanism for applying page changes
This kicks in when 'Next' is pressed. If applying fails, then stays on
the same page. Cancellation of apply will be further expanded in later
commits.
https://bugzilla.gnome.org/show_bug.cgi?id=701039
gnome-initial-setup/gis-assistant.c | 20 ++++-
gnome-initial-setup/gis-page.c | 92 ++++++++++++++++++++
gnome-initial-setup/gis-page.h | 10 ++
.../pages/account/gis-account-page.c | 21 +++--
4 files changed, 134 insertions(+), 9 deletions(-)
---
diff --git a/gnome-initial-setup/gis-assistant.c b/gnome-initial-setup/gis-assistant.c
index ecf2932..b3e8345 100644
--- a/gnome-initial-setup/gis-assistant.c
+++ b/gnome-initial-setup/gis-assistant.c
@@ -94,12 +94,28 @@ gis_assistant_switch_to (GisAssistant *assistant,
GIS_ASSISTANT_GET_CLASS (assistant)->switch_to (assistant, direction, page);
}
+static void
+on_apply_done (GisPage *page,
+ gboolean valid,
+ gpointer user_data)
+{
+ GisAssistant *assistant = GIS_ASSISTANT (user_data);
+ if (valid)
+ g_signal_emit (assistant, signals[NEXT_PAGE], 0,
+ assistant->priv->current_page);
+ g_object_unref (assistant);
+}
+
void
gis_assistant_next_page (GisAssistant *assistant)
{
GisAssistantPrivate *priv = assistant->priv;
- g_signal_emit (assistant, signals[NEXT_PAGE], 0,
- priv->current_page);
+ if (priv->current_page)
+ gis_page_apply_begin (priv->current_page, on_apply_done,
+ g_object_ref (assistant));
+ else
+ g_signal_emit (assistant, signals[NEXT_PAGE], 0,
+ priv->current_page);
}
static inline gboolean
diff --git a/gnome-initial-setup/gis-page.c b/gnome-initial-setup/gis-page.c
index fc05d08..d222d59 100644
--- a/gnome-initial-setup/gis-page.c
+++ b/gnome-initial-setup/gis-page.c
@@ -35,6 +35,11 @@ struct _GisPagePrivate
{
char *title;
+ gboolean applying;
+ GCancellable *apply_cancel;
+ GisPageApplyCallback apply_cb;
+ gpointer apply_data;
+
guint complete : 1;
guint padding : 6;
};
@@ -45,6 +50,7 @@ enum
PROP_DRIVER,
PROP_TITLE,
PROP_COMPLETE,
+ PROP_APPLYING,
PROP_LAST,
};
@@ -68,6 +74,9 @@ gis_page_get_property (GObject *object,
case PROP_COMPLETE:
g_value_set_boolean (value, page->priv->complete);
break;
+ case PROP_APPLYING:
+ g_value_set_boolean (value, gis_page_get_applying (page));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -104,6 +113,9 @@ gis_page_finalize (GObject *object)
GisPage *page = GIS_PAGE (object);
g_free (page->priv->title);
+ g_assert (!page->priv->applying);
+ g_assert (page->priv->apply_cb == NULL);
+ g_assert (page->priv->apply_cancel == NULL);
G_OBJECT_CLASS (gis_page_parent_class)->finalize (object);
}
@@ -113,6 +125,9 @@ gis_page_dispose (GObject *object)
{
GisPage *page = GIS_PAGE (object);
+ if (page->priv->apply_cancel)
+ g_cancellable_cancel (page->priv->apply_cancel);
+
g_clear_object (&page->driver);
g_clear_object (&page->builder);
@@ -187,6 +202,9 @@ gis_page_class_init (GisPageClass *klass)
obj_props[PROP_COMPLETE] =
g_param_spec_boolean ("complete", "", "", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+ obj_props[PROP_APPLYING] =
+ g_param_spec_boolean ("applying", "", "", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
@@ -243,3 +261,77 @@ gis_page_locale_changed (GisPage *page)
if (GIS_PAGE_GET_CLASS (page)->locale_changed)
return GIS_PAGE_GET_CLASS (page)->locale_changed (page);
}
+
+void
+gis_page_apply_begin (GisPage *page,
+ GisPageApplyCallback callback,
+ gpointer user_data)
+{
+ GisPageClass *klass;
+
+ g_return_if_fail (GIS_IS_PAGE (page));
+ g_return_if_fail (page->priv->applying == FALSE);
+
+ klass = GIS_PAGE_GET_CLASS (page);
+
+ /* Shortcut case where no apply vfunc, to avoid flicker */
+ if (!klass->apply) {
+ if (callback)
+ (callback) (page, TRUE, user_data);
+ return;
+ }
+
+ /* Unrefs in gis_page_apply_complete() */
+ g_object_ref (page);
+
+ page->priv->apply_cb = callback;
+ page->priv->apply_data = user_data;
+ page->priv->apply_cancel = g_cancellable_new ();
+ page->priv->applying = TRUE;
+ g_object_notify (G_OBJECT (page), "applying");
+
+ (klass->apply) (page, page->priv->apply_cancel);
+}
+
+void
+gis_page_apply_complete (GisPage *page,
+ gboolean valid)
+{
+ GisPageApplyCallback callback;
+ gpointer user_data;
+
+ g_return_if_fail (GIS_IS_PAGE (page));
+ g_return_if_fail (page->priv->applying == TRUE);
+
+ callback = page->priv->apply_cb;
+ page->priv->apply_cb = NULL;
+ user_data = page->priv->apply_data;
+ page->priv->apply_data = NULL;
+
+ g_clear_object (&page->priv->apply_cancel);
+ page->priv->applying = FALSE;
+ g_object_notify (G_OBJECT (page), "applying");
+
+ if (callback)
+ (callback) (page, valid, user_data);
+
+ /* Matches ref in gis_page_apply_begin() */
+ g_object_unref (page);
+}
+
+gboolean
+gis_page_get_applying (GisPage *page)
+{
+ g_return_val_if_fail (GIS_IS_PAGE (page), FALSE);
+
+ return page->priv->applying;
+}
+
+void
+gis_page_apply_cancel (GisPage *page)
+{
+ g_return_if_fail (GIS_IS_PAGE (page));
+ g_return_if_fail (page->priv->applying == TRUE);
+
+ g_cancellable_cancel (page->priv->apply_cancel);
+}
diff --git a/gnome-initial-setup/gis-page.h b/gnome-initial-setup/gis-page.h
index 2b28b69..8d287c6 100644
--- a/gnome-initial-setup/gis-page.h
+++ b/gnome-initial-setup/gis-page.h
@@ -40,6 +40,10 @@ typedef struct _GisPageClass GisPageClass;
typedef struct _GisPagePrivate GisPagePrivate;
typedef struct _GisAssistantPagePrivate GisAssistantPagePrivate;
+typedef void (* GisPageApplyCallback) (GisPage *page,
+ gboolean valid,
+ gpointer user_data);
+
struct _GisPage
{
GtkBin parent;
@@ -59,6 +63,8 @@ struct _GisPageClass
GtkBuilder * (*get_builder) (GisPage *page);
GtkWidget * (*get_action_widget) (GisPage *page);
void (*locale_changed) (GisPage *page);
+ void (*apply) (GisPage *page,
+ GCancellable *cancellable);
};
GType gis_page_get_type (void);
@@ -69,6 +75,10 @@ gboolean gis_page_get_complete (GisPage *page);
void gis_page_set_complete (GisPage *page, gboolean complete);
GtkWidget * gis_page_get_action_widget (GisPage *page);
void gis_page_locale_changed (GisPage *page);
+void gis_page_apply_begin (GisPage *page, GisPageApplyCallback callback, gpointer user_data);
+void gis_page_apply_cancel (GisPage *page);
+void gis_page_apply_complete (GisPage *page, gboolean valid);
+gboolean gis_page_get_applying (GisPage *page);
G_END_DECLS
diff --git a/gnome-initial-setup/pages/account/gis-account-page.c
b/gnome-initial-setup/pages/account/gis-account-page.c
index a60803a..74c0fc6 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.c
+++ b/gnome-initial-setup/pages/account/gis-account-page.c
@@ -556,12 +556,14 @@ on_permit_user_login (GObject *source,
g_debug ("Caching remote user: %s", login);
priv->act_user = act_user_manager_cache_user (priv->act_client, login, NULL);
+ gis_page_apply_complete (GIS_PAGE (page), TRUE);
g_free (login);
} else {
show_error_dialog (page, _("Failed to register account"), error);
g_message ("Couldn't permit logins on account: %s", error->message);
g_error_free (error);
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
}
}
@@ -619,11 +621,13 @@ on_realm_joined (GObject *source,
/* XXX */
/* join_show_prompt (self, error); */
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
/* Other failure */
} else {
show_error_dialog (page, _("Failed to join domain"), error);
g_message ("Failed to join the domain: %s", error->message);
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
}
g_clear_error (&error);
@@ -671,6 +675,7 @@ on_realm_login (GObject *source,
/* XXX: creds */
/* join_show_prompt (self, NULL); */
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
}
g_bytes_unref (creds);
@@ -680,16 +685,19 @@ on_realm_login (GObject *source,
g_debug ("Problem with the user's login: %s", error->message);
set_entry_validation_error (OBJ (GtkEntry *, "enterprise-login"), error->message);
gtk_widget_grab_focus (WID ("enterprise-login"));
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
} else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
g_debug ("Problem with the user's password: %s", error->message);
set_entry_validation_error (OBJ (GtkEntry *, "enterprise-password"), error->message);
gtk_widget_grab_focus (WID ("enterprise-password"));
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
/* Other login failure */
} else {
show_error_dialog (page, _("Failed to log into domain"), error);
g_message ("Couldn't log in as user: %s", error->message);
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
}
g_clear_error (&error);
@@ -735,6 +743,7 @@ on_realm_discover_input (GObject *source,
g_message ("Couldn't discover domain: %s", error->message);
gtk_widget_grab_focus (WID ("enterprise-domain-entry"));
set_entry_validation_error (OBJ (GtkEntry*, "enterprise-domain-entry"), error->message);
+ gis_page_apply_complete (GIS_PAGE (page), FALSE);
g_error_free (error);
}
}
@@ -770,6 +779,7 @@ save_account_data (GisAccountPage *page)
switch (priv->mode) {
case UM_LOCAL:
local_create_user (page);
+ gis_page_apply_complete (GIS_PAGE (page), TRUE);
break;
case UM_ENTERPRISE:
enterprise_add_user (page);
@@ -953,12 +963,10 @@ toggle_mode (GtkToggleButton *button,
}
static void
-next_page_cb (GisAssistant *assistant,
- GisPage *which_page,
- GisPage *this_page)
+gis_account_page_apply (GisPage *page,
+ GCancellable *cancellable)
{
- if (which_page == this_page)
- save_account_data (GIS_ACCOUNT_PAGE (this_page));
+ save_account_data (GIS_ACCOUNT_PAGE (page));
}
static void
@@ -1007,8 +1015,6 @@ gis_account_page_constructed (GObject *object)
priv->act_client = act_user_manager_get_default ();
- g_signal_connect (assistant, "next-page", G_CALLBACK (next_page_cb), page);
-
clear_account_page (page);
update_account_page_status (page);
@@ -1061,6 +1067,7 @@ gis_account_page_class_init (GisAccountPageClass *klass)
page_class->page_id = PAGE_ID;
page_class->locale_changed = gis_account_page_locale_changed;
page_class->get_action_widget = gis_account_page_get_action_widget;
+ page_class->apply = gis_account_page_apply;
object_class->constructed = gis_account_page_constructed;
object_class->dispose = gis_account_page_dispose;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]