kdganttconstraintmodel.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
00020 **
00021 **********************************************************************/
00022 
00023 #include "kdganttconstraintmodel.h"
00024 #include "kdganttconstraintmodel_p.h"
00025 
00026 #include <QDebug>
00027 
00028 #include <cassert>
00029 
00030 using namespace KDGantt;
00031 
00040 ConstraintModel::Private::Private()
00041 {
00042 }
00043 
00044 void ConstraintModel::Private::addConstraintToIndex( const QModelIndex& idx, const Constraint& c )
00045 {
00046     IndexType::iterator it = indexMap.find(idx);
00047     while (it != indexMap.end() && it.key() == idx) {
00048         // Check if we already have this
00049         if ( *it == c ) return;
00050         ++it;
00051     }
00052 
00053     indexMap.insert( idx, c );
00054 }
00055 
00056 void ConstraintModel::Private::removeConstraintFromIndex( const QModelIndex& idx,  const Constraint& c )
00057 {
00058     IndexType::iterator it = indexMap.find(idx);
00059     while (it != indexMap.end() && it.key() == idx) {
00060         if ( *it == c ) {
00061             it =indexMap.erase( it );
00062         } else {
00063             ++it;
00064         }
00065     }
00066 }
00067 
00070 ConstraintModel::ConstraintModel( QObject* parent )
00071     : QObject( parent ), _d( new Private )
00072 {
00073     init();
00074 }
00075 
00077 ConstraintModel::ConstraintModel( Private* d_ptr, QObject* parent )
00078     : QObject( parent ), _d( d_ptr )
00079 {
00080     init();
00081 }
00082 
00084 ConstraintModel::~ConstraintModel()
00085 {
00086     delete _d;
00087 }
00088 
00089 #define d d_func()
00090 
00091 void ConstraintModel::init()
00092 {
00093 }
00094 
00099 void ConstraintModel::addConstraint( const Constraint& c )
00100 {
00101     //int size = d->constraints.size();
00102     bool hasConstraint = d->constraints.contains( c );
00103     //d->constraints.insert( c );
00104     //if ( size != d->constraints.size() ) {
00105     if ( !hasConstraint ) {
00106         d->constraints.push_back( c );
00107         d->addConstraintToIndex( c.startIndex(), c );
00108         d->addConstraintToIndex( c.endIndex(), c );
00109         emit constraintAdded( c );
00110     }
00111 }
00112 
00120 bool ConstraintModel::removeConstraint( const Constraint& c )
00121 {
00122     //qDebug() << "ConstraintModel::removeConstraint("<<c<<") from "<< d->constraints;
00123     bool rc = d->constraints.removeAll( c );
00124     //bool rc = d->constraints.remove( c );
00125     if ( rc ) {
00126         d->removeConstraintFromIndex( c.startIndex(), c );
00127         d->removeConstraintFromIndex( c.endIndex(), c );
00128         emit constraintRemoved( c );
00129     }
00130     return rc;
00131 }
00132 
00137 void ConstraintModel::clear()
00138 {
00139     QList<Constraint> lst = constraints();
00140     Q_FOREACH( const Constraint& c, lst ) {
00141         removeConstraint( c );
00142     }
00143 }
00144 
00146 void ConstraintModel::cleanup()
00147 {
00148 #if 0
00149     QSet<Constraint> orphans;
00150     Q_FOREACH( const Constraint& c, d->constraints ) {
00151         if ( !c.startIndex().isValid() || !c.endIndex().isValid() ) orphans.insert( c );
00152     }
00153     //qDebug() << "Constraint::cleanup() found" << orphans << "orphans";
00154     d->constraints.subtract( orphans );
00155 #endif
00156 }
00157 
00161 QList<Constraint> ConstraintModel::constraints() const
00162 {
00163     //return d->constraints.toList();
00164     return d->constraints;
00165 }
00166 
00170 QList<Constraint> ConstraintModel::constraintsForIndex( const QModelIndex& idx ) const
00171 {
00172     // TODO: @Steffen: Please comment on this assert, it's long and not obvious (Johannes)
00173     assert( !idx.isValid() || d->indexMap.isEmpty() || !d->indexMap.keys().front().model() || idx.model() == d->indexMap.keys().front().model() );
00174     if ( !idx.isValid() ) {
00175         // Because of a Qt bug we need to treat this as a special case
00176         QSet<Constraint> result;
00177         Q_FOREACH( Constraint c, d->constraints ) {
00178             if ( !c.startIndex().isValid() || !c.endIndex().isValid() ) result.insert( c );
00179         }
00180         return result.toList();
00181     } else {
00182         QList<Constraint> result;
00183         Q_FOREACH( Constraint c, d->constraints ) {
00184             if ( c.startIndex() == idx || c.endIndex() == idx ) result.push_back( c );
00185         }
00186         return result;
00187     }
00188 
00189     //return d->indexMap.values( idx );
00190 }
00191 
00195 bool ConstraintModel::hasConstraint( const Constraint& c ) const
00196 {
00197     /*
00198     // Because of a Qt bug we have to search like this
00199     Q_FOREACH( Constraint c2, d->constraints ) {
00200         if ( c==c2 ) return true;
00201     }
00202     return false;
00203     */
00204     return d->constraints.contains( c );
00205 }
00206 
00207 #ifndef QT_NO_DEBUG_STREAM
00208 
00209 QDebug operator<<( QDebug dbg, const KDGantt::ConstraintModel& model )
00210 {
00211     dbg << "KDGantt::ConstraintModel[ " << static_cast<const QObject*>( &model ) << ":"
00212         << model.constraints() << "]";
00213     return dbg;
00214 }
00215 
00216 #endif /* QT_NO_DEBUG_STREAM */
00217 
00218 #undef d
00219 
00220 #ifndef KDAB_NO_UNIT_TESTS
00221 
00222 #include <QStandardItemModel>
00223 
00224 #include "unittest/test.h"
00225 
00226 std::ostream& operator<<( std::ostream& os, const QModelIndex& idx )
00227 {
00228     QString str;
00229     QDebug( &str )<<idx;
00230 #ifdef QT_NO_STL
00231     os<<str.toLatin1().constData();
00232 #else
00233     os<<str.toStdString();
00234 #endif
00235     return os;
00236 }
00237 
00238 KDAB_SCOPED_UNITTEST_SIMPLE( KDGantt, ConstraintModel, "test" )
00239 {
00240     QStandardItemModel dummyModel( 100, 100 );
00241     ConstraintModel model;
00242 
00243     QModelIndex invalidIndex;
00244     assertEqual( invalidIndex, invalidIndex );
00245 
00246     assertEqual( model.constraints().count(), 0 );
00247 
00248     model.addConstraint( Constraint( QModelIndex(), QModelIndex() ) );
00249     assertEqual( model.constraints().count(), 1 );
00250 
00251     model.addConstraint( Constraint( QModelIndex(), QModelIndex() ) );
00252     assertEqual( model.constraints().count(), 1 );
00253 
00254     QPersistentModelIndex idx1 = dummyModel.index( 7, 17, QModelIndex() );
00255     QPersistentModelIndex idx2 = dummyModel.index( 42, 17, QModelIndex() );
00256 
00257     model.addConstraint( Constraint( idx1, idx2 ) );
00258     assertEqual( model.constraints().count(), 2 );
00259     assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
00260 
00261     assertEqual( model.constraintsForIndex( QModelIndex() ).count(), 1 );
00262 
00263     assertEqual( model.constraints().count(), 2 );
00264     model.removeConstraint( Constraint( QModelIndex(), QModelIndex() ) );
00265     assertEqual( model.constraints().count(), 1 );
00266     assertFalse( model.hasConstraint( Constraint( QModelIndex(), QModelIndex() ) ) );
00267 
00268     model.removeConstraint( Constraint( QModelIndex(), QModelIndex() ) );
00269     assertEqual( model.constraints().count(), 1 );
00270 
00271     model.removeConstraint( Constraint( idx1, idx2 ) );
00272     assertEqual( model.constraints().count(), 0 );
00273     assertFalse( model.hasConstraint( Constraint( idx1, idx2 ) ) );
00274 
00275     model.addConstraint( Constraint( idx1, idx2 ) );
00276     assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
00277     dummyModel.removeRow( 8 );
00278     assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
00279     dummyModel.removeRow( 7 );
00280     assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
00281 }
00282 
00283 #endif /* KDAB_NO_UNIT_TESTS */
00284 
00285 #include "moc_kdganttconstraintmodel.cpp"