From 0f3dc232c13800b05c31550c53d56c348bb05e18 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Mon, 18 Sep 2023 10:27:31 -0400 Subject: [PATCH] add en show/hide/reorder --- CHANGELOG.md | 5 ++- modules/api/api.py | 3 +- modules/shared.py | 29 ++++++++++------- modules/ui_extra_networks.py | 62 +++++++++++++++++++++--------------- 4 files changed, 59 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd92b2c7e..2917625ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,13 @@ # Change Log for SD.Next -## Update for 2023-09-15 +## Update for 2023-09-18 Downgrade of `diffusers` to 0.20.2 due to critical issue with model offloading This means that new model **Wuerstchen** is not supported until diffusers issue is resolved +- Added **change log** to UI, see *System -> Changelog* +- **Extra networks**: faster search, ability to show/hide/sort networks + ## Update for 2023-09-13 Started as a mostly a service release with quite a few fixes, but then... diff --git a/modules/api/api.py b/modules/api/api.py index 36a22e423..e750fccb4 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -504,9 +504,8 @@ class Api: } def get_extra_networks(self, page: Optional[str] = None, name: Optional[str] = None, filename: Optional[str] = None, title: Optional[str] = None, fullname: Optional[str] = None, hash: Optional[str] = None): # pylint: disable=redefined-builtin - import modules.ui_extra_networks res = [] - for pg in modules.ui_extra_networks.extra_pages: + for pg in shared.extra_networks: if page is not None and pg.name != page.lower(): continue for item in pg.items: diff --git a/modules/shared.py b/modules/shared.py index 713074f45..97f15e5e5 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -11,7 +11,7 @@ from enum import Enum import gradio as gr import fasteners from rich.console import Console -from modules import errors, ui_components, shared_items, cmd_args +from modules import errors, shared_items, cmd_args, ui_components from modules.paths_internal import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir # pylint: disable=W0611 from modules.dml import memory_providers, default_memory_provider, directml_do_hijack import modules.interrogate @@ -37,6 +37,7 @@ interrogator = modules.interrogate.InterrogateModels("interrogate") sd_upscalers = [] face_restorers = [] tab_names = [] +extra_networks = [] options_templates = {} hypernetworks = {} loaded_hypernetworks = [] @@ -71,21 +72,12 @@ restricted_opts = { compatibility_opts = ['clip_skip', 'uni_pc_lower_order_final', 'uni_pc_order'] console = Console(log_time=True, log_time_format='%H:%M:%S-%f') -def is_url(string): - parsed_url = urlparse(string) - return all([parsed_url.scheme, parsed_url.netloc]) - class Backend(Enum): ORIGINAL = 1 DIFFUSERS = 2 -def reload_hypernetworks(): - from modules.hypernetworks import hypernetwork - global hypernetworks # pylint: disable=W0603 - hypernetworks = hypernetwork.list_hypernetworks(opts.hypernetwork_dir) - class State: skipped = False @@ -192,6 +184,7 @@ class State: self.current_image = image self.id_live_preview += 1 + state = State() state.server_start = time.time() if not hasattr(cmd_opts, "use_openvino"): @@ -251,6 +244,17 @@ def list_checkpoint_tiles(): default_checkpoint = list_checkpoint_tiles()[0] if len(list_checkpoint_tiles()) > 0 else "model.ckpt" +def is_url(string): + parsed_url = urlparse(string) + return all([parsed_url.scheme, parsed_url.netloc]) + + +def reload_hypernetworks(): + from modules.hypernetworks import hypernetwork + global hypernetworks # pylint: disable=W0603 + hypernetworks = hypernetwork.list_hypernetworks(opts.hypernetwork_dir) + + def refresh_checkpoints(): import modules.sd_models # pylint: disable=W0621 return modules.sd_models.list_models() @@ -644,6 +648,7 @@ options_templates.update(options_section(('interrogate', "Interrogate"), { })) options_templates.update(options_section(('extra_networks', "Extra Networks"), { + "extra_networks": OptionInfo(["All"], "Extra networks", ui_components.DropdownMulti, lambda: {"choices": ['All'] + [en.title for en in extra_networks]}), "extra_networks_card_cover": OptionInfo("sidebar", "UI position", gr.Radio, lambda: {"choices": ["cover", "inline", "sidebar"]}), "extra_networks_height": OptionInfo(53, "UI height (%)", gr.Slider, {"minimum": 10, "maximum": 100, "step": 1}), "extra_networks_sidebar_width": OptionInfo(35, "UI sidebar width (%)", gr.Slider, {"minimum": 10, "maximum": 80, "step": 1}), @@ -653,8 +658,8 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), { "extra_networks_card_fit": OptionInfo("cover", "UI image contain method", gr.Radio, lambda: {"choices": ["contain", "cover", "fill"]}), "extra_network_skip_indexing": OptionInfo(False, "Do not automatically build extra network pages", gr.Checkbox), "lyco_patch_lora": OptionInfo(False, "Use LyCoris handler for all LoRA types", gr.Checkbox), - "lora_functional": OptionInfo(False, "Use Kohya method for handling multiple LoRA", gr.Checkbox), - "extra_networks_default_multiplier": OptionInfo(1.0, "Multiplier for extra networks", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01}), + "lora_functional": OptionInfo(False, "Use Kohya method for handling multiple LoRA", gr.Checkbox, { "visible": False }), + "extra_networks_default_multiplier": OptionInfo(1.0, "Multiplier for extra networks", gr.Slider, {"minimum": 0.0, "maximum": 1.0, "step": 0.01, "visible": False}), "sd_hypernetwork": OptionInfo("None", "Add hypernetwork to prompt", gr.Dropdown, lambda: { "choices": ["None"] + list(hypernetworks.keys()), "visible": False }, refresh=reload_hypernetworks), })) diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py index caf0d39fd..bf70cf4d7 100644 --- a/modules/ui_extra_networks.py +++ b/modules/ui_extra_networks.py @@ -16,10 +16,10 @@ from modules.ui_components import ToolButton import modules.ui_symbols as symbols -extra_pages = [] allowed_dirs = [] dir_cache = {} # key=path, value=(mtime, listdir(path)) refresh_time = None +extra_pages = shared.extra_networks def listdir(path): @@ -37,9 +37,9 @@ def listdir(path): def register_page(page): # registers extra networks page for the UI; recommend doing it in on_before_ui() callback for extensions - extra_pages.append(page) + shared.extra_networks.append(page) allowed_dirs.clear() - for page in extra_pages: + for page in shared.extra_networks: for folder in page.allowed_directories_for_previews(): if folder not in allowed_dirs: allowed_dirs.append(os.path.abspath(folder)) @@ -58,7 +58,7 @@ def fetch_file(filename: str = ""): def get_metadata(page: str = "", item: str = ""): - page = next(iter([x for x in extra_pages if x.name == page]), None) + page = next(iter([x for x in shared.extra_networks if x.name == page]), None) if page is None: return JSONResponse({ 'metadata': 'none' }) metadata = page.metadata.get(item, 'none') @@ -69,7 +69,7 @@ def get_metadata(page: str = "", item: str = ""): def get_info(page: str = "", item: str = ""): - page = next(iter([x for x in extra_pages if x.name == page]), None) + page = next(iter([x for x in shared.extra_networks if x.name == page]), None) if page is None: return JSONResponse({ 'info': 'none' }) info = page.info.get(item, 'none') @@ -308,7 +308,7 @@ class ExtraNetworksPage: shared.log.error(f'Extra network save preview: {filename} {e}') return is_allowed = False - for page in extra_pages: + for page in shared.extra_networks: if any(path_is_parent(x, filename) for x in page.allowed_directories_for_previews()): is_allowed = True break @@ -339,7 +339,7 @@ class ExtraNetworksPage: def initialize(): - extra_pages.clear() + shared.extra_networks.clear() def register_pages(): @@ -353,6 +353,21 @@ def register_pages(): register_page(ExtraNetworksPageHypernetworks()) +def get_pages(): + pages = [] + if 'All' in shared.opts.extra_networks: + pages = shared.extra_networks + else: + titles = [page.title for page in shared.extra_networks] + for page in shared.opts.extra_networks: + try: + idx = titles.index(page) + except ValueError: + continue + pages.append(shared.extra_networks[idx]) + return pages + + class ExtraNetworksUi: def __init__(self): self.pages = None @@ -384,7 +399,7 @@ def create_ui(container, button, tabname, skip_indexing = False): if ui.tabname == 'txt2img': # refresh only once global refresh_time # pylint: disable=global-statement refresh_time = time.time() - for page in extra_pages: + for page in get_pages(): page.create_page(ui.tabname, skip_indexing) with gr.Tab(page.title, id=page.title.lower().replace(" ", "_"), elem_classes="extra-networks-tab"): hmtl = gr.HTML(page.html, elem_id=f'{tabname}{page.name}_extra_page', elem_classes="extra-networks-page") @@ -396,16 +411,16 @@ def create_ui(container, button, tabname, skip_indexing = False): return is_visible, gr.update(visible=is_visible), gr.update(variant=("secondary-down" if is_visible else "secondary")) def en_refresh(title): - res = [] - for page in extra_pages: + pages = [] + for page in get_pages(): if title is None or title == '' or title == page.title or len(page.html) == 0: page.refresh() page.refresh_time = None page.create_page(ui.tabname) shared.log.debug(f"Refreshing Extra networks: page='{page.title}' items={len(page.items)} tab={ui.tabname}") - res.append(page.html) + pages.append(page.html) ui.search.update(value = ui.search.value) - return res + return pages state_visible = gr.State(value=False) # pylint: disable=abstract-class-instantiated button.click(fn=toggle_visibility, inputs=[state_visible], outputs=[state_visible, container, button]) @@ -423,15 +438,13 @@ def path_is_parent(parent_path, child_path): def setup_ui(ui, gallery): def save_preview(pagename, index, images, filename): - res = [] - for page in extra_pages: + pages = [] + for page in get_pages(): if pagename is None or pagename == '' or pagename == page.title or len(page.html) == 0: page.save_preview(index, images, filename) - res.append(page.create_page(ui.tabname)) - else: - res.append(page.html) - return res - + page.create_page(ui.tabname) + pages.append(page.html) + return pages ui.button_save_preview.click( fn=save_preview, @@ -441,14 +454,13 @@ def setup_ui(ui, gallery): ) def save_description(pagename, filename, desc): - res = [] - for page in extra_pages: + pages = [] + for page in get_pages(): if pagename is None or pagename == '' or pagename == page.title or len(page.html) == 0: page.save_description(filename, desc) - res.append(page.create_page(ui.tabname)) - else: - res.append(page.html) - return res + page.create_page(ui.tabname) + pages.append(page.html) + return pages ui.button_save_description.click( fn=save_description,