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"