Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickheaderview.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtQuickTemplates2/private/qquickheaderview_p_p.h>
6#include <algorithm>
7
8/*!
9 \qmltype HorizontalHeaderView
10 \inqmlmodule QtQuick.Controls
11 \ingroup qtquickcontrols-containers
12 \inherits TableView
13 \brief Provides a horizontal header view to accompany a \l TableView.
14
15 \include qquickheaderview.qdocinc {detailed-description} {HorizontalHeaderView}
16
17 \sa VerticalHeaderView
18*/
19
20/*!
21 \qmltype VerticalHeaderView
22 \inqmlmodule QtQuick.Controls
23 \ingroup qtquickcontrols-containers
24 \inherits TableView
25 \brief Offers a vertical header view to accompany a \l TableView.
26
27 \include qquickheaderview.qdocinc {detailed-description} {VerticalHeaderView}
28
29 \sa HorizontalHeaderView
30*/
31
32/*!
33 \qmlproperty TableView QtQuick.Controls::HorizontalHeaderView::syncView
34
35 \include qquickheaderview.qdocinc {syncView} {horizontally}
36*/
37
38/*!
39 \qmlproperty TableView QtQuick.Controls::VerticalHeaderView::syncView
40
41 \include qquickheaderview.qdocinc {syncView} {vertically}
42*/
43
44/*!
45 \qmlproperty QVariant QtQuick.Controls::HorizontalHeaderView::model
46
47 \include qquickheaderview.qdocinc {model} {horizontal}
48*/
49
50/*!
51 \qmlproperty QVariant QtQuick.Controls::VerticalHeaderView::model
52
53 \include qquickheaderview.qdocinc {model} {vertical}
54*/
55
56/*!
57 \qmlproperty string QtQuick.Controls::HorizontalHeaderView::textRole
58
59 \include qquickheaderview.qdocinc {textRole}
60*/
61
62/*!
63 \qmlproperty string QtQuick.Controls::VerticalHeaderView::textRole
64
65 \include qquickheaderview.qdocinc {textRole}
66*/
67
68/*!
69 \qmlproperty bool QtQuick.Controls::HorizontalHeaderView::movableColumns
70 \since 6.8
71
72 \include qquickheaderview.qdocinc {movableColumns}
73*/
74
75/*!
76 \qmlproperty bool QtQuick.Controls::VerticalHeaderView::movableRows
77 \since 6.8
78
79 \include qquickheaderview.qdocinc {movableRows}
80*/
81
82/*!
83 \qmlproperty bool QtQuick.Controls::HorizontalHeaderView::showSortIndicator
84 \since 6.13
85
86 \include qquickheaderview.qdocinc {showSortIndicator}
87*/
88
89/*!
90 \qmlproperty bool QtQuick.Controls::HorizontalHeaderView::sortIndicatorClearable
91 \since 6.13
92
93 \include qquickheaderview.qdocinc {sortIndicatorClearable}
94*/
95
96/*!
97 \qmlsignal void QtQuick.Controls::HorizontalHeaderView::headerClicked(int logicalColumn)
98 \since 6.13
99
100 \include qquickheaderview.qdocinc {headerClicked}
101*/
102
104
105static const char *kRequiredProperty_headerView = "headerView";
106static const char *kRequiredProperty_model = "model";
107
108QQuickHeaderViewBasePrivate::QQuickHeaderViewBasePrivate()
109 : QQuickTableViewPrivate()
110{
111}
112
113QQuickHeaderViewBasePrivate::~QQuickHeaderViewBasePrivate()
114{
115}
116
117void QQuickHeaderViewBasePrivate::init()
118{
119 Q_Q(QQuickHeaderViewBase);
120 m_headerDataProxyModel.m_headerView = q;
121 setSizePolicy(orientation() == Qt::Horizontal ? QLayoutPolicy::Preferred : QLayoutPolicy::Fixed,
122 orientation() == Qt::Horizontal ? QLayoutPolicy::Fixed : QLayoutPolicy::Preferred);
123 q->setSyncDirection(orientation());
124}
125
126const QPointer<QQuickItem> QQuickHeaderViewBasePrivate::delegateItemAt(int row, int col) const
127{
128 return loadedTableItem(QPoint(col, row))->item;
129}
130
131QVariant QQuickHeaderViewBasePrivate::modelImpl() const
132{
133 // modelImpl is supposed to return the actual model that is
134 // is used (that is, the proxy model), and not the source model.
135 if (m_headerDataProxyModel.sourceModel())
136 return QVariant::fromValue(&m_headerDataProxyModel);
137
138 // If we're not using the proxy model, use the assigned model
139 return QQuickTableViewPrivate::modelImpl();
140}
141
142void QQuickHeaderViewBasePrivate::setModelImpl(const QVariant &newModel)
143{
144 m_modelExplicitlySet = newModel.isValid();
145
146 auto asTableModel = [](QAbstractItemModel *model) -> QAbstractItemModel* {
147 if (qobject_cast<QAbstractTableModel *>(model))
148 return model;
149
150 // Since QQmlTableModel is not derived from QAbstractTableModel (QATM),
151 // we have to check for this model separately. We want it to behave like
152 // QATM to keep existing code working. This model is in the Labs module,
153 // and we cannot link to it to make a qobject_cast. Therefore, we are checking
154 // the class name.
155 // TODO: When QQmlTableModel leaves Labs, change to qobject_cast?
156 if (model && QByteArrayView(model->metaObject()->className()) == "QQmlTableModel")
157 return model;
158 return nullptr;
159 };
160
161 if (auto qabstracttablemodel = asTableModel(qaim(newModel))) {
162 if (qabstracttablemodel != m_headerDataProxyModel.sourceModel()) {
163 m_headerDataProxyModel.setSourceModel(qabstracttablemodel);
164 assignedModel = QVariant::fromValue(std::addressof(m_headerDataProxyModel));
165 scheduleRebuildTable(QQuickTableViewPrivate::RebuildOption::All);
166 emit q_func()->modelChanged();
167 }
168 return;
169 }
170
171 m_headerDataProxyModel.setSourceModel(nullptr);
172 QQuickTableViewPrivate::setModelImpl(newModel);
173}
174
175void QQuickHeaderViewBasePrivate::syncModel()
176{
177 if (!m_modelExplicitlySet && assignedSyncView) {
178 // When no model has been explicitly set, but we have a syncView, we
179 // should use the headerData() from the syncView's model as model.
180 // If the model is not a QAbstractItemModel, or if it doesn't contain
181 // any header data, header view will be empty.
182 auto syncView_d = QQuickTableViewPrivate::get(assignedSyncView);
183 auto syncViewModelAsQaim = qaim(syncView_d->assignedModel);
184 if (syncViewModelAsQaim != m_headerDataProxyModel.sourceModel()) {
185 m_headerDataProxyModel.setSourceModel(syncViewModelAsQaim); // can be nullptr
186 assignedModel = QVariant::fromValue(std::addressof(m_headerDataProxyModel));
187 emit q_func()->modelChanged();
188 }
189 }
190
191 QQuickTableViewPrivate::syncModel();
192
193 // For models that are just a list or a number, and especially not a
194 // table, we transpose the view when the orientation is horizontal.
195 // The model (list) will then be laid out horizontally rather than
196 // vertically, which is otherwise the default.
197 isTransposed = false;
198 const auto aim = model->abstractItemModel();
199 if (orientation() == Qt::Horizontal)
200 isTransposed = !aim || aim->columnCount() == 1;
201
202 if (m_textRole.isEmpty() && aim)
203 m_textRole = QLatin1String("display");
204}
205
206void QQuickHeaderViewBasePrivate::syncSyncView()
207{
208 if (assignedSyncDirection != orientation()) {
209 qmlWarning(q_func()) << "Setting syncDirection other than Qt::"
210 << QVariant::fromValue(orientation()).toString()
211 << " is invalid.";
212 assignedSyncDirection = orientation();
213 }
214 QQuickTableViewPrivate::syncSyncView();
215}
216
217QAbstractItemModel *QQuickHeaderViewBasePrivate::selectionSourceModel()
218{
219 // Our proxy model shares no common model items with HeaderView.model. So
220 // selections done in HeaderView cannot be represented in an ItemSelectionModel
221 // that is shared with the syncView (and for the same reason, the mapping functions
222 // modelIndex(cell) and cellAtIndex(index) have not been overridden either).
223 // Instead, we set the internal proxy model as selection source model.
224 return &m_headerDataProxyModel;
225}
226
227void QQuickHeaderViewBasePrivate::initItemCallback(int modelIndex, QObject *object)
228{
229 Q_Q(QQuickHeaderViewBase);
230
231 QQuickTableViewPrivate::initItemCallback(modelIndex, object);
232
233 auto item = qobject_cast<QQuickItem *>(object);
234 if (!item)
235 return;
236
237 QQmlDelegateModelItem *modelItem = tableModel->getModelItem(modelIndex);
238
239 setRequiredProperty(kRequiredProperty_headerView, QVariant::fromValue(q),
240 modelIndex, item, true);
241 setRequiredProperty(kRequiredProperty_model, QVariant::fromValue(modelItem->modelObject()),
242 modelIndex, item, true);
243}
244
245int QQuickHeaderViewBasePrivate::logicalRowIndex(const int visualIndex) const
246{
247 return (m_headerDataProxyModel.orientation() == Qt::Horizontal) ? visualIndex : QQuickTableViewPrivate::logicalRowIndex(visualIndex);
248}
249
250int QQuickHeaderViewBasePrivate::logicalColumnIndex(const int visualIndex) const
251{
252 return (m_headerDataProxyModel.orientation() == Qt::Vertical) ? visualIndex : QQuickTableViewPrivate::logicalColumnIndex(visualIndex);
253}
254
255int QQuickHeaderViewBasePrivate::visualRowIndex(const int logicalIndex) const
256{
257 return (m_headerDataProxyModel.orientation() == Qt::Horizontal) ? logicalIndex : QQuickTableViewPrivate::visualRowIndex(logicalIndex);
258}
259
260int QQuickHeaderViewBasePrivate::visualColumnIndex(const int logicalIndex) const
261{
262 return (m_headerDataProxyModel.orientation() == Qt::Vertical) ? logicalIndex : QQuickTableViewPrivate::visualColumnIndex(logicalIndex);
263}
264
265QQuickHeaderViewBase::QQuickHeaderViewBase(Qt::Orientation orient, QQuickItem *parent)
266 : QQuickTableView(*(new QQuickHeaderViewBasePrivate), parent)
267{
268 Q_D(QQuickHeaderViewBase);
269 d->setOrientation(orient);
270 d->init();
271}
272
273QQuickHeaderViewBase::QQuickHeaderViewBase(QQuickHeaderViewBasePrivate &dd, QQuickItem *parent)
274 : QQuickTableView(dd, parent)
275{
276 Q_D(QQuickHeaderViewBase);
277 d->init();
278}
279
280QQuickHeaderViewBase::~QQuickHeaderViewBase()
281{
282}
283
284QString QQuickHeaderViewBase::textRole() const
285{
286 Q_D(const QQuickHeaderViewBase);
287 return d->m_textRole;
288}
289
290void QQuickHeaderViewBase::setTextRole(const QString &role)
291{
292 Q_D(QQuickHeaderViewBase);
293 if (d->m_textRole == role)
294 return;
295
296 d->m_textRole = role;
297 emit textRoleChanged();
298}
299
300Qt::Orientation QQuickHeaderViewBasePrivate::orientation() const
301{
302 return m_headerDataProxyModel.orientation();
303}
304
305void QQuickHeaderViewBasePrivate::setOrientation(Qt::Orientation orientation)
306{
307 if (QQuickHeaderViewBasePrivate::orientation() == orientation)
308 return;
309 m_headerDataProxyModel.setOrientation(orientation);
310}
311
312QQuickVerticalHeaderView::QQuickVerticalHeaderView(QQuickVerticalHeaderViewPrivate &dd, QQuickItem *parent)
313 : QQuickHeaderViewBase(dd, parent)
314{
315}
316
317/*! \internal
318 \class QHeaderDataProxyModel
319 \brief
320 QHeaderDataProxyModel is a proxy AbstractItemModel type that maps
321 source model's headerData() to correspondent data()
322 */
323QHeaderDataProxyModel::QHeaderDataProxyModel(QObject *parent)
324 : QAbstractItemModel(parent)
325{
326}
327
328QHeaderDataProxyModel::~QHeaderDataProxyModel() = default;
329
330void QHeaderDataProxyModel::setSourceModel(QAbstractItemModel *newSourceModel)
331{
332 if (m_model == newSourceModel)
333 return;
334 beginResetModel();
335 disconnectFromModel();
336 m_model = newSourceModel;
337 connectToModel();
338 endResetModel();
339}
340
341QModelIndex QHeaderDataProxyModel::index(int row, int column, const QModelIndex &parent) const
342{
343 return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex();
344}
345
346QModelIndex QHeaderDataProxyModel::parent(const QModelIndex &child) const
347{
348 Q_UNUSED(child);
349 return QModelIndex();
350}
351
352QModelIndex QHeaderDataProxyModel::sibling(int row, int column, const QModelIndex &) const
353{
354 return index(row, column);
355}
356
357int QHeaderDataProxyModel::rowCount(const QModelIndex &parent) const
358{
359 if (parent.isValid())
360 return 0;
361 return m_model.isNull() ? -1 : (m_orientation == Qt::Horizontal ? 1 : m_model->rowCount(parent));
362}
363
364int QHeaderDataProxyModel::columnCount(const QModelIndex &parent) const
365{
366 if (parent.isValid())
367 return 0;
368 return m_model.isNull() ? -1 : (m_orientation == Qt::Vertical ? 1 : m_model->columnCount(parent));
369}
370
371QVariant QHeaderDataProxyModel::data(const QModelIndex &index, int role) const
372{
373 if (m_model.isNull() || !hasIndex(index.row(), index.column()))
374 return QVariant();
375 auto section = m_orientation == Qt::Vertical ? index.row() : index.column();
376 return m_model->headerData(section, m_orientation, role);
377}
378
379bool QHeaderDataProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
380{
381 if (!hasIndex(index.row(), index.column()))
382 return false;
383 auto section = m_orientation == Qt::Vertical ? index.row() : index.column();
384 auto ret = m_model->setHeaderData(section, m_orientation, value, role);
385 return ret;
386}
387
388bool QHeaderDataProxyModel::hasChildren(const QModelIndex &parent) const
389{
390 if (!parent.isValid())
391 return rowCount(parent) > 0 && columnCount(parent) > 0;
392 return false;
393}
394
395QHash<int, QByteArray> QHeaderDataProxyModel::roleNames() const
396{
397 using namespace Qt::Literals::StringLiterals;
398
399 auto names = m_model ? m_model->roleNames() : QAbstractItemModel::roleNames();
400 if (m_headerView) {
401 QString textRole = m_headerView->textRole();
402 if (textRole.isEmpty())
403 textRole = u"display"_s;
404 if (!names.values().contains(textRole.toUtf8().constData())) {
405 qmlWarning(m_headerView).nospace() << "The 'textRole' property contains a role that doesn't exist in the model: "
406 << textRole << ". Check your model's roleNames() implementation";
407 }
408 }
409
410 return names;
411}
412
413QVariant QHeaderDataProxyModel::variantValue() const
414{
415 return QVariant::fromValue(static_cast<QObject *>(const_cast<QHeaderDataProxyModel *>(this)));
416}
417
418void QHeaderDataProxyModel::setOrientation(Qt::Orientation o)
419{
420 if (o == m_orientation)
421 return;
422 beginResetModel();
423 m_orientation = o;
424 endResetModel();
425}
426
427Qt::Orientation QHeaderDataProxyModel::orientation() const
428{
429 return m_orientation;
430}
431
432QPointer<QAbstractItemModel> QHeaderDataProxyModel::sourceModel() const
433{
434 return m_model;
435}
436
437void QHeaderDataProxyModel::connectToModel()
438{
439 if (m_model.isNull())
440 return;
441 connect(m_model, &QAbstractItemModel::headerDataChanged,
442 this, [this](Qt::Orientation orient, int first, int last) {
443 if (orient != orientation())
444 return;
445 if (orient == Qt::Horizontal) {
446 emit dataChanged(createIndex(0, first), createIndex(0, last));
447 } else {
448 emit dataChanged(createIndex(first, 0), createIndex(last, 0));
449 }
450 });
451 connect(m_model, &QAbstractItemModel::modelAboutToBeReset,
452 this, &QHeaderDataProxyModel::modelAboutToBeReset, Qt::UniqueConnection);
453 connect(m_model, &QAbstractItemModel::modelReset,
454 this, &QHeaderDataProxyModel::modelReset, Qt::UniqueConnection);
455 connect(m_model, &QAbstractItemModel::rowsAboutToBeMoved,
456 this, &QHeaderDataProxyModel::rowsAboutToBeMoved, Qt::UniqueConnection);
457 connect(m_model, &QAbstractItemModel::rowsMoved,
458 this, &QHeaderDataProxyModel::rowsMoved, Qt::UniqueConnection);
459 connect(m_model, &QAbstractItemModel::rowsAboutToBeInserted,
460 this, &QHeaderDataProxyModel::rowsAboutToBeInserted, Qt::UniqueConnection);
461 connect(m_model, &QAbstractItemModel::rowsInserted,
462 this, &QHeaderDataProxyModel::rowsInserted, Qt::UniqueConnection);
463 connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved,
464 this, &QHeaderDataProxyModel::rowsAboutToBeRemoved, Qt::UniqueConnection);
465 connect(m_model, &QAbstractItemModel::rowsRemoved,
466 this, &QHeaderDataProxyModel::rowsRemoved, Qt::UniqueConnection);
467 connect(m_model, &QAbstractItemModel::columnsAboutToBeMoved,
468 this, &QHeaderDataProxyModel::columnsAboutToBeMoved, Qt::UniqueConnection);
469 connect(m_model, &QAbstractItemModel::columnsMoved,
470 this, &QHeaderDataProxyModel::columnsMoved, Qt::UniqueConnection);
471 connect(m_model, &QAbstractItemModel::columnsAboutToBeInserted,
472 this, &QHeaderDataProxyModel::columnsAboutToBeInserted, Qt::UniqueConnection);
473 connect(m_model, &QAbstractItemModel::columnsInserted,
474 this, &QHeaderDataProxyModel::columnsInserted, Qt::UniqueConnection);
475 connect(m_model, &QAbstractItemModel::columnsAboutToBeRemoved,
476 this, &QHeaderDataProxyModel::columnsAboutToBeRemoved, Qt::UniqueConnection);
477 connect(m_model, &QAbstractItemModel::columnsRemoved,
478 this, &QHeaderDataProxyModel::columnsRemoved, Qt::UniqueConnection);
479 connect(m_model, &QAbstractItemModel::layoutAboutToBeChanged,
480 this, &QHeaderDataProxyModel::layoutAboutToBeChanged, Qt::UniqueConnection);
481 connect(m_model, &QAbstractItemModel::layoutChanged,
482 this, &QHeaderDataProxyModel::layoutChanged, Qt::UniqueConnection);
483}
484
485void QHeaderDataProxyModel::disconnectFromModel()
486{
487 if (m_model.isNull())
488 return;
489 m_model->disconnect(this);
490}
491
492QQuickHorizontalHeaderView::QQuickHorizontalHeaderView(QQuickItem *parent)
493 : QQuickHeaderViewBase(*(new QQuickHorizontalHeaderViewPrivate), parent)
494{
495 setFlickableDirection(FlickableDirection::HorizontalFlick);
496 setResizableColumns(true);
497}
498
499QQuickHorizontalHeaderView::~QQuickHorizontalHeaderView()
500{
501#if QT_CONFIG(quick_draganddrop)
502 Q_D(QQuickHorizontalHeaderView);
503 d->destroySectionDragHandler();
504#endif
505}
506
507bool QQuickHorizontalHeaderView::movableColumns() const
508{
509 Q_D(const QQuickHorizontalHeaderView);
510 return d->m_movableColumns;
511}
512
513void QQuickHorizontalHeaderView::setMovableColumns(bool movableColumns)
514{
515 Q_D(QQuickHorizontalHeaderView);
516 if (d->m_movableColumns == movableColumns)
517 return;
518
519 d->m_movableColumns = movableColumns;
520
521#if QT_CONFIG(quick_draganddrop)
522 if (d->m_movableColumns)
523 d->initSectionDragHandler(Qt::Horizontal);
524 else
525 d->destroySectionDragHandler();
526#endif
527
528 emit movableColumnsChanged();
529}
530
531bool QQuickHorizontalHeaderView::showSortIndicator() const
532{
533 Q_D(const QQuickHorizontalHeaderView);
534 return d->showSortIndicator;
535}
536
537void QQuickHorizontalHeaderView::setShowSortIndicator(bool show)
538{
539 Q_D(QQuickHorizontalHeaderView);
540 if (d->showSortIndicator == show)
541 return;
542
543 d->showSortIndicator = show;
544 emit showSortIndicatorChanged();
545}
546
547bool QQuickHorizontalHeaderView::sortIndicatorClearable() const
548{
549 Q_D(const QQuickHorizontalHeaderView);
550 return d->sortIndicatorClearable;
551}
552
553void QQuickHorizontalHeaderView::setSortIndicatorClearable(bool clearable)
554{
555 Q_D(QQuickHorizontalHeaderView);
556 if (d->sortIndicatorClearable == clearable)
557 return;
558
559 d->sortIndicatorClearable = clearable;
560 emit sortIndicatorClearableChanged();
561}
562
563QQuickVerticalHeaderView::QQuickVerticalHeaderView(QQuickItem *parent)
564 : QQuickHeaderViewBase(*(new QQuickVerticalHeaderViewPrivate), parent)
565{
566 setFlickableDirection(FlickableDirection::VerticalFlick);
567 setResizableRows(true);
568}
569
570QQuickVerticalHeaderView::~QQuickVerticalHeaderView()
571{
572#if QT_CONFIG(quick_draganddrop)
573 Q_D(QQuickVerticalHeaderView);
574 d->destroySectionDragHandler();
575#endif
576}
577
578bool QQuickVerticalHeaderView::movableRows() const
579{
580 Q_D(const QQuickVerticalHeaderView);
581 return d->m_movableRows ;
582}
583
584void QQuickVerticalHeaderView::setMovableRows(bool movableRows)
585{
586 Q_D(QQuickVerticalHeaderView);
587 if (d->m_movableRows == movableRows)
588 return;
589
590 d->m_movableRows = movableRows;
591
592#if QT_CONFIG(quick_draganddrop)
593 if (d->m_movableRows)
594 d->initSectionDragHandler(Qt::Vertical);
595 else
596 d->destroySectionDragHandler();
597#endif
598
599 emit movableRowsChanged();
600}
601
602QQuickHorizontalHeaderViewPrivate::QQuickHorizontalHeaderViewPrivate()
603{
604 setOrientation(Qt::Horizontal);
605};
606
607QQuickHorizontalHeaderViewPrivate::~QQuickHorizontalHeaderViewPrivate() = default;
608
609void QQuickHorizontalHeaderViewPrivate::executeTap(const QQuickHandlerPoint &point)
610{
611 Q_Q(QQuickHorizontalHeaderView);
612
613 QQuickTableViewPrivate::executeTap(point);
614
615 const QPoint cell = q->cellAtPosition(point.position());
616 const int visualColumn = cell.x();
617 const int logicalColumn = logicalColumnIndex(visualColumn);
618
619 if (logicalColumn < 0)
620 return;
621
622 emit q->headerClicked(logicalColumn);
623
624 if (!assignedSyncView)
625 return;
626
627 QQuickTableViewPrivate::get(assignedSyncView)->requestSort(logicalColumn, sortIndicatorClearable);
628}
629
630QQuickVerticalHeaderViewPrivate::QQuickVerticalHeaderViewPrivate()
631{
632 setOrientation(Qt::Vertical);
633};
634
635QQuickVerticalHeaderViewPrivate::~QQuickVerticalHeaderViewPrivate() = default;
636
637QT_END_NAMESPACE
638
639#include "moc_qquickheaderview_p_p.cpp"
640
641#include "moc_qquickheaderview_p.cpp"
static QT_BEGIN_NAMESPACE const char * kRequiredProperty_headerView
\qmltype HorizontalHeaderView \inqmlmodule QtQuick.Controls\inherits TableView
static const char * kRequiredProperty_model