1 /* This file is part of the KDE project
2    Copyright (C) 2005 - 2011 Dag Andersen <danders@get2net.dk>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18 */
19 
20 #ifndef KPTAPPOINTMENT_H
21 #define KPTAPPOINTMENT_H
22 
23 #include "plankernel_export.h"
24 
25 #include "kptglobal.h"
26 
27 #include "kptduration.h"
28 #include "kptdatetime.h"
29 
30 #include <KoXmlReaderForward.h>
31 
32 #include <QString>
33 #include <QList>
34 #include <QMultiMap>
35 #include <QSharedData>
36 
37 class QDomElement;
38 
39 namespace KPlato
40 {
41 
42 class Effort;
43 class Appointment;
44 class Node;
45 class Resource;
46 class EffortCost;
47 class EffortCostMap;
48 class Schedule;
49 class XMLLoaderObject;
50 class DateTimeInterval;
51 class TimeInterval;
52 
53 class AppointmentIntervalData : public QSharedData
54 {
55 public:
AppointmentIntervalData()56     AppointmentIntervalData() : load(0) {}
AppointmentIntervalData(const AppointmentIntervalData & other)57     AppointmentIntervalData(const AppointmentIntervalData &other)
58         : QSharedData(other), start(other.start), end(other.end), load(other.load) {}
~AppointmentIntervalData()59     ~AppointmentIntervalData() {}
60 
61     DateTime start;
62     DateTime end;
63     double load; //percent
64 };
65 
66 class PLANKERNEL_EXPORT AppointmentInterval
67 {
68 public:
69     AppointmentInterval();
70     AppointmentInterval(const AppointmentInterval &AppointmentInterval);
71     AppointmentInterval(const DateTime &start, const DateTime &end, double load=100);
72     AppointmentInterval(QDate date, const TimeInterval &timeInterval, double load=100);
73     ~AppointmentInterval();
74 
75     Duration effort() const;
76     Duration effort(const DateTime &start, const DateTime &end) const;
77     Duration effort(QDate time, bool upto) const;
78 
79     bool loadXML(KoXmlElement &element, XMLLoaderObject &status);
80     void saveXML(QDomElement &element) const;
81 
82     const DateTime &startTime() const;
83     void setStartTime(const DateTime &time);
84     const DateTime &endTime() const;
85     void setEndTime(const DateTime &time);
86     double load() const;
87     void setLoad(double load);
88 
89     bool isValid() const;
90     AppointmentInterval firstInterval(const AppointmentInterval &interval, const DateTime &from) const;
91 
92     bool operator==(const AppointmentInterval &interval) const;
93     bool operator<(const AppointmentInterval &interval) const;
94 
95     bool intersects(const AppointmentInterval &other) const;
96     AppointmentInterval interval(const DateTime &start, const DateTime &end) const;
97 
98     QString toString() const;
99 
100 private:
101     QSharedDataPointer<AppointmentIntervalData> d;
102 };
103 PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::AppointmentInterval& i);
104 
105 
106 /**
107  * This list is sorted after 1) startdatetime, 2) enddatetime.
108  * The intervals do not overlap, an interval does not start before the
109  * previous interval ends.
110  */
111 class PLANKERNEL_EXPORT AppointmentIntervalList
112 {
113 public:
114     AppointmentIntervalList();
115     AppointmentIntervalList(const QMultiMap<QDate, AppointmentInterval> &other);
116 
117     /// Add @p interval to the list. Handle overlapping with existing intervals.
118     void add(const AppointmentInterval &interval);
119     /// Add an interval to the list. Handle overlapping with existing intervals.
120     void add(const DateTime &st, const DateTime &et, double load);
121     /// Load intervals from document
122     bool loadXML(KoXmlElement &element, XMLLoaderObject &status);
123     /// Save intervals to document
124     void saveXML(QDomElement &element) const;
125 
126     AppointmentIntervalList &operator+=(const AppointmentIntervalList &lst);
127     AppointmentIntervalList &operator-=(const AppointmentIntervalList &lst);
128     AppointmentIntervalList &operator=(const AppointmentIntervalList &lst);
129 
130     /// Returns the intervals in the range @p start, @p end
131     AppointmentIntervalList extractIntervals(const DateTime &start, const DateTime &end) const;
132 
133     /// Return the total effort
134     Duration effort() const;
135     /// Return the effort limited to the interval @p start, @p end
136     Duration effort(const DateTime &start, const DateTime &end) const;
137 
138     QMultiMap<QDate, AppointmentInterval> map();
139     const QMultiMap<QDate, AppointmentInterval> &map() const;
isEmpty()140     bool isEmpty() const { return m_map.isEmpty(); }
clear()141     void clear() { m_map.clear(); }
142 
143 protected:
144     void subtract(const AppointmentInterval &interval);
145     void subtract(const DateTime &st, const DateTime &et, double load);
146 
147 private:
148     QMultiMap<QDate, AppointmentInterval> m_map;
149 };
150 PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::AppointmentIntervalList& i);
151 
152 /**
153  * A Resource can be scheduled to be used at any time,
154  * this is represented internally with Appointments
155  * There is one Appointment per resource-task pair.
156  * An appointment can be divided into several intervals, represented with
157  * a list of AppointmentInterval.
158  * This list is sorted after 1) startdatetime, 2) enddatetime.
159  * The intervals do not overlap, an interval does not start before the
160  * previous interval ends.
161  * An interval is a continuous time interval with the same load. It can span dates.
162  */
163 class PLANKERNEL_EXPORT Appointment {
164 public:
165     explicit Appointment();
166     Appointment(Schedule *resource, Schedule *node, const DateTime &start, const DateTime &end, double load);
167     Appointment(Schedule *resource, Schedule *node, const DateTime &start, Duration duration, double load);
168     Appointment(const Appointment &app);
169     ~Appointment();
170 
isEmpty()171     bool isEmpty() const { return m_intervals.isEmpty(); }
172     void clear();
173 
174     // get/set member values.
node()175     Schedule *node() const { return m_node; }
setNode(Schedule * n)176     void setNode(Schedule *n) { m_node = n; }
177 
resource()178     Schedule *resource() const { return m_resource; }
setResource(Schedule * r)179     void setResource(Schedule *r) { m_resource = r; }
180 
181     DateTime startTime() const;
182     DateTime endTime() const;
183     double maxLoad() const;
184 
repeatInterval()185     const Duration &repeatInterval() const {return m_repeatInterval;}
setRepeatInterval(Duration ri)186     void setRepeatInterval(Duration ri) {m_repeatInterval=ri;}
187 
repeatCount()188     int repeatCount() const { return m_repeatCount; }
setRepeatCount(int rc)189     void setRepeatCount(int rc) { m_repeatCount=rc; }
190 
191     bool isBusy(const DateTime &start, const DateTime &end);
192 
193     /// attach appointment to resource and node
194     bool attach();
195     /// detach appointment from resource and node
196     void detach();
197 
198     void addInterval(const AppointmentInterval &a);
199     void addInterval(const DateTime &start, const DateTime &end, double load=100);
200     void addInterval(const DateTime &start, KPlato::Duration duration, double load=100);
201     void setIntervals(const AppointmentIntervalList &lst);
202 
intervals()203     const AppointmentIntervalList &intervals() const { return m_intervals; }
count()204     int count() const { return m_intervals.map().count(); }
intervalAt(int index)205     AppointmentInterval intervalAt(int index) const { return m_intervals.map().values().value(index); }
206     /// Return intervals between @p start and @p end
207     AppointmentIntervalList intervals(const DateTime &start, const DateTime &end) const;
208 
209     bool loadXML(KoXmlElement &element, XMLLoaderObject &status, Schedule &sch);
210     void saveXML(QDomElement &element) const;
211 
212     /**
213      * Returns the planned effort and cost for the interval start to end (inclusive).
214      * Only dates with any planned effort is returned.
215      * If start or end is not valid, startTime.date() respectively endTime().date() is used.
216      */
217     EffortCostMap plannedPrDay(QDate start, QDate end, EffortCostCalculationType type = ECCT_All) const;
218 
219     /// Returns the planned effort from start to end
220     Duration effort(const DateTime &start, const DateTime &end, EffortCostCalculationType type = ECCT_All) const;
221     /// Returns the planned effort from start for the duration
222     Duration effort(const DateTime &start, KPlato::Duration duration, EffortCostCalculationType type = ECCT_All) const;
223 
224     /// Returns the total planned effort for @p resource on this appointment
225     Duration plannedEffort(const Resource *resource, EffortCostCalculationType type = ECCT_All) const;
226     /// Returns the total planned effort for this appointment
227     Duration plannedEffort(EffortCostCalculationType type = ECCT_All) const;
228     /// Returns the planned effort on the date
229     Duration plannedEffort(QDate date, EffortCostCalculationType type = ECCT_All) const;
230     /// Returns the planned effort for @p resource on the @p date date
231     Duration plannedEffort(const Resource *resource, QDate date, EffortCostCalculationType type = ECCT_All) const;
232     /// Returns the planned effort upto and including date
233     Duration plannedEffortTo(QDate date, EffortCostCalculationType type = ECCT_All) const;
234     /// Returns the planned effort upto and including date
235     Duration plannedEffortTo(const Resource *resource, QDate date, EffortCostCalculationType type = ECCT_All) const;
236 
237     /// Returns the planned effort upto and including @p time
238     Duration plannedEffortTo(const QDateTime &time, EffortCostCalculationType type = ECCT_All) const;
239 
240      /// Calculates the total planned cost for this appointment
241     EffortCost plannedCost(EffortCostCalculationType type = ECCT_All) const;
242     /// Calculates the planned cost on date
243     double plannedCost(QDate date, EffortCostCalculationType type = ECCT_All);
244     /// Calculates the planned cost upto and including date
245     double plannedCostTo(QDate date, EffortCostCalculationType type = ECCT_All);
246 
247     Appointment &operator=(const Appointment &app);
248     Appointment &operator+=(const Appointment &app);
249     Appointment operator+(const Appointment &app);
250     Appointment &operator-=(const Appointment &app);
251 
setCalculationMode(int mode)252     void setCalculationMode(int mode) { m_calculationMode = mode; }
calculationMode()253     int calculationMode() const { return m_calculationMode; }
254 
255     void merge(const Appointment &app);
256     Appointment extractIntervals(const DateTimeInterval &interval) const;
257 
setAuxcilliaryInfo(const QString & info)258     void setAuxcilliaryInfo(const QString &info) { m_auxcilliaryInfo = info; }
auxcilliaryInfo()259     QString auxcilliaryInfo() const { return m_auxcilliaryInfo; }
260 
261 protected:
262     void copy(const Appointment &app);
263 
264 private:
265     Schedule *m_node;
266     Schedule *m_resource;
267     int m_calculationMode; // Type of appointment
268     Duration m_repeatInterval;
269     int m_repeatCount;
270     QList<Duration*> m_extraRepeats;
271     QList<Duration*> m_skipRepeats;
272 
273     AppointmentIntervalList m_intervals;
274 
275     QString m_auxcilliaryInfo;
276 };
277 
278 
279 }  //KPlato namespace
280 
281 #endif
282