KD Chart 2: KDChartAttributesModel.cpp Source File

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

# KDChartAttributesModel.cpp

Go to the documentation of this file.

    00001 /* -*- Mode: C++ -*-
    00002    KDChart - a multi-platform charting engine
    00003    */
    00004
    00005 /****************************************************************************
    00006  ** Copyright (C) 2001-2006 Klaraelvdalens Datakonsult AB.  All rights reserved.
    00007  **
    00008  ** This file is part of the KD Chart library.
    00009  **
    00010  ** This file may be distributed and/or modified under the terms of the
    00011  ** GNU General Public License version 2 as published by the Free Software
    00012  ** Foundation and appearing in the file LICENSE.GPL included in the
    00013  ** packaging of this file.
    00014  **
    00015  ** Licensees holding valid commercial KD Chart licenses may use this file in
    00016  ** accordance with the KD Chart Commercial License Agreement provided with
    00017  ** the Software.
    00018  **
    00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
    00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    00021  **
    00022  ** See http://www.kdab.net/kdchart for
    00023  **   information about KD Chart Commercial License Agreements.
    00024  **
    00025  ** Contact info@kdab.net if any conditions of this
    00026  ** licensing are not clear to you.
    00027  **
    00028  **********************************************************************/
    00029 #include <QDebug>
    00030 #include <QPen>
    00031 #include <QPointer>
    00032
    00033 #include "KDChartAttributesModel.h"
    00034 #include "KDChartPalette.h"
    00035 #include "KDChartGlobal.h"
    00036
    00037 #include <KDChartTextAttributes>
    00038 #include <KDChartFrameAttributes>
    00039 #include <KDChartBackgroundAttributes>
    00040 #include <KDChartDataValueAttributes>
    00041 #include <KDChartMarkerAttributes>
    00042 #include <KDChartBarAttributes>
    00043 #include <KDChartLineAttributes>
    00044 #include <KDChartPieAttributes>
    00045 #include <KDChartAbstractThreeDAttributes>
    00046 #include <KDChartThreeDBarAttributes>
    00047 #include <KDChartThreeDLineAttributes>
    00048 #include <KDChartThreeDPieAttributes>
    00049 #include <KDChartGridAttributes>
    00050
    00051 #include <KDABLibFakes>
    00052
    00053
    00054 using namespace KDChart;
    00055
    00056 AttributesModel::AttributesModel( QAbstractItemModel* model, QObject * parent/* = 0 */ )
    00057   : AbstractProxyModel( parent ),
    00058     mPaletteType( PaletteTypeDefault )
    00059 {
    00060   setSourceModel(model);
    00061 }
    00062
    00063 AttributesModel::~AttributesModel()
    00064 {
    00065 }
    00066
    00067 void AttributesModel::initFrom( const AttributesModel* other )
    00068 {
    00069     if( other == this || ! other ) return;
    00070
    00071     mDataMap = other->mDataMap;
    00072     mHorizontalHeaderDataMap = other->mHorizontalHeaderDataMap;
    00073     mVerticalHeaderDataMap = other->mVerticalHeaderDataMap;
    00074     mModelDataMap = other->mModelDataMap;
    00075
    00076     setPaletteType( other->paletteType() );
    00077 }
    00078
    00079 bool AttributesModel::compare( const AttributesModel* other )const
    00080 {
    00081     if( other == this ) return true;
    00082     if( ! other ){
    00083         //qDebug() << "AttributesModel::compare() cannot compare to Null pointer";
    00084         return false;
    00085     }
    00086
    00087     {
    00088         if (mDataMap.count() != other->mDataMap.count()){
    00089             //qDebug() << "AttributesModel::compare() dataMap have different sizes";
    00090             return false;
    00091         }
    00092         QMap<int, QMap<int, QMap<int, QVariant> > >::const_iterator itA = mDataMap.constBegin();
    00093         QMap<int, QMap<int, QMap<int, QVariant> > >::const_iterator itB = other->mDataMap.constBegin();
    00094         while (itA != mDataMap.constEnd()) {
    00095             if ((*itA).count() != (*itB).count()){
    00096                 //qDebug() << "AttributesModel::compare() dataMap/map have different sizes";
    00097                 return false;
    00098             }
    00099             QMap<int, QMap<int, QVariant> >::const_iterator it2A = (*itA).constBegin();
    00100             QMap<int, QMap<int, QVariant> >::const_iterator it2B = (*itB).constBegin();
    00101             while (it2A != itA->constEnd()) {
    00102                 if ((*it2A).count() != (*it2B).count()){
    00103                     //qDebug() << "AttributesModel::compare() dataMap/map/map have different sizes:"
    00104                     //        << (*it2A).count() << (*it2B).count();
    00105                     return false;
    00106                 }
    00107                 QMap<int, QVariant>::const_iterator it3A = (*it2A).constBegin();
    00108                 QMap<int, QVariant>::const_iterator it3B = (*it2B).constBegin();
    00109                 while (it3A != it2A->constEnd()) {
    00110                     if ( it3A.key() != it3B.key() ){
    00111                         //qDebug( "AttributesModel::compare()\n"
    00112                         //        "   dataMap[%i, %i] values have different types.  A: %x  B: %x",
    00113                         //        itA.key(), it2A.key(), it3A.key(), it3B.key());
    00114                         return false;
    00115                     }
    00116                     if ( ! compareAttributes( it3A.key(), it3A.value(), it3B.value() ) ){
    00117                         //qDebug( "AttributesModel::compare()\n"
    00118                         //        "   dataMap[%i, %i] values are different. Role: %x", itA.key(), it2A.key(), it3A.key());
    00119                         return false;
    00120                     }
    00121                     ++it3A;
    00122                     ++it3B;
    00123                 }
    00124                 ++it2A;
    00125                 ++it2B;
    00126             }
    00127             ++itA;
    00128             ++itB;
    00129         }
    00130     }
    00131     {
    00132         if (mHorizontalHeaderDataMap.count() != other->mHorizontalHeaderDataMap.count()){
    00133             //qDebug() << "AttributesModel::compare() horizontalHeaderDataMap have different sizes";
    00134             return false;
    00135         }
    00136         QMap<int, QMap<int, QVariant> >::const_iterator itA = mHorizontalHeaderDataMap.constBegin();
    00137         QMap<int, QMap<int, QVariant> >::const_iterator itB = other->mHorizontalHeaderDataMap.constBegin();
    00138         while (itA != mHorizontalHeaderDataMap.constEnd()) {
    00139             if ((*itA).count() != (*itB).count()){
    00140                 //qDebug() << "AttributesModel::compare() horizontalHeaderDataMap/map have different sizes";
    00141                 return false;
    00142             }
    00143             QMap<int, QVariant>::const_iterator it2A = (*itA).constBegin();
    00144             QMap<int, QVariant>::const_iterator it2B = (*itB).constBegin();
    00145             while (it2A != itA->constEnd()) {
    00146                 if ( it2A.key() != it2B.key() ){
    00147                     //qDebug( "AttributesModel::compare()\n"
    00148                     //        "   horizontalHeaderDataMap[ %i ] values have different types.  A: %x  B: %x",
    00149                     //        itA.key(), it2A.key(), it2B.key());
    00150                     return false;
    00151                 }
    00152                 if ( ! compareAttributes( it2A.key(), it2A.value(), it2B.value() ) ){
    00153                     //qDebug( "AttributesModel::compare()\n"
    00154                     //        "   horizontalHeaderDataMap[ %i ] values are different. Role: %x", itA.key(), it2A.key() );
    00155                     return false;
    00156                 }
    00157                 ++it2A;
    00158                 ++it2B;
    00159             }
    00160             ++itA;
    00161             ++itB;
    00162         }
    00163     }
    00164     {
    00165         if (mVerticalHeaderDataMap.count() != other->mVerticalHeaderDataMap.count()){
    00166             //qDebug() << "AttributesModel::compare() verticalHeaderDataMap have different sizes";
    00167             return false;
    00168         }
    00169         QMap<int, QMap<int, QVariant> >::const_iterator itA = mVerticalHeaderDataMap.constBegin();
    00170         QMap<int, QMap<int, QVariant> >::const_iterator itB = other->mVerticalHeaderDataMap.constBegin();
    00171         while (itA != mVerticalHeaderDataMap.constEnd()) {
    00172             if ((*itA).count() != (*itB).count()){
    00173                 //qDebug() << "AttributesModel::compare() verticalHeaderDataMap/map have different sizes";
    00174                 return false;
    00175             }
    00176             QMap<int, QVariant>::const_iterator it2A = (*itA).constBegin();
    00177             QMap<int, QVariant>::const_iterator it2B = (*itB).constBegin();
    00178             while (it2A != itA->constEnd()) {
    00179                 if ( it2A.key() != it2B.key() ){
    00180                     //qDebug( "AttributesModel::compare()\n"
    00181                     //        "   verticalHeaderDataMap[ %i ] values have different types.  A: %x  B: %x",
    00182                     //        itA.key(), it2A.key(), it2B.key());
    00183                     return false;
    00184                 }
    00185                 if ( ! compareAttributes( it2A.key(), it2A.value(), it2B.value() ) ){
    00186                     //qDebug( "AttributesModel::compare()\n"
    00187                     //        "   verticalHeaderDataMap[ %i ] values are different. Role: %x", itA.key(), it2A.key() );
    00188                     return false;
    00189                 }
    00190                 ++it2A;
    00191                 ++it2B;
    00192             }
    00193             ++itA;
    00194             ++itB;
    00195         }
    00196     }
    00197     {
    00198         if (mModelDataMap.count() != other->mModelDataMap.count()){
    00199             //qDebug() << "AttributesModel::compare() modelDataMap have different sizes:" << mModelDataMap.count() << other->mModelDataMap.count();
    00200             return false;
    00201         }
    00202         QMap<int, QVariant>::const_iterator itA = mModelDataMap.constBegin();
    00203         QMap<int, QVariant>::const_iterator itB = other->mModelDataMap.constBegin();
    00204         while (itA != mModelDataMap.constEnd()) {
    00205             if ( itA.key() != itB.key() ){
    00206                 //qDebug( "AttributesModel::compare()\n"
    00207                 //        "   modelDataMap values have different types.  A: %x  B: %x",
    00208                 //        itA.key(), itB.key());
    00209                 return false;
    00210             }
    00211             if ( ! compareAttributes( itA.key(), itA.value(), itB.value() ) ){
    00212                 //qDebug( "AttributesModel::compare()\n"
    00213                 //        "   modelDataMap values are different. Role: %x", itA.key() );
    00214                 return false;
    00215             }
    00216             ++itA;
    00217             ++itB;
    00218         }
    00219     }
    00220     if (paletteType() != other->paletteType()){
    00221         //qDebug() << "AttributesModel::compare() palette types are different";
    00222         return false;
    00223     }
    00224     return true;
    00225 }
    00226
    00227 bool AttributesModel::compareAttributes(
    00228         int role, const QVariant& a, const QVariant& b )const
    00229 {
    00230     if( isKnownAttributesRole( role ) ){
    00231         switch( role ) {
    00232             case DataValueLabelAttributesRole:
    00233                 return (qVariantValue<DataValueAttributes>( a ) ==
    00234                         qVariantValue<DataValueAttributes>( b ));
    00235             case DatasetBrushRole:
    00236                 return (qVariantValue<QBrush>( a ) ==
    00237                         qVariantValue<QBrush>( b ));
    00238             case DatasetPenRole:
    00239                 return (qVariantValue<QPen>( a ) ==
    00240                         qVariantValue<QPen>( b ));
    00241             case ThreeDAttributesRole:
    00242                 // As of yet there is no ThreeDAttributes class,
    00243                 // and the AbstractThreeDAttributes class is pure virtual,
    00244                 // so we ignore this role for now.
    00245                 // (khz, 04.04.2007)
    00246                 /*
    00247                 return (qVariantValue<ThreeDAttributes>( a ) ==
    00248                         qVariantValue<ThreeDAttributes>( b ));
    00249                 */
    00250                 break;
    00251             case LineAttributesRole:
    00252                 return (qVariantValue<LineAttributes>( a ) ==
    00253                         qVariantValue<LineAttributes>( b ));
    00254             case ThreeDLineAttributesRole:
    00255                 return (qVariantValue<ThreeDLineAttributes>( a ) ==
    00256                         qVariantValue<ThreeDLineAttributes>( b ));
    00257             case BarAttributesRole:
    00258                 return (qVariantValue<BarAttributes>( a ) ==
    00259                         qVariantValue<BarAttributes>( b ));
    00260             case ThreeDBarAttributesRole:
    00261                 return (qVariantValue<ThreeDBarAttributes>( a ) ==
    00262                         qVariantValue<ThreeDBarAttributes>( b ));
    00263             case PieAttributesRole:
    00264                 return (qVariantValue<PieAttributes>( a ) ==
    00265                         qVariantValue<PieAttributes>( b ));
    00266             case ThreeDPieAttributesRole:
    00267                 return (qVariantValue<ThreeDPieAttributes>( a ) ==
    00268                         qVariantValue<ThreeDPieAttributes>( b ));
    00269             case DataHiddenRole:
    00270                 return (qVariantValue<bool>( a ) ==
    00271                         qVariantValue<bool>( b ));
    00272             default:
    00273                 Q_ASSERT( false ); // all of our own roles need to be handled
    00274                 break;
    00275         }
    00276     }else{
    00277         return (a == b);
    00278     }
    00279     return true;
    00280 }
    00281
    00282
    00283 QVariant AttributesModel::headerData ( int section,
    00284                                        Qt::Orientation orientation,
    00285                                        int role/* = Qt::DisplayRole */ ) const
    00286 {
    00287   QVariant sourceData = sourceModel()->headerData( section, orientation, role );
    00288   if ( sourceData.isValid() ) return sourceData;
    00289   // the source model didn't have data set, let's use our stored values
    00290   const QMap<int, QMap<int, QVariant> >& map = orientation == Qt::Horizontal ? mHorizontalHeaderDataMap : mVerticalHeaderDataMap;
    00291   if ( map.contains( section ) ) {
    00292       const QMap<int, QVariant> &dataMap = map[ section ];
    00293       if ( dataMap.contains( role ) ) {
    00294           return dataMap[ role ];
    00295       }
    00296   }
    00297
    00298   // Default values if nothing else matches
    00299   switch ( role ) {
    00300   case Qt::DisplayRole:
    00301       return QLatin1String( orientation == Qt::Vertical ?  "Series " : "Item " ) + QString::number( section ) ;
    00302
    00303   case KDChart::DatasetBrushRole: {
    00304       if ( paletteType() == PaletteTypeSubdued )
    00305           return Palette::subduedPalette().getBrush( section );
    00306       else if ( paletteType() == PaletteTypeRainbow )
    00307           return Palette::rainbowPalette().getBrush( section );
    00308       else if ( paletteType() == PaletteTypeDefault )
    00309           return Palette::defaultPalette().getBrush( section );
    00310       else
    00311           qWarning("Unknown type of fallback palette!");
    00312   }
    00313   case KDChart::DatasetPenRole: {
    00314       // default to the color set for the brush (or it's defaults)
    00315       // but only if no per model override was set
    00316       if ( !modelData( role ).isValid() ) {
    00317           QBrush brush = qVariantValue<QBrush>( headerData( section, orientation, DatasetBrushRole ) );
    00318           return QPen( brush.color() );
    00319       }
    00320   }
    00321   default:
    00322       break;
    00323   }
    00324
    00325   return QVariant();
    00326 }
    00327
    00328
    00329 // Note: Our users NEED this method - even if
    00330 //       we do not need it at drawing time!
    00331 //       (khz, 2006-07-28)
    00332 QVariant AttributesModel::data( int role ) const
    00333 {
    00334   if ( isKnownAttributesRole( role ) ) {
    00335       // check if there is something set at global level
    00336       QVariant v = modelData( role );
    00337
    00338       // else return the default setting, if any
    00339       if ( !v.isValid() )
    00340           v = defaultsForRole( role );
    00341       return v;
    00342   }
    00343   return QVariant();
    00344 }
    00345
    00346
    00347 // Note: Our users NEED this method - even if
    00348 //       we do not need it at drawing time!
    00349 //       (khz, 2006-07-28)
    00350 QVariant AttributesModel::data( int column, int role ) const
    00351 {
    00352   if ( isKnownAttributesRole( role ) ) {
    00353       // check if there is something set for the column (dataset)
    00354       QVariant v;
    00355       v = headerData( column, Qt::Vertical, role );
    00356
    00357       // check if there is something set at global level
    00358       if ( !v.isValid() )
    00359           v = data( role ); // includes automatic fallback to default
    00360       return v;
    00361   }
    00362   return QVariant();
    00363 }
    00364
    00365
    00366 QVariant AttributesModel::data( const QModelIndex& index, int role ) const
    00367 {
    00368   //qDebug() << "AttributesModel::data(" << index << role << ")";
    00369   if( index.isValid() ) {
    00370     Q_ASSERT( index.model() == this );
    00371   }
    00372   QVariant sourceData = sourceModel()->data( mapToSource(index), role );
    00373   if ( sourceData.isValid() )
    00374       return sourceData;
    00375
    00376   // check if we are storing a value for this role at this cell index
    00377   if ( mDataMap.contains( index.column() ) ) {
    00378       const QMap< int,  QMap< int, QVariant> > &colDataMap = mDataMap[ index.column() ];
    00379       if ( colDataMap.contains( index.row() ) ) {
    00380           const QMap<int, QVariant> &dataMap = colDataMap[ index.row() ];
    00381           if ( dataMap.contains( role ) ) {
    00382               QVariant v = dataMap[ role ];
    00383               if( v.isValid() )
    00384                   return dataMap[ role ];
    00385           }
    00386       }
    00387   }
    00388   // check if there is something set for the column (dataset), or at global level
    00389   if( index.isValid() )
    00390       return data( index.column(), role ); // includes automatic fallback to default
    00391
    00392   return QVariant();
    00393 }
    00394
    00395
    00396 bool AttributesModel::isKnownAttributesRole( int role ) const
    00397 {
    00398     bool oneOfOurs = false;
    00399     switch( role ) {
    00400       // fallthrough intended
    00401       case DataValueLabelAttributesRole:
    00402       case DatasetBrushRole:
    00403       case DatasetPenRole:
    00404       case ThreeDAttributesRole:
    00405       case LineAttributesRole:
    00406       case ThreeDLineAttributesRole:
    00407       case BarAttributesRole:
    00408       case ThreeDBarAttributesRole:
    00409       case PieAttributesRole:
    00410       case ThreeDPieAttributesRole:
    00411       case DataHiddenRole:
    00412             oneOfOurs = true;
    00413         default:
    00414         break;
    00415     }
    00416     return oneOfOurs;
    00417 }
    00418
    00419 QVariant AttributesModel::defaultsForRole( int role ) const
    00420 {
    00421     switch ( role ) {
    00422         case KDChart::DataValueLabelAttributesRole:
    00423             return DataValueAttributes::defaultAttributesAsVariant();
    00424             // for the below there isn't a per-value default, since there's a per-column one
    00425         case KDChart::DatasetBrushRole:
    00426         case KDChart::DatasetPenRole:
    00427         default:
    00428             break;
    00429     }
    00430     return QVariant();
    00431 }
    00432
    00433 bool AttributesModel::setData ( const QModelIndex & index, const QVariant & value, int role )
    00434 {
    00435     if ( !isKnownAttributesRole( role ) ) {
    00436         return sourceModel()->setData( mapToSource(index), value, role );
    00437     } else {
    00438         QMap< int,  QMap< int, QVariant> > &colDataMap = mDataMap[ index.column() ];
    00439         QMap<int, QVariant> &dataMap = colDataMap[ index.row() ];
    00440         //qDebug() <<  "AttributesModel::setData" <<"role" << role << "value" << value;
    00441         dataMap.insert( role, value );
    00442         emit attributesChanged( index, index );
    00443         return true;
    00444     }
    00445 }
    00446
    00447 bool AttributesModel::resetData ( const QModelIndex & index, int role )
    00448 {
    00449     return setData ( index, QVariant(), role );
    00450 }
    00451
    00452 bool AttributesModel::setHeaderData ( int section, Qt::Orientation orientation,
    00453                                       const QVariant & value, int role )
    00454 {
    00455     if ( !isKnownAttributesRole( role ) ) {
    00456         return sourceModel()->setHeaderData( section, orientation, value, role );
    00457     } else {
    00458         QMap<int,  QMap<int, QVariant> > &sectionDataMap
    00459             = orientation == Qt::Horizontal ? mHorizontalHeaderDataMap : mVerticalHeaderDataMap;
    00460         QMap<int, QVariant> &dataMap = sectionDataMap[ section ];
    00461         dataMap.insert( role, value );
    00462         emit attributesChanged( index( 0, section, QModelIndex() ),
    00463                                 index( rowCount( QModelIndex() ), section, QModelIndex() ) );
    00464         return true;
    00465     }
    00466 }
    00467
    00468 bool AttributesModel::resetHeaderData ( int section, Qt::Orientation orientation, int role )
    00469 {
    00470     return setHeaderData ( section, orientation, QVariant(), role );
    00471 }
    00472
    00473 void AttributesModel::setPaletteType( AttributesModel::PaletteType type )
    00474 {
    00475     mPaletteType = type;
    00476 }
    00477
    00478 AttributesModel::PaletteType AttributesModel::paletteType() const
    00479 {
    00480     return mPaletteType;
    00481 }
    00482
    00483 bool KDChart::AttributesModel::setModelData( const QVariant value, int role )
    00484 {
    00485     mModelDataMap.insert( role, value );
    00486     emit attributesChanged( index( 0, 0, QModelIndex() ),
    00487                             index( rowCount( QModelIndex() ),
    00488                                     columnCount( QModelIndex() ), QModelIndex() ) );
    00489     return true;
    00490 }
    00491
    00492 QVariant KDChart::AttributesModel::modelData( int role ) const
    00493 {
    00494     return mModelDataMap.value( role, QVariant() );
    00495 }
    00496
    00497 int AttributesModel::rowCount( const QModelIndex& index ) const
    00498 {
    00499     Q_ASSERT(sourceModel());
    00500     return sourceModel()->rowCount( mapToSource(index) );
    00501 }
    00502
    00503 int AttributesModel::columnCount( const QModelIndex& index ) const
    00504 {
    00505     Q_ASSERT(sourceModel());
    00506     return sourceModel()->columnCount( mapToSource(index) );
    00507 }
    00508
    00509 void AttributesModel::setSourceModel( QAbstractItemModel* sourceModel )
    00510 {
    00511     if( this->sourceModel() != 0 )
    00512         disconnect( this->sourceModel(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex&)),
    00513                                   this, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex&)));
    00514     QAbstractProxyModel::setSourceModel( sourceModel );
    00515     if( this->sourceModel() != NULL )
    00516         connect( this->sourceModel(), SIGNAL( dataChanged( const QModelIndex&, const QModelIndex&)),
    00517                                 this, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex&)));
    00518 }
    00519
    00521 const QMap<int, QMap<int, QMap<int, QVariant> > > AttributesModel::dataMap()const
    00522 {
    00523     return mDataMap;
    00524 }
    00526 const QMap<int, QMap<int, QVariant> > AttributesModel::horizontalHeaderDataMap()const
    00527 {
    00528     return mHorizontalHeaderDataMap;
    00529 }
    00531 const QMap<int, QMap<int, QVariant> > AttributesModel::verticalHeaderDataMap()const
    00532 {
    00533     return mVerticalHeaderDataMap;
    00534 }
    00536 const QMap<int, QVariant> AttributesModel::modelDataMap()const
    00537 {
    00538     return mModelDataMap;
    00539 }
    00540
    00542 void AttributesModel::setDataMap( const QMap<int, QMap<int, QMap<int, QVariant> > > map )
    00543 {
    00544     mDataMap = map;
    00545 }
    00547 void AttributesModel::setHorizontalHeaderDataMap( const QMap<int, QMap<int, QVariant> > map )
    00548 {
    00549     mHorizontalHeaderDataMap = map;
    00550 }
    00552 void AttributesModel::setVerticalHeaderDataMap( const QMap<int, QMap<int, QVariant> > map )
    00553 {
    00554     mVerticalHeaderDataMap = map;
    00555 }
    00557 void AttributesModel::setModelDataMap( const QMap<int, QVariant> map )
    00558 {
    00559     mModelDataMap = map;
    00560 }