123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- 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">(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,
- )
|