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

6.4 KiB
Raw Blame History

id, title, phase, deps, status, created
id title phase deps status created
T-626 ②封面画廊生成图随窗口自适应显示 7
T-574
DONE 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。