| File: | ctk/ctkactionable.c |
| Warning: | line 78, column 27 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 | /* |
| 2 | * Copyright © 2012 Canonical Limited |
| 3 | * |
| 4 | * This library is free software: you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU Lesser General Public License as |
| 6 | * published by the Free Software Foundation; either version 2 of the |
| 7 | * licence or (at your option) any later version. |
| 8 | * |
| 9 | * This library is distributed in the hope that it will be useful, but |
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | * Lesser General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU Lesser General Public |
| 15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| 16 | * |
| 17 | * Authors: Ryan Lortie <desrt@desrt.ca> |
| 18 | */ |
| 19 | |
| 20 | #include "config.h" |
| 21 | |
| 22 | #include "ctkactionable.h" |
| 23 | |
| 24 | #include "ctkwidget.h" |
| 25 | #include "ctkintl.h" |
| 26 | |
| 27 | /** |
| 28 | * SECTION:ctkactionable |
| 29 | * @title: CtkActionable |
| 30 | * @short_description: An interface for widgets that can be associated |
| 31 | * with actions |
| 32 | * |
| 33 | * This interface provides a convenient way of associating widgets with |
| 34 | * actions on a #CtkApplicationWindow or #CtkApplication. |
| 35 | * |
| 36 | * It primarily consists of two properties: #CtkActionable:action-name |
| 37 | * and #CtkActionable:action-target. There are also some convenience APIs |
| 38 | * for setting these properties. |
| 39 | * |
| 40 | * The action will be looked up in action groups that are found among |
| 41 | * the widgets ancestors. Most commonly, these will be the actions with |
| 42 | * the “win.” or “app.” prefix that are associated with the #CtkApplicationWindow |
| 43 | * or #CtkApplication, but other action groups that are added with |
| 44 | * ctk_widget_insert_action_group() will be consulted as well. |
| 45 | * |
| 46 | * Since: 3.4 |
| 47 | **/ |
| 48 | |
| 49 | /** |
| 50 | * CtkActionable: |
| 51 | * |
| 52 | * An opaque pointer type. |
| 53 | **/ |
| 54 | |
| 55 | /** |
| 56 | * CtkActionableInterface: |
| 57 | * @get_action_name: virtual function for ctk_actionable_get_action_name() |
| 58 | * @set_action_name: virtual function for ctk_actionable_set_action_name() |
| 59 | * @get_action_target_value: virtual function for ctk_actionable_get_action_target_value() |
| 60 | * @set_action_target_value: virtual function for ctk_actionable_set_action_target_value() |
| 61 | * |
| 62 | * The interface vtable for #CtkActionable. |
| 63 | **/ |
| 64 | |
| 65 | G_DEFINE_INTERFACE (CtkActionable, ctk_actionable, CTK_TYPE_WIDGET)static void ctk_actionable_default_init (CtkActionableInterface *klass); GType ctk_actionable_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); (void) (0 ? (gpointer) * ( &static_g_define_type_id) : ((void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = g_type_register_static_simple (((GType) ((2) << (2)) ), g_intern_static_string ("CtkActionable"), sizeof (CtkActionableInterface ), (GClassInitFunc)(void (*)(void)) ctk_actionable_default_init , 0, (GInstanceInitFunc)((void*)0), (GTypeFlags) 0); if ((ctk_widget_get_type ()) != ((GType) ((0) << (2)))) g_type_interface_add_prerequisite (g_define_type_id, (ctk_widget_get_type ())); { {;;} } (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); 0 ? (void ) (*(&static_g_define_type_id) = (g_define_type_id)) : (void ) 0; g_once_init_leave_pointer ((&static_g_define_type_id ), (gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id ; } |
| 66 | |
| 67 | static void |
| 68 | ctk_actionable_default_init (CtkActionableInterface *iface) |
| 69 | { |
| 70 | g_object_interface_install_property (iface, |
| 71 | g_param_spec_string ("action-name", P_("Action name")g_dgettext("ctk30" "-properties","Action name"), |
| 72 | P_("The name of the associated action, like 'app.quit'")g_dgettext("ctk30" "-properties","The name of the associated action, like 'app.quit'" ), |
| 73 | NULL((void*)0), G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB ))); |
| 74 | |
| 75 | g_object_interface_install_property (iface, |
| 76 | g_param_spec_variant ("action-target", P_("Action target value")g_dgettext("ctk30" "-properties","Action target value"), |
| 77 | P_("The parameter for action invocations")g_dgettext("ctk30" "-properties","The parameter for action invocations" ), |
| 78 | G_VARIANT_TYPE_ANY((const GVariantType *) "*"), NULL((void*)0), G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB ))); |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * ctk_actionable_get_action_name: |
| 83 | * @actionable: a #CtkActionable widget |
| 84 | * |
| 85 | * Gets the action name for @actionable. |
| 86 | * |
| 87 | * See ctk_actionable_set_action_name() for more information. |
| 88 | * |
| 89 | * Returns: (nullable): the action name, or %NULL if none is set |
| 90 | * |
| 91 | * Since: 3.4 |
| 92 | **/ |
| 93 | const gchar * |
| 94 | ctk_actionable_get_action_name (CtkActionable *actionable) |
| 95 | { |
| 96 | g_return_val_if_fail (CTK_IS_ACTIONABLE (actionable), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((actionable)); GType __t = ((ctk_actionable_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; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ACTIONABLE (actionable)"); return ((( void*)0)); } } while (0); |
| 97 | |
| 98 | return CTK_ACTIONABLE_GET_IFACE (actionable)((((CtkActionableInterface*) g_type_interface_peek (((GTypeInstance *) ((actionable)))->g_class, ((ctk_actionable_get_type ()) ))))) |
| 99 | ->get_action_name (actionable); |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * ctk_actionable_set_action_name: |
| 104 | * @actionable: a #CtkActionable widget |
| 105 | * @action_name: (nullable): an action name, or %NULL |
| 106 | * |
| 107 | * Specifies the name of the action with which this widget should be |
| 108 | * associated. If @action_name is %NULL then the widget will be |
| 109 | * unassociated from any previous action. |
| 110 | * |
| 111 | * Usually this function is used when the widget is located (or will be |
| 112 | * located) within the hierarchy of a #CtkApplicationWindow. |
| 113 | * |
| 114 | * Names are of the form “win.save” or “app.quit” for actions on the |
| 115 | * containing #CtkApplicationWindow or its associated #CtkApplication, |
| 116 | * respectively. This is the same form used for actions in the #GMenu |
| 117 | * associated with the window. |
| 118 | * |
| 119 | * Since: 3.4 |
| 120 | **/ |
| 121 | void |
| 122 | ctk_actionable_set_action_name (CtkActionable *actionable, |
| 123 | const gchar *action_name) |
| 124 | { |
| 125 | g_return_if_fail (CTK_IS_ACTIONABLE (actionable))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((actionable)); GType __t = ((ctk_actionable_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; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ACTIONABLE (actionable)"); return; } } while (0); |
| 126 | |
| 127 | CTK_ACTIONABLE_GET_IFACE (actionable)((((CtkActionableInterface*) g_type_interface_peek (((GTypeInstance *) ((actionable)))->g_class, ((ctk_actionable_get_type ()) ))))) |
| 128 | ->set_action_name (actionable, action_name); |
| 129 | } |
| 130 | |
| 131 | /** |
| 132 | * ctk_actionable_get_action_target_value: |
| 133 | * @actionable: a #CtkActionable widget |
| 134 | * |
| 135 | * Gets the current target value of @actionable. |
| 136 | * |
| 137 | * See ctk_actionable_set_action_target_value() for more information. |
| 138 | * |
| 139 | * Returns: (transfer none): the current target value |
| 140 | * |
| 141 | * Since: 3.4 |
| 142 | **/ |
| 143 | GVariant * |
| 144 | ctk_actionable_get_action_target_value (CtkActionable *actionable) |
| 145 | { |
| 146 | g_return_val_if_fail (CTK_IS_ACTIONABLE (actionable), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((actionable)); GType __t = ((ctk_actionable_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; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ACTIONABLE (actionable)"); return ((( void*)0)); } } while (0); |
| 147 | |
| 148 | return CTK_ACTIONABLE_GET_IFACE (actionable)((((CtkActionableInterface*) g_type_interface_peek (((GTypeInstance *) ((actionable)))->g_class, ((ctk_actionable_get_type ()) ))))) |
| 149 | ->get_action_target_value (actionable); |
| 150 | } |
| 151 | |
| 152 | /** |
| 153 | * ctk_actionable_set_action_target_value: |
| 154 | * @actionable: a #CtkActionable widget |
| 155 | * @target_value: (nullable): a #GVariant to set as the target value, or %NULL |
| 156 | * |
| 157 | * Sets the target value of an actionable widget. |
| 158 | * |
| 159 | * If @target_value is %NULL then the target value is unset. |
| 160 | * |
| 161 | * The target value has two purposes. First, it is used as the |
| 162 | * parameter to activation of the action associated with the |
| 163 | * #CtkActionable widget. Second, it is used to determine if the widget |
| 164 | * should be rendered as “active” — the widget is active if the state |
| 165 | * is equal to the given target. |
| 166 | * |
| 167 | * Consider the example of associating a set of buttons with a #GAction |
| 168 | * with string state in a typical “radio button” situation. Each button |
| 169 | * will be associated with the same action, but with a different target |
| 170 | * value for that action. Clicking on a particular button will activate |
| 171 | * the action with the target of that button, which will typically cause |
| 172 | * the action’s state to change to that value. Since the action’s state |
| 173 | * is now equal to the target value of the button, the button will now |
| 174 | * be rendered as active (and the other buttons, with different targets, |
| 175 | * rendered inactive). |
| 176 | * |
| 177 | * Since: 3.4 |
| 178 | **/ |
| 179 | void |
| 180 | ctk_actionable_set_action_target_value (CtkActionable *actionable, |
| 181 | GVariant *target_value) |
| 182 | { |
| 183 | g_return_if_fail (CTK_IS_ACTIONABLE (actionable))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((actionable)); GType __t = ((ctk_actionable_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; } )))))) { } else { g_return_if_fail_warning ("Ctk", ((const char *) (__func__)), "CTK_IS_ACTIONABLE (actionable)"); return; } } while (0); |
| 184 | |
| 185 | CTK_ACTIONABLE_GET_IFACE (actionable)((((CtkActionableInterface*) g_type_interface_peek (((GTypeInstance *) ((actionable)))->g_class, ((ctk_actionable_get_type ()) ))))) |
| 186 | ->set_action_target_value (actionable, target_value); |
| 187 | } |
| 188 | |
| 189 | /** |
| 190 | * ctk_actionable_set_action_target: |
| 191 | * @actionable: a #CtkActionable widget |
| 192 | * @format_string: a GVariant format string |
| 193 | * @...: arguments appropriate for @format_string |
| 194 | * |
| 195 | * Sets the target of an actionable widget. |
| 196 | * |
| 197 | * This is a convenience function that calls g_variant_new() for |
| 198 | * @format_string and uses the result to call |
| 199 | * ctk_actionable_set_action_target_value(). |
| 200 | * |
| 201 | * If you are setting a string-valued target and want to set the action |
| 202 | * name at the same time, you can use |
| 203 | * ctk_actionable_set_detailed_action_name (). |
| 204 | * |
| 205 | * Since: 3.4 |
| 206 | **/ |
| 207 | void |
| 208 | ctk_actionable_set_action_target (CtkActionable *actionable, |
| 209 | const gchar *format_string, |
| 210 | ...) |
| 211 | { |
| 212 | va_list ap; |
| 213 | |
| 214 | va_start (ap, format_string)__builtin_va_start(ap, format_string); |
| 215 | ctk_actionable_set_action_target_value (actionable, g_variant_new_va (format_string, NULL((void*)0), &ap)); |
| 216 | va_end (ap)__builtin_va_end(ap); |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * ctk_actionable_set_detailed_action_name: |
| 221 | * @actionable: a #CtkActionable widget |
| 222 | * @detailed_action_name: the detailed action name |
| 223 | * |
| 224 | * Sets the action-name and associated string target value of an |
| 225 | * actionable widget. |
| 226 | * |
| 227 | * @detailed_action_name is a string in the format accepted by |
| 228 | * g_action_parse_detailed_name(). |
| 229 | * |
| 230 | * (Note that prior to version 3.22.25, |
| 231 | * this function is only usable for actions with a simple "s" target, and |
| 232 | * @detailed_action_name must be of the form `"action::target"` where |
| 233 | * `action` is the action name and `target` is the string to use |
| 234 | * as the target.) |
| 235 | * |
| 236 | * Since: 3.4 |
| 237 | **/ |
| 238 | void |
| 239 | ctk_actionable_set_detailed_action_name (CtkActionable *actionable, |
| 240 | const gchar *detailed_action_name) |
| 241 | { |
| 242 | GError *error = NULL((void*)0); |
| 243 | GVariant *target; |
| 244 | gchar *name; |
| 245 | |
| 246 | if (detailed_action_name == NULL((void*)0)) |
| 247 | { |
| 248 | ctk_actionable_set_action_name (actionable, NULL((void*)0)); |
| 249 | ctk_actionable_set_action_target_value (actionable, NULL((void*)0)); |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | if (!g_action_parse_detailed_name (detailed_action_name, &name, &target, &error)) |
| 254 | g_error ("ctk_actionable_set_detailed_action_name: %s", error->message); |
| 255 | |
| 256 | ctk_actionable_set_action_name (actionable, name); |
| 257 | ctk_actionable_set_action_target_value (actionable, target); |
| 258 | |
| 259 | if (target) |
| 260 | g_variant_unref (target); |
| 261 | g_free (name); |
| 262 | } |
| 263 |