Merge lp:~ted/libdbusmenu/now-with-parsing into lp:libdbusmenu/0.5
- now-with-parsing
- Merge into trunk
Proposed by
Ted Gould
Status: | Merged |
---|---|
Merged at revision: | 196 |
Proposed branch: | lp:~ted/libdbusmenu/now-with-parsing |
Merge into: | lp:libdbusmenu/0.5 |
Diff against target: |
930 lines (+861/-4) 6 files modified
.bzrignore (+4/-0) libdbusmenu-gtk/Makefile.am (+5/-2) libdbusmenu-gtk/parser.c (+667/-0) libdbusmenu-gtk/parser.h (+37/-0) tests/Makefile.am (+33/-2) tests/test-gtk-parser.c (+115/-0) |
To merge this branch: | bzr merge lp:~ted/libdbusmenu/now-with-parsing |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mikkel Kamstrup Erlandsen (community) | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change
This is the parser taken from appmenu-gtk with some clean ups so that it can work well with libappindicator as well. It is basically a GtkMenu to DbusmenuMenuitem translator.
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
review:
Needs Fixing
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ted Gould (ted) wrote : | # |
On Thu, 2011-01-27 at 08:46 +0000, Mikkel Kamstrup Erlandsen wrote:
> dbusmenu_
> documentation.
r211
> In order to help would/be consumers with debugging you
> should also add a g_return_
> GTK_IS_MENU_SHELL (widget),NULL).
r212
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2010-12-02 20:13:09 +0000 | |||
3 | +++ .bzrignore 2011-01-27 14:52:20 +0000 | |||
4 | @@ -220,3 +220,7 @@ | |||
5 | 220 | libdbusmenu-gtk/DbusmenuGtk-0.4.vapi | 220 | libdbusmenu-gtk/DbusmenuGtk-0.4.vapi |
6 | 221 | libdbusmenu-gtk/dbusmenu-gtk-0.4.pc | 221 | libdbusmenu-gtk/dbusmenu-gtk-0.4.pc |
7 | 222 | libdbusmenu-gtk/dbusmenu-gtk3-0.4.pc | 222 | libdbusmenu-gtk/dbusmenu-gtk3-0.4.pc |
8 | 223 | libdbusmenu-gtk/libdbusmenu_gtk_la-parser.lo | ||
9 | 224 | test-gtk-parser | ||
10 | 225 | test-gtk-parser-test | ||
11 | 226 | test-gtk-parser.xml | ||
12 | 223 | 227 | ||
13 | === modified file 'libdbusmenu-gtk/Makefile.am' | |||
14 | --- libdbusmenu-gtk/Makefile.am 2011-01-21 16:35:55 +0000 | |||
15 | +++ libdbusmenu-gtk/Makefile.am 2011-01-27 14:52:20 +0000 | |||
16 | @@ -23,7 +23,8 @@ | |||
17 | 23 | dbusmenu-gtk.h \ | 23 | dbusmenu-gtk.h \ |
18 | 24 | client.h \ | 24 | client.h \ |
19 | 25 | menu.h \ | 25 | menu.h \ |
21 | 26 | menuitem.h | 26 | menuitem.h \ |
22 | 27 | parser.h | ||
23 | 27 | 28 | ||
24 | 28 | libdbusmenu_gtk_la_SOURCES = \ | 29 | libdbusmenu_gtk_la_SOURCES = \ |
25 | 29 | client.h \ | 30 | client.h \ |
26 | @@ -33,7 +34,9 @@ | |||
27 | 33 | menu.h \ | 34 | menu.h \ |
28 | 34 | menu.c \ | 35 | menu.c \ |
29 | 35 | menuitem.h \ | 36 | menuitem.h \ |
31 | 36 | menuitem.c | 37 | menuitem.c \ |
32 | 38 | parser.h \ | ||
33 | 39 | parser.c | ||
34 | 37 | 40 | ||
35 | 38 | libdbusmenu_gtk_la_LDFLAGS = \ | 41 | libdbusmenu_gtk_la_LDFLAGS = \ |
36 | 39 | -version-info $(LIBDBUSMENU_CURRENT):$(LIBDBUSMENU_REVISION):$(LIBDBUSMENU_AGE) \ | 42 | -version-info $(LIBDBUSMENU_CURRENT):$(LIBDBUSMENU_REVISION):$(LIBDBUSMENU_AGE) \ |
37 | 40 | 43 | ||
38 | === added file 'libdbusmenu-gtk/parser.c' | |||
39 | --- libdbusmenu-gtk/parser.c 1970-01-01 00:00:00 +0000 | |||
40 | +++ libdbusmenu-gtk/parser.c 2011-01-27 14:52:20 +0000 | |||
41 | @@ -0,0 +1,667 @@ | |||
42 | 1 | /* | ||
43 | 2 | Parse to take a set of GTK Menus and turn them into something that can | ||
44 | 3 | be sent over the wire. | ||
45 | 4 | |||
46 | 5 | Copyright 2011 Canonical Ltd. | ||
47 | 6 | |||
48 | 7 | Authors: | ||
49 | 8 | Numerous (check Bazaar) | ||
50 | 9 | |||
51 | 10 | This program is free software: you can redistribute it and/or modify it | ||
52 | 11 | under the terms of either or both of the following licenses: | ||
53 | 12 | |||
54 | 13 | 1) the GNU Lesser General Public License version 3, as published by the | ||
55 | 14 | Free Software Foundation; and/or | ||
56 | 15 | 2) the GNU Lesser General Public License version 2.1, as published by | ||
57 | 16 | the Free Software Foundation. | ||
58 | 17 | |||
59 | 18 | This program is distributed in the hope that it will be useful, but | ||
60 | 19 | WITHOUT ANY WARRANTY; without even the implied warranties of | ||
61 | 20 | MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR | ||
62 | 21 | PURPOSE. See the applicable version of the GNU Lesser General Public | ||
63 | 22 | License for more details. | ||
64 | 23 | |||
65 | 24 | You should have received a copy of both the GNU Lesser General Public | ||
66 | 25 | License version 3 and version 2.1 along with this program. If not, see | ||
67 | 26 | <http://www.gnu.org/licenses/> | ||
68 | 27 | */ | ||
69 | 28 | |||
70 | 29 | #include "parser.h" | ||
71 | 30 | #include "menuitem.h" | ||
72 | 31 | |||
73 | 32 | #define CACHED_MENUITEM "dbusmenu-gtk-parser-cached-item" | ||
74 | 33 | |||
75 | 34 | typedef struct _RecurseContext | ||
76 | 35 | { | ||
77 | 36 | GtkWidget * toplevel; | ||
78 | 37 | DbusmenuMenuitem * parent; | ||
79 | 38 | } RecurseContext; | ||
80 | 39 | |||
81 | 40 | static void parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse); | ||
82 | 41 | static DbusmenuMenuitem * construct_dbusmenu_for_widget (GtkWidget * widget); | ||
83 | 42 | static void accel_changed (GtkWidget * widget, | ||
84 | 43 | gpointer data); | ||
85 | 44 | static gboolean update_stock_item (DbusmenuMenuitem * menuitem, | ||
86 | 45 | GtkWidget * widget); | ||
87 | 46 | static void checkbox_toggled (GtkWidget * widget, | ||
88 | 47 | DbusmenuMenuitem * mi); | ||
89 | 48 | static void update_icon_name (DbusmenuMenuitem * menuitem, | ||
90 | 49 | GtkWidget * widget); | ||
91 | 50 | static GtkWidget * find_menu_label (GtkWidget * widget); | ||
92 | 51 | static void label_notify_cb (GtkWidget * widget, | ||
93 | 52 | GParamSpec * pspec, | ||
94 | 53 | gpointer data); | ||
95 | 54 | static void action_notify_cb (GtkAction * action, | ||
96 | 55 | GParamSpec * pspec, | ||
97 | 56 | gpointer data); | ||
98 | 57 | static void item_activated (DbusmenuMenuitem * item, | ||
99 | 58 | guint timestamp, | ||
100 | 59 | gpointer user_data); | ||
101 | 60 | static gboolean item_about_to_show (DbusmenuMenuitem * item, | ||
102 | 61 | gpointer user_data); | ||
103 | 62 | static void widget_notify_cb (GtkWidget * widget, | ||
104 | 63 | GParamSpec * pspec, | ||
105 | 64 | gpointer data); | ||
106 | 65 | static gboolean should_show_image (GtkImage * image); | ||
107 | 66 | static void menuitem_notify_cb (GtkWidget * widget, | ||
108 | 67 | GParamSpec * pspec, | ||
109 | 68 | gpointer data); | ||
110 | 69 | |||
111 | 70 | /** | ||
112 | 71 | dbusmenu_gtk_parse_menu_structure: | ||
113 | 72 | @widget: A #GtkMenuItem or #GtkMenuShell to turn into a #DbusmenuMenuitem | ||
114 | 73 | |||
115 | 74 | Goes through the GTK structures and turns them into the appropraite | ||
116 | 75 | Dbusmenu structures along with setting up all the relationships | ||
117 | 76 | between the objects. It also stores the dbusmenu items as a cache | ||
118 | 77 | on the GTK items so that they'll be reused if necissary. | ||
119 | 78 | |||
120 | 79 | Return value: A dbusmenu item representing the menu structure | ||
121 | 80 | */ | ||
122 | 81 | DbusmenuMenuitem * | ||
123 | 82 | dbusmenu_gtk_parse_menu_structure (GtkWidget * widget) | ||
124 | 83 | { | ||
125 | 84 | g_return_val_if_fail(GTK_IS_MENU_ITEM(widget) || GTK_IS_MENU_SHELL(widget), NULL); | ||
126 | 85 | |||
127 | 86 | RecurseContext recurse = {0}; | ||
128 | 87 | |||
129 | 88 | recurse.toplevel = gtk_widget_get_toplevel(widget); | ||
130 | 89 | |||
131 | 90 | parse_menu_structure_helper(widget, &recurse); | ||
132 | 91 | |||
133 | 92 | return recurse.parent; | ||
134 | 93 | } | ||
135 | 94 | |||
136 | 95 | /* Called when the dbusmenu item that we're keeping around | ||
137 | 96 | is finalized */ | ||
138 | 97 | static void | ||
139 | 98 | dbusmenu_cache_freed (gpointer data, GObject * obj) | ||
140 | 99 | { | ||
141 | 100 | /* If the dbusmenu item is killed we don't need to remove | ||
142 | 101 | the weak ref as well. */ | ||
143 | 102 | g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM); | ||
144 | 103 | g_signal_handlers_disconnect_by_func(data, G_CALLBACK(widget_notify_cb), obj); | ||
145 | 104 | return; | ||
146 | 105 | } | ||
147 | 106 | |||
148 | 107 | /* Called if we replace the cache on the object with a new | ||
149 | 108 | dbusmenu menuitem */ | ||
150 | 109 | static void | ||
151 | 110 | object_cache_freed (gpointer data) | ||
152 | 111 | { | ||
153 | 112 | if (!G_IS_OBJECT(data)) return; | ||
154 | 113 | g_object_weak_unref(G_OBJECT(data), dbusmenu_cache_freed, data); | ||
155 | 114 | return; | ||
156 | 115 | } | ||
157 | 116 | |||
158 | 117 | static void | ||
159 | 118 | parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse) | ||
160 | 119 | { | ||
161 | 120 | |||
162 | 121 | /* If this is a shell, then let's handle the items in it. */ | ||
163 | 122 | if (GTK_IS_MENU_SHELL (widget)) { | ||
164 | 123 | /* Okay, this is a little janky and all.. but some applications update some | ||
165 | 124 | * menuitem properties such as sensitivity on the activate callback. This | ||
166 | 125 | * seems a little weird, but it's not our place to judge when all this code | ||
167 | 126 | * is so crazy. So we're going to get ever crazier and activate all the | ||
168 | 127 | * menus that are directly below the menubar and force the applications to | ||
169 | 128 | * update their sensitivity. The menus won't actually popup in the app | ||
170 | 129 | * window due to our gtk+ patches. | ||
171 | 130 | * | ||
172 | 131 | * Note that this will not force menuitems in submenus to be updated as well. | ||
173 | 132 | */ | ||
174 | 133 | if (recurse->parent == NULL && GTK_IS_MENU_BAR(widget)) { | ||
175 | 134 | GList *children = gtk_container_get_children (GTK_CONTAINER (widget)); | ||
176 | 135 | |||
177 | 136 | for (; children != NULL; children = children->next) { | ||
178 | 137 | gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget), | ||
179 | 138 | children->data, | ||
180 | 139 | TRUE); | ||
181 | 140 | } | ||
182 | 141 | |||
183 | 142 | g_list_free (children); | ||
184 | 143 | } | ||
185 | 144 | |||
186 | 145 | if (recurse->parent == NULL) { | ||
187 | 146 | recurse->parent = dbusmenu_menuitem_new(); | ||
188 | 147 | } | ||
189 | 148 | |||
190 | 149 | gtk_container_foreach (GTK_CONTAINER (widget), | ||
191 | 150 | (GtkCallback)parse_menu_structure_helper, | ||
192 | 151 | recurse); | ||
193 | 152 | return; | ||
194 | 153 | } | ||
195 | 154 | |||
196 | 155 | if (GTK_IS_MENU_ITEM(widget)) { | ||
197 | 156 | DbusmenuMenuitem * thisitem = NULL; | ||
198 | 157 | |||
199 | 158 | /* Check to see if we're cached already */ | ||
200 | 159 | gpointer pmi = g_object_get_data(G_OBJECT(widget), CACHED_MENUITEM); | ||
201 | 160 | if (pmi != NULL) { | ||
202 | 161 | thisitem = DBUSMENU_MENUITEM(pmi); | ||
203 | 162 | g_object_ref(G_OBJECT(thisitem)); | ||
204 | 163 | } | ||
205 | 164 | |||
206 | 165 | /* We don't have one, so we'll need to build it */ | ||
207 | 166 | if (thisitem == NULL) { | ||
208 | 167 | thisitem = construct_dbusmenu_for_widget (widget); | ||
209 | 168 | g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, thisitem, object_cache_freed); | ||
210 | 169 | g_object_weak_ref(G_OBJECT(thisitem), dbusmenu_cache_freed, widget); | ||
211 | 170 | |||
212 | 171 | if (!gtk_widget_get_visible (widget)) { | ||
213 | 172 | g_signal_connect (G_OBJECT (widget), | ||
214 | 173 | "notify::visible", | ||
215 | 174 | G_CALLBACK (menuitem_notify_cb), | ||
216 | 175 | recurse->toplevel); | ||
217 | 176 | } | ||
218 | 177 | |||
219 | 178 | if (GTK_IS_TEAROFF_MENU_ITEM (widget)) { | ||
220 | 179 | dbusmenu_menuitem_property_set_bool (thisitem, | ||
221 | 180 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
222 | 181 | FALSE); | ||
223 | 182 | } | ||
224 | 183 | } | ||
225 | 184 | |||
226 | 185 | /* Check to see if we're in our parents list of children, if we have | ||
227 | 186 | a parent. */ | ||
228 | 187 | if (recurse->parent != NULL) { | ||
229 | 188 | GList * children = dbusmenu_menuitem_get_children (recurse->parent); | ||
230 | 189 | GList * peek = NULL; | ||
231 | 190 | |||
232 | 191 | if (children != NULL) { | ||
233 | 192 | peek = g_list_find (children, thisitem); | ||
234 | 193 | } | ||
235 | 194 | |||
236 | 195 | /* Oops, let's tell our parents about us */ | ||
237 | 196 | if (peek == NULL) { | ||
238 | 197 | /* TODO: Should we set a weak ref on the parent? */ | ||
239 | 198 | g_object_set_data (G_OBJECT (thisitem), | ||
240 | 199 | "dbusmenu-parent", | ||
241 | 200 | recurse->parent); | ||
242 | 201 | dbusmenu_menuitem_child_append (recurse->parent, | ||
243 | 202 | thisitem); | ||
244 | 203 | } | ||
245 | 204 | } | ||
246 | 205 | |||
247 | 206 | GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)); | ||
248 | 207 | if (menu != NULL) { | ||
249 | 208 | DbusmenuMenuitem * parent_save = recurse->parent; | ||
250 | 209 | recurse->parent = thisitem; | ||
251 | 210 | parse_menu_structure_helper (menu, recurse); | ||
252 | 211 | recurse->parent = parent_save; | ||
253 | 212 | } | ||
254 | 213 | |||
255 | 214 | if (recurse->parent == NULL) { | ||
256 | 215 | recurse->parent = thisitem; | ||
257 | 216 | } else { | ||
258 | 217 | g_object_unref(thisitem); | ||
259 | 218 | } | ||
260 | 219 | } | ||
261 | 220 | |||
262 | 221 | return; | ||
263 | 222 | } | ||
264 | 223 | |||
265 | 224 | static DbusmenuMenuitem * | ||
266 | 225 | construct_dbusmenu_for_widget (GtkWidget * widget) | ||
267 | 226 | { | ||
268 | 227 | DbusmenuMenuitem *mi = dbusmenu_menuitem_new (); | ||
269 | 228 | |||
270 | 229 | if (GTK_IS_MENU_ITEM (widget)) | ||
271 | 230 | { | ||
272 | 231 | gboolean visible = FALSE; | ||
273 | 232 | gboolean sensitive = FALSE; | ||
274 | 233 | if (GTK_IS_SEPARATOR_MENU_ITEM (widget)) | ||
275 | 234 | { | ||
276 | 235 | dbusmenu_menuitem_property_set (mi, | ||
277 | 236 | "type", | ||
278 | 237 | "separator"); | ||
279 | 238 | |||
280 | 239 | visible = gtk_widget_get_visible (widget); | ||
281 | 240 | sensitive = gtk_widget_get_sensitive (widget); | ||
282 | 241 | } | ||
283 | 242 | else | ||
284 | 243 | { | ||
285 | 244 | gboolean label_set = FALSE; | ||
286 | 245 | |||
287 | 246 | g_signal_connect (widget, | ||
288 | 247 | "accel-closures-changed", | ||
289 | 248 | G_CALLBACK (accel_changed), | ||
290 | 249 | mi); | ||
291 | 250 | |||
292 | 251 | if (GTK_IS_CHECK_MENU_ITEM (widget)) | ||
293 | 252 | { | ||
294 | 253 | dbusmenu_menuitem_property_set (mi, | ||
295 | 254 | DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, | ||
296 | 255 | gtk_check_menu_item_get_draw_as_radio (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK); | ||
297 | 256 | |||
298 | 257 | dbusmenu_menuitem_property_set_int (mi, | ||
299 | 258 | DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, | ||
300 | 259 | gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); | ||
301 | 260 | |||
302 | 261 | g_signal_connect (widget, | ||
303 | 262 | "activate", | ||
304 | 263 | G_CALLBACK (checkbox_toggled), | ||
305 | 264 | mi); | ||
306 | 265 | } | ||
307 | 266 | |||
308 | 267 | if (GTK_IS_IMAGE_MENU_ITEM (widget)) | ||
309 | 268 | { | ||
310 | 269 | GtkWidget *image; | ||
311 | 270 | GtkImageType image_type; | ||
312 | 271 | |||
313 | 272 | image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget)); | ||
314 | 273 | |||
315 | 274 | if (GTK_IS_IMAGE (image)) | ||
316 | 275 | { | ||
317 | 276 | image_type = gtk_image_get_storage_type (GTK_IMAGE (image)); | ||
318 | 277 | |||
319 | 278 | if (image_type == GTK_IMAGE_STOCK) | ||
320 | 279 | { | ||
321 | 280 | label_set = update_stock_item (mi, image); | ||
322 | 281 | } | ||
323 | 282 | else if (image_type == GTK_IMAGE_ICON_NAME) | ||
324 | 283 | { | ||
325 | 284 | update_icon_name (mi, image); | ||
326 | 285 | } | ||
327 | 286 | else if (image_type == GTK_IMAGE_PIXBUF) | ||
328 | 287 | { | ||
329 | 288 | dbusmenu_menuitem_property_set_image (mi, | ||
330 | 289 | DBUSMENU_MENUITEM_PROP_ICON_DATA, | ||
331 | 290 | gtk_image_get_pixbuf (GTK_IMAGE (image))); | ||
332 | 291 | } | ||
333 | 292 | } | ||
334 | 293 | } | ||
335 | 294 | |||
336 | 295 | GtkWidget *label = find_menu_label (widget); | ||
337 | 296 | |||
338 | 297 | dbusmenu_menuitem_property_set (mi, | ||
339 | 298 | "label", | ||
340 | 299 | label ? gtk_label_get_text (GTK_LABEL (label)) : NULL); | ||
341 | 300 | |||
342 | 301 | if (label) | ||
343 | 302 | { | ||
344 | 303 | // Sometimes, an app will directly find and modify the label | ||
345 | 304 | // (like empathy), so watch the label especially for that. | ||
346 | 305 | g_signal_connect (G_OBJECT (label), | ||
347 | 306 | "notify", | ||
348 | 307 | G_CALLBACK (label_notify_cb), | ||
349 | 308 | mi); | ||
350 | 309 | } | ||
351 | 310 | |||
352 | 311 | if (GTK_IS_ACTIVATABLE (widget)) | ||
353 | 312 | { | ||
354 | 313 | GtkActivatable *activatable = GTK_ACTIVATABLE (widget); | ||
355 | 314 | |||
356 | 315 | if (gtk_activatable_get_use_action_appearance (activatable)) | ||
357 | 316 | { | ||
358 | 317 | GtkAction *action = gtk_activatable_get_related_action (activatable); | ||
359 | 318 | |||
360 | 319 | if (action) | ||
361 | 320 | { | ||
362 | 321 | visible = gtk_action_is_visible (action); | ||
363 | 322 | sensitive = gtk_action_is_sensitive (action); | ||
364 | 323 | |||
365 | 324 | g_signal_connect_object (action, "notify", | ||
366 | 325 | G_CALLBACK (action_notify_cb), | ||
367 | 326 | mi, | ||
368 | 327 | G_CONNECT_AFTER); | ||
369 | 328 | } | ||
370 | 329 | } | ||
371 | 330 | } | ||
372 | 331 | |||
373 | 332 | if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget)) | ||
374 | 333 | { | ||
375 | 334 | visible = gtk_widget_get_visible (widget); | ||
376 | 335 | sensitive = gtk_widget_get_sensitive (widget); | ||
377 | 336 | } | ||
378 | 337 | |||
379 | 338 | dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget)); | ||
380 | 339 | |||
381 | 340 | g_signal_connect (G_OBJECT (mi), | ||
382 | 341 | DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, | ||
383 | 342 | G_CALLBACK (item_activated), | ||
384 | 343 | widget); | ||
385 | 344 | |||
386 | 345 | g_signal_connect (G_OBJECT (mi), | ||
387 | 346 | DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW, | ||
388 | 347 | G_CALLBACK (item_about_to_show), | ||
389 | 348 | widget); | ||
390 | 349 | } | ||
391 | 350 | |||
392 | 351 | dbusmenu_menuitem_property_set_bool (mi, | ||
393 | 352 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
394 | 353 | visible); | ||
395 | 354 | |||
396 | 355 | dbusmenu_menuitem_property_set_bool (mi, | ||
397 | 356 | DBUSMENU_MENUITEM_PROP_ENABLED, | ||
398 | 357 | sensitive); | ||
399 | 358 | |||
400 | 359 | g_signal_connect (widget, | ||
401 | 360 | "notify", | ||
402 | 361 | G_CALLBACK (widget_notify_cb), | ||
403 | 362 | mi); | ||
404 | 363 | } | ||
405 | 364 | |||
406 | 365 | return mi; | ||
407 | 366 | |||
408 | 367 | return NULL; | ||
409 | 368 | } | ||
410 | 369 | |||
411 | 370 | static void | ||
412 | 371 | menuitem_notify_cb (GtkWidget *widget, | ||
413 | 372 | GParamSpec *pspec, | ||
414 | 373 | gpointer data) | ||
415 | 374 | { | ||
416 | 375 | if (pspec->name == g_intern_static_string ("visible")) | ||
417 | 376 | { | ||
418 | 377 | GtkWidget * new_toplevel = gtk_widget_get_toplevel (widget); | ||
419 | 378 | GtkWidget * old_toplevel = GTK_WIDGET(data); | ||
420 | 379 | |||
421 | 380 | if (new_toplevel == old_toplevel) { | ||
422 | 381 | /* TODO: Figure this out -> rebuild (context->bridge, window); */ | ||
423 | 382 | } | ||
424 | 383 | |||
425 | 384 | /* We only care about this once, so let's disconnect now. */ | ||
426 | 385 | g_signal_handlers_disconnect_by_func (widget, | ||
427 | 386 | G_CALLBACK (menuitem_notify_cb), | ||
428 | 387 | data); | ||
429 | 388 | } | ||
430 | 389 | } | ||
431 | 390 | |||
432 | 391 | static void | ||
433 | 392 | accel_changed (GtkWidget *widget, | ||
434 | 393 | gpointer data) | ||
435 | 394 | { | ||
436 | 395 | DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data; | ||
437 | 396 | dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget)); | ||
438 | 397 | } | ||
439 | 398 | |||
440 | 399 | static gboolean | ||
441 | 400 | update_stock_item (DbusmenuMenuitem *menuitem, | ||
442 | 401 | GtkWidget *widget) | ||
443 | 402 | { | ||
444 | 403 | GtkStockItem stock; | ||
445 | 404 | GtkImage *image; | ||
446 | 405 | |||
447 | 406 | g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE); | ||
448 | 407 | |||
449 | 408 | image = GTK_IMAGE (widget); | ||
450 | 409 | |||
451 | 410 | if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK) | ||
452 | 411 | return FALSE; | ||
453 | 412 | |||
454 | 413 | gchar * stock_id = NULL; | ||
455 | 414 | gtk_image_get_stock(image, &stock_id, NULL); | ||
456 | 415 | |||
457 | 416 | gtk_stock_lookup (stock_id, &stock); | ||
458 | 417 | |||
459 | 418 | if (should_show_image (image)) | ||
460 | 419 | dbusmenu_menuitem_property_set (menuitem, | ||
461 | 420 | DBUSMENU_MENUITEM_PROP_ICON_NAME, | ||
462 | 421 | stock_id); | ||
463 | 422 | else | ||
464 | 423 | dbusmenu_menuitem_property_remove (menuitem, | ||
465 | 424 | DBUSMENU_MENUITEM_PROP_ICON_NAME); | ||
466 | 425 | |||
467 | 426 | const gchar *label = dbusmenu_menuitem_property_get (menuitem, | ||
468 | 427 | DBUSMENU_MENUITEM_PROP_LABEL); | ||
469 | 428 | |||
470 | 429 | if (stock.label != NULL && label != NULL) | ||
471 | 430 | { | ||
472 | 431 | dbusmenu_menuitem_property_set (menuitem, | ||
473 | 432 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
474 | 433 | stock.label); | ||
475 | 434 | |||
476 | 435 | return TRUE; | ||
477 | 436 | } | ||
478 | 437 | |||
479 | 438 | return FALSE; | ||
480 | 439 | } | ||
481 | 440 | |||
482 | 441 | static void | ||
483 | 442 | checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi) | ||
484 | 443 | { | ||
485 | 444 | dbusmenu_menuitem_property_set_int (mi, | ||
486 | 445 | DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, | ||
487 | 446 | gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); | ||
488 | 447 | } | ||
489 | 448 | |||
490 | 449 | static void | ||
491 | 450 | update_icon_name (DbusmenuMenuitem *menuitem, | ||
492 | 451 | GtkWidget *widget) | ||
493 | 452 | { | ||
494 | 453 | GtkImage *image; | ||
495 | 454 | |||
496 | 455 | g_return_if_fail (GTK_IS_IMAGE (widget)); | ||
497 | 456 | |||
498 | 457 | image = GTK_IMAGE (widget); | ||
499 | 458 | |||
500 | 459 | if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME) | ||
501 | 460 | return; | ||
502 | 461 | |||
503 | 462 | if (should_show_image (image)) { | ||
504 | 463 | const gchar * icon_name = NULL; | ||
505 | 464 | gtk_image_get_icon_name(image, &icon_name, NULL); | ||
506 | 465 | dbusmenu_menuitem_property_set (menuitem, | ||
507 | 466 | DBUSMENU_MENUITEM_PROP_ICON_NAME, | ||
508 | 467 | icon_name); | ||
509 | 468 | } else { | ||
510 | 469 | dbusmenu_menuitem_property_remove (menuitem, | ||
511 | 470 | DBUSMENU_MENUITEM_PROP_ICON_NAME); | ||
512 | 471 | } | ||
513 | 472 | } | ||
514 | 473 | |||
515 | 474 | static GtkWidget * | ||
516 | 475 | find_menu_label (GtkWidget *widget) | ||
517 | 476 | { | ||
518 | 477 | GtkWidget *label = NULL; | ||
519 | 478 | |||
520 | 479 | if (GTK_IS_LABEL (widget)) | ||
521 | 480 | return widget; | ||
522 | 481 | |||
523 | 482 | if (GTK_IS_CONTAINER (widget)) | ||
524 | 483 | { | ||
525 | 484 | GList *children; | ||
526 | 485 | GList *l; | ||
527 | 486 | |||
528 | 487 | children = gtk_container_get_children (GTK_CONTAINER (widget)); | ||
529 | 488 | |||
530 | 489 | for (l = children; l; l = l->next) | ||
531 | 490 | { | ||
532 | 491 | label = find_menu_label (l->data); | ||
533 | 492 | |||
534 | 493 | if (label) | ||
535 | 494 | break; | ||
536 | 495 | } | ||
537 | 496 | |||
538 | 497 | g_list_free (children); | ||
539 | 498 | } | ||
540 | 499 | |||
541 | 500 | return label; | ||
542 | 501 | } | ||
543 | 502 | |||
544 | 503 | static void | ||
545 | 504 | label_notify_cb (GtkWidget *widget, | ||
546 | 505 | GParamSpec *pspec, | ||
547 | 506 | gpointer data) | ||
548 | 507 | { | ||
549 | 508 | DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; | ||
550 | 509 | |||
551 | 510 | if (pspec->name == g_intern_static_string ("label")) | ||
552 | 511 | { | ||
553 | 512 | dbusmenu_menuitem_property_set (child, | ||
554 | 513 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
555 | 514 | gtk_label_get_text (GTK_LABEL (widget))); | ||
556 | 515 | } | ||
557 | 516 | } | ||
558 | 517 | |||
559 | 518 | static void | ||
560 | 519 | action_notify_cb (GtkAction *action, | ||
561 | 520 | GParamSpec *pspec, | ||
562 | 521 | gpointer data) | ||
563 | 522 | { | ||
564 | 523 | DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data; | ||
565 | 524 | |||
566 | 525 | if (pspec->name == g_intern_static_string ("sensitive")) | ||
567 | 526 | { | ||
568 | 527 | dbusmenu_menuitem_property_set_bool (mi, | ||
569 | 528 | DBUSMENU_MENUITEM_PROP_ENABLED, | ||
570 | 529 | gtk_action_is_sensitive (action)); | ||
571 | 530 | } | ||
572 | 531 | else if (pspec->name == g_intern_static_string ("visible")) | ||
573 | 532 | { | ||
574 | 533 | dbusmenu_menuitem_property_set_bool (mi, | ||
575 | 534 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
576 | 535 | gtk_action_is_visible (action)); | ||
577 | 536 | } | ||
578 | 537 | else if (pspec->name == g_intern_static_string ("active")) | ||
579 | 538 | { | ||
580 | 539 | dbusmenu_menuitem_property_set_int (mi, | ||
581 | 540 | DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, | ||
582 | 541 | gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED); | ||
583 | 542 | } | ||
584 | 543 | else if (pspec->name == g_intern_static_string ("label")) | ||
585 | 544 | { | ||
586 | 545 | dbusmenu_menuitem_property_set (mi, | ||
587 | 546 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
588 | 547 | gtk_action_get_label (action)); | ||
589 | 548 | } | ||
590 | 549 | } | ||
591 | 550 | |||
592 | 551 | static void | ||
593 | 552 | item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data) | ||
594 | 553 | { | ||
595 | 554 | GtkWidget *child; | ||
596 | 555 | |||
597 | 556 | if (user_data != NULL) | ||
598 | 557 | { | ||
599 | 558 | child = (GtkWidget *)user_data; | ||
600 | 559 | |||
601 | 560 | if (GTK_IS_MENU_ITEM (child)) | ||
602 | 561 | { | ||
603 | 562 | gtk_menu_item_activate (GTK_MENU_ITEM (child)); | ||
604 | 563 | } | ||
605 | 564 | } | ||
606 | 565 | } | ||
607 | 566 | |||
608 | 567 | static gboolean | ||
609 | 568 | item_about_to_show (DbusmenuMenuitem *item, gpointer user_data) | ||
610 | 569 | { | ||
611 | 570 | GtkWidget *child; | ||
612 | 571 | |||
613 | 572 | if (user_data != NULL) | ||
614 | 573 | { | ||
615 | 574 | child = (GtkWidget *)user_data; | ||
616 | 575 | |||
617 | 576 | if (GTK_IS_MENU_ITEM (child)) | ||
618 | 577 | { | ||
619 | 578 | // Only called for items with submens. So we activate it here in | ||
620 | 579 | // case the program dynamically creates menus (like empathy does) | ||
621 | 580 | gtk_menu_item_activate (GTK_MENU_ITEM (child)); | ||
622 | 581 | } | ||
623 | 582 | } | ||
624 | 583 | |||
625 | 584 | return TRUE; | ||
626 | 585 | } | ||
627 | 586 | |||
628 | 587 | static void | ||
629 | 588 | widget_notify_cb (GtkWidget *widget, | ||
630 | 589 | GParamSpec *pspec, | ||
631 | 590 | gpointer data) | ||
632 | 591 | { | ||
633 | 592 | DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; | ||
634 | 593 | |||
635 | 594 | if (pspec->name == g_intern_static_string ("sensitive")) | ||
636 | 595 | { | ||
637 | 596 | dbusmenu_menuitem_property_set_bool (child, | ||
638 | 597 | DBUSMENU_MENUITEM_PROP_ENABLED, | ||
639 | 598 | gtk_widget_get_sensitive (widget)); | ||
640 | 599 | } | ||
641 | 600 | else if (pspec->name == g_intern_static_string ("label")) | ||
642 | 601 | { | ||
643 | 602 | dbusmenu_menuitem_property_set (child, | ||
644 | 603 | DBUSMENU_MENUITEM_PROP_LABEL, | ||
645 | 604 | gtk_menu_item_get_label (GTK_MENU_ITEM (widget))); | ||
646 | 605 | } | ||
647 | 606 | else if (pspec->name == g_intern_static_string ("visible")) | ||
648 | 607 | { | ||
649 | 608 | dbusmenu_menuitem_property_set_bool (child, | ||
650 | 609 | DBUSMENU_MENUITEM_PROP_VISIBLE, | ||
651 | 610 | gtk_widget_get_visible (widget)); | ||
652 | 611 | } | ||
653 | 612 | else if (pspec->name == g_intern_static_string ("stock")) | ||
654 | 613 | { | ||
655 | 614 | update_stock_item (child, widget); | ||
656 | 615 | } | ||
657 | 616 | else if (pspec->name == g_intern_static_string ("icon-name")) | ||
658 | 617 | { | ||
659 | 618 | update_icon_name (child, widget); | ||
660 | 619 | } | ||
661 | 620 | else if (pspec->name == g_intern_static_string ("parent")) | ||
662 | 621 | { | ||
663 | 622 | /* | ||
664 | 623 | * We probably should have added a 'remove' method to the | ||
665 | 624 | * UbuntuMenuProxy early on, but it's late in the cycle now. | ||
666 | 625 | */ | ||
667 | 626 | if (gtk_widget_get_parent (widget) == NULL) | ||
668 | 627 | { | ||
669 | 628 | g_signal_handlers_disconnect_by_func (widget, | ||
670 | 629 | G_CALLBACK (widget_notify_cb), | ||
671 | 630 | child); | ||
672 | 631 | |||
673 | 632 | DbusmenuMenuitem *parent = g_object_get_data (G_OBJECT (child), "dbusmenu-parent"); | ||
674 | 633 | |||
675 | 634 | if (DBUSMENU_IS_MENUITEM (parent) && DBUSMENU_IS_MENUITEM (child)) | ||
676 | 635 | { | ||
677 | 636 | dbusmenu_menuitem_child_delete (parent, child); | ||
678 | 637 | } | ||
679 | 638 | } | ||
680 | 639 | } | ||
681 | 640 | } | ||
682 | 641 | |||
683 | 642 | static gboolean | ||
684 | 643 | should_show_image (GtkImage *image) | ||
685 | 644 | { | ||
686 | 645 | GtkWidget *item; | ||
687 | 646 | |||
688 | 647 | item = gtk_widget_get_ancestor (GTK_WIDGET (image), | ||
689 | 648 | GTK_TYPE_IMAGE_MENU_ITEM); | ||
690 | 649 | |||
691 | 650 | if (item) | ||
692 | 651 | { | ||
693 | 652 | GtkSettings *settings; | ||
694 | 653 | gboolean gtk_menu_images; | ||
695 | 654 | |||
696 | 655 | settings = gtk_widget_get_settings (item); | ||
697 | 656 | |||
698 | 657 | g_object_get (settings, "gtk-menu-images", >k_menu_images, NULL); | ||
699 | 658 | |||
700 | 659 | if (gtk_menu_images) | ||
701 | 660 | return TRUE; | ||
702 | 661 | |||
703 | 662 | return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item)); | ||
704 | 663 | } | ||
705 | 664 | |||
706 | 665 | return FALSE; | ||
707 | 666 | } | ||
708 | 667 | |||
709 | 0 | 668 | ||
710 | === added file 'libdbusmenu-gtk/parser.h' | |||
711 | --- libdbusmenu-gtk/parser.h 1970-01-01 00:00:00 +0000 | |||
712 | +++ libdbusmenu-gtk/parser.h 2011-01-27 14:52:20 +0000 | |||
713 | @@ -0,0 +1,37 @@ | |||
714 | 1 | /* | ||
715 | 2 | Parse to take a set of GTK Menus and turn them into something that can | ||
716 | 3 | be sent over the wire. | ||
717 | 4 | |||
718 | 5 | Copyright 2011 Canonical Ltd. | ||
719 | 6 | |||
720 | 7 | Authors: | ||
721 | 8 | Ted Gould <ted@canonical.com> | ||
722 | 9 | |||
723 | 10 | This program is free software: you can redistribute it and/or modify it | ||
724 | 11 | under the terms of either or both of the following licenses: | ||
725 | 12 | |||
726 | 13 | 1) the GNU Lesser General Public License version 3, as published by the | ||
727 | 14 | Free Software Foundation; and/or | ||
728 | 15 | 2) the GNU Lesser General Public License version 2.1, as published by | ||
729 | 16 | the Free Software Foundation. | ||
730 | 17 | |||
731 | 18 | This program is distributed in the hope that it will be useful, but | ||
732 | 19 | WITHOUT ANY WARRANTY; without even the implied warranties of | ||
733 | 20 | MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR | ||
734 | 21 | PURPOSE. See the applicable version of the GNU Lesser General Public | ||
735 | 22 | License for more details. | ||
736 | 23 | |||
737 | 24 | You should have received a copy of both the GNU Lesser General Public | ||
738 | 25 | License version 3 and version 2.1 along with this program. If not, see | ||
739 | 26 | <http://www.gnu.org/licenses/> | ||
740 | 27 | */ | ||
741 | 28 | |||
742 | 29 | #ifndef DBUSMENU_GTK_PARSER_H__ | ||
743 | 30 | #define DBUSMENU_GTK_PARSER_H__ | ||
744 | 31 | |||
745 | 32 | #include <libdbusmenu-glib/menuitem.h> | ||
746 | 33 | #include <gtk/gtk.h> | ||
747 | 34 | |||
748 | 35 | DbusmenuMenuitem * dbusmenu_gtk_parse_menu_structure (GtkWidget * widget); | ||
749 | 36 | |||
750 | 37 | #endif /* DBUSMENU_GTK_PARSER_H__ */ | ||
751 | 0 | 38 | ||
752 | === modified file 'tests/Makefile.am' | |||
753 | --- tests/Makefile.am 2010-12-08 03:17:43 +0000 | |||
754 | +++ tests/Makefile.am 2011-01-27 14:52:20 +0000 | |||
755 | @@ -16,7 +16,8 @@ | |||
756 | 16 | test-gtk-label \ | 16 | test-gtk-label \ |
757 | 17 | test-gtk-shortcut \ | 17 | test-gtk-shortcut \ |
758 | 18 | test-gtk-reorder \ | 18 | test-gtk-reorder \ |
760 | 19 | test-gtk-submenu | 19 | test-gtk-submenu \ |
761 | 20 | test-gtk-parser-test | ||
762 | 20 | 21 | ||
763 | 21 | check_PROGRAMS = \ | 22 | check_PROGRAMS = \ |
764 | 22 | glib-server-nomenu \ | 23 | glib-server-nomenu \ |
765 | @@ -42,7 +43,8 @@ | |||
766 | 42 | test-json-client \ | 43 | test-json-client \ |
767 | 43 | test-json-server \ | 44 | test-json-server \ |
768 | 44 | test-gtk-submenu-server \ | 45 | test-gtk-submenu-server \ |
770 | 45 | test-gtk-submenu-client | 46 | test-gtk-submenu-client \ |
771 | 47 | test-gtk-parser | ||
772 | 46 | 48 | ||
773 | 47 | XVFB_RUN=". $(srcdir)/run-xvfb.sh" | 49 | XVFB_RUN=". $(srcdir)/run-xvfb.sh" |
774 | 48 | 50 | ||
775 | @@ -384,6 +386,35 @@ | |||
776 | 384 | $(DBUSMENUGLIB_LIBS) \ | 386 | $(DBUSMENUGLIB_LIBS) \ |
777 | 385 | $(DBUSMENUGTK_LIBS) | 387 | $(DBUSMENUGTK_LIBS) |
778 | 386 | 388 | ||
779 | 389 | ###################### | ||
780 | 390 | # Test GTK Parser | ||
781 | 391 | ###################### | ||
782 | 392 | |||
783 | 393 | GTK_PARSER_XML_REPORT = test-gtk-parser.xml | ||
784 | 394 | |||
785 | 395 | test-gtk-parser-test: test-gtk-parser Makefile.am | ||
786 | 396 | @echo "#!/bin/bash" > $@ | ||
787 | 397 | @echo $(XVFB_RUN) >> $@ | ||
788 | 398 | @echo gtester --verbose -k -o $(GTK_PARSER_XML_REPORT) ./test-gtk-parser >> $@ | ||
789 | 399 | @chmod +x $@ | ||
790 | 400 | |||
791 | 401 | test_gtk_parser_SOURCES = \ | ||
792 | 402 | test-gtk-parser.c | ||
793 | 403 | |||
794 | 404 | test_gtk_parser_CFLAGS = \ | ||
795 | 405 | -I $(srcdir)/.. \ | ||
796 | 406 | $(DBUSMENUGLIB_CFLAGS) \ | ||
797 | 407 | $(DBUSMENUGTK_CFLAGS) \ | ||
798 | 408 | -DSRCDIR="\"$(srcdir)\"" \ | ||
799 | 409 | -Wall -Werror | ||
800 | 410 | |||
801 | 411 | test_gtk_parser_LDADD = \ | ||
802 | 412 | ../libdbusmenu-glib/libdbusmenu-glib.la \ | ||
803 | 413 | ../libdbusmenu-gtk/libdbusmenu-gtk.la \ | ||
804 | 414 | $(DBUSMENUGLIB_LIBS) \ | ||
805 | 415 | $(DBUSMENUGTK_LIBS) | ||
806 | 416 | |||
807 | 417 | |||
808 | 387 | ######################### | 418 | ######################### |
809 | 388 | # Test GTK Label | 419 | # Test GTK Label |
810 | 389 | ######################### | 420 | ######################### |
811 | 390 | 421 | ||
812 | === added file 'tests/test-gtk-parser.c' | |||
813 | --- tests/test-gtk-parser.c 1970-01-01 00:00:00 +0000 | |||
814 | +++ tests/test-gtk-parser.c 2011-01-27 14:52:20 +0000 | |||
815 | @@ -0,0 +1,115 @@ | |||
816 | 1 | /* | ||
817 | 2 | Testing for the various objects just by themselves. | ||
818 | 3 | |||
819 | 4 | Copyright 2011 Canonical Ltd. | ||
820 | 5 | |||
821 | 6 | Authors: | ||
822 | 7 | Ted Gould <ted@canonical.com> | ||
823 | 8 | |||
824 | 9 | This program is free software: you can redistribute it and/or modify it | ||
825 | 10 | under the terms of the GNU General Public License version 3, as published | ||
826 | 11 | by the Free Software Foundation. | ||
827 | 12 | |||
828 | 13 | This program is distributed in the hope that it will be useful, but | ||
829 | 14 | WITHOUT ANY WARRANTY; without even the implied warranties of | ||
830 | 15 | MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
831 | 16 | PURPOSE. See the GNU General Public License for more details. | ||
832 | 17 | |||
833 | 18 | You should have received a copy of the GNU General Public License along | ||
834 | 19 | with this program. If not, see <http://www.gnu.org/licenses/>. | ||
835 | 20 | */ | ||
836 | 21 | |||
837 | 22 | #include <libdbusmenu-glib/menuitem-private.h> | ||
838 | 23 | #include <libdbusmenu-gtk/parser.h> | ||
839 | 24 | |||
840 | 25 | /* Just makes sure we can connect here people */ | ||
841 | 26 | static void | ||
842 | 27 | test_parser_runs (void) | ||
843 | 28 | { | ||
844 | 29 | GtkWidget * gmi = gtk_menu_item_new_with_label("Test Item"); | ||
845 | 30 | g_assert(gmi != NULL); | ||
846 | 31 | DbusmenuMenuitem * mi = dbusmenu_gtk_parse_menu_structure(gmi); | ||
847 | 32 | g_assert(mi != NULL); | ||
848 | 33 | |||
849 | 34 | g_object_unref(gmi); | ||
850 | 35 | g_object_unref(mi); | ||
851 | 36 | |||
852 | 37 | return; | ||
853 | 38 | } | ||
854 | 39 | |||
855 | 40 | const gchar * test_parser_children_builder = | ||
856 | 41 | "<?xml version=\"1.0\"?>" | ||
857 | 42 | "<interface>" | ||
858 | 43 | "<requires lib=\"gtk+\" version=\"2.16\"/>" | ||
859 | 44 | /* Start menu bar */ | ||
860 | 45 | "<object class=\"GtkMenuBar\" id=\"menubar\"><property name=\"visible\">True</property>" | ||
861 | 46 | /* Child 1 */ | ||
862 | 47 | "<child><object class=\"GtkMenuItem\" id=\"child_one\"><property name=\"visible\">True</property><property name=\"label\">Child One</property></object></child>" | ||
863 | 48 | /* Child 2 */ | ||
864 | 49 | "<child><object class=\"GtkMenuItem\" id=\"child_two\"><property name=\"visible\">True</property><property name=\"label\">Child Two</property></object></child>" | ||
865 | 50 | /* Child 3 */ | ||
866 | 51 | "<child><object class=\"GtkMenuItem\" id=\"child_three\"><property name=\"visible\">True</property><property name=\"label\">Child Three</property></object></child>" | ||
867 | 52 | /* Child 4 */ | ||
868 | 53 | "<child><object class=\"GtkMenuItem\" id=\"child_four\"><property name=\"visible\">True</property><property name=\"label\">Child Four</property></object></child>" | ||
869 | 54 | /* Stop menubar */ | ||
870 | 55 | "</object>" | ||
871 | 56 | "</interface>"; | ||
872 | 57 | |||
873 | 58 | /* Ensure the parser can find children */ | ||
874 | 59 | static void | ||
875 | 60 | test_parser_children (void) { | ||
876 | 61 | GtkBuilder * builder = gtk_builder_new(); | ||
877 | 62 | g_assert(builder != NULL); | ||
878 | 63 | |||
879 | 64 | GError * error = NULL; | ||
880 | 65 | gtk_builder_add_from_string(builder, test_parser_children_builder, -1, &error); | ||
881 | 66 | if (error != NULL) { | ||
882 | 67 | g_error("Unable to parse UI definition: %s", error->message); | ||
883 | 68 | g_error_free(error); | ||
884 | 69 | error = NULL; | ||
885 | 70 | } | ||
886 | 71 | |||
887 | 72 | GtkWidget * menu = GTK_WIDGET(gtk_builder_get_object(builder, "menubar")); | ||
888 | 73 | g_assert(menu != NULL); | ||
889 | 74 | |||
890 | 75 | DbusmenuMenuitem * mi = dbusmenu_gtk_parse_menu_structure(menu); | ||
891 | 76 | g_assert(mi != NULL); | ||
892 | 77 | |||
893 | 78 | /* | ||
894 | 79 | GPtrArray * xmlarray = g_ptr_array_new(); | ||
895 | 80 | dbusmenu_menuitem_buildxml(mi, xmlarray); | ||
896 | 81 | g_debug("XML: %s", g_strjoinv("", (gchar **)xmlarray->pdata)); | ||
897 | 82 | */ | ||
898 | 83 | |||
899 | 84 | GList * children = dbusmenu_menuitem_get_children(mi); | ||
900 | 85 | g_assert(children != NULL); | ||
901 | 86 | |||
902 | 87 | g_assert(g_list_length(children) == 4); | ||
903 | 88 | |||
904 | 89 | g_object_unref(mi); | ||
905 | 90 | g_object_unref(menu); | ||
906 | 91 | |||
907 | 92 | return; | ||
908 | 93 | } | ||
909 | 94 | |||
910 | 95 | /* Build the test suite */ | ||
911 | 96 | static void | ||
912 | 97 | test_gtk_parser_suite (void) | ||
913 | 98 | { | ||
914 | 99 | g_test_add_func ("/dbusmenu/gtk/parser/base", test_parser_runs); | ||
915 | 100 | g_test_add_func ("/dbusmenu/gtk/parser/children", test_parser_children); | ||
916 | 101 | return; | ||
917 | 102 | } | ||
918 | 103 | |||
919 | 104 | gint | ||
920 | 105 | main (gint argc, gchar * argv[]) | ||
921 | 106 | { | ||
922 | 107 | gtk_init(&argc, &argv); | ||
923 | 108 | g_test_init(&argc, &argv, NULL); | ||
924 | 109 | |||
925 | 110 | /* Test suites */ | ||
926 | 111 | test_gtk_parser_suite(); | ||
927 | 112 | |||
928 | 113 | |||
929 | 114 | return g_test_run (); | ||
930 | 115 | } |
review needsfixing
Just two minor things; dbusmenu_ gtk_parse_ menu_structure( ) needs val_if_ fail(GTK_ IS_MENU_ ITEM(widget) ||
documentation. In order to help would/be consumers with debugging you
should also add a g_return_
GTK_IS_MENU_SHELL (widget),NULL).