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): ...@@ -24,6 +24,9 @@ class HistoryBridge(QObject):
24 countChanged = Signal() 24 countChanged = Signal()
25 itemAdded = Signal(str) # timestamp 25 itemAdded = Signal(str) # timestamp
26 itemRemoved = Signal(str) # timestamp 26 itemRemoved = Signal(str) # timestamp
27 # "重做" 信号:把历史项的 prompt + 参考图 + 设置回填到图片生成 tab,
28 # 不带 resultPath(用户要重新生成不是重看结果)
29 redoRequested = Signal("QVariantMap")
27 30
28 def __init__(self, history_manager, parent=None): 31 def __init__(self, history_manager, parent=None):
29 super().__init__(parent) 32 super().__init__(parent)
...@@ -147,6 +150,47 @@ class HistoryBridge(QObject): ...@@ -147,6 +150,47 @@ class HistoryBridge(QObject):
147 except Exception: 150 except Exception:
148 self._logger.exception(f"revealInExplorer 失败 {path}") 151 self._logger.exception(f"revealInExplorer 失败 {path}")
149 152
153 @Slot(str)
154 def redoToImageGen(self, timestamp: str) -> None:
155 """把历史项的 prompt + 参考图 + 宽高比 + 尺寸 + 模式回填到图片生成 tab,
156 让用户微调提示词后重新生成。不回填生成图(用户要新结果)。
157 """
158 from core.generation import MODEL_BY_MODE
159
160 item = self._history.load_history_item_fast(timestamp)
161 if item is None:
162 self._logger.warning(f"redoToImageGen: 历史项不存在 {timestamp}")
163 return
164
165 # model_id → mode 中文(生成时存的是 model_id,回填要还原 ComboBox 文字)
166 mode = "慢速模式"
167 for k, v in MODEL_BY_MODE.items():
168 if v == item.model:
169 mode = k
170 break
171
172 # 只保留磁盘上仍存在的参考图(旧记录可能引用已删文件)
173 valid_refs = []
174 for p in item.reference_image_paths:
175 try:
176 if p and Path(p).exists():
177 valid_refs.append(Path(p).as_posix())
178 except Exception:
179 continue
180
181 payload = {
182 "timestamp": timestamp,
183 "prompt": item.prompt or "",
184 "referenceImages": valid_refs,
185 "aspectRatio": item.aspect_ratio or "",
186 "imageSize": item.image_size or "",
187 "mode": mode,
188 }
189 self._logger.info(
190 f"redoToImageGen: {timestamp} refs={len(valid_refs)} mode={mode}"
191 )
192 self.redoRequested.emit(payload)
193
150 @Slot(str, result=str) 194 @Slot(str, result=str)
151 def thumbnailPath(self, timestamp: str) -> str: 195 def thumbnailPath(self, timestamp: str) -> str:
152 """返回该 timestamp 缩略图本地路径(按需生成)。源图缺失时返回 ""。""" 196 """返回该 timestamp 缩略图本地路径(按需生成)。源图缺失时返回 ""。"""
......
...@@ -426,7 +426,7 @@ Item { ...@@ -426,7 +426,7 @@ Item {
426 } 426 }
427 } 427 }
428 428
429 // prompt header + 复制按钮 429 // prompt header + 重做 + 复制按钮
430 RowLayout { 430 RowLayout {
431 Layout.fillWidth: true 431 Layout.fillWidth: true
432 spacing: App.Theme.space2 432 spacing: App.Theme.space2
...@@ -434,6 +434,14 @@ Item { ...@@ -434,6 +434,14 @@ Item {
434 CaptionLabel { text: "提示词" } 434 CaptionLabel { text: "提示词" }
435 Item { Layout.fillWidth: true } 435 Item { Layout.fillWidth: true }
436 SecondaryButton { 436 SecondaryButton {
437 text: "🔁 重做"
438 enabled: tab.selectedTimestamp.length > 0
439 onClicked: {
440 // 走桥层 redoRequested 信号 → ImageGenTab 接住回填,并切到 tab 0
441 history.redoToImageGen(tab.selectedTimestamp)
442 }
443 }
444 SecondaryButton {
437 id: copyBtn 445 id: copyBtn
438 property bool justCopied: false 446 property bool justCopied: false
439 text: justCopied ? "✓ 已复制" : "📋 复制" 447 text: justCopied ? "✓ 已复制" : "📋 复制"
......
...@@ -176,6 +176,31 @@ Item { ...@@ -176,6 +176,31 @@ Item {
176 } 176 }
177 } 177 }
178 178
179 // 历史 tab 点"🔁 重做" → 回填提示词 + 参考图 + 设置到本 tab,但不回填生成图
180 Connections {
181 target: history
182 function onRedoRequested(payload) {
183 if (!payload) return
184 appState.setTab(0) // 切到图片生成 tab
185
186 promptArea.text = payload.prompt || ""
187 tab.refImages = (payload.referenceImages || []).slice()
188
189 var ai = aspectCombo.find(payload.aspectRatio || "")
190 if (ai >= 0) aspectCombo.currentIndex = ai
191 var si = sizeCombo.find(payload.imageSize || "")
192 if (si >= 0) sizeCombo.currentIndex = si
193 var mi = modeCombo.find(payload.mode || "")
194 if (mi >= 0) modeCombo.currentIndex = mi
195
196 // 重做不回填生成图,给用户一个干净的预览区开始
197 tab.lastResultPath = ""
198
199 tab.statusText = "● 已载入历史,可微调提示词后重新生成"
200 tab.statusColor = App.Theme.accent
201 }
202 }
203
179 // ===== 桥层信号 ===== 204 // ===== 桥层信号 =====
180 Connections { 205 Connections {
181 target: imageGen 206 target: imageGen
......