5#include <QtCore/qdebug.h>
6#include <QtCore/qloggingcategory.h>
7#include <private/qguiapplication_p.h>
9#if QT_CONFIG(accessibility)
13Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCache,
"qt.accessibility.cache");
16
17
18
19
21static QAccessibleCache *accessibleCache =
nullptr;
22static bool inCacheDestructor =
false;
24static void cleanupAccessibleCache()
26 delete accessibleCache;
27 accessibleCache =
nullptr;
30QAccessibleObjectDestroyedEvent::~QAccessibleObjectDestroyedEvent()
34QAccessibleCache::~QAccessibleCache()
36 inCacheDestructor =
true;
38 for (QAccessible::Id id: idToInterface.keys())
42QAccessibleCache *QAccessibleCache::instance()
44 if (!accessibleCache) {
45 accessibleCache =
new QAccessibleCache;
46 qAddPostRoutine(cleanupAccessibleCache);
48 return accessibleCache;
52
53
54
55
56QAccessible::Id QAccessibleCache::acquireId()
const
58 static const QAccessible::Id FirstId = QAccessible::Id(INT_MAX) + 1;
59 static QAccessible::Id nextId = FirstId;
61 while (idToInterface.contains(nextId)) {
64 if (nextId == UINT_MAX - 1)
73QAccessibleInterface *QAccessibleCache::interfaceForId(QAccessible::Id id)
const
75 return idToInterface.value(id);
78QAccessible::Id QAccessibleCache::idForInterface(QAccessibleInterface *iface)
const
80 return interfaceToId.value(iface);
83QAccessible::Id QAccessibleCache::idForObject(QObject *obj)
const
86 const QMetaObject *mo = obj->metaObject();
87 for (
auto pair : objectToId.values(obj)) {
88 if (pair.second == mo) {
97
98
99
100
101bool QAccessibleCache::containsObject(QObject *obj)
const
104 const QMetaObject *mo = obj->metaObject();
105 for (
auto pair : objectToId.values(obj)) {
106 if (pair.second == mo) {
114QAccessible::Id QAccessibleCache::insert(QObject *object, QAccessibleInterface *iface)
const
120 Q_ASSERT(!containsObject(object));
121 Q_ASSERT_X(!interfaceToId.contains(iface),
"",
"Accessible interface inserted into cache twice!");
123 QAccessible::Id id = acquireId();
124 QObject *obj = iface->object();
125 Q_ASSERT(object == obj);
127 objectToId.insert(obj, std::pair(id, obj->metaObject()));
128 connect(obj, &QObject::destroyed,
this, &QAccessibleCache::objectDestroyed);
130 idToInterface.insert(id, iface);
131 interfaceToId.insert(iface, id);
132 qCDebug(lcAccessibilityCache) <<
"insert - id:" << id <<
" iface:" << iface;
136void QAccessibleCache::objectDestroyed(QObject* obj)
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 for (
auto pair : objectToId.values(obj)) {
164 QAccessible::Id id = pair.first;
165 Q_ASSERT_X(idToInterface.contains(id),
"",
"QObject with accessible interface deleted, where interface not in cache!");
166 deleteInterface(id, obj);
170void QAccessibleCache::sendObjectDestroyedEvent(QObject *obj)
172 for (
auto pair : objectToId.values(obj)) {
173 QAccessible::Id id = pair.first;
174 Q_ASSERT_X(idToInterface.contains(id),
"",
"QObject with accessible interface deleted, where interface not in cache!");
176 QAccessibleObjectDestroyedEvent event(id);
177 QAccessible::updateAccessibility(&event);
181void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj)
183 const auto it = idToInterface.find(id);
184 if (it == idToInterface.end())
187 QAccessibleInterface *iface = *it;
188 qCDebug(lcAccessibilityCache) <<
"delete - id:" << id <<
" iface:" << iface;
190 idToInterface.erase(it);
196 if (!inCacheDestructor && !obj && !iface->object()) {
197 if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing && QAccessible::isActive()) {
198 QAccessibleObjectDestroyedEvent event(id);
199 QAccessible::updateAccessibility(&event);
203 idToInterface.erase(it);
204 interfaceToId.take(iface);
206 obj = iface->object();
208 objectToId.remove(obj);
212 removeAccessibleElement(id);
218#include "moc_qaccessiblecache_p.cpp"