Some refinements to the Menu infraestructure (#962)
* Correct definition of btrfs standard layout
* Solve issue #936
* make ask_for_a_timezone as synonym to ask_timezone
* Some refining in GeneralMenu
secret is now a general function
* Revert "Some refining in GeneralMenu"
This reverts commit e6e131cb19.
* New version of the FlexibleMenu
* Added new functionality to Selector
* Created a GeneralMenu class
* GlobalMenu is made a child of GeneralMenu
* Some refining in GeneralMenu
secret is now a general function
* log is invoked in GeneralMenu directly
* Materialize again _setup_selection_menu_options. Gives more room to play
* Callbacks converted as methods
Synch() (data area and menu) decoupled from enable()
and made general before any run
* Only_hd gets a new implementation of the menu
flake8 corrections
* New version of the FlexibleMenu
* Added new functionality to Selector
* Created a GeneralMenu class
* GlobalMenu is made a child of GeneralMenu
* changes from the rebase left dangling
* Adapt to PR #874
* Adapted to nationalization framework (PR 893).
String still NOT adapted
* flake8 complains
* Use of archinstall.output_config instead of local copy at swiss.py
* Problems with the last merge
* git complains
* Menu admits now preset values and cursor positioning
* Now GeneralMenu moves to the next entry after each selection
* flake8 complains
* Control of limits for cursor position at GeneralMenu
* Make auto cursor positioning optional at GeneralMenu.
True for GlobalMenu
* Code cleanup after rebase, and flake8 complains
This commit is contained in:
parent
18e033d2f0
commit
5990491292
|
|
@ -7,7 +7,7 @@ import sys
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
class Menu(TerminalMenu):
|
class Menu(TerminalMenu):
|
||||||
def __init__(self, title, p_options, skip=True, multi=False, default_option=None, sort=True):
|
def __init__(self, title, p_options, skip=True, multi=False, default_option=None, sort=True, preset_values=None, cursor_index=None):
|
||||||
"""
|
"""
|
||||||
Creates a new menu
|
Creates a new menu
|
||||||
|
|
||||||
|
|
@ -29,6 +29,12 @@ class Menu(TerminalMenu):
|
||||||
|
|
||||||
:param sort: Indicate if the options should be sorted alphabetically before displaying
|
:param sort: Indicate if the options should be sorted alphabetically before displaying
|
||||||
:type sort: bool
|
:type sort: bool
|
||||||
|
|
||||||
|
:param preset_values: Predefined value(s) of the menu. In a multi menu, it selects the options included therein. If the selection is simple, moves the cursor to the position of the value
|
||||||
|
:type preset_values: str or list
|
||||||
|
|
||||||
|
:param cursor_index: The position where the cursor will be located. If it is not in range (number of elements of the menu) it goes to the first position
|
||||||
|
:type cursor_index: int
|
||||||
"""
|
"""
|
||||||
# we guarantee the inmutability of the options outside the class.
|
# we guarantee the inmutability of the options outside the class.
|
||||||
# an unknown number of iterables (.keys(),.values(),generator,...) can't be directly copied, in this case
|
# an unknown number of iterables (.keys(),.values(),generator,...) can't be directly copied, in this case
|
||||||
|
|
@ -61,6 +67,7 @@ class Menu(TerminalMenu):
|
||||||
self.skip = skip
|
self.skip = skip
|
||||||
self.default_option = default_option
|
self.default_option = default_option
|
||||||
self.multi = multi
|
self.multi = multi
|
||||||
|
self.preselection(preset_values,cursor_index)
|
||||||
|
|
||||||
menu_title = f'\n{title}\n\n'
|
menu_title = f'\n{title}\n\n'
|
||||||
|
|
||||||
|
|
@ -86,7 +93,9 @@ class Menu(TerminalMenu):
|
||||||
cycle_cursor=True,
|
cycle_cursor=True,
|
||||||
clear_screen=True,
|
clear_screen=True,
|
||||||
multi_select=multi,
|
multi_select=multi,
|
||||||
show_search_hint=True
|
show_search_hint=True,
|
||||||
|
preselected_entries=self.preset_values,
|
||||||
|
cursor_index=self.cursor_index
|
||||||
)
|
)
|
||||||
|
|
||||||
def _show(self):
|
def _show(self):
|
||||||
|
|
@ -114,3 +123,36 @@ class Menu(TerminalMenu):
|
||||||
return self.run()
|
return self.run()
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def set_cursor_pos(self,pos :int):
|
||||||
|
if pos and 0 < pos < len(self._menu_entries):
|
||||||
|
self._view.active_menu_index = pos
|
||||||
|
else:
|
||||||
|
self._view.active_menu_index = 0 # we define a default
|
||||||
|
|
||||||
|
def set_cursor_pos_entry(self,value :str):
|
||||||
|
pos = self._menu_entries.index(value)
|
||||||
|
self.set_cursor_pos(pos)
|
||||||
|
|
||||||
|
def preselection(self,preset_values :list = [],cursor_index :int = None):
|
||||||
|
def from_preset_to_cursor():
|
||||||
|
if preset_values:
|
||||||
|
if isinstance(preset_values,str):
|
||||||
|
self.cursor_index = self.menu_options.index(preset_values)
|
||||||
|
else: # should return an error, but this is smoother
|
||||||
|
self.cursor_index = self.menu_options.index(preset_values[0])
|
||||||
|
|
||||||
|
self.preset_values = preset_values
|
||||||
|
self.cursor_index = cursor_index
|
||||||
|
if preset_values and cursor_index is None:
|
||||||
|
from_preset_to_cursor()
|
||||||
|
if preset_values and not self.multi: # Not supported by the infraestructure
|
||||||
|
self.preset_values = None
|
||||||
|
from_preset_to_cursor()
|
||||||
|
|
||||||
|
if self.default_option and self.multi:
|
||||||
|
if isinstance(preset_values,str) and self.default_option == preset_values:
|
||||||
|
self.preset_values = f"{preset_values} (default)"
|
||||||
|
elif isinstance(preset_values,(list,tuple)) and self.default_option in preset_values:
|
||||||
|
idx = preset_values.index(self.default_option)
|
||||||
|
self.preset_values[idx] = f"{preset_values[idx]} (default)"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import Callable, Any, List, Iterator
|
from typing import Callable, Any, List, Iterator
|
||||||
|
|
||||||
from .menu import Menu
|
from .menu import Menu
|
||||||
|
|
@ -32,7 +33,6 @@ from ..user_interaction import select_profile
|
||||||
from ..user_interaction import select_archinstall_language
|
from ..user_interaction import select_archinstall_language
|
||||||
from ..translation import Translation
|
from ..translation import Translation
|
||||||
|
|
||||||
|
|
||||||
class Selector:
|
class Selector:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -165,19 +165,22 @@ class Selector:
|
||||||
if status and not self.is_enabled():
|
if status and not self.is_enabled():
|
||||||
self.set_enabled(True)
|
self.set_enabled(True)
|
||||||
|
|
||||||
|
|
||||||
class GeneralMenu:
|
class GeneralMenu:
|
||||||
def __init__(self, data_store :dict = None):
|
def __init__(self, data_store :dict = None, auto_cursor=False):
|
||||||
"""
|
"""
|
||||||
Create a new selection menu.
|
Create a new selection menu.
|
||||||
|
|
||||||
:param data_store: Area (Dict) where the resulting data will be held. At least an entry for each option. Default area is self._data_store (not preset in the call, due to circular references
|
:param data_store: Area (Dict) where the resulting data will be held. At least an entry for each option. Default area is self._data_store (not preset in the call, due to circular references
|
||||||
:type data_store: Dict
|
:type data_store: Dict
|
||||||
|
|
||||||
|
:param auto_cursor: Boolean which determines if the cursor stays on the first item (false) or steps each invocation of a selection entry (true)
|
||||||
|
:type auto_cursor: bool
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._translation = Translation.load_nationalization()
|
self._translation = Translation.load_nationalization()
|
||||||
self.is_context_mgr = False
|
self.is_context_mgr = False
|
||||||
self._data_store = data_store if data_store is not None else {}
|
self._data_store = data_store if data_store is not None else {}
|
||||||
|
self.auto_cursor = auto_cursor
|
||||||
self._menu_options = {}
|
self._menu_options = {}
|
||||||
self._setup_selection_menu_options()
|
self._setup_selection_menu_options()
|
||||||
|
|
||||||
|
|
@ -247,14 +250,18 @@ class GeneralMenu:
|
||||||
# we synch all the options just in case
|
# we synch all the options just in case
|
||||||
for item in self.list_options():
|
for item in self.list_options():
|
||||||
self.synch(item)
|
self.synch(item)
|
||||||
|
cursor_pos = None
|
||||||
while True:
|
while True:
|
||||||
# Before continuing, set the preferred keyboard layout/language in the current terminal.
|
# Before continuing, set the preferred keyboard layout/language in the current terminal.
|
||||||
# This will just help the user with the next following questions.
|
# This will just help the user with the next following questions.
|
||||||
self._set_kb_language()
|
self._set_kb_language()
|
||||||
enabled_menus = self._menus_to_enable()
|
enabled_menus = self._menus_to_enable()
|
||||||
menu_text = [m.text for m in enabled_menus.values()]
|
menu_text = [m.text for m in enabled_menus.values()]
|
||||||
selection = Menu('Set/Modify the below options', menu_text, sort=False).run()
|
selection = Menu('Set/Modify the below options', menu_text, sort=False, cursor_index=cursor_pos).run()
|
||||||
if selection:
|
if selection and self.auto_cursor:
|
||||||
|
cursor_pos = menu_text.index(selection) + 1 # before the strip otherwise fails
|
||||||
|
if cursor_pos >= len(menu_text):
|
||||||
|
cursor_pos = len(menu_text) - 1
|
||||||
selection = selection.strip()
|
selection = selection.strip()
|
||||||
if selection:
|
if selection:
|
||||||
# if this calls returns false, we exit the menu. We allow for an callback for special processing on realeasing control
|
# if this calls returns false, we exit the menu. We allow for an callback for special processing on realeasing control
|
||||||
|
|
@ -294,6 +301,7 @@ class GeneralMenu:
|
||||||
|
|
||||||
result = None
|
result = None
|
||||||
if selector.func:
|
if selector.func:
|
||||||
|
# TODO insert code to allow selector functions with preset value
|
||||||
result = selector.func()
|
result = selector.func()
|
||||||
self._menu_options[selector_name].set_current_selection(result)
|
self._menu_options[selector_name].set_current_selection(result)
|
||||||
self._data_store[selector_name] = result
|
self._data_store[selector_name] = result
|
||||||
|
|
@ -399,7 +407,7 @@ class GeneralMenu:
|
||||||
|
|
||||||
class GlobalMenu(GeneralMenu):
|
class GlobalMenu(GeneralMenu):
|
||||||
def __init__(self,data_store):
|
def __init__(self,data_store):
|
||||||
super().__init__(data_store=data_store)
|
super().__init__(data_store=data_store, auto_cursor=True)
|
||||||
|
|
||||||
def _setup_selection_menu_options(self):
|
def _setup_selection_menu_options(self):
|
||||||
self._menu_options['archinstall-language'] = \
|
self._menu_options['archinstall-language'] = \
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue