/* This file is part of the KDE project Copyright (C) 2001 Thomas zander Copyright (C) 2004 - 2006 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptproject.h" #include "kptappointment.h" #include "kpttask.h" #include "kptprojectdialog.h" #include "kptdatetime.h" #include "kptpart.h" #include "kptconfig.h" #include "kpteffortcostmap.h" #include "kptschedule.h" #include #include #include #include #include #include #include #include namespace KPlato { Project::Project(Node *parent) : Node(parent), m_accounts(*this), m_baselined(false) { //kdDebug()<type(); if (type() == Type_Project) { initiateCalculation(*m_currentSchedule); if (m_constraint == Node::MustStartOn) { //kdDebug()< startnodes = m_startNodes; for (; startnodes.current(); ++startnodes) { startnodes.current()->calcCriticalPath(fromEnd); } } else { TQPtrListIterator endnodes = m_endNodes; for (; endnodes.current(); ++endnodes) { endnodes.current()->calcCriticalPath(fromEnd); } } return false; } DateTime Project::startTime() const { //kdDebug()<id():-1)<<" "<<(m_currentSchedule?m_currentSchedule->typeToString():"")<startTime; return m_constraintStartTime; } DateTime Project::endTime() const { //kdDebug()<id():-1)<<" "<<(m_currentSchedule?m_currentSchedule->typeToString():"")<endTime; return m_constraintEndTime; } Duration *Project::getExpectedDuration() { //kdDebug()< endnodes = m_endNodes; for (; endnodes.current(); ++endnodes) { time = endnodes.current()->calculateForward(use); if (!finish.isValid() || time > finish) finish = time; } //kdDebug()<"<setProject(this); if (child->load(e)) { addCalendar(child); } else { // TODO: Complain about this kdError()<load(e)) { setStandardWorktime(child); } else { kdError()<load(e)) { addResourceGroup(child); } else { // TODO: Complain about this delete child; } } } } for (unsigned int i=0; i"<load(e)) { if (!addTask(child, this)) { delete child; // TODO: Complain about this } } else { // TODO: Complain about this delete child; } } else if (e.tagName() == "task") { //kdDebug()<"<load(e, *this)) { if (!addTask(child, this)) { delete child; // TODO: Complain about this } } else { // TODO: Complain about this delete child; } } } } // These go last for (unsigned int i=0; i"<"<load(e, *this)) { // TODO: Complain about this kdError()<"<loadXML(el, *this)) { addSchedule(sch); sch->setNode(this); setParentSchedule(sch); // If it's here, it's scheduled! sch->setScheduled(true); } else { kdError()<"< calit(m_calendars); for (; calit.current(); ++calit) { if (calit.current()->id() == calit.current()->parentId()) { kdError()<setParent(calendar(calit.current()->parentId())); } //kdDebug()<"< it = m_schedules; if (it.current()) { if (m_constraint == Node::MustFinishOn) m_constraintEndTime = it.current()->endTime; else m_constraintStartTime = it.current()->startTime; } //kdDebug()< calit(m_calendars); for (; calit.current(); ++calit) { calit.current()->save(me); } // save standard worktime if (m_standardWorktime) m_standardWorktime->save(me); // save project resources, must be after calendars TQPtrListIterator git(m_resourceGroups); for ( ; git.current(); ++git ) { git.current()->save(me); } // Only save parent relations TQPtrListIterator it(m_dependParentNodes); for ( ; it.current(); ++it ) { it.current()->save(me); } for (int i=0; isave(me); // Now we can save relations assuming no tasks have relations outside the project TQPtrListIterator nodes(m_nodes); for ( ; nodes.current(); ++nodes ) { nodes.current()->saveRelations(me); } if (!m_schedules.isEmpty()) { TQDomElement el = me.ownerDocument().createElement("schedules"); me.appendChild(el); TQIntDictIterator it = m_schedules; for (; it.current(); ++it) { if (!it.current()->isDeleted() && it.current()->isScheduled()) { TQDomElement schs = el.ownerDocument().createElement("schedule"); el.appendChild(schs); it.current()->saveXML(schs); //kdDebug()<id()); } } } } void Project::setParentSchedule(Schedule *sch) { TQPtrListIterator it = m_nodes; for (; it.current(); ++it) { it.current()->setParentSchedule(sch); } } void Project::addResourceGroup(ResourceGroup * group) { m_resourceGroups.append(group); } void Project::removeResourceGroup(ResourceGroup * group){ m_resourceGroups.remove(group); } void Project::removeResourceGroup(int /* number */){ // always auto remove } void Project::insertResourceGroup( unsigned int /* index */, ResourceGroup * /* resource */) { } TQPtrList &Project::resourceGroups() { return m_resourceGroups; } bool Project::addTask( Node* task, Node* position ) { // we want to add a task at the given position. => the new node will // become next sibling right after position. if ( 0 == position ) { kdError()<name()<name()<<" after "<name()<type() ) { return addSubTask(task, position); } // find the position // we have to tell the parent that we want to delete one of its children Node* parentNode = position->getParent(); if ( !parentNode ) { kdDebug()<findChildNode( position ); if ( -1 == index ) { // ok, it does not exist kdDebug()<name()<name()<addChildNode(task); return true; } bool Project::addSubTask( Node* task, int index, Node* parent ) { // we want to add a subtask to the node "parent" at the given index. if ( 0 == parent ) { kdError()<name()<name()<insertChildNode(index, task); return true; } void Project::delTask(Node *node) { Node *parent = node->getParent(); if (parent == 0) { kdDebug()<id()); parent->delChildNode(node, false/*take*/); } bool Project::canIndentTask(Node* node) { if (0 == node) { // should always be != 0. At least we would get the Project, // but you never know who might change that, so better be careful return false; } if (node->type() == Node::Type_Project) { //kdDebug()<getParent(); if ( !parentNode ) { return false; } if (parentNode->findChildNode(node) == -1) { kdError()<siblingBefore(); if (!sib) { //kdDebug()<findParentRelation(sib) || node->findChildRelation(sib)) { //kdDebug()<siblingBefore(); node->getParent()->delChildNode(node, false/*do not delete objekt*/); newParent->addChildNode(node); return true; } return false; } bool Project::canUnindentTask( Node* node ) { if ( 0 == node ) { // is always != 0. At least we would get the Project, but you // never know who might change that, so better be careful return false; } if ( Node::Type_Project == node->type() ) { //kdDebug()<getParent(); if ( !parentNode ) { return false; } Node* grandParentNode = parentNode->getParent(); if ( !grandParentNode ) { //kdDebug()<findChildNode( node ); if ( -1 == index ) { kdError()<getParent(); Node *grandParentNode = parentNode->getParent(); parentNode->delChildNode(node, false/*do not delete objekt*/); grandParentNode->addChildNode(node,parentNode); return true; } return false; } bool Project::canMoveTaskUp( Node* node ) { if (node == 0) return false; // safety // we have to find the parent of task to manipulate its list of children Node* parentNode = node->getParent(); if (!parentNode) { //kdDebug()<findChildNode(node) == -1) { kdError()<siblingBefore()) { return true; } return false; } bool Project::moveTaskUp( Node* node ) { if (canMoveTaskUp(node)) { return node->getParent()->moveChildUp(node); } return false; } bool Project::canMoveTaskDown( Node* node ) { if (node == 0) return false; // safety // we have to find the parent of task to manipulate its list of children Node* parentNode = node->getParent(); if (!parentNode) { return false; } if (parentNode->findChildNode(node) == -1) { kdError()<siblingAfter()) { return true; } return false; } bool Project::moveTaskDown( Node* node ) { if (canMoveTaskDown(node)) { return node->getParent()->moveChildDown(node); } return false; } Task *Project::createTask(Node* parent) { Task* node = new Task(parent); node->setId(uniqueNodeId()); return node; } Task *Project::createTask(Task &def, Node* parent) { Task* node = new Task(def, parent); node->setId(uniqueNodeId()); return node; } TQString Project::uniqueNodeId(int seed) { int i = seed; while (findNode(TQString("%1").arg(i))) { ++i; } return TQString("%1").arg(i); } bool Project::removeId(const TQString &id) { kdDebug()<removeId(id) : nodeIdDict.remove(id)); } void Project::insertId(const TQString &id, const Node *node) { kdDebug()<name()<insertId(id, node) : nodeIdDict.insert(id, node); } bool Project::registerNodeId(Node *node) { if (node->id().isEmpty()) { kdError()<id()); if (rn == 0) { insertId(node->id(), node); return true; } if (rn != node) { kdError()<id()< it(childNodeIterator()); for (; it.current(); ++it) { eff += it.current()->plannedEffort(); } return eff; } // Returns the total planned effort for this project (or subproject) on date Duration Project::plannedEffort(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { eff += it.current()->plannedEffort(date); } return eff; } // Returns the total planned effort for this project (or subproject) upto and including date Duration Project::plannedEffortTo(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { eff += it.current()->plannedEffortTo(date); } return eff; } // Returns the total actual effort for this project (or subproject) Duration Project::actualEffort() { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { eff += it.current()->actualEffort(); } return eff; } // Returns the total actual effort for this project (or subproject) on date Duration Project::actualEffort(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { eff += it.current()->actualEffort(date); } return eff; } // Returns the total actual effort for this project (or subproject) upto and including date Duration Project::actualEffortTo(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { eff += it.current()->actualEffortTo(date); } return eff; } double Project::plannedCost() { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { c += it.current()->plannedCost(); } return c; } // Returns the total planned effort for this project (or subproject) on date double Project::plannedCost(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { c += it.current()->plannedCost(date); } return c; } // Returns the total planned effort for this project (or subproject) upto and including date double Project::plannedCostTo(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { c += it.current()->plannedCostTo(date); } return c; } double Project::actualCost() { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { c += it.current()->actualCost(); } return c; } // Returns the total planned effort for this project (or subproject) on date double Project::actualCost(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { c += it.current()->actualCost(date); } return c; } // Returns the total planned effort for this project (or subproject) upto and including date double Project::actualCostTo(const TQDate &date) { //kdDebug()< it(childNodeIterator()); for (; it.current(); ++it) { c += it.current()->actualCostTo(date); } return c; } void Project::addCalendar(Calendar *calendar) { //kdDebug()<name()< Project::calendars() { TQPtrList list; TQPtrListIterator it = m_calendars; for (; it.current(); ++it) { if (!it.current()->isDeleted()) { list.append(it.current()); } } return list; } void Project::setStandardWorktime(StandardWorktime * worktime) { if (m_standardWorktime != worktime) { delete m_standardWorktime; m_standardWorktime = worktime; } } bool Project::legalToLink(Node *par, Node *child) { //kdDebug()<isDependChildOf(child)) { return false; } bool legal = true; // see if par/child is related if (par->isParentOf(child) || child->isParentOf(par)) { legal = false; } if (legal) legal = legalChildren(par, child); if (legal) legal = legalParents(par, child); return legal; } bool Project::legalParents(Node *par, Node *child) { bool legal = true; //kdDebug()<name()<<" ("<numDependParentNodes()<<" parents) "<name()<<" ("<numDependChildNodes()<<" children)"<numDependParentNodes() && legal; ++i) { Node *pNode = par->getDependParentNode(i)->parent(); if (child->isParentOf(pNode) || pNode->isParentOf(child)) { //kdDebug()<name()<<" is related to "<name()<name()<<" ("<numDependParentNodes()<<" parents) "<name()<<" ("<numDependChildNodes()<<" children)"<numDependChildNodes() && legal; ++j) { Node *cNode = child->getDependChildNode(j)->child(); if (par->isParentOf(cNode) || cNode->isParentOf(par)) { //kdDebug()<name()<<" is related to "<name()< it = m_nodes; for (int i=0; it.current(); ++it) { it.current()->generateWBS(++i, def, m_wbs); } } } void Project::setCurrentSchedule(long id) { setCurrentSchedulePtr(findSchedule(id)); Node::setCurrentSchedule(id); TQDictIterator it = resourceIdDict; for (; it.current(); ++it) { it.current()->setCurrentSchedule(id); } } MainSchedule *Project::createSchedule(TQString name, Schedule::Type type) { //kdDebug()<name()< it(resourceGroups()); for ( ; it.current(); ++it) it.current()->printDebug(indent); Node::printDebug(children, indent); } void Project::printCalendarDebug(TQCString indent) { kdDebug()< it = m_calendars; for (; it.current(); ++it) { it.current()->printDebug(indent + "--"); kdDebug()<printDebug(); } #endif } //KPlato namespace