Move install summary into ConfigurationOutput

The summary helper that renders the install preview's two-column
configuration overview lived in GlobalMenu. Move it to
ConfigurationOutput.as_summary() so it sits alongside the JSON
output methods that share the same role. The preview now syncs
menu state to ArchConfig and delegates rendering.
This commit is contained in:
Softer 2026-04-26 17:20:20 +03:00
parent ce5ca8c682
commit bd6fc86732
2 changed files with 69 additions and 66 deletions

View File

@ -10,6 +10,8 @@ from archinstall.lib.args import ArchConfig
from archinstall.lib.crypt import encrypt
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.menu.util import get_password, prompt_dir
from archinstall.lib.models.bootloader import Bootloader
from archinstall.lib.models.network import NetworkConfiguration
from archinstall.lib.output import debug, logger, warn
from archinstall.lib.translationhandler import tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
@ -58,6 +60,70 @@ class ConfigurationOutput:
debug(' -- Chosen configuration --')
debug(self.user_config_to_json())
def as_summary(self) -> str:
"""
Render a concise two-column summary of the current configuration.
The left column holds section labels, the right column holds values.
Column width adapts to the longest translated label so translations
do not break the alignment. Rows whose underlying config is not set
are skipped.
Returns an empty string if nothing meaningful to show.
"""
rows: list[tuple[str, str]] = []
disk_config = self._config.disk_config
if disk_config and disk_config.device_modifications:
disk_parts: list[str] = []
for mod in disk_config.device_modifications:
path = str(mod.device_path)
root_part = mod.get_root_partition()
flags: list[str] = []
if root_part and root_part.fs_type:
flags.append(root_part.fs_type.value)
if disk_config.disk_encryption:
flags.append(tr('LUKS'))
disk_parts.append(f'{path} ({" + ".join(flags)})' if flags else path)
rows.append((tr('Disks'), ', '.join(disk_parts)))
bl_config = self._config.bootloader_config
if bl_config and bl_config.bootloader != Bootloader.NO_BOOTLOADER:
rows.append((tr('Bootloader'), bl_config.bootloader.value))
kernels = self._config.kernels
if kernels:
rows.append((tr('Kernel'), ', '.join(kernels)))
profile_config = self._config.profile_config
if profile_config and profile_config.profile:
names = profile_config.profile.current_selection_names()
rows.append((tr('Profile'), ', '.join(names) if names else profile_config.profile.name))
if profile_config.greeter:
rows.append((tr('Greeter'), profile_config.greeter.value))
packages = self._config.packages
if packages:
rows.append((tr('Packages'), str(len(packages))))
net_config = self._config.network_config
if isinstance(net_config, NetworkConfiguration):
rows.append((tr('Network'), net_config.type.display_msg()))
locale_config = self._config.locale_config
if locale_config:
rows.append((tr('Locale'), locale_config.sys_lang))
tz = self._config.timezone
if tz:
rows.append((tr('Timezone'), tz))
if not rows:
return ''
label_width = max(len(label) for label, _ in rows) + 2
return '\n'.join(f'{label:<{label_width}}{value}' for label, value in rows)
async def confirm_config(self) -> bool:
header = f'{tr("The specified configuration will be applied")}. '
header += tr('Would you like to continue?') + '\n'

View File

@ -6,7 +6,7 @@ from archinstall.lib.args import ArchConfig
from archinstall.lib.authentication.authentication_menu import AuthenticationMenu
from archinstall.lib.bootloader.bootloader_menu import BootloaderMenu
from archinstall.lib.bootloader.utils import validate_bootloader_layout
from archinstall.lib.configuration import save_config
from archinstall.lib.configuration import ConfigurationOutput, save_config
from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu
from archinstall.lib.general.general_menu import select_hostname, select_ntp, select_timezone
from archinstall.lib.general.system_menu import select_kernel, select_swap
@ -498,70 +498,6 @@ class GlobalMenu(AbstractMenu[None]):
return None
def _install_summary(self) -> str:
"""
Render a concise two-column summary of the current install configuration.
The left column holds section labels, the right column holds values.
Column width adapts to the longest translated label so translations
do not break the alignment. Rows whose underlying config is not set
are skipped.
Returns an empty string if nothing meaningful to show.
"""
rows: list[tuple[str, str]] = []
disk_config: DiskLayoutConfiguration | None = self._item_group.find_by_key('disk_config').value
if disk_config and disk_config.device_modifications:
disk_parts: list[str] = []
for mod in disk_config.device_modifications:
path = str(mod.device_path)
root_part = mod.get_root_partition()
flags: list[str] = []
if root_part and root_part.fs_type:
flags.append(root_part.fs_type.value)
if disk_config.disk_encryption:
flags.append(tr('LUKS'))
disk_parts.append(f'{path} ({" + ".join(flags)})' if flags else path)
rows.append((tr('Disks'), ', '.join(disk_parts)))
bl_config: BootloaderConfiguration | None = self._item_group.find_by_key('bootloader_config').value
if bl_config and bl_config.bootloader != Bootloader.NO_BOOTLOADER:
rows.append((tr('Bootloader'), bl_config.bootloader.value))
kernels: list[str] | None = self._item_group.find_by_key('kernels').value
if kernels:
rows.append((tr('Kernel'), ', '.join(kernels)))
profile_config: ProfileConfiguration | None = self._item_group.find_by_key('profile_config').value
if profile_config and profile_config.profile:
names = profile_config.profile.current_selection_names()
rows.append((tr('Profile'), ', '.join(names) if names else profile_config.profile.name))
if profile_config.greeter:
rows.append((tr('Greeter'), profile_config.greeter.value))
packages: list[str] | None = self._item_group.find_by_key('packages').value
if packages:
rows.append((tr('Packages'), str(len(packages))))
net_config = self._item_group.find_by_key('network_config').value
if isinstance(net_config, NetworkConfiguration):
rows.append((tr('Network'), net_config.type.display_msg()))
locale_config: LocaleConfiguration | None = self._item_group.find_by_key('locale_config').value
if locale_config:
rows.append((tr('Locale'), locale_config.sys_lang))
tz = self._item_group.find_by_key('timezone').value
if tz:
rows.append((tr('Timezone'), tz))
if not rows:
return ''
label_width = max(len(label) for label, _ in rows) + 2
return '\n'.join(f'{label:<{label_width}}{value}' for label, value in rows)
def _prev_install_invalid_config(self, item: MenuItem) -> str | None:
if missing := self._missing_configs():
text = tr('Missing configurations:\n')
@ -572,7 +508,8 @@ class GlobalMenu(AbstractMenu[None]):
if error := self._validate_bootloader():
return tr(f'Invalid configuration: {error}')
summary = self._install_summary()
self.sync_all_to_config()
summary = ConfigurationOutput(self._arch_config).as_summary()
if summary:
return f'{tr("Ready to install")}\n\n{summary}'
return tr('Ready to install')