Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

KDChartAbstractDiagram.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2006 Klarävdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Chart library.
00005  **
00006  ** This file may be distributed and/or modified under the terms of the
00007  ** GNU General Public License version 2 as published by the Free Software
00008  ** Foundation and appearing in the file LICENSE.GPL included in the
00009  ** packaging of this file.
00010  **
00011  ** Licensees holding valid commercial KD Chart licenses may use this file in
00012  ** accordance with the KD Chart Commercial License Agreement provided with
00013  ** the Software.
00014  **
00015  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017  **
00018  ** See http://www.kdab.net/kdchart for
00019  **   information about KDChart Commercial License Agreements.
00020  **
00021  ** Contact info@kdab.net if any conditions of this
00022  ** licensing are not clear to you.
00023  **
00024  **********************************************************************/
00025 
00026 #include <QPainter>
00027 #include <QDebug>
00028 #include <QApplication>
00029 #include <QAbstractProxyModel>
00030 #include <QStandardItemModel>
00031 #include <QSizeF>
00032 
00033 #include "KDChartAbstractCoordinatePlane.h"
00034 #include "KDChartChart.h"
00035 #include "KDChartDataValueAttributes.h"
00036 #include "KDChartTextAttributes.h"
00037 #include "KDChartMarkerAttributes.h"
00038 #include "KDChartAbstractDiagram.h"
00039 #include "KDChartAbstractDiagram_p.h"
00040 #include "KDChartAttributesModel.h"
00041 #include "KDChartAbstractThreeDAttributes.h"
00042 #include "KDChartThreeDLineAttributes.h"
00043 
00044 #include <KDABLibFakes>
00045 
00046 
00047 using namespace KDChart;
00048 
00049 namespace KDChart {
00050   class PrivateAttributesModel : public AttributesModel {
00051     Q_OBJECT
00052   public:
00053         explicit PrivateAttributesModel( QAbstractItemModel* model, QObject * parent = 0 )
00054           : AttributesModel(model,parent) {}
00055   };
00056 }
00057 
00058 AbstractDiagram::Private::Private()
00059   : plane( 0 )
00060   , attributesModel( new PrivateAttributesModel(0,0) )
00061   , allowOverlappingDataValueTexts( false )
00062   , antiAliasing( true )
00063   , percent( false )
00064   , datasetDimension( 1 )
00065   , databoundariesDirty(true)
00066   , lastRoundedValue()
00067   , lastX( 0 )
00068   , mCachedFontMetrics( QFontMetrics( qApp->font() ) )
00069 {
00070 }
00071 
00072 AbstractDiagram::Private::~Private()
00073 {
00074   if( attributesModel && qobject_cast<PrivateAttributesModel*>(attributesModel) )
00075     delete attributesModel;
00076 }
00077 
00078 void AbstractDiagram::Private::init()
00079 {
00080 }
00081 
00082 void AbstractDiagram::Private::init( AbstractCoordinatePlane* newPlane )
00083 {
00084     plane = newPlane;
00085 }
00086 
00087 bool AbstractDiagram::Private::usesExternalAttributesModel()const
00088 {
00089     return ( ! attributesModel.isNull() ) &&
00090            ( ! qobject_cast<PrivateAttributesModel*>(attributesModel) );
00091 }
00092 
00093 void AbstractDiagram::Private::setAttributesModel( AttributesModel* amodel )
00094 {
00095     if( !attributesModel.isNull() &&
00096         qobject_cast<PrivateAttributesModel*>(attributesModel) ) {
00097         delete attributesModel;
00098     }
00099     attributesModel = amodel;
00100 }
00101 
00102 AbstractDiagram::Private::Private( const AbstractDiagram::Private& rhs ) :
00103     // Do not copy the plane
00104     plane( 0 ),
00105     attributesModelRootIndex( QModelIndex() ),
00106     attributesModel( rhs.attributesModel ),
00107     allowOverlappingDataValueTexts( rhs.allowOverlappingDataValueTexts ),
00108     antiAliasing( rhs.antiAliasing ),
00109     percent( rhs.percent ),
00110     datasetDimension( rhs.datasetDimension ),
00111     mCachedFontMetrics( rhs.cachedFontMetrics() )
00112 {
00113     attributesModel = new PrivateAttributesModel( 0, 0);
00114     attributesModel->initFrom( rhs.attributesModel );
00115 }
00116 
00117 #define d d_func()
00118 
00119 AbstractDiagram::AbstractDiagram ( QWidget* parent, AbstractCoordinatePlane* plane )
00120     : QAbstractItemView ( parent ), _d( new Private() )
00121 {
00122     _d->init( plane );
00123 }
00124 
00125 AbstractDiagram::~AbstractDiagram()
00126 {
00127     delete _d;
00128 }
00129 
00130 void AbstractDiagram::init()
00131 {
00132 }
00133 
00134 
00135 bool AbstractDiagram::compare( const AbstractDiagram* other )const
00136 {
00137     if( other == this ) return true;
00138     if( ! other ){
00139         //qDebug() << "AbstractDiagram::compare() cannot compare to Null pointer";
00140         return false;
00141     }
00142     /*
00143     qDebug() << "\n             AbstractDiagram::compare() QAbstractScrollArea:";
00144             // compare QAbstractScrollArea properties
00145     qDebug() <<
00146             ((horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) &&
00147             (verticalScrollBarPolicy()    == other->verticalScrollBarPolicy()));
00148     qDebug() << "AbstractDiagram::compare() QFrame:";
00149             // compare QFrame properties
00150     qDebug() <<
00151             ((frameShadow() == other->frameShadow()) &&
00152             (frameShape()   == other->frameShape()) &&
00153             (frameWidth()   == other->frameWidth()) &&
00154             (lineWidth()    == other->lineWidth()) &&
00155             (midLineWidth() == other->midLineWidth()));
00156     qDebug() << "AbstractDiagram::compare() QAbstractItemView:";
00157             // compare QAbstractItemView properties
00158     qDebug() <<
00159             ((alternatingRowColors() == other->alternatingRowColors()) &&
00160             (hasAutoScroll()         == other->hasAutoScroll()) &&
00161 #if QT_VERSION > 0x040199
00162             (dragDropMode()          == other->dragDropMode()) &&
00163             (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
00164             (horizontalScrollMode()  == other->horizontalScrollMode ()) &&
00165             (verticalScrollMode()    == other->verticalScrollMode()) &&
00166 #endif
00167             (dragEnabled()           == other->dragEnabled()) &&
00168             (editTriggers()          == other->editTriggers()) &&
00169             (iconSize()              == other->iconSize()) &&
00170             (selectionBehavior()     == other->selectionBehavior()) &&
00171             (selectionMode()         == other->selectionMode()) &&
00172             (showDropIndicator()     == other->showDropIndicator()) &&
00173             (tabKeyNavigation()      == other->tabKeyNavigation()) &&
00174             (textElideMode()         == other->textElideMode()));
00175     qDebug() << "AbstractDiagram::compare() AttributesModel: ";
00176             // compare all of the properties stored in the attributes model
00177     qDebug() << attributesModel()->compare( other->attributesModel() );
00178     qDebug() << "AbstractDiagram::compare() own:";
00179             // compare own properties
00180     qDebug() <<
00181             ((rootIndex().column()            == other->rootIndex().column()) &&
00182             (rootIndex().row()                == other->rootIndex().row()) &&
00183             (allowOverlappingDataValueTexts() == other->allowOverlappingDataValueTexts()) &&
00184             (antiAliasing()                   == other->antiAliasing()) &&
00185             (percentMode()                    == other->percentMode()) &&
00186             (datasetDimension()               == other->datasetDimension()));
00187     */
00188     return  // compare QAbstractScrollArea properties
00189             (horizontalScrollBarPolicy() == other->horizontalScrollBarPolicy()) &&
00190             (verticalScrollBarPolicy()   == other->verticalScrollBarPolicy()) &&
00191             // compare QFrame properties
00192             (frameShadow()  == other->frameShadow()) &&
00193             (frameShape()   == other->frameShape()) &&
00194             (frameWidth()   == other->frameWidth()) &&
00195             (lineWidth()    == other->lineWidth()) &&
00196             (midLineWidth() == other->midLineWidth()) &&
00197             // compare QAbstractItemView properties
00198             (alternatingRowColors()  == other->alternatingRowColors()) &&
00199             (hasAutoScroll()         == other->hasAutoScroll()) &&
00200 #if QT_VERSION > 0x040199
00201             (dragDropMode()          == other->dragDropMode()) &&
00202             (dragDropOverwriteMode() == other->dragDropOverwriteMode()) &&
00203             (horizontalScrollMode()  == other->horizontalScrollMode ()) &&
00204             (verticalScrollMode()    == other->verticalScrollMode()) &&
00205 #endif
00206             (dragEnabled()           == other->dragEnabled()) &&
00207             (editTriggers()          == other->editTriggers()) &&
00208             (iconSize()              == other->iconSize()) &&
00209             (selectionBehavior()     == other->selectionBehavior()) &&
00210             (selectionMode()         == other->selectionMode()) &&
00211             (showDropIndicator()     == other->showDropIndicator()) &&
00212             (tabKeyNavigation()      == other->tabKeyNavigation()) &&
00213             (textElideMode()         == other->textElideMode()) &&
00214             // compare all of the properties stored in the attributes model
00215             attributesModel()->compare( other->attributesModel() ) &&
00216             // compare own properties
00217             (rootIndex().column()             == other->rootIndex().column()) &&
00218             (rootIndex().row()                == other->rootIndex().row()) &&
00219             (allowOverlappingDataValueTexts() == other->allowOverlappingDataValueTexts()) &&
00220             (antiAliasing()                   == other->antiAliasing()) &&
00221             (percentMode()                    == other->percentMode()) &&
00222             (datasetDimension()               == other->datasetDimension());
00223 }
00224 
00225 
00226 AbstractCoordinatePlane* AbstractDiagram::coordinatePlane() const
00227 {
00228     return d->plane;
00229 }
00230 
00231 const QPair<QPointF, QPointF> AbstractDiagram::dataBoundaries () const
00232 {
00233     if( d->databoundariesDirty ){
00234         d->databoundaries = calculateDataBoundaries ();
00235         d->databoundariesDirty = false;
00236     }
00237     return d->databoundaries;
00238 }
00239 
00240 void AbstractDiagram::setDataBoundariesDirty() const
00241 {
00242     d->databoundariesDirty = true;
00243 }
00244 
00245 void AbstractDiagram::setModel ( QAbstractItemModel * newModel )
00246 {
00247   QAbstractItemView::setModel( newModel );
00248   AttributesModel* amodel = new PrivateAttributesModel( newModel, this );
00249   amodel->initFrom( d->attributesModel );
00250   d->setAttributesModel(amodel);
00251   scheduleDelayedItemsLayout();
00252   d->databoundariesDirty = true;
00253   emit modelsChanged();
00254 }
00255 
00261 void AbstractDiagram::setAttributesModel( AttributesModel* amodel )
00262 {
00263     if( amodel->sourceModel() != model() ) {
00264         qWarning("KDChart::AbstractDiagram::setAttributesModel() failed: "
00265                  "Trying to set an attributesmodel which works on a different "
00266                  "model than the diagram.");
00267         return;
00268     }
00269     if( qobject_cast<PrivateAttributesModel*>(amodel) ) {
00270         qWarning("KDChart::AbstractDiagram::setAttributesModel() failed: "
00271                  "Trying to set an attributesmodel that is private to another diagram.");
00272         return;
00273     }
00274     d->setAttributesModel(amodel);
00275     scheduleDelayedItemsLayout();
00276     d->databoundariesDirty = true;
00277     emit modelsChanged();
00278 }
00279 
00280 bool AbstractDiagram::usesExternalAttributesModel()const
00281 {
00282     return d->usesExternalAttributesModel();
00283 }
00284 
00286 AttributesModel* AbstractDiagram::attributesModel() const
00287 {
00288     return d->attributesModel;
00289 }
00290 
00292 void AbstractDiagram::setRootIndex ( const QModelIndex& idx )
00293 {
00294     QAbstractItemView::setRootIndex(idx);
00295     setAttributesModelRootIndex( d->attributesModel->mapFromSource(idx) );
00296 }
00297 
00299 void AbstractDiagram::setAttributesModelRootIndex( const QModelIndex& idx )
00300 {
00301   d->attributesModelRootIndex=idx;
00302   d->databoundariesDirty = true;
00303   scheduleDelayedItemsLayout();
00304 }
00305 
00308 QModelIndex AbstractDiagram::attributesModelRootIndex() const
00309 {
00310     if ( !d->attributesModelRootIndex.isValid() )
00311         d->attributesModelRootIndex = d->attributesModel->mapFromSource( rootIndex() );
00312   return d->attributesModelRootIndex;
00313 }
00314 
00315 QModelIndex AbstractDiagram::columnToIndex( int column ) const
00316 {
00317     if( model() )
00318         return QModelIndex( model()->index( 0, column, rootIndex() ) );
00319     return QModelIndex();
00320 }
00321 
00322 void AbstractDiagram::setCoordinatePlane( AbstractCoordinatePlane* parent )
00323 {
00324     d->plane = parent;
00325 }
00326 
00327 void AbstractDiagram::doItemsLayout()
00328 {
00329     if ( d->plane ) {
00330         d->plane->layoutDiagrams();
00331         update();
00332     }
00333     QAbstractItemView::doItemsLayout();
00334 }
00335 
00336 void AbstractDiagram::dataChanged( const QModelIndex &topLeft,
00337                                    const QModelIndex &bottomRight )
00338 {
00339   // We are still too dumb to do intelligent updates...
00340   d->databoundariesDirty = true;
00341   scheduleDelayedItemsLayout();
00342 }
00343 
00344 
00345 void AbstractDiagram::setHidden( const QModelIndex & index, bool hidden )
00346 {
00347     d->attributesModel->setData(
00348         d->attributesModel->mapFromSource( index ),
00349         qVariantFromValue( hidden ),
00350         DataHiddenRole );
00351     emit dataHidden();
00352 }
00353 
00354 void AbstractDiagram::setHidden( int column, bool hidden )
00355 {
00356     d->attributesModel->setHeaderData(
00357         column, Qt::Vertical,
00358         qVariantFromValue( hidden ),
00359         DataHiddenRole );
00360     emit dataHidden();
00361 }
00362 
00363 void AbstractDiagram::setHidden( bool hidden )
00364 {
00365     d->attributesModel->setModelData(
00366         qVariantFromValue( hidden ),
00367         DataHiddenRole );
00368     emit dataHidden();
00369 }
00370 
00371 bool AbstractDiagram::isHidden() const
00372 {
00373     return qVariantValue<bool>(
00374         attributesModel()->modelData( DataHiddenRole ) );
00375 }
00376 
00377 bool AbstractDiagram::isHidden( int column ) const
00378 {
00379     return qVariantValue<bool>(
00380         attributesModel()->data(
00381             attributesModel()->mapFromSource(columnToIndex( column )),
00382             DataHiddenRole ) );
00383 }
00384 bool AbstractDiagram::isHidden( const QModelIndex & index ) const
00385 {
00386     return qVariantValue<bool>(
00387         attributesModel()->data(
00388             attributesModel()->mapFromSource(index),
00389             DataHiddenRole ) );
00390 }
00391 
00392 
00393 void AbstractDiagram::setDataValueAttributes( const QModelIndex & index,
00394                                               const DataValueAttributes & a )
00395 {
00396     d->attributesModel->setData(
00397         d->attributesModel->mapFromSource( index ),
00398         qVariantFromValue( a ),
00399         DataValueLabelAttributesRole );
00400     emit propertiesChanged();
00401 }
00402 
00403 
00404 void AbstractDiagram::setDataValueAttributes( int column, const DataValueAttributes & a )
00405 {
00406     d->attributesModel->setHeaderData(
00407         column, Qt::Vertical,
00408         qVariantFromValue( a ), DataValueLabelAttributesRole );
00409     emit propertiesChanged();
00410 }
00411 
00412 DataValueAttributes AbstractDiagram::dataValueAttributes() const
00413 {
00414     return qVariantValue<DataValueAttributes>(
00415         attributesModel()->modelData( KDChart::DataValueLabelAttributesRole ) );
00416 }
00417 
00418 DataValueAttributes AbstractDiagram::dataValueAttributes( int column ) const
00419 {
00420     return qVariantValue<DataValueAttributes>(
00421         attributesModel()->data( attributesModel()->mapFromSource(columnToIndex( column )),
00422         KDChart::DataValueLabelAttributesRole ) );
00423 }
00424 
00425 DataValueAttributes AbstractDiagram::dataValueAttributes( const QModelIndex & index ) const
00426 {
00427     return qVariantValue<DataValueAttributes>(
00428         attributesModel()->data( attributesModel()->mapFromSource(index),
00429         KDChart::DataValueLabelAttributesRole ) );
00430 }
00431 
00432 void AbstractDiagram::setDataValueAttributes( const DataValueAttributes & a )
00433 {
00434     d->attributesModel->setModelData( qVariantFromValue( a ), DataValueLabelAttributesRole );
00435     emit propertiesChanged();
00436 }
00437 
00438 void AbstractDiagram::setAllowOverlappingDataValueTexts( bool allow )
00439 {
00440     d->allowOverlappingDataValueTexts = allow;
00441     emit propertiesChanged();
00442 }
00443 
00444 bool AbstractDiagram::allowOverlappingDataValueTexts() const
00445 {
00446     return d->allowOverlappingDataValueTexts;
00447 }
00448 
00449 void AbstractDiagram::setAntiAliasing( bool enabled )
00450 {
00451     d->antiAliasing = enabled;
00452     emit propertiesChanged();
00453 }
00454 
00455 bool AbstractDiagram::antiAliasing() const
00456 {
00457     return d->antiAliasing;
00458 }
00459 
00460 void AbstractDiagram::setPercentMode ( bool percent )
00461 {
00462     d->percent = percent;
00463     emit propertiesChanged();
00464 }
00465 
00466 bool AbstractDiagram::percentMode() const
00467 {
00468     return d->percent;
00469 }
00470 
00471 
00472 void AbstractDiagram::paintDataValueText( QPainter* painter,
00473                                           const QModelIndex& index,
00474                                           const QPointF& pos,
00475                                           double value )
00476 {
00477     // paint one data series
00478     const DataValueAttributes a( dataValueAttributes(index) );
00479     if ( !a.isVisible() ) return;
00480 
00481     // handle decimal digits
00482     int decimalDigits = a.decimalDigits();
00483     int decimalPos = QString::number(  value ).indexOf( QLatin1Char( '.' ) );
00484     QString roundedValue;
00485     if ( a.dataLabel().isNull() ) {
00486         if ( decimalPos > 0 && value != 0 )
00487             roundedValue =  roundValues ( value, decimalPos, decimalDigits );
00488         else
00489             roundedValue = QString::number(  value );
00490     } else
00491         roundedValue = a.dataLabel();
00492         // handle prefix and suffix
00493     if ( !a.prefix().isNull() )
00494         roundedValue.prepend( a.prefix() );
00495 
00496     if ( !a.suffix().isNull() )
00497         roundedValue.append( a.suffix() );
00498 
00499     const TextAttributes ta( a.textAttributes() );
00500     // FIXME draw the non-text bits, background, etc
00501     if ( ta.isVisible() ) {
00502 
00503         QPointF pt( pos );
00504         /* for debugging:
00505         PainterSaver painterSaver( painter );
00506         painter->setPen( Qt::black );
00507         painter->drawLine( pos - QPointF( 1,1), pos + QPointF( 1,1) );
00508         painter->drawLine( pos - QPointF(-1,1), pos + QPointF(-1,1) );
00509         */
00510 
00511         // adjust the text start point position, if alignment is not Bottom/Left
00512         const RelativePosition relPos( a.position( value >= 0.0 ) );
00513         const Qt::Alignment alignBottomLeft = Qt::AlignBottom | Qt::AlignLeft;
00514         const QFont calculatedFont( ta.calculatedFont( d->plane, KDChartEnums::MeasureOrientationMinimum ) );
00515         //qDebug() << "calculatedFont's point size:" << calculatedFont.pointSizeF();
00516         if( (relPos.alignment() & alignBottomLeft) != alignBottomLeft ){
00517             const QRectF boundRect(
00518                     d->cachedFontMetrics( calculatedFont, this )->boundingRect( roundedValue ) );
00519             if( relPos.alignment() & Qt::AlignRight )
00520                 pt.rx() -= boundRect.width();
00521             else if( relPos.alignment() & Qt::AlignHCenter )
00522                 pt.rx() -= 0.5 * boundRect.width();
00523 
00524             if( relPos.alignment() & Qt::AlignTop )
00525                 pt.ry() += boundRect.height();
00526             else if( relPos.alignment() & Qt::AlignVCenter )
00527                 pt.ry() += 0.5 * boundRect.height();
00528         }
00529 
00530         // FIXME draw the non-text bits, background, etc
00531 
00532         if ( a.showRepetitiveDataLabels() ||
00533              pos.x() <= d->lastX ||
00534              d->lastRoundedValue != roundedValue ) {
00535             d->lastRoundedValue = roundedValue;
00536             d->lastX = pos.x();
00537 
00538             PainterSaver painterSaver( painter );
00539             painter->setPen( ta.pen() );
00540             painter->setFont( calculatedFont );
00541             painter->translate( pt );
00542             painter->rotate( ta.rotation() );
00543             painter->drawText( QPointF(0, 0), roundedValue );
00544         }
00545     }
00546 }
00547 
00548 
00549 QString  AbstractDiagram::roundValues( double value,
00550                                        const int decimalPos,
00551                                        const int decimalDigits ) const {
00552 
00553     QString digits( QString::number( value ).mid( decimalPos+1 ) );
00554     QString num( QString::number( value ) );
00555     num.truncate( decimalPos );
00556     int count = 0;
00557         for (  int i = digits.length(); i >= decimalDigits ; --i ) {
00558             count += 1;
00559             int lastval = QString( digits.data() [i] ).toInt();
00560             int val = QString( digits.data() [i-1] ) .toInt();
00561             if ( lastval >= 5 ) {
00562                 val += 1;
00563                 digits.replace( digits.length() - count,1 , QString::number( val ) );
00564             }
00565         }
00566 
00567     digits.truncate( decimalDigits );
00568     num.append( QLatin1Char( '.' ) + digits );
00569 
00570     return num;
00571 
00572 }
00573 
00574 void AbstractDiagram::paintDataValueTexts( QPainter* painter )
00575 {
00576     if ( !checkInvariants() ) return;
00577     const int rowCount = model()->rowCount(rootIndex());
00578     const int columnCount = model()->columnCount(rootIndex());
00579     for ( int i=datasetDimension()-1; i<columnCount; i += datasetDimension() ) {
00580        for ( int j=0; j< rowCount; ++j ) {
00581            const QModelIndex index = model()->index( j, i, rootIndex() );
00582            double value = model()->data( index ).toDouble();
00583            const QPointF pos = coordinatePlane()->translate( QPointF( j, value ) );
00584            paintDataValueText( painter, index, pos, value );
00585        }
00586     }
00587 }
00588 
00589 
00590 void AbstractDiagram::paintMarker( QPainter* painter,
00591                                    const QModelIndex& index,
00592                                    const QPointF& pos )
00593 {
00594 
00595     if ( !checkInvariants() ) return;
00596     DataValueAttributes a = dataValueAttributes(index);
00597     if ( !a.isVisible() ) return;
00598     const MarkerAttributes &ma = a.markerAttributes();
00599     if ( !ma.isVisible() ) return;
00600 
00601     PainterSaver painterSaver( painter );
00602     QSizeF maSize( ma.markerSize() );
00603     QBrush indexBrush( brush( index ) );
00604     QPen indexPen( ma.pen() );
00605     if ( ma.markerColor().isValid() )
00606         indexBrush.setColor( ma.markerColor() );
00607 
00608     paintMarker( painter, ma, indexBrush, indexPen, pos, maSize );
00609 }
00610 
00611 
00612 void AbstractDiagram::paintMarker( QPainter* painter,
00613                                    const MarkerAttributes& markerAttributes,
00614                                    const QBrush& brush,
00615                                    const QPen& pen,
00616                                    const QPointF& pos,
00617                                    const QSizeF& maSize )
00618 {
00619 
00620     const QPen oldPen( painter->pen() );
00621     // Pen is used to paint 4Pixels - 1 Pixel - Ring and FastCross types.
00622     // make sure to use the brush color - see above in those cases.
00623     const bool isFourPixels = (markerAttributes.markerStyle() == MarkerAttributes::Marker4Pixels);
00624     if( isFourPixels || (markerAttributes.markerStyle() == MarkerAttributes::Marker1Pixel) ){
00625         // for high-performance point charts with tiny point markers:
00626         painter->setPen( QPen( brush.color().light() ) );
00627         if( isFourPixels ){
00628             const qreal x = pos.x();
00629             const qreal y = pos.y();
00630             painter->drawLine( QPointF(x-1.0,y-1.0),
00631                                QPointF(x+1.0,y-1.0) );
00632             painter->drawLine( QPointF(x-1.0,y),
00633                                QPointF(x+1.0,y) );
00634             painter->drawLine( QPointF(x-1.0,y+1.0),
00635                                QPointF(x+1.0,y+1.0) );
00636         }
00637         painter->drawPoint( pos );
00638     }else{
00639         PainterSaver painterSaver( painter );
00640         // we only a solid line surrounding the markers
00641         QPen painterPen( pen );
00642         painterPen.setStyle( Qt::SolidLine );
00643         painter->setPen( painterPen );
00644         painter->setBrush( brush );
00645         painter->setRenderHint ( QPainter::Antialiasing );
00646         painter->translate( pos );
00647         switch ( markerAttributes.markerStyle() ) {
00648             case MarkerAttributes::MarkerCircle:
00649                 painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
00650                             maSize.height(), maSize.width()) );
00651                 break;
00652             case MarkerAttributes::MarkerSquare:
00653                 {
00654                     QRectF rect( 0 - maSize.width()/2, 0 - maSize.height()/2,
00655                                 maSize.width(), maSize.height() );
00656                     painter->drawRect( rect );
00657                     painter->fillRect( rect, brush.color() );
00658                     break;
00659                 }
00660             case MarkerAttributes::MarkerDiamond:
00661                 {
00662                     QVector <QPointF > diamondPoints;
00663                     QPointF top, left, bottom, right;
00664                     top    = QPointF( 0, 0 - maSize.height()/2 );
00665                     left   = QPointF( 0 - maSize.width()/2, 0 );
00666                     bottom = QPointF( 0, maSize.height()/2 );
00667                     right  = QPointF( maSize.width()/2, 0 );
00668                     diamondPoints << top << left << bottom << right;
00669                     painter->drawPolygon( diamondPoints );
00670                     break;
00671                 }
00672             // both handled on top of the method:
00673             case MarkerAttributes::Marker1Pixel:
00674             case MarkerAttributes::Marker4Pixels:
00675                     break;
00676             case MarkerAttributes::MarkerRing:
00677                 {
00678                     painter->setPen( QPen( brush.color() ) );
00679                     painter->setBrush( Qt::NoBrush );
00680                     painter->drawEllipse( QRectF( 0 - maSize.height()/2, 0 - maSize.width()/2,
00681                                         maSize.height(), maSize.width()) );
00682                     break;
00683                 }
00684             case MarkerAttributes::MarkerCross:
00685                 {
00686                     QRectF rect( maSize.width()*-0.5, maSize.height()*-0.2,
00687                                  maSize.width(), maSize.height()*0.4 );
00688                     painter->drawRect( rect );
00689                     rect.setTopLeft(QPointF( maSize.width()*-0.2, maSize.height()*-0.5 ));
00690                     rect.setSize(QSizeF( maSize.width()*0.4, maSize.height() ));
00691                     painter->drawRect( rect );
00692                     break;
00693                 }
00694             case MarkerAttributes::MarkerFastCross:
00695                 {
00696                     QPointF left, right, top, bottom;
00697                     left  = QPointF( -maSize.width()/2, 0 );
00698                     right = QPointF( maSize.width()/2, 0 );
00699                     top   = QPointF( 0, -maSize.height()/2 );
00700                     bottom= QPointF( 0, maSize.height()/2 );
00701                     painter->setPen( QPen( brush.color() ) );
00702                     painter->drawLine( left, right );
00703                     painter->drawLine(  top, bottom );
00704                     break;
00705                 }
00706             default:
00707                 Q_ASSERT_X ( false, "paintMarkers()",
00708                             "Type item does not match a defined Marker Type." );
00709         }
00710     }
00711     painter->setPen( oldPen );
00712 }
00713 
00714 void AbstractDiagram::paintMarkers( QPainter* painter )
00715 {
00716     if ( !checkInvariants() ) return;
00717     const int rowCount = model()->rowCount(rootIndex());
00718     const int columnCount = model()->columnCount(rootIndex());
00719     for ( int i=datasetDimension()-1; i<columnCount; i += datasetDimension() ) {
00720        for ( int j=0; j< rowCount; ++j ) {
00721            const QModelIndex index = model()->index( j, i, rootIndex() );
00722            double value = model()->data( index ).toDouble();
00723            const QPointF pos = coordinatePlane()->translate( QPointF( j, value ) );
00724            paintMarker( painter, index, pos );
00725        }
00726     }
00727 }
00728 
00729 
00730 void AbstractDiagram::setPen( const QModelIndex& index, const QPen& pen )
00731 {
00732     attributesModel()->setData(
00733         attributesModel()->mapFromSource( index ),
00734         qVariantFromValue( pen ), DatasetPenRole );
00735     emit propertiesChanged();
00736 }
00737 
00738 void AbstractDiagram::setPen( const QPen& pen )
00739 {
00740     attributesModel()->setModelData(
00741         qVariantFromValue( pen ), DatasetPenRole );
00742     emit propertiesChanged();
00743 }
00744 
00745 void AbstractDiagram::setPen( int column,const QPen& pen )
00746 {
00747     attributesModel()->setHeaderData(
00748         column, Qt::Vertical,
00749         qVariantFromValue( pen ),
00750         DatasetPenRole );
00751     emit propertiesChanged();
00752 }
00753 
00754 QPen AbstractDiagram::pen() const
00755 {
00756     return qVariantValue<QPen>(
00757         attributesModel()->data( DatasetPenRole ) );
00758 }
00759 
00760 QPen AbstractDiagram::pen( int dataset ) const
00761 {
00762     return qVariantValue<QPen>(
00763         attributesModel()->data(
00764             attributesModel()->mapFromSource( columnToIndex( dataset ) ),
00765             DatasetPenRole ) );
00766 }
00767 
00768 QPen AbstractDiagram::pen( const QModelIndex& index ) const
00769 {
00770     return qVariantValue<QPen>(
00771         attributesModel()->data(
00772             attributesModel()->mapFromSource( index ),
00773             DatasetPenRole ) );
00774 }
00775 
00776 void AbstractDiagram::setBrush( const QModelIndex& index, const QBrush& brush )
00777 {
00778     attributesModel()->setData(
00779         attributesModel()->mapFromSource( index ),
00780         qVariantFromValue( brush ), DatasetBrushRole );
00781     emit propertiesChanged();
00782 }
00783 
00784 void AbstractDiagram::setBrush( const QBrush& brush )
00785 {
00786     attributesModel()->setModelData(
00787         qVariantFromValue( brush ), DatasetBrushRole );
00788     emit propertiesChanged();
00789 }
00790 
00791 void AbstractDiagram::setBrush( int column, const QBrush& brush )
00792 {
00793     attributesModel()->setHeaderData(
00794         column, Qt::Vertical,
00795         qVariantFromValue( brush ),
00796         DatasetBrushRole );
00797     emit propertiesChanged();
00798 }
00799 
00800 QBrush AbstractDiagram::brush() const
00801 {
00802     return qVariantValue<QBrush>(
00803         attributesModel()->data( DatasetBrushRole ) );
00804 }
00805 
00806 QBrush AbstractDiagram::brush( int dataset ) const
00807 {
00808     return qVariantValue<QBrush>(
00809         attributesModel()->data(
00810             attributesModel()->mapFromSource( columnToIndex( dataset ) ),
00811             DatasetBrushRole ) );
00812 }
00813 
00814 QBrush AbstractDiagram::brush( const QModelIndex& index ) const
00815 {
00816     return qVariantValue<QBrush>(
00817         attributesModel()->data(
00818             attributesModel()->mapFromSource( index ),
00819             DatasetBrushRole ) );
00820 }
00821 
00822 // implement QAbstractItemView:
00823 QRect AbstractDiagram::visualRect(const QModelIndex &) const
00824 {
00825     return QRect();
00826 }
00827 
00828 void AbstractDiagram::scrollTo(const QModelIndex &, ScrollHint )
00829 {}
00830 
00831 QModelIndex AbstractDiagram::indexAt(const QPoint &) const
00832 { return QModelIndex(); }
00833 
00834 QModelIndex AbstractDiagram::moveCursor(CursorAction, Qt::KeyboardModifiers )
00835 { return QModelIndex(); }
00836 
00837 int AbstractDiagram::horizontalOffset() const
00838 { return 0; }
00839 
00840 int AbstractDiagram::verticalOffset() const
00841 { return 0; }
00842 
00843 bool AbstractDiagram::isIndexHidden(const QModelIndex &) const
00844 { return true; }
00845 
00846 void AbstractDiagram::setSelection(const QRect &, QItemSelectionModel::SelectionFlags)
00847 {}
00848 
00849 QRegion AbstractDiagram::visualRegionForSelection(const QItemSelection &) const
00850 { return QRegion(); }
00851 
00852 
00853 void KDChart::AbstractDiagram::useDefaultColors( )
00854 {
00855     d->attributesModel->setPaletteType( AttributesModel::PaletteTypeDefault );
00856 }
00857 
00858 void KDChart::AbstractDiagram::useSubduedColors( )
00859 {
00860     d->attributesModel->setPaletteType( AttributesModel::PaletteTypeSubdued );
00861 }
00862 
00863 void KDChart::AbstractDiagram::useRainbowColors( )
00864 {
00865     d->attributesModel->setPaletteType( AttributesModel::PaletteTypeRainbow );
00866 }
00867 
00868 QStringList AbstractDiagram::itemRowLabels() const
00869 {
00870     QStringList ret;
00871     //qDebug() << "AbstractDiagram::itemRowLabels(): " << attributesModel()->rowCount(attributesModelRootIndex()) << "entries";
00872     const int rowCount = attributesModel()->rowCount(attributesModelRootIndex());
00873     for( int i = 0; i < rowCount; ++i ){
00874         //qDebug() << "item row label: " << attributesModel()->headerData( i, Qt::Vertical, Qt::DisplayRole ).toString();
00875         ret << attributesModel()->headerData( i, Qt::Vertical, Qt::DisplayRole ).toString();
00876     }
00877     return ret;
00878 }
00879 
00880 QStringList AbstractDiagram::datasetLabels() const
00881 {
00882     QStringList ret;
00883     //qDebug() << "AbstractDiagram::datasetLabels(): " << attributesModel()->columnCount(attributesModelRootIndex()) << "entries";
00884     const int columnCount = attributesModel()->columnCount(attributesModelRootIndex());
00885     for( int i = datasetDimension()-1; i < columnCount; i += datasetDimension() ){
00886         //qDebug() << "dataset label: " << attributesModel()->headerData( i, Qt::Horizontal, Qt::DisplayRole ).toString();
00887         ret << attributesModel()->headerData( i, Qt::Horizontal, Qt::DisplayRole ).toString();
00888     }
00889     return ret;
00890 }
00891 
00892 QList<QBrush> AbstractDiagram::datasetBrushes() const
00893 {
00894     QList<QBrush> ret;
00895     const int columnCount = attributesModel()->columnCount(attributesModelRootIndex());
00896     for( int i = datasetDimension()-1; i < columnCount; i += datasetDimension() ) {
00897         QBrush brush = qVariantValue<QBrush>( attributesModel()->headerData( i, Qt::Vertical, DatasetBrushRole ) );
00898         ret << brush;
00899     }
00900 
00901     return ret;
00902 }
00903 
00904 QList<QPen> AbstractDiagram::datasetPens() const
00905 {
00906     QList<QPen> ret;
00907     const int columnCount = attributesModel()->columnCount(attributesModelRootIndex());
00908     for( int i = datasetDimension()-1; i < columnCount; i += datasetDimension() ) {
00909         QPen pen = qVariantValue<QPen>( attributesModel()->headerData( i, Qt::Vertical, DatasetPenRole ) );
00910         ret << pen;
00911     }
00912     return ret;
00913 }
00914 
00915 QList<MarkerAttributes> AbstractDiagram::datasetMarkers() const
00916 {
00917     QList<MarkerAttributes> ret;
00918     const int columnCount = attributesModel()->columnCount(attributesModelRootIndex());
00919     for( int i = datasetDimension()-1; i < columnCount; i += datasetDimension() ) {
00920         DataValueAttributes a =
00921             qVariantValue<DataValueAttributes>( attributesModel()->headerData( i, Qt::Vertical, DataValueLabelAttributesRole ) );
00922         const MarkerAttributes &ma = a.markerAttributes();
00923         ret << ma;
00924     }
00925     return ret;
00926 }
00927 
00928 bool AbstractDiagram::checkInvariants( bool justReturnTheStatus ) const
00929 {
00930     if( ! justReturnTheStatus ){
00931         Q_ASSERT_X ( model(), "AbstractDiagram::checkInvariants()",
00932                     "There is no usable model set, for the diagram." );
00933 
00934         Q_ASSERT_X ( coordinatePlane(), "AbstractDiagram::checkInvariants()",
00935                     "There is no usable coordinate plane set, for the diagram." );
00936     }
00937     return model() && coordinatePlane();
00938 }
00939 
00940 int AbstractDiagram::datasetDimension( ) const
00941 {
00942     return d->datasetDimension;
00943 }
00944 
00945 void AbstractDiagram::setDatasetDimension( int dimension )
00946 {
00947     if ( d->datasetDimension == dimension ) return;
00948     d->datasetDimension = dimension;
00949     d->databoundariesDirty = true;
00950     emit layoutChanged( this );
00951 }
00952 
00953 double AbstractDiagram::valueForCell( int row, int column ) const
00954 {
00955     return d->attributesModel->data(
00956             d->attributesModel->index( row, column, attributesModelRootIndex() ) ).toDouble();
00957 }
00958 
00959 void AbstractDiagram::update() const
00960 {
00961     //qDebug("KDChart::AbstractDiagram::update() called");
00962     if( d->plane )
00963         d->plane->update();
00964 }
00965 
00966 
00967 #include "KDChartAbstractDiagram.moc"

Generated on Thu May 10 11:06:24 2007 for KD Chart 2 by doxygen 1.3.6