qt.py
4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#NVDAObjects/IAccessible/qt.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2006-2009 NVDA Contributors <http://www.nvda-project.org/>
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
from comtypes import COMError
import controlTypes
from NVDAObjects.IAccessible import IAccessible
import eventHandler
from scriptHandler import isScriptWaiting
class Client(IAccessible):
def _get__containedWidget(self):
widget = self.firstChild
if not widget:
return None
wnext = widget.next
if not wnext:
# There is only one child, so this is probably a widget container.
return widget
try:
if wnext.firstChild.role == controlTypes.ROLE_SCROLLBAR:
# There is only one child plus a scrollbar, so this is probably a widget container.
return widget
except AttributeError:
pass
# This is not a widget container.
return None
def event_gainFocus(self):
if eventHandler.isPendingEvents("gainFocus"):
return
widget = self._containedWidget
if widget:
# This is a widget container.
# Redirect the focus to the contained widget, since QT doesn't do it properly.
self.event_focusEntered()
eventHandler.executeEvent("gainFocus", widget)
return
return super(Client, self).event_gainFocus()
class Container(IAccessible):
def _get_activeChild(self):
# QT doesn't do accFocus properly, so find the active child ourselves.
child = self.firstChild
while child:
states = child.states
if controlTypes.STATE_FOCUSED in states or controlTypes.STATE_SELECTED in states:
return child
child = child.next
return None
def _get_shouldAllowIAccessibleFocusEvent(self):
# QT doesn't fire focus on the active child as it should, so we will bounce the focus to it.
# However, as the container does not have the focused state in QT5, we must still ensure we can get the event if we are going to bounce it
res=super(Container,self).shouldAllowIAccessibleFocusEvent
if not res:
res=bool(self.activeChild)
return res
def event_gainFocus(self):
if eventHandler.isPendingEvents("gainFocus"):
return
child = self.activeChild
if child:
# QT doesn't fire focus on the active child as it should, so redirect the focus.
self.event_focusEntered()
eventHandler.executeEvent("gainFocus", child)
return
return super(Container, self).event_gainFocus()
class TableRow(Container):
value=None
description=None
def _get_activeChild(self):
# QT doesn't do accFocus properly, so find the active child ourselves.
child = self.firstChild
while child:
states = child.states
if controlTypes.STATE_FOCUSED in states:
return child
child = child.next
return None
class TableCell(IAccessible):
value=None
def script_nextColumn(self,gesture):
gesture.send()
if not isScriptWaiting():
next=self.next
if next and controlTypes.STATE_FOCUSED in next.states:
eventHandler.executeEvent("gainFocus", next)
def script_previousColumn(self,gesture):
gesture.send()
if not isScriptWaiting():
previous=self.previous
if previous and controlTypes.STATE_FOCUSED in previous.states:
eventHandler.executeEvent("gainFocus", previous)
__gestures = {
"kb:tab": "nextColumn",
"kb:rightArrow": "nextColumn",
"kb:shift+tab": "previousColumn",
"kb:leftArrow": "previousColumn",
}
class TreeViewItem(IAccessible):
value = None
hasEncodedAccDescription=True
class Menu(IAccessible):
# QT incorrectly fires a focus event on the parent menu immediately after (correctly) firing focus on the menu item.
# This is probably QT task 241161, which was apparently fixed in QT 4.5.1.
shouldAllowIAccessibleFocusEvent = False
class LayeredPane(IAccessible):
# QT < 4.6 uses ROLE_SYSTEM_IPADDRESS for layered pane.
# See QT task 258413.
role = controlTypes.ROLE_LAYEREDPANE
class Application(IAccessible):
# QT sets the path of the application in the description, which is irrelevant to the user.
description = None
def _get_states(self):
states = super(Application, self)._get_states()
# The application should not have the focused state.
# Otherwise, checks for the focused state will always hit the application and assume the focus is valid.
states.discard(controlTypes.STATE_FOCUSED)
return states