6#include <qaccessible.h>
7#include <qapplication.h>
9#if QT_CONFIG(itemviews)
10#include <qheaderview.h>
14#include <private/qtabbar_p.h>
16#if QT_CONFIG(combobox)
19#if QT_CONFIG(lineedit)
23#include <qstyleoption.h>
27#if QT_CONFIG(whatsthis)
28#include <qwhatsthis.h>
30#include <QAbstractScrollArea>
31#if QT_CONFIG(scrollarea)
34#if QT_CONFIG(scrollbar)
39#if QT_CONFIG(accessibility)
41#include <QtGui/private/qaccessiblehelper_p.h>
45using namespace Qt::StringLiterals;
47QString qt_accHotKey(
const QString &text);
51
52
53
54
55
56
58class QAccessibleTabButton:
public QAccessibleInterface,
public QAccessibleActionInterface
61 QAccessibleTabButton(QTabBar *parent,
int index)
62 : m_parent(parent), m_index(index)
65 void *interface_cast(QAccessible::InterfaceType t) override {
66 if (t == QAccessible::ActionInterface) {
67 return static_cast<QAccessibleActionInterface*>(
this);
72 QObject *object()
const override {
return nullptr; }
73 QAccessible::Role role()
const override {
return QAccessible::PageTab; }
74 QAccessible::State state()
const override {
81 QAccessible::State s = parent()->state();
83 s.focused = (m_index == m_parent->currentIndex());
84 s.selected = s.focused;
87 QRect rect()
const override {
91 QPoint tp = m_parent->mapToGlobal(QPoint(0,0));
92 QRect rec = m_parent->tabRect(m_index);
93 rec = QRect(tp.x() + rec.x(), tp.y() + rec.y(), rec.width(), rec.height());
97 bool isValid()
const override {
99 if (
static_cast<QWidget *>(m_parent.data())->d_func()->data.in_destructor)
101 return m_parent->count() > m_index;
106 QAccessibleInterface *childAt(
int,
int)
const override {
return nullptr; }
107 int childCount()
const override {
return 0; }
108 int indexOfChild(
const QAccessibleInterface *)
const override {
return -1; }
110 QString text(QAccessible::Text t)
const override
116 case QAccessible::Name:
117 str = m_parent->accessibleTabName(m_index);
119 str = qt_accStripAmp(m_parent->tabText(m_index));
121 case QAccessible::Accelerator:
122 str = qt_accHotKey(m_parent->tabText(m_index));
124#if QT_CONFIG(tooltip)
125 case QAccessible::Description:
126 str = m_parent->tabToolTip(m_index);
129#if QT_CONFIG(whatsthis)
130 case QAccessible::Help:
131 str = m_parent->tabWhatsThis(m_index);
140 void setText(QAccessible::Text,
const QString &) override {}
142 QAccessibleInterface *parent()
const override {
143 return QAccessible::queryAccessibleInterface(m_parent.data());
145 QAccessibleInterface *child(
int)
const override {
return nullptr; }
148 QStringList actionNames()
const override
150 return QStringList(pressAction());
153 void doAction(
const QString &actionName) override
155 if (isValid() && actionName == pressAction())
156 m_parent->setCurrentIndex(m_index);
159 QStringList keyBindingsForAction(
const QString &)
const override
161 return QStringList();
164 int index()
const {
return m_index; }
167 QPointer<QTabBar> m_parent;
173
174
175QAccessibleTabBar::QAccessibleTabBar(QWidget *w)
176: QAccessibleWidgetV2(w, QAccessible::PageTabList)
181QAccessibleTabBar::~QAccessibleTabBar()
183 for (QAccessible::Id id : std::as_const(m_childInterfaces))
184 QAccessible::deleteAccessibleInterface(id);
187void *QAccessibleTabBar::interface_cast(QAccessible::InterfaceType t)
189 if (t == QAccessible::SelectionInterface) {
190 return static_cast<QAccessibleSelectionInterface*>(
this);
192 return QAccessibleWidgetV2::interface_cast(t);
196QTabBar *QAccessibleTabBar::tabBar()
const
198 return qobject_cast<QTabBar*>(object());
201QAccessibleInterface* QAccessibleTabBar::focusChild()
const
203 for (
int i = 0; i < childCount(); ++i) {
204 if (child(i)->state().focused)
211QAccessibleInterface* QAccessibleTabBar::child(
int index)
const
213 if (QAccessible::Id id = m_childInterfaces.value(index))
214 return QAccessible::accessibleInterface(id);
217 if (index < tabBar()->count()) {
218 QAccessibleTabButton *button =
new QAccessibleTabButton(tabBar(), index);
219 QAccessible::registerAccessibleInterface(button);
220 m_childInterfaces.insert(index, QAccessible::uniqueId(button));
222 }
else if (index >= tabBar()->count()) {
224 if (index - tabBar()->count() == 0) {
225 return QAccessible::queryAccessibleInterface(tabBar()->d_func()->leftB);
228 if (index - tabBar()->count() == 1) {
229 return QAccessible::queryAccessibleInterface(tabBar()->d_func()->rightB);
235int QAccessibleTabBar::indexOfChild(
const QAccessibleInterface *child)
const
237 if (child->object() && child->object() == tabBar()->d_func()->leftB)
238 return tabBar()->count();
239 if (child->object() && child->object() == tabBar()->d_func()->rightB)
240 return tabBar()->count() + 1;
241 if (child->role() == QAccessible::PageTab) {
242 QAccessibleInterface *parent = child->parent();
243 if (parent ==
this) {
244 const QAccessibleTabButton *tabButton =
static_cast<
const QAccessibleTabButton *>(child);
245 return tabButton->index();
251int QAccessibleTabBar::childCount()
const
254 return tabBar()->count() + 2;
257QString QAccessibleTabBar::text(QAccessible::Text t)
const
259 if (t == QAccessible::Name) {
260 const QTabBar *tBar = tabBar();
261 int idx = tBar->currentIndex();
262 QString str = tBar->accessibleTabName(idx);
264 str = qt_accStripAmp(tBar->tabText(idx));
266 }
else if (t == QAccessible::Accelerator) {
267 return qt_accHotKey(tabBar()->tabText(tabBar()->currentIndex()));
272int QAccessibleTabBar::selectedItemCount()
const
274 if (tabBar()->currentIndex() >= 0)
279QList<QAccessibleInterface*> QAccessibleTabBar::selectedItems()
const
281 QList<QAccessibleInterface*> items;
282 QAccessibleInterface *selected = selectedItem(0);
284 items.push_back(selected);
288QAccessibleInterface* QAccessibleTabBar::selectedItem(
int selectionIndex)
const
290 const int currentIndex = tabBar()->currentIndex();
291 if (selectionIndex != 0 || currentIndex < 0)
293 return child(currentIndex);
296bool QAccessibleTabBar::isSelected(QAccessibleInterface *childItem)
const
298 return childItem && selectedItem(0) == childItem;
301bool QAccessibleTabBar::select(QAccessibleInterface *childItem)
303 const int childIndex = indexOfChild(childItem);
304 if (childIndex >= 0) {
305 tabBar()->setCurrentIndex(childIndex);
311bool QAccessibleTabBar::unselect(QAccessibleInterface *)
316bool QAccessibleTabBar::selectAll()
321bool QAccessibleTabBar::clear()
328#if QT_CONFIG(combobox)
330
331
332
333
334
335
338
339
340QAccessibleComboBox::QAccessibleComboBox(QWidget *w)
341: QAccessibleWidgetV2(w, QAccessible::ComboBox)
343 Q_ASSERT(comboBox());
347
348
349QComboBox *QAccessibleComboBox::comboBox()
const
351 return qobject_cast<QComboBox *>(object());
354QAccessibleInterface *QAccessibleComboBox::child(
int index)
const
356 if (QComboBox *cBox = comboBox()) {
358 QAbstractItemView *view = cBox->view();
360 return QAccessible::queryAccessibleInterface(view);
361 }
else if (index == 1 && cBox->isEditable()) {
362 return QAccessible::queryAccessibleInterface(cBox->lineEdit());
368int QAccessibleComboBox::childCount()
const
371 if (QComboBox *cBox = comboBox())
372 return (cBox->isEditable()) ? 2 : 1;
376QAccessibleInterface *QAccessibleComboBox::childAt(
int x,
int y)
const
378 if (QComboBox *cBox = comboBox()) {
379 if (cBox->isEditable() && cBox->lineEdit()->rect().contains(x, y))
385int QAccessibleComboBox::indexOfChild(
const QAccessibleInterface *child)
const
387 if (QComboBox *cBox = comboBox()) {
388 if (cBox->view() == child->object())
390 if (cBox->isEditable() && cBox->lineEdit() == child->object())
396QAccessibleInterface *QAccessibleComboBox::focusChild()
const
401 if (QComboBox *cBox = comboBox()) {
402 if (cBox->isEditable())
409QString QAccessibleComboBox::text(QAccessible::Text t)
const
412 if (QComboBox *cBox = comboBox()) {
414 case QAccessible::Name:
416 str = QAccessibleWidgetV2::text(t);
419 case QAccessible::Value:
420 if (cBox->isEditable())
421 str = cBox->lineEdit()->text();
423 str = cBox->currentText();
425#ifndef QT_NO_SHORTCUT
426 case QAccessible::Accelerator:
427 str = QKeySequence(Qt::Key_Down).toString(QKeySequence::NativeText);
434 str = QAccessibleWidgetV2::text(t);
439QAccessible::State QAccessibleComboBox::state()
const
441 QAccessible::State s = QAccessibleWidgetV2::state();
443 if (QComboBox *cBox = comboBox()) {
445 s.expanded = isValid() && cBox->view() && cBox->view()->isVisible();
446 s.editable = cBox->isEditable();
451QStringList QAccessibleComboBox::actionNames()
const
453 return QStringList() << showMenuAction() << pressAction();
456QString QAccessibleComboBox::localizedActionDescription(
const QString &actionName)
const
458 if (actionName == showMenuAction() || actionName == pressAction())
459 return QComboBox::tr(
"Open the combo box selection popup");
463void QAccessibleComboBox::doAction(
const QString &actionName)
465 if (QComboBox *cBox = comboBox()) {
466 if (actionName == showMenuAction() || actionName == pressAction()) {
467 if (cBox->view()->isVisible()) {
468#if defined(Q_OS_ANDROID)
469 const auto list = child(0)->tableInterface();
470 if (list && list->selectedRowCount() > 0) {
471 cBox->setCurrentIndex(list->selectedRows().at(0));
478#if defined(Q_OS_ANDROID)
479 const auto list = child(0)->tableInterface();
480 if (list && list->selectedRowCount() > 0) {
481 auto selectedCells = list->selectedCells();
482 QAccessibleEvent ev(selectedCells.at(0),QAccessible::Focus);
483 QAccessible::updateAccessibility(&ev);
491QStringList QAccessibleComboBox::keyBindingsForAction(
const QString &)
const
493 return QStringList();
498#if QT_CONFIG(scrollarea)
500QAccessibleAbstractScrollArea::QAccessibleAbstractScrollArea(QWidget *widget)
501 : QAccessibleWidgetV2(widget, QAccessible::Client)
503 Q_ASSERT(qobject_cast<QAbstractScrollArea *>(widget));
506QAccessibleInterface *QAccessibleAbstractScrollArea::child(
int index)
const
508 return QAccessible::queryAccessibleInterface(accessibleChildren().at(index));
511int QAccessibleAbstractScrollArea::childCount()
const
513 return accessibleChildren().size();
516int QAccessibleAbstractScrollArea::indexOfChild(
const QAccessibleInterface *child)
const
518 if (!child || !child->object())
520 return accessibleChildren().indexOf(qobject_cast<QWidget *>(child->object()));
523bool QAccessibleAbstractScrollArea::isValid()
const
525 return (QAccessibleWidgetV2::isValid() && abstractScrollArea() && abstractScrollArea()->viewport());
528QAccessibleInterface *QAccessibleAbstractScrollArea::childAt(
int x,
int y)
const
530 if (!abstractScrollArea()->isVisible())
533 for (
int i = 0; i < childCount(); ++i) {
534 QPoint wpos = accessibleChildren().at(i)->mapToGlobal(QPoint(0, 0));
535 QRect rect = QRect(wpos, accessibleChildren().at(i)->size());
536 if (rect.contains(x, y))
542QAbstractScrollArea *QAccessibleAbstractScrollArea::abstractScrollArea()
const
544 return static_cast<QAbstractScrollArea *>(object());
547QWidgetList QAccessibleAbstractScrollArea::accessibleChildren()
const
549 QWidgetList children;
552 QWidget * viewport = abstractScrollArea()->viewport();
554 children.append(viewport);
557 QScrollBar *horizontalScrollBar = abstractScrollArea()->horizontalScrollBar();
558 if (horizontalScrollBar && horizontalScrollBar->isVisible()) {
559 QWidget *scrollBarParent = horizontalScrollBar->parentWidget();
561 if (elementType(scrollBarParent) == HorizontalContainer)
562 children.append(scrollBarParent);
566 QScrollBar *verticalScrollBar = abstractScrollArea()->verticalScrollBar();
567 if (verticalScrollBar && verticalScrollBar->isVisible()) {
568 QWidget *scrollBarParent = verticalScrollBar->parentWidget();
570 if (elementType(scrollBarParent) == VerticalContainer)
571 children.append(scrollBarParent);
575 QWidget *cornerWidget = abstractScrollArea()->cornerWidget();
576 if (cornerWidget && cornerWidget->isVisible())
577 children.append(cornerWidget);
582QAccessibleAbstractScrollArea::AbstractScrollAreaElement
583QAccessibleAbstractScrollArea::elementType(QWidget *widget)
const
588 if (widget == abstractScrollArea())
590 if (widget == abstractScrollArea()->viewport())
592 if (widget->objectName() ==
"qt_scrollarea_hcontainer"_L1)
593 return HorizontalContainer;
594 if (widget->objectName() ==
"qt_scrollarea_vcontainer"_L1)
595 return VerticalContainer;
596 if (widget == abstractScrollArea()->cornerWidget())
602bool QAccessibleAbstractScrollArea::isLeftToRight()
const
604 return abstractScrollArea()->isLeftToRight();
608QAccessibleScrollArea::QAccessibleScrollArea(QWidget *widget)
609 : QAccessibleAbstractScrollArea(widget)
611 Q_ASSERT(qobject_cast<QScrollArea *>(widget));