/* This file is part of the KDE project Copyright (C) 2003 - 2006 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTCALENDAR_H #define KPTCALENDAR_H #include "kptmap.h" #include "kptduration.h" #include #include #include class QDomElement; class QDateTime; class QTime; class QDate; class QString; namespace KPlato { class DateTime; class Project; class CalendarDay { public: CalendarDay(); CalendarDay(int state); CalendarDay(QDate date, int state=0); CalendarDay(CalendarDay *day); ~CalendarDay(); bool load(QDomElement &element); void save(QDomElement &element) const; const QPtrList > &workingIntervals() const { return m_workingIntervals; } void addInterval(QPair *interval); void addInterval(QPair interval) { addInterval(new QPair(interval)); } void clearIntervals() { m_workingIntervals.clear(); } void setIntervals(QPtrList > intervals) { m_workingIntervals.clear(); m_workingIntervals = intervals; } QTime startOfDay() const; QTime endOfDay() const; QDate date() const { return m_date; } void setDate(QDate date) { m_date = date; } int state() const { return m_state; } void setState(int state) { m_state = state; } bool operator==(const CalendarDay *day) const; bool operator==(const CalendarDay &day) const; bool operator!=(const CalendarDay *day) const; bool operator!=(const CalendarDay &day) const; /** * Returns the amount of 'worktime' that can be done on * this day between the times start and end. */ Duration effort(const QTime &start, const QTime &end); /** * Returns the actual 'work interval' for the interval start to end. * If no 'work interval' exists, returns the interval start, end. * Use @ref hasInterval() to check if a 'work interval' exists. */ QPair interval(const QTime &start, const QTime &end) const; bool hasInterval() const; /** * Returns true if at least a part of a 'work interval' exists * for the interval start to end. */ bool hasInterval(const QTime &start, const QTime &end) const; Duration duration() const; const CalendarDay ©(const CalendarDay &day); private: QDate m_date; //NOTE: inValid if used for weekdays int m_state; QPtrList > m_workingIntervals; #ifndef NDEBUG public: void printDebug(QCString indent=""); #endif }; class CalendarWeekdays { public: CalendarWeekdays(); CalendarWeekdays(CalendarWeekdays *weekdays); ~CalendarWeekdays(); bool load(QDomElement &element); void save(QDomElement &element) const; void addWeekday(CalendarDay *day) { m_weekdays.append(day); } const QPtrList &weekdays() const { return m_weekdays; } /** * Returns the pointer to CalendarDay for day or 0 if not defined. * day is 0..6. * @param day todo : add a comment */ CalendarDay *weekday(int day) const; CalendarDay *weekday(const QDate &date) const { return weekday(date.dayOfWeek()-1); } CalendarDay *replace(int weekday, CalendarDay *day) { CalendarDay *d = m_weekdays.at(weekday); m_weekdays.replace(weekday, day); return d; } IntMap map(); void setWeekday(IntMap::iterator it, int state) { m_weekdays.at(it.key())->setState(state); } int state(const QDate &date) const; int state(int weekday) const; void setState(int weekday, int state); const QPtrList > &intervals(int weekday) const; void setIntervals(int weekday, QPtrList >intervals); void clearIntervals(int weekday); bool operator==(const CalendarWeekdays *weekdays) const; bool operator!=(const CalendarWeekdays *weekdays) const; Duration effort(const QDate &date, const QTime &start, const QTime &end); /** * Returns the actual 'work interval' on the weekday defined by date * for the interval start to end. * If no 'work interval' exists, returns the interval start, end. * Use @ref hasInterval() to check if a 'work interval' exists. */ QPair interval(const QDate date, const QTime &start, const QTime &end) const; /** * Returns true if at least a part of a 'work interval' exists * on the weekday defined by date for the interval start to end. */ bool hasInterval(const QDate date, const QTime &start, const QTime &end) const; bool hasInterval() const; Duration duration() const; Duration duration(int weekday) const; /// Returns the time when the weekday starts QTime startOfDay(int weekday) const; /// Returns the time when the weekday ends QTime endOfDay(int weekday) const; const CalendarWeekdays ©(const CalendarWeekdays &weekdays); private: QPtrList m_weekdays; double m_workHours; #ifndef NDEBUG public: void printDebug(QCString indent=""); #endif }; /** * Calendar defines the working and nonworking days and hours. * A day can have the three states None (Undefined), NonWorking, or Working. * A calendar can have a parent calendar that defines the days that are * undefined in this calendar. If a day is still undefined, it defaults * to Nonworking. * A Working day has one or more work intervals to define the work hours. * * The definition can consist of two parts: Weekdays and Day. * Day has highest priority. * * A typical calendar hierarchy could include calendars on three levels: * 1. Definition of normal weekdays and national holidays/vacation days. * 2. Definition of the company's special workdays/-time and vacation days. * 3. Definitions for groups of resources/individual resources. * */ class Calendar { public: Calendar(); Calendar(QString name, Calendar *parent=0); Calendar(Calendar *calendar); ~Calendar(); QString name() const { return m_name; } void setName(QString name) { m_name = name; } Calendar *parent() const { return m_parent; } void setParent(Calendar *parent) { m_parent = parent; } Project *project() const { return m_project; } void setProject(Project *project); bool isDeleted() const { return m_deleted; } void setDeleted(bool yes); QString id() const { return m_id; } bool setId(QString id); void generateId(); bool load(QDomElement &element); void save(QDomElement &element) const; /** * Find the definition for the day date. * If skipUndefined=true the day is NOT returned if it has state None (Undefined). */ CalendarDay *findDay(const QDate &date, bool skipUndefined=false) const; bool addDay(CalendarDay *day) { return m_days.insert(0, day); } bool removeDay(CalendarDay *day) { return m_days.removeRef(day); } CalendarDay *takeDay(CalendarDay *day) { return m_days.take(m_days.find(day)); } const QPtrList &days() const { return m_days; } /** * Returns the state of definition for parents day date in it. * Also checks the parents recursively. */ int parentDayState(const QDate &date) const; IntMap weekdaysMap() { return m_weekdays->map(); } void setWeekday(IntMap::iterator it, int state) { m_weekdays->setWeekday(it, state); } CalendarWeekdays *weekdays() { return m_weekdays; } CalendarDay *weekday(int day) const { return m_weekdays->weekday(day); } QString parentId() const { return m_parentId; } void setParentId(QString id) { m_parentId = id; } bool hasParent(Calendar *cal); /** * Returns the amount of 'worktime' that can be done on * the date date between the times start and end. */ Duration effort(const QDate &date, const QTime &start, const QTime &end) const; /** * Returns the amount of 'worktime' that can be done in the * interval from start to end */ Duration effort(const DateTime &start, const DateTime &end) const; /** * Returns the first 'work interval' for the interval * starting at start and ending at end. * If no 'work interval' exists, returns an interval with invalid DateTime. * You can also use @ref hasInterval() to check if a 'work interval' exists. */ QPair firstInterval(const DateTime &start, const DateTime &end) const; /** * Returns the first 'work interval' on date for the interval * starting at start and ending at end. * If no 'work interval' exists, returns an interval with first==second. * You can also use @ref hasInterval() to check if a 'work interval' exists. */ QPair firstInterval(const QDate &date, const QTime &start, const QTime &end) const; /** * Returns true if at least a part of a 'work interval' exists * for the interval starting at start and ending at end. */ bool hasInterval(const DateTime &start, const DateTime &end) const; /** * Returns true if at least a part of a 'work interval' exists * for the interval on date, starting at start and ending at end. */ bool hasInterval(const QDate &date, const QTime &start, const QTime &end) const; /** * Find the first available time after time before limit. * Return invalid datetime if not available. */ DateTime firstAvailableAfter(const DateTime &time, const DateTime &limit); /** * Find the first available time backwards from time. Search until limit. * Return invalid datetime if not available. */ DateTime firstAvailableBefore(const DateTime &time, const DateTime &limit); Calendar *findCalendar() const { return findCalendar(m_id); } Calendar *findCalendar(const QString &id) const; bool removeId() { return removeId(m_id); } bool removeId(const QString &id); void insertId(const QString &id); protected: const Calendar ©(Calendar &calendar); void init(); private: QString m_name; Calendar *m_parent; Project *m_project; bool m_deleted; QString m_id; QString m_parentId; QPtrList m_days; CalendarWeekdays *m_weekdays; #ifndef NDEBUG public: void printDebug(QCString indent=""); #endif }; class StandardWorktime { public: StandardWorktime(); StandardWorktime(StandardWorktime* worktime); ~StandardWorktime(); /// The work time of a normal year. Duration durationYear() const { return m_year; } /// The work time of a normal year. double year() const { return m_year.toDouble(Duration::Unit_h); } /// Set the work time of a normal year. void setYear(const Duration year) { m_year = year; } /// Set the work time of a normal year. void setYear(double hours) { m_year = Duration((Q_INT64)(hours*60.0*60.0)); } /// The work time of a normal month Duration durationMonth() const { return m_month; } /// The work time of a normal month double month() const { return m_month.toDouble(Duration::Unit_h); } /// Set the work time of a normal month void setMonth(const Duration month) { m_month = month; } /// Set the work time of a normal month void setMonth(double hours) { m_month = Duration((Q_INT64)(hours*60.0*60.0)); } /// The work time of a normal week Duration durationWeek() const { return m_week; } /// The work time of a normal week double week() const { return m_week.toDouble(Duration::Unit_h); } /// Set the work time of a normal week void setWeek(const Duration week) { m_week = week; } /// Set the work time of a normal week void setWeek(double hours) { m_week = Duration((Q_INT64)(hours*60.0*60.0)); } /// The work time of a normal day Duration durationDay() const { return m_day; } /// The work time of a normal day double day() const { return m_day.toDouble(Duration::Unit_h); } /// Set the work time of a normal day void setDay(const Duration day) { m_day = day; } /// Set the work time of a normal day void setDay(double hours) { m_day = Duration((Q_INT64)(hours*60.0*60.0)); } bool load(QDomElement &element); void save(QDomElement &element) const; Calendar *calendar() const { return m_calendar; } protected: void init(); private: Duration m_year; Duration m_month; Duration m_week; Duration m_day; Calendar *m_calendar; #ifndef NDEBUG public: void printDebug(QCString indent=""); #endif }; } //KPlato namespace #endif