| File: | tests/testgmenu.c |
| Warning: | line 239, column 36 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, |
| 132 | GVariant *parameter G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 133 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 134 | { |
| 135 | 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 ())))))))); |
| 136 | } |
| 137 | |
| 138 | static void |
| 139 | activate_toggle (GSimpleAction *action, |
| 140 | GVariant *parameter G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 141 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 142 | { |
| 143 | GVariant *old_state, *new_state; |
| 144 | |
| 145 | old_state = g_action_get_state (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
| 146 | new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state)); |
| 147 | |
| 148 | g_print ("Toggle action %s activated, state changes from %d to %d\n", |
| 149 | g_action_get_name (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))), |
| 150 | g_variant_get_boolean (old_state), |
| 151 | g_variant_get_boolean (new_state)); |
| 152 | |
| 153 | g_simple_action_set_state (action, new_state); |
| 154 | g_variant_unref (old_state); |
| 155 | } |
| 156 | |
| 157 | static void |
| 158 | activate_radio (GSimpleAction *action, |
| 159 | GVariant *parameter, |
| 160 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 161 | { |
| 162 | GVariant *old_state, *new_state; |
| 163 | |
| 164 | old_state = g_action_get_state (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))); |
| 165 | new_state = g_variant_new_string (g_variant_get_string (parameter, NULL((void*)0))); |
| 166 | |
| 167 | g_print ("Radio action %s activated, state changes from %s to %s\n", |
| 168 | g_action_get_name (G_ACTION (action)((((GAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_action_get_type ()))))))), |
| 169 | g_variant_get_string (old_state, NULL((void*)0)), |
| 170 | g_variant_get_string (new_state, NULL((void*)0))); |
| 171 | |
| 172 | g_simple_action_set_state (action, new_state); |
| 173 | g_variant_unref (old_state); |
| 174 | } |
| 175 | |
| 176 | static GActionEntry actions[] = { |
| 177 | { .name = "undo", .activate = activate_action }, |
| 178 | { .name = "redo", .activate = activate_action }, |
| 179 | { .name = "cut", .activate = activate_action }, |
| 180 | { .name = "copy", .activate = activate_action }, |
| 181 | { .name = "paste", .activate = activate_action }, |
| 182 | { .name = "bold", .activate = activate_toggle, .state = "true" }, |
| 183 | { .name = "lang", .activate = activate_radio, .parameter_type = "s", .state = "'latin'" }, |
| 184 | }; |
| 185 | |
| 186 | static GActionGroup * |
| 187 | get_group (void) |
| 188 | { |
| 189 | GSimpleActionGroup *group; |
| 190 | |
| 191 | group = g_simple_action_group_new (); |
| 192 | |
| 193 | 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)); |
| 194 | |
| 195 | return G_ACTION_GROUP (group)((((GActionGroup*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_group_get_type ())))))); |
| 196 | } |
| 197 | |
| 198 | /* The action treeview {{{1 */ |
| 199 | |
| 200 | static void |
| 201 | enabled_cell_func (CtkTreeViewColumn *column G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 202 | CtkCellRenderer *cell, |
| 203 | CtkTreeModel *model, |
| 204 | CtkTreeIter *iter, |
| 205 | gpointer data) |
| 206 | { |
| 207 | GActionGroup *group = data; |
| 208 | gchar *name; |
| 209 | gboolean enabled; |
| 210 | |
| 211 | ctk_tree_model_get (model, iter, 0, &name, -1); |
| 212 | enabled = g_action_group_get_action_enabled (group, name); |
| 213 | g_free (name); |
| 214 | |
| 215 | 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); |
| 216 | } |
| 217 | |
| 218 | static void |
| 219 | state_cell_func (CtkTreeViewColumn *column G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 220 | CtkCellRenderer *cell, |
| 221 | CtkTreeModel *model, |
| 222 | CtkTreeIter *iter, |
| 223 | gpointer data) |
| 224 | { |
| 225 | GActionGroup *group = data; |
| 226 | gchar *name; |
| 227 | GVariant *state; |
| 228 | |
| 229 | ctk_tree_model_get (model, iter, 0, &name, -1); |
| 230 | state = g_action_group_get_action_state (group, name); |
| 231 | g_free (name); |
| 232 | |
| 233 | ctk_cell_renderer_set_visible (cell, FALSE(0)); |
| 234 | g_object_set (cell, "mode", CTK_CELL_RENDERER_MODE_INERT, NULL((void*)0)); |
| 235 | |
| 236 | if (state == NULL((void*)0)) |
| 237 | return; |
| 238 | |
| 239 | if (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 | |
| 240 | 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; } ))))) |
| 241 | { |
| 242 | ctk_cell_renderer_set_visible (cell, TRUE(!(0))); |
| 243 | g_object_set (cell, "mode", CTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL((void*)0)); |
| 244 | 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 ())))))), |
| 245 | g_variant_get_boolean (state)); |
| 246 | } |
| 247 | else if (g_variant_is_of_type (state, G_VARIANT_TYPE_STRING((const GVariantType *) "s")) && |
| 248 | 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; } ))))) |
| 249 | { |
| 250 | ctk_cell_renderer_set_visible (cell, TRUE(!(0))); |
| 251 | g_object_set (cell, "mode", CTK_CELL_RENDERER_MODE_EDITABLE, NULL((void*)0)); |
| 252 | g_object_set (cell, "text", g_variant_get_string (state, NULL((void*)0)), NULL((void*)0)); |
| 253 | } |
| 254 | |
| 255 | g_variant_unref (state); |
| 256 | } |
| 257 | |
| 258 | static void |
| 259 | enabled_cell_toggled (CtkCellRendererToggle *cell G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 260 | const gchar *path_str, |
| 261 | CtkTreeModel *model) |
| 262 | { |
| 263 | GActionGroup *group; |
| 264 | GAction *action; |
| 265 | gchar *name; |
| 266 | CtkTreePath *path; |
| 267 | CtkTreeIter iter; |
| 268 | gboolean enabled; |
| 269 | |
| 270 | group = g_object_get_data (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), (((GType) ((20) << (2)))))))), "group"); |
| 271 | path = ctk_tree_path_new_from_string (path_str); |
| 272 | ctk_tree_model_get_iter (model, &iter, path); |
| 273 | ctk_tree_model_get (model, &iter, 0, &name, -1); |
| 274 | |
| 275 | enabled = g_action_group_get_action_enabled (group, name); |
| 276 | 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); |
| 277 | g_simple_action_set_enabled (G_SIMPLE_ACTION (action)((((GSimpleAction*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((action)), ((g_simple_action_get_type ())))))), !enabled); |
| 278 | |
| 279 | ctk_tree_model_row_changed (model, path, &iter); |
| 280 | |
| 281 | g_free (name); |
| 282 | ctk_tree_path_free (path); |
| 283 | } |
| 284 | |
| 285 | static void |
| 286 | state_cell_toggled (CtkCellRendererToggle *cell G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 287 | const gchar *path_str, |
| 288 | CtkTreeModel *model) |
| 289 | { |
| 290 | GActionGroup *group; |
| 291 | GAction *action; |
| 292 | gchar *name; |
| 293 | CtkTreePath *path; |
| 294 | CtkTreeIter iter; |
| 295 | GVariant *state; |
| 296 | |
| 297 | group = g_object_get_data (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), (((GType) ((20) << (2)))))))), "group"); |
| 298 | path = ctk_tree_path_new_from_string (path_str); |
| 299 | ctk_tree_model_get_iter (model, &iter, path); |
| 300 | ctk_tree_model_get (model, &iter, 0, &name, -1); |
| 301 | |
| 302 | state = g_action_group_get_action_state (group, name); |
| 303 | 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); |
| 304 | if (state && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN((const GVariantType *) "b"))) |
| 305 | { |
| 306 | gboolean b; |
| 307 | |
| 308 | b = g_variant_get_boolean (state); |
| 309 | 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)); |
| 310 | } |
| 311 | else |
| 312 | { |
| 313 | /* nothing to do */ |
| 314 | } |
| 315 | |
| 316 | ctk_tree_model_row_changed (model, path, &iter); |
| 317 | |
| 318 | g_free (name); |
| 319 | ctk_tree_path_free (path); |
| 320 | if (state) |
| 321 | g_variant_unref (state); |
| 322 | } |
| 323 | |
| 324 | static void |
| 325 | state_cell_edited (CtkCellRendererCombo *cell G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 326 | const gchar *path_str, |
| 327 | const gchar *new_text, |
| 328 | CtkTreeModel *model) |
| 329 | { |
| 330 | GActionGroup *group; |
| 331 | GAction *action; |
| 332 | gchar *name; |
| 333 | CtkTreePath *path; |
| 334 | CtkTreeIter iter; |
| 335 | |
| 336 | group = g_object_get_data (G_OBJECT (model)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((model)), (((GType) ((20) << (2)))))))), "group"); |
| 337 | path = ctk_tree_path_new_from_string (path_str); |
| 338 | ctk_tree_model_get_iter (model, &iter, path); |
| 339 | ctk_tree_model_get (model, &iter, 0, &name, -1); |
| 340 | 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); |
| 341 | 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)); |
| 342 | |
| 343 | ctk_tree_model_row_changed (model, path, &iter); |
| 344 | |
| 345 | g_free (name); |
| 346 | ctk_tree_path_free (path); |
| 347 | } |
| 348 | |
| 349 | static CtkWidget * |
| 350 | create_action_treeview (GActionGroup *group) |
| 351 | { |
| 352 | CtkWidget *tv; |
| 353 | CtkListStore *store; |
| 354 | CtkListStore *values; |
| 355 | CtkTreeIter iter; |
| 356 | CtkTreeViewColumn *column; |
| 357 | CtkCellRenderer *cell; |
| 358 | gchar **actions; |
| 359 | gint i; |
| 360 | |
| 361 | store = ctk_list_store_new (2, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_STRING((GType) ((16) << (2)))); |
| 362 | actions = g_action_group_list_actions (group); |
| 363 | for (i = 0; actions[i]; i++) |
| 364 | { |
| 365 | ctk_list_store_append (store, &iter); |
| 366 | ctk_list_store_set (store, &iter, 0, actions[i], -1); |
| 367 | } |
| 368 | g_strfreev (actions); |
| 369 | g_object_set_data (G_OBJECT (store)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), (((GType) ((20) << (2)))))))), "group", group); |
| 370 | |
| 371 | tv = ctk_tree_view_new (); |
| 372 | |
| 373 | 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 ) |
| 374 | 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 ); |
| 375 | 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 ) |
| 376 | 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 ); |
| 377 | |
| 378 | 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 ()))))))); |
| 379 | |
| 380 | cell = ctk_cell_renderer_text_new (); |
| 381 | column = ctk_tree_view_column_new_with_attributes ("Action", cell, |
| 382 | "text", 0, |
| 383 | NULL((void*)0)); |
| 384 | ctk_tree_view_append_column (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), column); |
| 385 | |
| 386 | column = ctk_tree_view_column_new (); |
| 387 | ctk_tree_view_column_set_title (column, "Enabled"); |
| 388 | cell = ctk_cell_renderer_toggle_new (); |
| 389 | ctk_tree_view_column_pack_start (column, cell, FALSE(0)); |
| 390 | ctk_tree_view_column_set_cell_data_func (column, cell, enabled_cell_func, group, NULL((void*)0)); |
| 391 | 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); |
| 392 | ctk_tree_view_append_column (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), column); |
| 393 | |
| 394 | column = ctk_tree_view_column_new (); |
| 395 | ctk_tree_view_column_set_title (column, "State"); |
| 396 | cell = ctk_cell_renderer_toggle_new (); |
| 397 | ctk_tree_view_column_pack_start (column, cell, FALSE(0)); |
| 398 | ctk_tree_view_column_set_cell_data_func (column, cell, state_cell_func, group, NULL((void*)0)); |
| 399 | 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); |
| 400 | cell = ctk_cell_renderer_combo_new (); |
| 401 | values = ctk_list_store_new (1, G_TYPE_STRING((GType) ((16) << (2)))); |
| 402 | ctk_list_store_append (values, &iter); |
| 403 | ctk_list_store_set (values, &iter, 0, "latin", -1); |
| 404 | ctk_list_store_append (values, &iter); |
| 405 | ctk_list_store_set (values, &iter, 0, "greek", -1); |
| 406 | ctk_list_store_append (values, &iter); |
| 407 | ctk_list_store_set (values, &iter, 0, "urdu", -1); |
| 408 | ctk_list_store_append (values, &iter); |
| 409 | ctk_list_store_set (values, &iter, 0, "sumerian", -1); |
| 410 | g_object_set (cell, |
| 411 | "has-entry", FALSE(0), |
| 412 | "model", values, |
| 413 | "text-column", 0, |
| 414 | "editable", TRUE(!(0)), |
| 415 | NULL((void*)0)); |
| 416 | ctk_tree_view_column_pack_start (column, cell, FALSE(0)); |
| 417 | ctk_tree_view_column_set_cell_data_func (column, cell, state_cell_func, group, NULL((void*)0)); |
| 418 | 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); |
| 419 | ctk_tree_view_append_column (CTK_TREE_VIEW (tv)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((tv)), ((ctk_tree_view_get_type ())))))), column); |
| 420 | |
| 421 | return tv; |
| 422 | } |
| 423 | |
| 424 | /* Dynamic menu changes {{{1 */ |
| 425 | |
| 426 | static void |
| 427 | toggle_sumerian (CtkToggleButton *button, |
| 428 | gpointer data G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 429 | { |
| 430 | GMenuModel *model; |
| 431 | gboolean adding; |
| 432 | GMenuModel *m; |
| 433 | |
| 434 | model = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model"); |
| 435 | |
| 436 | adding = ctk_toggle_button_get_active (button); |
| 437 | |
| 438 | m = g_menu_model_get_item_link (model, g_menu_model_get_n_items (model) - 1, G_MENU_LINK_SECTION"section"); |
| 439 | m = g_menu_model_get_item_link (m, g_menu_model_get_n_items (m) - 1, G_MENU_LINK_SUBMENU"submenu"); |
| 440 | if (adding) |
| 441 | g_menu_append (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), "Sumerian", "lang::sumerian"); |
| 442 | else |
| 443 | 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); |
| 444 | } |
| 445 | |
| 446 | static void |
| 447 | action_list_add (CtkTreeModel *store, |
| 448 | const gchar *action) |
| 449 | { |
| 450 | CtkTreeIter iter; |
| 451 | |
| 452 | ctk_list_store_append (CTK_LIST_STORE (store)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), ((ctk_list_store_get_type ())))))), &iter); |
| 453 | 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); |
| 454 | } |
| 455 | |
| 456 | static void |
| 457 | action_list_remove (CtkTreeModel *store, |
| 458 | const gchar *action) |
| 459 | { |
| 460 | CtkTreeIter iter; |
| 461 | gchar *text; |
| 462 | |
| 463 | ctk_tree_model_get_iter_first (store, &iter); |
| 464 | do { |
| 465 | ctk_tree_model_get (store, &iter, 0, &text, -1); |
| 466 | if (g_strcmp0 (action, text) == 0) |
| 467 | { |
| 468 | g_free (text); |
| 469 | ctk_list_store_remove (CTK_LIST_STORE (store)((((CtkListStore*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((store)), ((ctk_list_store_get_type ())))))), &iter); |
| 470 | break; |
| 471 | } |
| 472 | g_free (text); |
| 473 | } while (ctk_tree_model_iter_next (store, &iter)); |
| 474 | } |
| 475 | |
| 476 | static void |
| 477 | toggle_italic (CtkToggleButton *button, gpointer data) |
| 478 | { |
| 479 | GMenuModel *model; |
| 480 | GActionGroup *group; |
| 481 | gboolean adding; |
| 482 | GMenuModel *m; |
| 483 | CtkTreeView *tv = data; |
| 484 | CtkTreeModel *store; |
| 485 | |
| 486 | model = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model"); |
| 487 | group = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group"); |
| 488 | |
| 489 | store = ctk_tree_view_get_model (tv); |
| 490 | |
| 491 | adding = ctk_toggle_button_get_active (button); |
| 492 | |
| 493 | m = g_menu_model_get_item_link (model, g_menu_model_get_n_items (model) - 1, G_MENU_LINK_SECTION"section"); |
| 494 | if (adding) |
| 495 | { |
| 496 | GSimpleAction *action; |
| 497 | |
| 498 | action = g_simple_action_new_stateful ("italic", NULL((void*)0), g_variant_new_boolean (FALSE(0))); |
| 499 | 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 ()))))))); |
| 500 | 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); |
| 501 | g_object_unref (action); |
| 502 | action_list_add (store, "italic"); |
| 503 | g_menu_insert (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), 1, "Italic", "italic"); |
| 504 | } |
| 505 | else |
| 506 | { |
| 507 | g_action_map_remove_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), "italic"); |
| 508 | action_list_remove (store, "italic"); |
| 509 | g_menu_remove (G_MENU (m)((((GMenu*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((m)), ((g_menu_get_type ())))))), 1); |
| 510 | } |
| 511 | } |
| 512 | |
| 513 | static void |
| 514 | toggle_speed (CtkToggleButton *button, gpointer data) |
| 515 | { |
| 516 | GMenuModel *model; |
| 517 | GActionGroup *group; |
| 518 | gboolean adding; |
| 519 | GMenuModel *m; |
| 520 | CtkTreeView *tv = data; |
| 521 | CtkTreeModel *store; |
| 522 | |
| 523 | model = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model"); |
| 524 | group = g_object_get_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group"); |
| 525 | |
| 526 | store = ctk_tree_view_get_model (tv); |
| 527 | |
| 528 | adding = ctk_toggle_button_get_active (button); |
| 529 | |
| 530 | m = g_menu_model_get_item_link (model, 1, G_MENU_LINK_SECTION"section"); |
| 531 | if (adding) |
| 532 | { |
| 533 | GSimpleAction *action; |
| 534 | GMenu *submenu; |
| 535 | |
| 536 | action = g_simple_action_new ("faster", NULL((void*)0)); |
| 537 | 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 ()))))))); |
| 538 | 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); |
| 539 | g_object_unref (action); |
| 540 | |
| 541 | action = g_simple_action_new ("slower", NULL((void*)0)); |
| 542 | 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 ()))))))); |
| 543 | 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); |
| 544 | g_object_unref (action); |
| 545 | |
| 546 | action_list_add (store, "faster"); |
| 547 | action_list_add (store, "slower"); |
| 548 | |
| 549 | submenu = g_menu_new (); |
| 550 | g_menu_append (submenu, "Faster", "faster"); |
| 551 | g_menu_append (submenu, "Slower", "slower"); |
| 552 | 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 ()))))))); |
| 553 | } |
| 554 | else |
| 555 | { |
| 556 | g_action_map_remove_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), "faster"); |
| 557 | g_action_map_remove_action (G_ACTION_MAP (group)((((GActionMap*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((group)), ((g_action_map_get_type ())))))), "slower"); |
| 558 | |
| 559 | action_list_remove (store, "faster"); |
| 560 | action_list_remove (store, "slower"); |
| 561 | |
| 562 | 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); |
| 563 | } |
| 564 | } |
| 565 | static CtkWidget * |
| 566 | create_add_remove_buttons (GActionGroup *group, |
| 567 | GMenuModel *model, |
| 568 | CtkWidget *treeview) |
| 569 | { |
| 570 | CtkWidget *box; |
| 571 | CtkWidget *button; |
| 572 | |
| 573 | box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 6); |
| 574 | |
| 575 | button = ctk_check_button_new_with_label ("Add Italic"); |
| 576 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
| 577 | |
| 578 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group", group); |
| 579 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model", model); |
| 580 | |
| 581 | g_signal_connect (button, "toggled",g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_italic))), (treeview), ((void*)0), (GConnectFlags) 0) |
| 582 | G_CALLBACK (toggle_italic), treeview)g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_italic))), (treeview), ((void*)0), (GConnectFlags) 0); |
| 583 | |
| 584 | button = ctk_check_button_new_with_label ("Add Sumerian"); |
| 585 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
| 586 | |
| 587 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group", group); |
| 588 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model", model); |
| 589 | |
| 590 | g_signal_connect (button, "toggled",g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_sumerian))), (((void*)0)), ((void*)0), (GConnectFlags) 0) |
| 591 | G_CALLBACK (toggle_sumerian), NULL)g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_sumerian))), (((void*)0)), ((void*)0), (GConnectFlags) 0); |
| 592 | |
| 593 | button = ctk_check_button_new_with_label ("Add Speed"); |
| 594 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
| 595 | |
| 596 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "group", group); |
| 597 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "model", model); |
| 598 | |
| 599 | g_signal_connect (button, "toggled",g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_speed))), (treeview), ((void*)0), (GConnectFlags) 0) |
| 600 | G_CALLBACK (toggle_speed), treeview)g_signal_connect_data ((button), ("toggled"), (((GCallback) ( toggle_speed))), (treeview), ((void*)0), (GConnectFlags) 0); |
| 601 | return box; |
| 602 | } |
| 603 | |
| 604 | /* main {{{1 */ |
| 605 | |
| 606 | #define BUS_NAME"org.ctk.TestMenus" "org.ctk.TestMenus" |
| 607 | #define OBJ_PATH"/org/ctk/TestMenus" "/org/ctk/TestMenus" |
| 608 | |
| 609 | static gboolean |
| 610 | on_delete_event (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 611 | CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 612 | gpointer user_data G_GNUC_UNUSED__attribute__ ((__unused__))) |
| 613 | { |
| 614 | ctk_main_quit (); |
| 615 | return TRUE(!(0)); |
| 616 | } |
| 617 | |
| 618 | int |
| 619 | main (int argc, char *argv[]) |
| 620 | { |
| 621 | CtkWidget *window; |
| 622 | CtkWidget *box; |
| 623 | GMenuModel *model; |
| 624 | GActionGroup *group; |
| 625 | GDBusConnection *bus; |
| 626 | GError *error = NULL((void*)0); |
| 627 | gboolean do_export = FALSE(0); |
| 628 | gboolean do_import = FALSE(0); |
| 629 | GOptionEntry entries[] = { |
| 630 | { "export", 0, 0, G_OPTION_ARG_NONE, &do_export, "Export actions and menus over D-Bus", NULL((void*)0) }, |
| 631 | { "import", 0, 0, G_OPTION_ARG_NONE, &do_import, "Use exported actions and menus", NULL((void*)0) }, |
| 632 | { NULL((void*)0), } |
| 633 | }; |
| 634 | |
| 635 | ctk_init_with_args (&argc, &argv, NULL((void*)0), entries, NULL((void*)0), NULL((void*)0)); |
| 636 | |
| 637 | if (do_export && do_import) |
| 638 | { |
| 639 | g_error ("can't have it both ways\n"); |
| 640 | exit (1); |
| 641 | } |
| 642 | |
| 643 | window = ctk_window_new (CTK_WINDOW_TOPLEVEL); |
| 644 | 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); |
| 645 | box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 6); |
| 646 | ctk_container_add (CTK_CONTAINER (window)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((window)), ((ctk_container_get_type ())))))), box); |
| 647 | |
| 648 | bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL((void*)0), NULL((void*)0)); |
| 649 | |
| 650 | if (do_import) |
| 651 | { |
| 652 | g_print ("Getting menus from the bus...\n"); |
| 653 | model = (GMenuModel*)g_dbus_menu_model_get (bus, BUS_NAME"org.ctk.TestMenus", OBJ_PATH"/org/ctk/TestMenus"); |
| 654 | g_print ("Getting actions from the bus...\n"); |
| 655 | group = (GActionGroup*)g_dbus_action_group_get (bus, BUS_NAME"org.ctk.TestMenus", OBJ_PATH"/org/ctk/TestMenus"); |
| 656 | } |
| 657 | else |
| 658 | { |
| 659 | CtkWidget *tv; |
| 660 | CtkWidget *buttons; |
| 661 | |
| 662 | group = get_group (); |
| 663 | model = get_model (); |
| 664 | |
| 665 | tv = create_action_treeview (group); |
| 666 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), tv); |
| 667 | buttons = create_add_remove_buttons (group, model, tv); |
| 668 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), buttons); |
| 669 | } |
| 670 | |
| 671 | if (do_export) |
| 672 | { |
| 673 | g_print ("Exporting menus on the bus...\n"); |
| 674 | if (!g_dbus_connection_export_menu_model (bus, OBJ_PATH"/org/ctk/TestMenus", model, &error)) |
| 675 | { |
| 676 | g_warning ("Menu export failed: %s", error->message); |
| 677 | exit (1); |
| 678 | } |
| 679 | g_print ("Exporting actions on the bus...\n"); |
| 680 | if (!g_dbus_connection_export_action_group (bus, OBJ_PATH"/org/ctk/TestMenus", group, &error)) |
| 681 | { |
| 682 | g_warning ("Action export failed: %s", error->message); |
| 683 | exit (1); |
| 684 | } |
| 685 | 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)); |
| 686 | } |
| 687 | else |
| 688 | { |
| 689 | CtkWidget *button; |
| 690 | |
| 691 | button = ctk_menu_button_new (); |
| 692 | ctk_button_set_label (CTK_BUTTON (button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), ((ctk_button_get_type ())))))), "Click here"); |
| 693 | 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))); |
| 694 | 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); |
| 695 | ctk_widget_insert_action_group (button, "actions", group); |
| 696 | ctk_container_add (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), button); |
| 697 | } |
| 698 | |
| 699 | ctk_widget_show_all (window); |
| 700 | |
| 701 | ctk_main (); |
| 702 | |
| 703 | return 0; |
| 704 | } |
| 705 | |
| 706 | /* Epilogue {{{1 */ |
| 707 | /* vim:set foldmethod=marker: */ |