# 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 }