221 lines
8.4 KiB
Python
221 lines
8.4 KiB
Python
import sys
|
|
import json
|
|
import base64
|
|
import requests
|
|
import os
|
|
from time import sleep
|
|
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
|
|
QHBoxLayout, QLabel, QLineEdit, QPushButton,
|
|
QComboBox, QSpinBox, QDoubleSpinBox, QProgressBar,
|
|
QScrollArea, QTextEdit, QFileDialog, QMenuBar, QMenu)
|
|
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QTimer
|
|
from PyQt6.QtGui import QPixmap, QImage, QAction, QFontDatabase, QFont
|
|
from PIL import Image
|
|
from io import BytesIO
|
|
from pathlib import Path
|
|
from dotenv import load_dotenv
|
|
|
|
# Загружаем переменные окружения
|
|
load_dotenv()
|
|
|
|
# Импортируем модули
|
|
from modules.console_window import ConsoleWindow
|
|
from modules.model_manager import ModelManager
|
|
from modules.sampler_manager import SamplerManager
|
|
from modules.prompt_window import PromptWindow
|
|
from modules.negative_prompt_window import NegativePromptWindow
|
|
from modules.size_preset_manager import SizePresetManager
|
|
from modules.settings_menu import SettingsMenu
|
|
from modules.styles.base_window import BaseWindow
|
|
from modules.styles.navigation import NavigationPanel
|
|
from modules.styles.page import PageContainer
|
|
from modules.pages.home_page import HomePage
|
|
from modules.pages.models_page import ModelsPage
|
|
from modules.pages.settings_page import SettingsPage
|
|
from scripts.download_resources import download_font
|
|
|
|
class GenerationThread(QThread):
|
|
progress_updated = pyqtSignal(float, str)
|
|
generation_complete = pyqtSignal(list)
|
|
error_occurred = pyqtSignal(str)
|
|
|
|
def __init__(self, api_url, params):
|
|
super().__init__()
|
|
self.api_url = api_url
|
|
self.params = params
|
|
self.is_generating = False
|
|
|
|
def run(self):
|
|
try:
|
|
self.is_generating = True
|
|
self.progress_updated.emit(0, "Начало генерации...")
|
|
|
|
# Отправляем запрос на генерацию
|
|
response = requests.post(f"{self.api_url}/sdapi/v1/txt2img", json=self.params)
|
|
|
|
if response.status_code != 200:
|
|
self.error_occurred.emit(f"Ошибка API: {response.status_code}")
|
|
return
|
|
|
|
# Получаем результат
|
|
result = response.json()
|
|
images = result.get('images', [])
|
|
if not images:
|
|
self.error_occurred.emit("Не удалось получить изображения")
|
|
return
|
|
|
|
self.generation_complete.emit(images)
|
|
|
|
except Exception as e:
|
|
self.error_occurred.emit(f"Ошибка: {str(e)}")
|
|
finally:
|
|
self.is_generating = False
|
|
|
|
def stop(self):
|
|
self.is_generating = False
|
|
|
|
class MainWindow(BaseWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("Stable Diffusion UI")
|
|
self.setMinimumSize(1200, 800)
|
|
|
|
# Получаем URL API из переменных окружения
|
|
self.api_url = os.getenv('SD_API_URL', 'http://localhost:3000')
|
|
|
|
# Инициализируем менеджеры
|
|
self.model_manager = ModelManager(api_url=self.api_url)
|
|
self.sampler_manager = SamplerManager(api_url=self.api_url)
|
|
self.size_preset_manager = SizePresetManager()
|
|
|
|
# Инициализируем окна
|
|
self.prompt_window = PromptWindow()
|
|
self.negative_prompt_window = NegativePromptWindow()
|
|
self.console_window = ConsoleWindow()
|
|
|
|
self.setup_ui()
|
|
|
|
def setup_ui(self):
|
|
# Загружаем шрифт
|
|
font_path = Path("resources/fonts/InterVariable.ttf")
|
|
if not font_path.exists():
|
|
download_font()
|
|
font_id = QFontDatabase.addApplicationFont(str(font_path))
|
|
if font_id != -1:
|
|
font_family = QFontDatabase.applicationFontFamilies(font_id)[0]
|
|
app_font = QFont(font_family)
|
|
QApplication.setFont(app_font)
|
|
|
|
# Создаем центральный виджет
|
|
central_widget = QWidget()
|
|
self.setCentralWidget(central_widget)
|
|
main_layout = QVBoxLayout(central_widget)
|
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
main_layout.setSpacing(0)
|
|
|
|
# Создаем верхнюю панель
|
|
top_panel = QHBoxLayout()
|
|
|
|
# Кнопки для окон промптов
|
|
prompt_btn = QPushButton("Библиотека промптов")
|
|
prompt_btn.clicked.connect(self.show_prompt_window)
|
|
top_panel.addWidget(prompt_btn)
|
|
|
|
negative_prompt_btn = QPushButton("Негативные промпты")
|
|
negative_prompt_btn.clicked.connect(self.show_negative_prompt_window)
|
|
top_panel.addWidget(negative_prompt_btn)
|
|
|
|
# Пресеты разрешения
|
|
resolution_combo = QComboBox()
|
|
resolution_combo.addItems(self.size_preset_manager.get_preset_names())
|
|
resolution_combo.currentTextChanged.connect(self.on_resolution_changed)
|
|
top_panel.addWidget(resolution_combo)
|
|
|
|
# Кнопка консоли
|
|
console_btn = QPushButton("Консоль")
|
|
console_btn.clicked.connect(self.show_console)
|
|
top_panel.addWidget(console_btn)
|
|
|
|
top_panel.addStretch()
|
|
main_layout.addLayout(top_panel)
|
|
|
|
# Создаем горизонтальный layout для навигации и контента
|
|
content_layout = QHBoxLayout()
|
|
|
|
# Добавляем навигационную панель
|
|
self.nav_panel = NavigationPanel()
|
|
content_layout.addWidget(self.nav_panel)
|
|
|
|
# Создаем контейнер для страниц
|
|
self.page_container = PageContainer()
|
|
content_layout.addWidget(self.page_container)
|
|
|
|
main_layout.addLayout(content_layout)
|
|
|
|
# Добавляем страницы
|
|
self.home_page = HomePage(
|
|
model_manager=self.model_manager,
|
|
sampler_manager=self.sampler_manager,
|
|
size_preset_manager=self.size_preset_manager
|
|
)
|
|
self.models_page = ModelsPage(self.model_manager)
|
|
self.settings_page = SettingsPage()
|
|
|
|
self.page_container.add_page("home", self.home_page)
|
|
self.page_container.add_page("models", self.models_page)
|
|
self.page_container.add_page("settings", self.settings_page)
|
|
|
|
# Подключаем сигнал смены страницы
|
|
self.nav_panel.page_changed.connect(self.switch_page)
|
|
|
|
# Показываем домашнюю страницу по умолчанию
|
|
self.page_container.show_page("home")
|
|
|
|
# Загружаем данные
|
|
self.load_data()
|
|
|
|
def load_data(self):
|
|
"""Загрузка данных с сервера"""
|
|
try:
|
|
# Загружаем список моделей
|
|
self.model_manager.load_models()
|
|
|
|
# Загружаем список сэмплеров
|
|
self.sampler_manager.load_samplers()
|
|
|
|
# Обновляем интерфейс
|
|
self.home_page.update_ui()
|
|
self.models_page.update_ui()
|
|
|
|
except Exception as e:
|
|
self.console_window.log(f"Ошибка загрузки данных: {str(e)}", "ERROR")
|
|
|
|
def show_prompt_window(self):
|
|
"""Показать окно промптов"""
|
|
self.prompt_window.show()
|
|
|
|
def show_negative_prompt_window(self):
|
|
"""Показать окно негативных промптов"""
|
|
self.negative_prompt_window.show()
|
|
|
|
def show_console(self):
|
|
"""Показать консоль"""
|
|
self.console_window.show()
|
|
|
|
def on_resolution_changed(self, preset_name: str):
|
|
"""Обработка изменения пресета разрешения"""
|
|
preset = self.size_preset_manager.get_preset(preset_name)
|
|
if preset:
|
|
self.home_page.set_resolution(preset.width, preset.height)
|
|
|
|
def switch_page(self, page_name):
|
|
self.page_container.show_page(page_name)
|
|
|
|
def main():
|
|
app = QApplication(sys.argv)
|
|
window = MainWindow()
|
|
window.show()
|
|
sys.exit(app.exec())
|
|
|
|
if __name__ == "__main__":
|
|
main() |