53e6ff8f by 柴进

feat: 历史"重做"按钮 + 老 image_generator.py 改 .txt 后缀(保留参考)

# 1. 历史详情":repeat: 重做"按钮(在 ":clipboard: 复制" 左侧)

行为:把历史项的 prompt + 参考图 + 宽高比 + 尺寸 + 模式回填到图片生成 tab,
切到 tab 0,**不回填生成图**(用户要新结果)。便于微调提示词后重新生成。

bridges/history.py:
  + Signal redoRequested(payload)
  + Slot redoToImageGen(timestamp):load_history_item_fast → 反查 mode →
    过滤已删参考图 → emit payload

qml_poc/qml/HistoryTab.qml:
  详情面板 prompt header 加 SecondaryButton ":repeat: 重做"
  enabled: 已选中历史项

qml_poc/qml/ImageGenTab.qml:
  Connections target: history 接 redoRequested → 回填字段 + 切 tab 0
  状态文字: "● 已载入历史,可微调提示词后重新生成"

# 2. image_generator.py → image_generator.py.txt

老代码先不删,改 .txt 后缀:
  - Python 不再加载(new 主入口 main_qml.py 早已不依赖它,
    grep 全项目无 'from image_generator' 或 'import image_generator')
  - PyInstaller 不会扫 .txt
  - git mv 保留全部历史,需要扒老逻辑时直接打开看
  - task #19 真正"删掉"动作留作后续,避免一次性删后才发现还有 bug 要扒

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 02e76749
......@@ -24,6 +24,9 @@ class HistoryBridge(QObject):
countChanged = Signal()
itemAdded = Signal(str) # timestamp
itemRemoved = Signal(str) # timestamp
# "重做" 信号:把历史项的 prompt + 参考图 + 设置回填到图片生成 tab,
# 不带 resultPath(用户要重新生成不是重看结果)
redoRequested = Signal("QVariantMap")
def __init__(self, history_manager, parent=None):
super().__init__(parent)
......@@ -147,6 +150,47 @@ class HistoryBridge(QObject):
except Exception:
self._logger.exception(f"revealInExplorer 失败 {path}")
@Slot(str)
def redoToImageGen(self, timestamp: str) -> None:
"""把历史项的 prompt + 参考图 + 宽高比 + 尺寸 + 模式回填到图片生成 tab,
让用户微调提示词后重新生成。不回填生成图(用户要新结果)。
"""
from core.generation import MODEL_BY_MODE
item = self._history.load_history_item_fast(timestamp)
if item is None:
self._logger.warning(f"redoToImageGen: 历史项不存在 {timestamp}")
return
# model_id → mode 中文(生成时存的是 model_id,回填要还原 ComboBox 文字)
mode = "慢速模式"
for k, v in MODEL_BY_MODE.items():
if v == item.model:
mode = k
break
# 只保留磁盘上仍存在的参考图(旧记录可能引用已删文件)
valid_refs = []
for p in item.reference_image_paths:
try:
if p and Path(p).exists():
valid_refs.append(Path(p).as_posix())
except Exception:
continue
payload = {
"timestamp": timestamp,
"prompt": item.prompt or "",
"referenceImages": valid_refs,
"aspectRatio": item.aspect_ratio or "",
"imageSize": item.image_size or "",
"mode": mode,
}
self._logger.info(
f"redoToImageGen: {timestamp} refs={len(valid_refs)} mode={mode}"
)
self.redoRequested.emit(payload)
@Slot(str, result=str)
def thumbnailPath(self, timestamp: str) -> str:
"""返回该 timestamp 缩略图本地路径(按需生成)。源图缺失时返回 ""。"""
......
......@@ -426,7 +426,7 @@ Item {
}
}
// prompt header + 复制按钮
// prompt header + 重做 + 复制按钮
RowLayout {
Layout.fillWidth: true
spacing: App.Theme.space2
......@@ -434,6 +434,14 @@ Item {
CaptionLabel { text: "提示词" }
Item { Layout.fillWidth: true }
SecondaryButton {
text: "🔁 重做"
enabled: tab.selectedTimestamp.length > 0
onClicked: {
// 走桥层 redoRequested 信号 → ImageGenTab 接住回填,并切到 tab 0
history.redoToImageGen(tab.selectedTimestamp)
}
}
SecondaryButton {
id: copyBtn
property bool justCopied: false
text: justCopied ? "✓ 已复制" : "📋 复制"
......
......@@ -176,6 +176,31 @@ Item {
}
}
// 历史 tab 点"🔁 重做" → 回填提示词 + 参考图 + 设置到本 tab,但不回填生成图
Connections {
target: history
function onRedoRequested(payload) {
if (!payload) return
appState.setTab(0) // 切到图片生成 tab
promptArea.text = payload.prompt || ""
tab.refImages = (payload.referenceImages || []).slice()
var ai = aspectCombo.find(payload.aspectRatio || "")
if (ai >= 0) aspectCombo.currentIndex = ai
var si = sizeCombo.find(payload.imageSize || "")
if (si >= 0) sizeCombo.currentIndex = si
var mi = modeCombo.find(payload.mode || "")
if (mi >= 0) modeCombo.currentIndex = mi
// 重做不回填生成图,给用户一个干净的预览区开始
tab.lastResultPath = ""
tab.statusText = "● 已载入历史,可微调提示词后重新生成"
tab.statusColor = App.Theme.accent
}
}
// ===== 桥层信号 =====
Connections {
target: imageGen
......