File indexing completed on 2024-05-05 03:56:42
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"