77
78
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
78
79
/* Private Funcs */
79
80
static void layout_update (DBusGProxy * proxy, DbusmenuClient * client);
81
static void id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client);
82
static void id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client);
80
83
static void build_proxies (DbusmenuClient * client);
81
84
static guint parse_node_get_id (xmlNodePtr node);
82
static DbusmenuMenuitem * parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent);
85
static DbusmenuMenuitem * parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy);
83
86
static void parse_layout (DbusmenuClient * client, const gchar * layout);
84
87
static void update_layout_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data);
85
88
static void update_layout (DbusmenuClient * client);
244
/* Signal from the server that a property has changed
245
on one of our menuitems */
247
id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client)
249
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
250
g_return_if_fail(priv->root != NULL);
252
DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
253
g_return_if_fail(menuitem != NULL);
255
dbusmenu_menuitem_property_set(menuitem, property, value);
259
/* Oh, lots of updates now. That silly server, they want
260
to change all kinds of stuff! */
262
id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client)
264
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
265
g_return_if_fail(priv->root != NULL);
267
DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
268
g_return_if_fail(menuitem != NULL);
270
/* dbusmenu_menuitem_property_set(menuitem, property, value); */
241
274
/* When we have a name and an object, build the two proxies and get the
242
275
first version of the layout */
281
314
dbus_g_proxy_add_signal(priv->menuproxy, "LayoutUpdate", G_TYPE_INVALID);
282
315
dbus_g_proxy_connect_signal(priv->menuproxy, "LayoutUpdate", G_CALLBACK(layout_update), client, NULL);
317
dbus_g_object_register_marshaller(_dbusmenu_server_marshal_VOID__UINT_STRING_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
318
dbus_g_proxy_add_signal(priv->menuproxy, "IdPropUpdate", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
319
dbus_g_proxy_connect_signal(priv->menuproxy, "IdPropUpdate", G_CALLBACK(id_prop_update), client, NULL);
321
dbus_g_proxy_add_signal(priv->menuproxy, "IdUpdate", G_TYPE_UINT, G_TYPE_INVALID);
322
dbus_g_proxy_connect_signal(priv->menuproxy, "IdUpdate", G_CALLBACK(id_update), client, NULL);
301
341
if (g_strcmp0((gchar *)attrib->name, "id") == 0) {
302
342
if (attrib->children != NULL) {
303
343
guint id = (guint)g_ascii_strtoull((gchar *)attrib->children->content, NULL, 10);
304
g_debug ("Found ID: %d", id);
344
/* g_debug ("Found ID: %d", id); */
355
/* A small helper that calls _property_set on each hash table
356
entry in the properties hash. */
358
get_properties_helper (gpointer key, gpointer value, gpointer data)
360
dbusmenu_menuitem_property_set((DbusmenuMenuitem *)data, (gchar *)key, (gchar *)value);
364
/* This is the callback for the properties on a menu item. There
365
should be all of them in the Hash, and they we use foreach to
366
copy them into the menuitem.
367
This isn't the most efficient way. We can optimize this by
368
somehow removing the foreach. But that is for later. */
370
menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
372
g_hash_table_foreach(properties, get_properties_helper, data);
373
g_hash_table_destroy(properties);
315
377
/* Parse recursively through the XML and make it into
316
378
objects as need be */
317
379
static DbusmenuMenuitem *
318
parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent)
380
parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy)
320
382
guint id = parse_node_get_id(node);
321
g_debug("Looking at node with id: %d", id);
383
/* g_debug("Looking at node with id: %d", id); */
322
384
if (item == NULL || dbusmenu_menuitem_get_id(item) != id || id == 0) {
323
385
if (item != NULL) {
324
386
if (parent != NULL) {
335
397
/* Build a new item */
336
398
item = dbusmenu_menuitem_new_with_id(id);
399
/* Get the properties queued up for this item */
400
org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, item);
339
403
xmlNodePtr children;
341
405
GList * oldchildren = dbusmenu_menuitem_take_children(item);
343
407
for (children = node->children, position = 0; children != NULL; children = children->next, position++) {
344
g_debug("Looking at child: %d", position);
408
/* g_debug("Looking at child: %d", position); */
345
409
guint childid = parse_node_get_id(children);
346
410
DbusmenuMenuitem * childmi = NULL;
358
childmi = parse_layout_xml(children, childmi, item);
422
childmi = parse_layout_xml(children, childmi, item, proxy);
359
423
dbusmenu_menuitem_child_add_position(item, childmi, position);
383
447
xmlNodePtr root = xmlDocGetRootElement(xmldoc);
385
priv->root = parse_layout_xml(root, priv->root, NULL);
449
priv->root = parse_layout_xml(root, priv->root, NULL, priv->menuproxy);
386
450
if (priv->root == NULL) {
387
451
g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, layout);
411
475
const gchar * xml = g_value_get_string(&value);
412
g_debug("Got layout string: %s", xml);
476
/* g_debug("Got layout string: %s", xml); */
413
477
parse_layout(client, xml);
415
479
priv->layoutcall = NULL;
416
g_debug("Root is now: 0x%X", (unsigned int)priv->root);
480
/* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */
417
481
g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE);