F:/KPlato/koffice/kplato/kptcalendar.cc

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 - 2006 Dag Andersen <danders@get2net.dk>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation;
00007    version 2 of the License.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kptcalendar.h"
00021 #include "kptduration.h"
00022 #include "kptdatetime.h"
00023 #include "kptproject.h"
00024 
00025 #include <qdom.h>
00026 #include <QList>
00027 
00028 #include <klocale.h>
00029 #include <kdebug.h>
00030 
00031 namespace KPlato
00032 {
00033 
00035 CalendarDay::CalendarDay()
00036     : m_date(),
00037       m_state(0),
00038       m_workingIntervals() {
00039 
00040     //kDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00041 }
00042 
00043 CalendarDay::CalendarDay(int state)
00044     : m_date(),
00045       m_state(state),
00046       m_workingIntervals() {
00047 
00048     //kDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00049 }
00050 
00051 CalendarDay::CalendarDay(QDate date, int state)
00052     : m_date(date),
00053       m_state(state),
00054       m_workingIntervals() {
00055 
00056     //kDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00057 }
00058 
00059 CalendarDay::CalendarDay(CalendarDay *day)
00060     : m_workingIntervals() {
00061 
00062     //kDebug()<<k_funcinfo<<"("<<this<<") from ("<<day<<")"<<endl;
00063     copy(*day);
00064 }
00065 
00066 CalendarDay::~CalendarDay() {
00067     //kDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00068     while (!m_workingIntervals.isEmpty())
00069         delete m_workingIntervals.takeFirst();
00070 }
00071 
00072 const CalendarDay &CalendarDay::copy(const CalendarDay &day) {
00073     //kDebug()<<k_funcinfo<<"("<<&day<<") date="<<day.date().toString()<<endl;
00074     m_date = day.date();
00075     m_state = day.state();
00076     m_workingIntervals.clear();
00077     foreach (TimeInterval *i, day.workingIntervals()) {
00078         m_workingIntervals.append(new TimeInterval(i->first, i->second));
00079     }
00080     return *this;
00081 }
00082 
00083 bool CalendarDay::load(QDomElement &element) {
00084     //kDebug()<<k_funcinfo<<endl;
00085     bool ok=false;
00086     m_state = QString(element.attribute("state", "-1")).toInt(&ok);
00087     if (m_state < 0)
00088         return false;
00089     //kDebug()<<k_funcinfo<<" state="<<m_state<<endl;
00090     QString s = element.attribute("date");
00091     if (s != "") {
00092         m_date = QDate::fromString(s, Qt::ISODate);
00093         if (!m_date.isValid())
00094             m_date = QDate::fromString(s);
00095     }
00096     clearIntervals();
00097     QDomNodeList list = element.childNodes();
00098     for (unsigned int i=0; i<list.count(); ++i) {
00099         if (list.item(i).isElement()) {
00100             QDomElement e = list.item(i).toElement();
00101             if (e.tagName() == "interval") {
00102                 //kDebug()<<k_funcinfo<<"Interval start="<<e.attribute("start")<<" end="<<e.attribute("end")<<endl;
00103                 QString st = e.attribute("start");
00104                 QString en = e.attribute("end");
00105                 if (st != "" && en != "") {
00106                     QTime start = QTime::fromString(st);
00107                     QTime end = QTime::fromString(en);
00108                     addInterval(new TimeInterval(start,end));
00109                 }
00110             }
00111         }
00112     }
00113     return true;
00114 }
00115 
00116 void CalendarDay::save(QDomElement &element) const {
00117     //kDebug()<<k_funcinfo<<m_date.toString()<<endl;
00118     if (m_state == Map::None)
00119         return;
00120     if (m_date.isValid()) {
00121         element.setAttribute("date", m_date.toString(Qt::ISODate));
00122     }
00123     element.setAttribute("state", m_state);
00124     if (m_workingIntervals.count() == 0)
00125         return;
00126     
00127     foreach (TimeInterval *i, m_workingIntervals) {
00128         QDomElement me = element.ownerDocument().createElement("interval");
00129         element.appendChild(me);
00130         me.setAttribute("end", i->second.toString());
00131         me.setAttribute("start", i->first.toString());
00132     }
00133 } 
00134 
00135 void CalendarDay::addInterval(TimeInterval *interval) {
00136     m_workingIntervals.append(interval);
00137 }
00138 
00139 QTime CalendarDay::startOfDay() const {
00140     QTime t;
00141     if (!m_workingIntervals.isEmpty()) {
00142         QListIterator<TimeInterval*> it = m_workingIntervals;
00143         t = it.next()->first;
00144         while (it.hasNext()) {
00145             TimeInterval *i = it.next();
00146             if (t > i->first)
00147                 t = i->first;
00148         }
00149     }
00150     return t;
00151 }
00152 
00153 QTime CalendarDay::endOfDay() const {
00154     QTime t;
00155     if (!m_workingIntervals.isEmpty()) {
00156         QListIterator<TimeInterval*> it = m_workingIntervals;
00157         t = it.next()->second;
00158         while (it.hasNext()) {
00159             TimeInterval *i = it.next();
00160             if (t > i->second)
00161                 t = i->second;
00162         }
00163     }
00164     return t;
00165 }
00166     
00167 bool CalendarDay::operator==(const CalendarDay *day) const {
00168     return operator==(*day);
00169 }
00170 bool CalendarDay::operator==(const CalendarDay &day) const {
00171     //kDebug()<<k_funcinfo<<endl;
00172     if (m_date.isValid() && day.date().isValid()) {
00173         if (m_date != day.date()) {
00174             //kDebug()<<k_funcinfo<<m_date.toString()<<" != "<<day.date().toString()<<endl;
00175             return false;
00176         }
00177     } else if (m_date.isValid() != day.date().isValid()) {
00178         //kDebug()<<k_funcinfo<<"one of the dates is not valid"<<endl;
00179         return false;
00180     }
00181     if (m_state != day.state()) {
00182         //kDebug()<<k_funcinfo<<m_state<<" != "<<day.state()<<endl;
00183         return false;
00184     }
00185     if (m_workingIntervals.count() != day.workingIntervals().count()) {
00186         //kDebug()<<k_funcinfo<<m_workingIntervals.count()<<" != "<<day.workingIntervals().count()<<endl;
00187         return false;
00188     }
00189     foreach (TimeInterval *a, m_workingIntervals) {
00190         bool res = false;
00191         foreach (TimeInterval *b, day.workingIntervals()) {
00192             if (a->first == b->first && a->second == b->second) {
00193                 res = true;
00194                 break;
00195             }
00196         }
00197         if (res == false) {
00198             //kDebug()<<k_funcinfo<<"interval mismatch "<<a->first.toString()<<"-"<<a->second.toString()<<endl;
00199             return false;
00200         }
00201     }
00202     return true;
00203 }
00204 bool CalendarDay::operator!=(const CalendarDay *day) const {
00205     return operator!=(*day);
00206 }
00207 bool CalendarDay::operator!=(const CalendarDay &day) const {
00208     return !operator==(day);
00209 }
00210 
00211 Duration CalendarDay::effort(const QTime &start, const QTime &end) {
00212     //kDebug()<<k_funcinfo<<start.toString()<<" - "<<end.toString()<<endl;
00213     Duration eff;
00214     if (m_state != Map::Working) {
00215         //kDebug()<<k_funcinfo<<"Non working day"<<endl;
00216         return eff;
00217     }
00218     foreach (TimeInterval *i, m_workingIntervals) {
00219         //kDebug()<<k_funcinfo<<"Interval: "<<it.current()->first.toString()<<" - "<<it.current()->second.toString()<<endl;
00220         if (end > i->first && start < i->second) {
00221             DateTime dtStart(QDate::currentDate(), start);
00222             if (start < i->first) {
00223                 dtStart.setTime(i->first);
00224             }
00225             DateTime dtEnd(QDate::currentDate(), end);
00226             if (end > i->second) {
00227                 dtEnd.setTime(i->second);
00228             }
00229             eff += dtEnd - dtStart;
00230             //kDebug()<<k_funcinfo<<dtStart.time().toString()<<" - "<<dtEnd.time().toString()<<"="<<eff.toString(Duration::Format_Day)<<endl;
00231         }
00232     }
00233     //kDebug()<<k_funcinfo<<(m_date.isValid()?m_date.toString(Qt::ISODate):"Weekday")<<": "<<start.toString()<<" - "<<end.toString()<<": total="<<eff.toString(Duration::Format_Day)<<endl;
00234     return eff;
00235 }
00236 
00237 TimeInterval CalendarDay::interval(const QTime &start, const QTime &end) const {
00238     //kDebug()<<k_funcinfo<<endl;
00239     QTime t1, t2;
00240     if (m_state == Map::Working) {
00241         foreach (TimeInterval *i, m_workingIntervals) {
00242             if (start < i->second && end > i->first) {
00243                 t1 = start > i->first ? start : i->first;
00244                 t2 = end < i->second ? end : i->second;
00245                 //kDebug()<<k_funcinfo<<t1.toString()<<" to "<<t2.toString()<<endl;
00246                 return TimeInterval(t1, t2);
00247             }
00248         }
00249     }
00250     //kError()<<k_funcinfo<<"No interval "<<m_date<<": "<<start<<","<<end<<endl;
00251     return TimeInterval(t1, t2);
00252 }
00253 
00254 bool CalendarDay::hasInterval() const {
00255     return m_state == Map::Working && m_workingIntervals.count() > 0;
00256 }
00257 
00258 bool CalendarDay::hasInterval(const QTime &start, const QTime &end) const {
00259     //kDebug()<<k_funcinfo<<(m_date.isValid()?m_date.toString(Qt::ISODate):"Weekday")<<" "<<start.toString()<<" - "<<end.toString()<<endl;
00260     if (m_state != Map::Working) {
00261         return false;
00262     }
00263     foreach (TimeInterval *i, m_workingIntervals) {
00264         if (start < i->second && end > i->first) {
00265             //kDebug()<<k_funcinfo<<"true:"<<(m_date.isValid()?m_date.toString(Qt::ISODate):"Weekday")<<" "<<i->first.toString()<<" - "<<i->second.toString()<<endl;
00266             return true;
00267         }
00268     }
00269     return false;
00270 }
00271 
00272 Duration CalendarDay::duration() const {
00273     Duration dur;
00274     foreach (TimeInterval *i, m_workingIntervals) {
00275         DateTime start(QDate::currentDate(), i->first);
00276         DateTime end(QDate::currentDate(), i->second);
00277         dur += end - start;
00278     }
00279     return dur;
00280 }
00281 
00283 CalendarWeekdays::CalendarWeekdays()
00284     : m_weekdays(),
00285       m_workHours(40) {
00286 
00287     //kDebug()<<k_funcinfo<<"--->"<<endl;
00288     for (int i=0; i < 7; ++i) {
00289         m_weekdays.append(new CalendarDay());
00290     }
00291     //kDebug()<<k_funcinfo<<"<---"<<endl;
00292 }
00293 
00294 CalendarWeekdays::CalendarWeekdays(CalendarWeekdays *weekdays)
00295     : m_weekdays() {
00296     //kDebug()<<k_funcinfo<<"--->"<<endl;
00297     copy(*weekdays);
00298     //kDebug()<<k_funcinfo<<"<---"<<endl;
00299 }
00300 
00301 CalendarWeekdays::~CalendarWeekdays() {
00302     while (!m_weekdays.isEmpty())
00303         delete m_weekdays.takeFirst();
00304     //kDebug()<<k_funcinfo<<endl;
00305 }
00306 
00307 const CalendarWeekdays &CalendarWeekdays::copy(const CalendarWeekdays &weekdays) {
00308     //kDebug()<<k_funcinfo<<endl;
00309     while (!m_weekdays.isEmpty()) {
00310         delete m_weekdays.takeFirst();
00311     }
00312     foreach (CalendarDay *d, weekdays.weekdays()) {
00313         m_weekdays.append(new CalendarDay(d));
00314     }
00315     return *this;
00316 }
00317 
00318 bool CalendarWeekdays::load(QDomElement &element) {
00319     //kDebug()<<k_funcinfo<<endl;
00320     bool ok;
00321     int dayNo = QString(element.attribute("day","-1")).toInt(&ok);
00322     if (dayNo < 0 || dayNo > 6) {
00323         kError()<<k_funcinfo<<"Illegal weekday: "<<dayNo<<endl;
00324         return true; // we continue anyway
00325     }
00326     CalendarDay *day = m_weekdays.at(dayNo);
00327     if (!day)
00328         day = new CalendarDay();
00329     if (!day->load(element))
00330         day->setState(Map::None);
00331     return true;
00332 }
00333 
00334 void CalendarWeekdays::save(QDomElement &element) const {
00335     //kDebug()<<k_funcinfo<<endl;
00336     int i=0;
00337     foreach (CalendarDay *d, m_weekdays) {
00338         QDomElement me = element.ownerDocument().createElement("weekday");
00339         element.appendChild(me);
00340         me.setAttribute("day", i++);
00341         d->save(me);
00342     }
00343 }    
00344 
00345 IntMap CalendarWeekdays::map() {
00346     IntMap days;
00347     for (unsigned int i=0; i < m_weekdays.count(); ++i) {
00348         if (m_weekdays.at(i)->state() > 0)
00349             days.insert(i+1, m_weekdays.at(i)->state()); //Note: day numbers 1..7
00350     }
00351     return days;
00352 }
00353 
00354 int CalendarWeekdays::state(const QDate &date) const {
00355     return state(date.dayOfWeek()-1);
00356 }
00357 
00358 int CalendarWeekdays::state(int weekday) const {
00359     CalendarDay *day = const_cast<CalendarWeekdays*>(this)->m_weekdays.at(weekday);
00360     return day ? day->state() : Map::None;
00361 }
00362 
00363 void CalendarWeekdays::setState(int weekday, int state) {
00364     CalendarDay *day = m_weekdays.at(weekday);
00365     if (!day)
00366         return;
00367     day->setState(state);
00368 }
00369 
00370 const QList<TimeInterval*> &CalendarWeekdays::intervals(int weekday) const { 
00371     CalendarDay *day = const_cast<CalendarWeekdays*>(this)->m_weekdays.at(weekday);
00372     Q_ASSERT(day);
00373     return day->workingIntervals();
00374 }
00375 
00376 void CalendarWeekdays::setIntervals(int weekday, QList<TimeInterval*>intervals) {
00377     CalendarDay *day = m_weekdays.at(weekday);
00378     if (day)
00379         day->setIntervals(intervals); 
00380 }
00381 
00382 void CalendarWeekdays::clearIntervals(int weekday) {
00383     CalendarDay *day = m_weekdays.at(weekday);
00384     if (day)
00385         day->clearIntervals(); 
00386 }
00387 
00388 bool CalendarWeekdays::operator==(const CalendarWeekdays *wd) const {
00389     if (m_weekdays.count() != wd->weekdays().count())
00390         return false;
00391     for (unsigned int i=0; i < m_weekdays.count(); ++i) {
00392         // is there a better way to get around this const stuff?
00393         CalendarDay *day1 = const_cast<CalendarWeekdays*>(this)->m_weekdays.at(i);
00394         CalendarDay *day2 = const_cast<QList<CalendarDay*>&>(wd->weekdays()).at(i);
00395         if (day1 != day2)
00396             return false;
00397     }
00398     return true;
00399 }
00400 bool CalendarWeekdays::operator!=(const CalendarWeekdays *wd) const {
00401     if (m_weekdays.count() != wd->weekdays().count())
00402         return true;
00403     for (unsigned int i=0; i < m_weekdays.count(); ++i) {
00404         // is there a better way to get around this const stuff?
00405         CalendarDay *day1 = const_cast<CalendarWeekdays*>(this)->m_weekdays.at(i);
00406         CalendarDay *day2 = const_cast<QList<CalendarDay*>&>(wd->weekdays()).at(i);
00407         if (day1 != day2)
00408             return true;
00409     }
00410     return false;
00411 }
00412 
00413 Duration CalendarWeekdays::effort(const QDate &date, const QTime &start, const QTime &end) {
00414     //kDebug()<<k_funcinfo<<"Day of week="<<date.dayOfWeek()-1<<endl;
00415     CalendarDay *day = weekday(date.dayOfWeek()-1);
00416     if (day && day->state() == Map::Working) {
00417         return day->effort(start, end);
00418     }
00419     return Duration::zeroDuration;
00420 }
00421 
00422 TimeInterval CalendarWeekdays::interval(const QDate date, const QTime &start, const QTime &end) const {
00423     //kDebug()<<k_funcinfo<<endl;
00424     CalendarDay *day = weekday(date.dayOfWeek()-1);
00425     if (day && day->state() == Map::Working) {
00426         if (day->hasInterval(start, end)) {
00427             return day->interval(start, end);
00428         }
00429     }
00430     return TimeInterval(QTime(), QTime());
00431 }
00432 
00433 bool CalendarWeekdays::hasInterval(const QDate date, const QTime &start, const QTime &end) const {
00434     //kDebug()<<k_funcinfo<<date.toString()<<": "<<start.toString()<<" - "<<end.toString()<<endl;
00435     CalendarDay *day = weekday(date.dayOfWeek()-1);
00436     return day && day->hasInterval(start, end);
00437 }
00438 
00439 bool CalendarWeekdays::hasInterval() const {
00440     //kDebug()<<k_funcinfo<<endl;
00441     foreach (CalendarDay *d, m_weekdays) {
00442         if (d->hasInterval())
00443             return true;
00444     }
00445     return false;
00446 }
00447 
00448 CalendarDay *CalendarWeekdays::weekday(int day) const {
00449     int i=0;
00450     foreach (CalendarDay *d, m_weekdays) {
00451         if (i++ == day)
00452             return d;
00453     }
00454     return 0;
00455 }
00456 
00457 Duration CalendarWeekdays::duration() const {
00458     Duration dur;
00459     foreach (CalendarDay *d, m_weekdays) {
00460         dur += d->duration();
00461     }
00462     return dur;
00463 }
00464 
00465 Duration CalendarWeekdays::duration(int _weekday) const {
00466     CalendarDay *day = weekday(_weekday);
00467     if (day)
00468         return day->duration();
00469     return Duration();
00470 }
00471 
00472 QTime CalendarWeekdays::startOfDay(int _weekday) const {
00473     CalendarDay *day = weekday(_weekday);
00474     if (day)
00475         return day->startOfDay();
00476     return QTime();
00477 }
00478 
00479 QTime CalendarWeekdays::endOfDay(int _weekday) const {
00480     CalendarDay *day = weekday(_weekday);
00481     if (day)
00482         return day->endOfDay();
00483     return QTime();
00484 }
00485     
00486 
00488 
00489 Calendar::Calendar()
00490     : m_parent(0),
00491       m_project(0),
00492       m_deleted(false) {
00493 
00494     init();
00495 }
00496 
00497 Calendar::Calendar(QString name, Calendar *parent)
00498     : m_name(name),
00499       m_parent(parent),
00500       m_project(0),
00501       m_deleted(false),
00502       m_days() {
00503     
00504     init();
00505 }
00506 
00507 Calendar::~Calendar() {
00508     //kDebug()<<k_funcinfo<<"deleting "<<m_name<<endl;
00509     removeId();
00510     delete m_weekdays;
00511     while (!m_days.isEmpty())
00512         delete m_days.takeFirst();
00513 }
00514 Calendar::Calendar(Calendar *calendar)
00515     : m_project(0),
00516       m_days() {
00517     copy(*calendar);
00518 }
00519 
00520 const Calendar &Calendar::copy(Calendar &calendar) {
00521     m_name = calendar.name();
00522     m_parent = calendar.parent();
00523     m_deleted = calendar.isDeleted();
00524     m_id = calendar.id();
00525     
00526     foreach (CalendarDay *d, calendar.days()) {
00527         m_days.append(new CalendarDay(d));
00528     }
00529     m_weekdays = new CalendarWeekdays(calendar.weekdays());
00530     return *this;
00531 }
00532 
00533 void Calendar::init() {
00534     m_weekdays = new CalendarWeekdays();
00535 }
00536 
00537 void Calendar::setProject(Project *project) { 
00538     m_project = project;
00539     generateId();
00540 }
00541 
00542 void Calendar::setDeleted(bool yes) {
00543     if (yes) {
00544         removeId();
00545     } else {
00546         setId(m_id);
00547     }
00548     m_deleted = yes;
00549 }
00550 bool Calendar::setId(QString id) {
00551     //kDebug()<<k_funcinfo<<id<<endl;
00552     if (id.isEmpty()) {
00553         kError()<<k_funcinfo<<"id is empty"<<endl;
00554         m_id = id;
00555         return false;
00556     }
00557     Calendar *c = findCalendar();
00558     if (c == this) {
00559         //kDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
00560         removeId();
00561     } else if (c) {
00562         //can happen when making a copy
00563         kError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different node: "<<c->name()<<endl;
00564     }
00565     if (findCalendar(id)) {
00566         kError()<<k_funcinfo<<"id '"<<id<<"' is already used for different node: "<<findCalendar(id)->name()<<endl;
00567         m_id = QString(); // hmmm
00568         return false;
00569     }
00570     m_id = id;
00571     insertId(id);
00572     //kDebug()<<k_funcinfo<<m_name<<": inserted id="<<id<<endl;
00573     return true;
00574 }
00575 
00576 void Calendar::generateId() {
00577     if (!m_id.isEmpty()) {
00578         removeId();
00579     }
00580     for (int i=0; i<32000 ; ++i) {
00581         m_id = m_id.setNum(i);
00582         if (!findCalendar()) {
00583             insertId(m_id);
00584             return;
00585         }
00586     }
00587     m_id = QString();
00588 }
00589 
00590 bool Calendar::load(QDomElement &element) {
00591     //kDebug()<<k_funcinfo<<element.text()<<endl;
00592     //bool ok;
00593     setId(element.attribute("id"));
00594     m_parentId = element.attribute("parent");
00595     m_name = element.attribute("name","");
00596     //TODO parent
00597     
00598     QDomNodeList list = element.childNodes();
00599     for (unsigned int i=0; i<list.count(); ++i) {
00600         if (list.item(i).isElement()) {
00601             QDomElement e = list.item(i).toElement();
00602             if (e.tagName() == "weekday") {
00603                 if (!m_weekdays->load(e))
00604                     return false;
00605             }
00606             if (e.tagName() == "day") {
00607                 CalendarDay *day = new CalendarDay();
00608                 if (day->load(e)) {
00609                     if (!day->date().isValid()) {
00610                         delete day;
00611                         kError()<<k_funcinfo<<m_name<<": Failed to load calendarDay - Invalid date"<<endl;
00612                     } else {
00613                         CalendarDay *d = findDay(day->date());
00614                         if (d) {
00615                             // already exists, keep the new
00616                             deleteDay(d);
00617                             kWarning()<<k_funcinfo<<m_name<<" Load calendarDay - Date already exists"<<endl;
00618                         }
00619                         addDay(day);
00620                     }
00621                 } else {
00622                     delete day;
00623                     kError()<<k_funcinfo<<"Failed to load calendarDay"<<endl;
00624                     return true; //false; don't throw away the whole calendar
00625                 }
00626             }
00627         }
00628     }
00629     return true;
00630 }
00631 
00632 void Calendar::save(QDomElement &element) const {
00633     //kDebug()<<k_funcinfo<<m_name<<endl;
00634     if (m_deleted)
00635         return;
00636     
00637     QDomElement me = element.ownerDocument().createElement("calendar");
00638     element.appendChild(me);
00639     if (m_parent && !m_parent->isDeleted()) 
00640         me.setAttribute("parent", m_parent->id());
00641     me.setAttribute("name", m_name);
00642     me.setAttribute("id", m_id);
00643     m_weekdays->save(me);
00644     foreach (CalendarDay *d, m_days) {
00645         QDomElement e = me.ownerDocument().createElement("day");
00646         me.appendChild(e);
00647         d->save(e);
00648     }
00649     
00650 }
00651 
00652 CalendarDay *Calendar::findDay(const QDate &date, bool skipNone) const {
00653     //kDebug()<<k_funcinfo<<date.toString()<<endl;
00654     foreach (CalendarDay *d, m_days) {
00655         if (d->date() == date) {
00656             if (skipNone  && d->state() == Map::None) {
00657                 continue; // hmmm, break?
00658             }
00659             return d;
00660         }
00661     }
00662     //kDebug()<<k_funcinfo<<date.toString()<<" not found"<<endl;
00663     return 0;
00664 }
00665 
00666 bool Calendar::hasParent(Calendar *cal) {
00667     //kDebug()<<k_funcinfo<<endl;
00668     if (!m_parent)
00669         return false;
00670     if (m_parent == cal)
00671         return true;
00672     return m_parent->hasParent(cal);
00673 }
00674 
00675 Duration Calendar::effort(const QDate &date, const QTime &start, const QTime &end) const {
00676     //kDebug()<<k_funcinfo<<m_name<<": "<<date.toString(Qt::ISODate)<<" "<<start.toString()<<" - "<<end.toString()<<endl;
00677     if (start == end) {
00678         return Duration::zeroDuration;
00679     }
00680     QTime _start = start;
00681     QTime _end = end;
00682     if (start > end) {
00683         _start = end;
00684         _end = start;
00685     }
00686     // first, check my own day
00687     CalendarDay *day = findDay(date, true);
00688     if (day) {
00689         if (day->state() == Map::Working) {
00690             return day->effort(_start, _end);
00691         } else if (day->state() == Map::NonWorking) {
00692             return Duration::zeroDuration;
00693         } else {
00694             kError()<<k_funcinfo<<"Invalid state: "<<day->state()<<endl;
00695             return Duration::zeroDuration;
00696         }
00697     }
00698     // check my own weekdays
00699     if (m_weekdays) {
00700         if (m_weekdays->state(date) == Map::Working) {
00701             return m_weekdays->effort(date, _start, _end);
00702         }
00703         if (m_weekdays->state(date) == Map::NonWorking) {
00704             return Duration::zeroDuration;
00705         }
00706     }
00707     if (m_parent && !m_parent->isDeleted()) {
00708         return m_parent->effort(date, start, end);
00709     }
00710     // Check default calendar
00711     return project()->defaultCalendar()->effort(date, start, end);
00712 }
00713 
00714 Duration Calendar::effort(const DateTime &start, const DateTime &end) const {
00715     //kDebug()<<k_funcinfo<<m_name<<": "<<start<<" to "<<end<<endl;
00716     Duration eff;
00717     if (!start.isValid() || !end.isValid() || end <= start) {
00718         return eff;
00719     }
00720     QDate date = start.date();
00721     QTime startTime = start.time();
00722     QTime endTime = end.time();
00723     if (end.date() > date) {
00724         endTime.setHMS(23, 59, 59, 999);
00725     }
00726     eff = effort(date, startTime, endTime); // first day
00727     // Now get all the rest of the days
00728     for (date = date.addDays(1); date <= end.date(); date = date.addDays(1)) {
00729         if (date < end.date())
00730              eff += effort(date, QTime(), endTime); // whole days
00731         else 
00732              eff += effort(date, QTime(), end.time()); // last day
00733         //kDebug()<<k_funcinfo<<": eff now="<<eff.toString(Duration::Format_Day)<<endl;
00734     }
00735     //kDebug()<<k_funcinfo<<start.date().toString()<<"- "<<end.date().toString()<<": total="<<eff.toString(Duration::Format_Day)<<endl;
00736     return eff;
00737 }
00738 
00739 
00740 TimeInterval Calendar::firstInterval(const QDate &date, const QTime &startTime, const QTime &endTime) const {
00741     CalendarDay *day = findDay(date, true);
00742     if (day) {
00743         return day->interval(startTime, endTime);
00744     }
00745     if (m_weekdays) {
00746         if (m_weekdays->state(date) == Map::Working) {
00747             return m_weekdays->interval(date, startTime, endTime);
00748         }
00749         if (m_weekdays->state(date) == Map::NonWorking) {
00750             return TimeInterval(QTime(), QTime());
00751         }
00752     }
00753     if (m_parent && !m_parent->isDeleted()) {
00754         return m_parent->firstInterval(date, startTime, endTime);
00755     }
00756     return project()->defaultCalendar()->firstInterval(date, startTime, endTime);
00757 }
00758 
00759 DateTimeInterval Calendar::firstInterval(const DateTime &start, const DateTime &end) const {
00760     //kDebug()<<k_funcinfo<<start.toString()<<" - "<<end.toString()<<endl;
00761     if (!start.isValid()) {
00762         kWarning()<<k_funcinfo<<"Invalid start time"<<endl;
00763         return DateTimeInterval(DateTime(), DateTime());
00764     }
00765     if (!end.isValid()) {
00766         kWarning()<<k_funcinfo<<"Invalid end time"<<endl;
00767         return DateTimeInterval(DateTime(), DateTime());
00768     }
00769     QTime startTime;
00770     QTime endTime;
00771     QDate date = start.date();
00772     int i=0;
00773     for (; date <= end.date() && i++ < 10; date = date.addDays(1)) {
00774         if (date < end.date())
00775             endTime = QTime(23, 59, 59, 999);
00776         else
00777             endTime = end.time();
00778         if (date > start.date())
00779             startTime = QTime();
00780         else 
00781             startTime = start.time();
00782             
00783         TimeInterval res = firstInterval(date, startTime, endTime);
00784         if (res.first < res.second) {
00785             return DateTimeInterval(DateTime(date,res.first),DateTime(date, res.second));
00786         }
00787     }
00788     //kError()<<k_funcinfo<<"Didn't find an interval ("<<start<<", "<<end<<")"<<endl;
00789     return DateTimeInterval(DateTime(), DateTime());
00790 }
00791 
00792 
00793 bool Calendar::hasInterval(const QDate &date, const QTime &startTime, const QTime &endTime) const {
00794     CalendarDay *day = findDay(date, true);
00795     if (day) {
00796         //kDebug()<<k_funcinfo<<m_name<<" "<<date<<": "<<startTime<<" to "<<endTime<<endl;
00797         return day->hasInterval(startTime, endTime);
00798     } 
00799     if (m_weekdays) {
00800         if (m_weekdays->state(date) == Map::Working) {
00801             return m_weekdays->hasInterval(date, startTime, endTime);
00802         } else if (m_weekdays->state(date) == Map::NonWorking) {
00803             return false;
00804         }
00805     }
00806     if (m_parent && !m_parent->isDeleted()) {
00807         return m_parent->hasInterval(date, startTime, endTime);
00808     }
00809     return project()->defaultCalendar()->hasInterval(date, startTime, endTime);
00810 }
00811 
00812 bool Calendar::hasInterval(const DateTime &start, const DateTime &end) const {
00813     //kDebug()<<k_funcinfo<<m_name<<": "<<start<<" - "<<end<<endl;
00814     if (!start.isValid() || !end.isValid() || end <= start) {
00815         //kError()<<k_funcinfo<<"Invalid input: "<<(start.isValid()?"":"(start invalid) ")<<(end.isValid()?"":"(end invalid) ")<<(start>end?"":"(start<=end)")<<endl;
00816         //kDebug()<<kBacktrace(8)<<endl;
00817         return false;
00818     }
00819     QTime startTime;
00820     QTime endTime;
00821     QDate date = start.date();
00822     for (; date <= end.date(); date = date.addDays(1)) {
00823         if (date < end.date())
00824             endTime = QTime(23, 59, 59, 999);
00825         else
00826             endTime = end.time();
00827         if (date > start.date())
00828             startTime = QTime();
00829         else 
00830             startTime = start.time();
00831 
00832         if (hasInterval(date, startTime, endTime))
00833             return true;
00834     }
00835     return false;
00836 }
00837 
00838 DateTime Calendar::firstAvailableAfter(const DateTime &time, const DateTime &limit) {
00839     //kDebug()<<k_funcinfo<<m_name<<": check from "<<time.toString()<<" limit="<<limit.toString()<<endl;
00840     if (!time.isValid() || !limit.isValid() || time >= limit) {
00841         kError()<<k_funcinfo<<"Invalid input: "<<(time.isValid()?"":"(time invalid) ")<<(limit.isValid()?"":"(limit invalid) ")<<(time>limit?"":"(time>=limit)")<<endl;
00842         return DateTime();
00843     }
00844     if (!hasInterval(time, limit)) {
00845         return DateTime();
00846     }
00847     DateTime t = firstInterval(time, limit).first;
00848     //kDebug()<<k_funcinfo<<m_name<<": "<<t.toString()<<endl;
00849     return t;
00850 }
00851 
00852 DateTime Calendar::firstAvailableBefore(const DateTime &time, const DateTime &limit) {
00853     //kDebug()<<k_funcinfo<<m_name<<": check from "<<time.toString()<<" limit="<<limit.toString()<<endl;
00854     if (!time.isValid() || !limit.isValid() || time <= limit) {
00855         kError()<<k_funcinfo<<"Invalid input: "<<(time.isValid()?"":"(time invalid) ")<<(limit.isValid()?"":"(limit invalid) ")<<(time>limit?"":"(time<=limit)")<<endl;
00856         return DateTime();
00857     }
00858     DateTime lmt = time;
00859     DateTime t = DateTime(time.date()); // start of first day
00860     if (t == lmt)
00861         t = t.addDays(-1); // in case time == start of day
00862     if (t < limit)
00863         t = limit;  // always stop at limit (lower boundary)
00864     DateTime res;
00865     //kDebug()<<k_funcinfo<<m_name<<": t="<<t<<", "<<lmt<<" limit="<<limit<<endl;
00866     while (!res.isValid() && t >= limit) {
00867         // check intervals for 1 day
00868         DateTime r = firstInterval(t, lmt).second;
00869         res = r;
00870         // Find the last interval
00871         while(r.isValid() && r < lmt) {
00872             r = firstInterval(r, lmt).second;
00873             if (r.isValid())
00874                 res = r;
00875             //kDebug()<<k_funcinfo<<m_name<<": r="<<r<<", "<<lmt<<" res="<<res<<endl;
00876         }
00877         if (!res.isValid()) {
00878             if (t == limit) {
00879                 break;
00880             }
00881             lmt = t;
00882             t = t.addDays(-1);
00883             if (t < limit) {
00884                 t = limit;
00885             }
00886             if (t == lmt)
00887                 break;
00888         }
00889     }
00890     //kDebug()<<k_funcinfo<<m_name<<": "<<res<<endl;
00891     return res;
00892 }
00893 
00894 Calendar *Calendar::findCalendar(const QString &id) const { 
00895     return (m_project ? m_project->findCalendar(id) : 0); 
00896 }
00897 
00898 bool Calendar::removeId(const QString &id) { 
00899     return (m_project ? m_project->removeCalendarId(id) : false); 
00900 }
00901 
00902 void Calendar::insertId(const QString &id){ 
00903     if (m_project)
00904         m_project->insertCalendarId(id, this); 
00905 }
00906 
00908 StandardWorktime::StandardWorktime() {
00909     init();
00910 }
00911 
00912 StandardWorktime::StandardWorktime(StandardWorktime *worktime) {
00913     if (worktime) {
00914         m_year = worktime->durationYear();
00915         m_month = worktime->durationMonth();
00916         m_week = worktime->durationWeek();
00917         m_day = worktime->durationDay();
00918         m_calendar = new Calendar(*(worktime->calendar()));
00919     } else {
00920         init();
00921     }
00922 }
00923 
00924 StandardWorktime::~StandardWorktime() {
00925     //kDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
00926 }
00927 
00928 void StandardWorktime::init() {
00929     // Some sane default values
00930     m_year = Duration(0, 1760, 0);
00931     m_month = Duration(0, 176, 0);
00932     m_week = Duration(0, 40, 0);
00933     m_day = Duration(0, 8, 0);
00934     m_calendar = new Calendar;
00935     m_calendar->setName(i18n("Base"));
00936     TimeInterval t = TimeInterval(QTime(8,0,0), QTime(16,0,0));
00937     for (int i=0; i < 5; ++i) {
00938         m_calendar->weekday(i)->addInterval(t);
00939         m_calendar->weekday(i)->setState(Map::Working);
00940     }
00941     m_calendar->weekday(5)->setState(Map::NonWorking);
00942     m_calendar->weekday(6)->setState(Map::NonWorking);
00943 }
00944 
00945 bool StandardWorktime::load(QDomElement &element) {
00946     //kDebug()<<k_funcinfo<<endl;
00947     m_year = Duration::fromString(element.attribute("year"), Duration::Format_Hour); 
00948     m_month = Duration::fromString(element.attribute("month"), Duration::Format_Hour); 
00949     m_week = Duration::fromString(element.attribute("week"), Duration::Format_Hour); 
00950     m_day = Duration::fromString(element.attribute("day"), Duration::Format_Hour); 
00951     
00952     QDomNodeList list = element.childNodes();
00953     for (unsigned int i=0; i<list.count(); ++i) {
00954         if (list.item(i).isElement()) {
00955             QDomElement e = list.item(i).toElement();
00956             if (e.tagName() == "calendar") {
00957                 delete m_calendar;
00958                 m_calendar = new Calendar;
00959                 m_calendar->load(e);
00960             }
00961         }
00962     }
00963     return true;
00964 }
00965 
00966 void StandardWorktime::save(QDomElement &element) const {
00967     //kDebug()<<k_funcinfo<<endl;
00968     QDomElement me = element.ownerDocument().createElement("standard-worktime");
00969     element.appendChild(me);
00970     me.setAttribute("year", m_year.toString(Duration::Format_Hour));
00971     me.setAttribute("month", m_month.toString(Duration::Format_Hour));
00972     me.setAttribute("week", m_week.toString(Duration::Format_Hour));
00973     me.setAttribute("day", m_day.toString(Duration::Format_Hour));
00974     
00975     m_calendar->save(me);
00976 }
00977 
00978 #ifndef NDEBUG
00979 void CalendarDay::printDebug(QString indent) {
00980     QString s[] = {"None", "Non-working", "Working"};
00981     kDebug()<<indent<<" "<<m_date.toString()<<" = "<<s[m_state]<<endl;
00982     if (m_state == Map::Working) {
00983         indent += "  ";
00984         foreach (TimeInterval *i, m_workingIntervals) {
00985             kDebug()<<indent<<" Interval: "<<i->first<<" to "<<i->second<<endl;
00986         }
00987     }
00988     
00989 }
00990 void CalendarWeekdays::printDebug(QString indent) {
00991     kDebug()<<indent<<"Weekdays ------"<<endl;
00992     int c=1;
00993     foreach (CalendarDay *d, m_weekdays) {
00994         d->printDebug(indent + "  Day " + c++ + ": ");
00995     }
00996 
00997 }
00998 void Calendar::printDebug(QString indent) {
00999     kDebug()<<indent<<"Calendar "<<m_id<<": '"<<m_name<<"' Deleted="<<m_deleted<<endl;
01000     kDebug()<<indent<<"  Parent: "<<(m_parent ? m_parent->name() : "No parent")<<endl;
01001     m_weekdays->printDebug(indent + "  ");
01002     kDebug()<<indent<<"  Days --------"<<endl;
01003     foreach (CalendarDay *d, m_days) {
01004         d->printDebug(indent + "  ");
01005     }
01006 }
01007 
01008 void StandardWorktime::printDebug(QString indent) {
01009     kDebug()<<indent<<"StandardWorktime "<<endl;
01010     kDebug()<<indent<<"Year: "<<m_year.toString()<<endl;
01011     kDebug()<<indent<<"Month: "<<m_month.toString()<<endl;
01012     kDebug()<<indent<<"Week: "<<m_week.toString()<<endl;
01013     kDebug()<<indent<<"Day: "<<m_day.toString()<<endl;
01014 }
01015 
01016 #endif
01017 
01018 }  //KPlato namespace

Généré le Wed Nov 22 23:40:55 2006 pour KPlato par  doxygen 1.5.1-p1