File indexing completed on 2024-04-28 05:45:09

0001 /*
0002  * SPDX-FileCopyrightText: 2012 Amandeep Singh <aman.dedman@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef QT_NO_ACCESSIBILITY
0008 #include "kitemlistviewaccessible.h"
0009 
0010 #include "kitemlistcontainer.h"
0011 #include "kitemlistcontroller.h"
0012 #include "kitemlistselectionmanager.h"
0013 #include "kitemlistview.h"
0014 #include "private/kitemlistviewlayouter.h"
0015 
0016 #include <QGraphicsScene>
0017 #include <QGraphicsView>
0018 
0019 KItemListView *KItemListViewAccessible::view() const
0020 {
0021     return qobject_cast<KItemListView *>(object());
0022 }
0023 
0024 KItemListViewAccessible::KItemListViewAccessible(KItemListView *view_, KItemListContainerAccessible *parent)
0025     : QAccessibleObject(view_)
0026     , m_parent(parent)
0027 {
0028     Q_ASSERT(view());
0029     Q_CHECK_PTR(parent);
0030     m_cells.resize(childCount());
0031 }
0032 
0033 KItemListViewAccessible::~KItemListViewAccessible()
0034 {
0035     for (AccessibleIdWrapper idWrapper : std::as_const(m_cells)) {
0036         if (idWrapper.isValid) {
0037             QAccessible::deleteAccessibleInterface(idWrapper.id);
0038         }
0039     }
0040 }
0041 
0042 void *KItemListViewAccessible::interface_cast(QAccessible::InterfaceType type)
0043 {
0044     if (type == QAccessible::TableInterface) {
0045         return static_cast<QAccessibleTableInterface *>(this);
0046     }
0047     return nullptr;
0048 }
0049 
0050 void KItemListViewAccessible::modelReset()
0051 {
0052 }
0053 
0054 QAccessibleInterface *KItemListViewAccessible::cell(int index) const
0055 {
0056     if (index < 0 || index >= view()->model()->count()) {
0057         return nullptr;
0058     }
0059 
0060     if (m_cells.size() <= index) {
0061         m_cells.resize(childCount());
0062     }
0063     Q_ASSERT(index < m_cells.size());
0064 
0065     AccessibleIdWrapper idWrapper = m_cells.at(index);
0066     if (!idWrapper.isValid) {
0067         idWrapper.id = QAccessible::registerAccessibleInterface(new KItemListAccessibleCell(view(), index));
0068         idWrapper.isValid = true;
0069         m_cells.insert(index, idWrapper);
0070     }
0071     return QAccessible::accessibleInterface(idWrapper.id);
0072 }
0073 
0074 QAccessibleInterface *KItemListViewAccessible::cellAt(int row, int column) const
0075 {
0076     return cell(columnCount() * row + column);
0077 }
0078 
0079 QAccessibleInterface *KItemListViewAccessible::caption() const
0080 {
0081     return nullptr;
0082 }
0083 
0084 QString KItemListViewAccessible::columnDescription(int) const
0085 {
0086     return QString();
0087 }
0088 
0089 int KItemListViewAccessible::columnCount() const
0090 {
0091     return view()->m_layouter->columnCount();
0092 }
0093 
0094 int KItemListViewAccessible::rowCount() const
0095 {
0096     if (columnCount() <= 0) {
0097         return 0;
0098     }
0099 
0100     int itemCount = view()->model()->count();
0101     int rowCount = itemCount / columnCount();
0102 
0103     if (rowCount <= 0) {
0104         return 0;
0105     }
0106 
0107     if (itemCount % columnCount()) {
0108         ++rowCount;
0109     }
0110     return rowCount;
0111 }
0112 
0113 int KItemListViewAccessible::selectedCellCount() const
0114 {
0115     return view()->controller()->selectionManager()->selectedItems().count();
0116 }
0117 
0118 int KItemListViewAccessible::selectedColumnCount() const
0119 {
0120     return 0;
0121 }
0122 
0123 int KItemListViewAccessible::selectedRowCount() const
0124 {
0125     return 0;
0126 }
0127 
0128 QString KItemListViewAccessible::rowDescription(int) const
0129 {
0130     return QString();
0131 }
0132 
0133 QList<QAccessibleInterface *> KItemListViewAccessible::selectedCells() const
0134 {
0135     QList<QAccessibleInterface *> cells;
0136     const auto items = view()->controller()->selectionManager()->selectedItems();
0137     cells.reserve(items.count());
0138     for (int index : items) {
0139         cells.append(cell(index));
0140     }
0141     return cells;
0142 }
0143 
0144 QList<int> KItemListViewAccessible::selectedColumns() const
0145 {
0146     return QList<int>();
0147 }
0148 
0149 QList<int> KItemListViewAccessible::selectedRows() const
0150 {
0151     return QList<int>();
0152 }
0153 
0154 QAccessibleInterface *KItemListViewAccessible::summary() const
0155 {
0156     return nullptr;
0157 }
0158 
0159 bool KItemListViewAccessible::isColumnSelected(int) const
0160 {
0161     return false;
0162 }
0163 
0164 bool KItemListViewAccessible::isRowSelected(int) const
0165 {
0166     return false;
0167 }
0168 
0169 bool KItemListViewAccessible::selectRow(int)
0170 {
0171     return true;
0172 }
0173 
0174 bool KItemListViewAccessible::selectColumn(int)
0175 {
0176     return true;
0177 }
0178 
0179 bool KItemListViewAccessible::unselectRow(int)
0180 {
0181     return true;
0182 }
0183 
0184 bool KItemListViewAccessible::unselectColumn(int)
0185 {
0186     return true;
0187 }
0188 
0189 void KItemListViewAccessible::modelChange(QAccessibleTableModelChangeEvent * /*event*/)
0190 {
0191 }
0192 
0193 QAccessible::Role KItemListViewAccessible::role() const
0194 {
0195     return QAccessible::Table;
0196 }
0197 
0198 QAccessible::State KItemListViewAccessible::state() const
0199 {
0200     QAccessible::State s;
0201     return s;
0202 }
0203 
0204 QAccessibleInterface *KItemListViewAccessible::childAt(int x, int y) const
0205 {
0206     const QPointF point = QPointF(x, y);
0207     const std::optional<int> itemIndex = view()->itemAt(view()->mapFromScene(point));
0208     return child(itemIndex.value_or(-1));
0209 }
0210 
0211 QAccessibleInterface *KItemListViewAccessible::parent() const
0212 {
0213     return m_parent;
0214 }
0215 
0216 int KItemListViewAccessible::childCount() const
0217 {
0218     return view()->model()->count();
0219 }
0220 
0221 int KItemListViewAccessible::indexOfChild(const QAccessibleInterface *interface) const
0222 {
0223     const KItemListAccessibleCell *widget = static_cast<const KItemListAccessibleCell *>(interface);
0224     return widget->index();
0225 }
0226 
0227 QString KItemListViewAccessible::text(QAccessible::Text) const
0228 {
0229     return QString();
0230 }
0231 
0232 QRect KItemListViewAccessible::rect() const
0233 {
0234     if (!view()->isVisible()) {
0235         return QRect();
0236     }
0237 
0238     const QGraphicsScene *scene = view()->scene();
0239     if (scene) {
0240         const QPoint origin = scene->views().at(0)->mapToGlobal(QPoint(0, 0));
0241         const QRect viewRect = view()->geometry().toRect();
0242         return viewRect.translated(origin);
0243     } else {
0244         return QRect();
0245     }
0246 }
0247 
0248 QAccessibleInterface *KItemListViewAccessible::child(int index) const
0249 {
0250     if (index >= 0 && index < childCount()) {
0251         return cell(index);
0252     }
0253     return nullptr;
0254 }
0255 
0256 KItemListViewAccessible::AccessibleIdWrapper::AccessibleIdWrapper()
0257     : isValid(false)
0258     , id(0)
0259 {
0260 }
0261 
0262 // Table Cell
0263 
0264 KItemListAccessibleCell::KItemListAccessibleCell(KItemListView *view, int index)
0265     : m_view(view)
0266     , m_index(index)
0267 {
0268     Q_ASSERT(index >= 0 && index < view->model()->count());
0269 }
0270 
0271 void *KItemListAccessibleCell::interface_cast(QAccessible::InterfaceType type)
0272 {
0273     if (type == QAccessible::TableCellInterface) {
0274         return static_cast<QAccessibleTableCellInterface *>(this);
0275     }
0276     return nullptr;
0277 }
0278 
0279 int KItemListAccessibleCell::columnExtent() const
0280 {
0281     return 1;
0282 }
0283 
0284 int KItemListAccessibleCell::rowExtent() const
0285 {
0286     return 1;
0287 }
0288 
0289 QList<QAccessibleInterface *> KItemListAccessibleCell::rowHeaderCells() const
0290 {
0291     return QList<QAccessibleInterface *>();
0292 }
0293 
0294 QList<QAccessibleInterface *> KItemListAccessibleCell::columnHeaderCells() const
0295 {
0296     return QList<QAccessibleInterface *>();
0297 }
0298 
0299 int KItemListAccessibleCell::columnIndex() const
0300 {
0301     return m_view->m_layouter->itemColumn(m_index);
0302 }
0303 
0304 int KItemListAccessibleCell::rowIndex() const
0305 {
0306     return m_view->m_layouter->itemRow(m_index);
0307 }
0308 
0309 bool KItemListAccessibleCell::isSelected() const
0310 {
0311     return m_view->controller()->selectionManager()->isSelected(m_index);
0312 }
0313 
0314 QAccessibleInterface *KItemListAccessibleCell::table() const
0315 {
0316     return QAccessible::queryAccessibleInterface(m_view);
0317 }
0318 
0319 QAccessible::Role KItemListAccessibleCell::role() const
0320 {
0321     return QAccessible::Cell;
0322 }
0323 
0324 QAccessible::State KItemListAccessibleCell::state() const
0325 {
0326     QAccessible::State state;
0327 
0328     state.selectable = true;
0329     if (isSelected()) {
0330         state.selected = true;
0331     }
0332 
0333     state.focusable = true;
0334     if (m_view->controller()->selectionManager()->currentItem() == m_index) {
0335         state.focused = true;
0336     }
0337 
0338     if (m_view->controller()->selectionBehavior() == KItemListController::MultiSelection) {
0339         state.multiSelectable = true;
0340     }
0341 
0342     if (m_view->model()->isExpandable(m_index)) {
0343         if (m_view->model()->isExpanded(m_index)) {
0344             state.expanded = true;
0345         } else {
0346             state.collapsed = true;
0347         }
0348     }
0349 
0350     return state;
0351 }
0352 
0353 bool KItemListAccessibleCell::isExpandable() const
0354 {
0355     return m_view->model()->isExpandable(m_index);
0356 }
0357 
0358 QRect KItemListAccessibleCell::rect() const
0359 {
0360     QRect rect = m_view->itemRect(m_index).toRect();
0361 
0362     if (rect.isNull()) {
0363         return QRect();
0364     }
0365 
0366     rect.translate(m_view->mapToScene(QPointF(0.0, 0.0)).toPoint());
0367     rect.translate(m_view->scene()->views()[0]->mapToGlobal(QPoint(0, 0)));
0368     return rect;
0369 }
0370 
0371 QString KItemListAccessibleCell::text(QAccessible::Text t) const
0372 {
0373     switch (t) {
0374     case QAccessible::Name: {
0375         const QHash<QByteArray, QVariant> data = m_view->model()->data(m_index);
0376         return data["text"].toString();
0377     }
0378 
0379     default:
0380         break;
0381     }
0382 
0383     return QString();
0384 }
0385 
0386 void KItemListAccessibleCell::setText(QAccessible::Text, const QString &)
0387 {
0388 }
0389 
0390 QAccessibleInterface *KItemListAccessibleCell::child(int) const
0391 {
0392     return nullptr;
0393 }
0394 
0395 bool KItemListAccessibleCell::isValid() const
0396 {
0397     return m_view && (m_index >= 0) && (m_index < m_view->model()->count());
0398 }
0399 
0400 QAccessibleInterface *KItemListAccessibleCell::childAt(int, int) const
0401 {
0402     return nullptr;
0403 }
0404 
0405 int KItemListAccessibleCell::childCount() const
0406 {
0407     return 0;
0408 }
0409 
0410 int KItemListAccessibleCell::indexOfChild(const QAccessibleInterface *child) const
0411 {
0412     Q_UNUSED(child)
0413     return -1;
0414 }
0415 
0416 QAccessibleInterface *KItemListAccessibleCell::parent() const
0417 {
0418     return QAccessible::queryAccessibleInterface(m_view);
0419 }
0420 
0421 int KItemListAccessibleCell::index() const
0422 {
0423     return m_index;
0424 }
0425 
0426 QObject *KItemListAccessibleCell::object() const
0427 {
0428     return nullptr;
0429 }
0430 
0431 // Container Interface
0432 KItemListContainerAccessible::KItemListContainerAccessible(KItemListContainer *container)
0433     : QAccessibleWidget(container)
0434 {
0435 }
0436 
0437 KItemListContainerAccessible::~KItemListContainerAccessible()
0438 {
0439 }
0440 
0441 int KItemListContainerAccessible::childCount() const
0442 {
0443     return 1;
0444 }
0445 
0446 int KItemListContainerAccessible::indexOfChild(const QAccessibleInterface *child) const
0447 {
0448     if (child->object() == container()->controller()->view()) {
0449         return 0;
0450     }
0451     return -1;
0452 }
0453 
0454 QAccessibleInterface *KItemListContainerAccessible::child(int index) const
0455 {
0456     if (index == 0) {
0457         return QAccessible::queryAccessibleInterface(container()->controller()->view());
0458     }
0459     return nullptr;
0460 }
0461 
0462 const KItemListContainer *KItemListContainerAccessible::container() const
0463 {
0464     return qobject_cast<KItemListContainer *>(object());
0465 }
0466 
0467 #endif // QT_NO_ACCESSIBILITY