-
Notifications
You must be signed in to change notification settings - Fork 0
Add QT_ACCESSIBILITY=1 toggle for Qt6 accessibility support #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import configparser | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import winreg | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from ._virtualWindow import VirtualWindow | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import addonHandler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -83,6 +84,69 @@ def _readLineLanguage(): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Qt accessibility environment variable management | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns True if the variable is set to '1', False otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.debugWarning("Failed to read QT_ACCESSIBILITY from registry", exc_info=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _setQtAccessible(enable=True): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Set or remove QT_ACCESSIBILITY in user environment variables. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Writes to HKCU\\Environment so the setting persists across reboots. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| winreg.DeleteValue(key, _QT_ACCESSIBILITY_ENV_NAME) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info("QT_ACCESSIBILITY removed from user environment") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except FileNotFoundError: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pass | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Broadcast environment change to all windows | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ctypes.windll.user32.SendMessageTimeoutW( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _HWND_BROADCAST, _WM_SETTINGCHANGE, 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Environment", _SMTO_ABORTIFHUNG, 5000, None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| except Exception: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.warning("Failed to set QT_ACCESSIBILITY in registry", exc_info=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Window type classification — | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # LINE has two main window modes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # "AllInOneWindow" — sidebar (chat list) + chat area in one window | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -3481,11 +3545,13 @@ def __init__(self, *args, **kwargs): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Read and cache LINE installation info | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._lineVersion = _readLineVersion() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._lineLanguage = _readLineLanguage() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._qtAccessibleSet = _isQtAccessibleSet() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"LINE AppModule loaded for process: {self.processID}, " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"exe: {self.appName}, " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"lineVersion: {self._lineVersion}, " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"lineLanguage: {self._lineLanguage}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"lineLanguage: {self._lineLanguage}, " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"qtAccessible: {self._qtAccessibleSet}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def chooseNVDAObjectOverlayClasses(self, obj, clsList): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -6010,10 +6076,28 @@ def script_reportLineInfo(self, gesture): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parts.append(_("視窗類型: {type}").format( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type=typeNames.get(winType, winType) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| qtA11y = _isQtAccessibleSet() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parts.append( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _("Qt 無障礙: 已啟用") if qtA11y else _("Qt 無障礙: 未啟用") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = ", ".join(parts) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ui.message(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.info(f"LINE info: {msg}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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 環境變數失敗")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+6087
to
+6099
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
PR 說明明確列出「Keyboard shortcut: NVDA+Shift+A to toggle the setting」,但搜尋整個程式碼庫確認此手勢並未被宣告於任何地方。 對照同一檔案內其他腳本(如
Suggested change
補上裝飾器後,也建議在選單項目標籤中加入快捷鍵提示( Prompt To Fix With AIThis 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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _pollFileDialog(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Poll to detect when the file dialog closes, then resume addon. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,11 +8,65 @@ | |||||||||||||||||||||||||||||||
| from logHandler import log | ||||||||||||||||||||||||||||||||
| import gui | ||||||||||||||||||||||||||||||||
| import wx | ||||||||||||||||||||||||||||||||
| import winreg | ||||||||||||||||||||||||||||||||
| import ctypes | ||||||||||||||||||||||||||||||||
| import addonHandler | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| addonHandler.initTranslation() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # --------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||
| # 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 | ||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+40
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
建議對齊兩個實作的行為:
Suggested change
Prompt To Fix With AIThis 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. |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| 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: | ||||||||||||||||||||||||||||||||
|
Comment on lines
+18
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
建議將共用邏輯提取至 Prompt To Fix With AIThis 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. |
||||||||||||||||||||||||||||||||
| log.warning("Failed to set QT_ACCESSIBILITY in registry", exc_info=True) | ||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def _getLineAppModule(): | ||||||||||||||||||||||||||||||||
| """Find and return the LINE appModule instance, or None.""" | ||||||||||||||||||||||||||||||||
| for app in appModuleHandler.runningTable.values(): | ||||||||||||||||||||||||||||||||
|
|
@@ -144,6 +198,15 @@ def _createToolsMenu(self): | |||||||||||||||||||||||||||||||
| _("跳到通話視窗(&F)") + "\tNVDA+Windows+F", | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| self._lineSubMenu.AppendSeparator() | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # ── Settings ── | ||||||||||||||||||||||||||||||||
| self._qtAccessibleItem = self._lineSubMenu.Append( | ||||||||||||||||||||||||||||||||
| wx.ID_ANY, | ||||||||||||||||||||||||||||||||
| # Translators: Menu item for toggling Qt accessibility env var | ||||||||||||||||||||||||||||||||
| _("切換 Qt 無障礙環境變數(&Q)"), | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
greptile-apps[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Bind events | ||||||||||||||||||||||||||||||||
| gui.mainFrame.sysTrayIcon.Bind( | ||||||||||||||||||||||||||||||||
| wx.EVT_MENU, self._onAllChats, self._allChatsItem | ||||||||||||||||||||||||||||||||
|
|
@@ -187,6 +250,9 @@ def _createToolsMenu(self): | |||||||||||||||||||||||||||||||
| gui.mainFrame.sysTrayIcon.Bind( | ||||||||||||||||||||||||||||||||
| wx.EVT_MENU, self._onFocusCallWindow, self._focusCallItem | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
| gui.mainFrame.sysTrayIcon.Bind( | ||||||||||||||||||||||||||||||||
| wx.EVT_MENU, self._onToggleQtAccessible, self._qtAccessibleItem | ||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| # Add the submenu to NVDA's Tools menu | ||||||||||||||||||||||||||||||||
| self._toolsMenu = gui.mainFrame.sysTrayIcon.toolsMenu | ||||||||||||||||||||||||||||||||
|
|
@@ -429,6 +495,28 @@ def _announceCallWindow(): | |||||||||||||||||||||||||||||||
| log.warning(f"LINE focusCallWindow error: {e}", exc_info=True) | ||||||||||||||||||||||||||||||||
| ui.message(_("跳到通話視窗功能錯誤: {error}").format(error=e)) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def _onToggleQtAccessible(self, evt): | ||||||||||||||||||||||||||||||||
| wx.CallAfter(self._doToggleQtAccessible) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def _doToggleQtAccessible(self): | ||||||||||||||||||||||||||||||||
| import ui | ||||||||||||||||||||||||||||||||
| lineApp = _getLineAppModule() | ||||||||||||||||||||||||||||||||
| if lineApp and hasattr(lineApp, 'script_toggleQtAccessible'): | ||||||||||||||||||||||||||||||||
| lineApp.script_toggleQtAccessible(None) | ||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||
| # LINE not running — toggle the env var directly | ||||||||||||||||||||||||||||||||
| 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 環境變數失敗")) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| def terminate(self, *args, **kwargs): | ||||||||||||||||||||||||||||||||
| self._removeToolsMenu() | ||||||||||||||||||||||||||||||||
| super().terminate(*args, **kwargs) | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HKCU\Environment不存在時操作會靜默失敗_setQtAccessible使用winreg.OpenKey開啟已存在的機碼。若HKCU\Environment不存在(例如極度精簡的 Windows 環境或 Wine),函式會進入except Exception並回傳False,使用者只會看到錯誤訊息,而不知道原因是 key 不存在。建議改用
winreg.CreateKeyEx,它在 key 已存在時等同OpenKey,在不存在時則自動建立:這樣可同時處理 key 不存在與已存在的情況。此修改在
line.py與lineDesktopHelper.py兩處的_setQtAccessible都應套用。Prompt To Fix With AI