diff --git a/src/libs/kernel/kptresourcerequest.cpp b/src/libs/kernel/kptresourcerequest.cpp index bdc0946b..029af338 100644 --- a/src/libs/kernel/kptresourcerequest.cpp +++ b/src/libs/kernel/kptresourcerequest.cpp @@ -1,911 +1,931 @@ /* This file is part of the KDE project * Copyright (C) 2001 Thomas Zander zander@kde.org * Copyright (C) 2004-2007 Dag Andersen * Copyright (C) 2011 Dag Andersen * Copyright (C) 2019 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. */ // clazy:excludeall=qstring-arg #include "kptresourcerequest.h" #include "ResourceGroup.h" #include "Resource.h" #include "kptlocale.h" #include "kptaccount.h" #include "kptappointment.h" #include "kptproject.h" #include "kpttask.h" #include "kptdatetime.h" #include "kptcalendar.h" #include "kpteffortcostmap.h" #include "kptschedule.h" #include "kptxmlloaderobject.h" #include "kptdebug.h" #include #include #include #include using namespace KPlato; ResourceRequest::ResourceRequest(Resource *resource, int units) : m_id(0), m_resource(resource), m_units(units), m_collection(nullptr), m_dynamic(false) { if (resource) { m_required = resource->requiredResources(); } //debugPlan<<"("<name() : QString("None")); } ResourceRequest::ResourceRequest(const ResourceRequest &r) : m_id(r.m_id), m_resource(r.m_resource), m_units(r.m_units), m_collection(nullptr), m_dynamic(r.m_dynamic), m_required(r.m_required), m_alternativeRequests(r.m_alternativeRequests) { } ResourceRequest::~ResourceRequest() { if (m_resource) { m_resource->unregisterRequest(this); } m_resource = 0; if (m_collection && m_collection->contains(this)) { m_collection->removeResourceRequest(this); } } ResourceRequestCollection *ResourceRequest::collection() const { return m_collection; } void ResourceRequest::setCollection(ResourceRequestCollection *collection) { m_collection = collection; } int ResourceRequest::id() const { return m_id; } void ResourceRequest::setId(int id) { m_id = id; } void ResourceRequest::registerRequest() { if (m_resource) m_resource->registerRequest(this); } void ResourceRequest::unregisterRequest() { if (m_resource) m_resource->unregisterRequest(this); } bool ResourceRequest::load(KoXmlElement &element, Project &project) { debugPlanXml<id()); me.setAttribute("units", QString::number(m_units)); } int ResourceRequest::units() const { //debugPlan<name()<<": units="<task() : 0; } void ResourceRequest::changed() { if (task()) { task()->changed(Node::ResourceRequestProperty); } } void ResourceRequest::setCurrentSchedulePtr(Schedule *ns) { setCurrentSchedulePtr(m_resource, ns); } void ResourceRequest::setCurrentSchedulePtr(Resource *resource, Schedule *ns) { resource->setCurrentSchedulePtr(resourceSchedule(ns, resource)); if(resource->type() == Resource::Type_Team) { foreach (Resource *member, resource->teamMembers()) { member->setCurrentSchedulePtr(resourceSchedule(ns, member)); } } foreach (Resource *r, m_required) { r->setCurrentSchedulePtr(resourceSchedule(ns, r)); } } Schedule *ResourceRequest::resourceSchedule(Schedule *ns, Resource *res) { if (ns == 0) { return 0; } Resource *r = res == 0 ? resource() : res; Schedule *s = r->findSchedule(ns->id()); if (s == 0) { s = r->createSchedule(ns->parent()); } s->setCalculationMode(ns->calculationMode()); s->setAllowOverbookingState(ns->allowOverbookingState()); static_cast(s)->setNodeSchedule(ns); //debugPlan<name()<<": id="<id()<<" mode="<calculationMode(); return s; } DateTime ResourceRequest::workTimeAfter(const DateTime &dt, Schedule *ns) { if (m_resource->type() == Resource::Type_Work) { DateTime t = availableAfter(dt, ns); foreach (Resource *r, m_required) { if (! t.isValid()) { break; } t = r->availableAfter(t, DateTime(), resourceSchedule(ns, r)); } return t; } else if (m_resource->type() == Resource::Type_Team) { return availableAfter(dt, ns); } return DateTime(); } DateTime ResourceRequest::workTimeBefore(const DateTime &dt, Schedule *ns) { if (m_resource->type() == Resource::Type_Work) { DateTime t = availableBefore(dt, ns); foreach (Resource *r, m_required) { if (! t.isValid()) { break; } t = r->availableBefore(t, DateTime(), resourceSchedule(ns, r)); } return t; } else if (m_resource->type() == Resource::Type_Team) { return availableBefore(dt, ns); } return DateTime(); } DateTime ResourceRequest::availableFrom() { DateTime dt = m_resource->availableFrom(); if (! dt.isValid()) { dt = m_resource->project()->constraintStartTime(); } return dt; } DateTime ResourceRequest::availableUntil() { DateTime dt = m_resource->availableUntil(); if (! dt.isValid()) { dt = m_resource->project()->constraintEndTime(); } return dt; } DateTime ResourceRequest::availableAfter(const DateTime &time, Schedule *ns) { if (m_resource->type() == Resource::Type_Team) { DateTime t;// = m_resource->availableFrom(); foreach (Resource *r, m_resource->teamMembers()) { setCurrentSchedulePtr(r, ns); DateTime x = r->availableAfter(time); if (x.isValid()) { t = t.isValid() ? qMin(t, x) : x; } } return t; } setCurrentSchedulePtr(ns); return m_resource->availableAfter(time); } DateTime ResourceRequest::availableBefore(const DateTime &time, Schedule *ns) { if (m_resource->type() == Resource::Type_Team) { DateTime t; foreach (Resource *r, m_resource->teamMembers()) { setCurrentSchedulePtr(r, ns); DateTime x = r->availableBefore(time); if (x.isValid()) { t = t.isValid() ? qMax(t, x) : x; } } return t; } setCurrentSchedulePtr(ns); return resource()->availableBefore(time); } Duration ResourceRequest::effort(const DateTime &time, const Duration &duration, Schedule *ns, bool backward) { Duration e; if (m_resource->type() == Resource::Type_Team) { for (ResourceRequest *rr : teamMembers()) { e += rr->effort(time, duration, ns, backward); } } else { setCurrentSchedulePtr(ns); e = m_resource->effort(time, duration, m_units, backward, m_required); } //debugPlan<name()<makeAppointment(ns, (m_resource->units() * m_units / 100), m_required); } } void ResourceRequest::makeAppointment(Schedule *ns, int amount) { if (m_resource) { setCurrentSchedulePtr(ns); m_resource->makeAppointment(ns, amount, m_required); } } long ResourceRequest::allocationSuitability(const DateTime &time, const Duration &duration, Schedule *ns, bool backward) { setCurrentSchedulePtr(ns); return resource()->allocationSuitability(time, duration, backward); } QList ResourceRequest::teamMembers() const { qDeleteAll(m_teamMembers); m_teamMembers.clear(); if (m_resource->type() == Resource::Type_Team) { foreach (Resource *r, m_resource->teamMembers()) { m_teamMembers << new ResourceRequest(r, m_units); } } return m_teamMembers; } +QList ResourceRequest::requiredResources() const +{ + return m_required; +} + +void ResourceRequest::setRequiredResources(const QList &lst) +{ + m_required = lst; + changed(); +} + +void ResourceRequest::addRequiredResource(Resource *resource) +{ + Q_ASSERT(!m_required.contains(resource)); + if (!m_required.contains(resource)) { + m_required << resource; + changed(); + } +} + QList ResourceRequest::alternativeRequests() const { return m_alternativeRequests; } void ResourceRequest::setAlternativeRequests(const QList requests) { for (ResourceRequest *r : m_alternativeRequests) { removeAlternativeRequest(r); } for (ResourceRequest *r : requests) { addAlternativeRequest(r); } } bool ResourceRequest::addAlternativeRequest(ResourceRequest *request) { emitAlternativeRequestToBeAdded(this, m_alternativeRequests.count()); m_alternativeRequests.append(request); emitAlternativeRequestAdded(request); return true; } bool ResourceRequest::removeAlternativeRequest(ResourceRequest *request) { emitAlternativeRequestToBeRemoved(this, m_alternativeRequests.indexOf(request), request); m_alternativeRequests.removeAll(request); emitAlternativeRequestRemoved(); return true; } void ResourceRequest::emitAlternativeRequestToBeAdded(ResourceRequest *request, int row) { if (m_collection) { emit m_collection->alternativeRequestToBeAdded(request, row); } } void ResourceRequest::emitAlternativeRequestAdded(ResourceRequest *alternative) { if (m_collection) { emit m_collection->alternativeRequestAdded(alternative); } } void ResourceRequest::emitAlternativeRequestToBeRemoved(ResourceRequest *request, int row, ResourceRequest *alternative) { if (m_collection) { emit m_collection->alternativeRequestToBeRemoved(request, row, alternative); } } void ResourceRequest::emitAlternativeRequestRemoved() { if (m_collection) { emit m_collection->alternativeRequestRemoved(); } } ///////// ResourceRequestCollection::ResourceRequestCollection(Task *task) : QObject() , m_task(task) , m_lastResourceId(0) { //debugPlan<setCollection(nullptr); } qDeleteAll(m_resourceRequests); // removes themselves from possible group } bool ResourceRequestCollection::contains(ResourceRequest *request) const { return m_resourceRequests.contains(request->id()) && m_resourceRequests.value(request->id()) == request; } void ResourceRequestCollection::removeRequests() { const QList resourceRequests = m_resourceRequests.values(); for (ResourceRequest *r : resourceRequests) { removeResourceRequest(r); } } Task *ResourceRequestCollection::task() const { return m_task; } void ResourceRequestCollection::setTask(Task *t) { m_task = t; } void ResourceRequestCollection::addResourceRequest(ResourceRequest *request) { int id = request->id(); m_lastResourceId = std::max(m_lastResourceId, id); Q_ASSERT(!m_resourceRequests.contains(id)); if (id == 0) { while (m_resourceRequests.contains(++m_lastResourceId)) { } request->setId(m_lastResourceId); } Q_ASSERT(!m_resourceRequests.contains(request->id())); request->setCollection(this); request->registerRequest(); m_resourceRequests.insert(request->id(), request); if (m_task) { m_task->changed(Node::ResourceRequestProperty); } } void ResourceRequestCollection::removeResourceRequest(ResourceRequest *request) { Q_ASSERT(m_resourceRequests.contains(request->id())); Q_ASSERT(m_resourceRequests.values().contains(request)); m_resourceRequests.remove(request->id()); request->unregisterRequest(); Q_ASSERT(!m_resourceRequests.values().contains(request)); if (m_task) { m_task->changed(Node::ResourceRequestProperty); } } void ResourceRequestCollection::deleteResourceRequest(ResourceRequest *request) { delete request; } ResourceRequest *ResourceRequestCollection::find(const Resource *resource) const { for (ResourceRequest *r : m_resourceRequests) { if (r->resource() == resource) { return r; } } return nullptr; } ResourceRequest *ResourceRequestCollection::resourceRequest(int id) const { return m_resourceRequests.value(id); } ResourceRequest *ResourceRequestCollection::resourceRequest(const QString &name) const { for (ResourceRequest *r : m_resourceRequests) { if (r->resource()->name() == name) { return r; } } return nullptr; } QStringList ResourceRequestCollection::requestNameList() const { QStringList lst; for (ResourceRequest *r : m_resourceRequests) { lst << r->resource()->name(); } return lst; } QList ResourceRequestCollection::requestedResources() const { QList lst; for (ResourceRequest *r : m_resourceRequests) { lst += r->resource(); } return lst; } QList ResourceRequestCollection::resourceRequests(bool resolveTeam) const { QList lst = m_resourceRequests.values(); if (resolveTeam) { for (ResourceRequest *r : m_resourceRequests) { lst += r->teamMembers(); } } return lst; } bool ResourceRequestCollection::contains(const QString &identity) const { QStringList lst = requestNameList(); return lst.indexOf(QRegExp(identity, Qt::CaseSensitive, QRegExp::FixedString)) != -1; } // bool ResourceRequestCollection::load(KoXmlElement &element, Project &project) { // //debugPlan; // return true; // } void ResourceRequestCollection::save(QDomElement &element) const { //debugPlan; for (ResourceRequest *r : m_resourceRequests) { r->save(element); } } // Returns the duration needed by the working resources // "Material type" of resourcegroups does not (atm) affect the duration. Duration ResourceRequestCollection::duration(const DateTime &time, const Duration &effort, Schedule *ns, bool backward) { //debugPlan<<"time="<workTimeBefore(time, ns); if (t.isValid() && (!end.isValid() ||t > end)) end = t; } if (!end.isValid() || end > time) end = time; return end; } DateTime ResourceRequestCollection::availableAfter(const DateTime &time, Schedule *ns) { DateTime start; // TODO: Alternatives for (ResourceRequest *r : m_resourceRequests) { DateTime t = r->availableAfter(time, ns); if (t.isValid() && (!start.isValid() || t < start)) start = t; } if (start.isValid() && start < time) start = time; //debugPlan<availableBefore(time, ns); if (t.isValid() && (!end.isValid() ||t > end)) end = t; } if (!end.isValid() || end > time) end = time; return end; } DateTime ResourceRequestCollection::workStartAfter(const DateTime &time, Schedule *ns) { DateTime start; // TODO: Alternatives for (ResourceRequest *r : m_resourceRequests) { if (r->resource()->type() != Resource::Type_Work) { continue; } DateTime t = r->availableAfter(time, ns); if (t.isValid() && (!start.isValid() || t < start)) start = t; } if (start.isValid() && start < time) start = time; //debugPlan<resource()->type() != Resource::Type_Work) { continue; } DateTime t = r->availableBefore(time, ns); if (t.isValid() && (!end.isValid() ||t > end)) end = t; } if (!end.isValid() || end > time) end = time; return end; } void ResourceRequestCollection::makeAppointments(Schedule *schedule) { //debugPlan; // TODO: Alternatives for (ResourceRequest *r : m_resourceRequests) { r->makeAppointment(schedule); } } void ResourceRequestCollection::reserve(const DateTime &start, const Duration &duration) { //debugPlan; // TODO: Alternatives for (ResourceRequest *r : m_resourceRequests) { // r->reserve(start, duration); //FIXME } } bool ResourceRequestCollection::isEmpty() const { return m_resourceRequests.isEmpty(); } void ResourceRequestCollection::changed() { //debugPlan<changed(Node::ResourceRequestProperty); } } void ResourceRequestCollection::resetDynamicAllocations() { //TODO } Duration ResourceRequestCollection::effort(const QList &lst, const DateTime &time, const Duration &duration, Schedule *ns, bool backward) const { Duration e; foreach (ResourceRequest *r, lst) { e += r->effort(time, duration, ns, backward); //debugPlan<<(backward?"(B)":"(F)")<availableUntil(); if (!t2.isValid() || t2 < t1) t2 = t1; } //debugPlan<<"fw"< &lst, const DateTime &time, const Duration &_effort, Schedule *ns, bool backward) { //debugPlan<<"--->"<<(backward?"(B)":"(F)")<resource()->name(); } ns->logDebug("Match effort:" + time.toString() + "," + _effort.toString()); ns->logDebug("Resources: " + (nl.isEmpty() ? QString("None") : nl.join(", "))); } #endif QLocale locale; Duration e; if (_effort == Duration::zeroDuration) { return e; } DateTime logtime = time; bool match = false; DateTime start = time; int inc = backward ? -1 : 1; DateTime end = start; Duration e1; int nDays = numDays(lst, time, backward) + 1; int day = 0; for (day=0; !match && day <= nDays; ++day) { // days end = end.addDays(inc); e1 = effort(lst, start, backward ? start - end : end - start, ns, backward); //debugPlan<<"["<logDebug("Days: duration " + logtime.toString() + " - " + end.toString() + " e=" + e.toString() + " (" + (_effort - e).toString() + ')'); #endif logtime = start; for (int i=0; !match && i < 24; ++i) { // hours end = end.addSecs(inc*60*60); e1 = effort(lst, start, backward ? start - end : end - start, ns, backward); if (e + e1 < _effort) { e += e1; start = end; } else if (e + e1 == _effort) { e += e1; match = true; } else { if (false/*roundToHour*/ && (_effort - e) < (e + e1 - _effort)) { end = start; match = true; } else { end = start; } break; } //debugPlan<<"duration(h)["< _effort) { end = start; break; } //debugPlan<<"duration(m)"<<(backward?"backward":"forward:")<<" time="<logDebug("Minutes: duration " + logtime.toString() + " - " + end.toString() + " e=" + e.toString() + " (" + (_effort - e).toString() + ')'); #endif logtime = start; for (int i=0; !match && i < 60; ++i) { //seconds end = end.addSecs(inc); e1 = effort(lst, start, backward ? start - end : end - start, ns, backward); if (e + e1 < _effort) { e += e1; start = end; } else if (e + e1 == _effort) { e += e1; match = true; } else if (e + e1 > _effort) { end = start; break; } //debugPlan<<"duration(s)["<logDebug("Seconds: duration " + logtime.toString() + " - " + end.toString() + " e=" + e.toString() + " (" + (_effort - e).toString() + ')'); #endif for (int i=0; !match && i < 1000; ++i) { //milliseconds end.setTime(end.time().addMSecs(inc)); e1 = effort(lst, start, backward ? start - end : end - start, ns, backward); if (e + e1 < _effort) { e += e1; start = end; } else if (e + e1 == _effort) { e += e1; match = true; } else if (e + e1 > _effort) { break; } //debugPlan<<"duration(ms)["<logError(i18n("Could not match effort. Want: %1 got: %2", _effort.toString(Duration::Format_Hour), e.toString(Duration::Format_Hour))); foreach (ResourceRequest *r, lst) { Resource *res = r->resource(); ns->logInfo(i18n("Resource %1 available from %2 to %3", res->name(), locale.toString(r->availableFrom(), QLocale::ShortFormat), locale.toString(r->availableUntil(), QLocale::ShortFormat))); } } DateTime t; if (e != Duration::zeroDuration) { foreach (ResourceRequest *r, lst) { DateTime tt; if (backward) { tt = r->availableAfter(end, ns); if (tt.isValid() && (! t.isValid() || tt < t)) { t = tt; } } else { tt = r->availableBefore(end, ns); if (tt.isValid() && (! t.isValid() || tt > t)) { t = tt; } } } } end = t.isValid() ? t : time; //debugPlan<<"<---"<<(backward?"(B)":"(F)")<<":"<time?end-time:time-end); } QDebug operator<<(QDebug dbg, const KPlato::ResourceRequest *rr) { if (rr) { dbg<<*rr; } else { dbg<<(void*)rr; } return dbg; } QDebug operator<<(QDebug dbg, const KPlato::ResourceRequest &rr) { if (rr.resource()) { dbg<<"ResourceRequest["<name()<<']'; } else { dbg<<"ResourceRequest["< * Copyright (C) 2011 Dag Andersen * Copyright (C) 2019 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. */ #ifndef KPTRESOURCEREQUEST_H #define KPTRESOURCEREQUEST_H #include "plankernel_export.h" #include "kptglobal.h" #include "kptduration.h" #include "kptdatetime.h" #include #include #include #include class QDomElement; /// The main namespace. namespace KPlato { class Account; class Risk; class Effort; class Appointment; class Task; class Node; class Project; class Resource; class ResourceRequest; class ResourceRequestCollection; class Schedule; class ResourceSchedule; class Schedule; class XMLLoaderObject; class DateTimeInterval; class ResourceRequestCollection; class PLANKERNEL_EXPORT ResourceRequest { public: explicit ResourceRequest(Resource *resource = nullptr, int units = 1); explicit ResourceRequest(const ResourceRequest &r); ~ResourceRequest(); int id() const; void setId(int id); ResourceRequestCollection *collection() const; void setCollection(ResourceRequestCollection *collection); Resource *resource() const { return m_resource; } void setResource(Resource* resource) { m_resource = resource; } bool load(KoXmlElement &element, Project &project); void save(QDomElement &element) const; /** * Get amount of requested resource units in percent */ int units() const; void setUnits(int value); void registerRequest(); void unregisterRequest(); void makeAppointment(Schedule *schedule, int amount); void makeAppointment(Schedule *schedule); Task *task() const; /// Return the datetime from when the resource is available. /// If it is not valid, the project constraint start time is used. /// For teams the earliest time for any team member is used. DateTime availableFrom(); /// Return the datetime until when the resource is available. /// If it is not valid, the project constraint end time is used. /// For teams the latest time for any team member is used. DateTime availableUntil(); Schedule *resourceSchedule(Schedule *ns, Resource *resource = 0); DateTime availableAfter(const DateTime &time, Schedule *ns); DateTime availableBefore(const DateTime &time, Schedule *ns); Duration effort(const DateTime &time, const Duration &duration, Schedule *ns, bool backward); DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0); DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0); /// Resource is allocated dynamically by the group request bool isDynamicallyAllocated() const { return m_dynamic; } /// Set resource is allocated dynamically void setAllocatedDynaically(bool dyn) { m_dynamic = dyn; } /// Return a measure of how suitable the resource is for allocation long allocationSuitability(const DateTime &time, const Duration &duration, Schedule *ns, bool backward); /// Returns a list of all the required resources that will be used in scheduling. /// Note: This list overrides the resources own list which is just used as default for allocation dialog. - QList requiredResources() const { return m_required; } + QList requiredResources() const; /// Set the list of required resources that will be used in scheduling. - void setRequiredResources(const QList &lst) { m_required = lst; } + void setRequiredResources(const QList &lst); + /// Add @p resource to list of requred resources + void addRequiredResource(Resource *resource); QList alternativeRequests() const; void setAlternativeRequests(const QList requests); bool addAlternativeRequest(ResourceRequest *request); bool removeAlternativeRequest(ResourceRequest *request); QList teamMembers() const; private: void emitAlternativeRequestToBeAdded(ResourceRequest *request, int row); void emitAlternativeRequestAdded(ResourceRequest *alternative); void emitAlternativeRequestToBeRemoved(ResourceRequest *request, int row, ResourceRequest *alternative); void emitAlternativeRequestRemoved(); protected: void changed(); void setCurrentSchedulePtr(Schedule *ns); void setCurrentSchedulePtr(Resource *resource, Schedule *ns); private: int m_id; Resource *m_resource; int m_units; ResourceRequestCollection *m_collection; bool m_dynamic; QList m_required; mutable QList m_teamMembers; QList m_alternativeRequests; #ifndef NDEBUG public: void printDebug(const QString& ident); #endif }; class PLANKERNEL_EXPORT ResourceRequestCollection : public QObject { Q_OBJECT public: explicit ResourceRequestCollection(Task *task = 0); ~ResourceRequestCollection(); bool contains(ResourceRequest *request) const; /// Remove all group- and resource requests /// Note: Does not delete void removeRequests(); ResourceRequest *resourceRequest(int id) const; ResourceRequest *find(const Resource *resource) const; ResourceRequest *resourceRequest(const QString &name) const; /// The ResourceRequestCollection has no requests bool isEmpty() const; /// Empty the ResourceRequestCollection of all requets // void clear() { m_groupRequests.clear(); } /// Reset dynamic resource allocations void resetDynamicAllocations(); bool contains(const QString &identity) const; /// Return a list of names of allocated resources. /// Team resources are included but *not* the team members. QStringList requestNameList() const; /// Return a list of allocated resources. /// Team resources are included but *not* the team members. QList requestedResources() const; /// Return a list of all resource requests. /// If @p resolveTeam is true, include the team members, /// if @p resolveTeam is false, include the team resource itself. QList resourceRequests(bool resolveTeam=true) const; /// Add the resource request @p request void addResourceRequest(ResourceRequest *request); /// Remove resource request @p request void removeResourceRequest(ResourceRequest *request); /// Delete resource request @p request void deleteResourceRequest(ResourceRequest *request); //bool load(KoXmlElement &element, Project &project); void save(QDomElement &element) const; /** * Returns the duration needed to do the @p effort starting at @p time. */ Duration duration(const DateTime &time, const Duration &effort, Schedule *sch, bool backward = false); DateTime availableAfter(const DateTime &time, Schedule *ns); DateTime availableBefore(const DateTime &time, Schedule *ns); DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0) const; DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0) const; DateTime workStartAfter(const DateTime &time, Schedule *ns); DateTime workFinishBefore(const DateTime &time, Schedule *ns); /** * Makes appointments for the schedule @p schedule to the requested resources. * Assumes that @ref duration() has been run. * @param schedule the schedule */ void makeAppointments(Schedule *schedule); /** * Reserves the requested resources for the specified interval */ void reserve(const DateTime &start, const Duration &duration); Task *task() const; void setTask(Task *t); void changed(); Duration effort(const QList &lst, const DateTime &time, const Duration &duration, Schedule *ns, bool backward) const; int numDays(const QList &lst, const DateTime &time, bool backward) const; Duration duration(const QList &lst, const DateTime &time, const Duration &_effort, Schedule *ns, bool backward); Q_SIGNALS: void alternativeRequestToBeAdded(ResourceRequest *request, int row); void alternativeRequestAdded(ResourceRequest *alternative); void alternativeRequestToBeRemoved(ResourceRequest *request, int row, ResourceRequest *alternative); void alternativeRequestRemoved(); private: Task *m_task; int m_lastResourceId; QMap m_resourceRequests; }; } //KPlato namespace PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::ResourceRequest *r); PLANKERNEL_EXPORT QDebug operator<<(QDebug dbg, const KPlato::ResourceRequest &r); #endif