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