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 && project() != 0 && (m_calendar == 0 || m_calendar->isDeleted())) {
00326         return project()->defaultCalendar();
00327     }
00328     if (m_calendar && m_calendar->isDeleted()) {
00329         return 0;
00330     }
00331     return m_calendar;
00332 }
00333 
00334 DateTime Resource::getFirstAvailableTime(DateTime /*after*/) {
00335     return DateTime();
00336 }
00337 
00338 DateTime Resource::getBestAvailableTime(Duration /*duration*/) {
00339     return DateTime();
00340 }
00341 
00342 DateTime Resource::getBestAvailableTime(const DateTime /*after*/, const Duration /*duration*/) {
00343     return DateTime();
00344 }
00345 
00346 bool Resource::load(QDomElement &element) {
00347     //kdDebug()<<k_funcinfo<<endl;
00348     QString s;
00349     setId(element.attribute("id"));
00350     m_name = element.attribute("name");
00351     m_initials = element.attribute("initials");
00352     m_email = element.attribute("email");
00353     setType(element.attribute("type"));
00354     m_calendar = findCalendar(element.attribute("calendar-id"));
00355     m_units = element.attribute("units", "100").toInt();
00356     s = element.attribute("available-from");
00357     if (s != "")
00358         m_availableFrom = DateTime::fromString(s);
00359     s = element.attribute("available-until");
00360     if (s != "")
00361         m_availableUntil = DateTime::fromString(s);
00362         
00363     cost.normalRate = KGlobal::locale()->readMoney(element.attribute("normal-rate"));
00364     cost.overtimeRate = KGlobal::locale()->readMoney(element.attribute("overtime-rate"));
00365     return true;
00366 }
00367 
00368 void Resource::save(QDomElement &element) const {
00369     //kdDebug()<<k_funcinfo<<endl;
00370     QDomElement me = element.ownerDocument().createElement("resource");
00371     element.appendChild(me);
00372 
00373     if (calendar(true))
00374         me.setAttribute("calendar-id", m_calendar->id());
00375     me.setAttribute("id", m_id);
00376     me.setAttribute("name", m_name);
00377     me.setAttribute("initials", m_initials);
00378     me.setAttribute("email", m_email);
00379     me.setAttribute("type", typeToString());
00380     me.setAttribute("units", m_units);
00381     me.setAttribute("available-from", m_availableFrom.toString(Qt::ISODate));
00382     me.setAttribute("available-until", m_availableUntil.toString(Qt::ISODate));
00383     me.setAttribute("normal-rate", KGlobal::locale()->formatMoney(cost.normalRate));
00384     me.setAttribute("overtime-rate", KGlobal::locale()->formatMoney(cost.overtimeRate));
00385 }
00386 
00387 bool Resource::isAvailable(Task */*task*/) {
00388     bool busy = false;
00389 /*    QPtrListIterator<Appointment> it(m_appointments);
00390     for (; it.current(); ++it) {
00391         if (it.current()->isBusy(task->startTime(), task->endTime())) {
00392             busy = true;
00393             break;
00394         }
00395     }*/
00396     return !busy;
00397 }
00398 
00399 QPtrList<Appointment> Resource::appointments() {
00400     QPtrList<Appointment> lst;
00401     if (m_currentSchedule)
00402         lst = m_currentSchedule->appointments();
00403     //kdDebug()<<k_funcinfo<<lst.count()<<endl;
00404     return lst;
00405 }
00406 
00407 Appointment *Resource::findAppointment(Node */*node*/) {
00408 /*    QPtrListIterator<Appointment> it = m_appointments;
00409     for (; it.current(); ++it) {
00410         if (it.current()->node() == node)
00411             return it.current();
00412     }*/
00413     return 0;
00414 }
00415 
00416 bool Resource::addAppointment(Appointment *appointment) {
00417     if (m_currentSchedule)
00418         return m_currentSchedule->add(appointment);
00419     return false;
00420 }
00421 
00422 bool Resource::addAppointment(Appointment *appointment, Schedule &main) {
00423     Schedule *s = findSchedule(main.id());
00424     if (s == 0) {
00425         s = createSchedule(&main);
00426     }
00427     appointment->setResource(s);
00428     return s->add(appointment);
00429 }
00430 
00431 void Resource::addAppointment(Schedule *node, DateTime &start, DateTime &end, double load) {
00432     //kdDebug()<<k_funcinfo<<endl;
00433     Schedule *s = findSchedule(node->id());
00434     if (s == 0) {
00435         s = createSchedule(node->parent());
00436     }
00437     s->addAppointment(node, start, end, load);
00438 }
00439 
00440 void Resource::initiateCalculation(Schedule &sch) {
00441     m_currentSchedule = createSchedule(&sch);
00442 }
00443 
00444 void Resource::removeSchedule(Schedule *schedule) {
00445     takeSchedule(schedule);
00446     delete schedule;
00447 }
00448 
00449 void Resource::takeSchedule(const Schedule *schedule) {
00450     if (schedule == 0)
00451         return;
00452     if (m_currentSchedule == schedule)
00453         m_currentSchedule = 0;
00454     m_schedules.take(schedule->id());
00455 }
00456 
00457 void Resource::addSchedule(Schedule *schedule) {
00458     if (schedule == 0)
00459         return;
00460     m_schedules.replace(schedule->id(), schedule);
00461 }
00462 
00463 ResourceSchedule *Resource::createSchedule(QString name, int type, int id) {
00464     ResourceSchedule *sch = new ResourceSchedule(this, name, (Schedule::Type)type, id);
00465     addSchedule(sch);
00466     return sch;
00467 }
00468 
00469 ResourceSchedule *Resource::createSchedule(Schedule *parent) {
00470     ResourceSchedule *sch = new ResourceSchedule(parent, this);
00471     addSchedule(sch);
00472     return sch;
00473 }
00474 
00475 void Resource::makeAppointment(Schedule *node, const DateTime &from, const DateTime &end) {
00476     if (!from.isValid() || !end.isValid()) {
00477         kdWarning()<<k_funcinfo<<"Invalid time"<<endl;
00478         return;
00479     }
00480     Calendar *cal = calendar();
00481     if (cal == 0) {
00482         return;
00483     }
00484     DateTime time = from;
00485     while (time < end) {
00486         //kdDebug()<<k_funcinfo<<time.toString()<<" to "<<end.toString()<<endl;
00487         if (!time.isValid() || !end.isValid()) {
00488             kdWarning()<<k_funcinfo<<"Invalid time"<<endl;
00489             return;
00490         }
00491         if (!cal->hasInterval(time, end)) {
00492             //kdDebug()<<time.toString()<<" to "<<end.toString()<<": No (more) interval(s)"<<endl;
00493             kdWarning()<<k_funcinfo<<m_name<<": Resource only partially available"<<endl;
00494             //node->resourceNotAvailable = true;
00495             return; // nothing more to do
00496         }
00497         QPair<DateTime, DateTime> i = cal->firstInterval(time, end);
00498         if (!i.second.isValid()) {
00499             kdWarning()<<k_funcinfo<<"Invalid interval: "<<time<<", "<<end<<endl;
00500             return;
00501         }
00502         if (time == i.second)
00503             return; // hmmm, didn't get a new interval, avoid loop
00504         addAppointment(node, i.first, i.second, m_units);
00505         //kdDebug()<<k_funcinfo<<"Add :"<<i.first.toString()<<" to "<<i.second.toString()<<endl;
00506         if (!(node->workStartTime.isValid()) || i.first < node->workStartTime)
00507             node->workStartTime = i.first;
00508         if (!(node->workEndTime.isValid()) || i.second > node->workEndTime)
00509             node->workEndTime = i.second;
00510         time = i.second;
00511     }
00512     return;
00513 }
00514 void Resource::makeAppointment(Schedule *node) {
00515     //kdDebug()<<k_funcinfo<<m_name<< ": "<<node->node()->name()<<": "<<node->startTime.toString()<<" dur "<<node->duration.toString()<<endl;
00516     if (!node->startTime.isValid()) {
00517         kdWarning()<<k_funcinfo<<m_name<<": startTime invalid"<<endl;
00518         return;
00519     }
00520     if (!node->endTime.isValid()) {
00521         kdWarning()<<k_funcinfo<<m_name<<": endTime invalid"<<endl;
00522         return;
00523     }
00524     Calendar *cal = calendar();
00525     if (m_type == Type_Material) {
00526         DateTime from = availableAfter(node->startTime, node->endTime);
00527         DateTime end = availableBefore(node->endTime, node->startTime);
00528         if (!from.isValid() || !end.isValid()) {
00529             return;
00530         }
00531         if (cal == 0) {
00532             // Allocate the whole period
00533             addAppointment(node, from, end, m_units);
00534             return;
00535         }
00536         makeAppointment(node, from, end);
00537     }
00538     if (!cal) {
00539         kdWarning()<<k_funcinfo<<m_name<<": No calendar defined"<<endl;
00540         return; 
00541     }
00542     //TODO: units and standard non-working days
00543     DateTime time = node->startTime;
00544     DateTime end = node->endTime;
00545     time = availableAfter(time, end);
00546     if (!time.isValid()) {
00547         kdWarning()<<k_funcinfo<<m_name<<": Resource not available (after="<<node->startTime<<", "<<end<<")"<<endl;
00548         node->resourceNotAvailable = true;
00549         return;
00550     }
00551     end = availableBefore(end, time);
00552     if (!end.isValid()) {
00553         kdWarning()<<k_funcinfo<<m_name<<": Resource not available (before="<<node->endTime<<", "<<time<<")"<<endl;
00554         node->resourceNotAvailable = true;
00555         return;
00556     }
00557     //kdDebug()<<k_funcinfo<<time.toString()<<" to "<<end.toString()<<endl;
00558     makeAppointment(node, time, end);
00559 }
00560 
00561 // the amount of effort we can do within the duration
00562 Duration Resource::effort(const DateTime &start, const Duration &duration, bool backward, bool *ok) const {
00563     //kdDebug()<<k_funcinfo<<m_name<<": "<<start.date().toString()<<" for duration "<<duration.toString(Duration::Format_Day)<<endl;
00564     bool sts=false;
00565     Duration e;
00566     if (duration == 0) {
00567         kdWarning()<<k_funcinfo<<"zero duration"<<endl;
00568         return e;
00569     }
00570     Calendar *cal = calendar();
00571     if (cal == 0) {
00572         kdWarning()<<k_funcinfo<<m_name<<": No calendar defined"<<endl;
00573         return e;
00574     }
00575     if (backward) {
00576         DateTime limit = start - duration;
00577         DateTime t = availableBefore(start, limit);
00578         if (t.isValid()) {
00579             sts = true;
00580             e = (cal->effort(limit, t) * m_units)/100;
00581         } else {
00582             //kdDebug()<<k_funcinfo<<m_name<<": Not available (start="<<start<<", "<<limit<<")"<<endl;
00583         }
00584     } else {
00585         DateTime limit = start + duration;
00586         DateTime t = availableAfter(start, limit);
00587         if (t.isValid()) {
00588             sts = true;
00589             e = (cal->effort(t, limit) * m_units)/100;
00590         }
00591     }
00592     //kdDebug()<<k_funcinfo<<start.toString()<<" e="<<e.toString(Duration::Format_Day)<<" ("<<m_units<<")"<<endl;
00593     if (ok) *ok = sts;
00594     return e;
00595 }
00596 
00597 DateTime Resource::availableAfter(const DateTime &time, const DateTime limit, bool checkAppointments) const {
00598     DateTime t;
00599     if (m_units == 0) {
00600         return t;
00601     }
00602     DateTime lmt = m_availableUntil;
00603     if (limit.isValid() && limit < lmt) {
00604         lmt = limit;
00605     }
00606     if (time >= lmt) {
00607         return t;
00608     }
00609     if (type() == Type_Material) {
00610         t = time > m_availableFrom ? time : m_availableFrom;
00611         //kdDebug()<<k_funcinfo<<time.toString()<<"="<<t.toString()<<" "<<m_name<<endl;
00612         return t;
00613     }
00614     Calendar *cal = calendar();
00615     if (cal == 0) {
00616         return t;
00617     }
00618     t = m_availableFrom > time ? m_availableFrom : time;
00619     t = cal->firstAvailableAfter(t, lmt);
00620     if (checkAppointments) {
00621         //TODO
00622     }
00623     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<t.toString()<<" "<<m_name<<endl;
00624     return t;
00625 }
00626 
00627 DateTime Resource::availableBefore(const DateTime &time, const DateTime limit, bool checkAppointments) const {
00628     DateTime t;
00629     if (m_units == 0) {
00630         return t;
00631     }
00632     DateTime lmt = m_availableFrom;
00633     if (limit.isValid() && limit > lmt) {
00634         lmt = limit;
00635     }
00636     if (time <= lmt) {
00637         return t;
00638     }
00639     if (type() == Type_Material) {
00640         t = time < m_availableUntil ? time : m_availableUntil;
00641         //kdDebug()<<k_funcinfo<<time.toString()<<"="<<t.toString()<<" "<<m_name<<endl;
00642         return t;
00643     }
00644     Calendar *cal = calendar();
00645     if (cal == 0) {
00646         return t;
00647     }
00648     if (!m_availableUntil.isValid()) {
00649         kdWarning()<<k_funcinfo<<m_name<<": availabelUntil is invalid"<<endl;
00650         t = time;
00651     } else {
00652         t = m_availableUntil < time ? m_availableUntil : time;
00653     }
00654     //kdDebug()<<k_funcinfo<<t<<", "<<lmt<<endl;
00655     t = cal->firstAvailableBefore(t, lmt);
00656     if (checkAppointments) {
00657         //TODO
00658     }
00659     //kdDebug()<<k_funcinfo<<m_name<<" returns: "<<time<<"="<<t<<" "<<endl;
00660     return t;
00661 }
00662 
00663 Resource *Resource::findId(const QString &id) const { 
00664     return m_project ? m_project->findResource(id) : 0; 
00665 }
00666 
00667 bool Resource::removeId(const QString &id) { 
00668     return m_project ? m_project->removeResourceId(id) : false; 
00669 }
00670 
00671 void Resource::insertId(const QString &id) { 
00672     if (m_project)
00673         m_project->insertResourceId(id, this); 
00674 }
00675 
00676 Calendar *Resource::findCalendar(const QString &id) const { 
00677     return (m_project ? m_project->findCalendar(id) : 0); 
00678 }
00679 
00680 bool Resource::isOverbooked() const {
00681     return isOverbooked(DateTime(), DateTime());
00682 }
00683 
00684 bool Resource::isOverbooked(const QDate &date) const {
00685     return isOverbooked(DateTime(date), DateTime(date.addDays(1)));
00686 }
00687 
00688 bool Resource::isOverbooked(const DateTime &start, const DateTime &end) const {
00689     //kdDebug()<<k_funcinfo<<m_name<<": "<<start.toString()<<" - "<<end.toString()<<" cs=("<<m_currentSchedule<<")"<<endl;
00690     return m_currentSchedule ? m_currentSchedule->isOverbooked(start, end) : false;
00691 }
00692 
00693 Appointment Resource::appointmentIntervals() const {
00694     Appointment a;
00695     if (m_currentSchedule == 0)
00696         return a;
00697     QPtrListIterator<Appointment> it = m_currentSchedule->appointments();
00698     for (; it.current(); ++it) {
00699         a += *(it.current());
00700     }
00701     return a;
00702 }
00703 
00704 Duration Resource::plannedEffort(const QDate &date) const {
00705     return m_currentSchedule ? m_currentSchedule->plannedEffort(date) : Duration::zeroDuration;
00706 }
00707 
00709 Risk::Risk(Node *n, Resource *r, RiskType rt) {
00710     m_node=n;
00711     m_resource=r;
00712     m_riskType=rt;
00713 }
00714 
00715 Risk::~Risk() {
00716 }
00717 
00718 ResourceRequest::ResourceRequest(Resource *resource, int units)
00719     : m_resource(resource),
00720       m_units(units),
00721       m_parent(0) {
00722     //kdDebug()<<k_funcinfo<<"("<<this<<") Request to: "<<(resource ? resource->name() : QString("None"))<<endl;
00723 }
00724 
00725 ResourceRequest::~ResourceRequest() {
00726     //kdDebug()<<k_funcinfo<<"("<<this<<") resource: "<<(m_resource ? m_resource->name() : QString("None"))<<endl;
00727     if (m_resource)
00728         m_resource->unregisterRequest(this);
00729     m_resource = 0;
00730 }
00731 
00732 bool ResourceRequest::load(QDomElement &element, Project &project) {
00733     //kdDebug()<<k_funcinfo<<endl;
00734     m_resource = project.resource(element.attribute("resource-id"));
00735     if (m_resource == 0) {
00736         kdWarning()<<k_funcinfo<<"The referenced resource does not exist: resource id="<<element.attribute("resource-id")<<endl;
00737         return false;
00738     }
00739     m_units  = element.attribute("units").toInt();
00740     return true;
00741 }
00742 
00743 void ResourceRequest::save(QDomElement &element) const {
00744     QDomElement me = element.ownerDocument().createElement("resource-request");
00745     element.appendChild(me);
00746     me.setAttribute("resource-id", m_resource->id());
00747     me.setAttribute("units", m_units);
00748 }
00749 
00750 int ResourceRequest::units() const {
00751     //kdDebug()<<k_funcinfo<<m_resource->name()<<": units="<<m_units<<endl;
00752     return m_units;
00753 }
00754 
00755 int ResourceRequest::workUnits() const {
00756     if (m_resource->type() == Resource::Type_Work)
00757         return units();
00758         
00759     //kdDebug()<<k_funcinfo<<"units=0"<<endl;
00760     return 0;
00761 }
00762 
00763 Task *ResourceRequest::task() const {
00764     return m_parent ? m_parent->task() : 0;
00765 }
00766 
00768 ResourceGroupRequest::ResourceGroupRequest(ResourceGroup *group, int units)
00769     : m_group(group), m_units(units) {
00770 
00771     //kdDebug()<<k_funcinfo<<"Request to: "<<(group ? group->name() : QString("None"))<<endl;
00772     if (group)
00773         group->registerRequest(this);
00774     m_resourceRequests.setAutoDelete(true);
00775 }
00776 
00777 ResourceGroupRequest::~ResourceGroupRequest() {
00778     //kdDebug()<<k_funcinfo<<"Group: "<<m_group->name()<<endl;
00779     if (m_group)
00780         m_group->unregisterRequest(this);
00781     m_resourceRequests.clear();
00782 }
00783 
00784 void ResourceGroupRequest::addResourceRequest(ResourceRequest *request) {
00785     //kdDebug()<<k_funcinfo<<"("<<request<<") to Group: "<<m_group->name()<<endl;
00786     request->setParent(this);
00787     m_resourceRequests.append(request);
00788     request->registerRequest();
00789 }
00790 
00791 ResourceRequest *ResourceGroupRequest::takeResourceRequest(ResourceRequest *request) {
00792     if (request)
00793         request->unregisterRequest();
00794     return m_resourceRequests.take(m_resourceRequests.findRef(request)); 
00795 }
00796 
00797 ResourceRequest *ResourceGroupRequest::find(Resource *resource) const {
00798     QPtrListIterator<ResourceRequest> it(m_resourceRequests);
00799     for (; it.current(); ++it)
00800         if (it.current()->resource() == resource)
00801             return it.current();
00802 
00803     return 0;
00804 }
00805 
00806 bool ResourceGroupRequest::load(QDomElement &element, Project &project) {
00807     //kdDebug()<<k_funcinfo<<endl;
00808     m_group = project.findResourceGroup(element.attribute("group-id"));
00809     if (m_group == 0) {
00810         //kdDebug()<<k_funcinfo<<"The referenced resource group does not exist: group id="<<element.attribute("group-id")<<endl;
00811         return false;
00812     }
00813     m_group->registerRequest(this);
00814     
00815     m_units  = element.attribute("units").toInt();
00816 
00817     QDomNodeList list = element.childNodes();
00818     for (unsigned int i=0; i<list.count(); ++i) {
00819         if (list.item(i).isElement()) {
00820             QDomElement e = list.item(i).toElement();
00821             if (e.tagName() == "resource-request") {
00822                 ResourceRequest *r = new ResourceRequest();
00823                 if (r->load(e, project))
00824                     addResourceRequest(r);
00825                 else {
00826                     kdError()<<k_funcinfo<<"Failed to load resource request"<<endl;
00827                     delete r;
00828                 }
00829             }
00830         }
00831     }
00832     return true;
00833 }
00834 
00835 void ResourceGroupRequest::save(QDomElement &element) const {
00836     if (units() == 0)
00837         return;
00838     QDomElement me = element.ownerDocument().createElement("resourcegroup-request");
00839     element.appendChild(me);
00840     me.setAttribute("group-id", m_group->id());
00841     me.setAttribute("units", m_units);
00842     QPtrListIterator<ResourceRequest> it(m_resourceRequests);
00843     for (; it.current(); ++it)
00844         it.current()->save(me);
00845 }
00846 
00847 int ResourceGroupRequest::units() const {
00848     int units = m_units;
00849     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00850     for (; it.current(); ++it) {
00851         units += it.current()->units();
00852     }
00853     //kdDebug()<<k_funcinfo<<"units="<<units<<endl;
00854     return units;
00855 }
00856 
00857 int ResourceGroupRequest::workUnits() const {
00858     int units = 0;
00859     if (m_group->type() == ResourceGroup::Type_Work)
00860         units = m_units;
00861     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00862     for (; it.current(); ++it) {
00863         units += it.current()->workUnits();
00864     }
00865     //kdDebug()<<k_funcinfo<<"units="<<units<<endl;
00866     return units;
00867 }
00868 
00869 //TODO: handle nonspecific resources
00870 Duration ResourceGroupRequest::effort(const DateTime &time, const Duration &duration, bool backward, bool *ok) const {
00871     Duration e;
00872     bool sts=false;
00873     if (ok) *ok = sts;
00874     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00875     for (; it.current(); ++it) {
00876         e += it.current()->resource()->effort(time, duration, backward, &sts);
00877         if (sts && ok) *ok = sts;
00878         //kdDebug()<<k_funcinfo<<(backward?"(B)":"(F)" )<<it.current()->resource()->name()<<": time="<<time<<" dur="<<duration.toString()<<"gave e="<<e.toString()<<endl;
00879     }
00880     //kdDebug()<<k_funcinfo<<time.toString()<<"d="<<duration.toString()<<": e="<<e.toString()<<endl;
00881     return e;
00882 }
00883 
00884 int ResourceGroupRequest::numDays(const DateTime &time, bool backward) const {
00885     DateTime t1, t2 = time;
00886     if (backward) {
00887         QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00888         for (; it.current(); ++it) {
00889             t1 = it.current()->resource()->availableFrom();
00890             if (!t2.isValid() || t2 > t1)
00891                 t2 = t1;
00892         }
00893         //kdDebug()<<k_funcinfo<<"bw "<<time.toString()<<": "<<t2.daysTo(time)<<endl;
00894         return t2.daysTo(time);
00895     }
00896     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
00897     for (; it.current(); ++it) {
00898         t1 = it.current()->resource()->availableUntil();
00899         if (!t2.isValid() || t2 < t1)
00900             t2 = t1;
00901     }
00902     //kdDebug()<<k_funcinfo<<"fw "<<time.toString()<<": "<<time.daysTo(t2)<<endl;
00903     return time.daysTo(t2);
00904 }
00905 
00906 Duration ResourceGroupRequest::duration(const DateTime &time, const Duration &_effort, bool backward) {
00907     //kdDebug()<<k_funcinfo<<"--->"<<(backward?"(B) ":"(F) ")<<m_group->name()<<" "<<time.toString()<<": effort: "<<_effort.toString(Duration::Format_Day)<<" ("<<_effort.milliseconds()<<")"<<endl;
00908     Duration e;
00909     if (_effort == Duration::zeroDuration) {
00910         return e;
00911     }
00912     bool sts=true;
00913     bool match = false;
00914     DateTime start = time;
00915     int inc = backward ? -1 : 1;
00916     DateTime end = start;
00917     Duration e1;
00918     Duration d(1, 0, 0); // 1 day
00919     int nDays = numDays(time, backward) + 1;
00920     for (int i=0; !match && i <= nDays; ++i) {
00921         // days
00922         end = end.addDays(inc);
00923         e1 = effort(start, d, backward, &sts);
00924         //kdDebug()<<"["<<i<<"of"<<nDays<<"] "<<(backward?"(B)":"(F):")<<"  start="<<start<<" e+e1="<<(e+e1).toString()<<" match "<<_effort.toString()<<endl;
00925         if (e + e1 < _effort) {
00926             e += e1;
00927             start = end;
00928         } else if (e + e1 == _effort) {
00929             e += e1;
00930             match = true;
00931         } else {
00932             end = start;
00933             break;
00934         }
00935     }
00936     //kdDebug()<<"duration "<<(backward?"backward ":"forward: ")<<start.toString()<<" - "<<end.toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")  match="<<match<<" sts="<<sts<<endl;
00937     d = Duration(0, 1, 0); // 1 hour
00938     for (int i=0; !match && i < 24; ++i) {
00939         // hours
00940         end = end.addSecs(inc*60*60);
00941         e1 = effort(start, d, backward, &sts);
00942         if (e + e1 < _effort) {
00943             e += e1;
00944             start = end;
00945         } else if (e + e1 == _effort) {
00946             e += e1;
00947             match = true;
00948         } else {
00949             end = start;
00950             break;
00951         }
00952         //kdDebug()<<"duration(h)["<<i<<"]"<<(backward?"backward ":"forward:")<<" time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
00953     }
00954     //kdDebug()<<"duration "<<(backward?"backward ":"forward: ")<<start.toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")  match="<<match<<" sts="<<sts<<endl;
00955     d = Duration(0, 0, 1); // 1 minute
00956     for (int i=0; !match && i < 60; ++i) {
00957         //minutes
00958         end = end.addSecs(inc*60);
00959         e1 = effort(start, d, backward, &sts);
00960         if (e + e1 < _effort) {
00961             e += e1;
00962             start = end;
00963         } else if (e + e1 == _effort) {
00964             e += e1;
00965             match = true;
00966         } else if (e + e1 > _effort) {
00967             end = start;
00968             break;
00969         }
00970         //kdDebug()<<"duration(m) "<<(backward?"backward":"forward:")<<"  time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
00971     }
00972     //kdDebug()<<"duration "<<(backward?"backward":"forward:")<<"  start="<<start.toString()<<" e="<<e.toString()<<" match="<<match<<" sts="<<sts<<endl;
00973     d = Duration(0, 0, 0, 1); // 1 second
00974     for (int i=0; !match && i < 60 && sts; ++i) {
00975         //seconds
00976         end = end.addSecs(inc);
00977         e1 = effort(start, d, backward, &sts);
00978         if (e + e1 < _effort) {
00979             e += e1;
00980             start = end;
00981         } else if (e + e1 == _effort) {
00982             e += e1;
00983             match = true;
00984         } else if (e + e1 > _effort) {
00985             end = start;
00986             break;
00987         }
00988         //kdDebug()<<"duration(s)["<<i<<"]"<<(backward?"backward":"forward:")<<" time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
00989     }
00990     d = Duration(0, 0, 0, 0, 1); // 1 millisecond
00991     for (int i=0; !match && i < 1000; ++i) {
00992         //milliseconds
00993         end.setTime(end.time().addMSecs(inc));
00994         e1 = effort(start, d, backward, &sts);
00995         if (e + e1 < _effort) {
00996             e += e1;
00997             start = end;
00998         } else if (e + e1 == _effort) {
00999             e += e1;
01000             match = true;
01001         } else if (e + e1 > _effort) {
01002             break;
01003         }
01004         //kdDebug()<<"duration(ms)["<<i<<"]"<<(backward?"backward":"forward:")<<" time="<<start.time().toString()<<" e="<<e.toString()<<" ("<<e.milliseconds()<<")"<<endl;
01005     }
01006     if (!match) {
01007         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;
01008     }
01009     DateTime t;
01010     if (e != Duration::zeroDuration) {
01011         t = backward ? availableAfter(end) : availableBefore(end);
01012     }
01013     end = t.isValid() ? t : time;
01014     //kdDebug()<<k_funcinfo<<"<---"<<(backward?"(B) ":"(F) ")<<m_group->name()<<": "<<end.toString()<<"-"<<time.toString()<<"="<<(end - time).toString()<<" effort: "<<_effort.toString(Duration::Format_Day)<<endl;
01015     return (end>time?end-time:time-end);
01016 }
01017 
01018 DateTime ResourceGroupRequest::availableAfter(const DateTime &time) {
01019     DateTime start;
01020     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
01021     for (; it.current(); ++it) {
01022         DateTime t = it.current()->resource()->availableAfter(time);
01023         if (t.isValid() && (!start.isValid() || t < start))
01024             start = t;
01025     }
01026     if (start.isValid() && start < time)
01027         start = time;
01028     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<start.toString()<<" "<<m_group->name()<<endl;
01029     return start;
01030 }
01031 
01032 DateTime ResourceGroupRequest::availableBefore(const DateTime &time) {
01033     DateTime end;
01034     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
01035     for (; it.current(); ++it) {
01036         DateTime t = it.current()->resource()->availableBefore(time);
01037         if (t.isValid() && (!end.isValid() || t > end))
01038             end = t;
01039     }
01040     if (!end.isValid() || end > time)
01041         end = time;
01042     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<end.toString()<<" "<<m_group->name()<<endl;
01043     return end;
01044 }
01045 
01046 void ResourceGroupRequest::makeAppointments(Schedule *schedule) {
01047     //kdDebug()<<k_funcinfo<<endl;
01048     QPtrListIterator<ResourceRequest> it = m_resourceRequests;
01049     for (; it.current(); ++it) {
01050         it.current()->makeAppointment(schedule);
01051     }
01052 }
01053 
01054 void ResourceGroupRequest::reserve(const DateTime &start, const Duration &duration) {
01055     m_start = start;
01056     m_duration = duration;
01057 }
01058 
01059 bool ResourceGroupRequest::isEmpty() const {
01060     return m_resourceRequests.isEmpty() && m_units == 0;
01061 }
01062 
01063 Task *ResourceGroupRequest::task() const {
01064     return m_parent ? &(m_parent->task()) : 0;
01065 }
01066 
01068 ResourceRequestCollection::ResourceRequestCollection(Task &task)
01069     : m_task(task) {
01070     m_requests.setAutoDelete(true);
01071 }
01072 
01073 ResourceRequestCollection::~ResourceRequestCollection() {
01074     //kdDebug()<<k_funcinfo<<"Group: "<<m_group->name()<<endl;
01075     m_requests.clear();
01076 }
01077 
01078 ResourceGroupRequest *ResourceRequestCollection::find(ResourceGroup *group) const {
01079     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01080     for (; it.current(); ++it) {
01081         if (it.current()->group() == group)
01082             return it.current(); // we assume only one request to the same group
01083     }
01084     return 0;
01085 }
01086 
01087 
01088 ResourceRequest *ResourceRequestCollection::find(Resource *resource) const {
01089     ResourceRequest *req = 0;
01090     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01091     for (; !req && it.current(); ++it) {
01092         req = it.current()->find(resource);
01093     }
01094     return req;
01095 }
01096 
01097 // bool ResourceRequestCollection::load(QDomElement &element, Project &project) {
01098 //     //kdDebug()<<k_funcinfo<<endl;
01099 //     return true;
01100 // }
01101 
01102 void ResourceRequestCollection::save(QDomElement &element) const {
01103     //kdDebug()<<k_funcinfo<<endl;
01104     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01105     for ( ; it.current(); ++it ) {
01106         it.current()->save(element);
01107     }
01108 }
01109 
01110 int ResourceRequestCollection::units() const {
01111     //kdDebug()<<k_funcinfo<<endl;
01112     int units = 0;
01113     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01114     for (; it.current(); ++it) {
01115         units += it.current()->units();
01116         //kdDebug()<<k_funcinfo<<" Group: "<<it.current()->group()->name()<<" now="<<units<<endl;
01117     }
01118     return units;
01119 }
01120 
01121 int ResourceRequestCollection::workUnits() const {
01122     //kdDebug()<<k_funcinfo<<endl;
01123     int units = 0;
01124     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01125     for (; it.current(); ++it) {
01126         units += it.current()->workUnits();
01127     }
01128     //kdDebug()<<k_funcinfo<<" units="<<units<<endl;
01129     return units;
01130 }
01131 
01132 // Returns the longest duration needed by any of the groups.
01133 // The effort is distributed on "work type" resourcegroups in proportion to
01134 // the amount of resources requested for each group.
01135 // "Material type" of resourcegroups does not (atm) affect the duration.
01136 Duration ResourceRequestCollection::duration(const DateTime &time, const Duration &effort, bool backward) {
01137     //kdDebug()<<k_funcinfo<<"time="<<time.toString()<<" effort="<<effort.toString(Duration::Format_Day)<<" backward="<<backward<<endl;
01138     if (isEmpty()) {
01139         return effort;
01140     }
01141     Duration dur;
01142     int units = workUnits();
01143     if (units == 0)
01144         units = 100; //hmmmm
01145     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01146     for (; it.current(); ++it) {
01147         if (it.current()->isEmpty())
01148             continue;
01149         if (it.current()->group()->type() == ResourceGroup::Type_Work) {
01150             Duration d = it.current()->duration(time, (effort*it.current()->workUnits())/units, backward);
01151             if (d > dur)
01152                 dur = d;
01153         } else if (it.current()->group()->type() == ResourceGroup::Type_Material) {
01154             //TODO
01155             if (dur == Duration::zeroDuration)
01156                 dur = effort;
01157         }
01158     }
01159     return dur;
01160 }
01161 
01162 DateTime ResourceRequestCollection::availableAfter(const DateTime &time) {
01163     DateTime start;
01164     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01165     for (; it.current(); ++it) {
01166         DateTime t = it.current()->availableAfter(time);
01167         if (t.isValid() && (!start.isValid() || t < start))
01168             start = t;
01169     }
01170     if (start.isValid() && start < time)
01171         start = time;
01172     //kdDebug()<<k_funcinfo<<time.toString()<<"="<<start.toString()<<endl;
01173     return start;
01174 }
01175 
01176 DateTime ResourceRequestCollection::availableBefore(const DateTime &time) {
01177     DateTime end;
01178     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01179     for (; it.current(); ++it) {
01180         DateTime t = it.current()->availableBefore(time);
01181         if (t.isValid() && (!end.isValid() ||t > end))
01182             end = t;
01183     }
01184     if (!end.isValid() || end > time)
01185         end = time;
01186     return end;
01187 }
01188 
01189 
01190 void ResourceRequestCollection::makeAppointments(Schedule *schedule) {
01191     //kdDebug()<<k_funcinfo<<endl;
01192     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01193     for (; it.current(); ++it) {
01194         it.current()->makeAppointments(schedule);
01195     }
01196 }
01197 
01198 void ResourceRequestCollection::reserve(const DateTime &start, const Duration &duration) {
01199     //kdDebug()<<k_funcinfo<<endl;
01200     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01201     for (; it.current(); ++it) {
01202         it.current()->reserve(start, duration);
01203     }
01204 }
01205 
01206 bool ResourceRequestCollection::isEmpty() const {
01207     QPtrListIterator<ResourceGroupRequest> it(m_requests);
01208     for (; it.current(); ++it) {
01209         if (!it.current()->isEmpty())
01210             return false;
01211     }
01212     return true;
01213 }
01214 #ifndef NDEBUG
01215 
01216 void ResourceGroup::printDebug(QString indent)
01217 {
01218     kdDebug()<<indent<<"  + Resource group: "<<m_name<<" id="<<m_id<<endl;
01219     indent += "   !";
01220     QPtrListIterator<Resource> it(m_resources);
01221     for ( ; it.current(); ++it)
01222         it.current()->printDebug(indent);
01223 }
01224 void Resource::printDebug(QString indent)
01225 {
01226     kdDebug()<<indent<<"  + Resource: "<<m_name<<" id="<<m_id/*<<" Overbooked="<<isOverbooked()*/<<endl;
01227     QIntDictIterator<Schedule> it(m_schedules);
01228     indent += "      ";
01229     for (; it.current(); ++it) {
01230         it.current()->printDebug(indent);
01231     }
01232     indent += "  !";
01233 }
01234 
01235 void ResourceGroupRequest::printDebug(QString indent)
01236 {
01237     kdDebug()<<indent<<"  + Request to group: "<<(m_group ? m_group->name() : "None")<<" units="<<m_units<<"%"<<endl;
01238     indent += "  !";
01239     QPtrListIterator<ResourceRequest> it(m_resourceRequests);
01240     for (; it.current(); ++it) {
01241         it.current()->printDebug(indent);
01242     }
01243 }
01244 
01245 void ResourceRequest::printDebug(QString indent)
01246 {
01247     kdDebug()<<indent<<"  + Request to resource: "<<(m_resource ? m_resource->name() : "None")<<" units="<<m_units<<"%"<<endl;
01248 }
01249 
01250 void ResourceRequestCollection::printDebug(QString indent)
01251 {
01252     kdDebug()<<indent<<"  + Resource requests:"<<endl;
01253     QPtrListIterator<ResourceGroupRequest> it = m_requests;
01254     for (; it.current(); ++it) {
01255         it.current()->printDebug(indent+"  ");
01256     }
01257 }
01258 #endif
01259 
01260 }  //KPlato namespace
KDE Home | KDE Accessibility Home | Description of Access Keys