~dbusmenu-team/libdbusmenu/trunk.16.10

« back to all changes in this revision

Viewing changes to libdbusmenu-glib/client.c

Merging in the properties branch to provide some basis to work with.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
 
36
36
#include "client.h"
37
37
#include "dbusmenu-client.h"
 
38
#include "server-marshal.h"
38
39
 
39
40
/* Properties */
40
41
enum {
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);
238
241
        return;
239
242
}
240
243
 
 
244
/* Signal from the server that a property has changed
 
245
   on one of our menuitems */
 
246
static void
 
247
id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client)
 
248
{
 
249
        DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 
250
        g_return_if_fail(priv->root != NULL);
 
251
 
 
252
        DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
 
253
        g_return_if_fail(menuitem != NULL);
 
254
 
 
255
        dbusmenu_menuitem_property_set(menuitem, property, value);
 
256
        return;
 
257
}
 
258
 
 
259
/* Oh, lots of updates now.  That silly server, they want
 
260
   to change all kinds of stuff! */
 
261
static void
 
262
id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client)
 
263
{
 
264
        DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 
265
        g_return_if_fail(priv->root != NULL);
 
266
 
 
267
        DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
 
268
        g_return_if_fail(menuitem != NULL);
 
269
 
 
270
        /* dbusmenu_menuitem_property_set(menuitem, property, value); */
 
271
        return;
 
272
}
 
273
 
241
274
/* When we have a name and an object, build the two proxies and get the
242
275
   first version of the layout */
243
276
static void
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);
283
316
 
 
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);
 
320
 
 
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);
 
323
 
284
324
        return;
285
325
}
286
326
 
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); */
305
345
                                return id;
306
346
                        }
307
347
                        break;
312
352
        return 0;
313
353
}
314
354
 
 
355
/* A small helper that calls _property_set on each hash table
 
356
   entry in the properties hash. */
 
357
static void
 
358
get_properties_helper (gpointer key, gpointer value, gpointer data)
 
359
{
 
360
        dbusmenu_menuitem_property_set((DbusmenuMenuitem *)data, (gchar *)key, (gchar *)value);
 
361
        return;
 
362
}
 
363
 
 
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.  */
 
369
static void
 
370
menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
 
371
{
 
372
        g_hash_table_foreach(properties, get_properties_helper, data);
 
373
        g_hash_table_destroy(properties);
 
374
        return;
 
375
}
 
376
 
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)
319
381
{
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) {
334
396
 
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);
337
401
        } 
338
402
 
339
403
        xmlNodePtr children;
341
405
        GList * oldchildren = dbusmenu_menuitem_take_children(item);
342
406
 
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;
347
411
 
355
419
                        }
356
420
                }
357
421
 
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);
360
424
        }
361
425
 
382
446
 
383
447
        xmlNodePtr root = xmlDocGetRootElement(xmldoc);
384
448
 
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);
388
452
        }
409
473
        }
410
474
 
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);
414
478
 
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);
418
482
 
419
483
        return;