File indexing completed on 2024-12-15 04:02:28

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "KChartBarDiagram.h"
0010 #include "KChartBarDiagram_p.h"
0011 
0012 #include "KChartThreeDBarAttributes.h"
0013 #include "KChartPosition.h"
0014 #include "KChartAttributesModel.h"
0015 #include "KChartAbstractGrid.h"
0016 #include "KChartPainterSaver_p.h"
0017 
0018 #include <QPainter>
0019 #include <QDebug>
0020 
0021 #include "KChartNormalBarDiagram_p.h"
0022 #include "KChartStackedBarDiagram_p.h"
0023 #include "KChartPercentBarDiagram_p.h"
0024 #include "KChartNormalLyingBarDiagram_p.h"
0025 #include "KChartStackedLyingBarDiagram_p.h"
0026 #include "KChartPercentLyingBarDiagram_p.h"
0027 #include "KChartMath_p.h"
0028 
0029 
0030 using namespace KChart;
0031 
0032 BarDiagram::Private::Private()
0033     : orientation( Qt::Vertical )
0034     , implementor( nullptr )
0035     , normalDiagram( nullptr )
0036     , stackedDiagram( nullptr )
0037     , percentDiagram( nullptr )
0038     , normalLyingDiagram( nullptr )
0039     , stackedLyingDiagram( nullptr )
0040     , percentLyingDiagram( nullptr )
0041 {
0042 }
0043 
0044 BarDiagram::Private::~Private()
0045 {
0046     delete normalDiagram;
0047     delete stackedDiagram;
0048     delete percentDiagram;
0049     delete normalLyingDiagram;
0050     delete stackedLyingDiagram;
0051     delete percentLyingDiagram;
0052 }
0053 
0054 void BarDiagram::Private::setOrientationAndType( Qt::Orientation o, BarDiagram::BarType type )
0055 {
0056     if ( orientation == o && implementor->type() == type ) {
0057         return;
0058     }
0059     BarDiagram *barDia = qobject_cast< BarDiagram * >( diagram );
0060 
0061     orientation = o;
0062 
0063     if ( orientation == Qt::Vertical ) {
0064         switch ( type ) {
0065         case Normal:
0066             implementor = normalDiagram;
0067             break;
0068         case Stacked:
0069             implementor = stackedDiagram;
0070             break;
0071         case Percent:
0072             implementor = percentDiagram;
0073             break;
0074         default:
0075             Q_ASSERT_X( false, "BarDiagram::setType", "unknown diagram subtype" );
0076         }
0077     } else {
0078         switch ( type ) {
0079         case Normal:
0080             implementor = normalLyingDiagram;
0081             break;
0082         case Stacked:
0083             implementor = stackedLyingDiagram;
0084             break;
0085         case Percent:
0086             implementor = percentLyingDiagram;
0087             break;
0088         default:
0089             Q_ASSERT_X( false, "BarDiagram::setType", "unknown diagram subtype" );
0090         }
0091     }
0092 
0093     Q_ASSERT( implementor->type() == type );
0094 
0095     // AbstractAxis settings - see AbstractDiagram and CartesianAxis
0096     barDia->setPercentMode( type == BarDiagram::Percent );
0097     barDia->setDataBoundariesDirty();
0098     Q_EMIT barDia->layoutChanged( barDia );
0099     Q_EMIT barDia->propertiesChanged();
0100 }
0101 
0102 #define d d_func()
0103 
0104 
0105 BarDiagram::BarDiagram( QWidget* parent, CartesianCoordinatePlane* plane ) :
0106     AbstractCartesianDiagram( new Private(), parent, plane )
0107 {
0108     init();
0109 }
0110 
0111 void BarDiagram::init()
0112 {
0113     d->normalDiagram = new NormalBarDiagram( this );
0114     d->stackedDiagram = new StackedBarDiagram( this );
0115     d->percentDiagram = new PercentBarDiagram( this );
0116     d->normalLyingDiagram = new NormalLyingBarDiagram( this );
0117     d->stackedLyingDiagram = new StackedLyingBarDiagram( this );
0118     d->percentLyingDiagram = new PercentLyingBarDiagram( this );
0119     d->implementor = d->normalDiagram;
0120     d->compressor.setModel( attributesModel() );
0121 }
0122 
0123 BarDiagram::~BarDiagram()
0124 {
0125 }
0126 
0127 BarDiagram * BarDiagram::clone() const
0128 {
0129 
0130     BarDiagram* newDiagram = new BarDiagram( new Private( *d ) );
0131     newDiagram->setType( type() );
0132     return newDiagram;
0133 }
0134 
0135 bool BarDiagram::compare( const BarDiagram* other ) const
0136 {
0137     if ( other == this ) return true;
0138     if ( ! other ) {
0139         return false;
0140     }
0141 
0142     return  // compare the base class
0143             ( static_cast<const AbstractCartesianDiagram*>(this)->compare( other ) ) &&
0144             // compare own properties
0145             (type() == other->type());
0146 }
0147 
0148 void BarDiagram::setType( const BarType type )
0149 {
0150     d->setOrientationAndType( d->orientation, type );
0151 }
0152 
0153 BarDiagram::BarType BarDiagram::type() const
0154 {
0155     return d->implementor->type();
0156 }
0157 
0158 void BarDiagram::setOrientation( Qt::Orientation orientation )
0159 {
0160     d->setOrientationAndType( orientation, d->implementor->type() );
0161 }
0162 
0163 Qt::Orientation BarDiagram::orientation() const
0164 {
0165     return d->orientation;
0166 }
0167 
0168 void BarDiagram::setBarAttributes( const BarAttributes& ba )
0169 {
0170     d->attributesModel->setModelData( QVariant::fromValue( ba ), BarAttributesRole );
0171     Q_EMIT propertiesChanged();
0172 }
0173 
0174 void BarDiagram::setBarAttributes( int column, const BarAttributes& ba )
0175 {
0176     d->setDatasetAttrs( column, QVariant::fromValue( ba ), BarAttributesRole );
0177     Q_EMIT propertiesChanged();
0178 }
0179 
0180 void BarDiagram::setBarAttributes( const QModelIndex& index, const BarAttributes& ba )
0181 {
0182     attributesModel()->setData(
0183         d->attributesModel->mapFromSource( index ),
0184         QVariant::fromValue( ba ),
0185         BarAttributesRole );
0186     Q_EMIT propertiesChanged();
0187 }
0188 
0189 BarAttributes BarDiagram::barAttributes() const
0190 {
0191     return d->attributesModel->data( KChart::BarAttributesRole ).value<BarAttributes>();
0192 }
0193 
0194 BarAttributes BarDiagram::barAttributes( int column ) const
0195 {
0196     const QVariant attrs( d->datasetAttrs( column, KChart::BarAttributesRole ) );
0197     if ( attrs.isValid() )
0198         return attrs.value<BarAttributes>();
0199     return barAttributes();
0200 }
0201 
0202 BarAttributes BarDiagram::barAttributes( const QModelIndex& index ) const
0203 {
0204     return d->attributesModel->data(
0205             d->attributesModel->mapFromSource( index ),
0206             KChart::BarAttributesRole ).value<BarAttributes>();
0207 }
0208 
0209 void BarDiagram::setThreeDBarAttributes( const ThreeDBarAttributes& threeDAttrs )
0210 {
0211     setDataBoundariesDirty();
0212     d->attributesModel->setModelData( QVariant::fromValue( threeDAttrs ), ThreeDBarAttributesRole );
0213     Q_EMIT layoutChanged( this );
0214     Q_EMIT propertiesChanged();
0215 }
0216 
0217 void BarDiagram::setThreeDBarAttributes( int column, const ThreeDBarAttributes& threeDAttrs )
0218 {
0219     setDataBoundariesDirty();
0220     d->setDatasetAttrs( column,  QVariant::fromValue( threeDAttrs ), ThreeDBarAttributesRole );
0221     //Q_EMIT layoutChanged( this );
0222     Q_EMIT propertiesChanged();
0223 }
0224 
0225 void BarDiagram::setThreeDBarAttributes( const QModelIndex& index, const ThreeDBarAttributes& threeDAttrs )
0226 {
0227     setDataBoundariesDirty();
0228     d->attributesModel->setData(
0229         d->attributesModel->mapFromSource(index),
0230         QVariant::fromValue( threeDAttrs ),
0231         ThreeDBarAttributesRole );
0232     //Q_EMIT layoutChanged( this );
0233     Q_EMIT propertiesChanged();
0234 }
0235 
0236 ThreeDBarAttributes BarDiagram::threeDBarAttributes() const
0237 {
0238     return d->attributesModel->data( KChart::ThreeDBarAttributesRole ).value<ThreeDBarAttributes>();
0239 }
0240 
0241 ThreeDBarAttributes BarDiagram::threeDBarAttributes( int column ) const
0242 {
0243     const QVariant attrs( d->datasetAttrs( column, KChart::ThreeDBarAttributesRole ) );
0244     if ( attrs.isValid() )
0245         return attrs.value<ThreeDBarAttributes>();
0246     return threeDBarAttributes();
0247 }
0248 
0249 ThreeDBarAttributes BarDiagram::threeDBarAttributes( const QModelIndex& index ) const
0250 {
0251     return d->attributesModel->data(
0252             d->attributesModel->mapFromSource(index),
0253             KChart::ThreeDBarAttributesRole ).value<ThreeDBarAttributes>();
0254 }
0255 
0256 qreal BarDiagram::threeDItemDepth( const QModelIndex& index ) const
0257 {
0258     return threeDBarAttributes( index ).validDepth();
0259 }
0260 
0261 qreal BarDiagram::threeDItemDepth( int column ) const
0262 {
0263     return threeDBarAttributes( column ).validDepth();
0264 }
0265 
0266 void BarDiagram::resizeEvent ( QResizeEvent*)
0267 {
0268 
0269 }
0270 
0271 const QPair<QPointF, QPointF> BarDiagram::calculateDataBoundaries() const
0272 {
0273     d->compressor.setResolution( static_cast<int>( this->size().width() * coordinatePlane()->zoomFactorX() ),
0274                                  static_cast<int>( this->size().height() * coordinatePlane()->zoomFactorY() ) );
0275 
0276     if ( !checkInvariants( true ) ) {
0277         return QPair< QPointF, QPointF >( QPointF( 0, 0 ), QPointF( 0, 0 ) );
0278     }
0279 
0280     // note: calculateDataBoundaries() is ignoring the hidden flags.
0281     // That's not a bug but a feature: Hiding data does not mean removing them.
0282     // For totally removing data from KD Chart's view people can use e.g. a proxy model
0283     // calculate boundaries for different line types Normal - Stacked - Percent - Default Normal
0284     return d->implementor->calculateDataBoundaries();
0285 }
0286 
0287 void BarDiagram::paintEvent ( QPaintEvent*)
0288 {
0289     QPainter painter ( viewport() );
0290     PaintContext ctx;
0291     ctx.setPainter ( &painter );
0292     ctx.setRectangle( QRectF ( 0, 0, width(), height() ) );
0293     paint ( &ctx );
0294 }
0295 
0296 void BarDiagram::paint( PaintContext* ctx )
0297 {
0298     if ( !checkInvariants( true ) ) return;
0299     if ( !AbstractGrid::isBoundariesValid(dataBoundaries()) ) return;
0300     const PainterSaver p( ctx->painter() );
0301     if ( model()->rowCount( rootIndex() ) == 0 || model()->columnCount( rootIndex() ) == 0 )
0302         return; // nothing to paint for us
0303 
0304     AbstractCoordinatePlane* const plane = ctx->coordinatePlane();
0305     ctx->setCoordinatePlane( plane->sharedAxisMasterPlane( ctx->painter() ) );
0306 
0307     // This was intended as a fix for KDCH-515, however it caused KDCH-816
0308     // and the original problem in KDCH-515 had by then been fixed in another way.
0309     // Bottom line is, this code is wrong because the above call to
0310     // plane->sharedAxisMasterPlane() performs a translation of the painter, which
0311     // also translates the clip rect, so if we set the old clip rect again afterwards,
0312     // we get a wrong clipping.
0313     // Also, this code is unnecessary because CartesianCoordinatePlane::paint()
0314     // already sets the clipping properly before calling this method.
0315     // ctx->painter()->setClipping( true );
0316     // ctx->painter()->setClipRect( ctx->rectangle() );
0317 
0318     // paint different bar types Normal - Stacked - Percent - Default Normal
0319     d->implementor->paint( ctx );
0320 
0321     ctx->setCoordinatePlane( plane );
0322 }
0323 
0324 void BarDiagram::resize( const QSizeF& size )
0325 {
0326     d->compressor.setResolution( static_cast< int >( size.width() * coordinatePlane()->zoomFactorX() ),
0327                                  static_cast< int >( size.height() * coordinatePlane()->zoomFactorY() ) );
0328     setDataBoundariesDirty();
0329     AbstractCartesianDiagram::resize( size );
0330 }
0331 
0332 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
0333 const
0334 #endif
0335 int BarDiagram::numberOfAbscissaSegments () const
0336 {
0337     return d->attributesModel->rowCount(attributesModelRootIndex());
0338 }
0339 
0340 #if defined(Q_COMPILER_MANGLES_RETURN_TYPE)
0341 const
0342 #endif
0343 int BarDiagram::numberOfOrdinateSegments () const
0344 {
0345     return d->attributesModel->columnCount(attributesModelRootIndex());
0346 }
0347 
0348 //#undef d