Implement a basic accessible text interface
authorFrederik Gladhorn <frederik.gladhorn@digia.com>
Tue, 5 Mar 2013 00:19:42 +0000 (01:19 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 26 Apr 2013 08:49:36 +0000 (10:49 +0200)
Change-Id: Ic8a807f9de66d2d13da1193fe6e2abb7ccccb2a2
Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>

src/plugins/accessible/quick/qaccessiblequickitem.cpp
src/plugins/accessible/quick/qaccessiblequickitem.h
src/quick/items/qquickaccessibleattached.cpp
src/quick/items/qquickaccessibleattached_p.h

index da70fe0..f24d508 100644 (file)
 ****************************************************************************/
 
 #include "qaccessiblequickitem.h"
+
+#include <QtGui/qtextdocument.h>
+
 #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<QQuickItem *>(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*>()) {
+        QQuickTextDocument *qqdoc = docVariant.value<QQuickTextDocument*>();
+        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<int, int> 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<int, int> 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<int, int> 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
index e82b2f8..d9eb652 100644 (file)
@@ -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<QQuickItem*>(object()); }
     void *interface_cast(QAccessible::InterfaceType t);
+
+private:
+    QTextDocument *m_doc;
 };
 
 QRect itemScreenRect(QQuickItem *item);
index 0a0fac3..2025db4 100644 (file)
@@ -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()
index 2124356..131b379 100644 (file)
@@ -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();