1 | /* This file is part of the KDE project |
2 | Copyright (C) 2001 Thomas Zander zander@kde.org |
3 | Copyright (C) 2004 - 2011 Dag Andersen <danders@get2net.dk> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | * Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #ifndef KPTNODE_H |
22 | #define KPTNODE_H |
23 | |
24 | #include "kplatokernel_export.h" |
25 | |
26 | #include "kptglobal.h" |
27 | #include "kptrelation.h" |
28 | #include "kptduration.h" |
29 | #include "kptdatetime.h" |
30 | #include "kptschedule.h" |
31 | #include "kptdocuments.h" |
32 | #include "kptresource.h" |
33 | |
34 | #include <QObject> |
35 | #include <QHash> |
36 | #include <QString> |
37 | |
38 | #include <KoXmlReader.h> |
39 | |
40 | class QDomElement; |
41 | |
42 | |
43 | /// The main namespace. |
44 | namespace KPlato |
45 | { |
46 | |
47 | class Account; |
48 | class Project; |
49 | class Appointment; |
50 | class ResourceGroup; |
51 | class Resource; |
52 | class ResourceGroupRequest; |
53 | class Estimate; |
54 | class WBSDefinition; |
55 | class EffortCostMap; |
56 | class EffortCost; |
57 | class Calendar; |
58 | class KPlatoXmlLoaderBase; |
59 | |
60 | /** |
61 | * This class represents any node in the project, a node can be a project or |
62 | * a subproject or any task. |
63 | * This class is basically an abstract interface to make the design more OO. |
64 | */ |
65 | class KPLATOKERNEL_EXPORT Node : public QObject |
66 | { |
67 | Q_OBJECT |
68 | public: |
69 | enum ConstraintType { ASAP, ALAP, MustStartOn, MustFinishOn, StartNotEarlier, FinishNotLater, FixedInterval }; |
70 | |
71 | enum State { |
72 | State_None = 0, |
73 | State_Started = 1, |
74 | State_StartedLate = 2, |
75 | State_StartedEarly = 4, |
76 | State_Finished = 8, |
77 | State_FinishedLate = 16, |
78 | State_FinishedEarly = 32, |
79 | State_Running = 64, |
80 | State_RunningLate = 128, |
81 | State_RunningEarly = 256, |
82 | State_ReadyToStart = 512, // all precceeding tasks finished (if any) |
83 | State_NotReadyToStart = 1024, // all precceeding tasks not finished (must be one or more) |
84 | State_NotScheduled = 2048, |
85 | State_Late = 4096 |
86 | }; |
87 | |
88 | enum Properties { |
89 | Type, |
90 | StartupCost, |
91 | ShutdownCost, |
92 | CompletionEntry, |
93 | CompletionStarted, |
94 | CompletionFinished, |
95 | CompletionStartTime, |
96 | CompletionFinishTime, |
97 | CompletionPercentage, |
98 | CompletionRemainingEffort, |
99 | CompletionActualEffort, |
100 | CompletionUsedEffort |
101 | }; |
102 | |
103 | explicit Node(Node *parent = 0); |
104 | Node(const Node &node, Node *parent = 0); |
105 | |
106 | |
107 | // Declare the class abstract |
108 | virtual ~Node() = 0; |
109 | |
110 | void setId(const QString& id); |
111 | QString id() const { return m_id; } // unique identity |
112 | |
113 | enum NodeTypes { |
114 | Type_Node = 0, |
115 | Type_Project = 1, |
116 | Type_Subproject = 2, |
117 | Type_Task = 3, |
118 | Type_Milestone = 4, |
119 | Type_Periodic = 5, |
120 | Type_Summarytask = 6 |
121 | }; |
122 | |
123 | virtual int type() const = 0; |
124 | |
125 | QString typeToString( bool trans = false ) const; |
126 | static QString typeToString( NodeTypes typ, bool trans = false ); |
127 | static QStringList typeToStringList( bool trans ); |
128 | /** |
129 | * Returns a pointer to the project node (main- or sub-project) |
130 | * Returns 0 if no project exists. |
131 | */ |
132 | virtual Node *projectNode(); |
133 | /** |
134 | * Returns a pointer to the project node (main- or sub-project) |
135 | * Returns 0 if no project exists. |
136 | */ |
137 | virtual const Node *projectNode() const; |
138 | |
139 | // The load and save methods |
140 | virtual bool load(KoXmlElement &, XMLLoaderObject &) { return true; } |
141 | virtual void save(QDomElement &element) const = 0; |
142 | /// Save me and my childrens relations. |
143 | virtual void saveRelations(QDomElement &element) const; |
144 | |
145 | /// Save a workpackage document containing @p node with schedule identity @p id |
146 | virtual void saveWorkPackageXML( QDomElement &element, long id ) const; |
147 | |
148 | // simple child node management |
149 | // Child nodes are things like subtasks, basically a task can exists of |
150 | // several sub-tasks. Creating a table has 4 subtasks, 1) measuring |
151 | // 2) cutting 3) building 4) painting. |
152 | Node *parentNode() const { return m_parent; } |
153 | void setParentNode( Node* newParent ) { m_parent = newParent;} |
154 | const QList<Node*> &childNodeIterator() const { return m_nodes; } |
155 | int numChildren() const { return m_nodes.count(); } |
156 | virtual void addChildNode(Node *node, Node *after=0); |
157 | virtual void insertChildNode(int index, Node *node); |
158 | void takeChildNode(Node *node ); |
159 | void takeChildNode(int number ); |
160 | Node* childNode(int number); |
161 | const Node* childNode(int number) const; |
162 | int findChildNode( const Node* node ) const; |
163 | bool isChildOf( const Node *node ) const; |
164 | int indexOf( const Node *node ) const; |
165 | |
166 | // Time-dependent child-node-management. |
167 | // list all nodes that are dependent upon this one. |
168 | // Building a house requires the table to be finished, therefore the |
169 | // house-building is time dependent on the table-building. So a child |
170 | // of the table-building node is the house-building node. |
171 | |
172 | int numDependChildNodes() const { return m_dependChildNodes.count(); } |
173 | /// Adds relation of type @p p to both this node and @p node |
174 | virtual void addDependChildNode( Node *node, Relation::Type p=Relation::FinishStart); |
175 | /// Adds relation of type @p p with @p lag to both this node and @p node |
176 | virtual void addDependChildNode( Node *node, Relation::Type p, Duration lag); |
177 | /// Adds @p relation only to this node |
178 | virtual bool addDependChildNode( Relation *relation); |
179 | /// Inserts relation to this node at index @p index and appends relation to @p node |
180 | virtual void insertDependChildNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart); |
181 | /** |
182 | * Takes the relation rel from this node only. |
183 | */ |
184 | void takeDependChildNode( Relation *rel ); |
185 | Relation *getDependChildNode( int number ) const { |
186 | return m_dependChildNodes.at(number); |
187 | } |
188 | QList<Relation*> dependChildNodes() const { return m_dependChildNodes; } |
189 | |
190 | int numDependParentNodes() const { return m_dependParentNodes.count(); } |
191 | /// Adds relation if type @p to both this node and @p node |
192 | virtual void addDependParentNode(Node *node, Relation::Type p=Relation::FinishStart); |
193 | /// Adds relation to both this node and @p node |
194 | virtual void addDependParentNode( Node *node, Relation::Type p, Duration lag); |
195 | /// Adds relation only to this node |
196 | virtual bool addDependParentNode( Relation *relation); |
197 | /// Inserts relation to this node at index and appends relation to @p node |
198 | virtual void insertDependParentNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart); |
199 | /** |
200 | * Takes the relation @p rel from this node only. |
201 | */ |
202 | void takeDependParentNode( Relation *rel ); |
203 | Relation *getDependParentNode( int number ) const { |
204 | return m_dependParentNodes.at(number); |
205 | } |
206 | QList<Relation*> dependParentNodes() const { return m_dependParentNodes; } |
207 | QList<Node*> getParentNodes(); |
208 | bool isParentOf( const Node *node ) const; |
209 | bool isDependChildOf( const Node *node ) const; |
210 | virtual bool canMoveTo( const Node *newParent ) const; |
211 | |
212 | Relation *findParentRelation( const Node *node) const; |
213 | Relation *findChildRelation( const Node *node ) const; |
214 | Relation *findRelation( const Node *node ) const; |
215 | |
216 | /// Set the scheduled start time |
217 | void setStartTime(DateTime startTime, long id = CURRENTSCHEDULE ); |
218 | /// Return the scheduled start time |
219 | virtual DateTime startTime( long id = CURRENTSCHEDULE ) const; |
220 | /// Set the scheduled end time |
221 | void setEndTime(DateTime endTime, long id = CURRENTSCHEDULE ); |
222 | /// Return the scheduled end time |
223 | virtual DateTime endTime( long id = CURRENTSCHEDULE ) const; |
224 | /// Set the scheduled duration |
225 | void setDuration(const Duration &duration, long id = CURRENTSCHEDULE ); |
226 | |
227 | DateTime appointmentStartTime( long id = CURRENTSCHEDULE) const; |
228 | DateTime appointmentEndTime( long id = CURRENTSCHEDULE ) const; |
229 | |
230 | /// Return the estimate for this node |
231 | Estimate *estimate() const { return m_estimate; } |
232 | |
233 | /** |
234 | * Instead of using the expected duration, generate a random value using |
235 | * the Distribution of each Task. This can be used for Monte-Carlo |
236 | * estimation of Project duration. |
237 | */ |
238 | virtual Duration *getRandomDuration() = 0; |
239 | /** |
240 | * Calculate the delay of this node. |
241 | * It is the difference between the actual startTime and scheduled startTime. |
242 | */ |
243 | Duration *getDelay(); // TODO |
244 | |
245 | |
246 | QString &name() { return m_name; } |
247 | QString &leader() { return m_leader; } |
248 | QString &description() { return m_description; } |
249 | const QString &name() const { return m_name; } |
250 | const QString &leader() const { return m_leader; } |
251 | const QString &description() const { return m_description; } |
252 | void setName(const QString &n); |
253 | void setLeader(const QString &l); |
254 | void setDescription(const QString &d); |
255 | |
256 | void setConstraint(Node::ConstraintType type); |
257 | void setConstraint(QString &type); |
258 | int constraint() const { return m_constraint; } |
259 | QString constraintToString( bool trans=false ) const; |
260 | static QStringList constraintList( bool trans ); |
261 | |
262 | virtual void setConstraintStartTime(const DateTime time) |
263 | { m_constraintStartTime = time; changed( this ); } |
264 | virtual void setConstraintEndTime(const DateTime time) |
265 | { m_constraintEndTime = time; changed( this ); } |
266 | |
267 | virtual DateTime constraintStartTime() const { return m_constraintStartTime; } |
268 | virtual DateTime constraintEndTime() const { return m_constraintEndTime; } |
269 | virtual DateTime startNotEarlier() const { return m_constraintStartTime; } |
270 | virtual DateTime finishNotLater() const { return m_constraintEndTime; } |
271 | virtual DateTime mustStartOn() const { return m_constraintStartTime; } |
272 | virtual DateTime mustFinishOn() const { return m_constraintEndTime; } |
273 | |
274 | virtual ResourceGroupRequest *resourceGroupRequest(const ResourceGroup * /*group*/) const { return 0; } |
275 | virtual QStringList requestNameList() const { return QStringList(); } |
276 | virtual bool containsRequest( const QString &/*identity*/ ) const { return false; } |
277 | virtual ResourceRequest *resourceRequest( const QString &/*name*/ ) const { return 0; } |
278 | |
279 | /// Return the list of resources assigned to this task |
280 | virtual QStringList assignedNameList( long /*id*/ = CURRENTSCHEDULE ) const { return QStringList(); } |
281 | |
282 | virtual void makeAppointments(); |
283 | /// Calculates if the assigned resource is overbooked |
284 | /// within the duration of this node |
285 | virtual void calcResourceOverbooked(); |
286 | |
287 | /// Return the scheduling status of schedule @p id. If @p trans is true, text is translated |
288 | QStringList schedulingStatus( long id, bool trans = false ) const; |
289 | /// EstimateType == Estimate, but no resource is requested |
290 | bool resourceError( long id = CURRENTSCHEDULE ) const; |
291 | /// The assigned resource is overbooked |
292 | virtual bool resourceOverbooked( long id = CURRENTSCHEDULE ) const; |
293 | /// The requested resource is not available |
294 | bool resourceNotAvailable( long id = CURRENTSCHEDULE ) const; |
295 | /// The task cannot be scheduled to fullfil all the constraints |
296 | virtual bool constraintError( long id = CURRENTSCHEDULE ) const; |
297 | /// The task cannot be scheduled correctly |
298 | virtual bool schedulingError( long id = CURRENTSCHEDULE ) const; |
299 | /// The node has not been scheduled |
300 | bool notScheduled( long id = CURRENTSCHEDULE ) const; |
301 | /// Return a list of overbooked resources |
302 | virtual QStringList overbookedResources( long id = CURRENTSCHEDULE ) const; |
303 | /// The assigned resources can not fullfil the estimated effort. |
304 | virtual bool effortMetError( long /*id*/ = CURRENTSCHEDULE ) const { return false; } |
305 | |
306 | virtual EffortCostMap plannedEffortCostPrDay(const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; |
307 | virtual EffortCostMap plannedEffortCostPrDay(const Resource *resource, const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; |
308 | |
309 | /// Returns the total planned effort for @p resource on this task (or subtasks) |
310 | virtual Duration plannedEffort( const Resource *resource, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; |
311 | /// Returns the total planned effort for this task (or subtasks) |
312 | virtual Duration plannedEffort( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; } |
313 | /// Returns the total planned effort for this task (or subtasks) on date |
314 | virtual Duration plannedEffort(const QDate &, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; } |
315 | /// Returns the total planned effort for @p resource on this task (or subtasks) on date |
316 | virtual Duration plannedEffort( const Resource *resource, const QDate &date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; |
317 | /// Returns the planned effort up to and including date |
318 | virtual Duration plannedEffortTo(const QDate &, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; } |
319 | /// Returns the planned effort for @p resource up to and including date |
320 | virtual Duration plannedEffortTo( const Resource *resource, const QDate &date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; |
321 | |
322 | /// Returns the total actual effort for this task (or subtasks) |
323 | virtual Duration actualEffort() const { return Duration::zeroDuration; } |
324 | /// Returns the total actual effort for this task (or subtasks) on date |
325 | virtual Duration actualEffort(const QDate &/*date*/ ) const { return Duration::zeroDuration; } |
326 | /// Returns the total actual effort for this task (or subtasks) up to and including date |
327 | virtual Duration actualEffortTo(const QDate &/*date*/ ) const { return Duration::zeroDuration; } |
328 | virtual EffortCostMap actualEffortCostPrDay(const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; |
329 | /// Returns the actual effort and cost pr day used by @p resource |
330 | virtual EffortCostMap actualEffortCostPrDay(const Resource *resource, const QDate &start, const QDate &end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; |
331 | |
332 | /** |
333 | * Planned cost is the sum total of all resources and other costs |
334 | * planned for this node. |
335 | */ |
336 | virtual EffortCost plannedCost( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; |
337 | |
338 | /** |
339 | * Planned cost from start of activity up to and including date |
340 | * is the sum of all resource costs and other costs planned for this node. |
341 | */ |
342 | virtual double plannedCostTo(const QDate &/*date*/, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return 0; } |
343 | /// Actual cost up to and including date |
344 | virtual EffortCost actualCostTo( long int /*id*/, const QDate &/*date*/) const { return EffortCost(); } |
345 | |
346 | /// Returns the effort planned to be used to reach the actual percent finished |
347 | virtual Duration budgetedWorkPerformed( const QDate &, long = CURRENTSCHEDULE ) const = 0; |
348 | /// Returns the cost planned to be used to reach the actual percent finished |
349 | virtual double budgetedCostPerformed( const QDate &, long = CURRENTSCHEDULE ) const { return 0.0; }; |
350 | |
351 | /// Return map of Budgeted Cost of Work Scheduled pr day |
352 | virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); |
353 | /// Return map of Budgeted Cost of Work Scheduled pr day |
354 | virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const; |
355 | /// Budgeted Cost of Work Scheduled |
356 | virtual double bcws( const QDate &/*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return 0.0; } |
357 | |
358 | /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day) |
359 | virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); |
360 | /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day) |
361 | virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const; |
362 | /// Budgeted Cost of Work Performed |
363 | virtual double bcwp( long id ) const { Q_UNUSED(id); return 0.0; } |
364 | /// Budgeted Cost of Work Performed ( up to @p date ) |
365 | virtual double bcwp( const QDate &/*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return 0.0; } |
366 | |
367 | /// Return a map of Actual effort and Cost of Work Performed |
368 | virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); |
369 | /// Return a map of Actual effort and Cost of Work Performed |
370 | virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const; |
371 | /// Return Actual effort and Cost of Work Performed upto @date |
372 | virtual EffortCost acwp( const QDate &date, long id = CURRENTSCHEDULE ) const; |
373 | |
374 | /// Effort based performance index |
375 | virtual double effortPerformanceIndex(const QDate &/*date*/, long /*id*/ = CURRENTSCHEDULE ) const { return 0.0; } |
376 | /// Schedule performance index |
377 | virtual double schedulePerformanceIndex(const QDate &/*date*/, long /*id*/ = CURRENTSCHEDULE ) const { return 0.0; } |
378 | /// Cost performance index |
379 | virtual double costPerformanceIndex( long int /*id*/, const QDate &/*date*/, bool * /*error=0*/ ) const { return 0.0; } |
380 | |
381 | virtual void initiateCalculationLists(MainSchedule &sch) = 0; |
382 | virtual DateTime calculateForward(int /*use*/) = 0; |
383 | virtual DateTime calculateEarlyFinish(int /*use*/) { return DateTime(); } |
384 | virtual DateTime calculateBackward(int /*use*/) = 0; |
385 | virtual DateTime calculateLateStart(int /*use*/) { return DateTime(); } |
386 | virtual DateTime scheduleForward(const DateTime &, int /*use*/) = 0; |
387 | virtual DateTime scheduleFromStartTime(int /*use*/) { return DateTime(); } |
388 | virtual DateTime scheduleBackward(const DateTime &, int /*use*/) = 0; |
389 | virtual DateTime scheduleFromEndTime(int /*use*/) { return DateTime(); } |
390 | virtual void adjustSummarytask() = 0; |
391 | |
392 | /// Returns the (previously) calculated duration |
393 | Duration duration( long id = CURRENTSCHEDULE ) const; |
394 | |
395 | /** |
396 | * The variance is calculated based on |
397 | * the optimistic/pessimistic ratio specified for the estimate. |
398 | */ |
399 | double variance( long id = CURRENTSCHEDULE, Duration::Unit unit = Duration::Unit_ms ) const; |
400 | /** |
401 | * The standard deviation is calculated based on |
402 | * the optimistic/pessimistic ratio specified for the estimate. |
403 | */ |
404 | double deviation( long id = CURRENTSCHEDULE, Duration::Unit unit = Duration::Unit_ms ) const; |
405 | |
406 | Node *siblingBefore(); |
407 | Node *childBefore(Node *node); |
408 | Node *siblingAfter(); |
409 | Node *childAfter(Node *node); |
410 | bool moveChildUp(Node *node); |
411 | bool moveChildDown(Node *node); |
412 | |
413 | /// Check if this node can be linked to node |
414 | bool legalToLink( const Node *node ) const; |
415 | /// Check if node par can be linked to node child. (Reimplement) |
416 | virtual bool legalToLink( const Node *, const Node *) const { return false; } |
417 | |
418 | /// Save appointments for schedule with id |
419 | virtual void saveAppointments(QDomElement &element, long id) const; |
420 | ///Return the list of appointments for schedule with id. |
421 | QList<Appointment*> appointments( long id = CURRENTSCHEDULE ); |
422 | /// Adds appointment to this node only (not to resource) |
423 | virtual bool addAppointment(Appointment *appointment, Schedule &main); |
424 | |
425 | /// Return list of all resources with appointments to this task for schedule with @p id. |
426 | QList<Resource*> assignedResources( long id ) const; |
427 | |
428 | /// Find the node with my id |
429 | virtual Node *findNode() const { return findNode(m_id); } |
430 | /// Find the node with identity id |
431 | virtual Node *findNode(const QString &id) const |
432 | { return (m_parent ? m_parent->findNode(id) : 0); } |
433 | /// Remove myself from the id register |
434 | virtual bool removeId() { return removeId(m_id); } |
435 | /// Remove the registered identity @p id |
436 | virtual bool removeId(const QString &id) |
437 | { return (m_parent ? m_parent->removeId(id) : false); } |
438 | |
439 | /** |
440 | * This is when work can start on this node in accordance with |
441 | * the calendar of allocated resources. Normally this is the same |
442 | * as @ref startTime(), but may differ if timing constraints are set. |
443 | */ |
444 | virtual DateTime workStartTime( long id = CURRENTSCHEDULE ) const; |
445 | void setWorkStartTime(const DateTime &dt, long id = CURRENTSCHEDULE ); |
446 | |
447 | /** |
448 | * This is when work can finish on this node in accordance with |
449 | * the calendar of allocated resources. Normally this is the same |
450 | * as @ref endTime(), but may differ if timing constraints are set. |
451 | */ |
452 | virtual DateTime workEndTime( long id = CURRENTSCHEDULE ) const; |
453 | void setWorkEndTime(const DateTime &dt, long id = CURRENTSCHEDULE ); |
454 | |
455 | /// Returns true if this node is critical |
456 | virtual bool isCritical( long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return false; } |
457 | /// Returns true if this node is in a critical path |
458 | virtual bool inCriticalPath( long id = CURRENTSCHEDULE ) const; |
459 | |
460 | /// Returns the level this node is in the hierarchy. Top node is level 0. |
461 | virtual int level() const; |
462 | /// Generate WBS Code |
463 | virtual QString generateWBSCode( QList<int> &indexes ) const; |
464 | /// Returns the Work Breakdown Structure Code |
465 | QString wbsCode() const; |
466 | |
467 | double startupCost() const { return m_startupCost; } |
468 | void setStartupCost(double cost); |
469 | |
470 | Account *startupAccount() const { return m_startupAccount; } |
471 | void setStartupAccount(Account *acc); |
472 | |
473 | double shutdownCost() const { return m_shutdownCost; } |
474 | void setShutdownCost(double cost); |
475 | |
476 | Account *shutdownAccount() const { return m_shutdownAccount; } |
477 | void setShutdownAccount(Account *acc); |
478 | |
479 | Account *runningAccount() const { return m_runningAccount; } |
480 | void setRunningAccount(Account *acc); |
481 | |
482 | bool isBaselined( long int id = BASELINESCHEDULE ) const; |
483 | /** |
484 | * Return schedule with @p id |
485 | * If @p id == CURRENTSCHEDULE, return m_currentSchedule |
486 | * Return 0 if schedule with @p id doesn't exist. |
487 | */ |
488 | Schedule *schedule( long id = CURRENTSCHEDULE ) const; |
489 | /// Return current schedule |
490 | Schedule *currentSchedule() const { return m_currentSchedule; } |
491 | /// Set current schedule to schedule with identity @p id, for me and my children |
492 | virtual void setCurrentSchedule(long id); |
493 | /// Return true if this node has a valid schedule with identity == @p id |
494 | bool isScheduled( long id = CURRENTSCHEDULE ) const; |
495 | /// Return the list of schedules for this node |
496 | QHash<long, Schedule*> &schedules() { return m_schedules; } |
497 | /// Find schedule matching name and type. Does not return deleted schedule. |
498 | Schedule *findSchedule(const QString name, const Schedule::Type type); |
499 | /// Find schedule matching name. Does not return deleted schedule. |
500 | Schedule *findSchedule(const QString name); |
501 | /// Find schedule matching type. Does not return deleted schedule. |
502 | Schedule *findSchedule(const Schedule::Type type); |
503 | /// Find schedule matching id. Also returns deleted schedule. |
504 | Schedule *findSchedule(long id) const; |
505 | |
506 | /// Take, don't delete (as in destruct). |
507 | void takeSchedule(const Schedule *schedule); |
508 | /// Add schedule to list, replace if schedule with same id already exists. |
509 | void addSchedule(Schedule *schedule); |
510 | /// Create a new schedule. |
511 | Schedule *createSchedule(const QString& name, Schedule::Type type, long id); |
512 | /// Create a new schedule. |
513 | Schedule *createSchedule(Schedule *parent); |
514 | |
515 | /// Set deleted = onoff for schedule with id |
516 | void setScheduleDeleted(long id, bool onoff); |
517 | /// Set parent schedule recursivly |
518 | virtual void setParentSchedule(Schedule *sch); |
519 | |
520 | const ResourceRequestCollection &requests() const { return m_requests; } |
521 | ResourceRequestCollection &requests() { return m_requests; } |
522 | |
523 | virtual uint state( long ) const { return State_None; } |
524 | |
525 | const Documents &documents() const { return m_documents; } |
526 | Documents &documents() { return m_documents; } |
527 | |
528 | virtual void emitDocumentAdded( Node *node, Document *doc, int idx ); |
529 | virtual void emitDocumentRemoved( Node *node, Document *doc, int idx ); |
530 | virtual void emitDocumentChanged( Node *node, Document *doc, int idx ); |
531 | |
532 | public: |
533 | // These shouldn't be available to other than those who inherits |
534 | /// Calculate the critical path |
535 | virtual bool calcCriticalPath(bool fromEnd); |
536 | virtual void calcFreeFloat(); |
537 | |
538 | /// Check if this node has any dependent child nodes |
539 | virtual bool isEndNode() const; |
540 | /// Check if this node has any dependent parent nodes |
541 | virtual bool isStartNode() const; |
542 | |
543 | virtual void initiateCalculation(MainSchedule &sch); |
544 | virtual void resetVisited(); |
545 | void propagateEarliestStart(DateTime &time); |
546 | void propagateLatestFinish(DateTime &time); |
547 | void moveEarliestStart(DateTime &time); |
548 | void moveLatestFinish(DateTime &time); |
549 | // Reimplement this |
550 | virtual Duration summarytaskDurationForward(const DateTime &/*time*/) |
551 | { return Duration::zeroDuration; } |
552 | // Reimplement this |
553 | virtual DateTime summarytaskEarliestStart() |
554 | { return DateTime(); } |
555 | // Reimplement this |
556 | virtual Duration summarytaskDurationBackward(const DateTime &/*time*/) |
557 | { return Duration::zeroDuration; } |
558 | // Reimplement this |
559 | virtual DateTime summarytaskLatestFinish() |
560 | { return DateTime(); } |
561 | |
562 | /** |
563 | * earlyStart() returns earliest time this node can start |
564 | * given the constraints of the network. |
565 | */ |
566 | DateTime earlyStart( long id = CURRENTSCHEDULE ) const; |
567 | /** |
568 | * setEarlyStart() sets earliest time this node can start |
569 | */ |
570 | void setEarlyStart(const DateTime &dt, long id = CURRENTSCHEDULE ); |
571 | /** |
572 | * lateStart() returns latest time this node can start |
573 | * given the constraints of the network. |
574 | */ |
575 | DateTime lateStart( long id = CURRENTSCHEDULE ) const; |
576 | /** |
577 | * setLateStart() sets the earliest time this node can start |
578 | */ |
579 | void setLateStart(const DateTime &dt, long id = CURRENTSCHEDULE ); |
580 | /** |
581 | * earlyFinish() returns earliest time this node can finish |
582 | * given the constraints of the network. |
583 | */ |
584 | DateTime earlyFinish( long id = CURRENTSCHEDULE ) const; |
585 | /** |
586 | * setEarlyFinish() sets earliest time this node can finish |
587 | */ |
588 | void setEarlyFinish(const DateTime &dt, long id = CURRENTSCHEDULE ); |
589 | /** |
590 | * lateFinish() returns latest time this node can finish |
591 | * given the constraints of the network. |
592 | */ |
593 | DateTime lateFinish( long id = CURRENTSCHEDULE ) const; |
594 | /** |
595 | * setLateFinish() sets latest time this node can finish |
596 | */ |
597 | void setLateFinish(const DateTime &dt, long id = CURRENTSCHEDULE ); |
598 | |
599 | /// Adds appointment to both this node and resource |
600 | virtual void addAppointment(ResourceSchedule *resource, DateTime &start, DateTime &end, double load=100); |
601 | |
602 | virtual void clearProxyRelations() {} |
603 | virtual void addParentProxyRelations( const QList<Relation*> & ) {} |
604 | virtual void addChildProxyRelations( const QList<Relation*> & ) {} |
605 | virtual void addParentProxyRelation(Node *, const Relation *) {} |
606 | virtual void addChildProxyRelation(Node *, const Relation *) {} |
607 | |
608 | virtual void changed( int property = -1 ) { changed( this, property ); } |
609 | Duration getmDurationForward(){ return this->m_durationForward;} |
610 | |
611 | public slots: |
612 | void slotStandardWorktimeChanged( StandardWorktime* ); |
613 | |
614 | protected: |
615 | friend class KPlatoXmlLoaderBase; |
616 | /** |
617 | * Calculates and returns the duration of the node. |
618 | * Reimplement. |
619 | */ |
620 | virtual Duration duration(const DateTime &/*time*/, int /*use*/, bool /*backward*/) |
621 | { return Duration::zeroDuration; } |
622 | |
623 | // NOTE: Cannot use setCurrentSchedule() due to overload/casting problems |
624 | void setCurrentSchedulePtr(Schedule *schedule) { m_currentSchedule = schedule; } |
625 | virtual void changed(Node *node, int property = -1 ); |
626 | |
627 | QList<Node*> m_nodes; |
628 | QList<Relation*> m_dependChildNodes; |
629 | QList<Relation*> m_dependParentNodes; |
630 | QList<Node*>m_parentNodes; |
631 | Node *m_parent; |
632 | |
633 | |
634 | QString m_id; // unique id |
635 | QString m_name; // Name of this node |
636 | QString m_leader; // Person or group responsible for this node |
637 | QString m_description; // Description of this node |
638 | |
639 | Estimate *m_estimate; |
640 | |
641 | |
642 | ConstraintType m_constraint; |
643 | |
644 | /** |
645 | * m_constraintTime is used if any of the constraints |
646 | * FixedInterval, StartNotEarlier, MustStartOn or FixedInterval is selected |
647 | */ |
648 | DateTime m_constraintStartTime; |
649 | /** |
650 | * m_constraintEndTime is used if any of the constraints |
651 | * FixedInterval, FinishNotLater, MustFinishOn or FixedInterval is selected |
652 | */ |
653 | DateTime m_constraintEndTime; |
654 | |
655 | bool m_visitedForward; |
656 | bool m_visitedBackward; |
657 | Duration m_durationForward; |
658 | Duration m_durationBackward; |
659 | DateTime m_earlyStart; |
660 | DateTime m_earlyFinish; |
661 | DateTime m_lateFinish; |
662 | |
663 | QHash<long, Schedule*> m_schedules; |
664 | Schedule *m_currentSchedule; |
665 | |
666 | double m_startupCost; |
667 | Account *m_startupAccount; |
668 | double m_shutdownCost; |
669 | Account *m_shutdownAccount; |
670 | Account *m_runningAccount; |
671 | |
672 | Documents m_documents; |
673 | |
674 | ResourceRequestCollection m_requests; |
675 | |
676 | private: |
677 | void init(); |
678 | }; |
679 | |
680 | //////////////////////////////// Estimate //////////////////////////////// |
681 | /** |
682 | * The Estimate class stores how much time (or effort) it takes to complete a Task. |
683 | * The estimate which is needed to complete the task is not simply a single value but |
684 | * is stored as an optimistic, a pessimistic and an expected value. |
685 | * With statistical calculations using the PERT distribution, one can arrive at a more |
686 | * realistic estimate than when using the expected value alone. |
687 | */ |
688 | class KPLATOKERNEL_EXPORT Estimate { |
689 | public: |
690 | /// Constructor |
691 | explicit Estimate( Node *parent = 0 ); |
692 | /// Copy constructor. |
693 | Estimate (const Estimate &estimate, Node *parent = 0); |
694 | /// Destructor |
695 | ~Estimate(); |
696 | |
697 | /// Reset estimate |
698 | void clear(); |
699 | |
700 | /// Copy values from @p estimate |
701 | Estimate &operator=( const Estimate &estimate ); |
702 | |
703 | /// Type defines the types of estimates |
704 | enum Type { |
705 | Type_Effort, /// Changing amount of resources changes the task duration |
706 | Type_Duration /// Changing amount of resources will not change the tasks duration |
707 | }; |
708 | /// Return the node that owns this Estimate |
709 | Node *parentNode() const { return m_parent; } |
710 | /// Set the node that owns this Estimate |
711 | void setParentNode( Node* parent ) { m_parent = parent; } |
712 | |
713 | /// Return estimate Type |
714 | Type type() const { return m_type; } |
715 | /// Set estimate type to @p type |
716 | void setType(Type type); |
717 | /// Set estimate type to type represented by the string @p type |
718 | void setType(const QString& type); |
719 | /// Return estimate type as a string. If @p trans is true, it's translated |
720 | QString typeToString( bool trans=false ) const; |
721 | /// Return estimate type @p typ as a string. If @p trans is true, it's translated |
722 | static QString typeToString( Estimate::Type typ, bool trans=false ); |
723 | /// Return a stringlist of all estimate types. Translated if @p trans = true. |
724 | static QStringList typeToStringList( bool trans=false ); |
725 | |
726 | /// Return the calendar used when Type is Duration |
727 | Calendar *calendar() const { return m_calendar; } |
728 | /// Set the calendar to be used when Type is Duration |
729 | void setCalendar( Calendar *calendar ); |
730 | |
731 | enum Risktype { Risk_None, Risk_Low, Risk_High }; |
732 | Risktype risktype() const { return m_risktype; } |
733 | void setRisktype(Risktype type); |
734 | void setRisktype(const QString& type); |
735 | QString risktypeToString( bool trans=false ) const; |
736 | static QStringList risktypeToStringList( bool trans=false ); |
737 | |
738 | /// Use defines which value to access |
739 | enum Use { Use_Expected=0, Use_Optimistic=1, Use_Pessimistic=2 }; |
740 | |
741 | /// Return estimate (scaled) of type @p valueType. |
742 | /// If @p pert is true the pert value is calculated and returned |
743 | Duration value(int valueType, bool pert) const; |
744 | |
745 | /// Return unscaled value |
746 | Duration optimisticValue() const; |
747 | /// Return unscaled value |
748 | Duration pessimisticValue() const; |
749 | /// Return unscaled value |
750 | Duration expectedValue() const; |
751 | |
752 | /// The unit in which the estimates were entered. |
753 | Duration::Unit unit() const { return m_unit; } |
754 | /// Set display unit. |
755 | void setUnit( Duration::Unit unit ); |
756 | |
757 | /// Return the expected estimate (normally entered by user) |
758 | double expectedEstimate() const { return m_expectedEstimate; } |
759 | /// Return the optimistic estimate (normally entered by user) |
760 | double optimisticEstimate() const { return m_optimisticEstimate; } |
761 | /// Return the pessimistic estimate (normally entered by user) |
762 | double pessimisticEstimate() const { return m_pessimisticEstimate; } |
763 | /// Set the expected estimate |
764 | void setExpectedEstimate( double value ); |
765 | /// Set the optimistic estimate |
766 | void setOptimisticEstimate( double value ); |
767 | /// Set the pessimistic estimate |
768 | void setPessimisticEstimate( double value ); |
769 | |
770 | /** |
771 | * Set the optimistic estimate as a deviation from "expected" in percent |
772 | * @param percent should be a negative value. |
773 | */ |
774 | void setOptimisticRatio(int percent); |
775 | /** |
776 | * Return the "optimistic" estimate as deviation from "expected" in percent. |
777 | * This should be a negative value. |
778 | */ |
779 | int optimisticRatio() const; |
780 | /** |
781 | * Set the pessimistic estimate as a deviation from "expected" in percent |
782 | * @param percent should be a positive value. |
783 | */ |
784 | void setPessimisticRatio(int percent); |
785 | /** |
786 | * Return the "pessimistic" estimate as the deviation from "expected" in percent. |
787 | * This should be a positive value. |
788 | */ |
789 | int pessimisticRatio() const; |
790 | |
791 | /** |
792 | * The variance is calculated based on |
793 | * the optimistic/pessimistic estimates, scaled to current unit. |
794 | */ |
795 | double variance() const; |
796 | /** |
797 | * The variance is calculated based on |
798 | * the optimistic/pessimistic estimates, scaled to @p unit |
799 | */ |
800 | double variance( Duration::Unit unit ) const; |
801 | /** |
802 | * The standard deviation is calculated based on |
803 | * the optimistic/pessimistic estimates, scaled to current unit. |
804 | */ |
805 | double deviation() const; |
806 | /** |
807 | * The standard deviation is calculated based on |
808 | * the optimistic/pessimistic estimates, scaled to @p unit |
809 | */ |
810 | double deviation( Duration::Unit unit ) const; |
811 | |
812 | /// Returns the expected duration. Calculated based on the estimates expected, optimistic and pessimistic |
813 | Duration pertExpected() const; |
814 | /// Returns the most optimistic duration. Calculated based on the estimates expected, optimistic and pessimistic |
815 | Duration pertOptimistic() const; |
816 | /// Returns the most pessimistic duration. Calculated based on the estimates expected, optimistic and pessimistic |
817 | Duration pertPessimistic() const; |
818 | |
819 | /// Convert the duration @p value (in milliseconds) to a value in @p unit, using the scaling factors in @p scales |
820 | static double scale( const Duration &value, Duration::Unit unit, const QList<qint64> &scales ); |
821 | /// Convert the duration @p value (in @p unit) to a value in milliseconds (base unit), using the scaling factors in @p scales |
822 | static Duration scale( double value, Duration::Unit unit, const QList<qint64> &scales ); |
823 | |
824 | /// Return a list of default scales scaling factors |
825 | static QList<qint64> defaultScales(); |
826 | /// Return a list of scaling factors fetched from the projects standard worktime |
827 | QList<qint64> scales() const; |
828 | |
829 | /// Load from xml document |
830 | bool load(KoXmlElement &element, XMLLoaderObject &status); |
831 | /// Save to xml document |
832 | void save(QDomElement &element) const; |
833 | |
834 | protected: |
835 | /// Set (calculate) cached value |
836 | void setOptimisticValue(); |
837 | /// Set (calculate) cached value |
838 | void setExpectedValue(); |
839 | /// Set (calculate) cached value |
840 | void setPessimisticValue(); |
841 | /// Notify parent of changes |
842 | void changed() { if ( m_parent ) m_parent->changed(); } |
843 | /// Copy @p estimate, parentNode is not copied |
844 | void copy( const Estimate &estimate ); |
845 | |
846 | private: |
847 | friend class Node; |
848 | Node *m_parent; |
849 | /// Holds the unit entered by user |
850 | Duration::Unit m_unit; |
851 | /// Holds the value entered by user, in unit m_unit |
852 | double m_expectedEstimate; |
853 | /// Holds the value entered by user, in unit m_unit |
854 | double m_optimisticEstimate; |
855 | /// Holds the value entered by user, in unit m_unit |
856 | double m_pessimisticEstimate; |
857 | |
858 | mutable bool m_expectedCached, m_optimisticCached, m_pessimisticCached, m_pertCached; |
859 | /// Cached value in base unit (milliseconds) |
860 | Duration m_expectedValue; |
861 | /// Cached value in base unit (milliseconds) |
862 | Duration m_optimisticValue; |
863 | /// Cached value in base unit (milliseconds) |
864 | Duration m_pessimisticValue; |
865 | /// Cached pert expected value |
866 | mutable Duration m_pertExpected; |
867 | |
868 | Type m_type; |
869 | Risktype m_risktype; |
870 | |
871 | /// Calendar may be used when Type is Type_Duration |
872 | Calendar *m_calendar; |
873 | }; |
874 | |
875 | } //KPlato namespace |
876 | |
877 | #endif |
878 | |