Initial release: Comfy-Studio v1.0.0
Десктопная галерея и менеджер изображений ComfyUI (PyQt6 + SQLite): - мультипапочный мониторинг (watchdog), грид миниатюр, drag-and-drop - теги, избранное, рейтинг, поиск по промтам - парсер метаданных ComfyUI (PNG/WebP/JPEG), редактор workflow/prompt JSON - перевод выделенного текста через контекстное меню (настраиваемые языки) - отправка промта в очередь ComfyUI с внедрением правок и нового seed - полноэкранный просмотр, локализация ru/en, тёмная тема Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
"""
|
||||
Полноэкранный просмотрщик изображений.
|
||||
Стрелки ←/→ — листание, Esc / двойной клик — выход, колесо мыши — листание.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List
|
||||
|
||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel
|
||||
from PyQt6.QtGui import QPixmap, QKeyEvent
|
||||
from PyQt6.QtCore import Qt
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FullscreenViewer(QWidget):
|
||||
def __init__(self, filepaths: List[str], start_index: int = 0, parent=None):
|
||||
super().__init__(parent)
|
||||
self.filepaths = filepaths
|
||||
self.index = max(0, min(start_index, len(filepaths) - 1))
|
||||
|
||||
self.setWindowFlags(Qt.WindowType.Window | Qt.WindowType.FramelessWindowHint)
|
||||
self.setStyleSheet("background-color: #000000;")
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.image_label = QLabel()
|
||||
self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.image_label.setStyleSheet("background-color: #000000;")
|
||||
layout.addWidget(self.image_label, 1)
|
||||
|
||||
self.info_label = QLabel()
|
||||
self.info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.info_label.setStyleSheet(
|
||||
"color: #9e9e9e; background-color: #000000; padding: 6px; font-size: 12px;")
|
||||
layout.addWidget(self.info_label)
|
||||
|
||||
self._current_pixmap = None
|
||||
|
||||
def open_fullscreen(self):
|
||||
self.showFullScreen()
|
||||
self._load_current()
|
||||
|
||||
def _load_current(self):
|
||||
if not self.filepaths:
|
||||
return
|
||||
path = self.filepaths[self.index]
|
||||
pixmap = QPixmap(path)
|
||||
if pixmap.isNull():
|
||||
self.image_label.setText("⚠")
|
||||
self._current_pixmap = None
|
||||
else:
|
||||
self._current_pixmap = pixmap
|
||||
self._rescale()
|
||||
self.info_label.setText(f"{self.index + 1} / {len(self.filepaths)} — {path}")
|
||||
|
||||
def _rescale(self):
|
||||
if self._current_pixmap:
|
||||
scaled = self._current_pixmap.scaled(
|
||||
self.image_label.size(),
|
||||
Qt.AspectRatioMode.KeepAspectRatio,
|
||||
Qt.TransformationMode.SmoothTransformation
|
||||
)
|
||||
self.image_label.setPixmap(scaled)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
self._rescale()
|
||||
super().resizeEvent(event)
|
||||
|
||||
def keyPressEvent(self, event: QKeyEvent):
|
||||
key = event.key()
|
||||
if key == Qt.Key.Key_Escape:
|
||||
self.close()
|
||||
elif key in (Qt.Key.Key_Right, Qt.Key.Key_Down, Qt.Key.Key_Space):
|
||||
self._next()
|
||||
elif key in (Qt.Key.Key_Left, Qt.Key.Key_Up):
|
||||
self._prev()
|
||||
else:
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def wheelEvent(self, event):
|
||||
if event.angleDelta().y() < 0:
|
||||
self._next()
|
||||
else:
|
||||
self._prev()
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
self.close()
|
||||
|
||||
def _next(self):
|
||||
if self.index < len(self.filepaths) - 1:
|
||||
self.index += 1
|
||||
self._load_current()
|
||||
|
||||
def _prev(self):
|
||||
if self.index > 0:
|
||||
self.index -= 1
|
||||
self._load_current()
|
||||
Reference in New Issue
Block a user