Warning, file /frameworks/kitemmodels/src/core/krearrangecolumnsproxymodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
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 QVector<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 QVector<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 // We derive from QIdentityProxyModel simply to be able to use 0075 // its mapFromSource method which has friend access to createIndex() in the source model. 0076 0077 QModelIndex KRearrangeColumnsProxyModel::index(int row, int column, const QModelIndex &parent) const 0078 { 0079 Q_ASSERT(parent.isValid() ? parent.model() == this : true); 0080 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0081 Q_ASSERT(row >= 0); 0082 #else 0083 // workaround for QTreeView bug, fixed in https://codereview.qt-project.org/c/qt/qtbase/+/293092 0084 if (row < 0) { 0085 return {}; 0086 } 0087 #endif 0088 Q_ASSERT(column >= 0); 0089 0090 // Only first column has children 0091 if (parent.column() > 0) { 0092 return {}; 0093 } 0094 0095 if (!sourceModel()) { 0096 return {}; 0097 } 0098 if (d_ptr->m_sourceColumns.isEmpty()) { 0099 return {}; 0100 } 0101 0102 // The parent in the source model is on column 0, whatever swapping we are doing 0103 const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0); 0104 0105 // Find the child in the source model, we need its internal pointer 0106 const QModelIndex sourceIndex = sourceModel()->index(row, sourceColumnForProxyColumn(column), sourceParent); 0107 if (!sourceIndex.isValid()) { 0108 return QModelIndex(); 0109 } 0110 0111 return createIndex(row, column, sourceIndex.internalPointer()); 0112 } 0113 0114 QModelIndex KRearrangeColumnsProxyModel::parent(const QModelIndex &child) const 0115 { 0116 Q_ASSERT(child.isValid() ? child.model() == this : true); 0117 const QModelIndex sourceIndex = mapToSource(child); 0118 const QModelIndex sourceParent = sourceIndex.parent(); 0119 if (!sourceParent.isValid()) { 0120 return QModelIndex(); 0121 } 0122 return createIndex(sourceParent.row(), 0, sourceParent.internalPointer()); 0123 } 0124 0125 QVariant KRearrangeColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const 0126 { 0127 if (orientation == Qt::Horizontal) { 0128 if (!sourceModel() || section >= d_ptr->m_sourceColumns.count()) { 0129 return QVariant(); 0130 } 0131 const int sourceCol = sourceColumnForProxyColumn(section); 0132 return sourceModel()->headerData(sourceCol, orientation, role); 0133 } else { 0134 return QIdentityProxyModel::headerData(section, orientation, role); 0135 } 0136 } 0137 0138 QModelIndex KRearrangeColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const 0139 { 0140 if (column >= d_ptr->m_sourceColumns.count()) { 0141 return QModelIndex(); 0142 } 0143 return index(row, column, idx.parent()); 0144 } 0145 0146 QModelIndex KRearrangeColumnsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const 0147 { 0148 if (!sourceIndex.isValid()) { 0149 return QModelIndex(); 0150 } 0151 Q_ASSERT(sourceIndex.model() == sourceModel()); 0152 const int proxyColumn = proxyColumnForSourceColumn(sourceIndex.column()); 0153 return createIndex(sourceIndex.row(), proxyColumn, sourceIndex.internalPointer()); 0154 } 0155 0156 QModelIndex KRearrangeColumnsProxyModel::mapToSource(const QModelIndex &proxyIndex) const 0157 { 0158 if (!proxyIndex.isValid()) { 0159 return QModelIndex(); 0160 } 0161 // This is just an indirect way to call sourceModel->createIndex(row, sourceColumn, pointer) 0162 const QModelIndex fakeIndex = createIndex(proxyIndex.row(), sourceColumnForProxyColumn(proxyIndex.column()), proxyIndex.internalPointer()); 0163 return QIdentityProxyModel::mapToSource(fakeIndex); 0164 } 0165 0166 int KRearrangeColumnsProxyModel::proxyColumnForSourceColumn(int sourceColumn) const 0167 { 0168 // If this is too slow, we could add a second QVector with index=logical_source_column value=desired_pos_in_proxy. 0169 return d_ptr->m_sourceColumns.indexOf(sourceColumn); 0170 } 0171 0172 int KRearrangeColumnsProxyModel::sourceColumnForProxyColumn(int proxyColumn) const 0173 { 0174 Q_ASSERT(proxyColumn >= 0); 0175 Q_ASSERT(proxyColumn < d_ptr->m_sourceColumns.size()); 0176 return d_ptr->m_sourceColumns.at(proxyColumn); 0177 } 0178 0179 #include "moc_krearrangecolumnsproxymodel.cpp"