From e881222b1ac8cd74319da09a85de2505303854f3 Mon Sep 17 00:00:00 2001 From: uisl Date: Wed, 31 Dec 2025 22:16:12 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=8A=A0=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/config.py | 12 +++++----- modules/sdcpp.py | 5 +++++ modules/utils/encryption.py | 34 ++++++++++++++++++++++++++++ modules/utils/image_display.py | 41 ++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 5 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 modules/utils/encryption.py create mode 100644 modules/utils/image_display.py diff --git a/modules/config.py b/modules/config.py index 1f2340e..89199db 100644 --- a/modules/config.py +++ b/modules/config.py @@ -24,13 +24,15 @@ 'imgedit_dir': os.path.join(CURRENT_DIR, "outputs/imgedit/"), 'any2video_dir': os.path.join(CURRENT_DIR, "outputs/any2video/"), 'upscale_dir': os.path.join(CURRENT_DIR, "outputs/upscale/"), + 'enable_encryption': True, + 'encryption_password': '123', 'def_type': "Default", - 'def_sampling': "euler_a", - 'def_steps': 20, + 'def_sampling': "euler", + 'def_steps': 8, 'def_scheduler': "discrete", - 'def_width': 512, - 'def_height': 512, - 'def_cfg': 7.0, + 'def_width': 1024, + 'def_height': 1024, + 'def_cfg': 1.0, 'def_flow_shift_bool': False, 'def_flow_shift': 3.0, 'def_guidance_bool': False, diff --git a/modules/sdcpp.py b/modules/sdcpp.py index 52a7711..cbe4c8f 100644 --- a/modules/sdcpp.py +++ b/modules/sdcpp.py @@ -36,6 +36,8 @@ def __init__(self, mode: str, params: Dict[str, Any]): self.outputs = [] self.output_path = "" self.preview_path = None + self.enable_encryption = config.get('enable_encryption', False) + self.encryption_password = config.get('encryption_password', '123') def _extract_env_vars(self) -> Dict[str, Any]: """ @@ -139,6 +141,9 @@ def _add_base_args(self): '--lora-apply-mode', str(self._get_param('in_lora_apply')), '-o', self.output_path ]) + + if self.enable_encryption: + self.command.extend(['--encrypt', self.encryption_password]) def _add_options(self, options: Dict[str, Any]): """Adds key-value options to the command if the value is not None.""" diff --git a/modules/utils/encryption.py b/modules/utils/encryption.py new file mode 100644 index 0000000..b70e541 --- /dev/null +++ b/modules/utils/encryption.py @@ -0,0 +1,34 @@ +"""sd.cpp-webui - Image encryption module""" + +import os +import io +from PIL import Image + + +class ImageEncryption: + """处理图片的加密和解密(兼容 sd-cli 的 XOR 加密)""" + + def __init__(self, password="123"): + self.password = password + + def _generate_key(self): + """生成 256 字节密钥(与 decrypt.js 相同算法)""" + key = bytearray(256) + password_bytes = self.password.encode('utf-8') + for i in range(256): + key[i] = password_bytes[i % len(password_bytes)] ^ (i & 0xFF) + return bytes(key) + + def decrypt_image_file(self, encrypted_path): + """解密图片文件并返回 PIL Image 对象""" + with open(encrypted_path, 'rb') as f: + encrypted_data = f.read() + + # XOR 解密 + key = self._generate_key() + decrypted_data = bytearray(len(encrypted_data)) + for i in range(len(encrypted_data)): + decrypted_data[i] = encrypted_data[i] ^ key[i % len(key)] + + # 转换为 PIL Image + return Image.open(io.BytesIO(bytes(decrypted_data))) diff --git a/modules/utils/image_display.py b/modules/utils/image_display.py new file mode 100644 index 0000000..cd5710a --- /dev/null +++ b/modules/utils/image_display.py @@ -0,0 +1,41 @@ +"""sd.cpp-webui - Encrypted image display utilities""" + +import os +from modules.utils.encryption import ImageEncryption +from modules.shared_instance import config + + +def decrypt_and_display(image_paths): + """ + 解密图片列表并返回可显示的图片对象 + + Args: + image_paths: 图片路径列表或单个路径 + + Returns: + 解密后的 PIL Image 对象列表 + """ + enable_encryption = config.get('enable_encryption', False) + + if not enable_encryption: + return image_paths + + password = config.get('encryption_password', '123') + encryptor = ImageEncryption(password) + + if isinstance(image_paths, str): + image_paths = [image_paths] + + decrypted_images = [] + for path in image_paths: + if path and os.path.exists(path): + try: + img = encryptor.decrypt_image_file(path) + decrypted_images.append(img) + except Exception as e: + print(f"Failed to decrypt {path}: {e}") + decrypted_images.append(None) + else: + decrypted_images.append(None) + + return decrypted_images if len(decrypted_images) > 1 else decrypted_images[0] diff --git a/requirements.txt b/requirements.txt index 678bb85..a7930ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ gradio==5.44.1 +Pillow>=10.0.0 From b23192dbb67692850605a32484aed14f6bc579dd Mon Sep 17 00:00:00 2001 From: uisl Date: Wed, 31 Dec 2025 22:26:22 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=8A=A0=E5=AF=862?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/gallery.py | 13 ++++++++++++- modules/options_ui.py | 17 +++++++++++++++++ modules/txt2img_ui.py | 8 +++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/modules/gallery.py b/modules/gallery.py index 38eb95e..9def061 100644 --- a/modules/gallery.py +++ b/modules/gallery.py @@ -267,7 +267,18 @@ def reload_gallery( page_files = files[start_index:end_index] - imgs = [Image.open(path) for path in page_files] + # 解密图片 + from modules.utils.image_display import decrypt_and_display + imgs = [] + for path in page_files: + try: + img = decrypt_and_display(path) + if img is None: + img = Image.open(path) + imgs.append(img) + except Exception as e: + print(f"Failed to load image {path}: {e}") + imgs.append(Image.open(path)) dir_map = { 0: 'txt2img', diff --git a/modules/options_ui.py b/modules/options_ui.py index 3b98272..05ba52e 100644 --- a/modules/options_ui.py +++ b/modules/options_ui.py @@ -250,6 +250,23 @@ def save_settings_wrapper(*args): ) settings_map['def_gallery_sorting'] = sort_order + with gr.Accordion(label="Encryption Settings", open=False): + with gr.Row(): + enable_encryption = gr.Checkbox( + label="Enable Image Encryption", + value=config.get('enable_encryption', False), + interactive=True + ) + settings_map['enable_encryption'] = enable_encryption + with gr.Row(): + encryption_password = gr.Textbox( + label="Encryption Password", + value=config.get('encryption_password', '123'), + interactive=True, + type="password" + ) + settings_map['encryption_password'] = encryption_password + # Folders options folders_ui = create_folders_opt_ui() settings_map.update({ diff --git a/modules/txt2img_ui.py b/modules/txt2img_ui.py index d60144c..01bbfd3 100644 --- a/modules/txt2img_ui.py +++ b/modules/txt2img_ui.py @@ -229,13 +229,19 @@ def poll_status(): queue_update = gr.update(value=f"⏳ Jobs in queue: {q_len}", visible=True) else: queue_update = gr.update(visible=False) + + # 解密图片 + images = state["images"] + if images: + from modules.utils.image_display import decrypt_and_display + images = decrypt_and_display(images) return ( state["command"], state["progress"], state["status"], state["stats"], - state["images"], + images, timer_update, queue_update ) From e280bdec341b279e606242bcbb1fcf408c31363a Mon Sep 17 00:00:00 2001 From: uisl Date: Wed, 31 Dec 2025 22:34:16 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=8A=A0=E5=AF=863?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/txt2img_ui.py | 7 ++++++- modules/utils/image_display.py | 10 ++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/modules/txt2img_ui.py b/modules/txt2img_ui.py index 01bbfd3..3f43de5 100644 --- a/modules/txt2img_ui.py +++ b/modules/txt2img_ui.py @@ -234,7 +234,12 @@ def poll_status(): images = state["images"] if images: from modules.utils.image_display import decrypt_and_display - images = decrypt_and_display(images) + if isinstance(images, list): + images = [decrypt_and_display(img) if isinstance(img, str) else img for img in images] + else: + images = decrypt_and_display(images) + if not isinstance(images, list): + images = [images] return ( state["command"], diff --git a/modules/utils/image_display.py b/modules/utils/image_display.py index cd5710a..9b9e2e5 100644 --- a/modules/utils/image_display.py +++ b/modules/utils/image_display.py @@ -13,7 +13,7 @@ def decrypt_and_display(image_paths): image_paths: 图片路径列表或单个路径 Returns: - 解密后的 PIL Image 对象列表 + 解密后的 PIL Image 对象或列表 """ enable_encryption = config.get('enable_encryption', False) @@ -23,7 +23,8 @@ def decrypt_and_display(image_paths): password = config.get('encryption_password', '123') encryptor = ImageEncryption(password) - if isinstance(image_paths, str): + is_single = isinstance(image_paths, str) + if is_single: image_paths = [image_paths] decrypted_images = [] @@ -34,8 +35,9 @@ def decrypt_and_display(image_paths): decrypted_images.append(img) except Exception as e: print(f"Failed to decrypt {path}: {e}") - decrypted_images.append(None) + from PIL import Image + decrypted_images.append(Image.open(path)) else: decrypted_images.append(None) - return decrypted_images if len(decrypted_images) > 1 else decrypted_images[0] + return decrypted_images[0] if is_single else decrypted_images From a25feed3fc0f800365604cfd6a3e0c1602aaf0f2 Mon Sep 17 00:00:00 2001 From: uisl Date: Wed, 31 Dec 2025 22:58:12 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=8A=A0=E5=AF=864?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/txt2img_ui.py | 15 +++++++++++---- modules/utils/image_display.py | 11 +++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/modules/txt2img_ui.py b/modules/txt2img_ui.py index 3f43de5..826c1c0 100644 --- a/modules/txt2img_ui.py +++ b/modules/txt2img_ui.py @@ -235,11 +235,18 @@ def poll_status(): if images: from modules.utils.image_display import decrypt_and_display if isinstance(images, list): - images = [decrypt_and_display(img) if isinstance(img, str) else img for img in images] + decrypted = [] + for img in images: + if isinstance(img, str): + result = decrypt_and_display(img) + if result: + decrypted.append(result) + else: + decrypted.append(img) + images = decrypted if decrypted else images else: - images = decrypt_and_display(images) - if not isinstance(images, list): - images = [images] + result = decrypt_and_display(images) + images = [result] if result else images return ( state["command"], diff --git a/modules/utils/image_display.py b/modules/utils/image_display.py index 9b9e2e5..8669ebd 100644 --- a/modules/utils/image_display.py +++ b/modules/utils/image_display.py @@ -27,6 +27,7 @@ def decrypt_and_display(image_paths): if is_single: image_paths = [image_paths] + from PIL import Image decrypted_images = [] for path in image_paths: if path and os.path.exists(path): @@ -34,10 +35,12 @@ def decrypt_and_display(image_paths): img = encryptor.decrypt_image_file(path) decrypted_images.append(img) except Exception as e: - print(f"Failed to decrypt {path}: {e}") - from PIL import Image - decrypted_images.append(Image.open(path)) + print(f"Failed to decrypt {path}: {e}, trying direct open") + try: + decrypted_images.append(Image.open(path)) + except Exception as e2: + print(f"Failed to open {path}: {e2}") else: - decrypted_images.append(None) + print(f"Path does not exist: {path}") return decrypted_images[0] if is_single else decrypted_images From 62351a759095622c6931fcd95e6da565662d6e31 Mon Sep 17 00:00:00 2001 From: uisl Date: Wed, 31 Dec 2025 23:05:20 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=8A=A0=E5=AF=865?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/sdcpp.py | 4 ++-- modules/txt2img_ui.py | 4 ++-- modules/utils/image_display.py | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/sdcpp.py b/modules/sdcpp.py index cbe4c8f..74126d1 100644 --- a/modules/sdcpp.py +++ b/modules/sdcpp.py @@ -178,8 +178,8 @@ def _prepare_for_run(self): self.outputs = [self.output_path] else: base, ext = os.path.splitext(self.output_path) - self.outputs = [self.output_path] + [ - f"{base}_{i}{ext}" for i in range(2, batch_count + 1) + self.outputs = [ + f"{base}_{i}{ext}" for i in range(batch_count) ] def build_command(self): diff --git a/modules/txt2img_ui.py b/modules/txt2img_ui.py index 826c1c0..568a2e9 100644 --- a/modules/txt2img_ui.py +++ b/modules/txt2img_ui.py @@ -243,10 +243,10 @@ def poll_status(): decrypted.append(result) else: decrypted.append(img) - images = decrypted if decrypted else images + images = decrypted if decrypted else None else: result = decrypt_and_display(images) - images = [result] if result else images + images = result return ( state["command"], diff --git a/modules/utils/image_display.py b/modules/utils/image_display.py index 8669ebd..b0b69ff 100644 --- a/modules/utils/image_display.py +++ b/modules/utils/image_display.py @@ -43,4 +43,7 @@ def decrypt_and_display(image_paths): else: print(f"Path does not exist: {path}") + if not decrypted_images: + return None if is_single else [] + return decrypted_images[0] if is_single else decrypted_images From ad8b504eefb2ae6dc757cab1c0e42c9723240264 Mon Sep 17 00:00:00 2001 From: uisl Date: Thu, 1 Jan 2026 11:14:55 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0lora=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ui/lora_selector.py | 60 +++++++++++++++++++++++++++++++++++++ modules/ui/prompts.py | 17 +++++++++++ 2 files changed, 77 insertions(+) create mode 100644 modules/ui/lora_selector.py diff --git a/modules/ui/lora_selector.py b/modules/ui/lora_selector.py new file mode 100644 index 0000000..d73af0e --- /dev/null +++ b/modules/ui/lora_selector.py @@ -0,0 +1,60 @@ +"""sd.cpp-webui - LoRA selector UI component""" + +import os +import gradio as gr +from modules.shared_instance import config +from modules.loader import get_models + + +def create_lora_selector_ui(): + """Create LoRA selector UI with insert functionality""" + + lora_dir = config.get('lora_dir') + + def get_lora_list(): + """Get list of LoRA files without extensions""" + loras = get_models(lora_dir) + return [os.path.splitext(lora)[0] for lora in loras] + + def insert_lora(current_prompt, lora_name, strength): + """Insert LoRA tag into prompt""" + if not lora_name: + return current_prompt + + lora_tag = f"" + + if current_prompt: + return f"{current_prompt} {lora_tag}" + return lora_tag + + def refresh_loras(): + """Refresh LoRA list""" + return gr.update(choices=get_lora_list()) + + with gr.Accordion(label="LoRA Selector", open=False): + with gr.Row(): + lora_dropdown = gr.Dropdown( + label="Select LoRA", + choices=get_lora_list(), + interactive=True, + allow_custom_value=False + ) + lora_strength = gr.Slider( + label="Strength", + minimum=0.0, + maximum=2.0, + value=0.8, + step=0.05 + ) + with gr.Row(): + insert_btn = gr.Button(value="Insert to Prompt", size="sm") + refresh_btn = gr.Button(value="🔄", size="sm") + + return { + 'lora_dropdown': lora_dropdown, + 'lora_strength': lora_strength, + 'insert_btn': insert_btn, + 'refresh_btn': refresh_btn, + 'insert_lora_fn': insert_lora, + 'refresh_loras_fn': refresh_loras + } diff --git a/modules/ui/prompts.py b/modules/ui/prompts.py index cdd6130..16eaa0c 100644 --- a/modules/ui/prompts.py +++ b/modules/ui/prompts.py @@ -4,6 +4,7 @@ from modules.shared_instance import config from .constants import RELOAD_SYMBOL +from .lora_selector import create_lora_selector_ui def create_prompts_ui(nprompt_support = True): @@ -55,6 +56,9 @@ def refresh_prompt_list(): save_prompt_btn = gr.Button( value="Save prompt", size="lg", ) + # LoRA Selector + lora_ui = create_lora_selector_ui() + with gr.Row(): pprompt = gr.Textbox( placeholder="Positive prompt\nUse loras from the loras folder with: , for example: ", @@ -95,6 +99,19 @@ def refresh_prompt_list(): inputs=[saved_prompts], outputs=[pprompt, nprompt] ) + + # LoRA selector bindings + lora_ui['insert_btn'].click( + lora_ui['insert_lora_fn'], + inputs=[pprompt, lora_ui['lora_dropdown'], lora_ui['lora_strength']], + outputs=[pprompt] + ) + + lora_ui['refresh_btn'].click( + lora_ui['refresh_loras_fn'], + inputs=[], + outputs=[lora_ui['lora_dropdown']] + ) return { 'saved_prompts': saved_prompts, From 332e8ee26b94e158edf97006b0bdd18a65ebd7ed Mon Sep 17 00:00:00 2001 From: uisl Date: Thu, 12 Mar 2026 12:02:29 +0800 Subject: [PATCH 07/10] =?UTF-8?q?fix:=20=E5=B0=9D=E8=AF=95=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ui/cache.py | 9 ++++++--- modules/ui/extra.py | 9 ++++++--- modules/ui/generation_settings.py | 6 ++++-- modules/ui/preview.py | 3 ++- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/modules/ui/cache.py b/modules/ui/cache.py index a634574..3202376 100644 --- a/modules/ui/cache.py +++ b/modules/ui/cache.py @@ -25,14 +25,16 @@ def create_cache_ui(): label="Cache mode", choices=CACHE_MODE, value=config.get('def_cache_mode'), - interactive=False + interactive=False, + allow_custom_value=True ) cache_dit_preset = gr.Dropdown( label="cache-dit preset", choices=CACHE_DIT_PRESET, value=config.get('def_cache_dit_preset'), - interactive=False + interactive=False, + allow_custom_value=True ) with gr.Accordion( @@ -64,7 +66,8 @@ def create_cache_ui(): scm_policy = gr.Dropdown( label="SCM Policy", choices=SCM_POLICY, - value=config.get('def_scm_policy') + value=config.get('def_scm_policy'), + allow_custom_value=True ) cache_comp = [ diff --git a/modules/ui/extra.py b/modules/ui/extra.py index 3a78273..0cc69de 100644 --- a/modules/ui/extra.py +++ b/modules/ui/extra.py @@ -23,17 +23,20 @@ def create_extras_ui(): rng = gr.Dropdown( label="RNG", choices=RNG, - value=config.get('def_rng') + value=config.get('def_rng'), + allow_custom_value=True ) sampler_rng = gr.Dropdown( label="Sampler RNG", choices=SAMPLER_RNG, - value=config.get('def_sampler_rng') + value=config.get('def_sampler_rng'), + allow_custom_value=True ) predict = gr.Dropdown( label="Prediction", choices=PREDICTION, - value=config.get('def_predict') + value=config.get('def_predict'), + allow_custom_value=True ) lora_apply = gr.Dropdown( label="Lora apply mode", diff --git a/modules/ui/generation_settings.py b/modules/ui/generation_settings.py index a5cab8a..11879fb 100644 --- a/modules/ui/generation_settings.py +++ b/modules/ui/generation_settings.py @@ -54,14 +54,16 @@ def create_generation_settings_ui(unet_mode: bool = False): label="Sampling method", choices=SAMPLERS, value=config.get('def_sampling'), - interactive=True + interactive=True, + allow_custom_value=True ) with gr.Column(): scheduler = gr.Dropdown( label="Scheduler", choices=SCHEDULERS, value=config.get('def_scheduler'), - interactive=True + interactive=True, + allow_custom_value=True ) with gr.Row(): diff --git a/modules/ui/preview.py b/modules/ui/preview.py index c1d8a70..cc1da1e 100644 --- a/modules/ui/preview.py +++ b/modules/ui/preview.py @@ -20,7 +20,8 @@ def create_preview_ui(): preview_mode = gr.Dropdown( label="Preview mode", choices=PREVIEW, - value=config.get('def_preview_mode') + value=config.get('def_preview_mode'), + allow_custom_value=True ) preview_interval = gr.Number( label="Preview interval", From 888a06422c4cc524c748c72c747b195bf96339f7 Mon Sep 17 00:00:00 2001 From: uisl Date: Thu, 12 Mar 2026 12:18:22 +0800 Subject: [PATCH 08/10] =?UTF-8?q?Revert=20"fix:=20=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E8=AD=A6=E5=91=8A"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 332e8ee26b94e158edf97006b0bdd18a65ebd7ed. --- modules/ui/cache.py | 9 +++------ modules/ui/extra.py | 9 +++------ modules/ui/generation_settings.py | 6 ++---- modules/ui/preview.py | 3 +-- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/modules/ui/cache.py b/modules/ui/cache.py index 3202376..a634574 100644 --- a/modules/ui/cache.py +++ b/modules/ui/cache.py @@ -25,16 +25,14 @@ def create_cache_ui(): label="Cache mode", choices=CACHE_MODE, value=config.get('def_cache_mode'), - interactive=False, - allow_custom_value=True + interactive=False ) cache_dit_preset = gr.Dropdown( label="cache-dit preset", choices=CACHE_DIT_PRESET, value=config.get('def_cache_dit_preset'), - interactive=False, - allow_custom_value=True + interactive=False ) with gr.Accordion( @@ -66,8 +64,7 @@ def create_cache_ui(): scm_policy = gr.Dropdown( label="SCM Policy", choices=SCM_POLICY, - value=config.get('def_scm_policy'), - allow_custom_value=True + value=config.get('def_scm_policy') ) cache_comp = [ diff --git a/modules/ui/extra.py b/modules/ui/extra.py index 0cc69de..3a78273 100644 --- a/modules/ui/extra.py +++ b/modules/ui/extra.py @@ -23,20 +23,17 @@ def create_extras_ui(): rng = gr.Dropdown( label="RNG", choices=RNG, - value=config.get('def_rng'), - allow_custom_value=True + value=config.get('def_rng') ) sampler_rng = gr.Dropdown( label="Sampler RNG", choices=SAMPLER_RNG, - value=config.get('def_sampler_rng'), - allow_custom_value=True + value=config.get('def_sampler_rng') ) predict = gr.Dropdown( label="Prediction", choices=PREDICTION, - value=config.get('def_predict'), - allow_custom_value=True + value=config.get('def_predict') ) lora_apply = gr.Dropdown( label="Lora apply mode", diff --git a/modules/ui/generation_settings.py b/modules/ui/generation_settings.py index 11879fb..a5cab8a 100644 --- a/modules/ui/generation_settings.py +++ b/modules/ui/generation_settings.py @@ -54,16 +54,14 @@ def create_generation_settings_ui(unet_mode: bool = False): label="Sampling method", choices=SAMPLERS, value=config.get('def_sampling'), - interactive=True, - allow_custom_value=True + interactive=True ) with gr.Column(): scheduler = gr.Dropdown( label="Scheduler", choices=SCHEDULERS, value=config.get('def_scheduler'), - interactive=True, - allow_custom_value=True + interactive=True ) with gr.Row(): diff --git a/modules/ui/preview.py b/modules/ui/preview.py index cc1da1e..c1d8a70 100644 --- a/modules/ui/preview.py +++ b/modules/ui/preview.py @@ -20,8 +20,7 @@ def create_preview_ui(): preview_mode = gr.Dropdown( label="Preview mode", choices=PREVIEW, - value=config.get('def_preview_mode'), - allow_custom_value=True + value=config.get('def_preview_mode') ) preview_interval = gr.Number( label="Preview interval", From f9267303041f2b29f225a4fbb6669a4861566259 Mon Sep 17 00:00:00 2001 From: uisl Date: Thu, 12 Mar 2026 12:45:56 +0800 Subject: [PATCH 09/10] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E9=83=A8?= =?UTF-8?q?=E5=88=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/interfaces/cli/txt2img_tab.py | 68 +-------------------------- modules/utils/ui_events.py | 20 +++++++- 2 files changed, 21 insertions(+), 67 deletions(-) diff --git a/modules/interfaces/cli/txt2img_tab.py b/modules/interfaces/cli/txt2img_tab.py index 59b63a2..c1d0f81 100644 --- a/modules/interfaces/cli/txt2img_tab.py +++ b/modules/interfaces/cli/txt2img_tab.py @@ -218,72 +218,8 @@ 'queue_tracker': queue_tracker } - queue_manager.add_job(txt2img, params) - - q_len = queue_manager.get_queue_size() - - print(f"\n\nJob submitted! Position in queue: {q_len}.\n"), - - return ( - gr.Timer(value=0.01, active=True) - ) - - - def poll_status(): - state = queue_manager.get_status() - q_len = queue_manager.get_queue_size() - - if state["is_running"] or q_len > 0: - timer_update = gr.Timer(value=0.01, active=True) - else: - timer_update = gr.Timer(active=False) - - if q_len > 0: - queue_update = gr.update(value=f"⏳ Jobs in queue: {q_len}", visible=True) - else: - queue_update = gr.update(visible=False) - - # 解密图片 - images = state["images"] - if images: - from modules.utils.image_display import decrypt_and_display - if isinstance(images, list): - decrypted = [] - for img in images: - if isinstance(img, str): - result = decrypt_and_display(img) - if result: - decrypted.append(result) - else: - decrypted.append(img) - images = decrypted if decrypted else None - else: - result = decrypt_and_display(images) - images = result - - return ( - state["command"], - state["progress"], - state["status"], - state["stats"], - images, - timer_update, - queue_update - ) - - - timer = gr.Timer(value=0.01, active=False) - - gen_btn.click( - submit_job, - inputs=ordered_components, - outputs=[timer] - ) - - timer.tick( - poll_status, - inputs=[], - outputs=[command, progress_slider, progress_textbox, stats, img_final, timer, queue_tracker] + bind_generation_pipeline( + txt2img, ordered_keys, ordered_components, ui_outputs ) kill_btn.click( diff --git a/modules/utils/ui_events.py b/modules/utils/ui_events.py index 680dc1d..a9d0e52 100644 --- a/modules/utils/ui_events.py +++ b/modules/utils/ui_events.py @@ -71,12 +71,30 @@ def poll_status(): visible=(q_len > 0) ) + # 解密图片 + images = state["images"] + if images: + from modules.utils.image_display import decrypt_and_display + if isinstance(images, list): + decrypted = [] + for img in images: + if isinstance(img, str): + result = decrypt_and_display(img) + if result: + decrypted.append(result) + else: + decrypted.append(img) + images = decrypted if decrypted else None + else: + result = decrypt_and_display(images) + images = result + return ( state["command"], prog, stat, state["stats"], - state["images"], + images, gr.skip(), queue_display ) From d042e5649389153e6dcb41443a8fa2fab6c693e1 Mon Sep 17 00:00:00 2001 From: uisl Date: Thu, 12 Mar 2026 14:06:41 +0800 Subject: [PATCH 10/10] =?UTF-8?q?fix:=20=E4=BF=9D=E7=95=99=E5=8E=9F?= =?UTF-8?q?=E4=BD=9C=E8=80=85lora=E9=80=89=E6=8B=A9=E5=99=A8=EF=BC=8C?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E8=87=AA=E5=B7=B1=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ui/lora_selector.py | 60 ------------------------------------- modules/ui/prompts.py | 18 +---------- 2 files changed, 1 insertion(+), 77 deletions(-) delete mode 100644 modules/ui/lora_selector.py diff --git a/modules/ui/lora_selector.py b/modules/ui/lora_selector.py deleted file mode 100644 index d73af0e..0000000 --- a/modules/ui/lora_selector.py +++ /dev/null @@ -1,60 +0,0 @@ -"""sd.cpp-webui - LoRA selector UI component""" - -import os -import gradio as gr -from modules.shared_instance import config -from modules.loader import get_models - - -def create_lora_selector_ui(): - """Create LoRA selector UI with insert functionality""" - - lora_dir = config.get('lora_dir') - - def get_lora_list(): - """Get list of LoRA files without extensions""" - loras = get_models(lora_dir) - return [os.path.splitext(lora)[0] for lora in loras] - - def insert_lora(current_prompt, lora_name, strength): - """Insert LoRA tag into prompt""" - if not lora_name: - return current_prompt - - lora_tag = f"" - - if current_prompt: - return f"{current_prompt} {lora_tag}" - return lora_tag - - def refresh_loras(): - """Refresh LoRA list""" - return gr.update(choices=get_lora_list()) - - with gr.Accordion(label="LoRA Selector", open=False): - with gr.Row(): - lora_dropdown = gr.Dropdown( - label="Select LoRA", - choices=get_lora_list(), - interactive=True, - allow_custom_value=False - ) - lora_strength = gr.Slider( - label="Strength", - minimum=0.0, - maximum=2.0, - value=0.8, - step=0.05 - ) - with gr.Row(): - insert_btn = gr.Button(value="Insert to Prompt", size="sm") - refresh_btn = gr.Button(value="🔄", size="sm") - - return { - 'lora_dropdown': lora_dropdown, - 'lora_strength': lora_strength, - 'insert_btn': insert_btn, - 'refresh_btn': refresh_btn, - 'insert_lora_fn': insert_lora, - 'refresh_loras_fn': refresh_loras - } diff --git a/modules/ui/prompts.py b/modules/ui/prompts.py index 6866915..1d0613b 100644 --- a/modules/ui/prompts.py +++ b/modules/ui/prompts.py @@ -4,7 +4,6 @@ from modules.shared_instance import prompt_manager from .constants import RELOAD_SYMBOL -from .lora_selector import create_lora_selector_ui def create_prompts_ui(nprompt_support=True): @@ -56,9 +55,7 @@ def refresh_prompt_list(): save_prompt_btn = gr.Button( value="Save prompt", size="lg", ) - # LoRA Selector - lora_ui = create_lora_selector_ui() - + with gr.Row(): pprompt = gr.Textbox( placeholder="Positive prompt\nUse loras from the loras folder with: , for example: ", @@ -99,19 +96,6 @@ def refresh_prompt_list(): inputs=[saved_prompts], outputs=[pprompt, nprompt] ) - - # LoRA selector bindings - lora_ui['insert_btn'].click( - lora_ui['insert_lora_fn'], - inputs=[pprompt, lora_ui['lora_dropdown'], lora_ui['lora_strength']], - outputs=[pprompt] - ) - - lora_ui['refresh_btn'].click( - lora_ui['refresh_loras_fn'], - inputs=[], - outputs=[lora_ui['lora_dropdown']] - ) return { 'saved_prompts': saved_prompts,