summaryrefslogtreecommitdiffstats
path: root/src/gui/accessible/qaccessible.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/accessible/qaccessible.cpp')
-rw-r--r--src/gui/accessible/qaccessible.cpp106
1 files changed, 94 insertions, 12 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 3468ebc8a7..e007c9967e 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -41,6 +41,8 @@
#include "qaccessible.h"
+#include "qaccessible2_p.h"
+#include "qaccessiblecache_p.h"
#include "qaccessibleplugin.h"
#include "qaccessibleobject.h"
#include "qaccessiblebridge.h"
@@ -558,6 +560,8 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH
return old;
}
+Q_GLOBAL_STATIC(QAccessibleCache, qAccessibleCache)
+
/*!
If a QAccessibleInterface implementation exists for the given \a object,
this function returns a pointer to the implementation; otherwise it
@@ -574,8 +578,7 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH
function tries to find an implementation for the object's parent
class, using the above strategy.
- \warning The caller is responsible for deleting the returned
- interface after use.
+ All interfaces are managed by an internal cache and should not be deleted.
*/
QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
{
@@ -583,6 +586,9 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
if (!object)
return 0;
+ if (Id id = qAccessibleCache->objectToId.value(object))
+ return qAccessibleCache->interfaceForId(id);
+
// Create a QAccessibleInterface for the object class. Start by the most
// derived class and walk up the class hierarchy.
const QMetaObject *mo = object->metaObject();
@@ -592,8 +598,11 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
// Check if the class has a InterfaceFactory installed.
for (int i = qAccessibleFactories()->count(); i > 0; --i) {
InterfaceFactory factory = qAccessibleFactories()->at(i - 1);
- if (QAccessibleInterface *iface = factory(cn, object))
+ if (QAccessibleInterface *iface = factory(cn, object)) {
+ qAccessibleCache->insert(object, iface);
+ Q_ASSERT(qAccessibleCache->objectToId.contains(object));
return iface;
+ }
}
#ifndef QT_NO_ACCESSIBILITY
#ifndef QT_NO_LIBRARY
@@ -610,22 +619,84 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
// At this point the cache should contain a valid factory pointer or 0:
Q_ASSERT(qAccessiblePlugins()->contains(cn));
QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn);
- if (factory)
- return factory->create(cn, object);
+ if (factory) {
+ QAccessibleInterface *result = factory->create(cn, object);
+ if (result) { // Need this condition because of QDesktopScreenWidget
+ qAccessibleCache->insert(object, result);
+ Q_ASSERT(qAccessibleCache->objectToId.contains(object));
+ }
+ return result;
+ }
#endif
#endif
mo = mo->superClass();
}
#ifndef QT_NO_ACCESSIBILITY
- if (object == qApp)
- return new QAccessibleApplication;
+ if (object == qApp) {
+ QAccessibleInterface *appInterface = new QAccessibleApplication;
+ qAccessibleCache->insert(object, appInterface);
+ Q_ASSERT(qAccessibleCache->objectToId.contains(qApp));
+ return appInterface;
+ }
#endif
return 0;
}
/*!
+ \internal
+ Required to ensure that manually created interfaces
+ are properly memory managed.
+
+ Must only be called exactly once per interface.
+ This is implicitly called when calling queryAccessibleInterface,
+ so it's only required when re-implementing for example
+ the child function and returning the child after new-ing
+ a QAccessibleInterface subclass.
+ */
+QAccessible::Id QAccessible::registerAccessibleInterface(QAccessibleInterface *iface)
+{
+ Q_ASSERT(iface);
+ return qAccessibleCache->insert(iface->object(), iface);
+}
+
+/*!
+ \internal
+ Removes the interface belonging to this id from the cache and
+ deletes it. The id becomes invalid an may be re-used by the
+ cache.
+*/
+void QAccessible::deleteAccessibleInterface(Id id)
+{
+ qAccessibleCache->deleteInterface(id);
+}
+
+/*!
+ \internal
+ Returns the unique ID for the accessibleInterface.
+*/
+QAccessible::Id QAccessible::uniqueId(QAccessibleInterface *iface)
+{
+ Id id = qAccessibleCache->idToInterface.key(iface);
+ if (!id)
+ id = registerAccessibleInterface(iface);
+ return id;
+}
+
+/*!
+ \internal
+ Returns the QAccessibleInterface belonging to the id.
+
+ Returns 0 if the id is invalid.
+*/
+QAccessibleInterface *QAccessible::accessibleInterface(Id id)
+{
+ return qAccessibleCache->idToInterface.value(id);
+}
+
+
+/*!
Returns true if an accessibility implementation has been requested
during the runtime of the application; otherwise returns false.
@@ -687,15 +758,23 @@ void QAccessible::setRootObject(QObject *object)
*/
void QAccessible::updateAccessibility(QAccessibleEvent *event)
{
- if (updateHandler) {
- updateHandler(event);
+ if (!isActive())
return;
+
+#ifndef QT_NO_ACCESSIBILITY
+ if (event->type() == QAccessible::TableModelChanged) {
+ Q_ASSERT(event->object());
+ if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(event->object())) {
+ if (iface->tableInterface())
+ iface->tableInterface()->modelChange(static_cast<QAccessibleTableModelChangeEvent*>(event));
+ }
}
- if (!isActive())
+ if (updateHandler) {
+ updateHandler(event);
return;
+ }
-#ifndef QT_NO_ACCESSIBILITY
if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
pfAccessibility->notifyAccessibilityUpdate(event);
#endif
@@ -1028,6 +1107,10 @@ QColor QAccessibleInterface::backgroundColor() const
return QColor();
}
+QAccessibleInterface::~QAccessibleInterface()
+{
+}
+
/*!
\fn QAccessibleTextInterface *QAccessibleInterface::textInterface()
\internal
@@ -1362,7 +1445,6 @@ QAccessibleInterface *QAccessibleEvent::accessibleInterface() const
if (m_child >= 0) {
QAccessibleInterface *child = iface->child(m_child);
if (child) {
- delete iface;
iface = child;
} else {
qWarning() << "Cannot creat accessible child interface for object: " << m_object << " index: " << m_child;