mirror of
				https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
				synced 2025-10-31 10:03:40 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			297 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import gradio as gr
 | |
| 
 | |
| from modules import ui_common, shared, script_callbacks, scripts, sd_models, sysinfo
 | |
| from modules.call_queue import wrap_gradio_call
 | |
| from modules.shared import opts
 | |
| from modules.ui_components import FormRow
 | |
| from modules.ui_gradio_extensions import reload_javascript
 | |
| 
 | |
| 
 | |
| def get_value_for_setting(key):
 | |
|     value = getattr(opts, key)
 | |
| 
 | |
|     info = opts.data_labels[key]
 | |
|     args = info.component_args() if callable(info.component_args) else info.component_args or {}
 | |
|     args = {k: v for k, v in args.items() if k not in {'precision'}}
 | |
| 
 | |
|     return gr.update(value=value, **args)
 | |
| 
 | |
| 
 | |
| def create_setting_component(key, is_quicksettings=False):
 | |
|     def fun():
 | |
|         return opts.data[key] if key in opts.data else opts.data_labels[key].default
 | |
| 
 | |
|     info = opts.data_labels[key]
 | |
|     t = type(info.default)
 | |
| 
 | |
|     args = info.component_args() if callable(info.component_args) else info.component_args
 | |
| 
 | |
|     if info.component is not None:
 | |
|         comp = info.component
 | |
|     elif t == str:
 | |
|         comp = gr.Textbox
 | |
|     elif t == int:
 | |
|         comp = gr.Number
 | |
|     elif t == bool:
 | |
|         comp = gr.Checkbox
 | |
|     else:
 | |
|         raise Exception(f'bad options item type: {t} for key {key}')
 | |
| 
 | |
|     elem_id = f"setting_{key}"
 | |
| 
 | |
|     if info.refresh is not None:
 | |
|         if is_quicksettings:
 | |
|             res = comp(label=info.label, value=fun(), elem_id=elem_id, **(args or {}))
 | |
|             ui_common.create_refresh_button(res, info.refresh, info.component_args, f"refresh_{key}")
 | |
|         else:
 | |
|             with FormRow():
 | |
|                 res = comp(label=info.label, value=fun(), elem_id=elem_id, **(args or {}))
 | |
|                 ui_common.create_refresh_button(res, info.refresh, info.component_args, f"refresh_{key}")
 | |
|     else:
 | |
|         res = comp(label=info.label, value=fun(), elem_id=elem_id, **(args or {}))
 | |
| 
 | |
|     return res
 | |
| 
 | |
| 
 | |
| class UiSettings:
 | |
|     submit = None
 | |
|     result = None
 | |
|     interface = None
 | |
|     components = None
 | |
|     component_dict = None
 | |
|     dummy_component = None
 | |
|     quicksettings_list = None
 | |
|     quicksettings_names = None
 | |
|     text_settings = None
 | |
| 
 | |
|     def run_settings(self, *args):
 | |
|         changed = []
 | |
| 
 | |
|         for key, value, comp in zip(opts.data_labels.keys(), args, self.components):
 | |
|             assert comp == self.dummy_component or opts.same_type(value, opts.data_labels[key].default), f"Bad value for setting {key}: {value}; expecting {type(opts.data_labels[key].default).__name__}"
 | |
| 
 | |
|         for key, value, comp in zip(opts.data_labels.keys(), args, self.components):
 | |
|             if comp == self.dummy_component:
 | |
|                 continue
 | |
| 
 | |
|             if opts.set(key, value):
 | |
|                 changed.append(key)
 | |
| 
 | |
|         try:
 | |
|             opts.save(shared.config_filename)
 | |
|         except RuntimeError:
 | |
|             return opts.dumpjson(), f'{len(changed)} settings changed without save: {", ".join(changed)}.'
 | |
|         return opts.dumpjson(), f'{len(changed)} settings changed{": " if changed else ""}{", ".join(changed)}.'
 | |
| 
 | |
|     def run_settings_single(self, value, key):
 | |
|         if not opts.same_type(value, opts.data_labels[key].default):
 | |
|             return gr.update(visible=True), opts.dumpjson()
 | |
| 
 | |
|         if not opts.set(key, value):
 | |
|             return gr.update(value=getattr(opts, key)), opts.dumpjson()
 | |
| 
 | |
|         opts.save(shared.config_filename)
 | |
| 
 | |
|         return get_value_for_setting(key), opts.dumpjson()
 | |
| 
 | |
|     def create_ui(self, loadsave, dummy_component):
 | |
|         self.components = []
 | |
|         self.component_dict = {}
 | |
|         self.dummy_component = dummy_component
 | |
| 
 | |
|         shared.settings_components = self.component_dict
 | |
| 
 | |
|         script_callbacks.ui_settings_callback()
 | |
|         opts.reorder()
 | |
| 
 | |
|         with gr.Blocks(analytics_enabled=False) as settings_interface:
 | |
|             with gr.Row():
 | |
|                 with gr.Column(scale=6):
 | |
|                     self.submit = gr.Button(value="Apply settings", variant='primary', elem_id="settings_submit")
 | |
|                 with gr.Column():
 | |
|                     restart_gradio = gr.Button(value='Reload UI', variant='primary', elem_id="settings_restart_gradio")
 | |
| 
 | |
|             self.result = gr.HTML(elem_id="settings_result")
 | |
| 
 | |
|             self.quicksettings_names = opts.quicksettings_list
 | |
|             self.quicksettings_names = {x: i for i, x in enumerate(self.quicksettings_names) if x != 'quicksettings'}
 | |
| 
 | |
|             self.quicksettings_list = []
 | |
| 
 | |
|             previous_section = None
 | |
|             current_tab = None
 | |
|             current_row = None
 | |
|             with gr.Tabs(elem_id="settings"):
 | |
|                 for i, (k, item) in enumerate(opts.data_labels.items()):
 | |
|                     section_must_be_skipped = item.section[0] is None
 | |
| 
 | |
|                     if previous_section != item.section and not section_must_be_skipped:
 | |
|                         elem_id, text = item.section
 | |
| 
 | |
|                         if current_tab is not None:
 | |
|                             current_row.__exit__()
 | |
|                             current_tab.__exit__()
 | |
| 
 | |
|                         gr.Group()
 | |
|                         current_tab = gr.TabItem(elem_id=f"settings_{elem_id}", label=text)
 | |
|                         current_tab.__enter__()
 | |
|                         current_row = gr.Column(variant='compact')
 | |
|                         current_row.__enter__()
 | |
| 
 | |
|                         previous_section = item.section
 | |
| 
 | |
|                     if k in self.quicksettings_names and not shared.cmd_opts.freeze_settings:
 | |
|                         self.quicksettings_list.append((i, k, item))
 | |
|                         self.components.append(dummy_component)
 | |
|                     elif section_must_be_skipped:
 | |
|                         self.components.append(dummy_component)
 | |
|                     else:
 | |
|                         component = create_setting_component(k)
 | |
|                         self.component_dict[k] = component
 | |
|                         self.components.append(component)
 | |
| 
 | |
|                 if current_tab is not None:
 | |
|                     current_row.__exit__()
 | |
|                     current_tab.__exit__()
 | |
| 
 | |
|                 with gr.TabItem("Defaults", id="defaults", elem_id="settings_tab_defaults"):
 | |
|                     loadsave.create_ui()
 | |
| 
 | |
|                 with gr.TabItem("Sysinfo", id="sysinfo", elem_id="settings_tab_sysinfo"):
 | |
|                     gr.HTML('<a href="./internal/sysinfo-download" class="sysinfo_big_link" download>Download system info</a><br /><a href="./internal/sysinfo" target="_blank">(or open as text in a new page)</a>', elem_id="sysinfo_download")
 | |
| 
 | |
|                     with gr.Row():
 | |
|                         with gr.Column(scale=1):
 | |
|                             sysinfo_check_file = gr.File(label="Check system info for validity", type='binary')
 | |
|                         with gr.Column(scale=1):
 | |
|                             sysinfo_check_output = gr.HTML("", elem_id="sysinfo_validity")
 | |
|                         with gr.Column(scale=100):
 | |
|                             pass
 | |
| 
 | |
|                 with gr.TabItem("Actions", id="actions", elem_id="settings_tab_actions"):
 | |
|                     request_notifications = gr.Button(value='Request browser notifications', elem_id="request_notifications")
 | |
|                     download_localization = gr.Button(value='Download localization template', elem_id="download_localization")
 | |
|                     reload_script_bodies = gr.Button(value='Reload custom script bodies (No ui updates, No restart)', variant='secondary', elem_id="settings_reload_script_bodies")
 | |
|                     with gr.Row():
 | |
|                         unload_sd_model = gr.Button(value='Unload SD checkpoint to free VRAM', elem_id="sett_unload_sd_model")
 | |
|                         reload_sd_model = gr.Button(value='Reload the last SD checkpoint back into VRAM', elem_id="sett_reload_sd_model")
 | |
| 
 | |
|                 with gr.TabItem("Licenses", id="licenses", elem_id="settings_tab_licenses"):
 | |
|                     gr.HTML(shared.html("licenses.html"), elem_id="licenses")
 | |
| 
 | |
|                 gr.Button(value="Show all pages", elem_id="settings_show_all_pages")
 | |
| 
 | |
|                 self.text_settings = gr.Textbox(elem_id="settings_json", value=lambda: opts.dumpjson(), visible=False)
 | |
| 
 | |
|             unload_sd_model.click(
 | |
|                 fn=sd_models.unload_model_weights,
 | |
|                 inputs=[],
 | |
|                 outputs=[]
 | |
|             )
 | |
| 
 | |
|             reload_sd_model.click(
 | |
|                 fn=sd_models.reload_model_weights,
 | |
|                 inputs=[],
 | |
|                 outputs=[]
 | |
|             )
 | |
| 
 | |
|             request_notifications.click(
 | |
|                 fn=lambda: None,
 | |
|                 inputs=[],
 | |
|                 outputs=[],
 | |
|                 _js='function(){}'
 | |
|             )
 | |
| 
 | |
|             download_localization.click(
 | |
|                 fn=lambda: None,
 | |
|                 inputs=[],
 | |
|                 outputs=[],
 | |
|                 _js='download_localization'
 | |
|             )
 | |
| 
 | |
|             def reload_scripts():
 | |
|                 scripts.reload_script_body_only()
 | |
|                 reload_javascript()  # need to refresh the html page
 | |
| 
 | |
|             reload_script_bodies.click(
 | |
|                 fn=reload_scripts,
 | |
|                 inputs=[],
 | |
|                 outputs=[]
 | |
|             )
 | |
| 
 | |
|             restart_gradio.click(
 | |
|                 fn=shared.state.request_restart,
 | |
|                 _js='restart_reload',
 | |
|                 inputs=[],
 | |
|                 outputs=[],
 | |
|             )
 | |
| 
 | |
|             def check_file(x):
 | |
|                 if x is None:
 | |
|                     return ''
 | |
| 
 | |
|                 if sysinfo.check(x.decode('utf8', errors='ignore')):
 | |
|                     return 'Valid'
 | |
| 
 | |
|                 return 'Invalid'
 | |
| 
 | |
|             sysinfo_check_file.change(
 | |
|                 fn=check_file,
 | |
|                 inputs=[sysinfo_check_file],
 | |
|                 outputs=[sysinfo_check_output],
 | |
|             )
 | |
| 
 | |
|         self.interface = settings_interface
 | |
| 
 | |
|     def add_quicksettings(self):
 | |
|         with gr.Row(elem_id="quicksettings", variant="compact"):
 | |
|             for _i, k, _item in sorted(self.quicksettings_list, key=lambda x: self.quicksettings_names.get(x[1], x[0])):
 | |
|                 component = create_setting_component(k, is_quicksettings=True)
 | |
|                 self.component_dict[k] = component
 | |
| 
 | |
|     def add_functionality(self, demo):
 | |
|         self.submit.click(
 | |
|             fn=wrap_gradio_call(lambda *args: self.run_settings(*args), extra_outputs=[gr.update()]),
 | |
|             inputs=self.components,
 | |
|             outputs=[self.text_settings, self.result],
 | |
|         )
 | |
| 
 | |
|         for _i, k, _item in self.quicksettings_list:
 | |
|             component = self.component_dict[k]
 | |
|             info = opts.data_labels[k]
 | |
| 
 | |
|             if isinstance(component, gr.Textbox):
 | |
|                 methods = [component.submit, component.blur]
 | |
|             elif hasattr(component, 'release'):
 | |
|                 methods = [component.release]
 | |
|             else:
 | |
|                 methods = [component.change]
 | |
| 
 | |
|             for method in methods:
 | |
|                 method(
 | |
|                     fn=lambda value, k=k: self.run_settings_single(value, key=k),
 | |
|                     inputs=[component],
 | |
|                     outputs=[component, self.text_settings],
 | |
|                     show_progress=info.refresh is not None,
 | |
|                 )
 | |
| 
 | |
|         button_set_checkpoint = gr.Button('Change checkpoint', elem_id='change_checkpoint', visible=False)
 | |
|         button_set_checkpoint.click(
 | |
|             fn=lambda value, _: self.run_settings_single(value, key='sd_model_checkpoint'),
 | |
|             _js="function(v){ var res = desiredCheckpointName; desiredCheckpointName = ''; return [res || v, null]; }",
 | |
|             inputs=[self.component_dict['sd_model_checkpoint'], self.dummy_component],
 | |
|             outputs=[self.component_dict['sd_model_checkpoint'], self.text_settings],
 | |
|         )
 | |
| 
 | |
|         component_keys = [k for k in opts.data_labels.keys() if k in self.component_dict]
 | |
| 
 | |
|         def get_settings_values():
 | |
|             return [get_value_for_setting(key) for key in component_keys]
 | |
| 
 | |
|         demo.load(
 | |
|             fn=get_settings_values,
 | |
|             inputs=[],
 | |
|             outputs=[self.component_dict[k] for k in component_keys],
 | |
|             queue=False,
 | |
|         )
 | 
