File indexing completed on 2024-07-21 06:38:22

0001 /*
0002     SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003     SPDX-FileContributor: David Faure <david.faure@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "krearrangecolumnsproxymodel.h"
0009 
0010 class KRearrangeColumnsProxyModelPrivate
0011 {
0012 public:
0013     QList<int> m_sourceColumns;
0014 };
0015 
0016 KRearrangeColumnsProxyModel::KRearrangeColumnsProxyModel(QObject *parent)
0017     : QIdentityProxyModel(parent)
0018     , d_ptr(new KRearrangeColumnsProxyModelPrivate)
0019 {
0020 }
0021 
0022 KRearrangeColumnsProxyModel::~KRearrangeColumnsProxyModel()
0023 {
0024 }
0025 
0026 void KRearrangeColumnsProxyModel::setSourceColumns(const QList<int> &columns)
0027 {
0028     // We could use layoutChanged() here, but we would have to map persistent
0029     // indexes from the old to the new location...
0030     beginResetModel();
0031     d_ptr->m_sourceColumns = columns;
0032     endResetModel();
0033 }
0034 
0035 int KRearrangeColumnsProxyModel::columnCount(const QModelIndex &parent) const
0036 {
0037     Q_UNUSED(parent);
0038     if (!sourceModel()) {
0039         return 0;
0040     }
0041     return d_ptr->m_sourceColumns.count();
0042 }
0043 
0044 int KRearrangeColumnsProxyModel::rowCount(const QModelIndex &parent) const
0045 {
0046     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
0047     if (!sourceModel()) {
0048         return 0;
0049     }
0050     if (parent.column() > 0) {
0051         return 0;
0052     }
0053     // The parent in the source model is on column 0, whatever swapping we are doing
0054     const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0);
0055     return sourceModel()->rowCount(sourceParent);
0056 }
0057 
0058 bool KRearrangeColumnsProxyModel::hasChildren(const QModelIndex &parent) const
0059 {
0060     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
0061     if (!sourceModel()) {
0062         return false;
0063     }
0064     if (d_ptr->m_sourceColumns.isEmpty()) { // no columns configured yet
0065         return false;
0066     }
0067     if (parent.column() > 0) {
0068         return false;
0069     }
0070     const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0);
0071     return sourceModel()->rowCount(sourceParent) > 0;
0072 }
0073 
0074 QModelIndex KRearrangeColumnsProxyModel::index(int row, int column, const QModelIndex &parent) const
0075 {
0076     Q_ASSERT(parent.isValid() ? parent.model() == this : true);
0077     Q_ASSERT(row >= 0);
0078     Q_ASSERT(column >= 0);
0079 
0080     // Only first column has children
0081     if (parent.column() > 0) {
0082         return {};
0083     }
0084 
0085     if (!sourceModel()) {
0086         return {};
0087     }
0088     if (d_ptr->m_sourceColumns.isEmpty()) {
0089         return {};
0090     }
0091 
0092     // The parent in the source model is on column 0, whatever swapping we are doing
0093     const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0);
0094 
0095     // Find the child in the source model, we need its internal pointer
0096     const QModelIndex sourceIndex = sourceModel()->index(row, sourceColumnForProxyColumn(column), sourceParent);
0097     if (!sourceIndex.isValid()) {
0098         return QModelIndex();
0099     }
0100 
0101     return createIndex(row, column, sourceIndex.internalPointer());
0102 }
0103 
0104 QModelIndex KRearrangeColumnsProxyModel::parent(const QModelIndex &child) const
0105 {
0106     Q_ASSERT(child.isValid() ? child.model() == this : true);
0107     const QModelIndex sourceIndex = mapToSource(child);
0108     const QModelIndex sourceParent = sourceIndex.parent();
0109     if (!sourceParent.isValid()) {
0110         return QModelIndex();
0111     }
0112     return createIndex(sourceParent.row(), 0, sourceParent.internalPointer());
0113 }
0114 
0115 QVariant KRearrangeColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
0116 {
0117     if (orientation == Qt::Horizontal) {
0118         if (!sourceModel() || section >= d_ptr->m_sourceColumns.count()) {
0119             return QVariant();
0120         }
0121         const int sourceCol = sourceColumnForProxyColumn(section);
0122         return sourceModel()->headerData(sourceCol, orientation, role);
0123     } else {
0124         return QIdentityProxyModel::headerData(section, orientation, role);
0125     }
0126 }
0127 
0128 QModelIndex KRearrangeColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const
0129 {
0130     if (column >= d_ptr->m_sourceColumns.count()) {
0131         return QModelIndex();
0132     }
0133     return index(row, column, idx.parent());
0134 }
0135 
0136 QModelIndex KRearrangeColumnsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
0137 {
0138     if (!sourceIndex.isValid()) {
0139         return QModelIndex();
0140     }
0141     Q_ASSERT(sourceIndex.model() == sourceModel());
0142     const int proxyColumn = proxyColumnForSourceColumn(sourceIndex.column());
0143     return createIndex(sourceIndex.row(), proxyColumn, sourceIndex.internalPointer());
0144 }
0145 
0146 QModelIndex KRearrangeColumnsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
0147 {
0148     if (!proxyIndex.isValid()) {
0149         return QModelIndex();
0150     }
0151     return createSourceIndex(proxyIndex.row(), sourceColumnForProxyColumn(proxyIndex.column()), proxyIndex.internalPointer());
0152 }
0153 
0154 int KRearrangeColumnsProxyModel::proxyColumnForSourceColumn(int sourceColumn) const
0155 {
0156     // If this is too slow, we could add a second QList with index=logical_source_column value=desired_pos_in_proxy.
0157     return d_ptr->m_sourceColumns.indexOf(sourceColumn);
0158 }
0159 
0160 int KRearrangeColumnsProxyModel::sourceColumnForProxyColumn(int proxyColumn) const
0161 {
0162     Q_ASSERT(proxyColumn >= 0);
0163     Q_ASSERT(proxyColumn < d_ptr->m_sourceColumns.size());
0164     return d_ptr->m_sourceColumns.at(proxyColumn);
0165 }
0166 
0167 #include "moc_krearrangecolumnsproxymodel.cpp"