2.1.808
* Aspect ratios now show aspect ratios. * Added style search. * Added style sorting/ordering/favorites.
This commit is contained in:
parent
375b30f375
commit
cec0c2a8df
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@ __pycache__
|
|||||||
*.patch
|
*.patch
|
||||||
*.backup
|
*.backup
|
||||||
*.corrupted
|
*.corrupted
|
||||||
|
sorted_styles.json
|
||||||
/language/default.json
|
/language/default.json
|
||||||
lena.png
|
lena.png
|
||||||
lena_result.png
|
lena_result.png
|
||||||
|
@ -73,6 +73,10 @@ function processNode(node) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refresh_style_localization() {
|
||||||
|
processNode(document.querySelector('.style_selections'));
|
||||||
|
}
|
||||||
|
|
||||||
function localizeWholePage() {
|
function localizeWholePage() {
|
||||||
processNode(gradioApp());
|
processNode(gradioApp());
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ function refresh_grid() {
|
|||||||
if (gridContainer) if (final_gallery) {
|
if (gridContainer) if (final_gallery) {
|
||||||
let rect = final_gallery.getBoundingClientRect();
|
let rect = final_gallery.getBoundingClientRect();
|
||||||
let cols = Math.ceil((rect.width - 16.0) / rect.height);
|
let cols = Math.ceil((rect.width - 16.0) / rect.height);
|
||||||
if(cols < 2) cols = 2;
|
if (cols < 2) cols = 2;
|
||||||
gridContainer.style.setProperty('--grid-cols', cols);
|
gridContainer.style.setProperty('--grid-cols', cols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,3 +56,27 @@ window.addEventListener('resize', (e) => {
|
|||||||
onUiLoaded(async () => {
|
onUiLoaded(async () => {
|
||||||
resized();
|
resized();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function on_style_selection_blur() {
|
||||||
|
let target = document.querySelector("#gradio_receiver_style_selections textarea");
|
||||||
|
target.value = "on_style_selection_blur " + Math.random();
|
||||||
|
let e = new Event("input", {bubbles: true})
|
||||||
|
Object.defineProperty(e, "target", {value: target})
|
||||||
|
target.dispatchEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
onUiLoaded(async () => {
|
||||||
|
let spans = document.querySelectorAll('.aspect_ratios span');
|
||||||
|
|
||||||
|
spans.forEach(function (span) {
|
||||||
|
span.innerHTML = span.innerHTML.replace(/</g, '<').replace(/>/g, '>');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector('.style_selections').addEventListener('focusout', function (event) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this.contains(document.activeElement)) {
|
||||||
|
on_style_selection_blur();
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -209,7 +209,7 @@ def worker():
|
|||||||
tiled = False
|
tiled = False
|
||||||
inpaint_worker.current_task = None
|
inpaint_worker.current_task = None
|
||||||
|
|
||||||
width, height = aspect_ratios_selection.split('×')
|
width, height = aspect_ratios_selection.replace('×', ' ').split(' ')[:2]
|
||||||
width, height = int(width), int(height)
|
width, height = int(width), int(height)
|
||||||
|
|
||||||
skip_prompt_processing = False
|
skip_prompt_processing = False
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import math
|
||||||
import args_manager
|
import args_manager
|
||||||
import modules.flags
|
import modules.flags
|
||||||
import modules.sdxl_styles
|
import modules.sdxl_styles
|
||||||
@ -247,6 +248,17 @@ default_aspect_ratio = get_config_item_or_set_default(
|
|||||||
validator=lambda x: x in available_aspect_ratios
|
validator=lambda x: x in available_aspect_ratios
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def add_ratio(x):
|
||||||
|
a, b = x.replace('*', ' ').split(' ')[:2]
|
||||||
|
a, b = int(a), int(b)
|
||||||
|
g = math.gcd(a, b)
|
||||||
|
return f'{a}×{b} <span style="color: grey;"> \U00002223 {a // g}:{b // g}</span>'
|
||||||
|
|
||||||
|
|
||||||
|
default_aspect_ratio = add_ratio(default_aspect_ratio)
|
||||||
|
available_aspect_ratios = [add_ratio(x) for x in available_aspect_ratios]
|
||||||
|
|
||||||
with open(config_path, "w", encoding="utf-8") as json_file:
|
with open(config_path, "w", encoding="utf-8") as json_file:
|
||||||
json.dump({k: config_dict[k] for k in always_save_keys}, json_file, indent=4)
|
json.dump({k: config_dict[k] for k in always_save_keys}, json_file, indent=4)
|
||||||
|
|
||||||
@ -264,9 +276,6 @@ os.makedirs(path_outputs, exist_ok=True)
|
|||||||
model_filenames = []
|
model_filenames = []
|
||||||
lora_filenames = []
|
lora_filenames = []
|
||||||
|
|
||||||
available_aspect_ratios = [x.replace('*', '×') for x in available_aspect_ratios]
|
|
||||||
default_aspect_ratio = default_aspect_ratio.replace('*', '×')
|
|
||||||
|
|
||||||
|
|
||||||
def get_model_filenames(folder_path, name_filter=None):
|
def get_model_filenames(folder_path, name_filter=None):
|
||||||
return get_files_from_folder(folder_path, ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch'], name_filter)
|
return get_files_from_folder(folder_path, ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch'], name_filter)
|
||||||
|
@ -100,6 +100,18 @@ progress::after {
|
|||||||
overflow: auto !important;
|
overflow: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aspect_ratios label {
|
||||||
|
width: 140px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aspect_ratios label span {
|
||||||
|
white-space: nowrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aspect_ratios label input {
|
||||||
|
margin-left: -5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
'''
|
'''
|
||||||
progress_html = '''
|
progress_html = '''
|
||||||
<div class="loader-container">
|
<div class="loader-container">
|
||||||
|
@ -2,29 +2,30 @@ import json
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
current_translation = {}
|
||||||
localization_root = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'language')
|
localization_root = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'language')
|
||||||
|
|
||||||
|
|
||||||
def localization_js(filename):
|
def localization_js(filename):
|
||||||
data = {}
|
global current_translation
|
||||||
|
|
||||||
if isinstance(filename, str):
|
if isinstance(filename, str):
|
||||||
full_name = os.path.abspath(os.path.join(localization_root, filename + '.json'))
|
full_name = os.path.abspath(os.path.join(localization_root, filename + '.json'))
|
||||||
if os.path.exists(full_name):
|
if os.path.exists(full_name):
|
||||||
try:
|
try:
|
||||||
with open(full_name, encoding='utf-8') as f:
|
with open(full_name, encoding='utf-8') as f:
|
||||||
data = json.load(f)
|
current_translation = json.load(f)
|
||||||
assert isinstance(data, dict)
|
assert isinstance(current_translation, dict)
|
||||||
for k, v in data.items():
|
for k, v in current_translation.items():
|
||||||
assert isinstance(k, str)
|
assert isinstance(k, str)
|
||||||
assert isinstance(v, str)
|
assert isinstance(v, str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(str(e))
|
print(str(e))
|
||||||
print(f'Failed to load localization file {full_name}')
|
print(f'Failed to load localization file {full_name}')
|
||||||
|
|
||||||
# data = {k: 'XXX' for k in data.keys()} # use this to see if all texts are covered
|
# current_translation = {k: 'XXX' for k in current_translation.keys()} # use this to see if all texts are covered
|
||||||
|
|
||||||
return f"window.localization = {json.dumps(data)}"
|
return f"window.localization = {json.dumps(current_translation)}"
|
||||||
|
|
||||||
|
|
||||||
def dump_english_config(components):
|
def dump_english_config(components):
|
||||||
|
54
modules/style_sorter.py
Normal file
54
modules/style_sorter.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import os
|
||||||
|
import gradio as gr
|
||||||
|
import modules.localization as localization
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
all_styles = []
|
||||||
|
|
||||||
|
|
||||||
|
def try_load_sorted_styles(style_names, default_selected):
|
||||||
|
global all_styles
|
||||||
|
|
||||||
|
all_styles = style_names
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.path.exists('sorted_styles.json'):
|
||||||
|
with open('sorted_styles.json', 'rt', encoding='utf-8') as fp:
|
||||||
|
sorted_styles = json.load(fp)
|
||||||
|
if len(sorted_styles) == len(all_styles):
|
||||||
|
if all(x in all_styles for x in sorted_styles):
|
||||||
|
if all(x in sorted_styles for x in all_styles):
|
||||||
|
all_styles = sorted_styles
|
||||||
|
except Exception as e:
|
||||||
|
print('Load style sorting failed.')
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
unselected = [y for y in all_styles if y not in default_selected]
|
||||||
|
all_styles = default_selected + unselected
|
||||||
|
|
||||||
|
return all_styles
|
||||||
|
|
||||||
|
|
||||||
|
def sort_styles(selected):
|
||||||
|
unselected = [y for y in all_styles if y not in selected]
|
||||||
|
sorted_styles = selected + unselected
|
||||||
|
try:
|
||||||
|
with open('sorted_styles.json', 'wt', encoding='utf-8') as fp:
|
||||||
|
json.dump(sorted_styles, fp, indent=4)
|
||||||
|
except Exception as e:
|
||||||
|
print('Write style sorting failed.')
|
||||||
|
print(e)
|
||||||
|
return gr.CheckboxGroup.update(choices=sorted_styles)
|
||||||
|
|
||||||
|
|
||||||
|
def localization_key(x):
|
||||||
|
return x + localization.current_translation.get(x, '')
|
||||||
|
|
||||||
|
|
||||||
|
def search_styles(selected, query):
|
||||||
|
unselected = [y for y in all_styles if y not in selected]
|
||||||
|
matched = [y for y in unselected if query.lower() in localization_key(y).lower()] if len(query) > 0 else []
|
||||||
|
unmatched = [y for y in unselected if y not in matched]
|
||||||
|
sorted_styles = matched + selected + unmatched
|
||||||
|
return gr.CheckboxGroup.update(choices=sorted_styles)
|
35
webui.py
35
webui.py
@ -11,7 +11,9 @@ import modules.constants as constants
|
|||||||
import modules.flags as flags
|
import modules.flags as flags
|
||||||
import modules.gradio_hijack as grh
|
import modules.gradio_hijack as grh
|
||||||
import modules.advanced_parameters as advanced_parameters
|
import modules.advanced_parameters as advanced_parameters
|
||||||
|
import modules.style_sorter as style_sorter
|
||||||
import args_manager
|
import args_manager
|
||||||
|
import copy
|
||||||
|
|
||||||
from modules.sdxl_styles import legal_style_names
|
from modules.sdxl_styles import legal_style_names
|
||||||
from modules.private_logger import get_current_html_path
|
from modules.private_logger import get_current_html_path
|
||||||
@ -193,7 +195,8 @@ with shared.gradio_root:
|
|||||||
choices=['Speed', 'Quality', 'Extreme Speed'],
|
choices=['Speed', 'Quality', 'Extreme Speed'],
|
||||||
value='Speed')
|
value='Speed')
|
||||||
aspect_ratios_selection = gr.Radio(label='Aspect Ratios', choices=modules.config.available_aspect_ratios,
|
aspect_ratios_selection = gr.Radio(label='Aspect Ratios', choices=modules.config.available_aspect_ratios,
|
||||||
value=modules.config.default_aspect_ratio, info='width × height')
|
value=modules.config.default_aspect_ratio, info='width × height',
|
||||||
|
elem_classes='aspect_ratios')
|
||||||
image_number = gr.Slider(label='Image Number', minimum=1, maximum=32, step=1, value=modules.config.default_image_number)
|
image_number = gr.Slider(label='Image Number', minimum=1, maximum=32, step=1, value=modules.config.default_image_number)
|
||||||
negative_prompt = gr.Textbox(label='Negative Prompt', show_label=True, placeholder="Type prompt here.",
|
negative_prompt = gr.Textbox(label='Negative Prompt', show_label=True, placeholder="Type prompt here.",
|
||||||
info='Describing what you do not want to see.', lines=2,
|
info='Describing what you do not want to see.', lines=2,
|
||||||
@ -222,10 +225,34 @@ with shared.gradio_root:
|
|||||||
gr.HTML(f'<a href="/file={get_current_html_path()}" target="_blank">\U0001F4DA History Log</a>')
|
gr.HTML(f'<a href="/file={get_current_html_path()}" target="_blank">\U0001F4DA History Log</a>')
|
||||||
|
|
||||||
with gr.Tab(label='Style'):
|
with gr.Tab(label='Style'):
|
||||||
|
initial_style_sorting = style_sorter.try_load_sorted_styles(
|
||||||
|
style_names=legal_style_names, default_selected=modules.config.default_styles)
|
||||||
|
|
||||||
|
style_search_bar = gr.Textbox(show_label=False, container=False,
|
||||||
|
placeholder="\U0001F50E Type here to search styles ...",
|
||||||
|
value="",
|
||||||
|
label='Search Styles')
|
||||||
style_selections = gr.CheckboxGroup(show_label=False, container=False,
|
style_selections = gr.CheckboxGroup(show_label=False, container=False,
|
||||||
choices=legal_style_names,
|
choices=initial_style_sorting,
|
||||||
value=modules.config.default_styles,
|
value=copy.deepcopy(modules.config.default_styles),
|
||||||
label='Image Style')
|
label='Selected Styles',
|
||||||
|
elem_classes=['style_selections'])
|
||||||
|
gradio_receiver_style_selections = gr.Textbox(elem_id='gradio_receiver_style_selections', visible=False)
|
||||||
|
|
||||||
|
style_search_bar.change(style_sorter.search_styles,
|
||||||
|
inputs=[style_selections, style_search_bar],
|
||||||
|
outputs=style_selections,
|
||||||
|
queue=False,
|
||||||
|
show_progress=False).then(
|
||||||
|
lambda: None, _js='()=>{refresh_style_localization();}')
|
||||||
|
|
||||||
|
gradio_receiver_style_selections.input(style_sorter.sort_styles,
|
||||||
|
inputs=style_selections,
|
||||||
|
outputs=style_selections,
|
||||||
|
queue=False,
|
||||||
|
show_progress=False).then(
|
||||||
|
lambda: None, _js='()=>{refresh_style_localization();}')
|
||||||
|
|
||||||
with gr.Tab(label='Model'):
|
with gr.Tab(label='Model'):
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=modules.config.model_filenames, value=modules.config.default_base_model_name, show_label=True)
|
base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=modules.config.model_filenames, value=modules.config.default_base_model_name, show_label=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user