kplato

kptresource.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Thomas zander <zander@kde.org>
00003    Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kptresource.h"
00022 #include "kptappointment.h"
00023 #include "kptproject.h"
00024 #include "kpttask.h"
00025 #include "kptdatetime.h"
00026 #include "kptcalendar.h"
00027 #include "kpteffortcostmap.h"
00028 #include "kptschedule.h"
00029 
00030 #include <kdebug.h>
00031 #include <kglobal.h>
00032 #include <klocale.h>
00033 
00034 namespace KPlato
00035 {
00036 
00037 ResourceGroup::ResourceGroup(Project *project) {
00038     m_project = project;
00039     m_type = Type_Work;
00040     m_resources.setAutoDelete(true);
00041     generateId();
00042     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00043 }
00044 
00045 ResourceGroup::~ResourceGroup() {
00046     if (findId() == this) {
00047         removeId(); // only remove myself (I may be just a working copy)
00048     }
00049     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00050 }
00051 
00052 bool ResourceGroup::setId(QString id) {
00053     //kdDebug()<<k_funcinfo<<id<<endl;
00054     if (id.isEmpty()) {
00055         kdError()<<k_funcinfo<<"id is empty"<<endl;
00056         m_id = id;
00057         return false;
00058     }
00059     ResourceGroup *g = findId();
00060     if (g == this) {
00061         //kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
00062         removeId();
00063     } else if (g) {
00064         //Hmmm, shouldn't happen
00065         kdError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different group: "<<g->name()<<endl;
00066     }
00067     if (findId(id)) {
00068         kdError()<<k_funcinfo<<"id '"<<id<<"' is already used for different group: "<<findId(id)->name()<<endl;
00069         m_id = QString(); // hmmm
00070         return false;
00071     }
00072     m_id = id;
00073     insertId(id);
00074     //kdDebug()<<k_funcinfo<<m_name<<": inserted id="<<id<<endl;
00075     return true;
00076 }
00077 
00078 void ResourceGroup::generateId() {
00079     if (!m_id.isEmpty()) {
00080         removeId();
00081     }
00082     for (int i=0; i<32000 ; ++i) {
00083         m_id = m_id.setNum(i);
00084         if (!findId()) {
00085             insertId(m_id);
00086             return;
00087         }
00088     }
00089     m_id = QString();
00090 }
00091 
00092 void ResourceGroup::addResource(Resource* resource, Risk*) {
00093     m_resources.append(resource);
00094 }
00095 
00096 Resource* ResourceGroup::getResource(int) {
00097     return 0L;
00098 }
00099 
00100 Risk* ResourceGroup::getRisk(int) {
00101     return 0L;
00102 }
00103 
00104 void ResourceGroup::removeResource(Resource *resource) {
00105     m_resources.removeRef(resource);
00106 }
00107 
00108 Resource *ResourceGroup::takeResource(Resource *resource) {
00109     return m_resources.take(m_resources.findRef(resource));
00110 }
00111 
00112 void ResourceGroup::removeResource(int) {
00113 }
00114 
00115 void ResourceGroup::addRequiredResource(ResourceGroup*) {
00116 }
00117 
00118 ResourceGroup* ResourceGroup::getRequiredResource(int) {
00119     return 0L;
00120 }
00121 
00122 void ResourceGroup::removeRequiredResource(int) {
00123 }
00124 
00125 bool ResourceGroup::load(QDomElement &element) {
00126     //kdDebug()<<k_funcinfo<<endl;
00127     setId(element.attribute("id"));
00128     m_name = element.attribute("name");
00129 
00130     QDomNodeList list = element.childNodes();
00131     for (unsigned int i=0; i<list.count(); ++i) {
00132         if (list.item(i).isElement()) {
00133             QDomElement e = list.item(i).toElement();
00134             if (e.tagName() == "resource") {
00135                 // Load the resource
00136                 Resource *child = new Resource(m_project);
00137                 if (child->load(e))
00138                     addResource(child, 0);
00139                 else
00140                     // TODO: Complain about this
00141                     delete child;
00142             }
00143         }
00144     }
00145     return true;
00146 }
00147 
00148 void ResourceGroup::save(QDomElement &element)  const {
00149     //kdDebug()<<k_funcinfo<<endl;
00150 
00151     QDomElement me = element.ownerDocument().createElement("resource-group");
00152     element.appendChild(me);
00153 
00154     me.setAttribute("id", m_id);
00155     me.setAttribute("name", m_name);
00156 
00157     QPtrListIterator<Resource> it(m_resources);
00158     for ( ; it.current(); ++it ) {
00159         it.current()->save(me);
00160     }
00161 }
00162 
00163 void ResourceGroup::initiateCalculation(Schedule &sch) {
00164     QPtrListIterator<Resource> it(m_resources);
00165     for (; it.current(); ++it) {
00166         it.current()->initiateCalculation(sch);
00167     }
00168     clearNodes();
00169 }
00170 
00171 int ResourceGroup::units() {
00172     int u = 0;
00173     QPtrListIterator<Resource> it = m_resources;
00174     for (; it.current(); ++it) {
00175         u += it.current()->units();
00176     }
00177     return u;
00178 }
00179 
00180 ResourceGroup *ResourceGroup::findId(const QString &id) const {
00181     return m_project ? m_project->findResourceGroup(id) : 0;
00182 }
00183 
00184 bool ResourceGroup::removeId(const QString &id) { 
00185     return m_project ? m_project->removeResourceGroupId(id): false;
00186 }
00187 
00188 void ResourceGroup::insertId(const QString &id) { 
00189     if (m_project)
00190         m_project->insertResourceGroupId(id, this);
00191 }
00192 
00193 Appointment ResourceGroup::appointmentIntervals() const {
00194     Appointment a;
00195     QPtrListIterator<Resource> it = m_resources;
00196     for (; it.current(); ++it) {
00197         a += it.current()->appointmentIntervals();
00198     }
00199     return a;
00200 }
00201 
00202 Resource::Resource(Project *project) : m_project(project), m_schedules(), m_workingHours() {
00203     m_type = Type_Work;
00204     m_units = 100; // %
00205 
00206     m_availableFrom = DateTime(QDate::currentDate());
00207     m_availableUntil = m_availableFrom.addYears(2);
00208 
00209     cost.normalRate = 100;
00210     cost.overtimeRate = 200;
00211     cost.fixed = 0;
00212     m_calendar = 0;
00213     m_currentSchedule = 0;
00214     generateId();
00215     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00216 }
00217 
00218 Resource::Resource(Resource *resource) { 
00219     //kdDebug()<<k_funcinfo<<"("<<this<<") from ("<<resource<<")"<<endl;
00220     copy(resource); 
00221 }
00222 
00223 Resource::~Resource() {
00224     //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00225     if (findId() == this) {
00226         removeId(); // only remove myself (I may be just a working copy)
00227     }
00228     QPtrListIterator<ResourceRequest> it = m_requests;
00229     for (; it.current(); ++it) {
00230         it.current()->setResource(0); // avoid the request to mess with my list
00231     }
00232     m_requests.first();
00233     for (; m_requests.current(); m_requests.next()) {
00234         m_requests.current()->parent()->removeResourceRequest(m_requests.current()); // deletes the request
00235     }
00236 }
00237 
00238 bool Resource::setId(QString id) {
00239     //kdDebug()<<k_funcinfo<<id<<endl;
00240     if (id.isEmpty()) {
00241         kdError()<<k_funcinfo<<"id is empty"<<endl;
00242         m_id = id;
00243         return false;
00244     }
00245     Resource *r = findId();
00246     if (r == this) {
00247         //kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
00248         removeId();
00249     } else if (r) {
00250         //Hmmm, shouldn't happen
00251         kdError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different resource: "<<r->name()<<endl;
00252     }
00253     if (findId(id)) {
00254         kdError()<<k_funcinfo<<"id '"<<id<<"' is already used for different resource: "<<findId(id)->name()<<endl;
00255         m_id = QString(); // hmmm
00256         return false;
00257     }
00258     m_id = id;
00259     insertId(id);
00260     //kdDebug()<<k_funcinfo<<m_name<<": inserted id="<<id<<endl;
00261     return true;
00262 }
00263 
00264 void Resource::generateId() {
00265     if (!m_id.isEmpty()) {
00266         removeId();
00267     }
00268     for (int i=0; i<32000 ; ++i) {
00269         m_id = m_id.setNum(i);
00270         if (!findId()) {
00271             insertId(m_id);
00272             //kdDebug()<<k_funcinfo<<m_name<<": inserted id="<<m_id<<endl;
00273             return;
00274         }
00275     }
00276     m_id = QString();
00277 }
00278 
00279 void Resource::setType(const QString &type) {
00280     if (type == "Work")
00281         m_type = Type_Work;
00282     else if (type == "Material")
00283         m_type = Type_Material;
00284 }
00285 
00286 QString Resource::typeToString() const {
00287     if (m_type == Type_Work)
00288         return QString("Work");
00289     else if (m_type == Type_Material)
00290         return QString("Material");
00291 
00292     return QString();
00293 }
00294 
00295 void Resource::copy(Resource *resource) {
00296     m_project = resource->project();
00297     //m_appointments = resource->appointments(); // Note
00298     m_id = resource->id();
00299     m_name = resource->name();
00300     m_initials = resource->initials();
00301     m_email = resource->email();
00302     m_availableFrom = resource->availableFrom();
00303     m_availableUntil = resource->availableUntil();
00304     m_workingHours.clear();
00305     m_workingHours = resource->workingHours();
00306 
00307     m_units = resource->units(); // available units in percent
00308 
00309     m_type = resource->type();
00310 
00311     cost.normalRate = resource->normalRate();
00312     cost.overtimeRate = resource->overtimeRate();
00313     cost.fixed = resource->fixedCost();
00314     
00315     m_calendar = resource->m_calendar;
00316 }
00317 
00318 void Resource::addWorkingHour(QTime from, QTime until) {
00319     //kdDebug()<<k_funcinfo<<endl;
00320     m_workingHours.append(new QTime(from));
00321     m_workingHours.append(new QTime(until));
00322 }
00323 
00324 Calendar *Resource::calendar(bool local) const {
00325     if ( local == false && m_calendar == 0 && project() != 0)
00326         return project()->defaultCalendar();
00327     return m_calendar;
00328 }
00329 
00330 DateTime Resource::getFirstAvailableTime(DateTime /*after*/) {
00331     return DateTime();
00332 }
00333 
00334 DateTime Resource::getBestAvailableTime(Duration /*duration*/) {
00335     return DateTime();
00336 }
00337 
00338 DateTime Resource::getBestAvailableTime(const DateTime /*after*/, const Duration /*duration*/) {
00339     return DateTime();
00340 }
00341 
00342 bool Resource::load(QDomElement &element) {
00343     //kdDebug()<<k_funcinfo<<endl;
00344     QString s;
00345     setId(element.attribute("id"));
00346     m_name = element.attribute("name");
00347     m_initials = element.attribute("initials");
00348     m_email = element.attribute("email");
00349     setType(element.attribute("type"));
00350     m_calendar = findCalendar(element.attribute("calendar-id"));
00351     m_units = element.attribute("units", "100").toInt();
00352     s = element.attribute("available-from");
00353     if (s != "")
00354         m_availableFrom = DateTime::fromString(s);
00355     s = element.attribute("available-until");
00356     if (s != "")
00357         m_availableUntil = DateTime::fromString(s);
00358         
00359     cost.normalRate = KGlobal::locale()->readMoney(element.attribute("normal-rate"));
00360     cost.overtimeRate = KGlobal::locale()->readMoney(element.attribute("overtime-rate"));
00361     return true;
00362 }
00363 
00364 void Resource::save(QDomElement &element) const {
00365     //kdDebug()<<k_funcinfo<<endl;
00366     QDomElement me = element.ownerDocument().createElement("resource");
00367     element.appendChild(me);
00368 
00369     if (m_calendar)
00370         me.setAttribute("calendar-id", m_calendar->id());
00371     me.setAttribute("id", m_id);
00372     me.setAttribute("name", m_name);
00373     me.setAttribute("initials", m_initials);
00374     me.setAttribute("email", m_email);
00375     me.setAttribute("type", typeToString());
00376     me.setAttribute("units", m_units);
00377     me.setAttribute("available-from", m_availableFrom.toString(Qt::ISODate));
00378     me.setAttribute("available-until", m_availableUntil.toString(Qt::ISODate));
00379     me.setAttribute("normal-rate", KGlobal::locale()->formatMoney(cost.normalRate));
00380     me.setAttribute("overtime-rate", KGlobal::locale()->formatMoney(cost.overtimeRate));
00381 }
00382 
00383 bool Resource::isAvailable(Task */*task*/) {
00384     bool busy = false;
00385 /*    QPtrListIterator<Appointment> it(m_appointments);
00386     for (; it.current(); ++it) {
00387         if (it.current()->isBusy(task->startTime(), task->endTime())) {
00388             busy = true;
00389             break;
00390         }
00391     }*/
00392     return !busy;
00393 }
00394 
00395 QPtrList<Appointment> Resource::appointments() {
00396     QPtrList<Appointment> lst;
00397     if (m_currentSchedule)
00398         lst = m_currentSchedule->appointments();
00399     //kdDebug()<<k_funcinfo<<lst.count()<<endl;
00400     return lst;
00401 }
00402 
00403 Appointment *Resource::findAppointment(Node */*node*/) {
00404 /*    QPtrListIterator<Appointment> it = m_appointments;
00405     for (; it.current(); ++it) {
00406         if (it.current()->node() == node)
00407             return it.current();
00408     }*/
00409     return 0;
00410 }
00411 
00412 bool Resource::addAppointment(Appointment *appointment) {
00413     if (m_currentSchedule)
00414         return m_currentSchedule->add(appointment);
00415     return false;
00416 }
00417 
00418 bool Resource::addAppointment(Appointment *appointment, Schedule &main) {
00419     Schedule *s = findSchedule(main.id());
00420     if (s == 0) {
00421         s = createSchedule(&main);
00422     }
00423     appointment->setResource(s);
00424     return s->add(appointment);
00425 }
00426 
00427 void Resource::addAppointment(Schedule *node, DateTime &start, DateTime &end, double load) {
00428     //kdDebug()<<k_funcinfo<<endl;
00429     Schedule *s = findSchedule(node->id());
00430     if (s == 0) {
00431         s = createSchedule(node->parent());
00432     }
00433     s->addAppointment(node, start, end, load);
00434 }
00435 
00436 void Resource::initiateCalculation(Schedule &sch) {
00437     m_currentSchedule = createSchedule(&sch);
00438 }
00439 
00440 void Resource::removeSchedule(Schedule *schedule) {
00441     takeSchedule(schedule);
00442     delete schedule;
00443 }
00444 
00445 void Resource::takeSchedule(const Schedule *schedule) {
00446     if (schedule == 0)
00447         return;
00448     if (m_currentSchedule == schedule)
00449         m_currentSchedule = 0;
00450     m_schedules.take(schedule->id());
00451 }
00452 
00453 void Resource::addSchedule(Schedule *schedule) {
00454     if (schedule == 0)
00455         return;
00456     m_schedules.replace(schedule->id(), schedule);
00457 }
00458 
00459 ResourceSchedule *Resource::createSchedule(QString name, int type, int id) {
00460     ResourceSchedule *sch = new ResourceSchedule(this, name, (Schedule::Type)type, id);
00461     addSchedule(sch);
00462     return sch;
00463 }
00464 
00465 ResourceSchedule *Resource::createSchedule(Schedule *parent) {
00466     ResourceSchedule *sch = new ResourceSchedule(parent, this);
00467     addSchedule(sch);
00468     return sch;
00469 }
00470 
00471 void Resource::makeAppointment(Schedule *node, const DateTime &from, const DateTime &end) {
00472     if (!from.isValid() || !end.isValid()) {
00473         kdWarning()<<k_funcinfo<<"Invalid time"<<endl;
00474         return;
00475     }
00476     Calendar *cal = calendar();
00477     if (cal == 0) {
00478         return;
00479     }
00480     DateTime time = from;
00481     while (time < end) {
00482         //kdDebug()<<k_funcinfo<<time.toString()<<" to "<<end.toString()<<endl;
00483         if (!time.isValid() || !end.isValid()) {
00484             kdWarning()<<k_funcinfo<<"Invalid time"<<endl;
00485             return;
00486         }
00487         if (!cal->hasInterval(time, end)) {
00488             //kdDebug()<<time.toString()<<" to "<<end.toString()<<": No (more) interval(s)"<<endl;
00489             kdWarning()<<k_funcinfo<<m_name<<": Resource only partially available"<<endl;
00490             //node->resourceNotAvailable = true;
00491             return; // nothing more to do
00492         }
00493         QPair<DateTime, DateTime> i = cal->firstInterval(time, end);
00494         if (!i.second.isValid()) {
00495             kdWarning()<<k_funcinfo<<"Invalid interval: "<<time<<", "<<end<<endl;
00496             return;
00497         }
00498         if (time == i.second)
00499             return; // hmmm, didn't get a new interval, avoid loop
00500         addAppointment(node, i.first, i.second, m_units);
00501         //kdDebug()<<k_funcinfo<<"Add :"<<i.first.toString()<<" to "<<i.second.toString()<<endl;
00502         if (!(node->workStartTime.isValid()) || i.first < node->workStartTime)
00503             node->workStartTime = i.first;
00504         if (!(node->workEndTime.isValid()) || i.second > node->workEndTime)
00505             node->workEndTime = i.second;
00506         time = i.second;
00507     }
00508     return;
00509 }
00510 void Resource::makeAppointment(Schedule *node) {
00511     //kdDebug()<<k_funcinfo<<m_name<< ": "<<node->node()->name()<<": "<<node->startTime.toString()<<" dur "<<node->duration.toString()<<endl;
00512     if (!node->startTime.isValid()) {
00513         kdWarning()<<k_funcinfo<<m_name<<": startTime invalid"<<endl;
00514         return;
00515     }
00516     if (!node->endTime.isValid()) {
00517         kdWarning()<<k_funcinfo<<m_name<<": endTime invalid"<<endl;
00518         return;
00519     }
00520     Calendar *cal = calendar();
00521     if (m_type == Type_Material) {
00522         DateTime from = availableAfter(node->startTime, node->endTime);
00523         DateTime end = availableBefore(node->endTime, node->startTime);
00524         if (!from.isValid() || !end.isValid()) {
00525             return;
00526         }
00527         if (cal == 0) {
00528             // Allocate the whole period
00529             addAppointment(node, from, end, m_units);
00530             return;
00531         }
00532         makeAppointment(node, from, end);
00533     }
00534     if (!cal) {
00535         kdWarning()<<k_funcinfo<<m_name<<": No calendar defined"<<endl;
00536         return; 
00537     }
00538     //TODO: units and standard non-working days
00539     DateTime time = node->startTime;
00540     DateTime end = node->endTime;
00541     time = availableAfter(time, end);
00542     if (!time.isValid()) {
00543         kdWarning()<<k_funcinfo<<m_name<<": Resource not available (after="<<node->startTime<<", "<<end<<")"<<endl;
00544         node->resourceNotAvailable = true;
00545         return;
00546     }
00547     end = availableBefore(end, time);
00548     if (!end.isValid()) {
00549         kdWarning()<<k_funcinfo<<m_name<<": Resource not available (before="<<node->endTime<<", "<<time<<")"<<endl;
00550         node->resourceNotAvailable = true;
00551         return;
00552     }
00553     //kdDebug()<<k_funcinfo<<time.toString()<<" to "<<end.toString()<<endl;
00554     makeAppointment(node, time, end);
00555 }
00556 
00557 // the amount of effort we can do within the duration
00558 Duration Resource::effort(const DateTime &start, const Duration &duration, bool backward, bool *ok) const {
00559     //kdDebug()<<k_funcinfo<<m_name<<": "<<start.date().toString()<<" for duration "<<duration.toString(Duration::Format_Day)<<endl;
00560     bool sts=false;
00561     Duration e;
00562     if (duration == 0) {
00563         kdWarning()<<k_funcinfo<<"zero duration"<<endl;
00564         return e;
00565     }
00566     Calendar *cal = calendar();
00567     if (cal == 0) {
00568         kdWarning()<<k_funcinfo<<m_name<<": No calendar defined"<<endl;
00569         return e;
00570     }
00571     if (backward) {
00572         DateTime limit = start - duration;
00573         DateTime t = availableBefore(start, limit);
00574         if (t.isValid()) {
00575             sts = true;
00576             e = (cal->effort(limit, t) * m_units)/100;
00577         } else {
00578             //kdDebug()<<k_funcinfo<<m_name<<": Not available (start="<<start<<", "<<limit<<")"<<endl;
00579         }
00580     } else {
00581         DateTime limit = start + duration;
00582         DateTime t = availableAfter(start, limit);
00583         if (t.isValid()) {
00584             sts = true;
00585             e = (cal->effort(t, limit) * m_units)/100;
00586         }
00587     }
00588     //kdDebug()<<k_funcinfo<<start.toString()<<" e="<<e.toString(Duration::Format_Day)<<" ("<<m_units<<")"<<endl;
00589     if (ok) *ok = sts;
00590     return e;
00591 }
00592 
00593 DateTime Resource::availableAfter(const DateTime &time, const DateTime limit, bool checkAppointments) const {
00594     DateTime t;
00595     if (m_units == 0) {
00596         return t;
00597     }
00598     DateTime lmt = m_availableUntil;
00599     if (limit.isValid() && limit < lmt) {
00600         lmt = limit;
00601     }
00602     if (time >= lmt) {
00603         return t;
00604     }
00605     if (type() == Type_Material) {
00606         t = time > m_availableFrom ? time : m_availableFrom;
00607         //kdDebug()<<k_funcinfo<<time.toString()<<"="<<t.toString()<<" "<<m_name<<endl;
00608         return t;
00609     }
00610     Calendar *cal = calendar();
00611     if (cal == 0) {
00612         return t;
00613     }
00614     t = m_availableFrom > time ? m_availableFrom : time;
00615     t = cal->firstAvailableAfter(t, lmt);
00616     if (checkAppointments) {
00617         //TODO
00618     }
00619     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<t.toString()<<" "<<m_name<<endl;
00620     return t;
00621 }
00622 
00623 DateTime Resource::availableBefore(const DateTime &time, const DateTime limit, bool checkAppointments) const {
00624     DateTime t;
00625     if (m_units == 0) {
00626         return t;
00627     }
00628     DateTime lmt = m_availableFrom;
00629     if (limit.isValid() && limit > lmt) {
00630         lmt = limit;
00631     }
00632     if (time <= lmt) {
00633         return t;
00634     }
00635     if (type() == Type_Material) {
00636         t = time < m_availableUntil ? time : m_availableUntil;
00637         //kdDebug()<<k_funcinfo<<time.toString()<<"="<<t.toString()<<" "<<m_name<<endl;
00638         return t;
00639     }
00640     Calendar *cal = calendar();
00641     if (cal == 0) {
00642         return t;
00643     }
00644     if (!m_availableUntil.isValid()) {
00645         kdWarning()<<k_funcinfo<<m_name<<": availabelUntil is invalid"<<endl;
00646         t = time;
00647     } else {
00648         t = m_availableUntil < time ? m_availableUntil : time;
00649     }
00650     //kdDebug()<<k_funcinfo<<t<<", "<<lmt<<endl;
00651     t = cal->firstAvailableBefore(t, lmt);
00652     if (checkAppointments) {
00653         //TODO
00654     }
00655     //kdDebug()<<k_funcinfo<<m_name<<" returns: "<<time<<"="<<t<<" "<<endl;
00656     return t;
00657 }
00658 
00659 Resource *Resource::findId(const QString &id) const { 
00660     return m_project ? m_project->findResource(id) : 0; 
00661 }
00662 
00663 bool Resource::removeId(const QString &id) { 
00664     return m_project ? m_project->removeResourceId(id) : false; 
00665 }
00666 
00667 void Resource::insertId(const QString &id) { 
00668     if (m_project)
00669         m_project->insertResourceId(id, this); 
00670 }
00671 
00672 Calendar *Resource::findCalendar(const QString &id) const { 
00673     return (m_project ? m_project->findCalendar(id) : 0); 
00674 }
00675 
00676 bool Resource::isOverbooked() const {
00677     return isOverbooked(DateTime(), DateTime());
00678 }
00679 
00680 bool Resource::isOverbooked(const QDate &date) const {
00681     return isOverbooked(DateTime(date), DateTime(date.addDays(1)));
00682 }
00683 
00684 bool Resource::isOverbooked(const DateTime &start, const DateTime &end) const {
00685     //kdDebug()<<k_funcinfo<<m_name<<": "<<start.toString()<<" - "<<end.toString()<<" cs=("<<m_currentSchedule<<")"<<endl;
00686     return m_currentSchedule ? m_currentSchedule->isOverbooked(start, end) : false;
00687 }
00688 
00689 Appointment Resource::appointmentIntervals() const {
00690     Appointment a;
00691     if (m_currentSchedule == 0)
00692         return a;
00693     QPtrListIterator<Appointment> it = m_currentSchedule->appointments();
00694     for (; it.current(); ++it) {
00695         a += *(it.current());
00696     }
00697     return a;
00698 }
00699 
00700 Duration Resource::plannedEffort(const QDate &date) const {
00701     return m_currentSchedule ? m_currentSchedule->plannedEffort(date) : Duration::zeroDuration;
00702 }
00703 
00705 Risk::Risk(Node *n, Resource *r, RiskType rt) {
00706     m_node=n;
00707     m_resource=r;
00708     m_riskType=rt;
00709 }
00710 
00711 Risk::~Risk() {
00712 }
00713 
00714 ResourceRequest::ResourceRequest(Resource *resource, int units)
00715     : m_resource(resource),
00716       m_units(units),
00717       m_parent(0) {
00718     //kdDebug()<<k_funcinfo<<"("<<this<<") Request to: "<<(resource ? resource->name() : QString("None"))<<endl;
00719 }
00720 
00721 ResourceRequest::~ResourceRequest() {
00722     //kdDebug()<<k_funcinfo<<"("<<this<<") resource: "<<(m_resource ? m_resource->name() : QString("None"))<<endl;
00723     if (m_resource)
00724         m_resource->unregisterRequest(this);
00725     m_resource = 0;
00726 }
00727 
00728 bool ResourceRequest::load(QDomElement &element, Project &project) {
00729     //kdDebug()<<k_funcinfo<<endl;
00730     m_resource = project.resource(element.attribute("resource-id"));
00731     if (m_resource == 0) {
00732         kdWarning()<<k_funcinfo<<"The referenced resource does not exist: resource id="<<element.attribute("resource-id")<<endl;
00733         return false;
00734     }
00735     m_units  = element.attribute("units").toInt();
00736     return true;
00737 }
00738 
00739 void ResourceRequest::save(QDomElement &element) const {
00740     QDomElement me = element.ownerDocument().createElement("resource-request");
00741     element.appendChild(me);
00742     me.setAttribute("resource-id", m_resource->id());
00743     me.setAttribute("units", m_units);
00744 }
00745 
00746 int ResourceRequest::units() const {
00747     //kdDebug()<<k_funcinfo<<m_resource->name()<<": units="<<m_units<<endl;
00748     return m_units;
00749 }
00750 
00751 int ResourceRequest::workUnits() const {
00752     if (m_resource->type() == Resource::Type_Work)
00753         return units();
00754         
00755     //kdDebug()<<k_funcinfo<<"units=0"<<endl;
00756     return 0;
00757 }
00758 
00759 Task *ResourceRequest::task() const {
00760     return m_parent ? m_parent->task() : 0;
00761 }
00762 
00764 ResourceGroupRequest::ResourceGroupRequest(ResourceGroup *group, int units)
00765     : m_group(group), m_units(units) {
00766 
00767     //kdDebug()<<k_funcinfo<<"Request to: "<<(group ? group->name() : QString("None"))<<endl;
00768     if (group)
00769         group->registerRequest(this);
00770     m_resourceRequests.setAutoDelete(true);
00771 }
00772 
00773 ResourceGroupRequest::~ResourceGroupRequest() {
00774     //kdDebug()<<k_funcinfo<<"Group: "<<m_group->name()<<endl;
00775     if (m_group)
00776         m_group->unregisterRequest(this);
00777     m_resourceRequests.clear();
00778 }
00779 
00780 void ResourceGroupRequest::addResourceRequest(ResourceRequest *request) {
00781     //kdDebug()<<k_funcinfo<<"("<<request<<") to Group: "<<m_group->name()<<endl;
00782     request->setParent(this);
00783     m_resourceRequests.append(request);
00784     request->registerRequest();
00785 }
00786 
00787 ResourceRequest *ResourceGroupRequest::takeResourceRequest(ResourceRequest *request) {
00788     if (request)
00789         request->unregisterRequest();
00790     return m_resourceRequests.take(m_resourceRequests.findRef(request)); 
00791 }
00792 
00793 ResourceRequest *ResourceGroupRequest::find(Resource *resource) const {
00794     QPtrListIterator<ResourceRequest> it(m_resourceRequests);
00795     for (; it.current(); ++it)
00796         if (it.current()->resource() == resource)
00797             return it.current();
00798 
00799     return 0;
00800 }
00801 
00802 bool ResourceGroupRequest::load(QDomElement &element, Project &project) {
00803     //kdDebug()<<k_funcinfo<<endl;
00804     m_group = project.findResourceGroup(element.attribute("group-id"));
00805     if (m_group == 0) {
00806         //kdDebug()<<k_funcinfo<<"The referenced resource group does not exist: group id="<<element.attribute("group-id")<<endl;
00807         return false;
00808     }
00809     m_group->registerRequest(this);
00810     
00811     m_units  = element.attribute("units").toInt();
00812 
00813     QDomNodeList list = element.childNodes();
00814     for (unsigned int i=0; i<list.count(); ++i) {
00815         if (list.item(i).isElement()) {
00816             QDomElement e = list.item(i).toElement();
00817             if (e.tagName() == "resource-request") {
00818                 ResourceRequest *r = new ResourceRequest();
00819                 if (r->load(e, project))
00820                     addResourceRequest(r);
00821                 else {
00822                     kdError()<<k_funcinfo<<"Failed to load resource request"<<endl;
00823                     delete r;
00824                 }
00825             }
00826         }
00827     }
00828     return true;
00829 }
00830 
00831 void ResourceGroupRequest::save(QDomElement &element) const {
00832     if (units() == 0)
00833         return;
00834     QDomElement me = element.ownerDocument().createElement("resourcegroup-request");
00835     element.appendChild(me);
00836     me.setAttribute("group-id", m_group->id());
00837     me.setAttribute("units", m_units);
00838     QPtrListIterator<ResourceRequest> it(m_resourceRequests);
00839     for (; it.current(); ++it)
00840         it.current()->save(me);
00841 }
00842 
00843 int ResourceGroupRequest::units() const {
00844     int units = m_units;
00845     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00846     for (; it.current(); ++it) {
00847         units += it.current()->units();
00848     }
00849     //kdDebug()<<k_funcinfo<<"units="<<units<<endl;
00850     return units;
00851 }
00852 
00853 int ResourceGroupRequest::workUnits() const {
00854     int units = 0;
00855     if (m_group->type() == ResourceGroup::Type_Work)
00856         units = m_units;
00857     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00858     for (; it.current(); ++it) {
00859         units += it.current()->workUnits();
00860     }
00861     //kdDebug()<<k_funcinfo<<"units="<<units<<endl;
00862     return units;
00863 }
00864 
00865 //TODO: handle nonspecific resources
00866 Duration ResourceGroupRequest::effort(const DateTime &time, const Duration &duration, bool backward, bool *ok) const {
00867     Duration e;
00868     bool sts=false;
00869     if (ok) *ok = sts;
00870     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00871     for (; it.current(); ++it) {
00872         e += it.current()->resource()->effort(time, duration, backward, &sts);
00873         if (sts && ok) *ok = sts;
00874         //kdDebug()<<k_funcinfo<<(backward?"(B)":"(F)" )<<it.current()->resource()->name()<<": time="<<time<<" dur="<<duration.toString()<<"gave e="<<e.toString()<<endl;
00875     }
00876     //kdDebug()<<k_funcinfo<<time.toString()<<"d="<<duration.toString()<<": e="<<e.toString()<<endl;
00877     return e;
00878 }
00879 
00880 int ResourceGroupRequest::numDays(const DateTime &time, bool backward) const {
00881     DateTime t1, t2 = time;
00882     if (backward) {
00883         QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00884         for (; it.current(); ++it) {
00885             t1 = it.current()->resource()->availableFrom();
00886             if (!t2.isValid() || t2 > t1)
00887                 t2 = t1;
00888         }
00889         //kdDebug()<<k_funcinfo<<"bw "<<time.toString()<<": "<<t2.daysTo(time)<<endl;
00890         return t2.daysTo(time);
00891     }
00892     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00893     for (; it.current(); ++it) {
00894         t1 = it.current()->resource()->availableUntil();
00895         if (!t2.isValid() || t2 < t1)
00896             t2 = t1;
00897     }
00898     //kdDebug()<<k_funcinfo<<"fw "<<time.toString()<<": "<<time.daysTo(t2)<<endl;
00899     return time.daysTo(t2);
00900 }
00901 
00902 Duration ResourceGroupRequest::duration(const DateTime &time, const Duration &_effort, bool backward) {
00903     //kdDebug()<<k_funcinfo<<"--->"<<(backward?"(B) ":"(F) ")<<m_group->name()<<" "<<time.toString()<<": effort: "<<_effort.toString(Duration::Format_Day)<<" ("<<_effort.milliseconds()<<")"<<endl;
00904     Duration e;
00905     if (_effort == Duration::zeroDuration) {
00906         return e;
00907     }
00908     bool sts=true;
00909     bool match = false;
00910     DateTime start = time;
00911     int inc = backward ? -1 : 1;
00912     DateTime end = start;
00913     Duration e1;
00914     Duration d(1, 0, 0); // 1 day
00915     int nDays = numDays(time, backward) + 1;
00916     for (int i=0; !match && i <= nDays; ++i) {
00917         // days
00918         end = end.addDays(inc);
00919         e1 = effort(start, d, backward, &sts);
00920         //kdDebug()<<"["<<i<<"of"<<nDays<<"] "<<(backward?"(B)":"(F):")<<"  start="<<start<<" e+e1="<<(e+e1).toString()<<" match "<<_effort.toString()<<endl;
00921         if (e + e1 < _effort) {
00922             e += e1;
00923             start = end;
00924         } else if (e + e1 == _effort) {
00925             e += e1;
00926             match = true;
00927         } else {
00928             end = start;
00929             break;
00930         }
00931     }
00932     //kdDebug()<<"duration "<<(backward?"backward ":"forward: ")<<start.toString()<<" - "<<end.toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")  match="<<match<<" sts="<<sts<<endl;
00933     d = Duration(0, 1, 0); // 1 hour
00934     for (int i=0; !match && i < 24; ++i) {
00935         // hours
00936         end = end.addSecs(inc*60*60);
00937         e1 = effort(start, d, backward, &sts);
00938         if (e + e1 < _effort) {
00939             e += e1;
00940             start = end;
00941         } else if (e + e1 == _effort) {
00942             e += e1;
00943             match = true;
00944         } else {
00945             end = start;
00946             break;
00947         }
00948         //kdDebug()<<"duration(h)["<<i<<"]"<<(backward?"backward ":"forward:")<<" time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
00949     }
00950     //kdDebug()<<"duration "<<(backward?"backward ":"forward: ")<<start.toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")  match="<<match<<" sts="<<sts<<endl;
00951     d = Duration(0, 0, 1); // 1 minute
00952     for (int i=0; !match && i < 60; ++i) {
00953         //minutes
00954         end = end.addSecs(inc*60);
00955         e1 = effort(start, d, backward, &sts);
00956         if (e + e1 < _effort) {
00957             e += e1;
00958             start = end;
00959         } else if (e + e1 == _effort) {
00960             e += e1;
00961             match = true;
00962         } else if (e + e1 > _effort) {
00963             end = start;
00964             break;
00965         }
00966         //kdDebug()<<"duration(m) "<<(backward?"backward":"forward:")<<"  time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
00967     }
00968     //kdDebug()<<"duration "<<(backward?"backward":"forward:")<<"  start="<<start.toString()<<" e="<<e.toString()<<" match="<<match<<" sts="<<sts<<endl;
00969     d = Duration(0, 0, 0, 1); // 1 second
00970     for (int i=0; !match && i < 60 && sts; ++i) {
00971         //seconds
00972         end = end.addSecs(inc);
00973         e1 = effort(start, d, backward, &sts);
00974         if (e + e1 < _effort) {
00975             e += e1;
00976             start = end;
00977         } else if (e + e1 == _effort) {
00978             e += e1;
00979             match = true;
00980         } else if (e + e1 > _effort) {
00981             end = start;
00982             break;
00983         }
00984         //kdDebug()<<"duration(s)["<<i<<"]"<<(backward?"backward":"forward:")<<" time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
00985     }
00986     d = Duration(0, 0, 0, 0, 1); // 1 millisecond
00987     for (int i=0; !match && i < 1000; ++i) {
00988         //milliseconds
00989         end.setTime(end.time().addMSecs(inc));
00990         e1 = effort(start, d, backward, &sts);
00991         if (e + e1 < _effort) {
00992             e += e1;
00993             start = end;
00994         } else if (e + e1 == _effort) {
00995             e += e1;
00996             match = true;
00997         } else if (e + e1 > _effort) {
00998             break;
00999         }
01000         //kdDebug()<<"duration(ms)["<<i<<"]"<<(backward?"backward":"forward:")<<" time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
01001     }
01002     if (!match) {
01003         kdError()<<k_funcinfo<<(task()?task()->name():"No task")<<" "<<time<<": Could not match effort."<<" Want: "<<_effort.toString(Duration::Format_Day)<<" got: "<<e.toString(Duration::Format_Day)<<" sts="<<sts<<endl;
01004     }
01005     DateTime t;
01006     if (e != Duration::zeroDuration) {
01007         t = backward ? availableAfter(end) : availableBefore(end);
01008     }
01009     end = t.isValid() ? t : time;
01010     //kdDebug()<<k_funcinfo<<"<---"<<(backward?"(B) ":"(F) ")<<m_group->name()<<": "<<end.toString()<<"-"<<time.toString()<<"="<<(end - time).toString()<<" effort: "<<_effort.toString(Duration::Format_Day)<<endl;
01011     return (end>time?end-time:time-end);
01012 }
01013 
01014 DateTime ResourceGroupRequest::availableAfter(const DateTime &time) {
01015     DateTime start;
01016     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
01017     for (; it.current(); ++it) {
01018         DateTime t = it.current()->resource()->availableAfter(time);
01019         if (t.isValid() && (!start.isValid() || t < start))
01020             start = t;
01021     }
01022     if (start.isValid() && start < time)
01023         start = time;
01024     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<start.toString()<<" "<<m_group->name()<<endl;
01025     return start;
01026 }
01027 
01028 DateTime ResourceGroupRequest::availableBefore(const DateTime &time) {
01029     DateTime end;
01030     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
01031     for (; it.current(); ++it) {
01032         DateTime t = it.current()->resource()->availableBefore(time);
01033         if (t.isValid() && (!end.isValid() || t > end))
01034             end = t;
01035     }
01036     if (!end.isValid() || end > time)
01037         end = time;
01038     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<end.toString()<<" "<<m_group->name()<<endl;
01039     return end;
01040 }
01041 
01042 void ResourceGroupRequest::makeAppointments(Schedule *schedule) {
01043     //kdDebug()<<k_funcinfo<<endl;
01044     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
01045     for (; it.current(); ++it) {
01046         it.current()->makeAppointment(schedule);
01047     }
01048 }
01049 
01050 void ResourceGroupRequest::reserve(const DateTime &start, const Duration &duration) {
01051     m_start = start;
01052     m_duration = duration;
01053 }
01054 
01055 bool ResourceGroupRequest::isEmpty() const {
01056     return m_resourceRequests.isEmpty() && m_units == 0;
01057 }
01058 
01059 Task *ResourceGroupRequest::task() const {
01060     return m_parent ? &(m_parent->task()) : 0;
01061 }
01062 
01064 ResourceRequestCollection::ResourceRequestCollection(Task &task)
01065     : m_task(task) {
01066     m_requests.setAutoDelete(true);
01067 }
01068 
01069 ResourceRequestCollection::~ResourceRequestCollection() {
01070     //kdDebug()<<k_funcinfo<<"Group: "<<m_group->name()<<endl;
01071     m_requests.clear();
01072 }
01073 
01074 ResourceGroupRequest *ResourceRequestCollection::find(ResourceGroup *group) const {
01075     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01076     for (; it.current(); ++it) {
01077         if (it.current()->group() == group)
01078             return it.current(); // we assume only one request to the same group
01079     }
01080     return 0;
01081 }
01082 
01083 
01084 ResourceRequest *ResourceRequestCollection::find(Resource *resource) const {
01085     ResourceRequest *req = 0;
01086     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01087     for (; !req && it.current(); ++it) {
01088         req = it.current()->find(resource);
01089     }
01090     return req;
01091 }
01092 
01093 // bool ResourceRequestCollection::load(QDomElement &element, Project &project) {
01094 //     //kdDebug()<<k_funcinfo<<endl;
01095 //     return true;
01096 // }
01097 
01098 void ResourceRequestCollection::save(QDomElement &element) const {
01099     //kdDebug()<<k_funcinfo<<endl;
01100     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01101     for ( ; it.current(); ++it ) {
01102         it.current()->save(element);
01103     }
01104 }
01105 
01106 int ResourceRequestCollection::units() const {
01107     //kdDebug()<<k_funcinfo<<endl;
01108     int units = 0;
01109     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01110     for (; it.current(); ++it) {
01111         units += it.current()->units();
01112         //kdDebug()<<k_funcinfo<<" Group: "<<it.current()->group()->name()<<" now="<<units<<endl;
01113     }
01114     return units;
01115 }
01116 
01117 int ResourceRequestCollection::workUnits() const {
01118     //kdDebug()<<k_funcinfo<<endl;
01119     int units = 0;
01120     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01121     for (; it.current(); ++it) {
01122         units += it.current()->workUnits();
01123     }
01124     //kdDebug()<<k_funcinfo<<" units="<<units<<endl;
01125     return units;
01126 }
01127 
01128 // Returns the longest duration needed by any of the groups.
01129 // The effort is distributed on "work type" resourcegroups in proportion to
01130 // the amount of resources requested for each group.
01131 // "Material type" of resourcegroups does not (atm) affect the duration.
01132 Duration ResourceRequestCollection::duration(const DateTime &time, const Duration &effort, bool backward) {
01133     //kdDebug()<<k_funcinfo<<"time="<<time.toString()<<" effort="<<effort.toString(Duration::Format_Day)<<" backward="<<backward<<endl;
01134     if (isEmpty()) {
01135         return effort;
01136     }
01137     Duration dur;
01138     int units = workUnits();
01139     if (units == 0)
01140         units = 100; //hmmmm
01141     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01142     for (; it.current(); ++it) {
01143         if (it.current()->isEmpty())
01144             continue;
01145         if (it.current()->group()->type() == ResourceGroup::Type_Work) {
01146             Duration d = it.current()->duration(time, (effort*it.current()->workUnits())/units, backward);
01147             if (d > dur)
01148                 dur = d;
01149         } else if (it.current()->group()->type() == ResourceGroup::Type_Material) {
01150             //TODO
01151             if (dur == Duration::zeroDuration)
01152                 dur = effort;
01153         }
01154     }
01155     return dur;
01156 }
01157 
01158 DateTime ResourceRequestCollection::availableAfter(const DateTime &time) {
01159     DateTime start;
01160     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01161     for (; it.current(); ++it) {
01162         DateTime t = it.current()->availableAfter(time);
01163         if (t.isValid() && (!start.isValid() || t < start))
01164             start = t;
01165     }
01166     if (start.isValid() && start < time)
01167         start = time;
01168     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<start.toString()<<endl;
01169     return start;
01170 }
01171 
01172 DateTime ResourceRequestCollection::availableBefore(const DateTime &time) {
01173     DateTime end;
01174     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01175     for (; it.current(); ++it) {
01176         DateTime t = it.current()->availableBefore(time);
01177         if (t.isValid() && (!end.isValid() ||t > end))
01178             end = t;
01179     }
01180     if (!end.isValid() || end > time)
01181         end = time;
01182     return end;
01183 }
01184 
01185 
01186 void ResourceRequestCollection::makeAppointments(Schedule *schedule) {
01187     //kdDebug()<<k_funcinfo<<endl;
01188     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01189     for (; it.current(); ++it) {
01190         it.current()->makeAppointments(schedule);
01191     }
01192 }
01193 
01194 void ResourceRequestCollection::reserve(const DateTime &start, const Duration &duration) {
01195     //kdDebug()<<k_funcinfo<<endl;
01196     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01197     for (; it.current(); ++it) {
01198         it.current()->reserve(start, duration);
01199     }
01200 }
01201 
01202 bool ResourceRequestCollection::isEmpty() const {
01203     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01204     for (; it.current(); ++it) {
01205         if (!it.current()->isEmpty())
01206             return false;
01207     }
01208     return true;
01209 }
01210 #ifndef NDEBUG
01211 
01212 void ResourceGroup::printDebug(QString indent)
01213 {
01214     kdDebug()<<indent<<"  + Resource group: "<<m_name<<" id="<<m_id<<endl;
01215     indent += "   !";
01216     QPtrListIterator<Resource> it(m_resources);
01217     for ( ; it.current(); ++it)
01218         it.current()->printDebug(indent);
01219 }
01220 void Resource::printDebug(QString indent)
01221 {
01222     kdDebug()<<indent<<"  + Resource: "<<m_name<<" id="<<m_id/*<<" Overbooked="<<isOverbooked()*/<<endl;
01223     QIntDictIterator<Schedule> it(m_schedules);
01224     indent += "      ";
01225     for (; it.current(); ++it) {
01226         it.current()->printDebug(indent);
01227     }
01228     indent += "  !";
01229 }
01230 
01231 void ResourceGroupRequest::printDebug(QString indent)
01232 {
01233     kdDebug()<<indent<<"  + Request to group: "<<(m_group ? m_group->name() : "None")<<" units="<<m_units<<"%"<<endl;
01234     indent += "  !";
01235     QPtrListIterator<ResourceRequest> it(m_resourceRequests);
01236     for (; it.current(); ++it) {
01237         it.current()->printDebug(indent);
01238     }
01239 }
01240 
01241 void ResourceRequest::printDebug(QString indent)
01242 {
01243     kdDebug()<<indent<<"  + Request to resource: "<<(m_resource ? m_resource->name() : "None")<<" units="<<m_units<<"%"<<endl;
01244 }
01245 
01246 void ResourceRequestCollection::printDebug(QString indent)
01247 {
01248     kdDebug()<<indent<<"  + Resource requests:"<<endl;
01249     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01250     for (; it.current(); ++it) {
01251         it.current()->printDebug(indent+"  ");
01252     }
01253 }
01254 #endif
01255 
01256 }  //KPlato namespace
KDE Home | KDE Accessibility Home | Description of Access Keys