Compare commits

..

8 Commits

Author SHA1 Message Date
dw-0
cba96dec14 Merge branch 'refs/heads/kiauh-v6-dev' into feat/obico-for-v6 2024-06-22 16:15:08 +02:00
dw-0
08c10fdded refactor: rework some moonraker dialogs
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-06-22 15:57:13 +02:00
dw-0
cfc45a9746 refactor: rework some klipper dialogs
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-06-22 15:50:31 +02:00
dw-0
a90626de30 Merge branch 'refs/heads/kiauh-v6-dev' into feat/obico-for-v6
# Conflicts:
#	kiauh/core/settings/kiauh_settings.py
2024-06-22 12:33:03 +02:00
dw-0
205c84b3c3 refactor: make menus more visually appealing
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-06-22 12:30:29 +02:00
dw-0
e63eb47ee9 refactor: extract config filenames into constants
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-06-22 10:58:43 +02:00
dw-0
af57b9670d fix: wrong condition in _load_config
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-06-22 10:56:02 +02:00
dw-0
b758b3887b refactor: improve error logging on missing kiauh config file
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-06-22 10:55:11 +02:00
24 changed files with 470 additions and 487 deletions

View File

@@ -13,7 +13,12 @@ from typing import List
from core.instance_manager.base_instance import BaseInstance
from core.menus.base_menu import print_back_footer
from utils.constants import COLOR_CYAN, COLOR_GREEN, COLOR_YELLOW, RESET_FORMAT
from utils.constants import (
COLOR_CYAN,
COLOR_GREEN,
COLOR_YELLOW,
RESET_FORMAT,
)
@unique
@@ -29,7 +34,7 @@ def print_instance_overview(
show_index=False,
show_select_all=False,
):
dialog = "/=======================================================\\\n"
dialog = "╔═══════════════════════════════════════════════════════╗\n"
if show_headline:
d_type = (
"Klipper instances"
@@ -37,13 +42,13 @@ def print_instance_overview(
else "printer directories"
)
headline = f"{COLOR_GREEN}The following {d_type} were found:{RESET_FORMAT}"
dialog += f"|{headline:^64}|\n"
dialog += "|-------------------------------------------------------|\n"
dialog += f"{headline:^64}\n"
dialog += "╟───────────────────────────────────────────────────────╢\n"
if show_select_all:
select_all = f"{COLOR_YELLOW}a) Select all{RESET_FORMAT}"
dialog += f"| {select_all:<63}|\n"
dialog += "| |\n"
dialog += f" {select_all:<63}\n"
dialog += " \n"
for i, s in enumerate(instances):
if display_type is DisplayType.SERVICE_NAME:
@@ -51,7 +56,8 @@ def print_instance_overview(
else:
name = s.data_dir
line = f"{COLOR_CYAN}{f'{i})' if show_index else ''} {name}{RESET_FORMAT}"
dialog += f"| {line:<63}|\n"
dialog += f" {line:<63}\n"
dialog += "╟───────────────────────────────────────────────────────╢\n"
print(dialog, end="")
print_back_footer()
@@ -62,13 +68,14 @@ def print_select_instance_count_dialog():
line2 = f"{COLOR_YELLOW}Setting up too many instances may crash your system.{RESET_FORMAT}"
dialog = textwrap.dedent(
f"""
/=======================================================\\
| Please select the number of Klipper instances to set |
| up. The number of Klipper instances will determine |
| the amount of printers you can run from this host. |
| |
| {line1:<63}|
| {line2:<63}|
╔═══════════════════════════════════════════════════════╗
Please select the number of Klipper instances to set
up. The number of Klipper instances will determine
the amount of printers you can run from this host.
{line1:<63}
{line2:<63}
╟───────────────────────────────────────────────────────╢
"""
)[1:]
@@ -81,71 +88,16 @@ def print_select_custom_name_dialog():
line2 = f"{COLOR_YELLOW}Only alphanumeric characters are allowed!{RESET_FORMAT}"
dialog = textwrap.dedent(
f"""
/=======================================================\\
| You can now assign a custom name to each instance. |
| If skipped, each instance will get an index assigned |
| in ascending order, starting at index '1'. |
| |
| {line1:<63}|
| {line2:<63}|
╔═══════════════════════════════════════════════════════╗
You can now assign a custom name to each instance.
If skipped, each instance will get an index assigned
in ascending order, starting at index '1'.
{line1:<63}
{line2:<63}
╟───────────────────────────────────────────────────────╢
"""
)[1:]
print(dialog, end="")
print_back_footer()
def print_missing_usergroup_dialog(missing_groups) -> None:
line1 = f"{COLOR_YELLOW}WARNING: Your current user is not in group:{RESET_FORMAT}"
line2 = f"{COLOR_CYAN}● tty{RESET_FORMAT}"
line3 = f"{COLOR_CYAN}● dialout{RESET_FORMAT}"
line4 = f"{COLOR_YELLOW}INFO:{RESET_FORMAT}"
line5 = f"{COLOR_YELLOW}Relog required for group assignments to take effect!{RESET_FORMAT}"
dialog = textwrap.dedent(
f"""
/=======================================================\\
| {line1:<63}|
"""
)[1:]
if "tty" in missing_groups:
dialog += f"| {line2:<63}|\n"
if "dialout" in missing_groups:
dialog += f"| {line3:<63}|\n"
dialog += textwrap.dedent(
f"""
| |
| It is possible that you won't be able to successfully |
| connect and/or flash the controller board without |
| your user being a member of that group. |
| If you want to add the current user to the group(s) |
| listed above, answer with 'Y'. Else skip with 'n'. |
| |
| {line4:<63}|
| {line5:<63}|
\\=======================================================/
"""
)[1:]
print(dialog, end="")
def print_update_warn_dialog() -> None:
line1 = f"{COLOR_YELLOW}WARNING:{RESET_FORMAT}"
line2 = f"{COLOR_YELLOW}Do NOT continue if there are ongoing prints running!{RESET_FORMAT}"
line3 = f"{COLOR_YELLOW}All Klipper instances will be restarted during the {RESET_FORMAT}"
line4 = f"{COLOR_YELLOW}update process and ongoing prints WILL FAIL.{RESET_FORMAT}"
dialog = textwrap.dedent(
f"""
/=======================================================\\
| {line1:<63}|
| {line2:<63}|
| {line3:<63}|
| {line4:<63}|
\\=======================================================/
"""
)[1:]
print(dialog, end="")

View File

@@ -16,7 +16,6 @@ from components.klipper import (
KLIPPER_REQUIREMENTS_TXT,
)
from components.klipper.klipper import Klipper
from components.klipper.klipper_dialogs import print_update_warn_dialog
from components.klipper.klipper_utils import (
add_to_existing,
backup_klipper_dir,
@@ -39,7 +38,7 @@ from core.settings.kiauh_settings import KiauhSettings
from utils.common import check_install_dependencies
from utils.git_utils import git_clone_wrapper, git_pull_wrapper
from utils.input_utils import get_confirm
from utils.logger import Logger
from utils.logger import DialogType, Logger
from utils.sys_utils import (
cmd_sysctl_manage,
create_python_venv,
@@ -139,7 +138,16 @@ def install_klipper_packages(klipper_dir: Path) -> None:
def update_klipper() -> None:
print_update_warn_dialog()
Logger.print_dialog(
DialogType.WARNING,
[
"Do NOT continue if there are ongoing prints running!",
"All Klipper instances will be restarted during the update process and "
"ongoing prints WILL FAIL.",
],
end="",
)
if not get_confirm("Update Klipper now?"):
return

View File

@@ -23,7 +23,6 @@ from components.klipper import (
from components.klipper.klipper import Klipper
from components.klipper.klipper_dialogs import (
print_instance_overview,
print_missing_usergroup_dialog,
print_select_custom_name_dialog,
print_select_instance_count_dialog,
)
@@ -201,18 +200,29 @@ def klipper_to_multi_conversion(new_name: str) -> None:
def check_user_groups():
current_groups = [grp.getgrgid(gid).gr_name for gid in os.getgroups()]
missing_groups = []
if "tty" not in current_groups:
missing_groups.append("tty")
if "dialout" not in current_groups:
missing_groups.append("dialout")
user_groups = [grp.getgrgid(gid).gr_name for gid in os.getgroups()]
missing_groups = [g for g in user_groups if g == "tty" or g == "dialout"]
if not missing_groups:
return
print_missing_usergroup_dialog(missing_groups)
Logger.print_dialog(
DialogType.ATTENTION,
[
"Your current user is not in group:",
*[f"{g}" for g in missing_groups],
"\n\n",
"It is possible that you won't be able to successfully connect and/or "
"flash the controller board without your user being a member of that "
"group. If you want to add the current user to the group(s) listed above, "
"answer with 'Y'. Else skip with 'n'.",
"\n\n",
"INFO:",
"Relog required for group assignments to take effect!",
],
end="",
)
if not get_confirm(f"Add user '{CURRENT_USER}' to group(s) now?"):
log = "Skipped adding user to required groups. You might encounter issues."
Logger.warn(log)

View File

@@ -56,20 +56,21 @@ class KlipperRemoveMenu(BaseMenu):
o4 = checked if self.delete_klipper_logs else unchecked
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Enter a number and hit enter to select / deselect |
| the specific option for removal. |
|-------------------------------------------------------|
| 0) Select everything |
|-------------------------------------------------------|
| 1) {o1} Remove Service |
| 2) {o2} Remove Local Repository |
| 3) {o3} Remove Python Environment |
| 4) {o4} Delete all Log-Files |
|-------------------------------------------------------|
| C) Continue |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
Enter a number and hit enter to select / deselect
the specific option for removal.
╟───────────────────────────────────────────────────────╢
0) Select everything
╟───────────────────────────────────────────────────────╢
1) {o1} Remove Service
2) {o2} Remove Local Repository
3) {o3} Remove Python Environment
4) {o4} Delete all Log-Files
╟───────────────────────────────────────────────────────╢
C) Continue
╟───────────────────────────────────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -57,11 +57,11 @@ class KlipperBuildFirmwareMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| The following dependencies are required: |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
The following dependencies are required:
"""
)[1:]
@@ -71,15 +71,15 @@ class KlipperBuildFirmwareMenu(BaseMenu):
status = status_missing if d in self.missing_deps else status_ok
padding = 39 - len(d) + len(status) + (len(status_ok) - len(status))
d = f" {COLOR_CYAN}{d}{RESET_FORMAT}"
menu += f"| {d}{status:>{padding}} |\n"
menu += f" {d}{status:>{padding}} \n"
menu += "║ ║\n"
menu += "| |\n"
if len(self.missing_deps) == 0:
line = f"{COLOR_GREEN}All dependencies are met!{RESET_FORMAT}"
else:
line = f"{COLOR_RED}Dependencies are missing!{RESET_FORMAT}"
menu += f"| {line:<62} |\n"
menu += f" {line:<62} \n"
print(menu, end="")

View File

@@ -39,22 +39,22 @@ class KlipperNoFirmwareErrorMenu(BaseMenu):
line1 = f"{color}Unable to find a compiled firmware file!{RESET_FORMAT}"
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {line1:<62} |
| |
| Make sure, that: |
| ● the folder '~/klipper/out' and its content exist |
| ● the folder contains the following file: |
╔═══════════════════════════════════════════════════════╗
{color}{header:^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{line1:<62}
Make sure, that:
● the folder '~/klipper/out' and its content exist
● the folder contains the following file:
"""
)[1:]
if self.flash_options.flash_method is FlashMethod.REGULAR:
menu += "|'klipper.elf' |\n"
menu += "|'klipper.elf.hex' |\n"
menu += "'klipper.elf' \n"
menu += "'klipper.elf.hex' \n"
else:
menu += "|'klipper.bin' |\n"
menu += "'klipper.bin' \n"
print(menu, end="")
@@ -86,19 +86,19 @@ class KlipperNoBoardTypesErrorMenu(BaseMenu):
line1 = f"{color}Reading the list of supported boards failed!{RESET_FORMAT}"
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {line1:<62} |
| |
| Make sure, that: |
| ● the folder '~/klipper' and all its content exist |
| ● the content of folder '~/klipper' is not currupted |
| ● the file '~/klipper/scripts/flash-sd.py' exist |
| ● your current user has access to those files/folders |
| |
| If in doubt or this process continues to fail, please |
| consider to download Klipper again. |
╔═══════════════════════════════════════════════════════╗
{color}{header:^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{line1:<62}
Make sure, that:
● the folder '~/klipper' and all its content exist
● the content of folder '~/klipper' is not currupted
● the file '~/klipper/scripts/flash-sd.py' exist
● your current user has access to those files/folders
If in doubt or this process continues to fail, please
consider to download Klipper again.
"""
)[1:]
print(menu, end="")

View File

@@ -39,32 +39,33 @@ class KlipperFlashMethodHelpMenu(BaseMenu):
subheader2 = f"{COLOR_CYAN}Updating via SD-Card Update:{RESET_FORMAT}"
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {subheader1:<62} |
| The default method to flash controller boards which |
| are connected and updated over USB and not by placing |
| a compiled firmware file onto an internal SD-Card. |
| |
| Common controllers that get flashed that way are: |
| - Arduino Mega 2560 |
| - Fysetc F6 / S6 (used without a Display + SD-Slot) |
| |
| {subheader2:<62} |
| Many popular controller boards ship with a bootloader |
| capable of updating the firmware via SD-Card. |
| Choose this method if your controller board supports |
| this way of updating. This method ONLY works for up- |
| grading firmware. The initial flashing procedure must |
| be done manually per the instructions that apply to |
| your controller board. |
| |
| Common controllers that can be flashed that way are: |
| - BigTreeTech SKR 1.3 / 1.4 (Turbo) / E3 / Mini E3 |
| - Fysetc F6 / S6 (used with a Display + SD-Slot) |
| - Fysetc Spider |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{subheader1:<62}
The default method to flash controller boards which
are connected and updated over USB and not by placing
a compiled firmware file onto an internal SD-Card.
Common controllers that get flashed that way are:
- Arduino Mega 2560
- Fysetc F6 / S6 (used without a Display + SD-Slot)
{subheader2:<62}
Many popular controller boards ship with a bootloader
capable of updating the firmware via SD-Card.
Choose this method if your controller board supports
this way of updating. This method ONLY works for up-
grading firmware. The initial flashing procedure must
be done manually per the instructions that apply to
your controller board.
Common controllers that can be flashed that way are:
- BigTreeTech SKR 1.3 / 1.4 (Turbo) / E3 / Mini E3
- Fysetc F6 / S6 (used with a Display + SD-Slot)
- Fysetc Spider
╟───────────────────────────────────────────────────────╢
"""
)[1:]
print(menu, end="")
@@ -96,19 +97,19 @@ class KlipperFlashCommandHelpMenu(BaseMenu):
subheader2 = f"{COLOR_CYAN}make serialflash:{RESET_FORMAT}"
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {subheader1:<62} |
| The default command to flash controller board, it |
| will detect selected microcontroller and use suitable |
| tool for flashing it. |
| |
| {subheader2:<62} |
| Special command to flash STM32 microcontrollers in |
| DFU mode but connected via serial. stm32flash command |
| will be used internally. |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{subheader1:<62}
The default command to flash controller board, it
will detect selected microcontroller and use suitable
tool for flashing it.
{subheader2:<62}
Special command to flash STM32 microcontrollers in
DFU mode but connected via serial. stm32flash command
will be used internally.
"""
)[1:]
print(menu, end="")
@@ -142,25 +143,26 @@ class KlipperMcuConnectionHelpMenu(BaseMenu):
subheader2 = f"{COLOR_CYAN}UART:{RESET_FORMAT}"
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {subheader1:<62} |
| Selecting USB as the connection method will scan the |
| USB ports for connected controller boards. This will |
| be similar to the 'ls /dev/serial/by-id/*' command |
| suggested by the official Klipper documentation for |
| determining successfull USB connections! |
| |
| {subheader2:<62} |
| Selecting UART as the connection method will list all |
| possible UART serial ports. Note: This method ALWAYS |
| returns something as it seems impossible to determine |
| if a valid Klipper controller board is connected or |
| not. Because of that, you MUST know which UART serial |
| port your controller board is connected to when using |
| this connection method. |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{subheader1:<62}
Selecting USB as the connection method will scan the
USB ports for connected controller boards. This will
be similar to the 'ls /dev/serial/by-id/*' command
suggested by the official Klipper documentation for
determining successfull USB connections!
{subheader2:<62}
Selecting UART as the connection method will list all
possible UART serial ports. Note: This method ALWAYS
returns something as it seems impossible to determine
if a valid Klipper controller board is connected or
not. Because of that, you MUST know which UART serial
port your controller board is connected to when using
this connection method.
╟───────────────────────────────────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -38,7 +38,7 @@ from core.menus import FooterType, Option
from core.menus.base_menu import BaseMenu
from utils.constants import COLOR_CYAN, COLOR_RED, COLOR_YELLOW, RESET_FORMAT
from utils.input_utils import get_number_input
from utils.logger import Logger
from utils.logger import DialogType, Logger
# noinspection PyUnusedLocal
@@ -74,19 +74,18 @@ class KlipperFlashMethodMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Select the flash method for flashing the MCU. |
| |
| {subheader:<62} |
| {subline1:<62} |
| {subline2:<62} |
|-------------------------------------------------------|
| |
| 1) Regular flashing method |
| 2) Updating via SD-Card Update |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
Select the flash method for flashing the MCU.
{subheader:<62}
{subline1:<62}
{subline2:<62}
╟───────────────────────────────────────────────────────╢
║ 1) Regular flashing method
║ 2) Updating via SD-Card Update
╟───────────────────────────┬───────────────────────────╢
"""
)[1:]
print(menu, end="")
@@ -131,12 +130,12 @@ class KlipperFlashCommandMenu(BaseMenu):
def print_menu(self) -> None:
menu = textwrap.dedent(
"""
/=======================================================\\
| |
| Which flash command to use for flashing the MCU? |
| 1) make flash (default) |
| 2) make serialflash (stm32flash) |
| |
╔═══════════════════════════════════════════════════════╗
║ Which flash command to use for flashing the MCU?
╟───────────────────────────────────────────────────────╢
1) make flash (default)
2) make serialflash (stm32flash)
╟───────────────────────────┬───────────────────────────╢
"""
)[1:]
print(menu, end="")
@@ -185,15 +184,15 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| |
| How is the controller board connected to the host? |
| 1) USB |
| 2) UART |
| 3) USB (DFU mode) |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
║ How is the controller board connected to the host?
╟───────────────────────────────────────────────────────╢
1) USB
2) UART
3) USB (DFU mode)
╟───────────────────────────┬───────────────────────────╢
"""
)[1:]
print(menu, end="")
@@ -271,20 +270,20 @@ class KlipperSelectMcuIdMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Make sure, to select the correct MCU! |
| ONLY flash a firmware created for the respective MCU! |
| |
|{header2:-^64}|
╔═══════════════════════════════════════════════════════╗
{color}{header:^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
Make sure, to select the correct MCU!
ONLY flash a firmware created for the respective MCU!
{header2:^64}
"""
)[1:]
for i, mcu in enumerate(self.mcu_list):
mcu = mcu.split("/")[-1]
menu += f" ● MCU #{i}: {COLOR_CYAN}{mcu}{RESET_FORMAT}\n"
menu += "╟───────────────────────────┬───────────────────────────╢"
print(menu, end="\n")
@@ -325,12 +324,12 @@ class KlipperSelectSDFlashBoardMenu(BaseMenu):
else:
menu = textwrap.dedent(
"""
/=======================================================\\
| Please select the type of board that corresponds to |
| the currently selected MCU ID you chose before. |
| |
| The following boards are currently supported: |
|-------------------------------------------------------|
╔═══════════════════════════════════════════════════════╗
Please select the type of board that corresponds to
the currently selected MCU ID you chose before.
The following boards are currently supported:
╟───────────────────────────────────────────────────────╢
"""
)[1:]
@@ -346,17 +345,16 @@ class KlipperSelectSDFlashBoardMenu(BaseMenu):
self.baudrate_select()
def baudrate_select(self, **kwargs):
menu = textwrap.dedent(
"""
/=======================================================\\
| If your board is flashed with firmware that connects |
| at a custom baud rate, please change it now. |
| |
| If you are unsure, stick to the default 250000! |
\\=======================================================/
"""
)[1:]
print(menu, end="")
Logger.print_dialog(
DialogType.CUSTOM,
[
"If your board is flashed with firmware that connects "
"at a custom baud rate, please change it now.",
"\n\n",
"If you are unsure, stick to the default 250000!",
],
end="",
)
self.flash_options.selected_baudrate = get_number_input(
question="Please set the baud rate",
default=250000,
@@ -399,16 +397,15 @@ class KlipperFlashOverviewMenu(BaseMenu):
subheader = f"[{COLOR_CYAN}Overview{RESET_FORMAT}]"
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Before contuining the flashing process, please check |
| if all parameters were set correctly! Once you made |
| sure everything is correct, start the process. If any |
| parameter needs to be changed, you can go back (B) |
| step by step or abort and start from the beginning. |
|{subheader:-^64}|
╔═══════════════════════════════════════════════════════╗
{color}{header:^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
Before contuining the flashing process, please check
if all parameters were set correctly! Once you made
sure everything is correct, start the process. If any
parameter needs to be changed, you can go back (B)
step by step or abort and start from the beginning.
{subheader:-^64}
"""
)[1:]
@@ -423,9 +420,9 @@ class KlipperFlashOverviewMenu(BaseMenu):
menu += textwrap.dedent(
"""
|-------------------------------------------------------|
| Y) Start flash process |
| N) Abort - Return to Advanced Menu |
╟───────────────────────────────────────────────────────╢
Y) Start flash process
N) Abort - Return to Advanced Menu
"""
)
print(menu, end="")

View File

@@ -42,17 +42,18 @@ class LogUploadMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| You can select the following logfiles for uploading: |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
You can select the following logfiles for uploading:
"""
)[1:]
for logfile in enumerate(self.logfile_list):
line = f"{logfile[0]}) {logfile[1].get('display_name')}"
menu += f"| {line:<54}|\n"
menu += f" {line:<54}\n"
menu += "╟───────────────────────────────────────────────────────╢\n"
print(menu, end="")

View File

@@ -58,21 +58,22 @@ class MoonrakerRemoveMenu(BaseMenu):
o5 = checked if self.delete_moonraker_logs else unchecked
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Enter a number and hit enter to select / deselect |
| the specific option for removal. |
|-------------------------------------------------------|
| 0) Select everything |
|-------------------------------------------------------|
| 1) {o1} Remove Service |
| 2) {o2} Remove Local Repository |
| 3) {o3} Remove Python Environment |
| 4) {o4} Remove Policy Kit Rules |
| 5) {o5} Delete all Log-Files |
|-------------------------------------------------------|
| C) Continue |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
Enter a number and hit enter to select / deselect
the specific option for removal.
╟───────────────────────────────────────────────────────╢
0) Select everything
╟───────────────────────────────────────────────────────╢
1) {o1} Remove Service
2) {o2} Remove Local Repository
3) {o3} Remove Python Environment
4) {o4} Remove Policy Kit Rules
5) {o5} Delete all Log-Files
╟───────────────────────────────────────────────────────╢
C) Continue
╟───────────────────────────────────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -25,16 +25,16 @@ def print_moonraker_overview(
headline = f"{COLOR_GREEN}The following instances were found:{RESET_FORMAT}"
dialog = textwrap.dedent(
f"""
/=======================================================\\
|{headline:^64}|
|-------------------------------------------------------|
╔═══════════════════════════════════════════════════════╗
{headline:^64}
╟───────────────────────────────────────────────────────╢
"""
)[1:]
if show_select_all:
select_all = f"{COLOR_YELLOW}a) Select all{RESET_FORMAT}"
dialog += f"| {select_all:<63}|\n"
dialog += "| |\n"
dialog += f" {select_all:<63}\n"
dialog += " \n"
instance_map = {
k.get_service_file_name(): (
@@ -49,18 +49,19 @@ def print_moonraker_overview(
mr_name = instance_map.get(k)
m = f"<-> {mr_name}" if mr_name != "" else ""
line = f"{COLOR_CYAN}{f'{i})' if show_index else ''} {k} {m} {RESET_FORMAT}"
dialog += f"| {line:<63}|\n"
dialog += f" {line:<63}\n"
warn_l1 = f"{COLOR_YELLOW}PLEASE NOTE: {RESET_FORMAT}"
warn_l2 = f"{COLOR_YELLOW}If you select an instance with an existing Moonraker{RESET_FORMAT}"
warn_l3 = f"{COLOR_YELLOW}instance, that Moonraker instance will be re-created!{RESET_FORMAT}"
warning = textwrap.dedent(
f"""
| |
|-------------------------------------------------------|
| {warn_l1:<63}|
| {warn_l2:<63}|
| {warn_l3:<63}|
╟───────────────────────────────────────────────────────╢
{warn_l1:<63}
{warn_l2:<63}
{warn_l3:<63}
╟───────────────────────────────────────────────────────╢
"""
)[1:]

View File

@@ -60,16 +60,16 @@ class ClientRemoveMenu(BaseMenu):
o2 = checked if self.rm_client_config else unchecked
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Enter a number and hit enter to select / deselect |
| the specific option for removal. |
|-------------------------------------------------------|
| 0) Select everything |
|-------------------------------------------------------|
| 1) {o1} Remove {client_name:16} |
| 2) {o2} Remove {client_config_name:24} |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
Enter a number and hit enter to select / deselect
the specific option for removal.
╟───────────────────────────────────────────────────────╢
0) Select everything
╟───────────────────────────────────────────────────────╢
1) {o1} Remove {client_name:16}
2) {o2} Remove {client_config_name:24}
"""
)[1:]
@@ -77,14 +77,15 @@ class ClientRemoveMenu(BaseMenu):
o3 = checked if self.backup_mainsail_config_json else unchecked
menu += textwrap.dedent(
f"""
| 3) {o3} Backup config.json |
3) {o3} Backup config.json
"""
)[1:]
menu += textwrap.dedent(
"""
|-------------------------------------------------------|
| C) Continue |
╟───────────────────────────────────────────────────────╢
C) Continue
╟───────────────────────────────────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -43,12 +43,12 @@ class AdvancedMenu(BaseMenu):
def set_options(self):
self.options = {
"1": Option(method=self.klipper_rollback, menu=True),
"2": Option(method=self.moonraker_rollback, menu=True),
"3": Option(method=self.build, menu=True),
"4": Option(method=self.flash, menu=False),
"5": Option(method=self.build_flash, menu=False),
"6": Option(method=self.get_id, menu=False),
"1": Option(method=self.build, menu=True),
"2": Option(method=self.flash, menu=False),
"3": Option(method=self.build_flash, menu=False),
"4": Option(method=self.get_id, menu=False),
"5": Option(method=self.klipper_rollback, menu=True),
"6": Option(method=self.moonraker_rollback, menu=True),
}
def print_menu(self):
@@ -57,18 +57,15 @@ class AdvancedMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Repo Rollback: |
| 1) [Klipper] |
| 2) [Moonraker] |
| |
| Klipper Firmware: |
| 3) [Build] |
| 4) [Flash] |
| 5) [Build + Flash] |
| 6) [Get MCU ID] |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────┬───────────────────────────╢
║ Klipper Firmware: │ Repository Rollback: ║
1) [Build] 5) [Klipper]
2) [Flash] │ 6) [Moonraker]
║ 3) [Build + Flash] │
║ 4) [Get MCU ID] │
╟───────────────────────────┴───────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -62,20 +62,21 @@ class BackupMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {line1:^62} |
|-------------------------------------------------------|
| Klipper & Moonraker API: | Client-Config: |
| 1) [Klipper] | 7) [Mainsail-Config] |
| 2) [Moonraker] | 8) [Fluidd-Config] |
| 3) [Config Folder] | |
| 4) [Moonraker Database] | Touchscreen GUI: |
| | 9) [KlipperScreen] |
| Webinterface: | |
| 5) [Mainsail] | |
| 6) [Fluidd] | |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{line1:^62}
╟───────────────────────────┬───────────────────────────╢
Klipper & Moonraker API: Client-Config:
1) [Klipper] 7) [Mainsail-Config]
2) [Moonraker] 8) [Fluidd-Config]
3) [Config Folder]
4) [Moonraker Database] Touchscreen GUI:
9) [KlipperScreen]
Webinterface:
5) [Mainsail]
6) [Fluidd]
╟───────────────────────────┴───────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -39,11 +39,11 @@ def print_header():
count = 62 - len(color) - len(RESET_FORMAT)
header = textwrap.dedent(
f"""
/=======================================================\\
| {color}{line1:~^{count}}{RESET_FORMAT} |
| {color}{line2:^{count}}{RESET_FORMAT} |
| {color}{line3:~^{count}}{RESET_FORMAT} |
\=======================================================/
╔═══════════════════════════════════════════════════════╗
{color}{line1:~^{count}}{RESET_FORMAT}
{color}{line2:^{count}}{RESET_FORMAT}
{color}{line3:~^{count}}{RESET_FORMAT}
╚═══════════════════════════════════════════════════════╝
"""
)[1:]
print(header, end="")
@@ -55,9 +55,8 @@ def print_quit_footer():
count = 62 - len(color) - len(RESET_FORMAT)
footer = textwrap.dedent(
f"""
|-------------------------------------------------------|
| {color}{text:^{count}}{RESET_FORMAT} |
\=======================================================/
{color}{text:^{count}}{RESET_FORMAT}
╚═══════════════════════════════════════════════════════╝
"""
)[1:]
print(footer, end="")
@@ -69,9 +68,8 @@ def print_back_footer():
count = 62 - len(color) - len(RESET_FORMAT)
footer = textwrap.dedent(
f"""
|-------------------------------------------------------|
| {color}{text:^{count}}{RESET_FORMAT} |
\=======================================================/
{color}{text:^{count}}{RESET_FORMAT}
╚═══════════════════════════════════════════════════════╝
"""
)[1:]
print(footer, end="")
@@ -85,16 +83,15 @@ def print_back_help_footer():
count = 34 - len(color1) - len(RESET_FORMAT)
footer = textwrap.dedent(
f"""
|-------------------------------------------------------|
| {color1}{text1:^{count}}{RESET_FORMAT} | {color2}{text2:^{count}}{RESET_FORMAT} |
\=======================================================/
{color1}{text1:^{count}}{RESET_FORMAT}{color2}{text2:^{count}}{RESET_FORMAT}
╚═══════════════════════════╧═══════════════════════════╝
"""
)[1:]
print(footer, end="")
def print_blank_footer():
print("\=======================================================/")
print("╚═══════════════════════════════════════════════════════╝")
class PostInitCaller(type):
@@ -168,7 +165,7 @@ class BaseMenu(metaclass=PostInitCaller):
elif self.footer_type is FooterType.BLANK:
print_blank_footer()
else:
raise NotImplementedError
raise NotImplementedError("FooterType not correctly implemented!")
def display_menu(self) -> None:
if self.header:

View File

@@ -57,21 +57,22 @@ class InstallMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| Firmware & API: | Touchscreen GUI: |
| 1) [Klipper] | 7) [KlipperScreen] |
| 2) [Moonraker] | |
| | Android / iOS: |
| Webinterface: | 8) [Mobileraker] |
| 3) [Mainsail] | |
| 4) [Fluidd] | Webcam Streamer: |
| | 9) [Crowsnest] |
| Client-Config: | |
| 5) [Mainsail-Config] | |
| 6) [Fluidd-Config] | |
| | |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────┬───────────────────────────╢
Firmware & API: Touchscreen GUI:
1) [Klipper] 7) [KlipperScreen]
2) [Moonraker]
Android / iOS:
Webinterface: 8) [Mobileraker]
3) [Mainsail]
4) [Fluidd] Webcam Streamer:
9) [Crowsnest]
Client-Config:
5) [Mainsail-Config]
6) [Fluidd-Config]
╟───────────────────────────┴───────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -6,7 +6,7 @@
# #
# This file may be distributed under the terms of the GNU GPLv3 license #
# ======================================================================= #
import sys
import textwrap
from typing import Optional, Type
@@ -39,6 +39,7 @@ from utils.constants import (
COLOR_YELLOW,
RESET_FORMAT,
)
from utils.logger import Logger
from utils.types import ComponentStatus
@@ -117,7 +118,7 @@ class MainMenu(BaseMenu):
self.fetch_status()
header = " [ Main Menu ] "
footer1 = "KIAUH v6.0.0"
footer1 = f"{COLOR_CYAN}KIAUH v6.0.0{RESET_FORMAT}"
footer2 = f"Changelog: {COLOR_MAGENTA}https://git.io/JnmlX{RESET_FORMAT}"
color = COLOR_CYAN
count = 62 - len(color) - len(RESET_FORMAT)
@@ -125,28 +126,33 @@ class MainMenu(BaseMenu):
pad2 = 26
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| 0) [Log-Upload] | Klipper: {self.kl_status:<{pad1}} |
| | Repo: {self.kl_repo:<{pad1}} |
| 1) [Install] |------------------------------------|
| 2) [Update] | Moonraker: {self.mr_status:<{pad1}} |
| 3) [Remove] | Repo: {self.mr_repo:<{pad1}} |
| 4) [Advanced] |------------------------------------|
| 5) [Backup] | Mainsail: {self.ms_status:<{pad2}} |
| | Fluidd: {self.fl_status:<{pad2}} |
| S) [Settings] | Client-Config: {self.cc_status:<{pad2}} |
| | |
| Community: | KlipperScreen: {self.ks_status:<{pad2}} |
| E) [Extensions] | Mobileraker: {self.mb_status:<{pad2}} |
| | Crowsnest: {self.cn_status:<{pad2}} |
|-------------------------------------------------------|
| {COLOR_CYAN}{footer1:^16}{RESET_FORMAT} | {footer2:^43} |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟──────────────────┬────────────────────────────────────╢
0) [Log-Upload] Klipper: {self.kl_status:<{pad1}}
Repo: {self.kl_repo:<{pad1}}
1) [Install] ├────────────────────────────────────╢
2) [Update] Moonraker: {self.mr_status:<{pad1}}
3) [Remove] Repo: {self.mr_repo:<{pad1}}
4) [Advanced] ├────────────────────────────────────╢
5) [Backup] Mainsail: {self.ms_status:<{pad2}}
Fluidd: {self.fl_status:<{pad2}}
S) [Settings] Client-Config: {self.cc_status:<{pad2}}
Community: KlipperScreen: {self.ks_status:<{pad2}}
E) [Extensions] Mobileraker: {self.mb_status:<{pad2}}
Crowsnest: {self.cn_status:<{pad2}}
╟──────────────────┼────────────────────────────────────╢
{footer1:^25} {footer2:^43}
╟──────────────────┴────────────────────────────────────╢
"""
)[1:]
print(menu, end="")
def exit(self, **kwargs):
Logger.print_ok("###### Happy printing!", False)
sys.exit(0)
def log_upload_menu(self, **kwargs):
LogUploadMenu().run()

View File

@@ -56,19 +56,20 @@ class RemoveMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| INFO: Configurations and/or any backups will be kept! |
|-------------------------------------------------------|
| Firmware & API: | Touchscreen GUI: |
| 1) [Klipper] | 5) [KlipperScreen] |
| 2) [Moonraker] | |
| | Android / iOS: |
| Klipper Webinterface: | 6) [Mobileraker] |
| 3) [Mainsail] | |
| 4) [Fluidd] | Webcam Streamer: |
| | 7) [Crowsnest] |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
INFO: Configurations and/or any backups will be kept!
╟───────────────────────────┬───────────────────────────╢
Firmware & API: Touchscreen GUI:
1) [Klipper] 5) [KlipperScreen]
2) [Moonraker]
Android / iOS:
Klipper Webinterface: 6) [Mobileraker]
3) [Mainsail]
4) [Fluidd] Webcam Streamer:
7) [Crowsnest]
╟───────────────────────────┴───────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -65,30 +65,31 @@ class SettingsMenu(BaseMenu):
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 |
╔═══════════════════════════════════════════════════════╗
{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="")

View File

@@ -93,29 +93,30 @@ class UpdateMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| 0) Update all | | |
| | Current: | Latest: |
| Klipper & API: |---------------|---------------|
| 1) Klipper | {self.kl_local:<22} | {self.kl_remote:<22} |
| 2) Moonraker | {self.mr_local:<22} | {self.mr_remote:<22} |
| | | |
| Webinterface: |---------------|---------------|
| 3) Mainsail | {self.ms_local:<22} | {self.ms_remote:<22} |
| 4) Fluidd | {self.fl_local:<22} | {self.fl_remote:<22} |
| | | |
| Client-Config: |---------------|---------------|
| 5) Mainsail-Config | {self.mc_local:<22} | {self.mc_remote:<22} |
| 6) Fluidd-Config | {self.fc_local:<22} | {self.fc_remote:<22} |
| | | |
| Other: |---------------|---------------|
| 7) KlipperScreen | {self.ks_local:<22} | {self.ks_remote:<22} |
| 8) Mobileraker | {self.mb_local:<22} | {self.mb_remote:<22} |
| 9) Crowsnest | {self.cn_local:<22} | {self.cn_remote:<22} |
| |-------------------------------|
| 10) System | |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────┬───────────────┬───────────────╢
0) Update all
Current: Latest:
Klipper & API: ├───────────────┼───────────────╢
1) Klipper {self.kl_local:<22} {self.kl_remote:<22}
2) Moonraker {self.mr_local:<22} {self.mr_remote:<22}
Webinterface: ├───────────────┼───────────────╢
3) Mainsail {self.ms_local:<22} {self.ms_remote:<22}
4) Fluidd {self.fl_local:<22} {self.fl_remote:<22}
Client-Config: ├───────────────┼───────────────╢
5) Mainsail-Config {self.mc_local:<22} {self.mc_remote:<22}
6) Fluidd-Config {self.fc_local:<22} {self.fc_remote:<22}
Other: ├───────────────┼───────────────╢
7) KlipperScreen {self.ks_local:<22} {self.ks_remote:<22}
8) Mobileraker {self.mb_local:<22} {self.mb_remote:<22}
9) Crowsnest {self.cn_local:<22} {self.cn_remote:<22}
├───────────────┴───────────────╢
10) System
╟───────────────────────┴───────────────────────────────╢
"""
)[1:]
print(menu, end="")

View File

@@ -8,7 +8,6 @@
# ======================================================================= #
from __future__ import annotations
import textwrap
from typing import Union
from core.submodules.simple_config_parser.src.simple_config_parser.simple_config_parser import (
@@ -16,12 +15,14 @@ from core.submodules.simple_config_parser.src.simple_config_parser.simple_config
NoSectionError,
SimpleConfigParser,
)
from utils.constants import COLOR_RED, RESET_FORMAT
from utils.logger import Logger
from utils.logger import DialogType, Logger
from utils.sys_utils import kill
from kiauh import PROJECT_ROOT
DEFAULT_CFG = PROJECT_ROOT.joinpath("default.kiauh.cfg")
CUSTOM_CFG = PROJECT_ROOT.joinpath("kiauh.cfg")
class AppSettings:
def __init__(self) -> None:
@@ -56,8 +57,6 @@ class FluiddSettings:
# noinspection PyMethodMayBeStatic
class KiauhSettings:
_instance = None
_default_cfg = PROJECT_ROOT.joinpath("default_kiauh.cfg")
_custom_cfg = PROJECT_ROOT.joinpath("kiauh.cfg")
def __new__(cls, *args, **kwargs) -> "KiauhSettings":
if cls._instance is None:
@@ -120,14 +119,14 @@ class KiauhSettings:
def save(self) -> None:
self._set_config_options()
self.config.write(self._custom_cfg)
self.config.write(CUSTOM_CFG)
self._load_config()
def _load_config(self) -> None:
if not self._custom_cfg.exists() and not self._default_cfg.exists():
if not CUSTOM_CFG.exists() and not DEFAULT_CFG.exists():
self._kill()
cfg = self._custom_cfg if self._custom_cfg.exists() else self._default_cfg
cfg = CUSTOM_CFG if CUSTOM_CFG.exists() else DEFAULT_CFG
self.config.read(cfg)
self._validate_cfg()
@@ -212,15 +211,14 @@ class KiauhSettings:
)
def _kill(self) -> None:
l1 = "!!! ERROR !!!"
l2 = "No KIAUH configuration file found!"
error = textwrap.dedent(
f"""
{COLOR_RED}/=======================================================\\
| {l1:^53} |
| {l2:^53} |
\=======================================================/{RESET_FORMAT}
"""
)[1:]
print(error, end="")
Logger.print_dialog(
DialogType.ERROR,
[
"No KIAUH configuration file found! Please make sure you have at least "
"one of the following configuration files in KIAUH's root directory:",
"● default.kiauh.cfg",
"● kiauh.cfg",
],
end="",
)
kill()

View File

@@ -87,11 +87,11 @@ class ExtensionsMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {line1:<62} |
| |
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
{line1:<62}
"""
)[1:]
print(menu, end="")
@@ -100,7 +100,8 @@ class ExtensionsMenu(BaseMenu):
index = extension.metadata.get("index")
name = extension.metadata.get("display_name")
row = f"{index}) {name}"
print(f"| {row:<53} |")
print(f" {row:<53} ")
print("╟───────────────────────────────────────────────────────╢")
# noinspection PyUnusedLocal
@@ -135,29 +136,30 @@ class ExtensionSubmenu(BaseMenu):
description_text = Logger.format_content(
description,
line_width,
border_left="|",
border_right="|",
border_left="",
border_right="",
)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
╔═══════════════════════════════════════════════════════╗
{color}{header:~^{count}}{RESET_FORMAT}
╟───────────────────────────────────────────────────────╢
"""
)[1:]
menu += f"{description_text}\n"
menu += textwrap.dedent(
"""
|-------------------------------------------------------|
| 1) Install |
╟───────────────────────────────────────────────────────╢
1) Install
"""
)[1:]
if self.extension.metadata.get("updates"):
menu += "| 2) Update |\n"
menu += "| 3) Remove |\n"
menu += " 2) Update \n"
menu += " 3) Remove \n"
else:
menu += "| 2) Remove |\n"
menu += " 2) Remove \n"
menu += "╟───────────────────────────────────────────────────────╢\n"
print(menu, end="")

View File

@@ -120,15 +120,19 @@ class Logger:
@staticmethod
def _format_top_border(color: str) -> str:
return textwrap.dedent(f"""
return textwrap.dedent(
f"""
{color}┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
""")[:-1]
"""
)[1:-1]
@staticmethod
def _format_bottom_border() -> str:
return textwrap.dedent(f"""
return textwrap.dedent(
f"""
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
{RESET_FORMAT}""")
{RESET_FORMAT}"""
)
@staticmethod
def _format_dialog_title(title: str) -> str: