Maintenance tab, #57
parent
7eaa53ff32
commit
4cbcd1de17
|
|
@ -17,6 +17,7 @@ and restart your stable-diffusion-webui, then you can see the new tab "Image Bro
|
||||||
Please be aware that when scanning a directory for the first time, the png-cache will be built. This can take several minutes, depending on the amount of images.
|
Please be aware that when scanning a directory for the first time, the png-cache will be built. This can take several minutes, depending on the amount of images.
|
||||||
|
|
||||||
## Recent updates
|
## Recent updates
|
||||||
|
- Maintenance tab
|
||||||
- Custom tabs
|
- Custom tabs
|
||||||
- Copy/Move to directory
|
- Copy/Move to directory
|
||||||
- Keybindings
|
- Keybindings
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import gradio as gr
|
||||||
import csv
|
import csv
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
|
||||||
import platform
|
import platform
|
||||||
|
import random
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
|
|
@ -38,10 +38,15 @@ yappi_do = False
|
||||||
favorite_tab_name = "Favorites"
|
favorite_tab_name = "Favorites"
|
||||||
default_tab_options = ["txt2img", "img2img", "txt2img-grids", "img2img-grids", "Extras", favorite_tab_name, "Others"]
|
default_tab_options = ["txt2img", "img2img", "txt2img-grids", "img2img-grids", "Extras", favorite_tab_name, "Others"]
|
||||||
tabs_list = [tab.strip() for tab in chain.from_iterable(csv.reader(StringIO(opts.image_browser_active_tabs))) if tab] if hasattr(opts, "image_browser_active_tabs") else default_tab_options
|
tabs_list = [tab.strip() for tab in chain.from_iterable(csv.reader(StringIO(opts.image_browser_active_tabs))) if tab] if hasattr(opts, "image_browser_active_tabs") else default_tab_options
|
||||||
|
try:
|
||||||
|
if opts.image_browser_enable_maint:
|
||||||
|
tabs_list.append("Maintenance") # mandatory tab
|
||||||
|
except AttributeError:
|
||||||
|
tabs_list.append("Maintenance") # mandatory tab
|
||||||
|
|
||||||
num_of_imgs_per_page = 0
|
num_of_imgs_per_page = 0
|
||||||
loads_files_num = 0
|
loads_files_num = 0
|
||||||
image_ext_list = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp"]
|
image_ext_list = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp"]
|
||||||
cur_ranking_value="0"
|
|
||||||
finfo_aes = {}
|
finfo_aes = {}
|
||||||
exif_cache = {}
|
exif_cache = {}
|
||||||
finfo_exif = {}
|
finfo_exif = {}
|
||||||
|
|
@ -50,7 +55,7 @@ none_select = "Nothing selected"
|
||||||
refresh_symbol = '\U0001f504' # 🔄
|
refresh_symbol = '\U0001f504' # 🔄
|
||||||
up_symbol = '\U000025b2' # ▲
|
up_symbol = '\U000025b2' # ▲
|
||||||
down_symbol = '\U000025bc' # ▼
|
down_symbol = '\U000025bc' # ▼
|
||||||
rebuild_symbol = '\U0001f50e\U0001f4c2' # 🔎📂
|
caution_symbol = '\U000026a0' # ⚠
|
||||||
current_depth = 0
|
current_depth = 0
|
||||||
init = True
|
init = True
|
||||||
copy_move = ["Move", "Copy"]
|
copy_move = ["Move", "Copy"]
|
||||||
|
|
@ -71,13 +76,13 @@ class ImageBrowserTab():
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
self.name: str = os.path.basename(name) if os.path.isdir(name) else name
|
self.name: str = os.path.basename(name) if os.path.isdir(name) else name
|
||||||
self.path: str = path_maps.get(name, name)
|
self.path: str = os.path.abspath(path_maps.get(name, name))
|
||||||
self.base_tag: str = f"image_browser_tab_{self.get_unique_base_tag(self.remove_invalid_html_tag_chars(self.name).lower())}"
|
self.base_tag: str = f"image_browser_tab_{self.get_unique_base_tag(self.remove_invalid_html_tag_chars(self.name).lower())}"
|
||||||
|
|
||||||
def remove_invalid_html_tag_chars(self, tag: str) -> str:
|
def remove_invalid_html_tag_chars(self, tag: str) -> str:
|
||||||
# Matches any character that is not a letter, a digit, a hyphen, or an underscore
|
# Removes any character that is not a letter, a digit, a hyphen, or an underscore
|
||||||
pattern = re.compile(r'[^a-zA-Z0-9\-_]')
|
removed = re.sub(r'[^a-zA-Z0-9\-_]', '', tag)
|
||||||
return re.sub(pattern, '', tag)
|
return removed
|
||||||
|
|
||||||
def get_unique_base_tag(self, base_tag: str) -> str:
|
def get_unique_base_tag(self, base_tag: str) -> str:
|
||||||
counter = 1
|
counter = 1
|
||||||
|
|
@ -147,6 +152,7 @@ def img_path_subdirs_get(img_path):
|
||||||
return gr.update(choices=subdirs)
|
return gr.update(choices=subdirs)
|
||||||
|
|
||||||
def img_path_add_remove(img_dir, path_recorder, add_remove, img_path_depth):
|
def img_path_add_remove(img_dir, path_recorder, add_remove, img_path_depth):
|
||||||
|
img_dir = os.path.abspath(img_dir)
|
||||||
if add_remove == "add" or (add_remove == "remove" and img_dir in path_recorder):
|
if add_remove == "add" or (add_remove == "remove" and img_dir in path_recorder):
|
||||||
if add_remove == "add":
|
if add_remove == "add":
|
||||||
path_recorder[img_dir] = {
|
path_recorder[img_dir] = {
|
||||||
|
|
@ -173,7 +179,7 @@ def sort_order_flip(turn_page_switch, sort_order):
|
||||||
sort_order = up_symbol
|
sort_order = up_symbol
|
||||||
return 1, -turn_page_switch, sort_order
|
return 1, -turn_page_switch, sort_order
|
||||||
|
|
||||||
def read_path_recorder(path_recorder):
|
def read_path_recorder():
|
||||||
path_recorder = wib_db.load_path_recorder()
|
path_recorder = wib_db.load_path_recorder()
|
||||||
path_recorder_formatted = [value.get("path_display") for key, value in path_recorder.items()]
|
path_recorder_formatted = [value.get("path_display") for key, value in path_recorder.items()]
|
||||||
path_recorder_formatted = sorted(path_recorder_formatted, key=lambda x: natural_keys(x.lower()))
|
path_recorder_formatted = sorted(path_recorder_formatted, key=lambda x: natural_keys(x.lower()))
|
||||||
|
|
@ -191,6 +197,7 @@ def pure_path(path):
|
||||||
depth = int(match.group(1))
|
depth = int(match.group(1))
|
||||||
else:
|
else:
|
||||||
depth = 0
|
depth = 0
|
||||||
|
path = os.path.abspath(path)
|
||||||
return path, depth
|
return path, depth
|
||||||
|
|
||||||
def browser2path(img_path_browser):
|
def browser2path(img_path_browser):
|
||||||
|
|
@ -203,8 +210,8 @@ def totxt(file):
|
||||||
|
|
||||||
return file_txt
|
return file_txt
|
||||||
|
|
||||||
def tab_select(path_recorder):
|
def tab_select():
|
||||||
path_recorder, path_recorder_formatted, path_recorder_unformatted = read_path_recorder(path_recorder)
|
path_recorder, path_recorder_formatted, path_recorder_unformatted = read_path_recorder()
|
||||||
return path_recorder, gr.update(choices=path_recorder_unformatted)
|
return path_recorder, gr.update(choices=path_recorder_unformatted)
|
||||||
|
|
||||||
def reduplicative_file_move(src, dst):
|
def reduplicative_file_move(src, dst):
|
||||||
|
|
@ -417,10 +424,10 @@ def cache_exif(fileinfos):
|
||||||
cache_exif_end = time.time()
|
cache_exif_end = time.time()
|
||||||
logger.debug(f"cache_exif: {new_exif}/{len(fileinfos)} cache_aes: {new_aes}/{len(fileinfos)} {round(cache_exif_end - cache_exif_start, 1)} seconds")
|
logger.debug(f"cache_exif: {new_exif}/{len(fileinfos)} cache_aes: {new_aes}/{len(fileinfos)} {round(cache_exif_end - cache_exif_start, 1)} seconds")
|
||||||
|
|
||||||
def exif_rebuild(exif_rebuild_button):
|
def exif_rebuild(maint_wait):
|
||||||
global finfo_exif, exif_cache, finfo_aes, aes_cache
|
global finfo_exif, exif_cache, finfo_aes, aes_cache
|
||||||
if opts.image_browser_scan_exif:
|
if opts.image_browser_scan_exif:
|
||||||
print("Rebuild start")
|
logger.debug("Rebuild start")
|
||||||
exif_dirs = wib_db.get_exif_dirs()
|
exif_dirs = wib_db.get_exif_dirs()
|
||||||
finfo_aes = {}
|
finfo_aes = {}
|
||||||
exif_cache = {}
|
exif_cache = {}
|
||||||
|
|
@ -431,9 +438,37 @@ def exif_rebuild(exif_rebuild_button):
|
||||||
print(f"Rebuilding {key}")
|
print(f"Rebuilding {key}")
|
||||||
fileinfos = traverse_all_files(key, [], "", 0)
|
fileinfos = traverse_all_files(key, [], "", 0)
|
||||||
cache_exif(fileinfos)
|
cache_exif(fileinfos)
|
||||||
print("Rebuild end")
|
logger.debug("Rebuild end")
|
||||||
|
maint_last_msg = "Rebuild finished"
|
||||||
|
else:
|
||||||
|
maint_last_msg = "Exif cache not enabled in settings"
|
||||||
|
|
||||||
return exif_rebuild_button
|
return maint_wait, maint_last_msg
|
||||||
|
|
||||||
|
def exif_update_dirs(maint_update_dirs_from, maint_update_dirs_to, maint_wait):
|
||||||
|
global exif_cache, aes_cache
|
||||||
|
if maint_update_dirs_from == "":
|
||||||
|
maint_last_msg = "From is empty"
|
||||||
|
elif maint_update_dirs_to == "":
|
||||||
|
maint_last_msg = "To is empty"
|
||||||
|
else:
|
||||||
|
maint_update_dirs_from = os.path.abspath(maint_update_dirs_from)
|
||||||
|
maint_update_dirs_to = os.path.abspath(maint_update_dirs_to)
|
||||||
|
rows = 0
|
||||||
|
conn, cursor = wib_db.transaction_begin()
|
||||||
|
wib_db.update_path_recorder_mult(cursor, maint_update_dirs_from, maint_update_dirs_to)
|
||||||
|
rows = rows + cursor.rowcount
|
||||||
|
wib_db.update_exif_data_mult(cursor, maint_update_dirs_from, maint_update_dirs_to)
|
||||||
|
rows = rows + cursor.rowcount
|
||||||
|
wib_db.update_ranking_mult(cursor, maint_update_dirs_from, maint_update_dirs_to)
|
||||||
|
rows = rows + cursor.rowcount
|
||||||
|
wib_db.transaction_end(conn, cursor)
|
||||||
|
if rows == 0:
|
||||||
|
maint_last_msg = "No rows updated"
|
||||||
|
else:
|
||||||
|
maint_last_msg = f"{rows} rows updated. Please reload UI!"
|
||||||
|
|
||||||
|
return maint_wait, maint_last_msg
|
||||||
|
|
||||||
def atof(text):
|
def atof(text):
|
||||||
try:
|
try:
|
||||||
|
|
@ -633,24 +668,31 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
global init, exif_cache, aes_cache
|
global init, exif_cache, aes_cache
|
||||||
dir_name = None
|
dir_name = None
|
||||||
others_dir = False
|
others_dir = False
|
||||||
|
maint = False
|
||||||
|
standard_ui = True
|
||||||
path_recorder = {}
|
path_recorder = {}
|
||||||
path_recorder_formatted = []
|
path_recorder_formatted = []
|
||||||
path_recorder_unformatted = []
|
path_recorder_unformatted = []
|
||||||
|
|
||||||
if init:
|
if init:
|
||||||
wib_db.check()
|
db_version = wib_db.check()
|
||||||
|
logger.debug(f"db_version: {db_version}")
|
||||||
exif_cache = wib_db.load_exif_data(exif_cache)
|
exif_cache = wib_db.load_exif_data(exif_cache)
|
||||||
aes_cache = wib_db.load_aes_data(aes_cache)
|
aes_cache = wib_db.load_aes_data(aes_cache)
|
||||||
init = False
|
init = False
|
||||||
|
|
||||||
path_recorder, path_recorder_formatted, path_recorder_unformatted = read_path_recorder(path_recorder)
|
path_recorder, path_recorder_formatted, path_recorder_unformatted = read_path_recorder()
|
||||||
|
|
||||||
if tab.name == "Others":
|
if tab.name == "Others":
|
||||||
others_dir = True
|
others_dir = True
|
||||||
|
standard_ui = False
|
||||||
|
elif tab.name == "Maintenance":
|
||||||
|
maint = True
|
||||||
|
standard_ui = False
|
||||||
else:
|
else:
|
||||||
dir_name = tab.path
|
dir_name = tab.path
|
||||||
|
|
||||||
if not others_dir:
|
if standard_ui:
|
||||||
dir_name = str(Path(dir_name))
|
dir_name = str(Path(dir_name))
|
||||||
if not os.path.exists(dir_name):
|
if not os.path.exists(dir_name):
|
||||||
os.makedirs(dir_name)
|
os.makedirs(dir_name)
|
||||||
|
|
@ -681,14 +723,8 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
img_path_subdirs = gr.Dropdown(choices=[none_select], value=none_select, label="Sub directories", interactive=True, elem_id=f"{tab.base_tag}_img_path_subdirs")
|
img_path_subdirs = gr.Dropdown(choices=[none_select], value=none_select, label="Sub directories", interactive=True, elem_id=f"{tab.base_tag}_img_path_subdirs")
|
||||||
with gr.Column(scale=1):
|
with gr.Column(scale=1):
|
||||||
img_path_subdirs_button = gr.Button(value="Get sub directories")
|
img_path_subdirs_button = gr.Button(value="Get sub directories")
|
||||||
|
|
||||||
with gr.Row(visible=others_dir):
|
with gr.Row(visible=standard_ui, elem_id=f"{tab.base_tag}_image_browser") as main_panel:
|
||||||
with gr.Column(scale=10):
|
|
||||||
gr.Dropdown(visible=False)
|
|
||||||
with gr.Column(scale=1):
|
|
||||||
exif_rebuild_button = gr.Button(value=f"{rebuild_symbol} Rebuild exif cache")
|
|
||||||
|
|
||||||
with gr.Row(visible=not others_dir, elem_id=f"{tab.base_tag}_image_browser") as main_panel:
|
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
with gr.Column(scale=2):
|
with gr.Column(scale=2):
|
||||||
|
|
@ -774,6 +810,34 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
mod_keys = f"{mod_keys}S"
|
mod_keys = f"{mod_keys}S"
|
||||||
image_browser_mod_keys = gr.Textbox(value=mod_keys, elem_id=f"{tab.base_tag}_image_browser_mod_keys")
|
image_browser_mod_keys = gr.Textbox(value=mod_keys, elem_id=f"{tab.base_tag}_image_browser_mod_keys")
|
||||||
|
|
||||||
|
# Maintenance tab
|
||||||
|
with gr.Row(visible=maint):
|
||||||
|
with gr.Column(scale=4):
|
||||||
|
gr.HTML(f"{caution_symbol} Caution: You should only use these options if you know what you are doing. {caution_symbol}")
|
||||||
|
with gr.Column(scale=3):
|
||||||
|
maint_wait = gr.HTML("Status:")
|
||||||
|
with gr.Column(scale=7):
|
||||||
|
gr.HTML(" ")
|
||||||
|
with gr.Row(visible=maint):
|
||||||
|
maint_last_msg = gr.Textbox(label="Last message", interactive=False)
|
||||||
|
with gr.Row(visible=maint):
|
||||||
|
with gr.Column(scale=1):
|
||||||
|
maint_rebuild = gr.Button(value="Rebuild exif cache")
|
||||||
|
with gr.Column(scale=10):
|
||||||
|
gr.HTML(visible=False)
|
||||||
|
with gr.Row(visible=maint):
|
||||||
|
with gr.Column(scale=1):
|
||||||
|
maint_update_dirs = gr.Button(value="Update directory names in database")
|
||||||
|
with gr.Column(scale=10):
|
||||||
|
maint_update_dirs_from = gr.Textbox(label="From (full path)")
|
||||||
|
with gr.Column(scale=10):
|
||||||
|
maint_update_dirs_to = gr.Textbox(label="to (full path)")
|
||||||
|
with gr.Row(visible=False):
|
||||||
|
with gr.Column(scale=1):
|
||||||
|
maint_rebuild_ranking = gr.Button(value="Rebuild ranking from exif info")
|
||||||
|
with gr.Column(scale=10):
|
||||||
|
gr.HTML(visible=False)
|
||||||
|
|
||||||
change_dir_outputs = [warning_box, main_panel, img_path_browser, path_recorder, load_switch, img_path, img_path_depth]
|
change_dir_outputs = [warning_box, main_panel, img_path_browser, path_recorder, load_switch, img_path, img_path_depth]
|
||||||
img_path.submit(change_dir, inputs=[img_path, path_recorder, load_switch, img_path_browser, img_path_depth, img_path], outputs=change_dir_outputs)
|
img_path.submit(change_dir, inputs=[img_path, path_recorder, load_switch, img_path_browser, img_path_depth, img_path], outputs=change_dir_outputs)
|
||||||
img_path_browser.change(change_dir, inputs=[img_path_browser, path_recorder, load_switch, img_path_browser, img_path_depth, img_path], outputs=change_dir_outputs)
|
img_path_browser.change(change_dir, inputs=[img_path_browser, path_recorder, load_switch, img_path_browser, img_path_depth, img_path], outputs=change_dir_outputs)
|
||||||
|
|
@ -841,10 +905,17 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
inputs=[img_path, path_recorder, img_path_remove, img_path_depth],
|
inputs=[img_path, path_recorder, img_path_remove, img_path_depth],
|
||||||
outputs=[path_recorder, img_path_browser]
|
outputs=[path_recorder, img_path_browser]
|
||||||
)
|
)
|
||||||
exif_rebuild_button.click(
|
maint_rebuild.click(
|
||||||
fn=exif_rebuild,
|
fn=exif_rebuild,
|
||||||
inputs=[exif_rebuild_button],
|
show_progress=True,
|
||||||
outputs=[exif_rebuild_button]
|
inputs=[maint_wait],
|
||||||
|
outputs=[maint_wait, maint_last_msg]
|
||||||
|
)
|
||||||
|
maint_update_dirs.click(
|
||||||
|
fn=exif_update_dirs,
|
||||||
|
show_progress=True,
|
||||||
|
inputs=[maint_update_dirs_from, maint_update_dirs_to, maint_wait],
|
||||||
|
outputs=[maint_wait, maint_last_msg]
|
||||||
)
|
)
|
||||||
|
|
||||||
# other functions
|
# other functions
|
||||||
|
|
@ -865,10 +936,10 @@ def create_tab(tab: ImageBrowserTab, current_gr_tab: gr.Tab):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not others_dir:
|
if standard_ui:
|
||||||
current_gr_tab.select(
|
current_gr_tab.select(
|
||||||
fn=tab_select,
|
fn=tab_select,
|
||||||
inputs=[path_recorder],
|
inputs=[],
|
||||||
outputs=[path_recorder, to_dir_saved]
|
outputs=[path_recorder, to_dir_saved]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -949,6 +1020,8 @@ def on_ui_settings():
|
||||||
image_browser_options.append(("image_browser_scan_exif", True, "Scan Exif-/.txt-data (slower, but required for exif-keyword-search)", "images_scan_exif"))
|
image_browser_options.append(("image_browser_scan_exif", True, "Scan Exif-/.txt-data (slower, but required for exif-keyword-search)", "images_scan_exif"))
|
||||||
image_browser_options.append(("image_browser_mod_shift", False, "Change CTRL keybindings to SHIFT", None))
|
image_browser_options.append(("image_browser_mod_shift", False, "Change CTRL keybindings to SHIFT", None))
|
||||||
image_browser_options.append(("image_browser_mod_ctrl_shift", False, "or to CTRL+SHIFT", None))
|
image_browser_options.append(("image_browser_mod_ctrl_shift", False, "or to CTRL+SHIFT", None))
|
||||||
|
#image_browser_options.append(("image_browser_ranking_pnginfo", False, "Save ranking in image's pnginfo", None))
|
||||||
|
image_browser_options.append(("image_browser_enable_maint", True, "Enable Maintenance tab", None))
|
||||||
|
|
||||||
image_browser_options.append(("image_browser_page_columns", 6, "Number of columns on the page", "images_history_page_columns"))
|
image_browser_options.append(("image_browser_page_columns", 6, "Number of columns on the page", "images_history_page_columns"))
|
||||||
image_browser_options.append(("image_browser_page_rows", 6, "Number of rows on the page", "images_history_page_rows"))
|
image_browser_options.append(("image_browser_page_rows", 6, "Number of rows on the page", "images_history_page_rows"))
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import os
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from modules import scripts
|
from modules import scripts
|
||||||
|
|
||||||
|
version = 2
|
||||||
|
|
||||||
path_recorder_file = os.path.join(scripts.basedir(), "path_recorder.txt")
|
path_recorder_file = os.path.join(scripts.basedir(), "path_recorder.txt")
|
||||||
aes_cache_file = os.path.join(scripts.basedir(), "aes_scores.json")
|
aes_cache_file = os.path.join(scripts.basedir(), "aes_scores.json")
|
||||||
exif_cache_file = os.path.join(scripts.basedir(), "exif_data.json")
|
exif_cache_file = os.path.join(scripts.basedir(), "exif_data.json")
|
||||||
|
|
@ -65,12 +67,17 @@ def create_db(cursor):
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS ranking (
|
CREATE TABLE IF NOT EXISTS ranking (
|
||||||
file TEXT PRIMARY KEY,
|
file TEXT PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
ranking TEXT,
|
ranking TEXT,
|
||||||
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE INDEX IF NOT EXISTS ranking_name ON ranking (name)
|
||||||
|
''')
|
||||||
|
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
CREATE TRIGGER ranking_tr
|
CREATE TRIGGER ranking_tr
|
||||||
AFTER UPDATE ON ranking
|
AFTER UPDATE ON ranking
|
||||||
|
|
@ -88,8 +95,9 @@ def migrate_path_recorder(cursor):
|
||||||
# json-version
|
# json-version
|
||||||
path_recorder = json.load(f)
|
path_recorder = json.load(f)
|
||||||
for path, values in path_recorder.items():
|
for path, values in path_recorder.items():
|
||||||
|
path = os.path.abspath(path)
|
||||||
depth = values["depth"]
|
depth = values["depth"]
|
||||||
path_display = values["path_display"]
|
path_display = f"{path} [{depth}]"
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
INSERT INTO path_recorder (path, depth, path_display)
|
INSERT INTO path_recorder (path, depth, path_display)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
|
|
@ -99,6 +107,7 @@ def migrate_path_recorder(cursor):
|
||||||
# old txt-version
|
# old txt-version
|
||||||
path = f.readline().rstrip("\n")
|
path = f.readline().rstrip("\n")
|
||||||
while len(path) > 0:
|
while len(path) > 0:
|
||||||
|
path = os.path.abspath(path)
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
INSERT INTO path_recorder (path, depth, path_display)
|
INSERT INTO path_recorder (path, depth, path_display)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
|
|
@ -180,10 +189,10 @@ def update_exif_data(cursor, file, info):
|
||||||
def migrate_exif_data(cursor):
|
def migrate_exif_data(cursor):
|
||||||
if os.path.exists(exif_cache_file):
|
if os.path.exists(exif_cache_file):
|
||||||
with open(exif_cache_file, 'r') as file:
|
with open(exif_cache_file, 'r') as file:
|
||||||
#with open("c:\\tools\\ai\\stable-diffusion-webui\\extensions\\stable-diffusion-webui-images-browser\\test.json ", 'r') as file:
|
|
||||||
exif_cache = json.load(file)
|
exif_cache = json.load(file)
|
||||||
|
|
||||||
for file, info in exif_cache.items():
|
for file, info in exif_cache.items():
|
||||||
|
file = os.path.abspath(file)
|
||||||
update_exif_data(cursor, file, info)
|
update_exif_data(cursor, file, info)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
@ -194,10 +203,12 @@ def migrate_ranking(cursor):
|
||||||
ranking = json.load(file)
|
ranking = json.load(file)
|
||||||
for file, info in ranking.items():
|
for file, info in ranking.items():
|
||||||
if info != "None":
|
if info != "None":
|
||||||
|
file = os.path.abspath(file)
|
||||||
|
name = os.path.basename(file)
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
INSERT INTO ranking (file, ranking)
|
INSERT INTO ranking (file, name, ranking)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?, ?)
|
||||||
''', (file, info))
|
''', (file, name, info))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -210,17 +221,122 @@ def update_db_data(cursor, key, value):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
with sqlite3.connect(db_file, timeout=timeout) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT value
|
||||||
|
FROM db_data
|
||||||
|
WHERE key = 'version'
|
||||||
|
''',)
|
||||||
|
db_version = cursor.fetchone()
|
||||||
|
|
||||||
|
return db_version
|
||||||
|
|
||||||
|
def migrate_path_recorder_dirs(cursor):
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT path, path_display
|
||||||
|
FROM path_recorder
|
||||||
|
''')
|
||||||
|
for (path, path_display) in cursor.fetchall():
|
||||||
|
abs_path = os.path.abspath(path)
|
||||||
|
if path != abs_path:
|
||||||
|
update_from = path
|
||||||
|
update_to = abs_path
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE path_recorder
|
||||||
|
SET path = ?,
|
||||||
|
path_display = ? || SUBSTR(path_display, LENGTH(?) + 1)
|
||||||
|
WHERE path = ?
|
||||||
|
''', (update_to, update_to, update_from, update_from))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def migrate_exif_data_dirs(cursor):
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT file
|
||||||
|
FROM exif_data
|
||||||
|
''')
|
||||||
|
for (filepath,) in cursor.fetchall():
|
||||||
|
(path, file) = os.path.split(filepath)
|
||||||
|
abs_path = os.path.abspath(path)
|
||||||
|
if path != abs_path:
|
||||||
|
update_from = filepath
|
||||||
|
update_to = os.path.join(abs_path, file)
|
||||||
|
try:
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE exif_data
|
||||||
|
SET file = ?
|
||||||
|
WHERE file = ?
|
||||||
|
''', (update_to, update_from))
|
||||||
|
except sqlite3.IntegrityError as e:
|
||||||
|
# these are double keys, because the same file can be in the db with different path notations
|
||||||
|
(e_msg,) = e.args
|
||||||
|
if e_msg.startswith("UNIQUE constraint"):
|
||||||
|
cursor.execute('''
|
||||||
|
DELETE FROM exif_data
|
||||||
|
WHERE file = ?
|
||||||
|
''', (update_from,))
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def migrate_ranking_dirs(cursor):
|
||||||
|
cursor.execute('''
|
||||||
|
ALTER TABLE ranking
|
||||||
|
ADD COLUMN name TEXT
|
||||||
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE INDEX IF NOT EXISTS ranking_name ON ranking (name)
|
||||||
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT file, ranking
|
||||||
|
FROM ranking
|
||||||
|
''')
|
||||||
|
for (filepath, ranking) in cursor.fetchall():
|
||||||
|
if filepath == "" or ranking == "None":
|
||||||
|
cursor.execute('''
|
||||||
|
DELETE FROM ranking
|
||||||
|
WHERE file = ?
|
||||||
|
''', (filepath,))
|
||||||
|
else:
|
||||||
|
(path, file) = os.path.split(filepath)
|
||||||
|
abs_path = os.path.abspath(path)
|
||||||
|
name = file
|
||||||
|
update_from = filepath
|
||||||
|
update_to = os.path.join(abs_path, file)
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE ranking
|
||||||
|
SET file = ?,
|
||||||
|
name = ?
|
||||||
|
WHERE file = ?
|
||||||
|
''', (update_to, name, update_from))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def check():
|
def check():
|
||||||
if not os.path.exists(db_file):
|
if not os.path.exists(db_file):
|
||||||
conn, cursor = transaction_begin()
|
conn, cursor = transaction_begin()
|
||||||
create_db(cursor)
|
create_db(cursor)
|
||||||
update_db_data(cursor, "version", "1")
|
update_db_data(cursor, "version", version)
|
||||||
migrate_path_recorder(cursor)
|
migrate_path_recorder(cursor)
|
||||||
migrate_exif_data(cursor)
|
migrate_exif_data(cursor)
|
||||||
migrate_ranking(cursor)
|
migrate_ranking(cursor)
|
||||||
transaction_end(conn, cursor)
|
transaction_end(conn, cursor)
|
||||||
|
db_version = get_version()
|
||||||
|
if db_version[0] == "1":
|
||||||
|
# version 1 database had mixed path notations, this will change them all to abspath
|
||||||
|
conn, cursor = transaction_begin()
|
||||||
|
update_db_data(cursor, "version", version)
|
||||||
|
migrate_path_recorder_dirs(cursor)
|
||||||
|
migrate_exif_data_dirs(cursor)
|
||||||
|
migrate_ranking_dirs(cursor)
|
||||||
|
transaction_end(conn, cursor)
|
||||||
|
|
||||||
return
|
return version
|
||||||
|
|
||||||
def load_path_recorder():
|
def load_path_recorder():
|
||||||
with sqlite3.connect(db_file, timeout=timeout) as conn:
|
with sqlite3.connect(db_file, timeout=timeout) as conn:
|
||||||
|
|
@ -234,28 +350,54 @@ def load_path_recorder():
|
||||||
return path_recorder
|
return path_recorder
|
||||||
|
|
||||||
def select_ranking(filename):
|
def select_ranking(filename):
|
||||||
with sqlite3.connect(db_file, timeout=timeout) as conn:
|
conn, cursor = transaction_begin()
|
||||||
cursor = conn.cursor()
|
cursor.execute('''
|
||||||
|
SELECT ranking
|
||||||
|
FROM ranking
|
||||||
|
WHERE file = ?
|
||||||
|
''', (filename,))
|
||||||
|
ranking_value = cursor.fetchone()
|
||||||
|
|
||||||
|
# if ranking not found search again, without path (moved?)
|
||||||
|
if ranking_value is None:
|
||||||
|
name = os.path.basename(filename)
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
SELECT ranking
|
SELECT ranking
|
||||||
FROM ranking
|
FROM ranking
|
||||||
WHERE file = ?
|
WHERE name = ?
|
||||||
''', (filename,))
|
''', (name,))
|
||||||
ranking_value = cursor.fetchone()
|
ranking_value = cursor.fetchone()
|
||||||
|
# and insert with current filepath
|
||||||
|
if ranking_value is not None:
|
||||||
|
(insert_ranking,) = ranking_value
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO ranking (file, name, ranking)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
''', (filename, name, insert_ranking))
|
||||||
|
|
||||||
if ranking_value is None:
|
if ranking_value is None:
|
||||||
ranking_value = ["0"]
|
return_ranking = "None"
|
||||||
return ranking_value[0]
|
else:
|
||||||
|
(return_ranking,) = ranking_value
|
||||||
|
transaction_end(conn, cursor)
|
||||||
|
|
||||||
|
return return_ranking
|
||||||
|
|
||||||
def update_ranking(file, ranking):
|
def update_ranking(file, ranking):
|
||||||
if ranking != "0":
|
name = os.path.basename(file)
|
||||||
with sqlite3.connect(db_file, timeout=timeout) as conn:
|
with sqlite3.connect(db_file, timeout=timeout) as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute('''
|
if ranking == "None":
|
||||||
INSERT OR REPLACE
|
cursor.execute('''
|
||||||
INTO ranking (file, ranking)
|
DELETE FROM ranking
|
||||||
VALUES (?, ?)
|
WHERE name = ?
|
||||||
''', (file, ranking))
|
''', (name,))
|
||||||
|
else:
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT OR REPLACE
|
||||||
|
INTO ranking (file, name, ranking)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
''', (file, name, ranking))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -280,6 +422,38 @@ def delete_path_recorder(path):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def update_path_recorder_mult(cursor, update_from, update_to):
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE path_recorder
|
||||||
|
SET path = ?,
|
||||||
|
path_display = ? || SUBSTR(path_display, LENGTH(?) + 1)
|
||||||
|
WHERE path = ?
|
||||||
|
''', (update_to, update_to, update_from, update_from))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def update_exif_data_mult(cursor, update_from, update_to):
|
||||||
|
update_from = update_from + os.path.sep
|
||||||
|
update_to = update_to + os.path.sep
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE exif_data
|
||||||
|
SET file = ? || SUBSTR(file, LENGTH(?) + 1)
|
||||||
|
WHERE file like ? || '%'
|
||||||
|
''', (update_to, update_from, update_from))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def update_ranking_mult(cursor, update_from, update_to):
|
||||||
|
update_from = update_from + os.path.sep
|
||||||
|
update_to = update_to + os.path.sep
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE ranking
|
||||||
|
SET file = ? || SUBSTR(file, LENGTH(?) + 1)
|
||||||
|
WHERE file like ? || '%'
|
||||||
|
''', (update_to, update_from, update_from))
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def transaction_begin():
|
def transaction_begin():
|
||||||
conn = sqlite3.connect(db_file, timeout=timeout)
|
conn = sqlite3.connect(db_file, timeout=timeout)
|
||||||
conn.isolation_level = None
|
conn.isolation_level = None
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue