7#include <qaccessible.h>
8#include <qapplication.h>
10#if QT_CONFIG(itemviews)
11#include <qheaderview.h>
15#include <private/qtabbar_p.h>
17#if QT_CONFIG(combobox)
20#if QT_CONFIG(lineedit)
24#include <qstyleoption.h>
28#if QT_CONFIG(whatsthis)
29#include <qwhatsthis.h>
31#include <QAbstractScrollArea>
32#if QT_CONFIG(scrollarea)
35#if QT_CONFIG(scrollbar)
40#if QT_CONFIG(accessibility)
42#include <QtGui/private/qaccessiblehelper_p.h>
46using namespace Qt::StringLiterals;
48QString qt_accHotKey(
const QString &text);
52
53
54
55
56
57
59class QAccessibleTabButton:
public QAccessibleInterface,
public QAccessibleActionInterface,
60 public QAccessibleAttributesInterface
63 QAccessibleTabButton(QTabBar *parent,
int index)
64 : m_parent(parent), m_index(index)
67 void *interface_cast(QAccessible::InterfaceType t) override {
68 if (t == QAccessible::ActionInterface) {
69 return static_cast<QAccessibleActionInterface*>(
this);
71 if (t == QAccessible::AttributesInterface)
72 return static_cast<QAccessibleAttributesInterface *>(
this);
76 QObject *object()
const override {
return nullptr; }
77 QAccessible::Role role()
const override {
return QAccessible::PageTab; }
78 QAccessible::State state()
const override {
85 QAccessible::State s = parent()->state();
87 s.focused = (m_index == m_parent->currentIndex());
88 s.selected = s.focused;
91 QRect rect()
const override {
95 QPoint tp = m_parent->mapToGlobal(QPoint(0,0));
96 QRect rec = m_parent->tabRect(m_index);
97 rec = QRect(tp.x() + rec.x(), tp.y() + rec.y(), rec.width(), rec.height());
101 bool isValid()
const override {
103 if (
static_cast<QWidget *>(m_parent.data())->d_func()->data.in_destructor)
105 return m_parent->count() > m_index;
110 QAccessibleInterface *childAt(
int,
int)
const override {
return nullptr; }
111 int childCount()
const override {
return 0; }
112 int indexOfChild(
const QAccessibleInterface *)
const override {
return -1; }
114 QString text(QAccessible::Text t)
const override
120 case QAccessible::Name:
121 str = m_parent->accessibleTabName(m_index);
123 str = qt_accStripAmp(m_parent->tabText(m_index));
125 case QAccessible::Accelerator:
126 str = qt_accHotKey(m_parent->tabText(m_index));
128#if QT_CONFIG(tooltip)
129 case QAccessible::Description:
130 str = m_parent->tabToolTip(m_index);
133#if QT_CONFIG(whatsthis)
134 case QAccessible::Help:
135 str = m_parent->tabWhatsThis(m_index);
144 void setText(QAccessible::Text,
const QString &) override {}
146 QAccessibleInterface *parent()
const override {
147 return QAccessible::queryAccessibleInterface(m_parent.data());
149 QAccessibleInterface *child(
int)
const override {
return nullptr; }
152 QStringList actionNames()
const override
154 return QStringList(pressAction());
157 void doAction(
const QString &actionName) override
159 if (isValid() && actionName == pressAction())
160 m_parent->setCurrentIndex(m_index);
163 QStringList keyBindingsForAction(
const QString &)
const override
165 return QStringList();
169 QList<QAccessible::Attribute> attributeKeys()
const override
171 return { QAccessible::Attribute::PositionInSet, QAccessible::Attribute::SizeOfSet };
174 QVariant attributeValue(QAccessible::Attribute key)
const override
176 if (key == QAccessible::Attribute::PositionInSet)
178 if (key == QAccessible::Attribute::SizeOfSet)
179 return m_parent->count();
183 int index()
const {
return m_index; }
186 QPointer<QTabBar> m_parent;
192
193
194QAccessibleTabBar::QAccessibleTabBar(QWidget *w)
195: QAccessibleWidgetV2(w, QAccessible::PageTabList)
200QAccessibleTabBar::~QAccessibleTabBar()
202 for (QAccessible::Id id : std::as_const(m_childInterfaces))
203 QAccessible::deleteAccessibleInterface(id);
206void *QAccessibleTabBar::interface_cast(QAccessible::InterfaceType t)
208 if (t == QAccessible::SelectionInterface) {
209 return static_cast<QAccessibleSelectionInterface*>(
this);
211 return QAccessibleWidgetV2::interface_cast(t);
215QTabBar *QAccessibleTabBar::tabBar()
const
217 return qobject_cast<QTabBar*>(object());
220QAccessibleInterface* QAccessibleTabBar::focusChild()
const
222 for (
int i = 0; i < childCount(); ++i) {
223 if (child(i)->state().focused)
230QAccessibleInterface* QAccessibleTabBar::child(
int index)
const
232 if (QAccessible::Id id = m_childInterfaces.value(index))
233 return QAccessible::accessibleInterface(id);
236 if (index < tabBar()->count()) {
237 QAccessibleTabButton *button =
new QAccessibleTabButton(tabBar(), index);
238 QAccessible::registerAccessibleInterface(button);
239 m_childInterfaces.insert(index, QAccessible::uniqueId(button));
241 }
else if (index >= tabBar()->count()) {
243 if (index - tabBar()->count() == 0) {
244 return QAccessible::queryAccessibleInterface(tabBar()->d_func()->leftB);
247 if (index - tabBar()->count() == 1) {
248 return QAccessible::queryAccessibleInterface(tabBar()->d_func()->rightB);
254int QAccessibleTabBar::indexOfChild(
const QAccessibleInterface *child)
const
256 if (child->object() && child->object() == tabBar()->d_func()->leftB)
257 return tabBar()->count();
258 if (child->object() && child->object() == tabBar()->d_func()->rightB)
259 return tabBar()->count() + 1;
260 if (child->role() == QAccessible::PageTab) {
261 QAccessibleInterface *parent = child->parent();
262 if (parent ==
this) {
263 const QAccessibleTabButton *tabButton =
static_cast<
const QAccessibleTabButton *>(child);
264 return tabButton->index();
270int QAccessibleTabBar::childCount()
const
273 return tabBar()->count() + 2;
276QString QAccessibleTabBar::text(QAccessible::Text t)
const
278 if (t == QAccessible::Name) {
279 const QTabBar *tBar = tabBar();
280 int idx = tBar->currentIndex();
281 QString str = tBar->accessibleTabName(idx);
283 str = qt_accStripAmp(tBar->tabText(idx));
285 }
else if (t == QAccessible::Accelerator) {
286 return qt_accHotKey(tabBar()->tabText(tabBar()->currentIndex()));
291int QAccessibleTabBar::selectedItemCount()
const
293 if (tabBar()->currentIndex() >= 0)
298QList<QAccessibleInterface*> QAccessibleTabBar::selectedItems()
const
300 QList<QAccessibleInterface*> items;
301 QAccessibleInterface *selected = selectedItem(0);
303 items.push_back(selected);
307QAccessibleInterface* QAccessibleTabBar::selectedItem(
int selectionIndex)
const
309 const int currentIndex = tabBar()->currentIndex();
310 if (selectionIndex != 0 || currentIndex < 0)
312 return child(currentIndex);
315bool QAccessibleTabBar::isSelected(QAccessibleInterface *childItem)
const
317 return childItem && selectedItem(0) == childItem;
320bool QAccessibleTabBar::select(QAccessibleInterface *childItem)
322 const int childIndex = indexOfChild(childItem);
323 if (childIndex >= 0) {
324 tabBar()->setCurrentIndex(childIndex);
330bool QAccessibleTabBar::unselect(QAccessibleInterface *)
335bool QAccessibleTabBar::selectAll()
340bool QAccessibleTabBar::clear()
347#if QT_CONFIG(combobox)
349
350
351
352
353
354
357
358
359QAccessibleComboBox::QAccessibleComboBox(QWidget *w)
360: QAccessibleWidgetV2(w, QAccessible::ComboBox)
362 Q_ASSERT(comboBox());
366
367
368QComboBox *QAccessibleComboBox::comboBox()
const
370 return qobject_cast<QComboBox *>(object());
373QAccessibleInterface *QAccessibleComboBox::child(
int index)
const
375 if (QComboBox *cBox = comboBox()) {
377 QAbstractItemView *view = cBox->view();
379 return QAccessible::queryAccessibleInterface(view);
380 }
else if (index == 1 && cBox->isEditable()) {
381 return QAccessible::queryAccessibleInterface(cBox->lineEdit());
387int QAccessibleComboBox::childCount()
const
390 if (QComboBox *cBox = comboBox())
391 return (cBox->isEditable()) ? 2 : 1;
395QAccessibleInterface *QAccessibleComboBox::childAt(
int x,
int y)
const
397 if (QComboBox *cBox = comboBox()) {
398 if (cBox->isEditable() && cBox->lineEdit()->rect().contains(x, y))
404int QAccessibleComboBox::indexOfChild(
const QAccessibleInterface *child)
const
406 if (QComboBox *cBox = comboBox()) {
407 if (cBox->view() == child->object())
409 if (cBox->isEditable() && cBox->lineEdit() == child->object())
415QAccessibleInterface *QAccessibleComboBox::focusChild()
const
420 if (QComboBox *cBox = comboBox()) {
421 if (cBox->isEditable())
428QString QAccessibleComboBox::text(QAccessible::Text t)
const
431 if (QComboBox *cBox = comboBox()) {
433 case QAccessible::Name:
435 str = QAccessibleWidgetV2::text(t);
438 case QAccessible::Value:
439 if (cBox->isEditable())
440 str = cBox->lineEdit()->text();
442 str = cBox->currentText();
444#ifndef QT_NO_SHORTCUT
445 case QAccessible::Accelerator:
446 str = QKeySequence(Qt::Key_Down).toString(QKeySequence::NativeText);
453 str = QAccessibleWidgetV2::text(t);
458QAccessible::State QAccessibleComboBox::state()
const
460 QAccessible::State s = QAccessibleWidgetV2::state();
462 if (QComboBox *cBox = comboBox()) {
464 s.expanded = isValid() && cBox->view() && cBox->view()->isVisible();
465 s.editable = cBox->isEditable();
470QStringList QAccessibleComboBox::actionNames()
const
472 return QStringList() << showMenuAction() << pressAction();
475QString QAccessibleComboBox::localizedActionDescription(
const QString &actionName)
const
477 if (actionName == showMenuAction() || actionName == pressAction())
478 return QComboBox::tr(
"Open the combo box selection popup");
482void QAccessibleComboBox::doAction(
const QString &actionName)
484 if (QComboBox *cBox = comboBox()) {
485 if (actionName == showMenuAction() || actionName == pressAction()) {
486 if (cBox->view()->isVisible()) {
487#if defined(Q_OS_ANDROID)
488 const auto list = child(0)->tableInterface();
489 if (list && list->selectedRowCount() > 0) {
490 cBox->setCurrentIndex(list->selectedRows().at(0));
497#if defined(Q_OS_ANDROID)
498 const auto list = child(0)->tableInterface();
499 if (list && list->selectedRowCount() > 0) {
500 auto selectedCells = list->selectedCells();
501 QAccessibleEvent ev(selectedCells.at(0),QAccessible::Focus);
502 QAccessible::updateAccessibility(&ev);
510QStringList QAccessibleComboBox::keyBindingsForAction(
const QString &)
const
512 return QStringList();
517#if QT_CONFIG(scrollarea)
519QAccessibleAbstractScrollArea::QAccessibleAbstractScrollArea(QWidget *widget)
520 : QAccessibleWidgetV2(widget, QAccessible::Client)
522 Q_ASSERT(qobject_cast<QAbstractScrollArea *>(widget));
525QAccessibleInterface *QAccessibleAbstractScrollArea::child(
int index)
const
527 return QAccessible::queryAccessibleInterface(accessibleChildren().at(index));
530int QAccessibleAbstractScrollArea::childCount()
const
532 return accessibleChildren().size();
535int QAccessibleAbstractScrollArea::indexOfChild(
const QAccessibleInterface *child)
const
537 if (!child || !child->object())
539 return accessibleChildren().indexOf(qobject_cast<QWidget *>(child->object()));
542bool QAccessibleAbstractScrollArea::isValid()
const
544 return (QAccessibleWidgetV2::isValid() && abstractScrollArea() && abstractScrollArea()->viewport());
547QAccessibleInterface *QAccessibleAbstractScrollArea::childAt(
int x,
int y)
const
549 if (!abstractScrollArea()->isVisible())
552 for (
int i = 0; i < childCount(); ++i) {
553 QPoint wpos = accessibleChildren().at(i)->mapToGlobal(QPoint(0, 0));
554 QRect rect = QRect(wpos, accessibleChildren().at(i)->size());
555 if (rect.contains(x, y))
561QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea()
const
563 return static_cast<QAbstractScrollArea *>(object());
566QWidgetList QAccessibleAbstractScrollArea::accessibleChildren()
const
568 QWidgetList children;
571 QWidget * viewport = abstractScrollArea()->viewport();
573 children.append(viewport);
576 QScrollBar *horizontalScrollBar = abstractScrollArea()->horizontalScrollBar();
577 if (horizontalScrollBar && horizontalScrollBar->isVisible()) {
578 QWidget *scrollBarParent = horizontalScrollBar->parentWidget();
580 if (elementType(scrollBarParent) == HorizontalContainer)
581 children.append(scrollBarParent);
585 QScrollBar *verticalScrollBar = abstractScrollArea()->verticalScrollBar();
586 if (verticalScrollBar && verticalScrollBar->isVisible()) {
587 QWidget *scrollBarParent = verticalScrollBar->parentWidget();
589 if (elementType(scrollBarParent) == VerticalContainer)
590 children.append(scrollBarParent);
594 QWidget *cornerWidget = abstractScrollArea()->cornerWidget();
595 if (cornerWidget && cornerWidget->isVisible())
596 children.append(cornerWidget);
601QAccessibleAbstractScrollArea::AbstractScrollAreaElement
602QAccessibleAbstractScrollArea::elementType(QWidget *widget)
const
607 if (widget == abstractScrollArea())
609 if (widget == abstractScrollArea()->viewport())
611 if (widget->objectName() ==
"qt_scrollarea_hcontainer"_L1)
612 return HorizontalContainer;
613 if (widget->objectName() ==
"qt_scrollarea_vcontainer"_L1)
614 return VerticalContainer;
615 if (widget == abstractScrollArea()->cornerWidget())
621bool QAccessibleAbstractScrollArea::isLeftToRight()
const
623 return abstractScrollArea()->isLeftToRight();
627QAccessibleScrollArea::QAccessibleScrollArea(QWidget *widget)
628 : QAccessibleAbstractScrollArea(widget)
630 Q_ASSERT(qobject_cast<QScrollArea *>(widget));