From 69c2384fd0a4dde9231c7e9453ec9c8f4c6fd11f Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Wed, 30 Apr 2014 22:25:49 +0200 Subject: [PATCH 03/12] Add textWithBoundaries --- src/qaccessibilityclient/accessibleobject.cpp | 8 +++++++ src/qaccessibilityclient/accessibleobject.h | 31 +++++++++++++++++++++++++++ src/qaccessibilityclient/registry_p.cpp | 20 +++++++++++++++++ src/qaccessibilityclient/registry_p.h | 1 + tests/auto/tst_accessibilityclient.cpp | 24 ++++++++++++++++++++- 5 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/qaccessibilityclient/accessibleobject.cpp b/src/qaccessibilityclient/accessibleobject.cpp index bf17ae3..21686bd 100644 --- a/src/qaccessibilityclient/accessibleobject.cpp +++ b/src/qaccessibilityclient/accessibleobject.cpp @@ -235,6 +235,14 @@ QString AccessibleObject::text(int startOffset, int endOffset) const return QString(); } +QString AccessibleObject::textWithBoundary(int offset, TextBoundary boundary, int *startOffset, int *endOffset) const +{ + if (supportedInterfaces() & AccessibleObject::TextInterface) + return d->registryPrivate->textWithBoundary(*this, offset, boundary, startOffset, endOffset); + qWarning() << "text called on accessible that does not implement text"; + return QString(); +} + bool AccessibleObject::setText(const QString &text) { if( supportedInterfaces() & AccessibleObject::EditableTextInterface ) diff --git a/src/qaccessibilityclient/accessibleobject.h b/src/qaccessibilityclient/accessibleobject.h index c4913fc..a0d0db4 100644 --- a/src/qaccessibilityclient/accessibleobject.h +++ b/src/qaccessibilityclient/accessibleobject.h @@ -183,6 +183,20 @@ public: }; /** + \brief The TextBoundaries enum represents the different boundaries when + asking for text at a certain offset. + */ + enum TextBoundary { + CharBoundary, + WordStartBoundary, + WordEndBoundary, + SentenceStartBoundary, + SentenceEndBoundary, + LineStartBoundary, + LineEndBoundary + }; + + /** \brief Construct an invalid AccessibleObject. */ AccessibleObject(); @@ -434,6 +448,23 @@ public: QString text(int startOffset = 0, int endOffset = -1) const; /** + \brief Returns the text of the TextInterface by boundary. + + Especially for larger text fields it may be more performant and easier to + query the text at a certain position instead of the full text. + + For example the line where the cursor is currently can be retrieved with this function + in a convenient way. + + \param offset is the position of the requested text. + \param startOffset returns the beginning of the offset, for example the start of the line when + asking for line boundaries. + \param endOffset returns the end of the text section + \return the text at the offset. + */ + QString textWithBoundary(int offset, TextBoundary boundary, int *startOffset = 0, int *endOffset = 0) const; + + /** \brief Set the text of the EditableTextInterface. \param text The text to set. diff --git a/src/qaccessibilityclient/registry_p.cpp b/src/qaccessibilityclient/registry_p.cpp index 45e0834..d28bfb0 100644 --- a/src/qaccessibilityclient/registry_p.cpp +++ b/src/qaccessibilityclient/registry_p.cpp @@ -958,6 +958,26 @@ QString RegistryPrivate::text(const AccessibleObject &object, int startOffset, i return reply.value(); } +QString RegistryPrivate::textWithBoundary(const AccessibleObject &object, int offset, AccessibleObject::TextBoundary boundary, int *startOffset, int *endOffset) const +{ + QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("GetTextAtOffset")); + message.setArguments(QVariantList() << offset << (AtspiTextBoundaryType) boundary); + QDBusMessage reply = conn.connection().call(message); + if (reply.type() != QDBusMessage::ReplyMessage || reply.signature() != QStringLiteral("sii")) { + qWarning() << "Could not access text." << reply.errorMessage(); + if (startOffset) + *startOffset = 0; + if (endOffset) + *endOffset = 0; + return QString(); + } + if (startOffset) + *startOffset = reply.arguments().at(1).toInt(); + if (endOffset) + *endOffset = reply.arguments().at(2).toInt(); + return reply.arguments().first().toString();; +} + bool RegistryPrivate::setText(const AccessibleObject &object, const QString &text) { QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("SetTextContents")); diff --git a/src/qaccessibilityclient/registry_p.h b/src/qaccessibilityclient/registry_p.h index b35de51..e28ecd4 100644 --- a/src/qaccessibilityclient/registry_p.h +++ b/src/qaccessibilityclient/registry_p.h @@ -81,6 +81,7 @@ public: QList< QPair > textSelections(const AccessibleObject &object) const; void setTextSelections(const AccessibleObject &object, const QList< QPair > &selections); QString text(const AccessibleObject &object, int startOffset = 0, int endOffset = -1) const; + QString textWithBoundary(const AccessibleObject &object, int offset, AccessibleObject::TextBoundary boundary, int *startOffset, int *endOffset) const; bool setText(const AccessibleObject &object, const QString &text); bool insertText(const AccessibleObject &object, const QString &text, int position, int length = -1); diff --git a/tests/auto/tst_accessibilityclient.cpp b/tests/auto/tst_accessibilityclient.cpp index dc1eb69..2fcb856 100644 --- a/tests/auto/tst_accessibilityclient.cpp +++ b/tests/auto/tst_accessibilityclient.cpp @@ -467,8 +467,30 @@ void AccessibilityClientTest::tst_characterExtents() AccessibleObject textArea = app.child(0).child(0); QVERIFY(textArea.supportedInterfaces() & QAccessibleClient::AccessibleObject::TextInterface); - QCOMPARE(textArea.characterRect(0), QRect(20,40,0,14)); textEdit->setText("This is useless text that is being used to test this text area.\n I \n hope \n this will get correct\n\t\t\tCharacterExtents!"); + QPoint pos = w.pos(); + + int start; + int end; + QString textWord = textArea.textWithBoundary(0, AccessibleObject::WordStartBoundary, &start, &end); + QCOMPARE(textWord, QStringLiteral("This")); + QCOMPARE(start, 0); + QCOMPARE(end, 4); + textWord = textArea.textWithBoundary(6, AccessibleObject::WordStartBoundary, &start, &end); + QCOMPARE(textWord , QStringLiteral("is")); + QCOMPARE(start, 5); + QCOMPARE(end, 7); + textWord = textArea.textWithBoundary(3, AccessibleObject::WordEndBoundary); + QCOMPARE(textWord , QStringLiteral("This")); + + QString textSentence = textArea.textWithBoundary(0, AccessibleObject::SentenceEndBoundary); + QCOMPARE(textSentence, QStringLiteral("This is useless text that is being used to test this text area.")); + QString textLine = textArea.textWithBoundary(0, AccessibleObject::LineEndBoundary); + QCOMPARE(textLine, QStringLiteral("This is useless text that is being used to test this text area.")); + textLine = textArea.textWithBoundary(0, AccessibleObject::LineEndBoundary); + QCOMPARE(textLine, QStringLiteral("This is useless text that is being used to test this text area.")); + + QCOMPARE(textArea.characterRect(0), QRect(20,40,7,14).translated(pos)); QCOMPARE(textArea.characterRect(1), QRect(20,40,7,14)); } -- 2.9.4