From 4717d36c9110f016868e37d9eff74b1d28af5a9c Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 6 Oct 2012 02:53:44 +0300 Subject: [PATCH] Fix QTextBoundaryFinder usage cases in QAccessible2 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Make the implementation safer and closer to what http://www.linuxfoundation.org/collaborate/workgroups/accessibility/ia2/ia2_implementation_guide#boundaries requires us to do. Change-Id: I00af4697e52a9b6e7f5d7b3f403b29126fa1517b Reviewed-by: Konstantin Ritt Reviewed-by: Lars Knoll Reviewed-by: Jan Arve Sæther --- src/gui/accessible/qaccessible2.cpp | 288 ++++++++++++--------- src/gui/accessible/qaccessible2.h | 8 +- src/plugins/accessible/widgets/simplewidgets.cpp | 13 +- .../other/qaccessibility/tst_qaccessibility.cpp | 1 + 4 files changed, 179 insertions(+), 131 deletions(-) diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp index e3402ef..7f871f9 100644 --- a/src/gui/accessible/qaccessible2.cpp +++ b/src/gui/accessible/qaccessible2.cpp @@ -134,19 +134,184 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QString QAccessibleTextInterface::textBeforeOffset (int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset) const + Returns the text item of type \a boundaryType that is close to offset \a offset + and sets \a startOffset and \a endOffset values to the start and end positions + of that item; returns an empty string if there is no such an item. + Sets \a startOffset and \a endOffset values to -1 on error. */ +QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset) const +{ + const QString txt = text(0, characterCount()); + + if (txt.isEmpty() || offset < 0 || offset > txt.length()) { + *startOffset = *endOffset = -1; + return QString(); + } + if (offset == 0) { + *startOffset = *endOffset = offset; + return QString(); + } + + 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 = txt.length(); + return txt; + } + + // keep behavior in sync with QTextCursor::movePosition()! + + QTextBoundaryFinder boundary(type, txt); + boundary.setPosition(offset); + + do { + if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem))) + break; + } while (boundary.toPreviousBoundary() > 0); + Q_ASSERT(boundary.position() >= 0); + *endOffset = boundary.position(); + + while (boundary.toPreviousBoundary() > 0) { + if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem))) + break; + } + Q_ASSERT(boundary.position() >= 0); + *startOffset = boundary.position(); + + return txt.mid(*startOffset, *endOffset - *startOffset); +} /*! - \fn QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset) const + Returns the text item of type \a boundaryType that is right after offset \a offset + and sets \a startOffset and \a endOffset values to the start and end positions + of that item; returns an empty string if there is no such an item. + Sets \a startOffset and \a endOffset values to -1 on error. */ +QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset) const +{ + const QString txt = text(0, characterCount()); + + if (txt.isEmpty() || offset < 0 || offset > txt.length()) { + *startOffset = *endOffset = -1; + return QString(); + } + if (offset == txt.length()) { + *startOffset = *endOffset = offset; + return QString(); + } + + 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 = txt.length(); + return txt; + } + + // keep behavior in sync with QTextCursor::movePosition()! + + QTextBoundaryFinder boundary(type, txt); + boundary.setPosition(offset); + + while (boundary.toNextBoundary() < txt.length()) { + if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem))) + break; + } + Q_ASSERT(boundary.position() <= txt.length()); + *startOffset = boundary.position(); + + while (boundary.toNextBoundary() < txt.length()) { + if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem))) + break; + } + Q_ASSERT(boundary.position() <= txt.length()); + *endOffset = boundary.position(); + + return txt.mid(*startOffset, *endOffset - *startOffset); +} /*! - \fn QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset) const + Returns the text item of type \a boundaryType at offset \a offset + and sets \a startOffset and \a endOffset values to the start and end positions + of that item; returns an empty string if there is no such an item. + Sets \a startOffset and \a endOffset values to -1 on error. */ +QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset) const +{ + const QString txt = text(0, characterCount()); + + if (txt.isEmpty() || offset < 0 || offset > txt.length()) { + *startOffset = *endOffset = -1; + return QString(); + } + if (offset == txt.length()) { + *startOffset = *endOffset = offset; + return QString(); + } + + 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 = txt.length(); + return txt; + } + + // keep behavior in sync with QTextCursor::movePosition()! + + QTextBoundaryFinder boundary(type, txt); + boundary.setPosition(offset); + + do { + if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem))) + break; + } while (boundary.toPreviousBoundary() > 0); + Q_ASSERT(boundary.position() >= 0); + *startOffset = boundary.position(); + + while (boundary.toNextBoundary() < txt.length()) { + if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem))) + break; + } + Q_ASSERT(boundary.position() <= txt.length()); + *endOffset = boundary.position(); + + return txt.mid(*startOffset, *endOffset - *startOffset); +} /*! \fn void QAccessibleTextInterface::removeSelection(int selectionIndex) @@ -512,117 +677,6 @@ const QString &QAccessibleActionInterface::toggleAction() return accessibleActionStrings()->toggleAction; } - -/*! - \internal -*/ -QString Q_GUI_EXPORT qTextBeforeOffsetFromString(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 qTextAfterOffsetFromString(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 qTextAtOffsetFromString(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); -} - QT_END_NAMESPACE #endif // QT_NO_ACCESSIBILITY diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index ee0215e..c1e7b8b 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -83,12 +83,12 @@ public: // text virtual QString text(int startOffset, int endOffset) const = 0; - virtual QString textBeforeOffset (int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset) const = 0; + virtual QString textBeforeOffset(int offset, QAccessible2::BoundaryType boundaryType, + int *startOffset, int *endOffset) const; virtual QString textAfterOffset(int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset) const = 0; + int *startOffset, int *endOffset) const; virtual QString textAtOffset(int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset) const = 0; + int *startOffset, int *endOffset) const; virtual int characterCount() const = 0; // character <-> geometry diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index 2015929..bb90061 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -72,13 +72,6 @@ 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 qTextBeforeOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset, const QString& text); -QString Q_GUI_EXPORT qTextAtOffsetFromString(int offset, QAccessible2::BoundaryType boundaryType, - int *startOffset, int *endOffset, const QString& text); -QString Q_GUI_EXPORT qTextAfterOffsetFromString(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. @@ -725,7 +718,7 @@ QString QAccessibleLineEdit::textBeforeOffset(int offset, BoundaryType boundaryT *startOffset = *endOffset = -1; return QString(); } - return qTextBeforeOffsetFromString(offset, boundaryType, startOffset, endOffset, lineEdit()->text()); + return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset); } QString QAccessibleLineEdit::textAfterOffset(int offset, BoundaryType boundaryType, @@ -735,7 +728,7 @@ QString QAccessibleLineEdit::textAfterOffset(int offset, BoundaryType boundaryTy *startOffset = *endOffset = -1; return QString(); } - return qTextAfterOffsetFromString(offset, boundaryType, startOffset, endOffset, lineEdit()->text()); + return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset); } QString QAccessibleLineEdit::textAtOffset(int offset, BoundaryType boundaryType, @@ -745,7 +738,7 @@ QString QAccessibleLineEdit::textAtOffset(int offset, BoundaryType boundaryType, *startOffset = *endOffset = -1; return QString(); } - return qTextAtOffsetFromString(offset, boundaryType, startOffset, endOffset, lineEdit()->text()); + return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset); } void QAccessibleLineEdit::removeSelection(int selectionIndex) diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 1b789b2..0166d59 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -1885,6 +1885,7 @@ void tst_QAccessibility::lineEditTest() 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->textAtOffset(101, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(". --")); QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" ")); -- 2.7.4