feat: auto-preview, timestamped/grouped output, folder memory; fix batch format
- Auto-preview the first image after a folder loads (both panels), so the canvas isn't empty (§17.8). - Group exports as <output_dir>/<timestamp>/<print_stem>/<garment_stem>.<ext>; one timestamp per export run, shared across the batch (§17.9). - Remember the last garment/print folders and reopen the picker there; persisted via config, wired through main_window (§17.10). - Shrink the 3 box templates further and lower them (chest placement). - Fix: batch export ignored the chosen format/quality/output dir because the queue never received ExportOptions. Export panel now emits export_options_changed → queue.set_export_options (+ initial sync) (§17.11). Docs: PRD 6.1/6.8/9, architecture 4.12, UI design 5.1, tasks.md 17.8–17.11. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import logging
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtWidgets import (
|
||||
QComboBox,
|
||||
QFileDialog,
|
||||
@@ -17,7 +17,11 @@ from PySide6.QtWidgets import (
|
||||
|
||||
from core.composer import compose
|
||||
from core.models import ExportOptions, TransformState
|
||||
from services.file_service import get_output_dir, make_safe_output_path
|
||||
from services.file_service import (
|
||||
get_output_dir,
|
||||
make_safe_output_path,
|
||||
timestamped_run_dir,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -25,6 +29,8 @@ logger = logging.getLogger(__name__)
|
||||
class ExportPanel(QWidget):
|
||||
"""Right-panel section: output settings and single-image export."""
|
||||
|
||||
export_options_changed = Signal(object) # ExportOptions when dir/format/quality changes
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._garment_path: Optional[str] = None
|
||||
@@ -66,6 +72,7 @@ class ExportPanel(QWidget):
|
||||
self._dir_input.setReadOnly(True)
|
||||
self._dir_input.setPlaceholderText("输出目录")
|
||||
self._dir_input.setText(str(get_output_dir()))
|
||||
self._dir_input.textChanged.connect(self._emit_options)
|
||||
|
||||
browse_btn = QPushButton("浏览…")
|
||||
browse_btn.setObjectName("exportBrowseBtn")
|
||||
@@ -92,6 +99,7 @@ class ExportPanel(QWidget):
|
||||
self._quality_combo.addItem(label, val)
|
||||
self._quality_combo.setCurrentIndex(1) # default: 高 (90)
|
||||
self._quality_combo.setEnabled(False) # enabled only for JPG
|
||||
self._quality_combo.currentIndexChanged.connect(self._emit_options)
|
||||
|
||||
# 格式 and 质量 share one row (quality lights up only for JPG)
|
||||
row.addWidget(QLabel("格式"))
|
||||
@@ -133,11 +141,24 @@ class ExportPanel(QWidget):
|
||||
"""Update the operation-scope hint label."""
|
||||
self._hint_lbl.setText(text)
|
||||
|
||||
def current_options(self) -> ExportOptions:
|
||||
"""Build ExportOptions from the current output settings."""
|
||||
fmt = self._format_combo.currentData()
|
||||
return ExportOptions(
|
||||
output_dir=self._dir_input.text().strip(),
|
||||
output_format=fmt,
|
||||
quality=self._quality_combo.currentData() if fmt == "JPG" else 95,
|
||||
)
|
||||
|
||||
# ── slot handlers ────────────────────────────────────────────────────────
|
||||
|
||||
def _emit_options(self, *_):
|
||||
self.export_options_changed.emit(self.current_options())
|
||||
|
||||
def _on_format_changed(self, _index: int):
|
||||
fmt = self._format_combo.currentData()
|
||||
self._quality_combo.setEnabled(fmt == "JPG")
|
||||
self._emit_options()
|
||||
|
||||
def _browse_output_dir(self):
|
||||
folder = QFileDialog.getExistingDirectory(
|
||||
@@ -158,9 +179,8 @@ class ExportPanel(QWidget):
|
||||
QMessageBox.information(self, "提示", "当前没有可导出的印花参数。")
|
||||
return
|
||||
|
||||
out_dir = self._dir_input.text().strip() or str(get_output_dir())
|
||||
fmt = self._format_combo.currentData()
|
||||
quality = self._quality_combo.currentData() if fmt == "JPG" else 95
|
||||
options = self.current_options()
|
||||
out_dir = options.output_dir or str(get_output_dir())
|
||||
|
||||
out_dir_path = Path(out_dir)
|
||||
try:
|
||||
@@ -173,13 +193,10 @@ class ExportPanel(QWidget):
|
||||
)
|
||||
return
|
||||
|
||||
options = ExportOptions(
|
||||
output_dir=out_dir,
|
||||
output_format=fmt,
|
||||
quality=quality,
|
||||
)
|
||||
# Group this export under a timestamped run folder (compose creates it)
|
||||
run_dir = timestamped_run_dir(out_dir)
|
||||
output_path = make_safe_output_path(
|
||||
out_dir, self._garment_path, self._print_path, fmt
|
||||
run_dir, self._garment_path, self._print_path, options.output_format
|
||||
)
|
||||
|
||||
result = compose(
|
||||
|
||||
Reference in New Issue
Block a user