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