Files

62 lines
4.0 KiB
Markdown

---
id: T-572
title: ②封面画廊打开后上下键切换记录不受按钮焦点影响
phase: 7
deps: [T-569]
status: DONE
created: 2026-07-09
---
## 问题 / 背景
T-569 给②AI生成的封面画廊 `CoverGalleryDialog` 增加了「上一条 / 下一条」按钮和 `↑ / ↓` 键切换当前可见任务记录。但真实使用中,用户双击②表格某条记录打开弹窗后,不做任何点击,直接按 `↓` / `↑`,无法切换到其他行的图片。
原因是弹窗打开后 Qt 可能把焦点默认放在某个 `QPushButton` 上,例如「上一条」「下一条」「重新生成」「保存」「取消」。当前 `_should_consume_navigation_key()` 明确把 `QPushButton` 排除:
```python
return not isinstance(focus, (QPushButton, QLineEdit, QPlainTextEdit, QComboBox, QSpinBox))
```
所以当焦点在按钮上时,`CoverGalleryDialog.keyPressEvent()` 不会调用 `switch_task()`,上下键被按钮焦点/默认事件链消费。T-569 单测只覆盖了候选 radio 获得焦点时的方向键行为,没有覆盖弹窗刚打开、焦点在按钮上的真实路径。
## 方案
- `app/gui/tabs/generate.py`
- 调整 `CoverGalleryDialog` 的方向键处理,让 `↑ / ↓` 在焦点位于按钮、图片、空白区域、radio 时都切换上一条/下一条。
- 仍保留输入类控件默认行为:焦点在 `QLineEdit`、`QPlainTextEdit`、`QComboBox`、`QSpinBox` 等输入/选择控件时,不消费上下键。
- 可选实现方式:
- 修改 `_should_consume_navigation_key()`,不再把 `QPushButton` 视为排除项;或
- 给弹窗安装 `eventFilter` / `QShortcut` 做窗口级快捷键,但必须避免输入类控件被抢键。
- 不改「上一条 / 下一条」按钮点击逻辑,不改未保存选择确认逻辑。
- `tests/test_gui.py`
- 增加回归测试:创建 `CoverGalleryDialog` 后把焦点放到 `next_button` 或 `save_button`,发送 `Qt.Key_Down`,应切到下一条。
- 增加保护测试:焦点在输入类控件时,`Qt.Key_Down` 不触发 `switch_task()`。
## 验收要点
- 双击②AI生成表格某条记录打开封面画廊后,不点击任何控件,直接按 `↓` 可以切换到下一条记录;按 `↑` 可以切回上一条记录。
- 焦点在「上一条 / 下一条 / 重新生成 / 保存 / 取消」按钮上时,`↑ / ↓` 仍切换记录。
- 焦点在候选 radio 上时,`↑ / ↓` 仍切换记录,且不会改变 radio 选中的候选封面。
- 焦点在输入/选择类控件上时,不抢占上下键,保留控件默认行为。
- 切换记录仍走 T-569 的未保存选择确认;不绕过「保存 / 不保存 / 取消」。
- 验证命令:
- `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`
## 边界(不改什么)
- 不改 `CoverGalleryDialog.switch_task()` 的数据切换逻辑。
- 不改封面候选保存、重新生成、未保存选择确认。
- 不改 AI/cmhub、DB schema、Excel、③更新蝦皮或 CDP/Shopee 交互。
## 执行记录
- 2026-07-09:完成 T-572。
- `app/gui/tabs/generate.py`:调整 `CoverGalleryDialog._should_consume_navigation_key()`,不再把 `QPushButton` 作为方向键切换的排除焦点;同时给弹窗和子控件安装 `eventFilter`,处理真实 Qt 运行时按键先发给按钮/radio 等子控件、父弹窗 `keyPressEvent()` 收不到的路径。焦点在上一条/下一条/重新生成/保存/取消等按钮上时,`↑ / ↓` 会切换记录;焦点在输入类控件上仍不抢键。
- `tests/test_gui.py`:新增按钮焦点下通过真实子控件事件分发 `Qt.Key_Down` 可切到下一条的回归测试;新增输入框焦点下 `Qt.Key_Down` 不切换记录的保护测试;保留 radio 焦点不改变候选选择的既有测试。
- 验证通过:`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`。