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