From c8ef32e2b6cded37a6854b94a281464c1b7a298b Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Sun, 4 Nov 2012 12:54:30 +0100 Subject: Accessibility: Improve interface handling in Quick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changes how interfaces are handled: the QAccessibleQuickItem will simply subclass all interfaces and dynamically return 0 or the appropriate interface_cast. This makes our implementation a lot more flexible. To make use of the value interface, only a value property is needed (together with a corresponding role). Since the implementation of the interfaces became simpler, the value interface and some text interface improvements go along with the change. Change-Id: I003ec3016d48d730a4acac467bce322167842f4d Reviewed-by: Jan Arve Sæther --- src/plugins/accessible/quick/main.cpp | 17 +------ .../accessible/quick/qaccessiblequickitem.cpp | 28 +++++++---- .../accessible/quick/qaccessiblequickitem.h | 55 +++++++++++++++------- src/quick/items/qquickaccessibleattached_p.h | 12 +++++ src/quick/items/qquickitem.cpp | 10 ++-- src/quick/items/qquicktextinput.cpp | 17 +++++-- 6 files changed, 90 insertions(+), 49 deletions(-) diff --git a/src/plugins/accessible/quick/main.cpp b/src/plugins/accessible/quick/main.cpp index 882cbcda4f..cac5d7e58d 100644 --- a/src/plugins/accessible/quick/main.cpp +++ b/src/plugins/accessible/quick/main.cpp @@ -92,22 +92,7 @@ QAccessibleInterface *AccessibleQuickFactory::create(const QString &classname, Q QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (!itemPrivate->isAccessible) return 0; - - QVariant v = QQuickAccessibleAttached::property(item, "role"); - bool ok; - QAccessible::Role role = (QAccessible::Role)v.toInt(&ok); - if (!ok) // Not sure if this check is needed. - return new QAccessibleQuickItem(item); - - switch (role) { - case QAccessible::Slider: - case QAccessible::SpinBox: - case QAccessible::Dial: - case QAccessible::ScrollBar: - return new QAccessibleQuickItemValueInterface(item); - default: - return new QAccessibleQuickItem(item); - } + return new QAccessibleQuickItem(item); } return 0; diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.cpp b/src/plugins/accessible/quick/qaccessiblequickitem.cpp index 2d41379940..8d36834d48 100644 --- a/src/plugins/accessible/quick/qaccessiblequickitem.cpp +++ b/src/plugins/accessible/quick/qaccessiblequickitem.cpp @@ -228,7 +228,7 @@ QString QAccessibleQuickItem::text(QAccessible::Text textType) const break; } - // the following blocks handles item-specific behavior + // the following block handles item-specific behavior if (role() == QAccessible::EditableText) { if (textType == QAccessible::Value) { QVariant text = object()->property("text"); @@ -241,34 +241,44 @@ QString QAccessibleQuickItem::text(QAccessible::Text textType) const return QString(); } -void *QAccessibleQuickItemValueInterface::interface_cast(QAccessible::InterfaceType t) +void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t) { - if (t == QAccessible::ValueInterface) + QAccessible::Role r = role(); + if (t == QAccessible::ValueInterface && + (r == QAccessible::Slider || + r == QAccessible::SpinBox || + r == QAccessible::Dial || + r == QAccessible::ScrollBar)) return static_cast(this); - return QAccessibleQuickItem::interface_cast(t); + + if (t == QAccessible::TextInterface && + (r == QAccessible::EditableText)) + return static_cast(this); + + return QQmlAccessible::interface_cast(t); } -QVariant QAccessibleQuickItemValueInterface::currentValue() const +QVariant QAccessibleQuickItem::currentValue() const { return item()->property("value"); } -void QAccessibleQuickItemValueInterface::setCurrentValue(const QVariant &value) +void QAccessibleQuickItem::setCurrentValue(const QVariant &value) { item()->setProperty("value", value); } -QVariant QAccessibleQuickItemValueInterface::maximumValue() const +QVariant QAccessibleQuickItem::maximumValue() const { return item()->property("maximumValue"); } -QVariant QAccessibleQuickItemValueInterface::minimumValue() const +QVariant QAccessibleQuickItem::minimumValue() const { return item()->property("minimumValue"); } -QVariant QAccessibleQuickItemValueInterface::minimumStepSize() const +QVariant QAccessibleQuickItem::minimumStepSize() const { return item()->property("stepSize"); } diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.h b/src/plugins/accessible/quick/qaccessiblequickitem.h index 0d31749ee0..46f573cc75 100644 --- a/src/plugins/accessible/quick/qaccessiblequickitem.h +++ b/src/plugins/accessible/quick/qaccessiblequickitem.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY -class QAccessibleQuickItem : public QQmlAccessible +class QAccessibleQuickItem : public QQmlAccessible, public QAccessibleValueInterface, public QAccessibleTextInterface { public: QAccessibleQuickItem(QQuickItem *item); @@ -72,28 +72,51 @@ public: bool isAccessible() const; -protected: - QQuickItem *item() const { return static_cast(object()); } -}; - -QRect itemScreenRect(QQuickItem *item); - - -class QAccessibleQuickItemValueInterface: public QAccessibleQuickItem, public QAccessibleValueInterface -{ -public: - QAccessibleQuickItemValueInterface(QQuickItem *item) : QAccessibleQuickItem(item) - {} - - void *interface_cast(QAccessible::InterfaceType t); - + // Value Interface QVariant currentValue() const; void setCurrentValue(const QVariant &value); QVariant maximumValue() const; QVariant minimumValue() const; QVariant minimumStepSize() const; + + + // Text Interface + // selection (ignored for now) + void selection(int selectionIndex, int *startOffset, int *endOffset) const { *startOffset = 0; *endOffset = 0; } + int selectionCount() const { return 0; } + void addSelection(int startOffset, int endOffset) {} + void removeSelection(int selectionIndex) {} + void setSelection(int selectionIndex, int startOffset, int endOffset) {} + + // cursor + int cursorPosition() const { return 0; } + void setCursorPosition(int position) {} + + // text + QString text(int startOffset, int endOffset) const { return text(QAccessible::Name).mid(startOffset, endOffset - startOffset); } +// QString textBeforeOffset(int offset, QAccessible2::BoundaryType boundaryType, +// int *startOffset, int *endOffset) const; +// QString textAfterOffset(int offset, QAccessible2::BoundaryType boundaryType, +// int *startOffset, int *endOffset) const; +// QString textAtOffset(int offset, QAccessible2::BoundaryType boundaryType, +// int *startOffset, int *endOffset) const; + int characterCount() const { return text(QAccessible::Name).count(); } + + // character <-> geometry + QRect characterRect(int offset) const { return QRect(); } + int offsetAtPoint(const QPoint &point) const { return -1; } + + void scrollToSubstring(int startIndex, int endIndex) {} + QString attributes(int offset, int *startOffset, int *endOffset) const { return QString(); } + +protected: + QQuickItem *item() const { return static_cast(object()); } + void *interface_cast(QAccessible::InterfaceType t); }; +QRect itemScreenRect(QQuickItem *item); + + #endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 74f486ae7d..a11f40c535 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -127,6 +127,18 @@ public: return obj->setProperty(propertyName, value); } + static QObject *findAccessible(QObject *object, QAccessible::Role role = QAccessible::NoRole) + { + while (object) { + QObject *att = QQuickAccessibleAttached::attachedProperties(object); + if (att && (role == QAccessible::NoRole || att->property("role").toInt() == role)) { + break; + } + object = object->parent(); + } + return object; + } + Q_SIGNALS: void roleChanged(); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 2340da9b9f..b23ff68abd 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3129,8 +3129,12 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event) void QQuickItem::focusInEvent(QFocusEvent * /*event*/) { #ifndef QT_NO_ACCESSIBILITY - QAccessibleEvent ev(this, QAccessible::Focus); - QAccessible::updateAccessibility(&ev); + if (QAccessible::isActive()) { + if (QObject *acc = QQuickAccessibleAttached::findAccessible(this)) { + QAccessibleEvent ev(acc, QAccessible::Focus); + QAccessible::updateAccessibility(&ev); + } + } #endif } @@ -5274,7 +5278,7 @@ void QQuickItem::setFlags(Flags flags) } } - if ((flags & ItemClipsChildrenToShape ) != (d->flags & ItemClipsChildrenToShape)) + if ((flags & ItemClipsChildrenToShape) != (d->flags & ItemClipsChildrenToShape)) d->dirty(QQuickItemPrivate::Clip); d->flags = flags; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index fee49593ee..6dd8fb157d 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -59,6 +59,7 @@ #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" +#include "qquickaccessibleattached_p.h" #endif QT_BEGIN_NAMESPACE @@ -3374,9 +3375,11 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e #ifdef QT_NO_ACCESSIBILITY Q_UNUSED(changed) #else - if (changed) { - QAccessibleTextUpdateEvent ev(q, 0, oldText, m_text); - QAccessible::updateAccessibility(&ev); + if (changed && QAccessible::isActive()) { + if (QObject *acc = QQuickAccessibleAttached::findAccessible(q, QAccessible::EditableText)) { + QAccessibleTextUpdateEvent ev(acc, 0, oldText, m_text); + QAccessible::updateAccessibility(&ev); + } } #endif } @@ -4025,8 +4028,12 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged() } #ifndef QT_NO_ACCESSIBILITY - QAccessibleTextCursorEvent ev(q, m_cursor); - QAccessible::updateAccessibility(&ev); + if (QAccessible::isActive()) { + if (QObject *acc = QQuickAccessibleAttached::findAccessible(q, QAccessible::EditableText)) { + QAccessibleTextCursorEvent ev(acc, m_cursor); + QAccessible::updateAccessibility(&ev); + } + } #endif return true; -- cgit v1.2.3