LCOV - code coverage report
Current view: top level - src/plugins/gnome - valent-device-preferences-notification.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 40.5 % 168 68
Test Date: 2024-11-16 20:34:14 Functions: 47.4 % 19 9
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 10.7 % 56 6

             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-notification-preferences"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <glib/gi18n.h>
       9                 :             : #include <adwaita.h>
      10                 :             : #include <gtk/gtk.h>
      11                 :             : #include <valent.h>
      12                 :             : 
      13                 :             : #include "valent-device-preferences-notification.h"
      14                 :             : 
      15                 :             : 
      16                 :             : struct _ValentNotificationPreferences
      17                 :             : {
      18                 :             :   ValentDevicePreferencesGroup  parent_instance;
      19                 :             : 
      20                 :             :   /* template */
      21                 :             :   AdwExpanderRow               *forward_notifications;
      22                 :             :   GtkSwitch                    *forward_when_active;
      23                 :             : 
      24                 :             :   AdwNavigationPage            *application_page;
      25                 :             :   GtkStack                     *application_title_stack;
      26                 :             :   GtkToggleButton              *application_filter_button;
      27                 :             :   GtkSearchEntry               *application_filter_entry;
      28                 :             :   AdwActionRow                 *application_row;
      29                 :             :   GtkListBox                   *application_list;
      30                 :             : 
      31                 :             :   char                         *application_filter;
      32                 :             :   GHashTable                   *application_rows;
      33                 :             : };
      34                 :             : 
      35   [ +  +  +  - ]:          43 : G_DEFINE_FINAL_TYPE (ValentNotificationPreferences, valent_notification_preferences, VALENT_TYPE_DEVICE_PREFERENCES_GROUP)
      36                 :             : 
      37                 :             : 
      38                 :             : static gboolean
      39                 :           0 : application_list_filter (GtkListBoxRow *row,
      40                 :             :                          gpointer       user_data)
      41                 :             : {
      42                 :           0 :   ValentNotificationPreferences *self = VALENT_NOTIFICATION_PREFERENCES (user_data);
      43                 :           0 :   g_autofree char *haystack = NULL;
      44                 :           0 :   const char *title = NULL;
      45                 :             : 
      46         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
      47                 :             : 
      48   [ #  #  #  # ]:           0 :   if (self->application_filter == NULL || *self->application_filter == '\0')
      49                 :             :     return TRUE;
      50                 :             : 
      51                 :           0 :   title = adw_preferences_row_get_title (ADW_PREFERENCES_ROW (row));
      52                 :           0 :   haystack = g_utf8_casefold (title, -1);
      53                 :             : 
      54                 :           0 :   return g_strrstr (haystack, self->application_filter) != NULL;
      55                 :             : }
      56                 :             : 
      57                 :             : static int
      58                 :           0 : application_list_sort (GtkListBoxRow *row1,
      59                 :             :                        GtkListBoxRow *row2,
      60                 :             :                        gpointer       user_data)
      61                 :             : {
      62   [ #  #  #  # ]:           0 :   if G_UNLIKELY (!ADW_IS_PREFERENCES_ROW (row1) ||
      63                 :             :                  !ADW_IS_PREFERENCES_ROW (row2))
      64                 :           0 :     return 0;
      65                 :             : 
      66                 :           0 :   return g_utf8_collate (adw_preferences_row_get_title ((AdwPreferencesRow *)row1),
      67                 :           0 :                          adw_preferences_row_get_title ((AdwPreferencesRow *)row2));
      68                 :             : }
      69                 :             : 
      70                 :             : /*
      71                 :             :  * Template Callbacks
      72                 :             :  */
      73                 :             : static void
      74                 :           0 : on_search_changed (GtkSearchEntry                *entry,
      75                 :             :                    ValentNotificationPreferences *self)
      76                 :             : {
      77                 :           0 :   g_autofree char *query = NULL;
      78                 :             : 
      79         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
      80                 :             : 
      81                 :           0 :   query = g_utf8_casefold (gtk_editable_get_text (GTK_EDITABLE (entry)), -1);
      82                 :             : 
      83         [ #  # ]:           0 :   if (g_set_str (&self->application_filter, query))
      84                 :           0 :     gtk_list_box_invalidate_filter (self->application_list);
      85                 :           0 : }
      86                 :             : 
      87                 :             : static void
      88                 :           0 : on_search_toggled (GtkToggleButton               *button,
      89                 :             :                    GParamSpec                    *pspec,
      90                 :             :                    ValentNotificationPreferences *self)
      91                 :             : {
      92         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
      93                 :             : 
      94         [ #  # ]:           0 :   if (gtk_toggle_button_get_active (button))
      95                 :             :     {
      96                 :           0 :       gtk_stack_set_visible_child_name (self->application_title_stack, "search");
      97                 :           0 :       gtk_widget_grab_focus (GTK_WIDGET (self->application_filter_entry));
      98                 :           0 :       gtk_editable_set_position (GTK_EDITABLE (self->application_filter_entry), -1);
      99                 :             :     }
     100                 :             :   else
     101                 :             :     {
     102                 :           0 :       gtk_editable_set_text (GTK_EDITABLE (self->application_filter_entry), "");
     103                 :           0 :       gtk_stack_set_visible_child_name (self->application_title_stack, "title");
     104                 :             :     }
     105                 :           0 : }
     106                 :             : 
     107                 :             : static void
     108                 :           0 : on_search_started (GtkSearchEntry                *entry,
     109                 :             :                    ValentNotificationPreferences *self)
     110                 :             : {
     111         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
     112                 :             : 
     113                 :           0 :   gtk_toggle_button_set_active (self->application_filter_button, TRUE);
     114                 :           0 : }
     115                 :             : 
     116                 :             : static void
     117                 :           0 : on_stop_search (GtkSearchEntry                *entry,
     118                 :             :                 ValentNotificationPreferences *self)
     119                 :             : {
     120         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
     121                 :             : 
     122                 :           0 :   gtk_toggle_button_set_active (self->application_filter_button, FALSE);
     123                 :           0 : }
     124                 :             : 
     125                 :             : static void
     126                 :           0 : on_switch_toggled (GObject                       *object,
     127                 :             :                    GParamSpec                    *pspec,
     128                 :             :                    ValentNotificationPreferences *self)
     129                 :             : {
     130                 :           0 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     131                 :           0 :   GSettings *settings;
     132                 :           0 :   GHashTableIter iter;
     133                 :           0 :   gpointer row;
     134                 :           0 :   GVariantBuilder builder;
     135                 :           0 :   GVariant *forward_deny;
     136                 :             : 
     137                 :           0 :   g_hash_table_iter_init (&iter, self->application_rows);
     138                 :           0 :   g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
     139                 :             : 
     140         [ #  # ]:           0 :   while (g_hash_table_iter_next (&iter, &row, NULL))
     141                 :             :     {
     142                 :           0 :       const char *name;
     143                 :             : 
     144         [ #  # ]:           0 :       if (adw_switch_row_get_active (ADW_SWITCH_ROW (row)))
     145                 :           0 :         continue;
     146                 :             : 
     147                 :           0 :       name = adw_preferences_row_get_title (ADW_PREFERENCES_ROW (row));
     148                 :           0 :       g_variant_builder_add (&builder, "s", name);
     149                 :             :     }
     150                 :             : 
     151                 :           0 :   forward_deny = g_variant_builder_end (&builder);
     152                 :           0 :   settings = valent_device_preferences_group_get_settings (group);
     153                 :           0 :   g_settings_set_value (settings, "forward-deny", forward_deny);
     154                 :           0 : }
     155                 :             : 
     156                 :             : static void
     157                 :           0 : add_application (ValentNotificationPreferences *self,
     158                 :             :                  GVariant                      *app,
     159                 :             :                  gboolean                       enabled)
     160                 :             : {
     161                 :           0 :   GtkWidget *row;
     162                 :           0 :   GtkWidget *image;
     163                 :           0 :   const char *title;
     164                 :           0 :   g_autoptr (GVariant) icon_v = NULL;
     165         [ #  # ]:           0 :   g_autoptr (GIcon) icon = NULL;
     166                 :             : 
     167         [ #  # ]:           0 :   if (!g_variant_lookup (app, "name", "&s", &title))
     168                 :           0 :     return;
     169                 :             : 
     170                 :           0 :   row = g_object_new (ADW_TYPE_SWITCH_ROW,
     171                 :             :                       "activatable", TRUE,
     172                 :             :                       "selectable",  TRUE,
     173                 :             :                       "title",       title,
     174                 :             :                       "active",      enabled,
     175                 :             :                       NULL);
     176                 :           0 :   g_signal_connect_object (row,
     177                 :             :                            "notify::active",
     178                 :             :                            G_CALLBACK (on_switch_toggled),
     179                 :             :                            self, 0);
     180                 :             : 
     181                 :             :   /* App icon */
     182         [ #  # ]:           0 :   if ((icon_v = g_variant_lookup_value (app, "icon", NULL)) != NULL)
     183                 :           0 :     icon = g_icon_deserialize (icon_v);
     184                 :             : 
     185         [ #  # ]:           0 :   if (icon == NULL)
     186                 :           0 :     icon = g_icon_new_for_string ("application-x-executable", NULL);
     187                 :             : 
     188                 :           0 :   image = g_object_new (GTK_TYPE_IMAGE,
     189                 :             :                         "gicon",     icon,
     190                 :             :                         "icon-size", GTK_ICON_SIZE_LARGE,
     191                 :             :                         NULL);
     192                 :           0 :   adw_action_row_add_prefix (ADW_ACTION_ROW (row), image);
     193                 :             : 
     194                 :           0 :   g_hash_table_add (self->application_rows, row);
     195         [ #  # ]:           0 :   gtk_list_box_insert (self->application_list, row, -1);
     196                 :             : }
     197                 :             : 
     198                 :             : static void
     199                 :           1 : populate_applications (ValentNotificationPreferences *self)
     200                 :             : {
     201                 :           1 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     202                 :           1 :   GSettings *settings;
     203                 :           1 :   GVariant *known;
     204                 :           2 :   g_auto (GStrv) deny = NULL;
     205                 :           1 :   GVariantIter iter;
     206                 :           1 :   const char *key;
     207                 :           1 :   GVariant *value;
     208                 :             : 
     209                 :           1 :   settings = valent_device_preferences_group_get_settings (group);
     210                 :           1 :   deny = g_settings_get_strv (settings, "forward-deny");
     211                 :             : 
     212                 :             :   /* Query the known applications */
     213                 :           1 :   known = valent_notifications_get_applications (NULL);
     214                 :           1 :   g_variant_iter_init (&iter, known);
     215                 :             : 
     216         [ -  + ]:           1 :   while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
     217                 :             :     {
     218                 :           0 :       gboolean enabled;
     219                 :             : 
     220                 :           0 :       enabled = !g_strv_contains ((const char * const *)deny, key);
     221                 :           0 :       add_application (self, value, enabled);
     222                 :             :     }
     223                 :           1 : }
     224                 :             : 
     225                 :             : /*
     226                 :             :  * GAction
     227                 :             :  */
     228                 :             : static void
     229                 :           0 : applications_action (GtkWidget  *widget,
     230                 :             :                      const char *action,
     231                 :             :                      GVariant   *parameter)
     232                 :             : {
     233                 :           0 :   ValentNotificationPreferences *self = VALENT_NOTIFICATION_PREFERENCES (widget);
     234                 :           0 :   GtkWidget *dialog = NULL;
     235                 :             : 
     236         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
     237                 :             : 
     238                 :           0 :   dialog = gtk_widget_get_ancestor (widget, ADW_TYPE_PREFERENCES_DIALOG);
     239         [ #  # ]:           0 :   if (dialog != NULL)
     240                 :             :     {
     241                 :           0 :       adw_preferences_dialog_push_subpage (ADW_PREFERENCES_DIALOG (dialog),
     242                 :             :                                            self->application_page);
     243                 :             :     }
     244                 :           0 : }
     245                 :             : 
     246                 :             : static void
     247                 :           0 : reset_action (GtkWidget  *widget,
     248                 :             :               const char *action,
     249                 :             :               GVariant   *parameter)
     250                 :             : {
     251                 :           0 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (widget);
     252                 :           0 :   ValentNotificationPreferences *self = VALENT_NOTIFICATION_PREFERENCES (group);
     253                 :           0 :   GSettings *settings;
     254                 :           0 :   GHashTableIter iter;
     255                 :           0 :   gpointer row_switch;
     256                 :             : 
     257         [ #  # ]:           0 :   g_assert (VALENT_IS_NOTIFICATION_PREFERENCES (self));
     258         [ #  # ]:           0 :   g_assert (VALENT_IS_DEVICE_PREFERENCES_GROUP (self));
     259                 :             : 
     260                 :           0 :   g_hash_table_iter_init (&iter, self->application_rows);
     261                 :             : 
     262         [ #  # ]:           0 :   while (g_hash_table_iter_next (&iter, NULL, &row_switch))
     263                 :           0 :     gtk_switch_set_active (GTK_SWITCH (row_switch), TRUE);
     264                 :             : 
     265                 :           0 :   settings = valent_device_preferences_group_get_settings (group);
     266                 :           0 :   g_settings_reset (settings, "applications");
     267                 :           0 : }
     268                 :             : 
     269                 :             : /*
     270                 :             :  * GObject
     271                 :             :  */
     272                 :             : static void
     273                 :           1 : valent_notification_preferences_constructed (GObject *object)
     274                 :             : {
     275                 :           1 :   ValentNotificationPreferences *self = VALENT_NOTIFICATION_PREFERENCES (object);
     276                 :           1 :   ValentDevicePreferencesGroup *group = VALENT_DEVICE_PREFERENCES_GROUP (self);
     277                 :           1 :   GSettings *settings;
     278                 :             : 
     279                 :           1 :   settings = valent_device_preferences_group_get_settings (group);
     280                 :           1 :   g_settings_bind (settings,                    "forward-notifications",
     281                 :           1 :                    self->forward_notifications, "enable-expansion",
     282                 :             :                    G_SETTINGS_BIND_DEFAULT);
     283                 :           1 :   g_settings_bind (settings,                    "forward-when-active",
     284                 :           1 :                    self->forward_when_active,   "active",
     285                 :             :                    G_SETTINGS_BIND_INVERT_BOOLEAN);
     286                 :             : 
     287                 :           1 :   gtk_list_box_set_filter_func (self->application_list,
     288                 :             :                                 application_list_filter,
     289                 :             :                                 self, NULL);
     290                 :           1 :   gtk_list_box_set_sort_func (self->application_list,
     291                 :             :                               application_list_sort,
     292                 :             :                               self, NULL);
     293                 :           1 :   populate_applications (self);
     294                 :             : 
     295                 :           1 :   G_OBJECT_CLASS (valent_notification_preferences_parent_class)->constructed (object);
     296                 :           1 : }
     297                 :             : 
     298                 :             : static void
     299                 :           1 : valent_notification_preferences_dispose (GObject *object)
     300                 :             : {
     301                 :           1 :   GtkWidget *widget = GTK_WIDGET (object);
     302                 :             : 
     303                 :           1 :   gtk_widget_dispose_template (widget, VALENT_TYPE_NOTIFICATION_PREFERENCES);
     304                 :             : 
     305                 :           1 :   G_OBJECT_CLASS (valent_notification_preferences_parent_class)->dispose (object);
     306                 :           1 : }
     307                 :             : 
     308                 :             : static void
     309                 :           1 : valent_notification_preferences_finalize (GObject *object)
     310                 :             : {
     311                 :           1 :   ValentNotificationPreferences *self = VALENT_NOTIFICATION_PREFERENCES (object);
     312                 :             : 
     313         [ -  + ]:           1 :   g_clear_pointer (&self->application_filter, g_free);
     314         [ +  - ]:           1 :   g_clear_pointer (&self->application_rows, g_hash_table_unref);
     315                 :             : 
     316                 :           1 :   G_OBJECT_CLASS (valent_notification_preferences_parent_class)->finalize (object);
     317                 :           1 : }
     318                 :             : 
     319                 :             : static void
     320                 :           1 : valent_notification_preferences_class_init (ValentNotificationPreferencesClass *klass)
     321                 :             : {
     322                 :           1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     323                 :           1 :   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
     324                 :             : 
     325                 :           1 :   object_class->constructed = valent_notification_preferences_constructed;
     326                 :           1 :   object_class->dispose = valent_notification_preferences_dispose;
     327                 :           1 :   object_class->finalize = valent_notification_preferences_finalize;
     328                 :             : 
     329                 :           1 :   gtk_widget_class_set_template_from_resource (widget_class, "/plugins/gnome/valent-device-preferences-notification.ui");
     330                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, forward_notifications);
     331                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, forward_when_active);
     332                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, application_page);
     333                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, application_title_stack);
     334                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, application_filter_entry);
     335                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, application_filter_button);
     336                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, application_list);
     337                 :           1 :   gtk_widget_class_bind_template_child (widget_class, ValentNotificationPreferences, application_row);
     338                 :           1 :   gtk_widget_class_bind_template_callback (widget_class, on_search_changed);
     339                 :           1 :   gtk_widget_class_bind_template_callback (widget_class, on_search_started);
     340                 :           1 :   gtk_widget_class_bind_template_callback (widget_class, on_search_toggled);
     341                 :           1 :   gtk_widget_class_bind_template_callback (widget_class, on_stop_search);
     342                 :             : 
     343                 :           1 :   gtk_widget_class_install_action (widget_class, "preferences.applications", NULL, applications_action);
     344                 :           1 :   gtk_widget_class_install_action (widget_class, "preferences.reset", NULL, reset_action);
     345                 :           1 : }
     346                 :             : 
     347                 :             : static void
     348                 :           1 : valent_notification_preferences_init (ValentNotificationPreferences *self)
     349                 :             : {
     350                 :           1 :   gtk_widget_init_template (GTK_WIDGET (self));
     351                 :           1 :   gtk_search_entry_set_key_capture_widget (self->application_filter_entry,
     352                 :           1 :                                            GTK_WIDGET (self->application_page));
     353                 :             : 
     354                 :           1 :   self->application_rows = g_hash_table_new (NULL, NULL);
     355                 :           1 : }
     356                 :             : 
        

Generated by: LCOV version 2.0-1