[glib] gapplication: add bind_busy_property()
- From: Lars Uebernickel <larsu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gapplication: add bind_busy_property()
- Date: Mon, 16 Feb 2015 06:39:05 +0000 (UTC)
commit 0f2b54142a455dd7f31aa9f3795b9173edd8fb1d
Author: Lars Uebernickel <lars uebernickel canonical com>
Date: Sun Feb 15 18:54:13 2015 +0100
gapplication: add bind_busy_property()
Balancing g_application_{un,}mark_busy() is non-trivial in some cases.
Make it a bit more convenient by allowing to bind multiple boolean
properties (from different objects) to the busy state. As long as these
properties are true, the application is marked as busy.
https://bugzilla.gnome.org/show_bug.cgi?id=744565
docs/reference/gio/gio-sections.txt | 1 +
gio/gapplication.c | 104 +++++++++++++++++++++++++++++++++++
gio/gapplication.h | 5 ++
3 files changed, 110 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 4e5e907..5c186c0 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -3136,6 +3136,7 @@ g_application_get_default
<SUBSECTION>
g_application_mark_busy
g_application_unmark_busy
+g_application_bind_busy_property
<SUBSECTION Standard>
G_TYPE_APPLICATION
G_APPLICATION
diff --git a/gio/gapplication.c b/gio/gapplication.c
index d09cdb0..7533ae2 100644
--- a/gio/gapplication.c
+++ b/gio/gapplication.c
@@ -2679,5 +2679,109 @@ g_application_withdraw_notification (GApplication *application,
g_notification_backend_withdraw_notification (application->priv->notifications, id);
}
+/* Busy binding {{{1 */
+
+typedef struct
+{
+ GApplication *app;
+ gboolean is_busy;
+} GApplicationBusyBinding;
+
+static void
+g_application_busy_binding_destroy (gpointer data,
+ GClosure *closure)
+{
+ GApplicationBusyBinding *binding = data;
+
+ if (binding->is_busy)
+ g_application_unmark_busy (binding->app);
+
+ g_object_unref (binding->app);
+ g_slice_free (GApplicationBusyBinding, binding);
+}
+
+static void
+g_application_notify_busy_binding (GObject *object,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GApplicationBusyBinding *binding = user_data;
+ gboolean is_busy;
+
+ g_object_get (object, pspec->name, &is_busy, NULL);
+
+ if (is_busy && !binding->is_busy)
+ g_application_mark_busy (binding->app);
+ else if (!is_busy && binding->is_busy)
+ g_application_unmark_busy (binding->app);
+
+ binding->is_busy = is_busy;
+}
+
+/**
+ * g_application_bind_busy_property:
+ * @application: a #GApplication
+ * @object: a #GObject
+ * @property: (allow-none): the name of a boolean property of @object
+ *
+ * Marks @application as busy (see g_application_mark_busy()) while
+ * @property on @object is %TRUE.
+ *
+ * Multiple such bindings can exist, but only one property can be bound
+ * per object. Calling this function again for the same object replaces
+ * a previous binding. If @property is %NULL, the binding is destroyed.
+ *
+ * The binding holds a reference to @application while it is active, but
+ * not to @object. Instead, the binding is destroyed when @object is
+ * finalized.
+ *
+ * Since: 2.44
+ */
+void
+g_application_bind_busy_property (GApplication *application,
+ gpointer object,
+ const gchar *property)
+{
+ GClosure *closure = NULL;
+ guint notify_id;
+ gulong handler_id;
+
+ g_return_if_fail (G_IS_APPLICATION (application));
+ g_return_if_fail (G_IS_OBJECT (object));
+
+ notify_id = g_signal_lookup ("notify", G_TYPE_OBJECT);
+
+ if (property != NULL)
+ {
+ GParamSpec *pspec;
+ GApplicationBusyBinding *binding;
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property);
+ g_return_if_fail (pspec != NULL && pspec->value_type == G_TYPE_BOOLEAN);
+
+ binding = g_slice_new (GApplicationBusyBinding);
+ binding->app = g_object_ref (application);
+ binding->is_busy = FALSE;
+
+ /* fetch the initial value */
+ g_application_notify_busy_binding (object, pspec, binding);
+
+ closure = g_cclosure_new (G_CALLBACK (g_application_notify_busy_binding), binding,
+ g_application_busy_binding_destroy);
+ }
+
+ /* unset a previous binding after fetching the new initial value, so
+ * that we don't switch to FALSE for a brief moment when both the
+ * old and the new property are set to TRUE
+ */
+ handler_id = g_signal_handler_find (object, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, notify_id,
+ 0, NULL, g_application_notify_busy_binding, NULL);
+ if (handler_id > 0)
+ g_signal_handler_disconnect (object, handler_id);
+
+ if (closure)
+ g_signal_connect_closure_by_id (object, notify_id, g_quark_from_string (property), closure, FALSE);
+}
+
/* Epilogue {{{1 */
/* vim:set foldmethod=marker: */
diff --git a/gio/gapplication.h b/gio/gapplication.h
index 658c633..a5e9712 100644
--- a/gio/gapplication.h
+++ b/gio/gapplication.h
@@ -226,6 +226,11 @@ GLIB_AVAILABLE_IN_2_40
void g_application_withdraw_notification (GApplication
*application,
const gchar *id);
+GLIB_AVAILABLE_IN_2_44
+void g_application_bind_busy_property (GApplication
*application,
+ gpointer object,
+ const gchar *property);
+
G_END_DECLS
#endif /* __G_APPLICATION_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]