VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/extensions/QITableView.cpp

Last change on this file was 103987, checked in by vboxsync, 2 months ago

FE/Qt: bugref:10624. Adding RT_FINAL to virtual functions whereever appropriate.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.5 KB
Line 
1/* $Id: QITableView.cpp 103987 2024-03-21 12:33:33Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - Qt extensions: QITableView class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QAccessibleWidget>
30
31/* GUI includes: */
32#include "QIStyledItemDelegate.h"
33#include "QITableView.h"
34
35/* Other VBox includes: */
36#include "iprt/assert.h"
37
38
39/** QAccessibleObject extension used as an accessibility interface for QITableViewCell. */
40class QIAccessibilityInterfaceForQITableViewCell : public QAccessibleObject
41{
42public:
43
44 /** Returns an accessibility interface for passed @a strClassname and @a pObject. */
45 static QAccessibleInterface *pFactory(const QString &strClassname, QObject *pObject)
46 {
47 /* Creating QITableViewCell accessibility interface: */
48 if (pObject && strClassname == QLatin1String("QITableViewCell"))
49 return new QIAccessibilityInterfaceForQITableViewCell(pObject);
50
51 /* Null by default: */
52 return 0;
53 }
54
55 /** Constructs an accessibility interface passing @a pObject to the base-class. */
56 QIAccessibilityInterfaceForQITableViewCell(QObject *pObject)
57 : QAccessibleObject(pObject)
58 {}
59
60 /** Returns the parent. */
61 virtual QAccessibleInterface *parent() const RT_OVERRIDE RT_FINAL;
62
63 /** Returns the number of children. */
64 virtual int childCount() const RT_OVERRIDE { return 0; }
65 /** Returns the child with the passed @a iIndex. */
66 virtual QAccessibleInterface *child(int /* iIndex */) const RT_OVERRIDE { return 0; }
67 /** Returns the index of the passed @a pChild. */
68 virtual int indexOfChild(const QAccessibleInterface * /* pChild */) const RT_OVERRIDE { return -1; }
69
70 /** Returns the rect. */
71 virtual QRect rect() const RT_OVERRIDE RT_FINAL;
72 /** Returns a text for the passed @a enmTextRole. */
73 virtual QString text(QAccessible::Text enmTextRole) const RT_OVERRIDE RT_FINAL;
74
75 /** Returns the role. */
76 virtual QAccessible::Role role() const RT_OVERRIDE RT_FINAL;
77 /** Returns the state. */
78 virtual QAccessible::State state() const RT_OVERRIDE RT_FINAL;
79
80private:
81
82 /** Returns corresponding QITableViewCell. */
83 QITableViewCell *cell() const { return qobject_cast<QITableViewCell*>(object()); }
84};
85
86
87/** QAccessibleObject extension used as an accessibility interface for QITableViewRow. */
88class QIAccessibilityInterfaceForQITableViewRow : public QAccessibleObject
89{
90public:
91
92 /** Returns an accessibility interface for passed @a strClassname and @a pObject. */
93 static QAccessibleInterface *pFactory(const QString &strClassname, QObject *pObject)
94 {
95 /* Creating QITableViewRow accessibility interface: */
96 if (pObject && strClassname == QLatin1String("QITableViewRow"))
97 return new QIAccessibilityInterfaceForQITableViewRow(pObject);
98
99 /* Null by default: */
100 return 0;
101 }
102
103 /** Constructs an accessibility interface passing @a pObject to the base-class. */
104 QIAccessibilityInterfaceForQITableViewRow(QObject *pObject)
105 : QAccessibleObject(pObject)
106 {}
107
108 /** Returns the parent. */
109 virtual QAccessibleInterface *parent() const RT_OVERRIDE RT_FINAL;
110
111 /** Returns the number of children. */
112 virtual int childCount() const RT_OVERRIDE RT_FINAL;
113 /** Returns the child with the passed @a iIndex. */
114 virtual QAccessibleInterface *child(int iIndex) const RT_OVERRIDE RT_FINAL;
115 /** Returns the index of the passed @a pChild. */
116 virtual int indexOfChild(const QAccessibleInterface *pChild) const RT_OVERRIDE RT_FINAL;
117
118 /** Returns the rect. */
119 virtual QRect rect() const RT_OVERRIDE RT_FINAL;
120 /** Returns a text for the passed @a enmTextRole. */
121 virtual QString text(QAccessible::Text enmTextRole) const RT_OVERRIDE RT_FINAL;
122
123 /** Returns the role. */
124 virtual QAccessible::Role role() const RT_OVERRIDE RT_FINAL;
125 /** Returns the state. */
126 virtual QAccessible::State state() const RT_OVERRIDE RT_FINAL;
127
128private:
129
130 /** Returns corresponding QITableViewRow. */
131 QITableViewRow *row() const { return qobject_cast<QITableViewRow*>(object()); }
132};
133
134
135/** QAccessibleWidget extension used as an accessibility interface for QITableView. */
136class QIAccessibilityInterfaceForQITableView : public QAccessibleWidget
137{
138public:
139
140 /** Returns an accessibility interface for passed @a strClassname and @a pObject. */
141 static QAccessibleInterface *pFactory(const QString &strClassname, QObject *pObject)
142 {
143 /* Creating QITableView accessibility interface: */
144 if (pObject && strClassname == QLatin1String("QITableView"))
145 return new QIAccessibilityInterfaceForQITableView(qobject_cast<QWidget*>(pObject));
146
147 /* Null by default: */
148 return 0;
149 }
150
151 /** Constructs an accessibility interface passing @a pWidget to the base-class. */
152 QIAccessibilityInterfaceForQITableView(QWidget *pWidget)
153 : QAccessibleWidget(pWidget, QAccessible::List)
154 {}
155
156 /** Returns the number of children. */
157 virtual int childCount() const RT_OVERRIDE RT_FINAL;
158 /** Returns the child with the passed @a iIndex. */
159 virtual QAccessibleInterface *child(int iIndex) const RT_OVERRIDE RT_FINAL;
160 /** Returns the index of the passed @a pChild. */
161 virtual int indexOfChild(const QAccessibleInterface *pChild) const RT_OVERRIDE RT_FINAL;
162
163 /** Returns a text for the passed @a enmTextRole. */
164 virtual QString text(QAccessible::Text enmTextRole) const RT_OVERRIDE RT_FINAL;
165
166private:
167
168 /** Returns corresponding QITableView. */
169 QITableView *table() const { return qobject_cast<QITableView*>(widget()); }
170};
171
172
173/*********************************************************************************************************************************
174* Class QIAccessibilityInterfaceForQITableViewCell implementation. *
175*********************************************************************************************************************************/
176
177QAccessibleInterface *QIAccessibilityInterfaceForQITableViewCell::parent() const
178{
179 /* Make sure cell still alive: */
180 AssertPtrReturn(cell(), 0);
181
182 /* Return the parent: */
183 return QAccessible::queryAccessibleInterface(cell()->row());
184}
185
186QRect QIAccessibilityInterfaceForQITableViewCell::rect() const
187{
188 /* Make sure cell still alive: */
189 AssertPtrReturn(cell(), QRect());
190 AssertPtrReturn(cell()->row(), QRect());
191 AssertPtrReturn(cell()->row()->table(), QRect());
192
193 /* Calculate local item coordinates: */
194 const int iIndexInParent = parent()->indexOfChild(this);
195 const int iParentIndexInParent = parent()->parent()->indexOfChild(parent());
196 const int iX = cell()->row()->table()->columnViewportPosition(iIndexInParent);
197 const int iY = cell()->row()->table()->rowViewportPosition(iParentIndexInParent);
198 const int iWidth = cell()->row()->table()->columnWidth(iIndexInParent);
199 const int iHeight = cell()->row()->table()->rowHeight(iParentIndexInParent);
200
201 /* Map local item coordinates to global: */
202 const QPoint itemPosInScreen = cell()->row()->table()->viewport()->mapToGlobal(QPoint(iX, iY));
203
204 /* Return item rectangle: */
205 return QRect(itemPosInScreen, QSize(iWidth, iHeight));
206}
207
208QString QIAccessibilityInterfaceForQITableViewCell::text(QAccessible::Text enmTextRole) const
209{
210 /* Make sure cell still alive: */
211 AssertPtrReturn(cell(), QString());
212
213 /* Return a text for the passed enmTextRole: */
214 switch (enmTextRole)
215 {
216 case QAccessible::Name: return cell()->text();
217 default: break;
218 }
219
220 /* Null-string by default: */
221 return QString();
222}
223
224QAccessible::Role QIAccessibilityInterfaceForQITableViewCell::role() const
225{
226 /* Cell by default: */
227 return QAccessible::Cell;
228}
229
230QAccessible::State QIAccessibilityInterfaceForQITableViewCell::state() const
231{
232 /* Make sure cell still alive: */
233 AssertPtrReturn(cell(), QAccessible::State());
234
235 /* Empty state by default: */
236 return QAccessible::State();
237}
238
239
240/*********************************************************************************************************************************
241* Class QIAccessibilityInterfaceForQITableViewRow implementation. *
242*********************************************************************************************************************************/
243
244QAccessibleInterface *QIAccessibilityInterfaceForQITableViewRow::parent() const
245{
246 /* Make sure row still alive: */
247 AssertPtrReturn(row(), 0);
248
249 /* Return the parent: */
250 return QAccessible::queryAccessibleInterface(row()->table());
251}
252
253int QIAccessibilityInterfaceForQITableViewRow::childCount() const
254{
255 /* Make sure row still alive: */
256 AssertPtrReturn(row(), 0);
257
258 /* Return the number of children: */
259 return row()->childCount();
260}
261
262QAccessibleInterface *QIAccessibilityInterfaceForQITableViewRow::child(int iIndex) const /* override */
263{
264 /* Make sure row still alive: */
265 AssertPtrReturn(row(), 0);
266 /* Make sure index is valid: */
267 AssertReturn(iIndex >= 0 && iIndex < childCount(), 0);
268
269 /* Return the child with the passed iIndex: */
270 return QAccessible::queryAccessibleInterface(row()->childItem(iIndex));
271}
272
273int QIAccessibilityInterfaceForQITableViewRow::indexOfChild(const QAccessibleInterface *pChild) const /* override */
274{
275 /* Search for corresponding child: */
276 for (int i = 0; i < childCount(); ++i)
277 if (child(i) == pChild)
278 return i;
279
280 /* -1 by default: */
281 return -1;
282}
283
284QRect QIAccessibilityInterfaceForQITableViewRow::rect() const
285{
286 /* Make sure row still alive: */
287 AssertPtrReturn(row(), QRect());
288 AssertPtrReturn(row()->table(), QRect());
289
290 /* Calculate local item coordinates: */
291 const int iIndexInParent = parent()->indexOfChild(this);
292 const int iX = row()->table()->columnViewportPosition(0);
293 const int iY = row()->table()->rowViewportPosition(iIndexInParent);
294 int iWidth = 0;
295 int iHeight = 0;
296 for (int i = 0; i < childCount(); ++i)
297 iWidth += row()->table()->columnWidth(i);
298 iHeight += row()->table()->rowHeight(iIndexInParent);
299
300 /* Map local item coordinates to global: */
301 const QPoint itemPosInScreen = row()->table()->viewport()->mapToGlobal(QPoint(iX, iY));
302
303 /* Return item rectangle: */
304 return QRect(itemPosInScreen, QSize(iWidth, iHeight));
305}
306
307QString QIAccessibilityInterfaceForQITableViewRow::text(QAccessible::Text enmTextRole) const
308{
309 /* Make sure row still alive: */
310 AssertPtrReturn(row(), QString());
311
312 /* Return a text for the passed enmTextRole: */
313 switch (enmTextRole)
314 {
315 case QAccessible::Name: return childCount() > 0 && child(0) ? child(0)->text(enmTextRole) : QString();
316 default: break;
317 }
318
319 /* Null-string by default: */
320 return QString();
321}
322
323QAccessible::Role QIAccessibilityInterfaceForQITableViewRow::role() const
324{
325 /* Row by default: */
326 return QAccessible::Row;
327}
328
329QAccessible::State QIAccessibilityInterfaceForQITableViewRow::state() const
330{
331 /* Make sure row still alive: */
332 AssertPtrReturn(row(), QAccessible::State());
333
334 /* Empty state by default: */
335 return QAccessible::State();
336}
337
338
339/*********************************************************************************************************************************
340* Class QIAccessibilityInterfaceForQITableView implementation. *
341*********************************************************************************************************************************/
342
343int QIAccessibilityInterfaceForQITableView::childCount() const
344{
345 /* Make sure table still alive: */
346 AssertPtrReturn(table(), 0);
347
348 /* Return the number of children: */
349 return table()->childCount();
350}
351
352QAccessibleInterface *QIAccessibilityInterfaceForQITableView::child(int iIndex) const
353{
354 /* Make sure table still alive: */
355 AssertPtrReturn(table(), 0);
356 /* Make sure index is valid: */
357 AssertReturn(iIndex >= 0, 0);
358 if (iIndex >= childCount())
359 {
360 // WORKAROUND:
361 // Normally I would assert here, but Qt5 accessibility code has
362 // a hard-coded architecture for a table-views which we do not like
363 // but have to live with and this architecture enumerates cells
364 // including header column and row, so Qt5 can try to address
365 // our interface with index which surely out of bounds by our laws.
366 // So let's assume that's exactly such case and try to enumerate
367 // table cells including header column and row.
368 // printf("Invalid index: %d\n", iIndex);
369
370 // Split delimeter is overall column count, including vertical header:
371 const int iColumnCount = table()->model()->columnCount() + 1 /* v_header */;
372 // Real index is zero-based, incoming is 1-based:
373 const int iRealIndex = iIndex - 1;
374 // Real row index, excluding horizontal header:
375 const int iRealRowIndex = iRealIndex / iColumnCount - 1 /* h_header */;
376 // printf("Actual row index: %d\n", iRealRowIndex);
377
378 // Return what we found:
379 return iRealRowIndex >= 0 && iRealRowIndex < childCount() ?
380 QAccessible::queryAccessibleInterface(table()->childItem(iRealRowIndex)) : 0;
381 }
382
383 /* Return the child with the passed iIndex: */
384 return QAccessible::queryAccessibleInterface(table()->childItem(iIndex));
385}
386
387int QIAccessibilityInterfaceForQITableView::indexOfChild(const QAccessibleInterface *pChild) const
388{
389 /* Search for corresponding child: */
390 for (int i = 0; i < childCount(); ++i)
391 if (child(i) == pChild)
392 return i;
393
394 /* -1 by default: */
395 return -1;
396}
397
398QString QIAccessibilityInterfaceForQITableView::text(QAccessible::Text /* enmTextRole */) const
399{
400 /* Make sure table still alive: */
401 AssertPtrReturn(table(), QString());
402
403 /* Return table whats-this: */
404 return table()->whatsThis();
405}
406
407
408/*********************************************************************************************************************************
409* Class QITableView implementation. *
410*********************************************************************************************************************************/
411
412QITableView::QITableView(QWidget *pParent)
413 : QTableView(pParent)
414{
415 /* Prepare: */
416 prepare();
417}
418
419QITableView::~QITableView()
420{
421 /* Cleanup: */
422 cleanup();
423}
424
425void QITableView::makeSureEditorDataCommitted()
426{
427 /* Do we have current editor at all? */
428 QObject *pEditorObject = m_editors.value(currentIndex());
429 if (pEditorObject && pEditorObject->isWidgetType())
430 {
431 /* Cast the editor to widget type: */
432 QWidget *pEditor = qobject_cast<QWidget*>(pEditorObject);
433 AssertPtrReturnVoid(pEditor);
434 {
435 /* Commit the editor data and closes it: */
436 commitData(pEditor);
437 closeEditor(pEditor, QAbstractItemDelegate::SubmitModelCache);
438 }
439 }
440}
441
442void QITableView::sltEditorCreated(QWidget *pEditor, const QModelIndex &index)
443{
444 /* Connect created editor to the table and store it: */
445 connect(pEditor, &QWidget::destroyed, this, &QITableView::sltEditorDestroyed);
446 m_editors[index] = pEditor;
447}
448
449void QITableView::sltEditorDestroyed(QObject *pEditor)
450{
451 /* Clear destroyed editor from the table: */
452 const QModelIndex index = m_editors.key(pEditor);
453 AssertReturnVoid(index.isValid());
454 m_editors.remove(index);
455}
456
457void QITableView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
458{
459 /* Notify listeners about index changed: */
460 emit sigCurrentChanged(current, previous);
461 /* Call to base-class: */
462 QTableView::currentChanged(current, previous);
463}
464
465void QITableView::prepare()
466{
467 /* Install QITableViewCell accessibility interface factory: */
468 QAccessible::installFactory(QIAccessibilityInterfaceForQITableViewCell::pFactory);
469 /* Install QITableViewRow accessibility interface factory: */
470 QAccessible::installFactory(QIAccessibilityInterfaceForQITableViewRow::pFactory);
471 /* Install QITableView accessibility interface factory: */
472 QAccessible::installFactory(QIAccessibilityInterfaceForQITableView::pFactory);
473
474 /* Delete old delegate: */
475 delete itemDelegate();
476 /* Create new delegate: */
477 QIStyledItemDelegate *pStyledItemDelegate = new QIStyledItemDelegate(this);
478 AssertPtrReturnVoid(pStyledItemDelegate);
479 {
480 /* Assign newly created delegate to the table: */
481 setItemDelegate(pStyledItemDelegate);
482 /* Connect newly created delegate to the table: */
483 connect(pStyledItemDelegate, &QIStyledItemDelegate::sigEditorCreated,
484 this, &QITableView::sltEditorCreated);
485 }
486}
487
488void QITableView::cleanup()
489{
490 /* Disconnect all the editors prematurelly: */
491 foreach (QObject *pEditor, m_editors.values())
492 disconnect(pEditor, 0, this, 0);
493}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use