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 #include "KDChartLegend.h"
00027 #include "KDChartLegend_p.h"
00028 #include <KDChartTextAttributes.h>
00029 #include <KDChartMarkerAttributes.h>
00030 #include <QFont>
00031 #include <QPainter>
00032 #include <QTextTableCell>
00033 #include <QTextCursor>
00034 #include <QTextCharFormat>
00035 #include <QTextDocumentFragment>
00036 #include <QTimer>
00037 #include <QAbstractTextDocumentLayout>
00038 #include <QtDebug>
00039 #include <QLabel>
00040 #include <KDChartAbstractDiagram.h>
00041 #include "KDTextDocument.h"
00042 #include <KDChartDiagramObserver.h>
00043 #include <QGridLayout>
00044 #include "KDChartLayoutItems.h"
00045
00046 #include <KDABLibFakes>
00047
00048 using namespace KDChart;
00049
00050 Legend::Private::Private() :
00051 referenceArea(0),
00052 position( Position::East ),
00053 alignment( Qt::AlignCenter ),
00054 relativePosition( RelativePosition() ),
00055 orientation( Qt::Vertical ),
00056 showLines( false ),
00057 texts(),
00058 textAttributes(),
00059 titleText( QObject::tr( "Legend" ) ),
00060 titleTextAttributes(),
00061 spacing( 1 ),
00062 useAutomaticMarkerSize( true ),
00063 legendStyle( MarkersOnly )
00064
00065 {
00066
00067
00068 relativePosition.setReferencePoints( PositionPoints( QPointF( 0.0, 0.0 ) ) );
00069 relativePosition.setReferencePosition( Position::NorthWest );
00070 relativePosition.setAlignment( Qt::AlignTop | Qt::AlignLeft );
00071 relativePosition.setHorizontalPadding( KDChart::Measure( 4.0, KDChartEnums::MeasureCalculationModeAbsolute ) );
00072 relativePosition.setVerticalPadding( KDChart::Measure( 4.0, KDChartEnums::MeasureCalculationModeAbsolute ) );
00073 }
00074
00075 Legend::Private::~Private()
00076 {
00077
00078 }
00079
00080
00081
00082 #define d d_func()
00083
00084
00085 Legend::Legend( QWidget* parent ) :
00086 AbstractAreaWidget( new Private(), parent )
00087 {
00088 d->referenceArea = parent;
00089 init();
00090 }
00091
00092 Legend::Legend( KDChart::AbstractDiagram* diagram, QWidget* parent ) :
00093 AbstractAreaWidget( new Private(), parent )
00094 {
00095 d->referenceArea = parent;
00096 init();
00097 setDiagram( diagram );
00098 }
00099
00100 Legend::~Legend()
00101 {
00102 emit destroyedLegend( this );
00103 }
00104
00105 void Legend::init()
00106 {
00107 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00108
00109 d->layout = new QGridLayout( this );
00110 d->layout->setMargin( 2 );
00111 d->layout->setSpacing( d->spacing );
00112
00113
00114 const Measure normalFontSizeTitle( 12, KDChartEnums::MeasureCalculationModeAbsolute );
00115 const Measure normalFontSizeLabels( 10, KDChartEnums::MeasureCalculationModeAbsolute );
00116 const Measure minimalFontSize( 4, KDChartEnums::MeasureCalculationModeAbsolute );
00117
00118 TextAttributes textAttrs;
00119 textAttrs.setPen( QPen( Qt::black ) );
00120 textAttrs.setFont( QFont( QLatin1String( "helvetica" ), 10, QFont::Normal, false ) );
00121 textAttrs.setFontSize( normalFontSizeLabels );
00122 textAttrs.setMinimalFontSize( minimalFontSize );
00123 setTextAttributes( textAttrs );
00124
00125 TextAttributes titleTextAttrs;
00126 titleTextAttrs.setPen( QPen( Qt::black ) );
00127 titleTextAttrs.setFont( QFont( QLatin1String( "helvetica" ), 12, QFont::Bold, false ) );
00128 titleTextAttrs.setFontSize( normalFontSizeTitle );
00129 titleTextAttrs.setMinimalFontSize( minimalFontSize );
00130 setTitleTextAttributes( titleTextAttrs );
00131
00132 FrameAttributes frameAttrs;
00133 frameAttrs.setVisible( true );
00134 frameAttrs.setPen( QPen( Qt::black ) );
00135 frameAttrs.setPadding( 1 );
00136 setFrameAttributes( frameAttrs );
00137
00138 d->position = Position::NorthEast;
00139 d->alignment = Qt::AlignCenter;
00140 }
00141
00142
00143 QSize Legend::minimumSizeHint() const
00144 {
00145 return sizeHint();
00146 }
00147
00148
00149
00150 QSize Legend::sizeHint() const
00151 {
00152 #ifdef DEBUG_LEGEND_PAINT
00153 qDebug() << "Legend::sizeHint() started";
00154 #endif
00155 Q_FOREACH( KDChart::AbstractLayoutItem* layoutItem, d->layoutItems ) {
00156 layoutItem->sizeHint();
00157 }
00158 return AbstractAreaWidget::sizeHint();
00159 }
00160
00161 void Legend::needSizeHint()
00162 {
00163
00164
00165 buildLegend();
00166 }
00167
00168 void Legend::resizeLayout( const QSize& size )
00169 {
00170 #ifdef DEBUG_LEGEND_PAINT
00171 qDebug() << "Legend::resizeLayout started";
00172 #endif
00173 if( d->layout ){
00174 d->layout->setGeometry( QRect(QPoint(0,0), size) );
00175 activateTheLayout();
00176 }
00177 #ifdef DEBUG_LEGEND_PAINT
00178 qDebug() << "Legend::resizeLayout done";
00179 #endif
00180 }
00181
00182 void Legend::activateTheLayout()
00183 {
00184 if( d->layout && d->layout->parent() )
00185 d->layout->activate();
00186 }
00187
00188
00189 void Legend::setLegendStyle( LegendStyle style )
00190 {
00191 if( d->legendStyle == style ) return;
00192 d->legendStyle = style;
00193 setNeedRebuild();
00194 }
00195
00196 Legend::LegendStyle Legend::legendStyle() const
00197 {
00198 return d->legendStyle;
00199 }
00200
00201 Legend* Legend::clone() const
00202 {
00203 Legend* legend = new Legend( new Private( *d ), 0 );
00204 legend->setTextAttributes( textAttributes() );
00205 legend->setTitleTextAttributes( titleTextAttributes() );
00206 legend->setFrameAttributes( frameAttributes() );
00207 legend->setUseAutomaticMarkerSize( useAutomaticMarkerSize() );
00208 legend->setPosition( position() );
00209 legend->setAlignment( alignment() );
00210 legend->setLegendStyle( legendStyle() );
00211 return legend;
00212 }
00213
00214
00215 bool Legend::compare( const Legend* other )const
00216 {
00217 if( other == this ) return true;
00218 if( ! other ){
00219
00220 return false;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 return ( static_cast<const AbstractAreaBase*>(this)->compare( other ) ) &&
00242 (isVisible() == other->isVisible()) &&
00243 (position() == other->position()) &&
00244 (alignment() == other->alignment())&&
00245 (floatingPosition() == other->floatingPosition()) &&
00246 (orientation() == other->orientation())&&
00247 (showLines() == other->showLines())&&
00248 (texts() == other->texts())&&
00249 (brushes() == other->brushes())&&
00250 (pens() == other->pens())&&
00251 (markerAttributes() == other->markerAttributes())&&
00252 (useAutomaticMarkerSize() == other->useAutomaticMarkerSize()) &&
00253 (textAttributes() == other->textAttributes()) &&
00254 (titleText() == other->titleText())&&
00255 (titleTextAttributes() == other->titleTextAttributes()) &&
00256 (spacing() == other->spacing()) &&
00257 (legendStyle() == other->legendStyle());
00258 }
00259
00260
00261 void Legend::paint( QPainter* painter )
00262 {
00263 #ifdef DEBUG_LEGEND_PAINT
00264 qDebug() << "entering Legend::paint( QPainter* painter )";
00265 #endif
00266
00267 if( ! diagram() ) return;
00268
00269
00270
00271
00272
00273
00274 Q_FOREACH( KDChart::AbstractLayoutItem* layoutItem, d->layoutItems ) {
00275 layoutItem->paint( painter );
00276 }
00277 #ifdef DEBUG_LEGEND_PAINT
00278 qDebug() << "leaving Legend::paint( QPainter* painter )";
00279 #endif
00280 }
00281
00282
00283 uint Legend::datasetCount() const
00284 {
00285 int modelLabelsCount = 0;
00286 int modelBrushesCount = 0;
00287 for (int i = 0; i < d->observers.size(); ++i) {
00288 DiagramObserver * obs = d->observers.at(i);
00289 modelLabelsCount += obs->diagram()->datasetLabels().count();
00290 modelBrushesCount += obs->diagram()->datasetBrushes().count();
00291 }
00292 Q_ASSERT( modelLabelsCount == modelBrushesCount );
00293 return modelLabelsCount;
00294 }
00295
00296
00297 void Legend::setReferenceArea( const QWidget* area )
00298 {
00299 if( area == d->referenceArea ) return;
00300 d->referenceArea = area;
00301 setNeedRebuild();
00302 }
00303
00304 const QWidget* Legend::referenceArea() const
00305 {
00306
00307 return (d->referenceArea ? d->referenceArea : static_cast<const QWidget*>(parent()));
00308 }
00309
00310
00311 AbstractDiagram* Legend::diagram() const
00312 {
00313 if( d->observers.isEmpty() )
00314 return 0;
00315 return d->observers.first()->diagram();
00316 }
00317
00318 DiagramList Legend::diagrams() const
00319 {
00320 DiagramList list;
00321 for (int i = 0; i < d->observers.size(); ++i)
00322 list << d->observers.at(i)->diagram();
00323 return list;
00324 }
00325
00326 ConstDiagramList Legend::constDiagrams() const
00327 {
00328 ConstDiagramList list;
00329 for (int i = 0; i < d->observers.size(); ++i)
00330 list << d->observers.at(i)->diagram();
00331 return list;
00332 }
00333
00334 void Legend::addDiagram( AbstractDiagram* newDiagram )
00335 {
00336 if ( newDiagram )
00337 {
00338 DiagramObserver* observer = new DiagramObserver( newDiagram, this );
00339
00340 DiagramObserver* oldObs = d->findObserverForDiagram( newDiagram );
00341 if( oldObs ){
00342 delete oldObs;
00343 d->observers[ d->observers.indexOf( oldObs ) ] = observer;
00344 }else{
00345 d->observers.append( observer );
00346 }
00347 connect( observer, SIGNAL( diagramDestroyed(AbstractDiagram*) ),
00348 SLOT( resetDiagram(AbstractDiagram*) ));
00349 connect( observer, SIGNAL( diagramDataChanged(AbstractDiagram*) ),
00350 SLOT( setNeedRebuild() ));
00351 connect( observer, SIGNAL( diagramDataHidden(AbstractDiagram*) ),
00352 SLOT( setNeedRebuild() ));
00353 connect( observer, SIGNAL( diagramAttributesChanged(AbstractDiagram*) ),
00354 SLOT( setNeedRebuild() ));
00355 setNeedRebuild();
00356 }
00357 }
00358
00359 void Legend::removeDiagram( AbstractDiagram* oldDiagram )
00360 {
00361 if( oldDiagram ){
00362 DiagramObserver* oldObs = d->findObserverForDiagram( oldDiagram );
00363 if( oldObs ){
00364
00365 delete oldObs;
00366
00367 d->observers.removeAt( d->observers.indexOf( oldObs ) );
00368
00369 }
00370 setNeedRebuild();
00371 }
00372 }
00373
00374 void Legend::removeDiagrams()
00375 {
00376 for (int i = 0; i < d->observers.size(); ++i)
00377 removeDiagram( d->observers.at(i)->diagram() );
00378 }
00379
00380 void Legend::replaceDiagram( AbstractDiagram* newDiagram,
00381 AbstractDiagram* oldDiagram )
00382 {
00383 KDChart::AbstractDiagram* old = oldDiagram;
00384 if( ! d->observers.isEmpty() && ! old ){
00385 old = d->observers.first()->diagram();
00386 if( ! old )
00387 d->observers.removeFirst();
00388 }
00389 if( old )
00390 removeDiagram( old );
00391 if( newDiagram )
00392 addDiagram( newDiagram );
00393 }
00394
00395 void Legend::setDiagram( KDChart::AbstractDiagram* newDiagram )
00396 {
00397 replaceDiagram( newDiagram );
00398 }
00399
00400 void Legend::resetDiagram( AbstractDiagram* oldDiagram )
00401 {
00402
00403 removeDiagram( oldDiagram );
00404 }
00405
00406 void Legend::setVisible( bool visible )
00407 {
00408 QWidget::setVisible( visible );
00409 emitPositionChanged();
00410 }
00411
00412 void Legend::setNeedRebuild()
00413 {
00414
00415 buildLegend();
00416 sizeHint();
00417 }
00418
00419 void Legend::setPosition( Position position )
00420 {
00421 d->position = position;
00422 emitPositionChanged();
00423 }
00424
00425 void Legend::emitPositionChanged()
00426 {
00427 emit positionChanged( this );
00428 emit propertiesChanged();
00429 }
00430
00431
00432 Position Legend::position() const
00433 {
00434 return d->position;
00435 }
00436
00437 void Legend::setAlignment( Qt::Alignment alignment )
00438 {
00439 d->alignment = alignment;
00440 emitPositionChanged();
00441 }
00442
00443 Qt::Alignment Legend::alignment() const
00444 {
00445 return d->alignment;
00446 }
00447
00448 void Legend::setFloatingPosition( const RelativePosition& relativePosition )
00449 {
00450 d->position = Position::Floating;
00451 if( d->relativePosition != relativePosition ){
00452 d->relativePosition = relativePosition;
00453 emitPositionChanged();
00454 }
00455 }
00456
00457 const RelativePosition Legend::floatingPosition() const
00458 {
00459 return d->relativePosition;
00460 }
00461
00462 void Legend::setOrientation( Qt::Orientation orientation )
00463 {
00464 if( d->orientation == orientation ) return;
00465 d->orientation = orientation;
00466 setNeedRebuild();
00467 emitPositionChanged();
00468 }
00469
00470 Qt::Orientation Legend::orientation() const
00471 {
00472 return d->orientation;
00473 }
00474
00475 void Legend::setShowLines( bool legendShowLines )
00476 {
00477 if( d->showLines == legendShowLines ) return;
00478 d->showLines = legendShowLines;
00479 setNeedRebuild();
00480 emitPositionChanged();
00481 }
00482
00483 bool Legend::showLines() const
00484 {
00485 return d->showLines;
00486 }
00487
00488 void Legend::setUseAutomaticMarkerSize( bool useAutomaticMarkerSize )
00489 {
00490 d->useAutomaticMarkerSize = useAutomaticMarkerSize;
00491 setNeedRebuild();
00492 emitPositionChanged();
00493 }
00494
00495 bool Legend::useAutomaticMarkerSize() const
00496 {
00497 return d->useAutomaticMarkerSize;
00498 }
00499
00505 void Legend::resetTexts()
00506 {
00507 if( ! d->texts.count() ) return;
00508 d->texts.clear();
00509 setNeedRebuild();
00510 }
00511
00512 void Legend::setText( uint dataset, const QString& text )
00513 {
00514 if( d->texts[ dataset ] == text ) return;
00515 d->texts[ dataset ] = text;
00516 setNeedRebuild();
00517 }
00518
00519 QString Legend::text( uint dataset ) const
00520 {
00521 if( d->texts.find( dataset ) != d->texts.end() ){
00522
00523 return d->texts[ dataset ];
00524 }else{
00525
00526 return d->modelLabels[ dataset ];
00527 }
00528 }
00529
00530 const QMap<uint,QString> Legend::texts() const
00531 {
00532 return d->texts;
00533 }
00534
00535 void Legend::setColor( uint dataset, const QColor& color )
00536 {
00537 if( d->brushes[ dataset ] == color ) return;
00538 d->brushes[ dataset ] = color;
00539 setNeedRebuild();
00540 }
00541
00542 void Legend::setBrush( uint dataset, const QBrush& brush )
00543 {
00544 if( d->brushes[ dataset ] == brush ) return;
00545 d->brushes[ dataset ] = brush;
00546 setNeedRebuild();
00547 }
00548
00549 QBrush Legend::brush( uint dataset ) const
00550 {
00551 if( d->brushes.find( dataset ) != d->brushes.end() )
00552 return d->brushes[ dataset ];
00553 else
00554 return d->modelBrushes[ dataset ];
00555 }
00556
00557 const QMap<uint,QBrush> Legend::brushes() const
00558 {
00559 return d->brushes;
00560 }
00561
00562
00563 void Legend::setBrushesFromDiagram( KDChart::AbstractDiagram* diagram )
00564 {
00565 bool bChangesDone = false;
00566 QList<QBrush> datasetBrushes = diagram->datasetBrushes();
00567 for( int i = 0; i < datasetBrushes.count(); i++ ){
00568 if( d->brushes[ i ] != datasetBrushes[ i ] ){
00569 d->brushes[ i ] = datasetBrushes[ i ];
00570 bChangesDone = true;
00571 }
00572 }
00573 if( bChangesDone )
00574 setNeedRebuild();
00575 }
00576
00577
00578 void Legend::setPen( uint dataset, const QPen& pen )
00579 {
00580 if( d->pens[dataset] == pen ) return;
00581 d->pens[dataset] = pen;
00582 setNeedRebuild();
00583 }
00584
00585 QPen Legend::pen( uint dataset ) const
00586 {
00587 if( d->pens.find( dataset ) != d->pens.end() )
00588 return d->pens[dataset];
00589 else
00590 return d->modelPens[ dataset ];
00591 }
00592
00593 const QMap<uint,QPen> Legend::pens() const
00594 {
00595 return d->pens;
00596 }
00597
00598
00599 void Legend::setMarkerAttributes( uint dataset, const MarkerAttributes& markerAttributes )
00600 {
00601 if( d->markerAttributes[dataset] == markerAttributes ) return;
00602 d->markerAttributes[ dataset ] = markerAttributes;
00603 setNeedRebuild();
00604 }
00605
00606 MarkerAttributes Legend::markerAttributes( uint dataset ) const
00607 {
00608 if( d->markerAttributes.find( dataset ) != d->markerAttributes.end() )
00609 return d->markerAttributes[ dataset ];
00610 else if ( static_cast<uint>( d->modelMarkers.count() ) > dataset )
00611 return d->modelMarkers[ dataset ];
00612 return MarkerAttributes();
00613 }
00614
00615 const QMap<uint, MarkerAttributes> Legend::markerAttributes() const
00616 {
00617 return d->markerAttributes;
00618 }
00619
00620
00621 void Legend::setTextAttributes( const TextAttributes &a )
00622 {
00623 if( d->textAttributes == a ) return;
00624 d->textAttributes = a;
00625 setNeedRebuild();
00626 }
00627
00628 TextAttributes Legend::textAttributes() const
00629 {
00630 return d->textAttributes;
00631 }
00632
00633 void Legend::setTitleText( const QString& text )
00634 {
00635 if( d->titleText == text ) return;
00636 d->titleText = text;
00637 setNeedRebuild();
00638 }
00639
00640 QString Legend::titleText() const
00641 {
00642 return d->titleText;
00643 }
00644
00645 void Legend::setTitleTextAttributes( const TextAttributes &a )
00646 {
00647 if( d->titleTextAttributes == a ) return;
00648 d->titleTextAttributes = a;
00649 setNeedRebuild();
00650 }
00651
00652 TextAttributes Legend::titleTextAttributes() const
00653 {
00654 return d->titleTextAttributes;
00655 }
00656
00657 void Legend::forceRebuild()
00658 {
00659 #ifdef DEBUG_LEGEND_PAINT
00660 qDebug() << "entering Legend::forceRebuild()";
00661 #endif
00662
00663 buildLegend();
00664 #ifdef DEBUG_LEGEND_PAINT
00665 qDebug() << "leaving Legend::forceRebuild()";
00666 #endif
00667 }
00668
00669 void Legend::setSpacing( uint space )
00670 {
00671 if( d->spacing == space && d->layout->spacing() == static_cast<int>(space) ) return;
00672 d->spacing = space;
00673 d->layout->setSpacing( space );
00674 setNeedRebuild();
00675 }
00676
00677 uint Legend::spacing() const
00678 {
00679 return d->spacing;
00680 }
00681
00682 void Legend::setDefaultColors()
00683 {
00684 setColor( 0, Qt::red );
00685 setColor( 1, Qt::green );
00686 setColor( 2, Qt::blue );
00687 setColor( 3, Qt::cyan );
00688 setColor( 4, Qt::magenta );
00689 setColor( 5, Qt::yellow );
00690 setColor( 6, Qt::darkRed );
00691 setColor( 7, Qt::darkGreen );
00692 setColor( 8, Qt::darkBlue );
00693 setColor( 9, Qt::darkCyan );
00694 setColor( 10, Qt::darkMagenta );
00695 setColor( 11, Qt::darkYellow );
00696 }
00697
00698 void Legend::setRainbowColors()
00699 {
00700 setColor( 0, QColor(255, 0,196) );
00701 setColor( 1, QColor(255, 0, 96) );
00702 setColor( 2, QColor(255, 128,64) );
00703 setColor( 3, Qt::yellow );
00704 setColor( 4, Qt::green );
00705 setColor( 5, Qt::cyan );
00706 setColor( 6, QColor( 96, 96,255) );
00707 setColor( 7, QColor(160, 0,255) );
00708 for( int i = 8; i < 16; ++i )
00709 setColor( i, brush( i - 8 ).color().light() );
00710 }
00711
00712 void Legend::setSubduedColors( bool ordered )
00713 {
00714 static const int NUM_SUBDUEDCOLORS = 18;
00715 static const QColor SUBDUEDCOLORS[ NUM_SUBDUEDCOLORS ] = {
00716 QColor( 0xe0,0x7f,0x70 ),
00717 QColor( 0xe2,0xa5,0x6f ),
00718 QColor( 0xe0,0xc9,0x70 ),
00719 QColor( 0xd1,0xe0,0x70 ),
00720 QColor( 0xac,0xe0,0x70 ),
00721 QColor( 0x86,0xe0,0x70 ),
00722 QColor( 0x70,0xe0,0x7f ),
00723 QColor( 0x70,0xe0,0xa4 ),
00724 QColor( 0x70,0xe0,0xc9 ),
00725 QColor( 0x70,0xd1,0xe0 ),
00726 QColor( 0x70,0xac,0xe0 ),
00727 QColor( 0x70,0x86,0xe0 ),
00728 QColor( 0x7f,0x70,0xe0 ),
00729 QColor( 0xa4,0x70,0xe0 ),
00730 QColor( 0xc9,0x70,0xe0 ),
00731 QColor( 0xe0,0x70,0xd1 ),
00732 QColor( 0xe0,0x70,0xac ),
00733 QColor( 0xe0,0x70,0x86 ),
00734 };
00735 if( ordered )
00736 for(int i=0; i<NUM_SUBDUEDCOLORS; ++i)
00737 setColor( i, SUBDUEDCOLORS[i] );
00738 else{
00739 setColor( 0, SUBDUEDCOLORS[ 0] );
00740 setColor( 1, SUBDUEDCOLORS[ 5] );
00741 setColor( 2, SUBDUEDCOLORS[10] );
00742 setColor( 3, SUBDUEDCOLORS[15] );
00743 setColor( 4, SUBDUEDCOLORS[ 2] );
00744 setColor( 5, SUBDUEDCOLORS[ 7] );
00745 setColor( 6, SUBDUEDCOLORS[12] );
00746 setColor( 7, SUBDUEDCOLORS[17] );
00747 setColor( 8, SUBDUEDCOLORS[ 4] );
00748 setColor( 9, SUBDUEDCOLORS[ 9] );
00749 setColor(10, SUBDUEDCOLORS[14] );
00750 setColor(11, SUBDUEDCOLORS[ 1] );
00751 setColor(12, SUBDUEDCOLORS[ 6] );
00752 setColor(13, SUBDUEDCOLORS[11] );
00753 setColor(14, SUBDUEDCOLORS[16] );
00754 setColor(15, SUBDUEDCOLORS[ 3] );
00755 setColor(16, SUBDUEDCOLORS[ 8] );
00756 setColor(17, SUBDUEDCOLORS[13] );
00757 }
00758 }
00759
00760 void Legend::resizeEvent ( QResizeEvent * event )
00761 {
00762 #ifdef DEBUG_LEGEND_PAINT
00763 qDebug() << "Legend::resizeEvent() called";
00764 #endif
00765 forceRebuild();
00766 sizeHint();
00767 QTimer::singleShot(0, this, SLOT(emitPositionChanged()));
00768 }
00769
00770 void Legend::buildLegend()
00771 {
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 Q_FOREACH( QLayoutItem* layoutItem, d->layoutItems ) {
00789 d->layout->removeItem( layoutItem );
00790 }
00791 qDeleteAll( d->layoutItems );
00792 d->layoutItems.clear();
00793
00794 if( orientation() == Qt::Vertical ) {
00795 d->layout->setColumnStretch( 4, 1 );
00796 } else {
00797 d->layout->setColumnStretch( 4, 0 );
00798 }
00799
00800 d->modelLabels.clear();
00801 d->modelBrushes.clear();
00802 d->modelPens.clear();
00803 d->modelMarkers.clear();
00804
00805 for (int i = 0; i < d->observers.size(); ++i){
00806 const AbstractDiagram* diagram = d->observers.at(i)->diagram();
00807 if( diagram ){
00808
00809 const QStringList diagramLabels( diagram->datasetLabels() );
00810 const QList<QBrush> diagramBrushes( diagram->datasetBrushes() );
00811 const QList<QPen> diagramPens( diagram->datasetPens() );
00812 const QList<MarkerAttributes> diagramMarkers( diagram->datasetMarkers() );
00813 for ( int dataset = 0; dataset < diagramLabels.count(); dataset++ ) {
00814
00815 if( ! diagram->isHidden( dataset ) ){
00816 d->modelLabels += diagramLabels[ dataset ];
00817 d->modelBrushes += diagramBrushes[ dataset ];
00818 d->modelPens += diagramPens[ dataset ];
00819 d->modelMarkers += diagramMarkers[ dataset ];
00820 }
00821 }
00822 }
00823 }
00824
00825 Q_ASSERT( d->modelLabels.count() == d->modelBrushes.count() );
00826
00827
00828 if( !titleText().isEmpty() && titleTextAttributes().isVisible() ) {
00829
00830 KDChart::TextLayoutItem* titleItem =
00831 new KDChart::TextLayoutItem( titleText(),
00832 titleTextAttributes(),
00833 referenceArea(),
00834 (orientation() == Qt::Vertical)
00835 ? KDChartEnums::MeasureOrientationMinimum
00836 : KDChartEnums::MeasureOrientationHorizontal,
00837 Qt::AlignCenter );
00838 titleItem->setParentWidget( this );
00839
00840 d->layoutItems << titleItem;
00841 if( orientation() == Qt::Vertical )
00842 d->layout->addItem( titleItem, 0, 0, 1, 5, Qt::AlignCenter );
00843 else
00844 d->layout->addItem( titleItem, 0, 0, 1, d->modelLabels.count() ? (d->modelLabels.count()*4) : 1, Qt::AlignCenter );
00845
00846
00847 if( showLines() && d->modelLabels.count() ) {
00848 KDChart::HorizontalLineLayoutItem* lineItem = new KDChart::HorizontalLineLayoutItem();
00849 d->layoutItems << lineItem;
00850 if( orientation() == Qt::Vertical )
00851 d->layout->addItem( lineItem, 1, 0, 1, 5, Qt::AlignCenter );
00852 else
00853 d->layout->addItem( lineItem, 1, 0, 1, d->modelLabels.count()*4, Qt::AlignCenter );
00854 }
00855 }
00856
00857 const KDChartEnums::MeasureOrientation orient =
00858 (orientation() == Qt::Vertical)
00859 ? KDChartEnums::MeasureOrientationMinimum
00860 : KDChartEnums::MeasureOrientationHorizontal;
00861 const TextAttributes labelAttrs( textAttributes() );
00862 const qreal fontHeight = labelAttrs.calculatedFontSize( referenceArea(), orient );
00863 const LegendStyle style = legendStyle();
00864
00865
00866 const bool bShowMarkers = (style != LinesOnly);
00867
00868 QSizeF maxMarkersSize(1.0, 1.0);
00869 QVector <MarkerAttributes> markerAttrs( d->modelLabels.count() );
00870 if( bShowMarkers ){
00871 for ( int dataset = 0; dataset < d->modelLabels.count(); ++dataset ) {
00872 markerAttrs[dataset] = markerAttributes( dataset );
00873 QSizeF siz;
00874 if( useAutomaticMarkerSize() ||
00875 ! markerAttrs[dataset].markerSize().isValid() )
00876 {
00877 siz = QSizeF(fontHeight, fontHeight);
00878 markerAttrs[dataset].setMarkerSize( siz );
00879 }else{
00880 siz = markerAttrs[dataset].markerSize();
00881 }
00882 maxMarkersSize =
00883 QSizeF(qMax(maxMarkersSize.width(), siz.width()),
00884 qMax(maxMarkersSize.height(), siz.height()));
00885 }
00886 }
00887
00888
00889
00890
00891
00892
00893 const int markerOffsOnLine = 8;
00894
00895 int maxLineLength = 18;
00896 {
00897 bool hasComplexPenStyle = false;
00898 for ( int dataset = 0; dataset < d->modelLabels.count(); ++dataset ){
00899 const QPen pn = pen(dataset);
00900 const Qt::PenStyle ps = pn.style();
00901 if( ps != Qt::NoPen ){
00902 maxLineLength = qMax( pn.width() * 18, maxLineLength );
00903 if( ps != Qt::SolidLine )
00904 hasComplexPenStyle = true;
00905 }
00906 }
00907 if( hasComplexPenStyle && bShowMarkers )
00908 maxLineLength =
00909 maxLineLength + markerOffsOnLine +
00910 static_cast<int>(maxMarkersSize.width());
00911 }
00912
00913 for ( int dataset = 0; dataset < d->modelLabels.count(); ++dataset ) {
00914 KDChart::AbstractLayoutItem* markerLineItem = 0;
00915 switch( style ){
00916 case( MarkersOnly ):
00917 markerLineItem = new KDChart::MarkerLayoutItem(
00918 diagram(),
00919 markerAttrs[dataset],
00920 brush( dataset ),
00921 pen( dataset ),
00922 Qt::AlignLeft );
00923 break;
00924 case( LinesOnly ):
00925 markerLineItem = new KDChart::LineLayoutItem(
00926 diagram(),
00927 maxLineLength,
00928 pen( dataset ),
00929 Qt::AlignCenter );
00930 break;
00931 case( MarkersAndLines ):
00932 markerLineItem = new KDChart::LineWithMarkerLayoutItem(
00933 diagram(),
00934 maxLineLength,
00935 pen( dataset ),
00936 markerOffsOnLine,
00937 markerAttrs[dataset],
00938 brush( dataset ),
00939 pen( dataset ),
00940 Qt::AlignCenter );
00941 break;
00942 default:
00943 Q_ASSERT( false );
00944 }
00945 if( markerLineItem ){
00946 d->layoutItems << markerLineItem;
00947 if( orientation() == Qt::Vertical )
00948 d->layout->addItem( markerLineItem,
00949 dataset*2+2,
00950 1,
00951 1, 1, Qt::AlignCenter );
00952 else
00953 d->layout->addItem( markerLineItem,
00954 2,
00955 dataset*4 );
00956 }
00957
00958
00959 KDChart::TextLayoutItem* labelItem =
00960 new KDChart::TextLayoutItem( text( dataset ),
00961 labelAttrs,
00962 referenceArea(), orient,
00963 Qt::AlignLeft );
00964 labelItem->setParentWidget( this );
00965
00966 d->layoutItems << labelItem;
00967 if( orientation() == Qt::Vertical )
00968 d->layout->addItem( labelItem,
00969 dataset*2+2,
00970 3 );
00971 else
00972 d->layout->addItem( labelItem,
00973 2,
00974 dataset*4+1 );
00975
00976
00977 if( orientation() == Qt::Vertical && showLines() && dataset != d->modelLabels.count()-1 ) {
00978 KDChart::HorizontalLineLayoutItem* lineItem = new KDChart::HorizontalLineLayoutItem();
00979 d->layoutItems << lineItem;
00980 d->layout->addItem( lineItem,
00981 dataset*2+1+2,
00982 0,
00983 1, 5, Qt::AlignCenter );
00984 }
00985
00986
00987 if( orientation() == Qt::Horizontal && showLines() && dataset != d->modelLabels.count()-1 ) {
00988 KDChart::VerticalLineLayoutItem* lineItem = new KDChart::VerticalLineLayoutItem();
00989 d->layoutItems << lineItem;
00990 d->layout->addItem( lineItem,
00991 2,
00992 style == MarkersAndLines ? dataset*4+3 : dataset*4+2 ,
00993 1, 1, Qt::AlignCenter );
00994 }
00995
00996 if( orientation() != Qt::Vertical ) {
00997 d->layout->addItem( new QSpacerItem( spacing(), 1 ),
00998 2,
00999 dataset*4+3 );
01000 }
01001 }
01002
01003
01004 if( orientation() == Qt::Vertical && showLines() && d->modelLabels.count() ) {
01005 KDChart::VerticalLineLayoutItem* lineItem = new KDChart::VerticalLineLayoutItem();
01006 d->layoutItems << lineItem;
01007 d->layout->addItem( lineItem, 2, 2, d->modelLabels.count()*2, 1 );
01008 }
01009
01010
01011 activateTheLayout();
01012
01013 emit propertiesChanged();
01014
01015
01016 #ifdef DEBUG_LEGEND_PAINT
01017 qDebug() << "leaving Legend::buildLegend()";
01018 #endif
01019 }
01020