Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickaccessibleattached.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
7#if QT_CONFIG(accessibility)
8
9#include <QtQml/qqmlinfo.h>
10
11#include "private/qquickitem_p.h"
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \qmltype Accessible
17 \nativetype QQuickAccessibleAttached
18 \brief Enables accessibility of QML items.
19
20 \inqmlmodule QtQuick
21 \ingroup qtquick-visual-utility
22 \ingroup accessibility
23
24 This class is part of the \l {Accessibility for Qt Quick Applications}.
25
26 Items the user interacts with or that give information to the user
27 need to expose their information to the accessibility framework.
28 Then assistive tools can make use of that information to enable
29 users to interact with the application in various ways.
30 This enables Qt Quick applications to be used with screen-readers for example.
31
32 The most important properties are \l name, \l description and \l role.
33
34 Example implementation of a simple button:
35 \qml
36 Rectangle {
37 id: myButton
38 Text {
39 id: label
40 text: "next"
41 }
42 Accessible.role: Accessible.Button
43 Accessible.name: label.text
44 Accessible.description: "shows the next page"
45 Accessible.onPressAction: {
46 // do a button click
47 }
48 }
49 \endqml
50 The \l role is set to \c Button to indicate the type of control.
51 \l {Accessible::}{name} is the most important information and bound to the text on the button.
52 The name is a short and consise description of the control and should reflect the visual label.
53 In this case it is not clear what the button does with the name only, so \l description contains
54 an explanation.
55 There is also a signal handler \l {Accessible::pressAction}{Accessible.pressAction} which can be invoked by assistive tools to trigger
56 the button. This signal handler needs to have the same effect as tapping or clicking the button would have.
57
58 \sa Accessibility
59*/
60
61/*!
62 \qmlattachedproperty string QtQuick::Accessible::name
63
64 This property sets an accessible name.
65 For a button for example, this should have a binding to its text.
66 In general this property should be set to a simple and concise
67 but human readable name. Do not include the type of control
68 you want to represent but just the name.
69*/
70
71/*!
72 \qmlattachedproperty string QtQuick::Accessible::description
73
74 This property sets an accessible description.
75 Similar to the name it describes the item. The description
76 can be a little more verbose and tell what the item does,
77 for example the functionality of the button it describes.
78*/
79
80/*!
81 \qmlattachedproperty enumeration QtQuick::Accessible::role
82
83 This flags sets the semantic type of the widget.
84 A button for example would have "Button" as type.
85 The value must be one of \l QAccessible::Role.
86
87 Some roles have special semantics.
88 In order to implement check boxes for example a "checked" property is expected.
89
90 \table
91 \header
92 \li \b {Role}
93 \li \b {Properties and signals}
94 \li \b {Explanation}
95 \row
96 \li All interactive elements
97 \li \l focusable and \l focused
98 \li All elements that the user can interact with should have focusable set to \c true and
99 set \c focus to \c true when they have the focus. This is important even for applications
100 that run on touch-only devices since screen readers often implement a virtual focus that
101 can be moved from item to item.
102 \row
103 \li Button, CheckBox, RadioButton, Switch
104 \li \l {Accessible::pressAction}{Accessible.pressAction}
105 \li A button should have a signal handler with the name \c onPressAction.
106 This signal may be emitted by an assistive tool such as a screen-reader.
107 The implementation needs to behave the same as a mouse click or tap on the button.
108 \row
109 \li CheckBox, RadioButton, Switch
110 \li \l checkable, \l checked, \l {Accessible::toggleAction}{Accessible.toggleAction}
111
112 \li The check state of the check box. Updated on Press, Check and Uncheck actions.
113 \row
114 \li Slider, SpinBox, Dial, ScrollBar
115 \li \c value, \c minimumValue, \c maximumValue, \c stepSize
116 \li These properties reflect the state and possible values for the elements.
117 \row
118 \li Slider, SpinBox, Dial, ScrollBar
119 \li \l {Accessible::increaseAction}{Accessible.increaseAction}, \l {Accessible::decreaseAction}{Accessible.decreaseAction}
120 \li Actions to increase and decrease the value of the element.
121 \endtable
122*/
123
124/*!
125 \qmlattachedproperty string QtQuick::Accessible::id
126
127 This property sets an identifier for the object.
128 It can be used to provide stable identifiers to UI tests.
129 By default, the identifier is set to the ID of the QML object.
130 If the ID is not set the default of \l QAccessible::Identifier is used.
131*/
132
133/*! \qmlattachedproperty bool QtQuick::Accessible::focusable
134 \brief This property holds whether this item is focusable.
135
136 By default, this property is \c false except for items where the role is one of
137 \c CheckBox, \c RadioButton, \c Switch, \c Button, \c MenuItem, \c PageTab,
138 \c EditableText, \c SpinBox, \c ComboBox, \c Terminal or \c ScrollBar.
139 \sa focused
140*/
141/*! \qmlattachedproperty bool QtQuick::Accessible::focused
142 \brief This property holds whether this item currently has the active focus.
143
144 By default, this property is \c false, but it will return \c true for items that
145 have \l QQuickItem::hasActiveFocus() returning \c true.
146 \sa focusable
147*/
148/*! \qmlattachedproperty bool QtQuick::Accessible::checkable
149 \brief This property holds whether this item is checkable (like a check box or some buttons).
150
151 By default this property is \c false.
152 \sa checked
153*/
154/*! \qmlattachedproperty bool QtQuick::Accessible::checked
155 \brief This property holds whether this item is currently checked.
156
157 By default this property is \c false.
158 \sa checkable
159*/
160/*! \qmlattachedproperty bool QtQuick::Accessible::expandable
161 \brief This property holds whether this item is expandable.
162
163 \since 6.12
164 By default this property is \c false.
165 \sa expanded
166*/
167/*! \qmlattachedproperty bool QtQuick::Accessible::expanded
168 \brief This property holds whether this item is currently expanded.
169
170 \since 6.12
171 By default this property is \c false.
172 \sa expandable
173*/
174/*! \qmlattachedproperty bool QtQuick::Accessible::editable
175 \brief This property holds whether this item has editable text.
176
177 By default this property is \c false.
178*/
179/*! \qmlattachedproperty bool QtQuick::Accessible::searchEdit
180 \brief This property holds whether this item is input for a search query.
181 This property will only affect editable text.
182
183 By default this property is \c false.
184*/
185/*! \qmlattachedproperty int QtQuick::Accessible::levelAttribute
186 \brief This property holds the level of this item within a hierarchical structure.
187 This property is used to populate QAccessible::Attribute::Level of the \l QAccessibleAttributesInterface.
188
189 It is relevant when the role is \l QAccessible::Heading and its needed to distinguish between different levels of headings.
190 \since 6.13
191 By default this property is \c 0.
192 \sa QAccessible::Attribute
193*/
194/*! \qmlattachedproperty bool QtQuick::Accessible::ignored
195 \brief This property holds whether this item should be ignored by the accessibility framework.
196
197 Sometimes an item is part of a group of items that should be treated as one. For example two labels might be
198 visually placed next to each other, but separate items. For accessibility purposes they should be treated as one
199 and thus they are represented by a third invisible item with the right geometry.
200
201 For example a speed display adds "m/s" as a smaller label:
202 \qml
203 Row {
204 Label {
205 id: speedLabel
206 text: "Speed: 5"
207 Accessible.ignored: true
208 }
209 Label {
210 text: qsTr("m/s")
211 Accessible.ignored: true
212 }
213 Accessible.role: Accessible.StaticText
214 Accessible.name: speedLabel.text + " meters per second"
215 }
216 \endqml
217
218 \since 5.4
219 By default this property is \c false.
220*/
221/*! \qmlattachedproperty bool QtQuick::Accessible::multiLine
222 \brief This property holds whether this item has multiple text lines.
223
224 By default this property is \c false.
225*/
226/*! \qmlattachedproperty bool QtQuick::Accessible::readOnly
227 \brief This property indicates that a text field is read only.
228
229 It is relevant when the role is \l QAccessible::EditableText and set to be read-only.
230 By default this property is \c false.
231*/
232/*! \qmlattachedproperty bool QtQuick::Accessible::selected
233 \brief This property holds whether this item is selected.
234
235 By default this property is \c false.
236 \sa selectable
237*/
238/*! \qmlattachedproperty bool QtQuick::Accessible::selectable
239 \brief This property holds whether this item can be selected.
240
241 By default this property is \c false.
242 \sa selected
243*/
244/*! \qmlattachedproperty bool QtQuick::Accessible::pressed
245 \brief This property holds whether this item is pressed (for example a button during a mouse click).
246
247 By default this property is \c false.
248*/
249/*! \qmlattachedproperty bool QtQuick::Accessible::checkStateMixed
250 \brief This property holds whether this item is in the partially checked state.
251
252 By default this property is \c false.
253 \sa checked, checkable
254*/
255/*! \qmlattachedproperty bool QtQuick::Accessible::defaultButton
256 \brief This property holds whether this item is the default button of a dialog.
257
258 By default this property is \c false.
259*/
260/*! \qmlattachedproperty bool QtQuick::Accessible::passwordEdit
261 \brief This property holds whether this item is a password text edit.
262
263 By default this property is \c false.
264*/
265/*! \qmlattachedproperty bool QtQuick::Accessible::selectableText
266 \brief This property holds whether this item contains selectable text.
267
268 By default this property is \c false.
269*/
270/*! \qmlattachedproperty Item QtQuick::Accessible::labelledBy
271 \brief This property holds the item that is used as a label for this item.
272
273 Setting this property automatically sets up the labelFor relation of the other object.
274
275 By default this property is \c undefined.
276
277 \since 6.10
278 */
279/*! \qmlattachedproperty Item QtQuick::Accessible::labelFor
280 \brief This property holds the item that this item is a label for.
281
282 Setting this property automatically sets up the labelledBy relation of the other object.
283
284 By default this property is \c undefined.
285
286 \since 6.10
287 */
288
289/*!
290 \qmlattachedsignal QtQuick::Accessible::pressAction()
291
292 This signal is emitted when a press action is received from an assistive tool such as a screen-reader.
293*/
294/*!
295 \qmlattachedsignal QtQuick::Accessible::toggleAction()
296
297 This signal is emitted when a toggle action is received from an assistive tool such as a screen-reader.
298*/
299/*!
300 \qmlattachedsignal QtQuick::Accessible::increaseAction()
301
302 This signal is emitted when a increase action is received from an assistive tool such as a screen-reader.
303*/
304/*!
305 \qmlattachedsignal QtQuick::Accessible::decreaseAction()
306
307 This signal is emitted when a decrease action is received from an assistive tool such as a screen-reader.
308*/
309/*!
310 \qmlattachedsignal QtQuick::Accessible::showOnScreenAction()
311
312 This signal is emitted when an assistive tool such as a screen-reader detects a partially visible element
313 and requests it to be fully visible.
314*/
315/*!
316 \qmlattachedsignal QtQuick::Accessible::scrollUpAction()
317
318 This signal is emitted when a scroll up action is received from an assistive tool such as a screen-reader.
319*/
320/*!
321 \qmlattachedsignal QtQuick::Accessible::scrollDownAction()
322
323 This signal is emitted when a scroll down action is received from an assistive tool such as a screen-reader.
324*/
325/*!
326 \qmlattachedsignal QtQuick::Accessible::scrollLeftAction()
327
328 This signal is emitted when a scroll left action is received from an assistive tool such as a screen-reader.
329*/
330/*!
331 \qmlattachedsignal QtQuick::Accessible::scrollRightAction()
332
333 This signal is emitted when a scroll right action is received from an assistive tool such as a screen-reader.
334*/
335/*!
336 \qmlattachedsignal QtQuick::Accessible::previousPageAction()
337
338 This signal is emitted when a previous page action is received from an assistive tool such as a screen-reader.
339*/
340/*!
341 \qmlattachedsignal QtQuick::Accessible::nextPageAction()
342
343 This signal is emitted when a next page action is received from an assistive tool such as a screen-reader.
344*/
345
346QMetaMethod QQuickAccessibleAttached::sigPress;
347QMetaMethod QQuickAccessibleAttached::sigToggle;
348QMetaMethod QQuickAccessibleAttached::sigIncrease;
349QMetaMethod QQuickAccessibleAttached::sigDecrease;
350QMetaMethod QQuickAccessibleAttached::sigShowOnScreen;
351QMetaMethod QQuickAccessibleAttached::sigScrollUp;
352QMetaMethod QQuickAccessibleAttached::sigScrollDown;
353QMetaMethod QQuickAccessibleAttached::sigScrollLeft;
354QMetaMethod QQuickAccessibleAttached::sigScrollRight;
355QMetaMethod QQuickAccessibleAttached::sigPreviousPage;
356QMetaMethod QQuickAccessibleAttached::sigNextPage;
357
358// Connects the change signals of the value and cursorPosition properties of the
359// parent, for the interfaces that its role provides. The role of an item often
360// comes after the attached object, from Accessible.role, so this runs again from
361// setRole().
362static void connectPropertyChangeSignals(QQuickAccessibleAttached *attached,
363 QAccessibleInterface *accessibleInterface)
364{
365 QObject *parent = attached->parent();
366 const QMetaObject *parentMetaObject = parent->metaObject();
367 if (!accessibleInterface || !parentMetaObject)
368 return;
369
370 auto connectPropertyChangeSignal = [parent, parentMetaObject, attached](
371 const char *propertyName, const char *signalName, int slotIndex)
372 {
373 // basically does this:
374 // if the parent has the property \a propertyName with the associated \a signalName:
375 // connect(parent, signalName, attached, slotIndex)
376
377 // Note that we explicitly want to only connect to standard property/signal naming
378 // convention: "value" & "valueChanged"
379 // (e.g. avoid a compound property with e.g. a signal notifier named "updated()")
380 int propertyIndex = parentMetaObject->indexOfProperty(propertyName);
381 if (propertyIndex != -1) {
382 const QMetaProperty property = parentMetaObject->property(propertyIndex);
383 const QMetaMethod signal = property.notifySignal();
384 if (signal.name() == signalName) {
385 QMetaObject::connect(parent, signal.methodIndex(), attached, slotIndex,
386 Qt::UniqueConnection);
387 }
388 }
389 };
390 const QMetaObject &attachedMetaObject = QQuickAccessibleAttached::staticMetaObject;
391
392 if (accessibleInterface->valueInterface()) {
393 static const int valueChangedIndex = attachedMetaObject.indexOfSlot("valueChanged()");
394 connectPropertyChangeSignal("value", "valueChanged", valueChangedIndex);
395 }
396
397 if (accessibleInterface->textInterface()) {
398 static const int cursorPositionChangedIndex =
399 attachedMetaObject.indexOfSlot("cursorPositionChanged()");
400 connectPropertyChangeSignal("cursorPosition", "cursorPositionChanged",
401 cursorPositionChangedIndex);
402 }
403}
404
405QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
406 : QObject(parent), m_role(QAccessible::NoRole)
407{
408 Q_ASSERT(parent);
409 // Enable accessibility for items with accessible content. This also
410 // enables accessibility for the ancestors of such items.
411 auto item = qobject_cast<QQuickItem *>(parent);
412 if (item) {
413 item->d_func()->setAccessible();
414 } else {
415 const QLatin1StringView className(QQmlData::ensurePropertyCache(parent)->firstCppMetaObject()->className());
416 if (className != QLatin1StringView("QQuickAction")) {
417 qmlWarning(parent) << "Accessible attached property must be attached to an object deriving from Item or Action";
418 return;
419 }
420 }
421 QAccessibleEvent ev(parent, QAccessible::ObjectCreated);
422 QAccessible::updateAccessibility(&ev);
423
424 connectPropertyChangeSignals(this, ev.accessibleInterface());
425
426 if (!sigPress.isValid()) {
427 sigPress = QMetaMethod::fromSignal(&QQuickAccessibleAttached::pressAction);
428 sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction);
429 sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction);
430 sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction);
431 sigShowOnScreen = QMetaMethod::fromSignal(&QQuickAccessibleAttached::showOnScreenAction);
432 sigScrollUp = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollUpAction);
433 sigScrollDown = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollDownAction);
434 sigScrollLeft = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollLeftAction);
435 sigScrollRight = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollRightAction);
436 sigPreviousPage = QMetaMethod::fromSignal(&QQuickAccessibleAttached::previousPageAction);
437 sigNextPage= QMetaMethod::fromSignal(&QQuickAccessibleAttached::nextPageAction);
438 }
439}
440
441QQuickAccessibleAttached::~QQuickAccessibleAttached()
442{
443}
444
445void QQuickAccessibleAttached::setRole(QAccessible::Role role)
446{
447 if (role != m_role) {
448 m_role = role;
449 Q_EMIT roleChanged();
450 // There is no way to signify role changes at the moment.
451 // QAccessible::updateAccessibility(parent(), 0, QAccessible::);
452
453 switch (role) {
454 case QAccessible::CheckBox:
455 case QAccessible::RadioButton:
456 case QAccessible::Switch:
457 if (!m_stateExplicitlySet.focusable)
458 m_state.focusable = true;
459 if (!m_stateExplicitlySet.checkable)
460 m_state.checkable = true;
461 break;
462 case QAccessible::Button:
463 case QAccessible::MenuItem:
464 case QAccessible::PageTab:
465 case QAccessible::SpinBox:
466 case QAccessible::ComboBox:
467 case QAccessible::Terminal:
468 case QAccessible::ScrollBar:
469 if (!m_stateExplicitlySet.focusable)
470 m_state.focusable = true;
471 break;
472 case QAccessible::EditableText:
473 if (!m_stateExplicitlySet.editable)
474 m_state.editable = true;
475 if (!m_stateExplicitlySet.focusable)
476 m_state.focusable = true;
477 break;
478 case QAccessible::StaticText:
479 if (!m_stateExplicitlySet.readOnly)
480 m_state.readOnly = true;
481 if (!m_stateExplicitlySet.focusable)
482 m_state.focusable = true;
483 break;
484 default:
485 break;
486 }
487
488 connectPropertyChangeSignals(this, QAccessible::queryAccessibleInterface(parent()));
489 }
490}
491
492bool QQuickAccessibleAttached::wasNameExplicitlySet() const
493{
494 return m_nameExplicitlySet;
495}
496
497// Allows types to attach an accessible name to an item as a convenience,
498// so long as the user hasn't done so themselves.
499void QQuickAccessibleAttached::setNameImplicitly(const QString &name)
500{
501 setName(name);
502 m_nameExplicitlySet = false;
503}
504
505void QQuickAccessibleAttached::setDescriptionImplicitly(const QString &desc)
506{
507 if (m_descriptionExplicitlySet)
508 return;
509 setDescription(desc);
510 m_descriptionExplicitlySet = false;
511}
512
513QQuickAccessibleAttached *QQuickAccessibleAttached::qmlAttachedProperties(QObject *obj)
514{
515 return new QQuickAccessibleAttached(obj);
516}
517
518bool QQuickAccessibleAttached::ignored() const
519{
520 auto item = qobject_cast<QQuickItem *>(parent());
521 return item ? !item->d_func()->isAccessible : false;
522}
523
524void QQuickAccessibleAttached::setIgnored(bool ignored)
525{
526 auto item = qobject_cast<QQuickItem *>(parent());
527 if (item && this->ignored() != ignored) {
528 item->d_func()->isAccessible = !ignored;
529 QAccessibleEvent event(item,
530 ignored ? QAccessible::ObjectDestroyed : QAccessible::ObjectCreated);
531 QAccessible::updateAccessibility(&event);
532 emit ignoredChanged();
533 }
534}
535
536bool QQuickAccessibleAttached::doAction(const QString &actionName)
537{
538 QMetaMethod *sig = nullptr;
539 if (actionName == QAccessibleActionInterface::pressAction())
540 sig = &sigPress;
541 else if (actionName == QAccessibleActionInterface::toggleAction())
542 sig = &sigToggle;
543 else if (actionName == QAccessibleActionInterface::increaseAction())
544 sig = &sigIncrease;
545 else if (actionName == QAccessibleActionInterface::decreaseAction())
546 sig = &sigDecrease;
547 else if (actionName == QAccessibleActionInterface::showOnScreenAction())
548 sig = &sigShowOnScreen;
549 else if (actionName == QAccessibleActionInterface::scrollUpAction())
550 sig = &sigScrollUp;
551 else if (actionName == QAccessibleActionInterface::scrollDownAction())
552 sig = &sigScrollDown;
553 else if (actionName == QAccessibleActionInterface::scrollLeftAction())
554 sig = &sigScrollLeft;
555 else if (actionName == QAccessibleActionInterface::scrollRightAction())
556 sig = &sigScrollRight;
557 else if (actionName == QAccessibleActionInterface::previousPageAction())
558 sig = &sigPreviousPage;
559 else if (actionName == QAccessibleActionInterface::nextPageAction())
560 sig = &sigNextPage;
561 if (sig && isSignalConnected(*sig)) {
562 bool ret = false;
563 if (m_proxying)
564 ret = sig->invoke(m_proxying);
565 if (!ret)
566 ret = sig->invoke(this);
567 return ret;
568 }
569 return false;
570}
571
572void QQuickAccessibleAttached::availableActions(QStringList *actions) const
573{
574 if (isSignalConnected(sigPress))
575 actions->append(QAccessibleActionInterface::pressAction());
576 if (isSignalConnected(sigToggle))
577 actions->append(QAccessibleActionInterface::toggleAction());
578 if (isSignalConnected(sigIncrease))
579 actions->append(QAccessibleActionInterface::increaseAction());
580 if (isSignalConnected(sigDecrease))
581 actions->append(QAccessibleActionInterface::decreaseAction());
582 if (isSignalConnected(sigShowOnScreen))
583 actions->append(QAccessibleActionInterface::showOnScreenAction());
584 if (isSignalConnected(sigScrollUp))
585 actions->append(QAccessibleActionInterface::scrollUpAction());
586 if (isSignalConnected(sigScrollDown))
587 actions->append(QAccessibleActionInterface::scrollDownAction());
588 if (isSignalConnected(sigScrollLeft))
589 actions->append(QAccessibleActionInterface::scrollLeftAction());
590 if (isSignalConnected(sigScrollRight))
591 actions->append(QAccessibleActionInterface::scrollRightAction());
592 if (isSignalConnected(sigPreviousPage))
593 actions->append(QAccessibleActionInterface::previousPageAction());
594 if (isSignalConnected(sigNextPage))
595 actions->append(QAccessibleActionInterface::nextPageAction());
596}
597
598QString QQuickAccessibleAttached::stripHtml(const QString &html)
599{
600#ifndef QT_NO_TEXTHTMLPARSER
601 QTextDocument doc;
602 doc.setHtml(html);
603 return doc.toPlainText();
604#else
605 return html;
606#endif
607}
608
609void QQuickAccessibleAttached::setProxying(QQuickAccessibleAttached *proxying)
610{
611 if (proxying == m_proxying)
612 return;
613
614 const QMetaObject &mo = staticMetaObject;
615 if (m_proxying) {
616 // We disconnect all signals from the proxy into this object
617 auto mo = m_proxying->metaObject();
618 auto propertyCache = QQmlData::ensurePropertyCache(m_proxying);
619 for (int signalIndex = propertyCache->signalOffset();
620 signalIndex < propertyCache->signalCount(); ++signalIndex) {
621 const QMetaMethod m = mo->method(propertyCache->signal(signalIndex)->coreIndex());
622 Q_ASSERT(m.methodType() == QMetaMethod::Signal);
623 if (m.methodType() != QMetaMethod::Signal)
624 continue;
625
626 disconnect(m_proxying, m, this, m);
627 }
628 }
629
630 m_proxying = proxying;
631
632 if (m_proxying) {
633 // We connect all signals from the proxy into this object
634 auto propertyCache = QQmlData::ensurePropertyCache(m_proxying);
635 auto mo = m_proxying->metaObject();
636 for (int signalIndex = propertyCache->signalOffset();
637 signalIndex < propertyCache->signalCount(); ++signalIndex) {
638 const QMetaMethod m = mo->method(propertyCache->signal(signalIndex)->coreIndex());
639 Q_ASSERT(m.methodType() == QMetaMethod::Signal);
640 connect(proxying, m, this, m);
641 }
642 }
643
644 // We check all properties
645 for (int prop = mo.propertyOffset(); prop < mo.propertyCount(); ++prop) {
646 const QMetaProperty p = mo.property(prop);
647 if (!p.hasNotifySignal()) {
648 continue;
649 }
650
651 const QMetaMethod signal = p.notifySignal();
652 if (signal.parameterCount() == 0)
653 signal.invoke(this);
654 else
655 signal.invoke(this, Q_ARG(bool, p.read(this).toBool()));
656 }
657}
658
659/*!
660 * \qmlattachedmethod void QtQuick::Accessible::announce(string message, AnnouncementPoliteness politeness)
661 *
662 * \since 6.8
663 * Issues an announcement event with a \a message with politeness \a politeness.
664 *
665 * \sa QAccessibleAnnouncementEvent
666 */
667void QQuickAccessibleAttached::announce(const QString &message, QAccessible::AnnouncementPoliteness politeness)
668{
669 QAccessibleAnnouncementEvent event(parent(), message);
670 event.setPoliteness(politeness);
671 QAccessible::updateAccessibility(&event);
672}
673
674QQuickItem *QQuickAccessibleAttached::findRelation(QAccessible::Relation relation) const
675{
676 const auto it = std::find_if(m_relations.cbegin(), m_relations.cend(),
677 [relation](const auto &rel) {
678 return rel.second == relation;
679 });
680
681 return it != m_relations.cend() ? it->first : nullptr;
682}
683
684QT_END_NAMESPACE
685
686#include "moc_qquickaccessibleattached_p.cpp"
687
688#endif