-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend.cpp | 156 | ||||
-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend.h | 32 | ||||
-rw-r--r-- | libopie2/opiepim/core/odatebookaccess.cpp | 37 | ||||
-rw-r--r-- | libopie2/opiepim/core/odatebookaccess.h | 32 | ||||
-rw-r--r-- | libopie2/opiepim/oevent.cpp | 57 | ||||
-rw-r--r-- | libopie2/opiepim/oevent.h | 6 |
6 files changed, 288 insertions, 32 deletions
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend.cpp b/libopie2/opiepim/backend/odatebookaccessbackend.cpp new file mode 100644 index 0000000..8fa1a68 --- a/dev/null +++ b/libopie2/opiepim/backend/odatebookaccessbackend.cpp @@ -0,0 +1,156 @@ +#include <qtl.h> + +#include "orecur.h" + +#include "odatebookaccessbackend.h" + +namespace { +/* a small helper to get all NonRepeating events for a range of time */ + void events( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& events, + const QDate& from, const QDate& to ) { + QDateTime dtStart, dtEnd; + + for ( OEvent::ValueList::ConstIterator it = events.begin(); it != events.end(); ++it ) { + dtStart = (*it).startDateTime(); + dtEnd = (*it).endDateTime(); + + /* + * If in range + */ + if (dtStart.date() >= from && dtEnd.date() <= to ) { + OEffectiveEvent eff; + eff.setEvent( (*it) ); + eff.setDate( dtStart.date() ); + eff.setStartTime( dtStart.time() ); + + /* if not on the same day */ + if ( dtStart.date() != dtEnd.date() ) + eff.setEndTime( QTime(23, 59, 0 ) ); + else + eff.setEndTime( dtEnd.time() ); + + tmpList.append( eff ); + } + + /* we must also check for end date information... */ + if ( dtEnd.date() != dtStart.date() && dtEnd.date() >= from ) { + QDateTime dt = dtStart.addDays( 1 ); + dt.setTime( QTime(0, 0, 0 ) ); + QDateTime dtStop; + if ( dtEnd > to ) + dtStop = to; + else + dtStop = dtEnd; + + while ( dt <= dtStop ) { + OEffectiveEvent eff; + eff.setEvent( (*it) ); + eff.setDate( dt.date() ); + + if ( dt >= from ) { + eff.setStartTime( QTime(0, 0, 0 ) ); + if ( dt.date() == dtEnd.date() ) + eff.setEndTime( dtEnd.time() ); + else + eff.setEndTime( QTime(23, 59, 0 ) ); + tmpList.append( eff ); + } + dt = dt.addDays( 1 ); + } + } + } + } + + void repeat( OEffectiveEvent::ValueList& tmpList, const OEvent::ValueList& list, + const QDate& from, const QDate& to ) { + QDate repeat; + for ( OEvent::ValueList::ConstIterator it = list.begin(); it != list.end(); ++it ) { + int dur = (*it).startDateTime().date().daysTo( (*it).endDateTime().date() ); + QDate itDate = from.addDays(-dur ); + ORecur rec = (*it).recurrence(); + if ( !rec.hasEndDate() || rec.endDate() > to ) { + rec.setEndDate( to ); + rec.setHasEndDate( true ); + } + while (rec.nextOcurrence(itDate, repeat ) ) { + if (repeat > to ) break; + OEffectiveEvent eff; + eff.setDate( repeat ); + if ( (*it).isAllDay() ) { + eff.setStartTime( QTime(0, 0, 0 ) ); + eff.setEndTime( QTime(23, 59, 59 ) ); + }else { + /* we only occur by days, not hours/minutes/seconds. Hence + * the actual end and start times will be the same for + * every repeated event. For multi day events this is + * fixed up later if on wronge day span + */ + eff.setStartTime( (*it).startDateTime().time() ); + eff.setEndTime( (*it).endDateTime().time() ); + } + if ( dur != 0 ) { + // multi-day repeating events + QDate sub_it = QMAX( repeat, from ); + QDate startDate = repeat; + QDate endDate = startDate.addDays( dur ); + + while ( sub_it <= endDate && sub_it <= to ) { + OEffectiveEvent tmpEff = eff; + tmpEff.setEvent( (*it) ); + if ( sub_it != startDate ) + tmpEff.setStartTime( QTime(0, 0, 0 ) ); + if ( sub_it != endDate ) + tmpEff.setEndTime( QTime( 23, 59, 59 ) ); + + tmpEff.setDate( sub_it ); + tmpEff.setEffectiveDates( startDate, endDate ); + tmpList.append( tmpEff ); + + sub_it = sub_it.addDays( 1 ); + } + itDate = endDate; + }else { + eff.setEvent( (*it) ); + tmpList.append( eff ); + itDate = repeat.addDays( 1 ); + } + } + } + } +} + +ODateBookAccessBackend::ODateBookAccessBackend() + : OPimAccessBackend<OEvent>() +{ + +} +ODateBookAccessBackend::~ODateBookAccessBackend() { + +} +OEffectiveEvent::ValueList ODateBookAccessBackend::effecticeEvents( const QDate& from, + const QDate& to ) { + OEffectiveEvent::ValueList tmpList; + OEvent::ValueList list = directNonRepeats(); + + events( tmpList, list, from, to ); + repeat( tmpList, directRawRepeats(),from,to ); + + list = directRawRepeats(); + + qHeapSort( tmpList ); + return tmpList; +} +OEffectiveEvent::ValueList ODateBookAccessBackend::effecticeEvents( const QDateTime& dt ) { + OEffectiveEvent::ValueList day = effecticeEvents( dt.date(), dt.date() ); + OEffectiveEvent::ValueList::Iterator it; + + OEffectiveEvent::ValueList tmpList; + QDateTime dtTmp; + for ( it = day.begin(); it != day.end(); ++it ) { + dtTmp = QDateTime( (*it).date(), (*it).startTime() ); + if ( QABS(dt.secsTo(dtTmp) ) < 60 ) + tmpList.append( (*it) ); + } + + return tmpList; +} diff --git a/libopie2/opiepim/backend/odatebookaccessbackend.h b/libopie2/opiepim/backend/odatebookaccessbackend.h new file mode 100644 index 0000000..eb6e8fb --- a/dev/null +++ b/libopie2/opiepim/backend/odatebookaccessbackend.h @@ -0,0 +1,32 @@ +#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H +#define OPIE_DATE_BOOK_ACCESS_BACKEND_H + +#include <qarray.h> + +#include "opimaccessbackend.h" +#include "oevent.h" + +class ODateBookAccessBackend : public OPimAccessBackend<OEvent> { +public: + typedef int UID; + ODateBookAccessBackend(); + ~ODateBookAccessBackend(); + + virtual QArray<UID> rawEvents()const = 0; + virtual QArray<UID> rawRepeats()const = 0; + virtual QArray<UID> nonRepeats() const = 0; + + /** + * these two methods are used if you do not implement + * effectiveEvents... + */ + virtual OEvent::ValueList directNonRepeats() = 0; + virtual OEvent::ValueList directRawRepeats() = 0; + + /* is implemented by default but you can reimplement it*/ + virtual OEffectiveEvent::ValueList effecticeEvents( const QDate& from, const QDate& to ); + virtual OEffectiveEvent::ValueList effecticeEvents( const QDateTime& start ); + +}; + +#endif diff --git a/libopie2/opiepim/core/odatebookaccess.cpp b/libopie2/opiepim/core/odatebookaccess.cpp new file mode 100644 index 0000000..5f97e7c --- a/dev/null +++ b/libopie2/opiepim/core/odatebookaccess.cpp @@ -0,0 +1,37 @@ +#include "obackendfactory.h" +#include "odatebookaccess.h" + +ODateBookAccess::ODateBookAccess( ODateBookAccessBackend* back, enum Access ac ) + : OPimAccessTemplate<OEvent>( back ) +{ + if (!back ) + back = OBackendFactory<ODateBookAccessBackend>::Default("datebook", QString::null ); + + m_backEnd = back; +} +ODateBookAccess::~ODateBookAccess() { +} +ODateBookAccess::List ODateBookAccess::rawEvents()const { + QArray<int> ints = m_backEnd->rawEvents(); + + List lis( ints, this ); + return lis; +} +ODateBookAccess::List ODateBookAccess::rawRepeats()const { + QArray<int> ints = m_backEnd->rawRepeats(); + + List lis( ints, this ); + return lis; +} +ODateBookAccess::List ODateBookAccess::nonRepeats()const { + QArray<int> ints = m_backEnd->nonRepeats(); + + List lis( ints, this ); + return lis; +} +OEffectiveEvent::ValueList ODateBookAccess::effecticeEvents( const QDate& from, const QDate& to ) { + return m_backEnd->effecticeEvents( from, to ); +} +OEffectiveEvent::ValueList ODateBookAccess::effecticeEvents( const QDateTime& start ) { + return m_backEnd->effecticeEvents( start ); +} diff --git a/libopie2/opiepim/core/odatebookaccess.h b/libopie2/opiepim/core/odatebookaccess.h new file mode 100644 index 0000000..3f2c728 --- a/dev/null +++ b/libopie2/opiepim/core/odatebookaccess.h @@ -0,0 +1,32 @@ +#ifndef OPIE_DATE_BOOK_ACCESS_H +#define OPIE_DATE_BOOK_ACCESS_H + +#include "odatebookaccessbackend.h" +#include "opimaccesstemplate.h" + +#include "oevent.h" + +class ODateBookAccess : public OPimAccessTemplate<OEvent> { +public: + ODateBookAccess( ODateBookAccessBackend* = 0l, enum Access acc = Random ); + ~ODateBookAccess(); + + /** return all events */ + List rawEvents()const; + + /** return repeating events */ + List rawRepeats()const; + + /** return non repeating events */ + List nonRepeats()const; + + OEffectiveEvent::ValueList effecticeEvents( const QDate& from, const QDate& to ); + OEffectiveEvent::ValueList effecticeEvents( const QDateTime& start ); + +private: + ODateBookAccessBackend* m_backEnd; + class Private; + Private* d; +}; + +#endif diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp index 71b9441..aaae3b2 100644 --- a/libopie2/opiepim/oevent.cpp +++ b/libopie2/opiepim/oevent.cpp @@ -1,325 +1,324 @@ #include <qshared.h> #include <qpe/palmtopuidgen.h> #include <qpe/categories.h> #include "orecur.h" #include "opimresolver.h" #include "opimnotifymanager.h" #include "oevent.h" -namespace OCalendarHelper { - static int week( const QDate& date) { - // Calculates the week this date is in within that - // month. Equals the "row" is is in in the month view - int week = 1; - QDate tmp( date.year(), date.month(), 1 ); - if ( date.dayOfWeek() < tmp.dayOfWeek() ) - ++week; +int OCalendarHelper::week( const QDate& date) { + // Calculates the week this date is in within that + // month. Equals the "row" is is in in the month view + int week = 1; + QDate tmp( date.year(), date.month(), 1 ); + if ( date.dayOfWeek() < tmp.dayOfWeek() ) + ++week; - week += ( date.day() - 1 ) / 7; + week += ( date.day() - 1 ) / 7; - return week; - } - static int occurence( const QDate& date) { - // calculates the number of occurrances of this day of the - // week till the given date (e.g 3rd Wednesday of the month) - return ( date.day() - 1 ) / 7 + 1; - } - static int dayOfWeek( char day ) { - int dayOfWeek = 1; - char i = ORecur::MON; - while ( !( i & day ) && i <= ORecur::SUN ) { - i <<= 1; - ++dayOfWeek; - } - return dayOfWeek; - } - static int monthDiff( const QDate& first, const QDate& second ) { - return ( second.year() - first.year() ) * 12 + - second.month() - first.month(); + return week; +} +int OCalendarHelper::ocurrence( const QDate& date) { + // calculates the number of occurrances of this day of the + // week till the given date (e.g 3rd Wednesday of the month) + return ( date.day() - 1 ) / 7 + 1; +} +int OCalendarHelper::dayOfWeek( char day ) { + int dayOfWeek = 1; + char i = ORecur::MON; + while ( !( i & day ) && i <= ORecur::SUN ) { + i <<= 1; + ++dayOfWeek; } + return dayOfWeek; +} +int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) { + return ( second.year() - first.year() ) * 12 + + second.month() - first.month(); } struct OEvent::Data : public QShared { Data() : QShared() { recur = 0; manager = 0; isAllDay = false; } ~Data() { delete manager; delete recur; } QString description; QString location; OPimNotifyManager* manager; ORecur* recur; QString note; QDateTime created; QDateTime start; QDateTime end; bool isAllDay : 1; QString timezone; }; OEvent::OEvent( int uid ) : OPimRecord( uid ) { data = new Data; } OEvent::OEvent( const OEvent& ev) : OPimRecord( ev ), data( ev.data ) { data->ref(); } OEvent::~OEvent() { if ( data->deref() ) { delete data; data = 0; } } OEvent& OEvent::operator=( const OEvent& ev) { if ( *this == ev ) return *this; OPimRecord::operator=( ev ); ev.data->ref(); deref(); data = ev.data; return *this; } QString OEvent::description()const { return data->description; } void OEvent::setDescription( const QString& description ) { changeOrModify(); data->description = description; } void OEvent::setLocation( const QString& loc ) { changeOrModify(); data->location = loc; } QString OEvent::location()const { return data->location; } OPimNotifyManager &OEvent::notifiers() { // I hope we can skip the changeOrModify here // the notifier should take care of it // and OPimNotify is shared too if (!data->manager ) data->manager = new OPimNotifyManager; return *data->manager; } bool OEvent::hasNotifiers()const { return ( data->manager); } ORecur OEvent::recurrence()const { if (!data->recur) data->recur = new ORecur; return *data->recur; } void OEvent::setRecurrence( const ORecur& rec) { changeOrModify(); if (data->recur ) (*data->recur) = rec; else data->recur = new ORecur( rec ); } bool OEvent::hasRecurrence()const { - return data->recur; + if (!data->recur ) return false; + return data->recur->doesRecur(); } QString OEvent::note()const { return data->note; } void OEvent::setNote( const QString& note ) { changeOrModify(); data->note = note; } QDateTime OEvent::createdDateTime()const { return data->created; } void OEvent::setCreatedDateTime( const QDateTime& time ) { changeOrModify(); data->created = time; } QDateTime OEvent::startDateTime()const { if ( data->isAllDay ) return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); return data->start; } QDateTime OEvent::startDateTimeInZone()const { /* if no timezone, or all day event or if the current and this timeZone match... */ if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); OTimeZone zone(data->timezone ); return zone.toDateTime( data->start, OTimeZone::current() ); } void OEvent::setStartDateTime( const QDateTime& dt ) { changeOrModify(); data->start = dt; } QDateTime OEvent::endDateTime()const { /* * if all Day event the end time needs * to be on the same day as the start */ if ( data->isAllDay ) return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); return data->end; } QDateTime OEvent::endDateTimeInZone()const { /* if no timezone, or all day event or if the current and this timeZone match... */ if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); OTimeZone zone(data->timezone ); return zone.toDateTime( data->end, OTimeZone::current() ); } void OEvent::setEndDateTime( const QDateTime& dt ) { changeOrModify(); data->end = dt; } bool OEvent::isMultipleDay()const { return data->end.date().day() - data->start.date().day(); } bool OEvent::isAllDay()const { return data->isAllDay; } void OEvent::setTimeZone( const QString& tz ) { changeOrModify(); data->timezone = tz; } QString OEvent::timeZone()const { return data->timezone; } bool OEvent::match( const QRegExp& )const { // FIXME return false; } QString OEvent::toRichText()const { // FIXME return "OEvent test"; } QString OEvent::toShortText()const { return "OEvent shotText"; } QString OEvent::type()const { return QString::fromLatin1("OEvent"); } QString OEvent::recordField( int /*id */ )const { return QString::null; } int OEvent::rtti() { return OPimResolver::DateBook; } bool OEvent::loadFromStream( QDataStream& ) { return true; } bool OEvent::saveToStream( QDataStream& )const { return true; } void OEvent::changeOrModify() { if ( data->count != 1 ) { data->deref(); Data* d2 = new Data; d2->description = data->description; d2->location = data->location; d2->manager = data->manager; d2->recur = data->recur; d2->note = data->note; d2->created = data->created; d2->start = data->start; d2->end = data->end; d2->isAllDay = data->isAllDay; d2->timezone = data->timezone; data = d2; } } void OEvent::deref() { if ( data->deref() ) { delete data; data = 0; } } // FIXME QMap<int, QString> OEvent::toMap()const { return QMap<int, QString>(); } QMap<QString, QString> OEvent::toExtraMap()const { return QMap<QString, QString>(); } struct OEffectiveEvent::Data : public QShared { Data() : QShared() { } OEvent event; QDate date; QTime start, end; QDate startDate, endDate; bool dates : 1; }; OEffectiveEvent::OEffectiveEvent() { data = new Data; data->date = QDate::currentDate(); data->start = data->end = QTime::currentTime(); data->dates = false; } OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, Position pos ) { data = new Data; data->event = ev; data->date = startDate; if ( pos & Start ) data->start = ev.startDateTime().time(); else data->start = QTime( 0, 0, 0 ); if ( pos & End ) data->end = ev.endDateTime().time(); else data->end = QTime( 23, 59, 59 ); data->dates = false; } OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { data = ev.data; data->ref(); } OEffectiveEvent::~OEffectiveEvent() { if ( data->deref() ) { delete data; data = 0; } } OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { if ( *this == ev ) return *this; ev.data->ref(); deref(); data = ev.data; return *this; } void OEffectiveEvent::setStartTime( const QTime& ti) { changeOrModify(); data->start = ti; } void OEffectiveEvent::setEndTime( const QTime& en) { changeOrModify(); data->end = en; } void OEffectiveEvent::setEvent( const OEvent& ev) { changeOrModify(); data->event = ev; } void OEffectiveEvent::setDate( const QDate& da) { changeOrModify(); data->date = da; } diff --git a/libopie2/opiepim/oevent.h b/libopie2/opiepim/oevent.h index 4489be7..c718e2e 100644 --- a/libopie2/opiepim/oevent.h +++ b/libopie2/opiepim/oevent.h @@ -1,198 +1,198 @@ // CONTAINS GPLed code of TT #ifndef OPIE_PIM_EVENT_H #define OPIE_PIM_EVENT_H #include <qstring.h> #include <qdatetime.h> #include <qvaluelist.h> #include <qpe/recordfields.h> #include <qpe/palmtopuidgen.h> #include "otimezone.h" #include "opimrecord.h" -namespace OCalendarHelper { +struct OCalendarHelper { /** calculate the week number of the date */ static int week( const QDate& ); /** calculate the occurence of week days since the start of the month */ static int ocurrence( const QDate& ); // returns the dayOfWeek for the *first* day it finds (ignores // any further days!). Returns 1 (Monday) if there isn't any day found static int dayOfWeek( char day ); /** returns the diff of month */ static int monthDiff( const QDate& first, const QDate& second ); -} +}; class OPimNotifyManager; class ORecur; class OEvent : public OPimRecord { public: typedef QValueList<OEvent> ValueList; enum RecordFields { Uid = Qtopia::UID_ID, Category = Qtopia::CATEGORY_ID, Description, Location, Alarm, Reminder, Recurrence, Note, Created, StartDate, EndDate, AllDay, TimeZone }; OEvent(int uid = 0); OEvent( const OEvent& ); ~OEvent(); OEvent &operator=( const OEvent& ); QString description()const; void setDescription( const QString& description ); QString location()const; void setLocation( const QString& loc ); bool hasNotifiers()const; OPimNotifyManager ¬ifiers(); ORecur recurrence()const; void setRecurrence( const ORecur& ); bool hasRecurrence()const; QString note()const; void setNote( const QString& note ); QDateTime createdDateTime()const; void setCreatedDateTime( const QDateTime& dt); /** set the date to dt. dt is the QDateTime in localtime */ void setStartDateTime( const QDateTime& ); /** returns the datetime in the local timeZone */ QDateTime startDateTime()const; /** returns the start datetime in the current zone */ QDateTime startDateTimeInZone()const; /** in current timezone */ void setEndDateTime( const QDateTime& ); /** in current timezone */ QDateTime endDateTime()const; QDateTime endDateTimeInZone()const; bool isMultipleDay()const; bool isAllDay()const; void setAllDay( bool isAllDay ); /* pin this event to a timezone! FIXME */ void setTimeZone( const QString& timeZone ); QString timeZone()const; bool match( const QRegExp& )const; /* needed reimp */ QString toRichText()const; QString toShortText()const; QString type()const; QMap<int, QString> toMap()const; QMap<QString, QString> toExtraMap()const; QString recordField(int )const; static int rtti(); bool loadFromStream( QDataStream& ); bool saveToStream( QDataStream& )const; /* bool operator==( const OEvent& ); bool operator!=( const OEvent& ); bool operator<( const OEvent& ); bool operator<=( const OEvent& ); bool operator>( const OEvent& ); bool operator>=(const OEvent& ); */ private: inline void changeOrModify(); void deref(); struct Data; Data* data; class Private; Private* priv; }; /** * AN Event can span through multiple days. We split up a multiday eve */ class OEffectiveEvent { public: - QValueList<OEffectiveEvent> ValueList; + typedef QValueList<OEffectiveEvent> ValueList; enum Position { MidWay, Start, End, StartEnd }; // If we calculate the effective event of a multi-day event // we have to figure out whether we are at the first day, // at the end, or anywhere else ("middle"). This is important // for the start/end times (00:00/23:59) // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- // day event // Start: start time -> 23:59 // End: 00:00 -> end time // Start | End == StartEnd: for single-day events (default) // here we draw start time -> end time OEffectiveEvent(); OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); OEffectiveEvent( const OEffectiveEvent& ); OEffectiveEvent &operator=(const OEffectiveEvent& ); ~OEffectiveEvent(); void setStartTime( const QTime& ); void setEndTime( const QTime& ); void setEvent( const OEvent& ); void setDate( const QDate& ); void setEffectiveDates( const QDate& from, const QDate& to ); QString description()const; QString location()const; QString note()const; OEvent event()const; QTime startTime()const; QTime endTime()const; QDate date()const; /* return the length in hours */ int length()const; int size()const; QDate startDate()const; QDate endDate()const; bool operator<( const OEffectiveEvent &e ) const; bool operator<=( const OEffectiveEvent &e ) const; bool operator==( const OEffectiveEvent &e ) const; bool operator!=( const OEffectiveEvent &e ) const; bool operator>( const OEffectiveEvent &e ) const; bool operator>= ( const OEffectiveEvent &e ) const; private: void deref(); inline void changeOrModify(); class Private; Private* priv; struct Data; Data* data; }; #endif |