From c1ec1a95806cda54d5b4e9f8ed159a611bd75964 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 5 Jul 2011 17:05:11 +0200 Subject: Implement text interface for QLineEdit. Add boundary helper functions to the QAccessibleTextInterface. Move LineEdit over to use QTextBoundaryFinder. Reviewed-by: Jan-Arve --- src/gui/accessible/qaccessible2.cpp | 112 +++++++++++++++++++++++ src/plugins/accessible/widgets/simplewidgets.cpp | 40 +++++--- tests/auto/qaccessibility/tst_qaccessibility.cpp | 55 ++++++++++- 3 files changed, 194 insertions(+), 13 deletions(-) diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp index 35b24f6..b62a7a4 100644 --- a/src/gui/accessible/qaccessible2.cpp +++ b/src/gui/accessible/qaccessible2.cpp @@ -42,6 +42,7 @@ #include "qaccessible2.h" #include "qapplication.h" #include "qclipboard.h" +#include "qtextboundaryfinder.h" #ifndef QT_NO_ACCESSIBILITY @@ -132,6 +133,117 @@ QT_BEGIN_NAMESPACE \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink */ + +/*! + \internal +*/ +QString Q_GUI_EXPORT textBeforeOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset, const QString& text) +{ + QTextBoundaryFinder::BoundaryType type; + switch (boundaryType) { + case QAccessible2::CharBoundary: + type = QTextBoundaryFinder::Grapheme; + break; + case QAccessible2::WordBoundary: + type = QTextBoundaryFinder::Word; + break; + case QAccessible2::SentenceBoundary: + type = QTextBoundaryFinder::Sentence; + break; + default: + // in any other case return the whole line + *startOffset = 0; + *endOffset = text.length(); + return text; + } + + QTextBoundaryFinder boundary(type, text); + boundary.setPosition(offset); + + if (!boundary.isAtBoundary()) { + boundary.toPreviousBoundary(); + } + boundary.toPreviousBoundary(); + *startOffset = boundary.position(); + boundary.toNextBoundary(); + *endOffset = boundary.position(); + + return text.mid(*startOffset, *endOffset - *startOffset); +} + +/*! + \internal +*/ +QString Q_GUI_EXPORT textAfterOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset, const QString& text) +{ + QTextBoundaryFinder::BoundaryType type; + switch (boundaryType) { + case QAccessible2::CharBoundary: + type = QTextBoundaryFinder::Grapheme; + break; + case QAccessible2::WordBoundary: + type = QTextBoundaryFinder::Word; + break; + case QAccessible2::SentenceBoundary: + type = QTextBoundaryFinder::Sentence; + break; + default: + // in any other case return the whole line + *startOffset = 0; + *endOffset = text.length(); + return text; + } + + QTextBoundaryFinder boundary(type, text); + boundary.setPosition(offset); + + boundary.toNextBoundary(); + *startOffset = boundary.position(); + boundary.toNextBoundary(); + *endOffset = boundary.position(); + + return text.mid(*startOffset, *endOffset - *startOffset); +} + +/*! + \internal +*/ +QString Q_GUI_EXPORT textAtOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset, const QString& text) +{ + QTextBoundaryFinder::BoundaryType type; + switch (boundaryType) { + case QAccessible2::CharBoundary: + type = QTextBoundaryFinder::Grapheme; + break; + case QAccessible2::WordBoundary: + type = QTextBoundaryFinder::Word; + break; + case QAccessible2::SentenceBoundary: + type = QTextBoundaryFinder::Sentence; + break; + default: + // in any other case return the whole line + *startOffset = 0; + *endOffset = text.length(); + return text; + } + + QTextBoundaryFinder boundary(type, text); + boundary.setPosition(offset); + + if (!boundary.isAtBoundary()) { + boundary.toPreviousBoundary(); + } + *startOffset = boundary.position(); + boundary.toNextBoundary(); + *endOffset = boundary.position(); + + return text.mid(*startOffset, *endOffset - *startOffset); +} + QAccessibleSimpleEditableTextInterface::QAccessibleSimpleEditableTextInterface( QAccessibleInterface *accessibleInterface) : iface(accessibleInterface) diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index ad56cbd..4f469e5 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -68,6 +68,13 @@ extern QList childWidgets(const QWidget *widget, bool includeTopLevel QString Q_GUI_EXPORT qt_accStripAmp(const QString &text); QString Q_GUI_EXPORT qt_accHotKey(const QString &text); +QString Q_GUI_EXPORT textBeforeOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset, const QString& text); +QString Q_GUI_EXPORT textAtOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset, const QString& text); +QString Q_GUI_EXPORT textAfterOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset, const QString& text); + /*! \class QAccessibleButton \brief The QAccessibleButton class implements the QAccessibleInterface for button type widgets. @@ -815,25 +822,34 @@ QString QAccessibleLineEdit::text(int startOffset, int endOffset) return lineEdit()->text().mid(startOffset, endOffset - startOffset); } -QString QAccessibleLineEdit::textBeforeOffset (int /*offset*/, BoundaryType /*boundaryType*/, - int * /*startOffset*/, int * /*endOffset*/) +QString QAccessibleLineEdit::textBeforeOffset(int offset, BoundaryType boundaryType, + int *startOffset, int *endOffset) { - // TODO - return QString(); + if (lineEdit()->echoMode() != QLineEdit::Normal) { + *startOffset = *endOffset = -1; + return QString(); + } + return textBeforeOffsetFromString(offset, boundaryType, startOffset, endOffset, lineEdit()->text()); } -QString QAccessibleLineEdit::textAfterOffset(int /*offset*/, BoundaryType /*boundaryType*/, - int * /*startOffset*/, int * /*endOffset*/) +QString QAccessibleLineEdit::textAfterOffset(int offset, BoundaryType boundaryType, + int *startOffset, int *endOffset) { - // TODO - return QString(); + if (lineEdit()->echoMode() != QLineEdit::Normal) { + *startOffset = *endOffset = -1; + return QString(); + } + return textAfterOffsetFromString(offset, boundaryType, startOffset, endOffset, lineEdit()->text()); } -QString QAccessibleLineEdit::textAtOffset(int /*offset*/, BoundaryType /*boundaryType*/, - int * /*startOffset*/, int * /*endOffset*/) +QString QAccessibleLineEdit::textAtOffset(int offset, BoundaryType boundaryType, + int *startOffset, int *endOffset) { - // TODO - return QString(); + if (lineEdit()->echoMode() != QLineEdit::Normal) { + *startOffset = *endOffset = -1; + return QString(); + } + return textAtOffsetFromString(offset, boundaryType, startOffset, endOffset, lineEdit()->text()); } void QAccessibleLineEdit::removeSelection(int selectionIndex) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index aedb87e..d764187 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -3058,8 +3058,61 @@ void tst_QAccessibility::lineEditTest() delete iface; delete le; delete le2; - delete toplevel; QTestAccessibility::clearEvents(); + + // IA2 + QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde"; + QLineEdit *le3 = new QLineEdit(cite, toplevel); + iface = QAccessible::queryAccessibleInterface(le3); + QAccessibleTextInterface* textIface = iface->textInterface(); + le3->deselect(); + le3->setCursorPosition(3); + QCOMPARE(textIface->cursorPosition(), 3); + QCOMPARE(textIface->selectionCount(), 0); + int start, end; + + QCOMPARE(textIface->text(0, 8), QString::fromLatin1("I always")); + QCOMPARE(textIface->textAtOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("I")); + QCOMPARE(start, 0); + QCOMPARE(end, 1); + QCOMPARE(textIface->textBeforeOffset(0, QAccessible2::CharBoundary,&start,&end), QString()); + QCOMPARE(textIface->textAfterOffset(0, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(start, 1); + QCOMPARE(end, 2); + + QCOMPARE(textIface->textAtOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("a")); + QCOMPARE(start, 5); + QCOMPARE(end, 6); + QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("w")); + QCOMPARE(textIface->textAfterOffset(5, QAccessible2::CharBoundary,&start,&end), QString::fromLatin1("y")); + + QCOMPARE(textIface->textAtOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); + QCOMPARE(start, 2); + QCOMPARE(end, 8); + + QCOMPARE(textIface->textAtOffset(2, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); + QCOMPARE(textIface->textAtOffset(7, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("always")); + QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice")); + QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself")); + + QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); + QCOMPARE(textIface->textAtOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. ")); + QCOMPARE(start, 0); + QCOMPARE(end, 30); + + QCOMPARE(textIface->textBeforeOffset(40, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("I always pass on good advice. ")); + QCOMPARE(textIface->textAfterOffset(5, QAccessible2::SentenceBoundary,&start,&end), QString::fromLatin1("It is the only thing to do with it. ")); + + QCOMPARE(textIface->textAtOffset(5, QAccessible2::ParagraphBoundary,&start,&end), cite); + QCOMPARE(start, 0); + QCOMPARE(end, cite.length()); + QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite); + QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite); + + delete iface; + delete toplevel; } void tst_QAccessibility::workspaceTest() -- cgit v0.12