mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-24 00:03:42 +05:00
feat: implement functions of SettingsMenu
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
@@ -166,7 +166,7 @@ class MainMenu(BaseMenu):
|
||||
BackupMenu(previous_menu=self.__class__).run()
|
||||
|
||||
def settings_menu(self, **kwargs):
|
||||
SettingsMenu().run()
|
||||
SettingsMenu(previous_menu=self.__class__).run()
|
||||
|
||||
def extension_menu(self, **kwargs):
|
||||
ExtensionsMenu(previous_menu=self.__class__).run()
|
||||
|
||||
@@ -6,16 +6,37 @@
|
||||
# #
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||
# ======================================================================= #
|
||||
from typing import Type, Optional
|
||||
import shutil
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
from typing import Type, Optional, Tuple
|
||||
|
||||
from components.klipper import KLIPPER_DIR
|
||||
from components.klipper.klipper import Klipper
|
||||
from components.moonraker import MOONRAKER_DIR
|
||||
from components.moonraker.moonraker import Moonraker
|
||||
from core.instance_manager.instance_manager import InstanceManager
|
||||
from core.menus import Option
|
||||
from core.menus.base_menu import BaseMenu
|
||||
from core.repo_manager.repo_manager import RepoManager
|
||||
from core.settings.kiauh_settings import KiauhSettings
|
||||
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_GREEN, COLOR_YELLOW
|
||||
from utils.input_utils import get_string_input, get_confirm
|
||||
from utils.logger import Logger
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class SettingsMenu(BaseMenu):
|
||||
def __init__(self, previous_menu: Optional[Type[BaseMenu]] = None):
|
||||
super().__init__()
|
||||
self.previous_menu = previous_menu
|
||||
self.klipper_repo = None
|
||||
self.moonraker_repo = None
|
||||
self.mainsail_unstable = None
|
||||
self.fluidd_unstable = None
|
||||
self.auto_backups_enabled = None
|
||||
self._load_settings()
|
||||
|
||||
def set_previous_menu(self, previous_menu: Optional[Type[BaseMenu]]) -> None:
|
||||
from core.menus.main_menu import MainMenu
|
||||
@@ -25,19 +46,183 @@ class SettingsMenu(BaseMenu):
|
||||
)
|
||||
|
||||
def set_options(self) -> None:
|
||||
pass
|
||||
self.options = {
|
||||
"1": Option(method=self.set_klipper_repo, menu=True),
|
||||
"2": Option(method=self.set_moonraker_repo, menu=True),
|
||||
"3": Option(method=self.toggle_mainsail_release, menu=True),
|
||||
"4": Option(method=self.toggle_fluidd_release, menu=False),
|
||||
"5": Option(method=self.toggle_backup_before_update, menu=False),
|
||||
}
|
||||
|
||||
def print_menu(self):
|
||||
print("self")
|
||||
header = " [ KIAUH Settings ] "
|
||||
color = COLOR_CYAN
|
||||
count = 62 - len(color) - len(RESET_FORMAT)
|
||||
checked = f"[{COLOR_GREEN}x{RESET_FORMAT}]"
|
||||
unchecked = "[ ]"
|
||||
o1 = checked if self.mainsail_unstable else unchecked
|
||||
o2 = checked if self.fluidd_unstable else unchecked
|
||||
o3 = checked if self.auto_backups_enabled else unchecked
|
||||
menu = textwrap.dedent(
|
||||
f"""
|
||||
/=======================================================\\
|
||||
| {color}{header:~^{count}}{RESET_FORMAT} |
|
||||
|-------------------------------------------------------|
|
||||
| Klipper source repository: |
|
||||
| ● {self.klipper_repo:<67} |
|
||||
| |
|
||||
| Moonraker source repository: |
|
||||
| ● {self.moonraker_repo:<67} |
|
||||
| |
|
||||
| Install unstable Webinterface releases: |
|
||||
| {o1} Mainsail |
|
||||
| {o2} Fluidd |
|
||||
| |
|
||||
| Auto-Backup: |
|
||||
| {o3} Automatic backup before update |
|
||||
| |
|
||||
|-------------------------------------------------------|
|
||||
| 1) Set Klipper source repository |
|
||||
| 2) Set Moonraker source repository |
|
||||
| |
|
||||
| 3) Toggle unstable Mainsail releases |
|
||||
| 4) Toggle unstable Fluidd releases |
|
||||
| |
|
||||
| 5) Toggle automatic backups before updates |
|
||||
"""
|
||||
)[1:]
|
||||
print(menu, end="")
|
||||
|
||||
def execute_option_p(self):
|
||||
# Implement the functionality for Option P
|
||||
print("Executing Option P")
|
||||
def _load_settings(self):
|
||||
self.kiauh_settings = KiauhSettings()
|
||||
|
||||
def execute_option_q(self):
|
||||
# Implement the functionality for Option Q
|
||||
print("Executing Option Q")
|
||||
self._format_repo_str("klipper")
|
||||
self._format_repo_str("moonraker")
|
||||
|
||||
def execute_option_r(self):
|
||||
# Implement the functionality for Option R
|
||||
print("Executing Option R")
|
||||
self.auto_backups_enabled = self.kiauh_settings.get(
|
||||
"kiauh", "backup_before_update"
|
||||
)
|
||||
self.mainsail_unstable = self.kiauh_settings.get(
|
||||
"mainsail", "unstable_releases"
|
||||
)
|
||||
self.fluidd_unstable = self.kiauh_settings.get("fluidd", "unstable_releases")
|
||||
|
||||
def _format_repo_str(self, repo_name: str) -> None:
|
||||
repo = self.kiauh_settings.get(repo_name, "repo_url")
|
||||
repo = f"{'/'.join(repo.rsplit('/', 2)[-2:])}"
|
||||
branch = self.kiauh_settings.get(repo_name, "branch")
|
||||
branch = f"({COLOR_CYAN}@ {branch}{RESET_FORMAT})"
|
||||
setattr(self, f"{repo_name}_repo", f"{COLOR_CYAN}{repo}{RESET_FORMAT} {branch}")
|
||||
|
||||
def _gather_input(self) -> Tuple[str, str]:
|
||||
l2 = "Make sure your input is correct!"
|
||||
error = textwrap.dedent(
|
||||
f"""\n
|
||||
{COLOR_YELLOW}/=======================================================\\
|
||||
| ATTENTION: |
|
||||
| There is no input validation in place! Make sure your |
|
||||
| input is valid and has no typos! For any change to |
|
||||
| take effect, the repository must be cloned again. |
|
||||
| Make sure you don't have any ongoing prints running, |
|
||||
| as the services will be restarted! |
|
||||
\=======================================================/{RESET_FORMAT}
|
||||
"""
|
||||
)[1:]
|
||||
print(error, end="\n")
|
||||
repo = get_string_input(
|
||||
"Enter new repository URL",
|
||||
allow_special_chars=True,
|
||||
)
|
||||
branch = get_string_input(
|
||||
"Enter new branch name",
|
||||
allow_special_chars=True,
|
||||
)
|
||||
|
||||
return repo, branch
|
||||
|
||||
def _display_summary(self, name: str, repo: str, branch: str):
|
||||
l1 = f"New {name} repository URL:"
|
||||
l2 = f"● {repo}"
|
||||
l3 = f"New {name} repository branch:"
|
||||
l4 = f"● {branch}"
|
||||
summary = textwrap.dedent(
|
||||
f"""\n
|
||||
/=======================================================\\
|
||||
| {l1:<52} |
|
||||
| {l2:<52} |
|
||||
| {l3:<52} |
|
||||
| {l4:<52} |
|
||||
\=======================================================/
|
||||
"""
|
||||
)[1:]
|
||||
print(summary, end="")
|
||||
|
||||
def _set_repo(self, repo_name: str):
|
||||
repo, branch = self._gather_input()
|
||||
self._display_summary(repo_name.capitalize(), repo, branch)
|
||||
|
||||
if get_confirm("Apply changes?", allow_go_back=True):
|
||||
self.kiauh_settings.set(repo_name, "repo_url", repo)
|
||||
self.kiauh_settings.set(repo_name, "branch", branch)
|
||||
self.kiauh_settings.save()
|
||||
self._load_settings()
|
||||
Logger.print_ok("Changes saved!")
|
||||
else:
|
||||
Logger.print_info(
|
||||
f"Skipping change of {repo_name.capitalize()} source repository ..."
|
||||
)
|
||||
return
|
||||
|
||||
Logger.print_status(
|
||||
f"Switching to {repo_name.capitalize()}'s new source repository ..."
|
||||
)
|
||||
self._switch_repo(repo_name)
|
||||
Logger.print_ok(f"Switched to {repo} at branch {branch}!")
|
||||
|
||||
def _switch_repo(self, name: str) -> None:
|
||||
target_dir: Path
|
||||
if name == "klipper":
|
||||
target_dir = KLIPPER_DIR
|
||||
_type = Klipper
|
||||
elif name == "moonraker":
|
||||
target_dir = MOONRAKER_DIR
|
||||
_type = Moonraker
|
||||
else:
|
||||
Logger.print_error("Invalid repository name!")
|
||||
return
|
||||
|
||||
if target_dir.exists():
|
||||
shutil.rmtree(target_dir)
|
||||
|
||||
im = InstanceManager(_type)
|
||||
im.stop_all_instance()
|
||||
|
||||
repo = self.kiauh_settings.get(name, "repo_url")
|
||||
branch = self.kiauh_settings.get(name, "branch")
|
||||
repman = RepoManager(repo, str(target_dir), branch)
|
||||
repman.clone_repo()
|
||||
|
||||
im.start_all_instance()
|
||||
|
||||
def set_klipper_repo(self, **kwargs):
|
||||
self._set_repo("klipper")
|
||||
|
||||
def set_moonraker_repo(self, **kwargs):
|
||||
self._set_repo("moonraker")
|
||||
|
||||
def toggle_mainsail_release(self, **kwargs):
|
||||
self.mainsail_unstable = not self.mainsail_unstable
|
||||
self.kiauh_settings.set("mainsail", "unstable_releases", self.mainsail_unstable)
|
||||
self.kiauh_settings.save()
|
||||
|
||||
def toggle_fluidd_release(self, **kwargs):
|
||||
self.fluidd_unstable = not self.fluidd_unstable
|
||||
self.kiauh_settings.set("fluidd", "unstable_releases", self.fluidd_unstable)
|
||||
self.kiauh_settings.save()
|
||||
|
||||
def toggle_backup_before_update(self, **kwargs):
|
||||
self.auto_backups_enabled = not self.auto_backups_enabled
|
||||
self.kiauh_settings.set(
|
||||
"kiauh", "backup_before_update", self.auto_backups_enabled
|
||||
)
|
||||
self.kiauh_settings.save()
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
|
||||
import textwrap
|
||||
import configparser
|
||||
from configparser import ConfigParser
|
||||
from typing import Dict, Union
|
||||
|
||||
from core.config_manager.config_manager import CustomConfigParser
|
||||
from kiauh import PROJECT_ROOT
|
||||
from utils.constants import RESET_FORMAT, COLOR_RED
|
||||
from utils.logger import Logger
|
||||
@@ -34,33 +35,32 @@ class KiauhSettings:
|
||||
if self.__initialized:
|
||||
return
|
||||
self.__initialized = True
|
||||
self.config = CustomConfigParser()
|
||||
self.settings: Dict[str, Dict[str, Union[str, int, bool]]] = {}
|
||||
self._load_settings()
|
||||
|
||||
self.config = ConfigParser()
|
||||
if self._custom_cfg.exists():
|
||||
self.config.read(self._custom_cfg)
|
||||
elif self._default_cfg.exists():
|
||||
self.config.read(self._default_cfg)
|
||||
else:
|
||||
self._kill()
|
||||
def get(self, section: str, option: str) -> Union[str, int, bool]:
|
||||
return self.settings[section][option]
|
||||
|
||||
sections = self.config.sections()
|
||||
for s in sections:
|
||||
self.settings[s] = dict(self.config[s])
|
||||
|
||||
self._validate_cfg()
|
||||
|
||||
def get(self, key: str, value: Union[str, int, bool]) -> Union[str, int, bool]:
|
||||
return self.settings[key][value]
|
||||
|
||||
def set(self, key: str, value: Union[str, int, bool]) -> None:
|
||||
self.settings[key][value] = value
|
||||
def set(self, section: str, option: str, value: Union[str, int, bool]) -> None:
|
||||
self.settings[section][option] = value
|
||||
|
||||
def save(self) -> None:
|
||||
for section, option in self.settings.items():
|
||||
self.config[section] = option
|
||||
with open(self._custom_cfg, "w") as configfile:
|
||||
self.config.write(configfile)
|
||||
self._load_settings()
|
||||
|
||||
def _load_settings(self) -> None:
|
||||
if self._custom_cfg.exists():
|
||||
self.config.read(self._custom_cfg)
|
||||
elif self._default_cfg.exists():
|
||||
self.config.read(self._default_cfg)
|
||||
else:
|
||||
self._kill()
|
||||
self._validate_cfg()
|
||||
self._parse_settings()
|
||||
|
||||
def _validate_cfg(self) -> None:
|
||||
try:
|
||||
@@ -102,6 +102,19 @@ class KiauhSettings:
|
||||
if v.isdigit() or v.lower() == "true" or v.lower() == "false":
|
||||
raise ValueError
|
||||
|
||||
def _parse_settings(self):
|
||||
for s in self.config.sections():
|
||||
self.settings[s] = {}
|
||||
for o, v in self.config.items(s):
|
||||
if v.lower() == "true":
|
||||
self.settings[s][o] = True
|
||||
elif v.lower() == "false":
|
||||
self.settings[s][o] = False
|
||||
elif v.isdigit():
|
||||
self.settings[s][o] = int(v)
|
||||
else:
|
||||
self.settings[s][o] = v
|
||||
|
||||
def _kill(self) -> None:
|
||||
l1 = "!!! ERROR !!!"
|
||||
l2 = "No KIAUH configuration file found!"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license #
|
||||
# ======================================================================= #
|
||||
|
||||
from typing import Optional, List, Union
|
||||
from typing import List, Union
|
||||
|
||||
from utils import INVALID_CHOICE
|
||||
from utils.constants import COLOR_CYAN, RESET_FORMAT
|
||||
@@ -82,23 +82,33 @@ def get_number_input(
|
||||
Logger.print_error(INVALID_CHOICE)
|
||||
|
||||
|
||||
def get_string_input(question: str, exclude=Optional[List], default=None) -> str:
|
||||
def get_string_input(
|
||||
question: str,
|
||||
exclude: Union[List, None] = None,
|
||||
allow_special_chars=False,
|
||||
default=None,
|
||||
) -> str:
|
||||
"""
|
||||
Helper method to get a string input from the user
|
||||
:param question: The question to display
|
||||
:param exclude: List of strings which are not allowed
|
||||
:param allow_special_chars: Wheter to allow special characters in the input
|
||||
:param default: Optional default value
|
||||
:return: The validated string value
|
||||
"""
|
||||
_exclude = [] if exclude is None else exclude
|
||||
_question = format_question(question, default)
|
||||
while True:
|
||||
_input = input(format_question(question, default)).strip()
|
||||
_input = input(_question)
|
||||
|
||||
if _input.isalnum() and _input.lower() not in exclude:
|
||||
return _input
|
||||
|
||||
Logger.print_error(INVALID_CHOICE)
|
||||
if _input in exclude:
|
||||
if _input.lower() in _exclude:
|
||||
Logger.print_error("This value is already in use/reserved.")
|
||||
elif allow_special_chars:
|
||||
return _input
|
||||
elif not allow_special_chars and _input.isalnum():
|
||||
return _input
|
||||
else:
|
||||
Logger.print_error(INVALID_CHOICE)
|
||||
|
||||
|
||||
def get_selection_input(question: str, option_list: List, default=None) -> str:
|
||||
|
||||
Reference in New Issue
Block a user