Browse Source

set up a system to provide extra info for settings elements in python rather than js
add a bit of spacing/styling to settings elements
add link info for token merging

AUTOMATIC 2 years ago
parent
commit
ce515b81c5
3 changed files with 103 additions and 42 deletions
  1. 56 36
      javascript/ui_settings_hints.js
  2. 27 6
      modules/shared.py
  3. 20 0
      style.css

+ 56 - 36
javascript/ui_settings_hints.js

@@ -1,41 +1,61 @@
 // various hints and extra info for the settings tab
 // various hints and extra info for the settings tab
 
 
-onUiLoaded(function(){
-    createLink = function(elem_id, text, href){
-        var a = document.createElement('A')
-        a.textContent = text
-        a.target = '_blank';
-
-        elem = gradioApp().querySelector('#'+elem_id)
-        elem.insertBefore(a, elem.querySelector('label'))
-
-        return a
-    }
-
-    createLink("setting_samples_filename_pattern", "[wiki] ").href = "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"
-    createLink("setting_directories_filename_pattern", "[wiki] ").href = "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"
-
-    createLink("setting_quicksettings_list", "[info] ").addEventListener("click", function(event){
-        requestGet("./internal/quicksettings-hint", {}, function(data){
-            var table = document.createElement('table')
-            table.className = 'settings-value-table'
-
-            data.forEach(function(obj){
-                var tr = document.createElement('tr')
-                var td = document.createElement('td')
-                td.textContent = obj.name
-                tr.appendChild(td)
-
-                var td = document.createElement('td')
-                td.textContent = obj.label
-                tr.appendChild(td)
-
-                table.appendChild(tr)
-            })
-
-            popup(table);
-        })
-    });
+settingsHintsSetup = false
+
+onOptionsChanged(function(){
+    if(settingsHintsSetup) return
+    settingsHintsSetup = true
+
+    gradioApp().querySelectorAll('#settings [id^=setting_]').forEach(function(div){
+        var name = div.id.substr(8)
+        var commentBefore = opts._comments_before[name]
+        var commentAfter = opts._comments_after[name]
+
+        if(! commentBefore && !commentAfter) return
+
+        var span = null
+        if(div.classList.contains('gradio-checkbox')) span = div.querySelector('label span')
+        else if(div.classList.contains('gradio-checkboxgroup')) span = div.querySelector('span')
+        else span = div.querySelector('label span').firstChild
+
+        if(!span) return
+
+        if(commentBefore){
+            var comment = document.createElement('DIV')
+            comment.className = 'settings-comment'
+            comment.innerHTML = commentBefore
+            span.parentElement.insertBefore(document.createTextNode('\xa0'), span)
+            span.parentElement.insertBefore(comment, span)
+            span.parentElement.insertBefore(document.createTextNode('\xa0'), span)
+        }
+        if(commentAfter){
+            var comment = document.createElement('DIV')
+            comment.className = 'settings-comment'
+            comment.innerHTML = commentAfter
+            span.parentElement.insertBefore(comment, span.nextSibling)
+            span.parentElement.insertBefore(document.createTextNode('\xa0'), span.nextSibling)
+        }
+    })
 })
 })
 
 
+function settingsHintsShowQuicksettings(){
+	requestGet("./internal/quicksettings-hint", {}, function(data){
+		var table = document.createElement('table')
+		table.className = 'settings-value-table'
 
 
+		data.forEach(function(obj){
+			var tr = document.createElement('tr')
+			var td = document.createElement('td')
+			td.textContent = obj.name
+			tr.appendChild(td)
+
+			var td = document.createElement('td')
+			td.textContent = obj.label
+			tr.appendChild(td)
+
+			table.appendChild(tr)
+		})
+
+		popup(table);
+	})
+}

+ 27 - 6
modules/shared.py

@@ -199,8 +199,9 @@ interrogator = modules.interrogate.InterrogateModels("interrogate")
 
 
 face_restorers = []
 face_restorers = []
 
 
+
 class OptionInfo:
 class OptionInfo:
-    def __init__(self, default=None, label="", component=None, component_args=None, onchange=None, section=None, refresh=None):
+    def __init__(self, default=None, label="", component=None, component_args=None, onchange=None, section=None, refresh=None, comment_before='', comment_after=''):
         self.default = default
         self.default = default
         self.label = label
         self.label = label
         self.component = component
         self.component = component
@@ -209,6 +210,24 @@ class OptionInfo:
         self.section = section
         self.section = section
         self.refresh = refresh
         self.refresh = refresh
 
 
+        self.comment_before = comment_before
+        """HTML text that will be added after label in UI"""
+
+        self.comment_after = comment_after
+        """HTML text that will be added before label in UI"""
+
+    def link(self, label, url):
+        self.comment_before += f"[<a href='{url}' target='_blank'>{label}</a>]"
+        return self
+
+    def js(self, label, js_func):
+        self.comment_before += f"[<a onclick='{js_func}(); return false'>{label}</a>]"
+        return self
+
+    def info(self, info):
+        self.comment_after += f"<span class='info'>({info})</span>"
+        return self
+
 
 
 def options_section(section_identifier, options_dict):
 def options_section(section_identifier, options_dict):
     for v in options_dict.values():
     for v in options_dict.values():
@@ -240,7 +259,7 @@ options_templates = {}
 options_templates.update(options_section(('saving-images', "Saving images/grids"), {
 options_templates.update(options_section(('saving-images', "Saving images/grids"), {
     "samples_save": OptionInfo(True, "Always save all generated images"),
     "samples_save": OptionInfo(True, "Always save all generated images"),
     "samples_format": OptionInfo('png', 'File format for images'),
     "samples_format": OptionInfo('png', 'File format for images'),
-    "samples_filename_pattern": OptionInfo("", "Images filename pattern", component_args=hide_dirs),
+    "samples_filename_pattern": OptionInfo("", "Images filename pattern", component_args=hide_dirs).link("wiki", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"),
     "save_images_add_number": OptionInfo(True, "Add number to filename when saving", component_args=hide_dirs),
     "save_images_add_number": OptionInfo(True, "Add number to filename when saving", component_args=hide_dirs),
 
 
     "grid_save": OptionInfo(True, "Always save all generated image grids"),
     "grid_save": OptionInfo(True, "Always save all generated image grids"),
@@ -290,7 +309,7 @@ options_templates.update(options_section(('saving-to-dirs', "Saving to a directo
     "save_to_dirs": OptionInfo(True, "Save images to a subdirectory"),
     "save_to_dirs": OptionInfo(True, "Save images to a subdirectory"),
     "grid_save_to_dirs": OptionInfo(True, "Save grids to a subdirectory"),
     "grid_save_to_dirs": OptionInfo(True, "Save grids to a subdirectory"),
     "use_save_to_dirs_for_ui": OptionInfo(False, "When using \"Save\" button, save images to a subdirectory"),
     "use_save_to_dirs_for_ui": OptionInfo(False, "When using \"Save\" button, save images to a subdirectory"),
-    "directories_filename_pattern": OptionInfo("[date]", "Directory name pattern", component_args=hide_dirs),
+    "directories_filename_pattern": OptionInfo("[date]", "Directory name pattern", component_args=hide_dirs).link("wiki", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"),
     "directories_max_prompt_words": OptionInfo(8, "Max prompt words for [prompt_words] pattern", gr.Slider, {"minimum": 1, "maximum": 20, "step": 1, **hide_dirs}),
     "directories_max_prompt_words": OptionInfo(8, "Max prompt words for [prompt_words] pattern", gr.Slider, {"minimum": 1, "maximum": 20, "step": 1, **hide_dirs}),
 }))
 }))
 
 
@@ -350,7 +369,7 @@ options_templates.update(options_section(('sd', "Stable Diffusion"), {
     "CLIP_stop_at_last_layers": OptionInfo(1, "Clip skip", gr.Slider, {"minimum": 1, "maximum": 12, "step": 1}),
     "CLIP_stop_at_last_layers": OptionInfo(1, "Clip skip", gr.Slider, {"minimum": 1, "maximum": 12, "step": 1}),
     "upcast_attn": OptionInfo(False, "Upcast cross attention layer to float32"),
     "upcast_attn": OptionInfo(False, "Upcast cross attention layer to float32"),
     "randn_source": OptionInfo("GPU", "Random number generator source. Changes seeds drastically. Use CPU to produce the same picture across different vidocard vendors.", gr.Radio, {"choices": ["GPU", "CPU"]}),
     "randn_source": OptionInfo("GPU", "Random number generator source. Changes seeds drastically. Use CPU to produce the same picture across different vidocard vendors.", gr.Radio, {"choices": ["GPU", "CPU"]}),
-    "token_merging_ratio": OptionInfo(0.0, "Token merging ratio", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}),
+    "token_merging_ratio": OptionInfo(0.0, "Token merging ratio", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}).link("PR", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/9256").info("0=disable, higher=faster"),
     "token_merging_ratio_hr": OptionInfo(0.0, "Togen merging ratio for high-res pass", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}),
     "token_merging_ratio_hr": OptionInfo(0.0, "Togen merging ratio for high-res pass", gr.Slider, {"minimum": 0.0, "maximum": 0.9, "step": 0.1}),
 }))
 }))
 
 
@@ -404,7 +423,7 @@ options_templates.update(options_section(('ui', "User interface"), {
     "keyedit_precision_attention": OptionInfo(0.1, "Ctrl+up/down precision when editing (attention:1.1)", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
     "keyedit_precision_attention": OptionInfo(0.1, "Ctrl+up/down precision when editing (attention:1.1)", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
     "keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing <extra networks:0.9>", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
     "keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing <extra networks:0.9>", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
     "keyedit_delimiters": OptionInfo(".,\\/!?%^*;:{}=`~()", "Ctrl+up/down word delimiters"),
     "keyedit_delimiters": OptionInfo(".,\\/!?%^*;:{}=`~()", "Ctrl+up/down word delimiters"),
-    "quicksettings_list": OptionInfo(["sd_model_checkpoint"], "Quicksettings list", ui_components.DropdownMulti, lambda: {"choices": list(opts.data_labels.keys())}),
+    "quicksettings_list": OptionInfo(["sd_model_checkpoint"], "Quicksettings list", ui_components.DropdownMulti, lambda: {"choices": list(opts.data_labels.keys())}).js("info", "settingsHintsShowQuicksettings"),
     "hidden_tabs": OptionInfo([], "Hidden UI tabs (requires restart)", ui_components.DropdownMulti, lambda: {"choices": list(tab_names)}),
     "hidden_tabs": OptionInfo([], "Hidden UI tabs (requires restart)", ui_components.DropdownMulti, lambda: {"choices": list(tab_names)}),
     "ui_reorder": OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
     "ui_reorder": OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
     "ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order"),
     "ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order"),
@@ -572,7 +591,9 @@ class Options:
             func()
             func()
 
 
     def dumpjson(self):
     def dumpjson(self):
-        d = {k: self.data.get(k, self.data_labels.get(k).default) for k in self.data_labels.keys()}
+        d = {k: self.data.get(k, v.default) for k, v in self.data_labels.items()}
+        d["_comments_before"] = {k: v.comment_before for k, v in self.data_labels.items() if v.comment_before is not None}
+        d["_comments_after"] = {k: v.comment_after for k, v in self.data_labels.items() if v.comment_after is not None}
         return json.dumps(d)
         return json.dumps(d)
 
 
     def add_option(self, key, info):
     def add_option(self, key, info):

+ 20 - 0
style.css

@@ -421,6 +421,26 @@ table.settings-value-table td{
     color: #aaa !important;
     color: #aaa !important;
 }
 }
 
 
+#settings span{
+    color: var(--body-text-color);
+}
+
+#settings .gradio-textbox, #settings .gradio-slider, #settings .gradio-number, #settings .gradio-dropdown, #settings .gradio-checkboxgroup{
+    margin-top: 0.75em;
+}
+
+.gradio-textbox .settings-comment, .gradio-slider .settings-comment, .gradio-number .settings-comment, .gradio-dropdown .settings-comment, .gradio-checkboxgroup .settings-comment {
+    display: inline
+}
+
+.settings-comment a{
+    text-decoration: underline;
+}
+
+.settings-comment .info{
+    opacity: 0.75;
+}
+
 /* live preview */
 /* live preview */
 .progressDiv{
 .progressDiv{
     position: relative;
     position: relative;