summaryrefslogtreecommitdiffabout
path: root/libkcal/calendarlocal.cpp
Side-by-side diff
Diffstat (limited to 'libkcal/calendarlocal.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/calendarlocal.cpp655
1 files changed, 655 insertions, 0 deletions
diff --git a/libkcal/calendarlocal.cpp b/libkcal/calendarlocal.cpp
new file mode 100644
index 0000000..8ff8b14
--- a/dev/null
+++ b/libkcal/calendarlocal.cpp
@@ -0,0 +1,655 @@
+/*
+ This file is part of libkcal.
+
+ Copyright (c) 1998 Preston Brown
+ Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
+
+ 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; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <qdatetime.h>
+#include <qstring.h>
+#include <qptrlist.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "vcaldrag.h"
+#include "vcalformat.h"
+#include "icalformat.h"
+#include "exceptions.h"
+#include "incidence.h"
+#include "journal.h"
+#include "filestorage.h"
+#include "calfilter.h"
+
+#include "calendarlocal.h"
+
+// #ifndef DESKTOP_VERSION
+// #include <qtopia/alarmserver.h>
+// #endif
+using namespace KCal;
+
+CalendarLocal::CalendarLocal()
+ : Calendar()
+{
+ init();
+}
+
+CalendarLocal::CalendarLocal(const QString &timeZoneId)
+ : Calendar(timeZoneId)
+{
+ init();
+}
+
+void CalendarLocal::init()
+{
+ mNextAlarmIncidence = 0;
+}
+
+
+CalendarLocal::~CalendarLocal()
+{
+ close();
+}
+
+bool CalendarLocal::load( const QString &fileName )
+{
+ FileStorage storage( this, fileName );
+ return storage.load();
+}
+
+bool CalendarLocal::save( const QString &fileName, CalFormat *format )
+{
+ FileStorage storage( this, fileName, format );
+ return storage.save();
+}
+
+void CalendarLocal::close()
+{
+ mEventList.setAutoDelete( true );
+ mTodoList.setAutoDelete( true );
+ mJournalList.setAutoDelete( false );
+
+ mEventList.clear();
+ mTodoList.clear();
+ mJournalList.clear();
+
+ mEventList.setAutoDelete( false );
+ mTodoList.setAutoDelete( false );
+ mJournalList.setAutoDelete( false );
+
+ setModified( false );
+}
+bool CalendarLocal::addEventNoDup( Event *event )
+{
+ Event * eve;
+ for ( eve = mEventList.first(); eve ; eve = mEventList.next() ) {
+ if ( *eve == *event ) {
+ //qDebug("CalendarLocal::Duplicate event found! Not inserted! ");
+ return false;
+ }
+ }
+ return addEvent( event );
+}
+
+bool CalendarLocal::addEvent( Event *event )
+{
+ insertEvent( event );
+
+ event->registerObserver( this );
+
+ setModified( true );
+
+ return true;
+}
+
+void CalendarLocal::deleteEvent( Event *event )
+{
+
+
+ if ( mEventList.removeRef( event ) ) {
+ setModified( true );
+ }
+}
+
+
+Event *CalendarLocal::event( const QString &uid )
+{
+
+ Event *event;
+
+ for ( event = mEventList.first(); event; event = mEventList.next() ) {
+ if ( event->uid() == uid ) {
+ return event;
+ }
+ }
+
+ return 0;
+}
+bool CalendarLocal::addTodoNoDup( Todo *todo )
+{
+ Todo * eve;
+ for ( eve = mTodoList.first(); eve ; eve = mTodoList.next() ) {
+ if ( *eve == *todo ) {
+ //qDebug("duplicate todo found! not inserted! ");
+ return false;
+ }
+ }
+ return addTodo( todo );
+}
+bool CalendarLocal::addTodo( Todo *todo )
+{
+ mTodoList.append( todo );
+
+ todo->registerObserver( this );
+
+ // Set up subtask relations
+ setupRelations( todo );
+
+ setModified( true );
+
+ return true;
+}
+
+void CalendarLocal::deleteTodo( Todo *todo )
+{
+ // Handle orphaned children
+ removeRelations( todo );
+
+ if ( mTodoList.removeRef( todo ) ) {
+ setModified( true );
+ }
+}
+
+QPtrList<Todo> CalendarLocal::rawTodos()
+{
+ return mTodoList;
+}
+Todo *CalendarLocal::todo( int id )
+{
+ Todo *todo;
+ for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) {
+ if ( todo->zaurusId() == id ) return todo;
+ }
+
+ return 0;
+}
+
+Event *CalendarLocal::event( int id )
+{
+ Event *todo;
+ for ( todo = mEventList.first(); todo; todo = mEventList.next() ) {
+ if ( todo->zaurusId() == id ) return todo;
+ }
+
+ return 0;
+}
+Todo *CalendarLocal::todo( const QString &uid )
+{
+ Todo *todo;
+ for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) {
+ if ( todo->uid() == uid ) return todo;
+ }
+
+ return 0;
+}
+QString CalendarLocal::nextSummary() const
+{
+ return mNextSummary;
+}
+QDateTime CalendarLocal::nextAlarmEventDateTime() const
+{
+ return mNextAlarmEventDateTime;
+}
+void CalendarLocal::checkAlarmForIncidence( Incidence * incidence, bool deleted)
+{
+ //mNextAlarmIncidence
+ //mNextAlarmDateTime
+ //return mNextSummary;
+ //return mNextAlarmEventDateTime;
+ bool newNextAlarm = false;
+ bool computeNextAlarm = false;
+ bool ok;
+ int offset;
+ QDateTime nextA;
+ // QString nextSum;
+ //QDateTime nextEvent;
+ if ( mNextAlarmIncidence == 0 || incidence == 0 ) {
+ computeNextAlarm = true;
+ } else {
+ if ( ! deleted ) {
+ nextA = incidence->getNextAlarmDateTime(& ok, &offset ) ;
+ if ( ok ) {
+ if ( nextA < mNextAlarmDateTime ) {
+ deRegisterAlarm();
+ mNextAlarmDateTime = nextA;
+ mNextSummary = incidence->summary();
+ mNextAlarmEventDateTime = nextA.addSecs(offset ) ;
+ mNextAlarmEventDateTimeString = KGlobal::locale()->formatDateTime(mNextAlarmEventDateTime);
+ newNextAlarm = true;
+ mNextAlarmIncidence = incidence;
+ } else {
+ if ( incidence == mNextAlarmIncidence ) {
+ computeNextAlarm = true;
+ }
+ }
+ } else {
+ if ( mNextAlarmIncidence == incidence ) {
+ computeNextAlarm = true;
+ }
+ }
+ } else { // deleted
+ if ( incidence == mNextAlarmIncidence ) {
+ computeNextAlarm = true;
+ }
+ }
+ }
+ if ( computeNextAlarm ) {
+ deRegisterAlarm();
+ nextA = nextAlarm( 1000 );
+ if (! mNextAlarmIncidence ) {
+ return;
+ }
+ newNextAlarm = true;
+ }
+ if ( newNextAlarm )
+ registerAlarm();
+}
+QString CalendarLocal:: getAlarmNotification()
+{
+ QString ret;
+ // this should not happen
+ if (! mNextAlarmIncidence )
+ return "cal_alarm"+ mNextSummary.left( 25 )+"\n"+mNextAlarmEventDateTimeString;
+ Alarm* alarm = mNextAlarmIncidence->alarms().first();
+ if ( alarm->type() == Alarm::Procedure ) {
+ ret = "proc_alarm" + alarm->programFile()+"+++";
+ } else {
+ ret = "audio_alarm" +alarm->audioFile() +"+++";
+ }
+ ret += "cal_alarm"+ mNextSummary.left( 25 );
+ if ( mNextSummary.length() > 25 )
+ ret += "\n" + mNextSummary.mid(25, 25 );
+ ret+= "\n"+mNextAlarmEventDateTimeString;
+ return ret;
+}
+
+void CalendarLocal::registerAlarm()
+{
+ mLastAlarmNotificationString = getAlarmNotification();
+ // qDebug("++ register Alarm %s %s",mNextAlarmDateTime.toString().latin1(), mLastAlarmNotificationString.latin1() );
+ emit addAlarm ( mNextAlarmDateTime, mLastAlarmNotificationString );
+// #ifndef DESKTOP_VERSION
+// AlarmServer::addAlarm ( mNextAlarmDateTime,"koalarm", mLastAlarmNotificationString.latin1() );
+// #endif
+}
+void CalendarLocal::deRegisterAlarm()
+{
+ if ( mLastAlarmNotificationString.isNull() )
+ return;
+ //qDebug("-- deregister Alarm %s ", mLastAlarmNotificationString.latin1() );
+
+ emit removeAlarm ( mNextAlarmDateTime, mLastAlarmNotificationString );
+// #ifndef DESKTOP_VERSION
+// AlarmServer::deleteAlarm (mNextAlarmDateTime ,"koalarm" ,mLastAlarmNotificationString.latin1() );
+// #endif
+}
+
+QPtrList<Todo> CalendarLocal::todos( const QDate &date )
+{
+ QPtrList<Todo> todos;
+
+ Todo *todo;
+ for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) {
+ if ( todo->hasDueDate() && todo->dtDue().date() == date ) {
+ todos.append( todo );
+ }
+ }
+
+ filter()->apply( &todos );
+ return todos;
+}
+void CalendarLocal::reInitAlarmSettings()
+{
+ if ( !mNextAlarmIncidence ) {
+ nextAlarm( 1000 );
+ }
+ deRegisterAlarm();
+ mNextAlarmIncidence = 0;
+ checkAlarmForIncidence( 0, false );
+
+}
+
+
+
+QDateTime CalendarLocal::nextAlarm( int daysTo )
+{
+ QDateTime nextA = QDateTime::currentDateTime().addDays( daysTo );
+ QDateTime start = QDateTime::currentDateTime().addSecs( 30 );
+ QDateTime next;
+ Event *e;
+ bool ok;
+ bool found = false;
+ int offset;
+ mNextAlarmIncidence = 0;
+ for( e = mEventList.first(); e; e = mEventList.next() ) {
+ next = e->getNextAlarmDateTime(& ok, &offset ) ;
+ if ( ok ) {
+ if ( next < nextA ) {
+ nextA = next;
+ found = true;
+ mNextSummary = e->summary();
+ mNextAlarmEventDateTime = next.addSecs(offset ) ;
+ mNextAlarmIncidence = (Incidence *) e;
+ }
+ }
+ }
+ Todo *t;
+ for( t = mTodoList.first(); t; t = mTodoList.next() ) {
+ next = t->getNextAlarmDateTime(& ok, &offset ) ;
+ if ( ok ) {
+ if ( next < nextA ) {
+ nextA = next;
+ found = true;
+ mNextSummary = t->summary();
+ mNextAlarmEventDateTime = next.addSecs(offset );
+ mNextAlarmIncidence = (Incidence *) t;
+ }
+ }
+ }
+ if ( mNextAlarmIncidence ) {
+ mNextAlarmEventDateTimeString = KGlobal::locale()->formatDateTime(mNextAlarmEventDateTime);
+ mNextAlarmDateTime = nextA;
+ }
+ return nextA;
+}
+Alarm::List CalendarLocal::alarmsTo( const QDateTime &to )
+{
+ return alarms( QDateTime( QDate( 1900, 1, 1 ) ), to );
+}
+
+Alarm::List CalendarLocal::alarms( const QDateTime &from, const QDateTime &to )
+{
+ kdDebug(5800) << "CalendarLocal::alarms(" << from.toString() << " - "
+ << to.toString() << ")\n";
+
+ Alarm::List alarms;
+
+ Event *e;
+
+ for( e = mEventList.first(); e; e = mEventList.next() ) {
+ if ( e->doesRecur() ) appendRecurringAlarms( alarms, e, from, to );
+ else appendAlarms( alarms, e, from, to );
+ }
+
+ Todo *t;
+ for( t = mTodoList.first(); t; t = mTodoList.next() ) {
+ appendAlarms( alarms, t, from, to );
+ }
+
+ return alarms;
+}
+
+void CalendarLocal::appendAlarms( Alarm::List &alarms, Incidence *incidence,
+ const QDateTime &from, const QDateTime &to )
+{
+ QPtrList<Alarm> alarmList = incidence->alarms();
+ Alarm *alarm;
+ for( alarm = alarmList.first(); alarm; alarm = alarmList.next() ) {
+// kdDebug(5800) << "CalendarLocal::appendAlarms() '" << alarm->text()
+// << "': " << alarm->time().toString() << " - " << alarm->enabled() << endl;
+ if ( alarm->enabled() ) {
+ if ( alarm->time() >= from && alarm->time() <= to ) {
+ kdDebug(5800) << "CalendarLocal::appendAlarms() '" << incidence->summary()
+ << "': " << alarm->time().toString() << endl;
+ alarms.append( alarm );
+ }
+ }
+ }
+}
+
+void CalendarLocal::appendRecurringAlarms( Alarm::List &alarms,
+ Incidence *incidence,
+ const QDateTime &from,
+ const QDateTime &to )
+{
+
+ QPtrList<Alarm> alarmList = incidence->alarms();
+ Alarm *alarm;
+ QDateTime qdt;
+ for( alarm = alarmList.first(); alarm; alarm = alarmList.next() ) {
+ if (incidence->recursOn(from.date())) {
+ qdt.setTime(alarm->time().time());
+ qdt.setDate(from.date());
+ }
+ else qdt = alarm->time();
+ // qDebug("1 %s %s %s", qdt.toString().latin1(), from.toString().latin1(), to.toString().latin1());
+ if ( alarm->enabled() ) {
+ if ( qdt >= from && qdt <= to ) {
+ alarms.append( alarm );
+ }
+ }
+ }
+}
+
+
+/****************************** PROTECTED METHODS ****************************/
+
+// after changes are made to an event, this should be called.
+void CalendarLocal::update( IncidenceBase *incidence )
+{
+ incidence->setSyncStatus( Event::SYNCMOD );
+ incidence->setLastModified( QDateTime::currentDateTime() );
+ // we should probably update the revision number here,
+ // or internally in the Event itself when certain things change.
+ // need to verify with ical documentation.
+
+ setModified( true );
+}
+
+void CalendarLocal::insertEvent( Event *event )
+{
+ if ( mEventList.findRef( event ) < 0 ) mEventList.append( event );
+}
+
+
+QPtrList<Event> CalendarLocal::rawEventsForDate( const QDate &qd, bool sorted )
+{
+ QPtrList<Event> eventList;
+
+ Event *event;
+ for( event = mEventList.first(); event; event = mEventList.next() ) {
+ if ( event->doesRecur() ) {
+ if ( event->isMultiDay() ) {
+ int extraDays = event->dtStart().date().daysTo( event->dtEnd().date() );
+ int i;
+ for ( i = 0; i <= extraDays; i++ ) {
+ if ( event->recursOn( qd.addDays( -i ) ) ) {
+ eventList.append( event );
+ break;
+ }
+ }
+ } else {
+ if ( event->recursOn( qd ) )
+ eventList.append( event );
+ }
+ } else {
+ if ( event->dtStart().date() <= qd && event->dtEnd().date() >= qd ) {
+ eventList.append( event );
+ }
+ }
+ }
+
+ if ( !sorted ) {
+ return eventList;
+ }
+
+ // kdDebug(5800) << "Sorting events for date\n" << endl;
+ // now, we have to sort it based on dtStart.time()
+ QPtrList<Event> eventListSorted;
+ Event *sortEvent;
+ for ( event = eventList.first(); event; event = eventList.next() ) {
+ sortEvent = eventListSorted.first();
+ int i = 0;
+ while ( sortEvent && event->dtStart().time()>=sortEvent->dtStart().time() )
+ {
+ i++;
+ sortEvent = eventListSorted.next();
+ }
+ eventListSorted.insert( i, event );
+ }
+ return eventListSorted;
+}
+
+
+QPtrList<Event> CalendarLocal::rawEvents( const QDate &start, const QDate &end,
+ bool inclusive )
+{
+ Event *event = 0;
+
+ QPtrList<Event> eventList;
+
+ // Get non-recurring events
+ for( event = mEventList.first(); event; event = mEventList.next() ) {
+ if ( event->doesRecur() ) {
+ QDate rStart = event->dtStart().date();
+ bool found = false;
+ if ( inclusive ) {
+ if ( rStart >= start && rStart <= end ) {
+ // Start date of event is in range. Now check for end date.
+ // if duration is negative, event recurs forever, so do not include it.
+ if ( event->recurrence()->duration() == 0 ) { // End date set
+ QDate rEnd = event->recurrence()->endDate();
+ if ( rEnd >= start && rEnd <= end ) { // End date within range
+ found = true;
+ }
+ } else if ( event->recurrence()->duration() > 0 ) { // Duration set
+ // TODO: Calculate end date from duration. Should be done in Event
+ // For now exclude all events with a duration.
+ }
+ }
+ } else {
+ bool founOne;
+ QDate next = event->getNextOccurence( start, &founOne ).date();
+ if ( founOne ) {
+ if ( next <= end ) {
+ found = true;
+ }
+ }
+
+ /*
+ // crap !!!
+ if ( rStart <= end ) { // Start date not after range
+ if ( rStart >= start ) { // Start date within range
+ found = true;
+ } else if ( event->recurrence()->duration() == -1 ) { // Recurs forever
+ found = true;
+ } else if ( event->recurrence()->duration() == 0 ) { // End date set
+ QDate rEnd = event->recurrence()->endDate();
+ if ( rEnd >= start && rEnd <= end ) { // End date within range
+ found = true;
+ }
+ } else { // Duration set
+ // TODO: Calculate end date from duration. Should be done in Event
+ // For now include all events with a duration.
+ found = true;
+ }
+ }
+ */
+
+ }
+
+ if ( found ) eventList.append( event );
+ } else {
+ QDate s = event->dtStart().date();
+ QDate e = event->dtEnd().date();
+
+ if ( inclusive ) {
+ if ( s >= start && e <= end ) {
+ eventList.append( event );
+ }
+ } else {
+ if ( ( s >= start && s <= end ) || ( e >= start && e <= end ) ) {
+ eventList.append( event );
+ }
+ }
+ }
+ }
+
+ return eventList;
+}
+
+QPtrList<Event> CalendarLocal::rawEventsForDate( const QDateTime &qdt )
+{
+ return rawEventsForDate( qdt.date() );
+}
+
+QPtrList<Event> CalendarLocal::rawEvents()
+{
+ return mEventList;
+}
+
+bool CalendarLocal::addJournal(Journal *journal)
+{
+ if ( journal->dtStart().isValid())
+ kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl;
+ else
+ kdDebug(5800) << "Adding Journal without a DTSTART" << endl;
+
+ mJournalList.append(journal);
+
+ journal->registerObserver( this );
+
+ setModified( true );
+
+ return true;
+}
+
+void CalendarLocal::deleteJournal( Journal *journal )
+{
+ if ( mJournalList.removeRef(journal) ) {
+ setModified( true );
+ }
+}
+
+Journal *CalendarLocal::journal( const QDate &date )
+{
+// kdDebug(5800) << "CalendarLocal::journal() " << date.toString() << endl;
+
+ for ( Journal *it = mJournalList.first(); it; it = mJournalList.next() )
+ if ( it->dtStart().date() == date )
+ return it;
+
+ return 0;
+}
+
+Journal *CalendarLocal::journal( const QString &uid )
+{
+ for ( Journal *it = mJournalList.first(); it; it = mJournalList.next() )
+ if ( it->uid() == uid )
+ return it;
+
+ return 0;
+}
+
+QPtrList<Journal> CalendarLocal::journals()
+{
+ return mJournalList;
+}
+