From b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 Mon Sep 17 00:00:00 2001 From: zautrix Date: Sat, 26 Jun 2004 19:01:18 +0000 Subject: Initial revision --- (limited to 'libkcal/calendarlocal.cpp') 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 + + 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 +#include +#include + +#include +#include +#include +#include + +#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 +// #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 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 CalendarLocal::todos( const QDate &date ) +{ + QPtrList 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 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 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 CalendarLocal::rawEventsForDate( const QDate &qd, bool sorted ) +{ + QPtrList 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 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 CalendarLocal::rawEvents( const QDate &start, const QDate &end, + bool inclusive ) +{ + Event *event = 0; + + QPtrList 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 CalendarLocal::rawEventsForDate( const QDateTime &qdt ) +{ + return rawEventsForDate( qdt.date() ); +} + +QPtrList 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 CalendarLocal::journals() +{ + return mJournalList; +} + -- cgit v0.9.0.2