From c7f975bb2b1241e219fb5569b5baec714e8b602b Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 10 Jan 2020 17:03:20 +0000 Subject: [PATCH] malcontent-control: Add initial draft of main interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This replicates the old interface from Endless’ gnome-control-center, with no attempt to improve or rework it. That will come later. It might not work fully. It allows a user to be selected, and their parental controls to be changed. It currently doesn’t filter the users. It supports a simple ‘Loading’ screen, before displaying the main interface. If loading fails (due to a D-Bus error with accountsservice), an error page is displayed instead. Signed-off-by: Philip Withnall --- malcontent-control/application.c | 131 +++++++++++++++++++++++++++++-- malcontent-control/main.ui | 112 +++++++++++++++++++++++++- 2 files changed, 235 insertions(+), 8 deletions(-) diff --git a/malcontent-control/application.c b/malcontent-control/application.c index b5f6499..d2b69a4 100644 --- a/malcontent-control/application.c +++ b/malcontent-control/application.c @@ -21,6 +21,7 @@ #include "config.h" +#include #include #include #include @@ -28,6 +29,16 @@ #include #include "application.h" +#include "user-controls.h" +#include "user-selector.h" + + +static void user_selector_notify_user_cb (GObject *obj, + GParamSpec *pspec, + gpointer user_data); +static void user_manager_notify_is_loaded_cb (GObject *obj, + GParamSpec *pspec, + gpointer user_data); /** @@ -41,6 +52,14 @@ struct _MctApplication { GtkApplication parent_instance; + + ActUserManager *user_manager; /* (owned) */ + + MctUserSelector *user_selector; + MctUserControls *user_controls; + GtkStack *main_stack; + GtkLabel *error_title; + GtkLabel *error_message; }; G_DEFINE_TYPE (MctApplication, mct_application, GTK_TYPE_APPLICATION) @@ -69,27 +88,77 @@ mct_application_constructed (GObject *object) G_OBJECT_CLASS (mct_application_parent_class)->constructed (object); } +static void +mct_application_dispose (GObject *object) +{ + MctApplication *self = MCT_APPLICATION (object); + + if (self->user_manager != NULL) + { + g_signal_handlers_disconnect_by_func (self->user_manager, + user_manager_notify_is_loaded_cb, self); + g_clear_object (&self->user_manager); + } + + G_OBJECT_CLASS (mct_application_parent_class)->dispose (object); +} + +static GtkWindow * +mct_application_get_main_window (MctApplication *self) +{ + return gtk_application_get_active_window (GTK_APPLICATION (self)); +} + static void mct_application_activate (GApplication *application) { - GList *windows; /* (element-type GtkWindow) */ + MctApplication *self = MCT_APPLICATION (application); GtkWindow *window = NULL; - windows = gtk_application_get_windows (GTK_APPLICATION (application)); - if (windows != NULL) - window = windows->data; + window = mct_application_get_main_window (self); if (window == NULL) { g_autoptr(GtkBuilder) builder = NULL; + g_autoptr(GError) local_error = NULL; - builder = gtk_builder_new_from_resource ("/org/freedesktop/MalcontentControl/ui/main.ui"); + /* Ensure the types used in the UI are registered. */ + g_type_ensure (MCT_TYPE_USER_CONTROLS); + g_type_ensure (MCT_TYPE_USER_SELECTOR); + + builder = gtk_builder_new (); + + g_assert (self->user_manager == NULL); + self->user_manager = g_object_ref (act_user_manager_get_default ()); gtk_builder_set_translation_domain (builder, "malcontent"); + gtk_builder_expose_object (builder, "user_manager", G_OBJECT (self->user_manager)); + + gtk_builder_add_from_resource (builder, "/org/freedesktop/MalcontentControl/ui/main.ui", &local_error); + g_assert (local_error == NULL); /* Set up the main window. */ window = GTK_WINDOW (gtk_builder_get_object (builder, "main_window")); gtk_window_set_application (window, GTK_APPLICATION (application)); + + self->main_stack = GTK_STACK (gtk_builder_get_object (builder, "main_stack")); + self->user_selector = MCT_USER_SELECTOR (gtk_builder_get_object (builder, "user_selector")); + self->user_controls = MCT_USER_CONTROLS (gtk_builder_get_object (builder, "user_controls")); + self->error_title = GTK_LABEL (gtk_builder_get_object (builder, "error_title")); + self->error_message = GTK_LABEL (gtk_builder_get_object (builder, "error_message")); + + /* Connect signals. */ + g_signal_connect (self->user_selector, "notify::user", + G_CALLBACK (user_selector_notify_user_cb), + self); + g_signal_connect (self->user_manager, "notify::is-loaded", + G_CALLBACK (user_manager_notify_is_loaded_cb), self); + + /* Work out whether to show the loading page or the main page, and show + * the controls for the initially selected user. */ + user_selector_notify_user_cb (G_OBJECT (self->user_selector), NULL, self); + user_manager_notify_is_loaded_cb (G_OBJECT (self->user_manager), NULL, self); + gtk_widget_show (GTK_WIDGET (window)); } @@ -104,9 +173,61 @@ mct_application_class_init (MctApplicationClass *klass) GApplicationClass *application_class = G_APPLICATION_CLASS (klass); object_class->constructed = mct_application_constructed; + object_class->dispose = mct_application_dispose; + application_class->activate = mct_application_activate; } +static void +user_selector_notify_user_cb (GObject *obj, + GParamSpec *pspec, + gpointer user_data) +{ + MctUserSelector *selector = MCT_USER_SELECTOR (obj); + MctApplication *self = MCT_APPLICATION (user_data); + ActUser *user; + + user = mct_user_selector_get_user (selector); + + mct_user_controls_set_user (self->user_controls, user); +} + +static void +user_manager_notify_is_loaded_cb (GObject *obj, + GParamSpec *pspec, + gpointer user_data) +{ + MctApplication *self = MCT_APPLICATION (user_data); + ActUserManager *user_manager = ACT_USER_MANAGER (obj); + gboolean is_loaded; + const gchar *new_page_name; + + /* The implementation of #ActUserManager guarantees that once is-loaded is + * true, it is never reset to false. */ + g_object_get (user_manager, "is-loaded", &is_loaded, NULL); + + /* Handle any loading errors. */ + if (is_loaded && act_user_manager_no_service (user_manager)) + { + gtk_label_set_label (self->error_title, + _("Failed to load user data from the system")); + gtk_label_set_label (self->error_message, + _("Please make sure that the AccountsService is installed and enabled.")); + + new_page_name = "error"; + } + else if (is_loaded) + { + new_page_name = "controls"; + } + else + { + new_page_name = "loading"; + } + + gtk_stack_set_visible_child_name (self->main_stack, new_page_name); +} + /** * mct_application_new: * diff --git a/malcontent-control/main.ui b/malcontent-control/main.ui index ebc3ad5..6d3d026 100644 --- a/malcontent-control/main.ui +++ b/malcontent-control/main.ui @@ -1,11 +1,117 @@ - + + 500 + 700 - - vertical + + True + + + True + vertical + 0 + + + True + user_manager + + + + + + False + False + + + + + True + never + 450 + + + True + 12 + + + + + True + + + + + controls + + + + + + True + vertical + True + True + + + True + Loading… + + + + + + static + + + + + + + loading + + + + + + True + vertical + True + True + + + True + vertical + 12 + + + True + + + + + + + + + True + + + + + + + + alert + + + + + error + +