Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : *
3 : : * Copyright © 2020 Endless Mobile, Inc.
4 : : *
5 : : * This program is free software; you can redistribute it and/or modify
6 : : * it under the terms of the GNU General Public License as published by
7 : : * the Free Software Foundation; either version 2 of the License, or
8 : : * (at your option) any later version.
9 : : *
10 : : * This program is distributed in the hope that it will be useful,
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : : * GNU General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU General Public License
16 : : * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 : : *
18 : : * Authors:
19 : : * - Philip Withnall <withnall@endlessm.com>
20 : : */
21 : :
22 : : #include "config.h"
23 : :
24 : : #include <gio/gio.h>
25 : : #include <glib.h>
26 : : #include <glib-object.h>
27 : : #include <glib/gi18n-lib.h>
28 : : #include <gtk/gtk.h>
29 : :
30 : : #include "restrict-applications-dialog.h"
31 : : #include "restrict-applications-selector.h"
32 : :
33 : :
34 : : static void update_description (MctRestrictApplicationsDialog *self);
35 : :
36 : : /**
37 : : * MctRestrictApplicationsDialog:
38 : : *
39 : : * The ‘Restrict Applications’ dialog is a dialog which shows the available
40 : : * applications on the system alongside a column of toggle switches, which
41 : : * allows the given user to be prevented from running each application.
42 : : *
43 : : * The dialog contains a single #MctRestrictApplicationsSelector. It takes a
44 : : * #MctRestrictApplicationsDialog:user and
45 : : * #MctRestrictApplicationsDialog:app-filter as input to set up the UI, and
46 : : * returns its output as set of modifications to a given #MctAppFilterBuilder
47 : : * using mct_restrict_applications_dialog_build_app_filter().
48 : : *
49 : : * Since: 0.5.0
50 : : */
51 : : struct _MctRestrictApplicationsDialog
52 : : {
53 : : GtkDialog parent_instance;
54 : :
55 : : MctRestrictApplicationsSelector *selector;
56 : : GtkLabel *description;
57 : :
58 : : MctAppFilter *app_filter; /* (owned) (not nullable) */
59 : : gchar *user_display_name; /* (owned) (nullable) */
60 : : };
61 : :
62 [ + + + - : 3 : G_DEFINE_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, GTK_TYPE_DIALOG)
+ - ]
63 : :
64 : : typedef enum
65 : : {
66 : : PROP_APP_FILTER = 1,
67 : : PROP_USER_DISPLAY_NAME,
68 : : } MctRestrictApplicationsDialogProperty;
69 : :
70 : : static GParamSpec *properties[PROP_USER_DISPLAY_NAME + 1];
71 : :
72 : : static void
73 : 0 : mct_restrict_applications_dialog_constructed (GObject *obj)
74 : : {
75 : 0 : MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (obj);
76 : :
77 : 0 : g_assert (self->app_filter != NULL);
78 : 0 : g_assert (self->user_display_name == NULL ||
79 : : (*self->user_display_name != '\0' &&
80 : : g_utf8_validate (self->user_display_name, -1, NULL)));
81 : :
82 : 0 : G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->constructed (obj);
83 : 0 : }
84 : :
85 : : static void
86 : 0 : mct_restrict_applications_dialog_get_property (GObject *object,
87 : : guint prop_id,
88 : : GValue *value,
89 : : GParamSpec *pspec)
90 : : {
91 : 0 : MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (object);
92 : :
93 [ # # # ]: 0 : switch ((MctRestrictApplicationsDialogProperty) prop_id)
94 : : {
95 : 0 : case PROP_APP_FILTER:
96 : 0 : g_value_set_boxed (value, self->app_filter);
97 : 0 : break;
98 : :
99 : 0 : case PROP_USER_DISPLAY_NAME:
100 : 0 : g_value_set_string (value, self->user_display_name);
101 : 0 : break;
102 : :
103 : 0 : default:
104 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105 : : }
106 : 0 : }
107 : :
108 : : static void
109 : 0 : mct_restrict_applications_dialog_set_property (GObject *object,
110 : : guint prop_id,
111 : : const GValue *value,
112 : : GParamSpec *pspec)
113 : : {
114 : 0 : MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (object);
115 : :
116 [ # # # ]: 0 : switch ((MctRestrictApplicationsDialogProperty) prop_id)
117 : : {
118 : 0 : case PROP_APP_FILTER:
119 : 0 : mct_restrict_applications_dialog_set_app_filter (self, g_value_get_boxed (value));
120 : 0 : break;
121 : :
122 : 0 : case PROP_USER_DISPLAY_NAME:
123 : 0 : mct_restrict_applications_dialog_set_user_display_name (self, g_value_get_string (value));
124 : 0 : break;
125 : :
126 : 0 : default:
127 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
128 : : }
129 : 0 : }
130 : :
131 : : static void
132 : 0 : mct_restrict_applications_dialog_dispose (GObject *object)
133 : : {
134 : 0 : MctRestrictApplicationsDialog *self = (MctRestrictApplicationsDialog *)object;
135 : :
136 [ # # ]: 0 : g_clear_pointer (&self->app_filter, mct_app_filter_unref);
137 [ # # ]: 0 : g_clear_pointer (&self->user_display_name, g_free);
138 : :
139 : 0 : G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->dispose (object);
140 : 0 : }
141 : :
142 : : static void
143 : 1 : mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass *klass)
144 : : {
145 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
146 : 1 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
147 : :
148 : 1 : object_class->constructed = mct_restrict_applications_dialog_constructed;
149 : 1 : object_class->get_property = mct_restrict_applications_dialog_get_property;
150 : 1 : object_class->set_property = mct_restrict_applications_dialog_set_property;
151 : 1 : object_class->dispose = mct_restrict_applications_dialog_dispose;
152 : :
153 : : /**
154 : : * MctRestrictApplicationsDialog:app-filter: (not nullable)
155 : : *
156 : : * The user’s current app filter, used to set up the dialog. As app filters
157 : : * are immutable, it is not updated as the dialog is changed. Use
158 : : * mct_restrict_applications_dialog_build_app_filter() to build the new app
159 : : * filter.
160 : : *
161 : : * Since: 0.5.0
162 : : */
163 : 1 : properties[PROP_APP_FILTER] =
164 : 1 : g_param_spec_boxed ("app-filter",
165 : : "App Filter",
166 : : "The user’s current app filter, used to set up the dialog.",
167 : : MCT_TYPE_APP_FILTER,
168 : : G_PARAM_READWRITE |
169 : : G_PARAM_CONSTRUCT_ONLY |
170 : : G_PARAM_STATIC_STRINGS |
171 : : G_PARAM_EXPLICIT_NOTIFY);
172 : :
173 : : /**
174 : : * MctRestrictApplicationsDialog:user-display-name: (nullable)
175 : : *
176 : : * The display name for the currently selected user account, or %NULL if no
177 : : * user is selected. This will typically be the user’s full name (if known)
178 : : * or their username.
179 : : *
180 : : * If set, it must be valid UTF-8 and non-empty.
181 : : *
182 : : * Since: 0.5.0
183 : : */
184 : 1 : properties[PROP_USER_DISPLAY_NAME] =
185 : 1 : g_param_spec_string ("user-display-name",
186 : : "User Display Name",
187 : : "The display name for the currently selected user account, or %NULL if no user is selected.",
188 : : NULL,
189 : : G_PARAM_READWRITE |
190 : : G_PARAM_STATIC_STRINGS |
191 : : G_PARAM_EXPLICIT_NOTIFY);
192 : :
193 : 1 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
194 : :
195 : 1 : gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/restrict-applications-dialog.ui");
196 : :
197 : 1 : gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, selector);
198 : 1 : gtk_widget_class_bind_template_child (widget_class, MctRestrictApplicationsDialog, description);
199 : 1 : }
200 : :
201 : : static void
202 : 0 : mct_restrict_applications_dialog_init (MctRestrictApplicationsDialog *self)
203 : : {
204 : : /* Ensure the types used in the UI are registered. */
205 : 0 : g_type_ensure (MCT_TYPE_RESTRICT_APPLICATIONS_SELECTOR);
206 : :
207 : 0 : gtk_widget_init_template (GTK_WIDGET (self));
208 : 0 : }
209 : :
210 : : static void
211 : 0 : update_description (MctRestrictApplicationsDialog *self)
212 : : {
213 [ # # ]: 0 : g_autofree gchar *description = NULL;
214 : :
215 [ # # ]: 0 : if (self->user_display_name == NULL)
216 : : {
217 : 0 : gtk_widget_hide (GTK_WIDGET (self->description));
218 : 0 : return;
219 : : }
220 : :
221 : : /* Translators: the placeholder is a user’s full name */
222 : 0 : description = g_strdup_printf (_("Restrict %s from using the following installed applications."),
223 : : self->user_display_name);
224 : 0 : gtk_label_set_text (self->description, description);
225 : 0 : gtk_widget_show (GTK_WIDGET (self->description));
226 : : }
227 : :
228 : : /**
229 : : * mct_restrict_applications_dialog_new:
230 : : * @app_filter: (transfer none): the initial app filter configuration to show
231 : : * @user_display_name: (transfer none) (nullable): the display name of the user
232 : : * to show the app filter for, or %NULL if no user is selected
233 : : *
234 : : * Create a new #MctRestrictApplicationsDialog widget.
235 : : *
236 : : * Returns: (transfer full): a new restricted applications editing dialog
237 : : * Since: 0.5.0
238 : : */
239 : : MctRestrictApplicationsDialog *
240 : 0 : mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
241 : : const gchar *user_display_name)
242 : : {
243 : 0 : g_return_val_if_fail (app_filter != NULL, NULL);
244 : 0 : g_return_val_if_fail (user_display_name == NULL ||
245 : : (*user_display_name != '\0' &&
246 : : g_utf8_validate (user_display_name, -1, NULL)), NULL);
247 : :
248 : 0 : return g_object_new (MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG,
249 : : "app-filter", app_filter,
250 : : "user-display-name", user_display_name,
251 : : NULL);
252 : : }
253 : :
254 : : /**
255 : : * mct_restrict_applications_dialog_get_app_filter:
256 : : * @self: an #MctRestrictApplicationsDialog
257 : : *
258 : : * Get the value of #MctRestrictApplicationsDialog:app-filter. If the property
259 : : * was originally set to %NULL, this will be the empty app filter.
260 : : *
261 : : * Returns: (transfer none) (not nullable): the initial app filter used to
262 : : * populate the dialog
263 : : * Since: 0.5.0
264 : : */
265 : : MctAppFilter *
266 : 0 : mct_restrict_applications_dialog_get_app_filter (MctRestrictApplicationsDialog *self)
267 : : {
268 : 0 : g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self), NULL);
269 : :
270 : 0 : return self->app_filter;
271 : : }
272 : :
273 : : /**
274 : : * mct_restrict_applications_dialog_set_app_filter:
275 : : * @self: an #MctRestrictApplicationsDialog
276 : : * @app_filter: (nullable) (transfer none): the app filter to configure the dialog
277 : : * from, or %NULL to use an empty app filter
278 : : *
279 : : * Set the value of #MctRestrictApplicationsDialog:app-filter.
280 : : *
281 : : * Since: 0.5.0
282 : : */
283 : : void
284 : 0 : mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *self,
285 : : MctAppFilter *app_filter)
286 : : {
287 [ # # ]: 0 : g_autoptr(MctAppFilter) owned_app_filter = NULL;
288 : :
289 : 0 : g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self));
290 : :
291 : : /* Default app filter, typically for when we’re instantiated by #GtkBuilder. */
292 [ # # ]: 0 : if (app_filter == NULL)
293 : : {
294 : 0 : g_auto(MctAppFilterBuilder) builder = MCT_APP_FILTER_BUILDER_INIT ();
295 : 0 : owned_app_filter = mct_app_filter_builder_end (&builder);
296 : 0 : app_filter = owned_app_filter;
297 : : }
298 : :
299 [ # # ]: 0 : if (app_filter == self->app_filter)
300 : 0 : return;
301 : :
302 [ # # ]: 0 : g_clear_pointer (&self->app_filter, mct_app_filter_unref);
303 : 0 : self->app_filter = mct_app_filter_ref (app_filter);
304 : :
305 : 0 : mct_restrict_applications_selector_set_app_filter (self->selector, self->app_filter);
306 : :
307 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APP_FILTER]);
308 : : }
309 : :
310 : : /**
311 : : * mct_restrict_applications_dialog_get_user_display_name:
312 : : * @self: an #MctRestrictApplicationsDialog
313 : : *
314 : : * Get the value of #MctRestrictApplicationsDialog:user-display-name.
315 : : *
316 : : * Returns: (transfer none) (nullable): the display name of the user the dialog
317 : : * is configured for, or %NULL if unknown
318 : : * Since: 0.5.0
319 : : */
320 : : const gchar *
321 : 0 : mct_restrict_applications_dialog_get_user_display_name (MctRestrictApplicationsDialog *self)
322 : : {
323 : 0 : g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self), NULL);
324 : :
325 : 0 : return self->user_display_name;
326 : : }
327 : :
328 : : /**
329 : : * mct_restrict_applications_dialog_set_user_display_name:
330 : : * @self: an #MctRestrictApplicationsDialog
331 : : * @user_display_name: (nullable) (transfer none): the display name of the user
332 : : * to configure the dialog for, or %NULL if unknown
333 : : *
334 : : * Set the value of #MctRestrictApplicationsDialog:user-display-name.
335 : : *
336 : : * Since: 0.5.0
337 : : */
338 : : void
339 : 0 : mct_restrict_applications_dialog_set_user_display_name (MctRestrictApplicationsDialog *self,
340 : : const gchar *user_display_name)
341 : : {
342 : 0 : g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self));
343 : 0 : g_return_if_fail (user_display_name == NULL ||
344 : : (*user_display_name != '\0' &&
345 : : g_utf8_validate (user_display_name, -1, NULL)));
346 : :
347 [ # # ]: 0 : if (g_strcmp0 (self->user_display_name, user_display_name) == 0)
348 : 0 : return;
349 : :
350 [ # # ]: 0 : g_clear_pointer (&self->user_display_name, g_free);
351 : 0 : self->user_display_name = g_strdup (user_display_name);
352 : :
353 : 0 : update_description (self);
354 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_DISPLAY_NAME]);
355 : : }
356 : :
357 : : /**
358 : : * mct_restrict_applications_dialog_build_app_filter:
359 : : * @self: an #MctRestrictApplicationsDialog
360 : : * @builder: an existing #MctAppFilterBuilder to modify
361 : : *
362 : : * Get the app filter settings currently configured in the dialog, by modifying
363 : : * the given @builder.
364 : : *
365 : : * Typically this will be called in the handler for #GtkDialog::response.
366 : : *
367 : : * Since: 0.5.0
368 : : */
369 : : void
370 : 0 : mct_restrict_applications_dialog_build_app_filter (MctRestrictApplicationsDialog *self,
371 : : MctAppFilterBuilder *builder)
372 : : {
373 : 0 : g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self));
374 : 0 : g_return_if_fail (builder != NULL);
375 : :
376 : 0 : mct_restrict_applications_selector_build_app_filter (self->selector, builder);
377 : : }
|