Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qquickaccessibleattached_p.h"
++
++ #if QT_CONFIG(accessibility)
++
++ #include <QtQml/qqmlinfo.h>
++
++ #include "private/qquickitem_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \qmltype Accessible
++ \nativetype QQuickAccessibleAttached
++ \brief Enables accessibility of QML items.
++
++ \inqmlmodule QtQuick
++ \ingroup qtquick-visual-utility
++ \ingroup accessibility
++
++ This class is part of the \l {Accessibility for Qt Quick Applications}.
++
++ Items the user interacts with or that give information to the user
++ need to expose their information to the accessibility framework.
++ Then assistive tools can make use of that information to enable
++ users to interact with the application in various ways.
++ This enables Qt Quick applications to be used with screen-readers for example.
++
++ The most important properties are \l name, \l description and \l role.
++
++ Example implementation of a simple button:
++ \qml
++ Rectangle {
++ id: myButton
++ Text {
++ id: label
++ text: "next"
++ }
++ Accessible.role: Accessible.Button
++ Accessible.name: label.text
++ Accessible.description: "shows the next page"
++ Accessible.onPressAction: {
++ // do a button click
++ }
++ }
++ \endqml
++ The \l role is set to \c Button to indicate the type of control.
++ \l {Accessible::}{name} is the most important information and bound to the text on the button.
++ The name is a short and consise description of the control and should reflect the visual label.
++ In this case it is not clear what the button does with the name only, so \l description contains
++ an explanation.
++ There is also a signal handler \l {Accessible::pressAction}{Accessible.pressAction} which can be invoked by assistive tools to trigger
++ the button. This signal handler needs to have the same effect as tapping or clicking the button would have.
++
++ \sa Accessibility
++ */
++
++ /*!
++ \qmlattachedproperty string QtQuick::Accessible::name
++
++ This property sets an accessible name.
++ For a button for example, this should have a binding to its text.
++ In general this property should be set to a simple and concise
++ but human readable name. Do not include the type of control
++ you want to represent but just the name.
++ */
++
++ /*!
++ \qmlattachedproperty string QtQuick::Accessible::description
++
++ This property sets an accessible description.
++ Similar to the name it describes the item. The description
++ can be a little more verbose and tell what the item does,
++ for example the functionality of the button it describes.
++ */
++
++ /*!
++ \qmlattachedproperty enumeration QtQuick::Accessible::role
++
++ This flags sets the semantic type of the widget.
++ A button for example would have "Button" as type.
++ The value must be one of \l QAccessible::Role.
++
++ Some roles have special semantics.
++ In order to implement check boxes for example a "checked" property is expected.
++
++ \table
++ \header
++ \li \b {Role}
++ \li \b {Properties and signals}
++ \li \b {Explanation}
++ \row
++ \li All interactive elements
++ \li \l focusable and \l focused
++ \li All elements that the user can interact with should have focusable set to \c true and
++ set \c focus to \c true when they have the focus. This is important even for applications
++ that run on touch-only devices since screen readers often implement a virtual focus that
++ can be moved from item to item.
++ \row
++ \li Button, CheckBox, RadioButton, Switch
++ \li \l {Accessible::pressAction}{Accessible.pressAction}
++ \li A button should have a signal handler with the name \c onPressAction.
++ This signal may be emitted by an assistive tool such as a screen-reader.
++ The implementation needs to behave the same as a mouse click or tap on the button.
++ \row
++ \li CheckBox, RadioButton, Switch
++ \li \l checkable, \l checked, \l {Accessible::toggleAction}{Accessible.toggleAction}
++
++ \li The check state of the check box. Updated on Press, Check and Uncheck actions.
++ \row
++ \li Slider, SpinBox, Dial, ScrollBar
++ \li \c value, \c minimumValue, \c maximumValue, \c stepSize
++ \li These properties reflect the state and possible values for the elements.
++ \row
++ \li Slider, SpinBox, Dial, ScrollBar
++ \li \l {Accessible::increaseAction}{Accessible.increaseAction}, \l {Accessible::decreaseAction}{Accessible.decreaseAction}
++ \li Actions to increase and decrease the value of the element.
++ \endtable
++ */
++
++ /*!
++ \qmlattachedproperty string QtQuick::Accessible::id
++
++ This property sets an identifier for the object.
++ It can be used to provide stable identifiers to UI tests.
++ By default, the identifier is set to the ID of the QML object.
++ If the ID is not set the default of \l QAccessible::Identifier is used.
++ */
++
++ /*! \qmlattachedproperty bool QtQuick::Accessible::focusable
++ \brief This property holds whether this item is focusable.
++
++ By default, this property is \c false except for items where the role is one of
++ \c CheckBox, \c RadioButton, \c Switch, \c Button, \c MenuItem, \c PageTab,
++ \c EditableText, \c SpinBox, \c ComboBox, \c Terminal or \c ScrollBar.
++ \sa focused
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::focused
++ \brief This property holds whether this item currently has the active focus.
++
++ By default, this property is \c false, but it will return \c true for items that
++ have \l QQuickItem::hasActiveFocus() returning \c true.
++ \sa focusable
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::checkable
++ \brief This property holds whether this item is checkable (like a check box or some buttons).
++
++ By default this property is \c false.
++ \sa checked
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::checked
++ \brief This property holds whether this item is currently checked.
++
++ By default this property is \c false.
++ \sa checkable
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::expandable
++ \brief This property holds whether this item is expandable.
++
++ \since 6.12
++ By default this property is \c false.
++ \sa expanded
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::expanded
++ \brief This property holds whether this item is currently expanded.
++
++ \since 6.12
++ By default this property is \c false.
++ \sa expandable
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::editable
++ \brief This property holds whether this item has editable text.
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::searchEdit
++ \brief This property holds whether this item is input for a search query.
++ This property will only affect editable text.
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty int QtQuick::Accessible::levelAttribute
++ \brief This property holds the level of this item within a hierarchical structure.
++ This property is used to populate QAccessible::Attribute::Level of the \l QAccessibleAttributesInterface.
++
++ It is relevant when the role is \l QAccessible::Heading and its needed to distinguish between different levels of headings.
++ \since 6.13
++ By default this property is \c 0.
++ \sa QAccessible::Attribute
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::ignored
++ \brief This property holds whether this item should be ignored by the accessibility framework.
++
++ Sometimes an item is part of a group of items that should be treated as one. For example two labels might be
++ visually placed next to each other, but separate items. For accessibility purposes they should be treated as one
++ and thus they are represented by a third invisible item with the right geometry.
++
++ For example a speed display adds "m/s" as a smaller label:
++ \qml
++ Row {
++ Label {
++ id: speedLabel
++ text: "Speed: 5"
++ Accessible.ignored: true
++ }
++ Label {
++ text: qsTr("m/s")
++ Accessible.ignored: true
++ }
++ Accessible.role: Accessible.StaticText
++ Accessible.name: speedLabel.text + " meters per second"
++ }
++ \endqml
++
++ \since 5.4
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::multiLine
++ \brief This property holds whether this item has multiple text lines.
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::readOnly
++ \brief This property indicates that a text field is read only.
++
++ It is relevant when the role is \l QAccessible::EditableText and set to be read-only.
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::selected
++ \brief This property holds whether this item is selected.
++
++ By default this property is \c false.
++ \sa selectable
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::selectable
++ \brief This property holds whether this item can be selected.
++
++ By default this property is \c false.
++ \sa selected
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::pressed
++ \brief This property holds whether this item is pressed (for example a button during a mouse click).
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::checkStateMixed
++ \brief This property holds whether this item is in the partially checked state.
++
++ By default this property is \c false.
++ \sa checked, checkable
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::defaultButton
++ \brief This property holds whether this item is the default button of a dialog.
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::passwordEdit
++ \brief This property holds whether this item is a password text edit.
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty bool QtQuick::Accessible::selectableText
++ \brief This property holds whether this item contains selectable text.
++
++ By default this property is \c false.
++ */
++ /*! \qmlattachedproperty Item QtQuick::Accessible::labelledBy
++ \brief This property holds the item that is used as a label for this item.
++
++ Setting this property automatically sets up the labelFor relation of the other object.
++
++ By default this property is \c undefined.
++
++ \since 6.10
++ */
++ /*! \qmlattachedproperty Item QtQuick::Accessible::labelFor
++ \brief This property holds the item that this item is a label for.
++
++ Setting this property automatically sets up the labelledBy relation of the other object.
++
++ By default this property is \c undefined.
++
++ \since 6.10
++ */
++
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::pressAction()
++
++ This signal is emitted when a press action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::toggleAction()
++
++ This signal is emitted when a toggle action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::increaseAction()
++
++ This signal is emitted when a increase action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::decreaseAction()
++
++ This signal is emitted when a decrease action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::showOnScreenAction()
++
++ This signal is emitted when an assistive tool such as a screen-reader detects a partially visible element
++ and requests it to be fully visible.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::scrollUpAction()
++
++ This signal is emitted when a scroll up action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::scrollDownAction()
++
++ This signal is emitted when a scroll down action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::scrollLeftAction()
++
++ This signal is emitted when a scroll left action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::scrollRightAction()
++
++ This signal is emitted when a scroll right action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::previousPageAction()
++
++ This signal is emitted when a previous page action is received from an assistive tool such as a screen-reader.
++ */
++ /*!
++ \qmlattachedsignal QtQuick::Accessible::nextPageAction()
++
++ This signal is emitted when a next page action is received from an assistive tool such as a screen-reader.
++ */
++
++ QMetaMethod QQuickAccessibleAttached::sigPress;
++ QMetaMethod QQuickAccessibleAttached::sigToggle;
++ QMetaMethod QQuickAccessibleAttached::sigIncrease;
++ QMetaMethod QQuickAccessibleAttached::sigDecrease;
++ QMetaMethod QQuickAccessibleAttached::sigShowOnScreen;
++ QMetaMethod QQuickAccessibleAttached::sigScrollUp;
++ QMetaMethod QQuickAccessibleAttached::sigScrollDown;
++ QMetaMethod QQuickAccessibleAttached::sigScrollLeft;
++ QMetaMethod QQuickAccessibleAttached::sigScrollRight;
++ QMetaMethod QQuickAccessibleAttached::sigPreviousPage;
++ QMetaMethod QQuickAccessibleAttached::sigNextPage;
++
++ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
++ : QObject(parent), m_role(QAccessible::NoRole)
++ {
++ Q_ASSERT(parent);
++ // Enable accessibility for items with accessible content. This also
++ // enables accessibility for the ancestors of such items.
++ auto item = qobject_cast<QQuickItem *>(parent);
++ if (item) {
++ item->d_func()->setAccessible();
++ } else {
++ const QLatin1StringView className(QQmlData::ensurePropertyCache(parent)->firstCppMetaObject()->className());
++ if (className != QLatin1StringView("QQuickAction")) {
++ qmlWarning(parent) << "Accessible attached property must be attached to an object deriving from Item or Action";
++ return;
++ }
++ }
++ QAccessibleEvent ev(parent, QAccessible::ObjectCreated);
++ QAccessible::updateAccessibility(&ev);
++
++ if (const QMetaObject *pmo = parent->metaObject()) {
++ auto connectPropertyChangeSignal = [parent, pmo, this](
++ const char *propertyName, const char *signalName, int slotIndex)
++ {
++ // basically does this:
++ // if the parent has the property \a propertyName with the associated \a signalName:
++ // connect(parent, signalName, this, slotIndex)
++
++ // Note that we explicitly want to only connect to standard property/signal naming
++ // convention: "value" & "valueChanged"
++ // (e.g. avoid a compound property with e.g. a signal notifier named "updated()")
++ int idxProperty = pmo->indexOfProperty(propertyName);
++ if (idxProperty != -1) {
++ const QMetaProperty property = pmo->property(idxProperty);
++ const QMetaMethod signal = property.notifySignal();
++ if (signal.name() == signalName)
++ QMetaObject::connect(parent, signal.methodIndex(), this, slotIndex);
++ }
++ return;
++ };
++ const QMetaObject &smo = staticMetaObject;
++
++ QAccessibleInterface *iface = ev.accessibleInterface();
++ if (iface && iface->valueInterface()) {
++ static const int valueChangedIndex = smo.indexOfSlot("valueChanged()");
++ connectPropertyChangeSignal("value", "valueChanged", valueChangedIndex);
++ }
++
++ if (iface && iface->textInterface()) {
++ static const int cursorPositionChangedIndex =
++ smo.indexOfSlot("cursorPositionChanged()");
++ connectPropertyChangeSignal("cursorPosition", "cursorPositionChanged",
++ cursorPositionChangedIndex);
++ }
++ }
++
++ if (!sigPress.isValid()) {
++ sigPress = QMetaMethod::fromSignal(&QQuickAccessibleAttached::pressAction);
++ sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction);
++ sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction);
++ sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction);
++ sigShowOnScreen = QMetaMethod::fromSignal(&QQuickAccessibleAttached::showOnScreenAction);
++ sigScrollUp = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollUpAction);
++ sigScrollDown = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollDownAction);
++ sigScrollLeft = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollLeftAction);
++ sigScrollRight = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollRightAction);
++ sigPreviousPage = QMetaMethod::fromSignal(&QQuickAccessibleAttached::previousPageAction);
++ sigNextPage= QMetaMethod::fromSignal(&QQuickAccessibleAttached::nextPageAction);
++ }
++ }
++
++ QQuickAccessibleAttached::~QQuickAccessibleAttached()
++ {
++ }
++
++ void QQuickAccessibleAttached::setRole(QAccessible::Role role)
++ {
++ if (role != m_role) {
++ m_role = role;
++ Q_EMIT roleChanged();
++ // There is no way to signify role changes at the moment.
++ // QAccessible::updateAccessibility(parent(), 0, QAccessible::);
++
++ switch (role) {
++ case QAccessible::CheckBox:
++ case QAccessible::RadioButton:
++ case QAccessible::Switch:
++ if (!m_stateExplicitlySet.focusable)
++ m_state.focusable = true;
++ if (!m_stateExplicitlySet.checkable)
++ m_state.checkable = true;
++ break;
++ case QAccessible::Button:
++ case QAccessible::MenuItem:
++ case QAccessible::PageTab:
++ case QAccessible::SpinBox:
++ case QAccessible::ComboBox:
++ case QAccessible::Terminal:
++ case QAccessible::ScrollBar:
++ if (!m_stateExplicitlySet.focusable)
++ m_state.focusable = true;
++ break;
++ case QAccessible::EditableText:
++ if (!m_stateExplicitlySet.editable)
++ m_state.editable = true;
++ if (!m_stateExplicitlySet.focusable)
++ m_state.focusable = true;
++ break;
++ case QAccessible::StaticText:
++ if (!m_stateExplicitlySet.readOnly)
++ m_state.readOnly = true;
++ if (!m_stateExplicitlySet.focusable)
++ m_state.focusable = true;
++ break;
++ default:
++ break;
++ }
++ }
++ }
++
++ bool QQuickAccessibleAttached::wasNameExplicitlySet() const
++ {
++ return m_nameExplicitlySet;
++ }
++
++ // Allows types to attach an accessible name to an item as a convenience,
++ // so long as the user hasn't done so themselves.
++ void QQuickAccessibleAttached::setNameImplicitly(const QString &name)
++ {
++ setName(name);
++ m_nameExplicitlySet = false;
++ }
++
++ void QQuickAccessibleAttached::setDescriptionImplicitly(const QString &desc)
++ {
++ if (m_descriptionExplicitlySet)
++ return;
++ setDescription(desc);
++ m_descriptionExplicitlySet = false;
++ }
++
++ QQuickAccessibleAttached *QQuickAccessibleAttached::qmlAttachedProperties(QObject *obj)
++ {
++ return new QQuickAccessibleAttached(obj);
++ }
++
++ bool QQuickAccessibleAttached::ignored() const
++ {
++ auto item = qobject_cast<QQuickItem *>(parent());
++ return item ? !item->d_func()->isAccessible : false;
++ }
++
++ void QQuickAccessibleAttached::setIgnored(bool ignored)
++ {
++ auto item = qobject_cast<QQuickItem *>(parent());
++ if (item && this->ignored() != ignored) {
++ item->d_func()->isAccessible = !ignored;
++ QAccessibleEvent event(item,
++ ignored ? QAccessible::ObjectDestroyed : QAccessible::ObjectCreated);
++ QAccessible::updateAccessibility(&event);
++ emit ignoredChanged();
++ }
++ }
++
++ bool QQuickAccessibleAttached::doAction(const QString &actionName)
++ {
++ QMetaMethod *sig = nullptr;
++ if (actionName == QAccessibleActionInterface::pressAction())
++ sig = &sigPress;
++ else if (actionName == QAccessibleActionInterface::toggleAction())
++ sig = &sigToggle;
++ else if (actionName == QAccessibleActionInterface::increaseAction())
++ sig = &sigIncrease;
++ else if (actionName == QAccessibleActionInterface::decreaseAction())
++ sig = &sigDecrease;
++ else if (actionName == QAccessibleActionInterface::showOnScreenAction())
++ sig = &sigShowOnScreen;
++ else if (actionName == QAccessibleActionInterface::scrollUpAction())
++ sig = &sigScrollUp;
++ else if (actionName == QAccessibleActionInterface::scrollDownAction())
++ sig = &sigScrollDown;
++ else if (actionName == QAccessibleActionInterface::scrollLeftAction())
++ sig = &sigScrollLeft;
++ else if (actionName == QAccessibleActionInterface::scrollRightAction())
++ sig = &sigScrollRight;
++ else if (actionName == QAccessibleActionInterface::previousPageAction())
++ sig = &sigPreviousPage;
++ else if (actionName == QAccessibleActionInterface::nextPageAction())
++ sig = &sigNextPage;
++ if (sig && isSignalConnected(*sig)) {
++ bool ret = false;
++ if (m_proxying)
++ ret = sig->invoke(m_proxying);
++ if (!ret)
++ ret = sig->invoke(this);
++ return ret;
++ }
++ return false;
++ }
++
++ void QQuickAccessibleAttached::availableActions(QStringList *actions) const
++ {
++ if (isSignalConnected(sigPress))
++ actions->append(QAccessibleActionInterface::pressAction());
++ if (isSignalConnected(sigToggle))
++ actions->append(QAccessibleActionInterface::toggleAction());
++ if (isSignalConnected(sigIncrease))
++ actions->append(QAccessibleActionInterface::increaseAction());
++ if (isSignalConnected(sigDecrease))
++ actions->append(QAccessibleActionInterface::decreaseAction());
++ if (isSignalConnected(sigShowOnScreen))
++ actions->append(QAccessibleActionInterface::showOnScreenAction());
++ if (isSignalConnected(sigScrollUp))
++ actions->append(QAccessibleActionInterface::scrollUpAction());
++ if (isSignalConnected(sigScrollDown))
++ actions->append(QAccessibleActionInterface::scrollDownAction());
++ if (isSignalConnected(sigScrollLeft))
++ actions->append(QAccessibleActionInterface::scrollLeftAction());
++ if (isSignalConnected(sigScrollRight))
++ actions->append(QAccessibleActionInterface::scrollRightAction());
++ if (isSignalConnected(sigPreviousPage))
++ actions->append(QAccessibleActionInterface::previousPageAction());
++ if (isSignalConnected(sigNextPage))
++ actions->append(QAccessibleActionInterface::nextPageAction());
++ }
++
++ QString QQuickAccessibleAttached::stripHtml(const QString &html)
++ {
++ #ifndef QT_NO_TEXTHTMLPARSER
++ QTextDocument doc;
++ doc.setHtml(html);
++ return doc.toPlainText();
++ #else
++ return html;
++ #endif
++ }
++
++ void QQuickAccessibleAttached::setProxying(QQuickAccessibleAttached *proxying)
++ {
++ if (proxying == m_proxying)
++ return;
++
++ const QMetaObject &mo = staticMetaObject;
++ if (m_proxying) {
++ // We disconnect all signals from the proxy into this object
++ auto mo = m_proxying->metaObject();
++ auto propertyCache = QQmlData::ensurePropertyCache(m_proxying);
++ for (int signalIndex = propertyCache->signalOffset();
++ signalIndex < propertyCache->signalCount(); ++signalIndex) {
++ const QMetaMethod m = mo->method(propertyCache->signal(signalIndex)->coreIndex());
++ Q_ASSERT(m.methodType() == QMetaMethod::Signal);
++ if (m.methodType() != QMetaMethod::Signal)
++ continue;
++
++ disconnect(m_proxying, m, this, m);
++ }
++ }
++
++ m_proxying = proxying;
++
++ if (m_proxying) {
++ // We connect all signals from the proxy into this object
++ auto propertyCache = QQmlData::ensurePropertyCache(m_proxying);
++ auto mo = m_proxying->metaObject();
++ for (int signalIndex = propertyCache->signalOffset();
++ signalIndex < propertyCache->signalCount(); ++signalIndex) {
++ const QMetaMethod m = mo->method(propertyCache->signal(signalIndex)->coreIndex());
++ Q_ASSERT(m.methodType() == QMetaMethod::Signal);
++ connect(proxying, m, this, m);
++ }
++ }
++
++ // We check all properties
++ for (int prop = mo.propertyOffset(); prop < mo.propertyCount(); ++prop) {
++ const QMetaProperty p = mo.property(prop);
++ if (!p.hasNotifySignal()) {
++ continue;
++ }
++
++ const QMetaMethod signal = p.notifySignal();
++ if (signal.parameterCount() == 0)
++ signal.invoke(this);
++ else
++ signal.invoke(this, Q_ARG(bool, p.read(this).toBool()));
++ }
++ }
++
++ /*!
++ * \qmlattachedmethod void QtQuick::Accessible::announce(string message, AnnouncementPoliteness politeness)
++ *
++ * \since 6.8
++ * Issues an announcement event with a \a message with politeness \a politeness.
++ *
++ * \sa QAccessibleAnnouncementEvent
++ */
++ void QQuickAccessibleAttached::announce(const QString &message, QAccessible::AnnouncementPoliteness politeness)
++ {
++ QAccessibleAnnouncementEvent event(parent(), message);
++ event.setPoliteness(politeness);
++ QAccessible::updateAccessibility(&event);
++ }
++
++ QQuickItem *QQuickAccessibleAttached::findRelation(QAccessible::Relation relation) const
++ {
++ const auto it = std::find_if(m_relations.cbegin(), m_relations.cend(),
++ [relation](const auto &rel) {
++ return rel.second == relation;
++ });
++
++ return it != m_relations.cend() ? it->first : nullptr;
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qquickaccessibleattached_p.cpp"
++
++ #endif