KItemModels

krearrangecolumnsproxymodel.cpp
1 /*
2  SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
3  SPDX-FileContributor: David Faure <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "krearrangecolumnsproxymodel.h"
9 
10 class KRearrangeColumnsProxyModelPrivate
11 {
12 public:
13  QVector<int> m_sourceColumns;
14 };
15 
17  : QIdentityProxyModel(parent)
18  , d_ptr(new KRearrangeColumnsProxyModelPrivate)
19 {
20 }
21 
23 {
24 }
25 
27 {
28  // We could use layoutChanged() here, but we would have to map persistent
29  // indexes from the old to the new location...
31  d_ptr->m_sourceColumns = columns;
32  endResetModel();
33 }
34 
36 {
37  Q_UNUSED(parent);
38  if (!sourceModel()) {
39  return 0;
40  }
41  return d_ptr->m_sourceColumns.count();
42 }
43 
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(parent).sibling(parent.row(), 0);
55  return sourceModel()->rowCount(sourceParent);
56 }
57 
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(parent).sibling(parent.row(), 0);
71  return sourceModel()->rowCount(sourceParent) > 0;
72 }
73 
74 // We derive from QIdentityProxyModel simply to be able to use
75 // its mapFromSource method which has friend access to createIndex() in the source model.
76 
78 {
79  Q_ASSERT(parent.isValid() ? parent.model() == this : true);
80 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
81  Q_ASSERT(row >= 0);
82 #else
83  // workaround for QTreeView bug, fixed in https://codereview.qt-project.org/c/qt/qtbase/+/293092
84  if (row < 0) {
85  return {};
86  }
87 #endif
88  Q_ASSERT(column >= 0);
89 
90  // Only first column has children
91  if (parent.column() > 0) {
92  return {};
93  }
94 
95  if (!sourceModel()) {
96  return {};
97  }
98  if (d_ptr->m_sourceColumns.isEmpty()) {
99  return {};
100  }
101 
102  // The parent in the source model is on column 0, whatever swapping we are doing
103  const QModelIndex sourceParent = mapToSource(parent).sibling(parent.row(), 0);
104 
105  // Find the child in the source model, we need its internal pointer
106  const QModelIndex sourceIndex = sourceModel()->index(row, sourceColumnForProxyColumn(column), sourceParent);
107  if (!sourceIndex.isValid()) {
108  return QModelIndex();
109  }
110 
111  return createIndex(row, column, sourceIndex.internalPointer());
112 }
113 
115 {
116  Q_ASSERT(child.isValid() ? child.model() == this : true);
117  const QModelIndex sourceIndex = mapToSource(child);
118  const QModelIndex sourceParent = sourceIndex.parent();
119  if (!sourceParent.isValid()) {
120  return QModelIndex();
121  }
122  return createIndex(sourceParent.row(), 0, sourceParent.internalPointer());
123 }
124 
125 QVariant KRearrangeColumnsProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
126 {
127  if (orientation == Qt::Horizontal) {
128  if (!sourceModel() || section >= d_ptr->m_sourceColumns.count()) {
129  return QVariant();
130  }
131  const int sourceCol = sourceColumnForProxyColumn(section);
132  return sourceModel()->headerData(sourceCol, orientation, role);
133  } else {
134  return QIdentityProxyModel::headerData(section, orientation, role);
135  }
136 }
137 
138 QModelIndex KRearrangeColumnsProxyModel::sibling(int row, int column, const QModelIndex &idx) const
139 {
140  if (column >= d_ptr->m_sourceColumns.count()) {
141  return QModelIndex();
142  }
143  return index(row, column, idx.parent());
144 }
145 
147 {
148  if (!sourceIndex.isValid()) {
149  return QModelIndex();
150  }
151  Q_ASSERT(sourceIndex.model() == sourceModel());
152  const int proxyColumn = proxyColumnForSourceColumn(sourceIndex.column());
153  return createIndex(sourceIndex.row(), proxyColumn, sourceIndex.internalPointer());
154 }
155 
157 {
158  if (!proxyIndex.isValid()) {
159  return QModelIndex();
160  }
161  // This is just an indirect way to call sourceModel->createIndex(row, sourceColumn, pointer)
162  const QModelIndex fakeIndex = createIndex(proxyIndex.row(), sourceColumnForProxyColumn(proxyIndex.column()), proxyIndex.internalPointer());
163  return QIdentityProxyModel::mapToSource(fakeIndex);
164 }
165 
167 {
168  // If this is too slow, we could add a second QVector with index=logical_source_column value=desired_pos_in_proxy.
169  return d_ptr->m_sourceColumns.indexOf(sourceColumn);
170 }
171 
173 {
174  Q_ASSERT(proxyColumn >= 0);
175  Q_ASSERT(proxyColumn < d_ptr->m_sourceColumns.size());
176  return d_ptr->m_sourceColumns.at(proxyColumn);
177 }
virtual int rowCount(const QModelIndex &parent) const const =0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const =0
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const const override
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
int sourceColumnForProxyColumn(int proxyColumn) const
Returns the source column for the given proxy column.
int proxyColumnForSourceColumn(int sourceColumn) const
Returns the proxy column for the given source column or -1 if the source column isn&#39;t shown in the pr...
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
bool isValid() const const
QModelIndex sibling(int row, int column, const QModelIndex &idx) const override
~KRearrangeColumnsProxyModel() override
Destructor.
int row() const const
void * internalPointer() const const
QModelIndex parent() const const
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const const
QModelIndex createIndex(int row, int column, void *ptr) const const
KRearrangeColumnsProxyModel(QObject *parent=nullptr)
Creates a KRearrangeColumnsProxyModel proxy.
QAbstractItemModel * sourceModel() const const
const QAbstractItemModel * model() const const
QModelIndex sibling(int row, int column) const const
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
int column() const const
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
Orientation
void setSourceColumns(const QVector< int > &columns)
Set the chosen source columns, in the desired order for the proxy columns columns[proxyColumn=0] is t...
QObject * parent() const const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:51:10 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.