Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
828f3c6c12 |
No files matched your search
@@ -17,8 +17,6 @@ from modules.console_window import ConsoleWindow
|
|||||||
from modules.model_manager import ModelManager
|
from modules.model_manager import ModelManager
|
||||||
from modules.sampler_manager import SamplerManager
|
from modules.sampler_manager import SamplerManager
|
||||||
from modules.prompt_window import PromptWindow
|
from modules.prompt_window import PromptWindow
|
||||||
from modules.negative_prompt_window import NegativePromptWindow
|
|
||||||
from modules.size_preset_manager import SizePresetManager
|
|
||||||
|
|
||||||
class GenerationThread(QThread):
|
class GenerationThread(QThread):
|
||||||
progress_updated = pyqtSignal(float, str)
|
progress_updated = pyqtSignal(float, str)
|
||||||
@@ -66,7 +64,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.api_url = "http://localhost:7860" # URL по умолчанию
|
self.api_url = "http://localhost:7860" # URL по умолчанию
|
||||||
self.console_window = None
|
self.console_window = None
|
||||||
self.prompt_window = None
|
self.prompt_window = None
|
||||||
self.negative_prompt_window = None
|
|
||||||
self.progress_timer = None
|
self.progress_timer = None
|
||||||
self.init_ui()
|
self.init_ui()
|
||||||
|
|
||||||
@@ -167,32 +164,29 @@ class MainWindow(QMainWindow):
|
|||||||
settings_layout.addLayout(api_layout)
|
settings_layout.addLayout(api_layout)
|
||||||
|
|
||||||
# Промпт
|
# Промпт
|
||||||
prompt_layout = QVBoxLayout()
|
|
||||||
prompt_header = QHBoxLayout()
|
|
||||||
prompt_label = QLabel("Промпт:")
|
prompt_label = QLabel("Промпт:")
|
||||||
self.prompt_input = QTextEdit()
|
self.prompt_input = QTextEdit()
|
||||||
self.prompt_input.setMinimumHeight(100)
|
self.prompt_input.setPlaceholderText("Введите описание изображения...")
|
||||||
prompt_buttons = QHBoxLayout()
|
prompt_layout = QVBoxLayout()
|
||||||
|
prompt_header = QHBoxLayout()
|
||||||
|
prompt_header.addWidget(prompt_label)
|
||||||
|
|
||||||
|
# Добавляем кнопку промптов рядом с полем промпта
|
||||||
self.prompt_button = QPushButton("Готовые промпты")
|
self.prompt_button = QPushButton("Готовые промпты")
|
||||||
self.prompt_button.clicked.connect(self.toggle_prompt_window)
|
self.prompt_button.clicked.connect(self.toggle_prompt_window)
|
||||||
self.negative_prompt_button = QPushButton("Негативные промпты")
|
prompt_header.addWidget(self.prompt_button)
|
||||||
self.negative_prompt_button.clicked.connect(self.toggle_negative_prompt_window)
|
prompt_header.addStretch()
|
||||||
prompt_buttons.addWidget(self.prompt_button)
|
|
||||||
prompt_buttons.addWidget(self.negative_prompt_button)
|
|
||||||
prompt_header.addWidget(prompt_label)
|
|
||||||
prompt_header.addLayout(prompt_buttons)
|
|
||||||
prompt_layout.addLayout(prompt_header)
|
prompt_layout.addLayout(prompt_header)
|
||||||
prompt_layout.addWidget(self.prompt_input)
|
prompt_layout.addWidget(self.prompt_input)
|
||||||
settings_layout.addLayout(prompt_layout)
|
settings_layout.addLayout(prompt_layout)
|
||||||
|
|
||||||
# Негативный промпт
|
# Негативный промпт
|
||||||
negative_prompt_layout = QVBoxLayout()
|
neg_prompt_label = QLabel("Негативный промпт:")
|
||||||
negative_prompt_label = QLabel("Негативный промпт:")
|
self.neg_prompt_input = QTextEdit()
|
||||||
self.negative_prompt_input = QTextEdit()
|
self.neg_prompt_input.setPlaceholderText("Введите нежелательные элементы...")
|
||||||
self.negative_prompt_input.setMinimumHeight(100)
|
settings_layout.addWidget(neg_prompt_label)
|
||||||
negative_prompt_layout.addWidget(negative_prompt_label)
|
settings_layout.addWidget(self.neg_prompt_input)
|
||||||
negative_prompt_layout.addWidget(self.negative_prompt_input)
|
|
||||||
settings_layout.addLayout(negative_prompt_layout)
|
|
||||||
|
|
||||||
# Добавляем менеджер моделей
|
# Добавляем менеджер моделей
|
||||||
self.model_manager = ModelManager(self.api_url)
|
self.model_manager = ModelManager(self.api_url)
|
||||||
@@ -203,11 +197,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.sampler_manager = SamplerManager(self.api_url)
|
self.sampler_manager = SamplerManager(self.api_url)
|
||||||
settings_layout.addWidget(self.sampler_manager)
|
settings_layout.addWidget(self.sampler_manager)
|
||||||
|
|
||||||
# Добавляем менеджер пресетов размеров
|
|
||||||
self.size_preset_manager = SizePresetManager()
|
|
||||||
self.size_preset_manager.size_changed.connect(self.on_size_preset_changed)
|
|
||||||
settings_layout.addWidget(self.size_preset_manager)
|
|
||||||
|
|
||||||
# Параметры генерации
|
# Параметры генерации
|
||||||
params_layout = QVBoxLayout()
|
params_layout = QVBoxLayout()
|
||||||
|
|
||||||
@@ -327,28 +316,12 @@ class MainWindow(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
self.prompt_window.close()
|
self.prompt_window.close()
|
||||||
|
|
||||||
def toggle_negative_prompt_window(self):
|
def add_prompt(self, prompt):
|
||||||
"""Открыть/закрыть окно с негативными промптами"""
|
|
||||||
if self.negative_prompt_window is None:
|
|
||||||
self.negative_prompt_window = NegativePromptWindow(parent=self)
|
|
||||||
self.negative_prompt_window.prompt_selected.connect(self.add_negative_prompt)
|
|
||||||
self.negative_prompt_window.show()
|
|
||||||
else:
|
|
||||||
self.negative_prompt_window.close()
|
|
||||||
|
|
||||||
def add_prompt(self, text):
|
|
||||||
"""Добавить промпт в поле ввода"""
|
"""Добавить промпт в поле ввода"""
|
||||||
current_text = self.prompt_input.toPlainText()
|
current_text = self.prompt_input.toPlainText()
|
||||||
if current_text:
|
if current_text:
|
||||||
current_text += ", "
|
current_text += ", "
|
||||||
self.prompt_input.setText(current_text + text)
|
self.prompt_input.setText(current_text + prompt)
|
||||||
|
|
||||||
def add_negative_prompt(self, text):
|
|
||||||
"""Добавить негативный промпт в поле ввода"""
|
|
||||||
current_text = self.negative_prompt_input.toPlainText()
|
|
||||||
if current_text:
|
|
||||||
current_text += ", "
|
|
||||||
self.negative_prompt_input.setText(current_text + text)
|
|
||||||
|
|
||||||
def start_generation(self):
|
def start_generation(self):
|
||||||
self.generate_button.setEnabled(False)
|
self.generate_button.setEnabled(False)
|
||||||
@@ -356,7 +329,7 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
params = {
|
params = {
|
||||||
"prompt": self.prompt_input.toPlainText(),
|
"prompt": self.prompt_input.toPlainText(),
|
||||||
"negative_prompt": self.negative_prompt_input.toPlainText(),
|
"negative_prompt": self.neg_prompt_input.toPlainText(),
|
||||||
"width": self.width_input.value(),
|
"width": self.width_input.value(),
|
||||||
"height": self.height_input.value(),
|
"height": self.height_input.value(),
|
||||||
"seed": self.seed_input.value(),
|
"seed": self.seed_input.value(),
|
||||||
@@ -453,20 +426,11 @@ class MainWindow(QMainWindow):
|
|||||||
save_button = QPushButton("Сохранить")
|
save_button = QPushButton("Сохранить")
|
||||||
save_button.clicked.connect(lambda checked, img=img: self.save_image(img))
|
save_button.clicked.connect(lambda checked, img=img: self.save_image(img))
|
||||||
|
|
||||||
# Создаем кнопку копирования в буфер обмена
|
# Создаем контейнер для изображения и кнопки
|
||||||
copy_button = QPushButton("Копировать")
|
|
||||||
copy_button.clicked.connect(lambda checked, img=img: self.copy_to_clipboard(img))
|
|
||||||
|
|
||||||
# Создаем контейнер для изображения и кнопок
|
|
||||||
container = QWidget()
|
container = QWidget()
|
||||||
container_layout = QVBoxLayout(container)
|
container_layout = QVBoxLayout(container)
|
||||||
container_layout.addWidget(img_label)
|
container_layout.addWidget(img_label)
|
||||||
|
container_layout.addWidget(save_button)
|
||||||
# Создаем горизонтальный layout для кнопок
|
|
||||||
buttons_layout = QHBoxLayout()
|
|
||||||
buttons_layout.addWidget(save_button)
|
|
||||||
buttons_layout.addWidget(copy_button)
|
|
||||||
container_layout.addLayout(buttons_layout)
|
|
||||||
|
|
||||||
self.results_content_layout.addWidget(container)
|
self.results_content_layout.addWidget(container)
|
||||||
self.log_to_console("Изображение успешно добавлено в интерфейс")
|
self.log_to_console("Изображение успешно добавлено в интерфейс")
|
||||||
@@ -486,22 +450,6 @@ class MainWindow(QMainWindow):
|
|||||||
if file_path:
|
if file_path:
|
||||||
img.save(file_path)
|
img.save(file_path)
|
||||||
|
|
||||||
def copy_to_clipboard(self, img):
|
|
||||||
"""Копирование изображения в буфер обмена"""
|
|
||||||
# Конвертируем изображение в QPixmap
|
|
||||||
buffer = BytesIO()
|
|
||||||
img.save(buffer, format='PNG')
|
|
||||||
buffer.seek(0)
|
|
||||||
pixmap = QPixmap()
|
|
||||||
pixmap.loadFromData(buffer.getvalue())
|
|
||||||
|
|
||||||
# Копируем в буфер обмена
|
|
||||||
clipboard = QApplication.clipboard()
|
|
||||||
clipboard.setPixmap(pixmap)
|
|
||||||
|
|
||||||
# Показываем уведомление
|
|
||||||
self.log_to_console("Изображение скопировано в буфер обмена")
|
|
||||||
|
|
||||||
def update_api_url(self):
|
def update_api_url(self):
|
||||||
"""Обновление URL API во всех компонентах"""
|
"""Обновление URL API во всех компонентах"""
|
||||||
new_url = self.api_url_input.text()
|
new_url = self.api_url_input.text()
|
||||||
@@ -509,12 +457,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.sampler_manager.update_api_url(new_url)
|
self.sampler_manager.update_api_url(new_url)
|
||||||
self.log_to_console(f"API URL обновлен: {new_url}")
|
self.log_to_console(f"API URL обновлен: {new_url}")
|
||||||
|
|
||||||
def on_size_preset_changed(self, width, height):
|
|
||||||
"""Обработчик изменения размера через пресет"""
|
|
||||||
self.width_input.setValue(width)
|
|
||||||
self.height_input.setValue(height)
|
|
||||||
self.log_to_console(f"Размер изменен на: {width}x{height}")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+26
-19
@@ -17,36 +17,42 @@ class ConsoleWindow(QDialog):
|
|||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
QDialog {
|
QDialog {
|
||||||
background-color: #2b2b2b;
|
background-color: #1e1e1e;
|
||||||
min-width: 600px;
|
min-width: 700px;
|
||||||
min-height: 400px;
|
min-height: 500px;
|
||||||
}
|
}
|
||||||
QTextEdit {
|
QTextEdit {
|
||||||
background-color: #1e1e1e;
|
background-color: #252526;
|
||||||
color: #ffffff;
|
color: #d4d4d4;
|
||||||
border: 1px solid #3b3b3b;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
font-family: 'Consolas', 'Courier New', monospace;
|
font-family: 'JetBrains Mono', 'Consolas', 'Courier New', monospace;
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
padding: 8px;
|
padding: 12px;
|
||||||
|
selection-background-color: #264f78;
|
||||||
}
|
}
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #0d6efd;
|
background-color: #2d2d2d;
|
||||||
color: white;
|
color: #d4d4d4;
|
||||||
border: none;
|
border: 1px solid #3e3e3e;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
font-weight: bold;
|
font-weight: 500;
|
||||||
|
min-width: 100px;
|
||||||
|
margin: 4px;
|
||||||
}
|
}
|
||||||
QPushButton:hover {
|
QPushButton:hover {
|
||||||
background-color: #0b5ed7;
|
background-color: #3e3e3e;
|
||||||
|
border-color: #565656;
|
||||||
}
|
}
|
||||||
QPushButton:pressed {
|
QPushButton:pressed {
|
||||||
background-color: #0a58ca;
|
background-color: #565656;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
|
layout.setContentsMargins(16, 16, 16, 16)
|
||||||
|
layout.setSpacing(12)
|
||||||
|
|
||||||
# Область для логов
|
# Область для логов
|
||||||
self.console_output = QTextEdit()
|
self.console_output = QTextEdit()
|
||||||
@@ -55,11 +61,12 @@ class ConsoleWindow(QDialog):
|
|||||||
|
|
||||||
# Кнопки управления
|
# Кнопки управления
|
||||||
buttons_layout = QHBoxLayout()
|
buttons_layout = QHBoxLayout()
|
||||||
|
buttons_layout.setSpacing(8)
|
||||||
|
|
||||||
copy_button = QPushButton("Копировать всё")
|
copy_button = QPushButton("📋 Копировать")
|
||||||
copy_button.clicked.connect(self.copy_all)
|
copy_button.clicked.connect(self.copy_all)
|
||||||
|
|
||||||
clear_button = QPushButton("Очистить")
|
clear_button = QPushButton("🗑️ Очистить")
|
||||||
clear_button.clicked.connect(self.clear_console)
|
clear_button.clicked.connect(self.clear_console)
|
||||||
|
|
||||||
buttons_layout.addWidget(copy_button)
|
buttons_layout.addWidget(copy_button)
|
||||||
|
|||||||
@@ -13,8 +13,65 @@ class ModelManager(QWidget):
|
|||||||
self.load_models()
|
self.load_models()
|
||||||
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
QLabel {
|
||||||
|
color: #d4d4d4;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
QComboBox {
|
||||||
|
background-color: #252526;
|
||||||
|
color: #d4d4d4;
|
||||||
|
border: 1px solid #3e3e3e;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
min-width: 200px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
QComboBox:hover {
|
||||||
|
border-color: #565656;
|
||||||
|
}
|
||||||
|
QComboBox:focus {
|
||||||
|
border-color: #007acc;
|
||||||
|
}
|
||||||
|
QComboBox::drop-down {
|
||||||
|
border: none;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
QComboBox::down-arrow {
|
||||||
|
image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTggMTFMNCBTTDEyIDUiIHN0cm9rZT0iI2Q0ZDRkNCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+);
|
||||||
|
}
|
||||||
|
QComboBox QAbstractItemView {
|
||||||
|
background-color: #252526;
|
||||||
|
color: #d4d4d4;
|
||||||
|
border: 1px solid #3e3e3e;
|
||||||
|
selection-background-color: #094771;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
QPushButton {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
color: #d4d4d4;
|
||||||
|
border: 1px solid #3e3e3e;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: #3e3e3e;
|
||||||
|
border-color: #565656;
|
||||||
|
}
|
||||||
|
QPushButton:pressed {
|
||||||
|
background-color: #565656;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
layout = QHBoxLayout(self)
|
layout = QHBoxLayout(self)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
layout.setSpacing(8)
|
||||||
|
|
||||||
# Метка
|
# Метка
|
||||||
label = QLabel("Модель:")
|
label = QLabel("Модель:")
|
||||||
@@ -22,11 +79,13 @@ class ModelManager(QWidget):
|
|||||||
|
|
||||||
# Выпадающий список моделей
|
# Выпадающий список моделей
|
||||||
self.model_combo = QComboBox()
|
self.model_combo = QComboBox()
|
||||||
|
self.model_combo.setFixedHeight(32)
|
||||||
self.model_combo.currentTextChanged.connect(self.on_model_changed)
|
self.model_combo.currentTextChanged.connect(self.on_model_changed)
|
||||||
layout.addWidget(self.model_combo)
|
layout.addWidget(self.model_combo)
|
||||||
|
|
||||||
# Кнопка обновления
|
# Кнопка обновления
|
||||||
refresh_button = QPushButton("🔄")
|
refresh_button = QPushButton("🔄")
|
||||||
|
refresh_button.setFixedSize(32, 32)
|
||||||
refresh_button.setToolTip("Обновить список моделей")
|
refresh_button.setToolTip("Обновить список моделей")
|
||||||
refresh_button.clicked.connect(self.load_models)
|
refresh_button.clicked.connect(self.load_models)
|
||||||
layout.addWidget(refresh_button)
|
layout.addWidget(refresh_button)
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
NEGATIVE_PROMPT_CATEGORIES = {
|
|
||||||
"Общие проблемы": {
|
|
||||||
"Качество": [
|
|
||||||
"Низкое качество",
|
|
||||||
"Обычное качество",
|
|
||||||
"Худшее качество",
|
|
||||||
"Низкое разрешение",
|
|
||||||
"Размытое",
|
|
||||||
"Не в фокусе"
|
|
||||||
],
|
|
||||||
"Технические артефакты": [
|
|
||||||
"Логотип",
|
|
||||||
"Текст",
|
|
||||||
"Подпись",
|
|
||||||
"Водяной знак",
|
|
||||||
"Обрезанное",
|
|
||||||
"Монохромное",
|
|
||||||
"Оттенки серого"
|
|
||||||
],
|
|
||||||
"Контент": [
|
|
||||||
"Нецензурный контент",
|
|
||||||
"NSFW",
|
|
||||||
"Удалить взрослых",
|
|
||||||
"Удалить молодых"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Анатомия": {
|
|
||||||
"Общие проблемы": [
|
|
||||||
"Неправильная анатомия",
|
|
||||||
"Плохое тело",
|
|
||||||
"Длинное тело",
|
|
||||||
"Длинная шея",
|
|
||||||
"Неправильные пропорции",
|
|
||||||
"Деформированный",
|
|
||||||
"Мутировавший",
|
|
||||||
"Мутация",
|
|
||||||
"Уродливый",
|
|
||||||
"Испорченный"
|
|
||||||
],
|
|
||||||
"Лицо": [
|
|
||||||
"Плохо нарисованное лицо",
|
|
||||||
"Пятна на коже",
|
|
||||||
"Веснушки",
|
|
||||||
"Прыщи",
|
|
||||||
"Косоглазый"
|
|
||||||
],
|
|
||||||
"Конечности": [
|
|
||||||
"Отсутствующая конечность",
|
|
||||||
"Деформированные конечности",
|
|
||||||
"Плавающие конечности",
|
|
||||||
"Отсоединенные конечности",
|
|
||||||
"Дополнительная конечность",
|
|
||||||
"Дополнительные руки",
|
|
||||||
"Мутировавшие руки",
|
|
||||||
"Плохо нарисованные руки",
|
|
||||||
"Деформированные руки",
|
|
||||||
"Мутировавшие руки и пальцы",
|
|
||||||
"Плохие руки",
|
|
||||||
"Отсутствующие пальцы",
|
|
||||||
"Сросшиеся пальцы",
|
|
||||||
"Слишком много пальцев",
|
|
||||||
"Дополнительные ноги",
|
|
||||||
"Плохие ноги"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Дополнительные модели": {
|
|
||||||
"Негативные модели": [
|
|
||||||
"AS-YoungV2-neg",
|
|
||||||
"BadDream",
|
|
||||||
"badhandv4",
|
|
||||||
"BadNegAnatomyV1-neg",
|
|
||||||
"EasyNegative",
|
|
||||||
"FastNegativeV2"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Словарь для перевода русских названий в английские
|
|
||||||
NEGATIVE_PROMPT_TRANSLATIONS = {
|
|
||||||
"Низкое качество": "low quality",
|
|
||||||
"Обычное качество": "normal quality",
|
|
||||||
"Худшее качество": "worstquality",
|
|
||||||
"Низкое разрешение": "lowres",
|
|
||||||
"Размытое": "blurry",
|
|
||||||
"Не в фокусе": "out of focus",
|
|
||||||
"Логотип": "logo",
|
|
||||||
"Текст": "text",
|
|
||||||
"Подпись": "signature",
|
|
||||||
"Водяной знак": "watermark",
|
|
||||||
"Обрезанное": "cropped",
|
|
||||||
"Монохромное": "monochrome",
|
|
||||||
"Оттенки серого": "grayscale",
|
|
||||||
"Нецензурный контент": "NSFW content",
|
|
||||||
"NSFW": "NSFW",
|
|
||||||
"Удалить взрослых": "(AS-YoungV2-Neg:1.3)",
|
|
||||||
"Удалить молодых": "(AS-Adult-Neg:1.3)",
|
|
||||||
"Неправильная анатомия": "bad anatomy",
|
|
||||||
"Плохое тело": "bad body",
|
|
||||||
"Длинное тело": "long body",
|
|
||||||
"Длинная шея": "long neck",
|
|
||||||
"Неправильные пропорции": "bad proportions",
|
|
||||||
"Деформированный": "deformed",
|
|
||||||
"Мутировавший": "mutated",
|
|
||||||
"Мутация": "mutation",
|
|
||||||
"Уродливый": "ugly",
|
|
||||||
"Испорченный": "disfigured",
|
|
||||||
"Плохо нарисованное лицо": "poorly drawn face",
|
|
||||||
"Пятна на коже": "skin blemishes",
|
|
||||||
"Веснушки": "skin spots",
|
|
||||||
"Прыщи": "acnes",
|
|
||||||
"Косоглазый": "cross-eyed",
|
|
||||||
"Отсутствующая конечность": "missing limb",
|
|
||||||
"Деформированные конечности": "malformed limbs",
|
|
||||||
"Плавающие конечности": "floating limbs",
|
|
||||||
"Отсоединенные конечности": "disconnected limbs",
|
|
||||||
"Дополнительная конечность": "extra limb",
|
|
||||||
"Дополнительные руки": "extra arms",
|
|
||||||
"Мутировавшие руки": "mutated hands",
|
|
||||||
"Плохо нарисованные руки": "poorly drawn hands",
|
|
||||||
"Деформированные руки": "malformed hands",
|
|
||||||
"Мутировавшие руки и пальцы": "mutated hands and fingers",
|
|
||||||
"Плохие руки": "bad hands",
|
|
||||||
"Отсутствующие пальцы": "missing fingers",
|
|
||||||
"Сросшиеся пальцы": "fused fingers",
|
|
||||||
"Слишком много пальцев": "too many fingers",
|
|
||||||
"Дополнительные ноги": "extra legs",
|
|
||||||
"Плохие ноги": "bad feet",
|
|
||||||
"AS-YoungV2-neg": "AS-YoungV2-neg",
|
|
||||||
"BadDream": "BadDream",
|
|
||||||
"badhandv4": "badhandv4",
|
|
||||||
"BadNegAnatomyV1-neg": "BadNegAnatomyV1-neg",
|
|
||||||
"EasyNegative": "EasyNegative",
|
|
||||||
"FastNegativeV2": "FastNegativeV2"
|
|
||||||
}
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QPushButton,
|
|
||||||
QLineEdit, QLabel, QScrollArea, QWidget, QCheckBox, QFrame)
|
|
||||||
from PyQt6.QtCore import Qt, pyqtSignal
|
|
||||||
from .negative_prompt_categories import NEGATIVE_PROMPT_CATEGORIES, NEGATIVE_PROMPT_TRANSLATIONS
|
|
||||||
|
|
||||||
class NegativePromptWindow(QDialog):
|
|
||||||
prompt_selected = pyqtSignal(str)
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setWindowTitle("Негативные промпты")
|
|
||||||
self.setModal(False)
|
|
||||||
self.selected_prompts = set()
|
|
||||||
self.setup_ui()
|
|
||||||
self.load_categories()
|
|
||||||
|
|
||||||
def setup_ui(self):
|
|
||||||
self.setStyleSheet("""
|
|
||||||
QDialog {
|
|
||||||
background-color: #2b2b2b;
|
|
||||||
min-width: 1700px;
|
|
||||||
min-height: 800px;
|
|
||||||
}
|
|
||||||
QScrollArea {
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
border: 1px solid #3b3b3b;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
QScrollArea > QWidget > QWidget {
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
}
|
|
||||||
QLabel {
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 8px;
|
|
||||||
background-color: #3b3b3b;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
QCheckBox {
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 4px;
|
|
||||||
spacing: 8px;
|
|
||||||
}
|
|
||||||
QCheckBox::indicator {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
QCheckBox::indicator:unchecked {
|
|
||||||
border: 2px solid #555555;
|
|
||||||
background-color: #3b3b3b;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
QCheckBox::indicator:checked {
|
|
||||||
border: 2px solid #dc3545;
|
|
||||||
background-color: #dc3545;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
QCheckBox::indicator:hover {
|
|
||||||
border-color: #bb2d3b;
|
|
||||||
}
|
|
||||||
QPushButton {
|
|
||||||
background-color: #dc3545;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 8px 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
min-width: 120px;
|
|
||||||
}
|
|
||||||
QPushButton:hover {
|
|
||||||
background-color: #bb2d3b;
|
|
||||||
}
|
|
||||||
QPushButton:pressed {
|
|
||||||
background-color: #a52834;
|
|
||||||
}
|
|
||||||
QLineEdit {
|
|
||||||
background-color: #3b3b3b;
|
|
||||||
color: white;
|
|
||||||
border: 1px solid #555555;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 8px;
|
|
||||||
font-size: 14px;
|
|
||||||
min-height: 24px;
|
|
||||||
}
|
|
||||||
QFrame {
|
|
||||||
background-color: #1e1e1e;
|
|
||||||
border: 1px solid #3b3b3b;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
|
||||||
|
|
||||||
# Поиск
|
|
||||||
search_layout = QHBoxLayout()
|
|
||||||
search_label = QLabel("Поиск:")
|
|
||||||
self.search_input = QLineEdit()
|
|
||||||
self.search_input.textChanged.connect(self.filter_prompts)
|
|
||||||
search_layout.addWidget(search_label)
|
|
||||||
search_layout.addWidget(self.search_input)
|
|
||||||
layout.addLayout(search_layout)
|
|
||||||
|
|
||||||
# Горизонтальная прокрутка для категорий
|
|
||||||
categories_scroll = QScrollArea()
|
|
||||||
categories_scroll.setWidgetResizable(True)
|
|
||||||
categories_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
|
||||||
categories_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
||||||
|
|
||||||
categories_widget = QWidget()
|
|
||||||
self.categories_layout = QHBoxLayout(categories_widget)
|
|
||||||
self.categories_layout.setSpacing(10)
|
|
||||||
categories_scroll.setWidget(categories_widget)
|
|
||||||
|
|
||||||
layout.addWidget(categories_scroll)
|
|
||||||
|
|
||||||
# Кнопки
|
|
||||||
buttons_layout = QHBoxLayout()
|
|
||||||
add_button = QPushButton("Добавить выбранные")
|
|
||||||
add_button.clicked.connect(self.add_selected)
|
|
||||||
close_button = QPushButton("Закрыть")
|
|
||||||
close_button.clicked.connect(self.close)
|
|
||||||
buttons_layout.addWidget(add_button)
|
|
||||||
buttons_layout.addWidget(close_button)
|
|
||||||
layout.addLayout(buttons_layout)
|
|
||||||
|
|
||||||
def load_categories(self):
|
|
||||||
"""Загрузка категорий и промптов"""
|
|
||||||
for category, subcategories in NEGATIVE_PROMPT_CATEGORIES.items():
|
|
||||||
# Создаем фрейм для категории
|
|
||||||
category_frame = QFrame()
|
|
||||||
category_layout = QVBoxLayout(category_frame)
|
|
||||||
category_layout.setSpacing(5)
|
|
||||||
|
|
||||||
# Добавляем заголовок категории
|
|
||||||
category_label = QLabel(category)
|
|
||||||
category_layout.addWidget(category_label)
|
|
||||||
|
|
||||||
# Создаем скролл для подкатегорий
|
|
||||||
subcategories_scroll = QScrollArea()
|
|
||||||
subcategories_scroll.setWidgetResizable(True)
|
|
||||||
subcategories_widget = QWidget()
|
|
||||||
subcategories_layout = QVBoxLayout(subcategories_widget)
|
|
||||||
|
|
||||||
for subcategory, prompts in subcategories.items():
|
|
||||||
# Добавляем заголовок подкатегории
|
|
||||||
subcategory_label = QLabel(subcategory)
|
|
||||||
subcategories_layout.addWidget(subcategory_label)
|
|
||||||
|
|
||||||
# Добавляем чекбоксы для промптов
|
|
||||||
for prompt in prompts:
|
|
||||||
checkbox = QCheckBox(prompt)
|
|
||||||
checkbox.stateChanged.connect(lambda state, p=prompt: self.on_checkbox_changed(state, p))
|
|
||||||
subcategories_layout.addWidget(checkbox)
|
|
||||||
|
|
||||||
subcategories_scroll.setWidget(subcategories_widget)
|
|
||||||
category_layout.addWidget(subcategories_scroll)
|
|
||||||
|
|
||||||
# Добавляем категорию в горизонтальный layout
|
|
||||||
self.categories_layout.addWidget(category_frame)
|
|
||||||
|
|
||||||
def on_checkbox_changed(self, state, prompt):
|
|
||||||
"""Обработка изменения состояния чекбокса"""
|
|
||||||
if state == Qt.CheckState.Checked.value:
|
|
||||||
self.selected_prompts.add(prompt)
|
|
||||||
else:
|
|
||||||
self.selected_prompts.discard(prompt)
|
|
||||||
|
|
||||||
def filter_prompts(self, text):
|
|
||||||
"""Фильтрация промптов по поисковому запросу"""
|
|
||||||
text = text.lower()
|
|
||||||
for i in range(self.categories_layout.count()):
|
|
||||||
category_frame = self.categories_layout.itemAt(i).widget()
|
|
||||||
for j in range(category_frame.layout().count()):
|
|
||||||
widget = category_frame.layout().itemAt(j).widget()
|
|
||||||
if isinstance(widget, QScrollArea):
|
|
||||||
scroll_widget = widget.widget()
|
|
||||||
for k in range(scroll_widget.layout().count()):
|
|
||||||
sub_widget = scroll_widget.layout().itemAt(k).widget()
|
|
||||||
if isinstance(sub_widget, QCheckBox):
|
|
||||||
sub_widget.setVisible(text in sub_widget.text().lower())
|
|
||||||
elif isinstance(sub_widget, QLabel):
|
|
||||||
# Показываем/скрываем заголовок подкатегории в зависимости от видимости его промптов
|
|
||||||
has_visible_prompts = False
|
|
||||||
for l in range(k + 1, scroll_widget.layout().count()):
|
|
||||||
next_widget = scroll_widget.layout().itemAt(l).widget()
|
|
||||||
if isinstance(next_widget, QCheckBox) and next_widget.isVisible():
|
|
||||||
has_visible_prompts = True
|
|
||||||
break
|
|
||||||
sub_widget.setVisible(has_visible_prompts)
|
|
||||||
|
|
||||||
def add_selected(self):
|
|
||||||
"""Добавление выбранных промптов"""
|
|
||||||
if self.selected_prompts:
|
|
||||||
# Преобразуем русские названия в английские
|
|
||||||
translated_prompts = [NEGATIVE_PROMPT_TRANSLATIONS.get(prompt, prompt) for prompt in self.selected_prompts]
|
|
||||||
prompts_text = ", ".join(sorted(translated_prompts))
|
|
||||||
self.prompt_selected.emit(prompts_text)
|
|
||||||
@@ -1,316 +0,0 @@
|
|||||||
PROMPT_TRANSLATIONS = {
|
|
||||||
# Персонажи
|
|
||||||
"Девушка": "girl",
|
|
||||||
"Парень": "boy",
|
|
||||||
"Мужчина": "man",
|
|
||||||
"Женщина": "woman",
|
|
||||||
"Ребенок": "child",
|
|
||||||
"Малыш": "baby",
|
|
||||||
"Пожилой человек": "elderly person",
|
|
||||||
"Старик": "old man",
|
|
||||||
"Старушка": "old woman",
|
|
||||||
|
|
||||||
# Профессии
|
|
||||||
"Художник": "artist",
|
|
||||||
"Музыкант": "musician",
|
|
||||||
"Писатель": "writer",
|
|
||||||
"Учитель": "teacher",
|
|
||||||
"Врач": "doctor",
|
|
||||||
"Инженер": "engineer",
|
|
||||||
"Программист": "programmer",
|
|
||||||
"Повар": "chef",
|
|
||||||
"Полицейский": "police officer",
|
|
||||||
"Пожарный": "firefighter",
|
|
||||||
|
|
||||||
# Животные
|
|
||||||
"Кошка": "cat",
|
|
||||||
"Собака": "dog",
|
|
||||||
"Птица": "bird",
|
|
||||||
"Рыба": "fish",
|
|
||||||
"Лошадь": "horse",
|
|
||||||
"Корова": "cow",
|
|
||||||
"Овца": "sheep",
|
|
||||||
"Коза": "goat",
|
|
||||||
"Кролик": "rabbit",
|
|
||||||
"Хомяк": "hamster",
|
|
||||||
|
|
||||||
# Природа
|
|
||||||
"Гора": "mountain",
|
|
||||||
"Море": "sea",
|
|
||||||
"Океан": "ocean",
|
|
||||||
"Река": "river",
|
|
||||||
"Лес": "forest",
|
|
||||||
"Поле": "field",
|
|
||||||
"Цветок": "flower",
|
|
||||||
"Дерево": "tree",
|
|
||||||
"Трава": "grass",
|
|
||||||
"Песок": "sand",
|
|
||||||
|
|
||||||
# Погода
|
|
||||||
"Солнце": "sun",
|
|
||||||
"Дождь": "rain",
|
|
||||||
"Снег": "snow",
|
|
||||||
"Ветер": "wind",
|
|
||||||
"Туман": "fog",
|
|
||||||
"Облако": "cloud",
|
|
||||||
"Гроза": "thunderstorm",
|
|
||||||
"Радуга": "rainbow",
|
|
||||||
"Мороз": "frost",
|
|
||||||
"Иней": "hoarfrost",
|
|
||||||
|
|
||||||
# Время суток
|
|
||||||
"Утро": "morning",
|
|
||||||
"День": "day",
|
|
||||||
"Вечер": "evening",
|
|
||||||
"Ночь": "night",
|
|
||||||
"Рассвет": "dawn",
|
|
||||||
"Закат": "sunset",
|
|
||||||
"Полдень": "noon",
|
|
||||||
"Полночь": "midnight",
|
|
||||||
|
|
||||||
# Сезоны
|
|
||||||
"Весна": "spring",
|
|
||||||
"Лето": "summer",
|
|
||||||
"Осень": "autumn",
|
|
||||||
"Зима": "winter",
|
|
||||||
|
|
||||||
# Эмоции
|
|
||||||
"Счастье": "happiness",
|
|
||||||
"Грусть": "sadness",
|
|
||||||
"Гнев": "anger",
|
|
||||||
"Страх": "fear",
|
|
||||||
"Удивление": "surprise",
|
|
||||||
"Отвращение": "disgust",
|
|
||||||
"Любовь": "love",
|
|
||||||
"Ненависть": "hate",
|
|
||||||
"Спокойствие": "calmness",
|
|
||||||
"Волнение": "excitement",
|
|
||||||
|
|
||||||
# Действия
|
|
||||||
"Бег": "running",
|
|
||||||
"Ходьба": "walking",
|
|
||||||
"Прыжок": "jumping",
|
|
||||||
"Плавание": "swimming",
|
|
||||||
"Танцы": "dancing",
|
|
||||||
"Пение": "singing",
|
|
||||||
"Игра": "playing",
|
|
||||||
"Работа": "working",
|
|
||||||
"Отдых": "resting",
|
|
||||||
"Сон": "sleeping",
|
|
||||||
|
|
||||||
# Одежда
|
|
||||||
"Платье": "dress",
|
|
||||||
"Рубашка": "shirt",
|
|
||||||
"Брюки": "pants",
|
|
||||||
"Юбка": "skirt",
|
|
||||||
"Куртка": "jacket",
|
|
||||||
"Пальто": "coat",
|
|
||||||
"Шапка": "hat",
|
|
||||||
"Обувь": "shoes",
|
|
||||||
"Перчатки": "gloves",
|
|
||||||
"Шарф": "scarf",
|
|
||||||
|
|
||||||
# Цвета
|
|
||||||
"Красный": "red",
|
|
||||||
"Синий": "blue",
|
|
||||||
"Зеленый": "green",
|
|
||||||
"Желтый": "yellow",
|
|
||||||
"Белый": "white",
|
|
||||||
"Черный": "black",
|
|
||||||
"Серый": "gray",
|
|
||||||
"Коричневый": "brown",
|
|
||||||
"Оранжевый": "orange",
|
|
||||||
"Фиолетовый": "purple",
|
|
||||||
|
|
||||||
# Материалы
|
|
||||||
"Дерево": "wood",
|
|
||||||
"Металл": "metal",
|
|
||||||
"Стекло": "glass",
|
|
||||||
"Пластик": "plastic",
|
|
||||||
"Ткань": "fabric",
|
|
||||||
"Бумага": "paper",
|
|
||||||
"Камень": "stone",
|
|
||||||
"Керамика": "ceramics",
|
|
||||||
"Кожа": "leather",
|
|
||||||
"Резина": "rubber",
|
|
||||||
|
|
||||||
# Технологии
|
|
||||||
"Компьютер": "computer",
|
|
||||||
"Телефон": "phone",
|
|
||||||
"Планшет": "tablet",
|
|
||||||
"Робот": "robot",
|
|
||||||
"Дрон": "drone",
|
|
||||||
"Смартфон": "smartphone",
|
|
||||||
"Ноутбук": "laptop",
|
|
||||||
"Принтер": "printer",
|
|
||||||
"Камера": "camera",
|
|
||||||
"Наушники": "headphones",
|
|
||||||
|
|
||||||
# Транспорт
|
|
||||||
"Машина": "car",
|
|
||||||
"Велосипед": "bicycle",
|
|
||||||
"Мотоцикл": "motorcycle",
|
|
||||||
"Поезд": "train",
|
|
||||||
"Самолет": "airplane",
|
|
||||||
"Корабль": "ship",
|
|
||||||
"Автобус": "bus",
|
|
||||||
"Трамвай": "tram",
|
|
||||||
"Метро": "subway",
|
|
||||||
"Вертолет": "helicopter",
|
|
||||||
|
|
||||||
# Еда
|
|
||||||
"Фрукты": "fruits",
|
|
||||||
"Овощи": "vegetables",
|
|
||||||
"Мясо": "meat",
|
|
||||||
"Рыба": "fish",
|
|
||||||
"Хлеб": "bread",
|
|
||||||
"Молоко": "milk",
|
|
||||||
"Сок": "juice",
|
|
||||||
"Кофе": "coffee",
|
|
||||||
"Чай": "tea",
|
|
||||||
"Сладости": "sweets",
|
|
||||||
|
|
||||||
# Дом
|
|
||||||
"Дом": "house",
|
|
||||||
"Квартира": "apartment",
|
|
||||||
"Комната": "room",
|
|
||||||
"Кухня": "kitchen",
|
|
||||||
"Спальня": "bedroom",
|
|
||||||
"Ванная": "bathroom",
|
|
||||||
"Гостиная": "living room",
|
|
||||||
"Балкон": "balcony",
|
|
||||||
"Подвал": "basement",
|
|
||||||
"Чердак": "attic",
|
|
||||||
|
|
||||||
# Музыка
|
|
||||||
"Гитара": "guitar",
|
|
||||||
"Пианино": "piano",
|
|
||||||
"Скрипка": "violin",
|
|
||||||
"Барабаны": "drums",
|
|
||||||
"Флейта": "flute",
|
|
||||||
"Саксофон": "saxophone",
|
|
||||||
"Труба": "trumpet",
|
|
||||||
"Бас": "bass",
|
|
||||||
"Синтезатор": "synthesizer",
|
|
||||||
"Микрофон": "microphone",
|
|
||||||
|
|
||||||
# Спорт
|
|
||||||
"Футбол": "football",
|
|
||||||
"Баскетбол": "basketball",
|
|
||||||
"Волейбол": "volleyball",
|
|
||||||
"Теннис": "tennis",
|
|
||||||
"Хоккей": "hockey",
|
|
||||||
"Бег": "running",
|
|
||||||
"Плавание": "swimming",
|
|
||||||
"Бокс": "boxing",
|
|
||||||
"Йога": "yoga",
|
|
||||||
"Гимнастика": "gymnastics",
|
|
||||||
|
|
||||||
# Искусство
|
|
||||||
"Картина": "painting",
|
|
||||||
"Рисунок": "drawing",
|
|
||||||
"Скульптура": "sculpture",
|
|
||||||
"Фотография": "photography",
|
|
||||||
"Кино": "movie",
|
|
||||||
"Театр": "theater",
|
|
||||||
"Музыка": "music",
|
|
||||||
"Танец": "dance",
|
|
||||||
"Поэзия": "poetry",
|
|
||||||
"Литература": "literature",
|
|
||||||
|
|
||||||
# Наука
|
|
||||||
"Физика": "physics",
|
|
||||||
"Химия": "chemistry",
|
|
||||||
"Биология": "biology",
|
|
||||||
"Математика": "mathematics",
|
|
||||||
"Астрономия": "astronomy",
|
|
||||||
"Геология": "geology",
|
|
||||||
"Экология": "ecology",
|
|
||||||
"Психология": "psychology",
|
|
||||||
"История": "history",
|
|
||||||
"География": "geography",
|
|
||||||
|
|
||||||
# Время
|
|
||||||
"Секунда": "second",
|
|
||||||
"Минута": "minute",
|
|
||||||
"Час": "hour",
|
|
||||||
"День": "day",
|
|
||||||
"Неделя": "week",
|
|
||||||
"Месяц": "month",
|
|
||||||
"Год": "year",
|
|
||||||
"Век": "century",
|
|
||||||
"Эпоха": "era",
|
|
||||||
"Период": "period",
|
|
||||||
|
|
||||||
# География
|
|
||||||
"Страна": "country",
|
|
||||||
"Город": "city",
|
|
||||||
"Деревня": "village",
|
|
||||||
"Река": "river",
|
|
||||||
"Озеро": "lake",
|
|
||||||
"Море": "sea",
|
|
||||||
"Океан": "ocean",
|
|
||||||
"Гора": "mountain",
|
|
||||||
"Пустыня": "desert",
|
|
||||||
"Джунгли": "jungle",
|
|
||||||
|
|
||||||
# Космос
|
|
||||||
"Солнце": "sun",
|
|
||||||
"Луна": "moon",
|
|
||||||
"Звезда": "star",
|
|
||||||
"Планета": "planet",
|
|
||||||
"Галактика": "galaxy",
|
|
||||||
"Вселенная": "universe",
|
|
||||||
"Астероид": "asteroid",
|
|
||||||
"Комета": "comet",
|
|
||||||
"Спутник": "satellite",
|
|
||||||
"Космический корабль": "spaceship",
|
|
||||||
|
|
||||||
# Фэнтези
|
|
||||||
"Дракон": "dragon",
|
|
||||||
"Единорог": "unicorn",
|
|
||||||
"Фея": "fairy",
|
|
||||||
"Волшебник": "wizard",
|
|
||||||
"Ведьма": "witch",
|
|
||||||
"Гоблин": "goblin",
|
|
||||||
"Эльф": "elf",
|
|
||||||
"Гном": "dwarf",
|
|
||||||
"Орк": "orc",
|
|
||||||
"Тролль": "troll",
|
|
||||||
|
|
||||||
# Мифология
|
|
||||||
"Бог": "god",
|
|
||||||
"Богиня": "goddess",
|
|
||||||
"Герой": "hero",
|
|
||||||
"Миф": "myth",
|
|
||||||
"Легенда": "legend",
|
|
||||||
"Демон": "demon",
|
|
||||||
"Ангел": "angel",
|
|
||||||
"Призрак": "ghost",
|
|
||||||
"Вампир": "vampire",
|
|
||||||
"Оборотень": "werewolf",
|
|
||||||
|
|
||||||
# Стили искусства
|
|
||||||
"Реализм": "realism",
|
|
||||||
"Импрессионизм": "impressionism",
|
|
||||||
"Экспрессионизм": "expressionism",
|
|
||||||
"Сюрреализм": "surrealism",
|
|
||||||
"Абстракционизм": "abstract art",
|
|
||||||
"Поп-арт": "pop art",
|
|
||||||
"Модернизм": "modernism",
|
|
||||||
"Постмодернизм": "postmodernism",
|
|
||||||
"Кубизм": "cubism",
|
|
||||||
"Футуризм": "futurism",
|
|
||||||
|
|
||||||
# Эпохи
|
|
||||||
"Древний мир": "ancient world",
|
|
||||||
"Средневековье": "middle ages",
|
|
||||||
"Ренессанс": "renaissance",
|
|
||||||
"Барокко": "baroque",
|
|
||||||
"Классицизм": "classicism",
|
|
||||||
"Романтизм": "romanticism",
|
|
||||||
"Викторианская эпоха": "victorian era",
|
|
||||||
"Модерн": "art nouveau",
|
|
||||||
"Ар-деко": "art deco",
|
|
||||||
"Современность": "modern era"
|
|
||||||
}
|
|
||||||
+67
-48
@@ -3,7 +3,6 @@ from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QTreeWidget,
|
|||||||
QScrollArea, QWidget, QCheckBox, QFrame)
|
QScrollArea, QWidget, QCheckBox, QFrame)
|
||||||
from PyQt6.QtCore import Qt, pyqtSignal
|
from PyQt6.QtCore import Qt, pyqtSignal
|
||||||
from .prompt_categories import PROMPT_CATEGORIES
|
from .prompt_categories import PROMPT_CATEGORIES
|
||||||
from .prompt_translations import PROMPT_TRANSLATIONS
|
|
||||||
|
|
||||||
class PromptWindow(QDialog):
|
class PromptWindow(QDialog):
|
||||||
prompt_selected = pyqtSignal(str)
|
prompt_selected = pyqtSignal(str)
|
||||||
@@ -19,87 +18,105 @@ class PromptWindow(QDialog):
|
|||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
self.setStyleSheet("""
|
self.setStyleSheet("""
|
||||||
QDialog {
|
QDialog {
|
||||||
background-color: #2b2b2b;
|
background-color: #1e1e1e;
|
||||||
min-width: 1500px;
|
min-width: 1200px;
|
||||||
min-height: 700px;
|
min-height: 800px;
|
||||||
}
|
}
|
||||||
QScrollArea {
|
QScrollArea {
|
||||||
background-color: #1e1e1e;
|
background-color: #252526;
|
||||||
border: 1px solid #3b3b3b;
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
padding: 8px;
|
|
||||||
}
|
}
|
||||||
QScrollArea > QWidget > QWidget {
|
QScrollArea > QWidget > QWidget {
|
||||||
background-color: #1e1e1e;
|
background-color: #252526;
|
||||||
}
|
}
|
||||||
QLabel {
|
QLabel {
|
||||||
color: #ffffff;
|
color: #d4d4d4;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: 600;
|
||||||
padding: 8px;
|
padding: 12px;
|
||||||
background-color: #3b3b3b;
|
background-color: #2d2d2d;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
QCheckBox {
|
QCheckBox {
|
||||||
color: #ffffff;
|
color: #d4d4d4;
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
padding: 4px;
|
padding: 6px;
|
||||||
spacing: 8px;
|
spacing: 8px;
|
||||||
}
|
}
|
||||||
|
QCheckBox:hover {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
QCheckBox::indicator {
|
QCheckBox::indicator {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
QCheckBox::indicator:unchecked {
|
QCheckBox::indicator:unchecked {
|
||||||
border: 2px solid #555555;
|
border: 2px solid #565656;
|
||||||
background-color: #3b3b3b;
|
background-color: #252526;
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
QCheckBox::indicator:checked {
|
QCheckBox::indicator:checked {
|
||||||
border: 2px solid #0d6efd;
|
border: 2px solid #007acc;
|
||||||
background-color: #0d6efd;
|
background-color: #007acc;
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
QCheckBox::indicator:hover {
|
QCheckBox::indicator:hover {
|
||||||
border-color: #0b5ed7;
|
border-color: #007acc;
|
||||||
}
|
}
|
||||||
QPushButton {
|
QPushButton {
|
||||||
background-color: #0d6efd;
|
background-color: #2d2d2d;
|
||||||
color: white;
|
color: #d4d4d4;
|
||||||
border: none;
|
border: 1px solid #3e3e3e;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
font-weight: bold;
|
font-weight: 500;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
QPushButton:hover {
|
QPushButton:hover {
|
||||||
background-color: #0b5ed7;
|
background-color: #3e3e3e;
|
||||||
|
border-color: #565656;
|
||||||
}
|
}
|
||||||
QPushButton:pressed {
|
QPushButton:pressed {
|
||||||
background-color: #0a58ca;
|
background-color: #565656;
|
||||||
}
|
}
|
||||||
QLineEdit {
|
QLineEdit {
|
||||||
background-color: #3b3b3b;
|
background-color: #252526;
|
||||||
color: white;
|
color: #d4d4d4;
|
||||||
border: 1px solid #555555;
|
border: 1px solid #3e3e3e;
|
||||||
border-radius: 4px;
|
border-radius: 6px;
|
||||||
padding: 8px;
|
padding: 8px 12px;
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
min-height: 24px;
|
min-height: 32px;
|
||||||
|
}
|
||||||
|
QLineEdit:focus {
|
||||||
|
border-color: #007acc;
|
||||||
}
|
}
|
||||||
QFrame {
|
QFrame {
|
||||||
background-color: #1e1e1e;
|
background-color: #252526;
|
||||||
border: 1px solid #3b3b3b;
|
border: 1px solid #3e3e3e;
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
QFrame:hover {
|
||||||
|
border-color: #565656;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
|
layout.setContentsMargins(16, 16, 16, 16)
|
||||||
|
layout.setSpacing(12)
|
||||||
|
|
||||||
# Поиск
|
# Поиск
|
||||||
search_layout = QHBoxLayout()
|
search_layout = QHBoxLayout()
|
||||||
search_label = QLabel("Поиск:")
|
search_layout.setSpacing(8)
|
||||||
|
search_label = QLabel("🔍 Поиск:")
|
||||||
|
search_label.setStyleSheet("background: transparent; padding: 0;")
|
||||||
self.search_input = QLineEdit()
|
self.search_input = QLineEdit()
|
||||||
|
self.search_input.setPlaceholderText("Введите текст для поиска...")
|
||||||
self.search_input.textChanged.connect(self.filter_prompts)
|
self.search_input.textChanged.connect(self.filter_prompts)
|
||||||
search_layout.addWidget(search_label)
|
search_layout.addWidget(search_label)
|
||||||
search_layout.addWidget(self.search_input)
|
search_layout.addWidget(self.search_input)
|
||||||
@@ -110,22 +127,26 @@ class PromptWindow(QDialog):
|
|||||||
categories_scroll.setWidgetResizable(True)
|
categories_scroll.setWidgetResizable(True)
|
||||||
categories_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
categories_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
||||||
categories_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
categories_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||||
|
categories_scroll.setMinimumHeight(600)
|
||||||
|
|
||||||
categories_widget = QWidget()
|
categories_widget = QWidget()
|
||||||
self.categories_layout = QHBoxLayout(categories_widget)
|
self.categories_layout = QHBoxLayout(categories_widget)
|
||||||
self.categories_layout.setSpacing(10)
|
self.categories_layout.setSpacing(12)
|
||||||
|
self.categories_layout.setContentsMargins(12, 12, 12, 12)
|
||||||
categories_scroll.setWidget(categories_widget)
|
categories_scroll.setWidget(categories_widget)
|
||||||
|
|
||||||
layout.addWidget(categories_scroll)
|
layout.addWidget(categories_scroll)
|
||||||
|
|
||||||
# Кнопки
|
# Кнопки
|
||||||
buttons_layout = QHBoxLayout()
|
buttons_layout = QHBoxLayout()
|
||||||
add_button = QPushButton("Добавить выбранные")
|
buttons_layout.setSpacing(8)
|
||||||
|
add_button = QPushButton("✨ Добавить выбранные")
|
||||||
add_button.clicked.connect(self.add_selected)
|
add_button.clicked.connect(self.add_selected)
|
||||||
close_button = QPushButton("Закрыть")
|
close_button = QPushButton("❌ Закрыть")
|
||||||
close_button.clicked.connect(self.close)
|
close_button.clicked.connect(self.close)
|
||||||
buttons_layout.addWidget(add_button)
|
buttons_layout.addWidget(add_button)
|
||||||
buttons_layout.addWidget(close_button)
|
buttons_layout.addWidget(close_button)
|
||||||
|
buttons_layout.addStretch()
|
||||||
layout.addLayout(buttons_layout)
|
layout.addLayout(buttons_layout)
|
||||||
|
|
||||||
def load_categories(self):
|
def load_categories(self):
|
||||||
@@ -196,7 +217,5 @@ class PromptWindow(QDialog):
|
|||||||
def add_selected(self):
|
def add_selected(self):
|
||||||
"""Добавление выбранных промптов"""
|
"""Добавление выбранных промптов"""
|
||||||
if self.selected_prompts:
|
if self.selected_prompts:
|
||||||
# Преобразуем русские названия в английские
|
prompts_text = ", ".join(sorted(self.selected_prompts))
|
||||||
translated_prompts = [PROMPT_TRANSLATIONS.get(prompt, prompt) for prompt in self.selected_prompts]
|
|
||||||
prompts_text = ", ".join(sorted(translated_prompts))
|
|
||||||
self.prompt_selected.emit(prompts_text)
|
self.prompt_selected.emit(prompts_text)
|
||||||
@@ -13,8 +13,50 @@ class SamplerManager(QWidget):
|
|||||||
self.load_samplers()
|
self.load_samplers()
|
||||||
|
|
||||||
def setup_ui(self):
|
def setup_ui(self):
|
||||||
|
self.setStyleSheet("""
|
||||||
|
QWidget {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
QLabel {
|
||||||
|
color: #d4d4d4;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
QComboBox {
|
||||||
|
background-color: #252526;
|
||||||
|
color: #d4d4d4;
|
||||||
|
border: 1px solid #3e3e3e;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
min-width: 180px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
QComboBox:hover {
|
||||||
|
border-color: #565656;
|
||||||
|
}
|
||||||
|
QComboBox:focus {
|
||||||
|
border-color: #007acc;
|
||||||
|
}
|
||||||
|
QComboBox::drop-down {
|
||||||
|
border: none;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
QComboBox::down-arrow {
|
||||||
|
image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTggMTFMNCBTTDEyIDUiIHN0cm9rZT0iI2Q0ZDRkNCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+);
|
||||||
|
}
|
||||||
|
QComboBox QAbstractItemView {
|
||||||
|
background-color: #252526;
|
||||||
|
color: #d4d4d4;
|
||||||
|
border: 1px solid #3e3e3e;
|
||||||
|
selection-background-color: #094771;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
|
||||||
layout = QHBoxLayout(self)
|
layout = QHBoxLayout(self)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
layout.setSpacing(8)
|
||||||
|
|
||||||
# Метка
|
# Метка
|
||||||
label = QLabel("Сэмплер:")
|
label = QLabel("Сэмплер:")
|
||||||
@@ -22,6 +64,7 @@ class SamplerManager(QWidget):
|
|||||||
|
|
||||||
# Выпадающий список сэмплеров
|
# Выпадающий список сэмплеров
|
||||||
self.sampler_combo = QComboBox()
|
self.sampler_combo = QComboBox()
|
||||||
|
self.sampler_combo.setFixedHeight(32)
|
||||||
self.sampler_combo.currentTextChanged.connect(self.on_sampler_changed)
|
self.sampler_combo.currentTextChanged.connect(self.on_sampler_changed)
|
||||||
layout.addWidget(self.sampler_combo)
|
layout.addWidget(self.sampler_combo)
|
||||||
|
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFrame
|
|
||||||
from PyQt6.QtCore import Qt, pyqtSignal
|
|
||||||
from .size_presets import SIZE_PRESETS
|
|
||||||
|
|
||||||
class SizePresetManager(QWidget):
|
|
||||||
size_changed = pyqtSignal(int, int) # Сигнал для изменения размера
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setup_ui()
|
|
||||||
|
|
||||||
def setup_ui(self):
|
|
||||||
layout = QVBoxLayout(self)
|
|
||||||
layout.setSpacing(2)
|
|
||||||
|
|
||||||
# Заголовок
|
|
||||||
title = QLabel("Размеры:")
|
|
||||||
title.setStyleSheet("""
|
|
||||||
QLabel {
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 4px;
|
|
||||||
background-color: #3b3b3b;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
layout.addWidget(title)
|
|
||||||
|
|
||||||
# Создаем фрейм для кнопок
|
|
||||||
buttons_frame = QFrame()
|
|
||||||
buttons_frame.setStyleSheet("""
|
|
||||||
QFrame {
|
|
||||||
background-color: #2b2b2b;
|
|
||||||
border: 1px solid #3b3b3b;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 2px;
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
buttons_layout = QVBoxLayout(buttons_frame)
|
|
||||||
buttons_layout.setSpacing(2)
|
|
||||||
|
|
||||||
# Создаем две строки кнопок
|
|
||||||
row1_layout = QHBoxLayout()
|
|
||||||
row2_layout = QHBoxLayout()
|
|
||||||
|
|
||||||
# Разделяем пресеты на две группы
|
|
||||||
presets = list(SIZE_PRESETS.items())
|
|
||||||
half = len(presets) // 2
|
|
||||||
|
|
||||||
# Добавляем кнопки в первую строку
|
|
||||||
for name, (width, height) in presets[:half]:
|
|
||||||
button = self.create_preset_button(name, width, height)
|
|
||||||
row1_layout.addWidget(button)
|
|
||||||
|
|
||||||
# Добавляем кнопки во вторую строку
|
|
||||||
for name, (width, height) in presets[half:]:
|
|
||||||
button = self.create_preset_button(name, width, height)
|
|
||||||
row2_layout.addWidget(button)
|
|
||||||
|
|
||||||
buttons_layout.addLayout(row1_layout)
|
|
||||||
buttons_layout.addLayout(row2_layout)
|
|
||||||
layout.addWidget(buttons_frame)
|
|
||||||
|
|
||||||
def create_preset_button(self, name, width, height):
|
|
||||||
"""Создание кнопки пресета с улучшенным дизайном"""
|
|
||||||
button = QPushButton(name)
|
|
||||||
button.setStyleSheet(f"""
|
|
||||||
QPushButton {{
|
|
||||||
background-color: #3b3b3b;
|
|
||||||
color: white;
|
|
||||||
border: 1px solid #555555;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
min-width: 80px;
|
|
||||||
text-align: center;
|
|
||||||
}}
|
|
||||||
QPushButton:hover {{
|
|
||||||
background-color: #4a4a4a;
|
|
||||||
border-color: #666666;
|
|
||||||
}}
|
|
||||||
QPushButton:pressed {{
|
|
||||||
background-color: #0d6efd;
|
|
||||||
border-color: #0b5ed7;
|
|
||||||
}}
|
|
||||||
""")
|
|
||||||
button.clicked.connect(lambda checked, w=width, h=height: self.on_preset_clicked(w, h))
|
|
||||||
return button
|
|
||||||
|
|
||||||
def on_preset_clicked(self, width, height):
|
|
||||||
"""Обработчик нажатия на кнопку пресета"""
|
|
||||||
self.size_changed.emit(width, height)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
SIZE_PRESETS = {
|
|
||||||
"512x768": (512, 768),
|
|
||||||
"768x512": (768, 512),
|
|
||||||
"512x512": (512, 512),
|
|
||||||
"768x432": (768, 432),
|
|
||||||
"432x768": (432, 768),
|
|
||||||
"600x800": (600, 800)
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user