feat(ai-studio): streamline final selection rails
This commit is contained in:
@@ -5,7 +5,7 @@ from __future__ import annotations
|
||||
import os
|
||||
|
||||
from PySide6.QtCore import QObject, QMimeData, QSize, Signal
|
||||
from PySide6.QtWidgets import QListView, QListWidget, QListWidgetItem
|
||||
from PySide6.QtWidgets import QListView, QListWidget, QListWidgetItem, QSizePolicy
|
||||
|
||||
from ... import accounts, appconfig, cmhub_models, db, image_studio, image_studio_export, image_studio_images, prompts
|
||||
from .. import file_manager
|
||||
@@ -136,6 +136,16 @@ class ImageStudioSelectionList(QListWidget):
|
||||
self.setDragDropMode(QAbstractItemView.DragDrop)
|
||||
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
||||
self.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
self.setViewMode(QListView.IconMode)
|
||||
self.setFlow(QListView.LeftToRight)
|
||||
self.setWrapping(False)
|
||||
self.setResizeMode(QListView.Fixed)
|
||||
self.setMovement(QListView.Static)
|
||||
self.setSpacing(4)
|
||||
self.setUniformItemSizes(True)
|
||||
self.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
|
||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
self.customContextMenuRequested.connect(self._show_context_menu)
|
||||
|
||||
def mimeData(self, items):
|
||||
@@ -332,7 +342,8 @@ class ImageStudioTab(QWidget):
|
||||
self.main_splitter.setStretchFactor(2, 2)
|
||||
self.main_splitter.setSizes([150, 640, 360])
|
||||
root.addWidget(self.main_splitter, 1)
|
||||
root.addWidget(self._build_final_panel(), 0)
|
||||
self.final_panel = self._build_final_panel()
|
||||
root.addWidget(self.final_panel, 0)
|
||||
self._apply_workspace_style()
|
||||
self._update_generation_action_text()
|
||||
|
||||
@@ -579,51 +590,68 @@ class ImageStudioTab(QWidget):
|
||||
def _build_final_panel(self):
|
||||
panel = QWidget()
|
||||
panel.setObjectName("imageStudioFinalPanel")
|
||||
layout = QHBoxLayout(panel)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(10)
|
||||
main_panel = QWidget()
|
||||
main_layout = QVBoxLayout(main_panel)
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
panel.setMinimumHeight(150)
|
||||
panel.setMaximumHeight(170)
|
||||
panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
layout = QGridLayout(panel)
|
||||
layout.setContentsMargins(10, 8, 10, 8)
|
||||
layout.setHorizontalSpacing(8)
|
||||
layout.setVerticalSpacing(4)
|
||||
|
||||
header_layout = QHBoxLayout()
|
||||
final_title = QLabel("终选与排序")
|
||||
final_title.setObjectName("imageStudioSectionTitle")
|
||||
main_layout.addWidget(final_title)
|
||||
header_hint = QLabel("从照片池拖入,可在同一行拖动排序,双击查看大图")
|
||||
header_hint.setObjectName("imageStudioMutedLabel")
|
||||
header_layout.addWidget(final_title)
|
||||
header_layout.addWidget(header_hint)
|
||||
header_layout.addStretch(1)
|
||||
layout.addLayout(header_layout, 0, 0, 1, 2)
|
||||
|
||||
self.main_selection_label = QLabel("主图终选 0/9")
|
||||
self.main_selection_label.setObjectName("imageStudioMainSelectionLabel")
|
||||
self.main_selection_label.setFixedWidth(64)
|
||||
self.main_selection_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
self.main_selection_list = ImageStudioSelectionList("main", self)
|
||||
self.main_selection_list.setObjectName("imageStudioMainSelectionList")
|
||||
self.main_selection_list.setIconSize(QSize(48, 48))
|
||||
self.main_selection_list.setMinimumHeight(96)
|
||||
main_layout.addWidget(self.main_selection_label)
|
||||
main_layout.addWidget(self.main_selection_list)
|
||||
self.main_selection_list.setGridSize(QSize(60, 62))
|
||||
self.main_selection_list.setFixedHeight(66)
|
||||
layout.addWidget(self.main_selection_label, 1, 0)
|
||||
layout.addWidget(self.main_selection_list, 1, 1)
|
||||
|
||||
detail_panel = QWidget()
|
||||
detail_layout = QVBoxLayout(detail_panel)
|
||||
detail_layout.setContentsMargins(0, 0, 0, 0)
|
||||
detail_layout.addWidget(QLabel(" "))
|
||||
self.detail_selection_label = QLabel("详情图终选 0/12")
|
||||
self.detail_selection_label.setObjectName("imageStudioDetailSelectionLabel")
|
||||
self.detail_selection_label.setFixedWidth(64)
|
||||
self.detail_selection_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
self.detail_selection_list = ImageStudioSelectionList("detail", self)
|
||||
self.detail_selection_list.setObjectName("imageStudioDetailSelectionList")
|
||||
self.detail_selection_list.setIconSize(QSize(42, 42))
|
||||
self.detail_selection_list.setMinimumHeight(96)
|
||||
detail_layout.addWidget(self.detail_selection_label)
|
||||
detail_layout.addWidget(self.detail_selection_list)
|
||||
self.detail_selection_list.setIconSize(QSize(38, 38))
|
||||
self.detail_selection_list.setGridSize(QSize(50, 52))
|
||||
self.detail_selection_list.setFixedHeight(56)
|
||||
layout.addWidget(self.detail_selection_label, 2, 0)
|
||||
layout.addWidget(self.detail_selection_list, 2, 1)
|
||||
|
||||
action_panel = QWidget()
|
||||
action_layout = QVBoxLayout(action_panel)
|
||||
action_layout.setContentsMargins(0, 0, 0, 0)
|
||||
action_layout.addWidget(QLabel(" "))
|
||||
action_layout.setSpacing(3)
|
||||
self.export_summary_label = QLabel("当前未选择终选图片")
|
||||
self.export_summary_label.setObjectName("imageStudioExportSummaryLabel")
|
||||
self.export_summary_label.setWordWrap(True)
|
||||
self.export_button = QPushButton("导出到文件夹")
|
||||
self.export_button.setObjectName("imageStudioExportButton")
|
||||
self.export_hint_label = QLabel("可部分导出;文件名按终选顺序连续,目标目录存在时可覆盖或新建时间目录。")
|
||||
self.export_hint_label.setObjectName("imageStudioExportHintLabel")
|
||||
self.export_hint_label.setWordWrap(True)
|
||||
action_layout.addWidget(self.export_button)
|
||||
action_layout.addWidget(self.export_summary_label)
|
||||
action_layout.addWidget(self.export_hint_label)
|
||||
action_layout.addStretch(1)
|
||||
layout.addWidget(main_panel, 1)
|
||||
layout.addWidget(detail_panel, 1)
|
||||
layout.addWidget(action_panel, 0)
|
||||
action_layout.addWidget(self.export_button)
|
||||
action_panel.setMinimumWidth(248)
|
||||
action_panel.setMaximumWidth(280)
|
||||
layout.addWidget(action_panel, 1, 2, 2, 1)
|
||||
layout.setColumnStretch(1, 1)
|
||||
return panel
|
||||
|
||||
def _apply_workspace_style(self):
|
||||
@@ -652,6 +680,18 @@ class ImageStudioTab(QWidget):
|
||||
#imageStudioExportHintLabel {
|
||||
color: #6e7781;
|
||||
}
|
||||
#imageStudioMainSelectionLabel {
|
||||
color: #0969da;
|
||||
font-weight: 600;
|
||||
}
|
||||
#imageStudioDetailSelectionLabel {
|
||||
color: #1a7f37;
|
||||
font-weight: 600;
|
||||
}
|
||||
#imageStudioExportSummaryLabel {
|
||||
color: #1a7f37;
|
||||
font-weight: 600;
|
||||
}
|
||||
#imageStudioCurrentProjectLabel {
|
||||
color: #24292f;
|
||||
font-weight: 600;
|
||||
@@ -686,6 +726,17 @@ class ImageStudioTab(QWidget):
|
||||
selection-background-color: #ddf4ff;
|
||||
selection-color: #24292f;
|
||||
}
|
||||
QListWidget#imageStudioMainSelectionList::item,
|
||||
QListWidget#imageStudioDetailSelectionList::item {
|
||||
border: 1px dashed #bfc8d3;
|
||||
border-radius: 4px;
|
||||
padding: 0;
|
||||
}
|
||||
QListWidget#imageStudioMainSelectionList::item:selected,
|
||||
QListWidget#imageStudioDetailSelectionList::item:selected {
|
||||
border: 2px solid #0969da;
|
||||
background: #eaf2ff;
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -1979,6 +2030,13 @@ class ImageStudioTab(QWidget):
|
||||
detail_target = getattr(self.current_project, "target_detail_count", 12) if self.current_project else 12
|
||||
self.main_selection_label.setText(f"主图终选 {main_count}/{main_target}")
|
||||
self.detail_selection_label.setText(f"详情图终选 {detail_count}/{detail_target}")
|
||||
total_count = main_count + detail_count
|
||||
if total_count:
|
||||
self.export_summary_label.setText(
|
||||
f"当前已选 {total_count} 张:主图 {main_count}/{main_target} · 详情 {detail_count}/{detail_target}"
|
||||
)
|
||||
else:
|
||||
self.export_summary_label.setText("当前未选择终选图片")
|
||||
self._fill_selection_list(self.main_selection_list, "main")
|
||||
self._fill_selection_list(self.detail_selection_list, "detail")
|
||||
|
||||
@@ -1988,17 +2046,19 @@ class ImageStudioTab(QWidget):
|
||||
for index, selection in enumerate(selected, start=1):
|
||||
asset = self._asset_by_id(selection.asset_id)
|
||||
if asset is None:
|
||||
text = f"{index}. 缺失照片 #{selection.asset_id}"
|
||||
text = f"{index}\n缺失"
|
||||
item = QListWidgetItem(text)
|
||||
item.setData(Qt.UserRole, int(selection.asset_id))
|
||||
item.setToolTip("终选引用的照片记录不存在")
|
||||
item.setForeground(_qcolor(COLOR_DANGER))
|
||||
item.setSizeHint(widget.gridSize())
|
||||
widget.addItem(item)
|
||||
continue
|
||||
text = f"{index}. {_asset_badge(asset.kind)} #{asset.id} · {asset.aspect_ratio or '未知比例'}"
|
||||
text = str(index)
|
||||
item = QListWidgetItem(text)
|
||||
item.setIcon(_asset_icon(asset, str(index)))
|
||||
item.setIcon(_asset_icon(asset, str(index), size=widget.iconSize()))
|
||||
item.setData(Qt.UserRole, int(asset.id))
|
||||
item.setSizeHint(widget.gridSize())
|
||||
tooltip = _selection_tooltip(selection_type, asset)
|
||||
item.setToolTip(tooltip)
|
||||
if _selection_ratio_warning(selection_type, asset):
|
||||
@@ -2010,12 +2070,13 @@ class ImageStudioTab(QWidget):
|
||||
widget.addItem(item)
|
||||
target = self._selection_target_count(selection_type)
|
||||
for index in range(len(selected) + 1, target + 1):
|
||||
item = QListWidgetItem(f"{index}. 空位")
|
||||
item.setIcon(QIcon(_placeholder_pixmap("空", QSize(48, 48), "#f6f8fa")))
|
||||
item = QListWidgetItem("")
|
||||
item.setIcon(QIcon(_placeholder_pixmap(str(index), widget.iconSize(), "#f6f8fa")))
|
||||
item.setData(Qt.UserRole, None)
|
||||
item.setSizeHint(widget.gridSize())
|
||||
item.setToolTip(f"{_selection_label(selection_type)}空位,可从照片池拖入图片。")
|
||||
item.setForeground(_qcolor(COLOR_MUTED))
|
||||
item.setFlags(Qt.NoItemFlags)
|
||||
item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsDropEnabled)
|
||||
widget.addItem(item)
|
||||
|
||||
def _asset_from_grid_item(self, item):
|
||||
|
||||
Reference in New Issue
Block a user