LCOV - code coverage report
Current view: top level - glib/gio - gmenumodel.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 188 213 88.3 %
Date: 2024-04-23 05:16:05 Functions: 50 53 94.3 %
Branches: 58 82 70.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2011 Canonical Ltd.
       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, but
      12                 :            :  * 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 Public
      17                 :            :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  *
      19                 :            :  * Author: Ryan Lortie <desrt@desrt.ca>
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "config.h"
      23                 :            : 
      24                 :            : #include "gmenumodel.h"
      25                 :            : 
      26                 :            : #include "glibintl.h"
      27                 :            : #include "gmarshal-internal.h"
      28                 :            : 
      29                 :            : /**
      30                 :            :  * GMenuModel:
      31                 :            :  *
      32                 :            :  * `GMenuModel` represents the contents of a menu — an ordered list of
      33                 :            :  * menu items. The items are associated with actions, which can be
      34                 :            :  * activated through them. Items can be grouped in sections, and may
      35                 :            :  * have submenus associated with them. Both items and sections usually
      36                 :            :  * have some representation data, such as labels or icons. The type of
      37                 :            :  * the associated action (ie whether it is stateful, and what kind of
      38                 :            :  * state it has) can influence the representation of the item.
      39                 :            :  *
      40                 :            :  * The conceptual model of menus in `GMenuModel` is hierarchical:
      41                 :            :  * sections and submenus are again represented by `GMenuModel`s.
      42                 :            :  * Menus themselves do not define their own roles. Rather, the role
      43                 :            :  * of a particular `GMenuModel` is defined by the item that references
      44                 :            :  * it (or, in the case of the ‘root’ menu, is defined by the context
      45                 :            :  * in which it is used).
      46                 :            :  *
      47                 :            :  * As an example, consider the visible portions of this menu:
      48                 :            :  *
      49                 :            :  * ## An example menu
      50                 :            :  *
      51                 :            :  * ![](menu-example.png)
      52                 :            :  *
      53                 :            :  * There are 8 ‘menus’ visible in the screenshot: one menubar, two
      54                 :            :  * submenus and 5 sections:
      55                 :            :  *
      56                 :            :  * - the toplevel menubar (containing 4 items)
      57                 :            :  * - the View submenu (containing 3 sections)
      58                 :            :  * - the first section of the View submenu (containing 2 items)
      59                 :            :  * - the second section of the View submenu (containing 1 item)
      60                 :            :  * - the final section of the View submenu (containing 1 item)
      61                 :            :  * - the Highlight Mode submenu (containing 2 sections)
      62                 :            :  * - the Sources section (containing 2 items)
      63                 :            :  * - the Markup section (containing 2 items)
      64                 :            :  *
      65                 :            :  * The [example](#a-menu-example) illustrates the conceptual connection between
      66                 :            :  * these 8 menus. Each large block in the figure represents a menu and the
      67                 :            :  * smaller blocks within the large block represent items in that menu. Some
      68                 :            :  * items contain references to other menus.
      69                 :            :  *
      70                 :            :  * ## A menu example
      71                 :            :  *
      72                 :            :  * ![](menu-model.png)
      73                 :            :  *
      74                 :            :  * Notice that the separators visible in the [example](#an-example-menu)
      75                 :            :  * appear nowhere in the [menu model](#a-menu-example). This is because
      76                 :            :  * separators are not explicitly represented in the menu model. Instead,
      77                 :            :  * a separator is inserted between any two non-empty sections of a menu.
      78                 :            :  * Section items can have labels just like any other item. In that case,
      79                 :            :  * a display system may show a section header instead of a separator.
      80                 :            :  *
      81                 :            :  * The motivation for this abstract model of application controls is
      82                 :            :  * that modern user interfaces tend to make these controls available
      83                 :            :  * outside the application. Examples include global menus, jumplists,
      84                 :            :  * dash boards, etc. To support such uses, it is necessary to ‘export’
      85                 :            :  * information about actions and their representation in menus, which
      86                 :            :  * is exactly what the action group exporter and the menu model exporter do for
      87                 :            :  * [iface@Gio.ActionGroup] and [class@Gio.MenuModel]. The client-side
      88                 :            :  * counterparts to make use of the exported information are
      89                 :            :  * [class@Gio.DBusActionGroup] and [class@Gio.DBusMenuModel].
      90                 :            :  *
      91                 :            :  * The API of `GMenuModel` is very generic, with iterators for the
      92                 :            :  * attributes and links of an item, see
      93                 :            :  * [method@Gio.MenuModel.iterate_item_attributes] and
      94                 :            :  * [method@Gio.MenuModel.iterate_item_links]. The ‘standard’ attributes and
      95                 :            :  * link types have predefined names: `G_MENU_ATTRIBUTE_LABEL`,
      96                 :            :  * `G_MENU_ATTRIBUTE_ACTION`, `G_MENU_ATTRIBUTE_TARGET`, `G_MENU_LINK_SECTION`
      97                 :            :  * and `G_MENU_LINK_SUBMENU`.
      98                 :            :  *
      99                 :            :  * Items in a `GMenuModel` represent active controls if they refer to
     100                 :            :  * an action that can get activated when the user interacts with the
     101                 :            :  * menu item. The reference to the action is encoded by the string ID
     102                 :            :  * in the `G_MENU_ATTRIBUTE_ACTION` attribute. An action ID uniquely
     103                 :            :  * identifies an action in an action group. Which action group(s) provide
     104                 :            :  * actions depends on the context in which the menu model is used.
     105                 :            :  * E.g. when the model is exported as the application menu of a
     106                 :            :  * [`GtkApplication`](https://docs.gtk.org/gtk4/class.Application.html),
     107                 :            :  * actions can be application-wide or window-specific (and thus come from
     108                 :            :  * two different action groups). By convention, the application-wide actions
     109                 :            :  * have names that start with `app.`, while the names of window-specific
     110                 :            :  * actions start with `win.`.
     111                 :            :  *
     112                 :            :  * While a wide variety of stateful actions is possible, the following
     113                 :            :  * is the minimum that is expected to be supported by all users of exported
     114                 :            :  * menu information:
     115                 :            :  * - an action with no parameter type and no state
     116                 :            :  * - an action with no parameter type and boolean state
     117                 :            :  * - an action with string parameter type and string state
     118                 :            :  *
     119                 :            :  * ## Stateless
     120                 :            :  *
     121                 :            :  * A stateless action typically corresponds to an ordinary menu item.
     122                 :            :  *
     123                 :            :  * Selecting such a menu item will activate the action (with no parameter).
     124                 :            :  *
     125                 :            :  * ## Boolean State
     126                 :            :  *
     127                 :            :  * An action with a boolean state will most typically be used with a ‘toggle’
     128                 :            :  * or ‘switch’ menu item. The state can be set directly, but activating the
     129                 :            :  * action (with no parameter) results in the state being toggled.
     130                 :            :  *
     131                 :            :  * Selecting a toggle menu item will activate the action. The menu item should
     132                 :            :  * be rendered as ‘checked’ when the state is true.
     133                 :            :  *
     134                 :            :  * ## String Parameter and State
     135                 :            :  *
     136                 :            :  * Actions with string parameters and state will most typically be used to
     137                 :            :  * represent an enumerated choice over the items available for a group of
     138                 :            :  * radio menu items. Activating the action with a string parameter is
     139                 :            :  * equivalent to setting that parameter as the state.
     140                 :            :  *
     141                 :            :  * Radio menu items, in addition to being associated with the action, will
     142                 :            :  * have a target value. Selecting that menu item will result in activation
     143                 :            :  * of the action with the target value as the parameter. The menu item should
     144                 :            :  * be rendered as ‘selected’ when the state of the action is equal to the
     145                 :            :  * target value of the menu item.
     146                 :            :  *
     147                 :            :  * Since: 2.32
     148                 :            :  */
     149                 :            : 
     150                 :            : /**
     151                 :            :  * GMenuAttributeIter:
     152                 :            :  *
     153                 :            :  * #GMenuAttributeIter is an opaque structure type.  You must access it
     154                 :            :  * using the functions below.
     155                 :            :  *
     156                 :            :  * Since: 2.32
     157                 :            :  */
     158                 :            : 
     159                 :            : /**
     160                 :            :  * GMenuLinkIter:
     161                 :            :  *
     162                 :            :  * #GMenuLinkIter is an opaque structure type.  You must access it using
     163                 :            :  * the functions below.
     164                 :            :  *
     165                 :            :  * Since: 2.32
     166                 :            :  */
     167                 :            : 
     168                 :            : typedef struct
     169                 :            : {
     170                 :            :   GMenuLinkIter parent_instance;
     171                 :            :   GHashTableIter iter;
     172                 :            :   GHashTable *table;
     173                 :            : } GMenuLinkHashIter;
     174                 :            : 
     175                 :            : typedef GMenuLinkIterClass GMenuLinkHashIterClass;
     176                 :            : 
     177                 :            : static GType g_menu_link_hash_iter_get_type (void);
     178                 :            : 
     179   [ +  +  +  -  :     926393 : G_DEFINE_TYPE (GMenuLinkHashIter, g_menu_link_hash_iter, G_TYPE_MENU_LINK_ITER)
                   +  + ]
     180                 :            : 
     181                 :            : static gboolean
     182                 :    1080621 : g_menu_link_hash_iter_get_next (GMenuLinkIter  *link_iter,
     183                 :            :                                 const gchar   **out_name,
     184                 :            :                                 GMenuModel    **value)
     185                 :            : {
     186                 :    1080621 :   GMenuLinkHashIter *iter = (GMenuLinkHashIter *) link_iter;
     187                 :            :   gpointer keyptr, valueptr;
     188                 :            : 
     189         [ +  + ]:    1080621 :   if (!g_hash_table_iter_next (&iter->iter, &keyptr, &valueptr))
     190                 :     926391 :     return FALSE;
     191                 :            : 
     192                 :     154230 :   *out_name = keyptr;
     193                 :     154230 :   *value = g_object_ref (valueptr);
     194                 :            : 
     195                 :     154230 :   return TRUE;
     196                 :            : }
     197                 :            : 
     198                 :            : static void
     199                 :     926391 : g_menu_link_hash_iter_finalize (GObject *object)
     200                 :            : {
     201                 :     926391 :   GMenuLinkHashIter *iter = (GMenuLinkHashIter *) object;
     202                 :            : 
     203                 :     926391 :   g_hash_table_unref (iter->table);
     204                 :            : 
     205                 :     926391 :   G_OBJECT_CLASS (g_menu_link_hash_iter_parent_class)
     206                 :     926391 :     ->finalize (object);
     207                 :     926391 : }
     208                 :            : 
     209                 :            : static void
     210                 :     926391 : g_menu_link_hash_iter_init (GMenuLinkHashIter *iter)
     211                 :            : {
     212                 :     926391 : }
     213                 :            : 
     214                 :            : static void
     215                 :          1 : g_menu_link_hash_iter_class_init (GMenuLinkHashIterClass *class)
     216                 :            : {
     217                 :          1 :   GObjectClass *object_class = G_OBJECT_CLASS (class);
     218                 :            : 
     219                 :          1 :   object_class->finalize = g_menu_link_hash_iter_finalize;
     220                 :          1 :   class->get_next = g_menu_link_hash_iter_get_next;
     221                 :          1 : }
     222                 :            : 
     223                 :            : 
     224                 :            : typedef struct
     225                 :            : {
     226                 :            :   GMenuAttributeIter parent_instance;
     227                 :            :   GHashTableIter iter;
     228                 :            :   GHashTable *table;
     229                 :            : } GMenuAttributeHashIter;
     230                 :            : 
     231                 :            : typedef GMenuAttributeIterClass GMenuAttributeHashIterClass;
     232                 :            : 
     233                 :            : static GType g_menu_attribute_hash_iter_get_type (void);
     234                 :            : 
     235   [ +  +  +  -  :     926394 : G_DEFINE_TYPE (GMenuAttributeHashIter, g_menu_attribute_hash_iter, G_TYPE_MENU_ATTRIBUTE_ITER)
                   +  + ]
     236                 :            : 
     237                 :            : static gboolean
     238                 :    1814827 : g_menu_attribute_hash_iter_get_next (GMenuAttributeIter  *attr_iter,
     239                 :            :                                      const gchar        **name,
     240                 :            :                                      GVariant           **value)
     241                 :            : {
     242                 :    1814827 :   GMenuAttributeHashIter *iter = (GMenuAttributeHashIter *) attr_iter;
     243                 :            :   gpointer keyptr, valueptr;
     244                 :            : 
     245         [ +  + ]:    1814827 :   if (!g_hash_table_iter_next (&iter->iter, &keyptr, &valueptr))
     246                 :     926392 :     return FALSE;
     247                 :            : 
     248                 :     888435 :   *name = keyptr;
     249                 :            : 
     250                 :     888435 :   *value = g_variant_ref (valueptr);
     251                 :            : 
     252                 :     888435 :   return TRUE;
     253                 :            : }
     254                 :            : 
     255                 :            : static void
     256                 :     926392 : g_menu_attribute_hash_iter_finalize (GObject *object)
     257                 :            : {
     258                 :     926392 :   GMenuAttributeHashIter *iter = (GMenuAttributeHashIter *) object;
     259                 :            : 
     260                 :     926392 :   g_hash_table_unref (iter->table);
     261                 :            : 
     262                 :     926392 :   G_OBJECT_CLASS (g_menu_attribute_hash_iter_parent_class)
     263                 :     926392 :     ->finalize (object);
     264                 :     926392 : }
     265                 :            : 
     266                 :            : static void
     267                 :     926392 : g_menu_attribute_hash_iter_init (GMenuAttributeHashIter *iter)
     268                 :            : {
     269                 :     926392 : }
     270                 :            : 
     271                 :            : static void
     272                 :          1 : g_menu_attribute_hash_iter_class_init (GMenuAttributeHashIterClass *class)
     273                 :            : {
     274                 :          1 :   GObjectClass *object_class = G_OBJECT_CLASS (class);
     275                 :            : 
     276                 :          1 :   object_class->finalize = g_menu_attribute_hash_iter_finalize;
     277                 :          1 :   class->get_next = g_menu_attribute_hash_iter_get_next;
     278                 :          1 : }
     279                 :            : 
     280   [ +  +  +  -  :     316297 : G_DEFINE_ABSTRACT_TYPE (GMenuModel, g_menu_model, G_TYPE_OBJECT)
                   +  + ]
     281                 :            : 
     282                 :            : 
     283                 :            : static guint g_menu_model_items_changed_signal;
     284                 :            : 
     285                 :            : static GMenuAttributeIter *
     286                 :     926392 : g_menu_model_real_iterate_item_attributes (GMenuModel *model,
     287                 :            :                                            gint        item_index)
     288                 :            : {
     289                 :     926392 :   GHashTable *table = NULL;
     290                 :            :   GMenuAttributeIter *result;
     291                 :            : 
     292                 :     926392 :   G_MENU_MODEL_GET_CLASS (model)->get_item_attributes (model, item_index, &table);
     293                 :            : 
     294         [ +  - ]:     926392 :   if (table)
     295                 :            :     {
     296                 :     926392 :       GMenuAttributeHashIter *iter = g_object_new (g_menu_attribute_hash_iter_get_type (), NULL);
     297                 :     926392 :       g_hash_table_iter_init (&iter->iter, table);
     298                 :     926392 :       iter->table = g_hash_table_ref (table);
     299                 :     926392 :       result = G_MENU_ATTRIBUTE_ITER (iter);
     300                 :            :     }
     301                 :            :   else
     302                 :            :     {
     303                 :          0 :       g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_attributes() "
     304                 :            :                   "and fails to return valid values from get_item_attributes()",
     305                 :            :                   G_OBJECT_TYPE_NAME (model));
     306                 :          0 :       result = NULL;
     307                 :            :     }
     308                 :            : 
     309         [ +  - ]:     926392 :   if (table != NULL)
     310                 :     926392 :     g_hash_table_unref (table);
     311                 :            : 
     312                 :     926392 :   return result;
     313                 :            : }
     314                 :            : 
     315                 :            : static GVariant *
     316                 :     876708 : g_menu_model_real_get_item_attribute_value (GMenuModel         *model,
     317                 :            :                                             gint                item_index,
     318                 :            :                                             const gchar        *attribute,
     319                 :            :                                             const GVariantType *expected_type)
     320                 :            : {
     321                 :     876708 :   GHashTable *table = NULL;
     322                 :     876708 :   GVariant *value = NULL;
     323                 :            : 
     324                 :     876708 :   G_MENU_MODEL_GET_CLASS (model)
     325                 :     876708 :     ->get_item_attributes (model, item_index, &table);
     326                 :            : 
     327         [ +  - ]:     876708 :   if (table != NULL)
     328                 :            :     {
     329                 :     876708 :       value = g_hash_table_lookup (table, attribute);
     330                 :            : 
     331         [ +  + ]:     876708 :       if (value != NULL)
     332                 :            :         {
     333   [ -  +  -  - ]:     876632 :           if (expected_type == NULL || g_variant_is_of_type (value, expected_type))
     334                 :     876632 :             value = g_variant_ref (value);
     335                 :            :           else
     336                 :          0 :             value = NULL;
     337                 :            :         }
     338                 :            :     }
     339                 :            :   else
     340                 :            :     g_assert_not_reached ();
     341                 :            : 
     342         [ +  - ]:     876708 :   if (table != NULL)
     343                 :     876708 :     g_hash_table_unref (table);
     344                 :            : 
     345                 :     876708 :   return value;
     346                 :            : }
     347                 :            : 
     348                 :            : static GMenuLinkIter *
     349                 :     926391 : g_menu_model_real_iterate_item_links (GMenuModel *model,
     350                 :            :                                       gint        item_index)
     351                 :            : {
     352                 :     926391 :   GHashTable *table = NULL;
     353                 :            :   GMenuLinkIter *result;
     354                 :            : 
     355                 :     926391 :   G_MENU_MODEL_GET_CLASS (model)
     356                 :     926391 :     ->get_item_links (model, item_index, &table);
     357                 :            : 
     358         [ +  - ]:     926391 :   if (table)
     359                 :            :     {
     360                 :     926391 :       GMenuLinkHashIter *iter = g_object_new (g_menu_link_hash_iter_get_type (), NULL);
     361                 :     926391 :       g_hash_table_iter_init (&iter->iter, table);
     362                 :     926391 :       iter->table = g_hash_table_ref (table);
     363                 :     926391 :       result = G_MENU_LINK_ITER (iter);
     364                 :            :     }
     365                 :            :   else
     366                 :            :     {
     367                 :          0 :       g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_links() "
     368                 :            :                   "and fails to return valid values from get_item_links()",
     369                 :            :                   G_OBJECT_TYPE_NAME (model));
     370                 :          0 :       result = NULL;
     371                 :            :     }
     372                 :            : 
     373         [ +  - ]:     926391 :   if (table != NULL)
     374                 :     926391 :     g_hash_table_unref (table);
     375                 :            : 
     376                 :     926391 :   return result;
     377                 :            : }
     378                 :            : 
     379                 :            : static GMenuModel *
     380                 :     150479 : g_menu_model_real_get_item_link (GMenuModel  *model,
     381                 :            :                                  gint         item_index,
     382                 :            :                                  const gchar *link)
     383                 :            : {
     384                 :     150479 :   GHashTable *table = NULL;
     385                 :     150479 :   GMenuModel *value = NULL;
     386                 :            : 
     387                 :     150479 :   G_MENU_MODEL_GET_CLASS (model)
     388                 :     150479 :     ->get_item_links (model, item_index, &table);
     389                 :            : 
     390         [ +  - ]:     150479 :   if (table != NULL)
     391                 :     150479 :     value = g_hash_table_lookup (table, link);
     392                 :            :   else
     393                 :            :     g_assert_not_reached ();
     394                 :            : 
     395         [ +  + ]:     150479 :   if (value != NULL)
     396                 :     150209 :     g_object_ref (value);
     397                 :            : 
     398         [ +  - ]:     150479 :   if (table != NULL)
     399                 :     150479 :     g_hash_table_unref (table);
     400                 :            : 
     401                 :     150479 :   return value;
     402                 :            : }
     403                 :            : 
     404                 :            : static void
     405                 :     210797 : g_menu_model_init (GMenuModel *model)
     406                 :            : {
     407                 :     210797 : }
     408                 :            : 
     409                 :            : static void
     410                 :          3 : g_menu_model_class_init (GMenuModelClass *class)
     411                 :            : {
     412                 :          3 :   class->iterate_item_attributes = g_menu_model_real_iterate_item_attributes;
     413                 :          3 :   class->get_item_attribute_value = g_menu_model_real_get_item_attribute_value;
     414                 :          3 :   class->iterate_item_links = g_menu_model_real_iterate_item_links;
     415                 :          3 :   class->get_item_link = g_menu_model_real_get_item_link;
     416                 :            : 
     417                 :            :   /**
     418                 :            :    * GMenuModel::items-changed:
     419                 :            :    * @model: the #GMenuModel that is changing
     420                 :            :    * @position: the position of the change
     421                 :            :    * @removed: the number of items removed
     422                 :            :    * @added: the number of items added
     423                 :            :    *
     424                 :            :    * Emitted when a change has occurred to the menu.
     425                 :            :    *
     426                 :            :    * The only changes that can occur to a menu is that items are removed
     427                 :            :    * or added.  Items may not change (except by being removed and added
     428                 :            :    * back in the same location).  This signal is capable of describing
     429                 :            :    * both of those changes (at the same time).
     430                 :            :    *
     431                 :            :    * The signal means that starting at the index @position, @removed
     432                 :            :    * items were removed and @added items were added in their place.  If
     433                 :            :    * @removed is zero then only items were added.  If @added is zero
     434                 :            :    * then only items were removed.
     435                 :            :    *
     436                 :            :    * As an example, if the menu contains items a, b, c, d (in that
     437                 :            :    * order) and the signal (2, 1, 3) occurs then the new composition of
     438                 :            :    * the menu will be a, b, _, _, _, d (with each _ representing some
     439                 :            :    * new item).
     440                 :            :    *
     441                 :            :    * Signal handlers may query the model (particularly the added items)
     442                 :            :    * and expect to see the results of the modification that is being
     443                 :            :    * reported.  The signal is emitted after the modification.
     444                 :            :    **/
     445                 :          3 :   g_menu_model_items_changed_signal =
     446                 :          3 :     g_signal_new (I_("items-changed"), G_TYPE_MENU_MODEL,
     447                 :            :                   G_SIGNAL_RUN_LAST, 0, NULL, NULL,
     448                 :            :                   _g_cclosure_marshal_VOID__INT_INT_INT,
     449                 :            :                   G_TYPE_NONE,
     450                 :            :                   3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
     451                 :          3 :   g_signal_set_va_marshaller (g_menu_model_items_changed_signal,
     452                 :            :                               G_TYPE_FROM_CLASS (class),
     453                 :            :                               _g_cclosure_marshal_VOID__INT_INT_INTv);
     454                 :          3 : }
     455                 :            : 
     456                 :            : /**
     457                 :            :  * g_menu_model_is_mutable:
     458                 :            :  * @model: a #GMenuModel
     459                 :            :  *
     460                 :            :  * Queries if @model is mutable.
     461                 :            :  *
     462                 :            :  * An immutable #GMenuModel will never emit the #GMenuModel::items-changed
     463                 :            :  * signal. Consumers of the model may make optimisations accordingly.
     464                 :            :  *
     465                 :            :  * Returns: %TRUE if the model is mutable (ie: "items-changed" may be
     466                 :            :  *     emitted).
     467                 :            :  *
     468                 :            :  * Since: 2.32
     469                 :            :  */
     470                 :            : gboolean
     471                 :       3763 : g_menu_model_is_mutable (GMenuModel *model)
     472                 :            : {
     473                 :       7526 :   return G_MENU_MODEL_GET_CLASS (model)
     474                 :       3763 :     ->is_mutable (model);
     475                 :            : }
     476                 :            : 
     477                 :            : /**
     478                 :            :  * g_menu_model_get_n_items:
     479                 :            :  * @model: a #GMenuModel
     480                 :            :  *
     481                 :            :  * Query the number of items in @model.
     482                 :            :  *
     483                 :            :  * Returns: the number of items
     484                 :            :  *
     485                 :            :  * Since: 2.32
     486                 :            :  */
     487                 :            : gint
     488                 :     308011 : g_menu_model_get_n_items (GMenuModel *model)
     489                 :            : {
     490                 :     616022 :   return G_MENU_MODEL_GET_CLASS (model)
     491                 :     308011 :     ->get_n_items (model);
     492                 :            : }
     493                 :            : 
     494                 :            : /**
     495                 :            :  * g_menu_model_iterate_item_attributes:
     496                 :            :  * @model: a #GMenuModel
     497                 :            :  * @item_index: the index of the item
     498                 :            :  *
     499                 :            :  * Creates a #GMenuAttributeIter to iterate over the attributes of
     500                 :            :  * the item at position @item_index in @model.
     501                 :            :  *
     502                 :            :  * You must free the iterator with g_object_unref() when you are done.
     503                 :            :  *
     504                 :            :  * Returns: (transfer full): a new #GMenuAttributeIter
     505                 :            :  *
     506                 :            :  * Since: 2.32
     507                 :            :  */
     508                 :            : GMenuAttributeIter *
     509                 :     926392 : g_menu_model_iterate_item_attributes (GMenuModel *model,
     510                 :            :                                       gint        item_index)
     511                 :            : {
     512                 :    1852784 :   return G_MENU_MODEL_GET_CLASS (model)
     513                 :     926392 :     ->iterate_item_attributes (model, item_index);
     514                 :            : }
     515                 :            : 
     516                 :            : /**
     517                 :            :  * g_menu_model_get_item_attribute_value:
     518                 :            :  * @model: a #GMenuModel
     519                 :            :  * @item_index: the index of the item
     520                 :            :  * @attribute: the attribute to query
     521                 :            :  * @expected_type: (nullable): the expected type of the attribute, or
     522                 :            :  *     %NULL
     523                 :            :  *
     524                 :            :  * Queries the item at position @item_index in @model for the attribute
     525                 :            :  * specified by @attribute.
     526                 :            :  *
     527                 :            :  * If @expected_type is non-%NULL then it specifies the expected type of
     528                 :            :  * the attribute.  If it is %NULL then any type will be accepted.
     529                 :            :  *
     530                 :            :  * If the attribute exists and matches @expected_type (or if the
     531                 :            :  * expected type is unspecified) then the value is returned.
     532                 :            :  *
     533                 :            :  * If the attribute does not exist, or does not match the expected type
     534                 :            :  * then %NULL is returned.
     535                 :            :  *
     536                 :            :  * Returns: (nullable) (transfer full): the value of the attribute
     537                 :            :  *
     538                 :            :  * Since: 2.32
     539                 :            :  */
     540                 :            : GVariant *
     541                 :     876708 : g_menu_model_get_item_attribute_value (GMenuModel         *model,
     542                 :            :                                        gint                item_index,
     543                 :            :                                        const gchar        *attribute,
     544                 :            :                                        const GVariantType *expected_type)
     545                 :            : {
     546                 :    1753416 :   return G_MENU_MODEL_GET_CLASS (model)
     547                 :     876708 :     ->get_item_attribute_value (model, item_index, attribute, expected_type);
     548                 :            : }
     549                 :            : 
     550                 :            : /**
     551                 :            :  * g_menu_model_get_item_attribute:
     552                 :            :  * @model: a #GMenuModel
     553                 :            :  * @item_index: the index of the item
     554                 :            :  * @attribute: the attribute to query
     555                 :            :  * @format_string: a #GVariant format string
     556                 :            :  * @...: positional parameters, as per @format_string
     557                 :            :  *
     558                 :            :  * Queries item at position @item_index in @model for the attribute
     559                 :            :  * specified by @attribute.
     560                 :            :  *
     561                 :            :  * If the attribute exists and matches the #GVariantType corresponding
     562                 :            :  * to @format_string then @format_string is used to deconstruct the
     563                 :            :  * value into the positional parameters and %TRUE is returned.
     564                 :            :  *
     565                 :            :  * If the attribute does not exist, or it does exist but has the wrong
     566                 :            :  * type, then the positional parameters are ignored and %FALSE is
     567                 :            :  * returned.
     568                 :            :  *
     569                 :            :  * This function is a mix of g_menu_model_get_item_attribute_value() and
     570                 :            :  * g_variant_get(), followed by a g_variant_unref().  As such,
     571                 :            :  * @format_string must make a complete copy of the data (since the
     572                 :            :  * #GVariant may go away after the call to g_variant_unref()).  In
     573                 :            :  * particular, no '&' characters are allowed in @format_string.
     574                 :            :  *
     575                 :            :  * Returns: %TRUE if the named attribute was found with the expected
     576                 :            :  *     type
     577                 :            :  *
     578                 :            :  * Since: 2.32
     579                 :            :  */
     580                 :            : gboolean
     581                 :          0 : g_menu_model_get_item_attribute (GMenuModel  *model,
     582                 :            :                                  gint         item_index,
     583                 :            :                                  const gchar *attribute,
     584                 :            :                                  const gchar *format_string,
     585                 :            :                                  ...)
     586                 :            : {
     587                 :            :   GVariant *value;
     588                 :            :   va_list ap;
     589                 :            : 
     590                 :          0 :   value = g_menu_model_get_item_attribute_value (model, item_index, attribute, NULL);
     591                 :            : 
     592         [ #  # ]:          0 :   if (value == NULL)
     593                 :          0 :     return FALSE;
     594                 :            : 
     595         [ #  # ]:          0 :   if (!g_variant_check_format_string (value, format_string, TRUE))
     596                 :            :     {
     597                 :          0 :       g_variant_unref (value);
     598                 :          0 :       return FALSE;
     599                 :            :     }
     600                 :            : 
     601                 :          0 :   va_start (ap, format_string);
     602                 :          0 :   g_variant_get_va (value, format_string, NULL, &ap);
     603                 :          0 :   g_variant_unref (value);
     604                 :          0 :   va_end (ap);
     605                 :            : 
     606                 :          0 :   return TRUE;
     607                 :            : }
     608                 :            : 
     609                 :            : /**
     610                 :            :  * g_menu_model_iterate_item_links:
     611                 :            :  * @model: a #GMenuModel
     612                 :            :  * @item_index: the index of the item
     613                 :            :  *
     614                 :            :  * Creates a #GMenuLinkIter to iterate over the links of the item at
     615                 :            :  * position @item_index in @model.
     616                 :            :  *
     617                 :            :  * You must free the iterator with g_object_unref() when you are done.
     618                 :            :  *
     619                 :            :  * Returns: (transfer full): a new #GMenuLinkIter
     620                 :            :  *
     621                 :            :  * Since: 2.32
     622                 :            :  */
     623                 :            : GMenuLinkIter *
     624                 :     926391 : g_menu_model_iterate_item_links (GMenuModel *model,
     625                 :            :                                  gint        item_index)
     626                 :            : {
     627                 :    1852782 :   return G_MENU_MODEL_GET_CLASS (model)
     628                 :     926391 :     ->iterate_item_links (model, item_index);
     629                 :            : }
     630                 :            : 
     631                 :            : /**
     632                 :            :  * g_menu_model_get_item_link:
     633                 :            :  * @model: a #GMenuModel
     634                 :            :  * @item_index: the index of the item
     635                 :            :  * @link: the link to query
     636                 :            :  *
     637                 :            :  * Queries the item at position @item_index in @model for the link
     638                 :            :  * specified by @link.
     639                 :            :  *
     640                 :            :  * If the link exists, the linked #GMenuModel is returned.  If the link
     641                 :            :  * does not exist, %NULL is returned.
     642                 :            :  *
     643                 :            :  * Returns: (nullable) (transfer full): the linked #GMenuModel, or %NULL
     644                 :            :  *
     645                 :            :  * Since: 2.32
     646                 :            :  */
     647                 :            : GMenuModel *
     648                 :     150479 : g_menu_model_get_item_link (GMenuModel *model,
     649                 :            :                             gint        item_index,
     650                 :            :                             const gchar *link)
     651                 :            : {
     652                 :     300958 :   return G_MENU_MODEL_GET_CLASS (model)
     653                 :     150479 :     ->get_item_link (model, item_index, link);
     654                 :            : }
     655                 :            : 
     656                 :            : /**
     657                 :            :  * g_menu_model_items_changed:
     658                 :            :  * @model: a #GMenuModel
     659                 :            :  * @position: the position of the change
     660                 :            :  * @removed: the number of items removed
     661                 :            :  * @added: the number of items added
     662                 :            :  *
     663                 :            :  * Requests emission of the #GMenuModel::items-changed signal on @model.
     664                 :            :  *
     665                 :            :  * This function should never be called except by #GMenuModel
     666                 :            :  * subclasses.  Any other calls to this function will very likely lead
     667                 :            :  * to a violation of the interface of the model.
     668                 :            :  *
     669                 :            :  * The implementation should update its internal representation of the
     670                 :            :  * menu before emitting the signal.  The implementation should further
     671                 :            :  * expect to receive queries about the new state of the menu (and
     672                 :            :  * particularly added menu items) while signal handlers are running.
     673                 :            :  *
     674                 :            :  * The implementation must dispatch this call directly from a mainloop
     675                 :            :  * entry and not in response to calls -- particularly those from the
     676                 :            :  * #GMenuModel API.  Said another way: the menu must not change while
     677                 :            :  * user code is running without returning to the mainloop.
     678                 :            :  *
     679                 :            :  * Since: 2.32
     680                 :            :  */
     681                 :            : void
     682                 :     309913 : g_menu_model_items_changed (GMenuModel *model,
     683                 :            :                             gint        position,
     684                 :            :                             gint        removed,
     685                 :            :                             gint        added)
     686                 :            : {
     687                 :     309913 :   g_signal_emit (model, g_menu_model_items_changed_signal, 0, position, removed, added);
     688                 :     313148 : }
     689                 :            : 
     690                 :            : struct _GMenuAttributeIterPrivate
     691                 :            : {
     692                 :            :   GQuark name;
     693                 :            :   GVariant *value;
     694                 :            :   gboolean valid;
     695                 :            : };
     696                 :            : 
     697   [ +  +  +  -  :    2779184 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GMenuAttributeIter, g_menu_attribute_iter, G_TYPE_OBJECT)
                   +  + ]
     698                 :            : 
     699                 :            : /**
     700                 :            :  * g_menu_attribute_iter_get_next:
     701                 :            :  * @iter: a #GMenuAttributeIter
     702                 :            :  * @out_name: (out) (optional) (transfer none): the type of the attribute
     703                 :            :  * @value: (out) (optional) (transfer full): the attribute value
     704                 :            :  *
     705                 :            :  * This function combines g_menu_attribute_iter_next() with
     706                 :            :  * g_menu_attribute_iter_get_name() and g_menu_attribute_iter_get_value().
     707                 :            :  *
     708                 :            :  * First the iterator is advanced to the next (possibly first) attribute.
     709                 :            :  * If that fails, then %FALSE is returned and there are no other
     710                 :            :  * effects.
     711                 :            :  *
     712                 :            :  * If successful, @name and @value are set to the name and value of the
     713                 :            :  * attribute that has just been advanced to.  At this point,
     714                 :            :  * g_menu_attribute_iter_get_name() and g_menu_attribute_iter_get_value() will
     715                 :            :  * return the same values again.
     716                 :            :  *
     717                 :            :  * The value returned in @name remains valid for as long as the iterator
     718                 :            :  * remains at the current position.  The value returned in @value must
     719                 :            :  * be unreffed using g_variant_unref() when it is no longer in use.
     720                 :            :  *
     721                 :            :  * Returns: %TRUE on success, or %FALSE if there is no additional
     722                 :            :  *     attribute
     723                 :            :  *
     724                 :            :  * Since: 2.32
     725                 :            :  */
     726                 :            : gboolean
     727                 :    1814827 : g_menu_attribute_iter_get_next (GMenuAttributeIter  *iter,
     728                 :            :                                 const gchar        **out_name,
     729                 :            :                                 GVariant           **value)
     730                 :            : {
     731                 :            :   const gchar *name;
     732                 :            : 
     733         [ +  + ]:    1814827 :   if (iter->priv->value)
     734                 :            :     {
     735                 :     888435 :       g_variant_unref (iter->priv->value);
     736                 :     888435 :       iter->priv->value = NULL;
     737                 :            :     }
     738                 :            : 
     739                 :    3629654 :   iter->priv->valid = G_MENU_ATTRIBUTE_ITER_GET_CLASS (iter)
     740                 :    1814827 :     ->get_next (iter, &name, &iter->priv->value);
     741                 :            : 
     742         [ +  + ]:    1814827 :   if (iter->priv->valid)
     743                 :            :     {
     744                 :     888435 :       iter->priv->name = g_quark_from_string (name);
     745         [ +  + ]:     888435 :       if (out_name)
     746                 :     888423 :         *out_name = g_quark_to_string (iter->priv->name);
     747                 :            : 
     748         [ +  + ]:     888435 :       if (value)
     749                 :     888423 :         *value = g_variant_ref (iter->priv->value);
     750                 :            :     }
     751                 :            : 
     752                 :    1814827 :   return iter->priv->valid;
     753                 :            : }
     754                 :            : 
     755                 :            : /**
     756                 :            :  * g_menu_attribute_iter_next:
     757                 :            :  * @iter: a #GMenuAttributeIter
     758                 :            :  *
     759                 :            :  * Attempts to advance the iterator to the next (possibly first)
     760                 :            :  * attribute.
     761                 :            :  *
     762                 :            :  * %TRUE is returned on success, or %FALSE if there are no more
     763                 :            :  * attributes.
     764                 :            :  *
     765                 :            :  * You must call this function when you first acquire the iterator
     766                 :            :  * to advance it to the first attribute (and determine if the first
     767                 :            :  * attribute exists at all).
     768                 :            :  *
     769                 :            :  * Returns: %TRUE on success, or %FALSE when there are no more attributes
     770                 :            :  *
     771                 :            :  * Since: 2.32
     772                 :            :  */
     773                 :            : gboolean
     774                 :         24 : g_menu_attribute_iter_next (GMenuAttributeIter *iter)
     775                 :            : {
     776                 :         24 :   return g_menu_attribute_iter_get_next (iter, NULL, NULL);
     777                 :            : }
     778                 :            : 
     779                 :            : /**
     780                 :            :  * g_menu_attribute_iter_get_name:
     781                 :            :  * @iter: a #GMenuAttributeIter
     782                 :            :  *
     783                 :            :  * Gets the name of the attribute at the current iterator position, as
     784                 :            :  * a string.
     785                 :            :  *
     786                 :            :  * The iterator is not advanced.
     787                 :            :  *
     788                 :            :  * Returns: the name of the attribute
     789                 :            :  *
     790                 :            :  * Since: 2.32
     791                 :            :  */
     792                 :            : const gchar *
     793                 :         12 : g_menu_attribute_iter_get_name (GMenuAttributeIter *iter)
     794                 :            : {
     795                 :         12 :   g_return_val_if_fail (iter->priv->valid, 0);
     796                 :            : 
     797                 :         12 :   return g_quark_to_string (iter->priv->name);
     798                 :            : }
     799                 :            : 
     800                 :            : /**
     801                 :            :  * g_menu_attribute_iter_get_value:
     802                 :            :  * @iter: a #GMenuAttributeIter
     803                 :            :  *
     804                 :            :  * Gets the value of the attribute at the current iterator position.
     805                 :            :  *
     806                 :            :  * The iterator is not advanced.
     807                 :            :  *
     808                 :            :  * Returns: (transfer full): the value of the current attribute
     809                 :            :  *
     810                 :            :  * Since: 2.32
     811                 :            :  */
     812                 :            : GVariant *
     813                 :         12 : g_menu_attribute_iter_get_value (GMenuAttributeIter *iter)
     814                 :            : {
     815                 :         12 :   g_return_val_if_fail (iter->priv->valid, NULL);
     816                 :            : 
     817                 :         12 :   return g_variant_ref (iter->priv->value);
     818                 :            : }
     819                 :            : 
     820                 :            : static void
     821                 :     926392 : g_menu_attribute_iter_finalize (GObject *object)
     822                 :            : {
     823                 :     926392 :   GMenuAttributeIter *iter = G_MENU_ATTRIBUTE_ITER (object);
     824                 :            : 
     825         [ -  + ]:     926392 :   if (iter->priv->value)
     826                 :          0 :     g_variant_unref (iter->priv->value);
     827                 :            : 
     828                 :     926392 :   G_OBJECT_CLASS (g_menu_attribute_iter_parent_class)
     829                 :     926392 :     ->finalize (object);
     830                 :     926392 : }
     831                 :            : 
     832                 :            : static void
     833                 :     926392 : g_menu_attribute_iter_init (GMenuAttributeIter *iter)
     834                 :            : {
     835                 :     926392 :   iter->priv = g_menu_attribute_iter_get_instance_private (iter);
     836                 :     926392 : }
     837                 :            : 
     838                 :            : static void
     839                 :          2 : g_menu_attribute_iter_class_init (GMenuAttributeIterClass *class)
     840                 :            : {
     841                 :          2 :   GObjectClass *object_class = G_OBJECT_CLASS (class);
     842                 :            : 
     843                 :          2 :   object_class->finalize = g_menu_attribute_iter_finalize;
     844                 :          2 : }
     845                 :            : 
     846                 :            : struct _GMenuLinkIterPrivate
     847                 :            : {
     848                 :            :   GQuark name;
     849                 :            :   GMenuModel *value;
     850                 :            :   gboolean valid;
     851                 :            : };
     852                 :            : 
     853   [ +  +  +  -  :    2779181 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GMenuLinkIter, g_menu_link_iter, G_TYPE_OBJECT)
                   +  + ]
     854                 :            : 
     855                 :            : /**
     856                 :            :  * g_menu_link_iter_get_next:
     857                 :            :  * @iter: a #GMenuLinkIter
     858                 :            :  * @out_link: (out) (optional) (transfer none): the name of the link
     859                 :            :  * @value: (out) (optional) (transfer full): the linked #GMenuModel
     860                 :            :  *
     861                 :            :  * This function combines g_menu_link_iter_next() with
     862                 :            :  * g_menu_link_iter_get_name() and g_menu_link_iter_get_value().
     863                 :            :  *
     864                 :            :  * First the iterator is advanced to the next (possibly first) link.
     865                 :            :  * If that fails, then %FALSE is returned and there are no other effects.
     866                 :            :  *
     867                 :            :  * If successful, @out_link and @value are set to the name and #GMenuModel
     868                 :            :  * of the link that has just been advanced to.  At this point,
     869                 :            :  * g_menu_link_iter_get_name() and g_menu_link_iter_get_value() will return the
     870                 :            :  * same values again.
     871                 :            :  *
     872                 :            :  * The value returned in @out_link remains valid for as long as the iterator
     873                 :            :  * remains at the current position.  The value returned in @value must
     874                 :            :  * be unreffed using g_object_unref() when it is no longer in use.
     875                 :            :  *
     876                 :            :  * Returns: %TRUE on success, or %FALSE if there is no additional link
     877                 :            :  *
     878                 :            :  * Since: 2.32
     879                 :            :  */
     880                 :            : gboolean
     881                 :    1080621 : g_menu_link_iter_get_next (GMenuLinkIter  *iter,
     882                 :            :                            const gchar   **out_link,
     883                 :            :                            GMenuModel    **value)
     884                 :            : {
     885                 :            :   const gchar *name;
     886                 :            : 
     887         [ +  + ]:    1080621 :   if (iter->priv->value)
     888                 :            :     {
     889                 :     154230 :       g_object_unref (iter->priv->value);
     890                 :     154230 :       iter->priv->value = NULL;
     891                 :            :     }
     892                 :            : 
     893                 :    2161242 :   iter->priv->valid = G_MENU_LINK_ITER_GET_CLASS (iter)
     894                 :    1080621 :     ->get_next (iter, &name, &iter->priv->value);
     895                 :            : 
     896         [ +  + ]:    1080621 :   if (iter->priv->valid)
     897                 :            :     {
     898                 :     154230 :       g_assert (name != NULL);
     899                 :            : 
     900                 :     154230 :       iter->priv->name = g_quark_from_string (name);
     901         [ +  - ]:     154230 :       if (out_link)
     902                 :     154230 :         *out_link = g_quark_to_string (iter->priv->name);
     903                 :            : 
     904         [ +  - ]:     154230 :       if (value)
     905                 :     154230 :         *value = g_object_ref (iter->priv->value);
     906                 :            :     }
     907                 :            : 
     908                 :    1080621 :   return iter->priv->valid;
     909                 :            : }
     910                 :            : 
     911                 :            : /**
     912                 :            :  * g_menu_link_iter_next:
     913                 :            :  * @iter: a #GMenuLinkIter
     914                 :            :  *
     915                 :            :  * Attempts to advance the iterator to the next (possibly first)
     916                 :            :  * link.
     917                 :            :  *
     918                 :            :  * %TRUE is returned on success, or %FALSE if there are no more links.
     919                 :            :  *
     920                 :            :  * You must call this function when you first acquire the iterator to
     921                 :            :  * advance it to the first link (and determine if the first link exists
     922                 :            :  * at all).
     923                 :            :  *
     924                 :            :  * Returns: %TRUE on success, or %FALSE when there are no more links
     925                 :            :  *
     926                 :            :  * Since: 2.32
     927                 :            :  */
     928                 :            : gboolean
     929                 :         12 : g_menu_link_iter_next (GMenuLinkIter *iter)
     930                 :            : {
     931                 :         12 :   return g_menu_link_iter_get_next (iter, NULL, NULL);
     932                 :            : }
     933                 :            : 
     934                 :            : /**
     935                 :            :  * g_menu_link_iter_get_name:
     936                 :            :  * @iter: a #GMenuLinkIter
     937                 :            :  *
     938                 :            :  * Gets the name of the link at the current iterator position.
     939                 :            :  *
     940                 :            :  * The iterator is not advanced.
     941                 :            :  *
     942                 :            :  * Returns: the type of the link
     943                 :            :  *
     944                 :            :  * Since: 2.32
     945                 :            :  */
     946                 :            : const gchar *
     947                 :          0 : g_menu_link_iter_get_name (GMenuLinkIter *iter)
     948                 :            : {
     949                 :          0 :   g_return_val_if_fail (iter->priv->valid, 0);
     950                 :            : 
     951                 :          0 :   return g_quark_to_string (iter->priv->name);
     952                 :            : }
     953                 :            : 
     954                 :            : /**
     955                 :            :  * g_menu_link_iter_get_value:
     956                 :            :  * @iter: a #GMenuLinkIter
     957                 :            :  *
     958                 :            :  * Gets the linked #GMenuModel at the current iterator position.
     959                 :            :  *
     960                 :            :  * The iterator is not advanced.
     961                 :            :  *
     962                 :            :  * Returns: (transfer full): the #GMenuModel that is linked to
     963                 :            :  *
     964                 :            :  * Since: 2.32
     965                 :            :  */
     966                 :            : GMenuModel *
     967                 :          0 : g_menu_link_iter_get_value (GMenuLinkIter *iter)
     968                 :            : {
     969                 :          0 :   g_return_val_if_fail (iter->priv->valid, NULL);
     970                 :            : 
     971                 :          0 :   return g_object_ref (iter->priv->value);
     972                 :            : }
     973                 :            : 
     974                 :            : static void
     975                 :     926391 : g_menu_link_iter_finalize (GObject *object)
     976                 :            : {
     977                 :     926391 :   GMenuLinkIter *iter = G_MENU_LINK_ITER (object);
     978                 :            : 
     979         [ -  + ]:     926391 :   if (iter->priv->value)
     980                 :          0 :     g_object_unref (iter->priv->value);
     981                 :            : 
     982                 :     926391 :   G_OBJECT_CLASS (g_menu_link_iter_parent_class)
     983                 :     926391 :     ->finalize (object);
     984                 :     926391 : }
     985                 :            : 
     986                 :            : static void
     987                 :     926391 : g_menu_link_iter_init (GMenuLinkIter *iter)
     988                 :            : {
     989                 :     926391 :   iter->priv = g_menu_link_iter_get_instance_private (iter);
     990                 :     926391 : }
     991                 :            : 
     992                 :            : static void
     993                 :          2 : g_menu_link_iter_class_init (GMenuLinkIterClass *class)
     994                 :            : {
     995                 :          2 :   GObjectClass *object_class = G_OBJECT_CLASS (class);
     996                 :            : 
     997                 :          2 :   object_class->finalize = g_menu_link_iter_finalize;
     998                 :          2 : }

Generated by: LCOV version 1.14