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_days() {
00527 m_days.setAutoDelete(true);
00528 copy(*calendar);
00529 }
00530
00531 const Calendar &Calendar::copy(Calendar &calendar) {
00532 m_name = calendar.name();
00533 m_parent = calendar.parent();
00534 m_deleted = calendar.isDeleted();
00535 m_id = calendar.id();
00536
00537 QPtrListIterator<CalendarDay> it = calendar.days();
00538 for (; it.current(); ++it) {
00539 m_days.append(new CalendarDay(it.current()));
00540 }
00541 m_weekdays = new CalendarWeekdays(calendar.weekdays());
00542 return *this;
00543 }
00544
00545 void Calendar::init() {
00546 m_days.setAutoDelete(true);
00547 m_weekdays = new CalendarWeekdays();
00548 }
00549
00550 void Calendar::setProject(Project *project) {
00551 m_project = project;
00552 generateId();
00553 }
00554
00555 void Calendar::setDeleted(bool yes) {
00556 if (yes) {
00557 removeId();
00558 } else {
00559 setId(m_id);
00560 }
00561 m_deleted = yes;
00562 }
00563 bool Calendar::setId(QString id) {
00564
00565 if (id.isEmpty()) {
00566 kdError()<<k_funcinfo<<"id is empty"<<endl;
00567 m_id = id;
00568 return false;
00569 }
00570 Calendar *c = findCalendar();
00571 if (c == this) {
00572
00573 removeId();
00574 } else if (c) {
00575
00576 kdError()<<k_funcinfo<<"My id '"<<m_id<<"' already used for different node: "<<c->name()<<endl;
00577 }
00578 if (findCalendar(id)) {
00579 kdError()<<k_funcinfo<<"id '"<<id<<"' is already used for different node: "<<findCalendar(id)->name()<<endl;
00580 m_id = QString();
00581 return false;
00582 }
00583 m_id = id;
00584 insertId(id);
00585
00586 return true;
00587 }
00588
00589 void Calendar::generateId() {
00590 if (!m_id.isEmpty()) {
00591 removeId();
00592 }
00593 for (int i=0; i<32000 ; ++i) {
00594 m_id = m_id.setNum(i);
00595 if (!findCalendar()) {
00596 insertId(m_id);
00597 return;
00598 }
00599 }
00600 m_id = QString();
00601 }
00602
00603 bool Calendar::load(QDomElement &element) {
00604
00605
00606 setId(element.attribute("id"));
00607 m_parentId = element.attribute("parent");
00608 m_name = element.attribute("name","");
00609
00610
00611 QDomNodeList list = element.childNodes();
00612 for (unsigned int i=0; i<list.count(); ++i) {
00613 if (list.item(i).isElement()) {
00614 QDomElement e = list.item(i).toElement();
00615 if (e.tagName() == "weekday") {
00616 if (!m_weekdays->load(e))
00617 return false;
00618 }
00619 if (e.tagName() == "day") {
00620 CalendarDay *day = new CalendarDay();
00621 if (day->load(e)) {
00622 if (!day->date().isValid()) {
00623 delete day;
00624 kdError()<<k_funcinfo<<m_name<<": Failed to load calendarDay - Invalid date"<<endl;
00625 } else {
00626 CalendarDay *d = findDay(day->date());
00627 if (d) {
00628
00629 removeDay(d);
00630 kdWarning()<<k_funcinfo<<m_name<<" Load calendarDay - Date already exists"<<endl;
00631 }
00632 }
00633 addDay(day);
00634 } else {
00635 delete day;
00636 kdError()<<k_funcinfo<<"Failed to load calendarDay"<<endl;
00637 return true;
00638 }
00639 }
00640 }
00641 }
00642 return true;
00643 }
00644
00645 void Calendar::save(QDomElement &element) const {
00646
00647 if (m_deleted)
00648 return;
00649
00650 QDomElement me = element.ownerDocument().createElement("calendar");
00651 element.appendChild(me);
00652 if (m_parent && !m_parent->isDeleted())
00653 me.setAttribute("parent", m_parent->id());
00654 me.setAttribute("name", m_name);
00655 me.setAttribute("id", m_id);
00656 m_weekdays->save(me);
00657 QPtrListIterator<CalendarDay> it = m_days;
00658 for (; it.current(); ++it) {
00659 QDomElement e = me.ownerDocument().createElement("day");
00660 me.appendChild(e);
00661 it.current()->save(e);
00662 }
00663
00664 }
00665
00666 CalendarDay *Calendar::findDay(const QDate &date, bool skipNone) const {
00667
00668 QPtrListIterator<CalendarDay> it = m_days;
00669 for (; it.current(); ++it) {
00670 if (it.current()->date() == date) {
00671 if (skipNone && it.current()->state() == Map::None) {
00672 continue;
00673 }
00674 return it.current();
00675 }
00676 }
00677
00678 return 0;
00679 }
00680
00681 bool Calendar::hasParent(Calendar *cal) {
00682
00683 if (!m_parent)
00684 return false;
00685 if (m_parent == cal)
00686 return true;
00687 return m_parent->hasParent(cal);
00688 }
00689
00690 Duration Calendar::effort(const QDate &date, const QTime &start, const QTime &end) const {
00691
00692 if (start == end) {
00693 return Duration::zeroDuration;
00694 }
00695 QTime _start = start;
00696 QTime _end = end;
00697 if (start > end) {
00698 _start = end;
00699 _end = start;
00700 }
00701
00702 CalendarDay *day = findDay(date, true);
00703 if (day) {
00704 if (day->state() == Map::Working) {
00705 return day->effort(_start, _end);
00706 } else if (day->state() == Map::NonWorking) {
00707 return Duration::zeroDuration;
00708 } else {
00709 kdError()<<k_funcinfo<<"Invalid state: "<<day->state()<<endl;
00710 return Duration::zeroDuration;
00711 }
00712 }
00713
00714 if (m_weekdays) {
00715 if (m_weekdays->state(date) == Map::Working) {
00716 return m_weekdays->effort(date, _start, _end);
00717 }
00718 if (m_weekdays->state(date) == Map::NonWorking) {
00719 return Duration::zeroDuration;
00720 }
00721 }
00722 if (m_parent && !m_parent->isDeleted()) {
00723 return m_parent->effort(date, start, end);
00724 }
00725 return Duration::zeroDuration;
00726 }
00727
00728 Duration Calendar::effort(const DateTime &start, const DateTime &end) const {
00729
00730 Duration eff;
00731 if (!start.isValid() || !end.isValid() || end <= start) {
00732 return eff;
00733 }
00734 QDate date = start.date();
00735 QTime startTime = start.time();
00736 QTime endTime = end.time();
00737 if (end.date() > date) {
00738 endTime.setHMS(23, 59, 59, 999);
00739 }
00740 eff = effort(date, startTime, endTime);
00741
00742 for (date = date.addDays(1); date <= end.date(); date = date.addDays(1)) {
00743 if (date < end.date())
00744 eff += effort(date, QTime(), endTime);
00745 else
00746 eff += effort(date, QTime(), end.time());
00747
00748 }
00749
00750 return eff;
00751 }
00752
00753
00754 QPair<QTime, QTime> Calendar::firstInterval(const QDate &date, const QTime &startTime, const QTime &endTime) const {
00755 CalendarDay *day = findDay(date, true);
00756 if (day) {
00757 return day->interval(startTime, endTime);
00758 }
00759 if (m_weekdays) {
00760 if (m_weekdays->state(date) == Map::Working) {
00761 return m_weekdays->interval(date, startTime, endTime);
00762 }
00763 if (m_weekdays->state(date) == Map::NonWorking) {
00764 return QPair<QTime, QTime>(QTime(), QTime());
00765 }
00766 }
00767 if (m_parent && !m_parent->isDeleted()) {
00768 return m_parent->firstInterval(date, startTime, endTime);
00769 }
00770 return QPair<QTime, QTime>(QTime(), QTime());
00771 }
00772
00773 QPair<DateTime, DateTime> Calendar::firstInterval(const DateTime &start, const DateTime &end) const {
00774
00775 if (!start.isValid()) {
00776 kdWarning()<<k_funcinfo<<"Invalid start time"<<endl;
00777 return QPair<DateTime, DateTime>(DateTime(), DateTime());
00778 }
00779 if (!end.isValid()) {
00780 kdWarning()<<k_funcinfo<<"Invalid end time"<<endl;
00781 return QPair<DateTime, DateTime>(DateTime(), DateTime());
00782 }
00783 QTime startTime;
00784 QTime endTime;
00785 QDate date = start.date();
00786 int i=0;
00787 for (; date <= end.date() && i++ < 10; date = date.addDays(1)) {
00788 if (date < end.date())
00789 endTime = QTime(23, 59, 59, 999);
00790 else
00791 endTime = end.time();
00792 if (date > start.date())
00793 startTime = QTime();
00794 else
00795 startTime = start.time();
00796
00797 QPair<QTime, QTime> res = firstInterval(date, startTime, endTime);
00798 if (res.first < res.second) {
00799 return QPair<DateTime, DateTime>(DateTime(date,res.first),DateTime(date, res.second));
00800 }
00801 }
00802
00803 return QPair<DateTime, DateTime>(DateTime(), DateTime());
00804 }
00805
00806
00807 bool Calendar::hasInterval(const QDate &date, const QTime &startTime, const QTime &endTime) const {
00808 CalendarDay *day = findDay(date, true);
00809 if (day) {
00810
00811 return day->hasInterval(startTime, endTime);
00812 }
00813 if (m_weekdays) {
00814 if (m_weekdays->state(date) == Map::Working) {
00815 return m_weekdays->hasInterval(date, startTime, endTime);
00816 } else if (m_weekdays->state(date) == Map::NonWorking) {
00817 return false;
00818 }
00819 }
00820 if (m_parent && !m_parent->isDeleted()) {
00821 return m_parent->hasInterval(date, startTime, endTime);
00822 }
00823 return false;
00824 }
00825
00826 bool Calendar::hasInterval(const DateTime &start, const DateTime &end) const {
00827
00828 if (!start.isValid() || !end.isValid() || end <= start) {
00829
00830
00831 return false;
00832 }
00833 QTime startTime;
00834 QTime endTime;
00835 QDate date = start.date();
00836 for (; date <= end.date(); date = date.addDays(1)) {
00837 if (date < end.date())
00838 endTime = QTime(23, 59, 59, 999);
00839 else
00840 endTime = end.time();
00841 if (date > start.date())
00842 startTime = QTime();
00843 else
00844 startTime = start.time();
00845
00846 if (hasInterval(date, startTime, endTime))
00847 return true;
00848 }
00849 return false;
00850 }
00851
00852 DateTime Calendar::firstAvailableAfter(const DateTime &time, const DateTime &limit) {
00853
00854 if (!time.isValid() || !limit.isValid() || time >= limit) {
00855 kdError()<<k_funcinfo<<"Invalid input: "<<(time.isValid()?"":"(time invalid) ")<<(limit.isValid()?"":"(limit invalid) ")<<(time>limit?"":"(time>=limit)")<<endl;
00856 return DateTime();
00857 }
00858 if (!hasInterval(time, limit)) {
00859 return DateTime();
00860 }
00861 DateTime t = firstInterval(time, limit).first;
00862
00863 return t;
00864 }
00865
00866 DateTime Calendar::firstAvailableBefore(const DateTime &time, const DateTime &limit) {
00867
00868 if (!time.isValid() || !limit.isValid() || time <= limit) {
00869 kdError()<<k_funcinfo<<"Invalid input: "<<(time.isValid()?"":"(time invalid) ")<<(limit.isValid()?"":"(limit invalid) ")<<(time>limit?"":"(time<=limit)")<<endl;
00870 return DateTime();
00871 }
00872 DateTime lmt = time;
00873 DateTime t = DateTime(time.date());
00874 if (t == lmt)
00875 t = t.addDays(-1);
00876 if (t < limit)
00877 t = limit;
00878 DateTime res;
00879
00880 while (!res.isValid() && t >= limit) {
00881
00882 DateTime r = firstInterval(t, lmt).second;
00883 res = r;
00884
00885 while(r.isValid() && r < lmt) {
00886 r = firstInterval(r, lmt).second;
00887 if (r.isValid())
00888 res = r;
00889
00890 }
00891 if (!res.isValid()) {
00892 if (t == limit) {
00893 break;
00894 }
00895 lmt = t;
00896 t = t.addDays(-1);
00897 if (t < limit) {
00898 t = limit;
00899 }
00900 if (t == lmt)
00901 break;
00902 }
00903 }
00904
00905 return res;
00906 }
00907
00908 Calendar *Calendar::findCalendar(const QString &id) const {
00909 return (m_project ? m_project->findCalendar(id) : 0);
00910 }
00911
00912 bool Calendar::removeId(const QString &id) {
00913 return (m_project ? m_project->removeCalendarId(id) : false);
00914 }
00915
00916 void Calendar::insertId(const QString &id){
00917 if (m_project)
00918 m_project->insertCalendarId(id, this);
00919 }
00920
00922 StandardWorktime::StandardWorktime() {
00923 init();
00924 }
00925
00926 StandardWorktime::StandardWorktime(StandardWorktime *worktime) {
00927 if (worktime) {
00928 m_year = worktime->durationYear();
00929 m_month = worktime->durationMonth();
00930 m_week = worktime->durationWeek();
00931 m_day = worktime->durationDay();
00932 } else {
00933 init();
00934 }
00935 }
00936
00937 StandardWorktime::~StandardWorktime() {
00938
00939 }
00940
00941 void StandardWorktime::init() {
00942
00943 m_year = Duration(0, 1760, 0);
00944 m_month = Duration(0, 176, 0);
00945 m_week = Duration(0, 40, 0);
00946 m_day = Duration(0, 8, 0);
00947 }
00948
00949 bool StandardWorktime::load(QDomElement &element) {
00950
00951 m_year = Duration::fromString(element.attribute("year"), Duration::Format_Hour);
00952 m_month = Duration::fromString(element.attribute("month"), Duration::Format_Hour);
00953 m_week = Duration::fromString(element.attribute("week"), Duration::Format_Hour);
00954 m_day = Duration::fromString(element.attribute("day"), Duration::Format_Hour);
00955 return true;
00956 }
00957
00958 void StandardWorktime::save(QDomElement &element) const {
00959
00960 QDomElement me = element.ownerDocument().createElement("standard-worktime");
00961 element.appendChild(me);
00962 me.setAttribute("year", m_year.toString(Duration::Format_Hour));
00963 me.setAttribute("month", m_month.toString(Duration::Format_Hour));
00964 me.setAttribute("week", m_week.toString(Duration::Format_Hour));
00965 me.setAttribute("day", m_day.toString(Duration::Format_Hour));
00966 }
00967
00968 #ifndef NDEBUG
00969 void CalendarDay::printDebug(QCString indent) {
00970 QString s[] = {"None", "Non-working", "Working"};
00971 kdDebug()<<indent<<" "<<m_date.toString()<<" = "<<s[m_state]<<endl;
00972 if (m_state == Map::Working) {
00973 indent += " ";
00974 QPtrListIterator<QPair<QTime, QTime> > it = m_workingIntervals;
00975 for (; it.current(); ++it) {
00976 kdDebug()<<indent<<" Interval: "<<it.current()->first<<" to "<<it.current()->second<<endl;
00977 }
00978 }
00979
00980 }
00981 void CalendarWeekdays::printDebug(QCString indent) {
00982 kdDebug()<<indent<<"Weekdays ------"<<endl;
00983 QPtrListIterator<CalendarDay> it = m_weekdays;
00984 for (char c='0'; it.current(); ++it) {
00985 it.current()->printDebug(indent + " Day " + c++ + ": ");
00986 }
00987
00988 }
00989 void Calendar::printDebug(QCString indent) {
00990 kdDebug()<<indent<<"Calendar "<<m_id<<": '"<<m_name<<"' Deleted="<<m_deleted<<endl;
00991 kdDebug()<<indent<<" Parent: "<<(m_parent ? m_parent->name() : "No parent")<<endl;
00992 m_weekdays->printDebug(indent + " ");
00993 kdDebug()<<indent<<" Days --------"<<endl;
00994 QPtrListIterator<CalendarDay> it = m_days;
00995 for (; it.current(); ++it) {
00996 it.current()->printDebug(indent + " ");
00997 }
00998 }
00999
01000 void StandardWorktime::printDebug(QCString indent) {
01001 kdDebug()<<indent<<"StandardWorktime "<<endl;
01002 kdDebug()<<indent<<"Year: "<<m_year.toString()<<endl;
01003 kdDebug()<<indent<<"Month: "<<m_month.toString()<<endl;
01004 kdDebug()<<indent<<"Week: "<<m_week.toString()<<endl;
01005 kdDebug()<<indent<<"Day: "<<m_day.toString()<<endl;
01006 }
01007
01008 #endif
01009
01010 }