# P0-02 合并重复的 `MainWindow.eventFilter` — 执行证据 日期:2026-09-16(无人值守轮次) 平台:Windows 11 10.0.26200 x64 · Python 3.10.21(`.venv`)· PyQt6/Qt 6.10.0/6.10.2 · 离屏 `QT_QPA_PLATFORM=offscreen` ## 根因(源码确认) - `MainWindow` 类体内定义了两个 `eventFilter`(行 3697 与 3763):后定义者覆盖前者,前者的 `_active_streams` 守卫是死代码。 - 生效版本(3763)用 `btn_send.isEnabled()` 做守卫,而 `set_send_button_state` 只切换 图标、从不禁用按钮 → 守卫恒真 → 流式生成中按 Enter 会落入 `send_message` 的中断路径 (触发停止),与注释声称的「生成时按回车无效,防止误触」相反。 ## 修复摘要(仅 `ui/views/main_window.py` 事件过滤逻辑) - 删除行 3763 的重复 `eventFilter`(及其后不可达的两行过期分节注释)。 - 保留行 3697 处为 `MainWindow` 唯一 `eventFilter`:Enter(无 Shift)→ `send_message(from_enter=True)` 并消费事件(一次按键至多一次调用);Shift+Enter → 返回 False 放行换行;其他对象/事件交父类。 - `send_message(self, from_enter: bool = False)`:函数顶部为发送规则单一实现: 1) `btn_send` 禁用 → 一律不发送; 2) `from_enter=True` 且当前会话在 `_active_streams` → 直接返回(Enter 不参与停止/中断语义); 3) 按钮点击路径行为完全不变(流式中点击 = 原有红色停止按钮中断语义,含 Fix B/C)。 - `_update_send_button_state` 未改(其语义与规则一致)。 ## 定向测试(命令 / 退出码 / 结果) | 命令 | 退出码 | 结果 | |---|---|---| | `python tests/test_main_window_event_filter.py` | 0 | ALL PASS(18 项断言) | | `python tests/smoke_offscreen.py` | 0 | ALL PASS: 8/8 | | `python tests/smoke_mode.py` | 0 | ALL PASS | | 回归 `python tests/test_config_isolation.py` | 0 | ALL PASS(14 项) | | 回归 `python tests/test_error_persist.py` | 0 | 39 PASS | | 回归 `python tests/smoke_bash_panel.py` | 0 | 116 PASS | 注:`smoke_offscreen.py` / `smoke_mode.py` 自身只重定向数据库、未设置 `HAOCODE_CONFIG_FILE` (不在 P0-02 允许修改清单内)。本轮运行时在进程环境显式导出指向临时配置的 `HAOCODE_CONFIG_FILE`;P2-04 聚合入口将按子进程强制注入临时环境,彻底闭环。 ## 完成证据对应(test_main_window_event_filter.py) - **AST 静态断言**:解析 `ui/views/main_window.py`,`MainWindow` 类体内 `eventFilter` 定义恰好 1 个(行 3697); - **Enter 可发送**(A1–A5):空闲 + 按钮可用 + 有文本 → 一次 Enter 恰好一次 `send_message(from_enter=True)` 调用(计数 wrapper 包住真实实现),流同步注册、输入框清空、错误路径自清理; - **Enter 被禁用**(B1–B3):`btn_send.setEnabled(False)` → 至多一次调用且无流、输入内容保留(规则在 `send_message` 内生效); - **流式时 Enter 被拦截**(C1–C3):注入假流 → Enter 后假流对象未被替换、字段未被改动(未触发中断)、输入保留; - **Shift+Enter 换行**(D1–D3):零调用,事件放行到输入框(光标处插入 `\n`)、无流; - **其他键/事件交父类**(E1–E2):按 `a` 正常插入字符、零发送调用; - **一次按键至多一次调用**:A/B/C/D 各用例均以调用计数断言(全部 ≤1 且语义正确)。 ## 行为变化说明 - 流式生成中按 Enter:旧(生效)代码会触发停止/中断;新代码 no-op(Enter 只管发送, 停止只走按钮)。这与被覆盖版本注释中声明的原始意图(「生成时按回车无效,防止误触」) 和 P0-02 硬约束(「流式生成时不得发送」)一致,属本任务预期的确定性修复。 - 发送按钮点击路径(含流式中点击 = 中断):逐行未动。