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 : : #define GNOME_DESKTOP_USE_UNSTABLE_API
28 : : #include <libgnome-desktop/gnome-wall-clock.h>
29 : : #include <libmalcontent-ui/malcontent-ui.h>
30 : : #include <stdint.h>
31 : :
32 : : #include "user-page.h"
33 : : #include "user-image.h"
34 : : #include "access-page.h"
35 : :
36 : : #define CLOCK_SCHEMA "org.gnome.desktop.interface"
37 : : #define CLOCK_FORMAT_KEY "clock-format"
38 : :
39 : : static void user_page_clock_changed_cb (GSettings *settings, char *key, void *user_data);
40 : : static void update_last_login_label (MctUserPage *self);
41 : :
42 : : /**
43 : : * MctUserPage:
44 : : *
45 : : * A widget which shows available parental controls
46 : : * for the selected user.
47 : : *
48 : : * Since: 0.14.0
49 : : */
50 : : struct _MctUserPage
51 : : {
52 : : AdwNavigationPage parent;
53 : :
54 : : MctUserImage *user_image;
55 : : GtkLabel *name_label;
56 : : GtkLabel *last_login_label;
57 : : GSettings *clock_settings; /* (owned) */
58 : : unsigned long user_notify_id;
59 : :
60 : : unsigned long clock_changed_id;
61 : :
62 : : MctUser *user; /* (owned) */
63 : : };
64 : :
65 [ # # # # : 0 : G_DEFINE_TYPE (MctUserPage, mct_user_page, ADW_TYPE_NAVIGATION_PAGE)
# # ]
66 : :
67 : : typedef enum
68 : : {
69 : : PROP_USER = 1,
70 : : } MctUserPageProperties;
71 : :
72 : : static GParamSpec *properties[PROP_USER + 1];
73 : :
74 : : static void
75 : 0 : mct_user_page_get_property (GObject *object,
76 : : guint prop_id,
77 : : GValue *value,
78 : : GParamSpec *pspec)
79 : : {
80 : 0 : MctUserPage *self = MCT_USER_PAGE (object);
81 : :
82 [ # # ]: 0 : switch ((MctUserPageProperties) prop_id)
83 : : {
84 : 0 : case PROP_USER:
85 : 0 : g_value_set_object (value, self->user);
86 : 0 : break;
87 : :
88 : 0 : default:
89 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
90 : : }
91 : 0 : }
92 : :
93 : : static void
94 : 0 : mct_user_page_set_property (GObject *object,
95 : : guint prop_id,
96 : : const GValue *value,
97 : : GParamSpec *pspec)
98 : : {
99 : 0 : MctUserPage *self = MCT_USER_PAGE (object);
100 : :
101 [ # # ]: 0 : switch ((MctUserPageProperties) prop_id)
102 : : {
103 : 0 : case PROP_USER:
104 : 0 : mct_user_page_set_user (self, g_value_get_object (value), NULL);
105 : 0 : break;
106 : :
107 : 0 : default:
108 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
109 : : }
110 : 0 : }
111 : :
112 : : static void
113 : 0 : mct_user_page_dispose (GObject *object)
114 : : {
115 : 0 : MctUserPage *self = MCT_USER_PAGE (object);
116 : :
117 [ # # ]: 0 : g_clear_signal_handler (&self->user_notify_id, self->user);
118 [ # # ]: 0 : g_clear_object (&self->user);
119 [ # # ]: 0 : g_clear_signal_handler (&self->clock_changed_id, self->clock_settings);
120 [ # # ]: 0 : g_clear_object (&self->clock_settings);
121 : :
122 : 0 : G_OBJECT_CLASS (mct_user_page_parent_class)->dispose (object);
123 : 0 : }
124 : :
125 : : static void
126 : 0 : mct_user_page_class_init (MctUserPageClass *klass)
127 : : {
128 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
129 : 0 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
130 : :
131 : 0 : g_type_ensure (MCT_TYPE_USER_IMAGE);
132 : :
133 : 0 : object_class->get_property = mct_user_page_get_property;
134 : 0 : object_class->set_property = mct_user_page_set_property;
135 : 0 : object_class->dispose = mct_user_page_dispose;
136 : :
137 : : /**
138 : : * MctUserPage:user:
139 : : *
140 : : * The currently selected user account.
141 : : *
142 : : * Since 0.14.0
143 : : */
144 : 0 : properties[PROP_USER] =
145 : 0 : g_param_spec_object ("user", NULL, NULL,
146 : : MCT_TYPE_USER,
147 : : G_PARAM_READWRITE |
148 : : G_PARAM_STATIC_STRINGS |
149 : : G_PARAM_EXPLICIT_NOTIFY);
150 : :
151 : 0 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
152 : :
153 : 0 : gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentControl/ui/user-page.ui");
154 : :
155 : 0 : gtk_widget_class_bind_template_child (widget_class, MctUserPage, user_image);
156 : 0 : gtk_widget_class_bind_template_child (widget_class, MctUserPage, name_label);
157 : 0 : gtk_widget_class_bind_template_child (widget_class, MctUserPage, last_login_label);
158 : 0 : }
159 : :
160 : : static void
161 : 0 : mct_user_page_init (MctUserPage *self)
162 : : {
163 : 0 : gtk_widget_init_template (GTK_WIDGET (self));
164 : :
165 : 0 : self->clock_settings = g_settings_new (CLOCK_SCHEMA);
166 : :
167 : 0 : self->clock_changed_id = g_signal_connect (self->clock_settings,
168 : : "changed::" CLOCK_FORMAT_KEY,
169 : : G_CALLBACK (user_page_clock_changed_cb),
170 : : self);
171 : 0 : }
172 : :
173 : : static void
174 : 0 : update_last_login_label (MctUserPage *self)
175 : : {
176 : : GDesktopClockFormat clock_format;
177 : : uint64_t login_time;
178 [ # # ]: 0 : g_autoptr (GDateTime) date_time = NULL;
179 [ # # ]: 0 : g_autofree char *last_login = NULL;
180 [ # # ]: 0 : g_autofree char *last_login_label = NULL;
181 : :
182 : 0 : clock_format = g_settings_get_enum (self->clock_settings, CLOCK_FORMAT_KEY);
183 : 0 : login_time = mct_user_get_login_time (self->user);
184 : :
185 [ # # ]: 0 : if (login_time == 0)
186 : : {
187 : 0 : gtk_widget_set_visible (GTK_WIDGET (self->last_login_label), FALSE);
188 : 0 : return;
189 : : }
190 : : else
191 : : {
192 : 0 : gtk_widget_set_visible (GTK_WIDGET (self->last_login_label), TRUE);
193 : : }
194 : :
195 : 0 : date_time = g_date_time_new_from_unix_local (login_time);
196 : :
197 [ # # ]: 0 : if (clock_format == G_DESKTOP_CLOCK_FORMAT_12H)
198 : : {
199 : : /* Translators: This is the full date and time format used in 12-hour mode. */
200 : 0 : last_login = g_date_time_format (date_time, _("%-e %B %Y, %-l:%M %P"));
201 : : }
202 : : else
203 : : {
204 : : /* Translators: This is the full date and time format used in 24-hour mode. */
205 : 0 : last_login = g_date_time_format (date_time, _("%-e %B %Y, %-k:%M"));
206 : : }
207 : :
208 : 0 : last_login_label = g_strdup_printf (_("Last logged in: %s"), last_login);
209 : 0 : gtk_label_set_label (self->last_login_label, last_login_label);
210 : : }
211 : :
212 : : static void
213 : 0 : user_page_clock_changed_cb (GSettings *settings,
214 : : char *key,
215 : : void *user_data)
216 : : {
217 : 0 : MctUserPage *self = MCT_USER_PAGE (user_data);
218 : :
219 : 0 : update_last_login_label (self);
220 : 0 : }
221 : :
222 : : /**
223 : : * mct_user_page_new:
224 : : *
225 : : * Create a new #MctUserPage widget.
226 : : *
227 : : * Returns: (transfer full): a new user page
228 : : * Since: 0.14.0
229 : : */
230 : : MctUserPage *
231 : 0 : mct_user_page_new (void)
232 : : {
233 : 0 : return g_object_new (MCT_TYPE_USER_PAGE,
234 : : NULL);
235 : : }
236 : :
237 : : /**
238 : : * mct_user_page_get_user:
239 : : * @self: an #MctUserPage
240 : : *
241 : : * Get the currently selected user.
242 : : *
243 : : * Returns: (transfer none): the currently selected user
244 : : * Since: 0.14.0
245 : : */
246 : : MctUser *
247 : 0 : mct_user_page_get_user (MctUserPage *self)
248 : : {
249 : 0 : g_return_val_if_fail (MCT_IS_USER_PAGE (self), NULL);
250 : :
251 : 0 : return self->user;
252 : : }
253 : :
254 : : static void
255 : 0 : user_notify_cb (GObject *object,
256 : : GParamSpec *pspec,
257 : : void *user_data)
258 : : {
259 : 0 : MctUser *user = MCT_USER (object);
260 : 0 : MctUserPage *self = MCT_USER_PAGE (user_data);
261 : :
262 : 0 : gtk_label_set_label (self->name_label, mct_user_get_display_name (user));
263 : 0 : update_last_login_label (self);
264 : 0 : }
265 : :
266 : : /**
267 : : * mct_user_page_set_user:
268 : : * @self: an #MctUserPage
269 : : * @user: an #MctUser
270 : : * @permission: (nullable) (transfer none): the #GPermission indicating whether
271 : : * the current user has permission to view or change parental controls, or
272 : : * %NULL if permission is not allowed or is unknown
273 : : *
274 : : * Set the currently selected user
275 : : *
276 : : * Since: 0.14.0
277 : : */
278 : : void
279 : 0 : mct_user_page_set_user (MctUserPage *self,
280 : : MctUser *user,
281 : : GPermission *permission)
282 : : {
283 : 0 : g_return_if_fail (MCT_IS_USER_PAGE (self));
284 : 0 : g_return_if_fail (MCT_IS_USER (user));
285 : :
286 [ # # ]: 0 : if (g_set_object (&self->user, user))
287 : : {
288 : 0 : mct_user_image_set_user (self->user_image, user);
289 : 0 : mct_user_image_set_size (self->user_image, 128);
290 : 0 : gtk_widget_set_margin_top (GTK_WIDGET (self->user_image), 24);
291 : 0 : gtk_widget_set_margin_bottom (GTK_WIDGET (self->user_image), 18);
292 : :
293 : 0 : self->user_notify_id = g_signal_connect (user,
294 : : "notify",
295 : : G_CALLBACK (user_notify_cb),
296 : : self);
297 : 0 : user_notify_cb (G_OBJECT (user), NULL, self);
298 : :
299 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER]);
300 : : }
301 : : }
|