Merge lp:~ted/libdbusmenu/types into lp:libdbusmenu/0.5
- types
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~ted/libdbusmenu/types |
Merge into: | lp:libdbusmenu/0.5 |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~ted/libdbusmenu/types |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Neil J. Patel (community) | Approve | ||
Review via email: mp+10772@code.launchpad.net |
Commit message
Description of the change
Ted Gould (ted) wrote : | # |
Neil J. Patel (njpatel) wrote : | # |
Looks good. I had some suggestions/
menuitem_
- I'd normally check that data != NULL before accessing its members
menuitem_call_cb:
- I'd, normally check that returned pointer from g_new0 != NULL
dbusmenu_
- Would a check for type!= NULL make sense here, as you use it to lookup in the hashtable?
- Does newfunc need to also be checked? Or is is okay to add a NULL func (i.e. to unset a previously set function)?
new_item_seperator & new_item_normal:
- Are arg checks required for newitem, parent and client?
child_realized:
- I'd have g_return_if_fail (DBUS_MENU_GTKMENU (userdata)) before casting it as its a signal callback
Ted Gould (ted) wrote : | # |
On Thu, 2009-08-27 at 11:33 +0000, Neil J. Patel wrote:
> menuitem_
> - I'd normally check that data != NULL before accessing its members
Fixed. (r34)
> menuitem_call_cb:
> - I'd, normally check that returned pointer from g_new0 != NULL
Do you mean "parse_layout_xml"? I believe that is the only call to
g_new0 in client.c, fixed :) (r35)
> dbusmenu_
> - Would a check for type!= NULL make sense here, as you use it to lookup in the hashtable?
Fixed. (r36)
> - Does newfunc need to also be checked? Or is is okay to add a NULL func (i.e. to unset a previously set function)?
No, I think it's okay to have a NULL function. We check when it's
pulled out, so there's no risk. I'm not sure why you'd WANT to do that,
but I don't see any reason to restrict it.
> new_item_seperator & new_item_normal:
> - Are arg checks required for newitem, parent and client?
They're basically internal functions... but since people will probably
steal that code as examples when they make their own external ones it
makes sense to have it there, so they include it. (r37)
> child_realized:
> - I'd have g_return_if_fail (DBUS_MENU_GTKMENU (userdata)) before casting it as its a signal callback
I used DBUSMENU_
- 34. By Ted Gould
-
Comment for Neil. Checking data.
- 35. By Ted Gould
-
Check the return of g_new0 for NULL. Comment by Neil.
- 36. By Ted Gould
-
Making sure that type is not NULL. Comment from Neil.
- 37. By Ted Gould
-
Adding checks to the type handling functions in GTK+ version of the lib. Comments by Neil.
- 38. By Ted Gould
-
Checking the menu is a GTK menu before casting it. Comments by Neil.
Neil J. Patel (njpatel) wrote : | # |
> > menuitem_call_cb:
> > - I'd, normally check that returned pointer from g_new0 != NULL
>
> Do you mean "parse_layout_xml"? I believe that is the only call to
> g_new0 in client.c, fixed :) (r35)
>
yes :)
> > child_realized:
> > - I'd have g_return_if_fail (DBUS_MENU_GTKMENU (userdata)) before casting
> it as its a signal callback
>
> I used DBUSMENU_
Thankfully one of us woke up this morning :)
Approved.
Preview Diff
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2009-06-24 17:35:35 +0000 |
3 | +++ configure.ac 2009-08-26 21:31:40 +0000 |
4 | @@ -5,7 +5,7 @@ |
5 | AC_PREREQ(2.53) |
6 | |
7 | AM_CONFIG_HEADER(config.h) |
8 | -AM_INIT_AUTOMAKE(libdbusmenu, 0.0.1) |
9 | +AM_INIT_AUTOMAKE(libdbusmenu, 0.0.2) |
10 | |
11 | AM_MAINTAINER_MODE |
12 | |
13 | @@ -19,6 +19,8 @@ |
14 | AC_SUBST(VERSION) |
15 | AC_CONFIG_MACRO_DIR([m4]) |
16 | |
17 | +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) |
18 | + |
19 | ########################### |
20 | # Dependencies - GLib |
21 | ########################### |
22 | |
23 | === modified file 'libdbusmenu-glib/client.c' |
24 | --- libdbusmenu-glib/client.c 2009-07-20 21:34:39 +0000 |
25 | +++ libdbusmenu-glib/client.c 2009-08-26 20:42:27 +0000 |
26 | @@ -68,6 +68,16 @@ |
27 | DBusGProxyCall * layoutcall; |
28 | |
29 | DBusGProxy * dbusproxy; |
30 | + |
31 | + GHashTable * type_handlers; |
32 | +}; |
33 | + |
34 | +typedef struct _newItemPropData newItemPropData; |
35 | +struct _newItemPropData |
36 | +{ |
37 | + DbusmenuClient * client; |
38 | + DbusmenuMenuitem * item; |
39 | + DbusmenuMenuitem * parent; |
40 | }; |
41 | |
42 | #define DBUSMENU_CLIENT_GET_PRIVATE(o) \ |
43 | @@ -187,6 +197,9 @@ |
44 | |
45 | priv->dbusproxy = NULL; |
46 | |
47 | + priv->type_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, |
48 | + g_free, NULL); |
49 | + |
50 | return; |
51 | } |
52 | |
53 | @@ -230,6 +243,10 @@ |
54 | g_free(priv->dbus_name); |
55 | g_free(priv->dbus_object); |
56 | |
57 | + if (priv->type_handlers != NULL) { |
58 | + g_hash_table_destroy(priv->type_handlers); |
59 | + } |
60 | + |
61 | G_OBJECT_CLASS (dbusmenu_client_parent_class)->finalize (object); |
62 | return; |
63 | } |
64 | @@ -515,6 +532,43 @@ |
65 | return; |
66 | } |
67 | |
68 | +/* This is a different get properites call back that also sends |
69 | + new signals. It basically is a small wrapper around the original. */ |
70 | +static void |
71 | +menuitem_get_properties_new_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data) |
72 | +{ |
73 | + newItemPropData * propdata = (newItemPropData *)data; |
74 | + DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(propdata->client); |
75 | + |
76 | + menuitem_get_properties_cb (proxy, properties, error, propdata->item); |
77 | + |
78 | + gboolean handled = FALSE; |
79 | + |
80 | + const gchar * type; |
81 | + DbusmenuClientTypeHandler newfunc = NULL; |
82 | + |
83 | + type = dbusmenu_menuitem_property_get(propdata->item, "type"); |
84 | + if (type != NULL) { |
85 | + newfunc = g_hash_table_lookup(priv->type_handlers, type); |
86 | + } else { |
87 | + newfunc = g_hash_table_lookup(priv->type_handlers, DBUSMENU_CLIENT_TYPES_DEFAULT); |
88 | + } |
89 | + |
90 | + if (newfunc != NULL) { |
91 | + handled = newfunc(propdata->item, propdata->parent, propdata->client); |
92 | + } |
93 | + |
94 | + g_signal_emit(G_OBJECT(propdata->item), DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID, 0, TRUE); |
95 | + |
96 | + if (!handled) { |
97 | + g_signal_emit(G_OBJECT(propdata->client), signals[NEW_MENUITEM], 0, propdata->item, TRUE); |
98 | + } |
99 | + |
100 | + g_free(propdata); |
101 | + |
102 | + return; |
103 | +} |
104 | + |
105 | static void |
106 | menuitem_call_cb (DBusGProxy * proxy, GError * error, gpointer userdata) |
107 | { |
108 | @@ -562,9 +616,15 @@ |
109 | dbusmenu_menuitem_set_root(item, TRUE); |
110 | } |
111 | g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(menuitem_activate), client); |
112 | - g_signal_emit(G_OBJECT(client), signals[NEW_MENUITEM], 0, item, TRUE); |
113 | + |
114 | /* Get the properties queued up for this item */ |
115 | - org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, item); |
116 | + /* Not happy about this, but I need these :( */ |
117 | + newItemPropData * propdata = g_new0(newItemPropData, 1); |
118 | + propdata->client = client; |
119 | + propdata->item = item; |
120 | + propdata->parent = parent; |
121 | + |
122 | + org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_new_cb, propdata); |
123 | } |
124 | |
125 | xmlNodePtr children; |
126 | @@ -744,3 +804,46 @@ |
127 | |
128 | return priv->root; |
129 | } |
130 | + |
131 | +/** |
132 | + dbusmenu_client_add_type_handler: |
133 | + @client: Client where we're getting types coming in |
134 | + @type: A text string that will be matched with the 'type' |
135 | + property on incoming menu items |
136 | + @newfunc: The function that will be executed with those new |
137 | + items when they come in. |
138 | + |
139 | + This function connects into the type handling of the #DbusmenuClient. |
140 | + Every new menuitem that comes in immediately gets asked for it's |
141 | + properties. When we get those properties we check the 'type' |
142 | + property and look to see if it matches a handler that is known |
143 | + by the client. If so, the @newfunc function is executed on that |
144 | + #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem |
145 | + signal is sent. |
146 | + |
147 | + In the future the known types will be sent to the server so that it |
148 | + can make choices about the menu item types availble. |
149 | + |
150 | + Return value: If registering the new type was successful. |
151 | +*/ |
152 | +gboolean |
153 | +dbusmenu_client_add_type_handler (DbusmenuClient * client, const gchar * type, DbusmenuClientTypeHandler newfunc) |
154 | +{ |
155 | + g_return_val_if_fail(DBUSMENU_IS_CLIENT(client), FALSE); |
156 | + |
157 | + DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); |
158 | + |
159 | + if (priv->type_handlers == NULL) { |
160 | + g_warning("Type handlers hashtable not built"); |
161 | + return FALSE; |
162 | + } |
163 | + |
164 | + gpointer value = g_hash_table_lookup(priv->type_handlers, type); |
165 | + if (value != NULL) { |
166 | + g_warning("Type '%s' already had a registered handler.", type); |
167 | + return FALSE; |
168 | + } |
169 | + |
170 | + g_hash_table_insert(priv->type_handlers, g_strdup(type), newfunc); |
171 | + return TRUE; |
172 | +} |
173 | |
174 | === modified file 'libdbusmenu-glib/client.h' |
175 | --- libdbusmenu-glib/client.h 2009-06-23 20:44:29 +0000 |
176 | +++ libdbusmenu-glib/client.h 2009-08-26 20:15:13 +0000 |
177 | @@ -50,10 +50,15 @@ |
178 | #define DBUSMENU_CLIENT_PROP_DBUS_NAME "dbus-name" |
179 | #define DBUSMENU_CLIENT_PROP_DBUS_OBJECT "dbus-object" |
180 | |
181 | +#define DBUSMENU_CLIENT_TYPES_DEFAULT "menuitem" |
182 | +#define DBUSMENU_CLIENT_TYPES_SEPARATOR "separator" |
183 | +#define DBUSMENU_CLIENT_TYPES_IMAGE "imageitem" |
184 | + |
185 | /** |
186 | DbusmenuClientClass: |
187 | @parent_class: #GObjectClass |
188 | @layout_updated: Slot for #DbusmenuClient::layout-updated. |
189 | + @new_menuitem: Slot for #DbusmenuClient::new-menuitem. |
190 | @reserved1: Reserved for future use. |
191 | @reserved2: Reserved for future use. |
192 | @reserved3: Reserved for future use. |
193 | @@ -90,9 +95,15 @@ |
194 | GObject parent; |
195 | }; |
196 | |
197 | -GType dbusmenu_client_get_type (void); |
198 | -DbusmenuClient * dbusmenu_client_new (const gchar * name, const gchar * object); |
199 | -DbusmenuMenuitem * dbusmenu_client_get_root (DbusmenuClient * client); |
200 | +typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); |
201 | + |
202 | +GType dbusmenu_client_get_type (void); |
203 | +DbusmenuClient * dbusmenu_client_new (const gchar * name, |
204 | + const gchar * object); |
205 | +DbusmenuMenuitem * dbusmenu_client_get_root (DbusmenuClient * client); |
206 | +gboolean dbusmenu_client_add_type_handler (DbusmenuClient * client, |
207 | + const gchar * type, |
208 | + DbusmenuClientTypeHandler newfunc); |
209 | |
210 | /** |
211 | SECTION:client |
212 | |
213 | === modified file 'libdbusmenu-glib/menuitem.c' |
214 | --- libdbusmenu-glib/menuitem.c 2009-06-26 18:57:59 +0000 |
215 | +++ libdbusmenu-glib/menuitem.c 2009-08-25 16:16:26 +0000 |
216 | @@ -61,6 +61,7 @@ |
217 | CHILD_ADDED, |
218 | CHILD_REMOVED, |
219 | CHILD_MOVED, |
220 | + REALIZED, |
221 | LAST_SIGNAL |
222 | }; |
223 | |
224 | @@ -178,6 +179,22 @@ |
225 | NULL, NULL, |
226 | _dbusmenu_menuitem_marshal_VOID__OBJECT_UINT_UINT, |
227 | G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT); |
228 | + /** |
229 | + DbusmenuMenuitem::realized: |
230 | + @arg0: The #DbusmenuMenuitem object. |
231 | + |
232 | + Emitted when the initial request for properties |
233 | + is complete on the item. If there is a type |
234 | + handler configured for the "type" parameter |
235 | + that will be executed before this is signaled. |
236 | + */ |
237 | + signals[REALIZED] = g_signal_new(DBUSMENU_MENUITEM_SIGNAL_REALIZED, |
238 | + G_TYPE_FROM_CLASS(klass), |
239 | + G_SIGNAL_RUN_LAST, |
240 | + G_STRUCT_OFFSET(DbusmenuMenuitemClass, realized), |
241 | + NULL, NULL, |
242 | + _dbusmenu_menuitem_marshal_VOID__VOID, |
243 | + G_TYPE_NONE, 0, G_TYPE_NONE); |
244 | |
245 | g_object_class_install_property (object_class, PROP_ID, |
246 | g_param_spec_uint("id", "ID for the menu item", |
247 | |
248 | === modified file 'libdbusmenu-glib/menuitem.h' |
249 | --- libdbusmenu-glib/menuitem.h 2009-06-26 17:49:52 +0000 |
250 | +++ libdbusmenu-glib/menuitem.h 2009-08-26 20:18:50 +0000 |
251 | @@ -47,6 +47,13 @@ |
252 | #define DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED "child-added" |
253 | #define DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED "child-removed" |
254 | #define DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED "child-moved" |
255 | +#define DBUSMENU_MENUITEM_SIGNAL_REALIZED "realized" |
256 | +#define DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID (g_signal_lookup(DBUSMENU_MENUITEM_SIGNAL_REALIZED, DBUSMENU_TYPE_MENUITEM)) |
257 | + |
258 | +#define DBUSMENU_MENUITEM_PROP_VISIBLE "visible" |
259 | +#define DBUSMENU_MENUITEM_PROP_LABEL "label" |
260 | +#define DBUSMENU_MENUITEM_PROP_ICON "icon" |
261 | +#define DBUSMENU_MENUITEM_PROP_ICON_DATA "icon-data" |
262 | |
263 | /** |
264 | DbusmenuMenuitem: |
265 | @@ -71,6 +78,7 @@ |
266 | @child_added: Slot for #DbusmenuMenuitem::child-added. |
267 | @child_removed: Slot for #DbusmenuMenuitem::child-removed. |
268 | @child_moved: Slot for #DbusmenuMenuitem::child-moved. |
269 | + @realized: Slot for #DbusmenuMenuitem::realized. |
270 | @buildxml: Virtual function that appends the strings required |
271 | to represent this menu item in the menu XML file. |
272 | @reserved1: Reserved for future use. |
273 | @@ -89,6 +97,7 @@ |
274 | void (*child_added) (DbusmenuMenuitem * child, guint position); |
275 | void (*child_removed) (DbusmenuMenuitem * child); |
276 | void (*child_moved) (DbusmenuMenuitem * child, guint newpos, guint oldpos); |
277 | + void (*realized) (void); |
278 | |
279 | /* Virtual functions */ |
280 | void (*buildxml) (GPtrArray * stringarray); |
281 | @@ -96,7 +105,7 @@ |
282 | void (*reserved1) (void); |
283 | void (*reserved2) (void); |
284 | void (*reserved3) (void); |
285 | - void (*reserved4) (void); |
286 | + /* void (*reserved4) (void); -- realized, realloc when bumping lib version */ |
287 | }; |
288 | |
289 | GType dbusmenu_menuitem_get_type (void); |
290 | |
291 | === modified file 'libdbusmenu-gtk/client.c' |
292 | --- libdbusmenu-gtk/client.c 2009-06-26 17:53:15 +0000 |
293 | +++ libdbusmenu-gtk/client.c 2009-08-26 20:25:37 +0000 |
294 | @@ -44,6 +44,10 @@ |
295 | static void delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, DbusmenuGtkClient * gtkclient); |
296 | static void move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint old, DbusmenuGtkClient * gtkclient); |
297 | |
298 | +static gboolean new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); |
299 | +static gboolean new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); |
300 | +static gboolean new_item_image (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client); |
301 | + |
302 | /* GObject Stuff */ |
303 | G_DEFINE_TYPE (DbusmenuGtkClient, dbusmenu_gtkclient, DBUSMENU_TYPE_CLIENT); |
304 | |
305 | @@ -61,7 +65,12 @@ |
306 | static void |
307 | dbusmenu_gtkclient_init (DbusmenuGtkClient *self) |
308 | { |
309 | + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_DEFAULT, new_item_normal); |
310 | + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_SEPARATOR, new_item_seperator); |
311 | + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_IMAGE, new_item_image); |
312 | + |
313 | g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM, G_CALLBACK(new_menuitem), NULL); |
314 | + |
315 | return; |
316 | } |
317 | |
318 | @@ -95,14 +104,27 @@ |
319 | return TRUE; |
320 | } |
321 | |
322 | +/* Process the visible property */ |
323 | +static void |
324 | +process_visible (GtkMenuItem * gmi, const gchar * value) |
325 | +{ |
326 | + if (value == NULL || !g_strcmp0(value, "true")) { |
327 | + gtk_widget_show(GTK_WIDGET(gmi)); |
328 | + } else { |
329 | + gtk_widget_hide(GTK_WIDGET(gmi)); |
330 | + } |
331 | + return; |
332 | +} |
333 | + |
334 | /* Whenever we have a property change on a DbusmenuMenuitem |
335 | we need to be responsive to that. */ |
336 | static void |
337 | menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, GtkMenuItem * gmi) |
338 | { |
339 | - if (!g_strcmp0(prop, "label")) { |
340 | + if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_LABEL)) { |
341 | gtk_menu_item_set_label(gmi, value); |
342 | - gtk_widget_show(GTK_WIDGET(gmi)); |
343 | + } else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_VISIBLE)) { |
344 | + process_visible(gmi, value); |
345 | } |
346 | |
347 | return; |
348 | @@ -125,23 +147,20 @@ |
349 | static void |
350 | new_menuitem (DbusmenuClient * client, DbusmenuMenuitem * mi, gpointer userdata) |
351 | { |
352 | - gpointer ann_mi = g_object_get_data(G_OBJECT(mi), data_menuitem); |
353 | - GtkMenuItem * gmi = GTK_MENU_ITEM(ann_mi); |
354 | - |
355 | - if (gmi != NULL) { |
356 | - /* It's possible we've already been looked at, that's |
357 | - okay, but we can just ignore this signal then. */ |
358 | - return; |
359 | - } |
360 | - |
361 | - gmi = GTK_MENU_ITEM(gtk_menu_item_new()); |
362 | - |
363 | + g_warning("Got new menuitem signal, which means they want something"); |
364 | + g_warning(" that I simply don't have."); |
365 | + |
366 | + return; |
367 | +} |
368 | + |
369 | +static void |
370 | +base_new_menuitem (DbusmenuMenuitem * mi, GtkMenuItem * gmi, DbusmenuGtkClient * client) |
371 | +{ |
372 | /* Attach these two */ |
373 | g_object_set_data(G_OBJECT(mi), data_menuitem, gmi); |
374 | |
375 | /* DbusmenuMenuitem signals */ |
376 | g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi); |
377 | - g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(new_child), client); |
378 | g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(delete_child), client); |
379 | g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(move_child), client); |
380 | |
381 | @@ -151,6 +170,8 @@ |
382 | /* Life insurance */ |
383 | g_object_weak_ref(G_OBJECT(mi), destoryed_dbusmenuitem_cb, gmi); |
384 | |
385 | + process_visible(gmi, dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_VISIBLE)); |
386 | + |
387 | return; |
388 | } |
389 | |
390 | @@ -251,10 +272,47 @@ |
391 | |
392 | GtkMenuItem * mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem)); |
393 | if (mi == NULL) { |
394 | - new_menuitem(DBUSMENU_CLIENT(client), item, NULL); |
395 | + // new_menuitem(DBUSMENU_CLIENT(client), item, NULL); |
396 | + g_warning("GTK not updated"); |
397 | mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem)); |
398 | } |
399 | |
400 | return mi; |
401 | } |
402 | |
403 | +static gboolean |
404 | +new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) |
405 | +{ |
406 | + GtkMenuItem * gmi; |
407 | + |
408 | + gmi = GTK_MENU_ITEM(gtk_menu_item_new_with_label(dbusmenu_menuitem_property_get(newitem, "label"))); |
409 | + |
410 | + base_new_menuitem(newitem, gmi, DBUSMENU_GTKCLIENT(client)); |
411 | + if (parent != NULL) { |
412 | + new_child(parent, newitem, dbusmenu_menuitem_get_position(newitem, parent), DBUSMENU_GTKCLIENT(client)); |
413 | + } |
414 | + |
415 | + return TRUE; |
416 | +} |
417 | + |
418 | +static gboolean |
419 | +new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) |
420 | +{ |
421 | + GtkMenuItem * gmi; |
422 | + |
423 | + gmi = GTK_MENU_ITEM(gtk_separator_menu_item_new()); |
424 | + |
425 | + base_new_menuitem(newitem, gmi, DBUSMENU_GTKCLIENT(client)); |
426 | + if (parent != NULL) { |
427 | + new_child(parent, newitem, dbusmenu_menuitem_get_position(newitem, parent), DBUSMENU_GTKCLIENT(client)); |
428 | + } |
429 | + |
430 | + return TRUE; |
431 | +} |
432 | + |
433 | +static gboolean |
434 | +new_item_image (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client) |
435 | +{ |
436 | + |
437 | + return TRUE; |
438 | +} |
439 | |
440 | === modified file 'libdbusmenu-gtk/menu.c' |
441 | --- libdbusmenu-gtk/menu.c 2009-06-26 18:40:04 +0000 |
442 | +++ libdbusmenu-gtk/menu.c 2009-08-26 21:24:58 +0000 |
443 | @@ -64,6 +64,7 @@ |
444 | static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec); |
445 | /* Internal */ |
446 | static void build_client (DbusmenuGtkMenu * self); |
447 | +static void child_realized (DbusmenuMenuitem * child, gpointer userdata); |
448 | |
449 | /* GObject Stuff */ |
450 | G_DEFINE_TYPE (DbusmenuGtkMenu, dbusmenu_gtkmenu, GTK_TYPE_MENU); |
451 | @@ -188,9 +189,7 @@ |
452 | root_child_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, DbusmenuGtkMenu * menu) |
453 | { |
454 | g_debug("Root new child"); |
455 | - DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); |
456 | - gtk_menu_shell_insert(GTK_MENU_SHELL(menu), GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)), position); |
457 | - gtk_widget_show(GTK_WIDGET(menu)); |
458 | + g_signal_connect(G_OBJECT(child), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(child_realized), menu); |
459 | return; |
460 | } |
461 | |
462 | @@ -214,6 +213,16 @@ |
463 | } |
464 | |
465 | static void |
466 | +child_realized (DbusmenuMenuitem * child, gpointer userdata) |
467 | +{ |
468 | + DbusmenuGtkMenu * menu = DBUSMENU_GTKMENU(userdata); |
469 | + DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu); |
470 | + |
471 | + gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child))); |
472 | + return; |
473 | +} |
474 | + |
475 | +static void |
476 | root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu) { |
477 | if (newroot == NULL) { |
478 | gtk_widget_hide(GTK_WIDGET(menu)); |
479 | @@ -227,7 +236,8 @@ |
480 | GList * child = NULL; |
481 | guint count = 0; |
482 | for (child = dbusmenu_menuitem_get_children(newroot); child != NULL; child = g_list_next(child)) { |
483 | - gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(client, child->data))); |
484 | + /* gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(client, child->data))); */ |
485 | + g_signal_connect(G_OBJECT(child->data), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(child_realized), menu); |
486 | count++; |
487 | } |
488 | |
489 | |
490 | === modified file 'po/Makefile.in.in' |
491 | --- po/Makefile.in.in 2009-03-25 17:33:11 +0000 |
492 | +++ po/Makefile.in.in 2009-08-20 17:55:36 +0000 |
493 | @@ -56,7 +56,7 @@ |
494 | |
495 | PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) |
496 | |
497 | -USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep '^$$lang$$' $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep '^$$lang$$'`"; then printf "$$lang "; fi; done; fi) |
498 | +USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) |
499 | |
500 | USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) |
501 | |
502 | |
503 | === modified file 'tests/test-gtk-label.json' |
504 | --- tests/test-gtk-label.json 2009-06-17 19:59:57 +0000 |
505 | +++ tests/test-gtk-label.json 2009-08-26 20:32:37 +0000 |
506 | @@ -1,155 +1,155 @@ |
507 | [ |
508 | - {"id": 1, |
509 | + {"id": 1, "type": "menuitem", |
510 | "label": "value1", |
511 | "submenu": [ |
512 | - {"id": 30, |
513 | + {"id": 30, "type": "menuitem", |
514 | "label": "value30"}, |
515 | - {"id": 31, |
516 | + {"id": 31, "type": "menuitem", |
517 | "label": "value31"}, |
518 | - {"id": 32, |
519 | + {"id": 32, "type": "menuitem", |
520 | "label": "value32"}, |
521 | - {"id": 33, |
522 | + {"id": 33, "type": "menuitem", |
523 | "label": "value33"}, |
524 | - {"id": 34, |
525 | + {"id": 34, "type": "menuitem", |
526 | "label": "value34"}, |
527 | - {"id": 35, |
528 | + {"id": 35, "type": "menuitem", |
529 | "label": "value35"}, |
530 | - {"id": 36, |
531 | + {"id": 36, "type": "menuitem", |
532 | "label": "value36"}, |
533 | - {"id": 37, |
534 | + {"id": 37, "type": "menuitem", |
535 | "label": "value37"}, |
536 | - {"id": 38, |
537 | + {"id": 38, "type": "menuitem", |
538 | "label": "value38"}, |
539 | - {"id": 39, |
540 | + {"id": 39, "type": "menuitem", |
541 | "label": "value39"} |
542 | ] |
543 | }, |
544 | - {"id": 2, |
545 | + {"id": 2, "type": "menuitem", |
546 | "label": "value2", |
547 | "submenu": [ |
548 | - {"id": 20, |
549 | + {"id": 20, "type": "menuitem", |
550 | "label": "value20"}, |
551 | - {"id": 21, |
552 | + {"id": 21, "type": "separator", |
553 | "label": "value21"}, |
554 | - {"id": 22, |
555 | + {"id": 22, "type": "menuitem", |
556 | "label": "value22"}, |
557 | - {"id": 23, |
558 | + {"id": 23, "type": "separator", |
559 | "label": "value23"}, |
560 | - {"id": 24, |
561 | + {"id": 24, "type": "menuitem", |
562 | "label": "value24"}, |
563 | - {"id": 25, |
564 | + {"id": 25, "type": "separator", |
565 | "label": "value25"}, |
566 | - {"id": 26, |
567 | + {"id": 26, "type": "menuitem", |
568 | "label": "value26"}, |
569 | - {"id": 27, |
570 | + {"id": 27, "type": "separator", |
571 | "label": "value27"}, |
572 | - {"id": 28, |
573 | + {"id": 28, "type": "menuitem", |
574 | "label": "value28"}, |
575 | - {"id": 29, |
576 | + {"id": 29, "type": "menuitem", "visible": "false", |
577 | "label": "value29"} |
578 | ] |
579 | }, |
580 | - {"id": 3, |
581 | + {"id": 3, "type": "menuitem", |
582 | "label": "a super long label that is really of unreasonable length but we should make sure it makes it across the bus", |
583 | "not.a.value": "A useless value", |
584 | "submenu": [ |
585 | - {"id": 10, |
586 | + {"id": 10, "type": "menuitem", |
587 | "label": "value10"}, |
588 | - {"id": 11, |
589 | + {"id": 11, "type": "menuitem", |
590 | "label": "value11"}, |
591 | - {"id": 12, |
592 | + {"id": 12, "type": "menuitem", |
593 | "label": "value12"}, |
594 | - {"id": 13, |
595 | + {"id": 13, "type": "menuitem", |
596 | "label": "value13"}, |
597 | - {"id": 14, |
598 | + {"id": 14, "type": "menuitem", |
599 | "label": "value14"}, |
600 | - {"id": 15, |
601 | + {"id": 15, "type": "menuitem", |
602 | "label": "value15"}, |
603 | - {"id": 16, |
604 | + {"id": 16, "type": "menuitem", |
605 | "label": "value16"}, |
606 | - {"id": 17, |
607 | + {"id": 17, "type": "menuitem", |
608 | "label": "value17"}, |
609 | - {"id": 18, |
610 | + {"id": 18, "type": "menuitem", |
611 | "label": "value18"}, |
612 | - {"id": 19, |
613 | + {"id": 19, "type": "menuitem", |
614 | "label": "value19"} |
615 | ] |
616 | }, |
617 | - {"id": 4, |
618 | + {"id": 4, "type": "menuitem", |
619 | "label": "value2", |
620 | "submenu": [ |
621 | - {"id": 5, |
622 | + {"id": 5, "type": "menuitem", |
623 | "label": "value5", |
624 | "submenu": [ |
625 | - {"id": 10, |
626 | + {"id": 10, "type": "menuitem", |
627 | "label": "value10"}, |
628 | - {"id": 11, |
629 | + {"id": 11, "type": "menuitem", |
630 | "label": "value11"}, |
631 | - {"id": 12, |
632 | + {"id": 12, "type": "menuitem", |
633 | "label": "value12"}, |
634 | - {"id": 13, |
635 | + {"id": 13, "type": "menuitem", |
636 | "label": "value13"}, |
637 | - {"id": 14, |
638 | + {"id": 14, "type": "menuitem", |
639 | "label": "value14"}, |
640 | - {"id": 15, |
641 | + {"id": 15, "type": "menuitem", |
642 | "label": "value15"}, |
643 | - {"id": 16, |
644 | + {"id": 16, "type": "menuitem", |
645 | "label": "value16"}, |
646 | - {"id": 17, |
647 | + {"id": 17, "type": "menuitem", |
648 | "label": "value17"}, |
649 | - {"id": 18, |
650 | + {"id": 18, "type": "menuitem", |
651 | "label": "value18"}, |
652 | - {"id": 19, |
653 | + {"id": 19, "type": "menuitem", |
654 | "label": "value19"} |
655 | ] |
656 | }, |
657 | - {"id": 6, |
658 | + {"id": 6, "type": "menuitem", |
659 | "label": "value6", |
660 | "submenu": [ |
661 | - {"id": 20, |
662 | + {"id": 20, "type": "menuitem", |
663 | "label": "value20"}, |
664 | - {"id": 21, |
665 | + {"id": 21, "type": "menuitem", |
666 | "label": "value21"}, |
667 | - {"id": 22, |
668 | + {"id": 22, "type": "menuitem", |
669 | "label": "value22"}, |
670 | - {"id": 23, |
671 | + {"id": 23, "type": "menuitem", |
672 | "label": "value23"}, |
673 | - {"id": 24, |
674 | + {"id": 24, "type": "menuitem", |
675 | "label": "value24"}, |
676 | - {"id": 25, |
677 | + {"id": 25, "type": "menuitem", |
678 | "label": "value25"}, |
679 | - {"id": 26, |
680 | + {"id": 26, "type": "menuitem", |
681 | "label": "value26"}, |
682 | - {"id": 27, |
683 | + {"id": 27, "type": "menuitem", |
684 | "label": "value27"}, |
685 | - {"id": 28, |
686 | + {"id": 28, "type": "menuitem", |
687 | "label": "value28"}, |
688 | - {"id": 29, |
689 | + {"id": 29, "type": "menuitem", |
690 | "label": "value29"} |
691 | ] |
692 | }, |
693 | - {"id": 7, |
694 | + {"id": 7, "type": "menuitem", |
695 | "label": "value7", |
696 | "submenu": [ |
697 | - {"id": 30, |
698 | + {"id": 30, "type": "menuitem", |
699 | "label": "value30"}, |
700 | - {"id": 31, |
701 | + {"id": 31, "type": "menuitem", |
702 | "label": "value31"}, |
703 | - {"id": 32, |
704 | + {"id": 32, "type": "menuitem", |
705 | "label": "value32"}, |
706 | - {"id": 33, |
707 | + {"id": 33, "type": "menuitem", |
708 | "label": "value33"}, |
709 | - {"id": 34, |
710 | + {"id": 34, "type": "menuitem", |
711 | "label": "value34"}, |
712 | - {"id": 35, |
713 | + {"id": 35, "type": "menuitem", |
714 | "label": "value35"}, |
715 | - {"id": 36, |
716 | + {"id": 36, "type": "menuitem", |
717 | "label": "value36"}, |
718 | - {"id": 37, |
719 | + {"id": 37, "type": "menuitem", |
720 | "label": "value37"}, |
721 | - {"id": 38, |
722 | + {"id": 38, "type": "menuitem", |
723 | "label": "value38"}, |
724 | - {"id": 39, |
725 | + {"id": 39, "type": "menuitem", |
726 | "label": "value39"} |
727 | ] |
728 | }, |
Adds a simple system for extending the menu items to the point where it can say "I handle these types." Then use this in the gtk version of the library to add separators and a shell for images in the future. Also now we handle visibility.