8
8
9
9
from enum import IntEnum
10
10
11
+ import ctypes
11
12
import api
12
13
import appModuleHandler
13
14
import controlTypes
19
20
from NVDAObjects import NVDAObject
20
21
from NVDAObjects .window import Window
21
22
from scriptHandler import getLastScriptRepeatCount , script
23
+ from logHandler import log
24
+
22
25
23
26
LEFT_TO_RIGHT_EMBEDDING = "\u202a "
24
27
"""Character often found in translator comments."""
27
30
SCRCAT_POEDIT = _ ("Poedit" )
28
31
29
32
30
- class _WindowControlIdOffset (IntEnum ):
33
+ class _WindowControlIdOffsetFromDataView (IntEnum ):
31
34
"""Window control ID's are not static, however, the order of ids stays the same.
32
35
Therefore, using a wxDataView control in the translations list as a reference,
33
36
we can safely calculate control ids accross releases or instances.
34
37
This class contains window control id offsets relative to the wxDataView window.
35
38
"""
36
39
37
40
PRO_IDENTIFIER = - 10 # This is a button in the free version
38
- OLD_SOURCE_TEXT_PRO = 60
39
- OLD_SOURCE_TEXT = 65
40
- TRANSLATOR_NOTES_PRO = 63
41
- TRANSLATOR_NOTES = 68 # 63 in Pro
42
- COMMENT_PRO = 66
43
- COMMENT = 71
41
+ MAIN_SPLITTER_IDENTIFIER = - 2 # The splitter that holds the translation list
44
42
TRANSLATION_WARNING = 17
45
43
NEEDS_WORK_SWITCH = 21
46
44
47
45
46
+ class _WindowControlIdOffsetFromSidebar (IntEnum ):
47
+ """Window control ID's are not static, however, the order of ids stays the same.
48
+ Therefore, using the Sidebar window as a reference,
49
+ we can safely calculate control ids accross releases or instances.
50
+ This class contains window control id offsets relative to the Sidebar window.
51
+ Note that this Sidebar window itself is found relative to the dataview's ancestor splitter control.
52
+ """
53
+
54
+ PRO_OFFSET = - 5
55
+ OLD_SOURCE_TEXT = 36
56
+ TRANSLATOR_NOTES = 39
57
+ COMMENT = 42
58
+
59
+
48
60
def _findDescendantObject (
49
61
parentWindowHandle : int ,
50
62
controlId : int | None = None ,
@@ -79,42 +91,58 @@ def _get__dataViewControlId(self) -> int | None:
79
91
return None
80
92
return dataView .windowControlID
81
93
94
+ _sidebarControlId : int | None
95
+ """Type definition for auto prop '_get__sidebarControlId'"""
96
+
97
+ def _get__sidebarControlId (self ) -> int | None :
98
+ dataViewControlId = self ._dataViewControlId
99
+ splitterControlID = dataViewControlId + _WindowControlIdOffsetFromDataView .MAIN_SPLITTER_IDENTIFIER
100
+ fg = api .getForegroundObject ()
101
+ splitterHwnd = windowUtils .findDescendantWindow (fg .windowHandle , controlID = splitterControlID )
102
+ sidebarHwnd = winUser .getWindow (splitterHwnd , winUser .GW_HWNDNEXT )
103
+ while sidebarHwnd and not ctypes .windll .user32 .IsWindowVisible (sidebarHwnd ):
104
+ sidebarHwnd = winUser .getWindow (sidebarHwnd , winUser .GW_HWNDNEXT )
105
+ if not sidebarHwnd :
106
+ return None
107
+ return winUser .getControlID (sidebarHwnd )
108
+
82
109
_isPro : bool
83
110
"""Type definition for auto prop '_get__isPro'"""
84
111
85
112
def _get__isPro (self ) -> bool :
86
113
"""Returns whether this instance of Poedit is a pro version."""
87
- obj = self ._getNVDAObjectForWindowControlIdOffset (_WindowControlIdOffset .PRO_IDENTIFIER )
114
+ obj = self ._getNVDAObjectForWindowControlIdOffsetFromDataView (
115
+ _WindowControlIdOffsetFromDataView .PRO_IDENTIFIER
116
+ )
88
117
return obj is None
89
118
90
- def _correctWindowControllIdOfset (
91
- self ,
92
- windowControlIdOffset : _WindowControlIdOffset
93
- ) -> _WindowControlIdOffset :
94
- """Corrects a _WindowControlIdOffset when a pro version of Poedit is active."""
95
- if self ._isPro :
96
- match windowControlIdOffset :
97
- case _WindowControlIdOffset .OLD_SOURCE_TEXT :
98
- return _WindowControlIdOffset .OLD_SOURCE_TEXT_PRO
99
- case _WindowControlIdOffset .TRANSLATOR_NOTES :
100
- return _WindowControlIdOffset .TRANSLATOR_NOTES_PRO
101
- case _WindowControlIdOffset .COMMENT :
102
- return _WindowControlIdOffset .COMMENT_PRO
103
- return windowControlIdOffset
104
-
105
- def _getNVDAObjectForWindowControlIdOffset (
119
+ def _getNVDAObjectForWindowControlIdOffsetFromDataView (
106
120
self ,
107
- windowControlIdOffset : _WindowControlIdOffset
121
+ windowControlIdOffset : _WindowControlIdOffsetFromDataView
108
122
) -> Window | None :
109
123
fg = api .getForegroundObject ()
110
124
return _findDescendantObject (fg .windowHandle , self ._dataViewControlId + windowControlIdOffset )
111
125
126
+ def _getNVDAObjectForWindowControlIdOffsetFromSidebar (
127
+ self ,
128
+ windowControlIdOffset : _WindowControlIdOffsetFromSidebar
129
+ ) -> Window | None :
130
+ fg = api .getForegroundObject ()
131
+ sidebarControlId = self ._sidebarControlId
132
+ if sidebarControlId is None :
133
+ log .error ("Sidebar can not be found" )
134
+ return None
135
+ extraOffset = 0
136
+ if self ._isPro :
137
+ extraOffset = _WindowControlIdOffsetFromSidebar .PRO_OFFSET
138
+ return _findDescendantObject (fg .windowHandle , sidebarControlId + extraOffset + windowControlIdOffset )
139
+
112
140
_translatorNotesObj : Window | None
113
141
"""Type definition for auto prop '_get__translatorNotesObj'"""
114
142
115
143
def _get__translatorNotesObj (self ) -> Window | None :
116
- return self ._getNVDAObjectForWindowControlIdOffset (
117
- self . _correctWindowControllIdOfset ( _WindowControlIdOffset . TRANSLATOR_NOTES )
144
+ return self ._getNVDAObjectForWindowControlIdOffsetFromSidebar (
145
+ _WindowControlIdOffsetFromSidebar . TRANSLATOR_NOTES
118
146
)
119
147
120
148
def _reportControlScriptHelper (self , obj : Window , description : str ):
@@ -164,8 +192,8 @@ def script_reportAutoCommentsWindow(self, gesture):
164
192
"""Type definition for auto prop '_get__commentObj'"""
165
193
166
194
def _get__commentObj (self ) -> Window | None :
167
- return self ._getNVDAObjectForWindowControlIdOffset (
168
- self . _correctWindowControllIdOfset ( _WindowControlIdOffset . COMMENT )
195
+ return self ._getNVDAObjectForWindowControlIdOffsetFromSidebar (
196
+ _WindowControlIdOffsetFromSidebar . COMMENT
169
197
)
170
198
171
199
@script (
@@ -191,8 +219,8 @@ def script_reportCommentsWindow(self, gesture):
191
219
"""Type definition for auto prop '_get__oldSourceTextObj'"""
192
220
193
221
def _get__oldSourceTextObj (self ) -> Window | None :
194
- return self ._getNVDAObjectForWindowControlIdOffset (
195
- self . _correctWindowControllIdOfset ( _WindowControlIdOffset . OLD_SOURCE_TEXT )
222
+ return self ._getNVDAObjectForWindowControlIdOffsetFromSidebar (
223
+ _WindowControlIdOffsetFromSidebar . OLD_SOURCE_TEXT
196
224
)
197
225
198
226
@script (
@@ -217,7 +245,9 @@ def script_reportOldSourceText(self, gesture):
217
245
"""Type definition for auto prop '_get__translationWarningObj'"""
218
246
219
247
def _get__translationWarningObj (self ) -> Window | None :
220
- return self ._getNVDAObjectForWindowControlIdOffset (_WindowControlIdOffset .TRANSLATION_WARNING )
248
+ return self ._getNVDAObjectForWindowControlIdOffsetFromDataView (
249
+ _WindowControlIdOffsetFromDataView .TRANSLATION_WARNING
250
+ )
221
251
222
252
@script (
223
253
description = pgettext (
@@ -241,7 +271,9 @@ def script_reportTranslationWarning(self, gesture):
241
271
"""Type definition for auto prop '_get__needsWorkObj'"""
242
272
243
273
def _get__needsWorkObj (self ) -> Window | None :
244
- obj = self ._getNVDAObjectForWindowControlIdOffset (_WindowControlIdOffset .NEEDS_WORK_SWITCH )
274
+ obj = self ._getNVDAObjectForWindowControlIdOffsetFromDataView (
275
+ _WindowControlIdOffsetFromDataView .NEEDS_WORK_SWITCH
276
+ )
245
277
if obj and obj .role == controlTypes .Role .CHECKBOX :
246
278
return obj
247
279
return None
@@ -270,19 +302,19 @@ def _get_name(self) -> str:
270
302
271
303
272
304
class PoeditListItem (NVDAObject ):
273
- _warningControlToReport : _WindowControlIdOffset | None
305
+ _warningControlToReport : _WindowControlIdOffsetFromDataView | None
274
306
appModule : AppModule
275
307
276
- def _get__warningControlToReport (self ) -> _WindowControlIdOffset | None :
308
+ def _get__warningControlToReport (self ) -> int | None :
277
309
obj = self .appModule ._needsWorkObj
278
310
if obj and controlTypes .State .CHECKED in obj .states :
279
- return _WindowControlIdOffset .NEEDS_WORK_SWITCH
311
+ return _WindowControlIdOffsetFromDataView .NEEDS_WORK_SWITCH
280
312
obj = self .appModule ._oldSourceTextObj
281
313
if obj and not obj .hasIrrelevantLocation :
282
- return _WindowControlIdOffset .OLD_SOURCE_TEXT
314
+ return _WindowControlIdOffsetFromSidebar .OLD_SOURCE_TEXT
283
315
obj = self .appModule ._translationWarningObj
284
316
if obj and obj .parent and obj .parent .parent and not obj .parent .parent .hasIrrelevantLocation :
285
- return _WindowControlIdOffset .TRANSLATION_WARNING
317
+ return _WindowControlIdOffsetFromDataView .TRANSLATION_WARNING
286
318
return None
287
319
288
320
def _get_name (self ):
@@ -301,9 +333,9 @@ def reportFocus(self):
301
333
tones .beep (440 , 50 )
302
334
return
303
335
match self ._warningControlToReport :
304
- case _WindowControlIdOffset .OLD_SOURCE_TEXT :
336
+ case _WindowControlIdOffsetFromSidebar .OLD_SOURCE_TEXT :
305
337
tones .beep (495 , 50 )
306
- case _WindowControlIdOffset .TRANSLATION_WARNING :
338
+ case _WindowControlIdOffsetFromDataView .TRANSLATION_WARNING :
307
339
tones .beep (550 , 50 )
308
- case _WindowControlIdOffset .NEEDS_WORK_SWITCH :
340
+ case _WindowControlIdOffsetFromDataView .NEEDS_WORK_SWITCH :
309
341
tones .beep (660 , 50 )
0 commit comments