separate file, and more function

This commit is contained in:
nabilaba 2025-06-11 00:09:21 +07:00
parent cdf57c251d
commit 1cde3d325d
3 changed files with 311 additions and 177 deletions

View File

@ -1,13 +0,0 @@
{
"default_refiner_switch": 0.5,
"default_cfg_scale": 4.0,
"default_sample_sharpness": 2.0,
"default_sampler": "dpmpp_2m_sde_gpu",
"default_scheduler": "karras",
"default_performance": "Quality",
"default_prompt": "ultra-detailed, photorealistic, 8K resolution, high dynamic range, realistic lighting, global illumination, shallow depth of field, cinematic look, DSLR camera, ray tracing, volumetric lighting, bokeh effect, hyper-realistic textures, shot on Canon EOS R5, 50mm lens, HDR imaging, post-processed in Adobe Lightroom and Photoshop",
"default_prompt_negative": "low resolution, extra limbs, cartoon, anime, illustration, drawing, painting, sketch, grainy, noisy, watermark, logo, text, glitch, jpeg artifacts, duplicate, poorly drawn, out of frame, cropped, low quality, bad anatomy, bad hands, extra fingers, distorted face",
"default_styles": [],
"default_aspect_ratio": "1080*1920",
"default_overwrite_step": -1
}

195
webui.py
View File

@ -24,6 +24,7 @@ from modules.ui_gradio_extensions import reload_javascript
from modules.auth import auth_enabled, check_auth
from modules.util import is_json
import webui_others
import os
import shutil
import requests
@ -562,7 +563,7 @@ with shared.gradio_root:
outputs=enhance_input_panel, queue=False, show_progress=False, _js=switch_js)
with gr.Column(scale=1, visible=modules.config.default_advanced_checkbox) as advanced_column:
with gr.Tab(label='Settings'):
with gr.Tab(label='Settings') as seetings_tab:
if not args_manager.args.disable_preset_selection:
preset_selection = gr.Dropdown(label='Preset',
choices=modules.config.available_presets,
@ -891,7 +892,23 @@ with shared.gradio_root:
refresh_files_output += [preset_selection]
refresh_files.click(refresh_files_clicked, [], refresh_files_output + lora_ctrls,
queue=False, show_progress=False)
advanced_checkbox.select(
fn=refresh_files_clicked,
inputs=[],
outputs=refresh_files_output + lora_ctrls,
queue=False,
show_progress=False
)
seetings_tab.select(
fn=refresh_files_clicked,
inputs=[],
outputs=refresh_files_output + lora_ctrls,
queue=False,
show_progress=False
)
model_tab.select(
fn=refresh_files_clicked,
inputs=[],
@ -900,168 +917,18 @@ with shared.gradio_root:
show_progress=False
)
with gr.Tab(label='Others'):
with gr.Column():
with gr.Tab(label='Download'):
file_input_path = gr.Textbox(
label='File Path or URL',
placeholder='Enter full path to file or downloadable URL',
lines=1
)
destination_folder = gr.Dropdown(
label='Target Folder',
choices=[
modules.config.paths_checkpoints[0],
modules.config.paths_loras[0],
modules.config.path_embeddings,
modules.config.path_vae,
modules.config.path_outputs
],
value=modules.config.paths_checkpoints[0]
)
download_result_text = gr.Textbox(label='Download Status', interactive=False)
download_file_button = gr.Button(value='\U00002B07 Download', variant='secondary', elem_classes='refresh_button')
def perform_download(file_url_or_path, target_directory):
try:
if isinstance(target_directory, tuple):
target_directory = target_directory[1]
if file_url_or_path.startswith(('http://', 'https://')):
response = requests.get(file_url_or_path, stream=True)
response.raise_for_status()
# Ambil nama file dari header jika tersedia
content_disposition = response.headers.get('Content-Disposition', '')
if 'filename=' in content_disposition:
filename = content_disposition.split('filename=')[-1].strip('"')
else:
# Fallback: ambil dari path URL
parsed_url = urlparse(file_url_or_path)
filename = unquote(os.path.basename(parsed_url.path))
downloaded_path = load_file_from_url(
file_url_or_path,
model_dir=target_directory,
progress=True,
file_name=filename
)
modules.config.update_files() # ✅ REFRESH MODEL LIST
return (
f"✅ Downloaded to: {downloaded_path}",
gr.update(choices=['None'] + modules.config.model_filenames),
gr.update(choices=['None'] + modules.config.model_filenames),
*[
item
for _ in range(len(lora_ctrls) // 3)
for item in (
gr.update(interactive=True),
gr.update(choices=['None'] + modules.config.lora_filenames),
gr.update()
)
]
)
if os.path.isfile(file_url_or_path):
filename = os.path.basename(file_url_or_path)
destination_path = os.path.join(target_directory, filename)
shutil.copy(file_url_or_path, destination_path)
modules.config.update_files() # ✅ Auto-refresh files
return (
f"✅ Copied to: {destination_path}",
gr.update(choices=['None'] + modules.config.model_filenames),
gr.update(choices=['None'] + modules.config.model_filenames),
*[
item
for _ in range(len(lora_ctrls) // 3)
for item in (
gr.update(interactive=True),
gr.update(choices=['None'] + modules.config.lora_filenames),
gr.update()
)
]
)
return ("❌ Error: File not found or invalid input.",) + (
gr.update(), gr.update(), *[gr.update()] * len(lora_ctrls)
)
except Exception as e:
return (f"❌ Failed: {str(e)}",) + (
gr.update(), gr.update(), *[gr.update()] * len(lora_ctrls)
)
download_file_button.click(
fn=perform_download,
inputs=[file_input_path, destination_folder],
outputs=[download_result_text, base_model, refiner_model] + lora_ctrls
)
with gr.Tab(label='Delete') as delete_tab:
delete_folder_dropdown = gr.Dropdown(
label='Select Folder',
choices=[
modules.config.paths_checkpoints[0],
modules.config.paths_loras[0],
modules.config.path_embeddings,
modules.config.path_vae,
modules.config.path_outputs
],
value=modules.config.paths_checkpoints[0]
)
file_list_dropdown = gr.Dropdown(label="Select File to Delete", choices=[], multiselect=True)
delete_button = gr.Button(value='\U0001F5D1 Delete Selected File(s)', variant='stop')
delete_status = gr.Textbox(visible=True, interactive=False, label="Delete Status")
def update_file_list(folder):
try:
files = [f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f))]
return gr.update(choices=files, value=[])
except Exception as e:
return gr.update(choices=[], value=[])
def delete_selected_files(folder, selected_files):
deleted = []
errors = []
for fname in selected_files:
try:
file_path = os.path.join(folder, fname)
if os.path.isfile(file_path):
os.remove(file_path)
deleted.append(fname)
else:
errors.append(fname)
except Exception as e:
errors.append(f"{fname} (error: {e})")
if not deleted and not errors:
status = "⚠️ No files selected."
else:
status = ""
if deleted:
status += f"✅ Deleted: {', '.join(deleted)}. "
if errors:
status += f"❌ Failed: {', '.join(errors)}"
try:
files = [f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f))]
except Exception:
files = []
return status.strip(), gr.update(choices=files, value=[])
delete_folder_dropdown.change(update_file_list, inputs=[delete_folder_dropdown], outputs=[file_list_dropdown])
delete_button.click(delete_selected_files, inputs=[delete_folder_dropdown, file_list_dropdown], outputs=[delete_status, file_list_dropdown])
delete_tab.select(
fn=update_file_list,
inputs=[delete_folder_dropdown],
outputs=[file_list_dropdown],
queue=False,
show_progress=False
)
webui_others.build_others_tab(
prompt=prompt,
negative_prompt=negative_prompt,
aspect_ratio=aspect_ratios_selection,
performance=performance_selection,
styles=style_selections,
base_model=base_model,
refiner_model=refiner_model,
refiner_switch=refiner_switch,
image_number=image_number,
lora_ctrls=lora_ctrls
)
state_is_generating = gr.State(False)

280
webui_others.py Normal file
View File

@ -0,0 +1,280 @@
# webui_others.py
import os
import shutil
import requests
from urllib.parse import urlparse, unquote
import gradio as gr
import modules.config
from modules.model_loader import load_file_from_url
def build_others_tab(
prompt,
negative_prompt,
aspect_ratio,
performance,
styles,
base_model,
refiner_model,
refiner_switch,
image_number,
lora_ctrls
):
with gr.Tab(label="Others") as others_tab:
with gr.Tab(label="Download"):
file_input_path = gr.Textbox(
label="File Path or URL",
placeholder="Enter full path to file or downloadable URL",
lines=1,
)
destination_folder = gr.Dropdown(
label="Target Folder",
choices=[
modules.config.paths_checkpoints[0],
modules.config.paths_loras[0],
modules.config.path_embeddings,
modules.config.path_vae,
],
value=modules.config.paths_checkpoints[0],
)
download_result_text = gr.Textbox(
label="Download Status", interactive=False
)
download_file_button = gr.Button(
value="\u2b07 Download",
variant="secondary",
elem_classes="refresh_button",
)
def perform_download(file_url_or_path, target_directory):
try:
if isinstance(target_directory, tuple):
target_directory = target_directory[1]
if file_url_or_path.startswith(("http://", "https://")):
response = requests.get(file_url_or_path, stream=True)
response.raise_for_status()
content_disposition = response.headers.get(
"Content-Disposition", ""
)
if "filename=" in content_disposition:
filename = content_disposition.split("filename=")[
-1
].strip('"')
else:
parsed_url = urlparse(file_url_or_path)
filename = unquote(os.path.basename(parsed_url.path))
downloaded_path = load_file_from_url(
file_url_or_path,
model_dir=target_directory,
progress=True,
file_name=filename,
)
return f"\u2705 Downloaded to: {downloaded_path}"
if os.path.isfile(file_url_or_path):
filename = os.path.basename(file_url_or_path)
destination_path = os.path.join(target_directory, filename)
shutil.copy(file_url_or_path, destination_path)
return f"\u2705 Copied to: {destination_path}"
return "\u274c Error: File not found or invalid input."
except Exception as e:
return f"\u274c Failed: {str(e)}"
download_file_button.click(
fn=perform_download,
inputs=[file_input_path, destination_folder],
outputs=[download_result_text],
)
with gr.Tab(label="Delete"):
delete_folder_dropdown = gr.Dropdown(
label="Select Folder",
choices=[
modules.config.paths_checkpoints[0],
modules.config.paths_loras[0],
modules.config.path_embeddings,
modules.config.path_vae,
modules.config.get_dir_or_set_default("path_presets", "../presets"),
],
value=modules.config.paths_checkpoints[0],
)
file_list_dropdown = gr.Dropdown(
label="Select File to Delete", choices=[], multiselect=True
)
delete_button = gr.Button(
value="\U0001f5d1 Delete Selected File(s)", variant="stop"
)
delete_status = gr.Textbox(
visible=True, interactive=False, label="Delete Status"
)
def update_file_list(folder):
try:
files = [
f
for f in os.listdir(folder)
if os.path.isfile(os.path.join(folder, f))
]
return gr.update(choices=files, value=[])
except Exception as e:
return gr.update(choices=[], value=[])
def delete_selected_files(folder, selected_files):
deleted = []
errors = []
for fname in selected_files:
try:
file_path = os.path.join(folder, fname)
if os.path.isfile(file_path):
os.remove(file_path)
deleted.append(fname)
else:
errors.append(fname)
except Exception as e:
errors.append(f"{fname} (error: {e})")
status = ""
if deleted:
status += f"\u2705 Deleted: {', '.join(deleted)}. "
if errors:
status += f"\u274c Failed: {', '.join(errors)}"
if not deleted and not errors:
status = "\u26a0\ufe0f No files selected."
try:
files = [
f
for f in os.listdir(folder)
if os.path.isfile(os.path.join(folder, f))
]
except Exception:
files = []
return status.strip(), gr.update(choices=files, value=[])
delete_folder_dropdown.change(
update_file_list,
inputs=[delete_folder_dropdown],
outputs=[file_list_dropdown],
)
delete_button.click(
delete_selected_files,
inputs=[delete_folder_dropdown, file_list_dropdown],
outputs=[delete_status, file_list_dropdown],
)
with gr.Tab(label="Backup/Restore"):
with gr.Tab(label="Preset"):
with gr.Row():
backup_name = gr.Textbox(label="Backup Filename (no extension)", placeholder="e.g. my_config_backup")
backup_button = gr.Button(value="\u2B06 Backup Settings")
backup_file = gr.File(label="Download .json", interactive=False)
def clean_aspect_ratio(value):
if not value:
return None
raw = value.split(" ")[0]
return raw.replace("×", "*") # convert Unicode × to ASCII *
def backup_selected_settings(
filename,
prompt, negative_prompt, aspect_ratio, performance, styles,
base_model, refiner_model, refiner_switch, image_number,
*lora_ctrls
):
import json
if not filename:
return None
config = {
"default_prompt": prompt,
"default_prompt_negative": negative_prompt,
"default_aspect_ratio": clean_aspect_ratio(aspect_ratio),
"default_performance": performance,
"default_styles": styles,
"default_model": base_model,
"default_refiner": refiner_model,
"default_refiner_switch": refiner_switch,
"default_image_number": image_number
}
loras = []
for i in range(0, len(lora_ctrls), 3):
enabled = lora_ctrls[i]
model = lora_ctrls[i + 1]
weight = lora_ctrls[i + 2]
if model and model != "None":
loras.append([enabled, model, weight])
if loras:
config["default_loras"] = loras
config = {k: v for k, v in config.items() if v not in [None, "", [], "None"]}
out_path = os.path.join("outputs", f"{filename}.json")
with open(out_path, "w") as f:
json.dump(config, f, indent=2)
return out_path
backup_button.click(
fn=backup_selected_settings,
inputs=[
backup_name,
prompt,
negative_prompt,
aspect_ratio,
performance,
styles,
base_model,
refiner_model,
refiner_switch,
image_number,
] + lora_ctrls,
outputs=[backup_file],
)
with gr.Tab(label="Restore"):
with gr.Row():
restore_file = gr.File(label="Upload Config File (.json)", file_types=[".json"])
restore_button = gr.Button(value="\u267B Restore to Presets Folder")
restore_status = gr.Textbox(label="Status", interactive=False)
def restore_config_file(file_obj):
try:
if file_obj is None:
return "\u26A0 No file selected."
filename = os.path.basename(file_obj.name)
presets_dir = os.path.join("presets")
os.makedirs(presets_dir, exist_ok=True)
destination = os.path.join(presets_dir, filename)
shutil.copy(file_obj.name, destination)
return f"\u2705 Saved to presets/{filename}"
except Exception as e:
return f"\u274C Failed to restore: {e}"
restore_button.click(
fn=restore_config_file,
inputs=[restore_file],
outputs=[restore_status]
)
gr.Markdown(
"You can backup your current settings and restore them later. "
"This is useful for saving configurations or sharing with others."
)
others_tab.select(
fn=update_file_list,
inputs=[delete_folder_dropdown],
outputs=[file_list_dropdown],
queue=False,
show_progress=False,
)