22#include "kptappointment.h"
23#include "kptaccount.h"
24#include "kptwbsdefinition.h"
25#include "kptresource.h"
26#include "kptschedule.h"
37Node::Node(
Node *parent) : m_nodes(), m_dependChildNodes(), m_dependParentNodes() {
44Node::Node(Node &node, Node *parent)
47 m_dependParentNodes() {
52 m_leader = node.leader();
53 m_description = node.description();
54 m_constraint = (ConstraintType) node.constraint();
55 m_constraintStartTime = node.constraintStartTime();
56 m_constraintEndTime = node.constraintEndTime();
58 m_dateOnlyStartDate = node.startDate();
59 m_dateOnlyEndDate = node.endDate();
61 m_runningAccount = node.runningAccount();
62 m_startupAccount = node.startupAccount();
63 m_shutdownAccount = node.shutdownAccount();
65 m_startupCost = node.startupCost();
66 m_shutdownCost = node.shutdownCost();
68 m_schedules.setAutoDelete(node.m_schedules.autoDelete());
72 if (findNode() ==
this) {
76 while ((rel = m_dependParentNodes.getFirst())) {
79 while ((rel = m_dependChildNodes.getFirst())) {
83 m_runningAccount->removeRunning(*
this);
85 m_startupAccount->removeStartup(*
this);
86 if (m_shutdownAccount)
87 m_shutdownAccount->removeShutdown(*
this);
91 m_currentSchedule = 0;
92 m_nodes.setAutoDelete(
true);
94 m_constraint = Node::ASAP;
96 m_visitedForward =
false;
97 m_visitedBackward =
false;
99 m_dateOnlyStartDate = m_dateOnlyEndDate = TQDate::currentDate();
100 m_dateOnlyDuration.addDays(1);
102 m_runningAccount = 0;
103 m_startupAccount = 0;
104 m_shutdownAccount = 0;
106 m_shutdownCost = 0.0;
110 if ((type() == Type_Project) || (type() == Type_Subproject)) {
114 return m_parent->projectNode();
116 kdError()<<k_funcinfo<<
"Ooops, no parent and no project found"<<endl;
120void Node::delChildNode(
Node *node,
bool remove) {
122 if ( m_nodes.findRef(node) != -1 ) {
131void Node::delChildNode(
int number,
bool remove) {
132 Node *n = m_nodes.at(number);
135 m_nodes.remove(number);
137 m_nodes.take(number);
144void Node::insertChildNode(
unsigned int index, Node *node) {
146 m_nodes.insert(index,node);
147 node->setParent(
this);
150void Node::addChildNode( Node *node, Node *after) {
152 int index = m_nodes.findRef(after);
155 m_nodes.append(node);
156 node->setParent(
this);
160 m_nodes.insert(index+1, node);
161 node->setParent(
this);
164int Node::findChildNode( Node* node )
166 return m_nodes.findRef( node );
170const Node* Node::getChildNode(
int number)
const {
172 const TQPtrList<Node> &nodes = m_nodes;
173 return (
const_cast<TQPtrList<Node> &
>(nodes)).at(number);
190 m_dependChildNodes.append(relation);
198 m_dependChildNodes.insert(index, relation);
204 if(m_dependChildNodes.findRef(relation) != -1)
206 m_dependChildNodes.append(relation);
211void Node::delDependChildNode(
Node *node,
bool remove) {
212 if ( m_nodes.findRef(node) != -1 ) {
214 m_dependChildNodes.remove();
216 m_dependChildNodes.take();
220void Node::delDependChildNode( Relation *rel,
bool remove) {
221 if ( m_dependChildNodes.findRef(rel) != -1 ) {
223 m_dependChildNodes.remove();
225 m_dependChildNodes.take();
229void Node::delDependChildNode(
int number,
bool remove) {
231 m_dependChildNodes.remove(number);
233 m_dependChildNodes.take(number);
237 if (m_dependChildNodes.findRef(rel) != -1) {
238 m_dependChildNodes.take();
249 m_dependParentNodes.append(relation);
257 m_dependParentNodes.insert(index,relation);
263 if(m_dependParentNodes.findRef(relation) != -1)
265 m_dependParentNodes.append(relation);
270void Node::delDependParentNode(
Node *node,
bool remove) {
271 if ( m_nodes.findRef(node) != -1 ) {
273 m_dependParentNodes.remove();
275 m_dependParentNodes.take();
279void Node::delDependParentNode( Relation *rel,
bool remove) {
280 if ( m_dependParentNodes.findRef(rel) != -1 ) {
282 m_dependParentNodes.remove();
284 m_dependParentNodes.take();
288void Node::delDependParentNode(
int number,
bool remove) {
290 m_dependParentNodes.remove(number);
292 m_dependParentNodes.take(number);
296 if (m_dependParentNodes.findRef(rel) != -1) {
297 rel = m_dependParentNodes.take();
301bool Node::isParentOf(
Node *node) {
302 if (m_nodes.findRef(node) != -1)
305 TQPtrListIterator<Node> nit(childNodeIterator());
306 for ( ; nit.current(); ++nit ) {
307 if (nit.current()->isParentOf(node))
313Relation *Node::findParentRelation(Node *node) {
314 for (
int i=0; i<numDependParentNodes(); i++) {
315 Relation *rel = getDependParentNode(i);
316 if (rel->parent() == node)
319 return (Relation *)0;
322Relation *Node::findChildRelation(Node *node) {
323 for (
int i=0; i<numDependChildNodes(); i++) {
324 Relation *rel = getDependChildNode(i);
325 if (rel->child() == node)
328 return (Relation *)0;
331Relation *Node::findRelation(Node *node) {
332 Relation *rel = findParentRelation(node);
334 rel = findChildRelation(node);
338bool Node::isDependChildOf(Node *node) {
340 for (
int i=0; i<numDependParentNodes(); i++) {
341 Relation *rel = getDependParentNode(i);
342 if (rel->parent() == node)
344 if (rel->parent()->isDependChildOf(node))
353 if (!time.isValid()) {
354 kdError()<<k_funcinfo<<
"Time is invalid"<<endl;
358 kdError()<<k_funcinfo<<
"m_effort == 0"<<endl;
361 if (m_currentSchedule == 0) {
363 kdError()<<k_funcinfo<<
"No current schedule"<<endl;
365 kdDebug()<<k_funcinfo<<m_name<<
": Use="<<use<<endl;
366 return calcDuration(time, m_effort->effort(use), backward);
369void Node::makeAppointments() {
370 TQPtrListIterator<Node> nit(m_nodes);
371 for ( ; nit.current(); ++nit ) {
372 nit.current()->makeAppointments();
377 TQPtrListIterator<Node> nit(m_nodes);
378 for ( ; nit.current(); ++nit ) {
379 nit.current()->calcResourceOverbooked();
384 return m_currentSchedule ? m_currentSchedule->overbookedResources() : TQStringList();
388 TQPtrListIterator<Relation> it(m_dependChildNodes);
389 for (; it.current(); ++it) {
390 it.current()->save(element);
392 TQPtrListIterator<Node> nodes(m_nodes);
393 for ( ; nodes.current(); ++nodes ) {
394 nodes.current()->saveRelations(element);
398void Node::setConstraint(TQString &type) {
402 else if (type ==
"ALAP")
404 else if (type ==
"StartNotEarlier")
405 setConstraint(StartNotEarlier);
406 else if (type ==
"FinishNotLater")
407 setConstraint(FinishNotLater);
408 else if (type ==
"MustStartOn")
409 setConstraint(MustStartOn);
410 else if (type ==
"MustFinishOn")
411 setConstraint(MustFinishOn);
412 else if (type ==
"FixedInterval")
413 setConstraint(FixedInterval);
418TQString Node::constraintToString()
const {
420 if (m_constraint == ASAP)
421 return TQString(
"ASAP");
422 else if (m_constraint == ALAP)
423 return TQString(
"ALAP");
424 else if (m_constraint == StartNotEarlier)
425 return TQString(
"StartNotEarlier");
426 else if (m_constraint == FinishNotLater)
427 return TQString(
"FinishNotLater");
428 else if (m_constraint == MustStartOn)
429 return TQString(
"MustStartOn");
430 else if (m_constraint == MustFinishOn)
431 return TQString(
"MustFinishOn");
432 else if (m_constraint == FixedInterval)
433 return TQString(
"FixedInterval");
438void Node::propagateEarliestStart(DateTime &time) {
439 if (m_currentSchedule == 0)
441 m_currentSchedule->earliestStart = time;
443 TQPtrListIterator<Node> it = m_nodes;
444 for (; it.current(); ++it) {
445 it.current()->propagateEarliestStart(time);
449void Node::propagateLatestFinish(DateTime &time) {
450 if (m_currentSchedule == 0)
452 m_currentSchedule->latestFinish = time;
454 TQPtrListIterator<Node> it = m_nodes;
455 for (; it.current(); ++it) {
456 it.current()->propagateLatestFinish(time);
460void Node::moveEarliestStart(DateTime &time) {
461 if (m_currentSchedule == 0)
463 if (m_currentSchedule->earliestStart < time)
464 m_currentSchedule->earliestStart = time;
465 TQPtrListIterator<Node> it = m_nodes;
466 for (; it.current(); ++it) {
467 it.current()->moveEarliestStart(time);
471void Node::moveLatestFinish(DateTime &time) {
472 if (m_currentSchedule == 0)
474 if (m_currentSchedule->latestFinish > time)
475 m_currentSchedule->latestFinish = time;
476 TQPtrListIterator<Node> it = m_nodes;
477 for (; it.current(); ++it) {
478 it.current()->moveLatestFinish(time);
482void Node::initiateCalculation(Schedule &sch) {
483 TQPtrListIterator<Node> it = m_nodes;
484 for (; it.current(); ++it) {
485 it.current()->initiateCalculation(sch);
489void Node::resetVisited() {
490 m_visitedForward =
false;
491 m_visitedBackward =
false;
492 TQPtrListIterator<Node> it = m_nodes;
493 for (; it.current(); ++it) {
494 it.current()->resetVisited();
498Node *Node::siblingBefore() {
501 return getParent()->childBefore(
this);
505Node *Node::childBefore(Node *node) {
507 int index = m_nodes.findRef(node);
509 return m_nodes.at(index-1);
514Node *Node::siblingAfter() {
517 return getParent()->childAfter(
this);
521Node *Node::childAfter(Node *node)
524 uint index = m_nodes.findRef(node);
525 if (index < m_nodes.count()-1) {
526 return m_nodes.at(index+1); }
530bool Node::moveChildUp(Node* node)
532 if (findChildNode(node) == -1)
534 Node *sib = node->siblingBefore();
537 sib = sib->siblingBefore();
538 delChildNode(node,
false);
540 addChildNode(node, sib);
542 insertChildNode(0, node);
547bool Node::moveChildDown(Node* node)
549 if (findChildNode(node) == -1)
551 Node *sib = node->siblingAfter();
554 delChildNode(node,
false);
555 addChildNode(node, sib);
567 return m_dependChildNodes.isEmpty();
570 return m_dependParentNodes.isEmpty();
573bool Node::setId(TQString
id) {
576 kdError()<<k_funcinfo<<
"id is empty"<<endl;
580 if (!m_id.isEmpty()) {
581 Node *n = findNode();
587 kdError()<<k_funcinfo<<
"My id '"<<m_id<<
"' already used for different node: "<<n->name()<<endl;
591 kdError()<<k_funcinfo<<
"id '"<<
id<<
"' is already used for different node: "<<findNode(
id)->name()<<endl;
601void Node::setStartTime(DateTime startTime) {
602 if (m_currentSchedule)
603 m_currentSchedule->startTime = startTime;
604 m_dateOnlyStartDate = startTime.date();
607void Node::setEndTime(DateTime endTime) {
608 if (m_currentSchedule)
609 m_currentSchedule->endTime = endTime;
611 m_dateOnlyEndDate = endTime.date();
612 if (endTime.time().isNull() && m_dateOnlyEndDate > m_dateOnlyStartDate)
613 m_dateOnlyEndDate = m_dateOnlyEndDate.addDays(-1);
618 TQPtrListIterator<Node> it(m_nodes);
619 for (; it.current(); ++it ) {
620 it.current()->saveAppointments(element,
id);
625 TQPtrList<Appointment> lst;
626 if (m_currentSchedule)
627 lst = m_currentSchedule->appointments();
637 if (m_currentSchedule)
638 return m_currentSchedule->add(appointment);
648 appointment->setNode(s);
649 return s->
add(appointment);
663 if (m_currentSchedule == schedule)
664 m_currentSchedule = 0;
665 m_schedules.take(schedule->id());
671 m_schedules.replace(schedule->id(), schedule);
689 TQIntDictIterator<Schedule> it = m_schedules;
690 for (; it.current(); ++it) {
691 if (!it.current()->isDeleted() &&
692 it.current()->name() == name && it.current()->type() == type)
700 TQIntDictIterator<Schedule> it = m_schedules;
701 for (; it.current(); ++it) {
702 if (!it.current()->isDeleted() && it.current()->type() == type) {
712 kdError()<<k_funcinfo<<m_name<<
" Could not find schedule with id="<<
id<<endl;
723 TQPtrListIterator<Node> it = m_nodes;
724 for (; it.current(); ++it) {
725 it.current()->setParentSchedule(sch);
729bool Node::calcCriticalPath(
bool fromEnd) {
730 if (m_currentSchedule == 0)
736 if (!fromEnd && isStartNode()) {
737 m_currentSchedule->inCriticalPath =
true;
740 if (fromEnd && isEndNode()) {
741 m_currentSchedule->inCriticalPath =
true;
744 TQPtrListIterator<Relation> pit(m_dependParentNodes);
745 for (; pit.current(); ++pit) {
746 if (pit.current()->parent()->calcCriticalPath(fromEnd)) {
747 m_currentSchedule->inCriticalPath =
true;
750 return m_currentSchedule->inCriticalPath;
754 Node *n = getParent();
755 return n ? n->
level() + 1 : 0;
759 m_wbs = wbs + def.code(count,
level());
761 TQString w = wbs + def.wbs(count,
level());
762 TQPtrListIterator<Node> it = m_nodes;
763 for (
int i=0; it.current(); ++it) {
764 it.current()->generateWBS(++i, def, w);
770 TQPtrListIterator<Node> it = m_nodes;
771 for (; it.current(); ++it) {
772 it.current()->setCurrentSchedule(
id);
779 m_expectedEffort = e;
780 m_pessimisticEffort = p;
781 m_optimisticEffort = o;
782 m_type = Type_Effort;
783 m_risktype = Risk_None;
786Effort::Effort(
const Effort &effort) {
787 set(effort.expected(), effort.pessimistic(), effort.optimistic());
788 setType(effort.type());
789 setRisktype(effort.risktype());
795const Effort Effort::zeroEffort( Duration::zeroDuration,
796 Duration::zeroDuration,
797 Duration::zeroDuration );
799void Effort::set( Duration e, Duration p, Duration o ) {
800 m_expectedEffort = e;
801 m_pessimisticEffort = (p == Duration::zeroDuration) ? e : p;
802 m_optimisticEffort = (o == Duration::zeroDuration) ? e : o;
806void Effort::set(
int e,
int p,
int o ) {
807 m_expectedEffort = Duration(e);
808 m_pessimisticEffort = (p < 0) ? Duration(e) : Duration(p);
809 m_optimisticEffort = (o < 0) ? Duration(e) : Duration(o);
818void Effort::set(
unsigned days,
unsigned hours,
unsigned minutes) {
819 Duration dur(days, hours, minutes);
824void Effort::expectedEffort(
unsigned *days,
unsigned *hours,
unsigned *minutes) {
825 m_expectedEffort.get(days, hours, minutes);
828Duration Effort::variance()
const {
829 return (m_pessimisticEffort - m_optimisticEffort)/6;
831Duration Effort::pertExpected()
const {
832 if (m_risktype == Risk_Low) {
833 return (m_optimisticEffort + m_pessimisticEffort + (m_expectedEffort*4))/6;
834 }
else if (m_risktype == Risk_High) {
835 return (m_optimisticEffort + (m_pessimisticEffort*2) + (m_expectedEffort*4))/7;
837 return m_expectedEffort;
839Duration Effort::pertOptimistic()
const {
840 if (m_risktype != Risk_None) {
841 return pertExpected() - variance();
843 return m_optimisticEffort;
845Duration Effort::pertPessimistic()
const {
846 if (m_risktype != Risk_None) {
847 return pertExpected() + variance();
849 return m_pessimisticEffort;
852Duration Effort::effort(
int use)
const {
853 if (use == Effort::Use_Expected) {
854 return pertExpected();
855 }
else if (use == Effort::Use_Optimistic) {
856 return pertOptimistic();
857 }
else if (use == Effort::Use_Pessimistic)
858 return pertPessimistic();
860 return m_expectedEffort;
863bool Effort::load(TQDomElement &element) {
864 m_expectedEffort = Duration::fromString(element.attribute(
"expected"));
865 m_optimisticEffort = Duration::fromString(element.attribute(
"optimistic"));
866 m_pessimisticEffort = Duration::fromString(element.attribute(
"pessimistic"));
867 setType(element.attribute(
"type",
"WorkBased"));
868 setRisktype(element.attribute(
"risk"));
872void Effort::save(TQDomElement &element)
const {
873 TQDomElement me = element.ownerDocument().createElement(
"effort");
874 element.appendChild(me);
875 me.setAttribute(
"expected", m_expectedEffort.toString());
876 me.setAttribute(
"optimistic", m_optimisticEffort.toString());
877 me.setAttribute(
"pessimistic", m_pessimisticEffort.toString());
878 me.setAttribute(
"type", typeToString());
879 me.setAttribute(
"risk", risktypeToString());
882TQString Effort::typeToString()
const {
883 if (m_type == Type_Effort)
884 return TQString(
"Effort");
885 if (m_type == Type_FixedDuration)
886 return TQString(
"Type_FixedDuration");
891void Effort::setType(TQString type) {
892 if (type ==
"Effort")
893 setType(Type_Effort);
894 else if (type ==
"Type_FixedDuration")
895 setType(Type_FixedDuration);
897 setType(Type_Effort);
900TQString Effort::risktypeToString()
const {
901 if (m_risktype == Risk_None)
902 return TQString(
"None");
903 if (m_risktype == Risk_Low)
904 return TQString(
"Low");
905 if (m_risktype == Risk_High)
906 return TQString(
"High");
911void Effort::setRisktype(TQString type) {
913 setRisktype(Risk_High);
914 else if (type ==
"Low")
915 setRisktype(Risk_Low);
917 setRisktype(Risk_None);
922 int p = percent>0 ? -percent : percent;
923 m_optimisticEffort = m_expectedEffort*(100+p)/100;
929 return (m_optimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds())-100;
934 int p = percent<0 ? -percent : percent;
935 m_pessimisticEffort = m_expectedEffort*(100+p)/100;
940 return m_pessimisticEffort.milliseconds()*100/m_expectedEffort.milliseconds()-100;
945void Node::printDebug(
bool children, TQCString indent) {
946 kdDebug()<<indent<<
" Unique node identity="<<m_id<<endl;
947 if (m_effort) m_effort->printDebug(indent);
948 TQString s =
" Constraint: " + constraintToString();
949 if (m_constraint == MustStartOn || m_constraint == StartNotEarlier || m_constraint == FixedInterval)
950 kdDebug()<<indent<<s<<
" ("<<constraintStartTime().toString()<<
")"<<endl;
951 if (m_constraint == MustFinishOn || m_constraint == FinishNotLater || m_constraint == FixedInterval)
952 kdDebug()<<indent<<s<<
" ("<<constraintEndTime().toString()<<
")"<<endl;
955 kdDebug()<<indent<<
" Current schedule: "<<
"id="<<cs->id()<<
" '"<<cs->name()<<
"' type: "<<cs->type()<<endl;
957 kdDebug()<<indent<<
" Current schedule: None"<<endl;
959 TQIntDictIterator<Schedule> it = m_schedules;
960 for (; it.current(); ++it) {
961 it.current()->printDebug(indent+
" ");
963 kdDebug()<<indent<<
" Parent: "<<(m_parent ? m_parent->name() : TQString(
"None"))<<endl;
964 kdDebug()<<indent<<
" Level: "<<level()<<endl;
965 kdDebug()<<indent<<
" No of predecessors: "<<m_dependParentNodes.count()<<endl;
966 TQPtrListIterator<Relation> pit(m_dependParentNodes);
968 if (pit.count() > 0) {
969 for ( ; pit.current(); ++pit ) {
970 pit.current()->printDebug(indent);
973 kdDebug()<<indent<<
" No of successors: "<<m_dependChildNodes.count()<<endl;
974 TQPtrListIterator<Relation> cit(m_dependChildNodes);
976 if (cit.count() > 0) {
977 for ( ; cit.current(); ++cit ) {
978 cit.current()->printDebug(indent);
985 TQPtrListIterator<Node> it(m_nodes);
986 for ( ; it.current(); ++it ) {
987 it.current()->printDebug(
true,indent);
996void Effort::printDebug(TQCString indent) {
997 kdDebug()<<indent<<
" Effort:"<<endl;
999 kdDebug()<<indent<<
" Expected: "<<m_expectedEffort.toString()<<endl;
1000 kdDebug()<<indent<<
" Optimistic: "<<m_optimisticEffort.toString()<<endl;
1001 kdDebug()<<indent<<
" Pessimistic: "<<m_pessimisticEffort.toString()<<endl;
1003 kdDebug()<<indent<<
" Risk: "<<risktypeToString()<<endl;
1004 kdDebug()<<indent<<
" Pert expected: "<<pertExpected().toString()<<endl;
1005 kdDebug()<<indent<<
" Pert optimistic: "<<pertOptimistic().toString()<<endl;
1006 kdDebug()<<indent<<
" Pert pessimistic: "<<pertPessimistic().toString()<<endl;
1007 kdDebug()<<indent<<
" Pert variance: "<<variance().toString()<<endl;
A resource (Resource) can be scheduled to be used at any time, this is represented internally with Ap...
DateTime is a TQDateTime which knows about Duration.
The duration class can be used to store a timespan in a convenient format.
static const Duration zeroDuration
This is useful for occasions where we need a zero duration.
int pessimisticRatio() const
Return the "pessimistic" duration as the deviation from "expected" in percent.
void setOptimisticRatio(int percent)
Set the optimistic duration.
int optimisticRatio() const
Return the "optimistic" duration as deviation from "expected" in percent.
void setPessimisticRatio(int percent)
Set the pessimistic duration.
NodeSchedule holds scheduling information for a node (task).
This class represents any node in the project, a node can be a project or a subproject or any task.
virtual void addDependChildNode(Node *node, Relation::Type p=Relation::FinishStart)
Adds relation to both this node and address node.
void takeDependParentNode(Relation *rel)
Takes the relation rel from this node only.
void takeDependChildNode(Relation *rel)
Takes the relation rel from this node only.
Schedule * findSchedule(const TQString name, const Schedule::Type type) const
Find schedule matching name and type. Does not return deleted schedule.
Schedule * createSchedule(TQString name, Schedule::Type type, long id)
Create a new schedule.
virtual void insertDependChildNode(unsigned int index, Node *node, Relation::Type p=Relation::FinishStart)
Inserts relation to this node at index address index and appends relation to address node.
virtual int level()
Returns the level this node is in the hierarchy. Top node is level 0.
TQPtrList< Appointment > appointments()
Return the list of appointments for current schedule.
virtual void saveAppointments(TQDomElement &element, long id) const
Save appointments for schedule with id.
void takeSchedule(const Schedule *schedule)
Take, don't delete (as in destruct).
virtual TQStringList overbookedResources() const
Return a list of overbooked resources.
virtual void setParentSchedule(Schedule *sch)
Set parent schedule recursivly.
virtual void saveRelations(TQDomElement &element) const
Save my and my childrens relations.
bool legalToLink(Node *node)
Check if this node can be linked to node.
void addSchedule(Schedule *schedule)
Add schedule to list, replace if schedule with same id allready exists.
virtual void setCurrentSchedule(long id)
Set current schedule to schedule with identity id, for me and my children.
virtual Node * projectNode()
Returns a pointer to the project node (main- or sub-project) Returns 0 if no project exists.
virtual void insertDependParentNode(unsigned int index, Node *node, Relation::Type p=Relation::FinishStart)
Inserts relation to this node at index and appends relation to node.
Duration * getDelay()
Calculate the delay of this node.
virtual void calcResourceOverbooked()
Calculates if the assigned resource is overbooked within the duration of this node.
virtual void addDependParentNode(Node *node, Relation::Type p=Relation::FinishStart)
Adds relation to both this node and node.
virtual bool addAppointment(Appointment *appointment)
Return appointment this node have with resource.
virtual bool isStartNode() const
Check if this node has any dependent parent nodes.
void setScheduleDeleted(long id, bool onoff)
Set deleted = onoff for schedule with id.
virtual bool isEndNode() const
Check if this node has any dependent child nodes.
virtual void generateWBS(int count, WBSDefinition &def, TQString wbs=TQString())
Generate WBS.
The relation class couples a 2 nodes together which are dependent on each other.
ResourceSchedule holds scheduling information for a resource.
The Schedule class holds data calculated during project calculation and scheduling,...
virtual bool add(Appointment *appointment)
Adds appointment to this schedule only.
virtual void addAppointment(Schedule *, DateTime &, DateTime &, double=100)
Adds appointment to both this resource schedule and node schedule.