1
/****************************************************************************
2
** Copyright (C) 2001-2006 Klarälvdalens Datakonsult AB. All rights reserved.
4
** This file is part of the KD Gantt library.
6
** This file may be used under the terms of the GNU General Public
7
** License versions 2.0 or 3.0 as published by the Free Software
8
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
9
** included in the packaging of this file. Alternatively you may (at
10
** your option) use any later version of the GNU General Public
11
** License if such license has been publicly approved by
12
** Klarälvdalens Datakonsult AB (or its successors, if any).
14
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
15
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
16
** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
17
** not expressly granted herein.
19
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
**********************************************************************/
23
#include "kdganttconstraintmodel.h"
24
#include "kdganttconstraintmodel_p.h"
30
using namespace KDGantt;
32
/*!\class KDGantt::ConstraintModel
34
* The ConstraintModel keeps track of the
35
* interdependencies between gantt items in
40
ConstraintModel::Private::Private()
44
void ConstraintModel::Private::addConstraintToIndex( const QModelIndex& idx, const Constraint& c )
46
IndexType::iterator it = indexMap.find(idx);
47
while (it != indexMap.end() && it.key() == idx) {
48
// Check if we already have this
49
if ( *it == c ) return;
53
indexMap.insert( idx, c );
56
void ConstraintModel::Private::removeConstraintFromIndex( const QModelIndex& idx, const Constraint& c )
58
IndexType::iterator it = indexMap.find(idx);
59
while (it != indexMap.end() && it.key() == idx) {
61
it =indexMap.erase( it );
68
/*! Constructor. Creates an empty ConstraintModel with parent \a parent
70
ConstraintModel::ConstraintModel( QObject* parent )
71
: QObject( parent ), _d( new Private )
77
ConstraintModel::ConstraintModel( Private* d_ptr, QObject* parent )
78
: QObject( parent ), _d( d_ptr )
83
/*! Destroys this ConstraintModel */
84
ConstraintModel::~ConstraintModel()
91
void ConstraintModel::init()
95
/*! Adds the constraint \a c to this ConstraintModel
96
* If the Constraint \a c is already in this ConstraintModel,
99
void ConstraintModel::addConstraint( const Constraint& c )
101
//int size = d->constraints.size();
102
bool hasConstraint = d->constraints.contains( c );
103
//d->constraints.insert( c );
104
//if ( size != d->constraints.size() ) {
105
if ( !hasConstraint ) {
106
d->constraints.push_back( c );
107
d->addConstraintToIndex( c.startIndex(), c );
108
d->addConstraintToIndex( c.endIndex(), c );
109
emit constraintAdded( c );
113
/*! Removes the Constraint \a c from this
114
* ConstraintModel. If \a c was found and removed,
115
* the signal constraintRemoved(const Constraint&) is emitted.
117
* \returns If \a c was found and removed, it returns true,
118
* otherwise it returns false.
120
bool ConstraintModel::removeConstraint( const Constraint& c )
122
//qDebug() << "ConstraintModel::removeConstraint("<<c<<") from "<< d->constraints;
123
bool rc = d->constraints.removeAll( c );
124
//bool rc = d->constraints.remove( c );
126
d->removeConstraintFromIndex( c.startIndex(), c );
127
d->removeConstraintFromIndex( c.endIndex(), c );
128
emit constraintRemoved( c );
133
/*! Removes all Constraints from this model
134
* The signal constraintRemoved(const Constraint&) is emitted
135
* for every Constraint that is removed.
137
void ConstraintModel::clear()
139
QList<Constraint> lst = constraints();
140
Q_FOREACH( const Constraint& c, lst ) {
141
removeConstraint( c );
146
void ConstraintModel::cleanup()
149
QSet<Constraint> orphans;
150
Q_FOREACH( const Constraint& c, d->constraints ) {
151
if ( !c.startIndex().isValid() || !c.endIndex().isValid() ) orphans.insert( c );
153
//qDebug() << "Constraint::cleanup() found" << orphans << "orphans";
154
d->constraints.subtract( orphans );
158
/*! \returns A list of all Constraints in this
161
QList<Constraint> ConstraintModel::constraints() const
163
//return d->constraints.toList();
164
return d->constraints;
167
/*! \returns A list of all Constraints in this ConstraintModel
168
* that have an endpoint at \a idx.
170
QList<Constraint> ConstraintModel::constraintsForIndex( const QModelIndex& idx ) const
172
assert( idx.isValid() || !d->indexMap.isEmpty() || d->indexMap.keys().front().model() || idx.model() == d->indexMap.keys().front().model() );
173
if ( !idx.isValid() ) { //Why the assert idx.isValid() above? (dag)
174
// Because of a Qt bug we need to treat this as a special case
175
QSet<Constraint> result;
176
Q_FOREACH( Constraint c, d->constraints ) {
177
if ( !c.startIndex().isValid() || !c.endIndex().isValid() ) result.insert( c );
179
return result.toList();
181
QList<Constraint> result;
182
Q_FOREACH( Constraint c, d->constraints ) {
183
if ( c.startIndex() == idx || c.endIndex() == idx ) result.push_back( c );
188
//return d->indexMap.values( idx );
191
/*! Returns true if a Constraint with start \a s and end \a e
192
* exists, otherwise false.
194
bool ConstraintModel::hasConstraint( const Constraint& c ) const
197
// Because of a Qt bug we have to search like this
198
Q_FOREACH( Constraint c2, d->constraints ) {
199
if ( c==c2 ) return true;
203
return d->constraints.contains( c );
206
#ifndef QT_NO_DEBUG_STREAM
208
QDebug operator<<( QDebug dbg, const KDGantt::ConstraintModel& model )
210
dbg << "KDGantt::ConstraintModel[ " << static_cast<const QObject*>( &model ) << ":"
211
<< model.constraints() << "]";
215
#endif /* QT_NO_DEBUG_STREAM */
219
#ifndef KDAB_NO_UNIT_TESTS
221
#include <QStandardItemModel>
223
#include "unittest/test.h"
225
std::ostream& operator<<( std::ostream& os, const QModelIndex& idx )
229
os<<str.toStdString();
233
KDAB_SCOPED_UNITTEST_SIMPLE( KDGantt, ConstraintModel, "test" )
235
QStandardItemModel dummyModel( 100, 100 );
236
ConstraintModel model;
238
QModelIndex invalidIndex;
239
assertEqual( invalidIndex, invalidIndex );
241
assertEqual( model.constraints().count(), 0 );
243
model.addConstraint( Constraint( QModelIndex(), QModelIndex() ) );
244
assertEqual( model.constraints().count(), 1 );
246
model.addConstraint( Constraint( QModelIndex(), QModelIndex() ) );
247
assertEqual( model.constraints().count(), 1 );
249
QPersistentModelIndex idx1 = dummyModel.index( 7, 17, QModelIndex() );
250
QPersistentModelIndex idx2 = dummyModel.index( 42, 17, QModelIndex() );
252
model.addConstraint( Constraint( idx1, idx2 ) );
253
assertEqual( model.constraints().count(), 2 );
254
assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
256
assertEqual( model.constraintsForIndex( QModelIndex() ).count(), 1 );
258
assertEqual( model.constraints().count(), 2 );
259
model.removeConstraint( Constraint( QModelIndex(), QModelIndex() ) );
260
assertEqual( model.constraints().count(), 1 );
261
assertFalse( model.hasConstraint( Constraint( QModelIndex(), QModelIndex() ) ) );
263
model.removeConstraint( Constraint( QModelIndex(), QModelIndex() ) );
264
assertEqual( model.constraints().count(), 1 );
266
model.removeConstraint( Constraint( idx1, idx2 ) );
267
assertEqual( model.constraints().count(), 0 );
268
assertFalse( model.hasConstraint( Constraint( idx1, idx2 ) ) );
270
model.addConstraint( Constraint( idx1, idx2 ) );
271
assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
272
dummyModel.removeRow( 8 );
273
assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
274
dummyModel.removeRow( 7 );
275
assertTrue( model.hasConstraint( Constraint( idx1, idx2 ) ) );
278
#endif /* KDAB_NO_UNIT_TESTS */
280
#include "moc_kdganttconstraintmodel.cpp"