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
qtransposeproxymodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
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
6#include <private/qtransposeproxymodel_p.h>
7#include <QtCore/qlist.h>
8#include <QtCore/qmetaobject.h>
9#include <QtCore/qsize.h>
10#include <QtCore/qmap.h>
11
13
14QTransposeProxyModelPrivate::QTransposeProxyModelPrivate()
15 = default;
16
17QTransposeProxyModelPrivate::~QTransposeProxyModelPrivate()
18 = default;
19
20QModelIndex QTransposeProxyModelPrivate::uncheckedMapToSource(const QModelIndex &proxyIndex) const
21{
22 if (!model || !proxyIndex.isValid())
23 return QModelIndex();
24 Q_Q(const QTransposeProxyModel);
25 return q->createSourceIndex(proxyIndex.column(), proxyIndex.row(), proxyIndex.internalPointer());
26}
27
28QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelIndex &sourceIndex) const
29{
30 if (!model || !sourceIndex.isValid())
31 return QModelIndex();
32 Q_Q(const QTransposeProxyModel);
33 return q->createIndex(sourceIndex.column(), sourceIndex.row(), sourceIndex.internalPointer());
34}
35
36void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
37{
38 Q_Q(QTransposeProxyModel);
39 Q_ASSERT(layoutChangeProxyIndexes.size() == layoutChangePersistentIndexes.size());
40 QModelIndexList toList;
41 toList.reserve(layoutChangePersistentIndexes.size());
42 for (const QPersistentModelIndex &persistIdx : std::as_const(layoutChangePersistentIndexes))
43 toList << q->mapFromSource(persistIdx);
44 q->changePersistentIndexList(layoutChangeProxyIndexes, toList);
45 layoutChangeProxyIndexes.clear();
46 layoutChangePersistentIndexes.clear();
47 QList<QPersistentModelIndex> proxyParents;
48 proxyParents.reserve(parents.size());
49 for (const QPersistentModelIndex &srcParent : parents)
50 proxyParents << q->mapFromSource(srcParent);
51 QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
52 if (hint == QAbstractItemModel::VerticalSortHint)
53 proxyHint = QAbstractItemModel::HorizontalSortHint;
54 else if (hint == QAbstractItemModel::HorizontalSortHint)
55 proxyHint = QAbstractItemModel::VerticalSortHint;
56 emit q->layoutChanged(proxyParents, proxyHint);
57}
58
59void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
60{
61 Q_Q(QTransposeProxyModel);
62 QList<QPersistentModelIndex> proxyParents;
63 proxyParents.reserve(sourceParents.size());
64 for (const QPersistentModelIndex &parent : sourceParents) {
65 if (!parent.isValid()) {
66 proxyParents << QPersistentModelIndex();
67 continue;
68 }
69 const QModelIndex mappedParent = q->mapFromSource(parent);
70 Q_ASSERT(mappedParent.isValid());
71 proxyParents << mappedParent;
72 }
73 QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
74 if (hint == QAbstractItemModel::VerticalSortHint)
75 proxyHint = QAbstractItemModel::HorizontalSortHint;
76 else if (hint == QAbstractItemModel::HorizontalSortHint)
77 proxyHint = QAbstractItemModel::VerticalSortHint;
78 emit q->layoutAboutToBeChanged(proxyParents, proxyHint);
79 const QModelIndexList proxyPersistentIndexes = q->persistentIndexList();
80 layoutChangeProxyIndexes.clear();
81 layoutChangePersistentIndexes.clear();
82 layoutChangeProxyIndexes.reserve(proxyPersistentIndexes.size());
83 layoutChangePersistentIndexes.reserve(proxyPersistentIndexes.size());
84 for (const QModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
85 layoutChangeProxyIndexes << proxyPersistentIndex;
86 Q_ASSERT(proxyPersistentIndex.isValid());
87 const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
88 Q_ASSERT(srcPersistentIndex.isValid());
89 layoutChangePersistentIndexes << srcPersistentIndex;
90 }
91}
92
93void QTransposeProxyModelPrivate::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
94 const QList<int> &roles)
95{
96 Q_Q(QTransposeProxyModel);
97 emit q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
98}
99
100void QTransposeProxyModelPrivate::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
101{
102 Q_Q(QTransposeProxyModel);
103 emit q->headerDataChanged(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, first, last);
104}
105
106void QTransposeProxyModelPrivate::onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
107{
108 Q_Q(QTransposeProxyModel);
109 q->beginInsertRows(q->mapFromSource(parent), first, last);
110}
111
112void QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
113{
114 Q_Q(QTransposeProxyModel);
115 q->beginRemoveRows(q->mapFromSource(parent), first, last);
116}
117
118void QTransposeProxyModelPrivate::onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
119{
120 Q_Q(QTransposeProxyModel);
121 q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationColumn);
122}
123
124void QTransposeProxyModelPrivate::onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
125{
126 Q_Q(QTransposeProxyModel);
127 q->beginInsertColumns(q->mapFromSource(parent), first, last);
128}
129
130void QTransposeProxyModelPrivate::onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
131{
132 Q_Q(QTransposeProxyModel);
133 q->beginRemoveColumns(q->mapFromSource(parent), first, last);
134}
135
136void QTransposeProxyModelPrivate::onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
137{
138 Q_Q(QTransposeProxyModel);
139 q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationRow);
140}
141
142/*!
143 \since 5.13
144 \class QTransposeProxyModel
145 \inmodule QtCore
146 \brief This proxy transposes the source model.
147
148 This model will make the rows of the source model become columns of the proxy model and vice-versa.
149
150 If the model is a tree, the parents will be transposed as well. For example, if an index in the source model had parent `index(2,0)`, it will have parent `index(0,2)` in the proxy.
151*/
152
153/*!
154 Constructs a new proxy model with the given \a parent.
155*/
156QTransposeProxyModel::QTransposeProxyModel(QObject* parent)
157 : QAbstractProxyModel(*new QTransposeProxyModelPrivate, parent)
158{}
159
160/*!
161 Destructs the proxy model.
162*/
163QTransposeProxyModel::~QTransposeProxyModel() = default;
164
165/*!
166 \internal
167*/
168QTransposeProxyModel::QTransposeProxyModel(QTransposeProxyModelPrivate &dd, QObject *parent)
169 : QAbstractProxyModel(dd, parent)
170{}
171
172/*!
173 \reimp
174*/
175void QTransposeProxyModel::setSourceModel(QAbstractItemModel* newSourceModel)
176{
177 Q_D(QTransposeProxyModel);
178 if (newSourceModel == d->model)
179 return;
180 beginResetModel();
181 if (d->model) {
182 for (QMetaObject::Connection &discIter : d->sourceConnections)
183 disconnect(discIter);
184 }
185 QAbstractProxyModel::setSourceModel(newSourceModel);
186 if (d->model) {
187 using namespace std::placeholders;
188 d->sourceConnections = std::array{
189 connect(d->model, &QAbstractItemModel::modelAboutToBeReset, this, &QTransposeProxyModel::beginResetModel),
190 connect(d->model, &QAbstractItemModel::modelReset, this, &QTransposeProxyModel::endResetModel),
191 connect(d->model, &QAbstractItemModel::dataChanged, this, std::bind(&QTransposeProxyModelPrivate::onDataChanged, d, _1, _2, _3)),
192 connect(d->model, &QAbstractItemModel::headerDataChanged, this, std::bind(&QTransposeProxyModelPrivate::onHeaderDataChanged, d, _1, _2, _3)),
193 connect(d->model, &QAbstractItemModel::columnsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeInserted, d, _1, _2, _3)),
194 connect(d->model, &QAbstractItemModel::columnsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeMoved, d, _1, _2, _3, _4, _5)),
195 connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved, d, _1, _2, _3)),
196 connect(d->model, &QAbstractItemModel::columnsInserted, this, &QTransposeProxyModel::endInsertRows),
197 connect(d->model, &QAbstractItemModel::columnsRemoved, this, &QTransposeProxyModel::endRemoveRows),
198 connect(d->model, &QAbstractItemModel::columnsMoved, this, &QTransposeProxyModel::endMoveRows),
199 connect(d->model, &QAbstractItemModel::rowsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeInserted, d, _1, _2, _3)),
200 connect(d->model, &QAbstractItemModel::rowsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeMoved, d, _1, _2, _3, _4, _5)),
201 connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeRemoved, d, _1, _2, _3)),
202 connect(d->model, &QAbstractItemModel::rowsInserted, this, &QTransposeProxyModel::endInsertColumns),
203 connect(d->model, &QAbstractItemModel::rowsRemoved, this, &QTransposeProxyModel::endRemoveColumns),
204 connect(d->model, &QAbstractItemModel::rowsMoved, this, &QTransposeProxyModel::endMoveColumns),
205 connect(d->model, &QAbstractItemModel::layoutAboutToBeChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutAboutToBeChanged, d, _1, _2)),
206 connect(d->model, &QAbstractItemModel::layoutChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutChanged, d, _1, _2))
207 };
208 }
209 endResetModel();
210}
211
212/*!
213 \reimp
214*/
215int QTransposeProxyModel::rowCount(const QModelIndex &parent) const
216{
217 Q_D(const QTransposeProxyModel);
218 if (!d->model)
219 return 0;
220 Q_ASSERT(checkIndex(parent));
221 return d->model->columnCount(mapToSource(parent));
222}
223
224/*!
225 \reimp
226*/
227int QTransposeProxyModel::columnCount(const QModelIndex &parent) const
228{
229 Q_D(const QTransposeProxyModel);
230 if (!d->model)
231 return 0;
232 Q_ASSERT(checkIndex(parent));
233 return d->model->rowCount(mapToSource(parent));
234}
235
236/*!
237 \reimp
238*/
239QVariant QTransposeProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
240{
241 Q_D(const QTransposeProxyModel);
242 if (!d->model)
243 return QVariant();
244 return d->model->headerData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, role);
245}
246
247/*!
248 \reimp
249*/
250bool QTransposeProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
251{
252 Q_D(QTransposeProxyModel);
253 if (!d->model)
254 return false;
255 return d->model->setHeaderData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, value, role);
256}
257
258/*!
259 \reimp
260*/
261bool QTransposeProxyModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
262{
263 Q_D(QTransposeProxyModel);
264 Q_ASSERT(checkIndex(index));
265 if (!d->model || !index.isValid())
266 return false;
267 return d->model->setItemData(mapToSource(index), roles);
268}
269
270/*!
271 \reimp
272*/
273QSize QTransposeProxyModel::span(const QModelIndex &index) const
274{
275 Q_D(const QTransposeProxyModel);
276 Q_ASSERT(checkIndex(index));
277 if (!d->model || !index.isValid())
278 return QSize();
279 return d->model->span(mapToSource(index)).transposed();
280}
281
282/*!
283 \reimp
284*/
285QMap<int, QVariant> QTransposeProxyModel::itemData(const QModelIndex &index) const
286{
287 Q_D(const QTransposeProxyModel);
288 if (!d->model)
289 return QMap<int, QVariant>();
290 Q_ASSERT(checkIndex(index));
291 return d->model->itemData(mapToSource(index));
292}
293
294/*!
295 \reimp
296*/
297QModelIndex QTransposeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
298{
299 Q_D(const QTransposeProxyModel);
300 if (!d->model || !sourceIndex.isValid())
301 return QModelIndex();
302 Q_ASSERT(d->model->checkIndex(sourceIndex));
303 return d->uncheckedMapFromSource(sourceIndex);
304}
305
306/*!
307 \reimp
308*/
309QModelIndex QTransposeProxyModel::mapToSource(const QModelIndex &proxyIndex) const
310{
311 Q_D(const QTransposeProxyModel);
312 Q_ASSERT(checkIndex(proxyIndex));
313 if (!d->model || !proxyIndex.isValid())
314 return QModelIndex();
315 return d->uncheckedMapToSource(proxyIndex);
316}
317
318/*!
319 \reimp
320*/
321QModelIndex QTransposeProxyModel::parent(const QModelIndex &index) const
322{
323 Q_D(const QTransposeProxyModel);
324 Q_ASSERT(checkIndex(index, CheckIndexOption::DoNotUseParent));
325 if (!d->model || !index.isValid())
326 return QModelIndex();
327 return d->uncheckedMapFromSource(d->uncheckedMapToSource(index).parent());
328}
329
330/*!
331 \reimp
332*/
333QModelIndex QTransposeProxyModel::index(int row, int column, const QModelIndex &parent) const
334{
335 Q_D(const QTransposeProxyModel);
336 Q_ASSERT(checkIndex(parent));
337 if (!d->model)
338 return QModelIndex();
339 return mapFromSource(d->model->index(column, row, mapToSource(parent)));
340}
341
342/*!
343 \reimp
344*/
345bool QTransposeProxyModel::insertRows(int row, int count, const QModelIndex &parent)
346{
347 Q_D(QTransposeProxyModel);
348 Q_ASSERT(checkIndex(parent));
349 if (!d->model)
350 return false;
351 return d->model->insertColumns(row, count, mapToSource(parent));
352}
353
354/*!
355 \reimp
356*/
357bool QTransposeProxyModel::removeRows(int row, int count, const QModelIndex &parent)
358{
359 Q_D(QTransposeProxyModel);
360 Q_ASSERT(checkIndex(parent));
361 if (!d->model)
362 return false;
363 return d->model->removeColumns(row, count, mapToSource(parent));
364}
365
366/*!
367 \reimp
368*/
369bool QTransposeProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
370{
371 Q_D(QTransposeProxyModel);
372 Q_ASSERT(checkIndex(sourceParent));
373 Q_ASSERT(checkIndex(destinationParent));
374 if (!d->model)
375 return false;
376 return d->model->moveColumns(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
377}
378
379/*!
380 \reimp
381*/
382bool QTransposeProxyModel::insertColumns(int column, int count, const QModelIndex &parent)
383{
384 Q_D(QTransposeProxyModel);
385 Q_ASSERT(checkIndex(parent));
386 if (!d->model)
387 return false;
388 return d->model->insertRows(column, count, mapToSource(parent));
389}
390
391/*!
392 \reimp
393*/
394bool QTransposeProxyModel::removeColumns(int column, int count, const QModelIndex &parent)
395{
396 Q_D(QTransposeProxyModel);
397 Q_ASSERT(checkIndex(parent));
398 if (!d->model)
399 return false;
400 return d->model->removeRows(column, count, mapToSource(parent));
401}
402
403/*!
404 \reimp
405*/
406bool QTransposeProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
407{
408 Q_D(QTransposeProxyModel);
409 Q_ASSERT(checkIndex(sourceParent));
410 Q_ASSERT(checkIndex(destinationParent));
411 if (!d->model)
412 return false;
413 return d->model->moveRows(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
414}
415
416/*!
417 \reimp
418 This method will perform no action. Use a QSortFilterProxyModel on top of this one if you require sorting.
419*/
420void QTransposeProxyModel::sort(int column, Qt::SortOrder order)
421{
422 Q_UNUSED(column);
423 Q_UNUSED(order);
424 return;
425}
426
427QT_END_NAMESPACE
428
429#include "moc_qtransposeproxymodel.cpp"
Combined button and popup list for selecting options.