Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
fe50e8d
feat: split CTK UI into controller/base-view/ctk-view pattern
May 10, 2026
a88f369
refactor: abstract CTK views and migrate logic to controllers
May 10, 2026
f7e4159
copy: add PySide6 view copies mirroring CTK structure
May 10, 2026
ec2ee0a
refactor: replace manual entry+browse-button pairs with path_entry in…
May 11, 2026
c5b21f0
Merge branch 'ctk_abstraction' into pyside_copy
May 11, 2026
e19d149
refactor: mirror VideoToolUI path_entry refactor to PySide6VideoToolU…
May 11, 2026
65bdda2
copy: sync pyside6_components.py with ctk_components.py (allow_video_…
May 11, 2026
c3961ba
fix: declare undeclared self attrs in Base*View classes
May 15, 2026
d039871
refactor: move Windows DPI awareness block to CtkTrainUIView
May 15, 2026
307eef2
Merge branch 'ctk_abstraction' into pyside_copy
May 15, 2026
29a62a1
chore: sync PySide6 copies from ctk_abstraction merge
May 15, 2026
1bb5a56
refactor: remove unused __init__ from BaseConceptTabView
May 15, 2026
06ca10c
Merge branch 'ctk_abstraction' into pyside_copy
May 15, 2026
9f42590
Merge branch 'upstream' into ctk_copy
May 16, 2026
8dd86c6
fix: apply upstream COFT removal to CtkLoraTabView
May 16, 2026
19b5724
Merge branch 'ctk_copy' into ctk_abstraction
May 16, 2026
126bc97
Merge branch 'ctk_abstraction' into pyside_copy
May 16, 2026
3984c3f
Merge branch 'upstream' into ctk_copy
dxqb May 29, 2026
c602458
Sync Ctk* copies with upstream changes merged into Base* files
dxqb May 29, 2026
23ad1a2
Merge ctk_copy: LoKr support, Scaled OFT, ETA fix, row counter fix; k…
dxqb May 29, 2026
9f27035
Merge branch 'ctk_abstraction' into pyside_copy
dxqb May 29, 2026
01cca79
Move Rolling Backup Count under the Rolling Backup toggle
dxqb May 29, 2026
647afc2
Move Rolling Backup Count under the Rolling Backup toggle
dxqb May 29, 2026
6658da5
Merge branch 'ctk_abstraction' into pyside_copy
dxqb May 29, 2026
408e7e2
Merge branch 'upstream' into ctk_copy
dxqb Jun 4, 2026
a0bd3e4
Sync CtkConceptWindowView and ConceptWindowController with Base copy
dxqb Jun 4, 2026
3d90a9e
Merge ctk_copy: transformers 5.9, torch 2.12, compile thread-safety
dxqb Jun 4, 2026
dc4fdea
Merge branch 'ctk_abstraction' into pyside_copy
dxqb Jun 4, 2026
51a839e
Merge branch 'upstream' into ctk_copy
dxqb Jun 13, 2026
fdea894
Sync CtkConceptWindowView with BaseConceptWindowView after upstream m…
dxqb Jun 13, 2026
e70bada
Merge branch 'ctk_copy' into ctk_abstraction
dxqb Jun 13, 2026
2030db2
Merge branch 'ctk_abstraction' into pyside_copy
dxqb Jun 13, 2026
dd9bdbe
Merge branch 'upstream' into ctk_copy
dxqb Jun 19, 2026
1f73b3a
Sync Ctk* views with Base* after merging upstream
dxqb Jun 19, 2026
aee3609
Merge branch 'ctk_copy' into ctk_abstraction
dxqb Jun 19, 2026
c074a50
Merge branch 'ctk_abstraction' into pyside_copy
dxqb Jun 19, 2026
816c17a
Merge upstream: Disable LoRA rank check (false positive on Flux2 LoHA…
dxqb Jun 26, 2026
68b6a86
Merge ctk_copy: Disable LoRA rank check (false positive on Flux2 LoHA…
dxqb Jun 26, 2026
17dd810
Merge ctk_abstraction: Disable LoRA rank check (false positive on Flu…
dxqb Jun 26, 2026
826835e
Fix CaptionUI arrow-key navigation and SVD-frame docstring
dxqb Jun 27, 2026
3f676d7
Fix standalone caption/convert/video UI launch scripts after Ctk view…
dxqb Jun 27, 2026
9706006
Fix HF dataset download in concept window after Ctk view split
dxqb Jun 27, 2026
7377fd7
Fix stale UIState type reference in ctk_validation
dxqb Jun 27, 2026
8f70897
Drop customtkinter dependency from toolkit-agnostic Base views
dxqb Jun 27, 2026
d52b8d2
Re-apply aux-optimizer empty-state default fix (#1444) after Ctk view…
dxqb Jun 27, 2026
3c06587
Merge ctk_abstraction: fix scripts, validation, concept window, optim…
dxqb Jun 27, 2026
0f361c9
Fix sample-window lifecycle: scope <Destroy> binding and defer torch_…
dxqb Jun 29, 2026
57d53bf
Remove PLAN.md from .gitignore
dxqb Jun 29, 2026
cffd19e
Merge branch 'ctk_abstraction' into pyside_copy
dxqb Jun 29, 2026
18a06b0
Re-copy PySide6 view after ctk_abstraction merge (sample-window fix)
dxqb Jun 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ pixi.toml
train.bat
debug_report.log
config_diff.txt
PLAN.md
136 changes: 0 additions & 136 deletions modules/ui/AdditionalEmbeddingsTab.py

This file was deleted.

14 changes: 14 additions & 0 deletions modules/ui/AdditionalEmbeddingsTabController.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

from modules.util.config.TrainConfig import TrainConfig, TrainEmbeddingConfig


class AdditionalEmbeddingsTabController:
def __init__(self, config: TrainConfig):
self.train_config = config

def create_new_element(self) -> TrainEmbeddingConfig:
return TrainEmbeddingConfig.default_values()

def randomize_uuid(self, embedding_config: TrainEmbeddingConfig) -> TrainEmbeddingConfig:
embedding_config.uuid = TrainEmbeddingConfig.default_values().uuid
return embedding_config
73 changes: 73 additions & 0 deletions modules/ui/BaseAdditionalEmbeddingsTabView.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

from modules.ui.BaseConfigListView import BaseConfigListView
from modules.util import path_util


class BaseAdditionalEmbeddingsTabView(BaseConfigListView):

def refresh_ui(self):
if self.element_list is not None:
self._destroy_frame(self.element_list)
self.element_list = None
self.widgets_initialized = False
self._create_element_list()

def open_element_window(self, i, ui_state):
pass


class BaseEmbeddingWidgetView:

def __init__(self, components):
self.components = components

def build_content(self, top_frame, bottom_frame, ui_state, i, save_command, remove_command, clone_command, controller):
self.ui_state = ui_state
self.i = i
self.save_command = save_command

# close button
self.components.colored_icon_button(top_frame, 0, 0, "X", "#C00000", lambda: remove_command(self.i))

# clone button
self.components.colored_icon_button(top_frame, 0, 1, "+", "#00C000", lambda: clone_command(self.i, controller.randomize_uuid), padx=5)

# embedding model names
self.components.label(top_frame, 0, 2, "base embedding:",
tooltip="The base embedding to train on. Leave empty to create a new embedding")
self.components.path_entry(
top_frame, 0, 3, self.ui_state, "model_name",
mode="file", path_modifier=path_util.json_path_modifier
)

# placeholder
self.components.label(top_frame, 0, 4, "placeholder:",
tooltip="The placeholder used when using the embedding in a prompt")
self.components.entry(top_frame, 0, 5, self.ui_state, "placeholder")

# token count
self.components.label(top_frame, 0, 6, "token count:",
tooltip="The token count used when creating a new embedding. Leave empty to auto detect from the initial embedding text.")
self.components.entry(top_frame, 0, 7, self.ui_state, "token_count", width=40)

# trainable
self.components.label(bottom_frame, 0, 0, "train:")
self.components.switch(bottom_frame, 0, 1, self.ui_state, "train", command=save_command, width=40)

# output embedding
self.components.label(bottom_frame, 0, 2, "output embedding:",
tooltip="Output embeddings are calculated at the output of the text encoder, not the input. This can improve results for larger text encoders and lower VRAM usage.")
self.components.switch(bottom_frame, 0, 3, self.ui_state, "is_output_embedding", width=40)

# stop training after
self.components.label(bottom_frame, 0, 4, "stop training after:",
tooltip="When to stop training the embedding")
self.components.time_entry(bottom_frame, 0, 5, self.ui_state, "stop_training_after", "stop_training_after_unit")

# initial embedding text
self.components.label(bottom_frame, 0, 6, "initial embedding text:",
tooltip="The initial embedding text used when creating a new embedding")
self.components.entry(bottom_frame, 0, 7, self.ui_state, "initial_embedding_text")

def configure_element(self):
pass
51 changes: 51 additions & 0 deletions modules/ui/BaseCaptionUIView.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import platform
from abc import ABC, abstractmethod


class BaseCaptionUIView(ABC):
def __init__(self, components):
self.components = components

@abstractmethod
def open_directory(self): pass

@abstractmethod
def open_mask_window(self): pass

@abstractmethod
def open_caption_window(self): pass

@abstractmethod
def open_in_explorer(self): pass

@abstractmethod
def draw_mask_editing_mode(self, *args): pass

@abstractmethod
def fill_mask_editing_mode(self, *args): pass

def build_top_bar(self, frame, controller, ui_state):
self.components.button(frame, 0, 0, "Open", self.open_directory,
tooltip="open a new directory")
self.components.button(frame, 0, 1, "Generate Masks", self.open_mask_window,
tooltip="open a dialog to automatically generate masks")
self.components.button(frame, 0, 2, "Generate Captions", self.open_caption_window,
tooltip="open a dialog to automatically generate captions")

if platform.system() == "Windows":
self.components.button(frame, 0, 3, "Open in Explorer", self.open_in_explorer,
tooltip="open the current image in Explorer")

self.components.switch(frame, 0, 4, ui_state, "include_subdirectories",
text="include subdirectories")

frame.grid_columnconfigure(5, weight=1)

self.components.button(frame, 0, 6, "Help", controller.print_help,
tooltip=controller.help_text)

def build_mask_buttons(self, right_frame):
self.components.button(right_frame, 0, 0, "Draw", self.draw_mask_editing_mode,
tooltip="draw a mask using a brush")
self.components.button(right_frame, 0, 1, "Fill", self.fill_mask_editing_mode,
tooltip="draw a mask using a fill tool")
Loading