summaryrefslogtreecommitdiffstats
path: root/kplato/kptschedule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kplato/kptschedule.cpp')
-rw-r--r--kplato/kptschedule.cpp681
1 files changed, 681 insertions, 0 deletions
diff --git a/kplato/kptschedule.cpp b/kplato/kptschedule.cpp
new file mode 100644
index 000000000..7581312e0
--- /dev/null
+++ b/kplato/kptschedule.cpp
@@ -0,0 +1,681 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Dag Andersen <danders@get2net.dk>
+
+ 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;
+ version 2 of the License.
+
+ 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 "kptschedule.h"
+
+#include "kptappointment.h"
+#include "kptdatetime.h"
+#include "kptduration.h"
+#include "kptnode.h"
+
+#include <tqdom.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+
+#include <tdelocale.h>
+#include <kdebug.h>
+
+namespace KPlato
+{
+
+Schedule::Schedule()
+ : m_type(Expected),
+ m_id(0),
+ m_deleted(false),
+ m_parent(0) {
+}
+
+Schedule::Schedule(Schedule *parent)
+ : m_type(Expected),
+ m_id(0),
+ m_deleted(false),
+ m_appointments(),
+ m_parent(parent) {
+
+ if (parent) {
+ m_name = parent->name();
+ m_type = parent->type();
+ m_id = parent->id();
+ }
+ m_appointments.setAutoDelete(true);
+ //kdDebug()<<k_funcinfo<<"("<<this<<") Name: '"<<name<<"' Type="<<type<<" id="<<id<<endl;
+}
+
+Schedule::Schedule(TQString name, Type type, long id)
+ : m_name(name),
+ m_type(type),
+ m_id(id),
+ m_deleted(false),
+ m_appointments(),
+ m_parent(0) {
+
+ //kdDebug()<<k_funcinfo<<"("<<this<<") Name: '"<<name<<"' Type="<<type<<" id="<<id<<endl;
+ m_appointments.setAutoDelete(true);
+}
+
+Schedule::~Schedule() {
+}
+
+void Schedule::setParent(Schedule *parent) {
+ m_parent = parent;
+}
+
+void Schedule::setDeleted(bool on) {
+ //kdDebug()<<k_funcinfo<<"deleted="<<on<<endl;
+ m_deleted = on;
+}
+
+bool Schedule::isDeleted() const {
+ return m_parent == 0 ? m_deleted : m_parent->isDeleted();
+}
+
+void Schedule::setType(const TQString type) {
+ m_type = Expected;
+ if (type == "Expected")
+ m_type = Expected;
+ else if (type == "Optimistic")
+ m_type = Optimistic;
+ else if (type == "Pessimistic")
+ m_type = Pessimistic;
+}
+
+TQString Schedule::typeToString(bool translate) const {
+ if (translate) {
+ if (m_type == Expected)
+ return i18n("Expected");
+ if (m_type == Optimistic)
+ return i18n("Optimistic");
+ if (m_type == Pessimistic)
+ return i18n("Pessimistic");
+ return i18n("Expected");
+ } else {
+ if (m_type == Expected)
+ return "Expected";
+ if (m_type == Optimistic)
+ return "Optimistic";
+ if (m_type == Pessimistic)
+ return "Pessimistic";
+ return "Expected";
+ }
+}
+
+void Schedule::initiateCalculation() {
+ resourceError = false;
+ resourceOverbooked = false;
+ schedulingError = false;
+ inCriticalPath = false;
+ workStartTime = DateTime();
+ workEndTime = DateTime();
+}
+
+void Schedule::calcResourceOverbooked() {
+ resourceOverbooked = false;
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ if (it.current()->resource()->isOverbooked(startTime, endTime)) {
+ resourceOverbooked = true;
+ break;
+ }
+ }
+}
+
+TQStringList Schedule::overbookedResources() const {
+ TQStringList rl;
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ if (it.current()->resource()->isOverbooked(it.current()->startTime(), it.current()->endTime())) {
+ rl += it.current()->resource()->resource()->name();
+ }
+ }
+ return rl;
+}
+
+bool Schedule::loadXML(const TQDomElement &sch) {
+ m_name = sch.attribute("name");
+ setType(sch.attribute("type"));
+ m_id = sch.attribute("id").toLong();
+ return true;
+}
+
+void Schedule::saveXML(TQDomElement &element) const {
+ TQDomElement sch = element.ownerDocument().createElement("schedule");
+ element.appendChild(sch);
+ saveCommonXML(sch);
+}
+
+void Schedule::saveCommonXML(TQDomElement &element) const {
+ //kdDebug()<<k_funcinfo<<m_name<<" save schedule"<<endl;
+ element.setAttribute("name", m_name);
+ element.setAttribute("type", typeToString());
+ element.setAttribute("id", m_id);
+}
+
+void Schedule::saveAppointments(TQDomElement &element) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ it.current()->saveXML(element);
+ }
+}
+
+bool Schedule::add(Appointment *appointment) {
+ if (m_appointments.findRef(appointment) != -1) {
+ kdError()<<k_funcinfo<<"Appointment allready exists"<<endl;
+ return false;
+ }
+ m_appointments.append(appointment);
+ //if (resource()) kdDebug()<<k_funcinfo<<"For resource '"<<resource()->name()<<"'"<<endl;
+ //if (node()) kdDebug()<<k_funcinfo<<"For node '"<<node()->name()<<"'"<<endl;
+ return true;
+}
+
+void Schedule::removeAppointment(Appointment *appointment) {
+ takeAppointment(appointment);
+ delete appointment;
+}
+
+void Schedule::takeAppointment(Appointment *appointment) {
+ int i = m_appointments.findRef(appointment);
+ if (i != -1) {
+ m_appointments.take(i);
+ //kdDebug()<<k_funcinfo<<"Taken: "<<appointment<<endl;
+ if (appointment->node())
+ appointment->node()->takeAppointment(appointment);
+ } else {
+ //kdDebug()<<k_funcinfo<<"Couldn't find appointment: "<<appointment<<endl;
+ }
+}
+
+Appointment *Schedule::findAppointment(Schedule *resource, Schedule *node) {
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ if (it.current()->node() == node && it.current()->resource() == resource)
+ return it.current();
+ }
+ return 0;
+}
+
+EffortCostMap Schedule::plannedEffortCostPrDay(const TQDate &start, const TQDate &end) const {
+ //kdDebug()<<k_funcinfo<<m_name<<endl;
+ EffortCostMap ec;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ //kdDebug()<<k_funcinfo<<m_name<<endl;
+ ec += it.current()->plannedPrDay(start, end);
+ }
+ return ec;
+}
+
+Duration Schedule::plannedEffort() const {
+ //kdDebug()<<k_funcinfo<<endl;
+ Duration eff;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ eff += it.current()->plannedEffort();
+ }
+ return eff;
+}
+
+Duration Schedule::plannedEffort(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ Duration eff;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ eff += it.current()->plannedEffort(date);
+ }
+ return eff;
+}
+
+Duration Schedule::plannedEffortTo(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ Duration eff;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ eff += it.current()->plannedEffortTo(date);
+ }
+ return eff;
+}
+
+Duration Schedule::actualEffort() const {
+ //kdDebug()<<k_funcinfo<<endl;
+ Duration eff;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ eff += it.current()->actualEffort();
+ }
+ return eff;
+}
+
+Duration Schedule::actualEffort(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ Duration eff;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ eff += it.current()->actualEffort(date);
+ }
+ return eff;
+}
+
+Duration Schedule::actualEffortTo(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ Duration eff;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ eff += it.current()->actualEffortTo(date);
+ }
+ return eff;
+}
+
+double Schedule::plannedCost() const {
+ //kdDebug()<<k_funcinfo<<endl;
+ double c = 0;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ c += it.current()->plannedCost();
+ }
+ return c;
+}
+
+double Schedule::plannedCost(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ double c = 0;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ c += it.current()->plannedCost(date);
+ }
+ return c;
+}
+
+double Schedule::plannedCostTo(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ double c = 0;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ c += it.current()->plannedCostTo(date);
+ }
+ return c;
+}
+
+double Schedule::actualCost() const {
+ //kdDebug()<<k_funcinfo<<endl;
+ double c = 0;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ c += it.current()->actualCost();
+ }
+ return c;
+}
+
+double Schedule::actualCost(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ double c = 0;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ c += it.current()->actualCost(date);
+ }
+ return c;
+}
+
+double Schedule::actualCostTo(const TQDate &date) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ double c = 0;
+ TQPtrListIterator<Appointment> it(m_appointments);
+ for (; it.current(); ++it) {
+ c += it.current()->actualCostTo(date);
+ }
+ return c;
+}
+
+//-------------------------------------------------
+NodeSchedule::NodeSchedule()
+ : Schedule(),
+ m_node(0) {
+ //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
+ init();
+}
+
+NodeSchedule::NodeSchedule(Node *node, TQString name, Schedule::Type type, long id)
+ : Schedule(name, type, id),
+ m_node(node) {
+ //kdDebug()<<k_funcinfo<<"node name: "<<node->name()<<endl;
+ init();
+}
+
+NodeSchedule::NodeSchedule(Schedule *parent, Node *node)
+ : Schedule(parent),
+ m_node(node) {
+
+ //kdDebug()<<k_funcinfo<<"node name: "<<node->name()<<endl;
+ init();
+}
+
+NodeSchedule::~NodeSchedule() {
+ //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
+}
+
+void NodeSchedule::init() {
+ resourceError = false;
+ resourceOverbooked = false;
+ resourceNotAvailable = false;
+ schedulingError = false;
+ notScheduled = true;
+ inCriticalPath = false;
+}
+
+void NodeSchedule::setDeleted(bool on) {
+ //kdDebug()<<k_funcinfo<<"deleted="<<on<<endl;
+ m_deleted = on;
+ // set deleted also for possible resource schedules
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ if (it.current()->resource()) {
+ it.current()->resource()->setDeleted(on);
+ }
+ }
+}
+
+bool NodeSchedule::loadXML(const TQDomElement &sch) {
+ //kdDebug()<<k_funcinfo<<endl;
+ TQString s;
+ Schedule::loadXML(sch);
+ s = sch.attribute("earlieststart");
+ if (s != "")
+ earliestStart = DateTime::fromString(s);
+ s = sch.attribute("latestfinish");
+ if (s != "")
+ latestFinish = DateTime::fromString(s);
+ s = sch.attribute("start");
+ if (s != "")
+ startTime = DateTime::fromString(s);
+ s = sch.attribute("end");
+ if (s != "")
+ endTime = DateTime::fromString(s);
+ s = sch.attribute("start-work");
+ if (s != "")
+ workStartTime = DateTime::fromString(s);
+ s = sch.attribute("end-work");
+ if (s != "")
+ workEndTime = DateTime::fromString(s);
+ duration = Duration::fromString(sch.attribute("duration"));
+
+ inCriticalPath = sch.attribute("in-critical-path", "0").toInt();
+ resourceError = sch.attribute("resource-error", "0").toInt();
+ resourceOverbooked = sch.attribute("resource-overbooked", "0").toInt();
+ resourceNotAvailable = sch.attribute("resource-not-available", "0").toInt();
+ schedulingError = sch.attribute("scheduling-conflict", "0").toInt();
+ notScheduled = sch.attribute("not-scheduled", "1").toInt();
+
+ return true;
+}
+
+void NodeSchedule::saveXML(TQDomElement &element) const {
+ //kdDebug()<<k_funcinfo<<endl;
+ TQDomElement sch = element.ownerDocument().createElement("schedule");
+ element.appendChild(sch);
+ saveCommonXML(sch);
+
+ if (earliestStart.isValid())
+ sch.setAttribute("earlieststart",earliestStart.toString(Qt::ISODate));
+ if (latestFinish.isValid())
+ sch.setAttribute("latestfinish",latestFinish.toString(Qt::ISODate));
+ if (startTime.isValid())
+ sch.setAttribute("start",startTime.toString(Qt::ISODate));
+ if (endTime.isValid())
+ sch.setAttribute("end",endTime.toString(Qt::ISODate));
+ if (workStartTime.isValid())
+ sch.setAttribute("start-work", workStartTime.toString(Qt::ISODate));
+ if (workEndTime.isValid())
+ sch.setAttribute("end-work", workEndTime.toString(Qt::ISODate));
+
+ sch.setAttribute("duration",duration.toString());
+
+ sch.setAttribute("in-critical-path",inCriticalPath);
+ sch.setAttribute("resource-error",resourceError);
+ sch.setAttribute("resource-overbooked",resourceOverbooked);
+ sch.setAttribute("resource-not-available",resourceNotAvailable);
+ sch.setAttribute("scheduling-conflict",schedulingError);
+ sch.setAttribute("not-scheduled",notScheduled);
+}
+
+void NodeSchedule::addAppointment(Schedule *resource, DateTime &start, DateTime &end, double load) {
+ //kdDebug()<<k_funcinfo<<endl;
+ Appointment *a = findAppointment(resource, this);
+ if (a != 0) {
+ //kdDebug()<<k_funcinfo<<"Add interval"<<endl;
+ a->addInterval(start, end, load);
+ return;
+ }
+ a = new Appointment(resource, this, start, end, load);
+ if (!add(a)) {
+ delete a;
+ }
+ if (!resource->add(a)) {
+ delete a;
+ }
+}
+
+//-----------------------------------------------
+ResourceSchedule::ResourceSchedule()
+ : Schedule(),
+ m_resource(0) {
+ //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
+}
+
+ResourceSchedule::ResourceSchedule(Resource *resource, TQString name, Schedule::Type type, long id)
+ : Schedule(name, type, id),
+ m_resource(resource),
+ m_parent(0) {
+ //kdDebug()<<k_funcinfo<<"resource: "<<resource->name()<<endl;
+}
+
+ResourceSchedule::ResourceSchedule(Schedule *parent, Resource *resource)
+ : Schedule(parent),
+ m_resource(resource),
+ m_parent(parent) {
+ //kdDebug()<<k_funcinfo<<"resource: "<<resource->name()<<endl;
+}
+
+ResourceSchedule::~ResourceSchedule() {
+ //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
+}
+
+void ResourceSchedule::addAppointment(Schedule *node, DateTime &start, DateTime &end, double load) {
+ //kdDebug()<<k_funcinfo<<endl;
+ Appointment *a = findAppointment(this, node);
+ if (a != 0) {
+ //kdDebug()<<k_funcinfo<<"Add interval"<<endl;
+ a->addInterval(start, end, load);
+ return;
+ }
+ a = new Appointment(this, node, start, end, load);
+ if (!add(a)) {
+ delete a;
+ }
+ if (!node->add(a)) {
+ delete a;
+ }
+}
+
+bool ResourceSchedule::isOverbooked() const {
+ return false;
+}
+
+bool ResourceSchedule::isOverbooked(const DateTime &start, const DateTime &end) const {
+ if (m_resource == 0)
+ return false;
+ //kdDebug()<<k_funcinfo<<start.toString()<<" - "<<end.toString()<<endl;
+ Appointment a = appointmentIntervals();
+ TQPtrListIterator<AppointmentInterval> it = a.intervals();
+ for (; it.current(); ++it) {
+ if ((!end.isValid() || it.current()->startTime() < end) &&
+ (!start.isValid() || it.current()->endTime() > start))
+ {
+ if (it.current()->load() > m_resource->units()) {
+ //kdDebug()<<k_funcinfo<<m_name<<" overbooked"<<endl;
+ return true;
+ }
+ }
+ if (it.current()->startTime() >= end)
+ break;
+ }
+ //kdDebug()<<k_funcinfo<<m_name<<" not overbooked"<<endl;
+ return false;
+}
+
+Appointment ResourceSchedule::appointmentIntervals() const {
+ Appointment a;
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ a += *(it.current());
+ }
+ return a;
+}
+
+double ResourceSchedule::normalRatePrHour() const {
+ return m_resource ? m_resource->normalRate() : 0.0;
+}
+
+//--------------------------------------
+MainSchedule::MainSchedule()
+ : NodeSchedule() {
+ //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
+ init();
+}
+
+MainSchedule::MainSchedule(Node *node, TQString name, Schedule::Type type, long id)
+ : NodeSchedule(node, name, type, id) {
+ //kdDebug()<<k_funcinfo<<"node name: "<<node->name()<<endl;
+ init();
+}
+
+MainSchedule::~MainSchedule() {
+ //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
+}
+
+bool MainSchedule::loadXML(const TQDomElement &sch, Project &project) {
+ kdDebug()<<k_funcinfo<<endl;
+ TQString s;
+ Schedule::loadXML(sch);
+
+ s = sch.attribute("start");
+ if (s != "")
+ startTime = DateTime::fromString(s);
+ s = sch.attribute("end");
+ if (s != "")
+ endTime = DateTime::fromString(s);
+
+ TQDomNodeList al = sch.childNodes();
+ kdDebug()<<k_funcinfo<<"No of appointments: "<<al.count()<<endl;
+ for (unsigned int i=0; i<al.count(); ++i) {
+ if (al.item(i).isElement()) {
+ TQDomElement app = al.item(i).toElement();
+ if (app.tagName() == "appointment") {
+ // Load the appointments.
+ // Resources and tasks must allready loaded
+ Appointment *child = new Appointment();
+ if (!child->loadXML(app, project, *this)) {
+ // TODO: Complain about this
+ kdError()<<k_funcinfo<<"Failed to load appointment"<<endl;
+ delete child;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void MainSchedule::saveXML(TQDomElement &element) const {
+ saveCommonXML(element);
+
+ element.setAttribute("start",startTime.toString(Qt::ISODate));
+ element.setAttribute("end",endTime.toString(Qt::ISODate));
+}
+
+#ifndef NDEBUG
+void Schedule::printDebug(TQString indent) {
+ kdDebug()<<indent<<"Schedule["<<m_id<<"] '"<<m_name<<"' type: "<<typeToString()<<" ("<<m_type<<")"<<(isDeleted()?" Deleted":"")<<endl;
+}
+void NodeSchedule::printDebug(TQString indent) {
+ Schedule::printDebug(indent);
+ indent += "! ";
+ if (m_parent == 0)
+ kdDebug()<<indent<<"No parent schedule!"<<endl;
+ if (!notScheduled) {
+ if (node()) kdDebug()<<indent<<"Node: "<<node()->name()<<endl;
+ else kdDebug()<<indent<<"No parent node!"<<endl;
+ }
+ kdDebug()<<indent<<"Not scheduled="<<notScheduled<<endl;
+ kdDebug()<<indent<<"Start time: "<<startTime.toString()<<endl;
+ kdDebug()<<indent<<"End time: " <<endTime.toString()<<endl;
+ kdDebug()<<indent<<"Duration: "<<duration.seconds()<<TQCString(" secs")<<" ("<<duration.toString()<<")"<<endl;
+ kdDebug()<<indent<<"Earliest start: "<<earliestStart.toString()<<endl;
+ kdDebug()<<indent<<"Latest finish: " <<latestFinish.toString()<<endl;
+
+ kdDebug()<<indent<<"resourceError="<<resourceError<<endl;
+ kdDebug()<<indent<<"schedulingError="<<schedulingError<<endl;
+ kdDebug()<<indent<<"resourceNotAvailable="<<resourceNotAvailable<<endl;
+ kdDebug()<<indent<<"Resource overbooked="<<resourceOverbooked<<endl;
+ kdDebug()<<indent<<" "<<overbookedResources()<<endl;
+
+ kdDebug()<<indent<<"inCriticalPath="<<inCriticalPath<<endl;
+ kdDebug()<<indent<<endl;
+ kdDebug()<<indent<<"workStartTime="<<workStartTime.toString()<<endl;
+ kdDebug()<<indent<<"workEndTime="<<workEndTime.toString()<<endl;
+ kdDebug()<<indent<<endl;
+ kdDebug()<<indent<<"Appointments: "<<m_appointments.count()<<endl;
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ it.current()->printDebug(indent + " ");
+ }
+}
+void ResourceSchedule::printDebug(TQString indent) {
+ Schedule::printDebug(indent);
+ indent += "! ";
+ if (m_parent == 0)
+ kdDebug()<<indent<<"No parent schedule!"<<endl;
+ if (resource()) kdDebug()<<indent<<"Resource: "<<resource()->name()<<endl;
+ else kdDebug()<<indent<<"No parent resource!"<<endl;
+ kdDebug()<<indent<<endl;
+ kdDebug()<<indent<<"Appointments: "<<m_appointments.count()<<endl;
+}
+
+void MainSchedule::printDebug(TQString indent) {
+ Schedule::printDebug(indent);
+ indent += "! ";
+ if (node()) kdDebug()<<indent<<"Node: "<<node()->name()<<endl;
+ else kdDebug()<<indent<<"No parent node!"<<endl;
+
+ kdDebug()<<indent<<"Not scheduled="<<notScheduled<<endl;
+ kdDebug()<<indent<<"Start time: "<<startTime.toString()<<endl;
+ kdDebug()<<indent<<"End time: " <<endTime.toString()<<endl;
+ kdDebug()<<indent<<"Duration: "<<duration.seconds()<<TQCString(" secs")<<" ("<<duration.toString()<<")"<<endl;
+ kdDebug()<<indent<<"Earliest start: "<<earliestStart.toString()<<endl;
+ kdDebug()<<indent<<"Latest finish: " <<latestFinish.toString()<<endl;
+
+ kdDebug()<<indent<<endl;
+ kdDebug()<<indent<<"Appointments: "<<m_appointments.count()<<endl;
+ TQPtrListIterator<Appointment> it = m_appointments;
+ for (; it.current(); ++it) {
+ it.current()->printDebug(indent + " ");
+ }
+}
+#endif
+
+} //namespace KPlato
+