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 }

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