LCOV - code coverage report
Current view: top level - src/plugins/gnome - valent-device-preferences-commands.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 39.8 % 161 64
Test Date: 2024-11-25 01:35:12 Functions: 62.5 % 16 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 25.9 % 58 15

             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-runcommand-preferences"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <glib/gi18n.h>
       9                 :             : #include <adwaita.h>
      10                 :             : #include <gtk/gtk.h>
      11                 :             : #include <libportal/portal.h>
      12                 :             : #include <valent.h>
      13                 :             : 
      14                 :             : #include "valent-device-preferences-commands-editor.h"
      15                 :             : 
      16                 :             : #include "valent-device-preferences-commands.h"
      17                 :             : 
      18                 :             : 
      19                 :             : struct _ValentRuncommandPreferences
      20                 :             : {
      21                 :             :   ValentDevicePreferencesGroup  parent_instance;
      22                 :             : 
      23                 :             :   GtkWindow                    *editor;
      24                 :             : 
      25                 :             :   /* template */
      26                 :             :   AdwExpanderRow               *command_list_row;
      27                 :             :   GtkListBox                   *command_list;
      28                 :             : };
      29                 :             : 
      30   [ +  +  +  - ]:          44 : G_DEFINE_FINAL_TYPE (ValentRuncommandPreferences, valent_runcommand_preferences, VALENT_TYPE_DEVICE_PREFERENCES_GROUP)
      31                 :             : 
      32                 :             : 
      33                 :             : /*
      34                 :             :  * Rows
      35                 :             :  */
      36                 :             : static void
      37                 :           1 : valent_runcommand_preferences_populate (ValentRuncommandPreferences *self)
      38                 :             : {
      39                 :           1 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
      40                 :           1 :   GSettings *settings;
      41                 :           1 :   GtkWidget *child;
      42                 :           2 :   g_autoptr (GVariant) commands = NULL;
      43                 :           1 :   GVariantIter iter;
      44                 :           1 :   char *uuid;
      45                 :           1 :   GVariant *item;
      46                 :             : 
      47         [ +  - ]:           1 :   g_assert (VALENT_IS_RUNCOMMAND_PREFERENCES (self));
      48                 :             : 
      49                 :           1 :   for (child = gtk_widget_get_first_child (GTK_WIDGET (self->command_list));
      50         [ -  + ]:           1 :        child != NULL;)
      51                 :             :     {
      52                 :           0 :       GtkWidget *current_child = child;
      53                 :           0 :       child = gtk_widget_get_next_sibling (current_child);
      54                 :           0 :       gtk_list_box_remove (self->command_list, current_child);
      55                 :             :     }
      56                 :             : 
      57                 :           1 :   settings = valent_device_preferences_group_get_settings (group);
      58                 :           1 :   commands = g_settings_get_value (settings, "commands");
      59                 :             : 
      60                 :           1 :   g_variant_iter_init (&iter, commands);
      61                 :             : 
      62         [ -  + ]:           1 :   while (g_variant_iter_next (&iter, "{sv}", &uuid, &item))
      63                 :             :     {
      64                 :           0 :       const char *name = NULL;
      65                 :           0 :       const char *command = NULL;
      66                 :             : 
      67   [ #  #  #  # ]:           0 :       if (g_variant_lookup (item, "name", "&s", &name) &&
      68                 :           0 :           g_variant_lookup (item, "command", "&s", &command))
      69                 :             :         {
      70                 :           0 :           GtkWidget *row;
      71                 :           0 :           GtkWidget *icon;
      72                 :             : 
      73                 :           0 :           row = g_object_new (ADW_TYPE_ACTION_ROW,
      74                 :             :                               "name",          uuid,
      75                 :             :                               "title",         name,
      76                 :             :                               "subtitle",      command,
      77                 :             :                               "activatable",   TRUE,
      78                 :             :                               "selectable",    FALSE,
      79                 :             :                               "action-target", g_variant_new_string (uuid),
      80                 :             :                               "action-name",   "runcommand.edit",
      81                 :             :                               NULL);
      82                 :             : 
      83                 :           0 :           icon = g_object_new (GTK_TYPE_IMAGE,
      84                 :             :                                "icon-name",    "document-edit-symbolic",
      85                 :             :                                "tooltip-text", _("Edit Command"),
      86                 :             :                                NULL);
      87                 :           0 :           gtk_widget_add_css_class (icon, "dim-label");
      88                 :           0 :           adw_action_row_add_suffix (ADW_ACTION_ROW (row), icon);
      89                 :             : 
      90                 :             :           /* a11y: an activatable widget would change the label and description,
      91                 :             :            * but a button is unnecessary and the label should be unchanged. */
      92                 :           0 :           gtk_accessible_update_relation (GTK_ACCESSIBLE (row),
      93                 :             :                                           GTK_ACCESSIBLE_RELATION_DESCRIBED_BY,
      94                 :             :                                             icon, NULL,
      95                 :             :                                           -1);
      96                 :             : 
      97                 :           0 :           gtk_list_box_append (self->command_list, row);
      98                 :             :         }
      99                 :             : 
     100         [ #  # ]:           0 :       g_clear_pointer (&uuid, g_free);
     101         [ #  # ]:           0 :       g_clear_pointer (&item, g_variant_unref);
     102                 :             :     }
     103                 :           1 : }
     104                 :             : 
     105                 :             : static int
     106                 :           0 : sort_commands (GtkListBoxRow *row1,
     107                 :             :                GtkListBoxRow *row2,
     108                 :             :                gpointer       user_data)
     109                 :             : {
     110                 :           0 :   const char *title1;
     111                 :           0 :   const char *title2;
     112                 :             : 
     113                 :           0 :   title1 = adw_preferences_row_get_title (ADW_PREFERENCES_ROW (row1));
     114                 :           0 :   title2 = adw_preferences_row_get_title (ADW_PREFERENCES_ROW (row2));
     115                 :             : 
     116                 :           0 :   return g_utf8_collate (title1, title2);
     117                 :             : }
     118                 :             : 
     119                 :             : static inline GtkListBox *
     120                 :           1 : _adw_expander_row_get_list (AdwExpanderRow *row)
     121                 :             : {
     122                 :           1 :   GtkWidget *box;
     123                 :           1 :   GtkWidget *child;
     124                 :             : 
     125                 :             :   /* First child is a GtkBox */
     126                 :           1 :   box = gtk_widget_get_first_child (GTK_WIDGET (row));
     127                 :             : 
     128                 :             :   /* The GtkBox contains the primary AdwActionRow and a GtkRevealer */
     129                 :           1 :   for (child = gtk_widget_get_first_child (box);
     130         [ +  - ]:           2 :        child != NULL;
     131                 :           1 :        child = gtk_widget_get_next_sibling (child))
     132                 :             :     {
     133   [ +  -  +  +  :           2 :       if (GTK_IS_REVEALER (child))
                   +  - ]
     134                 :             :         break;
     135                 :             :     }
     136                 :             : 
     137                 :             :   /* The GtkRevealer's child is the GtkListBox */
     138   [ +  -  +  -  :           1 :   if (GTK_IS_REVEALER (child))
             -  +  -  - ]
     139                 :           1 :     return GTK_LIST_BOX (gtk_revealer_get_child (GTK_REVEALER (child)));
     140                 :             : 
     141                 :             :   return NULL;
     142                 :             : }
     143                 :             : 
     144                 :             : /*
     145                 :             :  * GAction
     146                 :             :  */
     147                 :             : static void
     148                 :           0 : on_command_changed (ValentRuncommandEditor      *editor,
     149                 :             :                     GParamSpec                  *pspec,
     150                 :             :                     ValentRuncommandPreferences *self)
     151                 :             : {
     152                 :           0 :   const char *uuid;
     153                 :           0 :   GVariant *command;
     154                 :             : 
     155         [ #  # ]:           0 :   g_assert (VALENT_IS_RUNCOMMAND_EDITOR (editor));
     156         [ #  # ]:           0 :   g_assert (VALENT_IS_RUNCOMMAND_PREFERENCES (self));
     157                 :             : 
     158                 :           0 :   uuid = valent_runcommand_editor_get_uuid (editor);
     159                 :           0 :   command = valent_runcommand_editor_get_command (editor);
     160                 :             : 
     161         [ #  # ]:           0 :   if (command != NULL)
     162                 :           0 :     gtk_widget_activate_action (GTK_WIDGET (self), "runcommand.save", "s", uuid);
     163                 :             :   else
     164                 :           0 :     gtk_widget_activate_action (GTK_WIDGET (self), "runcommand.remove", "s", uuid);
     165                 :             : 
     166                 :           0 :   gtk_window_destroy (GTK_WINDOW (editor));
     167                 :           0 : }
     168                 :             : 
     169                 :             : static void
     170                 :           0 : runcommand_add_action (GtkWidget  *widget,
     171                 :             :                        const char *action_name,
     172                 :             :                        GVariant   *parameter)
     173                 :             : {
     174                 :           0 :   g_autofree char *uuid = NULL;
     175                 :             : 
     176         [ #  # ]:           0 :   g_assert (VALENT_IS_RUNCOMMAND_PREFERENCES (widget));
     177                 :             : 
     178                 :           0 :   uuid = g_uuid_string_random ();
     179                 :           0 :   gtk_widget_activate_action (widget, "runcommand.edit", "s", uuid);
     180                 :           0 : }
     181                 :             : 
     182                 :             : static void
     183                 :           0 : runcommand_edit_action (GtkWidget  *widget,
     184                 :             :                         const char *action_name,
     185                 :             :                         GVariant   *parameter)
     186                 :             : {
     187                 :           0 :   ValentRuncommandPreferences *self = VALENT_RUNCOMMAND_PREFERENCES (widget);
     188                 :           0 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     189                 :           0 :   const char *uuid = NULL;
     190                 :           0 :   GSettings *settings;
     191                 :           0 :   GtkRoot *window;
     192                 :           0 :   g_autoptr (GVariant) commands = NULL;
     193         [ #  # ]:           0 :   g_autoptr (GVariant) command = NULL;
     194                 :             : 
     195         [ #  # ]:           0 :   g_assert (VALENT_IS_RUNCOMMAND_PREFERENCES (self));
     196                 :             : 
     197                 :           0 :   uuid = g_variant_get_string (parameter, NULL);
     198                 :           0 :   settings = valent_device_preferences_group_get_settings (group);
     199                 :           0 :   commands = g_settings_get_value (settings, "commands");
     200                 :           0 :   g_variant_lookup (commands, uuid, "@a{sv}", &command);
     201                 :             : 
     202                 :           0 :   window = gtk_widget_get_root (GTK_WIDGET (self));
     203                 :           0 :   self->editor = g_object_new (VALENT_TYPE_RUNCOMMAND_EDITOR,
     204                 :             :                                "uuid",          uuid,
     205                 :             :                                "command",       command,
     206                 :             :                                "modal",         (window != NULL),
     207                 :             :                                "transient-for", window,
     208                 :             :                                NULL);
     209                 :           0 :   g_object_add_weak_pointer (G_OBJECT (self->editor),
     210                 :           0 :                              (gpointer) &self->editor);
     211                 :           0 :   g_signal_connect_object (self->editor,
     212                 :             :                            "notify::command",
     213                 :             :                            G_CALLBACK (on_command_changed),
     214                 :             :                            self, 0);
     215                 :             : 
     216         [ #  # ]:           0 :   gtk_window_present (self->editor);
     217                 :           0 : }
     218                 :             : 
     219                 :             : static void
     220                 :           0 : runcommand_save_action (GtkWidget  *widget,
     221                 :             :                         const char *action_name,
     222                 :             :                         GVariant   *parameter)
     223                 :             : {
     224                 :           0 :   ValentRuncommandPreferences *self = VALENT_RUNCOMMAND_PREFERENCES (widget);
     225                 :           0 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     226                 :           0 :   GSettings *settings;
     227                 :           0 :   g_autoptr (GVariant) commands = NULL;
     228                 :           0 :   GVariant *command;
     229                 :           0 :   const char *uuid;
     230                 :           0 :   GVariantDict dict;
     231                 :           0 :   GVariant *value;
     232                 :             : 
     233         [ #  # ]:           0 :   g_assert (VALENT_IS_RUNCOMMAND_PREFERENCES (self));
     234                 :             : 
     235                 :           0 :   settings = valent_device_preferences_group_get_settings (group);
     236                 :           0 :   commands = g_settings_get_value (settings, "commands");
     237                 :             : 
     238                 :           0 :   uuid = valent_runcommand_editor_get_uuid (VALENT_RUNCOMMAND_EDITOR (self->editor));
     239                 :           0 :   command = valent_runcommand_editor_get_command (VALENT_RUNCOMMAND_EDITOR (self->editor));
     240                 :             : 
     241                 :           0 :   g_variant_dict_init (&dict, commands);
     242                 :           0 :   g_variant_dict_insert_value (&dict, uuid, command);
     243                 :           0 :   value = g_variant_dict_end (&dict);
     244                 :             : 
     245         [ #  # ]:           0 :   g_settings_set_value (settings, "commands", value);
     246                 :           0 : }
     247                 :             : 
     248                 :             : static void
     249                 :           0 : runcommand_remove_action (GtkWidget  *widget,
     250                 :             :                           const char *action_name,
     251                 :             :                           GVariant   *parameter)
     252                 :             : {
     253                 :           0 :   ValentRuncommandPreferences *self = VALENT_RUNCOMMAND_PREFERENCES (widget);
     254                 :           0 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     255                 :           0 :   GSettings *settings;
     256                 :           0 :   g_autoptr (GVariant) commands = NULL;
     257                 :           0 :   GVariantDict dict;
     258                 :           0 :   GVariant *value;
     259                 :           0 :   const char *uuid = NULL;
     260                 :             : 
     261         [ #  # ]:           0 :   g_assert (VALENT_IS_RUNCOMMAND_PREFERENCES (self));
     262                 :             : 
     263                 :           0 :   uuid = g_variant_get_string (parameter, NULL);
     264                 :           0 :   settings = valent_device_preferences_group_get_settings (group);
     265                 :           0 :   commands = g_settings_get_value (settings, "commands");
     266                 :             : 
     267                 :           0 :   g_variant_dict_init (&dict, commands);
     268                 :           0 :   g_variant_dict_remove (&dict, uuid);
     269                 :           0 :   value = g_variant_dict_end (&dict);
     270                 :             : 
     271         [ #  # ]:           0 :   g_settings_set_value (settings, "commands", value);
     272                 :           0 : }
     273                 :             : 
     274                 :             : /*
     275                 :             :  * GObject
     276                 :             :  */
     277                 :             : static void
     278                 :           1 : valent_runcommand_preferences_constructed (GObject *object)
     279                 :             : {
     280                 :           1 :   ValentRuncommandPreferences *self = VALENT_RUNCOMMAND_PREFERENCES (object);
     281                 :           1 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     282                 :           1 :   GSettings *settings;
     283                 :             : 
     284                 :           1 :   gtk_list_box_set_sort_func (self->command_list, sort_commands, self, NULL);
     285                 :             : 
     286                 :             :   /* Setup GSettings */
     287                 :           1 :   settings = valent_device_preferences_group_get_settings (group);
     288                 :           1 :   g_signal_connect_object (settings,
     289                 :             :                            "changed::commands",
     290                 :             :                            G_CALLBACK (valent_runcommand_preferences_populate),
     291                 :             :                            self,
     292                 :             :                            G_CONNECT_SWAPPED);
     293                 :           1 :   valent_runcommand_preferences_populate (self);
     294                 :             : 
     295                 :           1 :   G_OBJECT_CLASS (valent_runcommand_preferences_parent_class)->constructed (object);
     296                 :           1 : }
     297                 :             : 
     298                 :             : static void
     299                 :           1 : valent_runcommand_preferences_dispose (GObject *object)
     300                 :             : {
     301                 :           1 :   GtkWidget *widget = GTK_WIDGET (object);
     302                 :             : 
     303                 :           1 :   gtk_widget_dispose_template (widget, VALENT_TYPE_RUNCOMMAND_PREFERENCES);
     304                 :             : 
     305                 :           1 :   G_OBJECT_CLASS (valent_runcommand_preferences_parent_class)->dispose (object);
     306                 :           1 : }
     307                 :             : 
     308                 :             : static void
     309                 :           1 : valent_runcommand_preferences_finalize (GObject *object)
     310                 :             : {
     311                 :           1 :   ValentRuncommandPreferences *self = VALENT_RUNCOMMAND_PREFERENCES (object);
     312                 :             : 
     313         [ -  + ]:           1 :   g_clear_pointer (&self->editor, gtk_window_destroy);
     314                 :             : 
     315                 :           1 :   G_OBJECT_CLASS (valent_runcommand_preferences_parent_class)->finalize (object);
     316                 :           1 : }
     317                 :             : 
     318                 :             : static void
     319                 :           1 : valent_runcommand_preferences_class_init (ValentRuncommandPreferencesClass *klass)
     320                 :             : {
     321                 :           1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     322                 :           1 :   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
     323                 :             : 
     324                 :           1 :   object_class->constructed = valent_runcommand_preferences_constructed;
     325                 :           1 :   object_class->dispose = valent_runcommand_preferences_dispose;
     326                 :           1 :   object_class->finalize = valent_runcommand_preferences_finalize;
     327                 :             : 
     328                 :           1 :   gtk_widget_class_set_template_from_resource (widget_class, "/plugins/gnome/valent-device-preferences-commands.ui");
     329                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentRuncommandPreferences, command_list_row);
     330                 :             : 
     331                 :           1 :   gtk_widget_class_install_action (widget_class, "runcommand.add", NULL, runcommand_add_action);
     332                 :           1 :   gtk_widget_class_install_action (widget_class, "runcommand.edit", "s", runcommand_edit_action);
     333                 :           1 :   gtk_widget_class_install_action (widget_class, "runcommand.remove", "s", runcommand_remove_action);
     334                 :           1 :   gtk_widget_class_install_action (widget_class, "runcommand.save", "s", runcommand_save_action);
     335                 :           1 : }
     336                 :             : 
     337                 :             : static void
     338                 :           1 : valent_runcommand_preferences_init (ValentRuncommandPreferences *self)
     339                 :             : {
     340                 :           1 :   gtk_widget_init_template (GTK_WIDGET (self));
     341                 :             : 
     342                 :           1 :   self->command_list = _adw_expander_row_get_list (self->command_list_row);
     343                 :           1 : }
     344                 :             : 
        

Generated by: LCOV version 2.0-1