kplato

kptnode.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Thomas zander <zander@kde.org>
00003    Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 #include "kptnode.h"
00021 
00022 #include "kptappointment.h"
00023 #include "kptaccount.h"
00024 #include "kptwbsdefinition.h"
00025 #include "kptresource.h"
00026 #include "kptschedule.h"
00027 
00028 #include <qptrlist.h>
00029 #include <qdom.h>
00030 
00031 #include <klocale.h>
00032 #include <kdebug.h>
00033 
00034 namespace KPlato
00035 {
00036 
00037 Node::Node(Node *parent) : m_nodes(), m_dependChildNodes(), m_dependParentNodes() {
00038     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00039     m_parent = parent;
00040     init();
00041     m_id = QString(); // Not mapped
00042 }
00043 
00044 Node::Node(Node &node, Node *parent) 
00045     : m_nodes(), 
00046       m_dependChildNodes(), 
00047       m_dependParentNodes() {
00048     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00049     m_parent = parent;
00050     init();
00051     m_name = node.name();
00052     m_leader = node.leader();
00053     m_description = node.description();
00054     m_constraint = (ConstraintType) node.constraint();
00055     m_constraintStartTime = node.constraintStartTime();
00056     m_constraintEndTime = node.constraintEndTime();
00057     
00058     m_dateOnlyStartDate = node.startDate();
00059     m_dateOnlyEndDate = node.endDate();
00060     
00061     m_runningAccount = node.runningAccount();
00062     m_startupAccount = node.startupAccount();
00063     m_shutdownAccount = node.shutdownAccount();
00064 
00065     m_startupCost = node.startupCost();
00066     m_shutdownCost = node.shutdownCost();
00067     
00068     m_schedules.setAutoDelete(node.m_schedules.autoDelete());
00069 }
00070 
00071 Node::~Node() {
00072     if (findNode() == this) {
00073         removeId(); // only remove myself (I may be just a working copy)
00074     }
00075     Relation *rel = 0;
00076     while ((rel = m_dependParentNodes.getFirst())) {
00077         delete rel;
00078     }
00079     while ((rel = m_dependChildNodes.getFirst())) {
00080         delete rel;
00081     }
00082     if (m_runningAccount)
00083         m_runningAccount->removeRunning(*this);
00084     if (m_startupAccount)
00085         m_startupAccount->removeStartup(*this);
00086     if (m_shutdownAccount)
00087         m_shutdownAccount->removeShutdown(*this);
00088 }
00089 
00090 void Node::init() {
00091     m_currentSchedule = 0;
00092     m_nodes.setAutoDelete(true);
00093     m_name="";
00094     m_constraint = Node::ASAP;
00095     m_effort = 0;
00096     m_visitedForward = false;
00097     m_visitedBackward = false;
00098     
00099     m_dateOnlyStartDate = m_dateOnlyEndDate = QDate::currentDate();
00100     m_dateOnlyDuration.addDays(1);
00101     
00102     m_runningAccount = 0;
00103     m_startupAccount = 0;
00104     m_shutdownAccount = 0;
00105     m_startupCost = 0.0;
00106     m_shutdownCost = 0.0;
00107 }
00108 
00109 Node *Node::projectNode() {
00110     if ((type() == Type_Project) || (type() == Type_Subproject)) {
00111         return this;
00112     }
00113     if (m_parent)
00114         return m_parent->projectNode();
00115 
00116     kdError()<<k_funcinfo<<"Ooops, no parent and no project found"<<endl;
00117     return 0;
00118 }
00119 
00120 //HACK
00121 void Node::delChildNode_NoId( Node *node, bool remove) {
00122     //kdDebug()<<k_funcinfo<<"find="<<m_nodes.findRef(node)<<endl;
00123     if ( m_nodes.findRef(node) != -1 ) {
00124         if(remove)
00125             m_nodes.remove();
00126         else
00127             m_nodes.take();
00128     }
00129 }
00130 
00131 void Node::delChildNode( Node *node, bool remove) {
00132     //kdDebug()<<k_funcinfo<<"find="<<m_nodes.findRef(node)<<endl;
00133     if ( m_nodes.findRef(node) != -1 ) {
00134         removeId(node->id());
00135         if(remove)
00136             m_nodes.remove();
00137         else
00138             m_nodes.take();
00139     }
00140 }
00141 
00142 //HACK
00143 void Node::delChildNode_NoId( int number, bool remove) {
00144     if(remove)
00145         m_nodes.remove(number);
00146     else
00147         m_nodes.take(number);
00148 }
00149 
00150 void Node::delChildNode( int number, bool remove) {
00151     Node *n = m_nodes.at(number);
00152     if (n)
00153         removeId(n->id());
00154     if(remove)
00155         m_nodes.remove(number);
00156     else
00157         m_nodes.take(number);
00158 }
00159 
00160 //HACK
00161 void Node::insertChildNode_NoId( unsigned int index, Node *node) {
00162     m_nodes.insert(index,node);
00163     node->setParent(this);
00164 }
00165 
00166 void Node::insertChildNode( unsigned int index, Node *node) {
00167     node->setParent(this);
00168     if (!node->setId(node->id())) {
00169         kdError()<<k_funcinfo<<node->name()<<" Not unique id: "<<m_id<<endl;
00170     }
00171     m_nodes.insert(index,node);
00172 }
00173 
00174 void Node::addChildNode( Node *node, Node *after) {
00175     int index = m_nodes.findRef(after);
00176     node->setParent(this);
00177     if (!node->setId(node->id())) {
00178          kdError()<<k_funcinfo<<node->name()<<" Not unique id: "<<m_id<<endl;
00179     }
00180     if (index == -1) {
00181         m_nodes.append(node);
00182         
00183         return;
00184     }
00185     m_nodes.insert(index+1, node);
00186 }
00187 
00188 //HACK
00189 void Node::addChildNode_NoId( Node *node, Node *after) {
00190     int index = m_nodes.findRef(after);
00191     if (index == -1) {
00192         m_nodes.append(node);
00193         node->setParent(this);
00194         return;
00195     }
00196     m_nodes.insert(index+1, node);
00197     node->setParent(this);
00198 }
00199 
00200 int Node::findChildNode( Node* node )
00201 {
00202     return m_nodes.findRef( node );
00203 }
00204 
00205 
00206 const Node* Node::getChildNode(int number) const {
00207     // Work around missing const at() method in QPtrList
00208     const QPtrList<Node> &nodes = m_nodes;
00209     return (const_cast<QPtrList<Node> &>(nodes)).at(number);
00210 }
00211 
00212 Duration *Node::getDelay() {
00213     /* TODO
00214        Calculate the delay of this node. Use the calculated startTime and the setted startTime.
00215     */
00216     return 0L;
00217 }
00218 
00219 void Node::addDependChildNode( Node *node, Relation::Type p) {
00220     addDependChildNode(node,p,Duration());
00221 }
00222 
00223 void Node::addDependChildNode( Node *node, Relation::Type p, Duration lag) {
00224     Relation *relation = new Relation(this, node, p, lag);
00225     if (node->addDependParentNode(relation))
00226         m_dependChildNodes.append(relation);
00227     else
00228         delete relation;
00229 }
00230 
00231 void Node::insertDependChildNode( unsigned int index, Node *node, Relation::Type p) {
00232     Relation *relation = new Relation(this, node, p, Duration());
00233     if (node->addDependParentNode(relation))
00234         m_dependChildNodes.insert(index, relation);
00235     else
00236         delete relation;
00237 }
00238 
00239 bool Node::addDependChildNode( Relation *relation) {
00240     if(m_dependChildNodes.findRef(relation) != -1)
00241         return false;
00242     m_dependChildNodes.append(relation);
00243     return true;
00244 }
00245 
00246 // These delDepend... methods look suspicious to me, can someone review?
00247 void Node::delDependChildNode( Node *node, bool remove) {
00248     if ( m_nodes.findRef(node) != -1 ) {
00249         if(remove)
00250             m_dependChildNodes.remove();
00251         else
00252             m_dependChildNodes.take();
00253     }
00254 }
00255 
00256 void Node::delDependChildNode( Relation *rel, bool remove) {
00257     if ( m_dependChildNodes.findRef(rel) != -1 ) {
00258         if(remove)
00259             m_dependChildNodes.remove();
00260         else
00261             m_dependChildNodes.take();
00262     }
00263 }
00264 
00265 void Node::delDependChildNode( int number, bool remove) {
00266     if(remove)
00267         m_dependChildNodes.remove(number);
00268     else
00269         m_dependChildNodes.take(number);
00270 }
00271 
00272 void Node::takeDependChildNode(Relation *rel) {
00273     if (m_dependChildNodes.findRef(rel) != -1) {
00274         m_dependChildNodes.take();
00275     }
00276 }
00277 
00278 void Node::addDependParentNode( Node *node, Relation::Type p) {
00279     addDependParentNode(node,p,Duration());
00280 }
00281 
00282 void Node::addDependParentNode( Node *node, Relation::Type p, Duration lag) {
00283     Relation *relation = new Relation(node, this, p, lag);
00284     if (node->addDependChildNode(relation))
00285         m_dependParentNodes.append(relation);
00286     else
00287         delete relation;
00288 }
00289 
00290 void Node::insertDependParentNode( unsigned int index, Node *node, Relation::Type p) {
00291     Relation *relation = new Relation(this, node, p, Duration());
00292     if (node->addDependChildNode(relation))
00293         m_dependParentNodes.insert(index,relation);
00294     else
00295         delete relation;
00296 }
00297 
00298 bool Node::addDependParentNode( Relation *relation) {
00299     if(m_dependParentNodes.findRef(relation) != -1)
00300         return false;
00301     m_dependParentNodes.append(relation);
00302     return true;
00303 }
00304 
00305 // These delDepend... methods look suspicious to me, can someone review?
00306 void Node::delDependParentNode( Node *node, bool remove) {
00307     if ( m_nodes.findRef(node) != -1 ) {
00308         if(remove)
00309             m_dependParentNodes.remove();
00310         else
00311             m_dependParentNodes.take();
00312     }
00313 }
00314 
00315 void Node::delDependParentNode( Relation *rel, bool remove) {
00316     if ( m_dependParentNodes.findRef(rel) != -1 ) {
00317         if(remove)
00318             m_dependParentNodes.remove();
00319         else
00320             m_dependParentNodes.take();
00321     }
00322 }
00323 
00324 void Node::delDependParentNode( int number, bool remove) {
00325     if(remove)
00326         m_dependParentNodes.remove(number);
00327     else
00328         m_dependParentNodes.take(number);
00329 }
00330 
00331 void Node::takeDependParentNode(Relation *rel) {
00332     if (m_dependParentNodes.findRef(rel) != -1) {
00333         rel = m_dependParentNodes.take();
00334     }      
00335 }
00336 
00337 bool Node::isParentOf(Node *node) {
00338     if (m_nodes.findRef(node) != -1)
00339         return true;
00340 
00341     QPtrListIterator<Node> nit(childNodeIterator());
00342     for ( ; nit.current(); ++nit ) {
00343         if (nit.current()->isParentOf(node))
00344             return true;
00345     }
00346     return false;
00347 }
00348 
00349 Relation *Node::findParentRelation(Node *node) {
00350     for (int i=0; i<numDependParentNodes(); i++) {
00351         Relation *rel = getDependParentNode(i);
00352         if (rel->parent() == node)
00353             return rel;
00354     }
00355     return (Relation *)0;
00356 }
00357 
00358 Relation *Node::findChildRelation(Node *node) {
00359     for (int i=0; i<numDependChildNodes(); i++) {
00360         Relation *rel = getDependChildNode(i);
00361         if (rel->child() == node)
00362             return rel;
00363     }
00364     return (Relation *)0;
00365 }
00366 
00367 Relation *Node::findRelation(Node *node) {
00368     Relation *rel = findParentRelation(node);
00369     if (!rel)
00370         rel = findChildRelation(node);
00371     return rel;
00372 }
00373 
00374 bool Node::isDependChildOf(Node *node) {
00375     //kdDebug()<<k_funcinfo<<" '"<<m_name<<"' checking against '"<<node->name()<<"'"<<endl;
00376     for (int i=0; i<numDependParentNodes(); i++) {
00377         Relation *rel = getDependParentNode(i);
00378         if (rel->parent() == node)
00379             return true;
00380         if (rel->parent()->isDependChildOf(node))
00381             return true;
00382     }
00383     return false;
00384 }
00385 
00386 Duration Node::duration(const DateTime &time, int use, bool backward) {
00387     //kdDebug()<<k_funcinfo<<endl;
00388     // TODO: handle risc
00389     if (!time.isValid()) {
00390         kdError()<<k_funcinfo<<"Time is invalid"<<endl;
00391         return Duration::zeroDuration;
00392     }
00393     if (m_effort == 0) {
00394         kdError()<<k_funcinfo<<"m_effort == 0"<<endl;
00395         return Duration::zeroDuration;
00396     }
00397     if (m_currentSchedule == 0) {
00398         return Duration::zeroDuration;
00399         kdError()<<k_funcinfo<<"No current schedule"<<endl;
00400     }
00401     return calcDuration(time, m_effort->effort(use), backward);
00402 }
00403 
00404 void Node::makeAppointments() {
00405     QPtrListIterator<Node> nit(m_nodes);
00406     for ( ; nit.current(); ++nit ) {
00407         nit.current()->makeAppointments();
00408     }
00409 }
00410 
00411 void Node::calcResourceOverbooked() {
00412     QPtrListIterator<Node> nit(m_nodes);
00413     for ( ; nit.current(); ++nit ) {
00414         nit.current()->calcResourceOverbooked();
00415     }
00416 }
00417 
00418 void Node::saveRelations(QDomElement &element) const {
00419     QPtrListIterator<Relation> it(m_dependChildNodes);
00420     for (; it.current(); ++it) {
00421         it.current()->save(element);
00422     }
00423     QPtrListIterator<Node> nodes(m_nodes);
00424     for ( ; nodes.current(); ++nodes ) {
00425         nodes.current()->saveRelations(element);
00426     }
00427 }
00428 
00429 void Node::setConstraint(QString &type) {
00430     // Do not i18n these, they are used in load()
00431     if (type == "ASAP")
00432         setConstraint(ASAP);
00433     else if (type == "ALAP")
00434         setConstraint(ALAP);
00435     else if (type == "StartNotEarlier")
00436         setConstraint(StartNotEarlier);
00437     else if (type == "FinishNotLater")
00438         setConstraint(FinishNotLater);
00439     else if (type == "MustStartOn")
00440         setConstraint(MustStartOn);
00441     else if (type == "MustFinishOn")
00442         setConstraint(MustFinishOn);
00443     else if (type == "FixedInterval")
00444         setConstraint(FixedInterval);
00445     else
00446         setConstraint(ASAP);  // default
00447 }
00448 
00449 QString Node::constraintToString() const {
00450     // Do not i18n these, they are used in save()
00451     if (m_constraint == ASAP)
00452         return QString("ASAP");
00453     else if (m_constraint == ALAP)
00454         return QString("ALAP");
00455     else if (m_constraint == StartNotEarlier)
00456         return QString("StartNotEarlier");
00457     else if (m_constraint == FinishNotLater)
00458         return QString("FinishNotLater");
00459     else if (m_constraint == MustStartOn)
00460         return QString("MustStartOn");
00461     else if (m_constraint == MustFinishOn)
00462         return QString("MustFinishOn");
00463     else if (m_constraint == FixedInterval)
00464         return QString("FixedInterval");
00465 
00466     return QString();
00467 }
00468 
00469 void Node::propagateEarliestStart(DateTime &time) {
00470     if (m_currentSchedule == 0)
00471         return;
00472     m_currentSchedule->earliestStart = time;
00473     //kdDebug()<<k_funcinfo<<m_name<<": "<<m_currentSchedule->earliestStart.toString()<<endl;
00474     QPtrListIterator<Node> it = m_nodes;
00475     for (; it.current(); ++it) {
00476         it.current()->propagateEarliestStart(time);
00477     }
00478 }
00479 
00480 void Node::propagateLatestFinish(DateTime &time) {
00481     if (m_currentSchedule == 0)
00482         return;
00483     m_currentSchedule->latestFinish = time;
00484     //kdDebug()<<k_funcinfo<<m_name<<": "<<m_currentSchedule->latestFinish<<endl;
00485     QPtrListIterator<Node> it = m_nodes;
00486     for (; it.current(); ++it) {
00487         it.current()->propagateLatestFinish(time);
00488     }
00489 }
00490 
00491 void Node::moveEarliestStart(DateTime &time) {
00492     if (m_currentSchedule == 0)
00493         return;
00494     if (m_currentSchedule->earliestStart < time)
00495         m_currentSchedule->earliestStart = time;
00496     QPtrListIterator<Node> it = m_nodes;
00497     for (; it.current(); ++it) {
00498         it.current()->moveEarliestStart(time);
00499     }
00500 }
00501 
00502 void Node::moveLatestFinish(DateTime &time) {
00503     if (m_currentSchedule == 0)
00504         return;
00505     if (m_currentSchedule->latestFinish > time)
00506         m_currentSchedule->latestFinish = time;
00507     QPtrListIterator<Node> it = m_nodes;
00508     for (; it.current(); ++it) {
00509         it.current()->moveLatestFinish(time);
00510     }
00511 }
00512 
00513 void Node::initiateCalculation(Schedule &sch) {
00514     QPtrListIterator<Node> it = m_nodes;
00515     for (; it.current(); ++it) {
00516         it.current()->initiateCalculation(sch);
00517     }
00518 }
00519 
00520 void Node::resetVisited() {
00521     m_visitedForward = false;
00522     m_visitedBackward = false;
00523     QPtrListIterator<Node> it = m_nodes;
00524     for (; it.current(); ++it) {
00525         it.current()->resetVisited();
00526     }
00527 }
00528 
00529 Node *Node::siblingBefore() {
00530     //kdDebug()<<k_funcinfo<<endl;
00531     if (getParent())
00532         return getParent()->childBefore(this);
00533     return 0;
00534 }
00535 
00536 Node *Node::childBefore(Node *node) {
00537     //kdDebug()<<k_funcinfo<<endl;
00538     int index = m_nodes.findRef(node);
00539     if (index > 0){
00540         return m_nodes.at(index-1);
00541     }
00542     return 0;
00543 }
00544 
00545 Node *Node::siblingAfter() {
00546     //kdDebug()<<k_funcinfo<<endl;
00547     if (getParent())
00548         return getParent()->childAfter(this);
00549     return 0;
00550 }
00551 
00552 Node *Node::childAfter(Node *node)
00553 {
00554     //kdDebug()<<k_funcinfo<<endl;
00555     uint index = m_nodes.findRef(node);
00556     if (index < m_nodes.count()-1) {
00557         return m_nodes.at(index+1);    }
00558     return 0;
00559 }
00560 
00561 bool Node::moveChildUp(Node* node)
00562 {
00563     if (findChildNode(node) == -1)
00564         return false; // not my node!
00565     Node *sib = node->siblingBefore();
00566     if (!sib)
00567         return false;
00568     sib = sib->siblingBefore();
00569     delChildNode(node, false);
00570     if (sib) {
00571         addChildNode(node, sib);
00572     } else {
00573         insertChildNode(0, node);
00574     }        
00575     return true;
00576 }
00577 
00578 bool Node::moveChildDown(Node* node)
00579 {
00580     if (findChildNode(node) == -1)
00581         return false; // not my node!
00582     Node *sib = node->siblingAfter();
00583     if (!sib)
00584         return false;
00585     delChildNode(node, false);
00586     addChildNode(node, sib);
00587     return true;
00588 }
00589 
00590 bool Node::legalToLink(Node *node) {
00591     Node *p = projectNode();
00592     if (p)
00593         return p->legalToLink(this, node);
00594     return false;
00595 }
00596 
00597 bool Node::isEndNode() const {
00598     return m_dependChildNodes.isEmpty();
00599 }
00600 bool Node::isStartNode() const {
00601     return m_dependParentNodes.isEmpty();
00602 }
00603 
00604 bool Node::setId(QString id) {
00605     //kdDebug()<<k_funcinfo<<id<<endl;
00606     if (id.isEmpty()) {
00607         kdError()<<k_funcinfo<<"id is empty"<<endl;
00608         m_id = id;
00609         return false;
00610     }
00611     if (!m_id.isEmpty()) {
00612         Node *n = findNode();
00613         if (n == this) {
00614             //kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
00615             removeId();
00616         } else if (n) {
00617             //Hmmm, shouldn't happen
00618             kdError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different node: "<<n->name()<<endl;
00619         }
00620     }
00621     if (findNode(id)) {
00622         kdError()<<k_funcinfo<<"id '"<<id<<"' is already used for different node: "<<findNode(id)->name()<<endl;
00623         m_id = QString(); // hmmm
00624         return false;
00625     }
00626     m_id = id;
00627     insertId(id);
00628     //kdDebug()<<k_funcinfo<<m_name<<": inserted id="<<id<<endl;
00629     return true;
00630 }
00631 
00632 void Node::setStartTime(DateTime startTime) { 
00633     if (m_currentSchedule)
00634         m_currentSchedule->startTime = startTime;
00635     m_dateOnlyStartDate = startTime.date();
00636 }
00637 
00638 void Node::setEndTime(DateTime endTime) { 
00639     if (m_currentSchedule)
00640         m_currentSchedule->endTime = endTime;
00641     
00642     m_dateOnlyEndDate = endTime.date();
00643     if (endTime.time().isNull() && m_dateOnlyEndDate > m_dateOnlyStartDate)
00644         m_dateOnlyEndDate = m_dateOnlyEndDate.addDays(-1);
00645 }
00646 
00647 void Node::saveAppointments(QDomElement &element, long id) const {
00648     //kdDebug()<<k_funcinfo<<m_name<<" id="<<id<<endl;
00649     QPtrListIterator<Node> it(m_nodes);
00650     for (; it.current(); ++it ) {
00651         it.current()->saveAppointments(element, id);
00652     }
00653 }
00654 
00655 QPtrList<Appointment> Node::appointments() {
00656     QPtrList<Appointment> lst;
00657     if (m_currentSchedule)
00658         lst = m_currentSchedule->appointments();
00659     return lst;
00660 }
00661 
00662 // Appointment *Node::findAppointment(Resource *resource) {
00663 //     if (m_currentSchedule)
00664 //         return m_currentSchedule->findAppointment(resource);
00665 //     return 0;
00666 // }
00667 bool Node::addAppointment(Appointment *appointment) {
00668     if (m_currentSchedule)
00669         return m_currentSchedule->add(appointment);
00670     return false;
00671 }
00672 
00673 bool Node::addAppointment(Appointment *appointment, Schedule &main) {
00674     //kdDebug()<<k_funcinfo<<this<<endl;
00675     Schedule *s = findSchedule(main.id());
00676     if (s == 0) {
00677         s = createSchedule(&main);
00678     }
00679     appointment->setNode(s);
00680     return s->add(appointment);
00681 }
00682 
00683 void Node::addAppointment(ResourceSchedule *resource, DateTime &start, DateTime &end, double load) {
00684     Schedule *node = findSchedule(resource->id());
00685     if (node == 0) {
00686         node = createSchedule(resource->parent());
00687     }
00688     node->addAppointment(resource, start, end, load);
00689 }
00690 
00691 void Node::takeSchedule(const Schedule *schedule) {
00692     if (schedule == 0)
00693         return;
00694     if (m_currentSchedule == schedule)
00695         m_currentSchedule = 0;
00696     m_schedules.take(schedule->id());
00697 }
00698 
00699 void Node::addSchedule(Schedule *schedule) {
00700     if (schedule == 0)
00701         return;
00702     m_schedules.replace(schedule->id(), schedule);
00703 }
00704 
00705 Schedule *Node::createSchedule(QString name, Schedule::Type type, long id) {
00706     //kdDebug()<<k_funcinfo<<name<<" type="<<type<<" id="<<(int)id<<endl;
00707     NodeSchedule *sch = new NodeSchedule(this, name, type, id);
00708     addSchedule(sch);
00709     return sch;
00710 }
00711 
00712 Schedule *Node::createSchedule(Schedule *parent) {
00713     //kdDebug()<<k_funcinfo<<name<<" type="<<type<<" id="<<(int)id<<endl;
00714     NodeSchedule *sch = new NodeSchedule(parent, this);
00715     addSchedule(sch);
00716     return sch;
00717 }
00718 
00719 Schedule *Node::findSchedule(const QString name, const Schedule::Type type) const {
00720     QIntDictIterator<Schedule> it = m_schedules;
00721     for (; it.current(); ++it) {
00722         if (!it.current()->isDeleted() && 
00723             it.current()->name() == name && it.current()->type() == type)
00724             return it.current();
00725     }
00726     return 0;
00727 }
00728 
00729 Schedule *Node::findSchedule(const Schedule::Type type) const {
00730     //kdDebug()<<k_funcinfo<<m_name<<" find type="<<type<<" nr="<<m_schedules.count()<<endl;
00731     QIntDictIterator<Schedule> it = m_schedules;
00732     for (; it.current(); ++it) {
00733         if (!it.current()->isDeleted() && it.current()->type() == type) {
00734             return it.current();
00735         }
00736     }
00737     return 0;
00738 }
00739 
00740 void Node::setScheduleDeleted(long id, bool on) {
00741     Schedule *ns = findSchedule(id);
00742     if (ns == 0) {
00743         kdError()<<k_funcinfo<<m_name<<" Could not find schedule with id="<<id<<endl;
00744     } else {
00745         ns->setDeleted(on);
00746     }
00747 }
00748 
00749 void Node::setParentSchedule(Schedule *sch) {
00750     Schedule *s = findSchedule(sch->id());
00751     if (s) {
00752         s->setParent(sch);
00753     }
00754     QPtrListIterator<Node> it = m_nodes;
00755     for (; it.current(); ++it) {
00756         it.current()->setParentSchedule(sch);
00757     }
00758 }
00759 
00760 bool Node::calcCriticalPath(bool fromEnd) {
00761     if (m_currentSchedule == 0)
00762         return false;
00763     //kdDebug()<<k_funcinfo<<m_name<<endl;
00764     if (!isCritical()) {
00765         return false;
00766     }
00767     if (!fromEnd && isStartNode()) {
00768         m_currentSchedule->inCriticalPath = true;
00769         return true;
00770     }
00771     if (fromEnd && isEndNode()) {
00772         m_currentSchedule->inCriticalPath = true;
00773         return true;
00774     }
00775     QPtrListIterator<Relation> pit(m_dependParentNodes);
00776     for (; pit.current(); ++pit) {
00777         if (pit.current()->parent()->calcCriticalPath(fromEnd)) {
00778             m_currentSchedule->inCriticalPath = true;
00779         }
00780     }
00781     return m_currentSchedule->inCriticalPath;
00782 }
00783 
00784 int Node::level() {
00785     Node *n = getParent();
00786     return n ? n->level() + 1 : 0;
00787 }
00788 
00789 void Node::generateWBS(int count, WBSDefinition &def, QString wbs) {
00790     m_wbs = wbs + def.code(count, level());
00791     //kdDebug()<<k_funcinfo<<m_name<<" wbs: "<<m_wbs<<endl;
00792     QString w = wbs + def.wbs(count, level());
00793     QPtrListIterator<Node> it = m_nodes;
00794     for (int i=0; it.current(); ++it) {
00795         it.current()->generateWBS(++i, def, w);
00796     }
00797 
00798 }
00799 
00800 void Node::setCurrentSchedule(long id) {
00801     QPtrListIterator<Node> it = m_nodes;
00802     for (; it.current(); ++it) {
00803         it.current()->setCurrentSchedule(id);
00804     }
00805     //kdDebug()<<k_funcinfo<<m_name<<" id: "<<id<<"="<<m_currentSchedule<<endl;
00806 }
00808 
00809 Effort::Effort( Duration e, Duration p, Duration o) {
00810   m_expectedEffort = e;
00811   m_pessimisticEffort = p;
00812   m_optimisticEffort = o;
00813   m_type = Type_Effort;
00814 }
00815 
00816 Effort::Effort(const Effort &effort) {
00817     set(effort.expected(), effort.pessimistic(), effort.optimistic());
00818     setType(effort.type());
00819 }
00820 
00821 Effort::~Effort() {
00822 }
00823 
00824 const Effort Effort::zeroEffort( Duration::zeroDuration,
00825                        Duration::zeroDuration,
00826                        Duration::zeroDuration );
00827 
00828 void Effort::set( Duration e, Duration p, Duration o ) {
00829     m_expectedEffort = e;
00830     m_pessimisticEffort = (p == Duration::zeroDuration) ? e :  p;
00831     m_optimisticEffort = (o == Duration::zeroDuration) ? e :  o;
00832     //kdDebug()<<k_funcinfo<<"   Expected: "<<m_expectedEffort.toString()<<endl;
00833 }
00834 
00835 void Effort::set( int e, int p, int o ) {
00836     m_expectedEffort = Duration(e);
00837     m_pessimisticEffort = (p < 0) ? Duration(e) :  Duration(p);
00838     m_optimisticEffort = (o < 0) ? Duration(e) :  Duration(o);
00839     //kdDebug()<<k_funcinfo<<"   Expected: "<<m_expectedEffort.toString()<<endl;
00840     //kdDebug()<<k_funcinfo<<"   Optimistic: "<<m_optimisticEffort.toString()<<endl;
00841     //kdDebug()<<k_funcinfo<<"   Pessimistic: "<<m_pessimisticEffort.toString()<<endl;
00842 
00843     //kdDebug()<<k_funcinfo<<"   Expected: "<<m_expectedEffort.duration()<<" manseconds"<<endl;
00844 }
00845 
00846 //TODO (?): effort is not really a duration, should maybe not use Duration for storage
00847 void Effort::set(unsigned days, unsigned hours, unsigned minutes) {
00848     Duration dur(days, hours, minutes);
00849     set(dur);
00850     //kdDebug()<<k_funcinfo<<"effort="<<dur.toString()<<endl;
00851 }
00852 
00853 void Effort::expectedEffort(unsigned *days, unsigned *hours, unsigned *minutes) {
00854     m_expectedEffort.get(days, hours, minutes);
00855 }
00856 
00857 bool Effort::load(QDomElement &element) {
00858     m_expectedEffort = Duration::fromString(element.attribute("expected"));
00859     m_optimisticEffort = Duration::fromString(element.attribute("optimistic"));
00860     m_pessimisticEffort = Duration::fromString(element.attribute("pessimistic"));
00861     setType(element.attribute("type", "WorkBased"));
00862     return true;
00863 }
00864 
00865 void Effort::save(QDomElement &element) const {
00866     QDomElement me = element.ownerDocument().createElement("effort");
00867     element.appendChild(me);
00868     me.setAttribute("expected", m_expectedEffort.toString());
00869     me.setAttribute("optimistic", m_optimisticEffort.toString());
00870     me.setAttribute("pessimistic", m_pessimisticEffort.toString());
00871     me.setAttribute("type", typeToString());
00872 }
00873 
00874 QString Effort::typeToString() const {
00875     if (m_type == Type_Effort)
00876         return QString("Effort");
00877     if (m_type == Type_FixedDuration)
00878         return QString("Type_FixedDuration");
00879 
00880     return QString();
00881 }
00882 
00883 void Effort::setType(QString type) {
00884     if (type == "Effort")
00885         setType(Type_Effort);
00886     else if (type == "Type_FixedDuration")
00887         setType(Type_FixedDuration);
00888     else
00889         setType(Type_Effort); // default
00890 }
00891 
00892 void Effort::setOptimisticRatio(int percent)
00893 {
00894     int p = percent>0 ? -percent : percent;
00895     m_optimisticEffort = m_expectedEffort*(100+p)/100;
00896 }
00897 
00898 int Effort::optimisticRatio() const {
00899     if (m_expectedEffort == Duration::zeroDuration)
00900         return 0;
00901     return (m_optimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds())-100;
00902 }
00903 
00904 void Effort::setPessimisticRatio(int percent) 
00905 {
00906     int p = percent<0 ? -percent : percent;
00907     m_pessimisticEffort = m_expectedEffort*(100+p)/100;
00908 }
00909 int Effort::pessimisticRatio() const {
00910     if (m_expectedEffort == Duration::zeroDuration)
00911         return 0;
00912     return m_pessimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds()-100;
00913 }
00914 
00915 // Debugging
00916 #ifndef NDEBUG
00917 void Node::printDebug(bool children, QCString indent) {
00918     kdDebug()<<indent<<"  Unique node identity="<<m_id<<endl;
00919     if (m_effort) m_effort->printDebug(indent);
00920     QString s = "  Constraint: " + constraintToString();
00921     if (m_constraint == MustStartOn || m_constraint == StartNotEarlier || m_constraint == FixedInterval)
00922         kdDebug()<<indent<<s<<" ("<<constraintStartTime().toString()<<")"<<endl;
00923     if (m_constraint == MustFinishOn || m_constraint == FinishNotLater || m_constraint == FixedInterval)
00924         kdDebug()<<indent<<s<<" ("<<constraintEndTime().toString()<<")"<<endl;
00925     Schedule *cs = m_currentSchedule; 
00926     if (cs) {
00927         kdDebug()<<indent<<"  Current schedule: "<<"id="<<cs->id()<<" '"<<cs->name()<<"' type: "<<cs->type()<<endl;
00928     } else {
00929         kdDebug()<<indent<<"  Current schedule: None"<<endl;
00930     }
00931     QIntDictIterator<Schedule> it = m_schedules;
00932     for (; it.current(); ++it) {
00933         it.current()->printDebug(indent+"  ");
00934     }
00935     kdDebug()<<indent<<"  Parent: "<<(m_parent ? m_parent->name() : QString("None"))<<endl;
00936     kdDebug()<<indent<<"  Level: "<<level()<<endl;
00937     kdDebug()<<indent<<"  No of predecessors: "<<m_dependParentNodes.count()<<endl;
00938     QPtrListIterator<Relation> pit(m_dependParentNodes);
00939     //kdDebug()<<indent<<"  Dependant parents="<<pit.count()<<endl;
00940     if (pit.count() > 0) {
00941         for ( ; pit.current(); ++pit ) {
00942             pit.current()->printDebug(indent);
00943         }
00944     }
00945     kdDebug()<<indent<<"  No of successors: "<<m_dependChildNodes.count()<<endl;
00946     QPtrListIterator<Relation> cit(m_dependChildNodes);
00947     //kdDebug()<<indent<<"  Dependant children="<<cit.count()<<endl;
00948     if (cit.count() > 0) {
00949         for ( ; cit.current(); ++cit ) {
00950             cit.current()->printDebug(indent);
00951         }
00952     }
00953 
00954     //kdDebug()<<indent<<endl;
00955     indent += "  ";
00956     if (children) {
00957         QPtrListIterator<Node> it(m_nodes);
00958         for ( ; it.current(); ++it ) {
00959             it.current()->printDebug(true,indent);
00960         }
00961     }
00962 
00963 }
00964 #endif
00965 
00966 
00967 #ifndef NDEBUG
00968 void Effort::printDebug(QCString indent) {
00969     kdDebug()<<indent<<"  Effort:"<<endl;
00970     indent += "  ";
00971     kdDebug()<<indent<<"  Expected: "<<m_expectedEffort.toString()<<endl;
00972     kdDebug()<<indent<<"  Optimistic: "<<m_optimisticEffort.toString()<<endl;
00973     kdDebug()<<indent<<"  Pessimistic: "<<m_pessimisticEffort.toString()<<endl;
00974 }
00975 #endif
00976 
00977 }  //KPlato namespace
KDE Home | KDE Accessibility Home | Description of Access Keys