~dbusmenu-team/libdbusmenu/trunk.16.10

« back to all changes in this revision

Viewing changes to libdbusmenu-glib/client.c

  • Committer: Ted Gould
  • Date: 2009-06-05 20:08:56 UTC
  • mfrom: (1.2.42 properties)
  • Revision ID: ted@canonical.com-20090605200856-k9rhuw19mnwqnpsc
Merging in work on properties.  Cody reviewed in merge request 6707.

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);
 
89
static void menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data);
86
90
 
87
91
/* Build a type */
88
92
G_DEFINE_TYPE (DbusmenuClient, dbusmenu_client, G_TYPE_OBJECT);
238
242
        return;
239
243
}
240
244
 
 
245
/* Signal from the server that a property has changed
 
246
   on one of our menuitems */
 
247
static void
 
248
id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client)
 
249
{
 
250
        DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 
251
        g_return_if_fail(priv->root != NULL);
 
252
 
 
253
        DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
 
254
        g_return_if_fail(menuitem != NULL);
 
255
 
 
256
        dbusmenu_menuitem_property_set(menuitem, property, value);
 
257
        return;
 
258
}
 
259
 
 
260
/* Oh, lots of updates now.  That silly server, they want
 
261
   to change all kinds of stuff! */
 
262
static void
 
263
id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client)
 
264
{
 
265
        DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 
266
        g_return_if_fail(priv->root != NULL);
 
267
 
 
268
        DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
 
269
        g_return_if_fail(menuitem != NULL);
 
270
 
 
271
        org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, menuitem);
 
272
        return;
 
273
}
 
274
 
241
275
/* When we have a name and an object, build the two proxies and get the
242
276
   first version of the layout */
243
277
static void
281
315
        dbus_g_proxy_add_signal(priv->menuproxy, "LayoutUpdate", G_TYPE_INVALID);
282
316
        dbus_g_proxy_connect_signal(priv->menuproxy, "LayoutUpdate", G_CALLBACK(layout_update), client, NULL);
283
317
 
 
318
        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);
 
319
        dbus_g_proxy_add_signal(priv->menuproxy, "IdPropUpdate", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
 
320
        dbus_g_proxy_connect_signal(priv->menuproxy, "IdPropUpdate", G_CALLBACK(id_prop_update), client, NULL);
 
321
 
 
322
        dbus_g_proxy_add_signal(priv->menuproxy, "IdUpdate", G_TYPE_UINT, G_TYPE_INVALID);
 
323
        dbus_g_proxy_connect_signal(priv->menuproxy, "IdUpdate", G_CALLBACK(id_update), client, NULL);
 
324
 
284
325
        return;
285
326
}
286
327
 
301
342
                if (g_strcmp0((gchar *)attrib->name, "id") == 0) {
302
343
                        if (attrib->children != NULL) {
303
344
                                guint id = (guint)g_ascii_strtoull((gchar *)attrib->children->content, NULL, 10);
304
 
                                g_debug ("Found ID: %d", id);
 
345
                                /* g_debug ("Found ID: %d", id); */
305
346
                                return id;
306
347
                        }
307
348
                        break;
312
353
        return 0;
313
354
}
314
355
 
 
356
/* A small helper that calls _property_set on each hash table
 
357
   entry in the properties hash. */
 
358
static void
 
359
get_properties_helper (gpointer key, gpointer value, gpointer data)
 
360
{
 
361
        dbusmenu_menuitem_property_set((DbusmenuMenuitem *)data, (gchar *)key, (gchar *)value);
 
362
        return;
 
363
}
 
364
 
 
365
/* This is the callback for the properties on a menu item.  There
 
366
   should be all of them in the Hash, and they we use foreach to
 
367
   copy them into the menuitem.
 
368
   This isn't the most efficient way.  We can optimize this by
 
369
   somehow removing the foreach.  But that is for later.  */
 
370
static void
 
371
menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
 
372
{
 
373
        g_hash_table_foreach(properties, get_properties_helper, data);
 
374
        g_hash_table_destroy(properties);
 
375
        return;
 
376
}
 
377
 
315
378
/* Parse recursively through the XML and make it into
316
379
   objects as need be */
317
380
static DbusmenuMenuitem *
318
 
parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent)
 
381
parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy)
319
382
{
320
383
        guint id = parse_node_get_id(node);
321
 
        g_debug("Looking at node with id: %d", id);
 
384
        /* g_debug("Looking at node with id: %d", id); */
322
385
        if (item == NULL || dbusmenu_menuitem_get_id(item) != id || id == 0) {
323
386
                if (item != NULL) {
324
387
                        if (parent != NULL) {
334
397
 
335
398
                /* Build a new item */
336
399
                item = dbusmenu_menuitem_new_with_id(id);
 
400
                /* Get the properties queued up for this item */
 
401
                org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, item);
337
402
        } 
338
403
 
339
404
        xmlNodePtr children;
341
406
        GList * oldchildren = dbusmenu_menuitem_take_children(item);
342
407
 
343
408
        for (children = node->children, position = 0; children != NULL; children = children->next, position++) {
344
 
                g_debug("Looking at child: %d", position);
 
409
                /* g_debug("Looking at child: %d", position); */
345
410
                guint childid = parse_node_get_id(children);
346
411
                DbusmenuMenuitem * childmi = NULL;
347
412
 
355
420
                        }
356
421
                }
357
422
 
358
 
                childmi = parse_layout_xml(children, childmi, item);
 
423
                childmi = parse_layout_xml(children, childmi, item, proxy);
359
424
                dbusmenu_menuitem_child_add_position(item, childmi, position);
360
425
        }
361
426
 
382
447
 
383
448
        xmlNodePtr root = xmlDocGetRootElement(xmldoc);
384
449
 
385
 
        priv->root = parse_layout_xml(root, priv->root, NULL);
 
450
        priv->root = parse_layout_xml(root, priv->root, NULL, priv->menuproxy);
386
451
        if (priv->root == NULL) {
387
452
                g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, layout);
388
453
        }
409
474
        }
410
475
 
411
476
        const gchar * xml = g_value_get_string(&value);
412
 
        g_debug("Got layout string: %s", xml);
 
477
        /* g_debug("Got layout string: %s", xml); */
413
478
        parse_layout(client, xml);
414
479
 
415
480
        priv->layoutcall = NULL;
416
 
        g_debug("Root is now: 0x%X", (unsigned int)priv->root);
 
481
        /* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */
417
482
        g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE);
418
483
 
419
484
        return;