ability to disable parts of the app

Signed-off-by: Vladimir Mandic <mandic00@live.com>
pull/4356/head
Vladimir Mandic 2025-11-03 19:36:55 -05:00
parent aa42dd9cca
commit 05261e708a
16 changed files with 191 additions and 127 deletions

View File

@ -2,6 +2,15 @@
## Update for 2025-11-03
- **Features**
- ability to disable parts of the app
useful for custom deployments where some features are not desired
*note*: this doesn't just hide it from user, it completely disables the code paths
use `--disable x,y,z`
possible values:
- main tabs: *control,txt2img,img2img,video,extras,caption,gallery*
- aside tabs: *extensions,models,info,update,history,monitor,onnx,system,networks,logs*
- special: *settings,config*
- **Fixes**
- video save to subfolder
- `taesd` warn on long decode times

@ -1 +1 @@
Subproject commit 5d9a6bb44e34bf48eb34582bd70e0eef06b2b451
Subproject commit 9f0e3f3360f5927d05ca8a2e728c80fbbda4c941

View File

@ -120,6 +120,9 @@
{"id":"","label":"Save","localized":"","reload":"","hint":"Save image"},
{"id":"","label":"Delete","localized":"","reload":"","hint":"Delete image"},
{"id":"","label":"Replace","localized":"","reload":"","hint":"Replace image"},
{"id":"","label":"List","localized":"","reload":"","hint":"List all available models"},
{"id":"","label":"Metadata","localized":"","reload":"","hint":"Update metadata for all available models"},
{"id":"","label":"Loader","localized":"","reload":"","hint":"Allows to manually assemble a diffusion model from individual modules"},
{"id":"","label":"➠ Text","localized":"","reload":"","hint":"Transfer image to text interface"},
{"id":"","label":"➠ Image","localized":"","reload":"","hint":"Transfer image to image interface"},
{"id":"","label":"➠ Inpaint","localized":"","reload":"","hint":"Transfer image to inpaint interface"},
@ -139,6 +142,8 @@
{"id":"","label":"HDR Maximize","localized":"","reload":"","hint":"Calculates a 'normalization factor' by dividing the maximum tensor value by the specified range multiplied by 4. This factor is then used to shift the channels within the given boundary, ensuring maximum dynamic range for subsequent processing. The objective is to optimize dynamic range for external applications like Photoshop, particularly for adjusting levels, contrast, and brightness"},
{"id":"","label":"Enable refine pass","localized":"","reload":"","hint":"Use a similar process as image to image to upscale and/or add detail to the final image. Optionally uses refiner model to enhance image details."},
{"id":"","label":"Enable detailer pass","localized":"","reload":"","hint":"Detect target objects such as face and reprocess it at higher resolution"},
{"id":"","label":"Include detection results","localized":"","reload":"","hint":"Include original image with detected areas marked"},
{"id":"","label":"Sort detections","localized":"","reload":"","hint":"Sort detected areas by from left to right instead of detection score"},
{"id":"","label":"Denoising strength","localized":"","reload":"","hint":"Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies"},
{"id":"","label":"Denoise start","localized":"","reload":"","hint":"Override denoise strength by stating how early base model should finish and when refiner should start. Only applicable to refiner usage. If set to 0 or 1, denoising strength will be used"},
{"id":"","label":"Hires steps","localized":"","reload":"","hint":"Number of sampling steps for upscaled picture. If 0, uses same as for original"},
@ -151,20 +156,27 @@
{"id":"","label":"Refiner start","localized":"","reload":"","hint":"Refiner pass will start when base model is this much complete (set to larger than 0 and smaller than 1 to run after full base model run)"},
{"id":"","label":"Refiner steps","localized":"","reload":"","hint":"Number of steps to use for refiner pass"},
{"id":"","label":"Refine guidance","localized":"","reload":"","hint":"CFG scale used for refiner pass"},
{"id":"","label":"Input media","localized":"","reload":"","hint":"Add input image to be used for image-to-image, inpaint or control processing"},
{"id":"","label":"Control media","localized":"","reload":"","hint":"Add input image as separate initialization image for control processing"},
{"id":"","label":"Processed preview","localized":"","reload":"","hint":"Display results from pre-processing of input images before actual generate"},
{"id":"","label":"Attention guidance","localized":"","reload":"","hint":"CFG scale used for with PAG: Perturbed-Attention Guidance"},
{"id":"","label":"Adaptive scaling","localized":"","reload":"","hint":"Adaptive modifier for attention guidance scale"},
{"id":"","label":"Rescale guidance","localized":"","reload":"","hint":"Rescale CFG generated noise to avoid overexposed images"},
{"id":"","label":"Refine Prompt","localized":"","reload":"","hint":"Prompt used for both second encoder in base model (if it exists) and for refiner pass (if enabled)"},
{"id":"","label":"Refine negative prompt","localized":"","reload":"","hint":"Negative prompt used for both second encoder in base model (if it exists) and for refiner pass (if enabled)"},
{"id":"","label":"Initial","localized":"","reload":"","hint":"Set image resolution before processing"},
{"id":"","label":"Post","localized":"","reload":"","hint":"Resize image after processing"},
{"id":"","label":"Width","localized":"","reload":"","hint":"Image width"},
{"id":"","label":"Height","localized":"","reload":"","hint":"Image height"},
{"id":"","label":"Batch count","localized":"","reload":"","hint":"How many batches of images to create (has no impact on generation performance or VRAM usage)"},
{"id":"","label":"Batch size","localized":"","reload":"","hint":"How many image to create in a single batch (increases generation performance at cost of higher VRAM usage)"},
{"id":"","label":"guidance scale","localized":"","reload":"","hint":"Classifier Free Guidance scale: how strongly the image should conform to prompt. Lower values produce more creative results, higher values make it follow the prompt more strictly; recommended values between 5-10"},
{"id":"","label":"Guidance scale","localized":"","reload":"","hint":"Classifier Free Guidance scale: how strongly the image should conform to prompt. Lower values produce more creative results, higher values make it follow the prompt more strictly; recommended values between 5-10"},
{"id":"","label":"Guidance rescale","localized":"","reload":"","hint":"Rescale guidance to avoid overexposed images at higher guidance values"},
{"id":"","label":"Guidance End","localized":"","reload":"","hint":"Ends the effect of CFG and PAG early: A value of 1 acts as normal, 0.5 stops guidance at 50% of steps"},
{"id":"","label":"Initial seed","localized":"","reload":"","hint":"A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result"},
{"id":"","label":"Variation","localized":"","reload":"","hint":"Second seed to be mixed with primary seed"},
{"id":"","label":"Variation strength","localized":"","reload":"","hint":"How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something)"},
{"id":"","label":"Resize method","localized":"","reload":"","hint":"Method used to resize the image: can be simple resize, upscaling model, latent resize or asymmetric decode"},
{"id":"","label":"Resize seed from width","localized":"","reload":"","hint":"Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution"},
{"id":"","label":"Resize seed from height","localized":"","reload":"","hint":"Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution"},
{"id":"","label":"Fixed","localized":"","reload":"","hint":"Resize image to target resolution. Unless height and width match, you will get incorrect aspect ratio"},
@ -184,6 +196,7 @@
{"id":"","label":"Adjust end","localized":"","reload":"","hint":"Ending step when sigma adjust occurs"},
{"id":"","label":"Options","localized":"","reload":"","hint":"Options"},
{"id":"","label":"ControlNet","localized":"","reload":"","hint":"ControlNet is an advanced guidance model"},
{"id":"","label":"Processor","localized":"","reload":"","hint":"Processor type to use to preprocess image used for ControlNet"},
{"id":"","label":"Renoise","localized":"","reload":"","hint":"Apply additional noise during detailing"},
{"id":"","label":"Renoise end","localized":"","reload":"","hint":"Final step when renoise is applied"},
{"id":"","label":"Merge detailers","localized":"","reload":"","hint":"Merge results from multiple detailers into single mask before running detailing process"},
@ -305,7 +318,6 @@
{"id":"","label":"Text encoder","localized":"","reload":"","hint":"Settings related to text encoder and prompt encoding processing during generate"},
{"id":"","label":"Compute Settings","localized":"","reload":"","hint":"Settings related to compute precision, cross attention, and optimizations for computing platforms"},
{"id":"","label":"Backend Settings","localized":"","reload":"","hint":"Settings related to compute backends: torch, onnx and olive"},
{"id":"","label":"Quantization Settings","localized":"","reload":"","hint":"Settings related to model quantization"},
{"id":"","label":"Pipeline modifiers","localized":"","reload":"","hint":"Additional functionality that can be enabled during generate"},
{"id":"","label":"Model compile","localized":"","reload":"","hint":"Settings related to different model compilation methods"},
{"id":"","label":"System Paths","localized":"","reload":"","hint":"Settings related to location of various model directories"},
@ -1007,7 +1019,6 @@
{"id":"","label":"preview end","localized":"","reload":"","hint":"preview end"},
{"id":"","label":"preview start","localized":"","reload":"","hint":"preview start"},
{"id":"","label":"primary model","localized":"","reload":"","hint":"primary model"},
{"id":"","label":"processor","localized":"","reload":"","hint":"processor"},
{"id":"","label":"processor move to cpu after use","localized":"","reload":"","hint":"processor move to cpu after use"},
{"id":"","label":"processor settings","localized":"","reload":"","hint":"processor settings"},
{"id":"","label":"processor unload after use","localized":"","reload":"","hint":"processor unload after use"},

View File

@ -61,7 +61,7 @@ async function initChangelog() {
const search = gradioApp().querySelector('#changelog_search > label> textarea');
const md = gradioApp().getElementById('changelog_markdown');
if (!search || !md) {
error('initChangelog', 'Missing search or markdown elements');
// error('initChangelog', 'Missing search or markdown elements');
return;
}
const searchChangelog = async (e) => {

View File

@ -577,7 +577,8 @@ function setupExtraNetworksForTab(tabName) {
async function showNetworks() {
for (const tabName of ['txt2img', 'img2img', 'control', 'video']) {
if (window.opts.extra_networks_show) gradioApp().getElementById(`${tabName}_extra_networks_btn`).click();
const btn = gradioApp().getElementById(`${tabName}_extra_networks_btn`);
if (window.opts.extra_networks_show && btn) btn.click();
}
log('showNetworks');
}

View File

@ -99,6 +99,7 @@ async function initLogMonitor() {
const el = document.getElementsByTagName('footer')[0];
if (!el) return;
el.classList.add('log-monitor');
if (window.opts.ui_disabled?.includes('logs')) return;
el.innerHTML = `
<table id="logMonitor" style="width: 100%;">
<thead style="display: block; text-align: left; border-bottom: solid 1px var(--button-primary-border-color)">

View File

@ -74,6 +74,8 @@ function executeCallbacks(queue, arg) {
}
}
const anyPromptExists = () => gradioApp().querySelectorAll('.main-prompts').length > 0;
function scheduleAfterUiUpdateCallbacks() {
clearTimeout(uiAfterUpdateTimeout);
uiAfterUpdateTimeout = setTimeout(() => executeCallbacks(uiAfterUpdateCallbacks, 500));
@ -96,7 +98,7 @@ async function mutationCallback(mutations) {
if (mutationTimer) clearTimeout(mutationTimer);
mutationTimer = setTimeout(async () => {
if (!executedOnLoaded && gradioApp().getElementById('txt2img_prompt')) { // execute once
if (!executedOnLoaded && anyPromptExists()) { // execute once
executedOnLoaded = true;
executeCallbacks(uiLoadedCallbacks);
}

View File

@ -168,17 +168,21 @@ async function tooltipHide(e) {
localeData.currentElement = null;
}
async function validateHints(json, elements) {
async function validateHints(json, elements, tab) {
json.missing = [];
const data = Object.values(json).flat().filter((e) => e.hint.length > 0);
for (const e of data) e.label = e.label.trim();
if (tab) {
elements = elements.filter((el) => el.closest(`#${tab}_tabitem`)); // include only elements within specified tab
elements = elements.filter((el) => !el.closest(`#${tab}_scripts_tabitem`));
}
let original = elements.map((e) => e.textContent.toLowerCase().trim()).sort(); // should be case sensitive
let duplicateUI = original.filter((e, i, a) => a.indexOf(e.toLowerCase()) !== i).sort();
original = [...new Set(original)]; // remove duplicates
duplicateUI = [...new Set(duplicateUI)]; // remove duplicates
const current = data.map((e) => e.label.toLowerCase().trim()).sort(); // should be case sensitive
log('all elements:', original);
log('all hints:', current);
// log('all elements:', original);
// log('all hints:', current);
log('hints-differences', { elements: original.length, hints: current.length });
const missingHints = original.filter((e) => !current.includes(e.toLowerCase())).sort();
const orphanedHints = current.filter((e) => !original.includes(e.toLowerCase())).sort();
@ -333,6 +337,7 @@ async function setHints(analyze = false) {
log('setHints', { type: localeData.type, locale: localeData.locale, elements: elements.length, localized, hints, data: localeData.data.length, override: overrideData.length, time: Math.round(t1 - t0) });
// sortUIElements();
if (analyze) {
log('analyzing hints', 'control_tabitem');
const [missingHints, orphanedHints] = await validateHints(json, elements);
await addMissingHints(json, missingHints);
await removeOrphanedHints(json, orphanedHints);

View File

@ -24,6 +24,7 @@ def main_args():
group_config.add_argument("--freeze", default=os.environ.get("SD_FREEZE", False), action='store_true', help="Disable editing settings")
group_config.add_argument("--medvram", default=os.environ.get("SD_MEDVRAM", False), action='store_true', help="Split model stages and keep only active part in VRAM, default: %(default)s")
group_config.add_argument("--lowvram", default=os.environ.get("SD_LOWVRAM", False), action='store_true', help="Split model components and keep only active part in VRAM, default: %(default)s")
group_config.add_argument("--disable", default=os.environ.get("SD_DISABLE", ''), help="Disable specific UI tabs: %(default)s")
def compatibility_args():

View File

@ -49,7 +49,7 @@ def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
class ScriptPostprocessingRunner:
def __init__(self):
self.scripts = None
self.scripts = []
self.ui_created = False
def initialize_scripts(self, scripts_data):

View File

@ -570,6 +570,9 @@ options_templates.update(options_section(('ui', "User Interface"), {
"subpath": OptionInfo("", "Mount URL subpath"),
"ui_request_timeout": OptionInfo(120000, "UI request timeout", gr.Slider, {"minimum": 1000, "maximum": 300000, "step": 10}),
"ui_tabs": OptionInfo("<h2>UI Tabs</h2>", "", gr.HTML),
"ui_disabled": OptionInfo("", "Disabled UI tabs", gr.Textbox, { 'visible': False }),
"cards_sep_ui": OptionInfo("<h2>Networks panel</h2>", "", gr.HTML),
"extra_networks_card_size": OptionInfo(140, "Network card size (px)", gr.Slider, {"minimum": 20, "maximum": 2000, "step": 1}),
"extra_networks_card_cover": OptionInfo("sidebar", "Network panel position", gr.Radio, {"choices": ["cover", "inline", "sidebar"]}),

View File

@ -69,86 +69,98 @@ def setup_progressbar(*args, **kwargs): # pylint: disable=unused-argument
def create_ui(startup_timer = None):
global interfaces # pylint: disable=global-statement
if startup_timer is None:
timer.startup = timer.Timer()
ui_javascript.reload_javascript()
generation_parameters_copypaste.reset()
scripts_manager.scripts_current = None
ui_disabled = [x.strip().lower() for x in shared.cmd_opts.disable.split(',') if x.strip()]
interfaces.clear()
shared.opts.ui_disabled = ui_disabled
if len(ui_disabled) > 0:
shared.log.warning(f'UI disabled: {ui_disabled}')
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
from modules import ui_txt2img
ui_txt2img.create_ui()
timer.startup.record("ui-txt2img")
if 'txt2img' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
from modules import ui_txt2img
ui_txt2img.create_ui()
timer.startup.record("ui-txt2img")
interfaces += [(txt2img_interface, "Text", "txt2img")]
with gr.Blocks(analytics_enabled=False) as img2img_interface:
from modules import ui_img2img
ui_img2img.create_ui()
timer.startup.record("ui-img2img")
if 'img2img' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as img2img_interface:
from modules import ui_img2img
ui_img2img.create_ui()
timer.startup.record("ui-img2img")
interfaces += [(img2img_interface, "Image", "img2img")]
with gr.Blocks(analytics_enabled=False) as control_interface:
from modules import ui_control
ui_control.create_ui()
timer.startup.record("ui-control")
if 'control' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as control_interface:
from modules import ui_control
ui_control.create_ui()
timer.startup.record("ui-control")
interfaces += [(control_interface, "Control", "control")]
with gr.Blocks(analytics_enabled=False) as video_interface:
from modules import ui_video
ui_video.create_ui()
timer.startup.record("ui-video")
if 'video' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as video_interface:
from modules import ui_video
ui_video.create_ui()
timer.startup.record("ui-video")
interfaces += [(video_interface, "Video", "video")]
with gr.Blocks(analytics_enabled=False) as extras_interface:
from modules import ui_postprocessing
ui_postprocessing.create_ui()
timer.startup.record("ui-extras")
if 'extras' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as extras_interface:
from modules import ui_postprocessing
ui_postprocessing.create_ui()
timer.startup.record("ui-extras")
interfaces += [(extras_interface, "Process", "process")]
with gr.Blocks(analytics_enabled=False) as caption_interface:
from modules import ui_caption
ui_caption.create_ui()
timer.startup.record("ui-caption")
if 'caption' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as caption_interface:
from modules import ui_caption
ui_caption.create_ui()
timer.startup.record("ui-caption")
interfaces += [(caption_interface, "Caption", "caption")]
with gr.Blocks(analytics_enabled=False) as models_interface:
from modules import ui_models
ui_models.create_ui()
timer.startup.record("ui-models")
if 'models' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as models_interface:
from modules import ui_models
ui_models.create_ui()
timer.startup.record("ui-models")
interfaces += [(models_interface, "Models", "models")]
with gr.Blocks(analytics_enabled=False) as gallery_interface:
from modules import ui_gallery
ui_gallery.create_ui()
timer.startup.record("ui-gallery")
if 'gallery' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as gallery_interface:
from modules import ui_gallery
ui_gallery.create_ui()
timer.startup.record("ui-gallery")
interfaces += [(gallery_interface, "Gallery", "gallery")]
interfaces += script_callbacks.ui_tabs_callback()
with gr.Blocks(analytics_enabled=False) as settings_interface:
from modules import ui_settings
ui_settings.create_ui()
ui_settings.create_ui(ui_disabled)
global ui_system_tabs # pylint: disable=global-statement
ui_system_tabs = ui_settings.ui_system_tabs
shared.opts.reorder()
timer.startup.record("ui-extensions")
interfaces += [(settings_interface, "System", "system")]
with gr.Blocks(analytics_enabled=False) as info_interface:
from modules import ui_docs
ui_docs.create_ui()
timer.startup.record("ui-info")
if 'info' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as info_interface:
from modules import ui_docs
ui_docs.create_ui()
timer.startup.record("ui-info")
interfaces += [(info_interface, "Info", "info")]
with gr.Blocks(analytics_enabled=False) as extensions_interface:
from modules import ui_extensions
ui_extensions.create_ui()
timer.startup.record("ui-extensions")
global interfaces # pylint: disable=global-statement
interfaces.clear()
interfaces += [(txt2img_interface, "Text", "txt2img")]
interfaces += [(img2img_interface, "Image", "img2img")]
if control_interface is not None:
interfaces += [(control_interface, "Control", "control")]
if video_interface is not None:
interfaces += [(video_interface, "Video", "video")]
interfaces += [(extras_interface, "Process", "process")]
interfaces += [(caption_interface, "Caption", "caption")]
interfaces += [(gallery_interface, "Gallery", "gallery")]
interfaces += [(models_interface, "Models", "models")]
interfaces += script_callbacks.ui_tabs_callback()
interfaces += [(settings_interface, "System", "system")]
interfaces += [(info_interface, "Info", "info")]
interfaces += [(extensions_interface, "Extensions", "extensions")]
if 'extensions' not in ui_disabled:
with gr.Blocks(analytics_enabled=False) as extensions_interface:
from modules import ui_extensions
ui_extensions.create_ui()
timer.startup.record("ui-extensions")
interfaces += [(extensions_interface, "Extensions", "extensions")]
ui_app = ui_settings.create_quicksettings(interfaces)

View File

@ -603,6 +603,8 @@ class ExtraNetworksUi:
def create_ui(container, button_parent, tabname, skip_indexing = False):
if 'networks' in shared.opts.ui_disabled:
return None
debug(f'EN create-ui: {tabname}')
ui = ExtraNetworksUi()
ui.tabname = tabname
@ -1054,4 +1056,6 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
def setup_ui(ui, gallery: gr.Gallery = None):
if ui is None:
return
ui.gallery = gallery

View File

@ -290,7 +290,11 @@ class UiLoadsave:
self.ui_defaults_review = gr.HTML("", elem_id="ui_defaults_review")
def setup_ui(self):
self.ui_defaults_view.click(fn=self.ui_view, inputs=list(self.component_mapping.values()), outputs=[self.ui_defaults_review])
self.ui_defaults_apply.click(fn=self.ui_apply, inputs=list(self.component_mapping.values()), outputs=[self.ui_defaults_review])
self.ui_defaults_restore.click(fn=self.ui_restore, inputs=[], outputs=[self.ui_defaults_review])
self.ui_defaults_submenu.click(fn=self.ui_submenu_apply, _js='uiOpenSubmenus', inputs=[self.ui_defaults_review], outputs=[self.ui_defaults_review])
if self.ui_defaults_view:
self.ui_defaults_view.click(fn=self.ui_view, inputs=list(self.component_mapping.values()), outputs=[self.ui_defaults_review])
if self.ui_defaults_apply:
self.ui_defaults_apply.click(fn=self.ui_apply, inputs=list(self.component_mapping.values()), outputs=[self.ui_defaults_review])
if self.ui_defaults_restore:
self.ui_defaults_restore.click(fn=self.ui_restore, inputs=[], outputs=[self.ui_defaults_review])
if self.ui_defaults_submenu:
self.ui_defaults_submenu.click(fn=self.ui_submenu_apply, _js='uiOpenSubmenus', inputs=[self.ui_defaults_review], outputs=[self.ui_defaults_review])

View File

@ -20,11 +20,11 @@ def create_toprow(is_img2img: bool = False, id_part: str = None, generate_visibl
with gr.Row():
with gr.Column(scale=80):
with gr.Row(elem_id=f"{id_part}_prompt_row"):
prompt = gr.Textbox(elem_id=f"{id_part}_prompt", label="Prompt", show_label=False, lines=3 if negative_visible else 5, placeholder="Prompt", elem_classes=["prompt"])
prompt = gr.Textbox(elem_id=f"{id_part}_prompt", label="Prompt", show_label=False, lines=3 if negative_visible else 5, placeholder="Prompt", elem_classes=["prompt", "main-prompts"])
with gr.Row():
with gr.Column(scale=80):
with gr.Row(elem_id=f"{id_part}_negative_row"):
negative_prompt = gr.Textbox(elem_id=f"{id_part}_neg_prompt", label="Negative prompt", show_label=False, lines=3, placeholder="Negative prompt", elem_classes=["prompt"], visible=negative_visible)
negative_prompt = gr.Textbox(elem_id=f"{id_part}_neg_prompt", label="Negative prompt", show_label=False, lines=3, placeholder="Negative prompt", elem_classes=["prompt", "main-prompts"], visible=negative_visible)
with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"):
with gr.Row(elem_id=f"{id_part}_generate_box"):
reprocess = []

View File

@ -56,6 +56,8 @@ def create_setting_component(key, is_quicksettings=False):
info = shared.opts.data_labels[key]
t = type(info.default)
args = (info.component_args() if callable(info.component_args) else info.component_args) or {}
if 'settings' in shared.opts.ui_disabled:
args['visible'] = False
if info.component is not None:
comp = info.component
elif t == str:
@ -171,16 +173,35 @@ def run_settings_single(value, key, progress=False):
return get_value_for_setting(key), shared.opts.dumpjson()
def create_ui():
def create_ui(disabled_tabs=[]):
shared.log.debug('UI initialize: tab=settings')
global text_settings # pylint: disable=global-statement
text_settings = gr.Textbox(elem_id="settings_json", elem_classes=["settings_json"], value=lambda: shared.opts.dumpjson(), visible=False)
with gr.Row(elem_id="system_row"):
unload_sd_model = gr.Button(value='Unload model', variant='primary', elem_id="sett_unload_sd_model")
reload_sd_model = gr.Button(value='Reload model', variant='primary', elem_id="sett_reload_sd_model")
restart_submit = gr.Button(value="Restart server", variant='primary', elem_id="restart_submit")
shutdown_submit = gr.Button(value="Shutdown server", variant='primary', elem_id="shutdown_submit")
enable_profiling = gr.Button(value='Start profiling', variant='primary', elem_id="enable_profiling")
def unload_sd_weights():
sd_models.unload_model_weights(op='model')
sd_models.unload_model_weights(op='refiner')
def reload_sd_weights():
sd_models.reload_model_weights(force=True)
def switch_profiling():
shared.cmd_opts.profile = not shared.cmd_opts.profile
shared.log.warning(f'Profiling: {shared.cmd_opts.profile}')
return 'Stop profiling' if shared.cmd_opts.profile else 'Start profiling'
if 'system' not in disabled_tabs:
with gr.Row(elem_id="system_row"):
unload_sd_model = gr.Button(value='Unload model', variant='primary', elem_id="sett_unload_sd_model")
reload_sd_model = gr.Button(value='Reload model', variant='primary', elem_id="sett_reload_sd_model")
restart_submit = gr.Button(value="Restart server", variant='primary', elem_id="restart_submit")
shutdown_submit = gr.Button(value="Shutdown server", variant='primary', elem_id="shutdown_submit")
enable_profiling = gr.Button(value='Start profiling', variant='primary', elem_id="enable_profiling")
unload_sd_model.click(fn=unload_sd_weights, inputs=[], outputs=[])
reload_sd_model.click(fn=reload_sd_weights, inputs=[], outputs=[])
enable_profiling.click(fn=switch_profiling, inputs=[], outputs=[enable_profiling])
restart_submit.click(fn=lambda: shared.restart_server(restart=True), _js="restartReload")
shutdown_submit.click(fn=lambda: shared.restart_server(restart=False), _js="restartReload")
with gr.Tabs(elem_id="system") as system_tabs:
global ui_system_tabs # pylint: disable=global-statement
@ -242,61 +263,51 @@ def create_ui():
shared.log.debug(f'Settings: sections={len(sections)} settings={len(shared.opts.list())}/{len(list(shared.opts.data_labels))} quicksettings={len(quicksettings_list)}')
with gr.TabItem("Update", id="system_update", elem_id="tab_update"):
from modules import update
update.create_ui()
if 'update' not in disabled_tabs:
with gr.TabItem("Update", id="system_update", elem_id="tab_update"):
from modules import update
update.create_ui()
with gr.TabItem("User interface", id="system_config", elem_id="tab_config"):
loadsave.create_ui()
create_dirty_indicator("tab_defaults", [], interactive=False)
if 'config' not in disabled_tabs:
with gr.TabItem("User interface", id="system_config", elem_id="tab_config"):
loadsave.create_ui()
create_dirty_indicator("tab_defaults", [], interactive=False)
with gr.TabItem("History", id="system_history", elem_id="tab_history"):
ui_history.create_ui()
if 'history' not in disabled_tabs:
with gr.TabItem("History", id="system_history", elem_id="tab_history"):
ui_history.create_ui()
with gr.TabItem("GPU Monitor", id="system_gpu", elem_id="tab_gpu"):
with gr.Row(elem_id='gpu-controls'):
gpu_start = gr.Button(value="Start", elem_id="gpu_start", variant="primary")
gpu_stop = gr.Button(value="Stop", elem_id="gpu_stop", variant="primary")
gpu_start.click(fn=lambda: None, _js='startGPU', inputs=[], outputs=[])
gpu_stop.click(fn=lambda: None, _js='disableGPU', inputs=[], outputs=[])
gr.HTML('''
<div class="gpu" id="gpu">
<table class="gpu-table" id="gpu-table">
<thead><tr><th></th><th></th></tr></thead>
<tbody></tbody>
</table>
<div id="gpuChart"></div>
</div>
''', elem_id='gpu-container', visible=True)
if 'monitor' not in disabled_tabs:
with gr.TabItem("GPU Monitor", id="system_gpu", elem_id="tab_gpu"):
with gr.Row(elem_id='gpu-controls'):
gpu_start = gr.Button(value="Start", elem_id="gpu_start", variant="primary")
gpu_stop = gr.Button(value="Stop", elem_id="gpu_stop", variant="primary")
gpu_start.click(fn=lambda: None, _js='startGPU', inputs=[], outputs=[])
gpu_stop.click(fn=lambda: None, _js='disableGPU', inputs=[], outputs=[])
gr.HTML('''
<div class="gpu" id="gpu">
<table class="gpu-table" id="gpu-table">
<thead><tr><th></th><th></th></tr></thead>
<tbody></tbody>
</table>
<div id="gpuChart"></div>
</div>
''', elem_id='gpu-container', visible=True)
with gr.TabItem("ONNX", id="onnx_config", elem_id="tab_onnx"):
from modules.onnx_impl import ui as ui_onnx
ui_onnx.create_ui()
if 'onnx' not in disabled_tabs:
with gr.TabItem("ONNX", id="onnx_config", elem_id="tab_onnx"):
from modules.onnx_impl import ui as ui_onnx
ui_onnx.create_ui()
def unload_sd_weights():
sd_models.unload_model_weights(op='model')
sd_models.unload_model_weights(op='refiner')
def reload_sd_weights():
sd_models.reload_model_weights(force=True)
def switch_profiling():
shared.cmd_opts.profile = not shared.cmd_opts.profile
shared.log.warning(f'Profiling: {shared.cmd_opts.profile}')
return 'Stop profiling' if shared.cmd_opts.profile else 'Start profiling'
unload_sd_model.click(fn=unload_sd_weights, inputs=[], outputs=[])
reload_sd_model.click(fn=reload_sd_weights, inputs=[], outputs=[])
enable_profiling.click(fn=switch_profiling, inputs=[], outputs=[enable_profiling])
request_notifications.click(fn=lambda: None, inputs=[], outputs=[], _js='function(){}')
if request_notifications:
request_notifications.click(fn=lambda: None, inputs=[], outputs=[], _js='function(){}')
settings_submit.click(
fn=call_queue.wrap_gradio_call(run_settings, extra_outputs=[gr.update()]),
inputs=components,
outputs=[text_settings, result],
)
defaults_submit.click(fn=lambda: shared.restore_defaults(restart=True), _js="restartReload")
restart_submit.click(fn=lambda: shared.restart_server(restart=True), _js="restartReload")
shutdown_submit.click(fn=lambda: shared.restart_server(restart=False), _js="restartReload")
if defaults_submit:
defaults_submit.click(fn=lambda: shared.restore_defaults(restart=True), _js="restartReload")
def reset_quicksettings(quick_components):