diff options
Diffstat (limited to 'src/widgets')
15 files changed, 131 insertions, 23 deletions
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index f4fc96b867d..d43b6ec4fb2 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -339,12 +339,12 @@ set(qstyle_resource_fusion_files "styles/images/fusion_closedock-32.png" "styles/images/fusion_closedock-48.png" "styles/images/fusion_closedock-64.png" - "styles/images/fusion_normalizedockup_10.png" + "styles/images/fusion_normalizedockup-10.png" "styles/images/fusion_normalizedockup-16.png" - "styles/images/fusion_normalizedockup_20.png" + "styles/images/fusion_normalizedockup-20.png" "styles/images/fusion_normalizedockup-32.png" - "styles/images/fusion_normalizedockup_48.png" - "styles/images/fusion_normalizedockup_64.png" + "styles/images/fusion_normalizedockup-48.png" + "styles/images/fusion_normalizedockup-64.png" "styles/images/fusion_titlebar-min-10.png" "styles/images/fusion_titlebar-min-16.png" "styles/images/fusion_titlebar-min-20.png" diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp index cc3a230f9b4..ba941012dd7 100644 --- a/src/widgets/accessible/itemviews.cpp +++ b/src/widgets/accessible/itemviews.cpp @@ -99,6 +99,21 @@ QHeaderView *QAccessibleTable::verticalHeader() const return header; } +// Normally cellAt takes row/column in the range +// [0 .. rowCount()) +// [0 .. columnCount()) +// +// As an extension we allow clients to ask for headers +// +// * Has both vertical and horizontal headers: +// (-1,-1) -> corner button +// * Has column headers: +// (-1, column) -> column header for column \a column +// * has row headers +// (row, -1) -> row header for row \a row +// +// If asking for a header that does not exist, The invalid +// index warning is logged, and nullptr is returned. QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const { const QAbstractItemView *theView = view(); @@ -107,6 +122,22 @@ QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const return nullptr; Q_ASSERT(role() != QAccessible::List); Q_ASSERT(role() != QAccessible::Tree); + + const int vHeader = verticalHeader() ? 1 : 0; + const int hHeader = horizontalHeader() ? 1 : 0; + + const int doHHeader = ((row == -1) && hHeader); + const int doVHeader = ((column == -1) && vHeader); + + if (doVHeader && doHHeader) + return child(0); + + if (doVHeader) + return child((row + hHeader) * (columnCount() + vHeader) + (column + vHeader)); + + if (doHHeader) + return child((row + hHeader) * (columnCount() + vHeader) + (column + vHeader)); + QModelIndex index = theModel->index(row, column, theView->rootIndex()); if (Q_UNLIKELY(!index.isValid())) { qWarning() << "QAccessibleTable::cellAt: invalid index: " << index << " for " << theView; diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index 6288aae096a..05233ba5801 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -172,6 +172,43 @@ void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index } } +#if QT_CONFIG(accessibility) +void QAbstractItemViewPrivate::updateItemAccessibility(const QModelIndex &index, + const QList<int> &roles) +{ + Q_Q(QAbstractItemView); + + if (!QAccessible::isActive()) + return; + + const int childIndex = accessibleChildIndex(index); + if (childIndex < 0) + return; + + // see QAccessibleTableCell for how role data are mapped to the a11y layer + + for (int role : roles) { + if (role == Qt::AccessibleTextRole + || (role == Qt::DisplayRole + && index.data(Qt::AccessibleTextRole).toString().isEmpty())) { + QAccessibleEvent event(q, QAccessible::NameChanged); + event.setChild(childIndex); + QAccessible::updateAccessibility(&event); + } else if (role == Qt::AccessibleDescriptionRole) { + QAccessibleEvent event(q, QAccessible::DescriptionChanged); + event.setChild(childIndex); + QAccessible::updateAccessibility(&event); + } else if (role == Qt::CheckStateRole) { + QAccessible::State state; + state.checked = true; + QAccessibleStateChangeEvent event(q, state); + event.setChild(childIndex); + QAccessible::updateAccessibility(&event); + } + } +} +#endif + #if QT_CONFIG(gestures) && QT_CONFIG(scroller) // stores and restores the selection and current item when flicking @@ -3495,6 +3532,10 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde accessibleEvent.setLastRow(bottomRight.row()); accessibleEvent.setLastColumn(bottomRight.column()); QAccessible::updateAccessibility(&accessibleEvent); + + // send accessibility events as needed when current item is modified + if (topLeft == bottomRight && topLeft == currentIndex()) + d->updateItemAccessibility(topLeft, roles); } #endif d->updateGeometry(); diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h index 60799fb8a50..f9e899d7fc8 100644 --- a/src/widgets/itemviews/qabstractitemview_p.h +++ b/src/widgets/itemviews/qabstractitemview_p.h @@ -272,6 +272,18 @@ public: return isIndexValid(index) && isIndexSelectable(index); } +#if QT_CONFIG(accessibility) + virtual int accessibleChildIndex(const QModelIndex &index) const + { + Q_UNUSED(index); + return -1; + } +#endif + +#if QT_CONFIG(accessibility) + void updateItemAccessibility(const QModelIndex &index, const QList<int> &roles); +#endif + // reimplemented from QAbstractScrollAreaPrivate QPoint contentsOffset() const override { Q_Q(const QAbstractItemView); diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index e245f98151b..50b6034500d 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -1959,6 +1959,14 @@ bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QMo } #endif +#if QT_CONFIG(accessibility) +int QListViewPrivate::accessibleChildIndex(const QModelIndex &index) const +{ + Q_Q(const QListView); + return q->visualIndex(index); +} +#endif + void QListViewPrivate::removeCurrentAndDisabled(QList<QModelIndex> *indexes, const QModelIndex ¤t) const { @@ -3397,11 +3405,12 @@ void QIconModeViewBase::updateContentsSize() */ void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { + Q_D(const QListView); QAbstractItemView::currentChanged(current, previous); #if QT_CONFIG(accessibility) if (QAccessible::isActive()) { if (current.isValid() && hasFocus()) { - int entry = visualIndex(current); + int entry = d->accessibleChildIndex(current); QAccessibleEvent event(this, QAccessible::Focus); event.setChild(entry); QAccessible::updateAccessibility(&event); @@ -3417,18 +3426,19 @@ void QListView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { #if QT_CONFIG(accessibility) + Q_D(const QListView); if (QAccessible::isActive()) { // ### does not work properly for selection ranges. QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { - int entry = visualIndex(sel); + int entry = d->accessibleChildIndex(sel); QAccessibleEvent event(this, QAccessible::SelectionAdd); event.setChild(entry); QAccessible::updateAccessibility(&event); } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { - int entry = visualIndex(desel); + int entry = d->accessibleChildIndex(desel); QAccessibleEvent event(this, QAccessible::SelectionRemove); event.setChild(entry); QAccessible::updateAccessibility(&event); diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h index 4475fa5461f..7e36887a65c 100644 --- a/src/widgets/itemviews/qlistview_p.h +++ b/src/widgets/itemviews/qlistview_p.h @@ -346,6 +346,10 @@ public: bool dropOn(QDropEvent *event, int *row, int *col, QModelIndex *index) override; #endif +#if QT_CONFIG(accessibility) + int accessibleChildIndex(const QModelIndex &index) const override; +#endif + inline void setGridSize(const QSize &size) { grid = size; } inline QSize gridSize() const { return grid; } inline void setWrapping(bool b) { wrap = b; } diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 40e3fcaf91b..2d28b3d4a81 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -3593,7 +3593,7 @@ void QTableView::currentChanged(const QModelIndex ¤t, const QModelIndex &p if (QAccessible::isActive()) { if (current.isValid() && hasFocus()) { Q_D(QTableView); - int entry = d->accessibleTable2Index(current); + int entry = d->accessibleChildIndex(current); QAccessibleEvent event(this, QAccessible::Focus); event.setChild(entry); QAccessible::updateAccessibility(&event); @@ -3616,14 +3616,14 @@ void QTableView::selectionChanged(const QItemSelection &selected, // ### does not work properly for selection ranges. QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { - int entry = d->accessibleTable2Index(sel); + int entry = d->accessibleChildIndex(sel); QAccessibleEvent event(this, QAccessible::SelectionAdd); event.setChild(entry); QAccessible::updateAccessibility(&event); } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { - int entry = d->accessibleTable2Index(desel); + int entry = d->accessibleChildIndex(desel); QAccessibleEvent event(this, QAccessible::SelectionRemove); event.setChild(entry); QAccessible::updateAccessibility(&event); diff --git a/src/widgets/itemviews/qtableview_p.h b/src/widgets/itemviews/qtableview_p.h index 8ddb8e797a9..9a7ce229880 100644 --- a/src/widgets/itemviews/qtableview_p.h +++ b/src/widgets/itemviews/qtableview_p.h @@ -141,11 +141,14 @@ public: QStyleOptionViewItem::ViewItemPosition viewItemPosition(const QModelIndex &index) const; - inline int accessibleTable2Index(const QModelIndex &index) const { +#if QT_CONFIG(accessibility) + inline int accessibleChildIndex(const QModelIndex &index) const override + { const int vHeader = verticalHeader ? 1 : 0; return (index.row() + (horizontalHeader ? 1 : 0)) * (index.model()->columnCount() + vHeader) + index.column() + vHeader; } +#endif int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const; int sectionSpanSize(const QHeaderView *header, int logical, int span) const; diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index e38d78b72f8..570566793dc 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -4083,13 +4083,15 @@ void QTreeViewPrivate::sortIndicatorChanged(int column, Qt::SortOrder order) model->sort(column, order); } -int QTreeViewPrivate::accessibleTree2Index(const QModelIndex &index) const +#if QT_CONFIG(accessibility) +int QTreeViewPrivate::accessibleChildIndex(const QModelIndex &index) const { Q_Q(const QTreeView); // Note that this will include the header, even if its hidden. return (q->visualIndex(index) + (q->header() ? 1 : 0)) * index.model()->columnCount() + index.column(); } +#endif void QTreeViewPrivate::updateIndentationFromStyle() { @@ -4116,7 +4118,7 @@ void QTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr Q_D(QTreeView); QAccessibleEvent event(this, QAccessible::Focus); - event.setChild(d->accessibleTree2Index(current)); + event.setChild(d->accessibleChildIndex(current)); QAccessible::updateAccessibility(&event); } #endif @@ -4136,7 +4138,7 @@ void QTreeView::selectionChanged(const QItemSelection &selected, // ### does not work properly for selection ranges. QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { - int entry = d->accessibleTree2Index(sel); + int entry = d->accessibleChildIndex(sel); Q_ASSERT(entry >= 0); QAccessibleEvent event(this, QAccessible::SelectionAdd); event.setChild(entry); @@ -4144,7 +4146,7 @@ void QTreeView::selectionChanged(const QItemSelection &selected, } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { - int entry = d->accessibleTree2Index(desel); + int entry = d->accessibleChildIndex(desel); Q_ASSERT(entry >= 0); QAccessibleEvent event(this, QAccessible::SelectionRemove); event.setChild(entry); diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h index 5a4e057901c..34db2fcdacb 100644 --- a/src/widgets/itemviews/qtreeview_p.h +++ b/src/widgets/itemviews/qtreeview_p.h @@ -234,7 +234,9 @@ public: return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column(); } - int accessibleTree2Index(const QModelIndex &index) const; +#if QT_CONFIG(accessibility) + int accessibleChildIndex(const QModelIndex &index) const override; +#endif void updateIndentationFromStyle(); diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index d989feb7f91..fa17c94a23f 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -389,13 +389,16 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) p += offset; #if QT_CONFIG(wayland) - create(); - if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(windowHandle()->handle())) { - // based on the existing code below, by default position at 'p' stored at the bottom right of our rect - // then flip to the other arbitrary 4x24 space if constrained - const QRect controlGeometry(QRect(p.x() - 4, p.y() - 24, 4, 24)); - waylandWindow->setParentControlGeometry(controlGeometry); - waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ToolTip); + if (w) { + create(); + if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(windowHandle()->handle())) { + // based on the existing code below, by default position at 'p' stored at the bottom right of our rect + // then flip to the other arbitrary 4x24 space if constrained + const QRect controlGeometry = QRect(p.x() - 4, p.y() - 24, 4, 24) + .translated(-w->window()->mapToGlobal(QPoint(0, 0))); + waylandWindow->setParentControlGeometry(controlGeometry); + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ToolTip); + } } #endif diff --git a/src/widgets/styles/images/fusion_normalizedockup_10.png b/src/widgets/styles/images/fusion_normalizedockup-10.png Binary files differindex 7516e4ee4f8..7516e4ee4f8 100644 --- a/src/widgets/styles/images/fusion_normalizedockup_10.png +++ b/src/widgets/styles/images/fusion_normalizedockup-10.png diff --git a/src/widgets/styles/images/fusion_normalizedockup_20.png b/src/widgets/styles/images/fusion_normalizedockup-20.png Binary files differindex 2bc9421d5ac..2bc9421d5ac 100644 --- a/src/widgets/styles/images/fusion_normalizedockup_20.png +++ b/src/widgets/styles/images/fusion_normalizedockup-20.png diff --git a/src/widgets/styles/images/fusion_normalizedockup_48.png b/src/widgets/styles/images/fusion_normalizedockup-48.png Binary files differindex 6c497abdded..6c497abdded 100644 --- a/src/widgets/styles/images/fusion_normalizedockup_48.png +++ b/src/widgets/styles/images/fusion_normalizedockup-48.png diff --git a/src/widgets/styles/images/fusion_normalizedockup_64.png b/src/widgets/styles/images/fusion_normalizedockup-64.png Binary files differindex 5ec620e5a04..5ec620e5a04 100644 --- a/src/widgets/styles/images/fusion_normalizedockup_64.png +++ b/src/widgets/styles/images/fusion_normalizedockup-64.png |
