[Xfce4-commits] <xfce4-panel:devel> Add custom xfconf property bindings.

Nick Schermer nick at xfce.org
Tue Aug 11 20:34:07 CEST 2009


Updating branch refs/heads/devel
         to 7c4460246cb3676e5df860ba235817bc7a174c2c (commit)
       from ee938abfd54bea1a9da4cb7f45e6ae04618f5e3e (commit)

commit 7c4460246cb3676e5df860ba235817bc7a174c2c
Author: Nick Schermer <nick at xfce.org>
Date:   Sun May 31 16:04:31 2009 +0200

    Add custom xfconf property bindings.
    
    The goals of these bindings is speeding up the panel startup.
    The bindings can optionally take a hash table for searching
    properties, this way the panel only has to call dbus once
    during startup for panel settings.

 common/Makefile.am                                 |    4 +-
 common/panel-xfconf.c                              |  212 ++++++++++++++++++++
 .../panel-xfconf.h                                 |   34 ++--
 3 files changed, 232 insertions(+), 18 deletions(-)

diff --git a/common/Makefile.am b/common/Makefile.am
index 909f29e..be8dd04 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -2,6 +2,8 @@
 
 EXTRA_DIST = \
 	panel-dbus.h \
-	panel-private.h
+	panel-private.h \
+	panel-xfconf.c \
+	panel-xfconf.h
 
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/common/panel-xfconf.c b/common/panel-xfconf.c
new file mode 100644
index 0000000..a5d1ad3
--- /dev/null
+++ b/common/panel-xfconf.c
@@ -0,0 +1,212 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <common/panel-xfconf.h>
+#include <libxfce4panel/libxfce4panel.h>
+
+
+typedef struct
+{
+  XfconfChannel *channel;
+  gchar         *channel_prop;
+
+  GObject       *object;
+  gchar         *object_prop;
+} PropertyBinding;
+
+
+
+static void panel_properties_object_notify     (GObject       *object,
+                                                GParamSpec    *pspec,
+				                gpointer       user_data);
+static void panel_properties_object_destroyed  (gpointer       user_data,
+				                GObject       *where_the_object_was);
+static void panel_properties_channel_notify    (XfconfChannel *channel,
+                                                const gchar   *property,
+                                                const GValue  *value,
+                                                gpointer       user_data);
+static void panel_properties_channel_destroyed (gpointer       user_data,
+				                GObject       *where_the_channel_was);
+
+
+
+static void
+panel_properties_object_notify (GObject    *object,
+                                GParamSpec *pspec,
+				gpointer    user_data)
+{
+  GValue           value = { 0, };
+  PropertyBinding *binding = user_data;
+
+  panel_return_if_fail (G_IS_OBJECT (object));
+  panel_return_if_fail (binding->object == object);
+  panel_return_if_fail (XFCONF_IS_CHANNEL (binding->channel));
+
+  /* get the property from the object */
+  g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+  g_object_get_property (object, g_param_spec_get_name (pspec), &value);
+
+  /* set the xfconf property */
+  xfconf_channel_set_property (binding->channel, binding->channel_prop,
+                               &value);
+
+  /* cleanup */
+  g_value_unset (&value);
+}
+
+
+
+static void
+panel_properties_object_destroyed (gpointer  user_data,
+				   GObject  *where_the_object_was)
+{
+  PropertyBinding *binding = user_data;
+
+  panel_return_if_fail (binding->object == where_the_object_was);
+  panel_return_if_fail (XFCONF_IS_CHANNEL (binding->channel));
+
+  /* disconnect from the object */
+  g_signal_handlers_disconnect_by_func (G_OBJECT (binding->channel),
+      panel_properties_channel_notify, binding);
+  g_object_weak_unref (G_OBJECT (binding->channel),
+      panel_properties_channel_destroyed, binding);
+
+  /* cleanup */
+  g_slice_free (PropertyBinding, binding);
+}
+
+
+
+static void
+panel_properties_channel_notify (XfconfChannel *channel,
+                                 const gchar   *property,
+                                 const GValue  *value,
+                                 gpointer       user_data)
+{
+  PropertyBinding *binding = user_data;
+
+  panel_return_if_fail (XFCONF_IS_CHANNEL (channel));
+  panel_return_if_fail (binding->channel == channel);
+  panel_return_if_fail (G_IS_OBJECT (binding->object));
+
+  /* block property notify */
+  g_signal_handlers_block_by_func (G_OBJECT (binding->object),
+      G_CALLBACK (panel_properties_object_notify), binding);
+
+  /* set the property */
+  g_object_set_property (binding->object, binding->object_prop, value);
+
+  /* unblock property notify */
+  g_signal_handlers_unblock_by_func (G_OBJECT (binding->object),
+      G_CALLBACK (panel_properties_object_notify), binding);
+}
+
+
+
+static void
+panel_properties_channel_destroyed (gpointer  user_data,
+				    GObject  *where_the_channel_was)
+{
+  PropertyBinding *binding = user_data;
+
+  panel_return_if_fail (binding->channel == (XfconfChannel *) where_the_channel_was);
+  panel_return_if_fail (G_IS_OBJECT (binding->object));
+
+  /* disconnect from the object */
+  g_signal_handlers_disconnect_by_func (G_OBJECT (binding->object),
+      panel_properties_object_notify, binding);
+  g_object_weak_unref (G_OBJECT (binding->object),
+      panel_properties_object_destroyed, binding);
+
+  /* cleanup */
+  g_slice_free (PropertyBinding, binding);
+}
+
+
+
+void
+panel_properties_bind (XfconfChannel       *channel,
+                       GObject             *object,
+		       const gchar         *property_base,
+		       const PanelProperty *properties,
+		       GHashTable          *hash_table)
+{
+  const PanelProperty *prop;
+  const GValue        *value;
+  gchar                buf[512];
+  PropertyBinding     *binding;
+
+  panel_return_if_fail (XFCONF_IS_CHANNEL (channel));
+  panel_return_if_fail (G_IS_OBJECT (object));
+  panel_return_if_fail (property_base != NULL && *property_base == '/');
+  panel_return_if_fail (properties != NULL);
+
+  /* get or ref the hash table */
+  if (G_LIKELY (hash_table != NULL))
+    g_hash_table_ref (hash_table);
+  else
+    hash_table = xfconf_channel_get_properties (channel, property_base);
+
+  /* walk the properties array */
+  for (prop = properties; prop->property != NULL; prop++)
+    {
+      /* create a new binding */
+      binding = g_slice_new (PropertyBinding);
+      binding->channel = channel;
+      binding->channel_prop = g_strconcat (property_base, "/", prop->property, NULL);
+      binding->object = object;
+      binding->object_prop = g_strdup (prop->property);
+
+      /* lookup the property value */
+      if (hash_table != NULL)
+        {
+	  value = g_hash_table_lookup (hash_table, binding->channel_prop);
+	  if (value != NULL)
+	    {
+	      if (G_LIKELY (G_VALUE_TYPE (value) == prop->type))
+	        g_object_set_property (object, prop->property, value);
+	      else
+	        g_message ("Value types of property \"%s\" do not "
+		           "match: channel = %s, property = %s", buf,
+			   G_VALUE_TYPE_NAME (value),
+			   g_type_name (prop->type));
+	    }
+	}
+
+      /* monitor object property changes */
+      g_snprintf (buf, sizeof (buf), "notify::%s", prop->property);
+      g_object_weak_ref (G_OBJECT (object), panel_properties_object_destroyed, binding);
+      g_signal_connect (G_OBJECT (object), buf,
+          G_CALLBACK (panel_properties_object_notify), binding);
+
+      /* monitor channel changes */
+      g_snprintf (buf, sizeof (buf), "property-changed::%s", binding->channel_prop);
+      g_object_weak_ref (G_OBJECT (channel), panel_properties_channel_destroyed, binding);
+      g_signal_connect (G_OBJECT (channel), buf,
+          G_CALLBACK (panel_properties_channel_notify), binding);
+    }
+
+  /* cleanup */
+  if (hash_table != NULL)
+    g_hash_table_unref (hash_table);
+}
diff --git a/libxfce4panel/xfce-panel-convenience.h b/common/panel-xfconf.h
similarity index 51%
copy from libxfce4panel/xfce-panel-convenience.h
copy to common/panel-xfconf.h
index 5c25f5b..7c12732 100644
--- a/libxfce4panel/xfce-panel-convenience.h
+++ b/common/panel-xfconf.h
@@ -1,7 +1,6 @@
 /* $Id$ */
 /*
- * Copyright (C) 2006-2007 Jasper Huijsmans <jasper at xfce.org>
- * Copyright (C) 2008-2009 Nick Schermer <nick at xfce.org>
+ * Copyright (C) 2009 Nick Schermer <nick at xfce.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,23 +17,24 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#if !defined(LIBXFCE4PANEL_INSIDE_LIBXFCE4PANEL_H) && !defined(LIBXFCE4PANEL_COMPILATION)
-#error "Only <libxfce4panel/libxfce4panel.h> can be included directly, this file may disappear or change contents"
-#endif
+#ifndef __PANEL_XFCONF_H__
+#define __PANEL_XFCONF_H__
 
-#ifndef __XFCE_PANEL_CONVENIENCE_H__
-#define __XFCE_PANEL_CONVENIENCE_H__
+#include <xfconf/xfconf.h>
 
-#include <gtk/gtk.h>
+typedef struct _PanelProperty PanelProperty;
+struct _PanelProperty
+{
+  const gchar *property;
+  GType        type;
+};
 
-G_BEGIN_DECLS
+void panel_properties_bind   (XfconfChannel       *channel,
+                              GObject             *object,
+			      const gchar         *property_base,
+			      const PanelProperty *properties,
+			      GHashTable          *hash_table);
 
-GtkWidget *xfce_panel_create_button         (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+void panel_properties_unbind (GObject             *object);
 
-GtkWidget *xfce_panel_create_toggle_button  (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-
-gboolean   xfce_panel_allow_customization   (void);
-
-G_END_DECLS
-
-#endif /* !__XFCE_PANEL_CONVENIENCE_H__ */
+#endif /* !__PANEL_XFCONF_H__ */



More information about the Xfce4-commits mailing list