1/*
2 SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
3 SPDX-FileContributor: David Faure <david.faure@kdab.com>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "krearrangecolumnsproxymodel.h"
9
10class KRearrangeColumnsProxyModelPrivate
11{
12public:
13 QList<int> m_sourceColumns;
14};
15
16KRearrangeColumnsProxyModel::KRearrangeColumnsProxyModel(QObject *parent)
17 : QIdentityProxyModel(parent)
18 , d_ptr(new KRearrangeColumnsProxyModelPrivate)
19{
20}
21
22KRearrangeColumnsProxyModel::~KRearrangeColumnsProxyModel()
23{
24}
25
26void KRearrangeColumnsProxyModel::setSourceColumns(const QList<int> &columns)
27{
28 // We could use layoutChanged() here, but we would have to map persistent
29 // indexes from the old to the new location...
30 beginResetModel();
31 d_ptr->m_sourceColumns = columns;
32 endResetModel();
33}
34
35int KRearrangeColumnsProxyModel::columnCount(const QModelIndex &parent) const
36{
37 Q_UNUSED(parent);
38 if (!sourceModel()) {
39 return 0;
40 }
41 return d_ptr->m_sourceColumns.count();
42}
43
44int KRearrangeColumnsProxyModel::rowCount(const QModelIndex &parent) const
45{
46 Q_ASSERT(parent.isValid() ? parent.model() == this : true);
47 if (!sourceModel()) {
48 return 0;
49 }
50 if (parent.column() > 0) {
51 return 0;
52 }
53 // The parent in the source model is on column 0, whatever swapping we are doing
54 const QModelIndex sourceParent = mapToSource(proxyIndex: parent).sibling(arow: parent.row(), acolumn: 0);
55 return sourceModel()->rowCount(parent: sourceParent);
56}
57
58bool KRearrangeColumnsProxyModel::hasChildren(const QModelIndex &parent) const
59{
60 Q_ASSERT(parent.isValid() ? parent.model() == this : true);
61 if (!sourceModel()) {
62 return false;
63 }
64 if (d_ptr->m_sourceColumns.isEmpty()) { // no columns configured yet
65 return false;
66 }
67 if (parent.column() > 0) {
68 return false;
69 }
70 const QModelIndex sourceParent = mapToSource(proxyIndex: parent).sibling(arow: parent.row(), acolumn: 0);
71 return sourceModel()->rowCount(parent: sourceParent) > 0;
72}
73
74QModelIndex KRearrangeColumnsProxyModel::index(int row, int column, const QModelIndex &parent) const
75{
76 Q_ASSERT(parent.isValid() ? parent.model() == this : true);
77 Q_ASSERT(row >= 0);
78 Q_ASSERT(column >= 0);
79
80 // Only first column has children
81 if (parent.column() > 0) {
82 return {};
83 }
84
85 if (!sourceModel()) {
86 return {};
87 }
88 if (d_ptr->m_sourceColumns.isEmpty()) {
89 return {};
90 }
91
92 // The parent in the source model is on column 0, whatever swapping we are doing
93 const QModelIndex sourceParent = mapToSource(proxyIndex: parent).sibling(arow: parent.row(), acolumn: 0);
94
95 // Find the child in the source model, we need its internal pointer
96 const QModelIndex sourceIndex = sourceModel()->index(row, column: sourceColumnForProxyColumn(proxyColumn: column), parent: sourceParent);
97 if (!sourceIndex.isValid()) {
98 return QModelIndex();
99 }
100
101 return createIndex(arow: row, acolumn: column, adata: sourceIndex.internalPointer());
102}
103
104QModelIndex KRearrangeColumnsProxyModel::parent(const QModelIndex &child) const
105{
106 Q_ASSERT(child.isValid() ? child.model() == this : true);
107 const QModelIndex sourceIndex = mapToSource(proxyIndex: child);
108 const QModelIndex sourceParent = sourceIndex.parent();
109 if (!sourceParent.isValid()) {
110 return QModelIndex();
111 }
112 return createIndex(arow: sourceParent.row(), acolumn: 0, adata: sourceParent.internalPointer());
113}
114
115QVariant KRearrangeColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
116{
117 if (orientation == Qt::Horizontal) {
118 if (!sourceModel() || section >= d_ptr->m_sourceColumns.count()) {
119 return QVariant();
120 }
121 const int sourceCol = sourceColumnForProxyColumn(proxyColumn: section);
122 return sourceModel()->headerData(section: sourceCol, orientation, role);
123 } else {
124 return QIdentityProxyModel::headerData(section, orientation, role);
125 }
126}
127
128QModelIndex KRearrangeColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const
129{
130 if (column >= d_ptr->m_sourceColumns.count()) {
131 return QModelIndex();
132 }
133 return index(row, column, parent: idx.parent());
134}
135
136QModelIndex KRearrangeColumnsProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
137{
138 if (!sourceIndex.isValid()) {
139 return QModelIndex();
140 }
141 Q_ASSERT(sourceIndex.model() == sourceModel());
142 const int proxyColumn = proxyColumnForSourceColumn(sourceColumn: sourceIndex.column());
143 return createIndex(arow: sourceIndex.row(), acolumn: proxyColumn, adata: sourceIndex.internalPointer());
144}
145
146QModelIndex KRearrangeColumnsProxyModel::mapToSource(const QModelIndex &proxyIndex) const
147{
148 if (!proxyIndex.isValid()) {
149 return QModelIndex();
150 }
151 return createSourceIndex(row: proxyIndex.row(), col: sourceColumnForProxyColumn(proxyColumn: proxyIndex.column()), internalPtr: proxyIndex.internalPointer());
152}
153
154int KRearrangeColumnsProxyModel::proxyColumnForSourceColumn(int sourceColumn) const
155{
156 // If this is too slow, we could add a second QList with index=logical_source_column value=desired_pos_in_proxy.
157 return d_ptr->m_sourceColumns.indexOf(t: sourceColumn);
158}
159
160int KRearrangeColumnsProxyModel::sourceColumnForProxyColumn(int proxyColumn) const
161{
162 Q_ASSERT(proxyColumn >= 0);
163 Q_ASSERT(proxyColumn < d_ptr->m_sourceColumns.size());
164 return d_ptr->m_sourceColumns.at(i: proxyColumn);
165}
166
167#include "moc_krearrangecolumnsproxymodel.cpp"
168

source code of kitemmodels/src/core/krearrangecolumnsproxymodel.cpp