Bug Summary

File:tests/testgmenu.c
Warning:line 241, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name testgmenu.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/tests -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../cdk -I ../cdk -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/tests -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-172241-43638-1 -x c testgmenu.c
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
35static 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 &amp; 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
94static GMenuModel *
95get_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
130static void
131activate_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
136static void
137activate_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
153static void
154activate_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
170static 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
180static GActionGroup *
181get_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
194static void
195enabled_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
212static void
213state_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")) &&
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
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
252static void
253enabled_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
279static void
280state_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")))
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
318static void
319state_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
343static CtkWidget *
344create_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
420static void
421toggle_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
439static void
440action_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
449static void
450action_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
469static void
470toggle_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
506static void
507toggle_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}
558static CtkWidget *
559create_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
602static gboolean
603on_delete_event (CtkWidget *widget,
604 CdkEvent *event,
605 gpointer user_data)
606{
607 ctk_main_quit ();
608 return TRUE(!(0));
609}
610
611int
612main (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: */