diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2023-04-22 09:22:38 +0300 |
---|---|---|
committer | Michael Weghorn <m.weghorn@posteo.de> | 2023-04-22 11:33:32 +0200 |
commit | 84183c84d86456e3c311b35150b1fc9b63a85561 (patch) | |
tree | 689f972dcc3ca4194fd31d5458f067849b2fbf8a /vcl | |
parent | dabe502c362f528a529e14a90abcc79d95d393be (diff) |
qt a11y: Implement QAccessibleSelectionInterface added in Qt 6.5
This adds an implementation of the
`QAccessibleSelectionInterface` that was added
in Qt 6.5 in commit [1]
commit 9d16d5e2245c26e5746fd7609300b84a2a983457
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Tue Oct 11 15:23:54 2022 +0200
a11y: Add new QAccessibleSelectionInterface
, s.a. QTBUG-105909 [2].
The `QAccessibleSelectionInterface` is currently still marked as
preliminary in Qt, so changes to the API *might* still happen
and require an update of the implementation here as well).
Quoting from the commit message of the above commit:
> This interface is marked \preliminary until:
>
> 1. There is a working a11y bridge for macOS/VoiceOver
> 2. There is a working a11y bridge for Windows/UI Automation
> 3. There is a working a11y bridge for linux/AT-SPI
> 4. There is at least one implementation (e.g. QAccessibleTable)
> that implements it successfully (second candidate:
> Qt Quick TableView [...])
The AT-SPI bridge (point 3 from above) has been implemented in [3]
commit ece2feee0317b582a56a0bfc783f11fe67d3edee
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Tue Oct 11 15:24:04 2022 +0200
a11y atspi: Bridge newly introduced QAccessibleSelectionInterface
, an implementation for `QAccessibleTable` (point 4 from above) was
added in [4]
commit 092bbc9ad30c6cd7389053dc4b332cc762693676
Author: Michael Weghorn <m.weghorn@posteo.de>
Date: Wed Oct 12 07:07:48 2022 +0200
a11y: Implement QAccessibleSelectionInterface for item views
. The Qt Gerrit changes for the macOS implementation (point 1 from
above) and the Windows/UIA implementation (point 2 from above)
are currently still awaiting review: [5] [6]
To avoid duplication, just call the newly added methods
`QtAccessibleWidget::selectedItemCount` and
`QtAccessibleWidget::selectedItem` from the
`QAccessibleTableInterface` methods
`QtAccessibleWidget::selectedCellCount` and
and `QtAccessibleWidget::selectedCells`, and
therefore implement the former also for Qt < 6.5.
Sample use of the interface from Accerciser's IPython
console (with 18 cells selected in Calc and the spreadsheet
object selected in Accerciser's a11y object tree; screencast
attached to QTBUG-105909 [2]):
In [10]: acc.get_interfaces()
Out[10]: ['Accessible', 'Component', 'Selection', 'Table']
In [11]: sel = acc.querySelection()
In [12]: sel.nSelectedChildren
Out[12]: 18
In [13]: sel.getSelectedChild(0).name
Out[13]: 'B1'
In [14]: sel.deselectSelectedChild(1)
Out[14]: True
In [15]: sel.deselectChild(1)
Out[15]: True
In [16]: sel.selectChild(0)
Out[16]: True
In [17]: sel.clearSelection()
Out[17]: True
In [18]: sel.selectAll()
Out[18]: True
[1] https://code.qt.io/cgit/qt/qtbase.git/commit/?id=9d16d5e2245c26e5746fd7609300b84a2a983457
[2] https://bugreports.qt.io/browse/QTBUG-105909
[3] https://code.qt.io/cgit/qt/qtbase.git/commit/?id=ece2feee0317b582a56a0bfc783f11fe67d3edee
[4] https://code.qt.io/cgit/qt/qtbase.git/commit/?id=092bbc9ad30c6cd7389053dc4b332cc762693676
[5] https://codereview.qt-project.org/c/qt/qtbase/+/451353
[6] https://codereview.qt-project.org/c/qt/qtbase/+/451646
Change-Id: Iac3c050448183610af3bd3b10a56e82d7d52cb91
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138750
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/qt5/QtAccessibleWidget.hxx | 19 | ||||
-rw-r--r-- | vcl/qt5/QtAccessibleWidget.cxx | 212 |
2 files changed, 183 insertions, 48 deletions
diff --git a/vcl/inc/qt5/QtAccessibleWidget.hxx b/vcl/inc/qt5/QtAccessibleWidget.hxx index 7e7625041c4f..d6d27c9cfcbd 100644 --- a/vcl/inc/qt5/QtAccessibleWidget.hxx +++ b/vcl/inc/qt5/QtAccessibleWidget.hxx @@ -40,6 +40,9 @@ class QtAccessibleWidget final : public QAccessibleInterface, public QAccessibleActionInterface, public QAccessibleTextInterface, public QAccessibleEditableTextInterface, +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + public QAccessibleSelectionInterface, +#endif public QAccessibleTableCellInterface, public QAccessibleTableInterface, public QAccessibleValueInterface @@ -147,6 +150,22 @@ public: virtual int rowIndex() const override; virtual QAccessibleInterface* table() const override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + // QAccessibleSelectionInterface + virtual int selectedItemCount() const override; + virtual QList<QAccessibleInterface*> selectedItems() const override; + virtual QAccessibleInterface* selectedItem(int selectionIndex) const override; + virtual bool isSelected(QAccessibleInterface* item) const override; + virtual bool select(QAccessibleInterface* item) override; + virtual bool unselect(QAccessibleInterface* item) override; + virtual bool selectAll() override; + virtual bool clear() override; +#else + // no override, but used in QAccessibleTableInterface methods + virtual int selectedItemCount() const; + virtual QList<QAccessibleInterface*> selectedItems() const; +#endif + // Factory static QAccessibleInterface* customFactory(const QString& classname, QObject* object); diff --git a/vcl/qt5/QtAccessibleWidget.cxx b/vcl/qt5/QtAccessibleWidget.cxx index 237b2db64735..84b398c006cc 100644 --- a/vcl/qt5/QtAccessibleWidget.cxx +++ b/vcl/qt5/QtAccessibleWidget.cxx @@ -727,6 +727,10 @@ void* QtAccessibleWidget::interface_cast(QAccessible::InterfaceType t) } if (t == QAccessible::TableInterface && accessibleProvidesInterface<XAccessibleTable>()) return static_cast<QAccessibleTableInterface*>(this); +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + if (t == QAccessible::SelectionInterface && accessibleProvidesInterface<XAccessibleSelection>()) + return static_cast<QAccessibleSelectionInterface*>(this); +#endif return nullptr; } @@ -1631,55 +1635,9 @@ bool QtAccessibleWidget::selectRow(int row) return xTableSelection->selectRow(row); } -int QtAccessibleWidget::selectedCellCount() const -{ - Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); - if (!xAcc.is()) - return 0; - - Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); - if (!xSelection.is()) - return 0; - - sal_Int64 nSelected = xSelection->getSelectedAccessibleChildCount(); - if (nSelected > std::numeric_limits<int>::max()) - { - SAL_WARN("vcl.qt", - "QtAccessibleWidget::selectedCellCount: Cell count exceeds maximum int value, " - "using max int."); - nSelected = std::numeric_limits<int>::max(); - } - return nSelected; -} - -QList<QAccessibleInterface*> QtAccessibleWidget::selectedCells() const -{ - Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); - if (!xAcc.is()) - return QList<QAccessibleInterface*>(); - - Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); - if (!xSelection.is()) - return QList<QAccessibleInterface*>(); +int QtAccessibleWidget::selectedCellCount() const { return selectedItemCount(); } - QList<QAccessibleInterface*> aSelectedCells; - sal_Int64 nSelected = xSelection->getSelectedAccessibleChildCount(); - if (nSelected > std::numeric_limits<int>::max()) - { - SAL_WARN("vcl.qt", - "QtAccessibleWidget::selectedCells: Cell count exceeds maximum int value, " - "using max int."); - nSelected = std::numeric_limits<int>::max(); - } - for (sal_Int64 i = 0; i < nSelected; i++) - { - Reference<XAccessible> xChild = xSelection->getSelectedAccessibleChild(i); - QAccessibleInterface* pInterface - = QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild)); - aSelectedCells.push_back(pInterface); - } - return aSelectedCells; -} +QList<QAccessibleInterface*> QtAccessibleWidget::selectedCells() const { return selectedItems(); } int QtAccessibleWidget::selectedColumnCount() const { @@ -1897,4 +1855,162 @@ QAccessibleInterface* QtAccessibleWidget::table() const return QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xTableAcc)); } +// QAccessibleSelectionInterface +int QtAccessibleWidget::selectedItemCount() const +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return 0; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return 0; + + sal_Int64 nSelected = xSelection->getSelectedAccessibleChildCount(); + if (nSelected > std::numeric_limits<int>::max()) + { + SAL_WARN("vcl.qt", + "QtAccessibleWidget::selectedItemCount: Cell count exceeds maximum int value, " + "using max int."); + nSelected = std::numeric_limits<int>::max(); + } + return nSelected; +} + +QList<QAccessibleInterface*> QtAccessibleWidget::selectedItems() const +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return QList<QAccessibleInterface*>(); + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return QList<QAccessibleInterface*>(); + + QList<QAccessibleInterface*> aSelectedItems; + sal_Int64 nSelected = xSelection->getSelectedAccessibleChildCount(); + if (nSelected > std::numeric_limits<int>::max()) + { + SAL_WARN("vcl.qt", + "QtAccessibleWidget::selectedItems: Cell count exceeds maximum int value, " + "using max int."); + nSelected = std::numeric_limits<int>::max(); + } + for (sal_Int64 i = 0; i < nSelected; i++) + { + Reference<XAccessible> xChild = xSelection->getSelectedAccessibleChild(i); + QAccessibleInterface* pInterface + = QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild)); + aSelectedItems.push_back(pInterface); + } + return aSelectedItems; +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) +QAccessibleInterface* QtAccessibleWidget::selectedItem(int nSelectionIndex) const +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return nullptr; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return nullptr; + + if (nSelectionIndex < 0 || nSelectionIndex >= xSelection->getSelectedAccessibleChildCount()) + { + SAL_WARN("vcl.qt", + "QtAccessibleWidget::selectedItem called with invalid index: " << nSelectionIndex); + return nullptr; + } + + Reference<XAccessible> xChild = xSelection->getSelectedAccessibleChild(nSelectionIndex); + if (!xChild) + return nullptr; + + return QAccessible::queryAccessibleInterface(QtAccessibleRegistry::getQObject(xChild)); +} + +bool QtAccessibleWidget::isSelected(QAccessibleInterface* pItem) const +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return false; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return false; + + int nChildIndex = indexOfChild(pItem); + if (nChildIndex < 0) + return false; + + return xSelection->isAccessibleChildSelected(nChildIndex); +} + +bool QtAccessibleWidget::select(QAccessibleInterface* pItem) +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return false; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return false; + + int nChildIndex = indexOfChild(pItem); + if (nChildIndex < 0) + return false; + + xSelection->selectAccessibleChild(nChildIndex); + return true; +} + +bool QtAccessibleWidget::unselect(QAccessibleInterface* pItem) +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return false; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return false; + + int nChildIndex = indexOfChild(pItem); + if (nChildIndex < 0) + return false; + + xSelection->deselectAccessibleChild(nChildIndex); + return true; +} + +bool QtAccessibleWidget::selectAll() +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return false; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return false; + + xSelection->selectAllAccessibleChildren(); + return true; +} + +bool QtAccessibleWidget::clear() +{ + Reference<XAccessibleContext> xAcc = getAccessibleContextImpl(); + if (!xAcc.is()) + return false; + + Reference<XAccessibleSelection> xSelection(xAcc, UNO_QUERY); + if (!xSelection.is()) + return false; + + xSelection->clearAccessibleSelection(); + return true; +} +#endif + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |