GCC Code Coverage Report


Directory: ./
File: panels/notifications/cc-app-notifications-dialog.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 165 0.0%
Functions: 0 22 0.0%
Branches: 0 85 0.0%

Line Branch Exec Source
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /*
3 * Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
4 * Copyright (C) 2015 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <glib/gi18n-lib.h>
25 #include <glib.h>
26 #include <gio/gio.h>
27 #include <gio/gdesktopappinfo.h>
28
29 #include "cc-notifications-panel.h"
30 #include "cc-app-notifications-dialog.h"
31
32 /*
33 * Key Switch
34 *
35 * "enable", "notifications-switch" When set to off, all other switches in the dialog are insensitive
36 * "enable-sound-alerts", "sound-alerts-switch"
37 * "show-banners", "notification-banners-switch" Off and insensitive when corresponding panel switch is off
38 * "force-expanded", "notification-banners-content-switch" Off and insensitive when switch above is off
39 * "show-in-lock-screen", "lock-screen-notifications-switch" Off and insensitive when corresponding panel switch is off
40 * "details-in-lock-screen", "lock-screen-content-switch" Off and insensitive when switch above is off
41 */
42
43 static void update_banner_row (CcAppNotificationsDialog *dialog);
44 static void update_banner_content_row (CcAppNotificationsDialog *dialog);
45 static void update_lock_screen_row (CcAppNotificationsDialog *dialog);
46 static void update_lock_screen_content_row (CcAppNotificationsDialog *dialog);
47 static void update_sound_row (CcAppNotificationsDialog *dialog);
48 static void update_notification_row (CcAppNotificationsDialog *dialog);
49
50 struct _CcAppNotificationsDialog {
51 AdwDialog parent;
52
53 GSettings *settings;
54 GSettings *master_settings;
55 gchar *app_id;
56 GDBusProxy *perm_store;
57
58 AdwSwitchRow *notifications_row;
59 AdwSwitchRow *sound_alerts_row;
60 AdwSwitchRow *notification_banners_row;
61 AdwSwitchRow *notification_banners_content_row;
62 AdwSwitchRow *lock_screen_notifications_row;
63 AdwSwitchRow *lock_screen_content_row;
64 };
65
66 G_DEFINE_TYPE (CcAppNotificationsDialog, cc_app_notifications_dialog, ADW_TYPE_DIALOG)
67
68 static void
69 on_perm_store_set_done (GObject *source_object,
70 GAsyncResult *res,
71 gpointer user_data)
72 {
73 g_autoptr(GVariant) results = NULL;
74 g_autoptr(GError) error = NULL;
75
76 results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
77 res,
78 &error);
79 if (results == NULL)
80 {
81 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
82 g_warning ("Failed to store permissions: %s", error->message);
83 return;
84 }
85 }
86
87 static void
88 set_portal_permissions_for_app (CcAppNotificationsDialog *dialog, AdwSwitchRow *row)
89 {
90 gboolean allow = adw_switch_row_get_active (row);
91 g_autoptr(GVariant) perms = NULL;
92 g_autoptr(GVariant) new_perms = NULL;
93 g_autoptr(GVariant) data = NULL;
94 GVariantBuilder builder;
95 gboolean found;
96 int i;
97 const char *yes_strv[] = { "yes", NULL };
98 const char *no_strv[] = { "no", NULL };
99 g_autoptr(GVariant) reply = NULL;
100
101 if (dialog->perm_store == NULL)
102 {
103 g_warning ("Could not find PermissionStore, not syncing notification permissions");
104 return;
105 }
106
107 new_perms = g_variant_new_strv (allow ? yes_strv : no_strv, 1);
108 g_variant_ref_sink (new_perms);
109
110 g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sas}"));
111 found = FALSE;
112
113 reply = g_dbus_proxy_call_sync (dialog->perm_store,
114 "Lookup",
115 g_variant_new ("(ss)",
116 "notifications",
117 "notification"),
118 G_DBUS_CALL_FLAGS_NONE,
119 -1,
120 NULL,
121 NULL);
122 if (reply)
123 {
124 g_variant_get (reply, "(@a{sas}v)", &perms, &data);
125
126 for (i = 0; i < g_variant_n_children (perms); i++)
127 {
128 const char *key;
129 g_autoptr(GVariant) value = NULL;
130
131 g_variant_get_child (perms, i, "{&s@as}", &key, &value);
132 if (g_strcmp0 (key, dialog->app_id) == 0)
133 {
134 found = TRUE;
135 g_variant_builder_add (&builder, "{s@as}", key, new_perms);
136 }
137 else
138 g_variant_builder_add (&builder, "{s@as}", key, value);
139 }
140 }
141
142 if (!found)
143 g_variant_builder_add (&builder, "{s@as}", dialog->app_id, new_perms);
144
145 g_dbus_proxy_call (dialog->perm_store,
146 "Set",
147 g_variant_new ("(sbsa{sas}v)",
148 "notifications",
149 TRUE,
150 "notification",
151 &builder,
152 data ? data : g_variant_new_byte (0)),
153 G_DBUS_CALL_FLAGS_NONE,
154 -1,
155 NULL,
156 on_perm_store_set_done,
157 data);
158 }
159
160 static void
161 notifications_row_state_set_cb (CcAppNotificationsDialog *dialog)
162 {
163 g_settings_set_boolean (dialog->settings, "enable", adw_switch_row_get_active (dialog->notifications_row));
164 set_portal_permissions_for_app (dialog, dialog->notifications_row);
165 update_sound_row (dialog);
166 update_banner_row (dialog);
167 update_banner_content_row (dialog);
168 update_lock_screen_row (dialog);
169 update_lock_screen_content_row (dialog);
170 }
171
172 static void
173 sound_alerts_row_state_set_cb (CcAppNotificationsDialog *dialog)
174 {
175 g_settings_set_boolean (dialog->settings, "enable-sound-alerts", adw_switch_row_get_active (dialog->sound_alerts_row));
176 }
177
178 static void
179 notification_banners_row_state_set_cb (CcAppNotificationsDialog *dialog)
180 {
181 g_settings_set_boolean (dialog->settings, "show-banners", adw_switch_row_get_active (dialog->notification_banners_row));
182 update_banner_content_row (dialog);
183 }
184
185 static void
186 notification_banners_content_row_state_set_cb (CcAppNotificationsDialog *dialog)
187 {
188 g_settings_set_boolean (dialog->settings, "force-expanded", adw_switch_row_get_active (dialog->notification_banners_content_row));
189 }
190
191 static void
192 lock_screen_notifications_row_state_set_cb (CcAppNotificationsDialog *dialog)
193 {
194 g_settings_set_boolean (dialog->settings, "show-in-lock-screen", adw_switch_row_get_active (dialog->lock_screen_notifications_row));
195 update_lock_screen_content_row (dialog);
196 }
197
198 static void
199 lock_screen_content_row_state_set_cb (CcAppNotificationsDialog *dialog)
200 {
201 g_settings_set_boolean (dialog->settings, "details-in-lock-screen", adw_switch_row_get_active (dialog->lock_screen_notifications_row));
202 }
203
204 static void
205 update_switches (CcAppNotificationsDialog *dialog)
206 {
207 update_notification_row (dialog);
208 update_sound_row (dialog);
209 update_banner_row (dialog);
210 update_banner_content_row (dialog);
211 update_lock_screen_row (dialog);
212 update_lock_screen_content_row (dialog);
213 }
214
215 static void
216 update_notification_row (CcAppNotificationsDialog *dialog)
217 {
218 g_signal_handlers_block_by_func (G_OBJECT (dialog->notifications_row), notifications_row_state_set_cb, dialog);
219 adw_switch_row_set_active (dialog->notifications_row, g_settings_get_boolean (dialog->settings, "enable"));
220 g_signal_handlers_unblock_by_func (G_OBJECT (dialog->notifications_row), notifications_row_state_set_cb, dialog);
221 }
222
223 static void
224 update_sound_row (CcAppNotificationsDialog *dialog)
225 {
226 g_signal_handlers_block_by_func (G_OBJECT (dialog->sound_alerts_row), sound_alerts_row_state_set_cb, dialog);
227 adw_switch_row_set_active (dialog->sound_alerts_row, g_settings_get_boolean (dialog->settings, "enable-sound-alerts"));
228 g_signal_handlers_unblock_by_func (G_OBJECT (dialog->sound_alerts_row), sound_alerts_row_state_set_cb, dialog);
229 gtk_widget_set_sensitive (GTK_WIDGET (dialog->sound_alerts_row), g_settings_get_boolean (dialog->settings, "enable"));
230 }
231
232 static void
233 update_banner_row (CcAppNotificationsDialog *dialog)
234 {
235 gboolean notifications_enabled;
236 gboolean show_banners;
237 gboolean active;
238 gboolean sensitive;
239
240 show_banners = g_settings_get_boolean (dialog->master_settings, "show-banners");
241 notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
242
243 active = g_settings_get_boolean (dialog->settings, "show-banners") &&
244 show_banners;
245 sensitive = notifications_enabled &&
246 show_banners;
247 g_signal_handlers_block_by_func (G_OBJECT (dialog->notification_banners_row), notification_banners_row_state_set_cb, dialog);
248 adw_switch_row_set_active (dialog->notification_banners_row, active);
249 g_signal_handlers_unblock_by_func (G_OBJECT (dialog->notification_banners_row), notification_banners_row_state_set_cb, dialog);
250 gtk_widget_set_sensitive (GTK_WIDGET (dialog->notification_banners_row), sensitive);
251 }
252
253 static void
254 update_banner_content_row (CcAppNotificationsDialog *dialog)
255 {
256 gboolean notifications_enabled;
257 gboolean show_banners;
258 gboolean active;
259 gboolean sensitive;
260
261 show_banners = g_settings_get_boolean (dialog->master_settings, "show-banners");
262 notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
263
264 active = g_settings_get_boolean (dialog->settings, "force-expanded") &&
265 g_settings_get_boolean (dialog->settings, "show-banners") &&
266 show_banners;
267 sensitive = g_settings_get_boolean (dialog->settings, "show-banners") &&
268 notifications_enabled &&
269 show_banners;
270 g_signal_handlers_block_by_func (G_OBJECT (dialog->notification_banners_content_row), notification_banners_content_row_state_set_cb, dialog);
271 adw_switch_row_set_active (dialog->notification_banners_content_row, active);
272 g_signal_handlers_unblock_by_func (G_OBJECT (dialog->notification_banners_content_row), notification_banners_content_row_state_set_cb, dialog);
273 gtk_widget_set_sensitive (GTK_WIDGET (dialog->notification_banners_content_row), sensitive);
274 }
275
276 static void
277 update_lock_screen_row (CcAppNotificationsDialog *dialog)
278 {
279 gboolean notifications_enabled;
280 gboolean show_in_lock_screen;
281 gboolean active;
282 gboolean sensitive;
283
284 show_in_lock_screen = g_settings_get_boolean (dialog->master_settings, "show-in-lock-screen");
285 notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
286
287 active = g_settings_get_boolean (dialog->settings, "show-in-lock-screen") &&
288 show_in_lock_screen;
289 sensitive = notifications_enabled &&
290 show_in_lock_screen;
291
292 g_signal_handlers_block_by_func (G_OBJECT (dialog->lock_screen_notifications_row), lock_screen_notifications_row_state_set_cb, dialog);
293 adw_switch_row_set_active (dialog->lock_screen_notifications_row, active);
294 g_signal_handlers_unblock_by_func (G_OBJECT (dialog->lock_screen_notifications_row), lock_screen_notifications_row_state_set_cb, dialog);
295 gtk_widget_set_sensitive (GTK_WIDGET (dialog->lock_screen_notifications_row), sensitive);
296 }
297
298 static void
299 update_lock_screen_content_row (CcAppNotificationsDialog *dialog)
300 {
301 gboolean notifications_enabled;
302 gboolean show_in_lock_screen;
303 gboolean active;
304 gboolean sensitive;
305
306 show_in_lock_screen = g_settings_get_boolean (dialog->master_settings, "show-in-lock-screen");
307 notifications_enabled = g_settings_get_boolean (dialog->settings, "enable");
308
309 active = g_settings_get_boolean (dialog->settings, "details-in-lock-screen") &&
310 g_settings_get_boolean (dialog->settings, "show-in-lock-screen") &&
311 show_in_lock_screen;
312 sensitive = g_settings_get_boolean (dialog->settings, "show-in-lock-screen") &&
313 notifications_enabled &&
314 show_in_lock_screen;
315 g_signal_handlers_block_by_func (G_OBJECT (dialog->lock_screen_content_row), lock_screen_content_row_state_set_cb, dialog);
316 adw_switch_row_set_active (dialog->lock_screen_content_row, active);
317 g_signal_handlers_unblock_by_func (G_OBJECT (dialog->lock_screen_content_row), lock_screen_content_row_state_set_cb, dialog);
318 gtk_widget_set_sensitive (GTK_WIDGET (dialog->lock_screen_content_row), sensitive);
319 }
320
321 static void
322 cc_app_notifications_dialog_dispose (GObject *object)
323 {
324 CcAppNotificationsDialog *dialog = CC_APP_NOTIFICATIONS_DIALOG (object);
325
326 g_clear_object (&dialog->settings);
327 g_clear_object (&dialog->master_settings);
328 g_clear_pointer (&dialog->app_id, g_free);
329 g_clear_object (&dialog->perm_store);
330
331 G_OBJECT_CLASS (cc_app_notifications_dialog_parent_class)->dispose (object);
332 }
333
334 static void
335 cc_app_notifications_dialog_class_init (CcAppNotificationsDialogClass *klass)
336 {
337 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
338 GObjectClass *object_class = G_OBJECT_CLASS (klass);
339
340 object_class->dispose = cc_app_notifications_dialog_dispose;
341
342 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/notifications/cc-app-notifications-dialog.ui");
343
344 gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, notifications_row);
345 gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, sound_alerts_row);
346 gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, notification_banners_row);
347 gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, notification_banners_content_row);
348 gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, lock_screen_notifications_row);
349 gtk_widget_class_bind_template_child (widget_class, CcAppNotificationsDialog, lock_screen_content_row);
350
351 gtk_widget_class_bind_template_callback (widget_class, notifications_row_state_set_cb);
352 gtk_widget_class_bind_template_callback (widget_class, sound_alerts_row_state_set_cb);
353 gtk_widget_class_bind_template_callback (widget_class, notification_banners_row_state_set_cb);
354 gtk_widget_class_bind_template_callback (widget_class, notification_banners_content_row_state_set_cb);
355 gtk_widget_class_bind_template_callback (widget_class, lock_screen_notifications_row_state_set_cb);
356 gtk_widget_class_bind_template_callback (widget_class, lock_screen_content_row_state_set_cb);
357 }
358
359 void
360 cc_app_notifications_dialog_init (CcAppNotificationsDialog *dialog)
361 {
362 gtk_widget_init_template (GTK_WIDGET (dialog));
363 }
364
365 CcAppNotificationsDialog *
366 cc_app_notifications_dialog_new (const gchar *app_id,
367 const gchar *title,
368 GSettings *settings,
369 GSettings *master_settings,
370 GDBusProxy *perm_store)
371 {
372 CcAppNotificationsDialog *dialog;
373
374 dialog = g_object_new (CC_TYPE_APP_NOTIFICATIONS_DIALOG, NULL);
375
376 adw_dialog_set_title (ADW_DIALOG (dialog), title);
377 dialog->settings = g_object_ref (settings);
378 dialog->master_settings = g_object_ref (master_settings);
379 dialog->app_id = g_strdup (app_id);
380 dialog->perm_store = g_object_ref (perm_store);
381
382 update_switches (dialog);
383
384 return dialog;
385 }
386