summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/configure.json7
-rw-r--r--src/corelib/itemmodels/itemmodels.pri9
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h2
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.cpp446
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel.h83
-rw-r--r--src/corelib/itemmodels/qtransposeproxymodel_p.h73
6 files changed, 620 insertions, 0 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index f09ef6c1dd..f18e79f1aa 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -793,6 +793,13 @@
"condition": "features.proxymodel",
"output": [ "publicFeature", "feature" ]
},
+ "transposeproxymodel": {
+ "label": "QTransposeProxyModel",
+ "purpose": "Provides a proxy to swap rows and columns of a model.",
+ "section": "ItemViews",
+ "condition": "features.proxymodel",
+ "output": [ "publicFeature", "feature" ]
+ },
"concatenatetablesproxymodel": {
"label": "QConcatenateTablesProxyModel",
"purpose": "Supports concatenating source models.",
diff --git a/src/corelib/itemmodels/itemmodels.pri b/src/corelib/itemmodels/itemmodels.pri
index 5a977c6623..ebeac6e211 100644
--- a/src/corelib/itemmodels/itemmodels.pri
+++ b/src/corelib/itemmodels/itemmodels.pri
@@ -43,6 +43,15 @@ qtConfig(proxymodel) {
SOURCES += \
itemmodels/qsortfilterproxymodel.cpp
}
+
+ qtConfig(transposeproxymodel) {
+ HEADERS += \
+ itemmodels/qtransposeproxymodel.h \
+ itemmodels/qtransposeproxymodel_p.h
+
+ SOURCES += \
+ itemmodels/qtransposeproxymodel.cpp
+ }
}
qtConfig(stringlistmodel) {
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index bec71b0606..0aa75d6ff7 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -163,6 +163,7 @@ typedef QList<QModelIndex> QModelIndexList;
class QMimeData;
class QAbstractItemModelPrivate;
+class QTransposeProxyModelPrivate;
template <class Key, class T> class QMap;
@@ -173,6 +174,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject
friend class QPersistentModelIndexData;
friend class QAbstractItemViewPrivate;
friend class QIdentityProxyModel;
+ friend class QTransposeProxyModelPrivate;
public:
explicit QAbstractItemModel(QObject *parent = nullptr);
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp
new file mode 100644
index 0000000000..dd84b97118
--- /dev/null
+++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtransposeproxymodel.h"
+#include <private/qtransposeproxymodel_p.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qsize.h>
+
+QT_BEGIN_NAMESPACE
+
+QModelIndex QTransposeProxyModelPrivate::uncheckedMapToSource(const QModelIndex &proxyIndex) const
+{
+ if (!model || !proxyIndex.isValid())
+ return QModelIndex();
+ if (proxyIndex.internalPointer())
+ return model->createIndex(proxyIndex.column(), proxyIndex.row(), proxyIndex.internalPointer());
+ return model->index(proxyIndex.column(), proxyIndex.row());
+}
+
+QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelIndex &sourceIndex) const
+{
+ if (!model || !sourceIndex.isValid())
+ return QModelIndex();
+ Q_Q(const QTransposeProxyModel);
+ return q->createIndex(sourceIndex.column(), sourceIndex.row(), sourceIndex.internalPointer());
+}
+
+void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(QTransposeProxyModel);
+ QModelIndexList toList;
+ toList.reserve(layoutChangePersistentIndexes.size());
+ for (const QPersistentModelIndex &persistIdx : qAsConst(layoutChangePersistentIndexes))
+ toList << q->mapFromSource(persistIdx);
+ q->changePersistentIndexList(layoutChangeProxyIndexes, toList);
+ layoutChangeProxyIndexes.clear();
+ layoutChangePersistentIndexes.clear();
+ QList<QPersistentModelIndex> proxyParents;
+ proxyParents.reserve(parents.size());
+ for (const QPersistentModelIndex &srcParent : parents)
+ proxyParents << q->mapFromSource(srcParent);
+ QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
+ if (hint == QAbstractItemModel::VerticalSortHint)
+ proxyHint = QAbstractItemModel::HorizontalSortHint;
+ else if (hint == QAbstractItemModel::HorizontalSortHint)
+ proxyHint = QAbstractItemModel::VerticalSortHint;
+ q->layoutChanged(proxyParents, proxyHint);
+}
+
+void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
+{
+ Q_Q(QTransposeProxyModel);
+ const QModelIndexList proxyPersistentIndexes = q->persistentIndexList();
+ layoutChangeProxyIndexes.clear();
+ layoutChangePersistentIndexes.clear();
+ layoutChangeProxyIndexes.reserve(proxyPersistentIndexes.size());
+ layoutChangePersistentIndexes.reserve(proxyPersistentIndexes.size());
+ for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
+ layoutChangeProxyIndexes << proxyPersistentIndex;
+ Q_ASSERT(proxyPersistentIndex.isValid());
+ const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
+ Q_ASSERT(srcPersistentIndex.isValid());
+ layoutChangePersistentIndexes << srcPersistentIndex;
+ }
+ QList<QPersistentModelIndex> proxyParents;
+ proxyParents.reserve(parents.size());
+ for (auto& srcParent : parents)
+ proxyParents << q->mapFromSource(srcParent);
+ QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint;
+ if (hint == QAbstractItemModel::VerticalSortHint)
+ proxyHint = QAbstractItemModel::HorizontalSortHint;
+ else if (hint == QAbstractItemModel::HorizontalSortHint)
+ proxyHint = QAbstractItemModel::VerticalSortHint;
+ q->layoutAboutToBeChanged(proxyParents, proxyHint);
+}
+
+void QTransposeProxyModelPrivate::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
+{
+ Q_Q(QTransposeProxyModel);
+ q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
+}
+
+void QTransposeProxyModelPrivate::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->headerDataChanged(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, first, last);
+}
+
+void QTransposeProxyModelPrivate::onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginInsertRows(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginRemoveRows(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationColumn);
+}
+
+void QTransposeProxyModelPrivate::onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginInsertColumns(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginRemoveColumns(q->mapFromSource(parent), first, last);
+}
+
+void QTransposeProxyModelPrivate::onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+{
+ Q_Q(QTransposeProxyModel);
+ q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationRow);
+}
+
+/*!
+ \since 5.13
+ \class QTransposeProxyModel
+ \brief This proxy transposes the source model
+ \details This model will make the rows of the source model become columns of the proxy model and vice-versa.
+
+ 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.
+*/
+
+/*!
+ Constructs a new proxy model with the given \a parent.
+*/
+QTransposeProxyModel::QTransposeProxyModel(QObject* parent)
+ : QAbstractProxyModel(*new QTransposeProxyModelPrivate, parent)
+{}
+
+/*!
+ Destructs the proxy model.
+*/
+QTransposeProxyModel::~QTransposeProxyModel() = default;
+
+/*!
+ \internal
+*/
+QTransposeProxyModel::QTransposeProxyModel(QTransposeProxyModelPrivate &dd, QObject *parent)
+ : QAbstractProxyModel(dd, parent)
+{}
+
+/*!
+ \reimp
+*/
+void QTransposeProxyModel::setSourceModel(QAbstractItemModel* newSourceModel)
+{
+ Q_D(QTransposeProxyModel);
+ if (newSourceModel == d->model)
+ return;
+ beginResetModel();
+ if (d->model) {
+ for (const QMetaObject::Connection& discIter : qAsConst(d->sourceConnections))
+ disconnect(discIter);
+ }
+ d->sourceConnections.clear();
+ QAbstractProxyModel::setSourceModel(newSourceModel);
+ if (d->model) {
+ using namespace std::placeholders;
+ d->sourceConnections = QVector<QMetaObject::Connection>{
+ connect(d->model, &QAbstractItemModel::modelAboutToBeReset, this, &QTransposeProxyModel::beginResetModel),
+ connect(d->model, &QAbstractItemModel::modelReset, this, &QTransposeProxyModel::endResetModel),
+ connect(d->model, &QAbstractItemModel::dataChanged, this, std::bind(&QTransposeProxyModelPrivate::onDataChanged, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::headerDataChanged, this, std::bind(&QTransposeProxyModelPrivate::onHeaderDataChanged, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::columnsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeInserted, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::columnsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeMoved, d, _1, _2, _3, _4, _5)),
+ connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::columnsInserted, this, &QTransposeProxyModel::endInsertRows),
+ connect(d->model, &QAbstractItemModel::columnsRemoved, this, &QTransposeProxyModel::endRemoveRows),
+ connect(d->model, &QAbstractItemModel::columnsMoved, this, &QTransposeProxyModel::endMoveRows),
+ connect(d->model, &QAbstractItemModel::rowsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeInserted, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::rowsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeMoved, d, _1, _2, _3, _4, _5)),
+ connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeRemoved, d, _1, _2, _3)),
+ connect(d->model, &QAbstractItemModel::rowsInserted, this, &QTransposeProxyModel::endInsertColumns),
+ connect(d->model, &QAbstractItemModel::rowsRemoved, this, &QTransposeProxyModel::endRemoveColumns),
+ connect(d->model, &QAbstractItemModel::rowsMoved, this, &QTransposeProxyModel::endMoveColumns),
+ connect(d->model, &QAbstractItemModel::layoutAboutToBeChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutAboutToBeChanged, d, _1, _2)),
+ connect(d->model, &QAbstractItemModel::layoutChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutChanged, d, _1, _2))
+ };
+ }
+ endResetModel();
+}
+
+/*!
+ \reimp
+*/
+int QTransposeProxyModel::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return 0;
+ Q_ASSERT(checkIndex(parent));
+ return d->model->columnCount(mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+int QTransposeProxyModel::columnCount(const QModelIndex &parent) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return 0;
+ Q_ASSERT(checkIndex(parent));
+ return d->model->rowCount(mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+QVariant QTransposeProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return QVariant();
+ return d->model->headerData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, role);
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
+{
+ Q_D(QTransposeProxyModel);
+ if (!d->model)
+ return false;
+ return d->model->setHeaderData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, value, role);
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(index));
+ if (!d->model || !index.isValid())
+ return false;
+ return d->model->setItemData(mapToSource(index), roles);
+}
+
+/*!
+ \reimp
+*/
+QSize QTransposeProxyModel::span(const QModelIndex &index) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(index));
+ if (!d->model || !index.isValid())
+ return QSize();
+ return d->model->span(mapToSource(index)).transposed();
+}
+
+/*!
+ \reimp
+*/
+QMap<int, QVariant> QTransposeProxyModel::itemData(const QModelIndex &index) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model)
+ return QMap<int, QVariant>();
+ Q_ASSERT(checkIndex(index));
+ return d->model->itemData(mapToSource(index));
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ Q_D(const QTransposeProxyModel);
+ if (!d->model || !sourceIndex.isValid())
+ return QModelIndex();
+ Q_ASSERT(d->model->checkIndex(sourceIndex));
+ return d->uncheckedMapFromSource(sourceIndex);
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(proxyIndex));
+ if (!d->model || !proxyIndex.isValid())
+ return QModelIndex();
+ return d->uncheckedMapToSource(proxyIndex);
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::parent(const QModelIndex &index) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(index, CheckIndexOption::DoNotUseParent));
+ if (!d->model || !index.isValid())
+ return QModelIndex();
+ return d->uncheckedMapFromSource(d->uncheckedMapToSource(index).parent());
+}
+
+/*!
+ \reimp
+*/
+QModelIndex QTransposeProxyModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_D(const QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return QModelIndex();
+ return mapFromSource(d->model->index(column, row, mapToSource(parent)));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::insertRows(int row, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->insertColumns(row, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->removeColumns(row, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(sourceParent));
+ Q_ASSERT(checkIndex(destinationParent));
+ if (!d->model)
+ return false;
+ return d->model->moveColumns(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::insertColumns(int column, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->insertRows(column, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::removeColumns(int column, int count, const QModelIndex &parent)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(parent));
+ if (!d->model)
+ return false;
+ return d->model->removeRows(column, count, mapToSource(parent));
+}
+
+/*!
+ \reimp
+*/
+bool QTransposeProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_D(QTransposeProxyModel);
+ Q_ASSERT(checkIndex(sourceParent));
+ Q_ASSERT(checkIndex(destinationParent));
+ if (!d->model)
+ return false;
+ return d->model->moveRows(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild);
+}
+
+/*!
+ \reimp
+ This method will perform no action. Use a QSortFilterProxyModel on top of this one if you require sorting.
+*/
+void QTransposeProxyModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column)
+ Q_UNUSED(order)
+ return;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/itemmodels/qtransposeproxymodel.h b/src/corelib/itemmodels/qtransposeproxymodel.h
new file mode 100644
index 0000000000..879266d931
--- /dev/null
+++ b/src/corelib/itemmodels/qtransposeproxymodel.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPOSEPROXYMODEL_H
+#define QTRANSPOSEPROXYMODEL_H
+
+#include <QtCore/qabstractproxymodel.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTransposeProxyModelPrivate;
+
+class Q_CORE_EXPORT QTransposeProxyModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QTransposeProxyModel)
+ Q_DECLARE_PRIVATE(QTransposeProxyModel)
+public:
+ explicit QTransposeProxyModel(QObject* parent = nullptr);
+ ~QTransposeProxyModel();
+ void setSourceModel(QAbstractItemModel* newSourceModel) override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
+ bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
+ QSize span(const QModelIndex &index) const override;
+ QMap<int, QVariant> itemData(const QModelIndex &index) const override;
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
+ QModelIndex parent(const QModelIndex &index) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override;
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
+protected:
+ QTransposeProxyModel(QTransposeProxyModelPrivate &, QObject *parent);
+};
+
+QT_END_NAMESPACE
+
+#endif // QTRANSPOSEPROXYMODEL_H
diff --git a/src/corelib/itemmodels/qtransposeproxymodel_p.h b/src/corelib/itemmodels/qtransposeproxymodel_p.h
new file mode 100644
index 0000000000..240fc4ccae
--- /dev/null
+++ b/src/corelib/itemmodels/qtransposeproxymodel_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPOSEPROXYMODEL_P_H
+#define QTRANSPOSEPROXYMODEL_P_H
+
+#include "qtransposeproxymodel.h"
+#include <private/qabstractproxymodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTransposeProxyModelPrivate : public QAbstractProxyModelPrivate
+{
+ Q_DECLARE_PUBLIC(QTransposeProxyModel)
+ Q_DISABLE_COPY(QTransposeProxyModelPrivate)
+private:
+ QTransposeProxyModelPrivate() = default;
+ QVector<QMetaObject::Connection> sourceConnections;
+ QVector<QPersistentModelIndex> layoutChangePersistentIndexes;
+ QModelIndexList layoutChangeProxyIndexes;
+ QModelIndex uncheckedMapToSource(const QModelIndex &proxyIndex) const;
+ QModelIndex uncheckedMapFromSource(const QModelIndex &sourceIndex) const;
+ void onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
+ void onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint);
+ void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles);
+ void onHeaderDataChanged(Qt::Orientation orientation, int first, int last);
+ void onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn);
+ void onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow);
+};
+
+QT_END_NAMESPACE
+
+#endif //QTRANSPOSEPROXYMODEL_P_H