Add QT_ACCESSIBILITY=1 toggle for Qt6 accessibility support#53
Add QT_ACCESSIBILITY=1 toggle for Qt6 accessibility support#53
Conversation
Provide a persistent user environment variable toggle (HKCU\Environment) so LINE inherits QT_ACCESSIBILITY=1 on next launch. Accessible via NVDA+Shift+A shortcut and the NVDA Tools > LINE Desktop menu. The version info shortcut (NVDA+Shift+V) now also reports Qt accessibility status. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| def _isQtAccessibleSet(): | ||
| """Check if QT_ACCESSIBILITY=1 is set in user environment variables.""" | ||
| try: | ||
| with winreg.OpenKey( | ||
| winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_READ | ||
| ) as key: | ||
| value, _ = winreg.QueryValueEx(key, _QT_ACCESSIBILITY_ENV_NAME) | ||
| return str(value) == "1" | ||
| except FileNotFoundError: | ||
| return False | ||
| except Exception: | ||
| return False |
There was a problem hiding this comment.
lineDesktopHelper.py 的 _isQtAccessibleSet 在最後的 except Exception 中靜默忽略所有非 FileNotFoundError 的例外,沒有任何日誌紀錄,使除錯更加困難。相較之下,line.py 的同名函式有記錄 debugWarning。
建議對齊兩個實作的行為:
| def _isQtAccessibleSet(): | |
| """Check if QT_ACCESSIBILITY=1 is set in user environment variables.""" | |
| try: | |
| with winreg.OpenKey( | |
| winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_READ | |
| ) as key: | |
| value, _ = winreg.QueryValueEx(key, _QT_ACCESSIBILITY_ENV_NAME) | |
| return str(value) == "1" | |
| except FileNotFoundError: | |
| return False | |
| except Exception: | |
| return False | |
| except Exception: | |
| log.debugWarning("Failed to read QT_ACCESSIBILITY from registry", exc_info=True) | |
| return False |
Prompt To Fix With AI
This is a comment left during a code review.
Path: addon/globalPlugins/lineDesktopHelper.py
Line: 29-40
Comment:
**未記錄非預期例外**
`lineDesktopHelper.py` 的 `_isQtAccessibleSet` 在最後的 `except Exception` 中靜默忽略所有非 `FileNotFoundError` 的例外,沒有任何日誌紀錄,使除錯更加困難。相較之下,`line.py` 的同名函式有記錄 `debugWarning`。
建議對齊兩個實作的行為:
```suggestion
except Exception:
log.debugWarning("Failed to read QT_ACCESSIBILITY from registry", exc_info=True)
return False
```
How can I resolve this? If you propose a fix, please make it concise.| # --------------------------------------------------------------------------- | ||
| # Qt accessibility environment variable helpers (duplicated from line.py | ||
| # so the global plugin can toggle the setting even when LINE is not running) | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| _QT_ACCESSIBILITY_ENV_NAME = "QT_ACCESSIBILITY" | ||
| _HWND_BROADCAST = 0xFFFF | ||
| _WM_SETTINGCHANGE = 0x001A | ||
| _SMTO_ABORTIFHUNG = 0x0002 | ||
|
|
||
|
|
||
| def _isQtAccessibleSet(): | ||
| """Check if QT_ACCESSIBILITY=1 is set in user environment variables.""" | ||
| try: | ||
| with winreg.OpenKey( | ||
| winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_READ | ||
| ) as key: | ||
| value, _ = winreg.QueryValueEx(key, _QT_ACCESSIBILITY_ENV_NAME) | ||
| return str(value) == "1" | ||
| except FileNotFoundError: | ||
| return False | ||
| except Exception: | ||
| return False | ||
|
|
||
|
|
||
| def _setQtAccessible(enable=True): | ||
| """Set or remove QT_ACCESSIBILITY in user environment variables.""" | ||
| try: | ||
| with winreg.OpenKey( | ||
| winreg.HKEY_CURRENT_USER, "Environment", 0, | ||
| winreg.KEY_SET_VALUE | winreg.KEY_READ | ||
| ) as key: | ||
| if enable: | ||
| winreg.SetValueEx( | ||
| key, _QT_ACCESSIBILITY_ENV_NAME, 0, | ||
| winreg.REG_SZ, "1" | ||
| ) | ||
| else: | ||
| try: | ||
| winreg.DeleteValue(key, _QT_ACCESSIBILITY_ENV_NAME) | ||
| except FileNotFoundError: | ||
| pass | ||
| ctypes.windll.user32.SendMessageTimeoutW( | ||
| _HWND_BROADCAST, _WM_SETTINGCHANGE, 0, | ||
| "Environment", _SMTO_ABORTIFHUNG, 5000, None | ||
| ) | ||
| return True | ||
| except Exception: |
There was a problem hiding this comment.
_isQtAccessibleSet、_setQtAccessible 及所有常數(_QT_ACCESSIBILITY_ENV_NAME、_HWND_BROADCAST 等)都與 line.py 中的定義完全相同,程式碼注釋也坦承是「duplicated from line.py」。這造成維護負擔:若日後需修改邏輯(例如改用 CreateKeyEx 處理 key 不存在的邊緣案例),必須同步更新兩個地方。
建議將共用邏輯提取至 addon/appModules/_qtAccessibility.py(或 addon/lib/qtAccessibility.py),讓兩個模組都能 import 相同的實作,同時保留 GlobalPlugin 在 LINE 未執行時仍可作業的能力。
Prompt To Fix With AI
This is a comment left during a code review.
Path: addon/globalPlugins/lineDesktopHelper.py
Line: 18-65
Comment:
**輔助函式重複定義**
`_isQtAccessibleSet`、`_setQtAccessible` 及所有常數(`_QT_ACCESSIBILITY_ENV_NAME`、`_HWND_BROADCAST` 等)都與 `line.py` 中的定義完全相同,程式碼注釋也坦承是「duplicated from line.py」。這造成維護負擔:若日後需修改邏輯(例如改用 `CreateKeyEx` 處理 key 不存在的邊緣案例),必須同步更新兩個地方。
建議將共用邏輯提取至 `addon/appModules/_qtAccessibility.py`(或 `addon/lib/qtAccessibility.py`),讓兩個模組都能 import 相同的實作,同時保留 GlobalPlugin 在 LINE 未執行時仍可作業的能力。
How can I resolve this? If you propose a fix, please make it concise.| Broadcasts WM_SETTINGCHANGE so new processes pick up the change. | ||
| Returns True on success, False on failure. | ||
| """ | ||
| try: | ||
| with winreg.OpenKey( | ||
| winreg.HKEY_CURRENT_USER, "Environment", 0, | ||
| winreg.KEY_SET_VALUE | winreg.KEY_READ | ||
| ) as key: | ||
| if enable: | ||
| winreg.SetValueEx( | ||
| key, _QT_ACCESSIBILITY_ENV_NAME, 0, | ||
| winreg.REG_SZ, "1" | ||
| ) | ||
| log.info("QT_ACCESSIBILITY=1 set in user environment") | ||
| else: | ||
| try: |
There was a problem hiding this comment.
_setQtAccessible 使用 winreg.OpenKey 開啟已存在的機碼。若 HKCU\Environment 不存在(例如極度精簡的 Windows 環境或 Wine),函式會進入 except Exception 並回傳 False,使用者只會看到錯誤訊息,而不知道原因是 key 不存在。
建議改用 winreg.CreateKeyEx,它在 key 已存在時等同 OpenKey,在不存在時則自動建立:
with winreg.CreateKeyEx(
winreg.HKEY_CURRENT_USER, "Environment", 0,
winreg.KEY_SET_VALUE | winreg.KEY_READ
) as key:這樣可同時處理 key 不存在與已存在的情況。此修改在 line.py 與 lineDesktopHelper.py 兩處的 _setQtAccessible 都應套用。
Prompt To Fix With AI
This is a comment left during a code review.
Path: addon/appModules/line.py
Line: 119-134
Comment:
**`HKCU\Environment` 不存在時操作會靜默失敗**
`_setQtAccessible` 使用 `winreg.OpenKey` 開啟已存在的機碼。若 `HKCU\Environment` 不存在(例如極度精簡的 Windows 環境或 Wine),函式會進入 `except Exception` 並回傳 `False`,使用者只會看到錯誤訊息,而不知道原因是 key 不存在。
建議改用 `winreg.CreateKeyEx`,它在 key 已存在時等同 `OpenKey`,在不存在時則自動建立:
```python
with winreg.CreateKeyEx(
winreg.HKEY_CURRENT_USER, "Environment", 0,
winreg.KEY_SET_VALUE | winreg.KEY_READ
) as key:
```
這樣可同時處理 key 不存在與已存在的情況。此修改在 `line.py` 與 `lineDesktopHelper.py` 兩處的 `_setQtAccessible` 都應套用。
How can I resolve this? If you propose a fix, please make it concise.Keep the feature accessible only via the NVDA Tools > LINE Desktop menu to avoid conflicting with existing keyboard shortcuts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@greptileai nvda+shift+a快速鍵需要移除,只保留工具切換,避免快速鍵衝突 |
| def script_toggleQtAccessible(self, gesture): | ||
| """Toggle QT_ACCESSIBILITY=1 user environment variable.""" | ||
| currentlySet = _isQtAccessibleSet() | ||
| if currentlySet: | ||
| if _setQtAccessible(False): | ||
| ui.message(_("已移除 QT_ACCESSIBILITY 環境變數,重啟 LINE 後生效")) | ||
| else: | ||
| ui.message(_("移除 QT_ACCESSIBILITY 環境變數失敗")) | ||
| else: | ||
| if _setQtAccessible(True): | ||
| ui.message(_("已設定 QT_ACCESSIBILITY=1,重啟 LINE 後生效")) | ||
| else: | ||
| ui.message(_("設定 QT_ACCESSIBILITY 環境變數失敗")) |
There was a problem hiding this comment.
script_toggleQtAccessible 雖然遵循 NVDA 的 script_* 命名慣例,但完全缺少 @script 裝飾器與 gesture 宣告。如此一來,NVDA 不會將任何鍵盤手勢綁定到此函式,使用者無論按下 NVDA+Shift+A 或其他任何組合鍵,都不會有任何反應。
PR 說明明確列出「Keyboard shortcut: NVDA+Shift+A to toggle the setting」,但搜尋整個程式碼庫確認此手勢並未被宣告於任何地方。
對照同一檔案內其他腳本(如 script_reportLineInfo),正確的寫法應為:
| def script_toggleQtAccessible(self, gesture): | |
| """Toggle QT_ACCESSIBILITY=1 user environment variable.""" | |
| currentlySet = _isQtAccessibleSet() | |
| if currentlySet: | |
| if _setQtAccessible(False): | |
| ui.message(_("已移除 QT_ACCESSIBILITY 環境變數,重啟 LINE 後生效")) | |
| else: | |
| ui.message(_("移除 QT_ACCESSIBILITY 環境變數失敗")) | |
| else: | |
| if _setQtAccessible(True): | |
| ui.message(_("已設定 QT_ACCESSIBILITY=1,重啟 LINE 後生效")) | |
| else: | |
| ui.message(_("設定 QT_ACCESSIBILITY 環境變數失敗")) | |
| @script( | |
| # Translators: Description of a script to toggle Qt accessibility env var | |
| description=_("切換 Qt 無障礙環境變數"), | |
| gesture="kb:NVDA+shift+a", | |
| category="LINE Desktop", | |
| ) | |
| def script_toggleQtAccessible(self, gesture): | |
| """Toggle QT_ACCESSIBILITY=1 user environment variable.""" | |
| currentlySet = _isQtAccessibleSet() | |
| if currentlySet: | |
| if _setQtAccessible(False): | |
| ui.message(_("已移除 QT_ACCESSIBILITY 環境變數,重啟 LINE 後生效")) | |
| else: | |
| ui.message(_("移除 QT_ACCESSIBILITY 環境變數失敗")) | |
| else: | |
| if _setQtAccessible(True): | |
| ui.message(_("已設定 QT_ACCESSIBILITY=1,重啟 LINE 後生效")) | |
| else: | |
| ui.message(_("設定 QT_ACCESSIBILITY 環境變數失敗")) |
補上裝飾器後,也建議在選單項目標籤中加入快捷鍵提示(+ "\tNVDA+Shift+A"),與其他選單項目保持一致。
Prompt To Fix With AI
This is a comment left during a code review.
Path: addon/appModules/line.py
Line: 6087-6099
Comment:
**缺少 `@script` 裝飾器,快捷鍵無法運作**
`script_toggleQtAccessible` 雖然遵循 NVDA 的 `script_*` 命名慣例,但完全缺少 `@script` 裝飾器與 `gesture` 宣告。如此一來,NVDA 不會將任何鍵盤手勢綁定到此函式,使用者無論按下 `NVDA+Shift+A` 或其他任何組合鍵,都不會有任何反應。
PR 說明明確列出「**Keyboard shortcut: NVDA+Shift+A to toggle the setting**」,但搜尋整個程式碼庫確認此手勢並未被宣告於任何地方。
對照同一檔案內其他腳本(如 `script_reportLineInfo`),正確的寫法應為:
```suggestion
@script(
# Translators: Description of a script to toggle Qt accessibility env var
description=_("切換 Qt 無障礙環境變數"),
gesture="kb:NVDA+shift+a",
category="LINE Desktop",
)
def script_toggleQtAccessible(self, gesture):
"""Toggle QT_ACCESSIBILITY=1 user environment variable."""
currentlySet = _isQtAccessibleSet()
if currentlySet:
if _setQtAccessible(False):
ui.message(_("已移除 QT_ACCESSIBILITY 環境變數,重啟 LINE 後生效"))
else:
ui.message(_("移除 QT_ACCESSIBILITY 環境變數失敗"))
else:
if _setQtAccessible(True):
ui.message(_("已設定 QT_ACCESSIBILITY=1,重啟 LINE 後生效"))
else:
ui.message(_("設定 QT_ACCESSIBILITY 環境變數失敗"))
```
補上裝飾器後,也建議在選單項目標籤中加入快捷鍵提示(`+ "\tNVDA+Shift+A"`),與其他選單項目保持一致。
How can I resolve this? If you propose a fix, please make it concise.|
這個應該不需要快速鍵,很少人常常改這個 |
Summary
Adds a persistent user environment variable toggle for
QT_ACCESSIBILITY=1to improve Qt6 accessibility support in LINE Desktop. The setting is stored in the Windows registry (HKCU\Environment) and persists across reboots.Features
WM_SETTINGCHANGEto notify running processesImplementation
HKCU\Environment\QT_ACCESSIBILITYvia Windows registryline.pyandglobalPlugins/lineDesktopHelper.pyTesting
🤖 Generated with Claude Code
Greptile Summary
此 PR 新增了
QT_ACCESSIBILITY=1使用者環境變數的切換功能,以改善 LINE Desktop 在 Qt6 下的輔助功能支援。實作方式為直接讀寫 Windows 登錄機碼HKCU\\Environment,並透過WM_SETTINGCHANGE廣播通知所有執行中的程序,設定在重開機後持續有效。主要變更:
line.py:新增_isQtAccessibleSet/_setQtAccessible輔助函式、script_toggleQtAccessible腳本,並在script_reportLineInfo(NVDA+Shift+V)的狀態報告中加入 Qt 無障礙狀態lineDesktopHelper.py:新增對應的選單項目(「切換 Qt 無障礙環境變數」)及事件處理邏輯,LINE 未執行時仍可直接操作;輔助函式與line.py重複(註解中已坦承)發現的問題:
script_toggleQtAccessible在line.py中缺少@script裝飾器與gesture宣告,導致 PR 說明所列的 NVDA+Shift+A 鍵盤快捷鍵實際上不會被 NVDA 綁定,無法透過鍵盤觸發此功能。Confidence Score: 3/5
PR 存在一個明確的功能缺失:
@script裝飾器遺漏使鍵盤快捷鍵完全無法運作,需在合併前修正。核心功能(選單項目切換)可正常運作,登錄機碼讀寫邏輯無明顯錯誤,但 PR 說明宣稱的 NVDA+Shift+A 快捷鍵因缺少
@script裝飾器而完全失效,屬於功能性缺失,需在合併前補上裝飾器。加上先前評論中尚未修正的問題(CreateKeyEx、靜默例外、重複程式碼),整體還需多一輪修正。addon/appModules/line.py:script_toggleQtAccessible缺少@script裝飾器與 gesture 宣告。Important Files Changed
script_toggleQtAccessible,但後者缺少@script裝飾器,導致 PR 說明中宣稱的 NVDA+Shift+A 快捷鍵無法運作。_isQtAccessibleSet的最終 except 未記錄日誌(已於先前評論中提及)。Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[使用者觸發切換] --> B{觸發來源} B -->|選單項目| C[GlobalPlugin._onToggleQtAccessible] B -->|鍵盤快捷鍵| D[❌ @script 裝飾器缺失\nNVDA+Shift+A 無效] C --> E[wx.CallAfter → _doToggleQtAccessible] E --> F{LINE 是否執行中?} F -->|是| G[委派至 AppModule.script_toggleQtAccessible] F -->|否| H[直接呼叫 GlobalPlugin._isQtAccessibleSet / _setQtAccessible] G --> I[_isQtAccessibleSet → HKCU\\Environment] G --> J[_setQtAccessible → winreg.OpenKey / SetValueEx / DeleteValue] H --> I H --> J J --> K[SendMessageTimeoutW WM_SETTINGCHANGE 廣播] K --> L[ui.message 通知使用者]Prompt To Fix All With AI
Reviews (3): Last reviewed commit: "Remove NVDA+Shift+A shortcut from Qt acc..." | Re-trigger Greptile