smaller buttons, added refresh button, updated presets

-made the buttons smaller, fixes alignment issue
-added a refresh button
-updated default config presets
This commit is contained in:
Zyin055
2024-03-28 16:17:36 -05:00
parent d6b54327db
commit 6675175d4e
2 changed files with 210 additions and 225 deletions

View File

@@ -1,3 +1,4 @@
//A1111 1.6.0's Gradio added built in tooltip fields, but we use this method for backwards compatibility.
//add tooltip by piggybacking off of javascript/hints.js ...
//titles["Add/Remove..."] = "[Config Presets] Add or remove a preset"
//...or do it our more precise way:
@@ -6,12 +7,13 @@ onUiUpdate(function() {
gradioApp().querySelectorAll("#script_config_preset_open_config_file_button").forEach(el => el.setAttribute("title", "Open the config .json file for manual editing if you want to make changes that way, requires Gradio restart after editing. The txt2img and img2img tabs have separate config files."))
gradioApp().querySelectorAll("#script_config_preset_save_textbox").forEach(el => el.setAttribute("title", "The name of a new Config Preset that will be added to the dropdown above"))
gradioApp().querySelectorAll("#script_config_preset_save_button").forEach(el => el.setAttribute("title", "Save selected fields with the new preset name. It will overwrite an existing preset with the same name."))
gradioApp().querySelectorAll("#script_config_preset_add_button").forEach(el => el.setAttribute("title", "[Config Presets] Create or delete a preset"))
gradioApp().querySelectorAll("#script_config_preset_add_button").forEach(el => el.setAttribute("title", "Create or delete a config preset"))
gradioApp().querySelectorAll("#script_config_preset_cancel_save_button").forEach(el => el.setAttribute("title", "Go back"))
gradioApp().querySelectorAll("#script_config_preset_trash_button").forEach(el => el.setAttribute("title", "Permanently delete selected preset"))
gradioApp().querySelectorAll("#script_config_preset_fields_to_save > span").forEach(el => el.setAttribute("title", "Only selected field values will be saved with the preset. Unselected fields will be ignored."))
gradioApp().querySelectorAll("#script_config_preset_open_custom_tracked_components_config").forEach(el => el.setAttribute("title", "Open the config file to add new fields to the above list."))
gradioApp().querySelectorAll("#script_config_preset_reapply_button").forEach(el => el.setAttribute("title", "Reapply the selected preset"))
gradioApp().querySelectorAll("#script_config_preset_refresh_dropdown_button").forEach(el => el.setAttribute("title", "Reload the config text file from disk, useful when making external changes with a text editor."))
})
/* No longer needed after the bump to Gradio 3.23
//this function called by config_preset_dropdown in config_presets.py
@@ -31,10 +33,11 @@ function config_preset_dropdown_change() {
}, 200) //50ms is too fast
}
*/
/*
function config_preset_settings_restart_gradio() {
console.log('[Config-Presets] Restarting to apply new config preset...')
setTimeout(function() {
gradioApp().getElementById("settings_restart_gradio").click()
}, 1000)
}
}
*/

View File

@@ -7,6 +7,7 @@ import os
import platform
import subprocess as sp
from json import JSONDecodeError
from modules.ui_components import ToolButton
BASEDIR = scripts.basedir() #C:\path\to\Stable Diffusion\extensions\Config-Presets needs to be set in global space to get the extra 'extensions\Config-Presets' path
@@ -547,87 +548,64 @@ def load_txt2img_config_file():
"Low quality ------ steps: 10, batch size: 8, DPM++ 2M Karras": {
"txt2img_sampling": "DPM++ 2M Karras",
"txt2img_steps": 10,
#"txt2img_width": 512,
#"txt2img_height": 512,
"txt2img_enable_hr": False,
"txt2img_batch_count": 1,
"txt2img_batch_size": 8,
#"txt2img_cfg_scale": 7,
},
"Medium quality - steps: 15, batch size: 4, DPM++ 2M Karras": {
"txt2img_sampling": "DPM++ 2M Karras",
"txt2img_steps": 15,
#"txt2img_width": 512,
#"txt2img_height": 512,
"txt2img_enable_hr": False,
"txt2img_batch_count": 1,
"txt2img_batch_size": 4,
#"txt2img_cfg_scale": 7,
},
"High quality ------ steps: 20, batch size: 4, DPM++ 2S a Karras": {
"High quality ------ steps: 30, batch size: 4, DPM++ 2S a Karras": {
"txt2img_sampling": "DPM++ 2S a Karras",
"txt2img_steps": 20,
#"txt2img_width": 512,
#"txt2img_height": 512,
"txt2img_steps": 30,
"txt2img_enable_hr": False,
"txt2img_batch_count": 1,
"txt2img_batch_size": 4,
#"txt2img_cfg_scale": 7,
},
"High res -------- steps: 30, DPM++ 2M Karras, [Hires fix - Upscale by: 2, Denoising: 0.4, Hires steps: 10]": {
"txt2img_steps": 30,
"txt2img_sampling": "DPM++ 2M Karras",
#"txt2img_width": 512,
#"txt2img_height": 512,
"High res ----------- [Hires fix - Upscale by: 2, Denoising: 0.4, Hires steps: 10]": {
"txt2img_enable_hr": True,
"txt2img_hr_scale": 2,
"txt2img_hires_steps": 10,
"txt2img_denoising_strength": 0.4,
#"txt2img_batch_count": 1,
#"txt2img_batch_size": 1,
#"txt2img_cfg_scale": 7,
"txt2img_batch_count": 1,
"txt2img_batch_size": 1,
},
"1080p ----------- 432x768 -> 1920x1080, steps: 20, DPM++ 2M Karras, [Hires fix - Upscale by: 2.5, Denoising: 0.4, Hires steps: 10]": {
"SD 1.5 - 1080p --- 432x768 -> 1920x1080, [Hires fix - Upscale by: 2.5, Denoising: 0.4, Hires steps: 10]": {
# 2x 960x536, 2.5x 768x432, 3x 640x360
"txt2img_steps": 20,
"txt2img_sampling": "DPM++ 2M Karras",
"txt2img_width": 768,
"txt2img_height": 432,
"txt2img_enable_hr": True,
"txt2img_hr_scale": 2.5,
"txt2img_hires_steps": 10,
"txt2img_denoising_strength": 0.4,
#"txt2img_batch_count": 1,
#"txt2img_batch_size": 1,
#"txt2img_cfg_scale": 7,
"txt2img_batch_count": 1,
"txt2img_batch_size": 1,
},
"1440p ----------- 432x768 -> 2560x1440, steps: 25, DPM++ 2M Karras, [Hires fix - Upscale by: 3.3334, Denoising: 0.3, Hires steps: 10]": {
"SD 1.5 - 1440p --- 432x768 -> 2560x1440, [Hires fix - Upscale by: 3.3334, Denoising: 0.35, Hires steps: 10]": {
# 2x 1024x720, 2.5x 1024x576, 3.3334x 768x432, 4x 640x360
"txt2img_steps": 25,
"txt2img_sampling": "DPM++ 2M Karras",
"txt2img_width": 768,
"txt2img_height": 432,
"txt2img_enable_hr": True,
"txt2img_hr_scale": 3.3334,
"txt2img_hires_steps": 10,
"txt2img_denoising_strength": 0.4,
#"txt2img_batch_count": 1,
#"txt2img_batch_size": 1,
#"txt2img_cfg_scale": 7,
"txt2img_denoising_strength": 0.35,
"txt2img_batch_count": 1,
"txt2img_batch_size": 1,
},
"4k ---------------- 432x768 -> 3840x2160, steps: 30, DPM++ 2M Karras, [Upscale by: 5, Denoising: 0.3, Hires steps: 15]": {
"SD 1.5 - 4k -------- 432x768 -> 3840x2160, [Upscale by: 5, Denoising: 0.3, Hires steps: 15]": {
# 2x 1420x1080, 2.5x 1536x864, 3x 1280x720, 5x 768x432, 6x 640x360
"txt2img_steps": 30,
"txt2img_sampling": "DPM++ 2M Karras",
"txt2img_width": 768,
"txt2img_height": 432,
"txt2img_enable_hr": True,
"txt2img_hr_scale": 5,
"txt2img_hires_steps": 15,
"txt2img_denoising_strength": 0.4,
#"txt2img_batch_count": 1,
#"txt2img_batch_size": 1,
#"txt2img_cfg_scale": 7,
"txt2img_denoising_strength": 0.3,
"txt2img_batch_count": 1,
"txt2img_batch_size": 1,
},
}
@@ -953,208 +931,212 @@ class Script(scripts.Script):
elem_id="script_config_preset_fields_to_save",
).unrender() #we need to define this early on so that it can be used as an input for another function
with gr.Column(min_width=600, elem_id="config_preset_wrapper_txt2img" if self.is_txt2img else "config_preset_wrapper_img2img"): # pushes our stuff onto a new row at 1080p screen resolution
with gr.Row():
with gr.Column(scale=8, min_width=100) as dropdown_column:
with gr.Box(elem_id="config_preset_wrapper_txt2img" if self.is_txt2img else "config_preset_wrapper_img2img"):
with gr.Row(elem_id="config_preset_dropdown_row") as dropdown_row:
def config_preset_dropdown_change(dropdown_value, *components_value):
config_preset = config_presets[dropdown_value]
config_preset = dict_synonyms(config_preset, synonym_ids) # Add synonyms
print(f"[Config-Presets] Changed to: {dropdown_value}")
# update component values with user preset
current_components = dict(zip(component_map.keys(), components_value))
#print("Components before:", current_components)
current_components.update(config_preset)
def config_preset_dropdown_change(dropdown_value, *components_value):
config_preset = config_presets[dropdown_value]
config_preset = dict_synonyms(config_preset, synonym_ids) # Add synonyms
print(f"[Config-Presets] Changed to: {dropdown_value}")
# transform necessary components from index to value
for component_name, component_value in current_components.items():
#print(component_name, component_value)
if component_name in index_type_components and type(component_value) == int:
current_components[component_name] = component_map[component_name].choices[component_value]
# update component values with user preset
current_components = dict(zip(component_map.keys(), components_value))
#print("Components before:", current_components)
current_components.update(config_preset)
# A1111 1.6.0 changed radio buttons values into tuples.
# For example, for the "img2img_mask_mode" component it changed from:
# ['Inpaint masked', 'Inpaint not masked']
# to
# [('Inpaint masked', 'Inpaint masked'), ('Inpaint not masked', 'Inpaint not masked')]
# Using a type == tuple check here will ensure compatibility with the older versions.
if type(current_components[component_name]) == tuple:
current_components[component_name] = current_components[component_name][0]
# transform necessary components from index to value
for component_name, component_value in current_components.items():
#print(component_name, component_value)
if component_name in index_type_components and type(component_value) == int:
current_components[component_name] = component_map[component_name].choices[component_value]
#print("Components after :", current_components)
return list(current_components.values())
# A1111 1.6.0 changed radio buttons values into tuples.
# For example, for the "img2img_mask_mode" component it changed from:
# ['Inpaint masked', 'Inpaint not masked']
# to
# [('Inpaint masked', 'Inpaint masked'), ('Inpaint not masked', 'Inpaint not masked')]
# Using a type == tuple check here will ensure compatibility with the older versions.
if type(current_components[component_name]) == tuple:
current_components[component_name] = current_components[component_name][0]
config_preset_dropdown = gr.Dropdown(
label="Config Presets",
choices=get_config_preset_dropdown_choices(preset_values),
elem_id="config_preset_txt2img_dropdown" if self.is_txt2img else "config_preset_img2img_dropdown",
)
#print("Components after :", current_components)
return list(current_components.values())
config_preset_dropdown = gr.Dropdown(
label="Config Presets",
#choices=preset_values,
choices=get_config_preset_dropdown_choices(preset_values),
elem_id="config_preset_txt2img_dropdown" if self.is_txt2img else "config_preset_img2img_dropdown",
)
#self.txt2img_config_preset_dropdown = config_preset_dropdown
try:
components = list(component_map.values())
config_preset_dropdown.change(
fn=config_preset_dropdown_change,
show_progress=False,
inputs=[config_preset_dropdown, *components],
outputs=components
)
except AttributeError:
print(traceback.format_exc()) # prints the exception stacktrace
log_critical_error("The Config-Presets extension encountered a fatal error. A component required by this extension no longer exists in the Web UI. This is most likely due to the A1111 Web UI being updated. Try updating the Config-Presets extension. If that doesn't work, please post a bug report at https://github.com/Zyin055/Config-Presets/issues and delete your extensions/Config-Presets folder until an update is published.")
# No longer needed after the bump to Gradio 3.23
# config_preset_dropdown.change(
# fn=None,
# inputs=[],
# outputs=[],
# _js="function() { config_preset_dropdown_change() }", # JS is used to update the Hires fix row to show/hide it
# )
with gr.Column(scale=8, min_width=100, visible=False) as collapsable_column:
with gr.Row():
with gr.Column(scale=1, min_width=10):
def delete_selected_preset(config_preset_name):
if config_preset_name in config_presets.keys():
del config_presets[config_preset_name]
print(f'[Config-Presets] deleted: "{config_preset_name}"')
write_json_to_file(config_presets, config_file_name)
preset_keys = list(config_presets.keys())
return gr.Dropdown.update(value=preset_keys[len(preset_keys)-1],
#choices=preset_values,
choices=get_config_preset_dropdown_choices(preset_keys),
)
return gr.Dropdown.update() # do nothing if no value is selected
trash_button = gr.Button(
value="\U0001f5d1\ufe0f", #🗑
elem_id="script_config_preset_trash_button",
)
trash_button.click(
fn=delete_selected_preset,
inputs=[config_preset_dropdown],
outputs=[config_preset_dropdown],
)
with gr.Column(scale=2, min_width=190):
def open_file(f):
path = os.path.normpath(f)
if not os.path.exists(path):
print(f'Config Presets: The file at "{path}" does not exist.')
return
# copied from ui.py:538
if platform.system() == "Windows":
os.startfile(path)
elif platform.system() == "Darwin":
sp.Popen(["open", path])
else:
sp.Popen(["xdg-open", path])
open_config_file_button = gr.Button(
value="📂 Open config file...",
elem_id="script_config_preset_open_config_file_button",
)
open_config_file_button.click(
fn=lambda: open_file(f"{BASEDIR}/{config_file_name}"),
inputs=[],
outputs=[],
)
with gr.Column(scale=2, min_width=50):
cancel_button = gr.Button(
value="Cancel",
elem_id="script_config_preset_cancel_save_button",
)
with gr.Column(scale=4, min_width=160, visible=True) as add_remove_button_column:
with gr.Row():
reapply_button = gr.Button(
value="\U000021A9", # ↩
elem_id="script_config_preset_reapply_button",
min_width=40,
)
components = list(component_map.values())
reapply_button.click(
fn=config_preset_dropdown_change,
inputs=[config_preset_dropdown, *components],
show_progress=False,
outputs=components,
)
add_remove_button = gr.Button(
value="Add/Remove...",
elem_id="script_config_preset_add_button",
min_width=120,
try:
components = list(component_map.values())
config_preset_dropdown.change(
fn=config_preset_dropdown_change,
show_progress=False,
inputs=[config_preset_dropdown, *components],
outputs=components
)
except AttributeError:
print(traceback.format_exc()) # prints the exception stacktrace
log_critical_error("The Config-Presets extension encountered a fatal error. A component required by this extension no longer exists in the Web UI. This is most likely due to the A1111 Web UI being updated. Try updating the Config-Presets extension. If that doesn't work, please post a bug report at https://github.com/Zyin055/Config-Presets/issues and delete your extensions/Config-Presets folder until an update is published.")
def delete_selected_preset(config_preset_name):
if config_preset_name in config_presets.keys():
del config_presets[config_preset_name]
print(f'[Config-Presets] deleted: "{config_preset_name}"')
write_json_to_file(config_presets, config_file_name)
preset_keys = list(config_presets.keys())
return gr.Dropdown.update(value=preset_keys[len(preset_keys)-1],
choices=get_config_preset_dropdown_choices(preset_keys),
)
return gr.Dropdown.update() # do nothing if no value is selected
def refresh_dropdown_button_click():
if self.is_txt2img:
self.txt2img_config_presets = load_txt2img_config_file()
#new_config_presets = self.txt2img_config_presets
config_presets.update(self.txt2img_config_presets)
preset_values: list[str] = list(self.txt2img_config_presets.keys())
else:
self.img2img_config_presets = load_img2img_config_file()
#new_config_presets = self.img2img_config_presets
config_presets.update(self.img2img_config_presets)
preset_values: list[str] = list(self.img2img_config_presets.keys())
return gr.Dropdown.update(choices=get_config_preset_dropdown_choices(preset_values))
refresh_dropdown_button = ToolButton(
value="🔄",
elem_id="script_config_preset_refresh_dropdown_button",
visible=False,
)
refresh_dropdown_button.click(
fn=refresh_dropdown_button_click,
inputs=[],
outputs=[config_preset_dropdown],
)
trash_button = ToolButton(
value="🗑️",
elem_id="script_config_preset_trash_button",
visible=False,
)
trash_button.click(
fn=delete_selected_preset,
inputs=[config_preset_dropdown],
outputs=[config_preset_dropdown],
)
def open_file(f):
path = os.path.normpath(f)
if not os.path.exists(path):
print(f'Config Presets: The file at "{path}" does not exist.')
return
# copied from ui.py:538
if platform.system() == "Windows":
os.startfile(path)
elif platform.system() == "Darwin":
sp.Popen(["open", path])
else:
sp.Popen(["xdg-open", path])
open_config_file_button = ToolButton(
value="📂",
elem_id="script_config_preset_open_config_file_button",
visible=False,
)
open_config_file_button.click(
fn=lambda: open_file(f"{BASEDIR}/{config_file_name}"),
inputs=[],
outputs=[],
)
cancel_button = ToolButton(
value="\U000021A9",
elem_id="script_config_preset_cancel_save_button",
visible=False,
)
reapply_button = ToolButton(
value="📋",
elem_id="script_config_preset_reapply_button"
)
components = list(component_map.values())
reapply_button.click(
fn=config_preset_dropdown_change,
inputs=[config_preset_dropdown, *components],
show_progress=False,
outputs=components,
)
add_remove_button = ToolButton(
value="🖌️",
elem_id="script_config_preset_add_button"
)
with gr.Row() as collapsable_row:
collapsable_row.visible = False
with gr.Column():
with gr.Row():
with gr.Column(scale=10, min_width=100):
save_textbox = gr.Textbox(
label="New preset name",
placeholder="Ex: Low quality",
# value="My Preset",
max_lines=1,
elem_id="script_config_preset_save_textbox",
)
with gr.Column(scale=2, min_width=200):
save_button = gr.Button(
# value="Create",
value="💾 Save",
variant="primary",
elem_id="script_config_preset_save_button",
)
save_textbox = gr.Textbox(
label="New preset name",
placeholder="Ex: Low quality",
max_lines=1,
elem_id="script_config_preset_save_textbox",
)
save_button = ToolButton(
value="💾",
variant="primary",
elem_id="script_config_preset_save_button",
)
save_button.click(
fn=save_config(config_presets, component_map, config_file_name),
inputs=list(
[save_textbox] + [fields_checkboxgroup] + [component_map[comp_name] for comp_name in
component_ids if
component_map[comp_name] is not None]),
outputs=[config_preset_dropdown, save_textbox],
)
save_button.click(
fn=save_config(config_presets, component_map, config_file_name),
inputs=list(
[save_textbox] + [fields_checkboxgroup] + [component_map[comp_name] for comp_name in
component_ids if
component_map[comp_name] is not None]),
outputs=[config_preset_dropdown, save_textbox],
)
def add_remove_button_click(save_textbox_text: str, config_preset_dropdown_value: str):
if save_textbox_text == "" or save_textbox_text is None:
if config_preset_dropdown_value != "" and config_preset_dropdown_value is not None:
# save textbox is empty, and we have a dropdown value selected
# auto-populate the save textbox so it's easier to overwrite existing config preset
return gr.Textbox.update(value=config_preset_dropdown_value)
return gr.Textbox.update()
def add_remove_button_click(save_textbox_text: str, config_preset_dropdown_value: str):
if save_textbox_text == "" or save_textbox_text is None:
if config_preset_dropdown_value != "" and config_preset_dropdown_value is not None:
# save textbox is empty, and we have a dropdown value selected
# auto-populate the save textbox so it's easier to overwrite existing config preset
return gr.Textbox.update(value=config_preset_dropdown_value)
return gr.Textbox.update()
def expand_edit_ui():
return gr.update(visible=True), gr.update(visible=True), gr.update(visible=False)
def expand_edit_ui():
return gr.Row.update(visible=True), gr.Button.update(visible=True), gr.Button.update(visible=False), gr.Button.update(visible=False), gr.Button.update(visible=True), gr.Button.update(visible=True), gr.Button.update(visible=True)
def collapse_edit_ui():
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=True)
def collapse_edit_ui():
return gr.Row.update(visible=False), gr.Button.update(visible=False), gr.Button.update(visible=True), gr.Button.update(visible=True), gr.Button.update(visible=False), gr.Button.update(visible=False), gr.Button.update(visible=False)
add_remove_button.click(
fn=add_remove_button_click,
inputs=[save_textbox, config_preset_dropdown],
outputs=[save_textbox],
)
add_remove_button.click(
fn=expand_edit_ui,
inputs=[],
outputs=[collapsable_column, collapsable_row, add_remove_button_column],
)
add_remove_button.click(
fn=add_remove_button_click,
inputs=[save_textbox, config_preset_dropdown],
outputs=[save_textbox],
)
add_remove_button.click(
fn=expand_edit_ui,
inputs=[],
outputs=[collapsable_row, refresh_dropdown_button, reapply_button, add_remove_button, trash_button, open_config_file_button, cancel_button],
)
cancel_button.click(
fn=collapse_edit_ui,
inputs=[],
outputs=[collapsable_column, collapsable_row, add_remove_button_column],
)
cancel_button.click(
fn=collapse_edit_ui,
inputs=[],
outputs=[collapsable_row, refresh_dropdown_button, reapply_button, add_remove_button, trash_button, open_config_file_button, cancel_button],
)
with gr.Row():
fields_checkboxgroup.render()