From 5dbb215f54902b69d9bcd6ec159fdd03a1992e3c Mon Sep 17 00:00:00 2001 From: Mirko Brombin Date: Sat, 1 Oct 2022 19:04:48 +0200 Subject: [PATCH] parser: add support for warps and and no selection when using preferences template, without_selection can be used to alert the user; if False, a toast notification will be displayed preventing the navigation. warps can be used to run a command given a condition from another step; only supported by without_selection in the preferences template --- recipe.json | 14 +++++++++ vanilla_first_setup/gtk/window.ui | 16 +++++++---- vanilla_first_setup/layouts/preferences.py | 27 +++++++++++++++++- vanilla_first_setup/utils/parser.py | 33 +++++++++++++++++++++- vanilla_first_setup/window.py | 6 ++++ 5 files changed, 88 insertions(+), 8 deletions(-) diff --git a/recipe.json b/recipe.json index 8501888..926513b 100644 --- a/recipe.json +++ b/recipe.json @@ -14,6 +14,20 @@ "icon": "vanilla-package-symbolic", "title": "Package Manager", "description": "Choose one or more package managers to install", + "without_selection": { + "allowed": true, + "message": "You have chosen not to install any package manager, you will only be able to install packages using apx.\n\nGNOME Software will be disabled if you choose to enable the immutability feature later.", + "title": "No package manager selected", + "final": [ + { + "if": "warp::immutability", + "type": "command", + "commands": [ + "sudo apt remove -y gnome-software" + ] + } + ] + }, "preferences": [ { "id": "flatpak", diff --git a/vanilla_first_setup/gtk/window.ui b/vanilla_first_setup/gtk/window.ui index a386a99..7d1b6fe 100644 --- a/vanilla_first_setup/gtk/window.ui +++ b/vanilla_first_setup/gtk/window.ui @@ -30,12 +30,16 @@ - - True - True - False - False - False + + + + True + True + False + False + False + + diff --git a/vanilla_first_setup/layouts/preferences.py b/vanilla_first_setup/layouts/preferences.py index f44b430..55cf954 100644 --- a/vanilla_first_setup/layouts/preferences.py +++ b/vanilla_first_setup/layouts/preferences.py @@ -18,6 +18,7 @@ import time from gi.repository import Gtk, Gio, GLib, Adw from vanilla_first_setup.utils.run_async import RunAsync +from vanilla_first_setup.dialog import VanillaDialog @Gtk.Template(resource_path='/io/github/vanilla-os/FirstSetup/gtk/layout-preferences.ui') @@ -38,7 +39,7 @@ class VanillaLayoutPreferences(Adw.Bin): self.__build_ui() # signals - self.btn_next.connect("clicked", self.__window.next) + self.btn_next.connect("clicked", self.__next_step) def __build_ui(self): self.status_page.set_icon_name(self.__step["icon"]) @@ -58,11 +59,35 @@ class VanillaLayoutPreferences(Adw.Bin): self.prefs_list.add(_action_row) self.__register_widgets.append((item["id"], _switcher)) + + def __next_step(self, widget): + ws = self.__step.get("without_selection", {}) + + if not any([x[1].get_active() for x in self.__register_widgets]): + if not ws.get("allowed", True): + self.__window.toast("Please select at least one option.") + return + + if ws.get("message", None): + dialog = VanillaDialog( + self.__window, + ws.get("title", "No selection"), + ws.get("message"), + ) + dialog.show() + self.__window.next() def get_finals(self): + ws = self.__step.get("without_selection", {}) finals = {"vars": {}, "funcs": [x for x in self.__step["final"]]} for _id, switcher in self.__register_widgets: finals["vars"][_id] = switcher.get_active() + if not any([x[1].get_active() for x in self.__register_widgets]) \ + and ws.get("allowed", True) \ + and ws.get("final", None): + finals["vars"]["_managed"] = True + finals["funcs"].extend(ws["final"]) + return finals diff --git a/vanilla_first_setup/utils/parser.py b/vanilla_first_setup/utils/parser.py index 8299251..211874c 100644 --- a/vanilla_first_setup/utils/parser.py +++ b/vanilla_first_setup/utils/parser.py @@ -29,12 +29,22 @@ class Parser: @staticmethod def parse(finals): commands = [] + warps = [] + all_vars = [] for final in finals: if len(final) == 0: continue _vars = final["vars"] + for k, v in _vars.items(): + if k in all_vars: + logger.error( + f"variable {k} is defined multiple times") + sys.exit(1) + if not v: + continue + all_vars.append(k) for _func in final["funcs"]: @@ -42,7 +52,7 @@ class Parser: logger.critical(f"Missing an 'if' operand in {_func}") sys.exit(1) - if _func["if"] not in _vars: + if _func["if"] not in _vars and not _func["if"].startswith("warp::"): logger.critical( f"Missing a variable named '{_func['if']}' in the 'vars' section.") sys.exit(1) @@ -52,11 +62,32 @@ class Parser: f"Unsupported final type: {_func.get('type')}") sys.exit(1) + if _func["if"].startswith("warp::"): + _var = _func["if"].split("::")[1] + warps.append({ + "vars": [_var], + "func": [_func] + }) + continue + # assume True if no condition is given _condition = _func.get("condition", True) # check if the condition is met if _condition == _vars[_func["if"]]: commands += _func["commands"] + + # set-up warps if any + for warp in warps: + _vars = warp["vars"] + + for var in _vars: + if var not in all_vars: + continue + + for _func in warp["func"]: + _if = _func["if"].split("::")[1] + if _if in all_vars: + commands += _func["commands"] return commands diff --git a/vanilla_first_setup/window.py b/vanilla_first_setup/window.py index 43d246e..9330aaf 100644 --- a/vanilla_first_setup/window.py +++ b/vanilla_first_setup/window.py @@ -32,6 +32,7 @@ class VanillaWindow(Adw.ApplicationWindow): carousel = Gtk.Template.Child() btn_back = Gtk.Template.Child() + toasts = Gtk.Template.Child() def __init__(self, **kwargs): super().__init__(**kwargs) @@ -102,3 +103,8 @@ class VanillaWindow(Adw.ApplicationWindow): cur_index = self.carousel.get_position() page = self.carousel.get_nth_page(cur_index - 1) self.carousel.scroll_to(page, True) + + def toast(self, message, timeout=3): + toast = Adw.Toast.new(message) + toast.props.timeout = timeout + self.toasts.add_toast(toast)