Merge branch 'user-controls-without-user' into 'master'
Allow user controls to be used for not-yet-existing users See merge request pwithnall/malcontent!24
This commit is contained in:
commit
33167e7767
|
@ -70,14 +70,14 @@ pkgconfig.generate(libmalcontent_ui,
|
||||||
libraries_private: libmalcontent_ui_private_deps,
|
libraries_private: libmalcontent_ui_private_deps,
|
||||||
)
|
)
|
||||||
|
|
||||||
gnome.generate_gir(libmalcontent_ui,
|
libmalcontent_ui_gir = gnome.generate_gir(libmalcontent_ui,
|
||||||
sources: libmalcontent_ui_sources + libmalcontent_ui_headers + libmalcontent_ui_private_headers,
|
sources: libmalcontent_ui_sources + libmalcontent_ui_headers + libmalcontent_ui_private_headers,
|
||||||
nsversion: libmalcontent_ui_api_version,
|
nsversion: libmalcontent_ui_api_version,
|
||||||
namespace: 'MalcontentUi',
|
namespace: 'MalcontentUi',
|
||||||
symbol_prefix: 'mct_',
|
symbol_prefix: 'mct_',
|
||||||
identifier_prefix: 'Mct',
|
identifier_prefix: 'Mct',
|
||||||
export_packages: 'libmalcontent-ui',
|
export_packages: 'libmalcontent-ui',
|
||||||
includes: ['AccountsService-1.0', 'Gio-2.0', 'GObject-2.0', 'Gtk-3.0'],
|
includes: ['AccountsService-1.0', 'Gio-2.0', 'GObject-2.0', 'Gtk-3.0', libmalcontent_gir[0]],
|
||||||
install: true,
|
install: true,
|
||||||
dependencies: libmalcontent_ui_dep,
|
dependencies: libmalcontent_ui_dep,
|
||||||
)
|
)
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
* - Philip Withnall <withnall@endlessm.com>
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <act/act.h>
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
@ -55,7 +54,7 @@ struct _MctRestrictApplicationsDialog
|
||||||
GtkLabel *description;
|
GtkLabel *description;
|
||||||
|
|
||||||
MctAppFilter *app_filter; /* (owned) (not nullable) */
|
MctAppFilter *app_filter; /* (owned) (not nullable) */
|
||||||
ActUser *user; /* (owned) (nullable) */
|
gchar *user_display_name; /* (owned) (nullable) */
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, GTK_TYPE_DIALOG)
|
G_DEFINE_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, GTK_TYPE_DIALOG)
|
||||||
|
@ -63,10 +62,10 @@ G_DEFINE_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog,
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
PROP_APP_FILTER = 1,
|
PROP_APP_FILTER = 1,
|
||||||
PROP_USER,
|
PROP_USER_DISPLAY_NAME,
|
||||||
} MctRestrictApplicationsDialogProperty;
|
} MctRestrictApplicationsDialogProperty;
|
||||||
|
|
||||||
static GParamSpec *properties[PROP_USER + 1];
|
static GParamSpec *properties[PROP_USER_DISPLAY_NAME + 1];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mct_restrict_applications_dialog_constructed (GObject *obj)
|
mct_restrict_applications_dialog_constructed (GObject *obj)
|
||||||
|
@ -74,7 +73,9 @@ mct_restrict_applications_dialog_constructed (GObject *obj)
|
||||||
MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (obj);
|
MctRestrictApplicationsDialog *self = MCT_RESTRICT_APPLICATIONS_DIALOG (obj);
|
||||||
|
|
||||||
g_assert (self->app_filter != NULL);
|
g_assert (self->app_filter != NULL);
|
||||||
g_assert (self->user == NULL || ACT_IS_USER (self->user));
|
g_assert (self->user_display_name == NULL ||
|
||||||
|
(*self->user_display_name != '\0' &&
|
||||||
|
g_utf8_validate (self->user_display_name, -1, NULL)));
|
||||||
|
|
||||||
G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->constructed (obj);
|
G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->constructed (obj);
|
||||||
}
|
}
|
||||||
|
@ -93,8 +94,8 @@ mct_restrict_applications_dialog_get_property (GObject *object,
|
||||||
g_value_set_boxed (value, self->app_filter);
|
g_value_set_boxed (value, self->app_filter);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_USER:
|
case PROP_USER_DISPLAY_NAME:
|
||||||
g_value_set_object (value, self->user);
|
g_value_set_string (value, self->user_display_name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -116,8 +117,8 @@ mct_restrict_applications_dialog_set_property (GObject *object,
|
||||||
mct_restrict_applications_dialog_set_app_filter (self, g_value_get_boxed (value));
|
mct_restrict_applications_dialog_set_app_filter (self, g_value_get_boxed (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROP_USER:
|
case PROP_USER_DISPLAY_NAME:
|
||||||
mct_restrict_applications_dialog_set_user (self, g_value_get_object (value));
|
mct_restrict_applications_dialog_set_user_display_name (self, g_value_get_string (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -131,7 +132,7 @@ mct_restrict_applications_dialog_dispose (GObject *object)
|
||||||
MctRestrictApplicationsDialog *self = (MctRestrictApplicationsDialog *)object;
|
MctRestrictApplicationsDialog *self = (MctRestrictApplicationsDialog *)object;
|
||||||
|
|
||||||
g_clear_pointer (&self->app_filter, mct_app_filter_unref);
|
g_clear_pointer (&self->app_filter, mct_app_filter_unref);
|
||||||
g_clear_object (&self->user);
|
g_clear_pointer (&self->user_display_name, g_free);
|
||||||
|
|
||||||
G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->dispose (object);
|
G_OBJECT_CLASS (mct_restrict_applications_dialog_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
@ -168,19 +169,22 @@ mct_restrict_applications_dialog_class_init (MctRestrictApplicationsDialogClass
|
||||||
G_PARAM_EXPLICIT_NOTIFY);
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MctRestrictApplicationsDialog:user: (nullable)
|
* MctRestrictApplicationsDialog:user-display-name: (nullable)
|
||||||
*
|
*
|
||||||
* The currently selected user account, or %NULL if no user is selected.
|
* The display name for the currently selected user account, or %NULL if no
|
||||||
|
* user is selected. This will typically be the user’s full name (if known)
|
||||||
|
* or their username.
|
||||||
|
*
|
||||||
|
* If set, it must be valid UTF-8 and non-empty.
|
||||||
*
|
*
|
||||||
* Since: 0.5.0
|
* Since: 0.5.0
|
||||||
*/
|
*/
|
||||||
properties[PROP_USER] =
|
properties[PROP_USER_DISPLAY_NAME] =
|
||||||
g_param_spec_object ("user",
|
g_param_spec_string ("user-display-name",
|
||||||
"User",
|
"User Display Name",
|
||||||
"The currently selected user account, or %NULL if no user is selected.",
|
"The display name for the currently selected user account, or %NULL if no user is selected.",
|
||||||
ACT_TYPE_USER,
|
NULL,
|
||||||
G_PARAM_READWRITE |
|
G_PARAM_READWRITE |
|
||||||
G_PARAM_CONSTRUCT_ONLY |
|
|
||||||
G_PARAM_STATIC_STRINGS |
|
G_PARAM_STATIC_STRINGS |
|
||||||
G_PARAM_EXPLICIT_NOTIFY);
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
@ -201,31 +205,12 @@ mct_restrict_applications_dialog_init (MctRestrictApplicationsDialog *self)
|
||||||
gtk_widget_init_template (GTK_WIDGET (self));
|
gtk_widget_init_template (GTK_WIDGET (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *
|
|
||||||
get_user_display_name (ActUser *user)
|
|
||||||
{
|
|
||||||
const gchar *display_name;
|
|
||||||
|
|
||||||
g_return_val_if_fail (ACT_IS_USER (user), _("unknown"));
|
|
||||||
|
|
||||||
display_name = act_user_get_real_name (user);
|
|
||||||
if (display_name != NULL)
|
|
||||||
return display_name;
|
|
||||||
|
|
||||||
display_name = act_user_get_user_name (user);
|
|
||||||
if (display_name != NULL)
|
|
||||||
return display_name;
|
|
||||||
|
|
||||||
/* Translators: this is the full name for an unknown user account. */
|
|
||||||
return _("unknown");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_description (MctRestrictApplicationsDialog *self)
|
update_description (MctRestrictApplicationsDialog *self)
|
||||||
{
|
{
|
||||||
g_autofree gchar *description = NULL;
|
g_autofree gchar *description = NULL;
|
||||||
|
|
||||||
if (self->user == NULL)
|
if (self->user_display_name == NULL)
|
||||||
{
|
{
|
||||||
gtk_widget_hide (GTK_WIDGET (self->description));
|
gtk_widget_hide (GTK_WIDGET (self->description));
|
||||||
return;
|
return;
|
||||||
|
@ -233,7 +218,7 @@ update_description (MctRestrictApplicationsDialog *self)
|
||||||
|
|
||||||
/* Translators: the placeholder is a user’s full name */
|
/* Translators: the placeholder is a user’s full name */
|
||||||
description = g_strdup_printf (_("Allow %s to use the following installed applications."),
|
description = g_strdup_printf (_("Allow %s to use the following installed applications."),
|
||||||
get_user_display_name (self->user));
|
self->user_display_name);
|
||||||
gtk_label_set_text (self->description, description);
|
gtk_label_set_text (self->description, description);
|
||||||
gtk_widget_show (GTK_WIDGET (self->description));
|
gtk_widget_show (GTK_WIDGET (self->description));
|
||||||
}
|
}
|
||||||
|
@ -241,7 +226,8 @@ update_description (MctRestrictApplicationsDialog *self)
|
||||||
/**
|
/**
|
||||||
* mct_restrict_applications_dialog_new:
|
* mct_restrict_applications_dialog_new:
|
||||||
* @app_filter: (transfer none): the initial app filter configuration to show
|
* @app_filter: (transfer none): the initial app filter configuration to show
|
||||||
* @user: (transfer none) (nullable): the user to show the app filter for
|
* @user_display_name: (transfer none) (nullable): the display name of the user
|
||||||
|
* to show the app filter for, or %NULL if no user is selected
|
||||||
*
|
*
|
||||||
* Create a new #MctRestrictApplicationsDialog widget.
|
* Create a new #MctRestrictApplicationsDialog widget.
|
||||||
*
|
*
|
||||||
|
@ -250,14 +236,16 @@ update_description (MctRestrictApplicationsDialog *self)
|
||||||
*/
|
*/
|
||||||
MctRestrictApplicationsDialog *
|
MctRestrictApplicationsDialog *
|
||||||
mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
|
mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
|
||||||
ActUser *user)
|
const gchar *user_display_name)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (app_filter != NULL, NULL);
|
g_return_val_if_fail (app_filter != NULL, NULL);
|
||||||
g_return_val_if_fail (user == NULL || ACT_IS_USER (user), NULL);
|
g_return_val_if_fail (user_display_name == NULL ||
|
||||||
|
(*user_display_name != '\0' &&
|
||||||
|
g_utf8_validate (user_display_name, -1, NULL)), NULL);
|
||||||
|
|
||||||
return g_object_new (MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG,
|
return g_object_new (MCT_TYPE_RESTRICT_APPLICATIONS_DIALOG,
|
||||||
"app-filter", app_filter,
|
"app-filter", app_filter,
|
||||||
"user", user,
|
"user-display-name", user_display_name,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,45 +306,50 @@ mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mct_restrict_applications_dialog_get_user:
|
* mct_restrict_applications_dialog_get_user_display_name:
|
||||||
* @self: an #MctRestrictApplicationsDialog
|
* @self: an #MctRestrictApplicationsDialog
|
||||||
*
|
*
|
||||||
* Get the value of #MctRestrictApplicationsDialog:user.
|
* Get the value of #MctRestrictApplicationsDialog:user-display-name.
|
||||||
*
|
*
|
||||||
* Returns: (transfer none) (nullable): the user the dialog is configured for,
|
* Returns: (transfer none) (nullable): the display name of the user the dialog
|
||||||
* or %NULL if unknown
|
* is configured for, or %NULL if unknown
|
||||||
* Since: 0.5.0
|
* Since: 0.5.0
|
||||||
*/
|
*/
|
||||||
ActUser *
|
const gchar *
|
||||||
mct_restrict_applications_dialog_get_user (MctRestrictApplicationsDialog *self)
|
mct_restrict_applications_dialog_get_user_display_name (MctRestrictApplicationsDialog *self)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self), NULL);
|
g_return_val_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self), NULL);
|
||||||
|
|
||||||
return self->user;
|
return self->user_display_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mct_restrict_applications_dialog_set_user:
|
* mct_restrict_applications_dialog_set_user_display_name:
|
||||||
* @self: an #MctRestrictApplicationsDialog
|
* @self: an #MctRestrictApplicationsDialog
|
||||||
* @user: (nullable) (transfer none): the user to configure the dialog for,
|
* @user_display_name: (nullable) (transfer none): the display name of the user
|
||||||
* or %NULL if unknown
|
* to configure the dialog for, or %NULL if unknown
|
||||||
*
|
*
|
||||||
* Set the value of #MctRestrictApplicationsDialog:user.
|
* Set the value of #MctRestrictApplicationsDialog:user-display-name.
|
||||||
*
|
*
|
||||||
* Since: 0.5.0
|
* Since: 0.5.0
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
mct_restrict_applications_dialog_set_user (MctRestrictApplicationsDialog *self,
|
mct_restrict_applications_dialog_set_user_display_name (MctRestrictApplicationsDialog *self,
|
||||||
ActUser *user)
|
const gchar *user_display_name)
|
||||||
{
|
{
|
||||||
g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self));
|
g_return_if_fail (MCT_IS_RESTRICT_APPLICATIONS_DIALOG (self));
|
||||||
g_return_if_fail (user == NULL || ACT_IS_USER (user));
|
g_return_if_fail (user_display_name == NULL ||
|
||||||
|
(*user_display_name != '\0' &&
|
||||||
|
g_utf8_validate (user_display_name, -1, NULL)));
|
||||||
|
|
||||||
if (g_set_object (&self->user, user))
|
if (g_strcmp0 (self->user_display_name, user_display_name) == 0)
|
||||||
{
|
return;
|
||||||
update_description (self);
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER]);
|
g_clear_pointer (&self->user_display_name, g_free);
|
||||||
}
|
self->user_display_name = g_strdup (user_display_name);
|
||||||
|
|
||||||
|
update_description (self);
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_DISPLAY_NAME]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <act/act.h>
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
@ -34,15 +33,15 @@ G_BEGIN_DECLS
|
||||||
G_DECLARE_FINAL_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, MCT, RESTRICT_APPLICATIONS_DIALOG, GtkDialog)
|
G_DECLARE_FINAL_TYPE (MctRestrictApplicationsDialog, mct_restrict_applications_dialog, MCT, RESTRICT_APPLICATIONS_DIALOG, GtkDialog)
|
||||||
|
|
||||||
MctRestrictApplicationsDialog *mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
|
MctRestrictApplicationsDialog *mct_restrict_applications_dialog_new (MctAppFilter *app_filter,
|
||||||
ActUser *user);
|
const gchar *user_display_name);
|
||||||
|
|
||||||
MctAppFilter *mct_restrict_applications_dialog_get_app_filter (MctRestrictApplicationsDialog *self);
|
MctAppFilter *mct_restrict_applications_dialog_get_app_filter (MctRestrictApplicationsDialog *self);
|
||||||
void mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *self,
|
void mct_restrict_applications_dialog_set_app_filter (MctRestrictApplicationsDialog *self,
|
||||||
MctAppFilter *app_filter);
|
MctAppFilter *app_filter);
|
||||||
|
|
||||||
ActUser *mct_restrict_applications_dialog_get_user (MctRestrictApplicationsDialog *self);
|
const gchar *mct_restrict_applications_dialog_get_user_display_name (MctRestrictApplicationsDialog *self);
|
||||||
void mct_restrict_applications_dialog_set_user (MctRestrictApplicationsDialog *self,
|
void mct_restrict_applications_dialog_set_user_display_name (MctRestrictApplicationsDialog *self,
|
||||||
ActUser *user);
|
const gchar *user_display_name);
|
||||||
|
|
||||||
void mct_restrict_applications_dialog_build_app_filter (MctRestrictApplicationsDialog *self,
|
void mct_restrict_applications_dialog_build_app_filter (MctRestrictApplicationsDialog *self,
|
||||||
MctAppFilterBuilder *builder);
|
MctAppFilterBuilder *builder);
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <act/act.h>
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libmalcontent/malcontent.h>
|
#include <libmalcontent/malcontent.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <flatpak.h>
|
#include <flatpak.h>
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <gio/gdesktopappinfo.h>
|
#include <gio/gdesktopappinfo.h>
|
||||||
|
@ -37,6 +38,38 @@
|
||||||
/* The value which we store as an age to indicate that OARS filtering is disabled. */
|
/* The value which we store as an age to indicate that OARS filtering is disabled. */
|
||||||
static const guint32 oars_disabled_age = (guint32) -1;
|
static const guint32 oars_disabled_age = (guint32) -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctUserControls:
|
||||||
|
*
|
||||||
|
* A group of widgets which allow setting the parental controls for a given
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* If #MctUserControls:user is set, the current parental controls settings for
|
||||||
|
* that user will be loaded and displayed, and any changes made via the controls
|
||||||
|
* will be automatically saved for that user (potentially after a short
|
||||||
|
* timeout).
|
||||||
|
*
|
||||||
|
* If #MctUserControls:user is unset (for example, if setting the parental
|
||||||
|
* controls for a user account which hasn’t yet been created), the controls can
|
||||||
|
* be initialised by setting:
|
||||||
|
* * #MctUserControls:app-filter
|
||||||
|
* * #MctUserControls:user-account-type
|
||||||
|
* * #MctUserControls:user-locale
|
||||||
|
* * #MctUserControls:user-display-name
|
||||||
|
*
|
||||||
|
* When #MctUserControls:user is unset, changes made to the parental controls
|
||||||
|
* cannot be saved automatically, and must be queried using
|
||||||
|
* mct_user_controls_build_app_filter(), then saved by the calling code.
|
||||||
|
*
|
||||||
|
* As parental controls are system settings, privileges are needed to view and
|
||||||
|
* edit them (for the current user or for other users). These can be acquired
|
||||||
|
* using polkit. #MctUserControls:permission is used to query the current
|
||||||
|
* permissions for getting/setting parental controls. If it’s %NULL, or if
|
||||||
|
* permissions are not currently granted, the #MctUserControls will be
|
||||||
|
* insensitive.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
struct _MctUserControls
|
struct _MctUserControls
|
||||||
{
|
{
|
||||||
GtkGrid parent_instance;
|
GtkGrid parent_instance;
|
||||||
|
@ -58,11 +91,15 @@ struct _MctUserControls
|
||||||
|
|
||||||
GCancellable *cancellable; /* (owned) */
|
GCancellable *cancellable; /* (owned) */
|
||||||
MctManager *manager; /* (owned) */
|
MctManager *manager; /* (owned) */
|
||||||
MctAppFilter *filter; /* (owned) */
|
MctAppFilter *filter; /* (owned) (nullable) */
|
||||||
guint selected_age; /* @oars_disabled_age to disable OARS */
|
guint selected_age; /* @oars_disabled_age to disable OARS */
|
||||||
|
|
||||||
guint blacklist_apps_source_id;
|
guint blacklist_apps_source_id;
|
||||||
gboolean flushed_on_dispose;
|
gboolean flushed_on_dispose;
|
||||||
|
|
||||||
|
ActUserAccountType user_account_type;
|
||||||
|
gchar *user_locale; /* (nullable) (owned) */
|
||||||
|
gchar *user_display_name; /* (nullable) (owned) */
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean blacklist_apps_cb (gpointer data);
|
static gboolean blacklist_apps_cb (gpointer data);
|
||||||
|
@ -96,14 +133,17 @@ static void on_permission_allowed_cb (GObject *obj,
|
||||||
|
|
||||||
G_DEFINE_TYPE (MctUserControls, mct_user_controls, GTK_TYPE_GRID)
|
G_DEFINE_TYPE (MctUserControls, mct_user_controls, GTK_TYPE_GRID)
|
||||||
|
|
||||||
enum
|
typedef enum
|
||||||
{
|
{
|
||||||
PROP_USER = 1,
|
PROP_USER = 1,
|
||||||
PROP_PERMISSION,
|
PROP_PERMISSION,
|
||||||
N_PROPS
|
PROP_APP_FILTER,
|
||||||
};
|
PROP_USER_ACCOUNT_TYPE,
|
||||||
|
PROP_USER_LOCALE,
|
||||||
|
PROP_USER_DISPLAY_NAME,
|
||||||
|
} MctUserControlsProperty;
|
||||||
|
|
||||||
static GParamSpec *properties [N_PROPS];
|
static GParamSpec *properties[PROP_USER_DISPLAY_NAME + 1];
|
||||||
|
|
||||||
static const GActionEntry actions[] = {
|
static const GActionEntry actions[] = {
|
||||||
{ "set-age", on_set_age_action_activated, "u", NULL, NULL, { 0, }}
|
{ "set-age", on_set_age_action_activated, "u", NULL, NULL, { 0, }}
|
||||||
|
@ -146,13 +186,53 @@ static const gchar * const oars_categories[] =
|
||||||
/* Auxiliary methods */
|
/* Auxiliary methods */
|
||||||
|
|
||||||
static GsContentRatingSystem
|
static GsContentRatingSystem
|
||||||
get_content_rating_system (ActUser *user)
|
get_content_rating_system (MctUserControls *self)
|
||||||
{
|
{
|
||||||
const gchar *user_language;
|
if (self->user_locale == NULL)
|
||||||
|
return GS_CONTENT_RATING_SYSTEM_UNKNOWN;
|
||||||
|
|
||||||
user_language = act_user_get_language (user);
|
return gs_utils_content_rating_system_from_locale (self->user_locale);
|
||||||
|
}
|
||||||
|
|
||||||
return gs_utils_content_rating_system_from_locale (user_language);
|
static const gchar *
|
||||||
|
get_user_locale (ActUser *user)
|
||||||
|
{
|
||||||
|
const gchar *locale;
|
||||||
|
|
||||||
|
g_return_val_if_fail (ACT_IS_USER (user), "C");
|
||||||
|
|
||||||
|
/* accounts-service can return %NULL if loading over D-Bus failed. */
|
||||||
|
locale = act_user_get_language (user);
|
||||||
|
if (locale == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* It can return the empty string if the user uses the system default locale. */
|
||||||
|
if (*locale == '\0')
|
||||||
|
locale = setlocale (LC_MESSAGES, NULL);
|
||||||
|
|
||||||
|
if (locale == NULL || *locale == '\0')
|
||||||
|
locale = "C";
|
||||||
|
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar *
|
||||||
|
get_user_display_name (ActUser *user)
|
||||||
|
{
|
||||||
|
const gchar *display_name;
|
||||||
|
|
||||||
|
g_return_val_if_fail (ACT_IS_USER (user), _("unknown"));
|
||||||
|
|
||||||
|
display_name = act_user_get_real_name (user);
|
||||||
|
if (display_name != NULL)
|
||||||
|
return display_name;
|
||||||
|
|
||||||
|
display_name = act_user_get_user_name (user);
|
||||||
|
if (display_name != NULL)
|
||||||
|
return display_name;
|
||||||
|
|
||||||
|
/* Translators: this is the full name for an unknown user account. */
|
||||||
|
return _("unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -180,12 +260,10 @@ flush_update_blacklisted_apps (MctUserControls *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_app_filter (MctUserControls *self)
|
update_app_filter_from_user (MctUserControls *self)
|
||||||
{
|
{
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
g_clear_pointer (&self->filter, mct_app_filter_unref);
|
|
||||||
|
|
||||||
if (self->user == NULL)
|
if (self->user == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -199,6 +277,7 @@ update_app_filter (MctUserControls *self)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* FIXME: make it asynchronous */
|
/* FIXME: make it asynchronous */
|
||||||
|
g_clear_pointer (&self->filter, mct_app_filter_unref);
|
||||||
self->filter = mct_manager_get_app_filter (self->manager,
|
self->filter = mct_manager_get_app_filter (self->manager,
|
||||||
act_user_get_uid (self->user),
|
act_user_get_uid (self->user),
|
||||||
MCT_MANAGER_GET_VALUE_FLAGS_NONE,
|
MCT_MANAGER_GET_VALUE_FLAGS_NONE,
|
||||||
|
@ -226,7 +305,7 @@ update_categories_from_language (MctUserControls *self)
|
||||||
gsize i;
|
gsize i;
|
||||||
g_autofree gchar *disabled_action = NULL;
|
g_autofree gchar *disabled_action = NULL;
|
||||||
|
|
||||||
rating_system = get_content_rating_system (self->user);
|
rating_system = get_content_rating_system (self);
|
||||||
rating_system_str = gs_content_rating_system_to_str (rating_system);
|
rating_system_str = gs_content_rating_system_to_str (rating_system);
|
||||||
|
|
||||||
g_debug ("Using rating system %s", rating_system_str);
|
g_debug ("Using rating system %s", rating_system_str);
|
||||||
|
@ -306,7 +385,7 @@ update_oars_level (MctUserControls *self)
|
||||||
g_debug ("Effective age for this user: %u; %s", maximum_age,
|
g_debug ("Effective age for this user: %u; %s", maximum_age,
|
||||||
all_categories_unset ? "all categories unset" : "some categories set");
|
all_categories_unset ? "all categories unset" : "some categories set");
|
||||||
|
|
||||||
rating_system = get_content_rating_system (self->user);
|
rating_system = get_content_rating_system (self);
|
||||||
rating_age_category = gs_utils_content_rating_age_to_str (rating_system, maximum_age);
|
rating_age_category = gs_utils_content_rating_age_to_str (rating_system, maximum_age);
|
||||||
|
|
||||||
/* Unrestricted? */
|
/* Unrestricted? */
|
||||||
|
@ -323,7 +402,7 @@ update_allow_app_installation (MctUserControls *self)
|
||||||
gboolean allow_user_installation;
|
gboolean allow_user_installation;
|
||||||
gboolean non_admin_user = TRUE;
|
gboolean non_admin_user = TRUE;
|
||||||
|
|
||||||
if (act_user_get_account_type (self->user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR)
|
if (self->user_account_type == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR)
|
||||||
non_admin_user = FALSE;
|
non_admin_user = FALSE;
|
||||||
|
|
||||||
/* Admins are always allowed to install apps for all users. This behaviour is governed
|
/* Admins are always allowed to install apps for all users. This behaviour is governed
|
||||||
|
@ -334,8 +413,8 @@ update_allow_app_installation (MctUserControls *self)
|
||||||
/* If user is admin, we are done here, bail out. */
|
/* If user is admin, we are done here, bail out. */
|
||||||
if (!non_admin_user)
|
if (!non_admin_user)
|
||||||
{
|
{
|
||||||
g_debug ("User %s is administrator, hiding app installation controls",
|
g_debug ("User ‘%s’ is an administrator, hiding app installation controls",
|
||||||
act_user_get_user_name (self->user));
|
self->user_display_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,63 +506,16 @@ blacklist_apps_cb (gpointer data)
|
||||||
g_autoptr(MctAppFilter) new_filter = NULL;
|
g_autoptr(MctAppFilter) new_filter = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
MctUserControls *self = data;
|
MctUserControls *self = data;
|
||||||
gboolean allow_web_browsers;
|
|
||||||
gsize i;
|
|
||||||
|
|
||||||
self->blacklist_apps_source_id = 0;
|
self->blacklist_apps_source_id = 0;
|
||||||
|
|
||||||
g_debug ("Building parental controls settings…");
|
if (self->user == NULL)
|
||||||
|
|
||||||
/* Blacklist */
|
|
||||||
|
|
||||||
g_debug ("\t → Blacklisting apps");
|
|
||||||
|
|
||||||
mct_restrict_applications_dialog_build_app_filter (self->restrict_applications_dialog, &builder);
|
|
||||||
|
|
||||||
/* Maturity level */
|
|
||||||
|
|
||||||
g_debug ("\t → Maturity level");
|
|
||||||
|
|
||||||
if (self->selected_age == oars_disabled_age)
|
|
||||||
g_debug ("\t\t → Disabled");
|
|
||||||
|
|
||||||
for (i = 0; self->selected_age != oars_disabled_age && oars_categories[i] != NULL; i++)
|
|
||||||
{
|
{
|
||||||
MctAppFilterOarsValue oars_value;
|
g_debug ("Not saving app filter as user is unset");
|
||||||
const gchar *oars_category;
|
return G_SOURCE_REMOVE;
|
||||||
|
|
||||||
oars_category = oars_categories[i];
|
|
||||||
oars_value = as_content_rating_id_csm_age_to_value (oars_category, self->selected_age);
|
|
||||||
|
|
||||||
g_debug ("\t\t → %s: %s", oars_category, oars_value_to_string (oars_value));
|
|
||||||
|
|
||||||
mct_app_filter_builder_set_oars_value (&builder, oars_category, oars_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Web browsers */
|
|
||||||
allow_web_browsers = gtk_switch_get_active (self->allow_web_browsers_switch);
|
|
||||||
|
|
||||||
g_debug ("\t → %s web browsers", allow_web_browsers ? "Enabling" : "Disabling");
|
|
||||||
|
|
||||||
if (!allow_web_browsers)
|
|
||||||
mct_app_filter_builder_blacklist_content_type (&builder, WEB_BROWSERS_CONTENT_TYPE);
|
|
||||||
|
|
||||||
/* App installation */
|
|
||||||
if (act_user_get_account_type (self->user) != ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR)
|
|
||||||
{
|
|
||||||
gboolean allow_system_installation;
|
|
||||||
gboolean allow_user_installation;
|
|
||||||
|
|
||||||
allow_system_installation = gtk_switch_get_active (self->allow_system_installation_switch);
|
|
||||||
allow_user_installation = gtk_switch_get_active (self->allow_user_installation_switch);
|
|
||||||
|
|
||||||
g_debug ("\t → %s system installation", allow_system_installation ? "Enabling" : "Disabling");
|
|
||||||
g_debug ("\t → %s user installation", allow_user_installation ? "Enabling" : "Disabling");
|
|
||||||
|
|
||||||
mct_app_filter_builder_set_allow_user_installation (&builder, allow_user_installation);
|
|
||||||
mct_app_filter_builder_set_allow_system_installation (&builder, allow_system_installation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mct_user_controls_build_app_filter (self, &builder);
|
||||||
new_filter = mct_app_filter_builder_end (&builder);
|
new_filter = mct_app_filter_builder_end (&builder);
|
||||||
|
|
||||||
/* FIXME: should become asynchronous */
|
/* FIXME: should become asynchronous */
|
||||||
|
@ -549,7 +581,7 @@ on_restrict_applications_button_clicked_cb (GtkButton *button,
|
||||||
gtk_window_set_transient_for (GTK_WINDOW (self->restrict_applications_dialog),
|
gtk_window_set_transient_for (GTK_WINDOW (self->restrict_applications_dialog),
|
||||||
GTK_WINDOW (toplevel));
|
GTK_WINDOW (toplevel));
|
||||||
|
|
||||||
mct_restrict_applications_dialog_set_user (self->restrict_applications_dialog, self->user);
|
mct_restrict_applications_dialog_set_user_display_name (self->restrict_applications_dialog, self->user_display_name);
|
||||||
mct_restrict_applications_dialog_set_app_filter (self->restrict_applications_dialog, self->filter);
|
mct_restrict_applications_dialog_set_app_filter (self->restrict_applications_dialog, self->filter);
|
||||||
|
|
||||||
gtk_widget_show (GTK_WIDGET (self->restrict_applications_dialog));
|
gtk_widget_show (GTK_WIDGET (self->restrict_applications_dialog));
|
||||||
|
@ -598,7 +630,7 @@ on_set_age_action_activated (GSimpleAction *action,
|
||||||
self = MCT_USER_CONTROLS (user_data);
|
self = MCT_USER_CONTROLS (user_data);
|
||||||
age = g_variant_get_uint32 (param);
|
age = g_variant_get_uint32 (param);
|
||||||
|
|
||||||
rating_system = get_content_rating_system (self->user);
|
rating_system = get_content_rating_system (self);
|
||||||
entries = gs_utils_content_rating_get_values (rating_system);
|
entries = gs_utils_content_rating_get_values (rating_system);
|
||||||
ages = gs_utils_content_rating_get_ages (rating_system);
|
ages = gs_utils_content_rating_get_ages (rating_system);
|
||||||
|
|
||||||
|
@ -640,6 +672,8 @@ mct_user_controls_finalize (GObject *object)
|
||||||
g_clear_object (&self->action_group);
|
g_clear_object (&self->action_group);
|
||||||
g_clear_object (&self->cancellable);
|
g_clear_object (&self->cancellable);
|
||||||
g_clear_object (&self->user);
|
g_clear_object (&self->user);
|
||||||
|
g_clear_pointer (&self->user_locale, g_free);
|
||||||
|
g_clear_pointer (&self->user_display_name, g_free);
|
||||||
|
|
||||||
if (self->permission != NULL && self->permission_allowed_id != 0)
|
if (self->permission != NULL && self->permission_allowed_id != 0)
|
||||||
{
|
{
|
||||||
|
@ -682,7 +716,7 @@ mct_user_controls_get_property (GObject *object,
|
||||||
{
|
{
|
||||||
MctUserControls *self = MCT_USER_CONTROLS (object);
|
MctUserControls *self = MCT_USER_CONTROLS (object);
|
||||||
|
|
||||||
switch (prop_id)
|
switch ((MctUserControlsProperty) prop_id)
|
||||||
{
|
{
|
||||||
case PROP_USER:
|
case PROP_USER:
|
||||||
g_value_set_object (value, self->user);
|
g_value_set_object (value, self->user);
|
||||||
|
@ -692,6 +726,22 @@ mct_user_controls_get_property (GObject *object,
|
||||||
g_value_set_object (value, self->permission);
|
g_value_set_object (value, self->permission);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_APP_FILTER:
|
||||||
|
g_value_set_boxed (value, self->filter);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_ACCOUNT_TYPE:
|
||||||
|
g_value_set_enum (value, self->user_account_type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_LOCALE:
|
||||||
|
g_value_set_string (value, self->user_locale);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_DISPLAY_NAME:
|
||||||
|
g_value_set_string (value, self->user_display_name);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
|
@ -705,7 +755,7 @@ mct_user_controls_set_property (GObject *object,
|
||||||
{
|
{
|
||||||
MctUserControls *self = MCT_USER_CONTROLS (object);
|
MctUserControls *self = MCT_USER_CONTROLS (object);
|
||||||
|
|
||||||
switch (prop_id)
|
switch ((MctUserControlsProperty) prop_id)
|
||||||
{
|
{
|
||||||
case PROP_USER:
|
case PROP_USER:
|
||||||
mct_user_controls_set_user (self, g_value_get_object (value));
|
mct_user_controls_set_user (self, g_value_get_object (value));
|
||||||
|
@ -715,6 +765,22 @@ mct_user_controls_set_property (GObject *object,
|
||||||
mct_user_controls_set_permission (self, g_value_get_object (value));
|
mct_user_controls_set_permission (self, g_value_get_object (value));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PROP_APP_FILTER:
|
||||||
|
mct_user_controls_set_app_filter (self, g_value_get_boxed (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_ACCOUNT_TYPE:
|
||||||
|
mct_user_controls_set_user_account_type (self, g_value_get_enum (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_LOCALE:
|
||||||
|
mct_user_controls_set_user_locale (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_USER_DISPLAY_NAME:
|
||||||
|
mct_user_controls_set_user_display_name (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
|
@ -747,7 +813,92 @@ mct_user_controls_class_init (MctUserControlsClass *klass)
|
||||||
G_PARAM_STATIC_STRINGS |
|
G_PARAM_STATIC_STRINGS |
|
||||||
G_PARAM_EXPLICIT_NOTIFY);
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, N_PROPS, properties);
|
/**
|
||||||
|
* MctUserControls:app-filter: (nullable)
|
||||||
|
*
|
||||||
|
* The user’s current app filter, used to set up the user controls. As app
|
||||||
|
* filters are immutable, it is not updated as the user controls are changed.
|
||||||
|
* Use mct_user_controls_build_app_filter() to build the new app filter.
|
||||||
|
*
|
||||||
|
* This may be %NULL if the app filter is unknown, or if querying it from
|
||||||
|
* #MctUserControls:user fails.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
properties[PROP_APP_FILTER] =
|
||||||
|
g_param_spec_boxed ("app-filter",
|
||||||
|
"App Filter",
|
||||||
|
"The user’s current app filter, used to set up the user controls, or %NULL if unknown.",
|
||||||
|
MCT_TYPE_APP_FILTER,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS |
|
||||||
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctUserControls:user-account-type:
|
||||||
|
*
|
||||||
|
* The type of the currently selected user account.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
properties[PROP_USER_ACCOUNT_TYPE] =
|
||||||
|
g_param_spec_enum ("user-account-type",
|
||||||
|
"User Account Type",
|
||||||
|
"The type of the currently selected user account.",
|
||||||
|
/* FIXME: Not a typo here; libaccountsservice uses the wrong namespace.
|
||||||
|
* See: https://gitlab.freedesktop.org/accountsservice/accountsservice/issues/84 */
|
||||||
|
ACT_USER_TYPE_USER_ACCOUNT_TYPE,
|
||||||
|
ACT_USER_ACCOUNT_TYPE_STANDARD,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS |
|
||||||
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctUserControls:user-locale: (nullable)
|
||||||
|
*
|
||||||
|
* The locale for the currently selected user account, or %NULL if no
|
||||||
|
* user is selected.
|
||||||
|
*
|
||||||
|
* If set, it must be in the format documented by [`setlocale()`](man:setlocale(3)):
|
||||||
|
* ```
|
||||||
|
* language[_territory][.codeset][@modifier]
|
||||||
|
* ```
|
||||||
|
* where `language` is an ISO 639 language code, `territory` is an ISO 3166
|
||||||
|
* country code, and `codeset` is a character set or encoding identifier like
|
||||||
|
* `ISO-8859-1` or `UTF-8`.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
properties[PROP_USER_LOCALE] =
|
||||||
|
g_param_spec_string ("user-locale",
|
||||||
|
"User Locale",
|
||||||
|
"The locale for the currently selected user account, or %NULL if no user is selected.",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS |
|
||||||
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctUserControls:user-display-name: (nullable)
|
||||||
|
*
|
||||||
|
* The display name for the currently selected user account, or %NULL if no
|
||||||
|
* user is selected. This will typically be the user’s full name (if known)
|
||||||
|
* or their username.
|
||||||
|
*
|
||||||
|
* If set, it must be valid UTF-8 and non-empty.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
properties[PROP_USER_DISPLAY_NAME] =
|
||||||
|
g_param_spec_string ("user-display-name",
|
||||||
|
"User Display Name",
|
||||||
|
"The display name for the currently selected user account, or %NULL if no user is selected.",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS |
|
||||||
|
G_PARAM_EXPLICIT_NOTIFY);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties);
|
||||||
|
|
||||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/user-controls.ui");
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/user-controls.ui");
|
||||||
|
|
||||||
|
@ -808,6 +959,16 @@ mct_user_controls_init (MctUserControls *self)
|
||||||
G_BINDING_DEFAULT);
|
G_BINDING_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_get_user:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
*
|
||||||
|
* Get the value of #MctUserControls:user.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (nullable): the user the controls are configured for,
|
||||||
|
* or %NULL if unknown
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
ActUser *
|
ActUser *
|
||||||
mct_user_controls_get_user (MctUserControls *self)
|
mct_user_controls_get_user (MctUserControls *self)
|
||||||
{
|
{
|
||||||
|
@ -816,6 +977,16 @@ mct_user_controls_get_user (MctUserControls *self)
|
||||||
return self->user;
|
return self->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_set_user:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @user: (nullable) (transfer none): the user to configure the controls for,
|
||||||
|
* or %NULL if unknown
|
||||||
|
*
|
||||||
|
* Set the value of #MctUserControls:user.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
mct_user_controls_set_user (MctUserControls *self,
|
mct_user_controls_set_user (MctUserControls *self,
|
||||||
ActUser *user)
|
ActUser *user)
|
||||||
|
@ -829,10 +1000,21 @@ mct_user_controls_set_user (MctUserControls *self,
|
||||||
|
|
||||||
if (g_set_object (&self->user, user))
|
if (g_set_object (&self->user, user))
|
||||||
{
|
{
|
||||||
update_app_filter (self);
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
|
/* Update the starting widget state from the user. */
|
||||||
|
if (user != NULL)
|
||||||
|
{
|
||||||
|
mct_user_controls_set_user_account_type (self, act_user_get_account_type (user));
|
||||||
|
mct_user_controls_set_user_locale (self, get_user_locale (user));
|
||||||
|
mct_user_controls_set_user_display_name (self, get_user_display_name (user));
|
||||||
|
}
|
||||||
|
|
||||||
|
update_app_filter_from_user (self);
|
||||||
setup_parental_control_settings (self);
|
setup_parental_control_settings (self);
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER]);
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,11 +1025,22 @@ on_permission_allowed_cb (GObject *obj,
|
||||||
{
|
{
|
||||||
MctUserControls *self = MCT_USER_CONTROLS (user_data);
|
MctUserControls *self = MCT_USER_CONTROLS (user_data);
|
||||||
|
|
||||||
update_app_filter (self);
|
update_app_filter_from_user (self);
|
||||||
setup_parental_control_settings (self);
|
setup_parental_control_settings (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPermission * /* (nullable) */
|
/**
|
||||||
|
* mct_user_controls_get_permission:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
*
|
||||||
|
* Get the value of #MctUserControls:permission.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (nullable): a #GPermission indicating whether the
|
||||||
|
* current user has permission to view or change parental controls, or %NULL
|
||||||
|
* if permission is not allowed or is unknown
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
GPermission *
|
||||||
mct_user_controls_get_permission (MctUserControls *self)
|
mct_user_controls_get_permission (MctUserControls *self)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (MCT_IS_USER_CONTROLS (self), NULL);
|
g_return_val_if_fail (MCT_IS_USER_CONTROLS (self), NULL);
|
||||||
|
@ -855,9 +1048,20 @@ mct_user_controls_get_permission (MctUserControls *self)
|
||||||
return self->permission;
|
return self->permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_set_permission:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @permission: (nullable) (transfer none): the #GPermission indicating whether
|
||||||
|
* the current user has permission to view or change parental controls, or
|
||||||
|
* %NULL if permission is not allowed or is unknown
|
||||||
|
*
|
||||||
|
* Set the value of #MctUserControls:permission.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
mct_user_controls_set_permission (MctUserControls *self,
|
mct_user_controls_set_permission (MctUserControls *self,
|
||||||
GPermission *permission /* (nullable) */)
|
GPermission *permission)
|
||||||
{
|
{
|
||||||
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
||||||
g_return_if_fail (permission == NULL || G_IS_PERMISSION (permission));
|
g_return_if_fail (permission == NULL || G_IS_PERMISSION (permission));
|
||||||
|
@ -883,8 +1087,287 @@ mct_user_controls_set_permission (MctUserControls *self,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle changes. */
|
/* Handle changes. */
|
||||||
update_app_filter (self);
|
update_app_filter_from_user (self);
|
||||||
setup_parental_control_settings (self);
|
setup_parental_control_settings (self);
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PERMISSION]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PERMISSION]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_get_app_filter:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
*
|
||||||
|
* Get the value of #MctUserControls:app-filter. If the app filter is unknown
|
||||||
|
* or could not be retrieved from #MctUserControls:user, this will be %NULL.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (nullable): the initial app filter used to
|
||||||
|
* populate the user controls, or %NULL if unknown
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
MctAppFilter *
|
||||||
|
mct_user_controls_get_app_filter (MctUserControls *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MCT_IS_USER_CONTROLS (self), NULL);
|
||||||
|
|
||||||
|
return self->filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_set_app_filter:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @app_filter: (nullable) (transfer none): the app filter to configure the user
|
||||||
|
* controls from, or %NULL if unknown
|
||||||
|
*
|
||||||
|
* Set the value of #MctUserControls:app-filter.
|
||||||
|
*
|
||||||
|
* This will overwrite any user changes to the controls, so they should be saved
|
||||||
|
* first using mct_user_controls_build_app_filter() if desired. They will be
|
||||||
|
* saved automatically if #MctUserControls:user is set.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_user_controls_set_app_filter (MctUserControls *self,
|
||||||
|
MctAppFilter *app_filter)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
||||||
|
|
||||||
|
/* If we have pending unsaved changes from the previous configuration, force
|
||||||
|
* them to be saved first. */
|
||||||
|
flush_update_blacklisted_apps (self);
|
||||||
|
|
||||||
|
if (self->filter == app_filter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->filter, mct_app_filter_unref);
|
||||||
|
if (app_filter != NULL)
|
||||||
|
self->filter = mct_app_filter_ref (app_filter);
|
||||||
|
|
||||||
|
g_debug ("Set new app filter from caller");
|
||||||
|
setup_parental_control_settings (self);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APP_FILTER]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_get_user_account_type:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
*
|
||||||
|
* Get the value of #MctUserControls:user-account-type.
|
||||||
|
*
|
||||||
|
* Returns: the account type of the user the controls are configured for
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
ActUserAccountType
|
||||||
|
mct_user_controls_get_user_account_type (MctUserControls *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MCT_IS_USER_CONTROLS (self), ACT_USER_ACCOUNT_TYPE_STANDARD);
|
||||||
|
|
||||||
|
return self->user_account_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_set_user_account_type:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @user_account_type: the account type of the user to configure the controls for
|
||||||
|
*
|
||||||
|
* Set the value of #MctUserControls:user-account-type.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_user_controls_set_user_account_type (MctUserControls *self,
|
||||||
|
ActUserAccountType user_account_type)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
||||||
|
|
||||||
|
/* If we have pending unsaved changes from the previous user, force them to be
|
||||||
|
* saved first. */
|
||||||
|
flush_update_blacklisted_apps (self);
|
||||||
|
|
||||||
|
if (self->user_account_type == user_account_type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self->user_account_type = user_account_type;
|
||||||
|
|
||||||
|
setup_parental_control_settings (self);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_ACCOUNT_TYPE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_get_user_locale:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
*
|
||||||
|
* Get the value of #MctUserControls:user-locale.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (nullable): the locale of the user the controls
|
||||||
|
* are configured for, or %NULL if unknown
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
const gchar *
|
||||||
|
mct_user_controls_get_user_locale (MctUserControls *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MCT_IS_USER_CONTROLS (self), NULL);
|
||||||
|
|
||||||
|
return self->user_locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_set_user_locale:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @user_locale: (nullable) (transfer none): the locale of the user
|
||||||
|
* to configure the controls for, or %NULL if unknown
|
||||||
|
*
|
||||||
|
* Set the value of #MctUserControls:user-locale.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_user_controls_set_user_locale (MctUserControls *self,
|
||||||
|
const gchar *user_locale)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
||||||
|
g_return_if_fail (user_locale == NULL ||
|
||||||
|
(*user_locale != '\0' &&
|
||||||
|
g_utf8_validate (user_locale, -1, NULL)));
|
||||||
|
|
||||||
|
/* If we have pending unsaved changes from the previous user, force them to be
|
||||||
|
* saved first. */
|
||||||
|
flush_update_blacklisted_apps (self);
|
||||||
|
|
||||||
|
if (g_strcmp0 (self->user_locale, user_locale) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->user_locale, g_free);
|
||||||
|
self->user_locale = g_strdup (user_locale);
|
||||||
|
|
||||||
|
setup_parental_control_settings (self);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_LOCALE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_get_user_display_name:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
*
|
||||||
|
* Get the value of #MctUserControls:user-display-name.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none) (nullable): the display name of the user the controls
|
||||||
|
* are configured for, or %NULL if unknown
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
const gchar *
|
||||||
|
mct_user_controls_get_user_display_name (MctUserControls *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MCT_IS_USER_CONTROLS (self), NULL);
|
||||||
|
|
||||||
|
return self->user_display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_set_user_display_name:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @user_display_name: (nullable) (transfer none): the display name of the user
|
||||||
|
* to configure the controls for, or %NULL if unknown
|
||||||
|
*
|
||||||
|
* Set the value of #MctUserControls:user-display-name.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_user_controls_set_user_display_name (MctUserControls *self,
|
||||||
|
const gchar *user_display_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
||||||
|
g_return_if_fail (user_display_name == NULL ||
|
||||||
|
(*user_display_name != '\0' &&
|
||||||
|
g_utf8_validate (user_display_name, -1, NULL)));
|
||||||
|
|
||||||
|
/* If we have pending unsaved changes from the previous user, force them to be
|
||||||
|
* saved first. */
|
||||||
|
flush_update_blacklisted_apps (self);
|
||||||
|
|
||||||
|
if (g_strcmp0 (self->user_display_name, user_display_name) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->user_display_name, g_free);
|
||||||
|
self->user_display_name = g_strdup (user_display_name);
|
||||||
|
|
||||||
|
setup_parental_control_settings (self);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_DISPLAY_NAME]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_user_controls_build_app_filter:
|
||||||
|
* @self: an #MctUserControls
|
||||||
|
* @builder: an existing #MctAppFilterBuilder to modify
|
||||||
|
*
|
||||||
|
* Get the app filter settings currently configured in the user controls, by
|
||||||
|
* modifying the given @builder. This can be used to save the settings manually.
|
||||||
|
*
|
||||||
|
* Since: 0.5.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_user_controls_build_app_filter (MctUserControls *self,
|
||||||
|
MctAppFilterBuilder *builder)
|
||||||
|
{
|
||||||
|
gboolean allow_web_browsers;
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
g_return_if_fail (MCT_IS_USER_CONTROLS (self));
|
||||||
|
g_return_if_fail (builder != NULL);
|
||||||
|
|
||||||
|
g_debug ("Building parental controls settings…");
|
||||||
|
|
||||||
|
/* Blacklist */
|
||||||
|
|
||||||
|
g_debug ("\t → Blacklisting apps");
|
||||||
|
|
||||||
|
mct_restrict_applications_dialog_build_app_filter (self->restrict_applications_dialog, builder);
|
||||||
|
|
||||||
|
/* Maturity level */
|
||||||
|
|
||||||
|
g_debug ("\t → Maturity level");
|
||||||
|
|
||||||
|
if (self->selected_age == oars_disabled_age)
|
||||||
|
g_debug ("\t\t → Disabled");
|
||||||
|
|
||||||
|
for (i = 0; self->selected_age != oars_disabled_age && oars_categories[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
MctAppFilterOarsValue oars_value;
|
||||||
|
const gchar *oars_category;
|
||||||
|
|
||||||
|
oars_category = oars_categories[i];
|
||||||
|
oars_value = as_content_rating_id_csm_age_to_value (oars_category, self->selected_age);
|
||||||
|
|
||||||
|
g_debug ("\t\t → %s: %s", oars_category, oars_value_to_string (oars_value));
|
||||||
|
|
||||||
|
mct_app_filter_builder_set_oars_value (builder, oars_category, oars_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Web browsers */
|
||||||
|
allow_web_browsers = gtk_switch_get_active (self->allow_web_browsers_switch);
|
||||||
|
|
||||||
|
g_debug ("\t → %s web browsers", allow_web_browsers ? "Enabling" : "Disabling");
|
||||||
|
|
||||||
|
if (!allow_web_browsers)
|
||||||
|
mct_app_filter_builder_blacklist_content_type (builder, WEB_BROWSERS_CONTENT_TYPE);
|
||||||
|
|
||||||
|
/* App installation */
|
||||||
|
if (self->user_account_type != ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR)
|
||||||
|
{
|
||||||
|
gboolean allow_system_installation;
|
||||||
|
gboolean allow_user_installation;
|
||||||
|
|
||||||
|
allow_system_installation = gtk_switch_get_active (self->allow_system_installation_switch);
|
||||||
|
allow_user_installation = gtk_switch_get_active (self->allow_user_installation_switch);
|
||||||
|
|
||||||
|
g_debug ("\t → %s system installation", allow_system_installation ? "Enabling" : "Disabling");
|
||||||
|
g_debug ("\t → %s user installation", allow_user_installation ? "Enabling" : "Disabling");
|
||||||
|
|
||||||
|
mct_app_filter_builder_set_allow_user_installation (builder, allow_user_installation);
|
||||||
|
mct_app_filter_builder_set_allow_system_installation (builder, allow_system_installation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <act/act.h>
|
#include <act/act.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <libmalcontent/malcontent.h>
|
||||||
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
@ -39,4 +43,23 @@ GPermission *mct_user_controls_get_permission (MctUserControls *self);
|
||||||
void mct_user_controls_set_permission (MctUserControls *self,
|
void mct_user_controls_set_permission (MctUserControls *self,
|
||||||
GPermission *permission);
|
GPermission *permission);
|
||||||
|
|
||||||
|
MctAppFilter *mct_user_controls_get_app_filter (MctUserControls *self);
|
||||||
|
void mct_user_controls_set_app_filter (MctUserControls *self,
|
||||||
|
MctAppFilter *app_filter);
|
||||||
|
|
||||||
|
ActUserAccountType mct_user_controls_get_user_account_type (MctUserControls *self);
|
||||||
|
void mct_user_controls_set_user_account_type (MctUserControls *self,
|
||||||
|
ActUserAccountType user_account_type);
|
||||||
|
|
||||||
|
const gchar *mct_user_controls_get_user_locale (MctUserControls *self);
|
||||||
|
void mct_user_controls_set_user_locale (MctUserControls *self,
|
||||||
|
const gchar *user_locale);
|
||||||
|
|
||||||
|
const gchar *mct_user_controls_get_user_display_name (MctUserControls *self);
|
||||||
|
void mct_user_controls_set_user_display_name (MctUserControls *self,
|
||||||
|
const gchar *user_display_name);
|
||||||
|
|
||||||
|
void mct_user_controls_build_app_filter (MctUserControls *self,
|
||||||
|
MctAppFilterBuilder *builder);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -56,7 +56,7 @@ pkgconfig.generate(libmalcontent,
|
||||||
libraries_private: libmalcontent_private_deps,
|
libraries_private: libmalcontent_private_deps,
|
||||||
)
|
)
|
||||||
|
|
||||||
gnome.generate_gir(libmalcontent,
|
libmalcontent_gir = gnome.generate_gir(libmalcontent,
|
||||||
sources: libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers,
|
sources: libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers,
|
||||||
nsversion: libmalcontent_api_version,
|
nsversion: libmalcontent_api_version,
|
||||||
namespace: 'Malcontent',
|
namespace: 'Malcontent',
|
||||||
|
|
Loading…
Reference in New Issue