KD Chart 2  [rev.2.7]
KDChartDatasetProxyModel.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 ** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
3 **
4 ** This file is part of the KD Chart library.
5 **
6 ** Licensees holding valid commercial KD Chart licenses may use this file in
7 ** accordance with the KD Chart Commercial License Agreement provided with
8 ** the Software.
9 **
10 **
11 ** This file may be distributed and/or modified under the terms of the
12 ** GNU General Public License version 2 and version 3 as published by the
13 ** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
14 **
15 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 **
18 ** Contact info@kdab.com if any conditions of this licensing are not
19 ** clear to you.
20 **
21 **********************************************************************/
22 
24 
25 #include <QtDebug>
26 
27 #include <KDABLibFakes>
28 
29 
30 using namespace KDChart;
31 
33  : QSortFilterProxyModel( parent )
34 {
35 }
36 
37 QModelIndex DatasetProxyModel::buddy( const QModelIndex& index ) const
38 {
39  return index;
40 }
41 
42 Qt::ItemFlags DatasetProxyModel::flags( const QModelIndex& index ) const
43 {
44  return sourceModel()->flags( mapToSource( index ) );
45 }
46 
48  const DatasetDescriptionVector& configuration )
49 {
50  Q_ASSERT_X( sourceModel(), "DatasetProxyModel::setDatasetRowDescriptionVector",
51  "A source model must be set before the selection can be configured." );
52  initializeDatasetDecriptors( configuration, sourceModel()->rowCount(mRootIndex),
53  mRowSrcToProxyMap, mRowProxyToSrcMap );
54  clear(); // clear emits layoutChanged()
55 }
56 
58  const DatasetDescriptionVector& configuration )
59 {
60  Q_ASSERT_X( sourceModel(), "DatasetProxyModel::setDatasetColumnDescriptionVector",
61  "A source model must be set before the selection can be configured." );
62  initializeDatasetDecriptors( configuration, sourceModel()->columnCount(mRootIndex),
63  mColSrcToProxyMap, mColProxyToSrcMap );
64  clear(); // clear emits layoutChanged()
65 }
66 
68  const DatasetDescriptionVector& rowConfig,
69  const DatasetDescriptionVector& columnConfig )
70 {
71  setDatasetRowDescriptionVector( rowConfig );
72  setDatasetColumnDescriptionVector( columnConfig );
73 }
74 
75 QModelIndex DatasetProxyModel::index( int row, int column,
76  const QModelIndex &parent ) const
77 {
78  return mapFromSource( sourceModel()->index( mapProxyRowToSource(row),
79  mapProxyColumnToSource(column),
80  parent ) );
81 }
82 
83 QModelIndex DatasetProxyModel::parent( const QModelIndex& child ) const
84 {
85 // return mapFromSource( sourceModel()->parent( child ) );
86  return mapFromSource( sourceModel()->parent( mapToSource( child ) ) );
87 }
88 
89 QModelIndex DatasetProxyModel::mapFromSource( const QModelIndex & sourceIndex ) const
90 {
91  Q_ASSERT_X( sourceModel(), "DatasetProxyModel::mapFromSource", "A source "
92  "model must be set before the selection can be configured." );
93 
94  if ( !sourceIndex.isValid() ) return sourceIndex;
95 
96  if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
97  {
98  return createIndex( sourceIndex.row(), sourceIndex.column(),
99  sourceIndex.internalPointer() );
100  } else {
101  int row = mapSourceRowToProxy( sourceIndex.row() );
102  int column = mapSourceColumnToProxy( sourceIndex.column() );
103  return createIndex( row, column, sourceIndex.internalPointer() );
104  }
105 }
106 
107 QModelIndex DatasetProxyModel::mapToSource( const QModelIndex& proxyIndex ) const
108 {
109  Q_ASSERT_X( sourceModel(), "DatasetProxyModel::mapToSource", "A source "
110  "model must be set before the selection can be configured." );
111 
112  if ( !proxyIndex.isValid() ) return proxyIndex;
113  if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
114  {
115  return sourceModel()->index( proxyIndex.row(), proxyIndex.column(), mRootIndex );
116  } else {
117  int row = mapProxyRowToSource( proxyIndex.row() );
118  int column = mapProxyColumnToSource( proxyIndex.column() );
119  return sourceModel()->index( row, column, mRootIndex );
120  }
121 }
122 
124  const QModelIndex & ) const
125 {
126  if ( mRowSrcToProxyMap.isEmpty() )
127  { // no row mapping set, all rows are passed down:
128  return true;
129  } else {
130  Q_ASSERT( sourceModel() );
131  Q_ASSERT( mRowSrcToProxyMap.size() == sourceModel()->rowCount(mRootIndex) );
132  if ( mRowSrcToProxyMap[sourceRow] == -1 )
133  { // this row is explicitly not accepted:
134  return false;
135  } else {
136  Q_ASSERT( mRowSrcToProxyMap[sourceRow] >= 0
137  && mRowSrcToProxyMap[sourceRow] < mRowSrcToProxyMap.size() );
138  return true;
139  }
140  }
141 }
142 
144  const QModelIndex & ) const
145 {
146  if ( mColSrcToProxyMap.isEmpty() )
147  { // no column mapping set up yet, all columns are passed down:
148  return true;
149  } else {
150  Q_ASSERT( sourceModel() );
151  Q_ASSERT( mColSrcToProxyMap.size() == sourceModel()->columnCount(mRootIndex) );
152  if ( mColSrcToProxyMap[sourceColumn] == -1 )
153  { // this column is explicitly not accepted:
154  return false;
155  } else {
156  Q_ASSERT( mColSrcToProxyMap[sourceColumn] >= 0
157  && mColSrcToProxyMap[sourceColumn] < mColSrcToProxyMap.size() );
158  return true;
159  }
160  }
161 }
162 
163 int DatasetProxyModel::mapProxyRowToSource( const int& proxyRow ) const
164 {
165  if ( mRowProxyToSrcMap.isEmpty() )
166  { // if no row mapping is set, we pass down the row:
167  return proxyRow;
168  } else {
169  Q_ASSERT( proxyRow >= 0 && proxyRow < mRowProxyToSrcMap.size() );
170  return mRowProxyToSrcMap[ proxyRow ];
171  }
172 }
173 
174 int DatasetProxyModel::mapProxyColumnToSource( const int& proxyColumn ) const
175 {
176  if ( mColProxyToSrcMap.isEmpty() )
177  { // if no column mapping is set, we pass down the column:
178  return proxyColumn;
179  } else {
180  Q_ASSERT( proxyColumn >= 0 && proxyColumn < mColProxyToSrcMap.size() );
181  return mColProxyToSrcMap[ proxyColumn ];
182  }
183 }
184 
185 int DatasetProxyModel::mapSourceRowToProxy( const int& sourceRow ) const
186 {
187  if ( mRowSrcToProxyMap.isEmpty() )
188  {
189  return sourceRow;
190  } else {
191  Q_ASSERT( sourceRow >= 0 && sourceRow < mRowSrcToProxyMap.size() );
192  return mRowSrcToProxyMap[sourceRow];
193  }
194 }
195 
196 int DatasetProxyModel::mapSourceColumnToProxy( const int& sourceColumn ) const
197 {
198  if ( mColSrcToProxyMap.isEmpty() )
199  {
200  return sourceColumn;
201  } else {
202  Q_ASSERT( sourceColumn >= 0 && sourceColumn < mColSrcToProxyMap.size() );
203  return mColSrcToProxyMap.at( sourceColumn ) ;
204  }
205 }
206 
208 {
209  mRowSrcToProxyMap.clear();
210  mRowProxyToSrcMap.clear();
211  mColSrcToProxyMap.clear();
212  mColProxyToSrcMap.clear();
213  clear();
214 }
215 
216 QVariant DatasetProxyModel::data(const QModelIndex &index, int role) const
217 {
218  return sourceModel()->data( mapToSource( index ), role );
219 }
220 
221 bool DatasetProxyModel::setData( const QModelIndex& index, const QVariant& value, int role )
222 {
223  return sourceModel()->setData( mapToSource( index ), value, role );
224 }
225 
226 QVariant DatasetProxyModel::headerData( int section, Qt::Orientation orientation, int role ) const
227 {
228  if ( orientation == Qt::Horizontal )
229  {
230  if ( mapProxyColumnToSource ( section ) == -1 )
231  {
232  return QVariant();
233  } else {
234  return sourceModel()->headerData( mapProxyColumnToSource( section ), orientation, role );
235  }
236  } else {
237  if ( mapProxyRowToSource ( section ) == -1 )
238  {
239  return QVariant();
240  } else {
241  return sourceModel()->headerData( mapProxyRowToSource ( section ), orientation, role );
242  }
243  }
244 }
245 
246 void DatasetProxyModel::initializeDatasetDecriptors(
247  const DatasetDescriptionVector& inConfiguration,
248  const int sourceCount,
249  DatasetDescriptionVector& outSourceToProxyMap,
250  DatasetDescriptionVector& outProxyToSourceMap )
251 {
252  // in the current mapping implementation, the proxy-to-source map is
253  // identical to the configuration vector:
254  outProxyToSourceMap = inConfiguration;
255  outSourceToProxyMap.fill( -1, sourceCount );
256 
257  for ( int index = 0; index < inConfiguration.size(); ++index ) {
258  // make sure the values in inConfiguration point to columns in the
259  // source model:
260 
261  if ( inConfiguration[index] == -1 ) {
262  continue;
263  }
264 
265  Q_ASSERT_X( inConfiguration[ index ] >= 0 && inConfiguration[ index ] < sourceCount,
266  "DatasetProxyModel::initializeDatasetDecriptors",
267  "column index outside of source model" );
268  Q_ASSERT_X( outSourceToProxyMap[ inConfiguration[ index ] ] == -1 ,
269  "DatasetProxyModel::initializeDatasetDecriptors",
270  "no duplicates allowed in mapping configuration, mapping has to be reversible" );
271 
272  outSourceToProxyMap[ inConfiguration[ index ] ] = index;
273  }
274 }
275 
276 void DatasetProxyModel::setSourceModel(QAbstractItemModel *m)
277 {
278  if ( sourceModel() ) {
279  disconnect( sourceModel(), SIGNAL( layoutChanged() ),
280  this, SLOT( resetDatasetDescriptions() ) );
281  }
282  QSortFilterProxyModel::setSourceModel( m );
283  mRootIndex = QModelIndex();
284  if ( m ) {
285  connect( m, SIGNAL( layoutChanged() ),
286  this, SLOT( resetDatasetDescriptions() ) );
287  connect( m, SIGNAL( layoutChanged() ), this, SIGNAL( layoutChanged() ) );
288  }
290 }
291 
292 void DatasetProxyModel::setSourceRootIndex(const QModelIndex& rootIdx)
293 {
294  mRootIndex = rootIdx;
296 }
297 
DatasetProxyModel(QObject *parent=0)
Create a DatasetProxyModel.
void setDatasetDescriptionVectors(const DatasetDescriptionVector &rowConfig, const DatasetDescriptionVector &columnConfig)
Convenience method to configure rows and columns in one step.
void setSourceModel(QAbstractItemModel *sourceModel) override
Overloaded from base class.
void resetDatasetDescriptions()
Reset all dataset description.
void setDatasetRowDescriptionVector(const DatasetDescriptionVector &rowConfig)
Configure the dataset selection for the rows.
bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const override
Decide whether the column is accepted.
QModelIndex buddy(const QModelIndex &index) const override
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
Decide whether the row is accepted.
QVariant data(const QModelIndex &index, int role) const override
Overloaded from base class.
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Overloaded from base class.
void setDatasetColumnDescriptionVector(const DatasetDescriptionVector &columnConfig)
Configure the dataset selection for the columns.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Overloaded from base class.
Class only listed here to document inheritance of some KDChart classes.
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
Implements the mapping from the source to the proxy indexes.
QModelIndex parent(const QModelIndex &child) const override
Class only listed here to document inheritance of some KDChart classes.
void setSourceRootIndex(const QModelIndex &rootIdx)
Set the root index of the table in the source model.
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
Implements the mapping from the proxy to the source indexes.
Qt::ItemFlags flags(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override

Klarälvdalens Datakonsult AB (KDAB)
Qt-related services and products
https://www.kdab.com/
https://www.kdab.com/products/kd-chart/