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 <qpainter.h>
00030 #include <qregion.h>
00031 #include <qpalette.h>
00032 #include <qpoint.h>
00033 #include <qsimplerichtext.h>
00034 #include <qpaintdevicemetrics.h>
00035
00036 #include <KDChartCustomBox.h>
00037 #include <KDXMLTools.h>
00038 #include <KDFrame.h>
00039
00040
00041
00042 KDChartCustomBox::~KDChartCustomBox()
00043 {
00044
00045 }
00046
00047
00048 void KDChartCustomBox::deepCopy( const KDChartCustomBox* source )
00049 {
00050 if( !source || this == source )
00051 return;
00052 _rotation = source->_rotation;
00053 _content.deepCopy( &source->_content);
00054 _fontSize = source->_fontSize;
00055 _fontScaleGlobal = source->_fontScaleGlobal;
00056 _deltaX = source->_deltaX;
00057 _deltaY = source->_deltaY;
00058 _width = source->_width;
00059 _height = source->_height;
00060 _color = source->_color;
00061 _paper = source->_paper;
00062 _anchorArea = source->_anchorArea;
00063 _anchorPos = source->_anchorPos;
00064 _anchorAlign = source->_anchorAlign;
00065 _dataRow = source->_dataRow;
00066 _dataCol = source->_dataCol;
00067 _data3rd = source->_data3rd;
00068 _deltaAlign = source->_deltaAlign;
00069 _deltaScaleGlobal = source->_deltaScaleGlobal;
00070 _anchorBeingCalculated = source->_anchorBeingCalculated;
00071 }
00072
00073 const KDChartCustomBox* KDChartCustomBox::clone() const
00074 {
00075 KDChartCustomBox* newBox = new KDChartCustomBox();
00076 newBox->deepCopy( this );
00077 return newBox;
00078 }
00079
00080
00081 float KDChartCustomBox::trueFontSize( double areaWidthP1000,
00082 double areaHeightP1000,
00083 int rectHeight ) const
00084 {
00085 float size;
00086 if( 0 > _fontSize ) {
00087 if( _fontScaleGlobal ) {
00088
00089 size = _fontSize * QMIN(areaWidthP1000, areaHeightP1000) * -1.0;
00090
00091 } else {
00092
00093
00094 float targetLineSpacing = (_fontSize * rectHeight)/ -1000;
00095 size = targetLineSpacing;
00096
00097 QFont font( content().font() );
00098 font.setPointSizeFloat( size );
00099 QFontMetrics fm( font );
00100
00101
00102
00103 size *= targetLineSpacing / fm.lineSpacing();
00104
00105
00106 font.setPointSizeFloat( size );
00107 QFontMetrics fm2( font );
00108 size *= targetLineSpacing / fm2.lineSpacing();
00109
00110
00111
00112 }
00113 }
00114 else {
00115
00116 if( _fontSize )
00117 size = _fontSize;
00118 else{
00119 size = content().font().pointSize();
00120 if( -1 == size )
00121 size = content().font().pixelSize();
00122 if( -1 == size )
00123 size = 10;
00124 }
00125 }
00126 return size;
00127 }
00128
00129
00130 int KDChartCustomBox::trueFontLineSpacing( double areaWidthP1000,
00131 double areaHeightP1000,
00132 int rectHeight ) const
00133 {
00134 QFont font( content().font() );
00135 font.setPointSizeFloat( trueFontSize( areaWidthP1000,areaHeightP1000, rectHeight ) );
00136 QFontMetrics fm( font );
00137 return fm.lineSpacing();
00138 }
00139
00140
00141 void KDChartCustomBox::getTrueShift( double areaWidthP1000,
00142 double areaHeightP1000,
00143 int rectHeight,
00144 int& dX,
00145 int& dY ) const
00146 {
00147 int x, y;
00148 if( _deltaScaleGlobal ){
00149 x = (0 > _deltaX) ? static_cast < int > ( -areaWidthP1000 * _deltaX ) : _deltaX;
00150 y = (0 > _deltaY) ? static_cast < int > ( -areaHeightP1000 * _deltaY ) : _deltaY;
00151 }else{
00152 int fontHeight = trueFontLineSpacing( areaWidthP1000, areaHeightP1000, rectHeight );
00153
00154 x = (0 > _deltaX) ? static_cast < int > ( fontHeight * _deltaX / -100.0 ) : _deltaX;
00155 y = (0 > _deltaY) ? static_cast < int > ( fontHeight * _deltaY / -100.0 ) : _deltaY;
00156
00157 }
00158 uint deltaAlign = (KDCHART_AlignAuto == _deltaAlign) ? _anchorAlign : _deltaAlign;
00159 if ( Qt::AlignLeft == (Qt::AlignLeft & deltaAlign) )
00160 dX = x;
00161 else if ( Qt::AlignRight == (Qt::AlignRight & deltaAlign) )
00162 dX = -x;
00163 else
00164 dX = 0;
00165
00166 if ( Qt::AlignTop == (Qt::AlignTop & deltaAlign) )
00167 dY = y;
00168 else if ( Qt::AlignBottom == (Qt::AlignBottom & deltaAlign) )
00169 dY = -y;
00170 else
00171 dY = 0;
00172 }
00173
00174
00175
00176
00177
00178 QRect KDChartCustomBox::trueRect( QPoint anchor, double areaWidthP1000, double areaHeightP1000 ) const
00179 {
00180 int w = (0 > _width ) ? static_cast < int > ( -areaWidthP1000 * _width ) : _width;
00181 int h = (0 > _height) ? static_cast < int > ( -areaHeightP1000 * _height ) : _height;
00182
00183
00184
00185 if( _fontScaleGlobal && 0 == w && 0 == h ){
00186
00187 QFont font( content().font() );
00188 if ( _fontSize ) {
00189 font.setPointSizeFloat(
00190 (0 > _fontSize)
00191 ? (_fontSize * QMIN(areaWidthP1000, areaHeightP1000) * -1.0)
00192 : _fontSize );
00193
00194 }
00195 QString txt( content().text() );
00196 QString txtTest( txt.stripWhiteSpace().lower() );
00197 #if QT_VERSION >= 200 && QT_VERSION < 300
00198
00199 if( !(txtTest.left(4) == "<qt>") )
00200 txt.prepend( "<qt>" );
00201 if( !(txtTest.right(5)== "</qt>"))
00202 txt.append( "</qt>");
00203 #else
00204 if( !txtTest.startsWith("<qt>" ) )
00205 txt.prepend( "<qt>" );
00206 if( !txtTest.endsWith( "</qt>") )
00207 txt.append( "</qt>");
00208 #endif
00209
00210
00211 QSimpleRichText tmpContent( txt, font );
00212
00213
00214
00215
00216
00217
00218
00219 w = tmpContent.widthUsed();
00220 h = tmpContent.height();
00221
00222
00223 }
00224
00225
00226 int x,y;
00227 if ( Qt::AlignLeft == (Qt::AlignLeft & _anchorAlign) )
00228 x = 0;
00229 else if ( Qt::AlignRight == (Qt::AlignRight & _anchorAlign) )
00230 x = - w + 1;
00231 else
00232 x = - w / 2;
00233
00234 if ( Qt::AlignTop == (Qt::AlignTop & _anchorAlign) )
00235 y = 0;
00236 else if ( Qt::AlignBottom == (Qt::AlignBottom & _anchorAlign) )
00237 y = - h + 1;
00238 else
00239 y = - h / 2;
00240 int dX,dY;
00241 getTrueShift( areaWidthP1000, areaHeightP1000, h,
00242 dX, dY );
00243
00244
00245 return QRect( anchor.x()+x+dX, anchor.y()+y+dY, w, h );
00246 }
00247
00248
00249 int KDChartCustomBox::trueRectAlignX(const QRect& rect) const
00250 {
00251 int ret = rect.center().x();
00252 if ( Qt::AlignLeft == (Qt::AlignLeft & _anchorAlign) )
00253 ret -= rect.width();
00254 else if ( Qt::AlignRight == (Qt::AlignRight & _anchorAlign) )
00255 ret += rect.width();
00256 return ret;
00257 }
00258 int KDChartCustomBox::trueRectAlignY(const QRect& rect) const
00259 {
00260 int ret = rect.center().y();
00261 if ( Qt::AlignTop == (Qt::AlignTop & _anchorAlign) )
00262 ret -= rect.height();
00263 else if ( Qt::AlignBottom == (Qt::AlignBottom & _anchorAlign) )
00264 ret += rect.height();
00265 return ret;
00266 }
00267
00268 void KDChartCustomBox::paint( QPainter* painter,
00269 QPoint anchor,
00270 double areaWidthP1000,
00271 double areaHeightP1000,
00272 const KDFrame* frame,
00273 const QRect& frameRect,
00274 const QColor * color,
00275 const QBrush * paper ) const
00276 {
00277 painter->save();
00278 int rotDX = 0;
00279 int rotDY = 0;
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 QRect myRect( trueRect( anchor, areaWidthP1000, areaHeightP1000 ) );
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 QRect myFrameRect( frameRect );
00304 if ( myRect.isValid() ) {
00305
00306 if( _rotation ){
00307 getTrueShift( areaWidthP1000, areaHeightP1000, myRect.height(),
00308 rotDX, rotDY );
00309 myRect.moveBy( -rotDX, -rotDY );
00310 if( frame )
00311 myFrameRect.moveBy( -rotDX, -rotDY );
00312
00313
00314 myRect.moveCenter( QPoint( anchor.x() - trueRectAlignX(myRect),
00315 anchor.y() - trueRectAlignY(myRect) ) );
00316 if( frame )
00317 myFrameRect.moveCenter( QPoint( anchor.x() - trueRectAlignX(myFrameRect),
00318 anchor.y() - trueRectAlignY(myFrameRect) ) );
00319
00320 painter->translate( anchor.x(), anchor.y() );
00321 painter->rotate( _rotation );
00322 painter->translate( rotDX, rotDY );
00323 }
00324 if( frame )
00325 frame->paint( painter, KDFrame::PaintAll, myFrameRect );
00326 if ( _fontSize ) {
00327 QFont font( content().font() );
00328
00329 float trueSize = trueFontSize(areaWidthP1000,areaHeightP1000, myRect.height() );
00330 font.setPointSizeFloat( trueSize );
00331
00332 myRect.setHeight( (int)(trueSize )+ (int)(trueSize*0.5));
00333 const KDChartTextPiece tmpTextPiece( painter, content().text(), font );
00334
00335 tmpTextPiece.draw( painter, myRect.x(), myRect.y(), myRect,
00336 color ? *color : _color,
00337 paper ? paper : &_paper );
00338 }else{
00339
00340 content().draw( painter, myRect.x(), myRect.y(), myRect,
00341 color ? *color : _color,
00342 paper ? paper : &_paper );
00343 }
00344 }
00345 painter->restore();
00346 }
00347
00348
00349 void KDChartCustomBox::createCustomBoxNode( QDomDocument& document,
00350 QDomNode& parent,
00351 const QString& elementName,
00352 const KDChartCustomBox* custombox )
00353 {
00354 QDomElement customBoxElement = document.createElement( elementName );
00355 parent.appendChild( customBoxElement );
00356 KDXML::createIntNode( document, parent, "Rotation", custombox->_rotation );
00357 KDXML::createStringNode( document, parent, "ContentText",
00358 custombox->_content.text() );
00359 KDXML::createFontNode( document, parent, "ContentFont",
00360 custombox->_content.font() );
00361 KDXML::createIntNode( document, parent, "FontSize", custombox->_fontSize );
00362 KDXML::createBoolNode( document, parent, "FontScaleGlobal",
00363 custombox->_fontScaleGlobal );
00364 KDXML::createIntNode( document, parent, "DeltaX", custombox->_deltaX );
00365 KDXML::createIntNode( document, parent, "DeltaY", custombox->_deltaY );
00366 KDXML::createIntNode( document, parent, "Width", custombox->_width );
00367 KDXML::createIntNode( document, parent, "Height", custombox->_height );
00368 KDXML::createColorNode( document, parent, "Color", custombox->_color );
00369 KDXML::createBrushNode( document, parent, "Paper", custombox->_paper );
00370 KDXML::createIntNode( document, parent, "AnchorArea",
00371 custombox->_anchorArea );
00372 KDXML::createStringNode( document, parent, "AnchorPos",
00373 KDChartEnums::positionFlagToString( custombox->_anchorPos ) );
00374 KDXML::createIntNode( document, parent, "AnchorAlign",
00375 custombox->_anchorAlign );
00376 KDXML::createIntNode( document, parent, "DataRow",
00377 custombox->_dataRow );
00378 KDXML::createIntNode( document, parent, "DataCol",
00379 custombox->_dataCol );
00380 KDXML::createIntNode( document, parent, "Data3rd",
00381 custombox->_data3rd );
00382 KDXML::createIntNode( document, parent, "DeltaAlign",
00383 custombox->_deltaAlign );
00384 KDXML::createBoolNode( document, parent, "DeltaScaleGlobal",
00385 custombox->_deltaScaleGlobal );
00386 }
00387
00388
00389 bool KDChartCustomBox::readCustomBoxNode( const QDomElement& element,
00390 KDChartCustomBox& custombox )
00391 {
00392 bool ok = true;
00393 QString tempContentText;
00394 QFont tempContentFont;
00395 int tempRotation = 0;
00396 int tempDeltaAlign = KDCHART_AlignAuto;
00397 bool tempDeltaScaleGlobal = true;
00398 int tempFontSize, tempDeltaX, tempDeltaY,
00399 tempWidth, tempHeight, tempAnchorArea, tempAnchorAlign,
00400 tempDataRow, tempDataCol, tempData3rd;
00401 bool tempFontScaleGlobal;
00402 QColor tempColor;
00403 QBrush tempPaper;
00404 KDChartEnums::PositionFlag tempAnchorPos = KDChartEnums::PosTopLeft;
00405 QDomNode node = element.firstChild();
00406 while( !node.isNull() ) {
00407 QDomElement element = node.toElement();
00408 if( !element.isNull() ) {
00409 QString tagName = element.tagName();
00410 if( tagName == "Rotation" ) {
00411 ok = ok & KDXML::readIntNode( element, tempRotation );
00412 } else if( tagName == "ContentText" ) {
00413 ok = ok & KDXML::readStringNode( element, tempContentText );
00414 } else if( tagName == "ContentFont" ) {
00415 ok = ok & KDXML::readFontNode( element, tempContentFont );
00416 } else if( tagName == "FontSize" ) {
00417 ok = ok & KDXML::readIntNode( element, tempFontSize );
00418 } else if( tagName == "FontScaleGlobal" ) {
00419 ok = ok & KDXML::readBoolNode( element, tempFontScaleGlobal );
00420 } else if( tagName == "DeltaX" ) {
00421 ok = ok & KDXML::readIntNode( element, tempDeltaX );
00422 } else if( tagName == "DeltaY" ) {
00423 ok = ok & KDXML::readIntNode( element, tempDeltaY );
00424 } else if( tagName == "Width" ) {
00425 ok = ok & KDXML::readIntNode( element, tempWidth );
00426 } else if( tagName == "Height" ) {
00427 ok = ok & KDXML::readIntNode( element, tempHeight );
00428 } else if( tagName == "Color" ) {
00429 ok = ok & KDXML::readColorNode( element, tempColor );
00430 } else if( tagName == "Paper" ) {
00431 ok = ok & KDXML::readBrushNode( element, tempPaper );
00432 } else if( tagName == "AnchorArea" ) {
00433 ok = ok & KDXML::readIntNode( element, tempAnchorArea );
00434 } else if( tagName == "AnchorPos" ) {
00435 QString value;
00436 ok = ok & KDXML::readStringNode( element, value );
00437 tempAnchorPos = KDChartEnums::stringToPositionFlag( value );
00438 } else if( tagName == "AnchorAlign" ) {
00439 ok = ok & KDXML::readIntNode( element, tempAnchorAlign );
00440 } else if( tagName == "DataRow" ) {
00441 ok = ok & KDXML::readIntNode( element, tempDataRow );
00442 } else if( tagName == "DataCol" ) {
00443 ok = ok & KDXML::readIntNode( element, tempDataCol );
00444 } else if( tagName == "Data3rd" ) {
00445 ok = ok & KDXML::readIntNode( element, tempData3rd );
00446 } else if( tagName == "DeltaAlign" ) {
00447 ok = ok & KDXML::readIntNode( element, tempDeltaAlign );
00448 } else if( tagName == "DeltaScaleGlobal" ) {
00449 ok = ok & KDXML::readBoolNode( element, tempDeltaScaleGlobal );
00450 } else {
00451 qDebug( "Unknown tag in custom box" );
00452 }
00453 }
00454 node = node.nextSibling();
00455 }
00456
00457 if( ok ) {
00458 const KDChartTextPiece piece( 0, tempContentText, tempContentFont );
00459 custombox._content.deepCopy( &piece );
00460 custombox._rotation = tempRotation;
00461 custombox._fontSize = tempFontSize;
00462 custombox._fontScaleGlobal = tempFontScaleGlobal;
00463 custombox._deltaX = tempDeltaX;
00464 custombox._deltaY = tempDeltaY;
00465 custombox._width = tempWidth;
00466 custombox._height = tempHeight;
00467 custombox._color = tempColor;
00468 custombox._paper = tempPaper;
00469 custombox._anchorArea = tempAnchorArea;
00470 custombox._anchorPos = tempAnchorPos;
00471 custombox._anchorAlign = tempAnchorAlign;
00472 custombox._dataRow = tempDataRow;
00473 custombox._dataCol = tempDataCol;
00474 custombox._data3rd = tempData3rd;
00475 custombox._deltaAlign = tempDeltaAlign;
00476 custombox._deltaScaleGlobal = tempDeltaScaleGlobal;
00477 }
00478
00479 return ok;
00480 }
00481
00482 #include "KDChartCustomBox.moc"