kchart

KDChartTableBase.cpp

00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003 */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2001-2003 Klarälvdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KDChart library.
00009  **
00010  ** This file may be distributed and/or modified under the terms of the
00011  ** GNU General Public License version 2 as published by the Free Software
00012  ** Foundation and appearing in the file LICENSE.GPL included in the
00013  ** packaging of this file.
00014  **
00015  ** Licensees holding valid commercial KDChart licenses may use this file in
00016  ** accordance with the KDChart Commercial License Agreement provided with
00017  ** the Software.
00018  **
00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021  **
00022  ** See http://www.klaralvdalens-datakonsult.se/?page=products for
00023  **   information about KDChart Commercial License Agreements.
00024  **
00025  ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 #include <math.h>
00030 #include <limits.h>
00031 #include <qtable.h>
00032 
00033 #include <KDChartTableBase.h>
00034 
00035 
00093 void KDChartTableDataBase::setUsedRows( uint _rows ) {
00094     _usedRows = _rows;
00095     _useUsedRows = true;
00096 }
00097 uint KDChartTableDataBase::usedRows() const {
00098     return _useUsedRows ? _usedRows : rows();
00099 }
00100 void KDChartTableDataBase::setUsedCols( uint _cols ) {
00101     _usedCols = _cols;
00102     _useUsedCols = true;
00103 }
00104 uint KDChartTableDataBase::usedCols() const {
00105     return _useUsedCols ? _usedCols : cols();
00106 }
00107 
00108 
00109 bool KDChartTableDataBase::cellsHaveSeveralCoordinates(
00110     QVariant::Type* type2Ref ) const
00111 {
00112     return cellsHaveSeveralCoordinates( 0, UINT_MAX, type2Ref );
00113 }
00114 
00115 
00116 bool KDChartTableDataBase::cellsHaveSeveralCoordinates(
00117     uint row1,
00118     uint row2,
00119     QVariant::Type* type2Ref ) const
00120 {
00121     // return true if all wanted datasets have at least two coordinates
00122     // stored in all of their cells - BUT only if these coordinates are
00123     // of equal type for each of the cells
00124     // note: We skip cells that are empty, this means having
00125     //       set neither coordinate #1 nor coordinate #2.
00126     bool severalCoordinates = row1 < usedRows();
00127     if( severalCoordinates ) {
00128         severalCoordinates = false;
00129         QVariant::Type testType = QVariant::Invalid;
00130         const uint r2 = (UINT_MAX == row2)
00131                   ? usedRows()
00132                   : QMIN( row2+1, usedRows() );
00133         QVariant value1;
00134         QVariant value2;
00135         for ( uint row = row1; row < r2; ++row ){
00136             for ( uint col = 0; col < usedCols(); ++col ){
00137                 if( cellCoords( row, col, value1, value2 ) ){
00138                     if( QVariant::Invalid != value2.type() ){
00139                         if( (QVariant::Invalid != testType) &&
00140                             (value2.type()     != testType) ){
00141                             severalCoordinates = false;
00142                             break;
00143                         }else{
00144                             testType = value2.type();
00145                             if( NULL != type2Ref )
00146                                 *type2Ref = testType;
00147                             severalCoordinates = true;
00148                         }
00149                     }else if( QVariant::Invalid != value1.type() ){
00150                         severalCoordinates = false;
00151                         break;
00152                     }
00153                 }
00154             }
00155         }
00156     }
00157     return severalCoordinates;
00158 }
00159 
00160 
00161 QVariant::Type KDChartTableDataBase::cellsValueType(
00162     uint row1,
00163     uint row2,
00164     int coordinate ) const
00165 {
00166     QVariant::Type res = QVariant::Invalid;
00167     const uint r2 = (UINT_MAX == row2)
00168               ? usedRows()
00169               : QMIN( row2+1, usedRows() );
00170     
00171     QVariant value;
00172     for ( uint row = row1; row < r2; ++row )
00173         for ( uint col = 0; col < usedCols(); ++col )
00174             if( cellCoord( row, col, value, coordinate ) )
00175                 if( QVariant::Invalid != value.type() )
00176                     res = value.type();
00177     return res;
00178 }
00179 
00180 
00181 QVariant::Type KDChartTableDataBase::cellsValueType(
00182     int coordinate ) const
00183 {
00184     return cellsValueType( 0, UINT_MAX, coordinate );
00185 }
00186 
00187 
00188 double KDChartTableDataBase::maxValue( int coordinate ) const
00189 {
00190     double maxValue = 0.0;
00191     bool bStart = true;
00192     QVariant value;
00193     double dVal;
00194     for ( uint row = 0; row < usedRows(); row++ ) {
00195         for ( uint col = 0; col < usedCols(); col++ ) {
00196             if( cellCoord( row, col, value, coordinate ) &&
00197                 QVariant::Double == value.type() ) {
00198                 dVal = value.toDouble();
00199                 if( isNormalDouble( dVal ) ){
00200                     if ( bStart ) {
00201                         maxValue = dVal;
00202                         bStart = false;
00203                     } else
00204                         maxValue = QMAX( maxValue, dVal );
00205                 }
00206             }
00207         }
00208     }
00209     return maxValue;
00210 }
00211 
00212 
00213 
00214 double KDChartTableDataBase::minValue( int coordinate, bool bOnlyGTZero ) const
00215 {
00216     double minValue = 0.0;
00217     bool bStart = true;
00218     QVariant value;
00219     double dVal;
00220     for ( uint row = 0; row < usedRows(); row++ ) {
00221         for ( uint col = 0; col < usedCols(); col++ ) {
00222             if( cellCoord( row, col, value, coordinate ) &&
00223                 QVariant::Double == value.type() ) {
00224                 dVal = value.toDouble();
00225                 if( !bOnlyGTZero || 0.0 < dVal ){
00226                     if ( bStart ) {
00227                         minValue = dVal;
00228                         bStart = false;
00229                     }else{
00230                         minValue = QMIN( minValue, dVal );
00231                     }
00232                 }
00233             }
00234         }
00235     }
00236     return minValue;
00237 }
00238 
00239 
00240 QDateTime KDChartTableDataBase::maxDtValue( int coordinate ) const
00241 {
00242     QDateTime maxValue = QDateTime( QDate(1970,1,1) );
00243     bool bStart = true;
00244     QVariant value;
00245     QDateTime dtVal;
00246     for ( uint row = 0; row < usedRows(); row++ ) {
00247         for ( uint col = 0; col < usedCols(); col++ ) {
00248             if( cellCoord( row, col, value, coordinate ) &&
00249                 QVariant::DateTime == value.type() ) {
00250                 dtVal = value.toDateTime();
00251                 if ( bStart ) {
00252                     maxValue = dtVal;
00253                     bStart = false;
00254                 } else
00255                     maxValue = QMAX(maxValue, dtVal);
00256             }
00257         }
00258     }
00259     return maxValue;
00260 }
00261 
00262 
00263 
00264 QDateTime KDChartTableDataBase::minDtValue( int coordinate ) const
00265 {
00266     QDateTime minValue = QDateTime( QDate(1970,1,1) );
00267     bool bStart = true;
00268     QVariant value;
00269     QDateTime dtVal;
00270     for ( uint row = 0; row < usedRows(); row++ ) {
00271         for ( uint col = 0; col < usedCols(); col++ ) {
00272             if( cellCoord( row, col, value, coordinate ) &&
00273                 QVariant::DateTime == value.type() ) {
00274                 dtVal = value.toDateTime();
00275                 if ( bStart ) {
00276                     minValue = dtVal;
00277                     bStart = false;
00278                 } else
00279                     minValue = QMIN(minValue, dtVal);
00280             }
00281         }
00282     }
00283     return minValue;
00284 }
00285 
00286 
00287 double KDChartTableDataBase::maxColSum( int coordinate ) const
00288 {
00289     double maxValue = 0.0;
00290     bool bStart = true;
00291     for ( uint col = 0; col < usedCols(); col++ ) {
00292         double colValue = colSum( col, coordinate );
00293         if ( bStart ) {
00294             maxValue = colValue;
00295             bStart = false;
00296         } else
00297             maxValue = QMAX( maxValue, colValue );
00298     }
00299     return maxValue;
00300 }
00301 
00302 
00303 double KDChartTableDataBase::minColSum( int coordinate ) const
00304 {
00305     double minValue = 0.0;
00306     bool bStart = true;
00307     for ( uint col = 0; col < usedCols(); col++ ) {
00308         double colValue = colSum( col, coordinate );
00309         if ( bStart ) {
00310             minValue = colValue;
00311             bStart = false;
00312         } else
00313             minValue = QMIN( minValue, colValue );
00314     }
00315 
00316     return minValue;
00317 }
00318 
00319 
00320 double KDChartTableDataBase::maxColSum( uint row, uint row2, int coordinate ) const
00321 {
00322     double maxValue = 0;
00323     bool bStart = true;
00324     if ( 0 < usedRows() ) {
00325         uint a = row;
00326         uint z = row2;
00327         if ( usedRows() <= a )
00328             a = usedRows() - 1;
00329         if ( usedRows() <= z )
00330             z = usedRows() - 1;
00331         for ( uint col = 0; col < usedCols(); col++ ) {
00332             double valueValue = 0.0;
00333             QVariant value;
00334             double dVal;
00335             for ( uint row = a; row <= z; row++ ) {
00336                 if( cellCoord( row, col, value, coordinate ) &&
00337                     QVariant::Double == value.type() ) {
00338                     dVal = value.toDouble();
00339                     if( isNormalDouble( dVal ) )
00340                         valueValue += dVal;
00341                 }
00342             }
00343             if ( bStart ) {
00344                 maxValue = valueValue;
00345                 bStart = false;
00346             } else
00347                 maxValue = QMAX( maxValue, valueValue );
00348         }
00349     }
00350     return maxValue;
00351 }
00352 
00353 
00354 double KDChartTableDataBase::minColSum( uint row, uint row2, int coordinate ) const
00355 {
00356     double minValue = 0;
00357     bool bStart = true;
00358     if ( 0 < usedRows() ) {
00359         uint a = row;
00360         uint z = row2;
00361         if ( usedRows() <= a )
00362             a = usedRows() - 1;
00363         if ( usedRows() <= z )
00364             z = usedRows() - 1;
00365         for ( uint col = 0; col < usedCols(); col++ ) {
00366             double valueValue = 0.0;
00367             QVariant value;
00368             double dVal;
00369             for ( uint row = a; row <= z; row++ ) {
00370                 if( cellCoord( row, col, value, coordinate ) &&
00371                     QVariant::Double == value.type() ) {
00372                     dVal = value.toDouble();
00373                     if( isNormalDouble( dVal ) )
00374                         valueValue += dVal;
00375                 }
00376             }
00377             if ( bStart ) {
00378                 minValue = valueValue;
00379                 bStart = false;
00380             } else
00381                 minValue = QMIN( minValue, valueValue );
00382         }
00383     }
00384     return minValue;
00385 }
00386 
00387 
00388 double KDChartTableDataBase::colSum( uint col, int coordinate ) const
00389 {
00390     double sum = 0.0;
00391     QVariant value;
00392     double dVal;
00393     for ( uint row = 0; row < usedRows(); row++ ) {
00394         if( cellCoord( row, col, value, coordinate ) &&
00395             QVariant::Double == value.type() ) {
00396             dVal = value.toDouble();
00397             if( isNormalDouble( dVal ) )
00398                 sum += dVal;
00399         }
00400     }
00401 
00402     return sum;
00403 }
00404 
00405 
00406 double KDChartTableDataBase::colAbsSum( uint col, int coordinate ) const
00407 {
00408     double sum = 0.0;
00409     QVariant value;
00410     double dVal;
00411     for ( uint row = 0; row < usedRows(); row++ ) {
00412         if( cellCoord( row, col, value, coordinate ) &&
00413             QVariant::Double == value.type() ) {
00414             dVal = value.toDouble();
00415             if( isNormalDouble( dVal ) )
00416                 sum += fabs( dVal );
00417         }
00418     }
00419 
00420     return sum;
00421 }
00422 
00423 
00424 double KDChartTableDataBase::maxRowSum( int coordinate ) const
00425 {
00426     double maxValue = 0.0;
00427     bool bStart = true;
00428     for ( uint row = 0; row < usedRows(); row++ ) {
00429         double rowValue = rowSum( row, coordinate );
00430         if ( bStart ) {
00431             maxValue = rowValue;
00432             bStart = false;
00433         } else
00434             maxValue = QMAX( maxValue, rowValue );
00435     }
00436     return maxValue;
00437 }
00438 
00439 
00440 double KDChartTableDataBase::minRowSum( int coordinate ) const
00441 {
00442     double minValue = 0.0;
00443     bool bStart = true;
00444     for ( uint row = 0; row < usedRows(); row++ ) {
00445         double rowValue = rowSum( row, coordinate );
00446         if ( bStart ) {
00447             minValue = rowValue;
00448             bStart = false;
00449         } else
00450             minValue = QMIN( minValue, rowValue );
00451     }
00452 
00453     return minValue;
00454 }
00455 
00456 
00457 double KDChartTableDataBase::rowSum( uint row, int coordinate ) const
00458 {
00459     double sum = 0.0;
00460     QVariant value;
00461     double dVal;
00462     for ( uint col = 0; col < usedCols(); col++ ) {
00463         if( cellCoord( row, col, value, coordinate ) &&
00464             QVariant::Double == value.type() ) {
00465             dVal = value.toDouble();
00466             if( isNormalDouble( dVal ) )
00467                 sum += dVal;
00468         }
00469     }
00470     return sum;
00471 }
00472 
00473 
00474 double KDChartTableDataBase::rowAbsSum( uint row, int coordinate ) const
00475 {
00476     double sum = 0.0;
00477     QVariant value;
00478     double dVal;
00479     for ( uint col = 0; col < usedCols(); col++ ) {
00480         if( cellCoord( row, col, value, coordinate ) &&
00481             QVariant::Double == value.type() ) {
00482             dVal = value.toDouble();
00483             if( isNormalDouble( dVal ) )
00484                 sum += fabs( dVal );
00485         }
00486     }
00487     return sum;
00488 }
00489 
00490 
00491 double KDChartTableDataBase::maxInColumn( uint col, int coordinate ) const
00492 {
00493     double maxValue = 0.0;
00494     bool bStart = true;
00495     QVariant value;
00496     double dVal;
00497     for ( uint row = 0; row < usedRows(); row++ ) {
00498         if( cellCoord( row, col, value, coordinate ) &&
00499             QVariant::Double == value.type() ) {
00500             dVal = value.toDouble();
00501             if( isNormalDouble( dVal ) ){
00502                 if ( bStart ) {
00503                     maxValue = dVal;
00504                     bStart = false;
00505                 } else
00506                     maxValue = QMAX( maxValue, dVal );
00507             }
00508         }
00509     }
00510 
00511     return maxValue;
00512 }
00513 
00514 
00515 double KDChartTableDataBase::minInColumn( uint col, int coordinate ) const
00516 {
00517     double minValue = 0.0;
00518     bool bStart = true;
00519     QVariant value;
00520     double dVal;
00521     for ( uint row = 0; row < usedRows(); row++ ) {
00522         if( cellCoord( row, col, value, coordinate ) &&
00523             QVariant::Double == value.type() ) {
00524             dVal = value.toDouble();
00525             if( isNormalDouble( dVal ) ){
00526                 if ( bStart ) {
00527                     minValue = dVal;
00528                     bStart = false;
00529                 } else
00530                     minValue = QMIN( minValue, dVal );
00531             }
00532         }
00533     }
00534 
00535     return minValue;
00536 }
00537 
00538 
00539 double KDChartTableDataBase::maxInRow( uint row, int coordinate ) const
00540 {
00541     double maxValue = DBL_MIN;
00542     bool bStart = true;
00543     QVariant value;
00544     double dVal;
00545     if ( UINT_MAX > row ) {
00546         for ( uint col = 0; col < usedCols(); col++ ) {
00547             if( cellCoord( row, col, value, coordinate ) &&
00548                 QVariant::Double == value.type() ) {
00549                 dVal = value.toDouble();
00550                 if( isNormalDouble( dVal ) ){
00551                     if ( bStart ) {
00552                         maxValue = dVal;
00553                         bStart = false;
00554                     } else
00555                         maxValue = QMAX( maxValue, dVal );
00556                 }
00557             }
00558         }
00559     }
00560     return maxValue;
00561 }
00562 
00563 
00564 double KDChartTableDataBase::minInRow( uint row, int coordinate ) const
00565 {
00566     double minValue = DBL_MAX;
00567     bool bStart = true;
00568     QVariant value;
00569     double dVal;
00570     if ( UINT_MAX > row ) {
00571         for ( uint col = 0; col < usedCols(); col++ ) {
00572             if( cellCoord( row, col, value, coordinate ) &&
00573                 QVariant::Double == value.type() ) {
00574                 dVal = value.toDouble();
00575                 if( isNormalDouble( dVal ) ){
00576                     if ( bStart ) {
00577                         minValue = dVal;
00578                         bStart = false;
00579                     } else
00580                         minValue = QMIN( minValue, dVal );
00581                 }
00582             }
00583         }
00584     }
00585     return minValue;
00586 }
00587 
00588 
00589 double KDChartTableDataBase::maxInRows( uint row, uint row2, int coordinate ) const
00590 {
00591     double maxValue = 0.0;
00592     bool bStart = true;
00593     if ( 0 < usedRows() ) {
00594         uint a = row;
00595         uint z = row2;
00596         // qDebug("KDChartTableDataBase::maxInRows()   (1)     a: %u     z: %u", a, z);
00597         if ( usedRows() <= a )
00598             a = usedRows() - 1;
00599         if ( usedRows() <= z )
00600             z = usedRows() - 1;
00601         // qDebug("KDChartTableDataBase::maxInRows()   (2)     a: %u     z: %u", a, z);
00602         for ( uint row = a; row <= z; ++row ) {
00603             QVariant value;
00604             double dVal;
00605             for ( uint col = 0; col < usedCols(); ++col ) {
00606                 if( cellCoord( row, col, value, coordinate ) &&
00607                     QVariant::Double == value.type() ) {
00608                     dVal = value.toDouble();
00609                     if( isNormalDouble( dVal ) ){
00610                         if ( bStart ) {
00611                             maxValue = dVal;
00612                             bStart = false;
00613                         } else
00614                             maxValue = QMAX( maxValue, dVal );
00615                     }
00616                 }
00617             }
00618         }
00619     }
00620     return maxValue;
00621 }
00622 
00623 
00624 double KDChartTableDataBase::minInRows( uint row, uint row2, int coordinate, bool bOnlyGTZero ) const
00625 {
00626     double minValue = 0.0;
00627     bool bStart = true;
00628     if ( 0 < usedRows() ) {
00629         uint a = row;
00630         uint z = row2;
00631         // qDebug("KDChartTableDataBase::minInRows()   (1)     a: %u     z: %u", a, z);
00632         if ( usedRows() <= a )
00633             a = usedRows() - 1;
00634         if ( usedRows() <= z )
00635             z = usedRows() - 1;
00636         //qDebug("KDChartTableDataBase::minInRows()   (2)     a: %u     z: %u", a, z);
00637         for ( uint row = a; row <= z; ++row ) {
00638             QVariant value;
00639             double dVal;
00640             for ( uint col = 0; col < usedCols(); ++col ) {
00641                 if( cellCoord( row, col, value, coordinate ) &&
00642                     QVariant::Double == value.type() ) {
00643                     dVal = value.toDouble();
00644                     if( isNormalDouble( dVal ) ){
00645                         if( !bOnlyGTZero || 0.0 < dVal ){
00646                             if ( bStart ) {
00647                                 minValue = dVal;
00648                                 bStart = false;
00649                             }else{
00650                                 minValue = QMIN( minValue, dVal );
00651                             }
00652                         }
00653                     }
00654                 }
00655             }
00656         }
00657     }
00658     return minValue;
00659 }
00660 
00661 
00662 QDateTime KDChartTableDataBase::maxDtInRows( uint row, uint row2,
00663                                              int coordinate ) const
00664 {
00665     QDateTime maxValue = QDateTime( QDate(1970,1,1) );
00666     bool bStart = true;
00667     if ( 0 < usedRows() ) {
00668         uint a = row;
00669         uint z = row2;
00670         if ( usedRows() <= a )
00671             a = usedRows() - 1;
00672         if ( usedRows() <= z )
00673             z = usedRows() - 1;
00674         for ( uint row = a; row <= z; ++row ) {
00675             QVariant value;
00676             QDateTime dtVal;
00677             for ( uint col = 0; col < usedCols(); ++col ) {
00678                 if( cellCoord( row, col, value, coordinate ) &&
00679                     QVariant::DateTime == value.type() ) {
00680                     dtVal = value.toDateTime();
00681                     if ( bStart ) {
00682                         maxValue = dtVal;
00683                         bStart = false;
00684                     } else
00685                         maxValue = QMAX( maxValue, dtVal );
00686                 }
00687             }
00688         }
00689     }
00690     return maxValue;
00691 }
00692 
00693 
00694 QDateTime KDChartTableDataBase::minDtInRows( uint row, uint row2,
00695                                              int coordinate ) const
00696 {
00697     QDateTime minValue = QDateTime( QDate(1970,1,1) );
00698     bool bStart = true;
00699     if ( 0 < usedRows() ) {
00700         uint a = row;
00701         uint z = row2;
00702         if ( usedRows() <= a )
00703             a = usedRows() - 1;
00704         if ( usedRows() <= z )
00705             z = usedRows() - 1;
00706         for ( uint row = a; row <= z; ++row ) {
00707             QVariant value;
00708             QDateTime dtVal;
00709             for ( uint col = 0; col < usedCols(); ++col ) {
00710                 if( cellCoord( row, col, value, coordinate ) &&
00711                     QVariant::DateTime == value.type() ) {
00712                     dtVal = value.toDateTime();
00713                     if ( bStart ) {
00714                         minValue = dtVal;
00715                         bStart = false;
00716                     } else
00717                         minValue = QMIN( minValue, dtVal );
00718                 }
00719             }
00720         }
00721     }
00722     return minValue;
00723 }
00724 
00725 
00726 uint KDChartTableDataBase::lastPositiveCellInColumn( uint col, int coordinate ) const
00727 {
00728     uint ret = UINT_MAX;
00729     QVariant value;
00730     double dVal;
00731     for ( uint row = 0; row < usedRows(); row++ ) {
00732         if( cellCoord( row, col, value, coordinate ) &&
00733             QVariant::Double == value.type() ) {
00734             dVal = value.toDouble();
00735             if( isNormalDouble( dVal ) && 0 < dVal )
00736                 ret = row;
00737         }
00738     }
00739     return ret;
00740 }
00741 
00742 
00743 void KDChartTableDataBase::importFromQTable( QTable* table )
00744 {
00745     if( table->numRows() > (int)rows() ||
00746         table->numCols() > (int)cols() )
00747         expand( table->numRows(), table->numCols() );
00748     setUsedRows( table->numRows() );
00749     setUsedCols( table->numCols() );
00750     for( int row = 0; row < table->numRows(); row++ )
00751         for( int col = 0; col < table->numCols(); col++ ) {
00752             QString cellContents = table->text( row, col );
00753             if( !cellContents.isEmpty() ) {
00754                 // First try to parse a double
00755                 bool ok = false;
00756                 double value = cellContents.toDouble( &ok );
00757                 if( ok ) {
00758                     // there was a double
00759                     setCell( row, col, value );
00760                 } else {
00761                     // no double, but at least a string
00762                     setCell( row, col, cellContents );
00763                 }
00764             } // don't do anything if no contents
00765         }
00766     setSorted( false );
00767 }
00768 
00769 
00770 void KDChartTableDataBase::setSorted(bool sorted)
00771 {
00772     _sorted = sorted;
00773 }
00774 bool KDChartTableDataBase::sorted() const
00775 {
00776     return _sorted;
00777 }
00778 
00779 #include "KDChartTableBase.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys