00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kptproject.h"
00022 #include "kptappointment.h"
00023 #include "kpttask.h"
00024 #include "kptdatetime.h"
00025 #include "kptpart.h"
00026 #include "kptconfig.h"
00027 #include "kpteffortcostmap.h"
00028 #include "kptschedule.h"
00029
00030 #include <qdom.h>
00031 #include <QString>
00032 #include <qdatetime.h>
00033 #include <qbrush.h>
00034 #include <q3canvas.h>
00035 #include <QList>
00036
00037 #include <kdatetimewidget.h>
00038 #include <kdebug.h>
00039
00040 namespace KPlato
00041 {
00042
00043
00044 Project::Project( Node *parent )
00045 : Node( parent ),
00046 m_accounts( *this )
00047 {
00048
00049 m_constraint = Node::MustStartOn;
00050 m_standardWorktime = new StandardWorktime();
00051 init();
00052 }
00053
00054 void Project::init()
00055 {
00056 if ( m_parent == 0 ) {
00057
00058 m_constraintStartTime = QDateTime( QDate::currentDate(), QTime() );
00059 m_constraintEndTime = m_constraintStartTime.addDays( 1 );
00060 }
00061 }
00062
00063
00064 Project::~Project()
00065 {
00066 delete m_standardWorktime;
00067 while ( !m_resourceGroups.isEmpty() )
00068 delete m_resourceGroups.takeFirst();
00069 while ( !m_calendars.isEmpty() )
00070 delete m_calendars.takeFirst();
00071 }
00072
00073 int Project::type() const { return Node::Type_Project; }
00074
00075 void Project::calculate( Schedule *schedule )
00076 {
00077 if ( schedule == 0 ) {
00078 kError() << k_funcinfo << "Schedule == 0, cannot calculate" << endl;
00079 return ;
00080 }
00081 m_currentSchedule = schedule;
00082 calculate();
00083 }
00084
00085 void Project::calculate( Effort::Use estType )
00086 {
00087 m_currentSchedule = findSchedule( ( Schedule::Type ) estType );
00088 if ( m_currentSchedule == 0 ) {
00089 m_currentSchedule = createSchedule( i18n( "Standard" ), ( Schedule::Type ) estType );
00090 }
00091 calculate();
00092 }
00093
00094 void Project::calculate()
00095 {
00096 if ( m_currentSchedule == 0 ) {
00097 kError() << k_funcinfo << "No current schedule to calculate" << endl;
00098 return ;
00099 }
00100 Effort::Use estType = ( Effort::Use ) m_currentSchedule->type();
00101 if ( type() == Type_Project ) {
00102 initiateCalculation( *m_currentSchedule );
00103 if ( m_constraint == Node::MustStartOn ) {
00104
00105 m_currentSchedule->startTime = m_constraintStartTime;
00106 m_currentSchedule->earliestStart = m_constraintStartTime;
00107
00108 propagateEarliestStart( m_currentSchedule->earliestStart );
00109 m_currentSchedule->latestFinish = calculateForward( estType );
00110 propagateLatestFinish( m_currentSchedule->latestFinish );
00111 calculateBackward( estType );
00112 m_currentSchedule->endTime = scheduleForward( m_currentSchedule->startTime, estType );
00113 calcCriticalPath( false );
00114 } else {
00115
00116 m_currentSchedule->endTime = m_constraintEndTime;
00117 m_currentSchedule->latestFinish = m_constraintEndTime;
00118
00119 propagateLatestFinish( m_currentSchedule->latestFinish );
00120 m_currentSchedule->earliestStart = calculateBackward( estType );
00121 propagateEarliestStart( m_currentSchedule->earliestStart );
00122 calculateForward( estType );
00123 m_currentSchedule->startTime = scheduleBackward( m_currentSchedule->endTime, estType );
00124 calcCriticalPath( true );
00125 }
00126 makeAppointments();
00127 calcResourceOverbooked();
00128 m_currentSchedule->notScheduled = false;
00129 } else if ( type() == Type_Subproject ) {
00130 kWarning() << k_funcinfo << "Subprojects not implemented" << endl;
00131 } else {
00132 kError() << k_funcinfo << "Illegal project type: " << type() << endl;
00133 }
00134 }
00135
00136 bool Project::calcCriticalPath( bool fromEnd )
00137 {
00138
00139 if ( fromEnd ) {
00140 QListIterator<Node*> startnodes = m_startNodes;
00141 while ( startnodes.hasNext() ) {
00142 startnodes.next() ->calcCriticalPath( fromEnd );
00143 }
00144 } else {
00145 QListIterator<Node*> endnodes = m_endNodes;
00146 while ( endnodes.hasNext() ) {
00147 endnodes.next() ->calcCriticalPath( fromEnd );
00148 }
00149 }
00150 return false;
00151 }
00152
00153 DateTime Project::startTime() const
00154 {
00155
00156 if ( m_currentSchedule )
00157 return m_currentSchedule->startTime;
00158
00159 return m_constraintStartTime;
00160 }
00161
00162 DateTime Project::endTime() const
00163 {
00164
00165 if ( m_currentSchedule )
00166 return m_currentSchedule->endTime;
00167
00168 return m_constraintEndTime;
00169 }
00170
00171 Duration *Project::getExpectedDuration()
00172 {
00173
00174 return new Duration( getLatestFinish() - getEarliestStart() );
00175 }
00176
00177 Duration *Project::getRandomDuration()
00178 {
00179 return 0L;
00180 }
00181
00182 DateTime Project::calculateForward( int use )
00183 {
00184
00185 if ( type() == Node::Type_Project ) {
00186
00187
00188 DateTime finish;
00189 DateTime time;
00190 QListIterator<Node*> endnodes = m_endNodes;
00191 while ( endnodes.hasNext() ) {
00192 time = endnodes.next() ->calculateForward( use );
00193 if ( !finish.isValid() || time > finish )
00194 finish = time;
00195 }
00196
00197 return finish;
00198 } else {
00199
00200 }
00201 return DateTime();
00202 }
00203
00204 DateTime Project::calculateBackward( int use )
00205 {
00206
00207 if ( type() == Node::Type_Project ) {
00208
00209
00210 DateTime start;
00211 DateTime time;
00212 QListIterator<Node*> startnodes = m_startNodes;
00213 while ( startnodes.hasNext() ) {
00214 time = startnodes.next() ->calculateBackward( use );
00215 if ( !start.isValid() || time < start )
00216 start = time;
00217 }
00218
00219 return start;
00220 } else {
00221
00222 }
00223 return DateTime();
00224 }
00225
00226 DateTime Project::scheduleForward( const DateTime &earliest, int use )
00227 {
00228 resetVisited();
00229 DateTime end = earliest;
00230 DateTime time;
00231 QListIterator<Node*> it( m_endNodes );
00232 while ( it.hasNext() ) {
00233 time = it.next() ->scheduleForward( earliest, use );
00234 if ( time > end )
00235 end = time;
00236 }
00237
00238 adjustSummarytask();
00239 return end;
00240 }
00241
00242 DateTime Project::scheduleBackward( const DateTime &latest, int use )
00243 {
00244 resetVisited();
00245 DateTime start = latest;
00246 DateTime time;
00247 QListIterator<Node*> it( m_startNodes );
00248 while ( it.hasNext() ) {
00249 time = it.next() ->scheduleBackward( latest, use );
00250 if ( time < start )
00251 start = time;
00252 }
00253
00254 adjustSummarytask();
00255 return start;
00256 }
00257
00258 void Project::adjustSummarytask()
00259 {
00260 QListIterator<Node*> it( m_summarytasks );
00261 while ( it.hasNext() ) {
00262 it.next() ->adjustSummarytask();
00263 }
00264 }
00265
00266 void Project::initiateCalculation( Schedule &sch )
00267 {
00268
00269
00270 m_visitedForward = false;
00271 m_visitedBackward = false;
00272 QListIterator<ResourceGroup*> git( m_resourceGroups );
00273 while ( git.hasNext() ) {
00274 git.next() ->initiateCalculation( sch );
00275 }
00276 Node::initiateCalculation( sch );
00277 m_startNodes.clear();
00278 m_endNodes.clear();
00279 m_summarytasks.clear();
00280 initiateCalculationLists( m_startNodes, m_endNodes, m_summarytasks );
00281 }
00282
00283 void Project::initiateCalculationLists( QList<Node*> &startnodes, QList<Node*> &endnodes, QList<Node*> &summarytasks )
00284 {
00285
00286 if ( type() == Node::Type_Project ) {
00287 QListIterator<Node*> it = childNodeIterator();
00288 while ( it.hasNext() ) {
00289 it.next() ->initiateCalculationLists( startnodes, endnodes, summarytasks );
00290 }
00291 } else {
00292
00293 }
00294 }
00295
00296 bool Project::load( QDomElement &element )
00297 {
00298
00299 QString s;
00300 bool ok = false;
00301 QString id = element.attribute( "id" );
00302 if ( !setId( id ) ) {
00303 kWarning() << k_funcinfo << "Id must be unique: " << id << endl;
00304 }
00305 m_name = element.attribute( "name" );
00306 m_leader = element.attribute( "leader" );
00307 m_description = element.attribute( "description" );
00308
00309
00310 s = element.attribute( "scheduling", "0" );
00311 m_constraint = ( Node::ConstraintType ) s.toInt( &ok );
00312 if ( !ok )
00313 setConstraint( s );
00314 if ( m_constraint != Node::MustStartOn &&
00315 m_constraint != Node::MustFinishOn ) {
00316 kError() << k_funcinfo << "Illegal constraint: " << constraintToString() << endl;
00317 setConstraint( Node::MustStartOn );
00318 }
00319 s = element.attribute( "start-time" );
00320 if ( !s.isEmpty() )
00321 m_constraintStartTime = DateTime::fromString( s );
00322 s = element.attribute( "end-time" );
00323 if ( !s.isEmpty() )
00324 m_constraintEndTime = DateTime::fromString( s );
00325
00326
00327
00328 QDomNodeList list = element.childNodes();
00329 for ( unsigned int i = 0; i < list.count(); ++i ) {
00330 if ( list.item( i ).isElement() ) {
00331 QDomElement e = list.item( i ).toElement();
00332 if ( e.tagName() == "calendar" ) {
00333
00334
00335 Calendar * child = new Calendar();
00336 child->setProject( this );
00337 if ( child->load( e ) ) {
00338 addCalendar( child );
00339 } else {
00340
00341 kError() << k_funcinfo << "Failed to load calendar" << endl;
00342 delete child;
00343 }
00344 } else if ( e.tagName() == "standard-worktime" ) {
00345
00346 StandardWorktime * child = new StandardWorktime();
00347 if ( child->load( e ) ) {
00348 setStandardWorktime( child );
00349 } else {
00350 kError() << k_funcinfo << "Failed to load standard worktime" << endl;
00351 delete child;
00352 }
00353 }
00354 }
00355 }
00356 for ( unsigned int i = 0; i < list.count(); ++i ) {
00357 if ( list.item( i ).isElement() ) {
00358 QDomElement e = list.item( i ).toElement();
00359
00360 if ( e.tagName() == "resource-group" ) {
00361
00362
00363 ResourceGroup * child = new ResourceGroup( this );
00364 if ( child->load( e ) ) {
00365 addResourceGroup( child );
00366 } else {
00367
00368 delete child;
00369 }
00370 }
00371 }
00372 }
00373 for ( unsigned int i = 0; i < list.count(); ++i ) {
00374 if ( list.item( i ).isElement() ) {
00375 QDomElement e = list.item( i ).toElement();
00376
00377 if ( e.tagName() == "project" ) {
00378
00379
00380 Project * child = new Project( this );
00381 if ( child->load( e ) ) {
00382 if ( !addTask( child, this ) ) {
00383 delete child;
00384 }
00385 } else {
00386
00387 delete child;
00388 }
00389 } else if ( e.tagName() == "task" ) {
00390
00391
00392
00393 Task * child = new Task( this );
00394 if ( child->load( e, *this ) ) {
00395 if ( !addTask( child, this ) ) {
00396 delete child;
00397 }
00398 } else {
00399
00400 delete child;
00401 }
00402 }
00403 }
00404 }
00405
00406 for ( unsigned int i = 0; i < list.count(); ++i ) {
00407 if ( list.item( i ).isElement() ) {
00408 QDomElement e = list.item( i ).toElement();
00409 if ( e.tagName() == "accounts" ) {
00410
00411
00412
00413 if ( !m_accounts.load( e, *this ) ) {
00414 kError() << k_funcinfo << "Failed to load accounts" << endl;
00415 }
00416 } else if ( e.tagName() == "relation" ) {
00417
00418
00419
00420 Relation * child = new Relation();
00421 if ( !child->load( e, *this ) ) {
00422
00423 kError() << k_funcinfo << "Failed to load relation" << endl;
00424 delete child;
00425 }
00426
00427 } else if ( e.tagName() == "schedules" ) {
00428
00429
00430
00431 QDomNodeList lst = e.childNodes();
00432 for ( unsigned int i = 0; i < lst.count(); ++i ) {
00433 if ( lst.item( i ).isElement() ) {
00434 QDomElement el = lst.item( i ).toElement();
00435 if ( el.tagName() == "schedule" ) {
00436 MainSchedule * sch = new MainSchedule();
00437 if ( sch->loadXML( el, *this ) ) {
00438 addSchedule( sch );
00439 sch->setNode( this );
00440 setParentSchedule( sch );
00441
00442 sch->setScheduled( true );
00443 } else {
00444 kError() << k_funcinfo << "Failed to load schedule" << endl;
00445 delete sch;
00446 }
00447 }
00448 }
00449 }
00450
00451 }
00452 }
00453 }
00454
00455
00456 QListIterator<Calendar*> calit( m_calendars );
00457 while ( calit.hasNext() ) {
00458 Calendar * c = calit.next();
00459 if ( c->id() == c->parentId() ) {
00460 kError() << k_funcinfo << "Calendar want itself as parent" << endl;
00461 continue;
00462 }
00463 c->setParent( calendar( c->parentId() ) );
00464 }
00465
00466 foreach ( Schedule * s, m_schedules ) {
00467 if ( m_constraint == Node::MustFinishOn )
00468 m_constraintEndTime = s->endTime;
00469 else
00470 m_constraintStartTime = s->startTime;
00471 }
00472
00473
00474 return true;
00475 }
00476
00477 void Project::save( QDomElement &element ) const
00478 {
00479 QDomElement me = element.ownerDocument().createElement( "project" );
00480 element.appendChild( me );
00481
00482 me.setAttribute( "name", m_name );
00483 me.setAttribute( "leader", m_leader );
00484 me.setAttribute( "id", m_id );
00485 me.setAttribute( "description", m_description );
00486
00487 me.setAttribute( "scheduling", constraintToString() );
00488 me.setAttribute( "start-time", m_constraintStartTime.toString( Qt::ISODate ) );
00489 me.setAttribute( "end-time", m_constraintEndTime.toString( Qt::ISODate ) );
00490
00491 m_accounts.save( me );
00492
00493
00494 QListIterator<Calendar*> calit( m_calendars );
00495 while ( calit.hasNext() ) {
00496 calit.next() ->save( me );
00497 }
00498
00499 if ( m_standardWorktime )
00500 m_standardWorktime->save( me );
00501
00502
00503 QListIterator<ResourceGroup*> git( m_resourceGroups );
00504 while ( git.hasNext() ) {
00505 git.next() ->save( me );
00506 }
00507
00508
00509 QListIterator<Relation*> it( m_dependParentNodes );
00510 while ( it.hasNext() ) {
00511 it.next() ->save( me );
00512 }
00513
00514 for ( int i = 0; i < numChildren(); i++ )
00515
00516 childNode( i ) ->save( me );
00517
00518
00519 QListIterator<Node*> nodes( m_nodes );
00520 while ( nodes.hasNext() ) {
00521 nodes.next() ->saveRelations( me );
00522 }
00523
00524 if ( !m_schedules.isEmpty() ) {
00525 QDomElement el = me.ownerDocument().createElement( "schedules" );
00526 me.appendChild( el );
00527 QHash<long, Schedule*> hash = m_schedules;
00528 foreach ( Schedule * s, hash ) {
00529 if ( !s->isDeleted() && s->isScheduled() ) {
00530 QDomElement schs = el.ownerDocument().createElement( "schedule" );
00531 el.appendChild( schs );
00532 s->saveXML( schs );
00533
00534 Node::saveAppointments( schs, s->id() );
00535 }
00536 }
00537 }
00538 }
00539
00540 void Project::setParentSchedule( Schedule *sch )
00541 {
00542 QListIterator<Node*> it = m_nodes;
00543 while ( it.hasNext() ) {
00544 it.next() ->setParentSchedule( sch );
00545 }
00546 }
00547
00548 void Project::addResourceGroup( ResourceGroup * group )
00549 {
00550 m_resourceGroups.append( group );
00551 }
00552
00553
00554 void Project::deleteResourceGroup( ResourceGroup *group )
00555 {
00556 int i = m_resourceGroups.indexOf( group );
00557 if ( i != -1 )
00558 m_resourceGroups.removeAt( i );
00559 delete group;
00560 }
00561
00562
00563 void Project::deleteResourceGroup( int )
00564 {
00565
00566 }
00567
00568
00569 void Project::insertResourceGroup( unsigned int ,
00570 ResourceGroup * )
00571 {}
00572
00573 QList<ResourceGroup*> &Project::resourceGroups()
00574 {
00575 return m_resourceGroups;
00576 }
00577
00578 bool Project::addTask( Node* task, Node* position )
00579 {
00580
00581
00582 if ( 0 == position ) {
00583 kError() << k_funcinfo << "position=0, could not add task: " << task->name() << endl;
00584 return false;
00585 }
00586
00587
00588
00589 if ( Node::Type_Project == position->type() ) {
00590 return addSubTask( task, position );
00591 }
00592
00593
00594 Node* parentNode = position->getParent();
00595 if ( !parentNode ) {
00596 kDebug() << k_funcinfo << "parent node not found???" << endl;
00597 return false;
00598 }
00599 int index = parentNode->findChildNode( position );
00600 if ( -1 == index ) {
00601
00602 kDebug() << k_funcinfo << "Task not found???" << endl;
00603 return false;
00604 }
00605 return addSubTask( task, index + 1, parentNode );
00606 }
00607
00608 bool Project::addSubTask( Node* task, Node* position )
00609 {
00610
00611
00612 if ( 0 == position ) {
00613 kError() << k_funcinfo << "No parent, can not add subtask: " << task->name() << endl;
00614 return false;
00615 }
00616 if ( !registerNodeId( task ) ) {
00617 kError() << k_funcinfo << "Failed to register node id, can not add subtask: " << task->name() << endl;
00618 return false;
00619 }
00620 emit nodeToBeAdded( position );
00621 position->addChildNode( task );
00622 emit nodeAdded( task );
00623 kDebug()<<k_funcinfo<<endl;
00624 return true;
00625 }
00626
00627 bool Project::addSubTask( Node* task, int index, Node* parent )
00628 {
00629
00630 if ( 0 == parent ) {
00631 kError() << k_funcinfo << "No parent, can not add subtask: " << task->name() << endl;
00632 return false;
00633 }
00634 if ( !registerNodeId( task ) ) {
00635 kError() << k_funcinfo << "Failed to register node id, can not add subtask: " << task->name() << endl;
00636 return false;
00637 }
00638 emit nodeToBeAdded( parent );
00639 parent->insertChildNode( index, task );
00640 emit nodeAdded( task );
00641 return true;
00642 }
00643
00644 void Project::delTask( Node *node )
00645 {
00646 Node * parent = node->getParent();
00647 if ( parent == 0 ) {
00648 kDebug() << k_funcinfo << "Node must have a parent!" << endl;
00649 return ;
00650 }
00651 removeId( node->id() );
00652 emit nodeToBeRemoved( parent );
00653 parent->takeChildNode( node );
00654 emit nodeRemoved( node );
00655 }
00656
00657
00658 bool Project::canIndentTask( Node* node )
00659 {
00660 if ( 0 == node ) {
00661
00662
00663 return false;
00664 }
00665 if ( node->type() == Node::Type_Project ) {
00666
00667 return false;
00668 }
00669
00670 Node* parentNode = node->getParent();
00671 if ( !parentNode ) {
00672 return false;
00673 }
00674 if ( parentNode->findChildNode( node ) == -1 ) {
00675 kError() << k_funcinfo << "Tasknot found???" << endl;
00676 return false;
00677 }
00678 Node *sib = node->siblingBefore();
00679 if ( !sib ) {
00680
00681 return false;
00682 }
00683 if ( node->findParentRelation( sib ) || node->findChildRelation( sib ) ) {
00684
00685 return false;
00686 }
00687 return true;
00688 }
00689
00690 bool Project::indentTask( Node* node, int index )
00691 {
00692 if ( canIndentTask( node ) ) {
00693 Node * newParent = node->siblingBefore();
00694 emit nodeToBeMoved( node );
00695 node->getParent() ->takeChildNode( node );
00696 newParent->insertChildNode( index, node );
00697 emit nodeMoved( node );
00698 kDebug()<<k_funcinfo<<endl;
00699 return true;
00700 }
00701 return false;
00702 }
00703
00704 bool Project::canUnindentTask( Node* node )
00705 {
00706 if ( 0 == node ) {
00707
00708
00709 return false;
00710 }
00711 if ( Node::Type_Project == node->type() ) {
00712
00713 return false;
00714 }
00715
00716
00717 Node* parentNode = node->getParent();
00718 if ( !parentNode ) {
00719 return false;
00720 }
00721 Node* grandParentNode = parentNode->getParent();
00722 if ( !grandParentNode ) {
00723
00724 return false;
00725 }
00726 int index = parentNode->findChildNode( node );
00727 if ( -1 == index ) {
00728 kError() << k_funcinfo << "Tasknot found???" << endl;
00729 return false;
00730 }
00731 return true;
00732 }
00733
00734 bool Project::unindentTask( Node* node )
00735 {
00736 if ( canUnindentTask( node ) ) {
00737 Node * parentNode = node->getParent();
00738 emit nodeToBeMoved( node );
00739 Node *grandParentNode = parentNode->getParent();
00740 parentNode->takeChildNode( node );
00741 grandParentNode->addChildNode( node, parentNode );
00742 emit nodeMoved( node );
00743 kDebug()<<k_funcinfo<<endl;
00744 return true;
00745 }
00746 return false;
00747 }
00748
00749 bool Project::canMoveTaskUp( Node* node )
00750 {
00751 if ( node == 0 )
00752 return false;
00753
00754 Node* parentNode = node->getParent();
00755 if ( !parentNode ) {
00756
00757 return false;
00758 }
00759 if ( parentNode->findChildNode( node ) == -1 ) {
00760 kError() << k_funcinfo << "Tasknot found???" << endl;
00761 return false;
00762 }
00763 if ( node->siblingBefore() ) {
00764 return true;
00765 }
00766 return false;
00767 }
00768
00769 bool Project::moveTaskUp( Node* node )
00770 {
00771 if ( canMoveTaskUp( node ) ) {
00772 emit nodeToBeMoved( node );
00773 if ( node->getParent()->moveChildUp( node ) ) {
00774 emit nodeMoved( node );
00775 kDebug()<<k_funcinfo<<endl;
00776 return true;
00777 }
00778 emit nodeMoved( node );
00779 }
00780 return false;
00781 }
00782
00783 bool Project::canMoveTaskDown( Node* node )
00784 {
00785 if ( node == 0 )
00786 return false;
00787
00788 Node* parentNode = node->getParent();
00789 if ( !parentNode ) {
00790 return false;
00791 }
00792 if ( parentNode->findChildNode( node ) == -1 ) {
00793 kError() << k_funcinfo << "Tasknot found???" << endl;
00794 return false;
00795 }
00796 if ( node->siblingAfter() ) {
00797 return true;
00798 }
00799 return false;
00800 }
00801
00802 bool Project::moveTaskDown( Node* node )
00803 {
00804 if ( canMoveTaskDown( node ) ) {
00805 emit nodeToBeMoved( node );
00806 if ( node->getParent() ->moveChildDown( node ) ) {
00807 emit nodeMoved( node );
00808 return true;
00809 }
00810 emit nodeMoved( node );
00811 }
00812 return false;
00813 }
00814
00815 Task *Project::createTask( Node* parent )
00816 {
00817 Task * node = new Task( parent );
00818 node->setId( uniqueNodeId() );
00819 return node;
00820 }
00821
00822 Task *Project::createTask( Task &def, Node* parent )
00823 {
00824 Task * node = new Task( def, parent );
00825 node->setId( uniqueNodeId() );
00826 return node;
00827 }
00828
00829 QString Project::uniqueNodeId( int seed )
00830 {
00831 int i = seed;
00832 while ( findNode( QString( "%1" ).arg( i ) ) ) {
00833 ++i;
00834 }
00835 return QString( "%1" ).arg( i );
00836 }
00837
00838 bool Project::removeId( const QString &id )
00839 {
00840 kDebug() << k_funcinfo << "id=" << id << endl;
00841 return ( m_parent ? m_parent->removeId( id ) : nodeIdDict.remove( id ) );
00842 }
00843
00844 void Project::insertId( const QString &id, Node *node )
00845 {
00846 kDebug() << k_funcinfo << "id=" << id << " " << node->name() << endl;
00847 if ( m_parent == 0 )
00848 return ( void ) nodeIdDict.insert( id, node );
00849 m_parent->insertId( id, node );
00850 }
00851
00852 bool Project::registerNodeId( Node *node )
00853 {
00854 if ( node->id().isEmpty() ) {
00855 kError() << k_funcinfo << "Id is empty." << endl;
00856 return false;
00857 }
00858 Node *rn = findNode( node->id() );
00859 if ( rn == 0 ) {
00860 insertId( node->id(), node );
00861 return true;
00862 }
00863 if ( rn != node ) {
00864 kError() << k_funcinfo << "Id already exists for different task: " << node->id() << endl;
00865 return false;
00866 }
00867 return true;
00868 }
00869
00870
00871 ResourceGroup *Project::group( QString id )
00872 {
00873 return findResourceGroup( id );
00874 }
00875
00876 Resource *Project::resource( QString id )
00877 {
00878 return findResource( id );
00879 }
00880
00881
00882 EffortCostMap Project::plannedEffortCostPrDay( const QDate & , const QDate & ) const
00883 {
00884
00885 EffortCostMap ec;
00886 return ec;
00887
00888 }
00889
00890
00891 Duration Project::plannedEffort()
00892 {
00893
00894 Duration eff;
00895 QListIterator<Node*> it( childNodeIterator() );
00896 while ( it.hasNext() ) {
00897 eff += it.next() ->plannedEffort();
00898 }
00899 return eff;
00900 }
00901
00902
00903 Duration Project::plannedEffort( const QDate &date )
00904 {
00905
00906 Duration eff;
00907 QListIterator<Node*> it( childNodeIterator() );
00908 while ( it.hasNext() ) {
00909 eff += it.next() ->plannedEffort( date );
00910 }
00911 return eff;
00912 }
00913
00914
00915 Duration Project::plannedEffortTo( const QDate &date )
00916 {
00917
00918 Duration eff;
00919 QListIterator<Node*> it( childNodeIterator() );
00920 while ( it.hasNext() ) {
00921 eff += it.next() ->plannedEffortTo( date );
00922 }
00923 return eff;
00924 }
00925
00926
00927 Duration Project::actualEffort()
00928 {
00929
00930 Duration eff;
00931 QListIterator<Node*> it( childNodeIterator() );
00932 while ( it.hasNext() ) {
00933 eff += it.next() ->actualEffort();
00934 }
00935 return eff;
00936 }
00937
00938
00939 Duration Project::actualEffort( const QDate &date )
00940 {
00941
00942 Duration eff;
00943 QListIterator<Node*> it( childNodeIterator() );
00944 while ( it.hasNext() ) {
00945 eff += it.next() ->actualEffort( date );
00946 }
00947 return eff;
00948 }
00949
00950
00951 Duration Project::actualEffortTo( const QDate &date )
00952 {
00953
00954 Duration eff;
00955 QListIterator
00956 <Node*> it( childNodeIterator() );
00957 while ( it.hasNext() ) {
00958 eff += it.next() ->actualEffortTo( date );
00959 }
00960 return eff;
00961 }
00962
00963 double Project::plannedCost()
00964 {
00965
00966 double c = 0;
00967 QListIterator
00968 <Node*> it( childNodeIterator() );
00969 while ( it.hasNext() ) {
00970 c += it.next() ->plannedCost();
00971 }
00972 return c;
00973 }
00974
00975
00976 double Project::plannedCost( const QDate &date )
00977 {
00978
00979 double c = 0;
00980 QListIterator
00981 <Node*> it( childNodeIterator() );
00982 while ( it.hasNext() ) {
00983 c += it.next() ->plannedCost( date );
00984 }
00985 return c;
00986 }
00987
00988
00989 double Project::plannedCostTo( const QDate &date )
00990 {
00991
00992 double c = 0;
00993 QListIterator
00994 <Node*> it( childNodeIterator() );
00995 while ( it.hasNext() ) {
00996 c += it.next() ->plannedCostTo( date );
00997 }
00998 return c;
00999 }
01000
01001 double Project::actualCost()
01002 {
01003
01004 double c = 0;
01005 QListIterator
01006 <Node*> it( childNodeIterator() );
01007 while ( it.hasNext() ) {
01008 c += it.next() ->actualCost();
01009 }
01010 return c;
01011 }
01012
01013
01014 double Project::actualCost( const QDate &date )
01015 {
01016
01017 double c = 0;
01018 QListIterator
01019 <Node*> it( childNodeIterator() );
01020 while ( it.hasNext() ) {
01021 c += it.next() ->actualCost( date );
01022 }
01023 return c;
01024 }
01025
01026
01027 double Project::actualCostTo( const QDate &date )
01028 {
01029
01030 double c = 0;
01031 QListIterator
01032 <Node*> it( childNodeIterator() );
01033 while ( it.hasNext() ) {
01034 c += it.next() ->actualCostTo( date );
01035 }
01036 return c;
01037 }
01038
01039 void Project::addCalendar( Calendar *calendar )
01040 {
01041
01042 m_calendars.append( calendar );
01043 }
01044
01045 Calendar *Project::calendar( const QString id ) const
01046 {
01047 return findCalendar( id );
01048 }
01049
01050 QList<Calendar*> Project::calendars()
01051 {
01052 QList<Calendar*> list;
01053 QListIterator<Calendar*> it = m_calendars;
01054 while ( it.hasNext() ) {
01055 Calendar * c = it.next();
01056 if ( !c->isDeleted() ) {
01057 list.append( c );
01058 }
01059 }
01060 return list;
01061 }
01062
01063 void Project::setStandardWorktime( StandardWorktime * worktime )
01064 {
01065 if ( m_standardWorktime != worktime ) {
01066 delete m_standardWorktime;
01067 m_standardWorktime = worktime;
01068 }
01069 }
01070
01071 bool Project::legalToLink( Node *par, Node *child )
01072 {
01073
01074
01075 if ( !child || par->isDependChildOf( child ) ) {
01076 return false;
01077 }
01078 bool legal = true;
01079
01080 if ( par->isParentOf( child ) || child->isParentOf( par ) ) {
01081 legal = false;
01082 }
01083 if ( legal )
01084 legal = legalChildren( par, child );
01085 if ( legal )
01086 legal = legalParents( par, child );
01087
01088 return legal;
01089 }
01090
01091 bool Project::legalParents( Node *par, Node *child )
01092 {
01093 bool legal = true;
01094
01095 for ( int i = 0; i < par->numDependParentNodes() && legal; ++i ) {
01096 Node *pNode = par->getDependParentNode( i ) ->parent();
01097 if ( child->isParentOf( pNode ) || pNode->isParentOf( child ) ) {
01098
01099 legal = false;
01100 } else {
01101 legal = legalChildren( pNode, child );
01102 }
01103 if ( legal )
01104 legal = legalParents( pNode, child );
01105 }
01106 return legal;
01107 }
01108
01109 bool Project::legalChildren( Node *par, Node *child )
01110 {
01111 bool legal = true;
01112
01113 for ( int j = 0; j < child->numDependChildNodes() && legal; ++j ) {
01114 Node *cNode = child->getDependChildNode( j ) ->child();
01115 if ( par->isParentOf( cNode ) || cNode->isParentOf( par ) ) {
01116
01117 legal = false;
01118 } else {
01119 legal = legalChildren( par, cNode );
01120 }
01121 }
01122 return legal;
01123 }
01124
01125 void Project::generateWBS( int count, WBSDefinition &def, QString wbs )
01126 {
01127 if ( type() == Type_Subproject || def.level0Enabled() ) {
01128 Node::generateWBS( count, def, wbs );
01129 } else {
01130 QListIterator<Node*> it = m_nodes;
01131 int i = 0;
01132 while ( it.hasNext() ) {
01133 it.next() ->generateWBS( ++i, def, m_wbs );
01134 }
01135 }
01136 }
01137
01138 void Project::setCurrentSchedule( long id )
01139 {
01140 setCurrentSchedulePtr( findSchedule( id ) );
01141 Node::setCurrentSchedule( id );
01142 QHash<QString, Resource*> hash = resourceIdDict;
01143 foreach ( Resource * r, hash ) {
01144 r->setCurrentSchedule( id );
01145 }
01146 }
01147
01148 MainSchedule *Project::createSchedule( QString name, Schedule::Type type )
01149 {
01150
01151 long i = 1;
01152 while ( m_schedules.contains( i ) ) {
01153 ++i;
01154 }
01155 MainSchedule *sch = new MainSchedule( this, name, type, i );
01156 addSchedule( sch );
01157 return sch;
01158 }
01159
01160 bool Project::removeCalendarId( const QString &id )
01161 {
01162 kDebug() << k_funcinfo << "id=" << id << endl;
01163 return calendarIdDict.remove( id );
01164 }
01165
01166 void Project::insertCalendarId( const QString &id, Calendar *calendar )
01167 {
01168 kDebug() << k_funcinfo << "id=" << id << ": " << calendar->name() << endl;
01169 calendarIdDict.insert( id, calendar );
01170 }
01171
01172 void Project::changed( Node *node )
01173 {
01174 if ( m_parent == 0 ) {
01175 emit nodeChanged( node );
01176 return;
01177 }
01178 Node::changed( node );
01179 }
01180
01181 #ifndef NDEBUG
01182 void Project::printDebug( bool children, QByteArray indent )
01183 {
01184
01185 kDebug() << indent << "+ Project node: " << Node::name() << endl;
01186 indent += "!";
01187 QListIterator<ResourceGroup*> it( resourceGroups() );
01188 while ( it.hasNext() )
01189 it.next() ->printDebug( indent );
01190
01191 Node::printDebug( children, indent );
01192 }
01193 void Project::printCalendarDebug( QByteArray indent )
01194 {
01195 kDebug() << indent << "-------- Calendars debug printout --------" << endl;
01196 QListIterator
01197 <Calendar*> it = m_calendars;
01198 while ( it.hasNext() ) {
01199 it.next() ->printDebug( indent + "--" );
01200 kDebug() << endl;
01201 }
01202 if ( m_standardWorktime )
01203 m_standardWorktime->printDebug();
01204 }
01205 #endif
01206
01207 }
01208
01209 #include "kptproject.moc"