F:/KPlato/koffice/kplato/kptnode.cc

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

Généré le Wed Nov 22 23:40:56 2006 pour KPlato par  doxygen 1.5.1-p1