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 : : * 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 : : * - Philip Withnall <withnall@endlessm.com>
22 : : */
23 : :
24 : : #include <gio/gio.h>
25 : : #include <glib.h>
26 : : #include <glib-object.h>
27 : : #include <glib/gi18n.h>
28 : : #include <gtk/gtk.h>
29 : : #include <libmalcontent/malcontent.h>
30 : :
31 : : #include "user-image.h"
32 : : #include "user-selector.h"
33 : :
34 : :
35 : : static gint sort_users (gconstpointer a,
36 : : gconstpointer b,
37 : : gpointer user_data);
38 : : static void reload_users (MctUserSelector *self);
39 : : static void notify_n_items_cb (GObject *obj,
40 : : GParamSpec *pspec,
41 : : gpointer user_data);
42 : : static void user_manager_notify_is_loaded_cb (GObject *object,
43 : : GParamSpec *pspec,
44 : : void *user_data);
45 : : static void user_added_cb (MctUserManager *user_manager,
46 : : MctUser *user,
47 : : gpointer user_data);
48 : : static void user_removed_cb (MctUserManager *user_manager,
49 : : MctUser *user,
50 : : void *user_data);
51 : : static void on_user_row_activated (MctUserSelector *self,
52 : : AdwActionRow *row);
53 : : static GtkWidget *create_user_row (gpointer item, gpointer user_data);
54 : :
55 : :
56 : : /**
57 : : * MctUserSelector:
58 : : *
59 : : * The user selector is a widget which lists available user accounts and allows
60 : : * the user to select one.
61 : : *
62 : : * Since: 0.5.0
63 : : */
64 : : struct _MctUserSelector
65 : : {
66 : : GtkBox parent_instance;
67 : :
68 : : GtkListBox *user_list;
69 : :
70 : : GListStore *model /* (owned) */;
71 : :
72 : : MctUserManager *user_manager; /* (owned) */
73 : : MctUser *current_user; /* (owned) (nullable) */
74 : : MctUser *selected_user; /* (owned) (nullable) */
75 : : gboolean show_parents;
76 : : guint n_users;
77 : : GCancellable *cancellable; /* (owned) */
78 : : };
79 : :
80 [ # # # # : 0 : G_DEFINE_TYPE (MctUserSelector, mct_user_selector, GTK_TYPE_BOX)
# # ]
81 : :
82 : : typedef enum
83 : : {
84 : : PROP_SELECTED_USER = 1,
85 : : PROP_USER_MANAGER,
86 : : PROP_CURRENT_USER,
87 : : PROP_N_USERS,
88 : : PROP_SHOW_PARENTS,
89 : : } MctUserSelectorProperty;
90 : :
91 : : static GParamSpec *properties[PROP_SHOW_PARENTS + 1];
92 : :
93 : : static void
94 : 0 : mct_user_selector_constructed (GObject *obj)
95 : : {
96 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (obj);
97 : :
98 : : /* Chain up. */
99 : 0 : G_OBJECT_CLASS (mct_user_selector_parent_class)->constructed (obj);
100 : :
101 : : /* The user manager is mandatory and must have been loaded already. */
102 : 0 : g_assert (self->user_manager != NULL);
103 : :
104 : 0 : self->model = g_list_store_new (MCT_TYPE_USER);
105 : 0 : gtk_list_box_bind_model (self->user_list,
106 : 0 : G_LIST_MODEL (self->model),
107 : : (GtkListBoxCreateWidgetFunc)create_user_row,
108 : : self,
109 : : NULL);
110 : :
111 : 0 : g_signal_connect_object (self->model, "notify::n-items",
112 : : G_CALLBACK (notify_n_items_cb),
113 : : self, G_CONNECT_DEFAULT);
114 : 0 : g_signal_connect (self->user_manager, "notify::is-loaded",
115 : : G_CALLBACK (user_manager_notify_is_loaded_cb), self);
116 : 0 : g_signal_connect (self->user_manager, "user-added",
117 : : G_CALLBACK (user_added_cb), self);
118 : 0 : g_signal_connect (self->user_manager, "user-removed",
119 : : G_CALLBACK (user_removed_cb), self);
120 : 0 : }
121 : :
122 : : static void
123 : 0 : mct_user_selector_get_property (GObject *object,
124 : : guint prop_id,
125 : : GValue *value,
126 : : GParamSpec *pspec)
127 : : {
128 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (object);
129 : :
130 [ # # # # : 0 : switch ((MctUserSelectorProperty) prop_id)
# # ]
131 : : {
132 : 0 : case PROP_SELECTED_USER:
133 : 0 : g_value_set_object (value, self->selected_user);
134 : 0 : break;
135 : :
136 : 0 : case PROP_USER_MANAGER:
137 : 0 : g_value_set_object (value, self->user_manager);
138 : 0 : break;
139 : :
140 : 0 : case PROP_CURRENT_USER:
141 : 0 : g_value_set_object (value, self->current_user);
142 : 0 : break;
143 : :
144 : 0 : case PROP_N_USERS:
145 : 0 : g_value_set_uint (value, mct_user_selector_get_n_users (self));
146 : 0 : break;
147 : :
148 : 0 : case PROP_SHOW_PARENTS:
149 : 0 : g_value_set_boolean (value, self->show_parents);
150 : 0 : break;
151 : :
152 : 0 : default:
153 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
154 : : }
155 : 0 : }
156 : :
157 : : static void
158 : 0 : mct_user_selector_set_property (GObject *object,
159 : : guint prop_id,
160 : : const GValue *value,
161 : : GParamSpec *pspec)
162 : : {
163 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (object);
164 : :
165 [ # # # # : 0 : switch ((MctUserSelectorProperty) prop_id)
# # ]
166 : : {
167 : 0 : case PROP_SELECTED_USER:
168 : : /* Currently read only */
169 : : g_assert_not_reached ();
170 : : break;
171 : :
172 : 0 : case PROP_USER_MANAGER:
173 : 0 : g_assert (self->user_manager == NULL);
174 : 0 : self->user_manager = g_value_dup_object (value);
175 : 0 : break;
176 : :
177 : 0 : case PROP_CURRENT_USER:
178 : 0 : mct_user_selector_set_current_user (self, g_value_get_object (value));
179 : 0 : break;
180 : :
181 : 0 : case PROP_N_USERS:
182 : : /* Currently read only */
183 : : g_assert_not_reached ();
184 : : break;
185 : :
186 : 0 : case PROP_SHOW_PARENTS:
187 : 0 : self->show_parents = g_value_get_boolean (value);
188 : 0 : reload_users (self);
189 : 0 : break;
190 : :
191 : 0 : default:
192 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
193 : : }
194 : 0 : }
195 : :
196 : : static void
197 : 0 : mct_user_selector_dispose (GObject *object)
198 : : {
199 : 0 : MctUserSelector *self = (MctUserSelector *)object;
200 : :
201 : 0 : g_cancellable_cancel (self->cancellable);
202 [ # # ]: 0 : g_clear_object (&self->cancellable);
203 : :
204 [ # # ]: 0 : g_clear_object (&self->model);
205 [ # # ]: 0 : g_clear_object (&self->selected_user);
206 : :
207 [ # # ]: 0 : if (self->user_manager != NULL)
208 : : {
209 : 0 : g_signal_handlers_disconnect_by_func (self->user_manager, user_removed_cb, self);
210 : 0 : g_signal_handlers_disconnect_by_func (self->user_manager, user_added_cb, self);
211 : 0 : g_signal_handlers_disconnect_by_func (self->user_manager, user_manager_notify_is_loaded_cb, self);
212 : :
213 [ # # ]: 0 : g_clear_object (&self->user_manager);
214 : : }
215 : :
216 : 0 : G_OBJECT_CLASS (mct_user_selector_parent_class)->dispose (object);
217 : 0 : }
218 : :
219 : : static void
220 : 0 : mct_user_selector_class_init (MctUserSelectorClass *klass)
221 : : {
222 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
223 : 0 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
224 : :
225 : 0 : object_class->constructed = mct_user_selector_constructed;
226 : 0 : object_class->get_property = mct_user_selector_get_property;
227 : 0 : object_class->set_property = mct_user_selector_set_property;
228 : 0 : object_class->dispose = mct_user_selector_dispose;
229 : :
230 : : /**
231 : : * MctUserSelector:selected-user: (nullable)
232 : : *
233 : : * The currently selected user account.
234 : : *
235 : : * This may be `NULL` if no user is selected.
236 : : *
237 : : * Currently read only but may become writable in future.
238 : : *
239 : : * Since: 0.14.0
240 : : */
241 : 0 : properties[PROP_SELECTED_USER] =
242 : 0 : g_param_spec_object ("selected-user", NULL, NULL,
243 : : MCT_TYPE_USER,
244 : : G_PARAM_READABLE |
245 : : G_PARAM_STATIC_STRINGS |
246 : : G_PARAM_EXPLICIT_NOTIFY);
247 : :
248 : : /**
249 : : * MctUserSelector:user-manager: (not nullable)
250 : : *
251 : : * The user manager providing the data for the widget.
252 : : *
253 : : * This must have already been asynchronously loaded using
254 : : * [method@Malcontent.UserManager.load_async] before this widget is mapped.
255 : : * This widget has no ‘loading’ view.
256 : : *
257 : : * Since: 0.14.0
258 : : */
259 : 0 : properties[PROP_USER_MANAGER] =
260 : 0 : g_param_spec_object ("user-manager", NULL, NULL,
261 : : MCT_TYPE_USER_MANAGER,
262 : : G_PARAM_READWRITE |
263 : : G_PARAM_CONSTRUCT_ONLY |
264 : : G_PARAM_STATIC_STRINGS |
265 : : G_PARAM_EXPLICIT_NOTIFY);
266 : :
267 : : /**
268 : : * MctUserSelector:current-user: (nullable)
269 : : *
270 : : * The user currently using the widget.
271 : : *
272 : : * This is used to display the correct family group. Typically it is the
273 : : * result of calling:
274 : : * ```c
275 : : * mct_user_manager_get_user_by_uid (user_manager, getuid ())
276 : : * ```
277 : : *
278 : : * It may be `NULL` if the user’s data is not yet known, but it must be set
279 : : * before this widget is mapped. This widget has no ‘loading’ view.
280 : : *
281 : : * Since: 0.14.0
282 : : */
283 : 0 : properties[PROP_CURRENT_USER] =
284 : 0 : g_param_spec_object ("current-user", NULL, NULL,
285 : : MCT_TYPE_USER,
286 : : G_PARAM_READWRITE |
287 : : G_PARAM_STATIC_STRINGS |
288 : : G_PARAM_EXPLICIT_NOTIFY);
289 : :
290 : : /**
291 : : * MctUserSelector:show-parents:
292 : : *
293 : : * Whether to show parents in the list, or hide them.
294 : : *
295 : : * Since: 0.14.0
296 : : */
297 : 0 : properties[PROP_SHOW_PARENTS] =
298 : 0 : g_param_spec_boolean ("show-parents", NULL, NULL,
299 : : TRUE,
300 : : G_PARAM_READWRITE |
301 : : G_PARAM_STATIC_STRINGS);
302 : :
303 : : /**
304 : : * MctUserSelector:n-users:
305 : : *
306 : : * The number of users contained in this selector.
307 : : *
308 : : * Since: 0.14.0
309 : : */
310 : 0 : properties[PROP_N_USERS] =
311 : 0 : g_param_spec_uint ("n-users",
312 : : NULL,
313 : : NULL,
314 : : 0,
315 : : G_MAXUINT,
316 : : 0,
317 : : G_PARAM_READABLE |
318 : : G_PARAM_STATIC_STRINGS |
319 : : G_PARAM_EXPLICIT_NOTIFY);
320 : :
321 : 0 : g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
322 : :
323 : 0 : gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentControl/ui/user-selector.ui");
324 : :
325 : 0 : gtk_widget_class_bind_template_child (widget_class, MctUserSelector, user_list);
326 : :
327 : 0 : gtk_widget_class_bind_template_callback (widget_class, on_user_row_activated);
328 : 0 : }
329 : :
330 : : static void
331 : 0 : mct_user_selector_init (MctUserSelector *self)
332 : : {
333 : 0 : self->show_parents = TRUE;
334 : 0 : self->cancellable = g_cancellable_new ();
335 : :
336 : 0 : gtk_widget_init_template (GTK_WIDGET (self));
337 : 0 : }
338 : :
339 : : static void
340 : 0 : notify_n_items_cb (GObject *obj,
341 : : GParamSpec *pspec,
342 : : gpointer user_data)
343 : : {
344 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (user_data);
345 : :
346 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_USERS]);
347 : 0 : }
348 : :
349 : : static void
350 : 0 : user_manager_notify_is_loaded_cb (GObject *object,
351 : : GParamSpec *pspec,
352 : : void *user_data)
353 : : {
354 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (user_data);
355 : :
356 : 0 : reload_users (self);
357 : 0 : }
358 : :
359 : : static void
360 : 0 : on_user_row_activated (MctUserSelector *self,
361 : : AdwActionRow *row)
362 : : {
363 : : MctUser *user;
364 : :
365 [ # # ]: 0 : g_clear_object (&self->selected_user);
366 : :
367 : 0 : user = g_object_get_data (G_OBJECT (row), "user");
368 : :
369 [ # # ]: 0 : if (g_set_object (&self->selected_user, user))
370 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_USER]);
371 : 0 : }
372 : :
373 : : static void
374 : 0 : user_notify_display_name_cb (GObject *object,
375 : : GParamSpec *pspec,
376 : : void *user_data)
377 : : {
378 : 0 : MctUser *user = MCT_USER (object);
379 : 0 : AdwPreferencesRow *row = ADW_PREFERENCES_ROW (user_data);
380 : : MctUserSelector *self;
381 : :
382 : 0 : adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
383 : : mct_user_get_display_name (user));
384 : :
385 : : /* The new name might have changed the row’s position in the list, so re-sort
386 : : * the list. */
387 : 0 : self = MCT_USER_SELECTOR (gtk_widget_get_ancestor (GTK_WIDGET (row), MCT_TYPE_USER_SELECTOR));
388 [ # # ]: 0 : if (self != NULL)
389 : 0 : g_list_store_sort (self->model, sort_users, self);
390 : 0 : }
391 : :
392 : : static GtkWidget *
393 : 0 : create_user_row (gpointer item, gpointer user_data)
394 : : {
395 : : MctUser *user;
396 : : GtkWidget *row, *user_image;
397 : :
398 : 0 : row = adw_action_row_new ();
399 : 0 : gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE);
400 : :
401 : 0 : user = item;
402 : :
403 : 0 : g_object_set_data_full (G_OBJECT (row), "user", g_object_ref (user), g_object_unref);
404 : :
405 : 0 : adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row),
406 : : mct_user_get_display_name (user));
407 : 0 : g_signal_connect_object (user, "notify::display-name",
408 : : G_CALLBACK (user_notify_display_name_cb), row,
409 : : G_CONNECT_DEFAULT);
410 : :
411 : 0 : user_image = mct_user_image_new ();
412 : 0 : mct_user_image_set_user (MCT_USER_IMAGE (user_image), user);
413 : 0 : gtk_widget_set_margin_top (user_image, 12);
414 : 0 : gtk_widget_set_margin_bottom (user_image, 12);
415 : 0 : adw_action_row_add_prefix (ADW_ACTION_ROW (row), user_image);
416 : 0 : adw_action_row_activate (ADW_ACTION_ROW (row));
417 : :
418 : 0 : GtkWidget *arrow = gtk_image_new_from_icon_name ("go-next-symbolic");
419 : 0 : adw_action_row_add_suffix (ADW_ACTION_ROW (row), arrow);
420 : :
421 : 0 : return row;
422 : : }
423 : :
424 : : static gint
425 : 0 : sort_users (gconstpointer a, gconstpointer b, gpointer user_data)
426 : : {
427 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (user_data);
428 : : MctUser *ua, *ub;
429 : : gint result;
430 : :
431 : 0 : ua = MCT_USER ((gpointer) a);
432 : 0 : ub = MCT_USER ((gpointer) b);
433 : :
434 : : /* Make sure the current user is shown first */
435 [ # # # # ]: 0 : if (self->current_user != NULL && mct_user_equal (ua, self->current_user))
436 : : {
437 : 0 : result = G_MININT32;
438 : : }
439 [ # # # # ]: 0 : else if (self->current_user != NULL && mct_user_equal (ub, self->current_user))
440 : : {
441 : 0 : result = G_MAXINT32;
442 : : }
443 : : else
444 : : {
445 : 0 : g_autofree gchar *name1 = NULL, *name2 = NULL;
446 : :
447 : 0 : name1 = g_utf8_collate_key (mct_user_get_display_name (ua), -1);
448 : 0 : name2 = g_utf8_collate_key (mct_user_get_display_name (ub), -1);
449 : :
450 : 0 : result = strcmp (name1, name2);
451 : : }
452 : :
453 : 0 : return result;
454 : : }
455 : :
456 : : static void reload_users_cb (GObject *object,
457 : : GAsyncResult *result,
458 : : void *user_data);
459 : :
460 : : static void
461 : 0 : reload_users (MctUserSelector *self)
462 : : {
463 [ # # ]: 0 : if (!mct_user_manager_get_is_loaded (self->user_manager) ||
464 [ # # ]: 0 : self->current_user == NULL)
465 : 0 : return;
466 : :
467 : 0 : mct_user_manager_get_family_members_for_user_async (self->user_manager,
468 : : self->current_user,
469 : : self->cancellable,
470 : : reload_users_cb,
471 : : self);
472 : : }
473 : :
474 : : static void
475 : 0 : reload_users_cb (GObject *object,
476 : : GAsyncResult *result,
477 : : void *user_data)
478 : : {
479 : 0 : MctUserManager *user_manager = MCT_USER_MANAGER (object);
480 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (user_data);
481 : 0 : g_autoptr(MctUserArray) users = NULL;
482 : 0 : size_t n_users = 0;
483 : 0 : g_autoptr(GError) local_error = NULL;
484 : :
485 : 0 : users = mct_user_manager_get_family_members_for_user_finish (user_manager, result, &n_users, &local_error);
486 [ # # ]: 0 : if (local_error != NULL)
487 : 0 : g_debug ("Error getting users: %s", local_error->message);
488 : : else
489 : 0 : g_debug ("Got %zu users", n_users);
490 : :
491 : 0 : g_list_store_remove_all (self->model);
492 : :
493 [ # # ]: 0 : for (size_t i = 0; i < n_users; i++)
494 : : {
495 : 0 : MctUser *user = users[i];
496 : 0 : user_added_cb (self->user_manager, user, self);
497 : : }
498 : 0 : }
499 : :
500 : : static void
501 : 0 : user_added_cb (MctUserManager *user_manager,
502 : : MctUser *user,
503 : : void *user_data)
504 : : {
505 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (user_data);
506 : :
507 [ # # # # ]: 0 : if (self->current_user != NULL &&
508 : 0 : !mct_user_is_in_same_family (user, self->current_user))
509 : : {
510 : 0 : g_debug ("Ignoring user %s not in the same family as current user %s",
511 : : mct_user_get_display_name (user), mct_user_get_display_name (self->current_user));
512 : 0 : return;
513 : : }
514 : :
515 [ # # ]: 0 : if (mct_user_get_user_type (user) == MCT_USER_TYPE_PARENT &&
516 [ # # ]: 0 : !self->show_parents)
517 : : {
518 : 0 : g_debug ("Ignoring parent %s", mct_user_get_display_name (user));
519 : 0 : return;
520 : : }
521 : :
522 : 0 : g_debug ("User added: %u %s", (guint) mct_user_get_uid (user), mct_user_get_display_name (user));
523 : :
524 : 0 : g_list_store_insert_sorted (self->model, user, sort_users, self);
525 : : }
526 : :
527 : : static void
528 : 0 : user_removed_cb (MctUserManager *user_manager,
529 : : MctUser *user,
530 : : void *user_data)
531 : : {
532 : 0 : MctUserSelector *self = MCT_USER_SELECTOR (user_data);
533 : :
534 : 0 : reload_users (self);
535 : 0 : }
536 : :
537 : : /**
538 : : * mct_user_selector_new:
539 : : * @user_manager: (transfer none): a user manager to provide the user data
540 : : *
541 : : * Create a new #MctUserSelector widget.
542 : : *
543 : : * Returns: (transfer full): a new user selector
544 : : * Since: 0.14.0
545 : : */
546 : : MctUserSelector *
547 : 0 : mct_user_selector_new (MctUserManager *user_manager)
548 : : {
549 : 0 : g_return_val_if_fail (MCT_IS_USER_MANAGER (user_manager), NULL);
550 : :
551 : 0 : return g_object_new (MCT_TYPE_USER_SELECTOR,
552 : : "user-manager", user_manager,
553 : : NULL);
554 : : }
555 : :
556 : : /**
557 : : * mct_user_selector_get_selected_user:
558 : : * @self: an #MctUserSelector
559 : : *
560 : : * Get the value of [property@Malcontent.UserSelector:selected-user].
561 : : *
562 : : * Returns: (transfer none) (nullable): the currently selected user, or `NULL`
563 : : * if no user is selected.
564 : : * Since: 0.14.0
565 : : */
566 : : MctUser *
567 : 0 : mct_user_selector_get_selected_user (MctUserSelector *self)
568 : : {
569 : 0 : g_return_val_if_fail (MCT_IS_USER_SELECTOR (self), NULL);
570 : :
571 : 0 : return self->selected_user;
572 : : }
573 : :
574 : : /**
575 : : * mct_user_selector_get_current_user:
576 : : * @self: a user selector
577 : : *
578 : : * Get the value of [property@Malcontent.UserSelector:current-user].
579 : : *
580 : : * Returns: (transfer none) (nullable): the user currently using the widget, or
581 : : * `NULL` if not known
582 : : * Since: 0.14.0
583 : : */
584 : : MctUser *
585 : 0 : mct_user_selector_get_current_user (MctUserSelector *self)
586 : : {
587 : 0 : g_return_val_if_fail (MCT_IS_USER_SELECTOR (self), NULL);
588 : :
589 : 0 : return self->current_user;
590 : : }
591 : :
592 : : /**
593 : : * mct_user_selector_set_current_user:
594 : : * @self: a user selector
595 : : * @current_user: (transfer none) (nullable): the user currently using the
596 : : * widget, or `NULL` if not known
597 : : *
598 : : * Set the value of [property@Malcontent.UserSelector:current-user].
599 : : *
600 : : * Since: 0.14.0
601 : : */
602 : : void
603 : 0 : mct_user_selector_set_current_user (MctUserSelector *self,
604 : : MctUser *current_user)
605 : : {
606 : 0 : g_return_if_fail (MCT_IS_USER_SELECTOR (self));
607 : 0 : g_return_if_fail (current_user == NULL || MCT_IS_USER (current_user));
608 : :
609 [ # # ]: 0 : if (g_set_object (&self->current_user, current_user))
610 : : {
611 : 0 : reload_users (self);
612 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CURRENT_USER]);
613 : : }
614 : : }
615 : :
616 : : /**
617 : : * mct_user_selector_select_user_by_username:
618 : : * @self: an #MctUserSelector
619 : : * @user: the user to select
620 : : *
621 : : * Selects the given @user in the widget. This might fail if @user isn’t
622 : : * a valid user, or if they aren’t listed in the selector due to being a
623 : : * parent (see #MctUserSelector:show-parents).
624 : : *
625 : : * Returns: %TRUE if the user was successfully selected, %FALSE otherwise
626 : : * Since: 0.14.0
627 : : */
628 : : gboolean
629 : 0 : mct_user_selector_select_user (MctUserSelector *self,
630 : : MctUser *user)
631 : : {
632 : 0 : g_return_val_if_fail (MCT_IS_USER_SELECTOR (self), FALSE);
633 : 0 : g_return_val_if_fail (MCT_IS_USER (user), FALSE);
634 : :
635 [ # # ]: 0 : if (!g_list_store_find_with_equal_func (self->model, user, (GEqualFunc) mct_user_equal, NULL))
636 : 0 : return FALSE;
637 : :
638 [ # # ]: 0 : if (g_set_object (&self->selected_user, user))
639 : 0 : g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_USER]);
640 : :
641 : 0 : return TRUE;
642 : : }
643 : :
644 : : /**
645 : : * mct_user_selector_get_n_users:
646 : : * @self: an #MctUserSelector
647 : : *
648 : : * Gets the number of users in @self.
649 : : *
650 : : * Returns: the number of users in @self
651 : : * Since: 0.14.0
652 : : */
653 : : size_t
654 : 0 : mct_user_selector_get_n_users (MctUserSelector *self)
655 : : {
656 : 0 : g_return_val_if_fail (MCT_IS_USER_SELECTOR (self), 0);
657 : :
658 : 0 : return g_list_model_get_n_items (G_LIST_MODEL (self->model));
659 : : }
|