VirtualBox

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

Last change on this file since 82781 was 76606, checked in by vboxsync, 5 years ago

FE/Qt: Cleaning out old precompiled header experiment.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use