Fix QTextBoundaryFinder usage cases in QAccessible2
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 <ritt.ks@gmail.com> Reviewed-by: Lars Knoll <lars.knoll@digia.com> Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
This commit is contained in:
parent
539ef45689
commit
4717d36c91
@ -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
|
||||
|
@ -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
|
||||
|
@ -72,13 +72,6 @@ extern QList<QWidget*> 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)
|
||||
|
@ -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(" "));
|
||||
|
Loading…
Reference in New Issue
Block a user