allow user to interactively resize screen before UI runs

This commit is contained in:
Lincoln Stein 2023-08-08 12:27:25 -04:00
parent 0fd13d3604
commit f56f19710d
3 changed files with 52 additions and 35 deletions

View File

@ -52,11 +52,11 @@ from invokeai.frontend.install.widgets import (
CenteredButtonPress, CenteredButtonPress,
FileBox, FileBox,
IntTitleSlider, IntTitleSlider,
FloatTitleSlider,
set_min_terminal_size, set_min_terminal_size,
CyclingForm, CyclingForm,
MIN_COLS, MIN_COLS,
MIN_LINES, MIN_LINES,
WindowTooSmallException,
) )
from invokeai.backend.install.legacy_arg_parsing import legacy_parser from invokeai.backend.install.legacy_arg_parsing import legacy_parser
from invokeai.backend.install.model_install_backend import ( from invokeai.backend.install.model_install_backend import (
@ -395,7 +395,7 @@ Use cursor arrows to make a checkbox selection, and space to toggle.
) )
self.max_cache_size = self.add_widget_intelligent( self.max_cache_size = self.add_widget_intelligent(
IntTitleSlider, IntTitleSlider,
name="RAM cache size (GB). Make this at least large enough to hold a single model. Larger sizes will allow you to switch between models quickly without reading from disk.", name="RAM cache size (GB). Make this at least large enough to hold a single full model.",
value=old_opts.max_cache_size, value=old_opts.max_cache_size,
out_of=MAX_RAM, out_of=MAX_RAM,
lowest=3, lowest=3,
@ -440,7 +440,7 @@ Use cursor arrows to make a checkbox selection, and space to toggle.
self.autoimport_dirs = {} self.autoimport_dirs = {}
self.autoimport_dirs["autoimport_dir"] = self.add_widget_intelligent( self.autoimport_dirs["autoimport_dir"] = self.add_widget_intelligent(
FileBox, FileBox,
name=f"Folder to recursively scan for new checkpoints, ControlNets, LoRAs and TI models", name="Folder to recursively scan for new checkpoints, ControlNets, LoRAs and TI models",
value=str(config.root_path / config.autoimport_dir), value=str(config.root_path / config.autoimport_dir),
select_dir=True, select_dir=True,
must_exist=False, must_exist=False,
@ -635,9 +635,10 @@ def run_console_ui(program_opts: Namespace, initfile: Path = None) -> (Namespace
invokeai_opts = default_startup_options(initfile) invokeai_opts = default_startup_options(initfile)
invokeai_opts.root = program_opts.root invokeai_opts.root = program_opts.root
# The third argument is needed in the Windows 11 environment to if not set_min_terminal_size(MIN_COLS, MIN_LINES):
# launch a console window running this program. raise WindowTooSmallException(
set_min_terminal_size(MIN_COLS, MIN_LINES) "Could not increase terminal size. Try running again with a larger window or smaller font size."
)
# the install-models application spawns a subprocess to install # the install-models application spawns a subprocess to install
# models, and will crash unless this is set before running. # models, and will crash unless this is set before running.
@ -842,6 +843,8 @@ def main():
postscript(errors=errors) postscript(errors=errors)
if not opt.yes_to_all: if not opt.yes_to_all:
input("Press any key to continue...") input("Press any key to continue...")
except WindowTooSmallException as e:
logger.error(str(e))
except KeyboardInterrupt: except KeyboardInterrupt:
print("\nGoodbye! Come back soon.") print("\nGoodbye! Come back soon.")

View File

@ -28,7 +28,6 @@ from npyscreen import widget
from invokeai.backend.util.logging import InvokeAILogger from invokeai.backend.util.logging import InvokeAILogger
from invokeai.backend.install.model_install_backend import ( from invokeai.backend.install.model_install_backend import (
ModelInstallList,
InstallSelections, InstallSelections,
ModelInstall, ModelInstall,
SchedulerPredictionType, SchedulerPredictionType,
@ -41,12 +40,12 @@ from invokeai.frontend.install.widgets import (
SingleSelectColumns, SingleSelectColumns,
TextBox, TextBox,
BufferBox, BufferBox,
FileBox,
set_min_terminal_size, set_min_terminal_size,
select_stable_diffusion_config_file, select_stable_diffusion_config_file,
CyclingForm, CyclingForm,
MIN_COLS, MIN_COLS,
MIN_LINES, MIN_LINES,
WindowTooSmallException,
) )
from invokeai.app.services.config import InvokeAIAppConfig from invokeai.app.services.config import InvokeAIAppConfig
@ -156,7 +155,7 @@ class addModelsForm(CyclingForm, npyscreen.FormMultiPage):
BufferBox, BufferBox,
name="Log Messages", name="Log Messages",
editable=False, editable=False,
max_height=15, max_height=6,
) )
self.nextrely += 1 self.nextrely += 1
@ -693,7 +692,11 @@ def select_and_download_models(opt: Namespace):
# needed to support the probe() method running under a subprocess # needed to support the probe() method running under a subprocess
torch.multiprocessing.set_start_method("spawn") torch.multiprocessing.set_start_method("spawn")
set_min_terminal_size(MIN_COLS, MIN_LINES) if not set_min_terminal_size(MIN_COLS, MIN_LINES):
raise WindowTooSmallException(
"Could not increase terminal size. Try running again with a larger window or smaller font size."
)
installApp = AddModelApplication(opt) installApp = AddModelApplication(opt)
try: try:
installApp.run() installApp.run()
@ -787,6 +790,8 @@ def main():
curses.echo() curses.echo()
curses.endwin() curses.endwin()
logger.info("Goodbye! Come back soon.") logger.info("Goodbye! Come back soon.")
except WindowTooSmallException as e:
logger.error(str(e))
except widget.NotEnoughSpaceForWidget as e: except widget.NotEnoughSpaceForWidget as e:
if str(e).startswith("Height of 1 allocated"): if str(e).startswith("Height of 1 allocated"):
logger.error("Insufficient vertical space for the interface. Please make your window taller and try again") logger.error("Insufficient vertical space for the interface. Please make your window taller and try again")

View File

@ -21,31 +21,40 @@ MIN_COLS = 130
MIN_LINES = 38 MIN_LINES = 38
class WindowTooSmallException(Exception):
pass
# ------------------------------------- # -------------------------------------
def set_terminal_size(columns: int, lines: int): def set_terminal_size(columns: int, lines: int) -> bool:
ts = get_terminal_size()
width = max(columns, ts.columns)
height = max(lines, ts.lines)
OS = platform.uname().system OS = platform.uname().system
if OS == "Windows": screen_ok = False
pass while not screen_ok:
# not working reliably - ask user to adjust the window ts = get_terminal_size()
# _set_terminal_size_powershell(width,height) width = max(columns, ts.columns)
elif OS in ["Darwin", "Linux"]: height = max(lines, ts.lines)
_set_terminal_size_unix(width, height)
# check whether it worked.... if OS == "Windows":
ts = get_terminal_size() pass
pause = False # not working reliably - ask user to adjust the window
if ts.columns < columns: # _set_terminal_size_powershell(width,height)
print("\033[1mThis window is too narrow for the user interface.\033[0m") elif OS in ["Darwin", "Linux"]:
pause = True _set_terminal_size_unix(width, height)
if ts.lines < lines:
print("\033[1mThis window is too short for the user interface.\033[0m") # check whether it worked....
pause = True ts = get_terminal_size()
if pause: if ts.columns < columns or ts.lines < lines:
input("Maximize the window then press any key to continue..") print(
f"\033[1mThis window is too small for the interface. InvokeAI requires {columns}x{lines} (w x h) characters, but window is {ts.columns}x{ts.lines}\033[0m"
)
resp = input(
"Maximize the window and/or decrease the font size then press any key to continue. Type [Q] to give up.."
)
if resp.upper().startswith("Q"):
break
else:
screen_ok = True
return screen_ok
def _set_terminal_size_powershell(width: int, height: int): def _set_terminal_size_powershell(width: int, height: int):
@ -80,14 +89,14 @@ def _set_terminal_size_unix(width: int, height: int):
sys.stdout.flush() sys.stdout.flush()
def set_min_terminal_size(min_cols: int, min_lines: int): def set_min_terminal_size(min_cols: int, min_lines: int) -> bool:
# make sure there's enough room for the ui # make sure there's enough room for the ui
term_cols, term_lines = get_terminal_size() term_cols, term_lines = get_terminal_size()
if term_cols >= min_cols and term_lines >= min_lines: if term_cols >= min_cols and term_lines >= min_lines:
return return True
cols = max(term_cols, min_cols) cols = max(term_cols, min_cols)
lines = max(term_lines, min_lines) lines = max(term_lines, min_lines)
set_terminal_size(cols, lines) return set_terminal_size(cols, lines)
class IntSlider(npyscreen.Slider): class IntSlider(npyscreen.Slider):