gnome-control-center/panels/user-accounts/cc-user-panel.c
Philip Withnall 2809316fd1 user-accounts: Show ‘Add User’ button when panel is locked
Rather than hiding the ‘Add User’ button when the panel is locked, show
it in an insensitive state. This gives the user a hint that in order to
add a new user, they will need to unlock the panel.

See: https://gitlab.freedesktop.org/pwithnall/malcontent/-/issues/26#note_705945

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2020-12-11 17:19:11 +00:00

1686 lines
63 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright 2009-2010 Red Hat, Inc,
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Written by: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "cc-user-panel.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <locale.h>
#include <errno.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <polkit/polkit.h>
#include <act/act.h>
#include <cairo-gobject.h>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-languages.h>
#ifdef HAVE_MALCONTENT
#include <libmalcontent/malcontent.h>
#endif
#include "cc-add-user-dialog.h"
#include "cc-avatar-chooser.h"
#include "cc-carousel.h"
#include "cc-language-chooser.h"
#include "cc-login-history-dialog.h"
#include "cc-password-dialog.h"
#include "cc-realm-manager.h"
#include "cc-user-accounts-resources.h"
#include "cc-user-image.h"
#include "cc-fingerprint-manager.h"
#include "cc-fingerprint-dialog.h"
#include "user-utils.h"
#include "cc-common-language.h"
#include "cc-permission-infobar.h"
#include "cc-util.h"
#include "list-box-helper.h"
#define USER_ACCOUNTS_PERMISSION "org.gnome.controlcenter.user-accounts.administration"
struct _CcUserPanel {
CcPanel parent_instance;
ActUserManager *um;
GSettings *login_screen_settings;
GtkBox *accounts_box;
GtkBox *account_settings_box;
GtkListBox *account_settings_listbox;
GtkListBox *authentication_and_login_listbox;
GtkListBoxRow *account_type_row;
GtkSwitch *account_type_switch;
GtkButton *add_user_button;
GtkListBoxRow *autologin_row;
GtkSwitch *autologin_switch;
CcCarousel *carousel;
GtkLabel *fingerprint_state_label;
GtkListBoxRow *fingerprint_row;
GtkStack *full_name_stack;
GtkLabel *full_name_label;
GtkToggleButton *full_name_edit_button;
GtkEntry *full_name_entry;
GtkLabel *language_button_label;
GtkListBoxRow *language_row;
GtkLabel *last_login_button_label;
GtkListBoxRow *last_login_row;
GtkBox *no_users_box;
GtkRevealer *notification_revealer;
GtkLabel *password_button_label;
#ifdef HAVE_MALCONTENT
GtkLabel *parental_controls_button_label;
GtkImage *parental_control_go_next;
GtkListBoxRow *parental_controls_row;
#endif
GtkListBoxRow *password_row;
CcPermissionInfobar *permission_infobar;
GtkButton *remove_user_button;
GtkStack *stack;
GtkToggleButton *user_icon_button;
CcUserImage *user_icon_image;
CcUserImage *user_icon_image2;
GtkStack *user_icon_stack;
GtkOverlay *users_overlay;
ActUser *selected_user;
GPermission *permission;
CcLanguageChooser *language_chooser;
CcAvatarChooser *avatar_chooser;
CcFingerprintManager *fingerprint_manager;
gint other_accounts;
};
CC_PANEL_REGISTER (CcUserPanel, cc_user_panel)
static void show_restart_notification (CcUserPanel *self, const gchar *locale);
static gint user_compare (gconstpointer i, gconstpointer u);
typedef struct {
CcUserPanel *self;
GCancellable *cancellable;
gchar *login;
} AsyncDeleteData;
static void
async_delete_data_free (AsyncDeleteData *data)
{
g_object_unref (data->self);
g_object_unref (data->cancellable);
g_free (data->login);
g_slice_free (AsyncDeleteData, data);
}
static void
show_error_dialog (CcUserPanel *self,
const gchar *message,
GError *error)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"%s", message);
if (error != NULL) {
g_dbus_error_strip_remote_error (error);
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
}
g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_window_present (GTK_WINDOW (dialog));
}
static ActUser *
get_selected_user (CcUserPanel *self)
{
return self->selected_user;
}
static const gchar *
get_real_or_user_name (ActUser *user)
{
const gchar *name;
name = act_user_get_real_name (user);
if (name == NULL)
name = act_user_get_user_name (user);
return name;
}
static void show_user (ActUser *user, CcUserPanel *self);
static void
set_selected_user (CcUserPanel *self, CcCarouselItem *item)
{
uid_t uid;
uid = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "uid"));
g_set_object (&self->selected_user,
act_user_manager_get_user_by_id (self->um, uid));
if (self->selected_user != NULL) {
show_user (self->selected_user, self);
}
}
static GtkWidget *
create_carousel_entry (CcUserPanel *self, ActUser *user)
{
GtkWidget *box, *widget;
gchar *label;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
widget = cc_user_image_new ();
cc_user_image_set_user (CC_USER_IMAGE (widget), user);
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
label = g_markup_printf_escaped ("<b>%s</b>",
get_real_or_user_name (user));
widget = gtk_label_new (label);
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
gtk_widget_set_margin_top (widget, 5);
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
g_free (label);
if (act_user_get_uid (user) == getuid ())
label = g_strdup_printf ("<small>%s</small>", _("Your account"));
else
label = g_strdup (" ");
widget = gtk_label_new (label);
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
g_free (label);
gtk_box_pack_start (GTK_BOX (box), widget, FALSE, TRUE, 0);
gtk_style_context_add_class (gtk_widget_get_style_context (widget),
"dim-label");
return box;
}
static void
user_added (CcUserPanel *self, ActUser *user)
{
GtkWidget *item, *widget;
gboolean show_carousel;
if (act_user_is_system_account (user)) {
return;
}
g_debug ("user added: %d %s\n", act_user_get_uid (user), get_real_or_user_name (user));
widget = create_carousel_entry (self, user);
item = cc_carousel_item_new ();
gtk_container_add (GTK_CONTAINER (item), widget);
g_object_set_data (G_OBJECT (item), "uid", GINT_TO_POINTER (act_user_get_uid (user)));
gtk_container_add (GTK_CONTAINER (self->carousel), item);
if (act_user_get_uid (user) != getuid ()) {
self->other_accounts++;
}
/* Show heading for other accounts if new one have been added. */
show_carousel = (self->other_accounts > 0);
gtk_revealer_set_reveal_child (GTK_REVEALER (self->carousel), show_carousel);
gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->users_overlay));
}
static gint
sort_users (gconstpointer a, gconstpointer b)
{
ActUser *ua, *ub;
gchar *name1, *name2;
gint result;
ua = ACT_USER (a);
ub = ACT_USER (b);
/* Make sure the current user is shown first */
if (act_user_get_uid (ua) == getuid ()) {
result = -G_MAXINT32;
}
else if (act_user_get_uid (ub) == getuid ()) {
result = G_MAXINT32;
}
else {
name1 = g_utf8_collate_key (get_real_or_user_name (ua), -1);
name2 = g_utf8_collate_key (get_real_or_user_name (ub), -1);
result = strcmp (name1, name2);
g_free (name1);
g_free (name2);
}
return result;
}
static void
reload_users (CcUserPanel *self, ActUser *selected_user)
{
ActUser *user;
GSList *list, *l;
CcCarouselItem *item = NULL;
GtkSettings *settings;
gboolean animations;
guint users_count;
settings = gtk_widget_get_settings (GTK_WIDGET (self->carousel));
g_object_get (settings, "gtk-enable-animations", &animations, NULL);
g_object_set (settings, "gtk-enable-animations", FALSE, NULL);
cc_carousel_purge_items (self->carousel);
self->other_accounts = 0;
list = act_user_manager_list_users (self->um);
users_count = g_slist_length (list);
g_debug ("Got %d users\n", users_count);
list = g_slist_sort (list, (GCompareFunc) sort_users);
for (l = list; l; l = l->next) {
user = l->data;
g_debug ("adding user %s\n", get_real_or_user_name (user));
user_added (self, user);
}
g_slist_free (list);
if (cc_carousel_get_item_count (self->carousel) == 0)
gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->no_users_box));
if (self->other_accounts == 0)
gtk_revealer_set_reveal_child (GTK_REVEALER (self->carousel), FALSE);
if (selected_user)
item = cc_carousel_find_item (self->carousel, selected_user, user_compare);
cc_carousel_select_item (self->carousel, item);
g_object_set (settings, "gtk-enable-animations", animations, NULL);
#ifdef HAVE_MALCONTENT
/* Parental Controls row not to be shown for single user setups. */
gtk_widget_set_visible (GTK_WIDGET (self->parental_controls_row), users_count > 1);
#endif
}
static gint
user_compare (gconstpointer i,
gconstpointer u)
{
CcCarouselItem *item;
ActUser *user;
gint uid_a, uid_b;
gint result;
item = (CcCarouselItem *) i;
user = ACT_USER (u);
uid_a = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "uid"));
uid_b = act_user_get_uid (user);
result = uid_a - uid_b;
return result;
}
static void
user_changed (CcUserPanel *self, ActUser *user)
{
reload_users (self, self->selected_user);
}
static void
add_user (CcUserPanel *self)
{
CcAddUserDialog *dialog;
g_autoptr(GdkPixbuf) pixbuf = NULL;
GtkWindow *toplevel;
ActUser *user;
dialog = cc_add_user_dialog_new (self->permission);
toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel);
gtk_dialog_run (GTK_DIALOG (dialog));
user = cc_add_user_dialog_get_user (dialog);
if (user != NULL) {
set_default_avatar (user);
reload_users (self, user);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
}
static void
delete_user_done (ActUserManager *manager,
GAsyncResult *res,
CcUserPanel *self)
{
GError *error;
error = NULL;
if (!act_user_manager_delete_user_finish (manager, res, &error)) {
if (!g_error_matches (error, ACT_USER_MANAGER_ERROR,
ACT_USER_MANAGER_ERROR_PERMISSION_DENIED))
show_error_dialog (self, _("Failed to delete user"), error);
g_error_free (error);
}
}
static void
delete_user_response (CcUserPanel *self,
gint response_id,
GtkWidget *dialog)
{
ActUser *user;
gboolean remove_files;
gtk_widget_destroy (dialog);
if (response_id == GTK_RESPONSE_CANCEL) {
return;
}
else if (response_id == GTK_RESPONSE_NO) {
remove_files = TRUE;
}
else {
remove_files = FALSE;
}
user = get_selected_user (self);
/* remove autologin */
if (act_user_get_automatic_login (user)) {
act_user_set_automatic_login (user, FALSE);
}
act_user_manager_delete_user_async (self->um,
user,
remove_files,
NULL,
(GAsyncReadyCallback)delete_user_done,
self);
}
static void
enterprise_user_revoked (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
AsyncDeleteData *data = user_data;
CcUserPanel *self = data->self;
CcRealmCommon *common = CC_REALM_COMMON (source);
GError *error = NULL;
if (g_cancellable_is_cancelled (data->cancellable)) {
async_delete_data_free (data);
return;
}
cc_realm_common_call_change_login_policy_finish (common, result, &error);
if (error != NULL) {
show_error_dialog (self, _("Failed to revoke remotely managed user"), error);
g_error_free (error);
}
async_delete_data_free (data);
}
static CcRealmCommon *
find_matching_realm (CcRealmManager *realm_manager, const gchar *login)
{
CcRealmCommon *common = NULL;
GList *realms, *l;
realms = cc_realm_manager_get_realms (realm_manager);
for (l = realms; l != NULL; l = g_list_next (l)) {
const gchar * const *permitted_logins;
gint i;
common = cc_realm_object_get_common (l->data);
if (common == NULL)
continue;
permitted_logins = cc_realm_common_get_permitted_logins (common);
for (i = 0; permitted_logins[i] != NULL; i++) {
if (g_strcmp0 (permitted_logins[i], login) == 0)
break;
}
if (permitted_logins[i] != NULL)
break;
g_clear_object (&common);
}
g_list_free_full (realms, g_object_unref);
return common;
}
static void
realm_manager_found (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
AsyncDeleteData *data = user_data;
CcUserPanel *self = data->self;
CcRealmCommon *common;
CcRealmManager *realm_manager;
const gchar *add[1];
const gchar *remove[2];
GVariant *options;
GError *error = NULL;
if (g_cancellable_is_cancelled (data->cancellable)) {
async_delete_data_free (data);
return;
}
realm_manager = cc_realm_manager_new_finish (result, &error);
if (error != NULL) {
show_error_dialog (self, _("Failed to revoke remotely managed user"), error);
g_error_free (error);
async_delete_data_free (data);
return;
}
/* Find matching realm */
common = find_matching_realm (realm_manager, data->login);
if (common == NULL) {
/* The realm was probably left */
async_delete_data_free (data);
return;
}
/* Remove the user from permitted logins */
g_debug ("Denying future login for: %s", data->login);
add[0] = NULL;
remove[0] = data->login;
remove[1] = NULL;
options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
cc_realm_common_call_change_login_policy (common, "",
add, remove, options,
data->cancellable,
enterprise_user_revoked,
data);
g_object_unref (common);
}
static void
enterprise_user_uncached (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
AsyncDeleteData *data = user_data;
CcUserPanel *self = data->self;
ActUserManager *manager = ACT_USER_MANAGER (source);
GError *error = NULL;
if (g_cancellable_is_cancelled (data->cancellable)) {
async_delete_data_free (data);
return;
}
act_user_manager_uncache_user_finish (manager, res, &error);
if (error == NULL) {
/* Find realm manager */
cc_realm_manager_new (cc_panel_get_cancellable (CC_PANEL (self)), realm_manager_found, data);
}
else {
show_error_dialog (self, _("Failed to revoke remotely managed user"), error);
g_error_free (error);
async_delete_data_free (data);
}
}
static void
delete_enterprise_user_response (CcUserPanel *self,
gint response_id,
GtkWidget *dialog)
{
AsyncDeleteData *data;
ActUser *user;
gtk_widget_destroy (dialog);
if (response_id != GTK_RESPONSE_ACCEPT) {
return;
}
user = get_selected_user (self);
data = g_slice_new (AsyncDeleteData);
data->self = g_object_ref (self);
data->cancellable = g_object_ref (cc_panel_get_cancellable (CC_PANEL (self)));
data->login = g_strdup (act_user_get_user_name (user));
/* Uncache the user account from the accountsservice */
g_debug ("Uncaching remote user: %s", data->login);
act_user_manager_uncache_user_async (self->um, data->login,
data->cancellable,
enterprise_user_uncached,
data);
}
static void
delete_user (CcUserPanel *self)
{
ActUser *user;
GtkWidget *dialog;
user = get_selected_user (self);
if (user == NULL) {
return;
}
else if (act_user_get_uid (user) == getuid ()) {
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
0,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
_("You cannot delete your own account."));
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
}
else if (act_user_is_logged_in_anywhere (user)) {
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
0,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CLOSE,
_("%s is still logged in"),
get_real_or_user_name (user));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("Deleting a user while they are logged in can leave the system in an inconsistent state."));
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
}
else if (act_user_is_local_account (user)) {
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
0,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
_("Do you want to keep %ss files?"),
get_real_or_user_name (user));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("It is possible to keep the home directory, mail spool and temporary files around when deleting a user account."));
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
_("_Delete Files"), GTK_RESPONSE_NO,
_("_Keep Files"), GTK_RESPONSE_YES,
_("_Cancel"), GTK_RESPONSE_CANCEL,
NULL);
gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");
g_signal_connect_object (dialog, "response",
G_CALLBACK (delete_user_response), self, G_CONNECT_SWAPPED);
}
else {
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
0,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
_("Are you sure you want to revoke remotely managed %ss account?"),
get_real_or_user_name (user));
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
_("_Delete"), GTK_RESPONSE_ACCEPT,
_("_Cancel"), GTK_RESPONSE_CANCEL,
NULL);
gtk_window_set_icon_name (GTK_WINDOW (dialog), "system-users");
g_signal_connect_object (dialog, "response",
G_CALLBACK (delete_enterprise_user_response), self, G_CONNECT_SWAPPED);
}
g_signal_connect (dialog, "close",
G_CALLBACK (gtk_widget_destroy), NULL);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_present (GTK_WINDOW (dialog));
}
static const gchar *
get_invisible_text (void)
{
GtkWidget *entry;
gunichar invisible_char;
static gchar invisible_text[40];
gchar *p;
gint i;
entry = gtk_entry_new ();
invisible_char = gtk_entry_get_invisible_char (GTK_ENTRY (entry));
if (invisible_char == 0)
invisible_char = 0x2022;
g_object_ref_sink (entry);
g_object_unref (entry);
/* five bullets */
p = invisible_text;
for (i = 0; i < 5; i++)
p += g_unichar_to_utf8 (invisible_char, p);
*p = 0;
return invisible_text;
}
static const gchar *
get_password_mode_text (ActUser *user)
{
const gchar *text;
if (act_user_get_locked (user)) {
text = C_("Password mode", "Account disabled");
}
else {
switch (act_user_get_password_mode (user)) {
case ACT_USER_PASSWORD_MODE_REGULAR:
text = get_invisible_text ();
break;
case ACT_USER_PASSWORD_MODE_SET_AT_LOGIN:
text = C_("Password mode", "To be set at next login");
break;
case ACT_USER_PASSWORD_MODE_NONE:
text = C_("Password mode", "None");
break;
default:
g_assert_not_reached ();
}
}
return text;
}
static void
autologin_changed (CcUserPanel *self)
{
gboolean active;
ActUser *user;
active = gtk_switch_get_active (self->autologin_switch);
user = get_selected_user (self);
if (active != act_user_get_automatic_login (user)) {
act_user_set_automatic_login (user, active);
if (act_user_get_automatic_login (user)) {
GSList *list;
GSList *l;
list = act_user_manager_list_users (self->um);
for (l = list; l != NULL; l = l->next) {
ActUser *u = l->data;
if (act_user_get_uid (u) != act_user_get_uid (user)) {
act_user_set_automatic_login (user, FALSE);
}
}
g_slist_free (list);
}
}
}
static gchar *
get_login_time_text (ActUser *user)
{
gchar *text, *date_str, *time_str;
GDateTime *date_time;
gint64 time;
time = act_user_get_login_time (user);
if (act_user_is_logged_in (user)) {
text = g_strdup (_("Logged in"));
}
else if (time > 0) {
date_time = g_date_time_new_from_unix_local (time);
date_str = cc_util_get_smart_date (date_time);
/* Translators: This is a time format string in the style of "22:58".
It indicates a login time which follows a date. */
time_str = g_date_time_format (date_time, C_("login date-time", "%k:%M"));
/* Translators: This indicates a login date-time.
The first %s is a date, and the second %s a time. */
text = g_strdup_printf(C_("login date-time", "%s, %s"), date_str, time_str);
g_date_time_unref (date_time);
g_free (date_str);
g_free (time_str);
}
else {
text = g_strdup ("");
}
return text;
}
static gboolean
get_autologin_possible (ActUser *user)
{
gboolean locked;
gboolean set_password_at_login;
locked = act_user_get_locked (user);
set_password_at_login = (act_user_get_password_mode (user) == ACT_USER_PASSWORD_MODE_SET_AT_LOGIN);
return !(locked || set_password_at_login);
}
static void on_permission_changed (CcUserPanel *self);
static void full_name_edit_button_toggled (CcUserPanel *self);
#ifdef HAVE_MALCONTENT
static gboolean
is_parental_controls_enabled_for_user (ActUser *user)
{
g_autoptr(MctManager) manager = NULL;
g_autoptr(MctAppFilter) app_filter = NULL;
g_autoptr(GDBusConnection) system_bus = NULL;
g_autoptr(GError) error = NULL;
/* FIXME: should become asynchronous */
system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (system_bus == NULL) {
g_warning ("Error getting system bus while trying to show user details: %s", error->message);
return FALSE;
}
manager = mct_manager_new (system_bus);
app_filter = mct_manager_get_app_filter (manager,
act_user_get_uid (user),
MCT_GET_APP_FILTER_FLAGS_NONE,
NULL,
&error);
if (error) {
if (!g_error_matches (error, MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_DISABLED))
g_warning ("Error retrieving app filter for user %s: %s",
act_user_get_user_name (user),
error->message);
return FALSE;
}
return mct_app_filter_is_enabled (app_filter);
}
#endif
static void
update_fingerprint_row_state (CcUserPanel *self, GParamSpec *spec, CcFingerprintManager *fingerprint_manager)
{
CcFingerprintState state = cc_fingerprint_manager_get_state (fingerprint_manager);
if (state != CC_FINGERPRINT_STATE_UPDATING) {
gtk_widget_set_visible (GTK_WIDGET (self->fingerprint_row),
state != CC_FINGERPRINT_STATE_NONE);
}
gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row),
state != CC_FINGERPRINT_STATE_UPDATING);
if (state == CC_FINGERPRINT_STATE_ENABLED)
gtk_label_set_text (self->fingerprint_state_label, _("Enabled"));
else if (state == CC_FINGERPRINT_STATE_DISABLED)
gtk_label_set_text (self->fingerprint_state_label, _("Disabled"));
}
static void
show_user (ActUser *user, CcUserPanel *self)
{
gchar *lang, *text, *name;
gboolean show, enable;
ActUser *current;
self->selected_user = user;
cc_user_image_set_user (self->user_icon_image, user);
cc_user_image_set_user (self->user_icon_image2, user);
cc_avatar_chooser_set_user (self->avatar_chooser, user);
gtk_label_set_label (self->full_name_label, act_user_get_real_name (user));
gtk_entry_set_text (self->full_name_entry, act_user_get_real_name (user));
gtk_widget_set_tooltip_text (GTK_WIDGET (self->full_name_label), act_user_get_user_name (user));
g_signal_handlers_block_by_func (self->full_name_edit_button, full_name_edit_button_toggled, self);
gtk_stack_set_visible_child (self->full_name_stack, GTK_WIDGET (self->full_name_label));
gtk_toggle_button_set_active (self->full_name_edit_button, FALSE);
g_signal_handlers_unblock_by_func (self->full_name_edit_button, full_name_edit_button_toggled, self);
enable = (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR);
gtk_switch_set_active (self->account_type_switch, enable);
/* Do not show the "Account Type" option when there's a single user account. */
show = (self->other_accounts != 0);
gtk_widget_set_visible (GTK_WIDGET (self->account_settings_box), show);
gtk_label_set_label (self->password_button_label, get_password_mode_text (user));
enable = act_user_is_local_account (user);
gtk_widget_set_sensitive (GTK_WIDGET (self->password_button_label), enable);
g_signal_handlers_block_by_func (self->autologin_switch, autologin_changed, self);
gtk_switch_set_active (self->autologin_switch, act_user_get_automatic_login (user));
g_signal_handlers_unblock_by_func (self->autologin_switch, autologin_changed, self);
gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_switch), get_autologin_possible (user));
name = NULL;
lang = g_strdup (act_user_get_language (user));
if (lang && *lang != '\0') {
name = gnome_get_language_from_locale (lang, NULL);
} else {
name = g_strdup ("");
}
gtk_label_set_label (self->language_button_label, name);
g_free (lang);
g_free (name);
/* Fingerprint: show when self, local, enabled, and possible */
show = (act_user_get_uid (user) == getuid() &&
act_user_is_local_account (user) &&
(self->login_screen_settings &&
g_settings_get_boolean (self->login_screen_settings,
"enable-fingerprint-authentication")));
if (show) {
if (!self->fingerprint_manager) {
self->fingerprint_manager = cc_fingerprint_manager_new (user);
g_signal_connect_object (self->fingerprint_manager,
"notify::state",
G_CALLBACK (update_fingerprint_row_state),
self, G_CONNECT_SWAPPED);
}
update_fingerprint_row_state (self, NULL, self->fingerprint_manager);
} else {
gtk_widget_set_visible (GTK_WIDGET (self->fingerprint_row), FALSE);
}
/* Autologin: show when local account */
show = act_user_is_local_account (user);
gtk_widget_set_visible (GTK_WIDGET (self->autologin_row), show);
#ifdef HAVE_MALCONTENT
/* Parental Controls: Unavailable if user is admin */
if (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR) {
gtk_widget_hide (GTK_WIDGET (self->parental_control_go_next));
/* TRANSLATORS: Status of Parental Controls setup */
gtk_label_set_text (self->parental_controls_button_label, _("Unavailable"));
} else {
if (is_parental_controls_enabled_for_user (user))
/* TRANSLATORS: Status of Parental Controls setup */
gtk_label_set_text (self->parental_controls_button_label, _("Enabled"));
else
/* TRANSLATORS: Status of Parental Controls setup */
gtk_label_set_text (self->parental_controls_button_label, _("Disabled"));
gtk_widget_show (GTK_WIDGET (self->parental_control_go_next));
}
#endif
/* Language: do not show for current user */
show = act_user_get_uid (user) != getuid();
gtk_widget_set_visible (GTK_WIDGET (self->language_row), show);
/* Last login: show when administrator or current user */
current = act_user_manager_get_user_by_id (self->um, getuid ());
show = act_user_get_uid (user) == getuid () ||
act_user_get_account_type (current) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
if (show) {
text = get_login_time_text (user);
gtk_label_set_label (self->last_login_button_label, text);
g_free (text);
}
gtk_widget_set_visible (GTK_WIDGET (self->last_login_row), show);
enable = act_user_get_login_history (user) != NULL;
gtk_widget_set_sensitive (GTK_WIDGET (self->last_login_row), enable);
if (self->permission != NULL)
on_permission_changed (self);
}
static void
full_name_entry_activate (CcUserPanel *self)
{
const gchar *text;
ActUser *user;
user = get_selected_user (self);
text = gtk_entry_get_text (self->full_name_entry);
if (g_strcmp0 (text, act_user_get_real_name (user)) != 0 &&
is_valid_name (text)) {
act_user_set_real_name (user, text);
}
gtk_toggle_button_set_active (self->full_name_edit_button, FALSE);
}
static void
full_name_edit_button_toggled (CcUserPanel *self)
{
if (gtk_stack_get_visible_child (self->full_name_stack) == GTK_WIDGET (self->full_name_label)) {
gtk_stack_set_visible_child (self->full_name_stack, GTK_WIDGET (self->full_name_entry));
gtk_widget_grab_focus (GTK_WIDGET (self->full_name_entry));
} else {
gtk_stack_set_visible_child (self->full_name_stack, GTK_WIDGET (self->full_name_label));
full_name_entry_activate (self);
}
}
static gboolean
full_name_entry_key_press_cb (CcUserPanel *self,
GdkEvent *event)
{
GdkEventKey *key = (GdkEventKey *)event;
if (key->keyval == GDK_KEY_Escape) {
gtk_entry_set_text (self->full_name_entry, act_user_get_real_name (self->selected_user));
full_name_entry_activate (self);
return TRUE;
}
return FALSE;
}
static void
account_type_changed (CcUserPanel *self)
{
ActUser *user;
gboolean self_selected;
gboolean is_admin;
ActUserAccountType account_type;
user = get_selected_user (self);
self_selected = act_user_get_uid (user) == geteuid ();
is_admin = gtk_switch_get_active (self->account_type_switch);
account_type = is_admin ? ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR : ACT_USER_ACCOUNT_TYPE_STANDARD;
if (account_type != act_user_get_account_type (user)) {
act_user_set_account_type (user, account_type);
if (self_selected)
show_restart_notification (self, NULL);
}
}
static void
dismiss_notification (CcUserPanel *self)
{
gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
}
static void
restart_now (CcUserPanel *self)
{
GDBusConnection *bus;
gtk_revealer_set_reveal_child (self->notification_revealer, FALSE);
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_dbus_connection_call (bus,
"org.gnome.SessionManager",
"/org/gnome/SessionManager",
"org.gnome.SessionManager",
"Logout",
g_variant_new ("(u)", 0),
NULL, 0, G_MAXINT,
NULL, NULL, NULL);
g_object_unref (bus);
}
static void
show_restart_notification (CcUserPanel *self, const gchar *locale)
{
locale_t current_locale;
locale_t new_locale;
if (locale) {
new_locale = newlocale (LC_MESSAGES_MASK, locale, (locale_t) 0);
if (new_locale == (locale_t) 0)
g_warning ("Failed to create locale %s: %s", locale, g_strerror (errno));
else
current_locale = uselocale (new_locale);
}
gtk_revealer_set_reveal_child (self->notification_revealer, TRUE);
if (locale && new_locale != (locale_t) 0) {
uselocale (current_locale);
freelocale (new_locale);
}
}
static void
language_response (CcUserPanel *self,
gint response_id,
GtkDialog *dialog)
{
ActUser *user;
const gchar *lang, *account_language;
if (response_id != GTK_RESPONSE_OK) {
gtk_widget_hide (GTK_WIDGET (dialog));
return;
}
user = get_selected_user (self);
account_language = act_user_get_language (user);
lang = cc_language_chooser_get_language (CC_LANGUAGE_CHOOSER (dialog));
if (lang) {
g_autofree gchar *name = NULL;
if (g_strcmp0 (lang, account_language) != 0) {
act_user_set_language (user, lang);
}
name = gnome_get_language_from_locale (lang, NULL);
gtk_label_set_label (self->language_button_label, name);
}
gtk_widget_hide (GTK_WIDGET (dialog));
}
static void
change_language (CcUserPanel *self)
{
const gchar *current_language;
ActUser *user;
user = get_selected_user (self);
current_language = act_user_get_language (user);
if (self->language_chooser) {
cc_language_chooser_clear_filter (self->language_chooser);
cc_language_chooser_set_language (self->language_chooser, NULL);
}
else {
self->language_chooser = cc_language_chooser_new ();
gtk_window_set_transient_for (GTK_WINDOW (self->language_chooser),
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))));
g_signal_connect_object (self->language_chooser, "response",
G_CALLBACK (language_response), self, G_CONNECT_SWAPPED);
g_signal_connect (self->language_chooser, "delete-event",
G_CALLBACK (gtk_widget_hide_on_delete), NULL);
gdk_window_set_cursor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (self))), NULL);
}
if (current_language && *current_language != '\0')
cc_language_chooser_set_language (self->language_chooser, current_language);
gtk_window_present (GTK_WINDOW (self->language_chooser));
}
static void
change_password (CcUserPanel *self)
{
ActUser *user;
CcPasswordDialog *dialog;
GtkWindow *parent;
user = get_selected_user (self);
dialog = cc_password_dialog_new (user);
parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
}
static void
change_fingerprint (CcUserPanel *self)
{
ActUser *user;
GtkWindow *top_level;
CcFingerprintDialog *dialog;
user = get_selected_user (self);
top_level = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
g_assert (g_strcmp0 (g_get_user_name (), act_user_get_user_name (user)) == 0);
dialog = cc_fingerprint_dialog_new (self->fingerprint_manager);
gtk_window_set_transient_for (GTK_WINDOW (dialog), top_level);
gtk_widget_show (GTK_WIDGET (dialog));
}
static void
show_history (CcUserPanel *self)
{
CcLoginHistoryDialog *dialog;
ActUser *user;
GtkWindow *parent;
gint parent_width;
user = get_selected_user (self);
dialog = cc_login_history_dialog_new (user);
parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
gtk_window_get_size (parent, &parent_width, NULL);
gtk_window_set_default_size (GTK_WINDOW (dialog), parent_width * 0.6, -1);
gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
}
#ifdef HAVE_MALCONTENT
static void
spawn_malcontent_control (CcUserPanel *self)
{
ActUser *user;
user = get_selected_user (self);
/* no-op if the user is administrator */
if (act_user_get_account_type (user) != ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR) {
const gchar *argv[] = {
"malcontent-control",
#ifdef HAVE_MALCONTENT_0_10
"--user",
act_user_get_user_name (user),
#endif /* HAVE_MALCONTENT_0_10 */
NULL
};
g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
}
}
#endif
static void
activate_row (GtkListBox *box, GtkListBoxRow *row, CcUserPanel *self)
{
if (!gtk_widget_get_sensitive (GTK_WIDGET (row)))
return;
if (row == self->language_row) {
change_language (self);
} else if (row == self->password_row) {
change_password (self);
} else if (row == self->fingerprint_row) {
change_fingerprint (self);
} else if (row == self->last_login_row) {
show_history (self);
}
#ifdef HAVE_MALCONTENT
if (row == self->parental_controls_row) {
spawn_malcontent_control (self);
}
#endif
}
static void
users_loaded (CcUserPanel *self)
{
GtkWidget *dialog;
if (act_user_manager_no_service (self->um)) {
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
GTK_DIALOG_MODAL,
GTK_MESSAGE_OTHER,
GTK_BUTTONS_CLOSE,
_("Failed to contact the accounts service"));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
_("Please make sure that the AccountService is installed and enabled."));
g_signal_connect (dialog, "response",
G_CALLBACK (gtk_widget_destroy),
NULL);
gtk_widget_show (dialog);
gtk_widget_set_sensitive (GTK_WIDGET (self->accounts_box), FALSE);
}
g_signal_connect_object (self->um, "user-changed", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
g_signal_connect_object (self->um, "user-is-logged-in-changed", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
g_signal_connect_object (self->um, "user-added", G_CALLBACK (user_added), self, G_CONNECT_SWAPPED);
g_signal_connect_object (self->um, "user-removed", G_CALLBACK (user_changed), self, G_CONNECT_SWAPPED);
reload_users (self, NULL);
}
static void
add_unlock_tooltip (GtkWidget *widget)
{
gchar *names[3];
GIcon *icon;
names[0] = "changes-allow-symbolic";
names[1] = "changes-allow";
names[2] = NULL;
icon = (GIcon *)g_themed_icon_new_from_names (names, -1);
setup_tooltip_with_embedded_icon (widget,
/* Translator comments:
* We split the line in 2 here to "make it look good", as there's
* no good way to do this in GTK+ for tooltips. See:
* https://bugzilla.gnome.org/show_bug.cgi?id=657168 */
_("To make changes,\nclick the * icon first"),
"*",
icon);
g_object_unref (icon);
g_signal_connect (widget, "button-release-event",
G_CALLBACK (show_tooltip_now), NULL);
}
static void
remove_unlock_tooltip (GtkWidget *widget)
{
setup_tooltip_with_embedded_icon (widget, NULL, NULL, NULL);
g_signal_handlers_disconnect_by_func (widget,
G_CALLBACK (show_tooltip_now), NULL);
}
static guint
get_num_active_admin (ActUserManager *um)
{
GSList *list;
GSList *l;
guint num_admin = 0;
list = act_user_manager_list_users (um);
for (l = list; l != NULL; l = l->next) {
ActUser *u = l->data;
if (act_user_get_account_type (u) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR && !act_user_get_locked (u)) {
num_admin++;
}
}
g_slist_free (list);
return num_admin;
}
static gboolean
would_demote_only_admin (ActUser *user)
{
ActUserManager *um = act_user_manager_get_default ();
/* Prevent the user from demoting the only admin account.
* Returns TRUE when user is an administrator and there is only
* one enabled administrator. */
if (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_STANDARD ||
act_user_get_locked (user))
return FALSE;
if (get_num_active_admin (um) > 1)
return FALSE;
return TRUE;
}
static void
on_permission_changed (CcUserPanel *self)
{
gboolean is_authorized;
gboolean self_selected;
ActUser *user;
is_authorized = g_permission_get_allowed (G_PERMISSION (self->permission));
gtk_widget_set_sensitive (GTK_WIDGET (self->add_user_button), is_authorized);
user = get_selected_user (self);
if (!user) {
return;
}
self_selected = act_user_get_uid (user) == geteuid ();
gtk_widget_set_sensitive (GTK_WIDGET (self->remove_user_button), is_authorized && !self_selected
&& !would_demote_only_admin (user));
if (is_authorized) {
setup_tooltip_with_embedded_icon (GTK_WIDGET (self->remove_user_button), _("Delete the selected user account"), NULL, NULL);
}
else {
gchar *names[3];
GIcon *icon;
names[0] = "changes-allow-symbolic";
names[1] = "changes-allow";
names[2] = NULL;
icon = (GIcon *)g_themed_icon_new_from_names (names, -1);
setup_tooltip_with_embedded_icon (GTK_WIDGET (self->remove_user_button),
_("To delete the selected user account,\nclick the * icon first"),
"*",
icon);
g_object_unref (icon);
}
if (!act_user_is_local_account (user)) {
gtk_widget_set_sensitive (GTK_WIDGET (self->account_type_row), FALSE);
remove_unlock_tooltip (GTK_WIDGET (self->account_type_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_row), FALSE);
remove_unlock_tooltip (GTK_WIDGET (self->autologin_row));
} else if (is_authorized && act_user_is_local_account (user)) {
if (would_demote_only_admin (user)) {
gtk_widget_set_sensitive (GTK_WIDGET (self->account_type_row), FALSE);
} else {
gtk_widget_set_sensitive (GTK_WIDGET (self->account_type_row), TRUE);
}
remove_unlock_tooltip (GTK_WIDGET (self->account_type_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_row), get_autologin_possible (user));
remove_unlock_tooltip (GTK_WIDGET (self->autologin_row));
}
else {
gtk_widget_set_sensitive (GTK_WIDGET (self->account_type_row), FALSE);
if (would_demote_only_admin (user)) {
remove_unlock_tooltip (GTK_WIDGET (self->account_type_row));
} else {
add_unlock_tooltip (GTK_WIDGET (self->account_type_row));
}
gtk_widget_set_sensitive (GTK_WIDGET (self->autologin_row), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->autologin_row));
}
/* The full name entry: insensitive if remote or not authorized and not self */
if (!act_user_is_local_account (user)) {
gtk_widget_set_sensitive (GTK_WIDGET (self->full_name_edit_button), FALSE);
remove_unlock_tooltip (GTK_WIDGET (self->full_name_stack));
} else if (is_authorized || self_selected) {
gtk_widget_set_sensitive (GTK_WIDGET (self->full_name_edit_button), TRUE);
remove_unlock_tooltip (GTK_WIDGET (self->full_name_stack));
} else {
gtk_widget_set_sensitive (GTK_WIDGET (self->full_name_edit_button), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->full_name_stack));
}
if (is_authorized || self_selected) {
CcFingerprintState fingerprint_state = CC_FINGERPRINT_STATE_NONE;
if (self->fingerprint_manager)
fingerprint_state = cc_fingerprint_manager_get_state (self->fingerprint_manager);
gtk_stack_set_visible_child (self->user_icon_stack, GTK_WIDGET (self->user_icon_button));
gtk_widget_set_sensitive (GTK_WIDGET (self->language_row), TRUE);
remove_unlock_tooltip (GTK_WIDGET (self->language_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->password_row), TRUE);
remove_unlock_tooltip (GTK_WIDGET (self->password_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row),
fingerprint_state != CC_FINGERPRINT_STATE_UPDATING);
remove_unlock_tooltip (GTK_WIDGET (self->fingerprint_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->last_login_row), TRUE);
remove_unlock_tooltip (GTK_WIDGET (self->last_login_row));
#ifdef HAVE_MALCONTENT
gtk_widget_set_sensitive (GTK_WIDGET (self->parental_controls_row), TRUE);
remove_unlock_tooltip (GTK_WIDGET (self->parental_controls_row));
#endif
}
else {
gtk_stack_set_visible_child (self->user_icon_stack, GTK_WIDGET (self->user_icon_image));
gtk_widget_set_sensitive (GTK_WIDGET (self->language_row), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->language_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->password_row), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->password_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->fingerprint_row));
gtk_widget_set_sensitive (GTK_WIDGET (self->last_login_row), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->last_login_row));
#ifdef HAVE_MALCONTENT
gtk_widget_set_sensitive (GTK_WIDGET (self->parental_controls_row), FALSE);
add_unlock_tooltip (GTK_WIDGET (self->parental_controls_row));
#endif
}
}
static void
setup_main_window (CcUserPanel *self)
{
GIcon *icon;
GError *error = NULL;
gchar *names[3];
gboolean loaded;
self->other_accounts = 0;
add_unlock_tooltip (GTK_WIDGET (self->user_icon_image));
self->permission = (GPermission *)polkit_permission_new_sync (USER_ACCOUNTS_PERMISSION, NULL, NULL, &error);
if (self->permission != NULL) {
g_signal_connect_object (self->permission, "notify",
G_CALLBACK (on_permission_changed), self, G_CONNECT_SWAPPED);
on_permission_changed (self);
} else {
g_warning ("Cannot create '%s' permission: %s", USER_ACCOUNTS_PERMISSION, error->message);
g_error_free (error);
}
names[0] = "changes-allow-symbolic";
names[1] = "changes-allow";
names[2] = NULL;
icon = (GIcon *)g_themed_icon_new_from_names (names, -1);
setup_tooltip_with_embedded_icon (GTK_WIDGET (self->remove_user_button),
_("To delete the selected user account,\nclick the * icon first"),
"*",
icon);
g_object_unref (icon);
g_object_get (self->um, "is-loaded", &loaded, NULL);
if (loaded)
users_loaded (self);
else
g_signal_connect_object (self->um, "notify::is-loaded", G_CALLBACK (users_loaded), self, G_CONNECT_SWAPPED);
gtk_list_box_set_header_func (self->account_settings_listbox,
cc_list_box_update_header_func,
NULL, NULL);
gtk_list_box_set_header_func (self->authentication_and_login_listbox,
cc_list_box_update_header_func,
NULL, NULL);
}
static GSettings *
settings_or_null (const gchar *schema)
{
GSettingsSchemaSource *source = NULL;
gchar **non_relocatable = NULL;
gchar **relocatable = NULL;
GSettings *settings = NULL;
source = g_settings_schema_source_get_default ();
if (!source)
return NULL;
g_settings_schema_source_list_schemas (source, TRUE, &non_relocatable, &relocatable);
if (g_strv_contains ((const gchar * const *)non_relocatable, schema) ||
g_strv_contains ((const gchar * const *)relocatable, schema))
settings = g_settings_new (schema);
g_strfreev (non_relocatable);
g_strfreev (relocatable);
return settings;
}
static void
cc_user_panel_constructed (GObject *object)
{
CcUserPanel *self = CC_USER_PANEL (object);
CcShell *shell;
G_OBJECT_CLASS (cc_user_panel_parent_class)->constructed (object);
shell = cc_panel_get_shell (CC_PANEL (self));
cc_shell_embed_widget_in_header (shell, GTK_WIDGET (self->add_user_button), GTK_POS_RIGHT);
cc_permission_infobar_set_permission (self->permission_infobar, self->permission);
cc_permission_infobar_set_title (self->permission_infobar, _("Unlock to Add Users and Change Settings"));
}
static void
cc_user_panel_init (CcUserPanel *self)
{
volatile GType type G_GNUC_UNUSED;
GtkCssProvider *provider;
g_resources_register (cc_user_accounts_get_resource ());
/* register types that the builder might need */
type = cc_user_image_get_type ();
type = cc_carousel_get_type ();
type = cc_permission_infobar_get_type ();
gtk_widget_init_template (GTK_WIDGET (self));
self->um = act_user_manager_get_default ();
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/user-accounts/user-accounts-dialog.css");
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
self->login_screen_settings = settings_or_null ("org.gnome.login-screen");
self->avatar_chooser = cc_avatar_chooser_new (GTK_WIDGET (self->user_icon_button));
setup_main_window (self);
}
static void
cc_user_panel_dispose (GObject *object)
{
CcUserPanel *self = CC_USER_PANEL (object);
g_clear_object (&self->selected_user);
g_clear_object (&self->login_screen_settings);
g_clear_pointer ((GtkWidget **)&self->language_chooser, gtk_widget_destroy);
g_clear_object (&self->permission);
G_OBJECT_CLASS (cc_user_panel_parent_class)->dispose (object);
}
static const char *
cc_user_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/user-accounts";
}
static void
cc_user_panel_class_init (CcUserPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
object_class->dispose = cc_user_panel_dispose;
object_class->constructed = cc_user_panel_constructed;
panel_class->get_help_uri = cc_user_panel_get_help_uri;
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/user-accounts/cc-user-panel.ui");
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, accounts_box);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_settings_box);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_settings_listbox);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, authentication_and_login_listbox);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_type_row);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, account_type_switch);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, add_user_button);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, autologin_row);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, autologin_switch);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, carousel);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, fingerprint_state_label);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, fingerprint_row);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_stack);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_label);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_edit_button);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, full_name_entry);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, language_button_label);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, language_row);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, last_login_button_label);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, last_login_row);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, no_users_box);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, notification_revealer);
#ifdef HAVE_MALCONTENT
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, parental_controls_button_label);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, parental_control_go_next);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, parental_controls_row);
#endif
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, password_button_label);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, password_row);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, permission_infobar);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, remove_user_button);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, stack);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, user_icon_button);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, user_icon_image);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, user_icon_image2);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, user_icon_stack);
gtk_widget_class_bind_template_child (widget_class, CcUserPanel, users_overlay);
gtk_widget_class_bind_template_callback (widget_class, account_type_changed);
gtk_widget_class_bind_template_callback (widget_class, activate_row);
gtk_widget_class_bind_template_callback (widget_class, add_user);
gtk_widget_class_bind_template_callback (widget_class, autologin_changed);
gtk_widget_class_bind_template_callback (widget_class, change_fingerprint);
gtk_widget_class_bind_template_callback (widget_class, change_language);
gtk_widget_class_bind_template_callback (widget_class, full_name_edit_button_toggled);
gtk_widget_class_bind_template_callback (widget_class, full_name_entry_activate);
gtk_widget_class_bind_template_callback (widget_class, full_name_entry_key_press_cb);
gtk_widget_class_bind_template_callback (widget_class, change_password);
gtk_widget_class_bind_template_callback (widget_class, delete_user);
gtk_widget_class_bind_template_callback (widget_class, dismiss_notification);
gtk_widget_class_bind_template_callback (widget_class, restart_now);
gtk_widget_class_bind_template_callback (widget_class, set_selected_user);
}