File: | tests/testgmenu.c |
Warning: | line 298, column 45 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* testgmenu.c |
2 | * Copyright (C) 2011 Red Hat, Inc. |
3 | * Written by Matthias Clasen |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Library General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Library General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Library General Public |
16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | #include <stdlib.h> |
20 | #include <string.h> |
21 | #include <gio/gio.h> |
22 | #include <ctk/ctk.h> |
23 | |
24 | /* TODO |
25 | * |
26 | * - Labeled sections |
27 | * |
28 | * - Focus changes. Verify that stopping subscriptions works. |
29 | * |
30 | * - Other attributes. What about icons ? |
31 | */ |
32 | |
33 | /* The example menu {{{1 */ |
34 | |
35 | static const gchar menu_markup[] = |
36 | "<interface>\n" |
37 | "<menu id='edit-menu'>\n" |
38 | " <section>\n" |
39 | " <item>\n" |
40 | " <attribute name='action'>actions.undo</attribute>\n" |
41 | " <attribute name='label' translatable='yes' context='Stock label'>_Undo</attribute>\n" |
42 | " </item>\n" |
43 | " <item>\n" |
44 | " <attribute name='label' translatable='yes'>Redo</attribute>\n" |
45 | " <attribute name='action'>actions.redo</attribute>\n" |
46 | " </item>\n" |
47 | " </section>\n" |
48 | " <section/>\n" |
49 | " <section>\n" |
50 | " <attribute name='label' translatable='yes'>Copy & Paste</attribute>\n" |
51 | " <item>\n" |
52 | " <attribute name='label' translatable='yes'>Cut</attribute>\n" |
53 | " <attribute name='action'>actions.cut</attribute>\n" |
54 | " </item>\n" |
55 | " <item>\n" |
56 | " <attribute name='label' translatable='yes'>Copy</attribute>\n" |
57 | " <attribute name='action'>actions.copy</attribute>\n" |
58 | " </item>\n" |
59 | " <item>\n" |
60 | " <attribute name='label' translatable='yes'>Paste</attribute>\n" |
61 | " <attribute name='action'>actions.paste</attribute>\n" |
62 | " </item>\n" |
63 | " </section>\n" |
64 | " <section>\n" |
65 | " <item>\n" |
66 | " <attribute name='label' translatable='yes'>Bold</attribute>\n" |
67 | " <attribute name='action'>actions.bold</attribute>\n" |
68 | " </item>\n" |
69 | " <section id=\"size-placeholder\">\n" |
70 | " <attribute name=\"label\">Size</attribute>" |
71 | " </section>\n" |
72 | " <submenu>\n" |
73 | " <attribute name='label' translatable='yes'>Language</attribute>\n" |
74 | " <item>\n" |
75 | " <attribute name='label' translatable='yes'>Latin</attribute>\n" |
76 | " <attribute name='action'>actions.lang</attribute>\n" |
77 | " <attribute name='target'>latin</attribute>\n" |
78 | " </item>\n" |
79 | " <item>\n" |
80 | " <attribute name='label' translatable='yes'>Greek</attribute>\n" |
81 | " <attribute name='action'>actions.lang</attribute>\n" |
82 | " <attribute name='target'>greek</attribute>\n" |
83 | " </item>\n" |
84 | " <item>\n" |
85 | " <attribute name='label' translatable='yes'>Urdu</attribute>\n" |
86 | " <attribute name='action'>actions.lang</attribute>\n" |
87 | " <attribute name='target'>urdu</attribute>\n" |
88 | " </item>\n" |
89 | " </submenu>\n" |
90 | " </section>\n" |
91 | "</menu>\n" |
92 | "</interface>\n"; |
93 | |
94 | static GMenuModel * |
95 | get_model (void) |
96 | { |
97 | GError *error = NULL((void*)0); |
98 | CtkBuilder *builder; |
99 | GMenuModel *menu, *section; |
100 | float i; |
101 | |
102 | builder = ctk_builder_new (); |
103 | ctk_builder_add_from_string (builder, menu_markup, -1, &error); |
104 | g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "testgmenu.c" , 104, ((const char*) (__func__)), "error", error, 0, 0); } while (0); |
105 | |
106 | menu = G_MENU_MODEL (g_object_ref (ctk_builder_get_object (builder, "edit-menu")))((((GMenuModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((((__typeof__ (ctk_builder_get_object (builder, "edit-menu" ))) (g_object_ref) (ctk_builder_get_object (builder, "edit-menu" ))))), ((g_menu_model_get_type ())))))); |
107 | |
108 | section = G_MENU_MODEL (g_object_ref (ctk_builder_get_object (builder, "size-placeholder")))((((GMenuModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((((__typeof__ (ctk_builder_get_object (builder, "size-placeholder" ))) (g_object_ref) (ctk_builder_get_object (builder, "size-placeholder" ))))), ((g_menu_model_get_type ())))))); |
109 | g_object_unref (builder); |
110 | |
111 | for (i = 0.5; i <= 2.0; i += 0.5) |
112 | { |
113 | GMenuItem *item; |
114 | char *target; |
115 | char *label; |
116 | |
117 | target = g_strdup_printf ("actions.size::%.1f", i); |
118 | label = g_strdup_printf ("x %.1f", i); |
119 | item = g_menu_item_new (label, target); |
120 | g_menu_append_item (G_MENU (section)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((section)), ((g_menu_get_type ())))))), item); |
121 | g_free (label); |
122 | g_free (target); |
123 | } |
124 | |
125 | return menu; |
126 | } |
127 | |
128 | /* The example actions {{{1 */ |
129 | |
130 | static void |
131 | activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) |
132 | { |
133 | g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ())))))))); |
134 | } |
135 | |
136 | static void |
137 | activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data) |
138 | { |
139 | GVariant *old_state, *new_state; |
140 | |
141 | old_state = g_action_get_state (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
142 | new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state)); |
143 | |
144 | g_print ("Toggle action %s activated, state changes from %d to %d\n", |
145 | g_action_get_name (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))), |
146 | g_variant_get_boolean (old_state), |
147 | g_variant_get_boolean (new_state)); |
148 | |
149 | g_simple_action_set_state (action, new_state); |
150 | g_variant_unref (old_state); |
151 | } |
152 | |
153 | static void |
154 | activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data) |
155 | { |
156 | GVariant *old_state, *new_state; |
157 | |
158 | old_state = g_action_get_state (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
159 | new_state = g_variant_new_string (g_variant_get_string (parameter, NULL((void*)0))); |
160 | |
161 | g_print ("Radio action %s activated, state changes from %s to %s\n", |
162 | g_action_get_name (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))), |
163 | g_variant_get_string (old_state, NULL((void*)0)), |
164 | g_variant_get_string (new_state, NULL((void*)0))); |
165 | |
166 | g_simple_action_set_state (action, new_state); |
167 | g_variant_unref (old_state); |
168 | } |
169 | |
170 | static GActionEntry actions[] = { |
171 | { .name = "undo", .activate = activate_action }, |
172 | { .name = "redo", .activate = activate_action }, |
173 | { .name = "cut", .activate = activate_action }, |
174 | { .name = "copy", .activate = activate_action }, |
175 | { .name = "paste", .activate = activate_action }, |
176 | { .name = "bold", .activate = activate_toggle, .state = "true" }, |
177 | { .name = "lang", .activate = activate_radio, .parameter_type = "s", .state = "'latin'" }, |
178 | }; |
179 | |
180 | static GActionGroup * |
181 | get_group (void) |
182 | { |
183 | GSimpleActionGroup *group; |
184 | |
185 | group = g_simple_action_group_new (); |
186 | |
187 | g_action_map_add_action_entries (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), actions, G_N_ELEMENTS (actions)(sizeof (actions) / sizeof ((actions)[0])), NULL((void*)0)); |
188 | |
189 | return G_ACTION_GROUP (group)((((GActionGroup*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_group_get_type ())))))); |
190 | } |
191 | |
192 | /* The action treeview {{{1 */ |
193 | |
194 | static void |
195 | enabled_cell_func (CtkTreeViewColumn *column, |
196 | CtkCellRenderer *cell, |
197 | CtkTreeModel *model, |
198 | CtkTreeIter *iter, |
199 | gpointer data) |
200 | { |
201 | GActionGroup *group = data; |
202 | gchar *name; |
203 | gboolean enabled; |
204 | |
205 | ctk_tree_model_get (model, iter, 0, &name, -1); |
206 | enabled = g_action_group_get_action_enabled (group, name); |
207 | g_free (name); |
208 | |
209 | ctk_cell_renderer_toggle_set_active (CTK_CELL_RENDERER_TOGGLE (cell)((((CtkCellRendererToggle*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((cell)), ((ctk_cell_renderer_toggle_get_type ())))))), enabled); |
210 | } |
211 | |
212 | static void |
213 | state_cell_func (CtkTreeViewColumn *column, |
214 | CtkCellRenderer *cell, |
215 | CtkTreeModel *model, |
216 | CtkTreeIter *iter, |
217 | gpointer data) |
218 | { |
219 | GActionGroup *group = data; |
220 | gchar *name; |
221 | GVariant *state; |
222 | |
223 | ctk_tree_model_get (model, iter, 0, &name, -1); |
224 | state = g_action_group_get_action_state (group, name); |
225 | g_free (name); |
226 | |
227 | ctk_cell_renderer_set_visible (cell, FALSE(0)); |
228 | g_object_set (cell, "mode", CTK_CELL_RENDERER_MODE_INERT, NULL((void*)0)); |
229 | |
230 | if (state == NULL((void*)0)) |
231 | return; |
232 | |
233 | if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN((const GVariantType *) "b")) && |
234 | CTK_IS_CELL_RENDERER_TOGGLE (cell)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (cell)); GType __t = ((ctk_cell_renderer_toggle_get_type ())) ; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } ))))) |
235 | { |
236 | ctk_cell_renderer_set_visible (cell, TRUE(!(0))); |
237 | g_object_set (cell, "mode", CTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL((void*)0)); |
238 | ctk_cell_renderer_toggle_set_active (CTK_CELL_RENDERER_TOGGLE (cell)((((CtkCellRendererToggle*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((cell)), ((ctk_cell_renderer_toggle_get_type ())))))), |
239 | g_variant_get_boolean (state)); |
240 | } |
241 | else if (g_variant_is_of_type (state, G_VARIANT_TYPE_STRING((const GVariantType *) "s")) && |
242 | CTK_IS_CELL_RENDERER_COMBO (cell)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (cell)); GType __t = ((ctk_cell_renderer_combo_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } ))))) |
243 | { |
244 | ctk_cell_renderer_set_visible (cell, TRUE(!(0))); |
245 | g_object_set (cell, "mode", CTK_CELL_RENDERER_MODE_EDITABLE, NULL((void*)0)); |
246 | g_object_set (cell, "text", g_variant_get_string (state, NULL((void*)0)), NULL((void*)0)); |
247 | } |
248 | |
249 | g_variant_unref (state); |
250 | } |
251 | |
252 | static void |
253 | enabled_cell_toggled (CtkCellRendererToggle *cell, |
254 | const gchar *path_str, |
255 | CtkTreeModel *model) |
256 | { |
257 | GActionGroup *group; |
258 | GAction *action; |
259 | gchar *name; |
260 | CtkTreePath *path; |
261 | CtkTreeIter iter; |
262 | gboolean enabled; |
263 | |
264 | group = g_object_get_data (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), (((GType) ((20) << (2)))))))), "group"); |
265 | path = ctk_tree_path_new_from_string (path_str); |
266 | ctk_tree_model_get_iter (model, &iter, path); |
267 | ctk_tree_model_get (model, &iter, 0, &name, -1); |
268 | |
269 | enabled = g_action_group_get_action_enabled (group, name); |
270 | action = g_action_map_lookup_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), name); |
271 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action)((((GSimpleAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_simple_action_get_type ())))))), !enabled); |
272 | |
273 | ctk_tree_model_row_changed (model, path, &iter); |
274 | |
275 | g_free (name); |
276 | ctk_tree_path_free (path); |
277 | } |
278 | |
279 | static void |
280 | state_cell_toggled (CtkCellRendererToggle *cell, |
281 | const gchar *path_str, |
282 | CtkTreeModel *model) |
283 | { |
284 | GActionGroup *group; |
285 | GAction *action; |
286 | gchar *name; |
287 | CtkTreePath *path; |
288 | CtkTreeIter iter; |
289 | GVariant *state; |
290 | |
291 | group = g_object_get_data (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), (((GType) ((20) << (2)))))))), "group"); |
292 | path = ctk_tree_path_new_from_string (path_str); |
293 | ctk_tree_model_get_iter (model, &iter, path); |
294 | ctk_tree_model_get (model, &iter, 0, &name, -1); |
295 | |
296 | state = g_action_group_get_action_state (group, name); |
297 | action = g_action_map_lookup_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), name); |
298 | if (state && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN((const GVariantType *) "b"))) |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
299 | { |
300 | gboolean b; |
301 | |
302 | b = g_variant_get_boolean (state); |
303 | g_simple_action_set_state (G_SIMPLE_ACTION (action)((((GSimpleAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_simple_action_get_type ())))))), g_variant_new_boolean (!b)); |
304 | } |
305 | else |
306 | { |
307 | /* nothing to do */ |
308 | } |
309 | |
310 | ctk_tree_model_row_changed (model, path, &iter); |
311 | |
312 | g_free (name); |
313 | ctk_tree_path_free (path); |
314 | if (state) |
315 | g_variant_unref (state); |
316 | } |
317 | |
318 | static void |
319 | state_cell_edited (CtkCellRendererCombo *cell, |
320 | const gchar *path_str, |
321 | const gchar *new_text, |
322 | CtkTreeModel *model) |
323 | { |
324 | GActionGroup *group; |
325 | GAction *action; |
326 | gchar *name; |
327 | CtkTreePath *path; |
328 | CtkTreeIter iter; |
329 | |
330 | group = g_object_get_data (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), (((GType) ((20) << (2)))))))), "group"); |
331 | path = ctk_tree_path_new_from_string (path_str); |
332 | ctk_tree_model_get_iter (model, &iter, path); |
333 | ctk_tree_model_get (model, &iter, 0, &name, -1); |
334 | action = g_action_map_lookup_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), name); |
335 | g_simple_action_set_state (G_SIMPLE_ACTION (action)((((GSimpleAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_simple_action_get_type ())))))), g_variant_new_string (new_text)); |
336 | |
337 | ctk_tree_model_row_changed (model, path, &iter); |
338 | |
339 | g_free (name); |
340 | ctk_tree_path_free (path); |
341 | } |
342 | |
343 | static CtkWidget * |
344 | create_action_treeview (GActionGroup *group) |
345 | { |
346 | CtkWidget *tv; |
347 | CtkListStore *store; |
348 | CtkListStore *values; |
349 | CtkTreeIter iter; |
350 | CtkTreeViewColumn *column; |
351 | CtkCellRenderer *cell; |
352 | gchar **actions; |
353 | gint i; |
354 | |
355 | store = ctk_list_store_new (2, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_STRING((GType) ((16) << (2)))); |
356 | actions = g_action_group_list_actions (group); |
357 | for (i = 0; actions[i]; i++) |
358 | { |
359 | ctk_list_store_append (store, &iter); |
360 | ctk_list_store_set (store, &iter, 0, actions[i], -1); |
361 | } |
362 | g_strfreev (actions); |
363 | g_object_set_data (G_OBJECT (store)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), (((GType) ((20) << (2)))))))), "group", group); |
364 | |
365 | tv = ctk_tree_view_new (); |
366 | |
367 | g_signal_connect_swapped (group, "action-enabled-changed",g_signal_connect_data ((group), ("action-enabled-changed"), ( ((GCallback) (ctk_widget_queue_draw))), (tv), ((void*)0), G_CONNECT_SWAPPED ) |
368 | G_CALLBACK (ctk_widget_queue_draw), tv)g_signal_connect_data ((group), ("action-enabled-changed"), ( ((GCallback) (ctk_widget_queue_draw))), (tv), ((void*)0), G_CONNECT_SWAPPED ); |
369 | g_signal_connect_swapped (group, "action-state-changed",g_signal_connect_data ((group), ("action-state-changed"), ((( GCallback) (ctk_widget_queue_draw))), (tv), ((void*)0), G_CONNECT_SWAPPED ) |
370 | G_CALLBACK (ctk_widget_queue_draw), tv)g_signal_connect_data ((group), ("action-state-changed"), ((( GCallback) (ctk_widget_queue_draw))), (tv), ((void*)0), G_CONNECT_SWAPPED ); |
371 | |
372 | ctk_tree_view_set_model (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), CTK_TREE_MODEL (store)((((CtkTreeModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), ((ctk_tree_model_get_type ()))))))); |
373 | |
374 | cell = ctk_cell_renderer_text_new (); |
375 | column = ctk_tree_view_column_new_with_attributes ("Action", cell, |
376 | "text", 0, |
377 | NULL((void*)0)); |
378 | ctk_tree_view_append_column (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), column); |
379 | |
380 | column = ctk_tree_view_column_new (); |
381 | ctk_tree_view_column_set_title (column, "Enabled"); |
382 | cell = ctk_cell_renderer_toggle_new (); |
383 | ctk_tree_view_column_pack_start (column, cell, FALSE(0)); |
384 | ctk_tree_view_column_set_cell_data_func (column, cell, enabled_cell_func, group, NULL((void*)0)); |
385 | g_signal_connect (cell, "toggled", G_CALLBACK (enabled_cell_toggled), store)g_signal_connect_data ((cell), ("toggled"), (((GCallback) (enabled_cell_toggled ))), (store), ((void*)0), (GConnectFlags) 0); |
386 | ctk_tree_view_append_column (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), column); |
387 | |
388 | column = ctk_tree_view_column_new (); |
389 | ctk_tree_view_column_set_title (column, "State"); |
390 | cell = ctk_cell_renderer_toggle_new (); |
391 | ctk_tree_view_column_pack_start (column, cell, FALSE(0)); |
392 | ctk_tree_view_column_set_cell_data_func (column, cell, state_cell_func, group, NULL((void*)0)); |
393 | g_signal_connect (cell, "toggled", G_CALLBACK (state_cell_toggled), store)g_signal_connect_data ((cell), ("toggled"), (((GCallback) (state_cell_toggled ))), (store), ((void*)0), (GConnectFlags) 0); |
394 | cell = ctk_cell_renderer_combo_new (); |
395 | values = ctk_list_store_new (1, G_TYPE_STRING((GType) ((16) << (2)))); |
396 | ctk_list_store_append (values, &iter); |
397 | ctk_list_store_set (values, &iter, 0, "latin", -1); |
398 | ctk_list_store_append (values, &iter); |
399 | ctk_list_store_set (values, &iter, 0, "greek", -1); |
400 | ctk_list_store_append (values, &iter); |
401 | ctk_list_store_set (values, &iter, 0, "urdu", -1); |
402 | ctk_list_store_append (values, &iter); |
403 | ctk_list_store_set (values, &iter, 0, "sumerian", -1); |
404 | g_object_set (cell, |
405 | "has-entry", FALSE(0), |
406 | "model", values, |
407 | "text-column", 0, |
408 | "editable", TRUE(!(0)), |
409 | NULL((void*)0)); |
410 | ctk_tree_view_column_pack_start (column, cell, FALSE(0)); |
411 | ctk_tree_view_column_set_cell_data_func (column, cell, state_cell_func, group, NULL((void*)0)); |
412 | g_signal_connect (cell, "edited", G_CALLBACK (state_cell_edited), store)g_signal_connect_data ((cell), ("edited"), (((GCallback) (state_cell_edited ))), (store), ((void*)0), (GConnectFlags) 0); |
413 | ctk_tree_view_append_column (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), column); |
414 | |
415 | return tv; |
416 | } |
417 | |
418 | /* Dynamic menu changes {{{1 */ |
419 | |
420 | static void |
421 | toggle_sumerian (CtkToggleButton *button, gpointer data) |
422 | { |
423 | GMenuModel *model; |
424 | gboolean adding; |
425 | GMenuModel *m; |
426 | |
427 | model = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model"); |
428 | |
429 | adding = ctk_toggle_button_get_active (button); |
430 | |
431 | m = g_menu_model_get_item_link (model, g_menu_model_get_n_items (model) - 1, G_MENU_LINK_SECTION"section"); |
432 | m = g_menu_model_get_item_link (m, g_menu_model_get_n_items (m) - 1, G_MENU_LINK_SUBMENU"submenu"); |
433 | if (adding) |
434 | g_menu_append (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), "Sumerian", "lang::sumerian"); |
435 | else |
436 | g_menu_remove (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), g_menu_model_get_n_items (m) - 1); |
437 | } |
438 | |
439 | static void |
440 | action_list_add (CtkTreeModel *store, |
441 | const gchar *action) |
442 | { |
443 | CtkTreeIter iter; |
444 | |
445 | ctk_list_store_append (CTK_LIST_STORE (store)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), ((ctk_list_store_get_type ())))))), &iter); |
446 | ctk_list_store_set (CTK_LIST_STORE (store)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), ((ctk_list_store_get_type ())))))), &iter, 0, action, -1); |
447 | } |
448 | |
449 | static void |
450 | action_list_remove (CtkTreeModel *store, |
451 | const gchar *action) |
452 | { |
453 | CtkTreeIter iter; |
454 | gchar *text; |
455 | |
456 | ctk_tree_model_get_iter_first (store, &iter); |
457 | do { |
458 | ctk_tree_model_get (store, &iter, 0, &text, -1); |
459 | if (g_strcmp0 (action, text) == 0) |
460 | { |
461 | g_free (text); |
462 | ctk_list_store_remove (CTK_LIST_STORE (store)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), ((ctk_list_store_get_type ())))))), &iter); |
463 | break; |
464 | } |
465 | g_free (text); |
466 | } while (ctk_tree_model_iter_next (store, &iter)); |
467 | } |
468 | |
469 | static void |
470 | toggle_italic (CtkToggleButton *button, gpointer data) |
471 | { |
472 | GMenuModel *model; |
473 | GActionGroup *group; |
474 | gboolean adding; |
475 | GMenuModel *m; |
476 | CtkTreeView *tv = data; |
477 | CtkTreeModel *store; |
478 | |
479 | model = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model"); |
480 | group = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group"); |
481 | |
482 | store = ctk_tree_view_get_model (tv); |
483 | |
484 | adding = ctk_toggle_button_get_active (button); |
485 | |
486 | m = g_menu_model_get_item_link (model, g_menu_model_get_n_items (model) - 1, G_MENU_LINK_SECTION"section"); |
487 | if (adding) |
488 | { |
489 | GSimpleAction *action; |
490 | |
491 | action = g_simple_action_new_stateful ("italic", NULL((void*)0), g_variant_new_boolean (FALSE(0))); |
492 | g_action_map_add_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
493 | g_signal_connect (action, "activate", G_CALLBACK (activate_toggle), NULL)g_signal_connect_data ((action), ("activate"), (((GCallback) ( activate_toggle))), (((void*)0)), ((void*)0), (GConnectFlags) 0); |
494 | g_object_unref (action); |
495 | action_list_add (store, "italic"); |
496 | g_menu_insert (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), 1, "Italic", "italic"); |
497 | } |
498 | else |
499 | { |
500 | g_action_map_remove_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), "italic"); |
501 | action_list_remove (store, "italic"); |
502 | g_menu_remove (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), 1); |
503 | } |
504 | } |
505 | |
506 | static void |
507 | toggle_speed (CtkToggleButton *button, gpointer data) |
508 | { |
509 | GMenuModel *model; |
510 | GActionGroup *group; |
511 | gboolean adding; |
512 | GMenuModel *m; |
513 | CtkTreeView *tv = data; |
514 | CtkTreeModel *store; |
515 | |
516 | model = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model"); |
517 | group = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group"); |
518 | |
519 | store = ctk_tree_view_get_model (tv); |
520 | |
521 | adding = ctk_toggle_button_get_active (button); |
522 | |
523 | m = g_menu_model_get_item_link (model, 1, G_MENU_LINK_SECTION"section"); |
524 | if (adding) |
525 | { |
526 | GSimpleAction *action; |
527 | GMenu *submenu; |
528 | |
529 | action = g_simple_action_new ("faster", NULL((void*)0)); |
530 | g_action_map_add_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
531 | g_signal_connect (action, "activate", G_CALLBACK (activate_action), NULL)g_signal_connect_data ((action), ("activate"), (((GCallback) ( activate_action))), (((void*)0)), ((void*)0), (GConnectFlags) 0); |
532 | g_object_unref (action); |
533 | |
534 | action = g_simple_action_new ("slower", NULL((void*)0)); |
535 | g_action_map_add_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
536 | g_signal_connect (action, "activate", G_CALLBACK (activate_action), NULL)g_signal_connect_data ((action), ("activate"), (((GCallback) ( activate_action))), (((void*)0)), ((void*)0), (GConnectFlags) 0); |
537 | g_object_unref (action); |
538 | |
539 | action_list_add (store, "faster"); |
540 | action_list_add (store, "slower"); |
541 | |
542 | submenu = g_menu_new (); |
543 | g_menu_append (submenu, "Faster", "faster"); |
544 | g_menu_append (submenu, "Slower", "slower"); |
545 | g_menu_append_submenu (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), "Speed", G_MENU_MODEL (submenu)((((GMenuModel*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((submenu)), ((g_menu_model_get_type ()))))))); |
546 | } |
547 | else |
548 | { |
549 | g_action_map_remove_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), "faster"); |
550 | g_action_map_remove_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), "slower"); |
551 | |
552 | action_list_remove (store, "faster"); |
553 | action_list_remove (store, "slower"); |
554 | |
555 | g_menu_remove (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), g_menu_model_get_n_items (m) - 1); |
556 | } |
557 | } |
558 | static CtkWidget * |
559 | create_add_remove_buttons (GActionGroup *group, |
560 | GMenuModel *model, |
561 | CtkWidget *treeview) |
562 | { |
563 | CtkWidget *box; |
564 | CtkWidget *button; |
565 | |
566 | box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 6); |
567 | |
568 | button = ctk_check_button_new_with_label ("Add Italic"); |
569 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
570 | |
571 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group", group); |
572 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model", model); |
573 | |
574 | g_signal_connect (button, "toggled",g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_italic))), (treeview), ((void*)0), (GConnectFlags) 0) |
575 | G_CALLBACK (toggle_italic), treeview)g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_italic))), (treeview), ((void*)0), (GConnectFlags) 0); |
576 | |
577 | button = ctk_check_button_new_with_label ("Add Sumerian"); |
578 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
579 | |
580 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group", group); |
581 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model", model); |
582 | |
583 | g_signal_connect (button, "toggled",g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_sumerian))), (((void*)0)), ((void*)0), (GConnectFlags) 0) |
584 | G_CALLBACK (toggle_sumerian), NULL)g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_sumerian))), (((void*)0)), ((void*)0), (GConnectFlags) 0); |
585 | |
586 | button = ctk_check_button_new_with_label ("Add Speed"); |
587 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
588 | |
589 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group", group); |
590 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model", model); |
591 | |
592 | g_signal_connect (button, "toggled",g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_speed))), (treeview), ((void*)0), (GConnectFlags) 0) |
593 | G_CALLBACK (toggle_speed), treeview)g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_speed))), (treeview), ((void*)0), (GConnectFlags) 0); |
594 | return box; |
595 | } |
596 | |
597 | /* main {{{1 */ |
598 | |
599 | #define BUS_NAME"org.ctk.TestMenus" "org.ctk.TestMenus" |
600 | #define OBJ_PATH"/org/ctk/TestMenus" "/org/ctk/TestMenus" |
601 | |
602 | static gboolean |
603 | on_delete_event (CtkWidget *widget, |
604 | CdkEvent *event, |
605 | gpointer user_data) |
606 | { |
607 | ctk_main_quit (); |
608 | return TRUE(!(0)); |
609 | } |
610 | |
611 | int |
612 | main (int argc, char *argv[]) |
613 | { |
614 | CtkWidget *window; |
615 | CtkWidget *box; |
616 | GMenuModel *model; |
617 | GActionGroup *group; |
618 | GDBusConnection *bus; |
619 | GError *error = NULL((void*)0); |
620 | gboolean do_export = FALSE(0); |
621 | gboolean do_import = FALSE(0); |
622 | GOptionEntry entries[] = { |
623 | { "export", 0, 0, G_OPTION_ARG_NONE, &do_export, "Export actions and menus over D-Bus", NULL((void*)0) }, |
624 | { "import", 0, 0, G_OPTION_ARG_NONE, &do_import, "Use exported actions and menus", NULL((void*)0) }, |
625 | { NULL((void*)0), } |
626 | }; |
627 | |
628 | ctk_init_with_args (&argc, &argv, NULL((void*)0), entries, NULL((void*)0), NULL((void*)0)); |
629 | |
630 | if (do_export && do_import) |
631 | { |
632 | g_error ("can't have it both ways\n"); |
633 | exit (1); |
634 | } |
635 | |
636 | window = ctk_window_new (CTK_WINDOW_TOPLEVEL); |
637 | g_signal_connect (window, "delete-event", G_CALLBACK(on_delete_event), NULL)g_signal_connect_data ((window), ("delete-event"), (((GCallback ) (on_delete_event))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); |
638 | box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 6); |
639 | ctk_container_add (CTK_CONTAINER (window)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((window)), ((ctk_container_get_type ())))))), box); |
640 | |
641 | bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL((void*)0), NULL((void*)0)); |
642 | |
643 | if (do_import) |
644 | { |
645 | g_print ("Getting menus from the bus...\n"); |
646 | model = (GMenuModel*)g_dbus_menu_model_get (bus, BUS_NAME"org.ctk.TestMenus", OBJ_PATH"/org/ctk/TestMenus"); |
647 | g_print ("Getting actions from the bus...\n"); |
648 | group = (GActionGroup*)g_dbus_action_group_get (bus, BUS_NAME"org.ctk.TestMenus", OBJ_PATH"/org/ctk/TestMenus"); |
649 | } |
650 | else |
651 | { |
652 | CtkWidget *tv; |
653 | CtkWidget *buttons; |
654 | |
655 | group = get_group (); |
656 | model = get_model (); |
657 | |
658 | tv = create_action_treeview (group); |
659 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), tv); |
660 | buttons = create_add_remove_buttons (group, model, tv); |
661 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), buttons); |
662 | } |
663 | |
664 | if (do_export) |
665 | { |
666 | g_print ("Exporting menus on the bus...\n"); |
667 | if (!g_dbus_connection_export_menu_model (bus, OBJ_PATH"/org/ctk/TestMenus", model, &error)) |
668 | { |
669 | g_warning ("Menu export failed: %s", error->message); |
670 | exit (1); |
671 | } |
672 | g_print ("Exporting actions on the bus...\n"); |
673 | if (!g_dbus_connection_export_action_group (bus, OBJ_PATH"/org/ctk/TestMenus", group, &error)) |
674 | { |
675 | g_warning ("Action export failed: %s", error->message); |
676 | exit (1); |
677 | } |
678 | g_bus_own_name_on_connection (bus, BUS_NAME"org.ctk.TestMenus", 0, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
679 | } |
680 | else |
681 | { |
682 | CtkWidget *button; |
683 | |
684 | button = ctk_menu_button_new (); |
685 | ctk_button_set_label (CTK_BUTTON (button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), ((ctk_button_get_type ())))))), "Click here"); |
686 | ctk_menu_button_set_use_popover (CTK_MENU_BUTTON (button)((((CtkMenuButton*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), ((ctk_menu_button_get_type ())))))), TRUE(!(0))); |
687 | ctk_menu_button_set_menu_model (CTK_MENU_BUTTON (button)((((CtkMenuButton*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), ((ctk_menu_button_get_type ())))))), model); |
688 | ctk_widget_insert_action_group (button, "actions", group); |
689 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
690 | } |
691 | |
692 | ctk_widget_show_all (window); |
693 | |
694 | ctk_main (); |
695 | |
696 | return 0; |
697 | } |
698 | |
699 | /* Epilogue {{{1 */ |
700 | /* vim:set foldmethod=marker: */ |