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 #include "KDChartHiLoPainter.h"
00030 #include <KDChartParams.h>
00031 #include "KDChartTextPiece.h"
00032
00033 #include <qpainter.h>
00034
00035 #include <stdlib.h>
00036
00048 KDChartHiLoPainter::KDChartHiLoPainter( KDChartParams* params ) :
00049 KDChartAxesPainter( params )
00050 {
00051
00052
00053 }
00054
00055
00059 KDChartHiLoPainter::~KDChartHiLoPainter()
00060 {
00061
00062 }
00063
00064
00078 QString KDChartHiLoPainter::fallbackLegendText( uint dataset ) const
00079 {
00080 return QObject::tr( "Value " ) + QString::number( dataset + 1 );
00081 }
00082
00083
00093 uint KDChartHiLoPainter::numLegendFallbackTexts( KDChartTableDataBase* data ) const
00094 {
00095 return data->usedRows();
00096 }
00097
00098
00099 bool KDChartHiLoPainter::isNormalMode() const
00100 {
00101 return KDChartParams::HiLoNormal == params()->hiLoChartSubType();
00102 }
00103
00104 int KDChartHiLoPainter::clipShiftUp( bool, double ) const
00105 {
00106 return 0;
00107 }
00108
00109 void KDChartHiLoPainter::specificPaintData( QPainter* painter,
00110 const QRect& ourClipRect,
00111 KDChartTableDataBase* data,
00112 KDChartDataRegionList* ,
00113 const KDChartAxisParams* axisPara,
00114 bool ,
00115 uint ,
00116 double logWidth,
00117 double areaWidthP1000,
00118 double logHeight,
00119 double axisYOffset,
00120 double ,
00121 double ,
00122 double ,
00123 uint chartDatasetStart,
00124 uint chartDatasetEnd,
00125 uint datasetStart,
00126 uint datasetEnd )
00127 {
00128 double areaHeightP1000 = logHeight / 1000.0;
00129 double averageValueP1000 = ( areaWidthP1000 + areaHeightP1000 ) / 2.0;
00130 int datasetNum=abs(static_cast<int>(chartDatasetEnd-chartDatasetStart))+1;
00131
00132 painter->setPen( params()->outlineDataColor() );
00133
00134
00135
00136 int numValues = 0;
00137 if ( params()->numValues() != -1 )
00138 numValues = params()->numValues();
00139 else
00140 numValues = data->usedCols();
00141
00142
00143
00144 if( (numValues < 2) ||
00145 ((params()->hiLoChartSubType() == KDChartParams::HiLoClose) && (numValues < 3)) ||
00146 ((params()->hiLoChartSubType() == KDChartParams::HiLoOpenClose) && (numValues < 4)) ){
00147 qDebug( "\nNot enough data to display a High/Low Chart!\n" );
00148 qDebug( "type requiring" );
00149 qDebug( "---- ---------" );
00150 qDebug( "High/Low 2 data cells per series" );
00151 qDebug( "High/Low/Close 3 data cells per series" );
00152 qDebug( "High/Low/open/Close 4 data cells per series\n" );
00153 return;
00154 }
00155
00156 double pixelsPerUnit = 0.0;
00157 if( 0.0 != axisPara->trueAxisHigh() - axisPara->trueAxisLow() )
00158 pixelsPerUnit = logHeight / (axisPara->trueAxisHigh() - axisPara->trueAxisLow());
00159 else
00160 pixelsPerUnit = logHeight / 10;
00161
00162
00163 double pointDist = logWidth / (double)datasetNum;
00164
00165
00166 double zeroXAxisI = axisPara->axisZeroLineStartY() - _dataRect.y();
00167
00168 const int nLineWidth = params()->lineWidth();
00169
00170
00171 for ( uint dataset = chartDatasetStart;
00172 dataset <= chartDatasetEnd;
00173 ++dataset ) {
00174
00175
00176 QVariant valueA;
00177 QVariant valueB;
00178 if( dataset >= datasetStart &&
00179 dataset <= datasetEnd &&
00180 data->cellCoord( dataset, 0, valueA, 1 ) &&
00181 data->cellCoord( dataset, 1, valueB, 1 ) &&
00182 QVariant::Double == valueA.type() &&
00183 QVariant::Double == valueB.type() ){
00184 const double cellValue1 = valueA.toDouble();
00185 const double cellValue2 = valueB.toDouble();
00186 const double lowValue = QMIN( cellValue1, cellValue2 );
00187 const double highValue = QMAX( cellValue1, cellValue2 );
00188 const double lowDrawValue = lowValue * pixelsPerUnit;
00189 const double highDrawValue = highValue * pixelsPerUnit;
00190
00191 painter->setPen( QPen( params()->dataColor( dataset ),
00192 nLineWidth ) );
00193
00194 int xpos = static_cast<int>(
00195 pointDist * ( (double)(dataset-chartDatasetStart) + 0.5 ) );
00196 int lowYPos = static_cast<int>( zeroXAxisI - lowDrawValue );
00197 int highYPos = static_cast<int>( zeroXAxisI - highDrawValue );
00198
00199 painter->drawLine( xpos, lowYPos, xpos, highYPos );
00200
00201
00202
00203
00204 int openCloseTickLength = static_cast<int>( pointDist * 0.1 );
00205
00206
00207 bool hasOpen = false, hasClose = false;
00208 double openValue = 0.0, openDrawValue = 0.0,
00209 closeValue = 0.0, closeDrawValue = 0.0;
00210
00211
00212 if( params()->hiLoChartSubType() == KDChartParams::HiLoOpenClose ) {
00213
00214 if( data->cellCoord( dataset, 2, valueA, 1 ) &&
00215 QVariant::Double == valueA.type() ) {
00216 hasOpen = true;
00217 openValue = valueA.toDouble();
00218 openDrawValue = openValue * pixelsPerUnit;
00219 painter->drawLine( xpos - openCloseTickLength,
00220 static_cast<int>( zeroXAxisI - openDrawValue ),
00221 xpos,
00222 static_cast<int>( zeroXAxisI - openDrawValue ) );
00223 }
00224 }
00225
00226
00227
00228
00229
00230 if( ( params()->hiLoChartSubType() == KDChartParams::HiLoClose &&
00231 data->cellCoord( dataset, 2, valueA, 1 ) &&
00232 QVariant::Double == valueA.type() ) ||
00233 ( params()->hiLoChartSubType() == KDChartParams::HiLoOpenClose &&
00234 data->cellCoord( dataset, 3, valueB, 1 ) &&
00235 QVariant::Double == valueB.type() ) ) {
00236 hasClose = true;
00237 closeValue = ( params()->hiLoChartSubType() == KDChartParams::HiLoClose )
00238 ? valueA.toDouble()
00239 : valueB.toDouble();
00240 closeDrawValue = closeValue * pixelsPerUnit;
00241 painter->drawLine( xpos,
00242 static_cast<int>( zeroXAxisI - closeDrawValue ),
00243 xpos + openCloseTickLength,
00244 static_cast<int>( zeroXAxisI - closeDrawValue ) );
00245 }
00246
00247
00248 if( params()->hiLoChartPrintLowValues() ) {
00249
00250 QFont theFont( params()->hiLoChartLowValuesFont() );
00251 if ( params()->hiLoChartLowValuesUseFontRelSize() ) {
00252 int nTxtHeight =
00253 static_cast < int > ( params()->hiLoChartLowValuesFontRelSize()
00254 * averageValueP1000 );
00255 theFont.setPointSizeFloat( nTxtHeight );
00256 }
00257 KDChartTextPiece lowText( painter, QString::number( lowValue ),
00258 theFont );
00259 int width = lowText.width();
00260 int height = lowText.height();
00261
00262
00263 int valX = 0, valY = 0;
00264
00265
00266
00267 if( zeroXAxisI - lowDrawValue + height < axisYOffset+logHeight ) {
00268
00269 valX = xpos - ( width / 2 );
00270 valY = (int)lowDrawValue - lowText.fontLeading();
00271 } else {
00272
00273 if( !hasOpen || height < openDrawValue ) {
00274
00275
00276 valX = xpos - width - nLineWidth;
00277 valY = static_cast<int>(zeroXAxisI)
00278 - lowYPos
00279 + height/2
00280 + nLineWidth/2;
00281 }
00282 }
00283 lowText.draw( painter,
00284 valX, static_cast<int>( zeroXAxisI - valY ),
00285 ourClipRect,
00286 params()->hiLoChartLowValuesColor() );
00287 }
00288
00289
00290 if( params()->hiLoChartPrintHighValues() ) {
00291
00292 QFont theFont( params()->hiLoChartHighValuesFont() );
00293 if ( params()->hiLoChartHighValuesUseFontRelSize() ) {
00294 int nTxtHeight =
00295 static_cast < int > ( params()->hiLoChartHighValuesFontRelSize()
00296 * averageValueP1000 );
00297 theFont.setPointSizeFloat( nTxtHeight );
00298 }
00299 KDChartTextPiece highText( painter, QString::number( highValue ),
00300 theFont );
00301 int width = highText.width();
00302 int height = highText.height();
00303
00304
00305 int valX = 0, valY = 0;
00306 if( zeroXAxisI - highDrawValue - height > axisYOffset ) {
00307
00308 valX = xpos - ( width / 2 );
00309 valY = (int)highDrawValue + highText.fontLeading() + height;
00310 } else {
00311
00312 if( !hasClose ||
00313 height < ( _dataRect.height() - closeDrawValue ) ) {
00314
00315
00316 valX = xpos + nLineWidth;
00317 valY = static_cast<int>(zeroXAxisI)
00318 - highYPos
00319 + height/2
00320 - nLineWidth/2;
00321 }
00322 }
00323 highText.draw( painter,
00324 valX, static_cast<int>( zeroXAxisI - valY ),
00325 ourClipRect,
00326 params()->hiLoChartHighValuesColor() );
00327 }
00328
00329
00330 if( params()->hiLoChartPrintOpenValues() &&
00331 params()->hiLoChartSubType() == KDChartParams::HiLoOpenClose ) {
00332
00333 QFont theFont( params()->hiLoChartOpenValuesFont() );
00334 if ( params()->hiLoChartOpenValuesUseFontRelSize() ) {
00335 int nTxtHeight =
00336 static_cast < int > ( params()->hiLoChartOpenValuesFontRelSize()
00337 * averageValueP1000 );
00338 theFont.setPointSizeFloat( nTxtHeight );
00339 }
00340 KDChartTextPiece openText( painter, QString::number( openValue ),
00341 theFont );
00342 int width = openText.width();
00343 int height = openText.height();
00344
00345
00346
00347 int valX = 0, valY = 0;
00348 valX = xpos - openCloseTickLength - width;
00349 valY = (int)openDrawValue + ( height / 2 );
00350 openText.draw( painter,
00351 valX, static_cast<int>( zeroXAxisI - valY ),
00352 ourClipRect,
00353 params()->hiLoChartOpenValuesColor() );
00354 }
00355
00356
00357 if( params()->hiLoChartPrintCloseValues() &&
00358 ( params()->hiLoChartSubType() == KDChartParams::HiLoOpenClose
00359 ||
00360 params()->hiLoChartSubType() == KDChartParams::HiLoClose ) ) {
00361
00362 QFont theFont( params()->hiLoChartCloseValuesFont() );
00363 if ( params()->hiLoChartCloseValuesUseFontRelSize() ) {
00364 int nTxtHeight =
00365 static_cast < int > ( params()->hiLoChartCloseValuesFontRelSize()
00366 * averageValueP1000 );
00367 theFont.setPointSizeFloat( nTxtHeight );
00368 }
00369 KDChartTextPiece closeText( painter, QString::number( closeValue ),
00370 theFont );
00371
00372 int height = closeText.height();
00373
00374
00375
00376 int valX = 0, valY = 0;
00377 valX = xpos + openCloseTickLength;
00378 valY = (int)closeDrawValue + ( height / 2 );
00379 closeText.draw( painter,
00380 valX, static_cast<int>( zeroXAxisI - valY ),
00381 ourClipRect,
00382 params()->hiLoChartCloseValuesColor() );
00383 }
00384
00385 } else
00386 continue;
00387 }
00388 }