(root)/
glib-2.79.0/
gio/
gsimpleaction.c
       1  /*
       2   * Copyright © 2010 Codethink Limited
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General
      17   * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   *
      19   * Authors: Ryan Lortie <desrt@desrt.ca>
      20   */
      21  
      22  #include "config.h"
      23  
      24  #include "gsimpleaction.h"
      25  
      26  #include "gaction.h"
      27  #include "glibintl.h"
      28  
      29  /**
      30   * GSimpleAction:
      31   *
      32   * A `GSimpleAction` is the obvious simple implementation of the
      33   * [iface@Gio.Action] interface. This is the easiest way to create an action for
      34   * purposes of adding it to a [class@Gio.SimpleActionGroup].
      35   *
      36   * See also [class@Gtk.Action].
      37   */
      38  
      39  struct _GSimpleAction
      40  {
      41    GObject       parent_instance;
      42  
      43    gchar        *name;
      44    GVariantType *parameter_type;
      45    gboolean      enabled;
      46    GVariant     *state;
      47    GVariant     *state_hint;
      48    gboolean      state_set_already;
      49  };
      50  
      51  typedef GObjectClass GSimpleActionClass;
      52  
      53  static void g_simple_action_iface_init (GActionInterface *iface);
      54  G_DEFINE_TYPE_WITH_CODE (GSimpleAction, g_simple_action, G_TYPE_OBJECT,
      55    G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, g_simple_action_iface_init))
      56  
      57  enum
      58  {
      59    PROP_NONE,
      60    PROP_NAME,
      61    PROP_PARAMETER_TYPE,
      62    PROP_ENABLED,
      63    PROP_STATE_TYPE,
      64    PROP_STATE
      65  };
      66  
      67  enum
      68  {
      69    SIGNAL_CHANGE_STATE,
      70    SIGNAL_ACTIVATE,
      71    NR_SIGNALS
      72  };
      73  
      74  static guint g_simple_action_signals[NR_SIGNALS];
      75  
      76  static const gchar *
      77  g_simple_action_get_name (GAction *action)
      78  {
      79    GSimpleAction *simple = G_SIMPLE_ACTION (action);
      80  
      81    return simple->name;
      82  }
      83  
      84  static const GVariantType *
      85  g_simple_action_get_parameter_type (GAction *action)
      86  {
      87    GSimpleAction *simple = G_SIMPLE_ACTION (action);
      88  
      89    return simple->parameter_type;
      90  }
      91  
      92  static const GVariantType *
      93  g_simple_action_get_state_type (GAction *action)
      94  {
      95    GSimpleAction *simple = G_SIMPLE_ACTION (action);
      96  
      97    if (simple->state != NULL)
      98      return g_variant_get_type (simple->state);
      99    else
     100      return NULL;
     101  }
     102  
     103  static GVariant *
     104  g_simple_action_get_state_hint (GAction *action)
     105  {
     106    GSimpleAction *simple = G_SIMPLE_ACTION (action);
     107  
     108    if (simple->state_hint != NULL)
     109      return g_variant_ref (simple->state_hint);
     110    else
     111      return NULL;
     112  }
     113  
     114  static gboolean
     115  g_simple_action_get_enabled (GAction *action)
     116  {
     117    GSimpleAction *simple = G_SIMPLE_ACTION (action);
     118  
     119    return simple->enabled;
     120  }
     121  
     122  static void
     123  g_simple_action_change_state (GAction  *action,
     124                                GVariant *value)
     125  {
     126    GSimpleAction *simple = G_SIMPLE_ACTION (action);
     127  
     128    /* If the user connected a signal handler then they are responsible
     129     * for handling state changes.
     130     */
     131    if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, TRUE))
     132      g_signal_emit (action, g_simple_action_signals[SIGNAL_CHANGE_STATE], 0, value);
     133  
     134    /* If not, then the default behaviour is to just set the state. */
     135    else
     136      g_simple_action_set_state (simple, value);
     137  }
     138  
     139  /**
     140   * g_simple_action_set_state:
     141   * @simple: a #GSimpleAction
     142   * @value: the new #GVariant for the state
     143   *
     144   * Sets the state of the action.
     145   *
     146   * This directly updates the 'state' property to the given value.
     147   *
     148   * This should only be called by the implementor of the action.  Users
     149   * of the action should not attempt to directly modify the 'state'
     150   * property.  Instead, they should call g_action_change_state() to
     151   * request the change.
     152   *
     153   * If the @value GVariant is floating, it is consumed.
     154   *
     155   * Since: 2.30
     156   **/
     157  void
     158  g_simple_action_set_state (GSimpleAction *simple,
     159                             GVariant      *value)
     160  {
     161    g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
     162    g_return_if_fail (value != NULL);
     163  
     164    {
     165      const GVariantType *state_type;
     166  
     167      state_type = simple->state ?
     168                     g_variant_get_type (simple->state) : NULL;
     169      g_return_if_fail (state_type != NULL);
     170      g_return_if_fail (g_variant_is_of_type (value, state_type));
     171    }
     172  
     173    g_variant_ref_sink (value);
     174  
     175    if (!simple->state || !g_variant_equal (simple->state, value))
     176      {
     177        if (simple->state)
     178          g_variant_unref (simple->state);
     179  
     180        simple->state = g_variant_ref (value);
     181  
     182        g_object_notify (G_OBJECT (simple), "state");
     183      }
     184  
     185    g_variant_unref (value);
     186  }
     187  
     188  static GVariant *
     189  g_simple_action_get_state (GAction *action)
     190  {
     191    GSimpleAction *simple = G_SIMPLE_ACTION (action);
     192  
     193    return simple->state ? g_variant_ref (simple->state) : NULL;
     194  }
     195  
     196  static void
     197  g_simple_action_activate (GAction  *action,
     198                            GVariant *parameter)
     199  {
     200    GSimpleAction *simple = G_SIMPLE_ACTION (action);
     201  
     202    g_return_if_fail (simple->parameter_type == NULL ?
     203                        parameter == NULL :
     204                      (parameter != NULL &&
     205                       g_variant_is_of_type (parameter,
     206                                             simple->parameter_type)));
     207  
     208    if (parameter != NULL)
     209      g_variant_ref_sink (parameter);
     210  
     211    if (simple->enabled)
     212      {
     213        /* If the user connected a signal handler then they are responsible
     214         * for handling activation.
     215         */
     216        if (g_signal_has_handler_pending (action, g_simple_action_signals[SIGNAL_ACTIVATE], 0, TRUE))
     217          g_signal_emit (action, g_simple_action_signals[SIGNAL_ACTIVATE], 0, parameter);
     218  
     219        /* If not, do some reasonable defaults for stateful actions. */
     220        else if (simple->state)
     221          {
     222            /* If we have no parameter and this is a boolean action, toggle. */
     223            if (parameter == NULL && g_variant_is_of_type (simple->state, G_VARIANT_TYPE_BOOLEAN))
     224              {
     225                gboolean was_enabled = g_variant_get_boolean (simple->state);
     226                g_simple_action_change_state (action, g_variant_new_boolean (!was_enabled));
     227              }
     228  
     229            /* else, if the parameter and state type are the same, do a change-state */
     230            else if (g_variant_is_of_type (simple->state, g_variant_get_type (parameter)))
     231              g_simple_action_change_state (action, parameter);
     232          }
     233      }
     234  
     235    if (parameter != NULL)
     236      g_variant_unref (parameter);
     237  }
     238  
     239  static void
     240  g_simple_action_set_property (GObject    *object,
     241                                guint       prop_id,
     242                                const GValue     *value,
     243                                GParamSpec *pspec)
     244  {
     245    GSimpleAction *action = G_SIMPLE_ACTION (object);
     246  
     247    switch (prop_id)
     248      {
     249      case PROP_NAME:
     250        action->name = g_strdup (g_value_get_string (value));
     251        break;
     252  
     253      case PROP_PARAMETER_TYPE:
     254        action->parameter_type = g_value_dup_boxed (value);
     255        break;
     256  
     257      case PROP_ENABLED:
     258        action->enabled = g_value_get_boolean (value);
     259        break;
     260  
     261      case PROP_STATE:
     262        /* The first time we see this (during construct) we should just
     263         * take the state as it was handed to us.
     264         *
     265         * After that, we should make sure we go through the same checks
     266         * as the C API.
     267         */
     268        if (!action->state_set_already)
     269          {
     270            action->state = g_value_dup_variant (value);
     271            action->state_set_already = TRUE;
     272          }
     273        else
     274          g_simple_action_set_state (action, g_value_get_variant (value));
     275  
     276        break;
     277  
     278      default:
     279        g_assert_not_reached ();
     280      }
     281  }
     282  
     283  static void
     284  g_simple_action_get_property (GObject    *object,
     285                                guint       prop_id,
     286                                GValue     *value,
     287                                GParamSpec *pspec)
     288  {
     289    GAction *action = G_ACTION (object);
     290  
     291    switch (prop_id)
     292      {
     293      case PROP_NAME:
     294        g_value_set_string (value, g_simple_action_get_name (action));
     295        break;
     296  
     297      case PROP_PARAMETER_TYPE:
     298        g_value_set_boxed (value, g_simple_action_get_parameter_type (action));
     299        break;
     300  
     301      case PROP_ENABLED:
     302        g_value_set_boolean (value, g_simple_action_get_enabled (action));
     303        break;
     304  
     305      case PROP_STATE_TYPE:
     306        g_value_set_boxed (value, g_simple_action_get_state_type (action));
     307        break;
     308  
     309      case PROP_STATE:
     310        g_value_take_variant (value, g_simple_action_get_state (action));
     311        break;
     312  
     313      default:
     314        g_assert_not_reached ();
     315      }
     316  }
     317  
     318  static void
     319  g_simple_action_finalize (GObject *object)
     320  {
     321    GSimpleAction *simple = G_SIMPLE_ACTION (object);
     322  
     323    g_free (simple->name);
     324    if (simple->parameter_type)
     325      g_variant_type_free (simple->parameter_type);
     326    if (simple->state)
     327      g_variant_unref (simple->state);
     328    if (simple->state_hint)
     329      g_variant_unref (simple->state_hint);
     330  
     331    G_OBJECT_CLASS (g_simple_action_parent_class)
     332      ->finalize (object);
     333  }
     334  
     335  void
     336  g_simple_action_init (GSimpleAction *simple)
     337  {
     338    simple->enabled = TRUE;
     339  }
     340  
     341  void
     342  g_simple_action_iface_init (GActionInterface *iface)
     343  {
     344    iface->get_name = g_simple_action_get_name;
     345    iface->get_parameter_type = g_simple_action_get_parameter_type;
     346    iface->get_state_type = g_simple_action_get_state_type;
     347    iface->get_state_hint = g_simple_action_get_state_hint;
     348    iface->get_enabled = g_simple_action_get_enabled;
     349    iface->get_state = g_simple_action_get_state;
     350    iface->change_state = g_simple_action_change_state;
     351    iface->activate = g_simple_action_activate;
     352  }
     353  
     354  void
     355  g_simple_action_class_init (GSimpleActionClass *class)
     356  {
     357    GObjectClass *object_class = G_OBJECT_CLASS (class);
     358  
     359    object_class->set_property = g_simple_action_set_property;
     360    object_class->get_property = g_simple_action_get_property;
     361    object_class->finalize = g_simple_action_finalize;
     362  
     363    /**
     364     * GSimpleAction::activate:
     365     * @simple: the #GSimpleAction
     366     * @parameter: (nullable): the parameter to the activation, or %NULL if it has
     367     *   no parameter
     368     *
     369     * Indicates that the action was just activated.
     370     *
     371     * @parameter will always be of the expected type, i.e. the parameter type
     372     * specified when the action was created. If an incorrect type is given when
     373     * activating the action, this signal is not emitted.
     374     *
     375     * Since GLib 2.40, if no handler is connected to this signal then the
     376     * default behaviour for boolean-stated actions with a %NULL parameter
     377     * type is to toggle them via the #GSimpleAction::change-state signal.
     378     * For stateful actions where the state type is equal to the parameter
     379     * type, the default is to forward them directly to
     380     * #GSimpleAction::change-state.  This should allow almost all users
     381     * of #GSimpleAction to connect only one handler or the other.
     382     *
     383     * Since: 2.28
     384     */
     385    g_simple_action_signals[SIGNAL_ACTIVATE] =
     386      g_signal_new (I_("activate"),
     387                    G_TYPE_SIMPLE_ACTION,
     388                    G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
     389                    0, NULL, NULL,
     390                    NULL,
     391                    G_TYPE_NONE, 1,
     392                    G_TYPE_VARIANT);
     393  
     394    /**
     395     * GSimpleAction::change-state:
     396     * @simple: the #GSimpleAction
     397     * @value: (nullable): the requested value for the state
     398     *
     399     * Indicates that the action just received a request to change its
     400     * state.
     401     *
     402     * @value will always be of the correct state type, i.e. the type of the
     403     * initial state passed to g_simple_action_new_stateful(). If an incorrect
     404     * type is given when requesting to change the state, this signal is not
     405     * emitted.
     406     *
     407     * If no handler is connected to this signal then the default
     408     * behaviour is to call g_simple_action_set_state() to set the state
     409     * to the requested value. If you connect a signal handler then no
     410     * default action is taken. If the state should change then you must
     411     * call g_simple_action_set_state() from the handler.
     412     *
     413     * An example of a 'change-state' handler:
     414     * |[<!-- language="C" -->
     415     * static void
     416     * change_volume_state (GSimpleAction *action,
     417     *                      GVariant      *value,
     418     *                      gpointer       user_data)
     419     * {
     420     *   gint requested;
     421     *
     422     *   requested = g_variant_get_int32 (value);
     423     *
     424     *   // Volume only goes from 0 to 10
     425     *   if (0 <= requested && requested <= 10)
     426     *     g_simple_action_set_state (action, value);
     427     * }
     428     * ]|
     429     *
     430     * The handler need not set the state to the requested value.
     431     * It could set it to any value at all, or take some other action.
     432     *
     433     * Since: 2.30
     434     */
     435    g_simple_action_signals[SIGNAL_CHANGE_STATE] =
     436      g_signal_new (I_("change-state"),
     437                    G_TYPE_SIMPLE_ACTION,
     438                    G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
     439                    0, NULL, NULL,
     440                    NULL,
     441                    G_TYPE_NONE, 1,
     442                    G_TYPE_VARIANT);
     443  
     444    /**
     445     * GSimpleAction:name:
     446     *
     447     * The name of the action. This is mostly meaningful for identifying
     448     * the action once it has been added to a #GSimpleActionGroup.
     449     *
     450     * Since: 2.28
     451     **/
     452    g_object_class_install_property (object_class, PROP_NAME,
     453                                     g_param_spec_string ("name", NULL, NULL,
     454                                                          NULL,
     455                                                          G_PARAM_READWRITE |
     456                                                          G_PARAM_CONSTRUCT_ONLY |
     457                                                          G_PARAM_STATIC_STRINGS));
     458  
     459    /**
     460     * GSimpleAction:parameter-type:
     461     *
     462     * The type of the parameter that must be given when activating the
     463     * action.
     464     *
     465     * Since: 2.28
     466     **/
     467    g_object_class_install_property (object_class, PROP_PARAMETER_TYPE,
     468                                     g_param_spec_boxed ("parameter-type", NULL, NULL,
     469                                                         G_TYPE_VARIANT_TYPE,
     470                                                         G_PARAM_READWRITE |
     471                                                         G_PARAM_CONSTRUCT_ONLY |
     472                                                         G_PARAM_STATIC_STRINGS));
     473  
     474    /**
     475     * GSimpleAction:enabled:
     476     *
     477     * If @action is currently enabled.
     478     *
     479     * If the action is disabled then calls to g_action_activate() and
     480     * g_action_change_state() have no effect.
     481     *
     482     * Since: 2.28
     483     **/
     484    g_object_class_install_property (object_class, PROP_ENABLED,
     485                                     g_param_spec_boolean ("enabled", NULL, NULL,
     486                                                           TRUE,
     487                                                           G_PARAM_READWRITE |
     488                                                           G_PARAM_STATIC_STRINGS));
     489  
     490    /**
     491     * GSimpleAction:state-type:
     492     *
     493     * The #GVariantType of the state that the action has, or %NULL if the
     494     * action is stateless.
     495     *
     496     * Since: 2.28
     497     **/
     498    g_object_class_install_property (object_class, PROP_STATE_TYPE,
     499                                     g_param_spec_boxed ("state-type", NULL, NULL,
     500                                                         G_TYPE_VARIANT_TYPE,
     501                                                         G_PARAM_READABLE |
     502                                                         G_PARAM_STATIC_STRINGS));
     503  
     504    /**
     505     * GSimpleAction:state:
     506     *
     507     * The state of the action, or %NULL if the action is stateless.
     508     *
     509     * Since: 2.28
     510     **/
     511    g_object_class_install_property (object_class, PROP_STATE,
     512                                     g_param_spec_variant ("state", NULL, NULL,
     513                                                           G_VARIANT_TYPE_ANY,
     514                                                           NULL,
     515                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
     516                                                           G_PARAM_STATIC_STRINGS));
     517  }
     518  
     519  /**
     520   * g_simple_action_set_enabled:
     521   * @simple: a #GSimpleAction
     522   * @enabled: whether the action is enabled
     523   *
     524   * Sets the action as enabled or not.
     525   *
     526   * An action must be enabled in order to be activated or in order to
     527   * have its state changed from outside callers.
     528   *
     529   * This should only be called by the implementor of the action.  Users
     530   * of the action should not attempt to modify its enabled flag.
     531   *
     532   * Since: 2.28
     533   **/
     534  void
     535  g_simple_action_set_enabled (GSimpleAction *simple,
     536                               gboolean       enabled)
     537  {
     538    g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
     539  
     540    enabled = !!enabled;
     541  
     542    if (simple->enabled != enabled)
     543      {
     544        simple->enabled = enabled;
     545        g_object_notify (G_OBJECT (simple), "enabled");
     546      }
     547  }
     548  
     549  /**
     550   * g_simple_action_set_state_hint:
     551   * @simple: a #GSimpleAction
     552   * @state_hint: (nullable): a #GVariant representing the state hint
     553   *
     554   * Sets the state hint for the action.
     555   *
     556   * See g_action_get_state_hint() for more information about
     557   * action state hints.
     558   *
     559   * Since: 2.44
     560   **/
     561  void
     562  g_simple_action_set_state_hint (GSimpleAction *simple,
     563                                  GVariant      *state_hint)
     564  {
     565    g_return_if_fail (G_IS_SIMPLE_ACTION (simple));
     566  
     567    if (simple->state_hint != NULL)
     568      {
     569        g_variant_unref (simple->state_hint);
     570        simple->state_hint = NULL;
     571      }
     572  
     573    if (state_hint != NULL)
     574      simple->state_hint = g_variant_ref (state_hint);
     575  }
     576  
     577  /**
     578   * g_simple_action_new:
     579   * @name: the name of the action
     580   * @parameter_type: (nullable): the type of parameter that will be passed to
     581   *   handlers for the #GSimpleAction::activate signal, or %NULL for no parameter
     582   *
     583   * Creates a new action.
     584   *
     585   * The created action is stateless. See g_simple_action_new_stateful() to create
     586   * an action that has state.
     587   *
     588   * Returns: a new #GSimpleAction
     589   *
     590   * Since: 2.28
     591   **/
     592  GSimpleAction *
     593  g_simple_action_new (const gchar        *name,
     594                       const GVariantType *parameter_type)
     595  {
     596    g_return_val_if_fail (name != NULL, NULL);
     597  
     598    return g_object_new (G_TYPE_SIMPLE_ACTION,
     599                         "name", name,
     600                         "parameter-type", parameter_type,
     601                         NULL);
     602  }
     603  
     604  /**
     605   * g_simple_action_new_stateful:
     606   * @name: the name of the action
     607   * @parameter_type: (nullable): the type of the parameter that will be passed to
     608   *   handlers for the #GSimpleAction::activate signal, or %NULL for no parameter
     609   * @state: the initial state of the action
     610   *
     611   * Creates a new stateful action.
     612   *
     613   * All future state values must have the same #GVariantType as the initial
     614   * @state.
     615   *
     616   * If the @state #GVariant is floating, it is consumed.
     617   *
     618   * Returns: a new #GSimpleAction
     619   *
     620   * Since: 2.28
     621   **/
     622  GSimpleAction *
     623  g_simple_action_new_stateful (const gchar        *name,
     624                                const GVariantType *parameter_type,
     625                                GVariant           *state)
     626  {
     627    return g_object_new (G_TYPE_SIMPLE_ACTION,
     628                         "name", name,
     629                         "parameter-type", parameter_type,
     630                         "state", state,
     631                         NULL);
     632  }