File indexing completed on 2024-05-12 15:53:53
0001 /** 0002 * Copyright (C) 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved. 0003 * 0004 * This file is part of the KD Chart library. 0005 * 0006 * This program is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include <QtDebug> 0021 #include <QDebug> 0022 #include <QtTest/QtTest> 0023 #include <QStandardItem> 0024 #include <QStandardItemModel> 0025 0026 #include <KChartCartesianDiagramDataCompressor_p.h> 0027 0028 typedef KChart::CartesianDiagramDataCompressor::CachePosition CachePosition; 0029 0030 struct Match { 0031 Match( const CachePosition& pos, const QModelIndex& index ) 0032 : cachePosition( pos ), 0033 index( index ) 0034 { 0035 } 0036 CachePosition cachePosition; 0037 QModelIndex index; 0038 }; 0039 0040 class CartesianDiagramDataCompressorTests : public QObject 0041 { 0042 Q_OBJECT 0043 0044 private Q_SLOTS: 0045 0046 void initTestCase() 0047 { 0048 // make 10 data sets a n elements 0049 model.clear(); 0050 model.setColumnCount( ColumnCount ); 0051 model.setRowCount( RowCount ); 0052 for ( int row = 0; row < RowCount; ++row ) 0053 for ( int column = 0; column < ColumnCount; ++column ) { 0054 QStandardItem* item = new QStandardItem(); 0055 item->setData( 1, Qt::DisplayRole ); 0056 model.setItem( row, column, item ); 0057 } 0058 0059 width = 200; 0060 height = 100; 0061 // these settings result in 5 indexes per pixel 0062 } 0063 0064 void initializationTest() 0065 { 0066 QVERIFY2( compressor.modelDataColumns() == 0, "without a model, columns should be zero" ); 0067 QVERIFY2( compressor.modelDataRows() == 0, "without a model,rows should be zero" ); 0068 } 0069 0070 void setModelTest() 0071 { 0072 compressor.setModel( &model ); 0073 QVERIFY2( compressor.modelDataColumns() == model.columnCount(), 0074 "columns should be equal to model columns, independent of resolution" ); 0075 QVERIFY2( compressor.modelDataRows() == 0, "without a diagram resolution, columns should be zero" ); 0076 } 0077 0078 void setResolutionTest() 0079 { 0080 compressor.setResolution( width, height ); 0081 QVERIFY2( compressor.modelDataColumns() == model.columnCount(), 0082 "column count should be equal to dataset count when both model and resolution are set" ); 0083 QVERIFY2( compressor.modelDataRows() == width, 0084 "row count should be equal to width when both model and resolution are set, and " 0085 "model row count exceeds widget width"); 0086 } 0087 0088 void mapToCacheTest() 0089 { 0090 CachePosition NullPoint( -1, -1 ); 0091 Match matches[] = { 0092 Match( CachePosition( 0, 0 ), model.index( 0, 0 ) ), 0093 Match( CachePosition( 0, 0 ), model.index( 1, 0 ) ), 0094 Match( CachePosition( 0, 0 ), model.index( 2, 0 ) ), 0095 Match( CachePosition( 0, 0 ), model.index( 3, 0 ) ), 0096 Match( CachePosition( 0, 0 ), model.index( 4, 0 ) ), 0097 Match( CachePosition( 0, 1 ), model.index( 0, 1 ) ), 0098 Match( CachePosition( 0, 1 ), model.index( 1, 1 ) ), 0099 Match( CachePosition( 0, 1 ), model.index( 2, 1 ) ), 0100 Match( CachePosition( 0, 1 ), model.index( 3, 1 ) ), 0101 Match( CachePosition( 0, 1 ), model.index( 4, 1 ) ), 0102 Match( CachePosition( 2, 2 ), model.index( 10, 2 ) ), 0103 Match( CachePosition( 2, 2 ), model.index( 11, 2 ) ), 0104 Match( CachePosition( 2, 2 ), model.index( 12, 2 ) ), 0105 Match( CachePosition( 2, 2 ), model.index( 13, 2 ) ), 0106 Match( CachePosition( 2, 2 ), model.index( 14, 2 ) ), 0107 // the following are outside the model boundary: 0108 Match( NullPoint, model.index( 0, ColumnCount ) ), 0109 Match( NullPoint, model.index( 1, ColumnCount ) ), 0110 Match( NullPoint, model.index( 2, ColumnCount ) ), 0111 Match( NullPoint, model.index( 3, ColumnCount ) ), 0112 Match( NullPoint, model.index( 4, ColumnCount) ), 0113 Match( NullPoint, model.index( RowCount, 0 ) ), 0114 // sentinel 0115 Match( CachePosition( 0, 0 ), QModelIndex() ) 0116 }; 0117 0118 for ( int i = 0; matches[i].index.isValid(); ++i ) { 0119 QCOMPARE( matches[i].cachePosition, compressor.mapToCache( matches[i].index ) ); 0120 } 0121 0122 QCOMPARE( NullPoint, compressor.mapToCache( QModelIndex() ) ); 0123 } 0124 0125 void mapToModelTest() 0126 { 0127 // test 1: valid point: 0128 { 0129 QModelIndexList indexes; 0130 CachePosition point( 0, 0 ); 0131 indexes = compressor.mapToModel( point ); 0132 for ( const QModelIndex& index : qAsConst(indexes) ) { 0133 QVERIFY2( compressor.mapToCache( index ) == point, 0134 "index mapToModel does not map back to the original cache point" ); 0135 } 0136 } 0137 // test 2: invalid point: 0138 { 0139 QModelIndexList indexes; 0140 CachePosition point( 0, ColumnCount ); // just outside column count 0141 indexes = compressor.mapToModel( point ); 0142 QVERIFY2( indexes.isEmpty(), 0143 "index list for a point outside the data space should be empty" ); 0144 } 0145 { 0146 QModelIndexList indexes; 0147 CachePosition point( RowCount, 0 ); // just outside row count 0148 indexes = compressor.mapToModel( point ); 0149 QVERIFY2( indexes.isEmpty(), 0150 "index list for a point outside the data space should be empty" ); 0151 } 0152 } 0153 0154 0155 void invalidateTest() 0156 { 0157 CachePosition position( 0, 0 ); 0158 // KChart::CartesianDiagramDataCompressor::DataPoint point; 0159 QVERIFY( compressor.mapsToModelIndex( position ) ); 0160 compressor.retrieveModelData( position ); 0161 QVERIFY2( compressor.isCached( position ), 0162 "datapoint should be valid after retrieveModelData( position )" ); 0163 QModelIndex index( model.index( 0, 0 ) ); 0164 compressor.slotModelDataChanged( index, index ); 0165 QVERIFY2( ! compressor.isCached( position ), 0166 "datapoint should be not valid after call to dataChanged slot" ); 0167 CachePosition position2( 1, 0 ); 0168 CachePosition position3( 2, 1 ); 0169 compressor.retrieveModelData( position2 ); 0170 compressor.retrieveModelData( position3 ); 0171 QVERIFY2( ! compressor.isCached( position ), 0172 "datapoint should be not valid after call to dataChanged slot" ); 0173 compressor.retrieveModelData( position ); 0174 QVERIFY2( compressor.isCached( position ) && compressor.isCached( position2 ) && compressor.isCached( position3 ), 0175 "datapoints should all be valid after retrieveModelData" ); 0176 QModelIndex index2( model.index( 1 * compressor.indexesPerPixel(), 0 ) ); 0177 compressor.slotModelDataChanged( index, index2 ); 0178 QVERIFY2( ! compressor.isCached( position ) && ! compressor.isCached( position2 ) && compressor.isCached( position3 ), 0179 "dataChanged needs to invalidate an exact range" ); 0180 } 0181 0182 void datasetDimensionTest() 0183 { 0184 int oldDimension = compressor.m_datasetDimension; 0185 compressor.setDatasetDimension( 2 ); 0186 QVERIFY2( compressor.modelDataColumns() == ColumnCount / 2, 0187 "datasetDimension == 2 should cut the column count in half" ); 0188 compressor.setDatasetDimension( oldDimension ); 0189 QVERIFY2( compressor.modelDataColumns() == ColumnCount, 0190 "datasetDimension == 1 should restore the old column count" ); 0191 } 0192 0193 void cleanupTestCase() 0194 { 0195 } 0196 0197 private: 0198 KChart::CartesianDiagramDataCompressor compressor; 0199 QStandardItemModel model; 0200 static const int RowCount; 0201 static const int ColumnCount; 0202 int width; 0203 int height; 0204 }; 0205 0206 const int CartesianDiagramDataCompressorTests::ColumnCount = 10; 0207 const int CartesianDiagramDataCompressorTests::RowCount = 1000; 0208 0209 0210 QTEST_MAIN(CartesianDiagramDataCompressorTests) 0211 0212 #include "CartesianDiagramDataCompressorTests.moc"