• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kdgantt

kdganttsummaryhandlingproxymodel.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2001-2006 Klarälvdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Gantt library.
00005  **
00006  ** This file may be used under the terms of the GNU General Public
00007  ** License versions 2.0 or 3.0 as published by the Free Software
00008  ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
00009  ** included in the packaging of this file.  Alternatively you may (at
00010  ** your option) use any later version of the GNU General Public
00011  ** License if such license has been publicly approved by
00012  ** Klarälvdalens Datakonsult AB (or its successors, if any).
00013  ** 
00014  ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
00015  ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
00016  ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
00017  ** not expressly granted herein.
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  **********************************************************************/
00023 #include "kdganttsummaryhandlingproxymodel.h"
00024 #include "kdganttsummaryhandlingproxymodel_p.h"
00025 
00026 #include <QDebug>
00027 
00028 #include <cassert>
00029 
00030 using namespace KDGantt;
00031 
00048 typedef ForwardingProxyModel BASE;
00049 
00050 bool SummaryHandlingProxyModel::Private::cacheLookup( const QModelIndex& idx,
00051                                                       QPair<QDateTime,QDateTime>* result ) const
00052 {
00053     //qDebug() << "cacheLookup("<<idx<<"), cache has " << cached_summary_items.count() << "items";
00054     QHash<QModelIndex,QPair<QDateTime,QDateTime> >::const_iterator it =
00055         cached_summary_items.find( idx );
00056     if ( it != cached_summary_items.constEnd() ) {
00057         *result = *it;
00058         return true;
00059     } else {
00060         return false;
00061     }
00062 }
00063 
00064 void SummaryHandlingProxyModel::Private::insertInCache( const SummaryHandlingProxyModel* model,
00065                                                         const QModelIndex& sourceIdx ) const
00066 {
00067     QAbstractItemModel* sourceModel = model->sourceModel();
00068     const QModelIndex& mainIdx = sourceIdx;
00069     QDateTime st;
00070     QDateTime et;
00071 
00072     for ( int r = 0; r < sourceModel->rowCount( mainIdx ); ++r ) {
00073         QModelIndex pdIdx = model->mapFromSource( sourceModel->index( r, 0, mainIdx ) );
00074         /* The probably results in recursive calls here */
00075     QVariant tmpsv = model->data( pdIdx, StartTimeRole );
00076     QVariant tmpev = model->data( pdIdx, EndTimeRole );
00077     if( !qVariantCanConvert<QDateTime>(tmpsv) ||
00078         !qVariantCanConvert<QDateTime>(tmpev) ) {
00079             qDebug() << "Skipping item " << sourceIdx << " because it doesn't contain QDateTime";
00080             continue;
00081         }
00082 
00083     // We need to test for empty strings to
00084     // avoid a stupid Qt warning
00085     if( tmpsv.type() == QVariant::String && qVariantValue<QString>(tmpsv).isEmpty()) continue;
00086     if( tmpev.type() == QVariant::String && qVariantValue<QString>(tmpev).isEmpty()) continue;
00087         QDateTime tmpst = tmpsv.toDateTime();
00088         QDateTime tmpet = tmpev.toDateTime();
00089         if ( st.isNull() || st > tmpst ) st = tmpst;
00090         if ( et.isNull() || et < tmpet ) et = tmpet;
00091     }
00092     QVariant tmpssv = sourceModel->data( mainIdx, StartTimeRole );
00093     QVariant tmpsev = sourceModel->data( mainIdx, EndTimeRole );
00094     if ( qVariantCanConvert<QDateTime>( tmpssv )
00095          && !( qVariantCanConvert<QString>( tmpssv ) && qVariantValue<QString>( tmpssv ).isEmpty() )
00096          && qVariantValue<QDateTime>( tmpssv ) != st )
00097         sourceModel->setData( mainIdx, st, StartTimeRole );
00098     if ( qVariantCanConvert<QDateTime>( tmpsev )
00099          && !( qVariantCanConvert<QString>( tmpsev ) && qVariantValue<QString>( tmpsev ).isEmpty() )
00100          && qVariantValue<QDateTime>( tmpsev ) != et )
00101         sourceModel->setData( mainIdx, et, EndTimeRole );
00102     cached_summary_items[sourceIdx]=qMakePair( st, et );
00103 }
00104 
00105 void SummaryHandlingProxyModel::Private::removeFromCache( const QModelIndex& idx ) const
00106 {
00107     cached_summary_items.remove( idx );
00108 }
00109 
00110 void SummaryHandlingProxyModel::Private::clearCache() const
00111 {
00112     cached_summary_items.clear();
00113 }
00114 
00118 SummaryHandlingProxyModel::SummaryHandlingProxyModel( QObject* parent )
00119     : BASE( parent ), _d( new Private )
00120 {
00121     init();
00122 }
00123 
00124 #define d d_func()
00125 SummaryHandlingProxyModel::~SummaryHandlingProxyModel()
00126 {
00127 }
00128 
00129 void SummaryHandlingProxyModel::init()
00130 {
00131 }
00132 
00133 namespace {
00134 
00135     // Think this is ugly? Well, it's not from me, it comes from QProxyModel
00136     struct KDPrivateModelIndex {
00137         int r, c;
00138         void *p;
00139         const QAbstractItemModel *m;
00140     };
00141 }
00142 
00147 void SummaryHandlingProxyModel::setSourceModel( QAbstractItemModel* model )
00148 {
00149     BASE::setSourceModel( model );
00150     d->clearCache();
00151 }
00152 
00153 void SummaryHandlingProxyModel::sourceModelReset()
00154 {
00155     d->clearCache();
00156     BASE::sourceModelReset();
00157 }
00158 
00159 void SummaryHandlingProxyModel::sourceLayoutChanged()
00160 {
00161     d->clearCache();
00162     BASE::sourceLayoutChanged();
00163 }
00164 
00165 void SummaryHandlingProxyModel::sourceDataChanged( const QModelIndex& from, const QModelIndex& to )
00166 {
00167     QAbstractItemModel* model = sourceModel();
00168     QModelIndex parentIdx = from;
00169     do {
00170         const QModelIndex& dataIdx = parentIdx;
00171         if ( model->data( dataIdx, ItemTypeRole )==TypeSummary ) {
00172             //qDebug() << "removing " << parentIdx << "from cache";
00173             d->removeFromCache( dataIdx );
00174             QModelIndex proxyDataIdx = mapFromSource( dataIdx );
00175             emit dataChanged( proxyDataIdx, proxyDataIdx );
00176         }
00177     } while ( ( parentIdx=model->parent( parentIdx ) ) != QModelIndex() );
00178 
00179     BASE::sourceDataChanged( from, to );
00180 }
00181 
00182 void SummaryHandlingProxyModel::sourceColumnsAboutToBeInserted( const QModelIndex& parentIdx,
00183                                                                     int start,
00184                                                                     int end )
00185 {
00186     BASE::sourceColumnsAboutToBeInserted( parentIdx, start, end );
00187     d->clearCache();
00188 }
00189 
00190 void SummaryHandlingProxyModel::sourceColumnsAboutToBeRemoved( const QModelIndex& parentIdx,
00191                                                                     int start,
00192                                                                     int end )
00193 {
00194     BASE::sourceColumnsAboutToBeRemoved( parentIdx, start, end );
00195     d->clearCache();
00196 }
00197 
00198 void SummaryHandlingProxyModel::sourceRowsAboutToBeInserted( const QModelIndex & parentIdx, int start, int end )
00199 {
00200     BASE::sourceRowsAboutToBeInserted( parentIdx, start, end );
00201     d->clearCache();
00202 }
00203 
00204 void SummaryHandlingProxyModel::sourceRowsAboutToBeRemoved( const QModelIndex & parentIdx, int start, int end )
00205 {
00206     BASE::sourceRowsAboutToBeRemoved( parentIdx, start, end );
00207     d->clearCache();
00208 }
00209 
00211 Qt::ItemFlags SummaryHandlingProxyModel::flags( const QModelIndex& idx ) const
00212 {
00213     const QModelIndex sidx = mapToSource( idx );
00214     const QAbstractItemModel* model = sourceModel();
00215     Qt::ItemFlags f = model->flags( sidx );
00216     if ( d->isSummary(sidx) ) {
00217         f &= !Qt::ItemIsEditable;
00218     }
00219     return f;
00220 }
00221 
00223 QVariant SummaryHandlingProxyModel::data( const QModelIndex& proxyIndex, int role) const
00224 {
00225   //qDebug() << "SummaryHandlingProxyModel::data("<<proxyIndex<<role<<")";
00226     const QModelIndex sidx = mapToSource( proxyIndex );
00227     const QAbstractItemModel* model = sourceModel();
00228     if ( d->isSummary(sidx) && ( role==StartTimeRole || role==EndTimeRole )) {
00229       //qDebug() << "requested summary";
00230         QPair<QDateTime,QDateTime> result;
00231         if ( d->cacheLookup( sidx, &result ) ) {
00232       //qDebug() << "SummaryHandlingProxyModel::data(): Looking up summary for " << proxyIndex << role;
00233             switch( role ) {
00234             case StartTimeRole: return result.first;
00235             case EndTimeRole: return result.second;
00236             default: /* fall thru */;
00237             }
00238         } else {
00239             d->insertInCache( this, sidx );
00240             return data( proxyIndex, role ); /* TODO: Optimise */
00241         }
00242     }
00243     return model->data( sidx, role );
00244 }
00245 
00247 bool SummaryHandlingProxyModel::setData( const QModelIndex& index, const QVariant& value, int role )
00248 {
00249     QAbstractItemModel* model = sourceModel();
00250     if ( role==StartTimeRole || role==EndTimeRole ) {
00251         QModelIndex parentIdx = mapToSource( index );
00252         do {
00253             if ( d->isSummary(parentIdx) ) {
00254           //qDebug() << "removing " << parentIdx << "from cache";
00255                 d->removeFromCache( parentIdx );
00256                 QModelIndex proxyParentIdx = mapFromSource( parentIdx );
00257                 emit dataChanged( proxyParentIdx, proxyParentIdx );
00258             }
00259         } while ( ( parentIdx=model->parent( parentIdx ) ) != QModelIndex() );
00260     }
00261     return BASE::setData( index, value, role );
00262 }
00263 
00264 #undef d
00265 
00266 #ifndef KDAB_NO_UNIT_TESTS
00267 
00268 #include "unittest/test.h"
00269 
00270 #include <QStandardItemModel>
00271 
00272 namespace {
00273     std::ostream& operator<<( std::ostream& os, const QDateTime& dt )
00274     {
00275         os << dt.toString().toStdString();
00276         return os;
00277     }
00278 }
00279 
00280 KDAB_SCOPED_UNITTEST_SIMPLE( KDGantt, SummaryHandlingProxyModel, "test" ) {
00281     SummaryHandlingProxyModel model;
00282     QStandardItemModel sourceModel;
00283 
00284     model.setSourceModel( &sourceModel );
00285 
00286     QStandardItem* topitem = new QStandardItem( QString::fromLatin1( "Summary" ) );
00287     topitem->setData( KDGantt::TypeSummary,  KDGantt::ItemTypeRole );
00288     sourceModel.appendRow( topitem );
00289 
00290     QStandardItem* task1 = new QStandardItem( QString::fromLatin1( "Task1" ) );
00291     task1->setData( KDGantt::TypeTask, KDGantt::ItemTypeRole );
00292     QStandardItem* task2 = new QStandardItem( QString::fromLatin1( "Task2" ) );
00293     task2->setData( KDGantt::TypeTask, KDGantt::ItemTypeRole );
00294     topitem->appendRow( task1 );
00295     topitem->appendRow( task2 );
00296 
00297 
00298     QDateTime startdt = QDateTime::currentDateTime();
00299     QDateTime enddt = startdt.addDays( 1 );
00300 
00301 
00302     task1->setData( startdt, KDGantt::StartTimeRole );
00303     task1->setData( enddt, KDGantt::EndTimeRole );
00304     task2->setData( startdt, KDGantt::StartTimeRole );
00305     task2->setData( enddt, KDGantt::EndTimeRole );
00306 
00307     const QModelIndex topidx = model.index( 0, 0, QModelIndex() );
00308 
00309     assertEqual( model.data( topidx, KDGantt::ItemTypeRole ).toInt(), KDGantt::TypeSummary );
00310     assertEqual( model.data( model.index( 0, 0, topidx ), KDGantt::ItemTypeRole ).toInt(), KDGantt::TypeTask );
00311 
00312     QDateTime task1startdt = model.data( model.index( 0, 0, topidx ), KDGantt::StartTimeRole ).toDateTime();
00313     assertEqual( task1startdt, startdt );
00314 
00315     QDateTime summarystartdt = model.data( topidx, KDGantt::StartTimeRole ).toDateTime();
00316     assertEqual( summarystartdt, startdt );
00317     assertTrue( model.flags( model.index( 0, 0, topidx ) ) & Qt::ItemIsEditable );
00318     assertFalse( model.flags( topidx ) & Qt::ItemIsEditable );
00319 }
00320 
00321 #endif /* KDAB_NO_UNIT_TESTS */
00322 
00323 #include "moc_kdganttsummaryhandlingproxymodel.cpp"

kdgantt

Skip menu "kdgantt"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal