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

KDChartBarDiagram.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 
00029 #include "KDChartBarDiagram.h"
00030 #include "KDChartBarDiagram_p.h"
00031 #include "KDChartThreeDBarAttributes.h"
00032 #include "KDChartPosition.h"
00033 #include "KDChartAttributesModel.h"
00034 #include "KDChartAbstractGrid.h"
00035 
00036 #include <KDABLibFakes>
00037 
00038 
00039 using namespace KDChart;
00040 
00041 BarDiagram::Private::Private()
00042     : barType( Normal )
00043     , maxDepth ( 0 )
00044 {
00045 }
00046 
00047 BarDiagram::Private::~Private() {}
00048 
00049 #define d d_func()
00050 
00051 
00052 BarDiagram::BarDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) :
00053     AbstractCartesianDiagram( new Private(), parent, plane )
00054 {
00055     init();
00056 }
00057 
00058 void BarDiagram::init()
00059 {
00060 }
00061 
00062 BarDiagram::~BarDiagram()
00063 {
00064 }
00065 
00066 BarDiagram * BarDiagram::clone() const
00067 {
00068     return new BarDiagram( new Private( *d ) );
00069 }
00070 
00071 void BarDiagram::setType( const BarType type )
00072 {
00073     if ( type == d->barType ) return;
00074 
00075     d->barType = type;
00076     // AbstractAxis settings - see AbstractDiagram and CartesianAxis
00077     setPercentMode( type == BarDiagram::Percent );
00078     setDataBoundariesDirty();
00079     emit layoutChanged( this );
00080 }
00081 
00082 BarDiagram::BarType BarDiagram::type() const
00083 {
00084    return d->barType;
00085 }
00086 
00087 void BarDiagram::setBarAttributes( const BarAttributes & ta )
00088 {
00089     d->attributesModel->setModelData( qVariantFromValue( ta ), BarAttributesRole );
00090 }
00091 
00092 void BarDiagram::setBarAttributes( int column, const BarAttributes & ta )
00093 {
00094     d->attributesModel->setHeaderData(
00095         column, Qt::Vertical,
00096         qVariantFromValue( ta ),
00097         BarAttributesRole );
00098 }
00099 
00100 void BarDiagram::setBarAttributes( const QModelIndex & index, const BarAttributes & ta )
00101 {
00102     attributesModel()->setData(
00103         d->attributesModel->mapFromSource( index ),
00104         qVariantFromValue( ta ),
00105         BarAttributesRole );
00106 }
00107 
00108 BarAttributes BarDiagram::barAttributes() const
00109 {
00110     return qVariantValue<BarAttributes>(
00111         d->attributesModel->data( KDChart::BarAttributesRole ) );
00112 }
00113 
00114 BarAttributes BarDiagram::barAttributes( int column ) const
00115 {
00116     return qVariantValue<BarAttributes>(
00117         d->attributesModel->data(
00118             d->attributesModel->mapFromSource( columnToIndex( column ) ),
00119             KDChart::BarAttributesRole ) );
00120 }
00121 
00122 BarAttributes BarDiagram::barAttributes( const QModelIndex & index ) const
00123 {
00124     return qVariantValue<BarAttributes>(
00125         d->attributesModel->data(
00126             d->attributesModel->mapFromSource( index ),
00127             KDChart::BarAttributesRole ) );
00128 }
00129 
00130 void BarDiagram::setThreeDBarAttributes( const ThreeDBarAttributes & threeDAttrs )
00131 {
00132     setDataBoundariesDirty();
00133     d->attributesModel->setModelData( qVariantFromValue( threeDAttrs ), ThreeDBarAttributesRole );
00134     emit layoutChanged( this );
00135 }
00136 
00137 void BarDiagram::setThreeDBarAttributes( int column, const ThreeDBarAttributes & threeDAttrs )
00138 {
00139     setDataBoundariesDirty();
00140     d->attributesModel->setHeaderData(
00141         column, Qt::Vertical,
00142         qVariantFromValue( threeDAttrs ),
00143         ThreeDBarAttributesRole );
00144     emit layoutChanged( this );
00145 }
00146 
00147 void BarDiagram::setThreeDBarAttributes( const QModelIndex & index, const ThreeDBarAttributes & threeDAttrs )
00148 {
00149     setDataBoundariesDirty();
00150     d->attributesModel->setData(
00151         d->attributesModel->mapFromSource(index),
00152         qVariantFromValue( threeDAttrs ),
00153         ThreeDBarAttributesRole );
00154     emit layoutChanged( this );
00155 }
00156 
00157 ThreeDBarAttributes BarDiagram::threeDBarAttributes() const
00158 {
00159     return qVariantValue<ThreeDBarAttributes>(
00160         d->attributesModel->data( KDChart::ThreeDBarAttributesRole ) );
00161 }
00162 
00163 ThreeDBarAttributes BarDiagram::threeDBarAttributes( int column ) const
00164 {
00165     return qVariantValue<ThreeDBarAttributes>(
00166         d->attributesModel->data(
00167             d->attributesModel->mapFromSource( columnToIndex( column ) ),
00168             KDChart::ThreeDBarAttributesRole ) );
00169 }
00170 
00171 ThreeDBarAttributes BarDiagram::threeDBarAttributes( const QModelIndex & index ) const
00172 {
00173     return qVariantValue<ThreeDBarAttributes>(
00174         d->attributesModel->data(
00175             d->attributesModel->mapFromSource(index),
00176             KDChart::ThreeDBarAttributesRole ) );
00177 }
00178 
00179 double BarDiagram::threeDItemDepth( const QModelIndex & index ) const
00180 {
00181     return threeDBarAttributes( index ).validDepth();
00182 }
00183 
00184 double BarDiagram::threeDItemDepth( int column ) const
00185 {
00186     return qVariantValue<ThreeDBarAttributes>(
00187         d->attributesModel->headerData (
00188             column,
00189             Qt::Vertical,
00190             KDChart::ThreeDBarAttributesRole ) ).validDepth();
00191 }
00192 
00193 void BarDiagram::resizeEvent ( QResizeEvent*)
00194 {
00195 
00196 }
00197 
00198 const QPair<QPointF, QPointF> BarDiagram::calculateDataBoundaries() const
00199 {
00200     if ( !checkInvariants(true) ) return QPair<QPointF, QPointF>( QPointF( 0, 0 ), QPointF( 0, 0 ) );
00201     const int rowCount = d->attributesModel->rowCount(attributesModelRootIndex());
00202     const int colCount = d->attributesModel->columnCount(attributesModelRootIndex());
00203 
00204     double xMin = 0;
00205     double xMax = rowCount;
00206     double yMin = 0, yMax = 0;
00207     //double maxThreeDDepth   = 0.0;
00208 
00209 
00210     // calculate boundaries for  different line types Normal - Stacked - Percent - Default Normal
00211     switch ( type() ){
00212         case BarDiagram::Normal:
00213         {
00214             bool bStarting = true;
00215             for ( int i=0; i<colCount; ++i ) {
00216                 for ( int j=0; j< rowCount; ++j ) {
00217                     const double value = d->attributesModel->data( d->attributesModel->index( j, i, attributesModelRootIndex() ) ).toDouble();
00218                     // this is always true yMin can be 0 in case all values
00219                     // are the same
00220                     // same for yMax it can be zero if all values are negative
00221                     if( bStarting ){
00222                         yMin = value;
00223                         yMax = value;
00224                         bStarting = false;
00225                     }else{
00226                         yMin = qMin( yMin, value );
00227                         yMax = qMax( yMax, value );
00228                     }
00229                 }
00230             }
00231         }
00232             break;
00233         case BarDiagram::Stacked:
00234         {
00235             bool bStarting = true;
00236             for ( int j=0; j< rowCount; ++j ) {
00237                 // calculate sum of values per column - Find out stacked Min/Max
00238                 double stackedValues = 0;
00239                 for ( int i=0; i<colCount ; ++i ) {
00240                     QModelIndex idx = model()->index( j, i, rootIndex() );
00241                     stackedValues +=  model()->data( idx ).toDouble();
00242                     // this is always true yMin can be 0 in case all values
00243                     // are the same
00244                     // same for yMax it can be zero if all values are negative
00245                     if( bStarting ){
00246                         yMin = stackedValues;
00247                         yMax = stackedValues;
00248                         bStarting = false;
00249                     }else{
00250                         yMin = qMin( yMin, stackedValues );
00251                         yMax = qMax( yMax, stackedValues );
00252                     }
00253                 }
00254             }
00255         }
00256             break;
00257         case BarDiagram::Percent:
00258         {
00259             for ( int i=0; i<colCount; ++i ) {
00260                 for ( int j=0; j< rowCount; ++j ) {
00261                     // Ordinate should begin at 0 the max value being the 100% pos
00262                     QModelIndex idx = model()->index( j, i, rootIndex() );
00263                     // only positive values are handled
00264                     double value = model()->data( idx ).toDouble();
00265                     if ( value > 0 )
00266                         yMax = qMax( yMax, value );
00267                 }
00268             }
00269         }
00270             break;
00271         case BarDiagram::Rows:
00272         {
00273             qDebug()<< "KDChartBarDiagram::calculateDataBoundaries"
00274                     << "Sorry Type Rows not implemented yet";
00275             break;
00276         }
00277 
00278 
00279         default:
00280              Q_ASSERT_X ( false, "calculateDataBoundaries()",
00281                          "Type item does not match a defined bar chart Type." );
00282     }
00283 
00284     // special cases
00285     if (  yMax == yMin ) {
00286         if ( yMin == 0.0 )
00287             yMax = 0.1; //we need at list a range
00288         else
00289             yMax = 0.0; // they are the same but negative
00290     }
00291     QPointF bottomLeft ( QPointF( xMin, yMin ) );
00292     QPointF topRight ( QPointF( xMax, yMax ) );
00293 
00294     //qDebug() << "BarDiagram::calculateDataBoundaries () returns ( " << bottomLeft << topRight <<")";
00295     return QPair<QPointF, QPointF> ( bottomLeft,  topRight );
00296 }
00297 
00298 /*
00299 void BarDiagram::paintEvent ( QPaintEvent*)
00300 {
00301     qDebug() << "BarDiagram::paintEvent";
00302     QPainter painter ( viewport() );
00303     PaintContext ctx;
00304     ctx.setPainter ( &painter );
00305     ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
00306     paint ( &ctx );
00307 }*/
00308 
00309 
00310 void BarDiagram::calculateValueAndGapWidths( int rowCount,int colCount,
00311                                              double groupWidth,
00312                                              double& outBarWidth,
00313                                              double& outSpaceBetweenBars,
00314                                              double& outSpaceBetweenGroups )
00315 {
00316     Q_UNUSED( rowCount );
00317 
00318     BarAttributes ba = barAttributes( model()->index( 0, 0, rootIndex() ) );
00319 
00320     // Pending Michel Fixme
00321     /* We are colCount groups to paint. Each group is centered around the
00322      * horizontal point position on the grid. The full area covers the
00323      * values -1 to colCount + 1. A bar has a relative width of one unit,
00324      * the gaps between bars are 0.5 wide, and the gap between groups is
00325      * also one unit, by default. */
00326 
00327     const double units = colCount // number of bars in group * 1.0
00328         + (colCount-1) * ba.barGapFactor() // number of bar gaps
00329         + 1 * ba.groupGapFactor(); // number of group gaps
00330 
00331     double unitWidth = groupWidth / units;
00332     outBarWidth = unitWidth;
00333     outSpaceBetweenBars += unitWidth * ba.barGapFactor();
00334     // Pending Michel - minLimit: allow space between bars to be reduced until the bars are displayed next to each other.
00335     // is that what we want?
00336     if ( outSpaceBetweenBars < 0 )
00337         outSpaceBetweenBars = 0;
00338     outSpaceBetweenGroups += unitWidth * ba.groupGapFactor();
00339 }
00340 
00341 void BarDiagram::paint( PaintContext* ctx )
00342 {
00343     // note: Not having any data model assigned is no bug
00344     //       but we can not draw a diagram then either.
00345     if ( !checkInvariants(true) )
00346         return;
00347 
00348     // Calculate width
00349     QPointF boundLeft, boundRight;
00350     QPair<QPointF,QPointF> boundaries = dataBoundaries();
00351     if( !AbstractGrid::isBoundariesValid(boundaries) ) return;
00352 
00353     CartesianCoordinatePlane* plane = dynamic_cast<KDChart::CartesianCoordinatePlane*>( coordinatePlane() );
00354     if( ! plane ) return;
00355 
00356     boundLeft = plane->translate( boundaries.first );
00357     boundRight = plane->translate( boundaries.second );
00358     double width = boundRight.x() - boundLeft.x();
00359     //calculates and stores the values
00360     const int rowCount = d->attributesModel->rowCount(attributesModelRootIndex());
00361     const int colCount = d->attributesModel->columnCount(attributesModelRootIndex());
00362     DataValueTextInfoList list;
00363     BarAttributes ba = barAttributes( model()->index( 0, 0, rootIndex() ) );
00364     double barWidth = 0;
00365     double maxDepth = 0;
00366     double spaceBetweenBars = 0;
00367     double spaceBetweenGroups = 0;
00368     double groupWidth =  /*ctx->rectangle().width() / ( rowCount + 2 )*/ width/ (rowCount + 2);
00369 
00370 
00371     if ( ba.useFixedBarWidth() ) {
00372         barWidth = ba.fixedBarWidth();
00373         groupWidth += barWidth;
00374 
00375         // Pending Michel set a min and max value for the groupWidth related to the area.width
00376         // FixMe
00377         if ( groupWidth < 0 )
00378             groupWidth = 0;
00379 
00380         if ( groupWidth  * rowCount > ctx->rectangle().width() )
00381             groupWidth = ctx->rectangle().width() / rowCount;
00382     }
00383 
00384     // maxLimit: allow the space between bars to be larger until area.width() is covered by the groups.
00385     double maxLimit = rowCount * (groupWidth + ((colCount-1) * ba.fixedDataValueGap()) );
00386 
00387     //Pending Michel: FixMe
00388     if ( ba.useFixedDataValueGap() ) {
00389         if ( ctx->rectangle().width() > maxLimit )
00390             spaceBetweenBars += ba.fixedDataValueGap();
00391         else
00392             spaceBetweenBars = ((ctx->rectangle().width()/rowCount) - groupWidth)/(colCount-1);
00393    }
00394 
00395     //Pending Michel: FixMe
00396     if ( ba.useFixedValueBlockGap() )
00397         spaceBetweenGroups += ba.fixedValueBlockGap();
00398 
00399     calculateValueAndGapWidths( rowCount, colCount,groupWidth,
00400                                 barWidth, spaceBetweenBars, spaceBetweenGroups );
00401 
00402     // paint different bar types: Normal - Stacked - Percent
00403     switch ( type() )
00404         {
00405         case BarDiagram::Normal:
00406         {
00407             // we paint the bars for all series next to each other, then move to the next value
00408             for ( int i=0; i<rowCount; ++i ) {
00409                 double offset = -groupWidth/2 + spaceBetweenGroups/2;
00410                 // case fixed data value gap - handles max and min limits as well
00411                 if ( ba.useFixedDataValueGap() ) {
00412                     if ( spaceBetweenBars > 0 ) {
00413                       if ( ctx->rectangle().width() > maxLimit )
00414                             offset -= ba.fixedDataValueGap();
00415                       else
00416                         offset -= ((ctx->rectangle().width()/rowCount) - groupWidth)/(colCount-1);
00417 
00418                     } else {
00419                         //allow reducing the gap until the bars are displayed next to each other - null gap
00420                         offset += barWidth/2;
00421                     }
00422                 }
00423 
00424                 for ( int j=0; j< colCount; ++j ) {
00425                     // paint one group
00426                     const qreal value = d->attributesModel->data( d->attributesModel->index( i, j, attributesModelRootIndex() ) ).toDouble();
00427                     QPointF topPoint = plane->translate( QPointF( i + 0.5, value ) );
00428                     QPointF bottomPoint = plane->translate( QPointF( i, 0 ) );
00429                     const double barHeight = bottomPoint.y() - topPoint.y();
00430                     topPoint.setX( topPoint.x() + offset );
00431 
00432                     const QModelIndex index = model()->index( i, j, rootIndex() );
00433 
00434                     //PENDING Michel: FIXME barWidth
00435                     const QRectF rect( topPoint, QSizeF( barWidth, barHeight ) );
00436                     d->appendDataValueTextInfoToList( this, list, index, PositionPoints( rect ),
00437                             Position::NorthWest, Position::SouthEast,
00438                             value );
00439                     paintBars( ctx, index, rect, maxDepth );
00440 
00441                     offset += barWidth + spaceBetweenBars;
00442                 }
00443             }
00444         }
00445             break;
00446         case BarDiagram::Stacked:
00447         {
00448            for ( int i = 0; i<colCount; ++i ) {
00449                double offset = spaceBetweenGroups;
00450                for ( int j = 0; j< rowCount; ++j ) {
00451                    QModelIndex index = model()->index( j, i, rootIndex() );
00452                    ThreeDBarAttributes threeDAttrs = threeDBarAttributes( index );
00453                    double value = 0, stackedValues = 0;
00454                    QPointF point, previousPoint;
00455 
00456                    if ( threeDAttrs.isEnabled() ) {
00457                        if ( barWidth > 0 )
00458                            barWidth =  (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00459                        if ( barWidth <= 0 ) {
00460                            barWidth = 0;
00461                            maxDepth = offset - (width/rowCount);
00462                        }
00463                    } else
00464                        barWidth =  (ctx->rectangle().width() - (offset*rowCount))/ rowCount ;
00465 
00466                    value = model()->data( index ).toDouble();
00467                    for ( int k = i; k >= 0 ; --k )
00468                        stackedValues += model()->data( model()->index( j, k, rootIndex() ) ).toDouble();
00469                    point = plane->translate( QPointF( j, stackedValues ) );
00470                    point.setX( point.x() + offset/2 );
00471                    previousPoint = plane->translate( QPointF( j, stackedValues - value ) );
00472                    const double barHeight = previousPoint.y() - point.y();
00473 
00474                    const QRectF rect( point, QSizeF( barWidth , barHeight ) );
00475                    d->appendDataValueTextInfoToList( this, list, index, PositionPoints( rect ),
00476                            Position::NorthWest, Position::SouthEast,
00477                            value );
00478                    paintBars( ctx, index, rect, maxDepth );
00479                }
00480 
00481            }
00482         }
00483            break;
00484         case BarDiagram::Percent:
00485         {
00486             double maxValue = 100; // always 100 %
00487             double sumValues = 0;
00488             QVector <double > sumValuesVector;
00489 
00490             //calculate sum of values for each column and store
00491             for ( int j=0; j<rowCount; ++j ) {
00492                 for ( int i=0; i<colCount; ++i ) {
00493                     double tmpValue = model()->data( model()->index( j, i, rootIndex() ) ).toDouble();
00494                     if ( tmpValue > 0 )
00495                         sumValues += tmpValue;
00496                     if ( i == colCount-1 ) {
00497                         sumValuesVector <<  sumValues ;
00498                         sumValues = 0;
00499                     }
00500                 }
00501             }
00502 
00503             // calculate stacked percent value
00504             for ( int i = 0; i<colCount; ++i ) {
00505                 double offset = spaceBetweenGroups;
00506                 for ( int j=0; j<rowCount ; ++j ) {
00507                     double value = 0, stackedValues = 0;
00508                     QPointF point, previousPoint;
00509                     QModelIndex index = model()->index( j, i, rootIndex() );
00510                     ThreeDBarAttributes threeDAttrs = threeDBarAttributes( index );
00511 
00512                     if ( threeDAttrs.isEnabled() ){
00513                         if ( barWidth > 0 )
00514                             barWidth =  (width - ((offset+(threeDAttrs.depth()))*rowCount))/ rowCount;
00515                         if ( barWidth <= 0 ) {
00516                             barWidth = 0;
00517                             maxDepth = offset - ( width/rowCount);
00518                         }
00519                     }else{
00520                         barWidth = (ctx->rectangle().width() - (offset*rowCount))/ rowCount;
00521                     }
00522 
00523                     value = model()->data( index ).toDouble();
00524 
00525                     // calculate stacked percent value
00526                     // we only take in account positives values for now.
00527                     for ( int k = i; k >= 0 ; --k ) {
00528                         double val = model()->data( model()->index( j, k, rootIndex() ) ).toDouble();
00529                         if ( val > 0)
00530                             stackedValues += val;
00531                     }
00532 
00533                     if (  sumValuesVector.at( j ) != 0 && value > 0 ) {
00534                       point = plane->translate( QPointF( j,  stackedValues/sumValuesVector.at(j)* maxValue ) );
00535 
00536                         point.setX( point.x() + offset/2 );
00537 
00538                         previousPoint = plane->translate( QPointF( j, (stackedValues - value)/sumValuesVector.at(j)* maxValue ) );
00539                     }
00540                     const double barHeight = previousPoint.y() - point.y();
00541 
00542                     const QRectF rect( point, QSizeF( barWidth, barHeight ) );
00543                     d->appendDataValueTextInfoToList( this, list, index, PositionPoints( rect ),
00544                             Position::NorthWest, Position::SouthEast,
00545                             value );
00546                     paintBars( ctx, index, rect, maxDepth );
00547 
00548                 }
00549             }
00550         }
00551         break;
00552         default:
00553             Q_ASSERT_X ( false, "paint()",
00554                          "Type item does not match a defined bar chart Type." );
00555         }
00556 
00557     // paint all data value texts, but no point markers
00558     d->paintDataValueTextsAndMarkers( this, ctx, list, false );
00559 }
00560 
00561 void BarDiagram::paintBars( PaintContext* ctx, const QModelIndex& index, const QRectF& bar, double& maxDepth )
00562 {
00563     QRectF isoRect;
00564     QPolygonF topPoints, sidePoints;
00565     ThreeDBarAttributes threeDAttrs = threeDBarAttributes( index );
00566     double usedDepth;
00567 
00568     //Pending Michel: configure threeDBrush settings - shadowColor etc...
00569     QBrush indexBrush ( brush( index ) );
00570     QPen indexPen( pen( index ) );
00571     PainterSaver painterSaver( ctx->painter() );
00572     if ( antiAliasing() )
00573         ctx->painter()->setRenderHint ( QPainter::Antialiasing );
00574     ctx->painter()->setBrush( indexBrush );
00575     ctx->painter()->setPen( indexPen );
00576     if ( threeDAttrs.isEnabled() ) {
00577         bool stackedMode = false;
00578         bool percentMode = false;
00579         bool paintTop = true;
00580         if ( maxDepth )
00581             threeDAttrs.setDepth( -maxDepth );
00582         QPointF boundRight = coordinatePlane()->translate( dataBoundaries().second );
00583         //fixme adjust the painting to reasonable depth value
00584         switch ( type() )
00585         {
00586         case BarDiagram::Normal:
00587             usedDepth = threeDAttrs.depth()/4;
00588             stackedMode = false;
00589             percentMode = false;
00590             break;
00591         case BarDiagram::Stacked:
00592             usedDepth = threeDAttrs.depth();
00593             stackedMode = true;
00594             percentMode = false;
00595             break;
00596         case BarDiagram::Percent:
00597             usedDepth = threeDAttrs.depth();
00598             stackedMode = false;
00599             percentMode = true;
00600             break;
00601         default:
00602             Q_ASSERT_X ( false, "dataBoundaries()",
00603                          "Type item does not match a defined bar chart Type." );
00604         }
00605         isoRect =  bar.translated( usedDepth, -usedDepth );
00606         // we need to find out if the height is negative
00607         // and in this case paint it up and down
00608         //qDebug() << isoRect.height();
00609         if (  isoRect.height() < 0 ) {
00610           topPoints << isoRect.bottomLeft() << isoRect.bottomRight()
00611                     << bar.bottomRight() << bar.bottomLeft();
00612           if ( stackedMode ) {
00613               // fix it when several negative stacked values
00614               if (  index.column() == 0 ) {
00615                   paintTop = true;
00616               }
00617               else
00618                   paintTop = false;
00619           }
00620 
00621         } else {
00622             ctx->painter()->drawRect( isoRect );
00623             topPoints << bar.topLeft() << bar.topRight() << isoRect.topRight() << isoRect.topLeft();
00624         }
00625 
00626         if ( percentMode && isoRect.height() == 0 )
00627             paintTop = false;
00628 
00629         bool needToSetClippingOffForTop = false;
00630         if ( paintTop ){
00631             // Draw the top, if at least one of the top's points is
00632             // either inside or near at the edge of the coordinate plane:
00633             bool drawIt = false;
00634             bool hasPointOutside = false;
00635             const QRectF r( ctx->rectangle().adjusted(0,-1,1,0) );
00636             KDAB_FOREACH( QPointF pt, topPoints ) {
00637                 if( r.contains( pt ) )
00638                     drawIt = true;
00639                 else
00640                     hasPointOutside = true;
00641             }
00642             if( drawIt ){
00643                 needToSetClippingOffForTop = hasPointOutside && ctx->painter()->hasClipping();
00644                 if( needToSetClippingOffForTop )
00645                     ctx->painter()->setClipping( false );
00646                 ctx->painter()->drawPolygon( topPoints );
00647                 if( needToSetClippingOffForTop )
00648                     ctx->painter()->setClipping( true );
00649             }
00650         }
00651 
00652 
00653 
00654         sidePoints << bar.topRight() << isoRect.topRight() << isoRect.bottomRight() << bar.bottomRight();
00655         if (  bar.height() != 0 ){
00656             if( needToSetClippingOffForTop )
00657                 ctx->painter()->setClipping( false );
00658             ctx->painter()->drawPolygon( sidePoints );
00659             if( needToSetClippingOffForTop )
00660                 ctx->painter()->setClipping( true );
00661         }
00662     }
00663 
00664     if (  bar.height() != 0 )
00665         ctx->painter()->drawRect( bar );
00666     // reset
00667     d->maxDepth = threeDAttrs.depth();
00668 }
00669 
00670 void BarDiagram::resize ( const QSizeF& )
00671 {
00672 }
00673 
00674 const int BarDiagram::numberOfAbscissaSegments () const
00675 {
00676     return d->attributesModel->rowCount(attributesModelRootIndex());
00677 }
00678 
00679 const int BarDiagram::numberOfOrdinateSegments () const
00680 {
00681     return d->attributesModel->columnCount(attributesModelRootIndex());
00682 }
00683 
00684 #undef d

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