From: Frederik Gladhorn Date: Tue, 5 Mar 2013 00:19:42 +0000 (+0100) Subject: Implement a basic accessible text interface X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=64688c34743bdb10ff814d65df08ea6bcdf53016;p=konrad%2Fqtdeclarative.git Implement a basic accessible text interface Change-Id: Ic8a807f9de66d2d13da1193fe6e2abb7ccccb2a2 Reviewed-by: Jan Arve Sæther --- diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.cpp b/src/plugins/accessible/quick/qaccessiblequickitem.cpp index da70fe0..f24d508 100644 --- a/src/plugins/accessible/quick/qaccessiblequickitem.cpp +++ b/src/plugins/accessible/quick/qaccessiblequickitem.cpp @@ -40,16 +40,20 @@ ****************************************************************************/ #include "qaccessiblequickitem.h" + +#include + #include "QtQuick/private/qquickitem_p.h" #include "QtQuick/private/qquicktext_p.h" #include "QtQuick/private/qquickaccessibleattached_p.h" +#include "QtQuick/qquicktextdocument.h" QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item) - : QQmlAccessible(item) + : QQmlAccessible(item), m_doc(textDocument()) { } @@ -86,7 +90,6 @@ bool QAccessibleQuickItem::clipsChildren() const return static_cast(item())->clip(); } - QAccessibleInterface *QAccessibleQuickItem::parent() const { QQuickItem *parent = item()->parentItem(); @@ -231,10 +234,11 @@ QString QAccessibleQuickItem::text(QAccessible::Text textType) const // the following block handles item-specific behavior if (role() == QAccessible::EditableText) { if (textType == QAccessible::Value) { + if (QTextDocument *doc = textDocument()) { + return doc->toPlainText(); + } QVariant text = object()->property("text"); return text.toString(); - } else if (textType == QAccessible::Name) { - return object()->objectName(); } } @@ -310,6 +314,138 @@ QRect itemScreenRect(QQuickItem *item) return QRect(screenPos, itemSize); } +QTextDocument *QAccessibleQuickItem::textDocument() const +{ + QVariant docVariant = item()->property("textDocument"); + if (docVariant.canConvert()) { + QQuickTextDocument *qqdoc = docVariant.value(); + return qqdoc->textDocument(); + } + return 0; +} + +int QAccessibleQuickItem::characterCount() const +{ + if (m_doc) { + QTextCursor cursor = QTextCursor(m_doc); + cursor.movePosition(QTextCursor::End); + return cursor.position(); + } + return text(QAccessible::Value).size(); +} + +int QAccessibleQuickItem::cursorPosition() const +{ + QVariant pos = item()->property("cursorPosition"); + return pos.toInt(); +} + +void QAccessibleQuickItem::setCursorPosition(int position) +{ + item()->setProperty("cursorPosition", position); +} + +QString QAccessibleQuickItem::text(int startOffset, int endOffset) const +{ + if (m_doc) { + QTextCursor cursor = QTextCursor(m_doc); + cursor.setPosition(startOffset); + cursor.setPosition(endOffset, QTextCursor::KeepAnchor); + return cursor.selectedText(); + } + return text(QAccessible::Value).mid(startOffset, endOffset - startOffset); +} + +QString QAccessibleQuickItem::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, + int *startOffset, int *endOffset) const +{ + Q_ASSERT(startOffset); + Q_ASSERT(endOffset); + + if (m_doc) { + QTextCursor cursor = QTextCursor(m_doc); + cursor.setPosition(offset); + QPair boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType); + cursor.setPosition(boundaries.first - 1); + boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType); + + *startOffset = boundaries.first; + *endOffset = boundaries.second; + + return text(boundaries.first, boundaries.second); + } else { + return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset); + } +} + +QString QAccessibleQuickItem::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, + int *startOffset, int *endOffset) const +{ + Q_ASSERT(startOffset); + Q_ASSERT(endOffset); + + if (m_doc) { + QTextCursor cursor = QTextCursor(m_doc); + cursor.setPosition(offset); + QPair boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType); + cursor.setPosition(boundaries.second); + boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType); + + *startOffset = boundaries.first; + *endOffset = boundaries.second; + + return text(boundaries.first, boundaries.second); + } else { + return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset); + } +} + +QString QAccessibleQuickItem::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, + int *startOffset, int *endOffset) const +{ + Q_ASSERT(startOffset); + Q_ASSERT(endOffset); + + if (m_doc) { + QTextCursor cursor = QTextCursor(m_doc); + cursor.setPosition(offset); + QPair boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType); + + *startOffset = boundaries.first; + *endOffset = boundaries.second; + return text(boundaries.first, boundaries.second); + } else { + return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset); + } +} + +void QAccessibleQuickItem::selection(int selectionIndex, int *startOffset, int *endOffset) const +{ + *startOffset = item()->property("selectionStart").toInt(); + *endOffset = item()->property("selectionEnd").toInt(); +} + +int QAccessibleQuickItem::selectionCount() const +{ + if (item()->property("selectionStart").toInt() != item()->property("selectionEnd").toInt()) + return 1; + return 0; +} + +void QAccessibleQuickItem::addSelection(int /* startOffset */, int /* endOffset */) +{ + +} +void QAccessibleQuickItem::removeSelection(int /* selectionIndex */) +{ + +} +void QAccessibleQuickItem::setSelection(int /* selectionIndex */, int /* startOffset */, int /* endOffset */) +{ + +} + + #endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/plugins/accessible/quick/qaccessiblequickitem.h b/src/plugins/accessible/quick/qaccessiblequickitem.h index e82b2f8..d9eb652 100644 --- a/src/plugins/accessible/quick/qaccessiblequickitem.h +++ b/src/plugins/accessible/quick/qaccessiblequickitem.h @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY +class QTextDocument; + class QAccessibleQuickItem : public QQmlAccessible, public QAccessibleValueInterface, public QAccessibleTextInterface { public: @@ -81,37 +83,41 @@ public: // 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 */) {} + void selection(int selectionIndex, int *startOffset, int *endOffset) const; + int selectionCount() const; + 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 */) {} + int cursorPosition() const; + 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(); } + QString text(int startOffset, int endOffset) const; + QString textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType, + int *startOffset, int *endOffset) const; + QString textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType, + int *startOffset, int *endOffset) const; + QString textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType, + int *startOffset, int *endOffset) const; + int characterCount() const; // 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(); } + QString attributes(int /* offset */, int *startOffset, int *endOffset) const { *startOffset = 0; *endOffset = 0; return QString(); } + + QTextDocument *textDocument() const; protected: QQuickItem *item() const { return static_cast(object()); } void *interface_cast(QAccessible::InterfaceType t); + +private: + QTextDocument *m_doc; }; QRect itemScreenRect(QQuickItem *item); diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 0a0fac3..2025db4 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -156,6 +156,9 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) if (!parent->property("value").isNull()) { connect(parent, SIGNAL(valueChanged()), this, SLOT(valueChanged())); } + if (!parent->property("cursorPosition").isNull()) { + connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged())); + } } QQuickAccessibleAttached::~QQuickAccessibleAttached() diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 2124356..131b379 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -142,6 +142,10 @@ public Q_SLOTS: QAccessibleValueChangeEvent ev(parent(), parent()->property("value")); QAccessible::updateAccessibility(&ev); } + void cursorPositionChanged() { + QAccessibleTextCursorEvent ev(parent(), parent()->property("cursorPosition").toInt()); + QAccessible::updateAccessibility(&ev); + } Q_SIGNALS: void roleChanged();