From d80ed105923e706b6f8d6fea74540e22d5dd9ba0 Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Mon, 8 Feb 2021 03:27:59 -0800 Subject: [PATCH 01/54] malcontent-control: Use HdyWindow and HdyHeaderBar --- malcontent-control/application.c | 3 + malcontent-control/main.ui | 516 ++++++++++++++++--------------- malcontent-control/meson.build | 1 + 3 files changed, 265 insertions(+), 255 deletions(-) diff --git a/malcontent-control/application.c b/malcontent-control/application.c index d226a83..c6c1b57 100644 --- a/malcontent-control/application.c +++ b/malcontent-control/application.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -250,6 +251,8 @@ mct_application_startup (GApplication *application) /* Chain up. */ G_APPLICATION_CLASS (mct_application_parent_class)->startup (application); + hdy_init (); + g_action_map_add_action_entries (G_ACTION_MAP (application), app_entries, G_N_ELEMENTS (app_entries), application); diff --git a/malcontent-control/main.ui b/malcontent-control/main.ui index 43baf25..d78a352 100644 --- a/malcontent-control/main.ui +++ b/malcontent-control/main.ui @@ -2,74 +2,124 @@ - + 540 580 - - - True - - Parental Controls - True - - - True - none - True - True - primary-menu - - - - - end - - - - - + True + vertical - + + True + + Parental Controls True - vertical - 0 - + True - user_manager - False - - - + none + True + True + primary-menu + + - False - False + end + + + + + True - + True - never - 370 + vertical + 0 - - 18 - vertical - 18 + True + user_manager + False + + + + + + False + False + + + + + True + never + 370 - - - It’s recommended that restrictions are set as part of an ongoing conversation with $name. Read guidance on what to consider. + + 18 + vertical + 18 True - True - 0.0 - 0.0 + + + + It’s recommended that restrictions are set as part of an ongoing conversation with $name. Read guidance on what to consider. + True + True + 0.0 + 0.0 + + + static + + + + + + + center + True + dbus_connection + + + + + + + True + + + + + controls + + + + + + True + vertical + True + True + + + True + vertical + 12 + 18 + + + True + Permission Required + + + static @@ -78,221 +128,177 @@ - - center + True - dbus_connection + Permission is required to view and change user parental controls settings. + True + + + static + + + + + + + True + center + True + True + True + + 6 - True + unlock + + + + + + True + vertical + True + True + + + True + vertical + 12 + 18 + + + system-users-symbolic + 96 + True + + + static + + + + + + + True + No Standard User Accounts + + + + + + static + + + + + + + True + center + Parental controls can only be applied to standard user + accounts. These can be created in the user settings. + True + + + static + + + + + + + True + _User Settings + center + True + True + True + True + + 6 + + + + + + + + no-other-users + + + + + + True + vertical + True + True + + + True + Loading… + + + + + + static + + + + + + + loading + + + + + + True + vertical + True + True + + + True + vertical + 12 + + + True + + + + + + + + + True + + + + + + + + alert + + + + + error - - controls - - - - - - True - vertical - True - True - - - True - vertical - 12 - 18 - - - True - Permission Required - - - - - - static - - - - - - - True - Permission is required to view and change user parental controls settings. - True - - - static - - - - - - - True - center - True - True - True - - 6 - - - - - - - unlock - - - - - - True - vertical - True - True - - - True - vertical - 12 - 18 - - - system-users-symbolic - 96 - True - - - static - - - - - - - True - No Standard User Accounts - - - - - - static - - - - - - - True - center - Parental controls can only be applied to standard user -accounts. These can be created in the user settings. - True - - - static - - - - - - - True - _User Settings - center - True - True - True - True - - 6 - - - - - - - - no-other-users - - - - - - True - vertical - True - True - - - True - Loading… - - - - - - static - - - - - - - loading - - - - - - True - vertical - True - True - - - True - vertical - 12 - - - True - - - - - - - - - True - - - - - - - - alert - - - - - error - diff --git a/malcontent-control/meson.build b/malcontent-control/meson.build index 9b9bb68..bd9f037 100644 --- a/malcontent-control/meson.build +++ b/malcontent-control/meson.build @@ -28,6 +28,7 @@ malcontent_control = executable('malcontent-control', dependency('glib-2.0', version: '>= 2.54.2'), dependency('gobject-2.0', version: '>= 2.54'), dependency('gtk+-3.0'), + dependency('libhandy-1', version: '>=1.1.0'), dependency('polkit-gobject-1'), libmalcontent_dep, libmalcontent_ui_dep, From 358cad3a24593f997dc0949f27ed9abb23462694 Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Mon, 8 Feb 2021 05:27:49 -0800 Subject: [PATCH 02/54] user-controls: Use HdyPreferencesPage and HdyActionRow API This allows us to get styling consistent with HdyPreferencesWindow and similar content across GNOME. Part of a consistency push for GNOME 40 --- libmalcontent-ui/meson.build | 1 + libmalcontent-ui/user-controls.c | 175 +++++----- libmalcontent-ui/user-controls.h | 6 +- libmalcontent-ui/user-controls.ui | 549 +++++++----------------------- malcontent-control/application.c | 3 +- malcontent-control/main.ui | 38 +-- 6 files changed, 216 insertions(+), 556 deletions(-) diff --git a/libmalcontent-ui/meson.build b/libmalcontent-ui/meson.build index 9df7b91..7fc0ad7 100644 --- a/libmalcontent-ui/meson.build +++ b/libmalcontent-ui/meson.build @@ -29,6 +29,7 @@ libmalcontent_ui_public_deps = [ dependency('glib-2.0', version: '>= 2.54.2'), dependency('gobject-2.0', version: '>= 2.54'), dependency('gtk+-3.0', version: '>= 3.24'), + dependency('libhandy-1', version: '>= 1.1.0'), libmalcontent_dep, ] libmalcontent_ui_private_deps = [ diff --git a/libmalcontent-ui/user-controls.c b/libmalcontent-ui/user-controls.c index cc9cd2c..3d22b9d 100644 --- a/libmalcontent-ui/user-controls.c +++ b/libmalcontent-ui/user-controls.c @@ -75,20 +75,18 @@ struct _MctUserControls { GtkGrid parent_instance; + GtkLabel *description_label; GMenu *age_menu; GtkSwitch *restrict_software_installation_switch; - GtkLabel *restrict_software_installation_description; + HdyActionRow *restrict_software_installation_row; GtkSwitch *restrict_web_browsers_switch; - GtkLabel *restrict_web_browsers_description; + HdyActionRow *restrict_web_browsers_row; GtkButton *oars_button; GtkLabel *oars_button_label; GtkPopover *oars_popover; MctRestrictApplicationsDialog *restrict_applications_dialog; GtkLabel *restrict_applications_description; - GtkListBoxRow *restrict_applications_row; - - GtkListBox *application_usage_permissions_listbox; - GtkListBox *software_installation_permissions_listbox; + HdyActionRow *restrict_applications_row; GSimpleActionGroup *action_group; /* (owned) */ @@ -111,6 +109,7 @@ struct _MctUserControls ActUserAccountType user_account_type; gchar *user_locale; /* (nullable) (owned) */ gchar *user_display_name; /* (nullable) (owned) */ + gchar *description; /* (nullable) (owned) */ }; static gboolean blocklist_apps_cb (gpointer data); @@ -123,8 +122,9 @@ static void on_restrict_web_browsers_switch_active_changed_cb (GtkSwitch GParamSpec *pspec, MctUserControls *self); -static void on_restrict_applications_button_clicked_cb (GtkButton *button, - gpointer user_data); +static void on_restrict_applications_action_activated (GSimpleAction *action, + GVariant *param, + gpointer user_data); static gboolean on_restrict_applications_dialog_delete_event_cb (GtkWidget *widget, GdkEvent *event, @@ -134,10 +134,6 @@ static void on_restrict_applications_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data); -static void on_application_usage_permissions_listbox_activated_cb (GtkListBox *list_box, - GtkListBoxRow *row, - gpointer user_data); - static void on_set_age_action_activated (GSimpleAction *action, GVariant *param, gpointer user_data); @@ -146,7 +142,7 @@ static void on_permission_allowed_cb (GObject *obj, GParamSpec *pspec, gpointer user_data); -G_DEFINE_TYPE (MctUserControls, mct_user_controls, GTK_TYPE_GRID) +G_DEFINE_TYPE (MctUserControls, mct_user_controls, GTK_TYPE_BIN) typedef enum { @@ -157,12 +153,14 @@ typedef enum PROP_USER_LOCALE, PROP_USER_DISPLAY_NAME, PROP_DBUS_CONNECTION, + PROP_DESCRIPTION, } MctUserControlsProperty; -static GParamSpec *properties[PROP_DBUS_CONNECTION + 1]; +static GParamSpec *properties[PROP_DESCRIPTION + 1]; 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, }}, + { "restrict-applications", on_restrict_applications_action_activated, NULL, NULL, NULL, { 0, }} }; /* Auxiliary methods */ @@ -472,19 +470,21 @@ update_labels_from_name (MctUserControls *self) { g_autofree gchar *l = NULL; + gtk_label_set_markup (self->description_label, self->description); + /* Translators: The placeholder is a user’s display name. */ l = g_strdup_printf (_("Prevents %s from running web browsers. Limited web content may still be available in other applications."), self->user_display_name); - gtk_label_set_label (self->restrict_web_browsers_description, l); + hdy_action_row_set_subtitle (self->restrict_web_browsers_row, l); g_clear_pointer (&l, g_free); /* Translators: The placeholder is a user’s display name. */ l = g_strdup_printf (_("Prevents specified applications from being used by %s."), self->user_display_name); - gtk_label_set_label (self->restrict_applications_description, l); + hdy_action_row_set_subtitle (self->restrict_applications_row, l); g_clear_pointer (&l, g_free); /* Translators: The placeholder is a user’s display name. */ l = g_strdup_printf (_("Prevents %s from installing applications."), self->user_display_name); - gtk_label_set_label (self->restrict_software_installation_description, l); + hdy_action_row_set_subtitle (self->restrict_software_installation_row, l); g_clear_pointer (&l, g_free); } @@ -585,8 +585,9 @@ on_restrict_web_browsers_switch_active_changed_cb (GtkSwitch *s, } static void -on_restrict_applications_button_clicked_cb (GtkButton *button, - gpointer user_data) +on_restrict_applications_action_activated (GSimpleAction *action, + GVariant *param, + gpointer user_data) { MctUserControls *self = MCT_USER_CONTROLS (user_data); GtkWidget *toplevel; @@ -632,17 +633,6 @@ on_restrict_applications_dialog_response_cb (GtkDialog *dialog, on_restrict_applications_dialog_delete_event_cb (GTK_WIDGET (dialog), NULL, self); } -static void -on_application_usage_permissions_listbox_activated_cb (GtkListBox *list_box, - GtkListBoxRow *row, - gpointer user_data) -{ - MctUserControls *self = MCT_USER_CONTROLS (user_data); - - if (row == self->restrict_applications_row) - on_restrict_applications_button_clicked_cb (NULL, self); -} - static void on_set_age_action_activated (GSimpleAction *action, GVariant *param, @@ -688,53 +678,6 @@ on_set_age_action_activated (GSimpleAction *action, schedule_update_blocklisted_apps (self); } -static void -list_box_header_func (GtkListBoxRow *row, - GtkListBoxRow *before, - gpointer user_data) -{ - GtkWidget *current; - - if (before == NULL) - { - gtk_list_box_row_set_header (row, NULL); - return; - } - - current = gtk_list_box_row_get_header (row); - if (current == NULL) - { - current = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); - gtk_widget_show (current); - gtk_list_box_row_set_header (row, current); - } -} - -static gboolean -on_keynav_failed (GtkWidget *listbox, - GtkDirectionType direction, - gpointer user_data) -{ - MctUserControls *self = MCT_USER_CONTROLS (user_data); - GtkWidget *new_widget = NULL; - - /* There are currently two listboxes, so don’t over-complicate this function. */ - if (listbox == GTK_WIDGET (self->application_usage_permissions_listbox) && - direction == GTK_DIR_DOWN) - new_widget = GTK_WIDGET (self->software_installation_permissions_listbox); - else if (listbox == GTK_WIDGET (self->software_installation_permissions_listbox) && - direction == GTK_DIR_UP) - new_widget = GTK_WIDGET (self->application_usage_permissions_listbox); - - if (new_widget != NULL) - { - gtk_widget_child_focus (new_widget, direction); - return TRUE; - } - - return FALSE; -} - /* GObject overrides */ static void @@ -850,6 +793,10 @@ mct_user_controls_get_property (GObject *object, g_value_set_object (value, self->dbus_connection); break; + case PROP_DESCRIPTION: + g_value_set_string (value, self->description); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -895,6 +842,10 @@ mct_user_controls_set_property (GObject *object, self->dbus_connection = g_value_dup_object (value); break; + case PROP_DESCRIPTION: + mct_user_controls_set_description (self, g_value_get_string (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -1013,6 +964,25 @@ mct_user_controls_class_init (MctUserControlsClass *klass) G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + /** + * MctUserControls:description: (nullable) + * + * The description for the currently selected user account, or %NULL if no + * user is selected. + * + * If set, it must be valid UTF-8 and non-empty. + * + * Since: 0.11.0 + */ + properties[PROP_DESCRIPTION] = + g_param_spec_string ("description", + "Description", + "The description 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:dbus-connection: (not nullable) * @@ -1036,26 +1006,21 @@ mct_user_controls_class_init (MctUserControlsClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/freedesktop/MalcontentUi/ui/user-controls.ui"); gtk_widget_class_bind_template_child (widget_class, MctUserControls, age_menu); + gtk_widget_class_bind_template_child (widget_class, MctUserControls, description_label); gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_software_installation_switch); - gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_software_installation_description); + gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_software_installation_row); gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_web_browsers_switch); - gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_web_browsers_description); + gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_web_browsers_row); gtk_widget_class_bind_template_child (widget_class, MctUserControls, oars_button); gtk_widget_class_bind_template_child (widget_class, MctUserControls, oars_button_label); gtk_widget_class_bind_template_child (widget_class, MctUserControls, oars_popover); gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_applications_dialog); - gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_applications_description); gtk_widget_class_bind_template_child (widget_class, MctUserControls, restrict_applications_row); - gtk_widget_class_bind_template_child (widget_class, MctUserControls, application_usage_permissions_listbox); - gtk_widget_class_bind_template_child (widget_class, MctUserControls, software_installation_permissions_listbox); gtk_widget_class_bind_template_callback (widget_class, on_restrict_installation_switch_active_changed_cb); gtk_widget_class_bind_template_callback (widget_class, on_restrict_web_browsers_switch_active_changed_cb); - gtk_widget_class_bind_template_callback (widget_class, on_restrict_applications_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, on_restrict_applications_dialog_delete_event_cb); gtk_widget_class_bind_template_callback (widget_class, on_restrict_applications_dialog_response_cb); - gtk_widget_class_bind_template_callback (widget_class, on_application_usage_permissions_listbox_activated_cb); - gtk_widget_class_bind_template_callback (widget_class, on_keynav_failed); } static void @@ -1091,12 +1056,6 @@ mct_user_controls_init (MctUserControls *self) G_ACTION_GROUP (self->action_group)); gtk_popover_bind_model (self->oars_popover, G_MENU_MODEL (self->age_menu), NULL); - - /* Automatically add separators between rows. */ - gtk_list_box_set_header_func (self->application_usage_permissions_listbox, - list_box_header_func, NULL, NULL); - gtk_list_box_set_header_func (self->software_installation_permissions_listbox, - list_box_header_func, NULL, NULL); } /** @@ -1461,6 +1420,38 @@ mct_user_controls_set_user_display_name (MctUserControls *self, g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USER_DISPLAY_NAME]); } +/** + * mct_user_controls_set_description: + * @self: an #MctUserControls + * @description: (nullable) (transfer none): the description shown + * above the controls, or %NULL if none. + * + * Set the value of #MctUserControls:description. + * + * Since: 0.11.0 + */ +void +mct_user_controls_set_description (MctUserControls *self, + const gchar *description) +{ + g_return_if_fail (MCT_IS_USER_CONTROLS (self)); + g_return_if_fail (description != NULL); + + /* If we have pending unsaved changes from the previous user, force them to be + * saved first. */ + flush_update_blocklisted_apps (self); + + if (g_strcmp0 (self->description, description) == 0) + return; + + g_clear_pointer (&self->description, g_free); + self->description = g_strdup (description); + + setup_parental_control_settings (self); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DESCRIPTION]); +} + /** * mct_user_controls_build_app_filter: * @self: an #MctUserControls diff --git a/libmalcontent-ui/user-controls.h b/libmalcontent-ui/user-controls.h index 91e0863..a8b2847 100644 --- a/libmalcontent-ui/user-controls.h +++ b/libmalcontent-ui/user-controls.h @@ -27,13 +27,14 @@ #include #include #include +#include #include G_BEGIN_DECLS #define MCT_TYPE_USER_CONTROLS (mct_user_controls_get_type()) -G_DECLARE_FINAL_TYPE (MctUserControls, mct_user_controls, MCT, USER_CONTROLS, GtkGrid) +G_DECLARE_FINAL_TYPE (MctUserControls, mct_user_controls, MCT, USER_CONTROLS, GtkBin) ActUser *mct_user_controls_get_user (MctUserControls *self); void mct_user_controls_set_user (MctUserControls *self, @@ -59,6 +60,9 @@ 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_set_description (MctUserControls *self, + const gchar *description); + void mct_user_controls_build_app_filter (MctUserControls *self, MctAppFilterBuilder *builder); diff --git a/libmalcontent-ui/user-controls.ui b/libmalcontent-ui/user-controls.ui index b699871..e2cff1b 100644 --- a/libmalcontent-ui/user-controls.ui +++ b/libmalcontent-ui/user-controls.ui @@ -2,454 +2,159 @@ -