]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/accessibility/kitemlistviewaccessible.h
Update kconf update script version to 6
[dolphin.git] / src / kitemviews / accessibility / kitemlistviewaccessible.h
1 /*
2 * SPDX-FileCopyrightText: 2012 Amandeep Singh <aman.dedman@gmail.com>
3 * SPDX-FileCopyrightText: 2024 Felix Ernst <felixernst@kde.org>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #ifndef KITEMLISTVIEWACCESSIBLE_H
9 #define KITEMLISTVIEWACCESSIBLE_H
10
11 #include "dolphin_export.h"
12
13 #include <QAccessible>
14 #include <QAccessibleObject>
15 #include <QAccessibleWidget>
16 #include <QPointer>
17
18 class KItemListView;
19 class KItemListContainer;
20 class KItemListContainerAccessible;
21 class KItemListSelectionManager;
22
23 /**
24 * The main class for making the main view accessible.
25 *
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.
29 *
30 * @note For documentation of most of the methods within this class, check out the documentation of the methods which are being overriden here.
31 */
32 class DOLPHIN_EXPORT KItemListViewAccessible : public QAccessibleObject,
33 public QAccessibleSelectionInterface,
34 public QAccessibleTableInterface,
35 public QAccessibleActionInterface
36 {
37 public:
38 explicit KItemListViewAccessible(KItemListView *view, KItemListContainerAccessible *parent);
39 ~KItemListViewAccessible() override;
40
41 // QAccessibleObject
42 void *interface_cast(QAccessible::InterfaceType type) override;
43
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;
48
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;
54
55 // Table interface
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;
63
64 // Selection
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;
78
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;
89
90 // Action interface
91 QStringList actionNames() const override;
92 void doAction(const QString &actionName) override;
93 QStringList keyBindingsForAction(const QString &actionName) const override;
94
95 // Custom non-interface methods
96 KItemListView *view() const;
97
98 /**
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.
101 */
102 void setAccessibleFocusAndAnnounceAll();
103
104 /**
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.
108 *
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().
111 *
112 * If there are items in the view and the placeholderMessage is therefore not visible, the current item and location is announced instead.
113 */
114 void announceNewlyLoadedLocation(const QString &placeholderMessage);
115
116 /**
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.
119 *
120 * When m_shouldAnnounceLocation is true, the current location will be announced following the announcement of the current item.
121 *
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
123 * view.
124 */
125 void announceCurrentItem();
126
127 /**
128 * Toggling selection mode completely changes how the application controls, so it is absolutely necessary to communicate this change to users as soon as it
129 * happens.
130 */
131 void announceSelectionModeEnabled(bool enabled);
132
133 private:
134 /**
135 * @returns a KItemListDelegateAccessible representing the file or folder at the @index. Returns nullptr for invalid indices.
136 * If a KItemListDelegateAccessible for an index does not yet exist, it will be created.
137 * Index is 0-based.
138 */
139 inline QAccessibleInterface *accessibleDelegate(int index) const;
140
141 KItemListSelectionManager *selectionManager() const;
142
143 private Q_SLOTS:
144 /**
145 * Is run in response to announceCurrentItem(). If the current item exists, it is announced. Otherwise the view is announced.
146 * Also announces some general information about the current location if it has changed recently.
147 */
148 void slotAnnounceCurrentItemTimerTimeout();
149
150 private:
151 /** @see setPlaceholderMessage(). */
152 QString m_placeholderMessage;
153 bool m_selectionMode = false;
154
155 /**
156 * Is started by announceCurrentItem().
157 * If we announce the current item as soon as it changes, we would announce multiple items while loading a folder.
158 * This timer makes sure we only announce the singular currently focused item when things have settled down.
159 */
160 QTimer *m_announceCurrentItemTimer;
161
162 /**
163 * If we want announceCurrentItem() to always announce the current item, we must be aware if this is equal to the previous current item, because
164 * - if the accessibility focus moves to a new item, it is automatically announced, but
165 * - 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
166 * need to instead send change events for the accessible name and accessible description.
167 */
168 int m_lastAnnouncedIndex = -1;
169
170 /**
171 * Is set to true in response to announceDescriptionChange(). When true, the next time slotAnnounceCurrentItemTimerTimeout() is called the description is
172 * also announced. Then this bool is set to false.
173 */
174 bool m_shouldAnnounceLocation = true;
175
176 class AccessibleIdWrapper
177 {
178 public:
179 AccessibleIdWrapper();
180 bool isValid;
181 QAccessible::Id id;
182 };
183 /**
184 * A list that maps the indices of the children of this KItemListViewAccessible to the accessible ids of the matching KItemListDelegateAccessible objects.
185 * For example: m_accessibleDelegates.at(2) would be the AccessibleIdWrapper with an id which can be used to retrieve the QAccessibleObject that represents
186 * the third file in this view.
187 */
188 mutable QVector<AccessibleIdWrapper> m_accessibleDelegates;
189
190 KItemListContainerAccessible *m_parent;
191 };
192
193 #endif