LCOV - code coverage report
Current view: top level - glib/gio - gactionmap.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 44 44 100.0 %
Date: 2024-04-23 05:16:05 Functions: 7 7 100.0 %
Branches: 25 26 96.2 %

           Branch data     Line data    Source code
       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                 :            : #include "gactionmap.h"
      26                 :            : #include "gaction.h"
      27                 :            : 
      28                 :            : /**
      29                 :            :  * GActionMap:
      30                 :            :  *
      31                 :            :  * `GActionMap` is an interface for action containers.
      32                 :            :  *
      33                 :            :  * The `GActionMap` interface is implemented by [iface@Gio.ActionGroup]
      34                 :            :  * implementations that operate by containing a number of named
      35                 :            :  * [iface@Gio.Action] instances, such as [class@Gio.SimpleActionGroup].
      36                 :            :  *
      37                 :            :  * One useful application of this interface is to map the
      38                 :            :  * names of actions from various action groups to unique,
      39                 :            :  * prefixed names (e.g. by prepending "app." or "win.").
      40                 :            :  * This is the motivation for the 'Map' part of the interface
      41                 :            :  * name.
      42                 :            :  *
      43                 :            :  * Since: 2.32
      44                 :            :  */
      45                 :            : 
      46                 :            : /**
      47                 :            :  * GActionMapInterface:
      48                 :            :  * @lookup_action: the virtual function pointer for g_action_map_lookup_action()
      49                 :            :  * @add_action: the virtual function pointer for g_action_map_add_action()
      50                 :            :  * @remove_action: the virtual function pointer for g_action_map_remove_action()
      51                 :            :  *
      52                 :            :  * The virtual function table for #GActionMap.
      53                 :            :  *
      54                 :            :  * Since: 2.32
      55                 :            :  **/
      56                 :            : 
      57   [ +  +  +  -  :     200231 : G_DEFINE_INTERFACE (GActionMap, g_action_map, G_TYPE_OBJECT)
                   +  + ]
      58                 :            : 
      59                 :            : static void
      60                 :         13 : g_action_map_default_init (GActionMapInterface *iface)
      61                 :            : {
      62                 :         13 : }
      63                 :            : 
      64                 :            : /**
      65                 :            :  * g_action_map_lookup_action:
      66                 :            :  * @action_map: a #GActionMap
      67                 :            :  * @action_name: the name of an action
      68                 :            :  *
      69                 :            :  * Looks up the action with the name @action_name in @action_map.
      70                 :            :  *
      71                 :            :  * If no such action exists, returns %NULL.
      72                 :            :  *
      73                 :            :  * Returns: (nullable) (transfer none): a #GAction, or %NULL
      74                 :            :  *
      75                 :            :  * Since: 2.32
      76                 :            :  */
      77                 :            : GAction *
      78                 :     100005 : g_action_map_lookup_action (GActionMap  *action_map,
      79                 :            :                             const gchar *action_name)
      80                 :            : {
      81                 :     100005 :   return G_ACTION_MAP_GET_IFACE (action_map)
      82                 :     100006 :     ->lookup_action (action_map, action_name);
      83                 :            : }
      84                 :            : 
      85                 :            : /**
      86                 :            :  * g_action_map_add_action:
      87                 :            :  * @action_map: a #GActionMap
      88                 :            :  * @action: a #GAction
      89                 :            :  *
      90                 :            :  * Adds an action to the @action_map.
      91                 :            :  *
      92                 :            :  * If the action map already contains an action with the same name
      93                 :            :  * as @action then the old action is dropped from the action map.
      94                 :            :  *
      95                 :            :  * The action map takes its own reference on @action.
      96                 :            :  *
      97                 :            :  * Since: 2.32
      98                 :            :  */
      99                 :            : void
     100                 :         82 : g_action_map_add_action (GActionMap *action_map,
     101                 :            :                          GAction    *action)
     102                 :            : {
     103                 :         82 :   G_ACTION_MAP_GET_IFACE (action_map)->add_action (action_map, action);
     104                 :         82 : }
     105                 :            : 
     106                 :            : /**
     107                 :            :  * g_action_map_remove_action:
     108                 :            :  * @action_map: a #GActionMap
     109                 :            :  * @action_name: the name of the action
     110                 :            :  *
     111                 :            :  * Removes the named action from the action map.
     112                 :            :  *
     113                 :            :  * If no action of this name is in the map then nothing happens.
     114                 :            :  *
     115                 :            :  * Since: 2.32
     116                 :            :  */
     117                 :            : void
     118                 :         10 : g_action_map_remove_action (GActionMap  *action_map,
     119                 :            :                             const gchar *action_name)
     120                 :            : {
     121                 :         10 :   G_ACTION_MAP_GET_IFACE (action_map)->remove_action (action_map, action_name);
     122                 :         10 : }
     123                 :            : 
     124                 :            : /**
     125                 :            :  * GActionEntry:
     126                 :            :  * @name: the name of the action
     127                 :            :  * @activate: the callback to connect to the "activate" signal of the
     128                 :            :  *            action.  Since GLib 2.40, this can be %NULL for stateful
     129                 :            :  *            actions, in which case the default handler is used.  For
     130                 :            :  *            boolean-stated actions with no parameter, this is a
     131                 :            :  *            toggle.  For other state types (and parameter type equal
     132                 :            :  *            to the state type) this will be a function that
     133                 :            :  *            just calls @change_state (which you should provide).
     134                 :            :  * @parameter_type: the type of the parameter that must be passed to the
     135                 :            :  *                  activate function for this action, given as a single
     136                 :            :  *                  GVariant type string (or %NULL for no parameter)
     137                 :            :  * @state: the initial state for this action, given in
     138                 :            :  *         [GVariant text format](gvariant-text-format.html).  The state is parsed
     139                 :            :  *         with no extra type information, so type tags must be added to
     140                 :            :  *         the string if they are necessary.  Stateless actions should
     141                 :            :  *         give %NULL here.
     142                 :            :  * @change_state: the callback to connect to the "change-state" signal
     143                 :            :  *                of the action.  All stateful actions should provide a
     144                 :            :  *                handler here; stateless actions should not.
     145                 :            :  *
     146                 :            :  * This struct defines a single action.  It is for use with
     147                 :            :  * g_action_map_add_action_entries().
     148                 :            :  *
     149                 :            :  * The order of the items in the structure are intended to reflect
     150                 :            :  * frequency of use.  It is permissible to use an incomplete initialiser
     151                 :            :  * in order to leave some of the later values as %NULL.  All values
     152                 :            :  * after @name are optional.  Additional optional fields may be added in
     153                 :            :  * the future.
     154                 :            :  *
     155                 :            :  * See g_action_map_add_action_entries() for an example.
     156                 :            :  **/
     157                 :            : 
     158                 :            : /**
     159                 :            :  * g_action_map_add_action_entries:
     160                 :            :  * @action_map: a #GActionMap
     161                 :            :  * @entries: (array length=n_entries) (element-type GActionEntry): a pointer to
     162                 :            :  *           the first item in an array of #GActionEntry structs
     163                 :            :  * @n_entries: the length of @entries, or -1 if @entries is %NULL-terminated
     164                 :            :  * @user_data: the user data for signal connections
     165                 :            :  *
     166                 :            :  * A convenience function for creating multiple #GSimpleAction instances
     167                 :            :  * and adding them to a #GActionMap.
     168                 :            :  *
     169                 :            :  * Each action is constructed as per one #GActionEntry.
     170                 :            :  *
     171                 :            :  * |[<!-- language="C" -->
     172                 :            :  * static void
     173                 :            :  * activate_quit (GSimpleAction *simple,
     174                 :            :  *                GVariant      *parameter,
     175                 :            :  *                gpointer       user_data)
     176                 :            :  * {
     177                 :            :  *   exit (0);
     178                 :            :  * }
     179                 :            :  *
     180                 :            :  * static void
     181                 :            :  * activate_print_string (GSimpleAction *simple,
     182                 :            :  *                        GVariant      *parameter,
     183                 :            :  *                        gpointer       user_data)
     184                 :            :  * {
     185                 :            :  *   g_print ("%s\n", g_variant_get_string (parameter, NULL));
     186                 :            :  * }
     187                 :            :  *
     188                 :            :  * static GActionGroup *
     189                 :            :  * create_action_group (void)
     190                 :            :  * {
     191                 :            :  *   const GActionEntry entries[] = {
     192                 :            :  *     { "quit",         activate_quit              },
     193                 :            :  *     { "print-string", activate_print_string, "s" }
     194                 :            :  *   };
     195                 :            :  *   GSimpleActionGroup *group;
     196                 :            :  *
     197                 :            :  *   group = g_simple_action_group_new ();
     198                 :            :  *   g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), NULL);
     199                 :            :  *
     200                 :            :  *   return G_ACTION_GROUP (group);
     201                 :            :  * }
     202                 :            :  * ]|
     203                 :            :  *
     204                 :            :  * Since: 2.32
     205                 :            :  */
     206                 :            : void
     207                 :         23 : g_action_map_add_action_entries (GActionMap         *action_map,
     208                 :            :                                  const GActionEntry *entries,
     209                 :            :                                  gint                n_entries,
     210                 :            :                                  gpointer            user_data)
     211                 :            : {
     212                 :         23 :   g_return_if_fail (G_IS_ACTION_MAP (action_map));
     213                 :         23 :   g_return_if_fail (entries != NULL || n_entries == 0);
     214                 :            : 
     215   [ +  +  +  + ]:         75 :   for (int i = 0; n_entries < 0 ? entries[i].name != NULL : i < n_entries; i++)
     216                 :            :     {
     217                 :         53 :       const GActionEntry *entry = &entries[i];
     218                 :            :       const GVariantType *parameter_type;
     219                 :            :       GSimpleAction *action;
     220                 :            : 
     221         [ +  + ]:         53 :       if (entry->parameter_type)
     222                 :            :         {
     223         [ +  + ]:         11 :           if (!g_variant_type_string_is_valid (entry->parameter_type))
     224                 :            :             {
     225                 :          1 :               g_critical ("g_action_map_add_entries: the type "
     226                 :            :                           "string '%s' given as the parameter type for "
     227                 :            :                           "action '%s' is not a valid GVariant type "
     228                 :            :                           "string.  This action will not be added.",
     229                 :            :                           entry->parameter_type, entry->name);
     230                 :          1 :               return;
     231                 :            :             }
     232                 :            : 
     233                 :         10 :           parameter_type = G_VARIANT_TYPE (entry->parameter_type);
     234                 :            :         }
     235                 :            :       else
     236                 :         42 :         parameter_type = NULL;
     237                 :            : 
     238         [ +  + ]:         52 :       if (entry->state)
     239                 :            :         {
     240                 :         12 :           GError *error = NULL;
     241                 :            :           GVariant *state;
     242                 :            : 
     243                 :         12 :           state = g_variant_parse (NULL, entry->state, NULL, NULL, &error);
     244         [ +  + ]:         12 :           if (state == NULL)
     245                 :            :             {
     246                 :          1 :               g_critical ("g_action_map_add_entries: GVariant could "
     247                 :            :                           "not parse the state value given for action '%s' "
     248                 :            :                           "('%s'): %s.  This action will not be added.",
     249                 :            :                           entry->name, entry->state, error->message);
     250                 :          1 :               g_error_free (error);
     251                 :          1 :               continue;
     252                 :            :             }
     253                 :            : 
     254                 :         11 :           action = g_simple_action_new_stateful (entry->name,
     255                 :            :                                                  parameter_type,
     256                 :            :                                                  state);
     257                 :            : 
     258                 :         11 :           g_variant_unref (state);
     259                 :            :         }
     260                 :            :       else
     261                 :            :         {
     262                 :         40 :           action = g_simple_action_new (entry->name,
     263                 :            :                                         parameter_type);
     264                 :            :         }
     265                 :            : 
     266         [ +  + ]:         51 :       if (entry->activate != NULL)
     267                 :         49 :         g_signal_connect (action, "activate",
     268                 :            :                           G_CALLBACK (entry->activate), user_data);
     269                 :            : 
     270         [ +  + ]:         51 :       if (entry->change_state != NULL)
     271                 :          1 :         g_signal_connect (action, "change-state",
     272                 :            :                           G_CALLBACK (entry->change_state), user_data);
     273                 :            : 
     274                 :         51 :       g_action_map_add_action (action_map, G_ACTION (action));
     275                 :         51 :       g_object_unref (action);
     276                 :            :     }
     277                 :            : }
     278                 :            : 
     279                 :            : /**
     280                 :            :  * g_action_map_remove_action_entries:
     281                 :            :  * @action_map: The #GActionMap
     282                 :            :  * @entries: (array length=n_entries) (element-type GActionEntry): a pointer to
     283                 :            :  *           the first item in an array of #GActionEntry structs
     284                 :            :  * @n_entries: the length of @entries, or -1 if @entries is %NULL-terminated
     285                 :            :  *
     286                 :            :  * Remove actions from a #GActionMap. This is meant as the reverse of
     287                 :            :  * g_action_map_add_action_entries().
     288                 :            :  *
     289                 :            :  *
     290                 :            :  * |[<!-- language="C" -->
     291                 :            :  * static const GActionEntry entries[] = {
     292                 :            :  *     { "quit",         activate_quit              },
     293                 :            :  *     { "print-string", activate_print_string, "s" }
     294                 :            :  * };
     295                 :            :  *
     296                 :            :  * void
     297                 :            :  * add_actions (GActionMap *map)
     298                 :            :  * {
     299                 :            :  *   g_action_map_add_action_entries (map, entries, G_N_ELEMENTS (entries), NULL);
     300                 :            :  * }
     301                 :            :  *
     302                 :            :  * void
     303                 :            :  * remove_actions (GActionMap *map)
     304                 :            :  * {
     305                 :            :  *   g_action_map_remove_action_entries (map, entries, G_N_ELEMENTS (entries));
     306                 :            :  * }
     307                 :            :  * ]|
     308                 :            :  *
     309                 :            :  * Since: 2.78
     310                 :            :  */
     311                 :            : void
     312                 :          2 : g_action_map_remove_action_entries (GActionMap         *action_map,
     313                 :            :                                     const GActionEntry  entries[],
     314                 :            :                                     gint                n_entries)
     315                 :            : {
     316                 :          2 :   g_return_if_fail (G_IS_ACTION_MAP (action_map));
     317                 :          2 :   g_return_if_fail (entries != NULL || n_entries == 0);
     318                 :            : 
     319   [ +  +  +  + ]:          8 :   for (int i = 0; n_entries < 0 ? entries[i].name != NULL : i < n_entries; i++)
     320                 :          6 :     g_action_map_remove_action (action_map, entries[i].name);
     321                 :            : }

Generated by: LCOV version 1.14