Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright 2025 GNOME Foundation, Inc.
4 : : *
5 : : * SPDX-License-Identifier: GPL-2.0-or-later
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 2 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 : : * Authors:
21 : : * - Ignacy Kuchciński <ignacykuchcinski@gnome.org>
22 : : */
23 : :
24 : : #include "config.h"
25 : :
26 : : #include <glib/gi18n-lib.h>
27 : : #include <libmalcontent/manager.h>
28 : :
29 : : #include "time-page.h"
30 : : #include "cc-duration-row.h"
31 : : #include "cc-time-row.h"
32 : :
33 : : static gboolean update_session_limits_cb (gpointer data);
34 : :
35 : : /**
36 : : * MctTimePage:
37 : : *
38 : : * A widget which shows parental controls for screen time limits
39 : : * for the selected user.
40 : : *
41 : : * Since: 0.14.0
42 : : */
43 : : struct _MctTimePage
44 : : {
45 : : AdwNavigationPage parent;
46 : :
47 : : AdwWindowTitle *time_window_title;
48 : : AdwPreferencesPage *preferences_page;
49 : : AdwSwitchRow *screen_time_limit_row;
50 : : AdwSwitchRow *bedtime_schedule_row;
51 : : CcDurationRow *daily_time_limit_row;
52 : : CcTimeRow *bedtime_row;
53 : :
54 : : unsigned int update_session_limits_source_id;
55 : : unsigned long session_limits_changed_id;
56 : : unsigned long user_notify_id;
57 : : gboolean flushed_on_dispose;
58 : : GCancellable *cancellable; /* (owned) */
59 : : MctSessionLimits *limits; /* (owned) */
60 : : MctSessionLimits *last_saved_limits; /* (owned); updated each time we internally time out and save the session limits */
61 : :
62 : : MctUser *user; /* (owned) */
63 : : MctManager *policy_manager; /* (owned) */
64 : : };
65 : :
66 [ # # # # : 0 : G_DEFINE_TYPE (MctTimePage, mct_time_page, ADW_TYPE_NAVIGATION_PAGE)
# # ]
67 : :
68 : : typedef enum
69 : : {
70 : : PROP_USER = 1,
71 : : PROP_POLICY_MANAGER,
72 : : } MctTimePageProperty;
73 : :
74 : : static GParamSpec *properties[PROP_POLICY_MANAGER + 1];
75 : :
76 : : static void
77 : 0 : schedule_update_session_limits (MctTimePage *self)
78 : : {
79 [ # # ]: 0 : if (self->update_session_limits_source_id > 0)
80 : 0 : return;
81 : :
82 : : /* Use a timeout to batch multiple quick changes into a single
83 : : * update. 1 second is an arbitrary sufficiently small number */
84 : 0 : self->update_session_limits_source_id =
85 : 0 : g_timeout_add_seconds (1, update_session_limits_cb, self);
86 : : }
87 : :
88 : : static void
89 : 0 : flush_update_session_limits (MctTimePage *self)
90 : : {
91 [ # # ]: 0 : if (self->update_session_limits_source_id > 0)
92 : : {
93 : : /* Remove the timer and forcefully call the timer callback. */
94 : 0 : g_source_remove (self->update_session_limits_source_id);
95 : 0 : self->update_session_limits_source_id = 0;
96 : :
97 : 0 : update_session_limits_cb (self);
98 : : }
99 : 0 : }
100 : :
101 : : static void
102 : 0 : setup_time_page (MctTimePage *self)
103 : : {
104 : : gboolean daily_limit, daily_schedule;
105 : : unsigned int limit_secs, bedtime_secs;
106 : :
107 : 0 : daily_limit = mct_session_limits_get_daily_limit (self->limits, &limit_secs);
108 : 0 : daily_schedule = mct_session_limits_get_daily_schedule (self->limits,
109 : : NULL,
110 : : &bedtime_secs);
111 : :
112 : 0 : adw_switch_row_set_active (self->screen_time_limit_row, daily_limit);
113 : 0 : adw_switch_row_set_active (self->bedtime_schedule_row, daily_schedule);
114 : 0 : cc_duration_row_set_duration (self->daily_time_limit_row, limit_secs / 60);
115 [ # # ]: 0 : if (daily_schedule)
116 : 0 : cc_time_row_set_time (self->bedtime_row, bedtime_secs / 60);
117 : 0 : }
118 : :
119 : : static void
120 : 0 : get_session_limits_cb (GObject *obj,
121 : : GAsyncResult *result,
122 : : gpointer user_data)
123 : : {
124 : 0 : MctTimePage *self = MCT_TIME_PAGE (user_data);
125 [ # # ]: 0 : g_autoptr(GError) error = NULL;
126 : :
127 [ # # ]: 0 : g_clear_pointer (&self->limits, mct_session_limits_unref);
128 [ # # ]: 0 : g_clear_pointer (&self->last_saved_limits, mct_session_limits_unref);
129 : 0 : self->limits = mct_manager_get_session_limits_finish (self->policy_manager,
130 : : result,
131 : : &error);
132 : :
133 [ # # ]: 0 : if (error)
134 : : {
135 : 0 : g_warning ("Error retrieving session limits for user '%s': %s",
136 : : mct_user_get_username (self->user),
137 : : error->message);
138 : 0 : return;
139 : : }
140 : :
141 : 0 : self->last_saved_limits = mct_session_limits_ref (self->limits);
142 : :
143 : 0 : g_debug ("Retrieved new session limits for user '%s'",
144 : : mct_user_get_username (self->user));
145 : :
146 : 0 : setup_time_page (self);
147 : : }
148 : :
149 : : static void
150 : 0 : set_session_limits_cb (GObject *obj,
151 : : GAsyncResult *result,
152 : : gpointer user_data)
153 : : {
154 : 0 : MctTimePage *self = MCT_TIME_PAGE (user_data);
155 : : gboolean success;
156 : 0 : g_autoptr(GError) error = NULL;
157 : :
158 : 0 : success = mct_manager_set_session_limits_finish (self->policy_manager,
159 : : result,
160 : : &error);
161 [ # # ]: 0 : if (!success)
162 : : {
163 : 0 : g_warning ("Error updating session limits: %s", error->message);
164 : 0 : setup_time_page (self);
165 : : }
166 : 0 : }
167 : :
168 : : static gboolean
169 : 0 : update_session_limits_cb (gpointer data)
170 : : {
171 : 0 : g_auto(MctSessionLimitsBuilder) builder = MCT_SESSION_LIMITS_BUILDER_INIT ();
172 : 0 : g_autoptr(MctSessionLimits) new_limits = NULL;
173 : 0 : g_autoptr(GError) error = NULL;
174 : 0 : MctTimePage *self = data;
175 : : guint limit, daily_schedule_start, daily_schedule_end, bedtime_minutes, bedtime_hours;
176 : : gboolean screen_time_limit, bedtime_schedule;
177 : :
178 : 0 : self->update_session_limits_source_id = 0;
179 : :
180 : 0 : screen_time_limit = adw_switch_row_get_active (self->screen_time_limit_row);
181 [ # # ]: 0 : if (screen_time_limit)
182 : : {
183 : 0 : limit = cc_duration_row_get_duration (self->daily_time_limit_row);
184 : 0 : mct_session_limits_builder_set_daily_limit (&builder, limit * 60);
185 : : }
186 : :
187 : 0 : bedtime_schedule = adw_switch_row_get_active (self->bedtime_schedule_row);
188 [ # # ]: 0 : if (bedtime_schedule)
189 : : {
190 : 0 : bedtime_minutes = cc_time_row_get_time (self->bedtime_row);
191 : 0 : bedtime_hours = bedtime_minutes / 60;
192 : 0 : const unsigned int sleep_time_hours = 6;
193 : 0 : const unsigned int midnight = 24;
194 : :
195 : : /* Calculate the start and the end of the daily schedule in seconds.
196 : : * Ensure at least 6 hours of sleep time for late bedtimes. For early
197 : : * bedtimes, the start of the daily schedule would need to be after
198 : : * the end, but split days aren't supported yet, so set it to zero
199 : : * for now. Also make sure the end of the daily schedule is non zero.*/
200 [ # # ]: 0 : if (bedtime_hours + sleep_time_hours >= midnight)
201 : 0 : daily_schedule_start = (bedtime_hours + sleep_time_hours) % midnight * 60 * 60;
202 : : else
203 : 0 : daily_schedule_start = 0;
204 : :
205 [ # # ]: 0 : if (bedtime_minutes != 0)
206 : 0 : daily_schedule_end = bedtime_minutes * 60;
207 : : else
208 : 0 : daily_schedule_end = 1;
209 : :
210 : 0 : mct_session_limits_builder_set_daily_schedule (&builder,
211 : : daily_schedule_start,
212 : : daily_schedule_end);
213 : : }
214 : :
215 : 0 : new_limits = mct_session_limits_builder_end (&builder);
216 : :
217 : : /* Don't bother saving the session limit (which could result in asking the
218 : : * user for admin permission) if it hasn't changed. */
219 [ # # # # ]: 0 : if (self->last_saved_limits != NULL &&
220 : 0 : mct_session_limits_equal (new_limits, self->last_saved_limits))
221 : : {
222 : 0 : g_debug ("Not saving session limits as they haven't changed");
223 : 0 : return G_SOURCE_REMOVE;
224 : : }
225 : :
226 : 0 : mct_manager_set_session_limits_async (self->policy_manager,
227 : : mct_user_get_uid (self->user),
228 : : new_limits,
229 : : MCT_MANAGER_SET_VALUE_FLAGS_INTERACTIVE,
230 : : self->cancellable,
231 : : set_session_limits_cb,
232 : : self);
233 : :
234 : : /* Update the cached copy */
235 : 0 : mct_session_limits_unref (self->last_saved_limits);
236 : 0 : self->last_saved_limits = g_steal_pointer (&new_limits);
237 : :
238 : 0 : return G_SOURCE_REMOVE;
239 : : }
240 : :
241 : : static void
242 : 0 : screen_time_limit_row_notify_active_cb (MctTimePage *self)
243 : : {
244 : 0 : schedule_update_session_limits (self);
245 : 0 : }
246 : :
247 : : static void
248 : 0 : bedtime_schedule_row_notify_active_cb (MctTimePage *self)
249 : : {
250 : 0 : schedule_update_session_limits (self);
251 : 0 : }
252 : :
253 : : static void
254 : 0 : bedtime_row_notify_time_cb (CcTimeRow *row,
255 : : GParamSpec *pspec,
256 : : gpointer user_data)
257 : : {
258 : 0 : MctTimePage *self = MCT_TIME_PAGE (user_data);
259 : :
260 : 0 : schedule_update_session_limits (self);
261 : 0 : }
262 : :
263 : : static void
264 : 0 : daily_time_limit_row_notify_duration_cb (CcDurationRow *row,
265 : : GParamSpec *pspec,
266 : : gpointer user_data)
267 : : {
268 : 0 : MctTimePage *self = MCT_TIME_PAGE (user_data);
269 : :
270 : 0 : schedule_update_session_limits (self);
271 : 0 : }
272 : :
273 : : static void
274 : 0 : session_limits_changed_cb (MctManager *policy_manager,
275 : : uid_t uid,
276 : : void *user_data)
277 : : {
278 : 0 : MctTimePage *self = MCT_TIME_PAGE (user_data);
279 : :
280 [ # # ]: 0 : if (uid != mct_user_get_uid (self->user))
281 : 0 : return;
282 : :
283 : 0 : mct_manager_get_session_limits_async (self->policy_manager,
284 : : mct_user_get_uid (self->user),
285 : : MCT_MANAGER_GET_VALUE_FLAGS_NONE,
286 : : self->cancellable,
287 : : get_session_limits_cb,
288 : : self);
289 : : }
290 : :
291 : : static void
292 : 0 : mct_time_page_get_property (GObject *object,
293 : : guint prop_id,
294 : : GValue *value,
295 : : GParamSpec *pspec)
296 : : {
297 : 0 : MctTimePage *self = MCT_TIME_PAGE (object);
298 : :
299 [ # # # ]: 0 : switch ((MctTimePageProperty) prop_id)
300 : : {
301 : 0 : case PROP_USER:
302 : 0 : g_value_set_object (value, self->user);
303 : 0 : break;
304 : :
305 : 0 : case PROP_POLICY_MANAGER:
306 : 0 : g_value_set_object (value, self->policy_manager);
307 : 0 : break;
308 : :
309 : 0 : default:
310 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
311 : : }
312 : 0 : }
313 : :
314 : : static void
315 : 0 : mct_time_page_set_property (GObject *object,
316 : : guint prop_id,
317 : : const GValue *value,
318 : : GParamSpec *pspec)
319 : : {
320 : 0 : MctTimePage *self = MCT_TIME_PAGE (object);
321 : :
322 [ # # # ]: 0 : switch ((MctTimePageProperty) prop_id)
323 : : {
324 : 0 : case PROP_USER:
325 : 0 : mct_time_page_set_user (self, g_value_get_object (value));
326 : 0 : break;
327 : :
328 : 0 : case PROP_POLICY_MANAGER:
329 : : /* Construct only. */
330 : 0 : g_assert (self->policy_manager == NULL);
331 : 0 : self->policy_manager = g_value_dup_object (value);
332 : 0 : break;
333 : :
334 : 0 : default:
335 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
336 : : }
337 : 0 : }
338 : :
339 : : static void
340 : 0 : mct_time_page_constructed (GObject *object)
341 : : {
342 : 0 : MctTimePage *self = MCT_TIME_PAGE (object);
343 : :
344 : : /* Chain up. */
345 : 0 : G_OBJECT_CLASS (mct_time_page_parent_class)->constructed (object);
346 : :
347 : : /* Check our construct properties. */
348 : 0 : g_assert (MCT_IS_MANAGER (self->policy_manager));
349 : :
350 : 0 : self->session_limits_changed_id =
351 : 0 : g_signal_connect (self->policy_manager,
352 : : "session-limits-changed",
353 : : G_CALLBACK (session_limits_changed_cb),
354 : : self);
355 : 0 : }
356 : :
357 : : static void
358 : 0 : mct_time_page_dispose (GObject *object)
359 : : {
360 : 0 : MctTimePage *self = MCT_TIME_PAGE (object);
361 : :
362 : : /* Since GTK calls g_object_run_dispose(), dispose() may be called multiple
363 : : * times. We definitely want to save any unsaved changes, but don’t need to
364 : : * do it multiple times, and after the first g_object_run_dispose() call,
365 : : * none of our child widgets are still around to extract data from anyway. */
366 [ # # ]: 0 : if (!self->flushed_on_dispose)
367 : 0 : flush_update_session_limits (self);
368 : 0 : self->flushed_on_dispose = TRUE;
369 : :
370 : 0 : G_OBJECT_CLASS (mct_time_page_parent_class)->dispose (object);
371 : 0 : }
372 : :
373 : : static void
374 : 0 : mct_time_page_finalize (GObject *object)
375 : : {
376 : 0 : MctTimePage *self = MCT_TIME_PAGE (object);
377 : :
378 : 0 : g_assert (self->update_session_limits_source_id == 0);
379 : :
380 : 0 : g_cancellable_cancel (self->cancellable);
381 [ # # ]: 0 : g_clear_object (&self->cancellable);
382 [ # # ]: 0 : g_clear_signal_handler (&self->user_notify_id, self->user);
383 [ # # ]: 0 : g_clear_object (&self->user);
384 [ # # ]: 0 : g_clear_pointer (&self->limits, mct_session_limits_unref);
385 [ # # ]: 0 : g_clear_pointer (&self->last_saved_limits, mct_session_limits_unref);
386 [ # # ]: 0 : g_clear_signal_handler (&self->session_limits_changed_id, self->policy_manager);
387 [ # # ]: 0 : g_clear_object (&self->policy_manager);
388 : :
389 : : /* Hopefully we don’t have data loss. */
390 : 0 : g_assert (self->flushed_on_dispose);
391 : :
392 : 0 : G_OBJECT_CLASS (mct_time_page_parent_class)->finalize (object);
393 : 0 : }
394 : :
395 : : static void
396 : 0 : mct_time_page_class_init (MctTimePageClass *klass)
397 : : {
398 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
399 : 0 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
400 : :
401 : 0 : object_class->get_property = mct_time_page_get_property;
402 : 0 : object_class->set_property = mct_time_page_set_property;
403 : 0 : object_class->constructed = mct_time_page_constructed;
404 : 0 : object_class->dispose = mct_time_page_dispose;
405 : 0 : object_class->finalize = mct_time_page_finalize;
406 : :
407 : : /**
408 : : * MctTimePage:user:
409 : : *
410 : : * The currently selected user account.
411 : : *
412 : : * Since 0.14.0
413 : : */
414 : 0 : properties[PROP_USER] =
415 : 0 : g_param_spec_object ("user",
416 : : "User",
417 : : "The currently selected user account.",
418 : : MCT_TYPE_USER,
419 : : G_PARAM_READWRITE |
420 : : G_PARAM_STATIC_STRINGS |
421 : : G_PARAM_EXPLICIT_NOTIFY);
422 : :
423 : : /**
424 : : * MctTimePage:policy-manager:
425 : : *
426 : : * Policy manager to provider users’ parental controls policies.
427 : : *
428 : : * Since 0.14.0
429 : : */
430 : 0 : properties[PROP_POLICY_MANAGER] =
431 : 0 : g_param_spec_object ("policy-manager", NULL, NULL,
432 : : MCT_TYPE_MANAGER,
433 : : G_PARAM_READWRITE |
434 : : G_PARAM_CONSTRUCT_ONLY |
435 : : G_PARAM_STATIC_STRINGS);
436 : :
437 : 0 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
438 : :
439 : 0 : g_type_ensure (CC_TYPE_DURATION_ROW);
440 : 0 : g_type_ensure (CC_TYPE_TIME_ROW);
441 : :
442 : 0 : gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentControl/ui/time-page.ui");
443 : :
444 : 0 : gtk_widget_class_bind_template_child (widget_class, MctTimePage, time_window_title);
445 : 0 : gtk_widget_class_bind_template_child (widget_class, MctTimePage, preferences_page);
446 : 0 : gtk_widget_class_bind_template_child (widget_class, MctTimePage, screen_time_limit_row);
447 : 0 : gtk_widget_class_bind_template_child (widget_class, MctTimePage, bedtime_schedule_row);
448 : 0 : gtk_widget_class_bind_template_child (widget_class, MctTimePage, daily_time_limit_row);
449 : 0 : gtk_widget_class_bind_template_child (widget_class, MctTimePage, bedtime_row);
450 : :
451 : 0 : gtk_widget_class_bind_template_callback (widget_class, screen_time_limit_row_notify_active_cb);
452 : 0 : gtk_widget_class_bind_template_callback (widget_class, bedtime_schedule_row_notify_active_cb);
453 : 0 : gtk_widget_class_bind_template_callback (widget_class, bedtime_row_notify_time_cb);
454 : 0 : gtk_widget_class_bind_template_callback (widget_class, daily_time_limit_row_notify_duration_cb);
455 : 0 : }
456 : :
457 : : static void
458 : 0 : mct_time_page_init (MctTimePage *self)
459 : : {
460 : 0 : gtk_widget_init_template (GTK_WIDGET (self));
461 : :
462 : 0 : self->cancellable = g_cancellable_new ();
463 : 0 : }
464 : :
465 : : /**
466 : : * mct_time_page_new:
467 : : * @policy_manager: (transfer none): policy manager for querying user parental
468 : : * controls policies
469 : : *
470 : : * Create a new #MctTimePage widget.
471 : : *
472 : : * Returns: (transfer full): a new time page
473 : : * Since: 0.14.0
474 : : */
475 : : MctTimePage *
476 : 0 : mct_time_page_new (MctManager *policy_manager)
477 : : {
478 : 0 : g_return_val_if_fail (MCT_IS_MANAGER (policy_manager), NULL);
479 : :
480 : 0 : return g_object_new (MCT_TYPE_TIME_PAGE,
481 : : "policy-manager", policy_manager,
482 : : NULL);
483 : : }
484 : :
485 : : /**
486 : : * mct_time_page_get_user:
487 : : * @self: an #MctTimePage
488 : : * @user: an #MctUser
489 : : *
490 : : * Get the currently selected user.
491 : : *
492 : : * Returns: (transfer none): the currently selected user
493 : : * Since: 0.14.0
494 : : */
495 : : MctUser *
496 : 0 : mct_time_page_get_user (MctTimePage *self)
497 : : {
498 : 0 : g_return_val_if_fail (MCT_IS_TIME_PAGE (self), NULL);
499 : :
500 : 0 : return self->user;
501 : : }
502 : :
503 : : static void
504 : 0 : user_notify_cb (GObject *object,
505 : : GParamSpec *pspec,
506 : : void *user_data)
507 : : {
508 : 0 : MctUser *user = MCT_USER (object);
509 : 0 : MctTimePage *self = MCT_TIME_PAGE (user_data);
510 : :
511 : 0 : g_autofree gchar *help_label = NULL;
512 : 0 : adw_window_title_set_subtitle (self->time_window_title,
513 : : mct_user_get_display_name (user));
514 : :
515 : : /* Translators: Replace the link to commonsensemedia.org with some
516 : : * localised guidance for parents/carers on how to set restrictions on
517 : : * their child/caree in a responsible way which is in keeping with the
518 : : * best practice and culture of the region. If no suitable localised
519 : : * guidance exists, and if the default commonsensemedia.org link is not
520 : : * suitable, please file an issue against malcontent so we can discuss
521 : : * further!
522 : : * https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/new
523 : : */
524 : 0 : help_label = g_strdup_printf (_("It’s recommended that Screen Time "
525 : : "limits and schedules are set as part of "
526 : : "an ongoing conversation with %s. <a href='https://www.commonsensemedia.org/privacy-and-internet-safety'>"
527 : : "Read guidance</a> on what to consider."),
528 : : mct_user_get_display_name (user));
529 : 0 : adw_preferences_page_set_description (self->preferences_page, help_label);
530 : 0 : }
531 : :
532 : : /**
533 : : * mct_time_page_set_user:
534 : : * @self: an #MctTimePage
535 : : * @user: an #MctUser
536 : : *
537 : : * Set the currently selected user.
538 : : *
539 : : * Since: 0.14.0
540 : : */
541 : : void
542 : 0 : mct_time_page_set_user (MctTimePage *self,
543 : : MctUser *user)
544 : : {
545 : 0 : g_return_if_fail (MCT_IS_TIME_PAGE (self));
546 : 0 : g_return_if_fail (MCT_IS_USER (user));
547 : :
548 : 0 : g_autoptr(MctUser) old_user = NULL;
549 : :
550 : : /* If we have pending unsaved changes from the previous user, force them to be
551 : : * saved first. */
552 : 0 : flush_update_session_limits (self);
553 : :
554 [ # # ]: 0 : old_user = (self->user != NULL) ? g_object_ref (self->user) : NULL;
555 : :
556 [ # # ]: 0 : if (g_set_object (&self->user, user))
557 : : {
558 [ # # ]: 0 : if (old_user != NULL)
559 [ # # ]: 0 : g_clear_signal_handler (&self->user_notify_id, old_user);
560 : :
561 [ # # ]: 0 : if (user != NULL)
562 : : {
563 : 0 : self->user_notify_id = g_signal_connect (user,
564 : : "notify",
565 : : G_CALLBACK (user_notify_cb),
566 : : self);
567 : 0 : user_notify_cb (G_OBJECT (user), NULL, self);
568 : : }
569 : :
570 : : /* Set a default bedtime of 20:00 */
571 : 0 : cc_time_row_set_time (self->bedtime_row, 20 * 60);
572 : :
573 : 0 : mct_manager_get_session_limits_async (self->policy_manager,
574 : : mct_user_get_uid (self->user),
575 : : MCT_MANAGER_GET_VALUE_FLAGS_NONE,
576 : : self->cancellable,
577 : : get_session_limits_cb,
578 : : self);
579 : :
580 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER]);
581 : : }
582 : : }
|