separate file, and more function
This commit is contained in:
parent
cdf57c251d
commit
1cde3d325d
|
|
@ -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
195
webui.py
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
Loading…
Reference in New Issue