1 /* 2 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 3 * 4 * This file is part of the KD Chart library. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef KCHARTDATASETPROXYMODEL_H 21 #define KCHARTDATASETPROXYMODEL_H 22 23 #include <QVector> 24 #include <QSortFilterProxyModel> 25 26 #include "kchart_export.h" 27 28 namespace KChart { 29 30 class IndexOutOfBoundsException; 31 32 typedef QVector<int> DatasetDescriptionVector; 33 34 /** DatasetProxyModel takes a KChart dataset configuration and translates 35 it into a filtering proxy model. 36 37 The resulting model will only contain the part of the model that is 38 selected by the dataset, and the according row and column header 39 data. 40 41 Currently, this model is implemented for table models only. The way it 42 would work with models representing a tree is to be decided. 43 44 The column selection is configured by passing a dataset description 45 vector to the model. This vector (of integers) is supposed to have one 46 value for each column of the original model. If the value at position 47 x is -1, column x of the original model is not included in the 48 dataset. If it is between 0 and (columnCount() -1), it is the column 49 the source column is mapped to in the resulting model. Any other value 50 is an error. 51 */ 52 class KCHART_EXPORT DatasetProxyModel : public QSortFilterProxyModel 53 { 54 Q_OBJECT 55 public: 56 /** Create a DatasetProxyModel. 57 Without further configuration, this model is invalid. 58 @see setDatasetDescriptionVector 59 */ 60 explicit DatasetProxyModel ( QObject* parent = nullptr ); 61 62 QModelIndex buddy( const QModelIndex& index ) const override; 63 64 Qt::ItemFlags flags( const QModelIndex& index ) const override; 65 66 QModelIndex index( int row, int column, 67 const QModelIndex &parent = QModelIndex() ) const override; 68 QModelIndex parent(const QModelIndex &child ) const override; 69 70 /** Implements the mapping from the source to the proxy indexes. */ 71 QModelIndex mapFromSource ( const QModelIndex & sourceIndex ) const override; 72 73 /** Implements the mapping from the proxy to the source indexes. */ 74 QModelIndex mapToSource ( const QModelIndex& proxyIndex ) const override; 75 76 /** Overloaded from base class. */ 77 QVariant data(const QModelIndex &index, int role) const override; 78 79 /** Overloaded from base class. */ 80 bool setData( const QModelIndex& index, const QVariant& value, int role ) override; 81 82 /** Overloaded from base class. */ 83 QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; 84 85 /** Overloaded from base class. */ 86 void setSourceModel(QAbstractItemModel *sourceModel) override; 87 88 /** Set the root index of the table in 89 the source model */ 90 void setSourceRootIndex(const QModelIndex& rootIdx); 91 92 93 public Q_SLOTS: 94 /** Reset all dataset description. 95 After that, the result of the proxying is an empty model (a new 96 dataset description needs to be set to achieve a non-empty result). 97 */ 98 void resetDatasetDescriptions(); 99 100 /** Configure the dataset selection for the columns. 101 Every call to this method resets the previous dataset 102 description. 103 */ 104 void setDatasetColumnDescriptionVector ( const DatasetDescriptionVector& columnConfig ); 105 106 /** Configure the dataset selection for the rows. 107 Every call to this method resets the previous dataset 108 description. 109 */ 110 void setDatasetRowDescriptionVector ( const DatasetDescriptionVector& rowConfig ); 111 112 /** Convenience method to configure rows and columns in one step. */ 113 void setDatasetDescriptionVectors ( 114 const DatasetDescriptionVector& rowConfig, 115 const DatasetDescriptionVector& columnConfig ); 116 117 // FIXME: add convenience methods to configure common dataset 118 // selections (like rectangular areas etc) 119 120 protected: 121 /** Decide whether the column is accepted. */ 122 bool filterAcceptsColumn ( int sourceColumn, 123 const QModelIndex & ) const override; 124 125 126 /** Decide whether the row is accepted. */ 127 bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const override; 128 129 private: 130 131 /** Map a proxy column to a source column. */ 132 int mapProxyColumnToSource ( const int& proxyColumn ) const; 133 134 /** Map a source column to a proxy column. */ 135 int mapSourceColumnToProxy ( const int& sourceColumn ) const; 136 137 /** Map a proxy row to a source row. */ 138 int mapProxyRowToSource ( const int& proxyRow ) const; 139 140 /** Map a source row to a proxy row. */ 141 int mapSourceRowToProxy ( const int& sourceRow ) const; 142 143 /** Initialize the transformation vectors from the dataset 144 description. 145 146 The input parameter "Configuration" is a vector that specifies 147 what srce column will be mapped to what proxy column. Example: 148 149 position: [0][1][2] 150 value: [2][0][1] 151 152 This will map the source column 2 to proxy column 0, source 0 to 153 proxy 1, and source 1 to proxy 2. Source needs to have at least 2 154 column. The source-to-proxy mapping looks the same, except that it 155 may contain values of -1, which means this column is not part of 156 the resulting model. The values in the configuration vector must 157 be unique (otherwise, a 1-to-1 mapping in both directions is 158 impossible). 159 160 sourceCount is the number of columns in the source model. The proxy-to-source map has 161 as many elements as the proxy has columns, the source-to-proxy map 162 has as many elements as the source has columns. Same goes for rows 163 (the mapping logic is the same). 164 165 */ 166 void initializeDatasetDecriptors ( 167 const DatasetDescriptionVector& inConfiguration, 168 int sourceCount, 169 DatasetDescriptionVector& outSourceToProxyMap, 170 DatasetDescriptionVector& outProxyToSourceMap ); 171 172 DatasetDescriptionVector mColSrcToProxyMap; 173 DatasetDescriptionVector mColProxyToSrcMap; 174 DatasetDescriptionVector mRowSrcToProxyMap; 175 DatasetDescriptionVector mRowProxyToSrcMap; 176 177 int mProxyRowCount; 178 int mProxyColumnCount; 179 QModelIndex mRootIndex; 180 }; 181 182 } 183 184 185 #endif 186