File indexing completed on 2024-05-12 04:20:30

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 "KChartAttributesModel.h"
0010 
0011 #include "KChartPalette.h"
0012 #include "KChartMath_p.h"
0013 
0014 #include <QDebug>
0015 #include <QPen>
0016 #include <QPointer>
0017 
0018 #include <KChartTextAttributes.h>
0019 #include <KChartFrameAttributes.h>
0020 #include <KChartBackgroundAttributes.h>
0021 #include <KChartDataValueAttributes.h>
0022 #include <KChartMarkerAttributes.h>
0023 #include <KChartBarAttributes.h>
0024 #include <KChartStockBarAttributes.h>
0025 #include <KChartLineAttributes.h>
0026 #include <KChartPieAttributes.h>
0027 #include <KChartAbstractThreeDAttributes.h>
0028 #include <KChartThreeDBarAttributes.h>
0029 #include <KChartThreeDLineAttributes.h>
0030 #include <KChartThreeDPieAttributes.h>
0031 #include <KChartGridAttributes.h>
0032 #include <KChartValueTrackerAttributes.h>
0033 
0034 
0035 using namespace KChart;
0036 
0037 
0038 class Q_DECL_HIDDEN AttributesModel::Private
0039 {
0040 public:
0041     Private();
0042 
0043     QMap< int, QMap< int, QMap< int, QVariant > > > dataMap;
0044     QMap< int, QMap< int, QVariant > > horizontalHeaderDataMap;
0045     QMap< int, QMap< int, QVariant > > verticalHeaderDataMap;
0046     QMap< int, QVariant > modelDataMap;
0047     QMap< int, QVariant > defaultsMap;
0048     int dataDimension;
0049     AttributesModel::PaletteType paletteType;
0050     Palette palette;
0051 };
0052 
0053 AttributesModel::Private::Private()
0054   : dataDimension( 1 ),
0055     paletteType( AttributesModel::PaletteTypeDefault ),
0056     palette( Palette::defaultPalette() )
0057 {
0058 }
0059 
0060 #define d d_func()
0061 
0062 AttributesModel::AttributesModel( QAbstractItemModel* model, QObject * parent/* = 0 */ )
0063   : AbstractProxyModel( parent ),
0064     _d( new Private )
0065 {
0066     setSourceModel( model );
0067     setDefaultForRole( KChart::DataValueLabelAttributesRole,
0068                        DataValueAttributes::defaultAttributesAsVariant() );
0069 }
0070 
0071 AttributesModel::~AttributesModel()
0072 {
0073     delete _d;
0074     _d = nullptr;
0075 }
0076 
0077 void AttributesModel::initFrom( const AttributesModel* other )
0078 {
0079     *d = *other->d;
0080 }
0081 
0082 bool AttributesModel::compareHeaderDataMaps( const QMap< int, QMap< int, QVariant > >& mapA,
0083                                              const QMap< int, QMap< int, QVariant > >& mapB ) const
0084 {
0085     if ( mapA.count() != mapB.count() ) {
0086         return false;
0087     }
0088     QMap< int, QMap< int, QVariant > >::const_iterator itA = mapA.constBegin();
0089     QMap< int, QMap< int, QVariant > >::const_iterator itB = mapB.constBegin();
0090     for ( ; itA != mapA.constEnd(); ++itA, ++itB ) {
0091         if ( itA->count() != itB->count() ) {
0092             return false;
0093         }
0094         QMap< int, QVariant >::const_iterator it2A = itA->constBegin();
0095         QMap< int, QVariant >::const_iterator it2B = itB->constBegin();
0096         for ( ; it2A != itA->constEnd(); ++it2A, ++it2B ) {
0097             if ( it2A.key() != it2B.key() ) {
0098                 return false;
0099             }
0100             if ( !compareAttributes( it2A.key(), it2A.value(), it2B.value() ) ) {
0101                 return false;
0102             }
0103         }
0104     }
0105     return true;
0106 }
0107 
0108 bool AttributesModel::compare( const AttributesModel* other ) const
0109 {
0110     if ( other == this ) {
0111         return true;
0112     }
0113     if ( !other || d->paletteType != other->d->paletteType ) {
0114         return false;
0115     }
0116 
0117     {
0118         if ( d->dataMap.count() != other->d->dataMap.count() ) {
0119             return false;
0120         }
0121         QMap< int, QMap< int, QMap<int, QVariant > > >::const_iterator itA = d->dataMap.constBegin();
0122         QMap< int, QMap< int, QMap<int, QVariant > > >::const_iterator itB = other->d->dataMap.constBegin();
0123         for ( ; itA != d->dataMap.constEnd(); ++itA, ++itB ) {
0124             if ( itA->count() != itB->count() ) {
0125                 return false;
0126             }
0127             QMap< int, QMap< int, QVariant > >::const_iterator it2A = itA->constBegin();
0128             QMap< int, QMap< int, QVariant > >::const_iterator it2B = itB->constBegin();
0129             for ( ; it2A != itA->constEnd(); ++it2A, ++it2B ) {
0130                 if ( it2A->count() != it2B->count() ) {
0131                     return false;
0132                 }
0133                 QMap< int, QVariant >::const_iterator it3A = it2A->constBegin();
0134                 QMap< int, QVariant >::const_iterator it3B = it2B->constBegin();
0135                 for ( ; it3A != it2A->constEnd(); ++it3A, ++it3B ) {
0136                     if ( it3A.key() != it3B.key() ) {
0137                         return false;
0138                     }
0139                     if ( !compareAttributes( it3A.key(), it3A.value(), it3B.value() ) ) {
0140                         return false;
0141                     }
0142                 }
0143             }
0144         }
0145     }
0146 
0147     if ( !compareHeaderDataMaps( d->horizontalHeaderDataMap, other->d->horizontalHeaderDataMap ) ||
0148          !compareHeaderDataMaps( d->verticalHeaderDataMap, other->d->verticalHeaderDataMap ) ) {
0149         return false;
0150     }
0151 
0152     {
0153         if ( d->modelDataMap.count() != other->d->modelDataMap.count() ) {
0154             return false;
0155         }
0156         QMap< int, QVariant >::const_iterator itA = d->modelDataMap.constBegin();
0157         QMap< int, QVariant >::const_iterator itB = other->d->modelDataMap.constBegin();
0158         for ( ; itA != d->modelDataMap.constEnd(); ++itA, ++itB ) {
0159             if ( itA.key() != itB.key() ) {
0160                 return false;
0161             }
0162             if ( !compareAttributes( itA.key(), itA.value(), itB.value() ) ) {
0163                 return false;
0164             }
0165         }
0166     }
0167     return true;
0168 }
0169 
0170 bool AttributesModel::compareAttributes(
0171         int role, const QVariant& a, const QVariant& b ) const
0172 {
0173     if ( isKnownAttributesRole( role ) ) {
0174         switch ( role ) {
0175             case DataValueLabelAttributesRole:
0176                 return (a.value<DataValueAttributes>() ==
0177                         b.value<DataValueAttributes>());
0178             case DatasetBrushRole:
0179                 return (a.value<QBrush>() ==
0180                         b.value<QBrush>());
0181             case DatasetPenRole:
0182                 return (a.value<QPen>() ==
0183                         b.value<QPen>());
0184             case ThreeDAttributesRole:
0185                 // As of yet there is no ThreeDAttributes class,
0186                 // and the AbstractThreeDAttributes class is pure virtual,
0187                 // so we ignore this role for now.
0188                 // (khz, 04.04.2007)
0189                 /*
0190                 return (qVariantValue<ThreeDAttributes>( a ) ==
0191                         qVariantValue<ThreeDAttributes>( b ));
0192                 */
0193                 break;
0194             case LineAttributesRole:
0195                 return (a.value<LineAttributes>() ==
0196                         b.value<LineAttributes>());
0197             case ThreeDLineAttributesRole:
0198                 return (a.value<ThreeDLineAttributes>() ==
0199                         b.value<ThreeDLineAttributes>());
0200             case BarAttributesRole:
0201                 return (a.value<BarAttributes>() ==
0202                         b.value<BarAttributes>());
0203             case StockBarAttributesRole:
0204                 return (a.value<StockBarAttributes>() ==
0205                         b.value<StockBarAttributes>());
0206             case ThreeDBarAttributesRole:
0207                 return (a.value<ThreeDBarAttributes>() ==
0208                         b.value<ThreeDBarAttributes>());
0209             case PieAttributesRole:
0210                 return (a.value<PieAttributes>() ==
0211                         b.value<PieAttributes>());
0212             case ThreeDPieAttributesRole:
0213                 return (a.value<ThreeDPieAttributes>() ==
0214                         b.value<ThreeDPieAttributes>());
0215             case ValueTrackerAttributesRole:
0216                 return (a.value<ValueTrackerAttributes>() ==
0217                         b.value<ValueTrackerAttributes>());
0218             case DataHiddenRole:
0219                 return (a.value<bool>() ==
0220                         b.value<bool>());
0221             default:
0222                 Q_ASSERT( false ); // all of our own roles need to be handled
0223                 break;
0224         }
0225     } else {
0226         return (a == b);
0227     }
0228     return true;
0229 }
0230 
0231 
0232 QVariant AttributesModel::headerData( int section, Qt::Orientation orientation,
0233                                       int role/* = Qt::DisplayRole */ ) const
0234 {
0235     if ( sourceModel() ) {
0236         const QVariant sourceData = sourceModel()->headerData( section, orientation, role );
0237         if ( sourceData.isValid() ) {
0238             return sourceData;
0239         }
0240     }
0241 
0242     // the source model didn't have data set, let's use our stored values
0243     const QMap< int, QMap< int, QVariant> >& map = orientation == Qt::Horizontal ?
0244                                                    d->horizontalHeaderDataMap : d->verticalHeaderDataMap;
0245     QMap< int, QMap< int, QVariant > >::const_iterator mapIt = map.find( section );
0246     if ( mapIt != map.constEnd() ) {
0247         const QMap< int, QVariant >& dataMap = mapIt.value();
0248         QMap< int, QVariant >::const_iterator dataMapIt = dataMap.find( role );
0249         if ( dataMapIt != dataMap.constEnd() ) {
0250             return dataMapIt.value();
0251         }
0252     }
0253 
0254     return defaultHeaderData( section, orientation, role );
0255 }
0256 
0257 
0258 QVariant AttributesModel::defaultHeaderData( int section, Qt::Orientation orientation, int role ) const
0259 {
0260     // Default values if nothing else matches
0261 
0262     const int dataset = section / d->dataDimension;
0263 
0264     switch ( role ) {
0265     case Qt::DisplayRole:
0266         //TODO for KChart 3.0: return QString::number( dataset + 1 );
0267         return QVariant( (orientation == Qt::Vertical ? QStringLiteral("Series ") : QStringLiteral("Item ")) + QString::number( dataset )) ;
0268     case KChart::DatasetBrushRole:
0269         return d->palette.getBrush( dataset );
0270     case KChart::DatasetPenRole:
0271         // if no per model override was set, use the (possibly default) color set for the brush
0272         if ( !modelData( role ).isValid() ) {
0273             QBrush brush = headerData( section, orientation, DatasetBrushRole ).value< QBrush >();
0274             return QPen( brush.color() );
0275         }
0276     default:
0277         break;
0278     }
0279 
0280     return QVariant();
0281 }
0282 
0283 
0284 QVariant AttributesModel::data( int role ) const
0285 {
0286   if ( isKnownAttributesRole( role ) ) {
0287       // check if there is something set at global level
0288       QVariant v = modelData( role );
0289 
0290       // else return the default setting, if any
0291       if ( !v.isValid() )
0292           v = defaultsForRole( role );
0293       return v;
0294   }
0295   return QVariant();
0296 }
0297 
0298 
0299 QVariant AttributesModel::data( int column, int role ) const
0300 {
0301   if ( isKnownAttributesRole( role ) ) {
0302       // check if there is something set for the column (dataset)
0303       QVariant v;
0304       v = headerData( column, Qt::Horizontal, role );
0305 
0306       // check if there is something set at global level
0307       if ( !v.isValid() )
0308           v = data( role ); // includes automatic fallback to default
0309       return v;
0310   }
0311   return QVariant();
0312 }
0313 
0314 
0315 QVariant AttributesModel::data( const QModelIndex& index, int role ) const
0316 {
0317     if ( index.isValid() ) {
0318         Q_ASSERT( index.model() == this );
0319     }
0320     if ( !sourceModel() ) {
0321         return QVariant();
0322     }
0323 
0324     if ( index.isValid() ) {
0325         const QVariant sourceData = sourceModel()->data( mapToSource( index ), role );
0326         if ( sourceData.isValid() ) {
0327             return sourceData;
0328         }
0329     }
0330 
0331     // check if we are storing a value for this role at this cell index
0332     if ( d->dataMap.contains( index.column() ) ) {
0333         const QMap< int,  QMap< int, QVariant > >& colDataMap = d->dataMap[ index.column() ];
0334         if ( colDataMap.contains( index.row() ) ) {
0335             const QMap< int, QVariant >& dataMap = colDataMap[ index.row() ];
0336             if ( dataMap.contains( role ) ) {
0337                 const QVariant v = dataMap[ role ];
0338                 if ( v.isValid() ) {
0339                     return v;
0340                 }
0341             }
0342         }
0343     }
0344     // check if there is something set for the column (dataset), or at global level
0345     if ( index.isValid() ) {
0346         return data( index.column(), role ); // includes automatic fallback to default
0347     }
0348 
0349     return QVariant();
0350 }
0351 
0352 
0353 bool AttributesModel::isKnownAttributesRole( int role ) const
0354 {
0355     switch ( role ) {
0356         // fallthrough intended
0357     case DataValueLabelAttributesRole:
0358     case DatasetBrushRole:
0359     case DatasetPenRole:
0360     case ThreeDAttributesRole:
0361     case LineAttributesRole:
0362     case ThreeDLineAttributesRole:
0363     case BarAttributesRole:
0364     case StockBarAttributesRole:
0365     case ThreeDBarAttributesRole:
0366     case PieAttributesRole:
0367     case ThreeDPieAttributesRole:
0368     case ValueTrackerAttributesRole:
0369     case DataHiddenRole:
0370         return true;
0371     default:
0372         return false;
0373     }
0374 }
0375 
0376 QVariant AttributesModel::defaultsForRole( int role ) const
0377 {
0378     // returns default-constructed QVariant if not found
0379     return d->defaultsMap.value( role );
0380 }
0381 
0382 bool AttributesModel::setData ( const QModelIndex & index, const QVariant & value, int role )
0383 {
0384     if ( !isKnownAttributesRole( role ) ) {
0385         return sourceModel()->setData( mapToSource(index), value, role );
0386     } else {
0387         QMap< int,  QMap< int, QVariant> > &colDataMap = d->dataMap[ index.column() ];
0388         QMap< int, QVariant > &dataMap = colDataMap[ index.row() ];
0389         dataMap.insert( role, value );
0390         Q_EMIT attributesChanged( index, index );
0391         return true;
0392     }
0393 }
0394 
0395 bool AttributesModel::resetData ( const QModelIndex & index, int role )
0396 {
0397     return setData( index, QVariant(), role );
0398 }
0399 
0400 bool AttributesModel::setHeaderData ( int section, Qt::Orientation orientation,
0401                                       const QVariant & value, int role )
0402 {
0403     if ( sourceModel() && headerData( section, orientation, role ) == value ) {
0404         return true;
0405     }
0406 
0407     if ( !isKnownAttributesRole( role ) ) {
0408         return sourceModel()->setHeaderData( section, orientation, value, role );
0409     } else {
0410         QMap< int,  QMap<int, QVariant > > &sectionDataMap
0411             = orientation == Qt::Horizontal ? d->horizontalHeaderDataMap : d->verticalHeaderDataMap;
0412 
0413         QMap< int, QVariant > &dataMap = sectionDataMap[ section ];
0414         dataMap.insert( role, value );
0415         if ( sourceModel() ) {
0416             int numRows = rowCount( QModelIndex() );
0417             int numCols = columnCount( QModelIndex() );
0418             if ( orientation == Qt::Horizontal && numRows > 0 )
0419                 Q_EMIT attributesChanged( index( 0, section, QModelIndex() ),
0420                                         index( numRows - 1, section, QModelIndex() ) );
0421             else if ( orientation == Qt::Vertical && numCols > 0 )
0422                 Q_EMIT attributesChanged( index( section, 0, QModelIndex() ),
0423                                         index( section, numCols - 1, QModelIndex() ) );
0424             Q_EMIT headerDataChanged( orientation, section, section );
0425 
0426             // FIXME: This only makes sense for orientation == Qt::Horizontal,
0427             // but what if orientation == Qt::Vertical?
0428             if ( section != -1 && numRows > 0 )
0429                 Q_EMIT dataChanged( index( 0, section, QModelIndex() ),
0430                                   index( numRows - 1, section, QModelIndex() ) );
0431         }
0432         return true;
0433     }
0434 }
0435 
0436 bool AttributesModel::resetHeaderData ( int section, Qt::Orientation orientation, int role )
0437 {
0438     return setHeaderData ( section, orientation, QVariant(), role );
0439 }
0440 
0441 void AttributesModel::setPaletteType( AttributesModel::PaletteType type )
0442 {
0443     if ( d->paletteType == type ) {
0444         return;
0445     }
0446     d->paletteType = type;
0447     switch ( type ) {
0448     case PaletteTypeDefault:
0449         d->palette = Palette::defaultPalette();
0450         break;
0451     case PaletteTypeSubdued:
0452         d->palette = Palette::subduedPalette();
0453         break;
0454     case PaletteTypeRainbow:
0455         d->palette = Palette::rainbowPalette();
0456         break;
0457     default:
0458         qWarning( "Unknown palette type!" );
0459     }
0460 }
0461 
0462 AttributesModel::PaletteType AttributesModel::paletteType() const
0463 {
0464     return d->paletteType;
0465 }
0466 
0467 bool KChart::AttributesModel::setModelData( const QVariant value, int role )
0468 {
0469     d->modelDataMap.insert( role, value );
0470     int numRows = rowCount( QModelIndex() );
0471     int numCols = columnCount( QModelIndex() );
0472     if ( sourceModel() && numRows > 0 && numCols > 0 ) {
0473         Q_EMIT attributesChanged( index( 0, 0, QModelIndex() ),
0474                                 index( numRows - 1, numCols - 1, QModelIndex() ) );
0475         beginResetModel();
0476     endResetModel();
0477     }
0478     return true;
0479 }
0480 
0481 QVariant KChart::AttributesModel::modelData( int role ) const
0482 {
0483     return d->modelDataMap.value( role, QVariant() );
0484 }
0485 
0486 int AttributesModel::rowCount( const QModelIndex& index ) const
0487 {
0488     if ( sourceModel() ) {
0489         return sourceModel()->rowCount( mapToSource(index) );
0490     } else {
0491         return 0;
0492     }
0493 }
0494 
0495 int AttributesModel::columnCount( const QModelIndex& index ) const
0496 {
0497     if ( sourceModel() ) {
0498         return sourceModel()->columnCount( mapToSource(index) );
0499     } else {
0500         return 0;
0501     }
0502 }
0503 
0504 void AttributesModel::setSourceModel( QAbstractItemModel* sourceModel )
0505 {
0506     if ( this->sourceModel() != nullptr )
0507     {
0508         disconnect( this->sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
0509                                    this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
0510         disconnect( this->sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
0511                                    this, SLOT(slotRowsInserted(QModelIndex,int,int)) );
0512         disconnect( this->sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
0513                                    this, SLOT(slotRowsRemoved(QModelIndex,int,int)) );
0514         disconnect( this->sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
0515                                    this, SLOT(slotRowsAboutToBeInserted(QModelIndex,int,int)) );
0516         disconnect( this->sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
0517                                    this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)) );
0518         disconnect( this->sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)),
0519                                    this, SLOT(slotColumnsInserted(QModelIndex,int,int)) );
0520         disconnect( this->sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
0521                                    this, SLOT(slotColumnsRemoved(QModelIndex,int,int)) );
0522         disconnect( this->sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
0523                                    this, SLOT(slotColumnsAboutToBeInserted(QModelIndex,int,int)) );
0524         disconnect( this->sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
0525                                    this, SLOT(slotColumnsAboutToBeRemoved(QModelIndex,int,int)) );
0526         disconnect( this->sourceModel(), SIGNAL(modelReset()),
0527                                    this, SIGNAL(modelReset()) );
0528         disconnect( this->sourceModel(), SIGNAL(layoutChanged()),
0529                                    this, SIGNAL(layoutChanged()) );
0530     }
0531     QAbstractProxyModel::setSourceModel( sourceModel );
0532     if ( this->sourceModel() != nullptr )
0533     {
0534         connect( this->sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
0535                                 this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
0536         connect( this->sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
0537                                 this, SLOT(slotRowsInserted(QModelIndex,int,int)) );
0538         connect( this->sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
0539                                 this, SLOT(slotRowsRemoved(QModelIndex,int,int)) );
0540         connect( this->sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
0541                                 this, SLOT(slotRowsAboutToBeInserted(QModelIndex,int,int)) );
0542         connect( this->sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
0543                                 this, SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int)) );
0544         connect( this->sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)),
0545                                 this, SLOT(slotColumnsInserted(QModelIndex,int,int)) );
0546         connect( this->sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
0547                                 this, SLOT(slotColumnsRemoved(QModelIndex,int,int)) );
0548         connect( this->sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
0549                                 this, SLOT(slotColumnsAboutToBeInserted(QModelIndex,int,int)) );
0550         connect( this->sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
0551                                 this, SLOT(slotColumnsAboutToBeRemoved(QModelIndex,int,int)) );
0552         connect( this->sourceModel(), SIGNAL(modelReset()),
0553                                 this, SIGNAL(modelReset()) );
0554         connect( this->sourceModel(), SIGNAL(layoutChanged()),
0555                                 this, SIGNAL(layoutChanged()) );
0556     }
0557 }
0558 
0559 void AttributesModel::slotRowsAboutToBeInserted( const QModelIndex& parent, int start, int end )
0560 {
0561     beginInsertRows( mapFromSource( parent ), start, end );
0562 }
0563 
0564 void AttributesModel::slotColumnsAboutToBeInserted( const QModelIndex& parent, int start, int end )
0565 {
0566     beginInsertColumns( mapFromSource( parent ), start, end );
0567 }
0568 
0569 void AttributesModel::slotRowsInserted( const QModelIndex& parent, int start, int end )
0570 {
0571     Q_UNUSED( parent );
0572     Q_UNUSED( start );
0573     Q_UNUSED( end );
0574     endInsertRows();
0575 }
0576 
0577 void AttributesModel::slotColumnsInserted( const QModelIndex& parent, int start, int end )
0578 {
0579     Q_UNUSED( parent );
0580     Q_UNUSED( start );
0581     Q_UNUSED( end );
0582     endInsertColumns();
0583 }
0584 
0585 void AttributesModel::slotRowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
0586 {
0587     beginRemoveRows( mapFromSource( parent ), start, end );
0588 }
0589 
0590 void AttributesModel::slotColumnsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
0591 {
0592     beginRemoveColumns( mapFromSource( parent ), start, end );
0593 }
0594 
0595 void AttributesModel::slotRowsRemoved( const QModelIndex& parent, int start, int end )
0596 {
0597     Q_UNUSED( parent );
0598     Q_UNUSED( start );
0599     Q_UNUSED( end );
0600     endRemoveRows();
0601 }
0602 
0603 void AttributesModel::removeEntriesFromDataMap( int start, int end )
0604 {
0605     QMap< int, QMap< int, QMap< int, QVariant > > >::iterator it = d->dataMap.find( end );
0606     // check that the element was found
0607     if ( it != d->dataMap.end() ) {
0608         ++it;
0609         QVector< int > indexesToDel;
0610         for ( int i = start; i < end && it != d->dataMap.end(); ++i ) {
0611             d->dataMap[ i ] = it.value();
0612             indexesToDel << it.key();
0613             ++it;
0614         }
0615         if ( indexesToDel.isEmpty() ) {
0616             for ( int i = start; i < end; ++i ) {
0617                 indexesToDel << i;
0618             }
0619         }
0620         for ( int i  = 0; i < indexesToDel.count(); ++i ) {
0621             d->dataMap.remove( indexesToDel[ i ] );
0622         }
0623     }
0624 }
0625 
0626 void AttributesModel::removeEntriesFromDirectionDataMaps( Qt::Orientation dir, int start, int end )
0627 {
0628     QMap<int,  QMap<int, QVariant> > &sectionDataMap
0629         = dir == Qt::Horizontal ? d->horizontalHeaderDataMap : d->verticalHeaderDataMap;
0630     QMap<int, QMap<int, QVariant> >::iterator it = sectionDataMap.upperBound( end );
0631     // check that the element was found
0632     if ( it != sectionDataMap.end() )
0633     {
0634         QVector< int > indexesToDel;
0635         for ( int i = start; i < end && it != sectionDataMap.end(); ++i )
0636         {
0637             sectionDataMap[ i ] = it.value();
0638             indexesToDel << it.key();
0639             ++it;
0640         }
0641         if ( indexesToDel.isEmpty() )
0642         {
0643             for ( int i = start; i < end; ++i )
0644             {
0645                 indexesToDel << i;
0646             }
0647         }
0648         for ( int i  = 0; i < indexesToDel.count(); ++i )
0649         {
0650             sectionDataMap.remove( indexesToDel[ i ] );
0651         }
0652     }
0653 }
0654 
0655 void AttributesModel::slotColumnsRemoved( const QModelIndex& parent, int start, int end )
0656 {
0657     Q_UNUSED( parent );
0658     Q_UNUSED( start );
0659     Q_UNUSED( end );
0660     Q_ASSERT_X( sourceModel(), "removeColumn", "This should only be triggered if a valid source Model exists!" );
0661     for ( int i = start; i <= end; ++i ) {
0662         d->verticalHeaderDataMap.remove( start );
0663     }
0664     removeEntriesFromDataMap( start, end );
0665     removeEntriesFromDirectionDataMaps( Qt::Horizontal, start, end );
0666     removeEntriesFromDirectionDataMaps( Qt::Vertical, start, end );
0667 
0668     endRemoveColumns();
0669 }
0670 
0671 void AttributesModel::slotDataChanged( const QModelIndex& topLeft, const QModelIndex& bottomRight )
0672 {
0673     Q_EMIT dataChanged( mapFromSource( topLeft ), mapFromSource( bottomRight ) );
0674 }
0675 
0676 void AttributesModel::setDefaultForRole( int role, const QVariant& value )
0677 {
0678     if ( value.isValid() ) {
0679         d->defaultsMap.insert( role, value );
0680     } else {
0681         // erase the possibly existing value to not let the map grow:
0682         QMap<int, QVariant>::iterator it = d->defaultsMap.find( role );
0683         if ( it != d->defaultsMap.end() ) {
0684             d->defaultsMap.erase( it );
0685         }
0686     }
0687 
0688     Q_ASSERT( defaultsForRole( role ).value<KChart::DataValueAttributes>()  == value.value<KChart::DataValueAttributes>() );
0689 }
0690 
0691 void AttributesModel::setDatasetDimension( int dimension )
0692 {
0693     //### need to "reformat" or throw away internal data?
0694     d->dataDimension = dimension;
0695 }
0696 
0697 int AttributesModel::datasetDimension() const
0698 {
0699     return d->dataDimension;
0700 }