GSettingsBackend: move 'has-unapplied' logic here

Add GSettingsBackend API to allow any backend to have a 'has-unapplied'
property.  Remove the 'owner' hackery that was used for notifying of
changes to 'has-unapplied' and just use normal GObject notify (and wire
into that from the frontend).
This commit is contained in:
Ryan Lortie 2011-12-29 04:58:20 -05:00
parent 05479beac9
commit ddc12323d1
7 changed files with 80 additions and 97 deletions

View File

@ -32,48 +32,12 @@ struct _GDelayedSettingsBackendPrivate
GSettingsBackend *backend; GSettingsBackend *backend;
GMutex lock; GMutex lock;
GTree *delayed; GTree *delayed;
GMainContext *owner_context;
gpointer owner;
}; };
G_DEFINE_TYPE (GDelayedSettingsBackend, G_DEFINE_TYPE (GDelayedSettingsBackend,
g_delayed_settings_backend, g_delayed_settings_backend,
G_TYPE_SETTINGS_BACKEND) G_TYPE_SETTINGS_BACKEND)
static gboolean
invoke_notify_unapplied (gpointer data)
{
g_object_notify (data, "has-unapplied");
g_object_unref (data);
return FALSE;
}
static void
g_delayed_settings_backend_notify_unapplied (GDelayedSettingsBackend *delayed)
{
GMainContext *target_context;
GObject *target;
g_mutex_lock (&delayed->priv->lock);
if (delayed->priv->owner)
{
target_context = delayed->priv->owner_context;
target = g_object_ref (delayed->priv->owner);
}
else
{
target_context = NULL;
target = NULL;
}
g_mutex_unlock (&delayed->priv->lock);
if (target != NULL)
g_main_context_invoke (target_context, invoke_notify_unapplied, target);
}
static GVariant * static GVariant *
g_delayed_settings_backend_read (GSettingsBackend *backend, g_delayed_settings_backend_read (GSettingsBackend *backend,
const gchar *key, const gchar *key,
@ -111,18 +75,13 @@ g_delayed_settings_backend_write (GSettingsBackend *backend,
gpointer origin_tag) gpointer origin_tag)
{ {
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend); GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
gboolean was_empty;
g_mutex_lock (&delayed->priv->lock); g_mutex_lock (&delayed->priv->lock);
was_empty = g_tree_nnodes (delayed->priv->delayed) == 0; g_tree_insert (delayed->priv->delayed, g_strdup (key), g_variant_ref_sink (value));
g_tree_insert (delayed->priv->delayed, g_strdup (key),
g_variant_ref_sink (value));
g_mutex_unlock (&delayed->priv->lock); g_mutex_unlock (&delayed->priv->lock);
g_settings_backend_changed (backend, key, origin_tag); g_settings_backend_changed (backend, key, origin_tag);
g_settings_backend_set_has_unapplied (backend, TRUE);
if (was_empty)
g_delayed_settings_backend_notify_unapplied (delayed);
return TRUE; return TRUE;
} }
@ -142,18 +101,13 @@ g_delayed_settings_backend_write_tree (GSettingsBackend *backend,
gpointer origin_tag) gpointer origin_tag)
{ {
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend); GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
gboolean was_empty;
g_mutex_lock (&delayed->priv->lock); g_mutex_lock (&delayed->priv->lock);
was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
g_tree_foreach (tree, add_to_tree, delayed->priv->delayed); g_tree_foreach (tree, add_to_tree, delayed->priv->delayed);
g_mutex_unlock (&delayed->priv->lock); g_mutex_unlock (&delayed->priv->lock);
g_settings_backend_changed_tree (backend, tree, origin_tag); g_settings_backend_changed_tree (backend, tree, origin_tag);
g_settings_backend_set_has_unapplied (backend, TRUE);
if (was_empty)
g_delayed_settings_backend_notify_unapplied (delayed);
return TRUE; return TRUE;
} }
@ -173,15 +127,13 @@ g_delayed_settings_backend_reset (GSettingsBackend *backend,
gpointer origin_tag) gpointer origin_tag)
{ {
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend); GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (backend);
gboolean was_empty;
g_mutex_lock (&delayed->priv->lock); g_mutex_lock (&delayed->priv->lock);
was_empty = g_tree_nnodes (delayed->priv->delayed) == 0;
g_tree_insert (delayed->priv->delayed, g_strdup (key), NULL); g_tree_insert (delayed->priv->delayed, g_strdup (key), NULL);
g_mutex_unlock (&delayed->priv->lock); g_mutex_unlock (&delayed->priv->lock);
if (was_empty) g_settings_backend_changed (backend, key, origin_tag);
g_delayed_settings_backend_notify_unapplied (delayed); g_settings_backend_set_has_unapplied (backend, TRUE);
} }
static void static void
@ -213,14 +165,6 @@ g_delayed_settings_backend_get_permission (GSettingsBackend *backend,
/* method calls */ /* method calls */
gboolean
g_delayed_settings_backend_get_has_unapplied (GDelayedSettingsBackend *delayed)
{
/* we don't need to lock for this... */
return g_tree_nnodes (delayed->priv->delayed) > 0;
}
void void
g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed) g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed)
{ {
@ -242,7 +186,7 @@ g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed)
g_tree_unref (tmp); g_tree_unref (tmp);
g_delayed_settings_backend_notify_unapplied (delayed); g_settings_backend_set_has_unapplied (G_SETTINGS_BACKEND (delayed), FALSE);
} }
} }
@ -260,7 +204,7 @@ g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed)
g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed), tmp, NULL); g_settings_backend_changed_tree (G_SETTINGS_BACKEND (delayed), tmp, NULL);
g_tree_unref (tmp); g_tree_unref (tmp);
g_delayed_settings_backend_notify_unapplied (delayed); g_settings_backend_set_has_unapplied (G_SETTINGS_BACKEND (delayed), FALSE);
} }
} }
@ -283,9 +227,6 @@ g_delayed_settings_backend_finalize (GObject *object)
g_object_unref (delayed->priv->backend); g_object_unref (delayed->priv->backend);
g_tree_unref (delayed->priv->delayed); g_tree_unref (delayed->priv->delayed);
/* if our owner is still alive, why are we finalizing? */
g_assert (delayed->priv->owner == NULL);
G_OBJECT_CLASS (g_delayed_settings_backend_parent_class) G_OBJECT_CLASS (g_delayed_settings_backend_parent_class)
->finalize (object); ->finalize (object);
} }
@ -321,31 +262,13 @@ g_delayed_settings_backend_init (GDelayedSettingsBackend *delayed)
g_mutex_init (&delayed->priv->lock); g_mutex_init (&delayed->priv->lock);
} }
static void
g_delayed_settings_backend_disown (gpointer data,
GObject *where_the_object_was)
{
GDelayedSettingsBackend *delayed = data;
g_mutex_lock (&delayed->priv->lock);
delayed->priv->owner_context = NULL;
delayed->priv->owner = NULL;
g_mutex_unlock (&delayed->priv->lock);
}
GDelayedSettingsBackend * GDelayedSettingsBackend *
g_delayed_settings_backend_new (GSettingsBackend *backend, g_delayed_settings_backend_new (GSettingsBackend *backend)
gpointer owner,
GMainContext *owner_context)
{ {
GDelayedSettingsBackend *delayed; GDelayedSettingsBackend *delayed;
delayed = g_object_new (G_TYPE_DELAYED_SETTINGS_BACKEND, NULL); delayed = g_object_new (G_TYPE_DELAYED_SETTINGS_BACKEND, NULL);
delayed->priv->backend = g_object_ref (backend); delayed->priv->backend = g_object_ref (backend);
delayed->priv->owner_context = owner_context;
delayed->priv->owner = owner;
g_object_weak_ref (owner, g_delayed_settings_backend_disown, delayed);
g_settings_backend_watch (delayed->priv->backend, g_delayed_settings_got_event, G_OBJECT (delayed)); g_settings_backend_watch (delayed->priv->backend, g_delayed_settings_got_event, G_OBJECT (delayed));

View File

@ -59,14 +59,10 @@ struct _GDelayedSettingsBackend
G_GNUC_INTERNAL G_GNUC_INTERNAL
GType g_delayed_settings_backend_get_type (void); GType g_delayed_settings_backend_get_type (void);
G_GNUC_INTERNAL G_GNUC_INTERNAL
GDelayedSettingsBackend * g_delayed_settings_backend_new (GSettingsBackend *backend, GDelayedSettingsBackend * g_delayed_settings_backend_new (GSettingsBackend *backend);
gpointer owner,
GMainContext *owner_context);
G_GNUC_INTERNAL G_GNUC_INTERNAL
void g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed); void g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed);
G_GNUC_INTERNAL G_GNUC_INTERNAL
void g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed); void g_delayed_settings_backend_apply (GDelayedSettingsBackend *delayed);
G_GNUC_INTERNAL
gboolean g_delayed_settings_backend_get_has_unapplied (GDelayedSettingsBackend *delayed);
#endif /* __G_DELAYED_SETTINGS_BACKEND_H__ */ #endif /* __G_DELAYED_SETTINGS_BACKEND_H__ */

View File

@ -1133,6 +1133,7 @@ g_file_descriptor_based_get_fd
#endif #endif
g_settings_backend_get_type g_settings_backend_get_type
g_settings_backend_report_event g_settings_backend_report_event
g_settings_backend_set_has_unapplied
g_settings_backend_changed g_settings_backend_changed
g_settings_backend_flatten_tree g_settings_backend_flatten_tree
g_settings_backend_keys_changed g_settings_backend_keys_changed

View File

@ -514,6 +514,25 @@ g_settings_got_event (GObject *target,
} }
} }
static gboolean
g_settings_emit_has_unapplied_notify (gpointer data)
{
g_object_notify (data, "has-unapplied");
g_object_unref (data);
return G_SOURCE_REMOVE;
}
static void
g_settings_got_has_unapplied_notify (GSettingsBackend *backend,
GParamSpec *pspec,
gpointer user_data)
{
GSettings *settings = G_SETTINGS (user_data);
g_main_context_invoke (settings->priv->main_context, g_settings_emit_has_unapplied_notify, g_object_ref (settings));
}
/* Properties, Construction, Destruction {{{1 */ /* Properties, Construction, Destruction {{{1 */
static void static void
g_settings_set_property (GObject *object, g_settings_set_property (GObject *object,
@ -658,6 +677,7 @@ g_settings_finalize (GObject *object)
{ {
GSettings *settings = G_SETTINGS (object); GSettings *settings = G_SETTINGS (object);
g_signal_handlers_disconnect_by_func (settings->priv->backend, g_settings_got_has_unapplied_notify, settings);
g_settings_backend_unsubscribe (settings->priv->backend, g_settings_backend_unsubscribe (settings->priv->backend,
settings->priv->path); settings->priv->path);
g_main_context_unref (settings->priv->main_context); g_main_context_unref (settings->priv->main_context);
@ -1966,16 +1986,15 @@ g_settings_delay (GSettings *settings)
if (settings->priv->delayed) if (settings->priv->delayed)
return; return;
settings->priv->delayed = settings->priv->delayed = g_delayed_settings_backend_new (settings->priv->backend);
g_delayed_settings_backend_new (settings->priv->backend,
settings,
settings->priv->main_context);
g_settings_backend_unwatch (settings->priv->backend, G_OBJECT (settings)); g_settings_backend_unwatch (settings->priv->backend, G_OBJECT (settings));
g_object_unref (settings->priv->backend); g_object_unref (settings->priv->backend);
settings->priv->backend = G_SETTINGS_BACKEND (settings->priv->delayed); settings->priv->backend = G_SETTINGS_BACKEND (settings->priv->delayed);
g_settings_backend_watch (settings->priv->backend, g_settings_got_event, G_OBJECT (settings)); g_settings_backend_watch (settings->priv->backend, g_settings_got_event, G_OBJECT (settings));
g_signal_connect (settings->priv->delayed, "notify::has-unapplied",
G_CALLBACK (g_settings_got_has_unapplied_notify), settings);
g_object_notify (G_OBJECT (settings), "delay-apply"); g_object_notify (G_OBJECT (settings), "delay-apply");
} }
@ -2039,9 +2058,7 @@ g_settings_get_has_unapplied (GSettings *settings)
{ {
g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE); g_return_val_if_fail (G_IS_SETTINGS (settings), FALSE);
return settings->priv->delayed && return g_settings_backend_get_has_unapplied (settings->priv->backend);
g_delayed_settings_backend_get_has_unapplied (
G_DELAYED_SETTINGS_BACKEND (settings->priv->backend));
} }
/* Extra API (reset, sync, get_child, is_writable, list_*, ranges) {{{1 */ /* Extra API (reset, sync, get_child, is_writable, list_*, ranges) {{{1 */

View File

@ -40,9 +40,19 @@ typedef struct _GSettingsBackendWatch GSettingsBackendWatch;
struct _GSettingsBackendPrivate struct _GSettingsBackendPrivate
{ {
GSettingsBackendWatch *watches; GSettingsBackendWatch *watches;
gboolean has_unapplied;
GMutex lock; GMutex lock;
}; };
enum
{
PROP_0,
PROP_HAS_UNAPPLIED,
N_PROPS
};
static GParamSpec *g_settings_backend_pspecs[N_PROPS];
/* For g_settings_backend_sync_default(), we only want to actually do /* For g_settings_backend_sync_default(), we only want to actually do
* the sync if the backend already exists. This avoids us creating an * the sync if the backend already exists. This avoids us creating an
* entire GSettingsBackend in order to call a do-nothing sync() * entire GSettingsBackend in order to call a do-nothing sync()
@ -807,6 +817,14 @@ g_settings_backend_subscribe (GSettingsBackend *backend,
->subscribe (backend, name); ->subscribe (backend, name);
} }
static void
g_settings_backend_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
g_assert (prop_id == PROP_HAS_UNAPPLIED);
g_value_set_boolean (value, g_settings_backend_get_has_unapplied (G_SETTINGS_BACKEND (object)));
}
static void static void
g_settings_backend_finalize (GObject *object) g_settings_backend_finalize (GObject *object)
{ {
@ -841,8 +859,14 @@ g_settings_backend_class_init (GSettingsBackendClass *class)
class->subscribe = ignore_subscription; class->subscribe = ignore_subscription;
class->unsubscribe = ignore_subscription; class->unsubscribe = ignore_subscription;
gobject_class->get_property = g_settings_backend_get_property;
gobject_class->finalize = g_settings_backend_finalize; gobject_class->finalize = g_settings_backend_finalize;
g_settings_backend_pspecs[PROP_HAS_UNAPPLIED] =
g_param_spec_boolean ("has-unapplied", "has unapplied", "TRUE if apply() is meaningful",
FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, g_settings_backend_pspecs);
g_type_class_add_private (class, sizeof (GSettingsBackendPrivate)); g_type_class_add_private (class, sizeof (GSettingsBackendPrivate));
} }
@ -954,3 +978,21 @@ g_settings_backend_sync_default (void)
class->sync (backend); class->sync (backend);
} }
} }
gboolean
g_settings_backend_get_has_unapplied (GSettingsBackend *backend)
{
return backend->priv->has_unapplied;
}
void
g_settings_backend_set_has_unapplied (GSettingsBackend *backend,
gboolean has_unapplied)
{
if (has_unapplied != backend->priv->has_unapplied)
{
backend->priv->has_unapplied = has_unapplied;
g_object_notify_by_pspec (G_OBJECT (backend), g_settings_backend_pspecs[PROP_HAS_UNAPPLIED]);
}
}

View File

@ -122,6 +122,8 @@ GType g_settings_backend_get_type (void);
void g_settings_backend_report_event (GSettingsBackend *backend, void g_settings_backend_report_event (GSettingsBackend *backend,
const GSettingsEvent *event); const GSettingsEvent *event);
void g_settings_backend_set_has_unapplied (GSettingsBackend *backend,
gboolean has_unapplied);
void g_settings_backend_changed (GSettingsBackend *backend, void g_settings_backend_changed (GSettingsBackend *backend,
const gchar *key, const gchar *key,
gpointer origin_tag); gpointer origin_tag);

View File

@ -71,6 +71,8 @@ G_GNUC_INTERNAL
GPermission * g_settings_backend_get_permission (GSettingsBackend *backend, GPermission * g_settings_backend_get_permission (GSettingsBackend *backend,
const gchar *path); const gchar *path);
G_GNUC_INTERNAL G_GNUC_INTERNAL
gboolean g_settings_backend_get_has_unapplied (GSettingsBackend *backend);
G_GNUC_INTERNAL
void g_settings_backend_sync_default (void); void g_settings_backend_sync_default (void);
G_GNUC_INTERNAL G_GNUC_INTERNAL