10#include <QtCore/qtextboundaryfinder.h>
11#include <QtGui/qclipboard.h>
12#include <QtGui/qguiapplication.h>
13#include <QtGui/qtextcursor.h>
14#include <private/qguiapplication_p.h>
15#include <qpa/qplatformaccessibility.h>
16#include <qpa/qplatformintegration.h>
18#include <QtCore/qdebug.h>
19#include <QtCore/qloggingcategory.h>
20#include <QtCore/qmetaobject.h>
21#include <QtCore/private/qmetaobject_p.h>
22#include <QtCore/qhash.h>
23#include <private/qfactoryloader_p.h>
501#if QT_CONFIG(accessibility)
506QAccessibleInterface::~QAccessibleInterface()
519 (QAccessibleFactoryInterface_iid,
"/accessible"_L1))
520typedef QHash<QString, QAccessiblePlugin*> QAccessiblePluginsHash;
524Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories)
525Q_GLOBAL_STATIC(QList<QAccessible::ActivationObserver *>, qAccessibleActivationObservers)
527QAccessible::UpdateHandler QAccessible::updateHandler =
nullptr;
528QAccessible::RootObjectHandler QAccessible::rootObjectHandler =
nullptr;
530static bool cleanupAdded =
false;
532static QPlatformAccessibility *platformAccessibility()
535 return pfIntegration ? pfIntegration->accessibility() :
nullptr;
550void QAccessible::cleanup()
552 if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
553 pfAccessibility->cleanup();
556static void qAccessibleCleanup()
558 qAccessibleActivationObservers()->clear();
559 qAccessibleFactories()->clear();
609void QAccessible::installFactory(InterfaceFactory
factory)
620 qAccessibleFactories()->append(
factory);
626void QAccessible::removeFactory(InterfaceFactory
factory)
628 qAccessibleFactories()->removeAll(
factory);
638QAccessible::UpdateHandler QAccessible::installUpdateHandler(UpdateHandler handler)
640 UpdateHandler old = updateHandler;
641 updateHandler = handler;
651QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectHandler handler)
653 RootObjectHandler old = rootObjectHandler;
654 rootObjectHandler = handler;
666QAccessible::ActivationObserver::~ActivationObserver()
675void QAccessible::installActivationObserver(QAccessible::ActivationObserver *observer)
684 if (qAccessibleActivationObservers()->
contains(observer))
686 qAccessibleActivationObservers()->append(observer);
695void QAccessible::removeActivationObserver(ActivationObserver *observer)
697 qAccessibleActivationObservers()->removeAll(observer);
718QAccessibleInterface *QAccessible::queryAccessibleInterface(
QObject *
object)
723 if (Id
id = QAccessibleCache::instance()->idForObject(
object))
724 return QAccessibleCache::instance()->interfaceForId(
id);
739 const bool qmlRelated = !objectPriv->isDeletingChildren &&
740 objectPriv->declarativeData;
741 while (qmlRelated &&
mo) {
746 mo =
mo->superClass();
752 for (
int i = qAccessibleFactories()->
size();
i > 0; --
i) {
753 InterfaceFactory
factory = qAccessibleFactories()->at(
i - 1);
754 if (QAccessibleInterface *iface =
factory(cn,
object)) {
755 QAccessibleCache::instance()->insert(
object, iface);
756 Q_ASSERT(QAccessibleCache::instance()->containsObject(
object));
762 if (!qAccessiblePlugins()->
contains(cn)) {
763 QAccessiblePlugin *
factory =
nullptr;
764 const int index = acLoader()->indexOf(cn);
766 factory = qobject_cast<QAccessiblePlugin *>(acLoader()->instance(
index));
767 qAccessiblePlugins()->insert(cn,
factory);
772 QAccessiblePlugin *
factory = qAccessiblePlugins()->value(cn);
776 QAccessibleCache::instance()->insert(
object,
result);
777 Q_ASSERT(QAccessibleCache::instance()->containsObject(
object));
781 mo =
mo->superClass();
784 if (
object ==
qApp) {
785 QAccessibleInterface *appInterface =
new QAccessibleApplication;
786 QAccessibleCache::instance()->insert(
object, appInterface);
787 Q_ASSERT(QAccessibleCache::instance()->containsObject(
qApp));
808QAccessible::Id QAccessible::registerAccessibleInterface(QAccessibleInterface *iface)
811 return QAccessibleCache::instance()->insert(
iface->object(), iface);
819void QAccessible::deleteAccessibleInterface(Id
id)
821 QAccessibleCache::instance()->deleteInterface(
id);
827QAccessible::Id QAccessible::uniqueId(QAccessibleInterface *iface)
829 Id id = QAccessibleCache::instance()->idForInterface(iface);
831 id = registerAccessibleInterface(iface);
840QAccessibleInterface *QAccessible::accessibleInterface(Id
id)
842 return QAccessibleCache::instance()->interfaceForId(
id);
857bool QAccessible::isActive()
859 if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
860 return pfAccessibility->isActive();
867void QAccessible::setActive(
bool active)
869 for (
int i = 0;
i < qAccessibleActivationObservers()->size() ;++
i)
870 qAccessibleActivationObservers()->at(
i)->accessibilityActiveChanged(active);
888void QAccessible::setRootObject(
QObject *
object)
890 if (rootObjectHandler) {
891 rootObjectHandler(
object);
895 if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
896 pfAccessibility->setRootObject(
object);
918void QAccessible::updateAccessibility(QAccessibleEvent *
event)
926 QAccessibleInterface *
iface =
event->accessibleInterface();
928 if (
event->type() == QAccessible::TableModelChanged) {
929 if (
iface->tableInterface())
930 iface->tableInterface()->modelChange(
static_cast<QAccessibleTableModelChangeEvent*
>(
event));
935 updateHandler(
event);
939 if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
940 pfAccessibility->notifyAccessibilityUpdate(
event);
950QPair< int, int > QAccessible::qAccessibleTextBoundaryHelper(
const QTextCursor &offsetCursor, TextBoundaryType boundaryType)
956 int characterCount = endCursor.position();
960 switch (boundaryType) {
972 case SentenceBoundary: {
981 const int offsetWithinBlockText = offsetCursor.position() -
result.first;
983 sentenceFinder.setPosition(offsetWithinBlockText);
984 int prevBoundary = offsetWithinBlockText;
985 int nextBoundary = offsetWithinBlockText;
987 prevBoundary = sentenceFinder.toPreviousBoundary();
988 nextBoundary = sentenceFinder.toNextBoundary();
989 if (nextBoundary != -1)
991 if (prevBoundary != -1)
992 result.first += prevBoundary;
1000 case ParagraphBoundary:
1008 result.second = characterCount;
1158QList<QPair<QAccessibleInterface*, QAccessible::Relation>>
1159QAccessibleInterface::relations(QAccessible::Relation
match)
const
1170QAccessibleInterface *QAccessibleInterface::focusChild()
const
1309QColor QAccessibleInterface::foregroundColor()
const
1319QColor QAccessibleInterface::backgroundColor()
const
1396QAccessibleEvent::~QAccessibleEvent()
1423QAccessible::Id QAccessibleEvent::uniqueId()
const
1427 QAccessibleInterface *
iface = QAccessible::queryAccessibleInterface(m_object);
1430 if (m_child != -1) {
1433 qCWarning(lcAccessibilityCore) <<
"Invalid child in QAccessibleEvent:" << m_object <<
"child:" << m_child;
1437 return QAccessible::uniqueId(iface);
1475QAccessibleValueChangeEvent::~QAccessibleValueChangeEvent()
1518QAccessibleStateChangeEvent::~QAccessibleStateChangeEvent()
1597QAccessibleTableModelChangeEvent::~QAccessibleTableModelChangeEvent()
1625QAccessibleTextCursorEvent::~QAccessibleTextCursorEvent()
1665QAccessibleTextInsertEvent::~QAccessibleTextInsertEvent()
1707QAccessibleTextRemoveEvent::~QAccessibleTextRemoveEvent()
1768QAccessibleTextUpdateEvent::~QAccessibleTextUpdateEvent()
1802QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent()
1853QAccessibleAnnouncementEvent::~QAccessibleAnnouncementEvent()
1860QAccessibleInterface *QAccessibleEvent::accessibleInterface()
const
1862 if (m_object ==
nullptr)
1863 return QAccessible::accessibleInterface(m_uniqueId);
1865 QAccessibleInterface *
iface = QAccessible::queryAccessibleInterface(m_object);
1866 if (!iface || !
iface->isValid())
1870 QAccessibleInterface *
child =
iface->child(m_child);
1874 qCWarning(lcAccessibilityCore) <<
"Cannot create accessible child interface for object: " << m_object <<
" index: " << m_child;
1893QWindow *QAccessibleInterface::window()
const
1906void QAccessibleInterface::virtual_hook(
int ,
void * )
1927const char *qAccessibleRoleString(QAccessible::Role role)
1929 if (role >= QAccessible::UserRole)
1930 role = QAccessible::UserRole;
1931 static int roleEnum = QAccessible::staticMetaObject.indexOfEnumerator(
"Role");
1932 return QAccessible::staticMetaObject.enumerator(roleEnum).valueToKey(role);
1936const char *qAccessibleEventString(QAccessible::Event
event)
1938 static int eventEnum = QAccessible::staticMetaObject.indexOfEnumerator(
"Event");
1939 return QAccessible::staticMetaObject.enumerator(eventEnum).valueToKey(
event);
1942#ifndef QT_NO_DEBUG_STREAM
1948 d <<
"QAccessibleInterface(null)";
1952 d <<
"QAccessibleInterface(" <<
Qt::hex << (
const void *) iface <<
Qt::dec;
1953 if (
iface->isValid()) {
1954 d <<
" name=" <<
iface->text(QAccessible::Name) <<
' ';
1955 d <<
"role=" << qAccessibleRoleString(
iface->role()) <<
' ';
1956 if (
iface->childCount())
1957 d <<
"childc=" <<
iface->childCount() <<
' ';
1958 if (
iface->object()) {
1959 d <<
"obj=" <<
iface->object();
1964 stateStrings << u
"focusable"_s;
1966 stateStrings << u
"focused"_s;
1968 stateStrings << u
"selected"_s;
1970 stateStrings << u
"invisible"_s;
1972 if (!stateStrings.isEmpty())
1973 d << stateStrings.join(u
'|');
1976 d <<
"rect=" <<
iface->rect();
1989 d.nospace() <<
"QAccessibleEvent(";
1992 d.nospace() <<
"child=" << ev.child();
1994 d.nospace() <<
"no object, uniqueId=" << ev.uniqueId();
1996 d <<
" event=" << qAccessibleEventString(ev.type());
1997 if (ev.type() == QAccessible::StateChanged) {
1998 QAccessible::State changed =
static_cast<const QAccessibleStateChangeEvent*
>(&ev)->changedStates();
1999 d <<
"State changed:";
2000 if (changed.disabled)
d <<
"disabled";
2001 if (changed.selected)
d <<
"selected";
2002 if (changed.focusable)
d <<
"focusable";
2003 if (changed.focused)
d <<
"focused";
2004 if (changed.pressed)
d <<
"pressed";
2005 if (changed.checkable)
d <<
"checkable";
2006 if (changed.checked)
d <<
"checked";
2007 if (changed.checkStateMixed)
d <<
"checkStateMixed";
2008 if (changed.readOnly)
d <<
"readOnly";
2009 if (changed.hotTracked)
d <<
"hotTracked";
2010 if (changed.defaultButton)
d <<
"defaultButton";
2011 if (changed.expanded)
d <<
"expanded";
2012 if (changed.collapsed)
d <<
"collapsed";
2013 if (changed.busy)
d <<
"busy";
2014 if (changed.expandable)
d <<
"expandable";
2015 if (changed.marqueed)
d <<
"marqueed";
2016 if (changed.animated)
d <<
"animated";
2017 if (changed.invisible)
d <<
"invisible";
2018 if (changed.offscreen)
d <<
"offscreen";
2019 if (changed.sizeable)
d <<
"sizeable";
2020 if (changed.movable)
d <<
"movable";
2021 if (changed.selfVoicing)
d <<
"selfVoicing";
2022 if (changed.selectable)
d <<
"selectable";
2023 if (changed.linked)
d <<
"linked";
2024 if (changed.traversed)
d <<
"traversed";
2025 if (changed.multiSelectable)
d <<
"multiSelectable";
2026 if (changed.extSelectable)
d <<
"extSelectable";
2027 if (changed.passwordEdit)
d <<
"passwordEdit";
2028 if (changed.hasPopup)
d <<
"hasPopup";
2029 if (changed.modal)
d <<
"modal";
2033 if (changed.active)
d <<
"active";
2034 if (changed.invalid)
d <<
"invalid";
2035 if (changed.editable)
d <<
"editable";
2036 if (changed.multiLine)
d <<
"multiLine";
2037 if (changed.selectableText)
d <<
"selectableText";
2038 if (changed.supportsAutoCompletion)
d <<
"supportsAutoCompletion";
2069QAccessibleTextInterface::~QAccessibleTextInterface()
2140static QString textLineBoundary(
int beforeAtAfter,
const QString &
text,
int offset,
int *startOffset,
int *endOffset)
2142 Q_ASSERT(beforeAtAfter >= -1 && beforeAtAfter <= 1);
2143 Q_ASSERT(*startOffset == -1 && *endOffset == -1);
2148 if (beforeAtAfter == 1) {
2153 }
else if (beforeAtAfter == -1) {
2164 if (*endOffset <= 0 || *endOffset >
length)
2167 return text.
mid(*startOffset, *endOffset - *startOffset);
2187QString QAccessibleTextInterface::textBeforeOffset(
int offset, QAccessible::TextBoundaryType boundaryType,
2188 int *startOffset,
int *endOffset)
const
2195 *startOffset = *endOffset = -1;
2196 if (
txt.isEmpty() || offset <= 0 || offset >
txt.size())
2201 switch (boundaryType) {
2202 case QAccessible::CharBoundary:
2205 case QAccessible::WordBoundary:
2208 case QAccessible::SentenceBoundary:
2211 case QAccessible::LineBoundary:
2212 case QAccessible::ParagraphBoundary:
2214 return textLineBoundary(-1,
txt,
offset, startOffset, endOffset);
2215 case QAccessible::NoBoundary:
2225 boundary.setPosition(
offset);
2230 }
while (boundary.toPreviousBoundary() > 0);
2231 Q_ASSERT(boundary.position() >= 0);
2232 *endOffset = boundary.position();
2234 while (boundary.toPreviousBoundary() > 0) {
2238 Q_ASSERT(boundary.position() >= 0);
2239 *startOffset = boundary.position();
2241 return txt.mid(*startOffset, *endOffset - *startOffset);
2261QString QAccessibleTextInterface::textAfterOffset(
int offset, QAccessible::TextBoundaryType boundaryType,
2262 int *startOffset,
int *endOffset)
const
2269 *startOffset = *endOffset = -1;
2270 if (
txt.isEmpty() || offset < 0 || offset >=
txt.size())
2275 switch (boundaryType) {
2276 case QAccessible::CharBoundary:
2279 case QAccessible::WordBoundary:
2282 case QAccessible::SentenceBoundary:
2285 case QAccessible::LineBoundary:
2286 case QAccessible::ParagraphBoundary:
2288 return textLineBoundary(1,
txt,
offset, startOffset, endOffset);
2289 case QAccessible::NoBoundary:
2299 boundary.setPosition(
offset);
2302 int toNext = boundary.toNextBoundary();
2305 if (toNext < 0 || toNext >=
txt.size())
2309 *startOffset = boundary.position();
2312 int toNext = boundary.toNextBoundary();
2315 if (toNext < 0 || toNext >=
txt.size())
2319 *endOffset = boundary.position();
2321 if ((*startOffset == -1) || (*endOffset == -1) || (*startOffset == *endOffset)) {
2326 return txt.mid(*startOffset, *endOffset - *startOffset);
2346QString QAccessibleTextInterface::textAtOffset(
int offset, QAccessible::TextBoundaryType boundaryType,
2347 int *startOffset,
int *endOffset)
const
2354 *startOffset = *endOffset = -1;
2355 if (
txt.isEmpty() || offset < 0 || offset >
txt.size())
2358 if (
offset ==
txt.size() && boundaryType == QAccessible::CharBoundary)
2363 switch (boundaryType) {
2364 case QAccessible::CharBoundary:
2367 case QAccessible::WordBoundary:
2370 case QAccessible::SentenceBoundary:
2373 case QAccessible::LineBoundary:
2374 case QAccessible::ParagraphBoundary:
2376 return textLineBoundary(0,
txt,
offset, startOffset, endOffset);
2377 case QAccessible::NoBoundary:
2379 *endOffset =
txt.size();
2388 boundary.setPosition(
offset);
2393 }
while (boundary.toPreviousBoundary() > 0);
2394 Q_ASSERT(boundary.position() >= 0);
2395 *startOffset = boundary.position();
2397 while (boundary.toNextBoundary() <
txt.size()) {
2402 *endOffset = boundary.position();
2404 return txt.mid(*startOffset, *endOffset - *startOffset);
2457QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface()
2501QAccessibleValueInterface::~QAccessibleValueInterface()
2564QAccessibleImageInterface::~QAccessibleImageInterface()
2583QAccessibleTableCellInterface::~QAccessibleTableCellInterface()
2651QAccessibleTableInterface::~QAccessibleTableInterface()
2827QAccessibleActionInterface::~QAccessibleActionInterface()
2895struct QAccessibleActionStrings
2897 QAccessibleActionStrings() :
2918 const QString scrollLeftAction;
2919 const QString scrollRightAction;
2921 const QString scrollDownAction;
2922 const QString previousPageAction;
2927 if (actionName == pressAction)
2928 return QAccessibleActionInterface::tr(
"Triggers the action");
2929 else if (actionName == increaseAction)
2930 return QAccessibleActionInterface::tr(
"Increase the value");
2931 else if (actionName == decreaseAction)
2932 return QAccessibleActionInterface::tr(
"Decrease the value");
2933 else if (actionName == showMenuAction)
2934 return QAccessibleActionInterface::tr(
"Shows the menu");
2935 else if (actionName == setFocusAction)
2936 return QAccessibleActionInterface::tr(
"Sets the focus");
2937 else if (actionName == toggleAction)
2938 return QAccessibleActionInterface::tr(
"Toggles the state");
2939 else if (actionName == scrollLeftAction)
2940 return QAccessibleActionInterface::tr(
"Scrolls to the left");
2941 else if (actionName == scrollRightAction)
2942 return QAccessibleActionInterface::tr(
"Scrolls to the right");
2943 else if (actionName == scrollUpAction)
2944 return QAccessibleActionInterface::tr(
"Scrolls up");
2945 else if (actionName == scrollDownAction)
2946 return QAccessibleActionInterface::tr(
"Scrolls down");
2947 else if (actionName == previousPageAction)
2948 return QAccessibleActionInterface::tr(
"Goes back a page");
2949 else if (actionName == nextPageAction)
2950 return QAccessibleActionInterface::tr(
"Goes to the next page");
2959QString QAccessibleActionInterface::localizedActionName(
const QString &actionName)
const
2961 return QAccessibleActionInterface::tr(
qPrintable(actionName));
2964QString QAccessibleActionInterface::localizedActionDescription(
const QString &actionName)
const
2966 return accessibleActionStrings()->localizedDescription(actionName);
2973const QString &QAccessibleActionInterface::pressAction()
2975 return accessibleActionStrings()->pressAction;
2982const QString &QAccessibleActionInterface::increaseAction()
2984 return accessibleActionStrings()->increaseAction;
2991const QString &QAccessibleActionInterface::decreaseAction()
2993 return accessibleActionStrings()->decreaseAction;
3000const QString &QAccessibleActionInterface::showMenuAction()
3002 return accessibleActionStrings()->showMenuAction;
3009const QString &QAccessibleActionInterface::setFocusAction()
3011 return accessibleActionStrings()->setFocusAction;
3018const QString &QAccessibleActionInterface::toggleAction()
3020 return accessibleActionStrings()->toggleAction;
3027QString QAccessibleActionInterface::scrollLeftAction()
3029 return accessibleActionStrings()->scrollLeftAction;
3036QString QAccessibleActionInterface::scrollRightAction()
3038 return accessibleActionStrings()->scrollRightAction;
3045QString QAccessibleActionInterface::scrollUpAction()
3047 return accessibleActionStrings()->scrollUpAction;
3054QString QAccessibleActionInterface::scrollDownAction()
3056 return accessibleActionStrings()->scrollDownAction;
3063QString QAccessibleActionInterface::previousPageAction()
3065 return accessibleActionStrings()->previousPageAction;
3072QString QAccessibleActionInterface::nextPageAction()
3074 return accessibleActionStrings()->nextPageAction;
3097QAccessibleSelectionInterface::~QAccessibleSelectionInterface()
3126QAccessibleInterface* QAccessibleSelectionInterface::selectedItem(
int selectionIndex)
const
3128 QList<QAccessibleInterface*>
items = selectedItems();
3129 if (selectionIndex < 0 || selectionIndex >
items.
length() -1) {
3130 qCWarning(lcAccessibilityCore) <<
"Selection index" << selectionIndex <<
"out of range.";
3134 return items.
at(selectionIndex);
3143bool QAccessibleSelectionInterface::isSelected(QAccessibleInterface *childItem)
const
3145 return selectedItems().contains(childItem);
3212QAccessibleAttributesInterface::~QAccessibleAttributesInterface()
3233QString qAccessibleLocalizedActionDescription(
const QString &actionName)
3235 return accessibleActionStrings()->localizedDescription(actionName);
3271QAccessibleHyperlinkInterface::~QAccessibleHyperlinkInterface()
3280#include "moc_qaccessible_base.cpp"
The QColor class provides colors based on RGB, HSV or CMYK values.
static QPlatformIntegration * platformIntegration()
qsizetype length() const noexcept
const_reference at(qsizetype i) const noexcept
static QObjectPrivate * get(QObject *o)
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
QString mid(qsizetype position, qsizetype n=-1) const &
qsizetype size() const noexcept
Returns the number of characters in this string.
BoundaryType
\value Grapheme Finds a grapheme which is the smallest boundary.
\reentrant \inmodule QtGui
bool movePosition(MoveOperation op, MoveMode=MoveAnchor, int n=1)
Moves the cursor by performing the given operation n times, using the specified mode,...
Combined button and popup list for selecting options.
constexpr QBindableInterface iface
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
void qAddPostRoutine(QtCleanUpFunction p)
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLuint GLintptr offset
#define qPrintable(string)
#define QStringLiteral(str)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define QT_TRANSLATE_NOOP(scope, x)
QItemEditorFactory * factory