11# A part of NonVisual Desktop Access (NVDA)
22# This file is covered by the GNU General Public License.
33# See the file COPYING for more details.
4- # Copyright (C) 2012-2023 Mesar Hameed, NV Access Limited, Leonard de Ruijter, Rui Fontes, Cyrille Bougot
4+ # Copyright (C) 2012-2024 Mesar Hameed, NV Access Limited, Leonard de Ruijter, Rui Fontes, Cyrille Bougot
55
66"""App module for Poedit 3.4+."""
77
88from enum import IntEnum
99
10- import ctypes
1110import api
1211import appModuleHandler
1312import controlTypes
1918from NVDAObjects import NVDAObject
2019from NVDAObjects .window import Window
2120from scriptHandler import getLastScriptRepeatCount , script
22- from logHandler import log
2321
2422
2523LEFT_TO_RIGHT_EMBEDDING = "\u202a "
2927SCRCAT_POEDIT = _ ("Poedit" )
3028
3129
32- class _WindowControlIdOffsetFromDataView (IntEnum ):
33- """Window control ID's are not static, however, the order of ids stays the same.
34- Therefore, using a wxDataView control in the translations list as a reference,
35- we can safely calculate control ids accross releases or instances.
36- This class contains window control id offsets relative to the wxDataView window.
37- """
30+ class _WindowControlId (IntEnum ):
31+ """Static window control ID's as defined in poedit src/static_ids.h."""
3832
39- PRO_IDENTIFIER = - 10 # This is a button in the free version
40- MAIN_SPLITTER_IDENTIFIER = - 2 # The splitter that holds the translation list
41- TRANSLATION_WARNING = 17
42- NEEDS_WORK_SWITCH = 21
33+ NEEDS_WORK_SWITCH = 10101
34+ """The "Needs work" toggle in editing area at the bottom"""
4335
36+ TRANSLATION_ISSUE_TEXT = 10102
37+ """
38+ The error or warning line above translation field
39+ (hidden when there's no issue; ID is of the static text child window with issue's text)
40+ """
4441
45- class _WindowControlIdOffsetFromSidebar (IntEnum ):
46- """Window control ID's are not static, however, the order of ids stays the same.
47- Therefore, using the Sidebar window as a reference,
48- we can safely calculate control ids accross releases or instances.
49- This class contains window control id offsets relative to the Sidebar window.
50- Note that this Sidebar window itself is found relative to the dataview's ancestor splitter control.
42+ PREVIOUS_SOURCE_TEXT = 10103
43+ """
44+ Text of previous source text
45+ (msgid) for current item (shown in sidebar, may be hidden, is static control with the text)
5146 """
5247
53- PRO_OFFSET = - 5
54- OLD_SOURCE_TEXT = 36
55- TRANSLATOR_NOTES = 39
56- COMMENT = 42
48+ NOTES_FOR_TRANSLATOR = 10104
49+ """
50+ Text of notes for translators (extracted from source code) for current item
51+ (shown in sidebar, may be hidden, is static control with the text)
52+ """
53+
54+ TRANSLATOR_COMMENT = 10105
55+ """
56+ Text of translator's comment for current item
57+ (shown in sidebar, may be hidden, is static control with the text)
58+ """
5759
5860
5961def _findDescendantObject (
@@ -80,68 +82,19 @@ def _findDescendantObject(
8082class AppModule (appModuleHandler .AppModule ):
8183 cachePropertiesByDefault = True
8284
83- _dataViewControlId : int | None
84- """Type definition for auto prop '_get__dataViewControlId'"""
85-
86- def _get__dataViewControlId (self ) -> int | None :
87- fg = api .getForegroundObject ()
88- dataView = _findDescendantObject (fg .windowHandle , className = "wxDataView" )
89- if not dataView :
90- return None
91- return dataView .windowControlID
92-
93- _sidebarControlId : int | None
94- """Type definition for auto prop '_get__sidebarControlId'"""
95-
96- def _get__sidebarControlId (self ) -> int | None :
97- dataViewControlId = self ._dataViewControlId
98- splitterControlID = dataViewControlId + _WindowControlIdOffsetFromDataView .MAIN_SPLITTER_IDENTIFIER
99- fg = api .getForegroundObject ()
100- splitterHwnd = windowUtils .findDescendantWindow (fg .windowHandle , controlID = splitterControlID )
101- sidebarHwnd = winUser .getWindow (splitterHwnd , winUser .GW_HWNDNEXT )
102- while sidebarHwnd and not ctypes .windll .user32 .IsWindowVisible (sidebarHwnd ):
103- sidebarHwnd = winUser .getWindow (sidebarHwnd , winUser .GW_HWNDNEXT )
104- if not sidebarHwnd :
105- return None
106- return winUser .getControlID (sidebarHwnd )
107-
108- _isPro : bool
109- """Type definition for auto prop '_get__isPro'"""
110-
111- def _get__isPro (self ) -> bool :
112- """Returns whether this instance of Poedit is a pro version."""
113- obj = self ._getNVDAObjectForWindowControlIdOffsetFromDataView (
114- _WindowControlIdOffsetFromDataView .PRO_IDENTIFIER ,
115- )
116- return obj is None
117-
118- def _getNVDAObjectForWindowControlIdOffsetFromDataView (
119- self ,
120- windowControlIdOffset : _WindowControlIdOffsetFromDataView ,
121- ) -> Window | None :
122- fg = api .getForegroundObject ()
123- return _findDescendantObject (fg .windowHandle , self ._dataViewControlId + windowControlIdOffset )
124-
125- def _getNVDAObjectForWindowControlIdOffsetFromSidebar (
85+ def _getNVDAObjectForWindowControlId (
12686 self ,
127- windowControlIdOffset : _WindowControlIdOffsetFromSidebar ,
87+ windowControlId : _WindowControlId ,
12888 ) -> Window | None :
12989 fg = api .getForegroundObject ()
130- sidebarControlId = self ._sidebarControlId
131- if sidebarControlId is None :
132- log .error ("Sidebar can not be found" )
133- return None
134- extraOffset = 0
135- if self ._isPro :
136- extraOffset = _WindowControlIdOffsetFromSidebar .PRO_OFFSET
137- return _findDescendantObject (fg .windowHandle , sidebarControlId + extraOffset + windowControlIdOffset )
90+ return _findDescendantObject (fg .windowHandle , windowControlId )
13891
13992 _translatorNotesObj : Window | None
14093 """Type definition for auto prop '_get__translatorNotesObj'"""
14194
14295 def _get__translatorNotesObj (self ) -> Window | None :
143- return self ._getNVDAObjectForWindowControlIdOffsetFromSidebar (
144- _WindowControlIdOffsetFromSidebar . TRANSLATOR_NOTES ,
96+ return self ._getNVDAObjectForWindowControlId (
97+ _WindowControlId . NOTES_FOR_TRANSLATOR ,
14598 )
14699
147100 def _reportControlScriptHelper (self , obj : Window , description : str ):
@@ -191,9 +144,7 @@ def script_reportAutoCommentsWindow(self, gesture):
191144 """Type definition for auto prop '_get__commentObj'"""
192145
193146 def _get__commentObj (self ) -> Window | None :
194- return self ._getNVDAObjectForWindowControlIdOffsetFromSidebar (
195- _WindowControlIdOffsetFromSidebar .COMMENT ,
196- )
147+ return self ._getNVDAObjectForWindowControlId (_WindowControlId .TRANSLATOR_COMMENT )
197148
198149 @script (
199150 description = pgettext (
@@ -214,64 +165,64 @@ def script_reportCommentsWindow(self, gesture):
214165 pgettext ("poedit" , "comment" ),
215166 )
216167
217- _oldSourceTextObj : Window | None
218- """Type definition for auto prop '_get__oldSourceTextObj '"""
168+ _previousSourceTextObj : Window | None
169+ """Type definition for auto prop '_get__previousSourceTextObj '"""
219170
220- def _get__oldSourceTextObj (self ) -> Window | None :
221- return self ._getNVDAObjectForWindowControlIdOffsetFromSidebar (
222- _WindowControlIdOffsetFromSidebar . OLD_SOURCE_TEXT ,
171+ def _get__previousSourceTextObj (self ) -> Window | None :
172+ return self ._getNVDAObjectForWindowControlId (
173+ _WindowControlId . PREVIOUS_SOURCE_TEXT ,
223174 )
224175
225176 @script (
226177 description = pgettext (
227178 "poedit" ,
228179 # Translators: The description of an NVDA command for Poedit.
229- "Reports the old source text, if any. If pressed twice, presents the text in browse mode" ,
180+ "Reports the previous source text, if any. If pressed twice, presents the text in browse mode" ,
230181 ),
231182 gesture = "kb:control+shift+o" ,
232183 category = SCRCAT_POEDIT ,
233184 speakOnDemand = True ,
234185 )
235186 def script_reportOldSourceText (self , gesture ):
236187 self ._reportControlScriptHelper (
237- self ._oldSourceTextObj ,
238- # Translators: The description of the "old source text" window in poedit.
188+ self ._previousSourceTextObj ,
189+ # Translators: The description of the "previous source text" window in poedit.
239190 # This text is reported when the given window contains no item to report or could not be found.
240- pgettext ("poedit" , "old source text" ),
191+ pgettext ("poedit" , "previous source text" ),
241192 )
242193
243- _translationWarningObj : Window | None
244- """Type definition for auto prop '_get__translationWarningObj '"""
194+ _translationIssueObj : Window | None
195+ """Type definition for auto prop '_get__translationIssueObj '"""
245196
246- def _get__translationWarningObj (self ) -> Window | None :
247- return self ._getNVDAObjectForWindowControlIdOffsetFromDataView (
248- _WindowControlIdOffsetFromDataView . TRANSLATION_WARNING ,
197+ def _get__translationIssueObj (self ) -> Window | None :
198+ return self ._getNVDAObjectForWindowControlId (
199+ _WindowControlId . TRANSLATION_ISSUE_TEXT ,
249200 )
250201
251202 @script (
252203 description = pgettext (
253204 "poedit" ,
254205 # Translators: The description of an NVDA command for Poedit.
255- "Reports a translation warning , if any. If pressed twice, presents the warning in browse mode" ,
206+ "Reports a translation issue , if any. If pressed twice, presents the warning in browse mode" ,
256207 ),
257208 gesture = "kb:control+shift+w" ,
258209 category = SCRCAT_POEDIT ,
259210 speakOnDemand = True ,
260211 )
261212 def script_reportTranslationWarning (self , gesture ):
262213 self ._reportControlScriptHelper (
263- self ._translationWarningObj ,
264- # Translators: The description of the "translation warning " window in poedit.
214+ self ._translationIssueObj ,
215+ # Translators: The description of the "translation issue " window in poedit.
265216 # This text is reported when the given window contains no item to report or could not be found.
266- pgettext ("poedit" , "translation warning " ),
217+ pgettext ("poedit" , "translation issue " ),
267218 )
268219
269220 _needsWorkObj : Window | None
270221 """Type definition for auto prop '_get__needsWorkObj'"""
271222
272223 def _get__needsWorkObj (self ) -> Window | None :
273- obj = self ._getNVDAObjectForWindowControlIdOffsetFromDataView (
274- _WindowControlIdOffsetFromDataView .NEEDS_WORK_SWITCH ,
224+ obj = self ._getNVDAObjectForWindowControlId (
225+ _WindowControlId .NEEDS_WORK_SWITCH ,
275226 )
276227 if obj and obj .role == controlTypes .Role .CHECKBOX :
277228 return obj
@@ -301,19 +252,19 @@ def _get_name(self) -> str:
301252
302253
303254class PoeditListItem (NVDAObject ):
304- _warningControlToReport : _WindowControlIdOffsetFromDataView | None
255+ _warningControlToReport : _WindowControlId | None
305256 appModule : AppModule
306257
307258 def _get__warningControlToReport (self ) -> int | None :
308- obj = self .appModule ._needsWorkObj
309- if obj and controlTypes .State .CHECKED in obj .states :
310- return _WindowControlIdOffsetFromDataView .NEEDS_WORK_SWITCH
311- obj = self .appModule ._oldSourceTextObj
259+ obj = self .appModule ._previousSourceTextObj
312260 if obj and not obj .hasIrrelevantLocation :
313- return _WindowControlIdOffsetFromSidebar . OLD_SOURCE_TEXT
314- obj = self .appModule ._translationWarningObj
261+ return _WindowControlId . PREVIOUS_SOURCE_TEXT
262+ obj = self .appModule ._translationIssueObj
315263 if obj and obj .parent and obj .parent .parent and not obj .parent .parent .hasIrrelevantLocation :
316- return _WindowControlIdOffsetFromDataView .TRANSLATION_WARNING
264+ return _WindowControlId .TRANSLATION_ISSUE_TEXT
265+ obj = self .appModule ._needsWorkObj
266+ if obj and controlTypes .State .CHECKED in obj .states :
267+ return _WindowControlId .NEEDS_WORK_SWITCH
317268 return None
318269
319270 def _get_name (self ):
@@ -332,9 +283,9 @@ def reportFocus(self):
332283 tones .beep (440 , 50 )
333284 return
334285 match self ._warningControlToReport :
335- case _WindowControlIdOffsetFromSidebar . OLD_SOURCE_TEXT :
286+ case _WindowControlId . PREVIOUS_SOURCE_TEXT :
336287 tones .beep (495 , 50 )
337- case _WindowControlIdOffsetFromDataView . TRANSLATION_WARNING :
288+ case _WindowControlId . TRANSLATION_ISSUE_TEXT :
338289 tones .beep (550 , 50 )
339- case _WindowControlIdOffsetFromDataView .NEEDS_WORK_SWITCH :
290+ case _WindowControlId .NEEDS_WORK_SWITCH :
340291 tones .beep (660 , 50 )
0 commit comments