GCC Code Coverage Report


Directory: ./
File: panels/common/cc-split-row.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 214 0.0%
Functions: 0 33 0.0%
Branches: 0 89 0.0%

Line Branch Exec Source
1 /* cc-split-row.c
2 *
3 * Copyright 2018 Purism SPC
4 * 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
5 * 2023 Red Hat, Inc
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * SPDX-License-Identifier: GPL-3.0-or-later
21 */
22
23 #include "cc-split-row.h"
24
25 struct _CcSplitRow
26 {
27 CcVerticalRow parent;
28
29 GtkWidget *box;
30 GtkSizeGroup *size_group;
31
32 GtkPicture *default_option_picture;
33 GtkPicture *alternative_option_picture;
34
35 GtkCheckButton *alternative_option_checkbutton;
36 GtkCheckButton *default_option_checkbutton;
37
38 gchar *alternative_resource_path;
39 gchar *default_resource_path;
40
41 gchar *alternative_option_title;
42 gchar *alternative_option_subtitle;
43 gchar *default_option_title;
44 gchar *default_option_subtitle;
45
46 gboolean use_default;
47 gboolean compact;
48 };
49
50 G_DEFINE_FINAL_TYPE (CcSplitRow, cc_split_row, CC_TYPE_VERTICAL_ROW);
51
52 enum
53 {
54 PROP_0,
55 PROP_USE_DEFAULT,
56 PROP_COMPACT,
57 PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE,
58 PROP_ALTERNATIVE_OPTION_TITLE,
59 PROP_ALTERNATIVE_OPTION_SUBTITLE,
60 PROP_DEFAULT_ILLUSTRATION_RESOURCE,
61 PROP_DEFAULT_OPTION_TITLE,
62 PROP_DEFAULT_OPTION_SUBTITLE,
63 N_PROPS,
64 };
65
66 static GParamSpec *props[N_PROPS] = { NULL, };
67
68 static void
69 on_default_option_click_released_cb (CcSplitRow *self)
70 {
71 gtk_widget_activate (GTK_WIDGET (self->default_option_checkbutton));
72 }
73
74 static void
75 on_alternative_option_click_released_cb (CcSplitRow *self)
76 {
77 gtk_widget_activate (GTK_WIDGET (self->alternative_option_checkbutton));
78 }
79
80 static void
81 focus_leave (GtkPicture *picture)
82 {
83 GtkMediaStream *stream;
84 GdkPaintable *paintable;
85
86 paintable = gtk_picture_get_paintable (picture);
87
88 if (!GTK_IS_MEDIA_STREAM (paintable))
89 return;
90
91 stream = GTK_MEDIA_STREAM (paintable);
92 gtk_media_stream_set_loop (stream, FALSE);
93 gtk_media_stream_pause (stream);
94 }
95
96 static void
97 on_default_option_focus_leave_cb (CcSplitRow *self)
98 {
99 focus_leave (self->default_option_picture);
100 }
101
102 static void
103 on_alternative_option_focus_leave_cb (CcSplitRow *self)
104 {
105 focus_leave (self->alternative_option_picture);
106 }
107
108 static void
109 focus_enter (GtkPicture *picture)
110 {
111 GtkMediaStream *stream;
112 GdkPaintable *paintable;
113
114 paintable = gtk_picture_get_paintable (picture);
115
116 if (!GTK_IS_MEDIA_STREAM (paintable))
117 return;
118
119 stream = GTK_MEDIA_STREAM (paintable);
120 gtk_media_stream_set_loop (stream, TRUE);
121 gtk_media_stream_play (stream);
122 }
123
124 static void
125 on_default_option_focus_enter_cb (CcSplitRow *self)
126 {
127 focus_enter (self->default_option_picture);
128 }
129
130 static void
131 on_alternative_option_focus_enter_cb (CcSplitRow *self)
132 {
133 focus_enter (self->alternative_option_picture);
134 }
135
136 static void
137 on_checkbutton_toggled_cb (CcSplitRow *self)
138 {
139 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_DEFAULT]);
140 }
141
142 static void
143 cc_split_row_dispose (GObject *object)
144 {
145 CcSplitRow *self = CC_SPLIT_ROW (object);
146
147 g_clear_pointer (&self->default_resource_path, g_free);
148 g_clear_pointer (&self->alternative_resource_path, g_free);
149 g_clear_pointer (&self->alternative_option_title, g_free);
150 g_clear_pointer (&self->alternative_option_subtitle, g_free);
151 g_clear_pointer (&self->default_option_title, g_free);
152 g_clear_pointer (&self->default_option_subtitle, g_free);
153
154 G_OBJECT_CLASS (cc_split_row_parent_class)->dispose (object);
155 }
156
157 static void
158 cc_split_row_get_property (GObject *object,
159 guint prop_id,
160 GValue *value,
161 GParamSpec *pspec)
162 {
163 CcSplitRow *self = CC_SPLIT_ROW (object);
164
165 switch (prop_id)
166 {
167 case PROP_USE_DEFAULT:
168 g_value_set_boolean (value, gtk_check_button_get_active (self->default_option_checkbutton));
169 break;
170 case PROP_COMPACT:
171 g_value_set_boolean (value, cc_split_row_get_compact (self));
172 break;
173 case PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE:
174 g_value_set_string (value, cc_split_row_get_alternative_illustration_resource (self));
175 break;
176 case PROP_ALTERNATIVE_OPTION_TITLE:
177 g_value_set_string (value, cc_split_row_get_alternative_option_title (self));
178 break;
179 case PROP_ALTERNATIVE_OPTION_SUBTITLE:
180 g_value_set_string (value, cc_split_row_get_alternative_option_subtitle (self));
181 break;
182 case PROP_DEFAULT_ILLUSTRATION_RESOURCE:
183 g_value_set_string (value, cc_split_row_get_default_illustration_resource (self));
184 break;
185 case PROP_DEFAULT_OPTION_TITLE:
186 g_value_set_string (value, cc_split_row_get_default_option_title (self));
187 break;
188 case PROP_DEFAULT_OPTION_SUBTITLE:
189 g_value_set_string (value, cc_split_row_get_default_option_subtitle (self));
190 break;
191 default:
192 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
193 }
194 }
195
196 static void
197 cc_split_row_set_property (GObject *object,
198 guint prop_id,
199 const GValue *value,
200 GParamSpec *pspec)
201 {
202 CcSplitRow *self = CC_SPLIT_ROW (object);
203
204 switch (prop_id)
205 {
206 case PROP_USE_DEFAULT:
207 cc_split_row_set_use_default (self, g_value_get_boolean (value));
208 break;
209 case PROP_COMPACT:
210 cc_split_row_set_compact (self, g_value_get_boolean (value));
211 break;
212 case PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE:
213 cc_split_row_set_alternative_illustration_resource (self, g_value_get_string (value));
214 break;
215 case PROP_ALTERNATIVE_OPTION_TITLE:
216 cc_split_row_set_alternative_option_title (self, g_value_get_string (value));
217 break;
218 case PROP_ALTERNATIVE_OPTION_SUBTITLE:
219 cc_split_row_set_alternative_option_subtitle (self, g_value_get_string (value));
220 break;
221 case PROP_DEFAULT_ILLUSTRATION_RESOURCE:
222 cc_split_row_set_default_illustration_resource (self, g_value_get_string (value));
223 break;
224 case PROP_DEFAULT_OPTION_TITLE:
225 cc_split_row_set_default_option_title (self, g_value_get_string (value));
226 break;
227 case PROP_DEFAULT_OPTION_SUBTITLE:
228 cc_split_row_set_default_option_subtitle (self, g_value_get_string (value));
229 break;
230 default:
231 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
232 }
233 }
234
235 static void
236 cc_split_row_class_init (CcSplitRowClass *klass)
237 {
238 GObjectClass *object_class = G_OBJECT_CLASS (klass);
239 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
240
241 object_class->dispose = cc_split_row_dispose;
242 object_class->get_property = cc_split_row_get_property;
243 object_class->set_property = cc_split_row_set_property;
244
245 props[PROP_USE_DEFAULT] =
246 g_param_spec_boolean ("use-default",
247 "Use Default",
248 "Use Default",
249 TRUE,
250 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
251
252 props[PROP_COMPACT] =
253 g_param_spec_boolean ("compact",
254 "Compact",
255 "Compact",
256 FALSE,
257 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
258
259 props[PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE] =
260 g_param_spec_string ("alternative-illustration-resource",
261 "Alternative illustration resource",
262 "Alternative illustration resource",
263 "",
264 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
265 props[PROP_ALTERNATIVE_OPTION_TITLE] =
266 g_param_spec_string ("alternative-option-title",
267 "Alternative option title",
268 "Alternative option title",
269 "",
270 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
271 props[PROP_ALTERNATIVE_OPTION_SUBTITLE] =
272 g_param_spec_string ("alternative-option-subtitle",
273 "Alternative option subtitle",
274 "Alternative option subtitle",
275 "",
276 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
277 props[PROP_DEFAULT_ILLUSTRATION_RESOURCE] =
278 g_param_spec_string ("default-illustration-resource",
279 "Default illustration resource",
280 "Default illustration resource",
281 "",
282 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
283 props[PROP_DEFAULT_OPTION_TITLE] =
284 g_param_spec_string ("default-option-title",
285 "Default option title",
286 "Default option title",
287 "",
288 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
289 props[PROP_DEFAULT_OPTION_SUBTITLE] =
290 g_param_spec_string ("default-option-subtitle",
291 "Default option subtitle",
292 "Default option subtitle",
293 "",
294 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
295
296 g_object_class_install_properties (object_class, N_PROPS, props);
297
298 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/common/cc-split-row.ui");
299
300 gtk_widget_class_bind_template_child (widget_class, CcSplitRow, box);
301 gtk_widget_class_bind_template_child (widget_class, CcSplitRow, size_group);
302 gtk_widget_class_bind_template_child (widget_class, CcSplitRow, alternative_option_checkbutton);
303 gtk_widget_class_bind_template_child (widget_class, CcSplitRow, alternative_option_picture);
304 gtk_widget_class_bind_template_child (widget_class, CcSplitRow, default_option_checkbutton);
305 gtk_widget_class_bind_template_child (widget_class, CcSplitRow, default_option_picture);
306
307 gtk_widget_class_bind_template_callback (widget_class, on_checkbutton_toggled_cb);
308 gtk_widget_class_bind_template_callback (widget_class, on_default_option_click_released_cb);
309 gtk_widget_class_bind_template_callback (widget_class, on_alternative_option_click_released_cb);
310 gtk_widget_class_bind_template_callback (widget_class, on_default_option_focus_enter_cb);
311 gtk_widget_class_bind_template_callback (widget_class, on_alternative_option_focus_enter_cb);
312 gtk_widget_class_bind_template_callback (widget_class, on_default_option_focus_leave_cb);
313 gtk_widget_class_bind_template_callback (widget_class, on_alternative_option_focus_leave_cb);
314 }
315
316 static void
317 cc_split_row_init (CcSplitRow *self)
318 {
319 gtk_widget_init_template (GTK_WIDGET (self));
320 gtk_widget_set_name (GTK_WIDGET (self), "split-row");
321 gtk_widget_add_css_class (GTK_WIDGET (self), "split-row");
322 }
323
324 const gchar *
325 cc_split_row_get_default_illustration_resource (CcSplitRow *self)
326 {
327 return self->default_resource_path;
328 }
329
330 void
331 cc_split_row_set_default_illustration_resource (CcSplitRow *self,
332 const gchar *resource_path)
333 {
334 g_autoptr(GtkMediaStream) media_file = NULL;
335
336 g_return_if_fail (CC_IS_SPLIT_ROW (self));
337
338 g_set_str (&self->default_resource_path, resource_path);
339 media_file = gtk_media_file_new_for_resource (resource_path);
340
341 gtk_picture_set_paintable (self->default_option_picture, GDK_PAINTABLE (media_file));
342 gtk_widget_set_visible (GTK_WIDGET (self->default_option_picture),
343 resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
344
345 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_ILLUSTRATION_RESOURCE]);
346 }
347
348 const gchar *
349 cc_split_row_get_alternative_illustration_resource (CcSplitRow *self)
350 {
351 return self->alternative_resource_path;
352 }
353
354 void
355 cc_split_row_set_alternative_illustration_resource (CcSplitRow *self,
356 const gchar *resource_path)
357 {
358 g_autoptr(GtkMediaStream) media_file = NULL;
359
360 g_return_if_fail (CC_IS_SPLIT_ROW (self));
361
362 g_set_str (&self->alternative_resource_path, resource_path);
363 media_file = gtk_media_file_new_for_resource (resource_path);
364 gtk_media_stream_set_loop (media_file, TRUE);
365
366 gtk_picture_set_paintable (self->alternative_option_picture, GDK_PAINTABLE (media_file));
367 gtk_widget_set_visible (GTK_WIDGET (self->alternative_option_picture),
368 resource_path != NULL && g_strcmp0 (resource_path, "") != 0);
369
370 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_ILLUSTRATION_RESOURCE]);
371 }
372
373 void
374 cc_split_row_set_use_default (CcSplitRow *self,
375 gboolean use_default)
376 {
377 g_return_if_fail (CC_IS_SPLIT_ROW (self));
378
379 gtk_check_button_set_active (use_default ? self->default_option_checkbutton : self->alternative_option_checkbutton, TRUE);
380
381 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_DEFAULT]);
382 }
383
384 gboolean
385 cc_split_row_get_use_default (CcSplitRow *self)
386 {
387 return gtk_check_button_get_active (self->default_option_checkbutton);
388 }
389
390 void
391 cc_split_row_set_compact (CcSplitRow *self,
392 gboolean compact)
393 {
394 g_return_if_fail (CC_IS_SPLIT_ROW (self));
395
396 self->compact = !!compact;
397
398 gtk_orientable_set_orientation (GTK_ORIENTABLE (self->box),
399 compact ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL);
400 gtk_size_group_set_mode (self->size_group,
401 compact ? GTK_SIZE_GROUP_NONE : GTK_SIZE_GROUP_VERTICAL);
402
403 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_COMPACT]);
404 }
405
406 gboolean
407 cc_split_row_get_compact (CcSplitRow *self)
408 {
409 return self->compact;
410 }
411
412 const gchar *
413 cc_split_row_get_default_option_title (CcSplitRow *self)
414 {
415 g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
416
417 return self->default_option_title;
418 }
419
420 void
421 cc_split_row_set_default_option_title (CcSplitRow *self,
422 const gchar *title)
423 {
424 g_return_if_fail (CC_IS_SPLIT_ROW (self));
425
426 if (g_set_str (&self->default_option_title, title))
427 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_OPTION_TITLE]);
428 }
429
430 const gchar *
431 cc_split_row_get_default_option_subtitle (CcSplitRow *self)
432 {
433 g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
434
435 return self->default_option_subtitle;
436 }
437
438 void
439 cc_split_row_set_default_option_subtitle (CcSplitRow *self,
440 const gchar *subtitle)
441 {
442 g_return_if_fail (CC_IS_SPLIT_ROW (self));
443
444 if (g_set_str (&self->default_option_subtitle, subtitle))
445 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEFAULT_OPTION_SUBTITLE]);
446 }
447
448 const gchar *
449 cc_split_row_get_alternative_option_title (CcSplitRow *self)
450 {
451 g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
452
453 return self->alternative_option_title;
454 }
455
456 void
457 cc_split_row_set_alternative_option_title (CcSplitRow *self,
458 const gchar *title)
459 {
460 g_return_if_fail (CC_IS_SPLIT_ROW (self));
461
462 if (g_set_str (&self->alternative_option_title, title))
463 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_OPTION_TITLE]);
464 }
465
466 const gchar *
467 cc_split_row_get_alternative_option_subtitle (CcSplitRow *self)
468 {
469 g_return_val_if_fail (CC_IS_SPLIT_ROW (self), NULL);
470
471 return self->alternative_option_subtitle;
472 }
473
474 void
475 cc_split_row_set_alternative_option_subtitle (CcSplitRow *self,
476 const gchar *subtitle)
477 {
478 g_return_if_fail (CC_IS_SPLIT_ROW (self));
479
480 if (g_set_str (&self->alternative_option_subtitle, subtitle))
481 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALTERNATIVE_OPTION_SUBTITLE]);
482 }
483