00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
00086 int maxFound = 0;
00087
00088
00089
00090
00091
00092
00093
00094 maxFound = columnCount;
00095
00096 const int lastVisibleColumn = maxFound - 1;
00097
00098 DataValueTextInfoList list;
00099 LineAttributesInfoList lineList;
00100 LineAttributes::MissingValuesPolicy policy;
00101
00102
00103
00104 double maxValue = 100;
00105 double sumValues = 0;
00106 QVector <double > percentSumValues;
00107
00108
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
00132 LineAttributes laPreviousCell;
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;
00148 column2 -= 1 )
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
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
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
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 }