00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00041 }
00042
00043 CalendarDay::CalendarDay(int state)
00044 : m_date(),
00045 m_state(state),
00046 m_workingIntervals() {
00047
00048
00049 }
00050
00051 CalendarDay::CalendarDay(QDate date, int state)
00052 : m_date(date),
00053 m_state(state),
00054 m_workingIntervals() {
00055
00056
00057 }
00058
00059 CalendarDay::CalendarDay(CalendarDay *day)
00060 : m_workingIntervals() {
00061
00062
00063 copy(*day);
00064 }
00065
00066 CalendarDay::~CalendarDay() {
00067
00068 while (!m_workingIntervals.isEmpty())
00069 delete m_workingIntervals.takeFirst();
00070 }
00071
00072 const CalendarDay &CalendarDay::copy(const CalendarDay &day) {
00073
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
00085 bool ok=false;
00086 m_state = QString(element.attribute("state", "-1")).toInt(&ok);
00087 if (m_state < 0)
00088 return false;
00089
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
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
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
00172 if (m_date.isValid() && day.date().isValid()) {
00173 if (m_date != day.date()) {
00174
00175 return false;
00176 }
00177 } else if (m_date.isValid() != day.date().isValid()) {
00178
00179 return false;
00180 }
00181 if (m_state != day.state()) {
00182
00183 return false;
00184 }
00185 if (m_workingIntervals.count() != day.workingIntervals().count()) {
00186
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
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
00213 Duration eff;
00214 if (m_state != Map::Working) {
00215
00216 return eff;
00217 }
00218 foreach (TimeInterval *i, m_workingIntervals) {
00219
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
00231 }
00232 }
00233
00234 return eff;
00235 }
00236
00237 TimeInterval CalendarDay::interval(const QTime &start, const QTime &end) const {
00238
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
00246 return TimeInterval(t1, t2);
00247 }
00248 }
00249 }
00250
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
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
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
00288 for (int i=0; i < 7; ++i) {
00289 m_weekdays.append(new CalendarDay());
00290 }
00291
00292 }
00293
00294 CalendarWeekdays::CalendarWeekdays(CalendarWeekdays *weekdays)
00295 : m_weekdays() {
00296
00297 copy(*weekdays);
00298
00299 }
00300
00301 CalendarWeekdays::~CalendarWeekdays() {
00302 while (!m_weekdays.isEmpty())
00303 delete m_weekdays.takeFirst();
00304
00305 }
00306
00307 const CalendarWeekdays &CalendarWeekdays::copy(const CalendarWeekdays &weekdays) {
00308
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
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;
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
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());
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
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
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
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
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
00435 CalendarDay *day = weekday(date.dayOfWeek()-1);
00436 return day && day->hasInterval(start, end);
00437 }
00438
00439 bool CalendarWeekdays::hasInterval() const {
00440
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
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
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
00560 removeId();
00561 } else if (c) {
00562
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();
00568 return false;
00569 }
00570 m_id = id;
00571 insertId(id);
00572
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
00592
00593 setId(element.attribute("id"));
00594 m_parentId = element.attribute("parent");
00595 m_name = element.attribute("name","");
00596
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
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;
00625 }
00626 }
00627 }
00628 }
00629 return true;
00630 }
00631
00632 void Calendar::save(QDomElement &element) const {
00633
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
00654 foreach (CalendarDay *d, m_days) {
00655 if (d->date() == date) {
00656 if (skipNone && d->state() == Map::None) {
00657 continue;
00658 }
00659 return d;
00660 }
00661 }
00662
00663 return 0;
00664 }
00665
00666 bool Calendar::hasParent(Calendar *cal) {
00667
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
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
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
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
00711 return project()->defaultCalendar()->effort(date, start, end);
00712 }
00713
00714 Duration Calendar::effort(const DateTime &start, const DateTime &end) const {
00715
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);
00727
00728 for (date = date.addDays(1); date <= end.date(); date = date.addDays(1)) {
00729 if (date < end.date())
00730 eff += effort(date, QTime(), endTime);
00731 else
00732 eff += effort(date, QTime(), end.time());
00733
00734 }
00735
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
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
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
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
00814 if (!start.isValid() || !end.isValid() || end <= start) {
00815
00816
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
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
00849 return t;
00850 }
00851
00852 DateTime Calendar::firstAvailableBefore(const DateTime &time, const DateTime &limit) {
00853
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());
00860 if (t == lmt)
00861 t = t.addDays(-1);
00862 if (t < limit)
00863 t = limit;
00864 DateTime res;
00865
00866 while (!res.isValid() && t >= limit) {
00867
00868 DateTime r = firstInterval(t, lmt).second;
00869 res = r;
00870
00871 while(r.isValid() && r < lmt) {
00872 r = firstInterval(r, lmt).second;
00873 if (r.isValid())
00874 res = r;
00875
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
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
00926 }
00927
00928 void StandardWorktime::init() {
00929
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
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
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 }