~dbusmenu-team/libdbusmenu/trunk.16.10

« back to all changes in this revision

Viewing changes to libdbusmenu-glib/server.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:
34
34
#include "server-marshal.h"
35
35
 
36
36
/* DBus Prototypes */
37
 
static gboolean _dbusmenu_server_get_property (void);
38
 
static gboolean _dbusmenu_server_get_properties (void);
39
 
static gboolean _dbusmenu_server_call (void);
40
 
static gboolean _dbusmenu_server_list_properties (void);
 
37
static gboolean _dbusmenu_server_get_property (DbusmenuServer * server, guint id, gchar * property, gchar ** value, GError ** error);
 
38
static gboolean _dbusmenu_server_get_properties (DbusmenuServer * server, guint id, GHashTable ** dict, GError ** error);
 
39
static gboolean _dbusmenu_server_call (DbusmenuServer * server, guint id, GError ** error);
41
40
 
42
41
#include "dbusmenu-server.h"
43
42
 
71
70
        PROP_LAYOUT
72
71
};
73
72
 
 
73
/* Errors */
 
74
enum {
 
75
        INVALID_MENUITEM_ID,
 
76
        INVALID_PROPERTY_NAME,
 
77
        UNKNOWN_DBUS_ERROR,
 
78
        LAST_ERROR
 
79
};
 
80
 
74
81
/* Prototype */
75
82
static void dbusmenu_server_class_init (DbusmenuServerClass *class);
76
83
static void dbusmenu_server_init       (DbusmenuServer *self);
78
85
static void dbusmenu_server_finalize   (GObject *object);
79
86
static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec);
80
87
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
 
88
static void menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, gchar * value, DbusmenuServer * server);
 
89
static void menuitem_child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, DbusmenuServer * server);
 
90
static void menuitem_child_removed (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, DbusmenuServer * server);
 
91
static void menuitem_signals_create (DbusmenuMenuitem * mi, gpointer data);
 
92
static void menuitem_signals_remove (DbusmenuMenuitem * mi, gpointer data);
 
93
static GQuark error_quark (void);
81
94
 
82
95
G_DEFINE_TYPE (DbusmenuServer, dbusmenu_server, G_TYPE_OBJECT);
83
96
 
93
106
        object_class->set_property = set_property;
94
107
        object_class->get_property = get_property;
95
108
 
 
109
        /**
 
110
                DbusmenuServer::id-prop-update:
 
111
                @arg0: The #DbusmenuServer emitting the signal.
 
112
                @arg1: The ID of the #DbusmenuMenuitem changing a property.
 
113
                @arg2: The property being changed.
 
114
                @arg3: The value of the property being changed.
 
115
 
 
116
                This signal is emitted when a menuitem updates or
 
117
                adds a property.
 
118
        */
96
119
        signals[ID_PROP_UPDATE] =   g_signal_new(DBUSMENU_SERVER_SIGNAL_ID_PROP_UPDATE,
97
120
                                                 G_TYPE_FROM_CLASS(class),
98
121
                                                 G_SIGNAL_RUN_LAST,
100
123
                                                 NULL, NULL,
101
124
                                                 _dbusmenu_server_marshal_VOID__UINT_STRING_STRING,
102
125
                                                 G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
 
126
        /**
 
127
                DbusmenuServer::id-update:
 
128
                @arg0: The #DbusmenuServer emitting the signal.
 
129
                @arg1: ID of the #DbusmenuMenuitem changing.
 
130
 
 
131
                The purpose of this signal is to show major change in
 
132
                a menuitem to the point that #DbusmenuServer::id-prop-update
 
133
                seems a little insubstantive.
 
134
        */
103
135
        signals[ID_UPDATE] =        g_signal_new(DBUSMENU_SERVER_SIGNAL_ID_UPDATE,
104
136
                                                 G_TYPE_FROM_CLASS(class),
105
137
                                                 G_SIGNAL_RUN_LAST,
107
139
                                                 NULL, NULL,
108
140
                                                 g_cclosure_marshal_VOID__UINT,
109
141
                                                 G_TYPE_NONE, 1, G_TYPE_UINT);
 
142
        /**
 
143
                DbusmenuServer::layout-update:
 
144
                @arg0: The #DbusmenuServer emitting the signal.
 
145
 
 
146
                This signal is emitted any time the layout of the
 
147
                menuitems under this server is changed.
 
148
        */
110
149
        signals[LAYOUT_UPDATE] =    g_signal_new(DBUSMENU_SERVER_SIGNAL_LAYOUT_UPDATE,
111
150
                                                 G_TYPE_FROM_CLASS(class),
112
151
                                                 G_SIGNAL_RUN_LAST,
151
190
static void
152
191
dbusmenu_server_dispose (GObject *object)
153
192
{
 
193
        DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(object);
 
194
 
 
195
        if (priv->root != NULL) {
 
196
                dbusmenu_menuitem_foreach(priv->root, menuitem_signals_remove, object);
 
197
                g_object_unref(priv->root);
 
198
        }
 
199
 
154
200
        G_OBJECT_CLASS (dbusmenu_server_parent_class)->dispose (object);
155
201
        return;
156
202
}
178
224
                break;
179
225
        case PROP_ROOT_NODE:
180
226
                if (priv->root != NULL) {
 
227
                        dbusmenu_menuitem_foreach(priv->root, menuitem_signals_remove, obj);
181
228
                        g_object_unref(G_OBJECT(priv->root));
182
229
                        priv->root = NULL;
183
230
                }
184
231
                priv->root = DBUSMENU_MENUITEM(g_value_get_object(value));
185
232
                if (priv->root != NULL) {
186
233
                        g_object_ref(G_OBJECT(priv->root));
 
234
                        dbusmenu_menuitem_foreach(priv->root, menuitem_signals_create, obj);
187
235
                } else {
188
236
                        g_debug("Setting root node to NULL");
189
237
                }
226
274
        case PROP_LAYOUT: {
227
275
                GPtrArray * xmlarray = g_ptr_array_new();
228
276
                if (priv->root == NULL) {
229
 
                        g_debug("Getting layout without root node!");
 
277
                        /* g_debug("Getting layout without root node!"); */
230
278
                        g_ptr_array_add(xmlarray, g_strdup("<menu />"));
231
279
                } else {
232
280
                        dbusmenu_menuitem_buildxml(priv->root, xmlarray);
236
284
                /* build string */
237
285
                gchar * finalstring = g_strjoinv("", (gchar **)xmlarray->pdata);
238
286
                g_value_take_string(value, finalstring);
239
 
                g_debug("Final string: %s", finalstring);
 
287
                /* g_debug("Final string: %s", finalstring); */
240
288
 
241
289
                g_ptr_array_foreach(xmlarray, xmlarray_foreach_free, NULL);
242
290
                g_ptr_array_free(xmlarray, TRUE);
250
298
        return;
251
299
}
252
300
 
 
301
static void 
 
302
menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, gchar * value, DbusmenuServer * server)
 
303
{
 
304
        g_signal_emit(G_OBJECT(server), signals[ID_PROP_UPDATE], 0, dbusmenu_menuitem_get_id(mi), property, value, TRUE);
 
305
        return;
 
306
}
 
307
 
 
308
static void
 
309
menuitem_child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, DbusmenuServer * server)
 
310
{
 
311
        menuitem_signals_create(child, server);
 
312
        /* TODO: We probably need to group the layout update signals to make the number more reasonble. */
 
313
        g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, TRUE);
 
314
        return;
 
315
}
 
316
 
 
317
static void 
 
318
menuitem_child_removed (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, DbusmenuServer * server)
 
319
{
 
320
        menuitem_signals_remove(child, server);
 
321
        /* TODO: We probably need to group the layout update signals to make the number more reasonble. */
 
322
        g_signal_emit(G_OBJECT(server), signals[LAYOUT_UPDATE], 0, TRUE);
 
323
        return;
 
324
}
 
325
 
 
326
/* Connects all the signals that we're interested in
 
327
   coming from a menuitem */
 
328
static void
 
329
menuitem_signals_create (DbusmenuMenuitem * mi, gpointer data)
 
330
{
 
331
        g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(menuitem_child_added), data);
 
332
        g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(menuitem_child_removed), data);
 
333
        g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menuitem_property_changed), data);
 
334
        return;
 
335
}
 
336
 
 
337
/* Removes all the signals that we're interested in
 
338
   coming from a menuitem */
 
339
static void
 
340
menuitem_signals_remove (DbusmenuMenuitem * mi, gpointer data)
 
341
{
 
342
        g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_child_added), data);
 
343
        g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_child_removed), data);
 
344
        g_signal_handlers_disconnect_by_func(G_OBJECT(mi), G_CALLBACK(menuitem_property_changed), data);
 
345
        return;
 
346
}
 
347
 
 
348
static GQuark
 
349
error_quark (void)
 
350
{
 
351
        static GQuark quark = 0;
 
352
        if (quark == 0) {
 
353
                quark = g_quark_from_static_string (G_LOG_DOMAIN);
 
354
        }
 
355
        return quark;
 
356
}
 
357
 
253
358
/* DBus interface */
254
359
static gboolean 
255
 
_dbusmenu_server_get_property (void)
256
 
{
257
 
 
258
 
        return TRUE;
259
 
}
260
 
 
261
 
static gboolean
262
 
_dbusmenu_server_get_properties (void)
263
 
{
264
 
 
265
 
        return TRUE;
266
 
}
267
 
 
268
 
static gboolean
269
 
_dbusmenu_server_call (void)
270
 
{
271
 
 
272
 
        return TRUE;
273
 
}
274
 
 
275
 
static gboolean
276
 
_dbusmenu_server_list_properties (void)
277
 
{
278
 
 
 
360
_dbusmenu_server_get_property (DbusmenuServer * server, guint id, gchar * property, gchar ** value, GError ** error)
 
361
{
 
362
        DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
 
363
        DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
 
364
 
 
365
        if (mi == NULL) {
 
366
                if (error != NULL) {
 
367
                        g_set_error(error,
 
368
                                    error_quark(),
 
369
                                    INVALID_MENUITEM_ID,
 
370
                                    "The ID supplied %d does not refer to a menu item we have",
 
371
                                    id);
 
372
                }
 
373
                return FALSE;
 
374
        }
 
375
 
 
376
        const gchar * prop = dbusmenu_menuitem_property_get(mi, property);
 
377
        if (prop == NULL) {
 
378
                if (error != NULL) {
 
379
                        g_set_error(error,
 
380
                                    error_quark(),
 
381
                                    INVALID_PROPERTY_NAME,
 
382
                                    "The property '%s' does not exist on menuitem with ID of %d",
 
383
                                    property,
 
384
                                    id);
 
385
                }
 
386
                return FALSE;
 
387
        }
 
388
 
 
389
        if (value == NULL) {
 
390
                if (error != NULL) {
 
391
                        g_set_error(error,
 
392
                                    error_quark(),
 
393
                                    UNKNOWN_DBUS_ERROR,
 
394
                                    "Uhm, yeah.  We didn't get anywhere to put the value, that's really weird.  Seems impossible really.");
 
395
                }
 
396
                return FALSE;
 
397
        }
 
398
 
 
399
        *value = g_strdup(prop);
 
400
 
 
401
        return TRUE;
 
402
}
 
403
 
 
404
static gboolean
 
405
_dbusmenu_server_get_properties (DbusmenuServer * server, guint id, GHashTable ** dict, GError ** error)
 
406
{
 
407
        DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
 
408
        DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
 
409
 
 
410
        if (mi == NULL) {
 
411
                if (error != NULL) {
 
412
                        g_set_error(error,
 
413
                                    error_quark(),
 
414
                                    INVALID_MENUITEM_ID,
 
415
                                    "The ID supplied %d does not refer to a menu item we have",
 
416
                                    id);
 
417
                }
 
418
                return FALSE;
 
419
        }
 
420
 
 
421
        *dict = dbusmenu_menuitem_properties_copy(mi);
 
422
 
 
423
        return TRUE;
 
424
}
 
425
 
 
426
static gboolean
 
427
_dbusmenu_server_call (DbusmenuServer * server, guint id, GError ** error)
 
428
{
 
429
        DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
 
430
        DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
 
431
 
 
432
        if (mi == NULL) {
 
433
                if (error != NULL) {
 
434
                        g_set_error(error,
 
435
                                    error_quark(),
 
436
                                    INVALID_MENUITEM_ID,
 
437
                                    "The ID supplied %d does not refer to a menu item we have",
 
438
                                    id);
 
439
                }
 
440
                return FALSE;
 
441
        }
 
442
 
 
443
        dbusmenu_menuitem_activate(mi);
279
444
        return TRUE;
280
445
}
281
446
 
320
485
        g_return_if_fail(DBUSMENU_IS_SERVER(self));
321
486
        g_return_if_fail(DBUSMENU_IS_MENUITEM(root));
322
487
 
323
 
        g_debug("Setting root object: 0x%X", (unsigned int)root);
 
488
        /* g_debug("Setting root object: 0x%X", (unsigned int)root); */
324
489
        GValue rootvalue = {0};
325
490
        g_value_init(&rootvalue, G_TYPE_OBJECT);
326
491
        g_value_set_object(&rootvalue, root);