[gnome-initial-setup/parental-controls: 1/8] WIP



commit 6d976988eb4dd6f6ce4a9eb307d0a451537db17c
Author: Philip Withnall <withnall endlessm com>
Date:   Wed Jan 29 19:36:34 2020 +0000

    WIP
    
    Signed-off-by: Philip Withnall <withnall endlessm com>

 gnome-initial-setup/meson.build                    |   2 +
 .../pages/account/gis-account-page-local.c         |   2 +
 .../pages/account/gis-account-page-local.ui        |   7 +
 gnome-initial-setup/pages/meson.build              |   4 +
 .../parental-controls/gis-parental-controls-page.c | 289 +++++++++++++++++++++
 .../parental-controls/gis-parental-controls-page.h |  36 +++
 .../gis-parental-controls-page.ui                  |  36 +++
 .../pages/parental-controls/meson.build            |  10 +
 .../parental-controls.gresource.xml                |   6 +
 meson.build                                        |   8 +
 meson_options.txt                                  |   6 +
 11 files changed, 406 insertions(+)
---
diff --git a/gnome-initial-setup/meson.build b/gnome-initial-setup/meson.build
index 3a7a8b8..6eaf7a6 100644
--- a/gnome-initial-setup/meson.build
+++ b/gnome-initial-setup/meson.build
@@ -36,6 +36,7 @@ dependencies = [
     dependency ('goa-1.0'),
     dependency ('goa-backend-1.0'),
     dependency ('gtk+-3.0', version: '>= 3.11.3'),
+    dependency ('glib-2.0', version: '>= 2.53.0'),
     dependency ('gio-unix-2.0', version: '>= 2.53.0'),
     dependency ('gdm', version: '>= 3.8.3'),
     dependency ('geocode-glib-1.0'),
@@ -51,6 +52,7 @@ dependencies = [
     cheese_dep,
     cheese_gtk_dep,
     ibus_dep,
+    libmalcontent_ui_dep,
 ]
 
 executable(
diff --git a/gnome-initial-setup/pages/account/gis-account-page-local.c 
b/gnome-initial-setup/pages/account/gis-account-page-local.c
index b8bdf5e..f44d282 100644
--- a/gnome-initial-setup/pages/account/gis-account-page-local.c
+++ b/gnome-initial-setup/pages/account/gis-account-page-local.c
@@ -50,6 +50,7 @@ struct _GisAccountPageLocalPrivate
   GtkWidget *header;
   GtkWidget *fullname_entry;
   GtkWidget *username_combo;
+  GtkWidget *enable_parental_controls_check_button;
   gboolean   has_custom_username;
   GtkWidget *username_explanation;
   UmPhotoDialog *photo_dialog;
@@ -547,6 +548,7 @@ gis_account_page_local_class_init (GisAccountPageLocalClass *klass)
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageLocal, 
fullname_entry);
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageLocal, 
username_combo);
   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageLocal, 
username_explanation);
+  gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageLocal, 
enable_parental_controls_check_button);
 
   object_class->constructed = gis_account_page_local_constructed;
   object_class->dispose = gis_account_page_local_dispose;
diff --git a/gnome-initial-setup/pages/account/gis-account-page-local.ui 
b/gnome-initial-setup/pages/account/gis-account-page-local.ui
index 520f80a..e17ea45 100644
--- a/gnome-initial-setup/pages/account/gis-account-page-local.ui
+++ b/gnome-initial-setup/pages/account/gis-account-page-local.ui
@@ -139,6 +139,13 @@
                 <property name="height">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkCheckButton" id="enable_parental_controls_check_button">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Set up _parental controls for this user</property>
+                <property name="use-underline">True</property>
+              </object>
+            </child>
           </object>
         </child>
       </object>
diff --git a/gnome-initial-setup/pages/meson.build b/gnome-initial-setup/pages/meson.build
index 431ca92..dbd28a5 100644
--- a/gnome-initial-setup/pages/meson.build
+++ b/gnome-initial-setup/pages/meson.build
@@ -10,6 +10,10 @@ pages = [
    'summary',
 ]
 
+if libmalcontent_ui_dep.found()
+  pages += 'parental-controls'
+endif
+
 foreach page: pages
     subdir (page)
 endforeach
diff --git a/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c 
b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c
new file mode 100644
index 0000000..9ec1d45
--- /dev/null
+++ b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c
@@ -0,0 +1,289 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright © 2020 Endless Mobile, 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:
+ *     Philip Withnall <withnall endlessm com>
+ */
+
+/* Parental controls page {{{1 */
+
+#define PAGE_ID "parental-controls"
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include "parental-controls-resources.h"
+#include "gis-parental-controls-page.h"
+
+struct _GisParentalControlsPage
+{
+  GisPage parent_instance;
+
+  GtkWidget *user_controls;
+};
+
+G_DEFINE_TYPE (GisParentalControlsPage, gis_parental_controls_page, GIS_TYPE_PAGE)
+
+static void
+enterprise_apply_complete (GisPage  *dummy,
+                           gboolean  valid,
+                           gpointer  user_data)
+{
+  GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (user_data);
+  gis_driver_set_username (GIS_PAGE (page)->driver, NULL);
+  gis_page_apply_complete (GIS_PAGE (page), valid);
+}
+
+static gboolean
+page_validate (GisParentalControlsPage *page)
+{
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+
+  switch (priv->mode) {
+  case UM_LOCAL:
+    return gis_parental_controls_page_local_validate (GIS_PARENTAL_CONTROLS_PAGE_LOCAL (priv->page_local));
+  case UM_ENTERPRISE:
+    return gis_parental_controls_page_enterprise_validate (GIS_PARENTAL_CONTROLS_PAGE_ENTERPRISE 
(priv->page_enterprise));
+  default:
+    g_assert_not_reached ();
+  }
+}
+
+static void
+update_page_validation (GisParentalControlsPage *page)
+{
+  gis_page_set_complete (GIS_PAGE (page), page_validate (page));
+}
+
+static void
+on_validation_changed (gpointer        page_area,
+                       GisParentalControlsPage *page)
+{
+  update_page_validation (page);
+}
+
+static void
+set_mode (GisParentalControlsPage *page,
+          UmParentalControlsMode   mode)
+{
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+
+  if (priv->mode == mode)
+    return;
+
+  priv->mode = mode;
+  gis_driver_set_parental_controls_mode (GIS_PAGE (page)->driver, mode);
+
+  switch (mode)
+    {
+    case UM_LOCAL:
+      gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->page_local);
+      gis_parental_controls_page_local_shown (GIS_PARENTAL_CONTROLS_PAGE_LOCAL (priv->page_local));
+      break;
+    case UM_ENTERPRISE:
+      gtk_stack_set_visible_child (GTK_STACK (priv->stack), priv->page_enterprise);
+      gis_parental_controls_page_enterprise_shown (GIS_PARENTAL_CONTROLS_PAGE_ENTERPRISE 
(priv->page_enterprise));
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  update_page_validation (page);
+}
+
+static void
+toggle_mode (GtkToggleButton *button,
+             gpointer         user_data)
+{
+  set_mode (GIS_PARENTAL_CONTROLS_PAGE (user_data),
+            gtk_toggle_button_get_active (button) ? UM_ENTERPRISE : UM_LOCAL);
+}
+
+static gboolean
+gis_parental_controls_page_apply (GisPage *gis_page,
+                        GCancellable *cancellable)
+{
+  GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (gis_page);
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+
+  switch (priv->mode) {
+  case UM_LOCAL:
+    return gis_parental_controls_page_local_apply (GIS_PARENTAL_CONTROLS_PAGE_LOCAL (priv->page_local), 
gis_page);
+  case UM_ENTERPRISE:
+    return gis_parental_controls_page_enterprise_apply (GIS_PARENTAL_CONTROLS_PAGE_ENTERPRISE 
(priv->page_enterprise), cancellable,
+                                              enterprise_apply_complete, page);
+  default:
+    g_assert_not_reached ();
+    break;
+  }
+}
+
+static void
+gis_parental_controls_page_save_data (GisPage *gis_page)
+{
+  GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (gis_page);
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+
+  switch (priv->mode) {
+  case UM_LOCAL:
+    gis_parental_controls_page_local_create_user (GIS_PARENTAL_CONTROLS_PAGE_LOCAL (priv->page_local));
+    break;
+  case UM_ENTERPRISE:
+    break;
+  default:
+    g_assert_not_reached ();
+  }
+}
+
+static void
+gis_parental_controls_page_shown (GisPage *gis_page)
+{
+  GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (gis_page);
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+
+  gis_parental_controls_page_local_shown (GIS_PARENTAL_CONTROLS_PAGE_LOCAL (priv->page_local));
+}
+
+static void
+on_local_user_created (GtkWidget      *page_local,
+                       ActUser        *user,
+                       char           *password,
+                       GisParentalControlsPage *page)
+{
+  const gchar *language;
+
+  language = gis_driver_get_user_language (GIS_PAGE (page)->driver);
+  if (language)
+    act_user_set_language (user, language);
+
+  gis_driver_set_user_permissions (GIS_PAGE (page)->driver, user, password);
+}
+
+static void
+on_local_page_confirmed (GisParentalControlsPageLocal *local,
+                         GisParentalControlsPage      *page)
+{
+  gis_assistant_next_page (gis_driver_get_assistant (GIS_PAGE (page)->driver));
+}
+
+static void
+on_local_user_cached (GtkWidget      *page_local,
+                      ActUser        *user,
+                      char           *password,
+                      GisParentalControlsPage *page)
+{
+  const gchar *language;
+
+  language = gis_driver_get_user_language (GIS_PAGE (page)->driver);
+  if (language)
+    act_user_set_language (user, language);
+
+  gis_driver_set_user_permissions (GIS_PAGE (page)->driver, user, password);
+}
+
+static void
+on_network_changed (GNetworkMonitor *monitor,
+                    gboolean         available,
+                    GisParentalControlsPage  *page)
+{
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+
+  if (!available && priv->mode != UM_ENTERPRISE)
+    gtk_stack_set_visible_child (GTK_STACK (priv->offline_stack), priv->offline_label);
+  else
+    gtk_stack_set_visible_child (GTK_STACK (priv->offline_stack), priv->page_toggle);
+}
+
+static void
+gis_parental_controls_page_constructed (GObject *object)
+{
+  GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (object);
+  GisParentalControlsPagePrivate *priv = gis_parental_controls_page_get_instance_private (page);
+  GNetworkMonitor *monitor;
+  gboolean available;
+
+  G_OBJECT_CLASS (gis_parental_controls_page_parent_class)->constructed (object);
+
+  g_signal_connect (priv->page_local, "validation-changed",
+                    G_CALLBACK (on_validation_changed), page);
+  g_signal_connect (priv->page_local, "user-created",
+                    G_CALLBACK (on_local_user_created), page);
+  g_signal_connect (priv->page_local, "confirm",
+                    G_CALLBACK (on_local_page_confirmed), page);
+
+  g_signal_connect (priv->page_enterprise, "validation-changed",
+                    G_CALLBACK (on_validation_changed), page);
+  g_signal_connect (priv->page_enterprise, "user-cached",
+                    G_CALLBACK (on_local_user_cached), page);
+
+  update_page_validation (page);
+
+  g_signal_connect (priv->page_toggle, "toggled", G_CALLBACK (toggle_mode), page);
+  g_object_bind_property (page, "applying", priv->page_toggle, "sensitive", G_BINDING_INVERT_BOOLEAN);
+  g_object_bind_property (priv->page_enterprise, "visible", priv->offline_stack, "visible", 
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+  /* force a refresh by setting to an invalid value */
+  priv->mode = NUM_MODES;
+  set_mode (page, UM_LOCAL);
+
+  monitor = g_network_monitor_get_default ();
+  available = g_network_monitor_get_network_available (monitor);
+  on_network_changed (monitor, available, page);
+  g_signal_connect_object (monitor, "network-changed", G_CALLBACK (on_network_changed), page, 0);
+
+  gtk_widget_show (GTK_WIDGET (page));
+}
+
+static void
+gis_parental_controls_page_locale_changed (GisPage *page)
+{
+  gis_page_set_title (GIS_PAGE (page), _("About You"));
+}
+
+static void
+gis_parental_controls_page_class_init (GisParentalControlsPageClass *klass)
+{
+  GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/initial-setup/gis-parental_controls-page.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GisParentalControlsPage, user_controls);
+
+  page_class->page_id = PAGE_ID;
+  page_class->locale_changed = gis_parental_controls_page_locale_changed;
+  page_class->apply = gis_parental_controls_page_apply;
+  page_class->save_data = gis_parental_controls_page_save_data;
+  page_class->shown = gis_parental_controls_page_shown;
+  object_class->constructed = gis_parental_controls_page_constructed;
+}
+
+static void
+gis_parental_controls_page_init (GisParentalControlsPage *page)
+{
+  g_resources_register (parental_controls_get_resource ());
+  g_type_ensure (GIS_TYPE_PARENTAL_CONTROLS_PAGE_LOCAL);
+  g_type_ensure (GIS_TYPE_PARENTAL_CONTROLS_PAGE_ENTERPRISE);
+
+  gtk_widget_init_template (GTK_WIDGET (page));
+}
diff --git a/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.h 
b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.h
new file mode 100644
index 0000000..3cd9c20
--- /dev/null
+++ b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.h
@@ -0,0 +1,36 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright © 2020 Endless Mobile, 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:
+ *     Philip Withnall <withnall endlessm com>
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gnome-initial-setup.h"
+
+G_BEGIN_DECLS
+
+#define GIS_TYPE_PARENTAL_CONTROLS_PAGE (gis_parental_controls_page_get_type ())
+G_DECLARE_FINAL_TYPE (GisParentalControlsPage, gis_parental_controls_page, GIS, PARENTAL_CONTROLS_PAGE, 
GisPage)
+
+GType gis_parental_controls_page_get_type (void);
+
+G_END_DECLS
diff --git a/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.ui 
b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.ui
new file mode 100644
index 0000000..3a3aff1
--- /dev/null
+++ b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.ui
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <template class="GisParentalControlsPage" parent="GisPage">
+    <child>
+      <object class="GtkBox" id="page">
+        <property name="visible">True</property>
+        <property name="halign">center</property>
+        <property name="valign">fill</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="visible">True</property>
+            <property name="valign">start</property>
+            <property name="vexpand">True</property>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <child>
+                  <object class="MctUserControls" id="user_controls">
+                    <property name="visible">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/gnome-initial-setup/pages/parental-controls/meson.build 
b/gnome-initial-setup/pages/parental-controls/meson.build
new file mode 100644
index 0000000..ddf5b72
--- /dev/null
+++ b/gnome-initial-setup/pages/parental-controls/meson.build
@@ -0,0 +1,10 @@
+sources += gnome.compile_resources(
+  'parental-controls-resources',
+  files('parental-controls.gresource.xml'),
+  c_name: 'parental-controls',
+)
+
+sources += files(
+  'gis-parental-controls-page.c',
+  'gis-parental-controls-page.h',
+)
diff --git a/gnome-initial-setup/pages/parental-controls/parental-controls.gresource.xml 
b/gnome-initial-setup/pages/parental-controls/parental-controls.gresource.xml
new file mode 100644
index 0000000..59460b5
--- /dev/null
+++ b/gnome-initial-setup/pages/parental-controls/parental-controls.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/initial-setup">
+    <file preprocess="xml-stripblanks" 
alias="gis-parental-controls-page.ui">gis-parental-controls-page.ui</file>
+  </gresource>
+</gresources>
diff --git a/meson.build b/meson.build
index ed7240c..567893a 100644
--- a/meson.build
+++ b/meson.build
@@ -29,6 +29,8 @@ conf.set_quoted('GNOMELOCALEDIR', locale_dir)
 conf.set_quoted('PKGDATADIR', pkgdata_dir)
 conf.set('SECRET_API_SUBJECT_TO_CHANGE', true)
 conf.set_quoted('G_LOG_DOMAIN', 'InitialSetup')
+conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_44')
+conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_62')
 
 enable_systemd = get_option('systemd')
 if enable_systemd
@@ -57,6 +59,12 @@ ibus_dep = dependency ('ibus-1.0',
                        required: get_option('ibus'))
 conf.set('HAVE_IBUS', ibus_dep.found())
 
+# Needed for the parental controls pages
+libmalcontent_ui_dep = dependency ('libmalcontent-ui',
+                                   version: '>= 0.5.0',
+                                   required: get_option('parental_controls'))
+conf.set('HAVE_PARENTAL_CONTROLS', libmalcontent_ui_dep.found())
+
 configure_file(output: 'config.h',
                configuration: conf)
 config_h_dir = include_directories('.')
diff --git a/meson_options.txt b/meson_options.txt
index 2d475e1..741e844 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -20,3 +20,9 @@ option('systemd',
   value: true,
   description: 'Enable systemd integration'
 )
+
+option('parental_controls',
+  type: 'feature',
+  value: 'auto',
+  description: 'Enable parental controls pages',
+)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]