LCOV - code coverage report
Current view: top level - src/libvalent/core - valent-extension.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 93.2 % 220 205
Test Date: 2025-12-04 03:51:48 Functions: 100.0 % 27 27
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 64.5 % 110 71

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-extension"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <gio/gio.h>
       9                 :             : #include <libpeas.h>
      10                 :             : 
      11                 :             : #include "valent-context.h"
      12                 :             : #include "valent-core-enums.h"
      13                 :             : #include "valent-object.h"
      14                 :             : 
      15                 :             : #include "valent-extension.h"
      16                 :             : 
      17                 :             : 
      18                 :             : /**
      19                 :             :  * ValentExtension:
      20                 :             :  *
      21                 :             :  * An abstract base class for extensions.
      22                 :             :  *
      23                 :             :  * `ValentExtension` is a base class for extensions with conveniences for
      24                 :             :  * [iface@Gio.Action], [class@Gio.Settings] backed by [class@Valent.Context].
      25                 :             :  *
      26                 :             :  * ## Implementation Notes
      27                 :             :  *
      28                 :             :  * Implementations that also implement [iface@Gio.Initable] or
      29                 :             :  * [iface@Gio.AsyncInitable] are marked as `VALENT_PLUGIN_STATE_INACTIVE` during
      30                 :             :  * construction and must call [method@Valent.Extension.plugin_state_changed] to
      31                 :             :  * reflect the result of initialization.
      32                 :             :  *
      33                 :             :  * ## Plugin Actions
      34                 :             :  *
      35                 :             :  * `ValentExtension` implements the [iface@Gio.ActionGroup] and
      36                 :             :  * [iface@Gio.ActionMap] interfaces, providing a simple way for plugins to
      37                 :             :  * expose functions and states. Each [iface@Gio.Action] added to the action map
      38                 :             :  * will be included in the object action group with the plugin's module name as
      39                 :             :  * a prefix (eg. `share.uri`).
      40                 :             :  *
      41                 :             :  * ## `.plugin` File
      42                 :             :  *
      43                 :             :  * Implementations may define the extra fields in the `.plugin` file, to take
      44                 :             :  * advantage of core features in the base class.
      45                 :             :  *
      46                 :             :  * The field names are inferred from the GType name of the implementation, with
      47                 :             :  * `Valent` being stripped if present. For example `ValentDevicePlugin` becomes
      48                 :             :  * `X-DevicePluginSettings`, while `NameDevicePlugin` would become
      49                 :             :  * `X-NameDevicePluginSettings`.
      50                 :             :  *
      51                 :             :  * - Extension Category Field
      52                 :             :  *
      53                 :             :  *     A list of categories separated by semi-colons, serving as a hint for
      54                 :             :  *     organizational purposes. This should be in the form `Main;Additional;`,
      55                 :             :  *     with values from the freedesktop.org Desktop Menu Specification.
      56                 :             :  *
      57                 :             :  *     Field pattern: `X-<type name>Category`
      58                 :             :  *
      59                 :             :  * - [class@Gio.Settings] Schema Field
      60                 :             :  *
      61                 :             :  *     A [class@Gio.Settings] schema ID for the extensions's settings. See
      62                 :             :  *     [method@Valent.Context.get_plugin_settings] for more information.
      63                 :             :  *
      64                 :             :  *     Field pattern: `X-<type name>Settings`
      65                 :             :  *
      66                 :             :  * Since: 1.0
      67                 :             :  */
      68                 :             : 
      69                 :             : typedef struct
      70                 :             : {
      71                 :             :   PeasPluginInfo    *plugin_info;
      72                 :             :   ValentPluginState  plugin_state;
      73                 :             :   GError            *plugin_error;
      74                 :             : 
      75                 :             :   GHashTable        *actions;
      76                 :             :   ValentContext     *context;
      77                 :             :   GSettings         *settings;
      78                 :             : } ValentExtensionPrivate;
      79                 :             : 
      80                 :             : static void   g_action_group_iface_init (GActionGroupInterface *iface);
      81                 :             : static void   g_action_map_iface_init   (GActionMapInterface   *iface);
      82                 :             : 
      83   [ +  +  +  - ]:        5811 : G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ValentExtension, valent_extension, VALENT_TYPE_OBJECT,
      84                 :             :                                   G_ADD_PRIVATE (ValentExtension)
      85                 :             :                                   G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_action_group_iface_init)
      86                 :             :                                   G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_MAP, g_action_map_iface_init))
      87                 :             : 
      88                 :             : typedef enum {
      89                 :             :   PROP_CONTEXT = 1,
      90                 :             :   PROP_PLUGIN_INFO,
      91                 :             :   PROP_PLUGIN_STATE,
      92                 :             :   PROP_SETTINGS,
      93                 :             : } ValentExtensionProperty;
      94                 :             : 
      95                 :             : static GParamSpec *properties[PROP_SETTINGS + 1] = { NULL, };
      96                 :             : 
      97                 :             : 
      98                 :             : /*
      99                 :             :  * GActionGroup
     100                 :             :  */
     101                 :             : static void
     102                 :          22 : valent_extension_activate_action (GActionGroup *action_group,
     103                 :             :                                   const char   *action_name,
     104                 :             :                                   GVariant     *parameter)
     105                 :             : {
     106                 :          22 :   ValentExtension *self = VALENT_EXTENSION (action_group);
     107                 :          22 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     108                 :          22 :   GAction *action;
     109                 :             : 
     110         [ +  - ]:          22 :   if ((action = g_hash_table_lookup (priv->actions, action_name)) != NULL)
     111                 :          22 :     g_action_activate (action, parameter);
     112                 :          22 : }
     113                 :             : 
     114                 :             : static void
     115                 :           1 : valent_extension_change_action_state (GActionGroup *action_group,
     116                 :             :                                       const char   *action_name,
     117                 :             :                                       GVariant     *value)
     118                 :             : {
     119                 :           1 :   ValentExtension *self = VALENT_EXTENSION (action_group);
     120                 :           1 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     121                 :           1 :   GAction *action;
     122                 :             : 
     123         [ +  - ]:           1 :   if ((action = g_hash_table_lookup (priv->actions, action_name)) != NULL)
     124                 :           1 :     g_action_change_state (action, value);
     125                 :           1 : }
     126                 :             : 
     127                 :             : static char **
     128                 :         116 : valent_extension_list_actions (GActionGroup *action_group)
     129                 :             : {
     130                 :         116 :   ValentExtension *self = VALENT_EXTENSION (action_group);
     131                 :         116 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     132                 :         232 :   g_auto (GStrv) actions = NULL;
     133                 :         116 :   GHashTableIter iter;
     134                 :         116 :   gpointer key;
     135                 :         116 :   unsigned int i = 0;
     136                 :             : 
     137         [ -  + ]:         116 :   actions = g_new0 (char *, g_hash_table_size (priv->actions) + 1);
     138                 :             : 
     139                 :         116 :   g_hash_table_iter_init (&iter, priv->actions);
     140                 :             : 
     141         [ +  + ]:         399 :   while (g_hash_table_iter_next (&iter, &key, NULL))
     142         [ -  + ]:         566 :     actions[i++] = g_strdup (key);
     143                 :             : 
     144                 :         116 :   return g_steal_pointer (&actions);
     145                 :             : }
     146                 :             : 
     147                 :             : static gboolean
     148                 :           8 : valent_extension_query_action (GActionGroup        *action_group,
     149                 :             :                                const char          *action_name,
     150                 :             :                                gboolean            *enabled,
     151                 :             :                                const GVariantType **parameter_type,
     152                 :             :                                const GVariantType **state_type,
     153                 :             :                                GVariant           **state_hint,
     154                 :             :                                GVariant           **state)
     155                 :             : {
     156                 :           8 :   ValentExtension *self = VALENT_EXTENSION (action_group);
     157                 :           8 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     158                 :           8 :   GAction *action;
     159                 :             : 
     160         [ +  - ]:           8 :   if ((action = g_hash_table_lookup (priv->actions, action_name)) == NULL)
     161                 :             :     return FALSE;
     162                 :             : 
     163         [ +  + ]:           8 :   if (enabled)
     164                 :           1 :     *enabled = g_action_get_enabled (action);
     165                 :             : 
     166         [ +  + ]:           8 :   if (parameter_type)
     167                 :           1 :     *parameter_type = g_action_get_parameter_type (action);
     168                 :             : 
     169         [ +  + ]:           8 :   if (state_type)
     170                 :           1 :     *state_type = g_action_get_state_type (action);
     171                 :             : 
     172         [ +  + ]:           8 :   if (state_hint)
     173                 :           1 :     *state_hint = g_action_get_state_hint (action);
     174                 :             : 
     175         [ +  - ]:           8 :   if (state)
     176                 :           8 :     *state = g_action_get_state (action);
     177                 :             : 
     178                 :             :   return TRUE;
     179                 :             : }
     180                 :             : 
     181                 :             : static void
     182                 :          53 : g_action_group_iface_init (GActionGroupInterface *iface)
     183                 :             : {
     184                 :          53 :   iface->activate_action = valent_extension_activate_action;
     185                 :          53 :   iface->change_action_state = valent_extension_change_action_state;
     186                 :          53 :   iface->list_actions = valent_extension_list_actions;
     187                 :          53 :   iface->query_action = valent_extension_query_action;
     188                 :          53 : }
     189                 :             : 
     190                 :             : /*
     191                 :             :  * GActionMap
     192                 :             :  */
     193                 :             : static void
     194                 :         478 : on_action_enabled_changed (GAction      *action,
     195                 :             :                            GParamSpec   *pspec,
     196                 :             :                            GActionGroup *action_group)
     197                 :             : {
     198                 :         478 :   g_action_group_action_enabled_changed (action_group,
     199                 :             :                                          g_action_get_name (action),
     200                 :             :                                          g_action_get_enabled (action));
     201                 :         478 : }
     202                 :             : 
     203                 :             : static void
     204                 :          70 : on_action_state_changed (GAction      *action,
     205                 :             :                          GParamSpec   *pspec,
     206                 :             :                          GActionGroup *action_group)
     207                 :             : {
     208                 :         140 :   g_autoptr (GVariant) value = NULL;
     209                 :             : 
     210                 :          70 :   value = g_action_get_state (action);
     211         [ +  - ]:          70 :   g_action_group_action_state_changed (action_group,
     212                 :             :                                        g_action_get_name (action),
     213                 :             :                                        value);
     214                 :          70 : }
     215                 :             : 
     216                 :             : static void
     217                 :         352 : valent_extension_disconnect_action (ValentExtension *self,
     218                 :             :                                     GAction         *action)
     219                 :             : {
     220                 :         352 :   g_signal_handlers_disconnect_by_func (action, on_action_enabled_changed, self);
     221                 :         352 :   g_signal_handlers_disconnect_by_func (action, on_action_state_changed, self);
     222                 :         352 : }
     223                 :             : 
     224                 :             : static GAction *
     225                 :         388 : valent_extension_lookup_action (GActionMap *action_map,
     226                 :             :                                 const char *action_name)
     227                 :             : {
     228                 :         388 :   ValentExtension *self = VALENT_EXTENSION (action_map);
     229                 :         388 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     230                 :             : 
     231                 :         388 :   return g_hash_table_lookup (priv->actions, action_name);
     232                 :             : }
     233                 :             : 
     234                 :             : static void
     235                 :         380 : valent_extension_add_action (GActionMap *action_map,
     236                 :             :                              GAction    *action)
     237                 :             : {
     238                 :         380 :   ValentExtension *self = VALENT_EXTENSION (action_map);
     239                 :         380 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     240                 :         380 :   const char *action_name;
     241                 :         380 :   GAction *replacing;
     242                 :             : 
     243                 :         380 :   action_name = g_action_get_name (action);
     244                 :             : 
     245         [ +  - ]:         380 :   if ((replacing = g_hash_table_lookup (priv->actions, action_name)) == action)
     246                 :             :     return;
     247                 :             : 
     248         [ -  + ]:         380 :   if (replacing != NULL)
     249                 :             :     {
     250                 :           0 :       g_action_group_action_removed (G_ACTION_GROUP (action_map), action_name);
     251                 :           0 :       valent_extension_disconnect_action (self, replacing);
     252                 :             :     }
     253                 :             : 
     254                 :         380 :   g_signal_connect_object (action,
     255                 :             :                            "notify::enabled",
     256                 :             :                            G_CALLBACK (on_action_enabled_changed),
     257                 :             :                            self,
     258                 :             :                            G_CONNECT_DEFAULT);
     259                 :             : 
     260         [ +  + ]:         380 :   if (g_action_get_state_type (action) != NULL)
     261                 :             :     {
     262                 :          52 :       g_signal_connect_object (action,
     263                 :             :                                "notify::state",
     264                 :             :                                G_CALLBACK (on_action_state_changed),
     265                 :             :                                self,
     266                 :             :                                G_CONNECT_DEFAULT);
     267                 :             :     }
     268                 :             : 
     269         [ -  + ]:         380 :   g_hash_table_replace (priv->actions,
     270                 :         380 :                         g_strdup (action_name),
     271                 :             :                         g_object_ref (action));
     272                 :         380 :   g_action_group_action_added (G_ACTION_GROUP (action_map), action_name);
     273                 :             : }
     274                 :             : 
     275                 :             : static void
     276                 :           1 : valent_extension_remove_action (GActionMap *action_map,
     277                 :             :                                 const char *action_name)
     278                 :             : {
     279                 :           1 :   ValentExtension *self = VALENT_EXTENSION (action_map);
     280                 :           1 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     281                 :           1 :   GAction *action;
     282                 :             : 
     283         [ +  - ]:           1 :   if ((action = g_hash_table_lookup (priv->actions, action_name)) != NULL)
     284                 :             :     {
     285                 :           1 :       g_action_group_action_removed (G_ACTION_GROUP (action_map), action_name);
     286                 :           1 :       valent_extension_disconnect_action (self, action);
     287                 :           1 :       g_hash_table_remove (priv->actions, action_name);
     288                 :             :     }
     289                 :           1 : }
     290                 :             : 
     291                 :             : static void
     292                 :          53 : g_action_map_iface_init (GActionMapInterface *iface)
     293                 :             : {
     294                 :          53 :   iface->add_action = valent_extension_add_action;
     295                 :          53 :   iface->lookup_action = valent_extension_lookup_action;
     296                 :          53 :   iface->remove_action = valent_extension_remove_action;
     297                 :          53 : }
     298                 :             : 
     299                 :             : /*
     300                 :             :  * ValentObject
     301                 :             :  */
     302                 :             : static void
     303                 :         430 : valent_extension_destroy (ValentObject *object)
     304                 :             : {
     305                 :         430 :   ValentExtension *self = VALENT_EXTENSION (object);
     306                 :         430 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     307                 :         430 :   GHashTableIter iter;
     308                 :         430 :   const char *action_name;
     309                 :         430 :   GAction *action;
     310                 :             : 
     311                 :         430 :   g_hash_table_iter_init (&iter, priv->actions);
     312         [ +  + ]:         781 :   while (g_hash_table_iter_next (&iter, (void **)&action_name, (void **)&action))
     313                 :             :     {
     314                 :         351 :       g_action_group_action_removed (G_ACTION_GROUP (self), action_name);
     315                 :         351 :       valent_extension_disconnect_action (self, action);
     316                 :         351 :       g_hash_table_iter_remove (&iter);
     317                 :             :     }
     318                 :             : 
     319                 :         430 :   valent_extension_plugin_state_changed (self, VALENT_PLUGIN_STATE_INACTIVE, NULL);
     320                 :             : 
     321                 :         430 :   VALENT_OBJECT_CLASS (valent_extension_parent_class)->destroy (object);
     322                 :         430 : }
     323                 :             : 
     324                 :             : /*
     325                 :             :  * GObject
     326                 :             :  */
     327                 :             : static void
     328                 :         255 : valent_extension_constructed (GObject *object)
     329                 :             : {
     330                 :         255 :   ValentExtension *self = VALENT_EXTENSION (object);
     331                 :         255 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     332                 :             : 
     333                 :         255 :   G_OBJECT_CLASS (valent_extension_parent_class)->constructed (object);
     334                 :             : 
     335                 :             :   /* If this is an extension backed by a plugin, try to create
     336                 :             :    * a settings object from the plugin info.
     337                 :             :    */
     338   [ +  +  +  - ]:         255 :   if (priv->plugin_info != NULL && priv->context != NULL)
     339                 :             :     {
     340                 :         229 :       GType type_base = g_type_parent (G_OBJECT_TYPE (self));
     341                 :         229 :       const char *type_name = g_type_name (type_base);
     342                 :         229 :       g_autofree char *key = NULL;
     343                 :             : 
     344   [ +  -  +  -  :         229 :       if (g_str_has_prefix (type_name, "Valent"))
                   +  - ]
     345                 :         229 :         key = g_strdup_printf ("X-%sSettings", &type_name[strlen ("Valent")]);
     346                 :             :       else
     347                 :           0 :         key = g_strdup_printf ("X-%sSettings", type_name);
     348                 :             : 
     349                 :         229 :       priv->settings = valent_context_get_plugin_settings (priv->context,
     350                 :             :                                                            priv->plugin_info,
     351                 :             :                                                            key);
     352                 :             :     }
     353                 :             : 
     354                 :             :   /* If this is an extension with failable initialization, it is
     355                 :             :    * expected to update the state with the result.
     356                 :             :    */
     357   [ +  -  +  -  :         255 :   if (G_IS_INITABLE (object) || G_IS_ASYNC_INITABLE (object))
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
     358                 :          14 :     priv->plugin_state = VALENT_PLUGIN_STATE_INACTIVE;
     359                 :         255 : }
     360                 :             : static void
     361                 :         227 : valent_extension_finalize (GObject *object)
     362                 :             : {
     363                 :         227 :   ValentExtension *self = VALENT_EXTENSION (object);
     364                 :         227 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     365                 :             : 
     366                 :         227 :   g_clear_error (&priv->plugin_error);
     367         [ +  - ]:         227 :   g_clear_pointer (&priv->actions, g_hash_table_unref);
     368         [ +  + ]:         227 :   g_clear_object (&priv->context);
     369         [ +  + ]:         227 :   g_clear_object (&priv->plugin_info);
     370         [ +  + ]:         227 :   g_clear_object (&priv->settings);
     371                 :             : 
     372                 :         227 :   G_OBJECT_CLASS (valent_extension_parent_class)->finalize (object);
     373                 :         227 : }
     374                 :             : 
     375                 :             : static void
     376                 :           8 : valent_extension_get_property (GObject    *object,
     377                 :             :                                guint       prop_id,
     378                 :             :                                GValue     *value,
     379                 :             :                                GParamSpec *pspec)
     380                 :             : {
     381                 :           8 :   ValentExtension *self = VALENT_EXTENSION (object);
     382                 :           8 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     383                 :             : 
     384   [ +  +  -  -  :           8 :   switch ((ValentExtensionProperty)prop_id)
                      - ]
     385                 :             :     {
     386                 :           6 :     case PROP_CONTEXT:
     387                 :           6 :       g_value_set_object (value, priv->context);
     388                 :           6 :       break;
     389                 :             : 
     390                 :           2 :     case PROP_PLUGIN_INFO:
     391                 :           2 :       g_value_set_object (value, priv->plugin_info);
     392                 :           2 :       break;
     393                 :             : 
     394                 :           0 :     case PROP_PLUGIN_STATE:
     395                 :           0 :       g_value_set_enum (value, priv->plugin_state);
     396                 :           0 :       break;
     397                 :             : 
     398                 :           0 :     case PROP_SETTINGS:
     399                 :           0 :       g_value_set_object (value, priv->settings);
     400                 :           0 :       break;
     401                 :             : 
     402                 :           0 :     default:
     403                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     404                 :             :     }
     405                 :           8 : }
     406                 :             : 
     407                 :             : static void
     408                 :         510 : valent_extension_set_property (GObject      *object,
     409                 :             :                                guint         prop_id,
     410                 :             :                                const GValue *value,
     411                 :             :                                GParamSpec   *pspec)
     412                 :             : {
     413                 :         510 :   ValentExtension *self = VALENT_EXTENSION (object);
     414                 :         510 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     415                 :             : 
     416      [ +  +  - ]:         510 :   switch ((ValentExtensionProperty)prop_id)
     417                 :             :     {
     418                 :         255 :     case PROP_CONTEXT:
     419                 :         255 :       priv->context = g_value_dup_object (value);
     420                 :         255 :       break;
     421                 :             : 
     422                 :         255 :     case PROP_PLUGIN_INFO:
     423                 :         255 :       priv->plugin_info = g_value_dup_object (value);
     424                 :         255 :       break;
     425                 :             : 
     426                 :           0 :     case PROP_PLUGIN_STATE:
     427                 :             :     case PROP_SETTINGS:
     428                 :             :     default:
     429                 :           0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     430                 :             :     }
     431                 :         510 : }
     432                 :             : 
     433                 :             : static void
     434                 :          53 : valent_extension_class_init (ValentExtensionClass *klass)
     435                 :             : {
     436                 :          53 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     437                 :          53 :   ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
     438                 :             : 
     439                 :          53 :   object_class->constructed = valent_extension_constructed;
     440                 :          53 :   object_class->finalize = valent_extension_finalize;
     441                 :          53 :   object_class->get_property = valent_extension_get_property;
     442                 :          53 :   object_class->set_property = valent_extension_set_property;
     443                 :             : 
     444                 :          53 :   vobject_class->destroy = valent_extension_destroy;
     445                 :             : 
     446                 :             :   /**
     447                 :             :    * ValentExtension:context: (getter get_context)
     448                 :             :    *
     449                 :             :    * The [class@Valent.Device] this plugin is bound to.
     450                 :             :    *
     451                 :             :    * Since: 1.0
     452                 :             :    */
     453                 :         106 :   properties [PROP_CONTEXT] =
     454                 :          53 :     g_param_spec_object ("context", NULL, NULL,
     455                 :             :                          VALENT_TYPE_CONTEXT,
     456                 :             :                          (G_PARAM_READWRITE |
     457                 :             :                           G_PARAM_CONSTRUCT_ONLY |
     458                 :             :                           G_PARAM_EXPLICIT_NOTIFY |
     459                 :             :                           G_PARAM_STATIC_STRINGS));
     460                 :             : 
     461                 :             :   /**
     462                 :             :    * ValentExtension:plugin-info:
     463                 :             :    *
     464                 :             :    * The [class@Peas.PluginInfo] describing this plugin.
     465                 :             :    *
     466                 :             :    * Since: 1.0
     467                 :             :    */
     468                 :         106 :   properties [PROP_PLUGIN_INFO] =
     469                 :          53 :     g_param_spec_object ("plugin-info", NULL, NULL,
     470                 :             :                          PEAS_TYPE_PLUGIN_INFO,
     471                 :             :                          (G_PARAM_READWRITE |
     472                 :             :                           G_PARAM_CONSTRUCT_ONLY |
     473                 :             :                           G_PARAM_EXPLICIT_NOTIFY |
     474                 :             :                           G_PARAM_STATIC_STRINGS));
     475                 :             : 
     476                 :             :   /**
     477                 :             :    * ValentExtension:plugin-state:
     478                 :             :    *
     479                 :             :    * The [enum@Valent.PluginState] describing the state of the extension.
     480                 :             :    *
     481                 :             :    * Since: 1.0
     482                 :             :    */
     483                 :         106 :   properties [PROP_PLUGIN_STATE] =
     484                 :          53 :     g_param_spec_enum ("plugin-state", NULL, NULL,
     485                 :             :                        VALENT_TYPE_PLUGIN_STATE,
     486                 :             :                        VALENT_PLUGIN_STATE_ACTIVE,
     487                 :             :                        (G_PARAM_READABLE |
     488                 :             :                         G_PARAM_EXPLICIT_NOTIFY |
     489                 :             :                         G_PARAM_STATIC_STRINGS));
     490                 :             : 
     491                 :             :   /**
     492                 :             :    * ValentExtension:settings: (getter get_settings)
     493                 :             :    *
     494                 :             :    * The [class@Gio.Settings] for this plugin.
     495                 :             :    *
     496                 :             :    * Since: 1.0
     497                 :             :    */
     498                 :         106 :   properties [PROP_SETTINGS] =
     499                 :          53 :     g_param_spec_object ("settings", NULL, NULL,
     500                 :             :                          G_TYPE_SETTINGS,
     501                 :             :                          (G_PARAM_READABLE |
     502                 :             :                           G_PARAM_EXPLICIT_NOTIFY |
     503                 :             :                           G_PARAM_STATIC_STRINGS));
     504                 :             : 
     505                 :          53 :   g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
     506                 :          53 : }
     507                 :             : 
     508                 :             : static void
     509                 :         255 : valent_extension_init (ValentExtension *self)
     510                 :             : {
     511                 :         255 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (self);
     512                 :             : 
     513                 :         255 :   priv->actions = g_hash_table_new_full (g_str_hash,
     514                 :             :                                          g_str_equal,
     515                 :             :                                          g_free,
     516                 :             :                                          g_object_unref);
     517                 :         255 : }
     518                 :             : 
     519                 :             : /**
     520                 :             :  * valent_extension_get_context: (get-property context)
     521                 :             :  * @extension: a `ValentExtension`
     522                 :             :  *
     523                 :             :  * Get the settings for this plugin.
     524                 :             :  *
     525                 :             :  * Returns: (transfer none) (nullable): a `ValentContext`
     526                 :             :  *
     527                 :             :  * Since: 1.0
     528                 :             :  */
     529                 :             : ValentContext *
     530                 :          34 : valent_extension_get_context (ValentExtension *extension)
     531                 :             : {
     532                 :          34 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (extension);
     533                 :             : 
     534         [ -  + ]:          34 :   g_return_val_if_fail (VALENT_IS_EXTENSION (extension), NULL);
     535                 :             : 
     536                 :          34 :   return priv->context;
     537                 :             : }
     538                 :             : 
     539                 :             : /**
     540                 :             :  * valent_extension_get_settings: (get-property settings)
     541                 :             :  * @extension: a `ValentExtension`
     542                 :             :  *
     543                 :             :  * Get the settings for this plugin.
     544                 :             :  *
     545                 :             :  * Returns: (transfer none) (nullable): a `GSettings`
     546                 :             :  *
     547                 :             :  * Since: 1.0
     548                 :             :  */
     549                 :             : GSettings *
     550                 :          92 : valent_extension_get_settings (ValentExtension *extension)
     551                 :             : {
     552                 :          92 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (extension);
     553                 :             : 
     554         [ -  + ]:          92 :   g_return_val_if_fail (VALENT_IS_EXTENSION (extension), NULL);
     555                 :             : 
     556                 :          92 :   return priv->settings;
     557                 :             : }
     558                 :             : 
     559                 :             : /**
     560                 :             :  * valent_extension_plugin_state_check:
     561                 :             :  * @extension: a `ValentExtension`
     562                 :             :  * @error: (nullable): a `GError`
     563                 :             :  *
     564                 :             :  * Get the extension state, while propagating any errors that describe it.
     565                 :             :  *
     566                 :             :  * Returns: a `ValentPluginState`
     567                 :             :  *
     568                 :             :  * Since: 1.0
     569                 :             :  */
     570                 :             : ValentPluginState
     571                 :         140 : valent_extension_plugin_state_check (ValentExtension  *extension,
     572                 :             :                                      GError          **error)
     573                 :             : {
     574                 :         140 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (extension);
     575                 :             : 
     576         [ -  + ]:         140 :   g_return_val_if_fail (VALENT_IS_EXTENSION (extension), VALENT_PLUGIN_STATE_INACTIVE);
     577   [ +  +  +  - ]:         140 :   g_return_val_if_fail (error == NULL || *error == NULL, VALENT_PLUGIN_STATE_INACTIVE);
     578                 :             : 
     579   [ -  +  -  - ]:         140 :   if (priv->plugin_error != NULL && error != NULL)
     580                 :           0 :     *error = g_error_copy (priv->plugin_error);
     581                 :             : 
     582                 :         140 :   return priv->plugin_state;
     583                 :             : }
     584                 :             : 
     585                 :             : /**
     586                 :             :  * valent_extension_plugin_state_changed:
     587                 :             :  * @extension: a `ValentExtension`
     588                 :             :  * @state: a `ValentPluginState`
     589                 :             :  * @error: (nullable): a `GError`
     590                 :             :  *
     591                 :             :  * Emits [signal@GObject.Object::notify] for
     592                 :             :  * [property@Valent.Extension:plugin-state].
     593                 :             :  *
     594                 :             :  * Implementations should call this method to inform the managing object of
     595                 :             :  * changes to the state of the extension, especially unrecoverable errors.
     596                 :             :  *
     597                 :             :  * Since: 1.0
     598                 :             :  */
     599                 :             : void
     600                 :         446 : valent_extension_plugin_state_changed (ValentExtension   *extension,
     601                 :             :                                        ValentPluginState  state,
     602                 :             :                                        const GError      *error)
     603                 :             : {
     604                 :         446 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (extension);
     605                 :             : 
     606         [ -  + ]:         446 :   g_return_if_fail (VALENT_IS_EXTENSION (extension));
     607         [ +  - ]:         446 :   g_return_if_fail (state != VALENT_PLUGIN_STATE_ERROR || error != NULL);
     608                 :             : 
     609                 :         446 :   g_clear_error (&priv->plugin_error);
     610         [ -  + ]:         446 :   if (state == VALENT_PLUGIN_STATE_ERROR && error != NULL)
     611                 :           0 :     priv->plugin_error = g_error_copy (error);
     612                 :             : 
     613   [ +  +  -  + ]:         446 :   if (priv->plugin_state != state || priv->plugin_error != NULL)
     614                 :             :     {
     615                 :         243 :       priv->plugin_state = state;
     616                 :         243 :       g_object_notify_by_pspec (G_OBJECT (extension),
     617                 :             :                                 properties[PROP_PLUGIN_STATE]);
     618                 :             :     }
     619                 :             : }
     620                 :             : 
     621                 :             : /**
     622                 :             :  * valent_extension_toggle_actions:
     623                 :             :  * @extension: a `ValentExtension`
     624                 :             :  * @enabled: boolean
     625                 :             :  *
     626                 :             :  * Enable or disable all actions.
     627                 :             :  *
     628                 :             :  * Set the [property@Gio.Action:enabled] property of the actions for @extension to
     629                 :             :  * @enabled.
     630                 :             :  *
     631                 :             :  * Since: 1.0
     632                 :             :  */
     633                 :             : void
     634                 :         188 : valent_extension_toggle_actions (ValentExtension *extension,
     635                 :             :                                  gboolean         enabled)
     636                 :             : {
     637                 :         188 :   ValentExtensionPrivate *priv = valent_extension_get_instance_private (extension);
     638                 :         188 :   GHashTableIter iter;
     639                 :         188 :   GSimpleAction *action;
     640                 :             : 
     641         [ -  + ]:         188 :   g_return_if_fail (VALENT_IS_EXTENSION (extension));
     642                 :             : 
     643                 :         188 :   g_hash_table_iter_init (&iter, priv->actions);
     644                 :             : 
     645         [ +  + ]:         714 :   while (g_hash_table_iter_next (&iter, NULL, (void **)&action))
     646                 :         526 :     g_simple_action_set_enabled (action, enabled);
     647                 :             : }
     648                 :             : 
        

Generated by: LCOV version 2.0-1