mirror of
https://github.com/openvinotoolkit/stable-diffusion-webui.git
synced 2024-12-15 23:22:48 +03:00
Merge branch 'AUTOMATIC1111:master' into Italian
This commit is contained in:
commit
44ae3504b0
24
javascript/extensions.js
Normal file
24
javascript/extensions.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
function extensions_apply(_, _){
|
||||||
|
disable = []
|
||||||
|
update = []
|
||||||
|
gradioApp().querySelectorAll('#extensions input[type="checkbox"]').forEach(function(x){
|
||||||
|
if(x.name.startsWith("enable_") && ! x.checked)
|
||||||
|
disable.push(x.name.substr(7))
|
||||||
|
|
||||||
|
if(x.name.startsWith("update_") && x.checked)
|
||||||
|
update.push(x.name.substr(7))
|
||||||
|
})
|
||||||
|
|
||||||
|
restart_reload()
|
||||||
|
|
||||||
|
return [JSON.stringify(disable), JSON.stringify(update)]
|
||||||
|
}
|
||||||
|
|
||||||
|
function extensions_check(){
|
||||||
|
gradioApp().querySelectorAll('#extensions .extension_status').forEach(function(x){
|
||||||
|
x.innerHTML = "Loading..."
|
||||||
|
})
|
||||||
|
|
||||||
|
return []
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
" images in this directory. Loaded ": "개의 이미지가 이 경로에 존재합니다. ",
|
" images in this directory. Loaded ": "개의 이미지가 이 경로에 존재합니다. ",
|
||||||
" pages": "페이지로 나뉘어 표시합니다.",
|
" pages": "페이지로 나뉘어 표시합니다.",
|
||||||
", divided into ": "입니다. ",
|
", divided into ": "입니다. ",
|
||||||
|
". Use Installed tab to restart.": "에 성공적으로 설치하였습니다. 설치된 확장기능 탭에서 UI를 재시작해주세요.",
|
||||||
"1st and last digit must be 1. ex:'1, 2, 1'": "1st and last digit must be 1. ex:'1, 2, 1'",
|
"1st and last digit must be 1. ex:'1, 2, 1'": "1st and last digit must be 1. ex:'1, 2, 1'",
|
||||||
"[wiki]": " [위키] 참조",
|
"[wiki]": " [위키] 참조",
|
||||||
"A directory on the same machine where the server is running.": "WebUI 서버가 돌아가고 있는 디바이스에 존재하는 디렉토리를 선택해 주세요.",
|
"A directory on the same machine where the server is running.": "WebUI 서버가 돌아가고 있는 디바이스에 존재하는 디렉토리를 선택해 주세요.",
|
||||||
@ -34,6 +35,7 @@
|
|||||||
"api": "",
|
"api": "",
|
||||||
"append": "뒤에 삽입",
|
"append": "뒤에 삽입",
|
||||||
"Append commas": "쉼표 삽입",
|
"Append commas": "쉼표 삽입",
|
||||||
|
"Apply and restart UI": "적용 후 UI 재시작",
|
||||||
"Apply color correction to img2img results to match original colors.": "이미지→이미지 결과물이 기존 색상과 일치하도록 색상 보정 적용하기",
|
"Apply color correction to img2img results to match original colors.": "이미지→이미지 결과물이 기존 색상과 일치하도록 색상 보정 적용하기",
|
||||||
"Apply selected styles to current prompt": "현재 프롬프트에 선택된 스타일 적용",
|
"Apply selected styles to current prompt": "현재 프롬프트에 선택된 스타일 적용",
|
||||||
"Apply settings": "설정 적용하기",
|
"Apply settings": "설정 적용하기",
|
||||||
@ -44,6 +46,7 @@
|
|||||||
"Batch img2img": "이미지→이미지 배치",
|
"Batch img2img": "이미지→이미지 배치",
|
||||||
"Batch Process": "이미지 여러장 처리",
|
"Batch Process": "이미지 여러장 처리",
|
||||||
"Batch size": "배치 크기",
|
"Batch size": "배치 크기",
|
||||||
|
"behind": "최신 아님",
|
||||||
"BSRGAN 4x": "BSRGAN 4x",
|
"BSRGAN 4x": "BSRGAN 4x",
|
||||||
"built with gradio": "gradio로 제작되었습니다",
|
"built with gradio": "gradio로 제작되었습니다",
|
||||||
"Cancel generate forever": "반복 생성 취소",
|
"Cancel generate forever": "반복 생성 취소",
|
||||||
@ -52,6 +55,7 @@
|
|||||||
"CFG Scale": "CFG 스케일",
|
"CFG Scale": "CFG 스케일",
|
||||||
"cfg1 min/max": "CFG1 최소/최대",
|
"cfg1 min/max": "CFG1 최소/최대",
|
||||||
"cfg2 min/max": "CFG2 최소/최대",
|
"cfg2 min/max": "CFG2 최소/최대",
|
||||||
|
"Check for updates": "업데이트 확인",
|
||||||
"Check progress": "진행도 체크",
|
"Check progress": "진행도 체크",
|
||||||
"Check progress (first)": "진행도 체크 (처음)",
|
"Check progress (first)": "진행도 체크 (처음)",
|
||||||
"checkpoint": " 체크포인트 ",
|
"checkpoint": " 체크포인트 ",
|
||||||
@ -136,6 +140,8 @@
|
|||||||
"Euler a": "Euler a",
|
"Euler a": "Euler a",
|
||||||
"Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps to higher than 30-40 does not help": "Euler Ancestral - 매우 창의적, 스텝 수에 따라 완전히 다른 결과물이 나올 수 있음. 30~40보다 높은 스텝 수는 효과가 미미함",
|
"Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps to higher than 30-40 does not help": "Euler Ancestral - 매우 창의적, 스텝 수에 따라 완전히 다른 결과물이 나올 수 있음. 30~40보다 높은 스텝 수는 효과가 미미함",
|
||||||
"Existing Caption txt Action": "이미 존재하는 캡션 텍스트 처리",
|
"Existing Caption txt Action": "이미 존재하는 캡션 텍스트 처리",
|
||||||
|
"Extension": "확장기능",
|
||||||
|
"Extensions": "확장기능",
|
||||||
"Extra": "고급",
|
"Extra": "고급",
|
||||||
"Extras": "부가기능",
|
"Extras": "부가기능",
|
||||||
"extras": "부가기능",
|
"extras": "부가기능",
|
||||||
@ -216,6 +222,10 @@
|
|||||||
"Inpainting conditioning mask strength": "인페인팅 조절 마스크 강도",
|
"Inpainting conditioning mask strength": "인페인팅 조절 마스크 강도",
|
||||||
"Input directory": "인풋 이미지 경로",
|
"Input directory": "인풋 이미지 경로",
|
||||||
"Input images directory": "이미지 경로 입력",
|
"Input images directory": "이미지 경로 입력",
|
||||||
|
"Install": "설치",
|
||||||
|
"Install from URL": "URL로부터 확장기능 설치",
|
||||||
|
"Installed": "설치된 확장기능",
|
||||||
|
"Installed into ": "확장기능을 ",
|
||||||
"Interpolation Method": "보간 방법",
|
"Interpolation Method": "보간 방법",
|
||||||
"Interrogate\nCLIP": "CLIP\n분석",
|
"Interrogate\nCLIP": "CLIP\n분석",
|
||||||
"Interrogate\nDeepBooru": "DeepBooru\n분석",
|
"Interrogate\nDeepBooru": "DeepBooru\n분석",
|
||||||
@ -242,10 +252,12 @@
|
|||||||
"Last saved image:": "마지막으로 저장된 이미지 : ",
|
"Last saved image:": "마지막으로 저장된 이미지 : ",
|
||||||
"latent noise": "잠재 노이즈",
|
"latent noise": "잠재 노이즈",
|
||||||
"latent nothing": "잠재 공백",
|
"latent nothing": "잠재 공백",
|
||||||
|
"latest": "최신 버전",
|
||||||
"LDSR": "LDSR",
|
"LDSR": "LDSR",
|
||||||
"LDSR processing steps. Lower = faster": "LDSR 스텝 수. 낮은 값 = 빠른 속도",
|
"LDSR processing steps. Lower = faster": "LDSR 스텝 수. 낮은 값 = 빠른 속도",
|
||||||
"leakyrelu": "leakyrelu",
|
"leakyrelu": "leakyrelu",
|
||||||
"Leave blank to save images to the default path.": "기존 저장 경로에 이미지들을 저장하려면 비워두세요.",
|
"Leave blank to save images to the default path.": "기존 저장 경로에 이미지들을 저장하려면 비워두세요.",
|
||||||
|
"Leave empty for auto": "자동 설정하려면 비워두십시오",
|
||||||
"left": "왼쪽",
|
"left": "왼쪽",
|
||||||
"linear": "linear",
|
"linear": "linear",
|
||||||
"List of prompt inputs": "프롬프트 입력 리스트",
|
"List of prompt inputs": "프롬프트 입력 리스트",
|
||||||
@ -254,6 +266,7 @@
|
|||||||
"LMS Karras": "LMS Karras",
|
"LMS Karras": "LMS Karras",
|
||||||
"Load": "불러오기",
|
"Load": "불러오기",
|
||||||
"Loading...": "로딩 중...",
|
"Loading...": "로딩 중...",
|
||||||
|
"Local directory name": "로컬 경로 이름",
|
||||||
"Localization (requires restart)": "현지화 (재시작 필요)",
|
"Localization (requires restart)": "현지화 (재시작 필요)",
|
||||||
"Log directory": "로그 경로",
|
"Log directory": "로그 경로",
|
||||||
"Loopback": "루프백",
|
"Loopback": "루프백",
|
||||||
@ -486,7 +499,9 @@
|
|||||||
"txt2img": "텍스트→이미지",
|
"txt2img": "텍스트→이미지",
|
||||||
"txt2img history": "텍스트→이미지 기록",
|
"txt2img history": "텍스트→이미지 기록",
|
||||||
"uniform": "uniform",
|
"uniform": "uniform",
|
||||||
|
"unknown": "알수 없음",
|
||||||
"up": "위쪽",
|
"up": "위쪽",
|
||||||
|
"Update": "업데이트",
|
||||||
"Upload mask": "마스크 업로드하기",
|
"Upload mask": "마스크 업로드하기",
|
||||||
"Upload prompt inputs": "입력할 프롬프트를 업로드하십시오",
|
"Upload prompt inputs": "입력할 프롬프트를 업로드하십시오",
|
||||||
"Upscale Before Restoring Faces": "얼굴 보정을 진행하기 전에 업스케일링 먼저 진행하기",
|
"Upscale Before Restoring Faces": "얼굴 보정을 진행하기 전에 업스케일링 먼저 진행하기",
|
||||||
@ -498,9 +513,12 @@
|
|||||||
"Upscaler 2 visibility": "업스케일러 2 가시성",
|
"Upscaler 2 visibility": "업스케일러 2 가시성",
|
||||||
"Upscaler for img2img": "이미지→이미지 업스케일러",
|
"Upscaler for img2img": "이미지→이미지 업스케일러",
|
||||||
"Upscaling": "업스케일링",
|
"Upscaling": "업스케일링",
|
||||||
|
"URL for extension's git repository": "확장기능의 git 레포 URL",
|
||||||
"Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition": "저해상도 이미지를 1차적으로 생성 후 업스케일을 진행하여, 이미지의 전체적인 구성을 바꾸지 않고 세부적인 디테일을 향상시킵니다.",
|
"Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition": "저해상도 이미지를 1차적으로 생성 후 업스케일을 진행하여, 이미지의 전체적인 구성을 바꾸지 않고 세부적인 디테일을 향상시킵니다.",
|
||||||
"Use an empty output directory to save pictures normally instead of writing to the output directory.": "저장 경로를 비워두면 기본 저장 폴더에 이미지들이 저장됩니다.",
|
"Use an empty output directory to save pictures normally instead of writing to the output directory.": "저장 경로를 비워두면 기본 저장 폴더에 이미지들이 저장됩니다.",
|
||||||
"Use BLIP for caption": "캡션에 BLIP 사용",
|
"Use BLIP for caption": "캡션에 BLIP 사용",
|
||||||
|
"Use checkbox to enable the extension; it will be enabled or disabled when you click apply button": "체크박스를 이용해 적용할 확장기능을 선택하세요. 변경사항은 적용 후 UI 재시작 버튼을 눌러야 적용됩니다.",
|
||||||
|
"Use checkbox to mark the extension for update; it will be updated when you click apply button": "체크박스를 이용해 업데이트할 확장기능을 선택하세요. 업데이트는 적용 후 UI 재시작 버튼을 눌러야 적용됩니다.",
|
||||||
"Use deepbooru for caption": "캡션에 deepbooru 사용",
|
"Use deepbooru for caption": "캡션에 deepbooru 사용",
|
||||||
"Use dropout": "드롭아웃 사용",
|
"Use dropout": "드롭아웃 사용",
|
||||||
"Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.": "다음 태그들을 사용해 이미지 파일명 형식을 결정하세요 : [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]. 비워두면 기본값으로 설정됩니다.",
|
"Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]; leave empty for default.": "다음 태그들을 사용해 이미지 파일명 형식을 결정하세요 : [steps], [cfg], [prompt], [prompt_no_styles], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [datetime<Format>], [datetime<Format><Time Zone>], [job_timestamp]. 비워두면 기본값으로 설정됩니다.",
|
||||||
|
83
modules/extensions.py
Normal file
83
modules/extensions.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import git
|
||||||
|
|
||||||
|
from modules import paths, shared
|
||||||
|
|
||||||
|
|
||||||
|
extensions = []
|
||||||
|
extensions_dir = os.path.join(paths.script_path, "extensions")
|
||||||
|
|
||||||
|
|
||||||
|
def active():
|
||||||
|
return [x for x in extensions if x.enabled]
|
||||||
|
|
||||||
|
|
||||||
|
class Extension:
|
||||||
|
def __init__(self, name, path, enabled=True):
|
||||||
|
self.name = name
|
||||||
|
self.path = path
|
||||||
|
self.enabled = enabled
|
||||||
|
self.status = ''
|
||||||
|
self.can_update = False
|
||||||
|
|
||||||
|
repo = None
|
||||||
|
try:
|
||||||
|
if os.path.exists(os.path.join(path, ".git")):
|
||||||
|
repo = git.Repo(path)
|
||||||
|
except Exception:
|
||||||
|
print(f"Error reading github repository info from {path}:", file=sys.stderr)
|
||||||
|
print(traceback.format_exc(), file=sys.stderr)
|
||||||
|
|
||||||
|
if repo is None or repo.bare:
|
||||||
|
self.remote = None
|
||||||
|
else:
|
||||||
|
self.remote = next(repo.remote().urls, None)
|
||||||
|
self.status = 'unknown'
|
||||||
|
|
||||||
|
def list_files(self, subdir, extension):
|
||||||
|
from modules import scripts
|
||||||
|
|
||||||
|
dirpath = os.path.join(self.path, subdir)
|
||||||
|
if not os.path.isdir(dirpath):
|
||||||
|
return []
|
||||||
|
|
||||||
|
res = []
|
||||||
|
for filename in sorted(os.listdir(dirpath)):
|
||||||
|
res.append(scripts.ScriptFile(self.path, filename, os.path.join(dirpath, filename)))
|
||||||
|
|
||||||
|
res = [x for x in res if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def check_updates(self):
|
||||||
|
repo = git.Repo(self.path)
|
||||||
|
for fetch in repo.remote().fetch("--dry-run"):
|
||||||
|
if fetch.flags != fetch.HEAD_UPTODATE:
|
||||||
|
self.can_update = True
|
||||||
|
self.status = "behind"
|
||||||
|
return
|
||||||
|
|
||||||
|
self.can_update = False
|
||||||
|
self.status = "latest"
|
||||||
|
|
||||||
|
def pull(self):
|
||||||
|
repo = git.Repo(self.path)
|
||||||
|
repo.remotes.origin.pull()
|
||||||
|
|
||||||
|
|
||||||
|
def list_extensions():
|
||||||
|
extensions.clear()
|
||||||
|
|
||||||
|
if not os.path.isdir(extensions_dir):
|
||||||
|
return
|
||||||
|
|
||||||
|
for dirname in sorted(os.listdir(extensions_dir)):
|
||||||
|
path = os.path.join(extensions_dir, dirname)
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
continue
|
||||||
|
|
||||||
|
extension = Extension(name=dirname, path=path, enabled=dirname not in shared.opts.disabled_extensions)
|
||||||
|
extensions.append(extension)
|
@ -17,6 +17,11 @@ paste_fields = {}
|
|||||||
bind_list = []
|
bind_list = []
|
||||||
|
|
||||||
|
|
||||||
|
def reset():
|
||||||
|
paste_fields.clear()
|
||||||
|
bind_list.clear()
|
||||||
|
|
||||||
|
|
||||||
def quote(text):
|
def quote(text):
|
||||||
if ',' not in str(text):
|
if ',' not in str(text):
|
||||||
return text
|
return text
|
||||||
|
@ -7,7 +7,7 @@ import modules.ui as ui
|
|||||||
import gradio as gr
|
import gradio as gr
|
||||||
|
|
||||||
from modules.processing import StableDiffusionProcessing
|
from modules.processing import StableDiffusionProcessing
|
||||||
from modules import shared, paths, script_callbacks
|
from modules import shared, paths, script_callbacks, extensions
|
||||||
|
|
||||||
AlwaysVisible = object()
|
AlwaysVisible = object()
|
||||||
|
|
||||||
@ -107,17 +107,8 @@ def list_scripts(scriptdirname, extension):
|
|||||||
for filename in sorted(os.listdir(basedir)):
|
for filename in sorted(os.listdir(basedir)):
|
||||||
scripts_list.append(ScriptFile(paths.script_path, filename, os.path.join(basedir, filename)))
|
scripts_list.append(ScriptFile(paths.script_path, filename, os.path.join(basedir, filename)))
|
||||||
|
|
||||||
extdir = os.path.join(paths.script_path, "extensions")
|
for ext in extensions.active():
|
||||||
if os.path.exists(extdir):
|
scripts_list += ext.list_files(scriptdirname, extension)
|
||||||
for dirname in sorted(os.listdir(extdir)):
|
|
||||||
dirpath = os.path.join(extdir, dirname)
|
|
||||||
scriptdirpath = os.path.join(dirpath, scriptdirname)
|
|
||||||
|
|
||||||
if not os.path.isdir(scriptdirpath):
|
|
||||||
continue
|
|
||||||
|
|
||||||
for filename in sorted(os.listdir(scriptdirpath)):
|
|
||||||
scripts_list.append(ScriptFile(dirpath, filename, os.path.join(scriptdirpath, filename)))
|
|
||||||
|
|
||||||
scripts_list = [x for x in scripts_list if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
|
scripts_list = [x for x in scripts_list if os.path.splitext(x.path)[1].lower() == extension and os.path.isfile(x.path)]
|
||||||
|
|
||||||
@ -127,11 +118,7 @@ def list_scripts(scriptdirname, extension):
|
|||||||
def list_files_with_name(filename):
|
def list_files_with_name(filename):
|
||||||
res = []
|
res = []
|
||||||
|
|
||||||
dirs = [paths.script_path]
|
dirs = [paths.script_path] + [ext.path for ext in extensions.active()]
|
||||||
|
|
||||||
extdir = os.path.join(paths.script_path, "extensions")
|
|
||||||
if os.path.exists(extdir):
|
|
||||||
dirs += [os.path.join(extdir, d) for d in sorted(os.listdir(extdir))]
|
|
||||||
|
|
||||||
for dirpath in dirs:
|
for dirpath in dirs:
|
||||||
if not os.path.isdir(dirpath):
|
if not os.path.isdir(dirpath):
|
||||||
|
@ -40,7 +40,7 @@ parser.add_argument("--lowram", action='store_true', help="load stable diffusion
|
|||||||
parser.add_argument("--always-batch-cond-uncond", action='store_true', help="disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram")
|
parser.add_argument("--always-batch-cond-uncond", action='store_true', help="disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram")
|
||||||
parser.add_argument("--unload-gfpgan", action='store_true', help="does not do anything.")
|
parser.add_argument("--unload-gfpgan", action='store_true', help="does not do anything.")
|
||||||
parser.add_argument("--precision", type=str, help="evaluate at this precision", choices=["full", "autocast"], default="autocast")
|
parser.add_argument("--precision", type=str, help="evaluate at this precision", choices=["full", "autocast"], default="autocast")
|
||||||
parser.add_argument("--share", action='store_true', help="use share=True for gradio and make the UI accessible through their site (doesn't work for me but you might have better luck)")
|
parser.add_argument("--share", action='store_true', help="use share=True for gradio and make the UI accessible through their site")
|
||||||
parser.add_argument("--ngrok", type=str, help="ngrok authtoken, alternative to gradio --share", default=None)
|
parser.add_argument("--ngrok", type=str, help="ngrok authtoken, alternative to gradio --share", default=None)
|
||||||
parser.add_argument("--ngrok-region", type=str, help="The region in which ngrok should start.", default="us")
|
parser.add_argument("--ngrok-region", type=str, help="The region in which ngrok should start.", default="us")
|
||||||
parser.add_argument("--codeformer-models-path", type=str, help="Path to directory with codeformer model file(s).", default=os.path.join(models_path, 'Codeformer'))
|
parser.add_argument("--codeformer-models-path", type=str, help="Path to directory with codeformer model file(s).", default=os.path.join(models_path, 'Codeformer'))
|
||||||
@ -97,6 +97,8 @@ restricted_opts = {
|
|||||||
"outdir_save",
|
"outdir_save",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd_opts.disable_extension_access = cmd_opts.share or cmd_opts.listen
|
||||||
|
|
||||||
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_swinir, devices.device_esrgan, devices.device_scunet, devices.device_codeformer = \
|
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_swinir, devices.device_esrgan, devices.device_scunet, devices.device_codeformer = \
|
||||||
(devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'swinir', 'esrgan', 'scunet', 'codeformer'])
|
(devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'swinir', 'esrgan', 'scunet', 'codeformer'])
|
||||||
|
|
||||||
@ -132,6 +134,7 @@ class State:
|
|||||||
current_image = None
|
current_image = None
|
||||||
current_image_sampling_step = 0
|
current_image_sampling_step = 0
|
||||||
textinfo = None
|
textinfo = None
|
||||||
|
need_restart = False
|
||||||
|
|
||||||
def skip(self):
|
def skip(self):
|
||||||
self.skipped = True
|
self.skipped = True
|
||||||
@ -354,6 +357,12 @@ options_templates.update(options_section(('sampler-params', "Sampler parameters"
|
|||||||
'eta_noise_seed_delta': OptionInfo(0, "Eta noise seed delta", gr.Number, {"precision": 0}),
|
'eta_noise_seed_delta': OptionInfo(0, "Eta noise seed delta", gr.Number, {"precision": 0}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
options_templates.update(options_section((None, "Hidden options"), {
|
||||||
|
"disabled_extensions": OptionInfo([], "Disable those extensions"),
|
||||||
|
}))
|
||||||
|
|
||||||
|
options_templates.update()
|
||||||
|
|
||||||
|
|
||||||
class Options:
|
class Options:
|
||||||
data = None
|
data = None
|
||||||
@ -365,8 +374,9 @@ class Options:
|
|||||||
|
|
||||||
def __setattr__(self, key, value):
|
def __setattr__(self, key, value):
|
||||||
if self.data is not None:
|
if self.data is not None:
|
||||||
if key in self.data:
|
if key in self.data or key in self.data_labels:
|
||||||
self.data[key] = value
|
self.data[key] = value
|
||||||
|
return
|
||||||
|
|
||||||
return super(Options, self).__setattr__(key, value)
|
return super(Options, self).__setattr__(key, value)
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import numpy as np
|
|||||||
from PIL import Image, PngImagePlugin
|
from PIL import Image, PngImagePlugin
|
||||||
|
|
||||||
|
|
||||||
from modules import sd_hijack, sd_models, localization, script_callbacks
|
from modules import sd_hijack, sd_models, localization, script_callbacks, ui_extensions
|
||||||
from modules.paths import script_path
|
from modules.paths import script_path
|
||||||
|
|
||||||
from modules.shared import opts, cmd_opts, restricted_opts
|
from modules.shared import opts, cmd_opts, restricted_opts
|
||||||
@ -671,6 +671,7 @@ def create_ui(wrap_gradio_gpu_call):
|
|||||||
import modules.img2img
|
import modules.img2img
|
||||||
import modules.txt2img
|
import modules.txt2img
|
||||||
|
|
||||||
|
parameters_copypaste.reset()
|
||||||
|
|
||||||
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
|
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
|
||||||
txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, _, txt2img_prompt_style_apply, txt2img_save_style, txt2img_paste, token_counter, token_button = create_toprow(is_img2img=False)
|
txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, _, txt2img_prompt_style_apply, txt2img_save_style, txt2img_paste, token_counter, token_button = create_toprow(is_img2img=False)
|
||||||
@ -1511,8 +1512,9 @@ def create_ui(wrap_gradio_gpu_call):
|
|||||||
column = None
|
column = None
|
||||||
with gr.Row(elem_id="settings").style(equal_height=False):
|
with gr.Row(elem_id="settings").style(equal_height=False):
|
||||||
for i, (k, item) in enumerate(opts.data_labels.items()):
|
for i, (k, item) in enumerate(opts.data_labels.items()):
|
||||||
|
section_must_be_skipped = item.section[0] is None
|
||||||
|
|
||||||
if previous_section != item.section:
|
if previous_section != item.section and not section_must_be_skipped:
|
||||||
if cols_displayed < settings_cols and (items_displayed >= items_per_col or previous_section is None):
|
if cols_displayed < settings_cols and (items_displayed >= items_per_col or previous_section is None):
|
||||||
if column is not None:
|
if column is not None:
|
||||||
column.__exit__()
|
column.__exit__()
|
||||||
@ -1531,6 +1533,8 @@ def create_ui(wrap_gradio_gpu_call):
|
|||||||
if k in quicksettings_names and not shared.cmd_opts.freeze_settings:
|
if k in quicksettings_names and not shared.cmd_opts.freeze_settings:
|
||||||
quicksettings_list.append((i, k, item))
|
quicksettings_list.append((i, k, item))
|
||||||
components.append(dummy_component)
|
components.append(dummy_component)
|
||||||
|
elif section_must_be_skipped:
|
||||||
|
components.append(dummy_component)
|
||||||
else:
|
else:
|
||||||
component = create_setting_component(k)
|
component = create_setting_component(k)
|
||||||
component_dict[k] = component
|
component_dict[k] = component
|
||||||
@ -1572,9 +1576,10 @@ def create_ui(wrap_gradio_gpu_call):
|
|||||||
|
|
||||||
def request_restart():
|
def request_restart():
|
||||||
shared.state.interrupt()
|
shared.state.interrupt()
|
||||||
settings_interface.gradio_ref.do_restart = True
|
shared.state.need_restart = True
|
||||||
|
|
||||||
restart_gradio.click(
|
restart_gradio.click(
|
||||||
|
|
||||||
fn=request_restart,
|
fn=request_restart,
|
||||||
inputs=[],
|
inputs=[],
|
||||||
outputs=[],
|
outputs=[],
|
||||||
@ -1612,14 +1617,15 @@ def create_ui(wrap_gradio_gpu_call):
|
|||||||
interfaces += script_callbacks.ui_tabs_callback()
|
interfaces += script_callbacks.ui_tabs_callback()
|
||||||
interfaces += [(settings_interface, "Settings", "settings")]
|
interfaces += [(settings_interface, "Settings", "settings")]
|
||||||
|
|
||||||
|
extensions_interface = ui_extensions.create_ui()
|
||||||
|
interfaces += [(extensions_interface, "Extensions", "extensions")]
|
||||||
|
|
||||||
with gr.Blocks(css=css, analytics_enabled=False, title="Stable Diffusion") as demo:
|
with gr.Blocks(css=css, analytics_enabled=False, title="Stable Diffusion") as demo:
|
||||||
with gr.Row(elem_id="quicksettings"):
|
with gr.Row(elem_id="quicksettings"):
|
||||||
for i, k, item in quicksettings_list:
|
for i, k, item in quicksettings_list:
|
||||||
component = create_setting_component(k, is_quicksettings=True)
|
component = create_setting_component(k, is_quicksettings=True)
|
||||||
component_dict[k] = component
|
component_dict[k] = component
|
||||||
|
|
||||||
settings_interface.gradio_ref = demo
|
|
||||||
|
|
||||||
parameters_copypaste.integrate_settings_paste_fields(component_dict)
|
parameters_copypaste.integrate_settings_paste_fields(component_dict)
|
||||||
parameters_copypaste.run_bind()
|
parameters_copypaste.run_bind()
|
||||||
|
|
||||||
|
172
modules/ui_extensions.py
Normal file
172
modules/ui_extensions.py
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import git
|
||||||
|
|
||||||
|
import gradio as gr
|
||||||
|
import html
|
||||||
|
|
||||||
|
from modules import extensions, shared, paths
|
||||||
|
|
||||||
|
|
||||||
|
def check_access():
|
||||||
|
assert not shared.cmd_opts.disable_extension_access, "extension access disabed because of commandline flags"
|
||||||
|
|
||||||
|
|
||||||
|
def apply_and_restart(disable_list, update_list):
|
||||||
|
check_access()
|
||||||
|
|
||||||
|
disabled = json.loads(disable_list)
|
||||||
|
assert type(disabled) == list, f"wrong disable_list data for apply_and_restart: {disable_list}"
|
||||||
|
|
||||||
|
update = json.loads(update_list)
|
||||||
|
assert type(update) == list, f"wrong update_list data for apply_and_restart: {update_list}"
|
||||||
|
|
||||||
|
update = set(update)
|
||||||
|
|
||||||
|
for ext in extensions.extensions:
|
||||||
|
if ext.name not in update:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
ext.pull()
|
||||||
|
except Exception:
|
||||||
|
print(f"Error pulling updates for {ext.name}:", file=sys.stderr)
|
||||||
|
print(traceback.format_exc(), file=sys.stderr)
|
||||||
|
|
||||||
|
shared.opts.disabled_extensions = disabled
|
||||||
|
shared.opts.save(shared.config_filename)
|
||||||
|
|
||||||
|
shared.state.interrupt()
|
||||||
|
shared.state.need_restart = True
|
||||||
|
|
||||||
|
|
||||||
|
def check_updates():
|
||||||
|
check_access()
|
||||||
|
|
||||||
|
for ext in extensions.extensions:
|
||||||
|
if ext.remote is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
ext.check_updates()
|
||||||
|
except Exception:
|
||||||
|
print(f"Error checking updates for {ext.name}:", file=sys.stderr)
|
||||||
|
print(traceback.format_exc(), file=sys.stderr)
|
||||||
|
|
||||||
|
return extension_table()
|
||||||
|
|
||||||
|
|
||||||
|
def extension_table():
|
||||||
|
code = f"""<!-- {time.time()} -->
|
||||||
|
<table id="extensions">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><abbr title="Use checkbox to enable the extension; it will be enabled or disabled when you click apply button">Extension</abbr></th>
|
||||||
|
<th>URL</th>
|
||||||
|
<th><abbr title="Use checkbox to mark the extension for update; it will be updated when you click apply button">Update</abbr></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
"""
|
||||||
|
|
||||||
|
for ext in extensions.extensions:
|
||||||
|
if ext.can_update:
|
||||||
|
ext_status = f"""<label><input class="gr-check-radio gr-checkbox" name="update_{html.escape(ext.name)}" checked="checked" type="checkbox">{html.escape(ext.status)}</label>"""
|
||||||
|
else:
|
||||||
|
ext_status = ext.status
|
||||||
|
|
||||||
|
code += f"""
|
||||||
|
<tr>
|
||||||
|
<td><label><input class="gr-check-radio gr-checkbox" name="enable_{html.escape(ext.name)}" type="checkbox" {'checked="checked"' if ext.enabled else ''}>{html.escape(ext.name)}</label></td>
|
||||||
|
<td><a href="{html.escape(ext.remote or '')}">{html.escape(ext.remote or '')}</a></td>
|
||||||
|
<td{' class="extension_status"' if ext.remote is not None else ''}>{ext_status}</td>
|
||||||
|
</tr>
|
||||||
|
"""
|
||||||
|
|
||||||
|
code += """
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
"""
|
||||||
|
|
||||||
|
return code
|
||||||
|
|
||||||
|
|
||||||
|
def install_extension_from_url(dirname, url):
|
||||||
|
check_access()
|
||||||
|
|
||||||
|
assert url, 'No URL specified'
|
||||||
|
|
||||||
|
if dirname is None or dirname == "":
|
||||||
|
*parts, last_part = url.split('/')
|
||||||
|
last_part = last_part.replace(".git", "")
|
||||||
|
|
||||||
|
dirname = last_part
|
||||||
|
|
||||||
|
target_dir = os.path.join(extensions.extensions_dir, dirname)
|
||||||
|
assert not os.path.exists(target_dir), f'Extension directory already exists: {target_dir}'
|
||||||
|
|
||||||
|
assert len([x for x in extensions.extensions if x.remote == url]) == 0, 'Extension with this URL is already installed'
|
||||||
|
|
||||||
|
tmpdir = os.path.join(paths.script_path, "tmp", dirname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
shutil.rmtree(tmpdir, True)
|
||||||
|
|
||||||
|
repo = git.Repo.clone_from(url, tmpdir)
|
||||||
|
repo.remote().fetch()
|
||||||
|
|
||||||
|
os.rename(tmpdir, target_dir)
|
||||||
|
|
||||||
|
extensions.list_extensions()
|
||||||
|
return [extension_table(), html.escape(f"Installed into {target_dir}. Use Installed tab to restart.")]
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir, True)
|
||||||
|
|
||||||
|
|
||||||
|
def create_ui():
|
||||||
|
import modules.ui
|
||||||
|
|
||||||
|
with gr.Blocks(analytics_enabled=False) as ui:
|
||||||
|
with gr.Tabs(elem_id="tabs_extensions") as tabs:
|
||||||
|
with gr.TabItem("Installed"):
|
||||||
|
extensions_disabled_list = gr.Text(elem_id="extensions_disabled_list", visible=False)
|
||||||
|
extensions_update_list = gr.Text(elem_id="extensions_update_list", visible=False)
|
||||||
|
|
||||||
|
with gr.Row():
|
||||||
|
apply = gr.Button(value="Apply and restart UI", variant="primary")
|
||||||
|
check = gr.Button(value="Check for updates")
|
||||||
|
|
||||||
|
extensions_table = gr.HTML(lambda: extension_table())
|
||||||
|
|
||||||
|
apply.click(
|
||||||
|
fn=apply_and_restart,
|
||||||
|
_js="extensions_apply",
|
||||||
|
inputs=[extensions_disabled_list, extensions_update_list],
|
||||||
|
outputs=[],
|
||||||
|
)
|
||||||
|
|
||||||
|
check.click(
|
||||||
|
fn=check_updates,
|
||||||
|
_js="extensions_check",
|
||||||
|
inputs=[],
|
||||||
|
outputs=[extensions_table],
|
||||||
|
)
|
||||||
|
|
||||||
|
with gr.TabItem("Install from URL"):
|
||||||
|
install_url = gr.Text(label="URL for extension's git repository")
|
||||||
|
install_dirname = gr.Text(label="Local directory name", placeholder="Leave empty for auto")
|
||||||
|
intall_button = gr.Button(value="Install", variant="primary")
|
||||||
|
intall_result = gr.HTML(elem_id="extension_install_result")
|
||||||
|
|
||||||
|
intall_button.click(
|
||||||
|
fn=modules.ui.wrap_gradio_call(install_extension_from_url, extra_outputs=[gr.update()]),
|
||||||
|
inputs=[install_dirname, install_url],
|
||||||
|
outputs=[extensions_table, intall_result],
|
||||||
|
)
|
||||||
|
|
||||||
|
return ui
|
@ -26,3 +26,4 @@ torchdiffeq
|
|||||||
kornia
|
kornia
|
||||||
lark
|
lark
|
||||||
inflection
|
inflection
|
||||||
|
GitPython
|
||||||
|
@ -23,3 +23,4 @@ torchdiffeq==0.2.3
|
|||||||
kornia==0.6.7
|
kornia==0.6.7
|
||||||
lark==1.1.2
|
lark==1.1.2
|
||||||
inflection==0.5.1
|
inflection==0.5.1
|
||||||
|
GitPython==3.1.27
|
||||||
|
20
style.css
20
style.css
@ -530,6 +530,26 @@ img2maskimg, #img2maskimg > .h-60, #img2maskimg > .h-60 > div, #img2maskimg > .h
|
|||||||
min-height: 480px !important;
|
min-height: 480px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extensions */
|
||||||
|
|
||||||
|
#extensions{
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
#extensions td, #extensions th{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#extensions input[type="checkbox"]{
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab_extensions button{
|
||||||
|
max-width: 16em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The following handles localization for right-to-left (RTL) languages like Arabic.
|
/* The following handles localization for right-to-left (RTL) languages like Arabic.
|
||||||
The rtl media type will only be activated by the logic in javascript/localization.js.
|
The rtl media type will only be activated by the logic in javascript/localization.js.
|
||||||
If you change anything above, you need to make sure it is RTL compliant by just running
|
If you change anything above, you need to make sure it is RTL compliant by just running
|
||||||
|
17
webui.py
17
webui.py
@ -9,7 +9,7 @@ from fastapi.middleware.gzip import GZipMiddleware
|
|||||||
|
|
||||||
from modules.paths import script_path
|
from modules.paths import script_path
|
||||||
|
|
||||||
from modules import devices, sd_samplers, upscaler
|
from modules import devices, sd_samplers, upscaler, extensions
|
||||||
import modules.codeformer_model as codeformer
|
import modules.codeformer_model as codeformer
|
||||||
import modules.extras
|
import modules.extras
|
||||||
import modules.face_restoration
|
import modules.face_restoration
|
||||||
@ -60,6 +60,8 @@ def wrap_gradio_gpu_call(func, extra_outputs=None):
|
|||||||
|
|
||||||
|
|
||||||
def initialize():
|
def initialize():
|
||||||
|
extensions.list_extensions()
|
||||||
|
|
||||||
if cmd_opts.ui_debug_mode:
|
if cmd_opts.ui_debug_mode:
|
||||||
shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
|
shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
|
||||||
modules.scripts.load_scripts()
|
modules.scripts.load_scripts()
|
||||||
@ -92,15 +94,18 @@ def create_api(app):
|
|||||||
api = Api(app, queue_lock)
|
api = Api(app, queue_lock)
|
||||||
return api
|
return api
|
||||||
|
|
||||||
|
|
||||||
def wait_on_server(demo=None):
|
def wait_on_server(demo=None):
|
||||||
while 1:
|
while 1:
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
if demo and getattr(demo, 'do_restart', False):
|
if shared.state.need_restart:
|
||||||
|
shared.state.need_restart = False
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
demo.close()
|
demo.close()
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
def api_only():
|
def api_only():
|
||||||
initialize()
|
initialize()
|
||||||
|
|
||||||
@ -132,14 +137,16 @@ def webui():
|
|||||||
|
|
||||||
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||||
|
|
||||||
if (launch_api):
|
if launch_api:
|
||||||
create_api(app)
|
create_api(app)
|
||||||
|
|
||||||
wait_on_server(demo)
|
wait_on_server(demo)
|
||||||
|
|
||||||
sd_samplers.set_samplers()
|
sd_samplers.set_samplers()
|
||||||
|
|
||||||
print('Reloading Custom Scripts')
|
print('Reloading extensions')
|
||||||
|
extensions.list_extensions()
|
||||||
|
print('Reloading custom scripts')
|
||||||
modules.scripts.reload_scripts()
|
modules.scripts.reload_scripts()
|
||||||
print('Reloading modules: modules.ui')
|
print('Reloading modules: modules.ui')
|
||||||
importlib.reload(modules.ui)
|
importlib.reload(modules.ui)
|
||||||
@ -148,8 +155,6 @@ def webui():
|
|||||||
print('Restarting Gradio')
|
print('Restarting Gradio')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
task = []
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if cmd_opts.nowebui:
|
if cmd_opts.nowebui:
|
||||||
api_only()
|
api_only()
|
||||||
|
Loading…
Reference in New Issue
Block a user