archinstall/archinstall/lib/profile/profile_menu.py

224 lines
6.8 KiB
Python

from typing import override
from archinstall.default_profiles.profile import GreeterType, Profile
from archinstall.lib.general.system_menu import select_driver
from archinstall.lib.hardware import GfxDriver
from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.models.profile import ProfileConfiguration
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
def __init__(
self,
preset: ProfileConfiguration | None = None,
):
if preset:
self._profile_config = preset
else:
self._profile_config = ProfileConfiguration()
menu_options = self._define_menu_options()
self._item_group = MenuItemGroup(menu_options, checkmarks=True)
super().__init__(
self._item_group,
self._profile_config,
allow_reset=True,
)
def _define_menu_options(self) -> list[MenuItem]:
return [
MenuItem(
text=tr('Type'),
action=self._select_profile,
value=self._profile_config.profile,
preview_action=self._preview_profile,
key='profile',
),
MenuItem(
text=tr('Graphics driver'),
action=self._select_gfx_driver,
value=self._profile_config.gfx_driver if self._profile_config.profile and self._profile_config.profile.is_graphic_driver_supported() else None,
preview_action=self._prev_gfx,
enabled=self._profile_config.profile.is_graphic_driver_supported() if self._profile_config.profile else False,
dependencies=['profile'],
key='gfx_driver',
),
MenuItem(
text=tr('Greeter'),
action=lambda x: select_greeter(preset=x),
value=self._profile_config.greeter if self._profile_config.profile and self._profile_config.profile.is_greeter_supported() else None,
enabled=self._profile_config.profile.is_graphic_driver_supported() if self._profile_config.profile else False,
preview_action=self._prev_greeter,
dependencies=['profile'],
key='greeter',
),
]
@override
async def show(self) -> ProfileConfiguration | None:
return await super().show()
async def _select_profile(self, preset: Profile | None) -> Profile | None:
profile = await select_profile(preset)
if profile is not None:
if not profile.is_graphic_driver_supported():
self._item_group.find_by_key('gfx_driver').enabled = False
self._item_group.find_by_key('gfx_driver').value = None
else:
self._item_group.find_by_key('gfx_driver').enabled = True
self._item_group.find_by_key('gfx_driver').value = GfxDriver.AllOpenSource
if not profile.is_greeter_supported():
self._item_group.find_by_key('greeter').enabled = False
self._item_group.find_by_key('greeter').value = None
else:
self._item_group.find_by_key('greeter').enabled = True
self._item_group.find_by_key('greeter').value = profile.default_greeter_type
else:
self._item_group.find_by_key('gfx_driver').value = None
self._item_group.find_by_key('greeter').value = None
return profile
async def _select_gfx_driver(self, preset: GfxDriver | None = None) -> GfxDriver | None:
driver = preset
profile: Profile | None = self._item_group.find_by_key('profile').value
if profile:
if profile.is_graphic_driver_supported():
driver = await select_driver(preset=preset)
if driver and 'Sway' in profile.current_selection_names():
if driver.is_nvidia_proprietary():
header = tr('The proprietary Nvidia driver is not supported by Sway.') + '\n'
header += tr('It is likely that you will run into issues, are you okay with that?') + '\n'
result = await Confirmation(
header=header,
allow_skip=False,
preset=False,
).show()
return driver if result.get_value() else preset
return driver
def _prev_gfx(self, item: MenuItem) -> str | None:
if item.value:
driver = item.get_value().value
packages = item.get_value().packages_text()
return f'Driver: {driver}\n{packages}'
return None
def _prev_greeter(self, item: MenuItem) -> str | None:
if item.value:
return f'{tr("Greeter")}: {item.value.value}'
return None
def _preview_profile(self, item: MenuItem) -> str | None:
profile: Profile | None = item.value
text = ''
if profile:
if (sub_profiles := profile.current_selection) is not None:
text += tr('Selected profiles: ')
text += ', '.join(p.name for p in sub_profiles) + '\n'
if packages := profile.packages_text(include_sub_packages=True):
text += f'{packages}'
if text:
return text
return None
async def select_greeter(
profile: Profile | None = None,
preset: GreeterType | None = None,
) -> GreeterType | None:
if not profile or profile.is_greeter_supported():
items = [MenuItem(greeter.value, value=greeter) for greeter in GreeterType]
group = MenuItemGroup(items, sort_items=True)
default: GreeterType | None = None
if preset is not None:
default = preset
elif profile is not None:
default_greeter = profile.default_greeter_type
default = default_greeter if default_greeter else None
group.set_default_by_value(default)
result = await Selection[GreeterType](
group,
header=tr('Select which greeter to install'),
allow_skip=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.get_value()
case ResultType.Reset:
raise ValueError('Unhandled result type')
return None
async def select_profile(
current_profile: Profile | None = None,
header: str | None = None,
allow_reset: bool = True,
) -> Profile | None:
from archinstall.lib.profile.profiles_handler import profile_handler
top_level_profiles = profile_handler.get_top_level_profiles()
if header is None:
header = tr('Select a profile type')
items = [MenuItem(p.name, value=p) for p in top_level_profiles]
group = MenuItemGroup(items, sort_items=True)
group.set_selected_by_value(current_profile)
result = await Selection[Profile](
group,
header=header,
allow_reset=allow_reset,
allow_skip=True,
).show()
match result.type_:
case ResultType.Reset:
return None
case ResultType.Skip:
return current_profile
case ResultType.Selection:
profile_selection = result.get_value()
select_result = await profile_selection.do_on_select()
if not select_result:
return None
# we're going to reset the currently selected profile(s) to avoid
# any stale data laying around
match select_result:
case select_result.NewSelection:
profile_handler.reset_top_level_profiles(exclude=[profile_selection])
current_profile = profile_selection
case select_result.ResetCurrent:
profile_handler.reset_top_level_profiles()
current_profile = None
case select_result.SameSelection:
pass
return current_profile