2 * SPDX-FileCopyrightText: 2012 Amandeep Singh <aman.dedman@gmail.com>
3 * SPDX-FileCopyrightText: 2024 Felix Ernst <felixernst@kde.org>
5 * SPDX-License-Identifier: GPL-2.0-or-later
8 #ifndef KITEMLISTVIEWACCESSIBLE_H
9 #define KITEMLISTVIEWACCESSIBLE_H
11 #include "dolphin_export.h"
13 #include <QAccessible>
14 #include <QAccessibleObject>
15 #include <QAccessibleWidget>
19 class KItemListContainer
;
20 class KItemListContainerAccessible
;
21 class KItemListSelectionManager
;
24 * The main class for making the main view accessible.
26 * Such a class is necessary because the KItemListView is a mostly custom entity. This class provides a lot of the functionality to make it possible to
27 * interact with the view using accessibility tools. It implements various interfaces mostly to generally allow working with the view as a whole. However,
28 * actually interacting with singular items within the view is implemented in KItemListDelegateAccessible.
30 * @note For documentation of most of the methods within this class, check out the documentation of the methods which are being overriden here.
32 class DOLPHIN_EXPORT KItemListViewAccessible
: public QAccessibleObject
,
33 public QAccessibleSelectionInterface
,
34 public QAccessibleTableInterface
,
35 public QAccessibleActionInterface
38 explicit KItemListViewAccessible(KItemListView
*view
, KItemListContainerAccessible
*parent
);
39 ~KItemListViewAccessible() override
;
42 void *interface_cast(QAccessible::InterfaceType type
) override
;
44 QAccessible::Role
role() const override
;
45 QAccessible::State
state() const override
;
46 QString
text(QAccessible::Text t
) const override
;
47 QRect
rect() const override
;
49 QAccessibleInterface
*child(int index
) const override
;
50 int childCount() const override
;
51 int indexOfChild(const QAccessibleInterface
*) const override
;
52 QAccessibleInterface
*childAt(int x
, int y
) const override
;
53 QAccessibleInterface
*parent() const override
;
56 QAccessibleInterface
*cellAt(int row
, int column
) const override
;
57 QAccessibleInterface
*caption() const override
;
58 QAccessibleInterface
*summary() const override
;
59 QString
columnDescription(int column
) const override
;
60 QString
rowDescription(int row
) const override
;
61 int columnCount() const override
;
62 int rowCount() const override
;
65 int selectedCellCount() const override
;
66 int selectedColumnCount() const override
;
67 int selectedRowCount() const override
;
68 QList
<QAccessibleInterface
*> selectedCells() const override
;
69 QList
<int> selectedColumns() const override
;
70 QList
<int> selectedRows() const override
;
71 bool isColumnSelected(int column
) const override
;
72 bool isRowSelected(int row
) const override
;
73 bool selectRow(int row
) override
;
74 bool selectColumn(int column
) override
;
75 bool unselectRow(int row
) override
;
76 bool unselectColumn(int column
) override
;
77 void modelChange(QAccessibleTableModelChangeEvent
*) override
;
79 // Selection interface
80 /** Clear selection */
81 bool clear() override
;
82 bool isSelected(QAccessibleInterface
*childItem
) const override
;
83 bool select(QAccessibleInterface
*childItem
) override
;
84 bool selectAll() override
;
85 QAccessibleInterface
*selectedItem(int selectionIndex
) const override
;
86 int selectedItemCount() const override
;
87 QList
<QAccessibleInterface
*> selectedItems() const override
;
88 bool unselect(QAccessibleInterface
*childItem
) override
;
91 QStringList
actionNames() const override
;
92 void doAction(const QString
&actionName
) override
;
93 QStringList
keyBindingsForAction(const QString
&actionName
) const override
;
95 // Custom non-interface methods
96 KItemListView
*view() const;
99 * Called by KItemListContainer when it passes on focus to the view. Accessible focus is then meant to go towards this accessible interface and a detailed
100 * announcement of the current view state (current item and overall location state) should be triggered.
102 void setAccessibleFocusAndAnnounceAll();
105 * Called multiple times while a new location is loading. A timer is restarted, and if this method has not been called for a split second, the newly loaded
106 * location is finally announced.
107 * Either the @p placeholderMessage is announced when there are no items in the view (yet), or the current item is announced together with the view state.
109 * @param placeholderMessage The message that should be announced when no items are visible (yet). This message is mostly identical to
110 * DolphinView::m_placeholderLabel in both content and purpose. @see DolphinView::updatePlaceHolderLabel().
112 * If there are items in the view and the placeholderMessage is therefore not visible, the current item and location is announced instead.
114 void announceNewlyLoadedLocation(const QString
&placeholderMessage
);
117 * Starts a timer that will trigger an announcement of the current item. The timer makes sure that quick changes to the current item will only lead to a
118 * singular announcement. This way when a new folder is loaded we only trigger a single announcement even if the items quickly change.
120 * When m_shouldAnnounceLocation is true, the current location will be announced following the announcement of the current item.
122 * If the current item is invalid, only the current location is announced, which has the responsibility of then telling why there is no valid item in the
125 void announceCurrentItem();
129 * @returns a KItemListDelegateAccessible representing the file or folder at the @index. Returns nullptr for invalid indices.
130 * If a KItemListDelegateAccessible for an index does not yet exist, it will be created.
133 inline QAccessibleInterface
*accessibleDelegate(int index
) const;
135 KItemListSelectionManager
*selectionManager() const;
139 * Is run in response to announceCurrentItem(). If the current item exists, it is announced. Otherwise the view is announced.
140 * Also announces some general information about the current location if it has changed recently.
142 void slotAnnounceCurrentItemTimerTimeout();
145 /** @see setPlaceholderMessage(). */
146 QString m_placeholderMessage
;
149 * Is started by announceCurrentItem().
150 * If we announce the current item as soon as it changes, we would announce multiple items while loading a folder.
151 * This timer makes sure we only announce the singular currently focused item when things have settled down.
153 QTimer
*m_announceCurrentItemTimer
;
156 * If we want announceCurrentItem() to always announce the current item, we must be aware if this is equal to the previous current item, because
157 * - if the accessibility focus moves to a new item, it is automatically announced, but
158 * - if the focus is still on the item at the same index, the focus does not technically move to a new item even if the file at that index changed, so we
159 * need to instead send change events for the accessible name and accessible description.
161 int m_lastAnnouncedIndex
= -1;
164 * Is set to true in response to announceDescriptionChange(). When true, the next time slotAnnounceCurrentItemTimerTimeout() is called the description is
165 * also announced. Then this bool is set to false.
167 bool m_shouldAnnounceLocation
= true;
169 class AccessibleIdWrapper
172 AccessibleIdWrapper();
177 * A list that maps the indices of the children of this KItemListViewAccessible to the accessible ids of the matching KItemListDelegateAccessible objects.
178 * For example: m_accessibleDelegates.at(2) would be the AccessibleIdWrapper with an id which can be used to retrieve the QAccessibleObject that represents
179 * the third file in this view.
181 mutable QVector
<AccessibleIdWrapper
> m_accessibleDelegates
;
183 KItemListContainerAccessible
*m_parent
;