Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qaccessiblequickitem.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
5
6#include <QtGui/qtextdocument.h>
7
8#include "QtQuick/private/qquickitem_p.h"
9#include "QtQuick/private/qquicktext_p.h"
10#include <private/qquicktext_p_p.h>
11
12#include "QtQuick/private/qquicktextinput_p.h"
13#include "QtQuick/private/qquickaccessibleattached_p.h"
14#include "QtQuick/qquicktextdocument.h"
15#include "QtQuick/qquickrendercontrol.h"
17
18#if QT_CONFIG(accessibility)
19
20class QAccessibleHyperlink : public QAccessibleInterface, public QAccessibleHyperlinkInterface {
21public:
22 QAccessibleHyperlink(QQuickItem *parentTextItem, int linkIndex);
23
24 // check for valid pointers
25 bool isValid() const override;
26 QObject *object() const override;
27 QWindow *window() const override;
28
29 // navigation, hierarchy
30 QAccessibleInterface *parent() const override;
31 QAccessibleInterface *child(int index) const override;
32 int childCount() const override;
33 int indexOfChild(const QAccessibleInterface *iface) const override;
34 QAccessibleInterface *childAt(int x, int y) const override;
35
36 // properties and state
37 QString text(QAccessible::Text) const override;
38 void setText(QAccessible::Text, const QString &text) override;
39 QRect rect() const override;
40 QAccessible::Role role() const override;
41 QAccessible::State state() const override;
42
43 void *interface_cast(QAccessible::InterfaceType t) override;
44
45 // QAccessibleHyperlinkInterface
46 QString anchor() const override
47 {
48 const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
49 if (linkIndex < links.size())
50 return links.at(linkIndex).m_anchor;
51 return QString();
52 }
53
54 QString anchorTarget() const override
55 {
56 const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
57 if (linkIndex < links.size())
58 return links.at(linkIndex).m_anchorTarget;
59 return QString();
60 }
61
62 int startIndex() const override
63 {
64 const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
65 if (linkIndex < links.size())
66 return links.at(linkIndex).m_startIndex;
67 return -1;
68 }
69
70 int endIndex() const override
71 {
72 const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
73 if (linkIndex < links.size())
74 return links.at(linkIndex).m_endIndex;
75 return -1;
76 }
77
78private:
79 QQuickText *textItem() const { return qobject_cast<QQuickText*>(parentTextItem); }
80 QQuickItem *parentTextItem;
81 const int linkIndex;
82
83 friend class QAccessibleQuickItem;
84};
85
86
87QAccessibleHyperlink::QAccessibleHyperlink(QQuickItem *parentTextItem, int linkIndex)
88 : parentTextItem(parentTextItem),
89 linkIndex(linkIndex)
90{
91}
92
93
94bool QAccessibleHyperlink::isValid() const
95{
96 return textItem();
97}
98
99
100QObject *QAccessibleHyperlink::object() const
101{
102 return nullptr;
103}
104
105
106QWindow *QAccessibleHyperlink::window() const
107{
108 return textItem()->window();
109}
110
111
112/* \reimp */
113QRect QAccessibleHyperlink::rect() const
114{
115 const QVector<QQuickTextPrivate::LinkDesc> links = QQuickTextPrivate::get(textItem())->getLinks();
116 if (linkIndex < links.size()) {
117 const QPoint tl = itemScreenRect(textItem()).topLeft();
118 return links.at(linkIndex).rect.translated(tl);
119 }
120 return QRect();
121}
122
123/* \reimp */
124QAccessibleInterface *QAccessibleHyperlink::childAt(int, int) const
125{
126 return nullptr;
127}
128
129/* \reimp */
130QAccessibleInterface *QAccessibleHyperlink::parent() const
131{
132 return QAccessible::queryAccessibleInterface(textItem());
133}
134
135/* \reimp */
136QAccessibleInterface *QAccessibleHyperlink::child(int) const
137{
138 return nullptr;
139}
140
141/* \reimp */
142int QAccessibleHyperlink::childCount() const
143{
144 return 0;
145}
146
147/* \reimp */
148int QAccessibleHyperlink::indexOfChild(const QAccessibleInterface *) const
149{
150 return -1;
151}
152
153/* \reimp */
154QAccessible::State QAccessibleHyperlink::state() const
155{
157 s.selectable = true;
158 s.focusable = true;
159 s.selectableText = true;
160 s.selected = false;
161 return s;
162}
163
164/* \reimp */
165QAccessible::Role QAccessibleHyperlink::role() const
166{
167 return QAccessible::Link;
168}
169
170/* \reimp */
171QString QAccessibleHyperlink::text(QAccessible::Text t) const
172{
173 // AT servers have different behaviors:
174 // Wordpad on windows have this behavior:
175 // * Name returns the anchor target (URL)
176 // * Value returns the anchor target (URL)
177
178 // Other AT servers (e.g. MS Edge on Windows) does what seems to be more sensible:
179 // * Name returns the anchor name
180 // * Value returns the anchor target (URL)
181 if (t == QAccessible::Name)
182 return anchor();
183 if (t == QAccessible::Value)
184 return anchorTarget();
185 return QString();
186}
187
188/* \reimp */
189void QAccessibleHyperlink::setText(QAccessible::Text, const QString &)
190{
191
192}
193
194/* \reimp */
195void *QAccessibleHyperlink::interface_cast(QAccessible::InterfaceType t)
196{
197 if (t == QAccessible::HyperlinkInterface)
198 return static_cast<QAccessibleHyperlinkInterface*>(this);
199 return nullptr;
200}
201
202
208QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
209 : QAccessibleObject(item), m_doc(textDocument())
210{
211}
212
213QWindow *QAccessibleQuickItem::window() const
214{
216
217 // For QQuickWidget the above window will be the offscreen QQuickWindow,
218 // which is not a part of the accessibility tree. Detect this case and
219 // return the window for the QQuickWidget instead.
220 if (window && !window->handle()) {
221 if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) {
222 if (QWindow *renderWindow = renderControl->renderWindow(nullptr))
223 return renderWindow;
224 }
225 }
226
227 return window;
228}
229
230int QAccessibleQuickItem::childCount() const
231{
232 // see comment in QAccessibleQuickItem::child() as to why we do this
233 int cc = 0;
234 if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
235 cc = QQuickTextPrivate::get(textItem)->getLinks().size();
236 }
237 cc += childItems().size();
238 return cc;
239}
240
241QRect QAccessibleQuickItem::rect() const
242{
243 const QRect r = itemScreenRect(item());
244 return r;
245}
246
247QRect QAccessibleQuickItem::viewRect() const
248{
249 // ### no window in some cases.
250 if (!item()->window()) {
251 return QRect();
252 }
253
255 QPoint screenPos = window->mapToGlobal(QPoint(0,0));
256 return QRect(screenPos, window->size());
257}
258
259
260bool QAccessibleQuickItem::clipsChildren() const
261{
262 return static_cast<QQuickItem *>(item())->clip();
263}
264
265QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
266{
267 if (item()->clip()) {
268 if (!rect().contains(x, y))
269 return nullptr;
270 }
271
272 // special case for text interfaces
273 if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
274 const auto hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().size();
275 for (auto i = 0; i < hyperLinkChildCount; i++) {
276 QAccessibleInterface *iface = child(i);
277 if (iface->rect().contains(x,y)) {
278 return iface;
279 }
280 }
281 }
282
283 // general item hit test
284 const QList<QQuickItem*> kids = accessibleUnignoredChildren(item(), true);
285 for (int i = kids.size() - 1; i >= 0; --i) {
286 QAccessibleInterface *childIface = QAccessible::queryAccessibleInterface(kids.at(i));
287 if (QAccessibleInterface *childChild = childIface->childAt(x, y))
288 return childChild;
289 if (childIface && !childIface->state().invisible) {
290 if (childIface->rect().contains(x, y))
291 return childIface;
292 }
293 }
294
295 return nullptr;
296}
297
298QAccessibleInterface *QAccessibleQuickItem::parent() const
299{
300 QQuickItem *parent = item()->parentItem();
301 QQuickWindow *itemWindow = item()->window();
302 QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr;
303 while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci)
304 parent = parent->parentItem();
305
306 if (parent) {
307 if (parent == ci) {
308 // Jump out to the window if the parent is the root item
309 return QAccessible::queryAccessibleInterface(window());
310 } else {
311 while (parent && !parent->d_func()->isAccessible)
312 parent = parent->parentItem();
313 return QAccessible::queryAccessibleInterface(parent);
314 }
315 }
316 return nullptr;
317}
318
319QAccessibleInterface *QAccessibleQuickItem::child(int index) const
320{
321 /* Text with hyperlinks will have dedicated children interfaces representing each hyperlink.
322
323 For the pathological case when a Text node has hyperlinks in its text *and* accessible
324 quick items as children, we put the hyperlink a11y interfaces as the first children, then
325 the other interfaces follows the hyperlink children (as siblings).
326
327 For example, suppose you have two links in the text and an image as a child of the text,
328 it will have the following a11y hierarchy:
329
330 [a11y:TextInterface]
331 |
332 +- [a11y:HyperlinkInterface]
333 +- [a11y:HyperlinkInterface]
334 +- [a11y:ImageInterface]
335
336 Having this order (as opposed to having hyperlink interfaces last) will at least
337 ensure that the child id of hyperlink children is not altered when child is added/removed
338 to the text item and marked accessible.
339 In addition, hyperlink interfaces as children should be the common case, so it is preferred
340 to explore those first when iterating.
341 */
342 if (index < 0)
343 return nullptr;
344
345
346 if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
347 const int hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().size();
348 if (index < hyperLinkChildCount) {
349 auto it = m_childToId.constFind(index);
350 if (it != m_childToId.constEnd())
351 return QAccessible::accessibleInterface(it.value());
352
353 QAccessibleHyperlink *iface = new QAccessibleHyperlink(item(), index);
354 QAccessible::Id id = QAccessible::registerAccessibleInterface(iface);
355 m_childToId.insert(index, id);
356 return iface;
357 }
358 index -= hyperLinkChildCount;
359 }
360
361 QList<QQuickItem *> children = childItems();
362 if (index < children.size()) {
363 QQuickItem *child = children.at(index);
364 return QAccessible::queryAccessibleInterface(child);
365 }
366 return nullptr;
367}
368
369int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const
370{
371 int hyperLinkChildCount = 0;
372 if (QQuickText *textItem = qobject_cast<QQuickText*>(item())) {
373 hyperLinkChildCount = QQuickTextPrivate::get(textItem)->getLinks().size();
374 if (QAccessibleHyperlinkInterface *hyperLinkIface = const_cast<QAccessibleInterface *>(iface)->hyperlinkInterface()) {
375 // ### assumes that there is only one subclass implementing QAccessibleHyperlinkInterface
376 // Alternatively, we could simply iterate with child() and do a linear search for it
377 QAccessibleHyperlink *hyperLink = static_cast<QAccessibleHyperlink*>(hyperLinkIface);
378 if (hyperLink->textItem() == static_cast<QQuickText*>(item())) {
379 return hyperLink->linkIndex;
380 }
381 }
382 }
383 QList<QQuickItem*> kids = childItems();
384 int idx = kids.indexOf(static_cast<QQuickItem*>(iface->object()));
385 if (idx >= 0)
386 idx += hyperLinkChildCount;
387 return idx;
388}
389
390static void unignoredChildren(QQuickItem *item, QList<QQuickItem *> *items, bool paintOrder)
391{
392 const QList<QQuickItem*> childItems = paintOrder ? QQuickItemPrivate::get(item)->paintOrderChildItems()
393 : item->childItems();
394 for (QQuickItem *child : childItems) {
395 if (QQuickItemPrivate::get(child)->isAccessible) {
397 } else {
398 unignoredChildren(child, items, paintOrder);
399 }
400 }
401}
402
403QList<QQuickItem *> accessibleUnignoredChildren(QQuickItem *item, bool paintOrder)
404{
405 QList<QQuickItem *> items;
406 unignoredChildren(item, &items, paintOrder);
407 return items;
408}
409
410QList<QQuickItem *> QAccessibleQuickItem::childItems() const
411{
412 return accessibleUnignoredChildren(item());
413}
414
415static bool isTextRole(QAccessible::Role role)
416{
417 return role == QAccessible::EditableText || role == QAccessible::StaticText;
418}
419
420QAccessible::State QAccessibleQuickItem::state() const
421{
422 QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item());
423 if (!attached)
424 return QAccessible::State();
425
426 QAccessible::State state = attached->state();
427
428 QRect viewRect_ = viewRect();
429 QRect itemRect = rect();
430
431 if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
432 state.invisible = true;
433 if (!viewRect_.intersects(itemRect))
434 state.offscreen = true;
435 if ((role() == QAccessible::CheckBox || role() == QAccessible::RadioButton) && object()->property("checked").toBool())
436 state.checked = true;
437 if (item()->activeFocusOnTab() || isTextRole(role()))
438 state.focusable = true;
439 if (item()->hasActiveFocus())
440 state.focused = true;
441 if (role() == QAccessible::EditableText)
442 if (auto ti = qobject_cast<QQuickTextInput *>(item()))
443 state.passwordEdit = ti->echoMode() != QQuickTextInput::Normal;
444 if (!item()->isEnabled()) {
445 state.focusable = false;
446 state.disabled = true;
447 }
448 return state;
449}
450
451QAccessible::Role QAccessibleQuickItem::role() const
452{
453 // Workaround for setAccessibleRole() not working for
454 // Text items. Text items are special since they are defined
455 // entirely from C++ (setting the role from QML works.)
456
457 QAccessible::Role role = QAccessible::NoRole;
458 if (item())
459 role = QQuickItemPrivate::get(item())->effectiveAccessibleRole();
460 if (role == QAccessible::NoRole) {
461 if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
462 role = QAccessible::StaticText;
463 else if (qobject_cast<QQuickTextInput*>(const_cast<QQuickItem *>(item())))
464 role = QAccessible::EditableText;
465 else
466 role = QAccessible::Client;
467 }
468
469 return role;
470}
471
472bool QAccessibleQuickItem::isAccessible() const
473{
474 return item()->d_func()->isAccessible;
475}
476
477QStringList QAccessibleQuickItem::actionNames() const
478{
479 QStringList actions;
480 switch (role()) {
481 case QAccessible::Link:
482 case QAccessible::PushButton:
483 actions << QAccessibleActionInterface::pressAction();
484 break;
485 case QAccessible::RadioButton:
486 case QAccessible::CheckBox:
487 actions << QAccessibleActionInterface::toggleAction()
488 << QAccessibleActionInterface::pressAction();
489 break;
490 case QAccessible::Slider:
491 case QAccessible::SpinBox:
492 case QAccessible::ScrollBar:
493 actions << QAccessibleActionInterface::increaseAction()
494 << QAccessibleActionInterface::decreaseAction();
495 break;
496 default:
497 break;
498 }
499 if (state().focusable)
500 actions.append(QAccessibleActionInterface::setFocusAction());
501
502 // ### The following can lead to duplicate action names.
503 if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item()))
504 attached->availableActions(&actions);
505 return actions;
506}
507
508void QAccessibleQuickItem::doAction(const QString &actionName)
509{
510 bool accepted = false;
511 if (actionName == QAccessibleActionInterface::setFocusAction()) {
512 item()->forceActiveFocus();
513 accepted = true;
514 }
515 if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item()))
516 accepted = attached->doAction(actionName);
517
518 if (accepted)
519 return;
520 // Look for and call the accessible[actionName]Action() function on the item.
521 // This allows for overriding the default action handling.
522 const QByteArray functionName = "accessible" + actionName.toLatin1() + "Action";
523 if (object()->metaObject()->indexOfMethod(QByteArray(functionName + "()")) != -1) {
524 QMetaObject::invokeMethod(object(), functionName);
525 return;
526 }
527
528 // Role-specific default action handling follows. Items are expected to provide
529 // properties according to role conventions. These will then be read and/or updated
530 // by the accessibility system.
531 // Checkable roles : checked
532 // Value-based roles : (via the value interface: value, minimumValue, maximumValue), stepSize
533 switch (role()) {
534 case QAccessible::RadioButton:
535 case QAccessible::CheckBox: {
536 QVariant checked = object()->property("checked");
537 if (checked.isValid()) {
538 if (actionName == QAccessibleActionInterface::toggleAction() ||
539 actionName == QAccessibleActionInterface::pressAction()) {
540
541 object()->setProperty("checked", QVariant(!checked.toBool()));
542 }
543 }
544 break;
545 }
546 case QAccessible::Slider:
547 case QAccessible::SpinBox:
548 case QAccessible::Dial:
549 case QAccessible::ScrollBar: {
550 if (actionName != QAccessibleActionInterface::increaseAction() &&
551 actionName != QAccessibleActionInterface::decreaseAction())
552 break;
553
554 // Update the value using QAccessibleValueInterface, respecting
555 // the minimum and maximum value (if set). Also check for and
556 // use the "stepSize" property on the item
557 if (QAccessibleValueInterface *valueIface = valueInterface()) {
558 QVariant valueV = valueIface->currentValue();
559 qreal newValue = valueV.toReal();
560
561 QVariant stepSizeV = object()->property("stepSize");
562 qreal stepSize = stepSizeV.isValid() ? stepSizeV.toReal() : qreal(1.0);
563 if (actionName == QAccessibleActionInterface::increaseAction()) {
564 newValue += stepSize;
565 } else {
566 newValue -= stepSize;
567 }
568
569 QVariant minimumValueV = valueIface->minimumValue();
570 if (minimumValueV.isValid()) {
571 newValue = qMax(newValue, minimumValueV.toReal());
572 }
573 QVariant maximumValueV = valueIface->maximumValue();
574 if (maximumValueV.isValid()) {
575 newValue = qMin(newValue, maximumValueV.toReal());
576 }
577
578 valueIface->setCurrentValue(QVariant(newValue));
579 }
580 break;
581 }
582 default:
583 break;
584 }
585}
586
587QStringList QAccessibleQuickItem::keyBindingsForAction(const QString &actionName) const
588{
589 Q_UNUSED(actionName);
590 return QStringList();
591}
592
593QString QAccessibleQuickItem::text(QAccessible::Text textType) const
594{
595 // handles generic behavior not specific to an item
596 switch (textType) {
597 case QAccessible::Name: {
598 QVariant accessibleName = QQuickAccessibleAttached::property(object(), "name");
599 if (!accessibleName.isNull())
600 return accessibleName.toString();
601 break;}
602 case QAccessible::Description: {
603 QVariant accessibleDecription = QQuickAccessibleAttached::property(object(), "description");
604 if (!accessibleDecription.isNull())
605 return accessibleDecription.toString();
606 break;}
607#ifdef Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
608 case QAccessible::DebugDescription: {
609 QString debugString;
610 debugString = QString::fromLatin1(object()->metaObject()->className()) + QLatin1Char(' ');
611 debugString += isAccessible() ? QLatin1String("enabled") : QLatin1String("disabled");
612 return debugString;
613 break; }
614#endif
615 case QAccessible::Value:
616 case QAccessible::Help:
617 case QAccessible::Accelerator:
618 default:
619 break;
620 }
621
622 // the following block handles item-specific behavior
623 if (role() == QAccessible::EditableText) {
624 if (textType == QAccessible::Value) {
625 if (auto textInput = qobject_cast<QQuickTextInput *>(item()))
626 return textInput->displayText();
627 if (QTextDocument *doc = textDocument()) {
628 return doc->toPlainText();
629 }
630 QVariant text = object()->property("text");
631 return text.toString();
632 }
633 }
634
635 return QString();
636}
637
638void QAccessibleQuickItem::setText(QAccessible::Text textType, const QString &text)
639{
640 if (role() != QAccessible::EditableText)
641 return;
642 if (textType != QAccessible::Value)
643 return;
644
645 if (QTextDocument *doc = textDocument()) {
646 doc->setPlainText(text);
647 return;
648 }
649 auto textPropertyName = "text";
650 if (object()->metaObject()->indexOfProperty(textPropertyName) >= 0)
651 object()->setProperty(textPropertyName, text);
652}
653
654void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t)
655{
656 QAccessible::Role r = role();
657 if (t == QAccessible::ActionInterface)
658 return static_cast<QAccessibleActionInterface*>(this);
659 if (t == QAccessible::ValueInterface &&
660 (r == QAccessible::Slider ||
661 r == QAccessible::SpinBox ||
662 r == QAccessible::Dial ||
663 r == QAccessible::ScrollBar))
664 return static_cast<QAccessibleValueInterface*>(this);
665
666 if (t == QAccessible::TextInterface) {
667 if (r == QAccessible::EditableText ||
668 r == QAccessible::StaticText)
669 return static_cast<QAccessibleTextInterface*>(this);
670 }
671
672 return QAccessibleObject::interface_cast(t);
673}
674
675QVariant QAccessibleQuickItem::currentValue() const
676{
677 return item()->property("value");
678}
679
680void QAccessibleQuickItem::setCurrentValue(const QVariant &value)
681{
682 item()->setProperty("value", value);
683}
684
685QVariant QAccessibleQuickItem::maximumValue() const
686{
687 return item()->property("maximumValue");
688}
689
690QVariant QAccessibleQuickItem::minimumValue() const
691{
692 return item()->property("minimumValue");
693}
694
695QVariant QAccessibleQuickItem::minimumStepSize() const
696{
697 return item()->property("stepSize");
698}
699
704QRect itemScreenRect(QQuickItem *item)
705{
706 // ### no window in some cases.
707 // ### Should we really check for 0 opacity?
708 if (!item->window() ||!item->isVisible() || qFuzzyIsNull(item->opacity())) {
709 return QRect();
710 }
711
712 QSize itemSize((int)item->width(), (int)item->height());
713 // ### If the bounding rect fails, we first try the implicit size, then we go for the
714 // parent size. WE MIGHT HAVE TO REVISIT THESE FALLBACKS.
715 if (itemSize.isEmpty()) {
716 itemSize = QSize((int)item->implicitWidth(), (int)item->implicitHeight());
717 if (itemSize.isEmpty() && item->parentItem())
718 // ### Seems that the above fallback is not enough, fallback to use the parent size...
719 itemSize = QSize((int)item->parentItem()->width(), (int)item->parentItem()->height());
720 }
721
722 QPointF scenePoint = item->mapToScene(QPointF(0, 0));
723 QPoint screenPos = item->window()->mapToGlobal(scenePoint.toPoint());
724 return QRect(screenPos, itemSize);
725}
726
727QTextDocument *QAccessibleQuickItem::textDocument() const
728{
729 QVariant docVariant = item()->property("textDocument");
730 if (docVariant.canConvert<QQuickTextDocument*>()) {
731 QQuickTextDocument *qqdoc = docVariant.value<QQuickTextDocument*>();
732 return qqdoc->textDocument();
733 }
734 return nullptr;
735}
736
737int QAccessibleQuickItem::characterCount() const
738{
739 if (m_doc) {
741 cursor.movePosition(QTextCursor::End);
742 return cursor.position();
743 }
744 return text(QAccessible::Value).size();
745}
746
747int QAccessibleQuickItem::cursorPosition() const
748{
749 QVariant pos = item()->property("cursorPosition");
750 return pos.toInt();
751}
752
753void QAccessibleQuickItem::setCursorPosition(int position)
754{
755 item()->setProperty("cursorPosition", position);
756}
757
758QString QAccessibleQuickItem::text(int startOffset, int endOffset) const
759{
760 if (m_doc) {
762 cursor.setPosition(startOffset);
763 cursor.setPosition(endOffset, QTextCursor::KeepAnchor);
764 return cursor.selectedText();
765 }
766 return text(QAccessible::Value).mid(startOffset, endOffset - startOffset);
767}
768
769QString QAccessibleQuickItem::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
770 int *startOffset, int *endOffset) const
771{
772 Q_ASSERT(startOffset);
773 Q_ASSERT(endOffset);
774
775 if (m_doc) {
777 cursor.setPosition(offset);
778 QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
779 cursor.setPosition(boundaries.first - 1);
780 boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
781
782 *startOffset = boundaries.first;
783 *endOffset = boundaries.second;
784
785 return text(boundaries.first, boundaries.second);
786 } else {
787 return QAccessibleTextInterface::textBeforeOffset(offset, boundaryType, startOffset, endOffset);
788 }
789}
790
791QString QAccessibleQuickItem::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
792 int *startOffset, int *endOffset) const
793{
794 Q_ASSERT(startOffset);
795 Q_ASSERT(endOffset);
796
797 if (m_doc) {
799 cursor.setPosition(offset);
800 QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
801 cursor.setPosition(boundaries.second);
802 boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
803
804 *startOffset = boundaries.first;
805 *endOffset = boundaries.second;
806
807 return text(boundaries.first, boundaries.second);
808 } else {
809 return QAccessibleTextInterface::textAfterOffset(offset, boundaryType, startOffset, endOffset);
810 }
811}
812
813QString QAccessibleQuickItem::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
814 int *startOffset, int *endOffset) const
815{
816 Q_ASSERT(startOffset);
817 Q_ASSERT(endOffset);
818
819 if (m_doc) {
821 cursor.setPosition(offset);
822 QPair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
823
824 *startOffset = boundaries.first;
825 *endOffset = boundaries.second;
826 return text(boundaries.first, boundaries.second);
827 } else {
828 return QAccessibleTextInterface::textAtOffset(offset, boundaryType, startOffset, endOffset);
829 }
830}
831
832void QAccessibleQuickItem::selection(int selectionIndex, int *startOffset, int *endOffset) const
833{
834 if (selectionIndex == 0) {
835 *startOffset = item()->property("selectionStart").toInt();
836 *endOffset = item()->property("selectionEnd").toInt();
837 } else {
838 *startOffset = 0;
839 *endOffset = 0;
840 }
841}
842
843int QAccessibleQuickItem::selectionCount() const
844{
845 if (item()->property("selectionStart").toInt() != item()->property("selectionEnd").toInt())
846 return 1;
847 return 0;
848}
849
850void QAccessibleQuickItem::addSelection(int /* startOffset */, int /* endOffset */)
851{
852
853}
854void QAccessibleQuickItem::removeSelection(int /* selectionIndex */)
855{
856
857}
858void QAccessibleQuickItem::setSelection(int /* selectionIndex */, int /* startOffset */, int /* endOffset */)
859{
860
861}
862
863
864#endif // accessibility
865
\inmodule QtGui
\inmodule QtCore
Definition qbytearray.h:57
QList< QGraphicsItem * > childItems() const
QGraphicsWidget * window() const
QPointF mapToScene(const QPointF &point) const
Maps the point point, which is in this item's coordinate system, to the scene's coordinate system,...
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
bool isVisible() const
Returns true if the item is visible; otherwise, false is returned.
qreal opacity() const
void append(parameter_type t)
Definition qlist.h:458
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore\reentrant
Definition qpoint.h:25
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QQuickItem * parentItem() const
The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph onto an offs...
\qmltype TextDocument \instantiates QQuickTextDocument \inqmlmodule QtQuick
QTextDocument * textDocument() const
Returns a pointer to the QTextDocument object.
static QQuickTextPrivate * get(QQuickText *t)
static QQuickWindowPrivate * get(QQuickWindow *c)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:164
const_iterator constEnd() const noexcept
Definition qset.h:143
const_iterator constFind(const T &value) const
Definition qset.h:161
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
\reentrant \inmodule QtGui
Definition qtextcursor.h:30
\reentrant \inmodule QtGui
\inmodule QtCore
Definition qvariant.h:65
qreal toReal(bool *ok=nullptr) const
Returns the variant as a qreal if the variant has userType() \l QMetaType::Double,...
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
bool isNull() const
Returns true if this is a null variant, false otherwise.
\inmodule QtGui
Definition qwindow.h:63
QString text
QCursor cursor
QSet< QString >::iterator it
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
bool isEnabled()
constexpr QBindableInterface iface
Definition qproperty.h:666
QList< QString > QStringList
Constructs a string list that contains the given string, str.
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLint GLint GLint GLint GLint x
[0]
GLuint index
[2]
GLboolean r
[2]
GLuint object
[3]
GLenum GLuint GLintptr offset
GLint y
GLdouble s
[6]
Definition qopenglext.h:235
GLdouble GLdouble t
Definition qopenglext.h:243
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
static int toInt(const QChar &qc, int R)
const char property[13]
Definition qwizard.cpp:101
const char className[16]
[1]
Definition qwizard.cpp:100
obj metaObject() -> className()
QGraphicsItem * item
edit isVisible()
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
insertRed setText("insert red text")
\inmodule QtCore \reentrant
Definition qchar.h:18
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
QT_BEGIN_NAMESPACE bool toBool(const QString &str)
Definition utils.h:14