feat(qml): task #16 历史记录 tab 完整重做(ListView + 详情面板)
core/history.py:
HistoryListModel.roleNames() 暴露 4 个 Qt 内置 role 给 QML:
display / decoration / toolTip / timestamp (UserRole)
旧 QListView 用 int role 不受影响
bridges/history.py:
Slot thumbnailPath(timestamp) → str
返回 thumb.jpg 本地路径(按需用 PIL 生成 240px JPEG),缩略图缺失回退原图
qml_poc/qml/HistoryTab.qml (新):
- 左侧 340px 卡片:列表 (history.model)
* delegate 76px 高:60×60 缩略图 + timestamp + prompt 双行摘要
* 选中态 accent 蓝边框 + accentSubtle 浅蓝底
* hover 提示完整 toolTip
- 右侧详情卡片:
* timestamp + createdAt + "在文件管理器中打开" + "删除"
* 360px 大图(双击系统查看器打开)
* GridLayout 4 列元信息(宽高比/尺寸/模型)
* prompt ScrollView(长文本可滚)
- Component.onCompleted + onCountChanged 自动选中第一条
- itemRemoved 信号 → 选中失效时回到空态
qml_poc/main_qml.py:
AppState 加 QML_DEBUG_TAB env var (0/1/2) 控制启动 tab 索引,方便 PoC 调试
MainWindow.qml: 历史记录占位 Item → HistoryTab {}
视觉验证:QML_DEBUG_TAB=2 直接进历史 tab,2 条已存历史正确渲染(缩略图 +
详情大图 + 元信息 + prompt 都对),UI 无回归。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Showing
5 changed files
with
30 additions
and
11 deletions
| ... | @@ -83,3 +83,15 @@ class HistoryBridge(QObject): | ... | @@ -83,3 +83,15 @@ class HistoryBridge(QObject): |
| 83 | "model": item.model, | 83 | "model": item.model, |
| 84 | "createdAt": item.created_at.strftime("%Y-%m-%d %H:%M:%S"), | 84 | "createdAt": item.created_at.strftime("%Y-%m-%d %H:%M:%S"), |
| 85 | } | 85 | } |
| 86 | |||
| 87 | @Slot(str, result=str) | ||
| 88 | def thumbnailPath(self, timestamp: str) -> str: | ||
| 89 | """返回该 timestamp 缩略图本地路径(按需生成)。源图缺失时返回 ""。""" | ||
| 90 | item = self._history.load_history_item_fast(timestamp) | ||
| 91 | if item is None or not item.generated_image_path.exists(): | ||
| 92 | return "" | ||
| 93 | thumb = self._history.get_or_create_thumbnail(item.generated_image_path) | ||
| 94 | if thumb is None: | ||
| 95 | # 缩略图生成失败时回退到原图(QML Image 读 PNG 没问题) | ||
| 96 | return str(item.generated_image_path) | ||
| 97 | return str(thumb) | ... | ... |
| ... | @@ -85,6 +85,19 @@ class HistoryListModel(QAbstractListModel): | ... | @@ -85,6 +85,19 @@ class HistoryListModel(QAbstractListModel): |
| 85 | return 0 | 85 | return 0 |
| 86 | return len(self._timestamps) | 86 | return len(self._timestamps) |
| 87 | 87 | ||
| 88 | def roleNames(self): | ||
| 89 | """暴露 Qt 内置 roles 给 QML(默认 QML 只能 model.display)。 | ||
| 90 | |||
| 91 | QListView (旧 QWidget UI) 用 int role 不受影响;QML ListView delegate | ||
| 92 | 现在能用 model.timestamp / model.toolTip 等访问。 | ||
| 93 | """ | ||
| 94 | return { | ||
| 95 | Qt.DisplayRole: b"display", | ||
| 96 | Qt.DecorationRole: b"decoration", | ||
| 97 | Qt.ToolTipRole: b"toolTip", | ||
| 98 | Qt.UserRole: b"timestamp", | ||
| 99 | } | ||
| 100 | |||
| 88 | def flags(self, index: QModelIndex): | 101 | def flags(self, index: QModelIndex): |
| 89 | if not index.isValid(): | 102 | if not index.isValid(): |
| 90 | return Qt.NoItemFlags | 103 | return Qt.NoItemFlags | ... | ... |
| ... | @@ -54,6 +54,10 @@ class AppState(QObject): | ... | @@ -54,6 +54,10 @@ class AppState(QObject): |
| 54 | self._auth = auth_bridge | 54 | self._auth = auth_bridge |
| 55 | # 兼容现有 QML:env QML_AUTO_LOGIN=1 时强制 loggedIn=True | 55 | # 兼容现有 QML:env QML_AUTO_LOGIN=1 时强制 loggedIn=True |
| 56 | self._poc_force_login = os.environ.get("QML_AUTO_LOGIN", "") == "1" | 56 | self._poc_force_login = os.environ.get("QML_AUTO_LOGIN", "") == "1" |
| 57 | # 调试便捷:env QML_DEBUG_TAB=0/1/2 控制启动时默认 tab | ||
| 58 | try: | ||
| 59 | self._current_tab = int(os.environ.get("QML_DEBUG_TAB", "0")) | ||
| 60 | except ValueError: | ||
| 57 | self._current_tab = 0 | 61 | self._current_tab = 0 |
| 58 | self._auth.loggedInChanged.connect(self.loggedInChanged.emit) | 62 | self._auth.loggedInChanged.connect(self.loggedInChanged.emit) |
| 59 | 63 | ... | ... |
qml_poc/qml/HistoryTab.qml
0 → 100644
This diff is collapsed.
Click to expand it.
| ... | @@ -107,17 +107,7 @@ Rectangle { | ... | @@ -107,17 +107,7 @@ Rectangle { |
| 107 | } | 107 | } |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | // 历史记录 — 占位 | 110 | HistoryTab {} |
| 111 | Item { | ||
| 112 | Text { | ||
| 113 | anchors.centerIn: parent | ||
| 114 | text: "历史记录 tab 内容\n(QML PoC 暂未实现)" | ||
| 115 | color: App.Theme.textTertiary | ||
| 116 | font.family: App.Theme.fontFamily | ||
| 117 | font.pointSize: App.Theme.fontLg | ||
| 118 | horizontalAlignment: Text.AlignHCenter | ||
| 119 | } | ||
| 120 | } | ||
| 121 | } | 111 | } |
| 122 | } | 112 | } |
| 123 | 113 | ... | ... |
-
Please register or sign in to post a comment