283 lines
6.7 KiB
Python
283 lines
6.7 KiB
Python
"""WizardKit: Setup - Windows"""
|
|
# vim: sts=2 sw=2 ts=2
|
|
|
|
import logging
|
|
import os
|
|
import platform
|
|
import re
|
|
import sys
|
|
import time
|
|
|
|
from subprocess import CalledProcessError, DEVNULL
|
|
|
|
from wk.cfg.main import KIT_NAME_FULL, KIT_NAME_SHORT
|
|
from wk.exe import (
|
|
get_procs,
|
|
run_program,
|
|
popen_program,
|
|
wait_for_procs,
|
|
)
|
|
from wk.io import (
|
|
delete_folder,
|
|
get_path_obj,
|
|
non_clobber_path,
|
|
rename_item,
|
|
)
|
|
from wk.kit.tools import (
|
|
ARCH,
|
|
download_tool,
|
|
extract_tool,
|
|
get_tool_path,
|
|
run_tool,
|
|
)
|
|
from wk.log import format_log_path, update_log_path
|
|
from wk.os.win import (
|
|
reg_delete_value,
|
|
reg_read_value,
|
|
reg_set_value,
|
|
reg_write_settings,
|
|
disable_service,
|
|
enable_service,
|
|
stop_service,
|
|
)
|
|
from wk.repairs.win import (
|
|
auto_backup_registry,
|
|
auto_backup_browser_profiles,
|
|
auto_backup_power_plans,
|
|
auto_reset_power_plans,
|
|
auto_set_custom_power_plan,
|
|
auto_enable_regback,
|
|
auto_system_restore_enable,
|
|
auto_system_restore_set_size,
|
|
auto_system_restore_create,
|
|
auto_windows_updates_enable,
|
|
)
|
|
from wk.std import (
|
|
GenericError,
|
|
GenericWarning,
|
|
Menu,
|
|
TryAndPrint,
|
|
abort,
|
|
ask,
|
|
clear_screen,
|
|
color_string,
|
|
pause,
|
|
print_info,
|
|
print_standard,
|
|
print_warning,
|
|
set_title,
|
|
show_data,
|
|
sleep,
|
|
strip_colors,
|
|
)
|
|
|
|
|
|
# STATIC VARIABLES
|
|
LOG = logging.getLogger(__name__)
|
|
CONEMU_EXE = get_tool_path('ConEmu', 'ConEmu', check=False)
|
|
IN_CONEMU = 'ConEmuPID' in os.environ
|
|
MENU_PRESETS = Menu()
|
|
PROGRAMFILES_32 = os.environ.get(
|
|
'PROGRAMFILES(X86)', os.environ.get(
|
|
'PROGRAMFILES', r'C:\Program Files (x86)',
|
|
),
|
|
)
|
|
OS_VERSION = float(platform.win32_ver()[0])
|
|
SYSTEMDRIVE = os.environ.get('SYSTEMDRIVE', 'C:')
|
|
WIDTH = 50
|
|
TRY_PRINT = TryAndPrint()
|
|
TRY_PRINT.width = WIDTH
|
|
TRY_PRINT.verbose = True
|
|
for error in ('CalledProcessError', 'FileNotFoundError'):
|
|
TRY_PRINT.add_error(error)
|
|
|
|
|
|
# Auto Setup
|
|
def build_menus(base_menus, title, presets):
|
|
"""Build menus, returns dict."""
|
|
menus = {}
|
|
menus['Main'] = Menu(title=f'{title}\n{color_string("Main Menu", "GREEN")}')
|
|
|
|
# Main Menu
|
|
for entry in base_menus['Actions']:
|
|
menus['Main'].add_action(entry.name, entry.details)
|
|
for group in base_menus['Groups']:
|
|
menus['Main'].add_option(group, {'Selected': True})
|
|
|
|
# Run groups
|
|
for group, entries in base_menus['Groups'].items():
|
|
menus[group] = Menu(title=f'{title}\n{color_string(group, "GREEN")}')
|
|
for entry in entries:
|
|
menus[group].add_option(entry.name, entry.details)
|
|
menus[group].add_action('All')
|
|
menus[group].add_action('None')
|
|
menus[group].add_action('Main Menu', {'Separator': True})
|
|
menus[group].add_action('Quit')
|
|
|
|
# Initialize main menu display names
|
|
menus['Main'].update()
|
|
|
|
# Fix Function references
|
|
for group, menu in menus.items():
|
|
if group not in base_menus['Groups']:
|
|
continue
|
|
for name in menu.options:
|
|
_function = menu.options[name]['Function']
|
|
if isinstance(_function, str):
|
|
menu.options[name]['Function'] = getattr(
|
|
sys.modules[__name__], _function,
|
|
)
|
|
|
|
# Update presets Menu
|
|
MENU_PRESETS.title = f'{title}\n{color_string("Load Preset", "GREEN")}'
|
|
MENU_PRESETS.add_option('Default')
|
|
for name in presets:
|
|
MENU_PRESETS.add_option(name)
|
|
MENU_PRESETS.add_action('Main Menu')
|
|
MENU_PRESETS.add_action('Quit')
|
|
MENU_PRESETS.update()
|
|
|
|
# Done
|
|
return menus
|
|
|
|
|
|
def load_preset(menus, presets):
|
|
"""Load menu settings from preset."""
|
|
selection = MENU_PRESETS.simple_select()
|
|
|
|
# Exit early
|
|
if 'Main Menu' in selection:
|
|
return
|
|
if 'Quit' in selection:
|
|
raise SystemExit
|
|
|
|
# Default case
|
|
if 'Default' in selection:
|
|
for menu in menus.values():
|
|
for name in menu.options:
|
|
menu.options[name]['Selected'] = True
|
|
return
|
|
|
|
# Load preset
|
|
preset = presets[selection[0]]
|
|
for group, menu in menus.items():
|
|
group_enabled = group in preset
|
|
for name in menu.options:
|
|
value = group_enabled and name in preset[group]
|
|
menu.options[name]['Selected'] = value
|
|
|
|
|
|
def run_auto_setup(base_menus, presets):
|
|
"""Run Auto Setup."""
|
|
update_log_path(dest_name='Auto Setup', timestamp=True)
|
|
title = f'{KIT_NAME_FULL}: Auto Setup'
|
|
clear_screen()
|
|
set_title(title)
|
|
print_info(title)
|
|
print('')
|
|
|
|
# Generate menus
|
|
print_standard('Initializing...')
|
|
menus = build_menus(base_menus, title, presets)
|
|
|
|
# Show Menu
|
|
show_main_menu(base_menus, menus, presets)
|
|
|
|
# Start setup
|
|
clear_screen()
|
|
print_standard(title)
|
|
print('')
|
|
print_info('Running setup')
|
|
|
|
# Run setup
|
|
for group, menu in menus.items():
|
|
if group in ('Main', 'Options'):
|
|
continue
|
|
try:
|
|
run_group(group, menu)
|
|
except KeyboardInterrupt:
|
|
abort()
|
|
|
|
# Done
|
|
print_info('Done')
|
|
pause('Press Enter to exit...')
|
|
|
|
|
|
def run_group(group, menu):
|
|
"""Run entries in group if appropriate."""
|
|
print_info(f' {group}')
|
|
for name, details in menu.options.items():
|
|
name_str = strip_colors(name)
|
|
|
|
# Not selected
|
|
if not details.get('Selected', False):
|
|
show_data(f'{name_str}...', 'Skipped', 'YELLOW', width=WIDTH)
|
|
continue
|
|
|
|
# Selected
|
|
details['Function'](group, name)
|
|
|
|
|
|
def show_main_menu(base_menus, menus, presets):
|
|
"""Show main menu and handle actions."""
|
|
while True:
|
|
update_main_menu(menus)
|
|
selection = menus['Main'].simple_select(update=False)
|
|
if selection[0] in base_menus['Groups'] or selection[0] == 'Options':
|
|
show_sub_menu(menus[selection[0]])
|
|
if selection[0] == 'Load Preset':
|
|
load_preset(menus, presets)
|
|
elif 'Start' in selection:
|
|
break
|
|
elif 'Quit' in selection:
|
|
raise SystemExit
|
|
|
|
|
|
def show_sub_menu(menu):
|
|
"""Show sub-menu and handle sub-menu actions."""
|
|
while True:
|
|
selection = menu.advanced_select()
|
|
if 'Main Menu' in selection:
|
|
break
|
|
if 'Quit' in selection:
|
|
raise SystemExit
|
|
|
|
# Select all or none
|
|
value = 'All' in selection
|
|
for name in menu.options:
|
|
if not menu.options[name].get('Disabled', False):
|
|
menu.options[name]['Selected'] = value
|
|
|
|
|
|
def update_main_menu(menus):
|
|
"""Update main menu based on current selections."""
|
|
index = 1
|
|
skip = 'Reboot'
|
|
for name in menus['Main'].options:
|
|
checkmark = ' '
|
|
selected = [
|
|
_v['Selected'] for _k, _v in menus[name].options.items() if _k != skip
|
|
]
|
|
if all(selected):
|
|
checkmark = '✓'
|
|
elif any(selected):
|
|
checkmark = '-'
|
|
display_name = f' {index}: [{checkmark}] {name}'
|
|
index += 1
|
|
menus['Main'].options[name]['Display Name'] = display_name
|
|
|
|
|
|
# Auto Setup: Wrapper Functions
|
|
## TODO
|
|
|
|
# Misc Functions
|
|
## TODO?
|
|
|
|
# Tool Functions
|
|
## TODO?
|
|
|
|
# OS Built-in Functions
|
|
## TODO?
|
|
|
|
if __name__ == '__main__':
|
|
print("This file is not meant to be called directly.")
|