KDChartStackedLineDiagram_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 <QAbstractItemModel>
00031 
00032 #include "KDChartBarDiagram.h"
00033 #include "KDChartLineDiagram.h"
00034 #include "KDChartTextAttributes.h"
00035 #include "KDChartAttributesModel.h"
00036 #include "KDChartAbstractCartesianDiagram.h"
00037 #include "KDChartStackedLineDiagram_p.h"
00038 
00039 using namespace KDChart;
00040 
00041 StackedLineDiagram::StackedLineDiagram( LineDiagram* d )
00042     : LineDiagramType( d )
00043 {
00044 }
00045 
00046 LineDiagram::LineType StackedLineDiagram::type() const
00047 {
00048     return LineDiagram::Stacked;
00049 }
00050 
00051 const QPair<QPointF, QPointF> StackedLineDiagram::calculateDataBoundaries() const
00052 {
00053     const int rowCount = compressor().modelDataRows();
00054     const int colCount = compressor().modelDataColumns();
00055     double xMin = 0;
00056     double xMax = diagram()->model() ? diagram()->model()->rowCount( diagram()->rootIndex() ) - 1 : 0;
00057     double yMin = 0, yMax = 0;
00058 
00059     bool bStarting = true;
00060     for( int row = 0; row < rowCount; ++row )
00061     {
00062         // calculate sum of values per column - Find out stacked Min/Max
00063         double stackedValues = 0;
00064         for( int col = datasetDimension() - 1; col < colCount; col += datasetDimension() ) {
00065             CartesianDiagramDataCompressor::CachePosition position( row, col );
00066             CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00067 
00068             stackedValues += point.value;
00069         }
00070 
00071         if( bStarting ){
00072             yMin = stackedValues;
00073             yMax = stackedValues;
00074             bStarting = false;
00075         }else{
00076             // Pending Michel:
00077             // I am taking in account all values negatives or positives
00078             // take in account all stacked values
00079             yMin = qMin( qMin( yMin,  0.0 ), stackedValues );
00080             yMax = qMax( yMax, stackedValues );
00081         }
00082     }
00083 
00084     QPointF bottomLeft( QPointF( xMin, yMin ) );
00085     QPointF topRight(   QPointF( xMax, yMax ) );
00086     return QPair<QPointF, QPointF> ( bottomLeft, topRight );
00087 }
00088 
00089 void StackedLineDiagram::paint(  PaintContext* ctx )
00090 {
00091     reverseMapper().clear();
00092 
00093     const QPair<QPointF, QPointF> boundaries = diagram()->dataBoundaries();
00094     const QPointF bottomLeft = boundaries.first;
00095     const QPointF topRight = boundaries.second;
00096         
00097     const int columnCount = compressor().modelDataColumns();
00098     const int rowCount = compressor().modelDataRows();
00099 
00100 // FIXME integrate column index retrieval to compressor:
00101     int maxFound = 0;
00102 //    {   // find the last column number that is not hidden
00103 //        for( int iColumn =  datasetDimension() - 1;
00104 //             iColumn <  columnCount;
00105 //             iColumn += datasetDimension() )
00106 //            if( ! diagram()->isHidden( iColumn ) )
00107 //                maxFound = iColumn;
00108 //    }
00109     maxFound = columnCount;
00110     // ^^^ temp
00111 
00112     DataValueTextInfoList list;
00113     LineAttributesInfoList lineList;
00114     LineAttributes::MissingValuesPolicy policy;
00115 
00116     //FIXME(khz): add LineAttributes::MissingValuesPolicy support for LineDiagram::Stacked and ::Percent
00117 
00118     QVector <double > percentSumValues;
00119 
00120     QList<QPointF> bottomPoints;
00121     bool bFirstDataset = true;
00122 
00123     for( int column = 0; column < columnCount; ++column )
00124     {
00125         CartesianDiagramDataCompressor::CachePosition previousCellPosition;
00126 
00127         //display area can be set by dataset ( == column) and/or by cell
00128         LineAttributes laPreviousCell; // by default no area is drawn
00129         QModelIndex indexPreviousCell;
00130         QList<QPolygonF> areas;
00131         QList<QPointF> points;
00132 
00133         for ( int row = 0; row < rowCount; ++row ) {
00134             const CartesianDiagramDataCompressor::CachePosition position( row, column );
00135             const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00136             const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00137 
00138             const LineAttributes laCell = diagram()->lineAttributes( sourceIndex );
00139             const bool bDisplayCellArea = laCell.displayArea();
00140 
00141             double stackedValues = 0, nextValues = 0, nextKey = 0;
00142             for ( int column2 = column; column2 >= 0; --column2 )
00143             {
00144                 const CartesianDiagramDataCompressor::CachePosition position( row, column2 );
00145                 const CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00146                 const QModelIndex sourceIndex = attributesModel()->mapToSource( point.index );
00147                 stackedValues += point.value;
00148                 //qDebug() << valueForCell( iRow, iColumn2 );
00149                 if ( row + 1 < rowCount ){
00150                     CartesianDiagramDataCompressor::CachePosition position( row + 1, column2 );
00151                     CartesianDiagramDataCompressor::DataPoint point = compressor().data( position );
00152                     nextValues += point.value;
00153                     nextKey = point.key;
00154                 }
00155             }
00156             //qDebug() << stackedValues << endl;
00157             const QPointF nextPoint = ctx->coordinatePlane()->translate( QPointF( point.key, stackedValues ) );
00158             points << nextPoint;
00159 
00160             const QPointF ptNorthWest( nextPoint );
00161             const QPointF ptSouthWest(
00162                 bDisplayCellArea
00163                 ? ( bFirstDataset
00164                     ? ctx->coordinatePlane()->translate( QPointF( point.key, 0.0 ) )
00165                     : bottomPoints.at( row )
00166                     )
00167                 : nextPoint );
00168             QPointF ptNorthEast;
00169             QPointF ptSouthEast;
00170 
00171             if ( row + 1 < rowCount ){
00172                 QPointF toPoint = ctx->coordinatePlane()->translate( QPointF( nextKey, nextValues ) );
00173                 lineList.append( LineAttributesInfo( sourceIndex, nextPoint, toPoint ) );
00174                 ptNorthEast = toPoint;
00175                 ptSouthEast =
00176                     bDisplayCellArea
00177                     ? ( bFirstDataset
00178                         ? ctx->coordinatePlane()->translate( QPointF( nextKey, 0.0 ) )
00179                         : bottomPoints.at( row + 1 )
00180                         )
00181                     : toPoint;
00182                 if( areas.count() && laCell != laPreviousCell ){
00183                     paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00184                     areas.clear();
00185                 }
00186                 if( bDisplayCellArea ){
00187                     QPolygonF poly;
00188                     poly << ptNorthWest << ptNorthEast << ptSouthEast << ptSouthWest;
00189                     areas << poly;
00190                     laPreviousCell = laCell;
00191                     indexPreviousCell = sourceIndex;
00192                 }else{
00193                     //qDebug() << "no area shown for row"<<iRow<<"  column"<<iColumn;
00194                 }
00195             }else{
00196                 ptNorthEast = ptNorthWest;
00197                 ptSouthEast = ptSouthWest;
00198             }
00199 
00200             const PositionPoints pts( ptNorthWest, ptNorthEast, ptSouthEast, ptSouthWest );
00201             appendDataValueTextInfoToList( diagram(), list, sourceIndex, pts,
00202                                            Position::NorthWest, Position::SouthWest,
00203                                            point.value );
00204         }
00205         if( areas.count() ){
00206             paintAreas( ctx, indexPreviousCell, areas, laPreviousCell.transparency() );
00207             areas.clear();
00208         }
00209         bottomPoints = points;
00210         bFirstDataset = false;
00211     }
00212     paintElements( ctx, list, lineList, policy );
00213 }

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