Files
cmshoppe/docs/tasks/T-626.md
T

85 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-626
title: ②封面画廊生成图随窗口自适应显示
phase: 7
deps: [T-574]
status: DONE
created: 2026-07-13
---
## 问题 / 背景
②「AI生成」列表双击任务行后会打开 `CoverGalleryDialog`。当前候选生成图使用固定 `THUMBNAIL_SIZE = 180`,候选项宽度也固定为 `THUMBNAIL_SIZE + 16`;弹窗 `_fit_to_screen()` 只设置一次窗口尺寸,没有在窗口变化后重新计算图片尺寸。因此在大屏幕上图片仍然很小、候选区留白明显,在较小屏幕或调整窗口尺寸后也不会随可用区域变化。
T-573 只修复了候选图横向容器没有按数量撑开导致的遮挡问题,没有实现响应式缩放。
候选图再次双击后打开的 `OriginalImageDialog` 也不是自适应预览:当前按图片原始像素设置 `QLabel` 尺寸,`QScrollArea.setWidgetResizable(False)`,大图只能通过滚动条局部查看。窗口虽然会限制在屏幕可用区域内,但图片本身不会适应窗口。
## 方案
### 1. 封面画廊候选图自适应
- 修改 `app/gui/tabs/generate.py` 的 `CoverGalleryDialog`:
- 不再把 `180px` 作为所有屏幕和窗口尺寸下唯一的候选图显示尺寸;保留合理最小值,并设置约 `180~360px` 的显示范围。
- 根据候选区 viewport 的实际宽高、候选数量、布局间距及候选说明文字所需高度计算正方形预览尺寸。
- 单张候选图可使用更多空间;多张候选图优先完整展示 2~3 张,更多候选继续使用 T-573 的横向滚动,不压缩到难以辨认,也不互相遮挡。
- 候选 item 宽度、图片 label 尺寸及 `candidate_content` 宽度必须使用同一轮计算结果,避免图片放大后重新出现遮挡或错误滚动范围。
- 覆盖 `resizeEvent()` 或使用等价的窗口级尺寸变化处理,在弹窗放大、缩小后重新计算候选图尺寸。
- `_rebuild_candidate_items()`、上一条/下一条切换、重置图片及候选重新生成后,按当前窗口尺寸重新同步候选布局。
### 2. 保持图片比例并控制重绘成本
- 使用 `Qt.KeepAspectRatio` + `Qt.SmoothTransformation` 重新生成预览图,不使用会拉伸图片的 `QLabel.setScaledContents(True)`。
- 缓存候选图的原始 `QImage`,窗口连续拖动时不重复从磁盘读取图片。
- 对连续 resize 事件做短时间合并,或只在计算出的目标尺寸发生变化时重绘,避免拖动窗口时卡顿。
- 图片读取失败时仍显示固定区域的中文失败占位,不因自适应逻辑造成布局跳动。
### 3. 原图窗口默认适应窗口
- 修改 `OriginalImageDialog`:
- 默认使用“适应窗口”模式,按图片显示区域等比例缩小或放大预览,让整张生成图在当前窗口内可见。
- 增加“原始尺寸 / 适应窗口”模式切换;原始尺寸模式保留滚动条,便于检查细节。
- 弹窗首次打开、窗口尺寸变化和模式切换时重新计算预览图。
- 窗口标题继续显示文件名和原始分辨率;模式切换按钮、tooltip 等用户可见文字全部使用中文。
### 4. 测试
- 更新 `tests/test_gui.py`:
- 覆盖画廊窗口放大、缩小后候选图显示尺寸随可用空间变化,并保持宽高比例。
- 覆盖单候选、多候选及候选数量超出可视宽度时的横向滚动内容宽度。
- 覆盖切换上一条/下一条和动态重建候选后,图片按当前窗口尺寸重新计算。
- 覆盖 `OriginalImageDialog` 默认适应窗口,以及切换原始尺寸后恢复图片原始像素和滚动行为。
- 覆盖图片读取失败占位状态。
## 验收要点
- 在常见的 `1366×768`、`1920×1080` 和 Windows 高 DPI 环境中打开封面画廊,候选生成图均完整、清晰且不变形。
- 放大或缩小画廊弹窗时,候选图跟随可用区域合理变化,不保持固定 `180px`,也不超出窗口或互相遮挡。
- 单张候选图能够合理利用可用空间;多张候选图可以比较,超出范围时可横向滚动查看全部候选。
- 切换任务、重置图片或候选列表重建后,当前窗口尺寸和位置保持不变,候选图尺寸正确刷新。
- 双击候选图打开原图窗口时,默认能看到完整图片;切换到“原始尺寸”后可以通过滚动条检查细节,再切回“适应窗口”可恢复完整预览。
- 不影响候选选择、保存提示、未保存确认、重置图片和 `↑ / ↓` 切换任务。
- 验证命令:
- `py -3.10 -m unittest tests.test_gui`
- `python -m ruff check app tests main.py`
- `py -3.10 -m compileall app main.py`
- `py -3.10 -m unittest discover -s tests`
- `git diff --check`
## 边界(不改什么)
- 不修改候选图文件发现、归档或排序规则。
- 不修改提示词、AI/cmhub 请求、生图并发或图片保存格式。
- 不修改 SQLite schema、Excel、③更新蝦皮、CDP 或蝦皮网页操作逻辑。
- 不改变保存封面、重置图片、上一条/下一条和未保存选择确认的业务语义。
## 执行记录
- 2026-07-14:完成 T-626。
- `app/gui/tabs/generate.py`:封面画廊候选图改为按候选区 viewport、候选数量和可用高度在 `180~360px` 内动态计算;候选 item、缩略图和横向内容宽度使用同一尺寸,窗口 resize、任务切换和候选重建后自动同步。
- 候选原始 `QImage` 在当前任务画廊内缓存,连续 resize 使用单次计时器合并重绘;预览继续使用 `Qt.KeepAspectRatio` 和平滑缩放,读取失败时保持中文占位。
- `OriginalImageDialog` 默认按窗口完整显示图片,新增「原始尺寸 / 适应窗口」切换;原始尺寸保留滚动查看,窗口尺寸变化后自动更新预览。
- `tests/test_gui.py`:新增候选图随窗口变化、非方图比例、损坏图片占位、任务切换后响应式尺寸,以及原图双模式和失败占位测试;既有候选内容宽度断言改为使用当前动态尺寸。
- 主工作区存在与本任务无关的默认封面模板未提交改名,导致两项旧模板断言失败;未回退用户改动,在基于 `HEAD` 的干净 worktree 中仅套用 T-626 代码和测试差异完成验证。
- 验证通过:`py -3.10 -m unittest tests.test_gui`(179 tests)、`py -3.10 -m unittest discover -s tests`(444 tests)、`python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。