[PATCH 3/3] EULA agreement spoke (#1000409)
Vratislav Podzimek
vpodzime at redhat.com
Fri Sep 20 18:08:38 UTC 2013
Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
initial-setup.spec | 2 +
initial_setup/__main__.py | 1 +
initial_setup/gui/hubs/initial_setup_hub.py | 22 +++++
initial_setup/gui/spokes/eula.glade | 132 ++++++++++++++++++++++++++++
initial_setup/gui/spokes/eula.py | 72 +++++++++++++++
initial_setup/product.py | 44 ++++++++++
6 files changed, 273 insertions(+)
create mode 100644 initial_setup/gui/spokes/eula.glade
create mode 100644 initial_setup/gui/spokes/eula.py
diff --git a/initial-setup.spec b/initial-setup.spec
index 793af05..329af92 100644
--- a/initial-setup.spec
+++ b/initial-setup.spec
@@ -26,10 +26,12 @@ BuildRequires: gobject-introspection-devel
BuildRequires: glade-devel
BuildRequires: pygobject3
BuildRequires: anaconda >= 19.13
+BuildRequires: pykickstart >= 1.99.35.5-1
BuildRequires: python-di
Requires: gtk3
Requires: python
Requires: anaconda >= 19.13
+Requires: pykickstart >= 1.99.35.5-1
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
diff --git a/initial_setup/__main__.py b/initial_setup/__main__.py
index 55cce93..ffe5db6 100644
--- a/initial_setup/__main__.py
+++ b/initial_setup/__main__.py
@@ -51,6 +51,7 @@ from pyanaconda import kickstart
# Construct a commandMap with the supported Anaconda's commands only
kickstart_commands = ["user",
+ "eula",
"group",
"keyboard",
"lang",
diff --git a/initial_setup/gui/hubs/initial_setup_hub.py b/initial_setup/gui/hubs/initial_setup_hub.py
index d9e798b..20ec0ae 100644
--- a/initial_setup/gui/hubs/initial_setup_hub.py
+++ b/initial_setup/gui/hubs/initial_setup_hub.py
@@ -2,7 +2,9 @@ from pyanaconda.constants import FIRSTBOOT_ENVIRON
from pyanaconda.ui.gui.hubs import Hub
from pyanaconda.ui.gui.spokes import Spoke
from pyanaconda.ui.common import collect
+from initial_setup import product
import os
+import sys
__all__ = ["InitialSetupMainHub"]
@@ -62,3 +64,23 @@ class InitialSetupMainHub(Hub):
@property
def quitButton(self):
return self.builder.get_object("quitButton")
+
+ def register_event_cb(self, event, cb):
+ if event == "continue" and self.continueButton:
+ self.continueButton.connect("clicked", lambda *args: cb())
+ elif event == "quit" and self.quitButton:
+ self.quitButton.connect("clicked", lambda *args: self._on_quit_clicked(cb))
+
+ def _on_quit_clicked(self, cb):
+ try:
+ cb()
+ except SystemExit:
+ # user wants to exit, check if EULA is available and accepted and do
+ # proper action
+ license_file = product.get_license_file_name()
+ if not license_file or self.data.eula.agreed:
+ # agreed, just exit
+ sys.exit(0)
+ else:
+ # not agreed, reboot the system and leave Initial Setup enabled
+ os.system("reboot")
diff --git a/initial_setup/gui/spokes/eula.glade b/initial_setup/gui/spokes/eula.glade
new file mode 100644
index 0000000..ea29652
--- /dev/null
+++ b/initial_setup/gui/spokes/eula.glade
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.6 -->
+ <!-- interface-requires AnacondaWidgets 1.0 -->
+ <object class="GtkTextBuffer" id="eulaBuffer">
+ <property name="text" translatable="yes">The license will go here</property>
+ </object>
+ <object class="AnacondaSpokeWindow" id="eulaWindow">
+ <property name="startup_id">filler</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="startup_id">filler</property>
+ <property name="window_name" translatable="yes">LICENSE INFORMATION</property>
+ <signal name="button-clicked" handler="on_back_clicked" swapped="no"/>
+ <child internal-child="main_box">
+ <object class="GtkBox" id="AnacondaSpokeWindow-main_box1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child internal-child="nav_box">
+ <object class="GtkEventBox" id="AnacondaSpokeWindow-nav_box1">
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <child internal-child="nav_area">
+ <object class="GtkGrid" id="AnacondaSpokeWindow-nav_area1">
+ <property name="can_focus">False</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">6</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="alignment">
+ <object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1">
+ <property name="can_focus">False</property>
+ <property name="xscale">0.80000001192092896</property>
+ <property name="yscale">0.80000001192092896</property>
+ <child internal-child="action_area">
+ <object class="GtkBox" id="mainBox">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="licenseAgreementLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="margin_top">24</property>
+ <property name="margin_bottom">6</property>
+ <property name="label" translatable="yes">License Agreement:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="eulaBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkTextView" id="eulaView">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_bottom">18</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="vscroll_policy">natural</property>
+ <property name="pixels_above_lines">12</property>
+ <property name="editable">False</property>
+ <property name="wrap_mode">word</property>
+ <property name="left_margin">12</property>
+ <property name="right_margin">12</property>
+ <property name="cursor_visible">False</property>
+ <property name="buffer">eulaBuffer</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="agreeCheckButton">
+ <property name="label" translatable="yes">I _accept the license agreement.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_check_button_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/initial_setup/gui/spokes/eula.py b/initial_setup/gui/spokes/eula.py
new file mode 100644
index 0000000..0704477
--- /dev/null
+++ b/initial_setup/gui/spokes/eula.py
@@ -0,0 +1,72 @@
+"""EULA spoke for the Initial Setup"""
+
+import gettext
+
+from gi.repository import Pango
+from pyanaconda.ui.common import FirstbootOnlySpokeMixIn
+from pyanaconda.ui.gui.spokes import NormalSpoke
+from pyanaconda.ui.gui.categories.localization import LocalizationCategory
+from pyanaconda.constants import FIRSTBOOT_ENVIRON
+
+from initial_setup.product import get_license_file_name
+
+_ = lambda x: gettext.ldgettext("initial-setup", x)
+N_ = lambda x: x
+
+__all__ = ["EULAspoke"]
+
+class EULAspoke(FirstbootOnlySpokeMixIn, NormalSpoke):
+ """The EULA spoke"""
+
+ builderObjects = ["eulaBuffer", "eulaWindow"]
+ mainWidgetName = "eulaWindow"
+ uiFile = "eula.glade"
+
+ icon = "application-certificate-symbolic"
+ title = N_("_LICENSE INFORMATION")
+ category = LocalizationCategory
+
+ def initialize(self):
+ NormalSpoke.initialize(self)
+
+ self._have_eula = True
+ self._eula_buffer = self.builder.get_object("eulaBuffer")
+ self._agree_check_button = self.builder.get_object("agreeCheckButton")
+ self._agree_label = self._agree_check_button.get_child()
+ self._agree_text = self._agree_label.get_text()
+
+ itr = self._eula_buffer.get_iter_at_offset(0)
+ license_file = get_license_file_name()
+ if not license_file:
+ self._have_eula = False
+ self._eula_buffer.set_text(_("No license found. Please report this "
+ "at http://bugzilla.redhat.com"))
+ return
+
+ with open(license_file, "r") as fobj:
+ for line in fobj:
+ self._eula_buffer.insert(itr, line)
+
+ def refresh(self):
+ self._agree_check_button.set_sensitive(self._have_eula)
+ self._agree_check_button.set_active(self.data.eula.agreed)
+
+ def apply(self):
+ self.data.eula.agreed = self._agree_check_button.get_active()
+
+ @property
+ def completed(self):
+ return not self._have_eula or self.data.eula.agreed
+
+ @property
+ def status(self):
+ if not self._have_eula:
+ return _("No license found")
+
+ return _("License agreed") if self.data.eula.agreed else _("License not agreed")
+
+ def on_check_button_toggled(self, checkbutton, *args):
+ if self._agree_check_button.get_active():
+ self._agree_label.set_markup("<b>%s</b>" % self._agree_text)
+ else:
+ self._agree_label.set_markup(self._agree_text)
diff --git a/initial_setup/product.py b/initial_setup/product.py
index 82f9b0f..aa9bda3 100644
--- a/initial_setup/product.py
+++ b/initial_setup/product.py
@@ -1,6 +1,12 @@
"""Module providing information about the installed product."""
+from pyanaconda.localization import find_best_locale_match
+from pyanaconda.constants import DEFAULT_LANG
+import os
+import glob
+
RELEASE_STRING_FILE = "/etc/os-release"
+LICENSE_FILE_GLOB = "/usr/share/doc/redhat-release*/EULA*"
def product_title():
"""
@@ -34,3 +40,41 @@ def is_final():
# doesn't really matter for the Initial Setup
return True
+
+def get_license_file_name():
+ """
+ Get filename of the license file best matching current localization settings.
+
+ :return: filename of the license file or None if no license file found
+ :rtype: str or None
+
+ """
+
+ all_eulas = glob.glob(LICENSE_FILE_GLOB)
+ non_localized_eulas = []
+ langs = set()
+ for eula in all_eulas:
+ if "EULA_" in eula:
+ # license file for a specific locale
+ lang = eula.rsplit("EULA_", 1)[1]
+ if lang:
+ langs.add(lang)
+ else:
+ non_localized_eulas.append(eula)
+
+ best_lang = find_best_locale_match(os.environ["LANG"], langs)
+ if not best_lang:
+ # nothing found for the current language, try the default one
+ best_lang = find_best_locale_match(DEFAULT_LANG, langs)
+
+ if not best_lang:
+ # nothing found even for the default language, use non-localized or None
+ if non_localized_eulas:
+ best_eula = non_localized_eulas[0]
+ else:
+ return None
+ else:
+ # use first of the best-matching EULA files (there should be only one)
+ best_eula = glob.glob(LICENSE_FILE_GLOB + ("_%s" % best_lang))[0]
+
+ return best_eula
--
1.7.11.7
More information about the anaconda-patches
mailing list