KDChartPercentLineDiagram_p.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C++ -*-
00002    KDChart - a multi-platform charting engine
00003    */
00004 
00005 /****************************************************************************
00006  ** Copyright (C) 2005-2007 Klarälvdalens Datakonsult AB.  All rights reserved.
00007  **
00008  ** This file is part of the KD Chart 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 KD Chart licenses may use this file in
00016  ** accordance with the KD Chart 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.kdab.net/kdchart for
00023  **   information about KD Chart Commercial License Agreements.
00024  **
00025  ** Contact info@kdab.net if any conditions of this
00026  ** licensing are not clear to you.
00027  **
00028  **********************************************************************/
00029 
00030 #include <QModelIndex>
00031 
00032 #include "KDChartBarDiagram.h"
00033 #include "KDChartLineDiagram.h"
00034 #include "KDChartTextAttributes.h"
00035 #include "KDChartAttributesModel.h"
00036 #include "KDChartAbstractCartesianDiagram.h"
00037 #include "KDChartPercentLineDiagram_p.h"
00038 
00039 using namespace KDChart;
00040 
00041 PercentLineDiagram::PercentLineDiagram( LineDiagram* d )
00042     : LineDiagramType( d )
00043 {
00044 }
00045 
00046 LineDiagram::LineType PercentLineDiagram::type() const
00047 {
00048     return LineDiagram::Percent;
00049 }
00050 
00051 const QPair<QPointF, QPointF> PercentLineDiagram::calculateDataBoundaries() const
00052 {
00053     const int rowCount = compressor().modelDataRows();
00054     const int colCount = compressor().modelDataColumns();
00055     double xMin = 0.0;
00056     double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) - 1 : 0;
00057     const double yMin = 0.0;
00058     double yMax = 0.0;
00059 
00060     for( int col = 0; col < colCount; ++col ) {
00061         for ( int row = 0; row < rowCount; ++row ) {
00062             CartesianDiagramDataCompressor::CachePosition position( row, col );
00063             CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00064 
00065             yMax = qMax( yMax, point.value );
00066         }
00067     }
00068 
00069     QPointF bottomLeft( QPointF( xMin, yMin ) );
00070     QPointF topRight( QPointF( xMax, yMax ) );
00071     return QPair<QPointF, QPointF> ( bottomLeft, topRight );
00072 }
00073 
00074 void PercentLineDiagram::paint(  PaintContext* ctx )
00075 {
00076     reverseMapper().clear();
00077 
00078     const QPair<QPointF, QPointF> boundaries = diagram()->dataBoundaries();
00079     const QPointF bottomLeft = boundaries.first;
00080     const QPointF topRight = boundaries.second;
00081 
00082     const int columnCount = compressor().modelDataColumns();
00083     const int rowCount = compressor().modelDataRows();
00084    
00085 // FIXME integrade column index retrieval to compressor: 
00086     int maxFound = 0;
00087 //    {   // find the last column number that is not hidden
00088 //        for( int iColumn =  datasetDimension() - 1;
00089 //             iColumn <  columnCount;
00090 //             iColumn += datasetDimension() )
00091 //            if( ! diagram()->isHidden( iColumn ) )
00092 //                maxFound = iColumn;
00093 //    }
00094     maxFound = columnCount;
00095     // ^^^ temp
00096     const int lastVisibleColumn = maxFound - 1;
00097 
00098     DataValueTextInfoList list;
00099     LineAttributesInfoList lineList;
00100     LineAttributes::MissingValuesPolicy policy;
00101 
00102     //FIXME(khz): add LineAttributes::MissingValuesPolicy support for LineDiagram::Stacked and ::Percent
00103 
00104     double maxValue = 100; // always 100%
00105     double sumValues = 0;
00106     QVector <double > percentSumValues;
00107 
00108     //calculate sum of values for each column and store
00109     for ( int row = 0; row < rowCount; ++row )
00110     {
00111         for( int col = 0; col < columnCount; ++col )
00112         {
00113             CartesianDiagramDataCompressor::CachePosition position( row, col );
00114             CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00115             const double tmpValue = point.value;
00116             if ( tmpValue > 0 )
00117                 sumValues += tmpValue;
00118             if ( col == lastVisibleColumn ) 
00119             {
00120                 percentSumValues << sumValues ;
00121                 sumValues = 0;
00122             }
00123         }
00124     }
00125 
00126     QList<QPointF> bottomPoints;
00127     bool bFirstDataset = true;
00128 
00129     for( int column = 0; column < columnCount; ++column )
00130     {
00131         //display area can be set by dataset ( == column) and/or by cell
00132         LineAttributes laPreviousCell; // by default no area is drawn
00133         QModelIndex indexPreviousCell;
00134         QList<QPolygonF> areas;
00135         QList<QPointF> points;
00136 
00137         for( int row = 0; row < rowCount; ++row ) 
00138         {
00139             CartesianDiagramDataCompressor::CachePosition position( row, column );
00140             CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00141             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00142             const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00143             const bool bDisplayCellArea = laCell.displayArea();
00144 
00145             double stackedValues = 0, nextValues = 0, nextKey = 0;
00146             for ( int column2 = column;
00147                   column2 >= 0;//datasetDimension() - 1;
00148                   column2 -= 1 )//datasetDimension() )
00149             {
00150                 CartesianDiagramDataCompressor::CachePosition position( row, column2 );
00151                 CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00152                 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00153                 const double val = point.value;
00154                 if( val > 0 )
00155                     stackedValues += val;
00156                 //qDebug() << valueForCell( iRow, iColumn2 );
00157                 if ( row + 1 < rowCount ){
00158                     CartesianDiagramDataCompressor::CachePosition position( row + 1, column2 );
00159                     CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00160                     const double val = point.value;
00161                     if( val > 0 )
00162                         nextValues += val;
00163                     nextKey = point.key;
00164                 }
00165             }
00166             if ( percentSumValues.at( row ) != 0  )
00167                 stackedValues = stackedValues / percentSumValues.at( row ) * maxValue;
00168             else
00169                 stackedValues = 0.0;
00170             //qDebug() << stackedValues << endl;
00171             QPointF nextPoint = ctx->coordinatePlane()->translate( QPointF( point.key, stackedValues ) );
00172             points << nextPoint;
00173 
00174             const QPointF ptNorthWest( nextPoint );
00175             const QPointF ptSouthWest(
00176                 bDisplayCellArea
00177                 ? ( bFirstDataset
00178                     ? ctx->coordinatePlane()->translate( QPointF( point.key, 0.0 ) )
00179                     : bottomPoints.at( row )
00180                     )
00181                 : nextPoint );
00182             QPointF ptNorthEast;
00183             QPointF ptSouthEast;
00184 
00185             if ( row + 1 < rowCount ){
00186                  if ( percentSumValues.at( row + 1 ) != 0  )
00187                      nextValues = nextValues / percentSumValues.at( row + 1 ) * maxValue;
00188                  else
00189                      nextValues = 0.0;
00190                 QPointF toPoint = ctx->coordinatePlane()->translate( QPointF( nextKey, nextValues ) );
00191                 lineList.append( LineAttributesInfo( sourceIndex, nextPoint, toPoint ) );
00192                 ptNorthEast = toPoint;
00193                 ptSouthEast =
00194                     bDisplayCellArea
00195                     ? ( bFirstDataset
00196                         ? ctx->coordinatePlane()->translate( QPointF( nextKey, 0.0 ) )
00197                         : bottomPoints.at( row + 1 )
00198                         )
00199                     : toPoint;
00200                 if( areas.count() && laCell != laPreviousCell ){
00201                     paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00202                     areas.clear();
00203                 }
00204                 if( bDisplayCellArea ){
00205                     QPolygonF poly;
00206                     poly << ptNorthWest << ptNorthEast << ptSouthEast << ptSouthWest;
00207                     areas << poly;
00208                     laPreviousCell = laCell;
00209                     indexPreviousCell = sourceIndex;
00210                 }else{
00211                     //qDebug() << "no area shown for row"<<iRow<<"  column"<<iColumn;
00212                 }
00213             }else{
00214                 ptNorthEast = ptNorthWest;
00215                 ptSouthEast = ptSouthWest;
00216             }
00217 
00218             const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
00219             appendDataValueTextInfoToList( diagram(), list, sourceIndex, pts,
00220                                            Position::NorthWest, Position::SouthWest,
00221                                            point.value );
00222         }
00223         if( areas.count() ){
00224             paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00225             areas.clear();
00226         }
00227         bottomPoints = points;
00228         bFirstDataset = false;
00229     }
00230     paintElements( ctx, list, lineList, policy );
00231 }

Generated on Mon Sep 17 16:16:50 2007 for KD Chart 2 by  doxygen 1.5.1