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