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 kdDebug()<<k_funcinfo<<"My id found, remove it"<<endl;
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
00727 return project()->defaultCalendar()->effort(date, start, end);
00728 }
00729
00730 Duration Calendar::effort(const DateTime &start, const DateTime &end) const {
00731
00732 Duration eff;
00733 if (!start.isValid() || !end.isValid() || end <= start) {
00734 return eff;
00735 }
00736 QDate date = start.date();
00737 QTime startTime = start.time();
00738 QTime endTime = end.time();
00739 if (end.date() > date) {
00740 endTime.setHMS(23, 59, 59, 999);
00741 }
00742 eff = effort(date, startTime, endTime);
00743
00744 for (date = date.addDays(1); date <= end.date(); date = date.addDays(1)) {
00745 if (date < end.date())
00746 eff += effort(date, QTime(), endTime);
00747 else
00748 eff += effort(date, QTime(), end.time());
00749
00750 }
00751
00752 return eff;
00753 }
00754
00755
00756 QPair<QTime, QTime> Calendar::firstInterval(const QDate &date, const QTime &startTime, const QTime &endTime) const {
00757 CalendarDay *day = findDay(date, true);
00758 if (day) {
00759 return day->interval(startTime, endTime);
00760 }
00761 if (m_weekdays) {
00762 if (m_weekdays->state(date) == Map::Working) {
00763 return m_weekdays->interval(date, startTime, endTime);
00764 }
00765 if (m_weekdays->state(date) == Map::NonWorking) {
00766 return QPair<QTime, QTime>(QTime(), QTime());
00767 }
00768 }
00769 if (m_parent && !m_parent->isDeleted()) {
00770 return m_parent->firstInterval(date, startTime, endTime);
00771 }
00772 return project()->defaultCalendar()->firstInterval(date, startTime, endTime);
00773 }
00774
00775 QPair<DateTime, DateTime> Calendar::firstInterval(const DateTime &start, const DateTime &end) const {
00776
00777 if (!start.isValid()) {
00778 kdWarning()<<k_funcinfo<<"Invalid start time"<<endl;
00779 return QPair<DateTime, DateTime>(DateTime(), DateTime());
00780 }
00781 if (!end.isValid()) {
00782 kdWarning()<<k_funcinfo<<"Invalid end time"<<endl;
00783 return QPair<DateTime, DateTime>(DateTime(), DateTime());
00784 }
00785 QTime startTime;
00786 QTime endTime;
00787 QDate date = start.date();
00788 int i=0;
00789 for (; date <= end.date() && i++ < 10; date = date.addDays(1)) {
00790 if (date < end.date())
00791 endTime = QTime(23, 59, 59, 999);
00792 else
00793 endTime = end.time();
00794 if (date > start.date())
00795 startTime = QTime();
00796 else
00797 startTime = start.time();
00798
00799 QPair<QTime, QTime> res = firstInterval(date, startTime, endTime);
00800 if (res.first < res.second) {
00801 return QPair<DateTime, DateTime>(DateTime(date,res.first),DateTime(date, res.second));
00802 }
00803 }
00804
00805 return QPair<DateTime, DateTime>(DateTime(), DateTime());
00806 }
00807
00808
00809 bool Calendar::hasInterval(const QDate &date, const QTime &startTime, const QTime &endTime) const {
00810 CalendarDay *day = findDay(date, true);
00811 if (day) {
00812
00813 return day->hasInterval(startTime, endTime);
00814 }
00815 if (m_weekdays) {
00816 if (m_weekdays->state(date) == Map::Working) {
00817 return m_weekdays->hasInterval(date, startTime, endTime);
00818 } else if (m_weekdays->state(date) == Map::NonWorking) {
00819 return false;
00820 }
00821 }
00822 if (m_parent && !m_parent->isDeleted()) {
00823 return m_parent->hasInterval(date, startTime, endTime);
00824 }
00825 return project()->defaultCalendar()->hasInterval(date, startTime, endTime);
00826 }
00827
00828 bool Calendar::hasInterval(const DateTime &start, const DateTime &end) const {
00829
00830 if (!start.isValid() || !end.isValid() || end <= start) {
00831
00832
00833 return false;
00834 }
00835 QTime startTime;
00836 QTime endTime;
00837 QDate date = start.date();
00838 for (; date <= end.date(); date = date.addDays(1)) {
00839 if (date < end.date())
00840 endTime = QTime(23, 59, 59, 999);
00841 else
00842 endTime = end.time();
00843 if (date > start.date())
00844 startTime = QTime();
00845 else
00846 startTime = start.time();
00847
00848 if (hasInterval(date, startTime, endTime))
00849 return true;
00850 }
00851 return false;
00852 }
00853
00854 DateTime Calendar::firstAvailableAfter(const DateTime &time, const DateTime &limit) {
00855
00856 if (!time.isValid() || !limit.isValid() || time >= limit) {
00857 kdError()<<k_funcinfo<<"Invalid input: "<<(time.isValid()?"":"(time invalid) ")<<(limit.isValid()?"":"(limit invalid) ")<<(time>limit?"":"(time>=limit)")<<endl;
00858 return DateTime();
00859 }
00860 if (!hasInterval(time, limit)) {
00861 return DateTime();
00862 }
00863 DateTime t = firstInterval(time, limit).first;
00864
00865 return t;
00866 }
00867
00868 DateTime Calendar::firstAvailableBefore(const DateTime &time, const DateTime &limit) {
00869
00870 if (!time.isValid() || !limit.isValid() || time <= limit) {
00871 kdError()<<k_funcinfo<<"Invalid input: "<<(time.isValid()?"":"(time invalid) ")<<(limit.isValid()?"":"(limit invalid) ")<<(time>limit?"":"(time<=limit)")<<endl;
00872 return DateTime();
00873 }
00874 DateTime lmt = time;
00875 DateTime t = DateTime(time.date());
00876 if (t == lmt)
00877 t = t.addDays(-1);
00878 if (t < limit)
00879 t = limit;
00880 DateTime res;
00881
00882 while (!res.isValid() && t >= limit) {
00883
00884 DateTime r = firstInterval(t, lmt).second;
00885 res = r;
00886
00887 while(r.isValid() && r < lmt) {
00888 r = firstInterval(r, lmt).second;
00889 if (r.isValid())
00890 res = r;
00891
00892 }
00893 if (!res.isValid()) {
00894 if (t == limit) {
00895 break;
00896 }
00897 lmt = t;
00898 t = t.addDays(-1);
00899 if (t < limit) {
00900 t = limit;
00901 }
00902 if (t == lmt)
00903 break;
00904 }
00905 }
00906
00907 return res;
00908 }
00909
00910 Calendar *Calendar::findCalendar(const QString &id) const {
00911 return (m_project ? m_project->findCalendar(id) : 0);
00912 }
00913
00914 bool Calendar::removeId(const QString &id) {
00915 return (m_project ? m_project->removeCalendarId(id) : false);
00916 }
00917
00918 void Calendar::insertId(const QString &id){
00919 if (m_project)
00920 m_project->insertCalendarId(id, this);
00921 }
00922
00924 StandardWorktime::StandardWorktime() {
00925 init();
00926 }
00927
00928 StandardWorktime::StandardWorktime(StandardWorktime *worktime) {
00929 if (worktime) {
00930 m_year = worktime->durationYear();
00931 m_month = worktime->durationMonth();
00932 m_week = worktime->durationWeek();
00933 m_day = worktime->durationDay();
00934 m_calendar = new Calendar(*(worktime->calendar()));
00935 } else {
00936 init();
00937 }
00938 }
00939
00940 StandardWorktime::~StandardWorktime() {
00941
00942 }
00943
00944 void StandardWorktime::init() {
00945
00946 m_year = Duration(0, 1760, 0);
00947 m_month = Duration(0, 176, 0);
00948 m_week = Duration(0, 40, 0);
00949 m_day = Duration(0, 8, 0);
00950 m_calendar = new Calendar;
00951 m_calendar->setName(i18n("Base"));
00952 QPair<QTime, QTime> t = QPair<QTime, QTime>(QTime(8,0,0), QTime(16,0,0));
00953 for (int i=0; i < 5; ++i) {
00954 m_calendar->weekday(i)->addInterval(t);
00955 m_calendar->weekday(i)->setState(Map::Working);
00956 }
00957 m_calendar->weekday(5)->setState(Map::NonWorking);
00958 m_calendar->weekday(6)->setState(Map::NonWorking);
00959 }
00960
00961 bool StandardWorktime::load(QDomElement &element) {
00962
00963 m_year = Duration::fromString(element.attribute("year"), Duration::Format_Hour);
00964 m_month = Duration::fromString(element.attribute("month"), Duration::Format_Hour);
00965 m_week = Duration::fromString(element.attribute("week"), Duration::Format_Hour);
00966 m_day = Duration::fromString(element.attribute("day"), Duration::Format_Hour);
00967
00968 QDomNodeList list = element.childNodes();
00969 for (unsigned int i=0; i<list.count(); ++i) {
00970 if (list.item(i).isElement()) {
00971 QDomElement e = list.item(i).toElement();
00972 if (e.tagName() == "calendar") {
00973 delete m_calendar;
00974 m_calendar = new Calendar;
00975 m_calendar->load(e);
00976 }
00977 }
00978 }
00979 return true;
00980 }
00981
00982 void StandardWorktime::save(QDomElement &element) const {
00983
00984 QDomElement me = element.ownerDocument().createElement("standard-worktime");
00985 element.appendChild(me);
00986 me.setAttribute("year", m_year.toString(Duration::Format_Hour));
00987 me.setAttribute("month", m_month.toString(Duration::Format_Hour));
00988 me.setAttribute("week", m_week.toString(Duration::Format_Hour));
00989 me.setAttribute("day", m_day.toString(Duration::Format_Hour));
00990
00991 m_calendar->save(me);
00992 }
00993
00994 #ifndef NDEBUG
00995 void CalendarDay::printDebug(QCString indent) {
00996 QString s[] = {"None", "Non-working", "Working"};
00997 kdDebug()<<indent<<" "<<m_date.toString()<<" = "<<s[m_state]<<endl;
00998 if (m_state == Map::Working) {
00999 indent += " ";
01000 QPtrListIterator<QPair<QTime, QTime> > it = m_workingIntervals;
01001 for (; it.current(); ++it) {
01002 kdDebug()<<indent<<" Interval: "<<it.current()->first<<" to "<<it.current()->second<<endl;
01003 }
01004 }
01005
01006 }
01007 void CalendarWeekdays::printDebug(QCString indent) {
01008 kdDebug()<<indent<<"Weekdays ------"<<endl;
01009 QPtrListIterator<CalendarDay> it = m_weekdays;
01010 for (char c='0'; it.current(); ++it) {
01011 it.current()->printDebug(indent + " Day " + c++ + ": ");
01012 }
01013
01014 }
01015 void Calendar::printDebug(QCString indent) {
01016 kdDebug()<<indent<<"Calendar "<<m_id<<": '"<<m_name<<"' Deleted="<<m_deleted<<endl;
01017 kdDebug()<<indent<<" Parent: "<<(m_parent ? m_parent->name() : "No parent")<<endl;
01018 m_weekdays->printDebug(indent + " ");
01019 kdDebug()<<indent<<" Days --------"<<endl;
01020 QPtrListIterator<CalendarDay> it = m_days;
01021 for (; it.current(); ++it) {
01022 it.current()->printDebug(indent + " ");
01023 }
01024 }
01025
01026 void StandardWorktime::printDebug(QCString indent) {
01027 kdDebug()<<indent<<"StandardWorktime "<<endl;
01028 kdDebug()<<indent<<"Year: "<<m_year.toString()<<endl;
01029 kdDebug()<<indent<<"Month: "<<m_month.toString()<<endl;
01030 kdDebug()<<indent<<"Week: "<<m_week.toString()<<endl;
01031 kdDebug()<<indent<<"Day: "<<m_day.toString()<<endl;
01032 }
01033
01034 #endif
01035
01036 }