vcl/inc/qt5/QtAccessibleWidget.hxx |   19 +++
 vcl/qt5/QtAccessibleWidget.cxx     |  212 ++++++++++++++++++++++++++++---------
 2 files changed, 183 insertions(+), 48 deletions(-)

New commits:
commit 84183c84d86456e3c311b35150b1fc9b63a85561
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Sat Apr 22 09:22:38 2023 +0300
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Sat Apr 22 11:33:32 2023 +0200

    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.wegh...@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.wegh...@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.wegh...@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.wegh...@posteo.de>

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: */

Reply via email to