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