-rw-r--r-- | libkcal/calendar.cpp | 6 | ||||
-rw-r--r-- | libkcal/calendarlocal.cpp | 6 | ||||
-rw-r--r-- | libkcal/calfilter.cpp | 6 | ||||
-rw-r--r-- | libkcal/event.h | 1 | ||||
-rw-r--r-- | libkcal/freebusy.h | 1 | ||||
-rw-r--r-- | libkcal/icalformat.cpp | 4 | ||||
-rw-r--r-- | libkcal/icalformatimpl.cpp | 6 | ||||
-rw-r--r-- | libkcal/incidence.cpp | 6 | ||||
-rw-r--r-- | libkcal/incidencebase.h | 2 | ||||
-rw-r--r-- | libkcal/journal.h | 1 | ||||
-rw-r--r-- | libkcal/kincidenceformatter.cpp | 4 | ||||
-rw-r--r-- | libkcal/todo.cpp | 5 | ||||
-rw-r--r-- | libkcal/todo.h | 1 |
13 files changed, 26 insertions, 23 deletions
diff --git a/libkcal/calendar.cpp b/libkcal/calendar.cpp index ed39ddb..7e8e2c5 100644 --- a/libkcal/calendar.cpp +++ b/libkcal/calendar.cpp @@ -1,475 +1,475 @@ /* This file is part of libkcal. Copyright (c) 1998 Preston Brown Copyright (c) 2000,2001 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 <stdlib.h> #include <time.h> #include <kdebug.h> #include <kglobal.h> #include <klocale.h> #include "exceptions.h" #include "calfilter.h" #include "calendar.h" #include "syncdefines.h" using namespace KCal; Calendar::Calendar() { init(); setTimeZoneId( " 00:00 Europe/London(UTC)" ); } Calendar::Calendar( const QString &timeZoneId ) { init(); setTimeZoneId(timeZoneId); } void Calendar::init() { mObserver = 0; mNewObserver = false; mUndoIncidence = 0; mModified = false; // Setup default filter, which does nothing mDefaultFilter = new CalFilter; mFilter = mDefaultFilter; mFilter->setEnabled(false); // initialize random numbers. This is a hack, and not // even that good of one at that. // srandom(time(0)); // user information... setOwner(i18n("Unknown Name")); setEmail(i18n("unknown@nowhere")); #if 0 tmpStr = KOPrefs::instance()->mTimeZone; // kdDebug(5800) << "Calendar::Calendar(): TimeZone: " << tmpStr << endl; int dstSetting = KOPrefs::instance()->mDaylightSavings; extern long int timezone; struct tm *now; time_t curtime; curtime = time(0); now = localtime(&curtime); int hourOff = - ((timezone / 60) / 60); if (now->tm_isdst) hourOff += 1; QString tzStr; tzStr.sprintf("%.2d%.2d", hourOff, abs((timezone / 60) % 60)); // if no time zone was in the config file, write what we just discovered. if (tmpStr.isEmpty()) { // KOPrefs::instance()->mTimeZone = tzStr; } else { tzStr = tmpStr; } // if daylight savings has changed since last load time, we need // to rewrite these settings to the config file. if ((now->tm_isdst && !dstSetting) || (!now->tm_isdst && dstSetting)) { KOPrefs::instance()->mTimeZone = tzStr; KOPrefs::instance()->mDaylightSavings = now->tm_isdst; } setTimeZone(tzStr); #endif // KOPrefs::instance()->writeConfig(); } Calendar::~Calendar() { delete mDefaultFilter; if ( mUndoIncidence ) delete mUndoIncidence; } const QString &Calendar::getOwner() const { return mOwner; } bool Calendar::undoDeleteIncidence() { if (!mUndoIncidence) return false; addIncidence(mUndoIncidence); mUndoIncidence = 0; return true; } void Calendar::setOwner(const QString &os) { int i; mOwner = os; i = mOwner.find(','); if (i != -1) mOwner = mOwner.left(i); setModified( true ); } void Calendar::setTimeZone(const QString & tz) { bool neg = FALSE; int hours, minutes; QString tmpStr(tz); if (tmpStr.left(1) == "-") neg = TRUE; if (tmpStr.left(1) == "-" || tmpStr.left(1) == "+") tmpStr.remove(0, 1); hours = tmpStr.left(2).toInt(); if (tmpStr.length() > 2) minutes = tmpStr.right(2).toInt(); else minutes = 0; mTimeZone = (60*hours+minutes); if (neg) mTimeZone = -mTimeZone; mLocalTime = false; setModified( true ); } QString Calendar::getTimeZoneStr() const { if (mLocalTime) return ""; QString tmpStr; int hours = abs(mTimeZone / 60); int minutes = abs(mTimeZone % 60); bool neg = mTimeZone < 0; tmpStr.sprintf("%c%.2d%.2d", (neg ? '-' : '+'), hours, minutes); return tmpStr; } void Calendar::setTimeZone(int tz) { mTimeZone = tz; mLocalTime = false; setModified( true ); } int Calendar::getTimeZone() const { return mTimeZone; } void Calendar::setTimeZoneId(const QString &id) { mTimeZoneId = id; mLocalTime = false; mTimeZone = KGlobal::locale()->timezoneOffset(mTimeZoneId); if ( mTimeZone > 1000) setLocalTime(); //qDebug("Calendar::setTimeZoneOffset %s %d ",mTimeZoneId.latin1(), mTimeZone); setModified( true ); } QString Calendar::timeZoneId() const { return mTimeZoneId; } void Calendar::setLocalTime() { //qDebug("Calendar::setLocalTime() "); mLocalTime = true; mTimeZone = 0; mTimeZoneId = ""; setModified( true ); } bool Calendar::isLocalTime() const { return mLocalTime; } const QString &Calendar::getEmail() { return mOwnerEmail; } void Calendar::setEmail(const QString &e) { mOwnerEmail = e; setModified( true ); } void Calendar::setFilter(CalFilter *filter) { mFilter = filter; } CalFilter *Calendar::filter() { return mFilter; } QPtrList<Incidence> Calendar::incidences() { QPtrList<Incidence> incidences; Incidence *i; QPtrList<Event> e = events(); for( i = e.first(); i; i = e.next() ) incidences.append( i ); QPtrList<Todo> t = todos(); for( i = t.first(); i; i = t.next() ) incidences.append( i ); QPtrList<Journal> j = journals(); for( i = j.first(); i; i = j.next() ) incidences.append( i ); return incidences; } void Calendar::resetPilotStat(int id ) { QPtrList<Incidence> incidences; Incidence *i; QPtrList<Event> e = rawEvents(); for( i = e.first(); i; i = e.next() ) i->setPilotId( id ); QPtrList<Todo> t = rawTodos(); for( i = t.first(); i; i = t.next() ) i->setPilotId( id ); QPtrList<Journal> j = journals(); for( i = j.first(); i; i = j.next() ) i->setPilotId( id ); } void Calendar::resetTempSyncStat() { QPtrList<Incidence> incidences; Incidence *i; QPtrList<Event> e = rawEvents(); for( i = e.first(); i; i = e.next() ) i->setTempSyncStat( SYNC_TEMPSTATE_INITIAL ); QPtrList<Todo> t = rawTodos(); for( i = t.first(); i; i = t.next() ) i->setTempSyncStat( SYNC_TEMPSTATE_INITIAL ); QPtrList<Journal> j = journals(); for( i = j.first(); i; i = j.next() ) i->setTempSyncStat( SYNC_TEMPSTATE_INITIAL ); } QPtrList<Incidence> Calendar::rawIncidences() { QPtrList<Incidence> incidences; Incidence *i; QPtrList<Event> e = rawEvents(); for( i = e.first(); i; i = e.next() ) incidences.append( i ); QPtrList<Todo> t = rawTodos(); for( i = t.first(); i; i = t.next() ) incidences.append( i ); QPtrList<Journal> j = journals(); for( i = j.first(); i; i = j.next() ) incidences.append( i ); return incidences; } QPtrList<Event> Calendar::events( const QDate &date, bool sorted ) { QPtrList<Event> el = rawEventsForDate(date,sorted); mFilter->apply(&el); return el; } QPtrList<Event> Calendar::events( const QDateTime &qdt ) { QPtrList<Event> el = rawEventsForDate(qdt); mFilter->apply(&el); return el; } QPtrList<Event> Calendar::events( const QDate &start, const QDate &end, bool inclusive) { QPtrList<Event> el = rawEvents(start,end,inclusive); mFilter->apply(&el); return el; } QPtrList<Event> Calendar::events() { QPtrList<Event> el = rawEvents(); mFilter->apply(&el); return el; } void Calendar::addIncidenceBranch(Incidence *i) { addIncidence( i ); Incidence * inc; QPtrList<Incidence> Relations = i->relations(); for (inc=Relations.first();inc;inc=Relations.next()) { addIncidenceBranch( inc ); } } bool Calendar::addIncidence(Incidence *i) { Incidence::AddVisitor<Calendar> v(this); return i->accept(v); } void Calendar::deleteIncidence(Incidence *in) { - if ( in->type() == "Event" ) + if ( in->typeID() == eventID ) deleteEvent( (Event*) in ); - else if ( in->type() =="Todo" ) + else if ( in->typeID() == todoID ) deleteTodo( (Todo*) in); - else if ( in->type() =="Journal" ) + else if ( in->typeID() == journalID ) deleteJournal( (Journal*) in ); } Incidence* Calendar::incidence( const QString& uid ) { Incidence* i; if( (i = todo( uid )) != 0 ) return i; if( (i = event( uid )) != 0 ) return i; if( (i = journal( uid )) != 0 ) return i; return 0; } QPtrList<Todo> Calendar::todos() { QPtrList<Todo> tl = rawTodos(); mFilter->apply( &tl ); return tl; } // When this is called, the todo have already been added to the calendar. // This method is only about linking related todos void Calendar::setupRelations( Incidence *incidence ) { QString uid = incidence->uid(); //qDebug("Calendar::setupRelations "); // First, go over the list of orphans and see if this is their parent while( Incidence* i = mOrphans[ uid ] ) { mOrphans.remove( uid ); i->setRelatedTo( incidence ); incidence->addRelation( i ); mOrphanUids.remove( i->uid() ); } // Now see about this incidences parent if( !incidence->relatedTo() && !incidence->relatedToUid().isEmpty() ) { // This incidence has a uid it is related to, but is not registered to it yet // Try to find it Incidence* parent = this->incidence( incidence->relatedToUid() ); if( parent ) { // Found it incidence->setRelatedTo( parent ); parent->addRelation( incidence ); } else { // Not found, put this in the mOrphans list mOrphans.insert( incidence->relatedToUid(), incidence ); mOrphanUids.insert( incidence->uid(), incidence ); } } } // If a task with subtasks is deleted, move it's subtasks to the orphans list void Calendar::removeRelations( Incidence *incidence ) { // qDebug("Calendar::removeRelations "); QString uid = incidence->uid(); QPtrList<Incidence> relations = incidence->relations(); for( Incidence* i = relations.first(); i; i = relations.next() ) if( !mOrphanUids.find( i->uid() ) ) { mOrphans.insert( uid, i ); mOrphanUids.insert( i->uid(), i ); i->setRelatedTo( 0 ); i->setRelatedToUid( uid ); } // If this incidence is related to something else, tell that about it if( incidence->relatedTo() ) incidence->relatedTo()->removeRelation( incidence ); // Remove this one from the orphans list if( mOrphanUids.remove( uid ) ) // This incidence is located in the orphans list - it should be removed if( !( incidence->relatedTo() != 0 && mOrphans.remove( incidence->relatedTo()->uid() ) ) ) { // Removing wasn't that easy for( QDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) { if( it.current()->uid() == uid ) { mOrphans.remove( it.currentKey() ); break; } } } } void Calendar::registerObserver( Observer *observer ) { mObserver = observer; mNewObserver = true; } void Calendar::setModified( bool modified ) { if ( mObserver ) mObserver->calendarModified( modified, this ); if ( modified != mModified || mNewObserver ) { mNewObserver = false; // if ( mObserver ) mObserver->calendarModified( modified, this ); mModified = modified; } } void Calendar::setLoadedProductId( const QString &id ) { mLoadedProductId = id; } QString Calendar::loadedProductId() { return mLoadedProductId; } //#include "calendar.moc" diff --git a/libkcal/calendarlocal.cpp b/libkcal/calendarlocal.cpp index bc76c0b..fe74052 100644 --- a/libkcal/calendarlocal.cpp +++ b/libkcal/calendarlocal.cpp @@ -1,730 +1,726 @@ /* 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() { Todo * i; for( i = mTodoList.first(); i; i = mTodoList.next() ) i->setRunning(false); 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::addAnniversaryNoDup( Event *event ) { QString cat; bool isBirthday = true; if( event->categoriesStr() == i18n( "Anniversary" ) ) { isBirthday = false; cat = i18n( "Anniversary" ); } else if( event->categoriesStr() == i18n( "Birthday" ) ) { isBirthday = true; cat = i18n( "Birthday" ); } else { qDebug("addAnniversaryNoDup called without fitting category! "); return false; } Event * eve; for ( eve = mEventList.first(); eve ; eve = mEventList.next() ) { if ( !(eve->categories().contains( cat ) )) continue; // now we have an event with fitting category if ( eve->dtStart().date() != event->dtStart().date() ) continue; // now we have an event with fitting category+date if ( eve->summary() != event->summary() ) continue; // now we have an event with fitting category+date+summary return false; } return addEvent( event ); } 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 ( mUndoIncidence ) delete mUndoIncidence; mUndoIncidence = event->clone(); 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 if ( mUndoIncidence ) delete mUndoIncidence; removeRelations( todo ); mUndoIncidence = todo->clone(); if ( mTodoList.removeRef( todo ) ) { setModified( true ); } } QPtrList<Todo> CalendarLocal::rawTodos() { return mTodoList; } Todo *CalendarLocal::todo( QString syncProf, QString id ) { Todo *todo; for ( todo = mTodoList.first(); todo; todo = mTodoList.next() ) { if ( todo->getID( syncProf ) == id ) return todo; } return 0; } void CalendarLocal::removeSyncInfo( QString syncProfile) { QPtrList<Incidence> all = rawIncidences() ; Incidence *inc; for ( inc = all.first(); inc; inc = all.next() ) { inc->removeID( syncProfile ); } if ( syncProfile.isEmpty() ) { QPtrList<Event> el; Event *todo; for ( todo = mEventList.first(); todo; todo = mEventList.next() ) { if ( todo->uid().left( 15 ) == QString("last-syncEvent-") ) el.append( todo ); } for ( todo = el.first(); todo; todo = el.next() ) { deleteIncidence ( todo ); } } else { Event *lse = event( "last-syncEvent-"+ syncProfile); if ( lse ) deleteIncidence ( lse ); } } QPtrList<Event> CalendarLocal::getExternLastSyncEvents() { QPtrList<Event> el; Event *todo; for ( todo = mEventList.first(); todo; todo = mEventList.next() ) { if ( todo->uid().left( 15 ) == QString("last-syncEvent-") ) if ( todo->summary().left(3) == "E: " ) el.append( todo ); } return el; } Event *CalendarLocal::event( QString syncProf, QString id ) { Event *todo; for ( todo = mEventList.first(); todo; todo = mEventList.next() ) { if ( todo->getID( syncProf ) == 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, QDateTime::currentDateTime() ) ; 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 ); mNextAlarmEventDateTime = QDateTime(); // #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, QDateTime::currentDateTime() ) ; 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, QDateTime::currentDateTime() ) ; 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 ( mUndoIncidence ) delete mUndoIncidence; mUndoIncidence = journal->clone(); mUndoIncidence->setSummary( mUndoIncidence->description().left(25)); 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; } diff --git a/libkcal/calfilter.cpp b/libkcal/calfilter.cpp index c425dfc..20078a7 100644 --- a/libkcal/calfilter.cpp +++ b/libkcal/calfilter.cpp @@ -1,212 +1,212 @@ /* This file is part of libkcal. Copyright (c) 2001 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 <kdebug.h> #include "calfilter.h" using namespace KCal; CalFilter::CalFilter() { mEnabled = true; mCriteria = ShowPublic | ShowPrivate| ShowConfidential ; } CalFilter::CalFilter(const QString &name) { mName = name; mEnabled = true; mCriteria = ShowPublic | ShowPrivate| ShowConfidential ; } CalFilter::~CalFilter() { } void CalFilter::apply(QPtrList<Event> *eventlist) { if (!mEnabled) return; // kdDebug(5800) << "CalFilter::apply()" << endl; Event *event = eventlist->first(); while(event) { if (!filterEvent(event)) { eventlist->remove(); event = eventlist->current(); } else { event = eventlist->next(); } } // kdDebug(5800) << "CalFilter::apply() done" << endl; } // TODO: avoid duplicating apply() code void CalFilter::apply(QPtrList<Todo> *eventlist) { if (!mEnabled) return; Todo *event = eventlist->first(); while(event) { if (!filterTodo(event)) { eventlist->remove(); event = eventlist->current(); } else { event = eventlist->next(); } } // kdDebug(5800) << "CalFilter::apply() done" << endl; } bool CalFilter::filterCalendarItem(Incidence *in) { - if ( in->type() == "Event" ) + if ( in->typeID() == eventID ) return filterEvent( (Event*) in ); - else if ( in->type() =="Todo" ) + else if ( in->typeID() == todoID ) return filterTodo( (Todo*) in); - else if ( in->type() =="Journal" ) + else if ( in->typeID () == journalID ) return filterJournal( (Journal*) in ); return false; } bool CalFilter::filterEvent(Event *event) { if (mCriteria & HideEvents) return false; if (mCriteria & HideRecurring) { if (event->recurrence()->doesRecur()) return false; } return filterIncidence(event); } bool CalFilter::filterJournal(Journal *j) { if (mCriteria & HideJournals) return false; return true; } bool CalFilter::filterTodo(Todo *todo) { if (mCriteria & HideTodos) return false; if (mCriteria & HideCompleted) { if (todo->isCompleted()) return false; } return filterIncidence(todo); } bool CalFilter::showCategories() { return mCriteria & ShowCategories; } int CalFilter::getSecrecy() { if ( (mCriteria & ShowPublic )) return Incidence::SecrecyPublic; if ( (mCriteria & ShowPrivate )) return Incidence::SecrecyPrivate; if ( (mCriteria & ShowConfidential )) return Incidence::SecrecyConfidential; return Incidence::SecrecyPublic; } bool CalFilter::filterIncidence(Incidence *incidence) { if ( mCriteria > 7 ) { switch (incidence->secrecy()) { case Incidence::SecrecyPublic: if (! (mCriteria & ShowPublic )) return false; break; case Incidence::SecrecyPrivate: if (! (mCriteria & ShowPrivate )) return false; break; case Incidence::SecrecyConfidential: if (! (mCriteria & ShowConfidential )) return false; break; default: return false; break; } } // kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl; if (mCriteria & ShowCategories) { for (QStringList::Iterator it = mCategoryList.begin(); it != mCategoryList.end(); ++it ) { QStringList incidenceCategories = incidence->categories(); for (QStringList::Iterator it2 = incidenceCategories.begin(); it2 != incidenceCategories.end(); ++it2 ) { if ((*it) == (*it2)) { return true; } } } return false; } else { for (QStringList::Iterator it = mCategoryList.begin(); it != mCategoryList.end(); ++it ) { QStringList incidenceCategories = incidence->categories(); for (QStringList::Iterator it2 = incidenceCategories.begin(); it2 != incidenceCategories.end(); ++it2 ) { if ((*it) == (*it2)) { return false; } } } return true; } // kdDebug(5800) << "CalFilter::filterEvent(): passed" << endl; return true; } void CalFilter::setEnabled(bool enabled) { mEnabled = enabled; } bool CalFilter::isEnabled() { return mEnabled; } void CalFilter::setCriteria(int criteria) { mCriteria = criteria; } int CalFilter::criteria() { return mCriteria; } void CalFilter::setCategoryList(const QStringList &categoryList) { mCategoryList = categoryList; } QStringList CalFilter::categoryList() { return mCategoryList; } diff --git a/libkcal/event.h b/libkcal/event.h index 8729956..287d403 100644 --- a/libkcal/event.h +++ b/libkcal/event.h @@ -1,90 +1,91 @@ /* This file is part of libkcal. Copyright (c) 2001 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. */ #ifndef EVENT_H #define EVENT_H // // Event component, representing a VEVENT object // #include "incidence.h" namespace KCal { /** This class provides an Event in the sense of RFC2445. */ class Event : public Incidence { public: enum Transparency { Opaque, Transparent }; typedef ListBase<Event> List; Event(); Event(const Event &); ~Event(); QCString type() const { return "Event"; } + IncTypeID typeID() const { return eventID; } Incidence *clone(); QDateTime getNextAlarmDateTime( bool * ok, int * offset ,QDateTime start_dt ) const; /** for setting an event's ending date/time with a QDateTime. */ void setDtEnd(const QDateTime &dtEnd); /** Return the event's ending date/time as a QDateTime. */ virtual QDateTime dtEnd() const; /** returns an event's end time as a string formatted according to the users locale settings */ QString dtEndTimeStr() const; /** returns an event's end date as a string formatted according to the users locale settings */ QString dtEndDateStr(bool shortfmt=true) const; /** returns an event's end date and time as a string formatted according to the users locale settings */ QString dtEndStr(bool shortfmt=true) const; void setHasEndDate(bool); /** Return whether the event has an end date/time. */ bool hasEndDate() const; /** Return true if the event spans multiple days, otherwise return false. */ bool isMultiDay() const; /** set the event's time transparency level. */ void setTransparency(Transparency transparency); /** get the event's time transparency level. */ Transparency transparency() const; void setDuration(int seconds); bool contains ( Event*); private: bool accept(Visitor &v) { return v.visit(this); } QDateTime mDtEnd; bool mHasEndDate; Transparency mTransparency; }; bool operator==( const Event&, const Event& ); } #endif diff --git a/libkcal/freebusy.h b/libkcal/freebusy.h index 054feda..d741c72 100644 --- a/libkcal/freebusy.h +++ b/libkcal/freebusy.h @@ -1,72 +1,73 @@ /* This file is part of libkcal. Copyright (c) 2001 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. */ #ifndef KCAL_FREEBUSY_H #define KCAL_FREEBUSY_H // // FreeBusy - information about free/busy times // #include <qdatetime.h> #include <qvaluelist.h> #include <qptrlist.h> #include "period.h" #include "calendar.h" #include "incidencebase.h" namespace KCal { /** This class provides information about free/busy time of a calendar user. */ class FreeBusy : public IncidenceBase { public: FreeBusy(); FreeBusy(const QDateTime &start, const QDateTime &end); FreeBusy(Calendar *calendar, const QDateTime &start, const QDateTime &end); FreeBusy(QValueList<Period> busyPeriods); ~FreeBusy(); QCString type() const { return "FreeBusy"; } + IncTypeID typeID() const { return freebusyID; } virtual QDateTime dtEnd() const; bool setDtEnd( const QDateTime &end ); QValueList<Period> busyPeriods() const; void addPeriod(const QDateTime &start, const QDateTime &end); void sortList(); private: //This is used for creating a freebusy object for the current user bool addLocalPeriod(const QDateTime &start, const QDateTime &end); QDateTime mDtEnd; QValueList<Period> mBusyPeriods; Calendar *mCalendar; }; } #endif diff --git a/libkcal/icalformat.cpp b/libkcal/icalformat.cpp index 3a2aac6..d9fe40b 100644 --- a/libkcal/icalformat.cpp +++ b/libkcal/icalformat.cpp @@ -1,460 +1,460 @@ /* This file is part of libkcal. Copyright (c) 2001 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 <qregexp.h> #include <qclipboard.h> #include <qfile.h> #include <qtextstream.h> #include <qtextcodec.h> #include <stdlib.h> #include <kdebug.h> #include <kglobal.h> #include <klocale.h> extern "C" { #include <ical.h> #include <icalss.h> #include <icalparser.h> #include <icalrestriction.h> } #include "calendar.h" #include "calendarlocal.h" #include "journal.h" #include "icalformat.h" #include "icalformatimpl.h" #define _ICAL_VERSION "2.0" using namespace KCal; ICalFormat::ICalFormat( ) { mImpl = new ICalFormatImpl( this ); tzOffsetMin = 0; //qDebug("new ICalFormat() "); } ICalFormat::~ICalFormat() { delete mImpl; //qDebug("delete ICalFormat "); } bool ICalFormat::load( Calendar *calendar, const QString &fileName) { clearException(); QFile file( fileName ); if (!file.open( IO_ReadOnly ) ) { setException(new ErrorFormat(ErrorFormat::LoadError)); return false; } QTextStream ts( &file ); QString text; ts.setEncoding( QTextStream::Latin1 ); text = ts.read(); file.close(); return fromString( calendar, text ); } //#include <qdatetime.h> bool ICalFormat::save( Calendar *calendar, const QString &fileName ) { //kdDebug(5800) << "ICalFormat::save(): " << fileName << endl; //qDebug("ICalFormat::save "); clearException(); QString text = toString( calendar ); //return false; // qDebug("to string takes ms: %d ",is.elapsed() ); if ( text.isNull() ) return false; // TODO: write backup file //is.restart(); QFile file( fileName ); if (!file.open( IO_WriteOnly ) ) { setException(new ErrorFormat(ErrorFormat::SaveError, i18n("Could not open file '%1'").arg(fileName))); return false; } QTextStream ts( &file ); ts.setEncoding( QTextStream::Latin1 ); ts << text; file.close(); //qDebug("saving file takes ms: %d ", is.elapsed() ); return true; } bool ICalFormat::fromString( Calendar *cal, const QString &text ) { setTimeZone( cal->timeZoneId(), !cal->isLocalTime() ); // qDebug("ICalFormat::fromString tz: %s ", cal->timeZoneId().latin1()); // Get first VCALENDAR component. // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components icalcomponent *calendar; //calendar = icalcomponent_new_from_string( text.local8Bit().data()); // good calendar = icalcomponent_new_from_string( text.utf8().data()); calendar = icalcomponent_new_from_string( (char*)text.latin1()); if (!calendar) { setException(new ErrorFormat(ErrorFormat::ParseErrorIcal)); return false; } bool success = true; if (icalcomponent_isa(calendar) != ICAL_VCALENDAR_COMPONENT) { setException(new ErrorFormat(ErrorFormat::NoCalendar)); success = false; } else { // put all objects into their proper places if ( !mImpl->populate( cal, calendar ) ) { if ( !exception() ) { setException(new ErrorFormat(ErrorFormat::ParseErrorKcal)); } success = false; } else mLoadedProductId = mImpl->loadedProductId(); } icalcomponent_free( calendar ); return success; } Incidence *ICalFormat::fromString( const QString &text ) { CalendarLocal cal( mTimeZoneId ); fromString(&cal, text); Incidence *ical = 0; QPtrList<Event> elist = cal.events(); if ( elist.count() > 0 ) { ical = elist.first(); } else { QPtrList<Todo> tlist = cal.todos(); if ( tlist.count() > 0 ) { ical = tlist.first(); } else { QPtrList<Journal> jlist = cal.journals(); if ( jlist.count() > 0 ) { ical = jlist.first(); } } } return ical; } #include <qapp.h> QString ICalFormat::toString( Calendar *cal ) { setTimeZone( cal->timeZoneId(), !cal->isLocalTime() ); icalcomponent *calendar = mImpl->createCalendarComponent(cal); icalcomponent *component; // todos QPtrList<Todo> todoList = cal->rawTodos(); QPtrListIterator<Todo> qlt(todoList); for (; qlt.current(); ++qlt) { component = mImpl->writeTodo(qlt.current()); icalcomponent_add_component(calendar,component); //qDebug(" todos "); qApp->processEvents(); } // events QPtrList<Event> events = cal->rawEvents(); Event *ev; for(ev=events.first();ev;ev=events.next()) { component = mImpl->writeEvent(ev); icalcomponent_add_component(calendar,component); //qDebug("events "); qApp->processEvents(); } // journals QPtrList<Journal> journals = cal->journals(); Journal *j; for(j=journals.first();j;j=journals.next()) { component = mImpl->writeJournal(j); icalcomponent_add_component(calendar,component); //qDebug("journals "); qApp->processEvents(); } const char *text; QString ret =""; text = icalcomponent_as_ical_string( calendar ); qApp->processEvents(); // text = "BEGIN:VCALENDAR\nPRODID\n :-//K Desktop Environment//NONSGML libkcal 3.1//EN\nVERSION\n :2.0\nBEGIN:VEVENT\nDTSTAMP\n :20031231T213514Z\nORGANIZER\n :MAILTO:lutz@putz.de\nCREATED\n :20031231T213513Z\nUID\n :libkcal-1295166342.120\nSEQUENCE\n :0\nLAST-MODIFIED\n :20031231T213513Z\nSUMMARY\n :test1\nCLASS\n :PUBLIC\nPRIORITY\n :3\nDTSTART\n :20040101T090000Z\nDTEND\n :20040101T110000Z\nTRANSP\n :OPAQUE\nEND:VEVENT\nEND:VCALENDAR\n"; if ( text ) { ret = QString ( text ); } icalcomponent_free( calendar ); if (!text) { setException(new ErrorFormat(ErrorFormat::SaveError, i18n("libical error"))); return QString::null; } return ret; } QString ICalFormat::toICalString( Incidence *incidence ) { CalendarLocal cal( mTimeZoneId ); cal.addIncidence( incidence->clone() ); return toString( &cal ); } QString ICalFormat::toString( Incidence *incidence ) { icalcomponent *component; component = mImpl->writeIncidence( incidence ); const char *text = icalcomponent_as_ical_string( component ); icalcomponent_free( component ); return QString::fromLocal8Bit( text ); } QString ICalFormat::toString( Recurrence *recurrence ) { icalproperty *property; property = mImpl->writeRecurrenceRule( recurrence ); const char *text = icalproperty_as_ical_string( property ); icalproperty_free( property ); return QString::fromLocal8Bit( text ); } /* bool ICalFormat::fromString( Recurrence * recurrence, const QString& rrule ) { bool success = true; icalerror_clear_errno(); struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule ); if ( icalerrno != ICAL_NO_ERROR ) { kdDebug() << "Recurrence parsing error: " << icalerror_strerror( icalerrno ) << endl; success = false; } if ( success ) { mImpl->readRecurrence( recur, recurrence ); } return success; } */ QString ICalFormat::createScheduleMessage(IncidenceBase *incidence, Scheduler::Method method) { icalcomponent *message = mImpl->createScheduleComponent(incidence,method); QString messageText = icalcomponent_as_ical_string(message); return messageText; } ScheduleMessage *ICalFormat::parseScheduleMessage( Calendar *cal, const QString &messageText ) { setTimeZone( cal->timeZoneId(), !cal->isLocalTime() ); clearException(); if (messageText.isEmpty()) return 0; icalcomponent *message; message = icalparser_parse_string(messageText.local8Bit()); if (!message) return 0; icalproperty *m = icalcomponent_get_first_property(message, ICAL_METHOD_PROPERTY); if (!m) return 0; icalcomponent *c; IncidenceBase *incidence = 0; c = icalcomponent_get_first_component(message,ICAL_VEVENT_COMPONENT); if (c) { incidence = mImpl->readEvent(c); } if (!incidence) { c = icalcomponent_get_first_component(message,ICAL_VTODO_COMPONENT); if (c) { incidence = mImpl->readTodo(c); } } if (!incidence) { c = icalcomponent_get_first_component(message,ICAL_VFREEBUSY_COMPONENT); if (c) { incidence = mImpl->readFreeBusy(c); } } if (!incidence) { kdDebug() << "ICalFormat:parseScheduleMessage: object is not a freebusy, event or todo" << endl; return 0; } kdDebug(5800) << "ICalFormat::parseScheduleMessage() getting method..." << endl; icalproperty_method icalmethod = icalproperty_get_method(m); Scheduler::Method method; switch (icalmethod) { case ICAL_METHOD_PUBLISH: method = Scheduler::Publish; break; case ICAL_METHOD_REQUEST: method = Scheduler::Request; break; case ICAL_METHOD_REFRESH: method = Scheduler::Refresh; break; case ICAL_METHOD_CANCEL: method = Scheduler::Cancel; break; case ICAL_METHOD_ADD: method = Scheduler::Add; break; case ICAL_METHOD_REPLY: method = Scheduler::Reply; break; case ICAL_METHOD_COUNTER: method = Scheduler::Counter; break; case ICAL_METHOD_DECLINECOUNTER: method = Scheduler::Declinecounter; break; default: method = Scheduler::NoMethod; kdDebug(5800) << "ICalFormat::parseScheduleMessage(): Unknow method" << endl; break; } if (!icalrestriction_check(message)) { setException(new ErrorFormat(ErrorFormat::Restriction, Scheduler::translatedMethodName(method) + ": " + mImpl->extractErrorProperty(c))); return 0; } icalcomponent *calendarComponent = mImpl->createCalendarComponent(cal); Incidence *existingIncidence = cal->event(incidence->uid()); if (existingIncidence) { // TODO: check, if cast is required, or if it can be done by virtual funcs. - if (existingIncidence->type() == "Todo") { + if (existingIncidence->typeID() == todoID ) { Todo *todo = static_cast<Todo *>(existingIncidence); icalcomponent_add_component(calendarComponent, mImpl->writeTodo(todo)); } - if (existingIncidence->type() == "Event") { + if (existingIncidence->typeID() == eventID ) { Event *event = static_cast<Event *>(existingIncidence); icalcomponent_add_component(calendarComponent, mImpl->writeEvent(event)); } } else { calendarComponent = 0; } qDebug("icalclassify commented out "); ScheduleMessage::Status status; #if 0 icalclass result = icalclassify(message,calendarComponent,(char *)""); switch (result) { case ICAL_PUBLISH_NEW_CLASS: status = ScheduleMessage::PublishNew; break; case ICAL_OBSOLETE_CLASS: status = ScheduleMessage::Obsolete; break; case ICAL_REQUEST_NEW_CLASS: status = ScheduleMessage::RequestNew; break; case ICAL_REQUEST_UPDATE_CLASS: status = ScheduleMessage::RequestUpdate; break; case ICAL_UNKNOWN_CLASS: default: status = ScheduleMessage::Unknown; break; } #endif status = ScheduleMessage::RequestUpdate; return new ScheduleMessage(incidence,method,status); } void ICalFormat::setTimeZone( const QString &id, bool utc ) { mTimeZoneId = id; mUtc = utc; tzOffsetMin = KGlobal::locale()->timezoneOffset(mTimeZoneId); //qDebug("ICalFormat::setTimeZoneOffset %s %d ",mTimeZoneId.latin1(), tzOffsetMin); } QString ICalFormat::timeZoneId() const { return mTimeZoneId; } bool ICalFormat::utc() const { return mUtc; } int ICalFormat::timeOffset() { return tzOffsetMin; } const char *ICalFormat::tzString() { const char* ret = (const char* ) mTzString; return ret; } diff --git a/libkcal/icalformatimpl.cpp b/libkcal/icalformatimpl.cpp index 2405682..3e28714 100644 --- a/libkcal/icalformatimpl.cpp +++ b/libkcal/icalformatimpl.cpp @@ -622,1551 +622,1551 @@ icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur) // r.by_set_pos[index] = ICAL_RECURRENCE_ARRAY_MAX; if (recur->doesRecur() == Recurrence::rYearlyPos) { tmpPositions = recur->monthPositions(); for (tmpPos = tmpPositions.first(); tmpPos; tmpPos = tmpPositions.next()) { for (i = 0; i < 7; i++) { if (tmpPos->rDays.testBit(i)) { day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 day += tmpPos->rPos*8; if (tmpPos->negative) day = -day; r.by_day[index2++] = day; } } } // r.by_day[index2] = ICAL_RECURRENCE_ARRAY_MAX; } break; case Recurrence::rYearlyDay: r.freq = ICAL_YEARLY_RECURRENCE; tmpDays = recur->yearNums(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_year_day[index++] = *tmpDay; } // r.by_year_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; default: r.freq = ICAL_NO_RECURRENCE; kdDebug(5800) << "ICalFormatImpl::writeRecurrence(): no recurrence" << endl; break; } r.interval = recur->frequency(); if (recur->duration() > 0) { r.count = recur->duration(); } else if (recur->duration() == -1) { r.count = 0; } else { if (datetime) r.until = writeICalDateTime(recur->endDateTime()); else r.until = writeICalDate(recur->endDate()); } // Debug output #if 0 const char *str = icalrecurrencetype_as_string(&r); if (str) { kdDebug(5800) << " String: " << str << endl; } else { kdDebug(5800) << " No String" << endl; } #endif return icalproperty_new_rrule(r); } icalcomponent *ICalFormatImpl::writeAlarm(Alarm *alarm) { icalcomponent *a = icalcomponent_new(ICAL_VALARM_COMPONENT); icalproperty_action action; icalattach *attach = 0; switch (alarm->type()) { case Alarm::Procedure: action = ICAL_ACTION_PROCEDURE; attach = icalattach_new_from_url( QFile::encodeName(alarm->programFile()).data() ); icalcomponent_add_property(a,icalproperty_new_attach(attach)); if (!alarm->programArguments().isEmpty()) { icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8())); } icalattach_unref( attach ); break; case Alarm::Audio: action = ICAL_ACTION_AUDIO; if (!alarm->audioFile().isEmpty()) { attach = icalattach_new_from_url(QFile::encodeName( alarm->audioFile() ).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); icalattach_unref( attach ); } break; case Alarm::Email: { action = ICAL_ACTION_EMAIL; QValueList<Person> addresses = alarm->mailAddresses(); for (QValueList<Person>::Iterator ad = addresses.begin(); ad != addresses.end(); ++ad) { icalproperty *p = icalproperty_new_attendee("MAILTO:" + (*ad).email().utf8()); if (!(*ad).name().isEmpty()) { icalproperty_add_parameter(p,icalparameter_new_cn((*ad).name().utf8())); } icalcomponent_add_property(a,p); } icalcomponent_add_property(a,icalproperty_new_summary(alarm->mailSubject().utf8())); icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); QStringList attachments = alarm->mailAttachments(); if (attachments.count() > 0) { for (QStringList::Iterator at = attachments.begin(); at != attachments.end(); ++at) { attach = icalattach_new_from_url(QFile::encodeName( *at ).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); icalattach_unref( attach ); } } break; } case Alarm::Display: action = ICAL_ACTION_DISPLAY; icalcomponent_add_property(a,icalproperty_new_description(alarm->text().utf8())); break; case Alarm::Invalid: default: kdDebug(5800) << "Unknown type of alarm" << endl; action = ICAL_ACTION_NONE; break; } icalcomponent_add_property(a,icalproperty_new_action(action)); // Trigger time icaltriggertype trigger; if ( alarm->hasTime() ) { trigger.time = writeICalDateTime(alarm->time()); trigger.duration = icaldurationtype_null_duration(); } else { trigger.time = icaltime_null_time(); Duration offset; if ( alarm->hasStartOffset() ) offset = alarm->startOffset(); else offset = alarm->endOffset(); trigger.duration = icaldurationtype_from_int( offset.asSeconds() ); } icalproperty *p = icalproperty_new_trigger(trigger); if ( alarm->hasEndOffset() ) icalproperty_add_parameter(p,icalparameter_new_related(ICAL_RELATED_END)); icalcomponent_add_property(a,p); // Repeat count and duration if (alarm->repeatCount()) { icalcomponent_add_property(a,icalproperty_new_repeat(alarm->repeatCount())); icalcomponent_add_property(a,icalproperty_new_duration( icaldurationtype_from_int(alarm->snoozeTime()*60))); } // Custom properties QMap<QCString, QString> custom = alarm->customProperties(); for (QMap<QCString, QString>::Iterator c = custom.begin(); c != custom.end(); ++c) { icalproperty *p = icalproperty_new_x(c.data().utf8()); icalproperty_set_x_name(p,c.key()); icalcomponent_add_property(a,p); } return a; } Todo *ICalFormatImpl::readTodo(icalcomponent *vtodo) { Todo *todo = new Todo; readIncidence(vtodo,todo); icalproperty *p = icalcomponent_get_first_property(vtodo,ICAL_ANY_PROPERTY); // int intvalue; icaltimetype icaltime; QStringList categories; while (p) { icalproperty_kind kind = icalproperty_isa(p); switch (kind) { case ICAL_DUE_PROPERTY: // due date icaltime = icalproperty_get_due(p); if (icaltime.is_date) { todo->setDtDue(QDateTime(readICalDate(icaltime),QTime(0,0,0))); todo->setFloats(true); } else { todo->setDtDue(readICalDateTime(icaltime)); todo->setFloats(false); } todo->setHasDueDate(true); break; case ICAL_COMPLETED_PROPERTY: // completion date icaltime = icalproperty_get_completed(p); todo->setCompleted(readICalDateTime(icaltime)); break; case ICAL_PERCENTCOMPLETE_PROPERTY: // Percent completed todo->setPercentComplete(icalproperty_get_percentcomplete(p)); break; case ICAL_RELATEDTO_PROPERTY: // related todo (parent) todo->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); mTodosRelate.append(todo); break; case ICAL_DTSTART_PROPERTY: // Flag that todo has start date. Value is read in by readIncidence(). todo->setHasStartDate(true); break; default: // kdDebug(5800) << "ICALFormat::readTodo(): Unknown property: " << kind // << endl; break; } p = icalcomponent_get_next_property(vtodo,ICAL_ANY_PROPERTY); } return todo; } Event *ICalFormatImpl::readEvent(icalcomponent *vevent) { Event *event = new Event; event->setFloats(false); readIncidence(vevent,event); icalproperty *p = icalcomponent_get_first_property(vevent,ICAL_ANY_PROPERTY); // int intvalue; icaltimetype icaltime; QStringList categories; QString transparency; while (p) { icalproperty_kind kind = icalproperty_isa(p); switch (kind) { case ICAL_DTEND_PROPERTY: // start date and time icaltime = icalproperty_get_dtend(p); if (icaltime.is_date) { event->setFloats( true ); // End date is non-inclusive QDate endDate = readICalDate( icaltime ).addDays( -1 ); mCompat->fixFloatingEnd( endDate ); if ( endDate < event->dtStart().date() ) { endDate = event->dtStart().date(); } event->setDtEnd( QDateTime( endDate, QTime( 0, 0, 0 ) ) ); } else { event->setDtEnd(readICalDateTime(icaltime)); } break; // TODO: // at this point, there should be at least a start or end time. // fix up for events that take up no time but have a time associated #if 0 if (!(vo = isAPropertyOf(vevent, VCDTstartProp))) anEvent->setDtStart(anEvent->dtEnd()); if (!(vo = isAPropertyOf(vevent, VCDTendProp))) anEvent->setDtEnd(anEvent->dtStart()); #endif // TODO: exdates #if 0 // recurrence exceptions if ((vo = isAPropertyOf(vevent, VCExDateProp)) != 0) { anEvent->setExDates(s = fakeCString(vObjectUStringZValue(vo))); deleteStr(s); } #endif #if 0 // secrecy if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) { anEvent->setSecrecy(s = fakeCString(vObjectUStringZValue(vo))); deleteStr(s); } else anEvent->setSecrecy("PUBLIC"); // attachments tmpStrList.clear(); initPropIterator(&voi, vevent); while (moreIteration(&voi)) { vo = nextVObject(&voi); if (strcmp(vObjectName(vo), VCAttachProp) == 0) { tmpStrList.append(s = fakeCString(vObjectUStringZValue(vo))); deleteStr(s); } } anEvent->setAttachments(tmpStrList); // resources if ((vo = isAPropertyOf(vevent, VCResourcesProp)) != 0) { QString resources = (s = fakeCString(vObjectUStringZValue(vo))); deleteStr(s); tmpStrList.clear(); index1 = 0; index2 = 0; QString resource; while ((index2 = resources.find(';', index1)) != -1) { resource = resources.mid(index1, (index2 - index1)); tmpStrList.append(resource); index1 = index2; } anEvent->setResources(tmpStrList); } #endif case ICAL_RELATEDTO_PROPERTY: // releated event (parent) event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); mEventsRelate.append(event); break; case ICAL_TRANSP_PROPERTY: // Transparency if(icalproperty_get_transp(p) == ICAL_TRANSP_TRANSPARENT ) event->setTransparency( Event::Transparent ); else event->setTransparency( Event::Opaque ); break; default: // kdDebug(5800) << "ICALFormat::readEvent(): Unknown property: " << kind // << endl; break; } p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY); } QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT"); if (!msade.isNull()) { bool floats = (msade == QString::fromLatin1("TRUE")); kdDebug(5800) << "ICALFormat::readEvent(): all day event: " << floats << endl; event->setFloats(floats); if (floats) { QDateTime endDate = event->dtEnd(); event->setDtEnd(endDate.addDays(-1)); } } // some stupid vCal exporters ignore the standard and use Description // instead of Summary for the default field. Correct for this. if (event->summary().isEmpty() && !(event->description().isEmpty())) { QString tmpStr = event->description().simplifyWhiteSpace(); event->setDescription(""); event->setSummary(tmpStr); } return event; } FreeBusy *ICalFormatImpl::readFreeBusy(icalcomponent *vfreebusy) { FreeBusy *freebusy = new FreeBusy; readIncidenceBase(vfreebusy,freebusy); icalproperty *p = icalcomponent_get_first_property(vfreebusy,ICAL_ANY_PROPERTY); icaltimetype icaltime; icalperiodtype icalperiod; QDateTime period_start, period_end; while (p) { icalproperty_kind kind = icalproperty_isa(p); switch (kind) { case ICAL_DTSTART_PROPERTY: // start date and time icaltime = icalproperty_get_dtstart(p); freebusy->setDtStart(readICalDateTime(icaltime)); break; case ICAL_DTEND_PROPERTY: // start End Date and Time icaltime = icalproperty_get_dtend(p); freebusy->setDtEnd(readICalDateTime(icaltime)); break; case ICAL_FREEBUSY_PROPERTY: //Any FreeBusy Times icalperiod = icalproperty_get_freebusy(p); period_start = readICalDateTime(icalperiod.start); period_end = readICalDateTime(icalperiod.end); freebusy->addPeriod(period_start, period_end); break; default: kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind << endl; break; } p = icalcomponent_get_next_property(vfreebusy,ICAL_ANY_PROPERTY); } return freebusy; } Journal *ICalFormatImpl::readJournal(icalcomponent *vjournal) { Journal *journal = new Journal; readIncidence(vjournal,journal); return journal; } Attendee *ICalFormatImpl::readAttendee(icalproperty *attendee) { icalparameter *p = 0; QString email = QString::fromUtf8(icalproperty_get_attendee(attendee)); QString name; QString uid = QString::null; p = icalproperty_get_first_parameter(attendee,ICAL_CN_PARAMETER); if (p) { name = QString::fromUtf8(icalparameter_get_cn(p)); } else { } bool rsvp=false; p = icalproperty_get_first_parameter(attendee,ICAL_RSVP_PARAMETER); if (p) { icalparameter_rsvp rsvpParameter = icalparameter_get_rsvp(p); if (rsvpParameter == ICAL_RSVP_TRUE) rsvp = true; } Attendee::PartStat status = Attendee::NeedsAction; p = icalproperty_get_first_parameter(attendee,ICAL_PARTSTAT_PARAMETER); if (p) { icalparameter_partstat partStatParameter = icalparameter_get_partstat(p); switch(partStatParameter) { default: case ICAL_PARTSTAT_NEEDSACTION: status = Attendee::NeedsAction; break; case ICAL_PARTSTAT_ACCEPTED: status = Attendee::Accepted; break; case ICAL_PARTSTAT_DECLINED: status = Attendee::Declined; break; case ICAL_PARTSTAT_TENTATIVE: status = Attendee::Tentative; break; case ICAL_PARTSTAT_DELEGATED: status = Attendee::Delegated; break; case ICAL_PARTSTAT_COMPLETED: status = Attendee::Completed; break; case ICAL_PARTSTAT_INPROCESS: status = Attendee::InProcess; break; } } Attendee::Role role = Attendee::ReqParticipant; p = icalproperty_get_first_parameter(attendee,ICAL_ROLE_PARAMETER); if (p) { icalparameter_role roleParameter = icalparameter_get_role(p); switch(roleParameter) { case ICAL_ROLE_CHAIR: role = Attendee::Chair; break; default: case ICAL_ROLE_REQPARTICIPANT: role = Attendee::ReqParticipant; break; case ICAL_ROLE_OPTPARTICIPANT: role = Attendee::OptParticipant; break; case ICAL_ROLE_NONPARTICIPANT: role = Attendee::NonParticipant; break; } } p = icalproperty_get_first_parameter(attendee,ICAL_X_PARAMETER); uid = icalparameter_get_xvalue(p); // This should be added, but there seems to be a libical bug here. /*while (p) { // if (icalparameter_get_xname(p) == "X-UID") { uid = icalparameter_get_xvalue(p); p = icalproperty_get_next_parameter(attendee,ICAL_X_PARAMETER); } */ return new Attendee( name, email, rsvp, status, role, uid ); } Attachment *ICalFormatImpl::readAttachment(icalproperty *attach) { icalattach *a = icalproperty_get_attach(attach); icalparameter_value v = ICAL_VALUE_NONE; icalparameter_encoding e = ICAL_ENCODING_NONE; Attachment *attachment = 0; /* icalparameter *vp = icalproperty_get_first_parameter(attach, ICAL_VALUE_PARAMETER); if (vp) v = icalparameter_get_value(vp); icalparameter *ep = icalproperty_get_first_parameter(attach, ICAL_ENCODING_PARAMETER); if (ep) e = icalparameter_get_encoding(ep); */ int isurl = icalattach_get_is_url (a); if (isurl == 0) attachment = new Attachment((const char*)icalattach_get_data(a)); else { attachment = new Attachment(QString(icalattach_get_url(a))); } icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER); if (p) attachment->setMimeType(QString(icalparameter_get_fmttype(p))); return attachment; } #include <qtextcodec.h> void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence) { readIncidenceBase(parent,incidence); icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); bool readrec = false; const char *text; int intvalue; icaltimetype icaltime; icaldurationtype icalduration; struct icalrecurrencetype rectype; QStringList categories; while (p) { icalproperty_kind kind = icalproperty_isa(p); switch (kind) { case ICAL_CREATED_PROPERTY: icaltime = icalproperty_get_created(p); incidence->setCreated(readICalDateTime(icaltime)); break; case ICAL_SEQUENCE_PROPERTY: // sequence intvalue = icalproperty_get_sequence(p); incidence->setRevision(intvalue); break; case ICAL_LASTMODIFIED_PROPERTY: // last modification date icaltime = icalproperty_get_lastmodified(p); incidence->setLastModified(readICalDateTime(icaltime)); break; case ICAL_DTSTART_PROPERTY: // start date and time icaltime = icalproperty_get_dtstart(p); if (icaltime.is_date) { incidence->setDtStart(QDateTime(readICalDate(icaltime),QTime(0,0,0))); incidence->setFloats(true); } else { incidence->setDtStart(readICalDateTime(icaltime)); } break; case ICAL_DURATION_PROPERTY: // start date and time icalduration = icalproperty_get_duration(p); incidence->setDuration(readICalDuration(icalduration)); break; case ICAL_DESCRIPTION_PROPERTY: // description text = icalproperty_get_description(p); incidence->setDescription(QString::fromUtf8(text)); break; case ICAL_SUMMARY_PROPERTY: // summary { text = icalproperty_get_summary(p); incidence->setSummary(QString::fromUtf8(text)); } break; case ICAL_STATUS_PROPERTY: // summary { if ( ICAL_STATUS_CANCELLED == icalproperty_get_status(p) ) incidence->setCancelled( true ); } break; case ICAL_LOCATION_PROPERTY: // location text = icalproperty_get_location(p); incidence->setLocation(QString::fromUtf8(text)); break; case ICAL_RECURRENCEID_PROPERTY: icaltime = icalproperty_get_recurrenceid(p); incidence->setRecurrenceID( readICalDateTime(icaltime) ); //qDebug(" RecurrenceID %s",incidence->recurrenceID().toString().latin1() ); break; #if 0 // status if ((vo = isAPropertyOf(vincidence, VCStatusProp)) != 0) { incidence->setStatus(s = fakeCString(vObjectUStringZValue(vo))); deleteStr(s); } else incidence->setStatus("NEEDS ACTION"); #endif case ICAL_PRIORITY_PROPERTY: // priority intvalue = icalproperty_get_priority(p); incidence->setPriority(intvalue); break; case ICAL_CATEGORIES_PROPERTY: // categories text = icalproperty_get_categories(p); categories.append(QString::fromUtf8(text)); break; //******************************************* case ICAL_RRULE_PROPERTY: // we do need (maybe )start datetime of incidence for recurrence // such that we can read recurrence only after we read incidence completely readrec = true; rectype = icalproperty_get_rrule(p); break; case ICAL_EXDATE_PROPERTY: icaltime = icalproperty_get_exdate(p); incidence->addExDate(readICalDate(icaltime)); break; case ICAL_CLASS_PROPERTY: { int inttext = icalproperty_get_class(p); if (inttext == ICAL_CLASS_PUBLIC ) { incidence->setSecrecy(Incidence::SecrecyPublic); } else if (inttext == ICAL_CLASS_CONFIDENTIAL ) { incidence->setSecrecy(Incidence::SecrecyConfidential); } else { incidence->setSecrecy(Incidence::SecrecyPrivate); } } break; case ICAL_ATTACH_PROPERTY: // attachments incidence->addAttachment(readAttachment(p)); break; default: // kdDebug(5800) << "ICALFormat::readIncidence(): Unknown property: " << kind // << endl; break; } p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); } if ( readrec ) { readRecurrenceRule(rectype,incidence); } // kpilot stuff // TODO: move this application-specific code to kpilot QString kp = incidence->nonKDECustomProperty("X-PILOTID"); if (!kp.isNull()) { incidence->setPilotId(kp.toInt()); } kp = incidence->nonKDECustomProperty("X-PILOTSTAT"); if (!kp.isNull()) { incidence->setSyncStatus(kp.toInt()); } kp = incidence->nonKDECustomProperty("X-KOPIEXTID"); if (!kp.isNull()) { incidence->setIDStr(kp); } // Cancel backwards compatibility mode for subsequent changes by the application incidence->recurrence()->setCompatVersion(); // add categories incidence->setCategories(categories); // iterate through all alarms for (icalcomponent *alarm = icalcomponent_get_first_component(parent,ICAL_VALARM_COMPONENT); alarm; alarm = icalcomponent_get_next_component(parent,ICAL_VALARM_COMPONENT)) { readAlarm(alarm,incidence); } } void ICalFormatImpl::readIncidenceBase(icalcomponent *parent,IncidenceBase *incidenceBase) { icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); while (p) { icalproperty_kind kind = icalproperty_isa(p); switch (kind) { case ICAL_UID_PROPERTY: // unique id incidenceBase->setUid(QString::fromUtf8(icalproperty_get_uid(p))); break; case ICAL_ORGANIZER_PROPERTY: // organizer incidenceBase->setOrganizer(QString::fromUtf8(icalproperty_get_organizer(p))); break; case ICAL_ATTENDEE_PROPERTY: // attendee incidenceBase->addAttendee(readAttendee(p)); break; default: break; } p = icalcomponent_get_next_property(parent,ICAL_ANY_PROPERTY); } // custom properties readCustomProperties(parent, incidenceBase); } void ICalFormatImpl::readCustomProperties(icalcomponent *parent,CustomProperties *properties) { QMap<QCString, QString> customProperties; icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY); while (p) { QString value = QString::fromUtf8(icalproperty_get_x(p)); customProperties[icalproperty_get_x_name(p)] = value; //qDebug("ICalFormatImpl::readCustomProperties %s %s",value.latin1(), icalproperty_get_x_name(p) ); p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY); } properties->setCustomProperties(customProperties); } void ICalFormatImpl::readRecurrenceRule(struct icalrecurrencetype rrule,Incidence *incidence) { // kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl; Recurrence *recur = incidence->recurrence(); recur->setCompatVersion(mCalendarVersion); recur->unsetRecurs(); struct icalrecurrencetype r = rrule; dumpIcalRecurrence(r); readRecurrence( r, recur, incidence); } void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur, Incidence *incidence) { int wkst; int index = 0; short day = 0; QBitArray qba(7); int frequ = r.freq; int interv = r.interval; // preprocessing for odd recurrence definitions if ( r.freq == ICAL_MONTHLY_RECURRENCE ) { if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { interv = 12; } } if ( r.freq == ICAL_YEARLY_RECURRENCE ) { if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX && r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) { frequ = ICAL_MONTHLY_RECURRENCE; interv = 12* r.interval; } } switch (frequ) { case ICAL_MINUTELY_RECURRENCE: if (!icaltime_is_null_time(r.until)) { recur->setMinutely(interv,readICalDateTime(r.until)); } else { if (r.count == 0) recur->setMinutely(interv,-1); else recur->setMinutely(interv,r.count); } break; case ICAL_HOURLY_RECURRENCE: if (!icaltime_is_null_time(r.until)) { recur->setHourly(interv,readICalDateTime(r.until)); } else { if (r.count == 0) recur->setHourly(interv,-1); else recur->setHourly(interv,r.count); } break; case ICAL_DAILY_RECURRENCE: if (!icaltime_is_null_time(r.until)) { recur->setDaily(interv,readICalDate(r.until)); } else { if (r.count == 0) recur->setDaily(interv,-1); else recur->setDaily(interv,r.count); } break; case ICAL_WEEKLY_RECURRENCE: // kdDebug(5800) << "WEEKLY_RECURRENCE" << endl; wkst = (r.week_start + 5)%7 + 1; if (!icaltime_is_null_time(r.until)) { recur->setWeekly(interv,qba,readICalDate(r.until),wkst); } else { if (r.count == 0) recur->setWeekly(interv,qba,-1,wkst); else recur->setWeekly(interv,qba,r.count,wkst); } if ( r.by_day[0] == ICAL_RECURRENCE_ARRAY_MAX) { int wday = incidence->dtStart().date().dayOfWeek ()-1; //qDebug("weekly error found "); qba.setBit(wday); } else { while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { // kdDebug(5800) << " " << day << endl; qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 } } break; case ICAL_MONTHLY_RECURRENCE: if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { if (!icaltime_is_null_time(r.until)) { recur->setMonthly(Recurrence::rMonthlyPos,interv, readICalDate(r.until)); } else { if (r.count == 0) recur->setMonthly(Recurrence::rMonthlyPos,interv,-1); else recur->setMonthly(Recurrence::rMonthlyPos,interv,r.count); } bool useSetPos = false; short pos = 0; while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { // kdDebug(5800) << "----a " << index << ": " << day << endl; pos = icalrecurrencetype_day_position(day); if (pos) { day = icalrecurrencetype_day_day_of_week(day); QBitArray ba(7); // don't wipe qba ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 recur->addMonthlyPos(pos,ba); } else { qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 useSetPos = true; } } if (useSetPos) { if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { recur->addMonthlyPos(r.by_set_pos[0],qba); } } } else if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { if (!icaltime_is_null_time(r.until)) { recur->setMonthly(Recurrence::rMonthlyDay,interv, readICalDate(r.until)); } else { if (r.count == 0) recur->setMonthly(Recurrence::rMonthlyDay,interv,-1); else recur->setMonthly(Recurrence::rMonthlyDay,interv,r.count); } while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { // kdDebug(5800) << "----b " << day << endl; recur->addMonthlyDay(day); } } break; case ICAL_YEARLY_RECURRENCE: if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { //qDebug(" YEARLY DAY OF YEAR"); if (!icaltime_is_null_time(r.until)) { recur->setYearly(Recurrence::rYearlyDay,interv, readICalDate(r.until)); } else { if (r.count == 0) recur->setYearly(Recurrence::rYearlyDay,interv,-1); else recur->setYearly(Recurrence::rYearlyDay,interv,r.count); } while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { recur->addYearlyNum(day); } } else if ( true /*r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX*/) { if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { qDebug("YEARLY POS NOT SUPPORTED BY GUI"); if (!icaltime_is_null_time(r.until)) { recur->setYearly(Recurrence::rYearlyPos,interv, readICalDate(r.until)); } else { if (r.count == 0) recur->setYearly(Recurrence::rYearlyPos,interv,-1); else recur->setYearly(Recurrence::rYearlyPos,interv,r.count); } bool useSetPos = false; short pos = 0; while((day = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { // kdDebug(5800) << "----a " << index << ": " << day << endl; pos = icalrecurrencetype_day_position(day); if (pos) { day = icalrecurrencetype_day_day_of_week(day); QBitArray ba(7); // don't wipe qba ba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 recur->addYearlyMonthPos(pos,ba); } else { qba.setBit((day+5)%7); // convert from Sunday=1 to Monday=0 useSetPos = true; } } if (useSetPos) { if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { recur->addYearlyMonthPos(r.by_set_pos[0],qba); } } } else { //qDebug("YEARLY MONTH "); if (!icaltime_is_null_time(r.until)) { recur->setYearly(Recurrence::rYearlyMonth,interv, readICalDate(r.until)); } else { if (r.count == 0) recur->setYearly(Recurrence::rYearlyMonth,interv,-1); else recur->setYearly(Recurrence::rYearlyMonth,interv,r.count); } if ( r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX ) { index = 0; while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { recur->addYearlyNum(day); } } else { recur->addYearlyNum(incidence->dtStart().date().month()); } } } break; default: ; break; } } void ICalFormatImpl::readAlarm(icalcomponent *alarm,Incidence *incidence) { //kdDebug(5800) << "Read alarm for " << incidence->summary() << endl; Alarm* ialarm = incidence->newAlarm(); ialarm->setRepeatCount(0); ialarm->setEnabled(true); // Determine the alarm's action type icalproperty *p = icalcomponent_get_first_property(alarm,ICAL_ACTION_PROPERTY); if ( !p ) { return; } icalproperty_action action = icalproperty_get_action(p); Alarm::Type type = Alarm::Display; switch ( action ) { case ICAL_ACTION_DISPLAY: type = Alarm::Display; break; case ICAL_ACTION_AUDIO: type = Alarm::Audio; break; case ICAL_ACTION_PROCEDURE: type = Alarm::Procedure; break; case ICAL_ACTION_EMAIL: type = Alarm::Email; break; default: ; return; } ialarm->setType(type); p = icalcomponent_get_first_property(alarm,ICAL_ANY_PROPERTY); while (p) { icalproperty_kind kind = icalproperty_isa(p); switch (kind) { case ICAL_TRIGGER_PROPERTY: { icaltriggertype trigger = icalproperty_get_trigger(p); if (icaltime_is_null_time(trigger.time)) { if (icaldurationtype_is_null_duration(trigger.duration)) { kdDebug(5800) << "ICalFormatImpl::readAlarm(): Trigger has no time and no duration." << endl; } else { Duration duration = icaldurationtype_as_int( trigger.duration ); icalparameter *param = icalproperty_get_first_parameter(p,ICAL_RELATED_PARAMETER); if (param && icalparameter_get_related(param) == ICAL_RELATED_END) ialarm->setEndOffset(duration); else ialarm->setStartOffset(duration); } } else { ialarm->setTime(readICalDateTime(trigger.time)); } break; } case ICAL_DURATION_PROPERTY: { icaldurationtype duration = icalproperty_get_duration(p); ialarm->setSnoozeTime(icaldurationtype_as_int(duration)/60); break; } case ICAL_REPEAT_PROPERTY: ialarm->setRepeatCount(icalproperty_get_repeat(p)); break; // Only in DISPLAY and EMAIL and PROCEDURE alarms case ICAL_DESCRIPTION_PROPERTY: { QString description = QString::fromUtf8(icalproperty_get_description(p)); switch ( action ) { case ICAL_ACTION_DISPLAY: ialarm->setText( description ); break; case ICAL_ACTION_PROCEDURE: ialarm->setProgramArguments( description ); break; case ICAL_ACTION_EMAIL: ialarm->setMailText( description ); break; default: break; } break; } // Only in EMAIL alarm case ICAL_SUMMARY_PROPERTY: ialarm->setMailSubject(QString::fromUtf8(icalproperty_get_summary(p))); break; // Only in EMAIL alarm case ICAL_ATTENDEE_PROPERTY: { QString email = QString::fromUtf8(icalproperty_get_attendee(p)); QString name; icalparameter *param = icalproperty_get_first_parameter(p,ICAL_CN_PARAMETER); if (param) { name = QString::fromUtf8(icalparameter_get_cn(param)); } ialarm->addMailAddress(Person(name, email)); break; } // Only in AUDIO and EMAIL and PROCEDURE alarms case ICAL_ATTACH_PROPERTY: { icalattach *attach = icalproperty_get_attach(p); QString url = QFile::decodeName(icalattach_get_url(attach)); switch ( action ) { case ICAL_ACTION_AUDIO: ialarm->setAudioFile( url ); break; case ICAL_ACTION_PROCEDURE: ialarm->setProgramFile( url ); break; case ICAL_ACTION_EMAIL: ialarm->addMailAttachment( url ); break; default: break; } break; } default: break; } p = icalcomponent_get_next_property(alarm,ICAL_ANY_PROPERTY); } // custom properties readCustomProperties(alarm, ialarm); // TODO: check for consistency of alarm properties } icaltimetype ICalFormatImpl::writeICalDate(const QDate &date) { icaltimetype t; t.year = date.year(); t.month = date.month(); t.day = date.day(); t.hour = 0; t.minute = 0; t.second = 0; t.is_date = 1; t.is_utc = 0; t.zone = 0; return t; } icaltimetype ICalFormatImpl::writeICalDateTime(const QDateTime &dt ) { icaltimetype t; t.is_date = 0; t.zone = 0; QDateTime datetime; if ( mParent->utc() ) { int offset = KGlobal::locale()->localTimeOffset( dt ); datetime = dt.addSecs ( -offset*60); t.is_utc = 1; } else { datetime = dt; t.is_utc = 0; } t.year = datetime.date().year(); t.month = datetime.date().month(); t.day = datetime.date().day(); t.hour = datetime.time().hour(); t.minute = datetime.time().minute(); t.second = datetime.time().second(); //qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() ); // if ( mParent->utc() ) { // datetime = KGlobal::locale()->localTime( dt ); // qDebug("*** time %s localtime %s ",dt .toString().latin1() ,datetime .toString().latin1() ); // if (mParent->timeZoneId().isEmpty()) // t = icaltime_as_utc(t, 0); // else // t = icaltime_as_utc(t,mParent->timeZoneId().local8Bit()); // } return t; } QDateTime ICalFormatImpl::readICalDateTime(icaltimetype t) { QDateTime dt (QDate(t.year,t.month,t.day), QTime(t.hour,t.minute,t.second) ); if (t.is_utc) { int offset = KGlobal::locale()->localTimeOffset( dt ); dt = dt.addSecs ( offset*60); } return dt; } QDate ICalFormatImpl::readICalDate(icaltimetype t) { return QDate(t.year,t.month,t.day); } icaldurationtype ICalFormatImpl::writeICalDuration(int seconds) { icaldurationtype d; d.is_neg = (seconds<0)?1:0; if (seconds<0) seconds = -seconds; d.weeks = seconds / gSecondsPerWeek; seconds %= gSecondsPerWeek; d.days = seconds / gSecondsPerDay; seconds %= gSecondsPerDay; d.hours = seconds / gSecondsPerHour; seconds %= gSecondsPerHour; d.minutes = seconds / gSecondsPerMinute; seconds %= gSecondsPerMinute; d.seconds = seconds; return d; } int ICalFormatImpl::readICalDuration(icaldurationtype d) { int result = 0; result += d.weeks * gSecondsPerWeek; result += d.days * gSecondsPerDay; result += d.hours * gSecondsPerHour; result += d.minutes * gSecondsPerMinute; result += d.seconds; if (d.is_neg) result *= -1; return result; } icalcomponent *ICalFormatImpl::createCalendarComponent(Calendar *cal) { icalcomponent *calendar; // Root component calendar = icalcomponent_new(ICAL_VCALENDAR_COMPONENT); icalproperty *p; // Product Identifier p = icalproperty_new_prodid(CalFormat::productId().utf8()); icalcomponent_add_property(calendar,p); // TODO: Add time zone // iCalendar version (2.0) p = icalproperty_new_version(const_cast<char *>(_ICAL_VERSION)); icalcomponent_add_property(calendar,p); // Custom properties if( cal != 0 ) writeCustomProperties(calendar, cal); return calendar; } // take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc. // and break it down from its tree-like format into the dictionary format // that is used internally in the ICalFormatImpl. bool ICalFormatImpl::populate( Calendar *cal, icalcomponent *calendar) { // this function will populate the caldict dictionary and other event // lists. It turns vevents into Events and then inserts them. if (!calendar) return false; // TODO: check for METHOD #if 0 if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) { char *methodType = 0; methodType = fakeCString(vObjectUStringZValue(curVO)); if (mEnableDialogs) KMessageBox::information(mTopWidget, i18n("This calendar is an iTIP transaction of type \"%1\".") .arg(methodType), i18n("%1: iTIP Transaction").arg(CalFormat::application())); delete methodType; } #endif icalproperty *p; p = icalcomponent_get_first_property(calendar,ICAL_PRODID_PROPERTY); if (!p) { // TODO: does no PRODID really matter? // mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); // return false; mLoadedProductId = ""; mCalendarVersion = 0; } else { mLoadedProductId = QString::fromUtf8(icalproperty_get_prodid(p)); mCalendarVersion = CalFormat::calendarVersion(mLoadedProductId); delete mCompat; mCompat = CompatFactory::createCompat( mLoadedProductId ); } // TODO: check for unknown PRODID #if 0 if (!mCalendarVersion && CalFormat::productId() != mLoadedProductId) { // warn the user that we might have trouble reading non-known calendar. if (mEnableDialogs) KMessageBox::information(mTopWidget, i18n("This vCalendar file was not created by KOrganizer " "or any other product we support. Loading anyway..."), i18n("%1: Unknown vCalendar Vendor").arg(CalFormat::application())); } #endif p = icalcomponent_get_first_property(calendar,ICAL_VERSION_PROPERTY); if (!p) { mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); return false; } else { const char *version = icalproperty_get_version(p); if (strcmp(version,"1.0") == 0) { mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1, i18n("Expected iCalendar format"))); return false; } else if (strcmp(version,"2.0") != 0) { mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); return false; } } // TODO: check for calendar format version #if 0 // warn the user we might have trouble reading this unknown version. if ((curVO = isAPropertyOf(vcal, VCVersionProp)) != 0) { char *s = fakeCString(vObjectUStringZValue(curVO)); if (strcmp(_VCAL_VERSION, s) != 0) if (mEnableDialogs) KMessageBox::sorry(mTopWidget, i18n("This vCalendar file has version %1.\n" "We only support %2.") .arg(s).arg(_VCAL_VERSION), i18n("%1: Unknown vCalendar Version").arg(CalFormat::application())); deleteStr(s); } #endif // custom properties readCustomProperties(calendar, cal); // TODO: set time zone #if 0 // set the time zone if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) { char *s = fakeCString(vObjectUStringZValue(curVO)); cal->setTimeZone(s); deleteStr(s); } #endif // Store all events with a relatedTo property in a list for post-processing mEventsRelate.clear(); mTodosRelate.clear(); // TODO: make sure that only actually added ecvens go to this lists. icalcomponent *c; // Iterate through all todos c = icalcomponent_get_first_component(calendar,ICAL_VTODO_COMPONENT); while (c) { // kdDebug(5800) << "----Todo found" << endl; Todo *todo = readTodo(c); if (!cal->todo(todo->uid())) cal->addTodo(todo); c = icalcomponent_get_next_component(calendar,ICAL_VTODO_COMPONENT); } // Iterate through all events c = icalcomponent_get_first_component(calendar,ICAL_VEVENT_COMPONENT); while (c) { // kdDebug(5800) << "----Event found" << endl; Event *event = readEvent(c); if (!cal->event(event->uid())) cal->addEvent(event); c = icalcomponent_get_next_component(calendar,ICAL_VEVENT_COMPONENT); } // Iterate through all journals c = icalcomponent_get_first_component(calendar,ICAL_VJOURNAL_COMPONENT); while (c) { // kdDebug(5800) << "----Journal found" << endl; Journal *journal = readJournal(c); if (!cal->journal(journal->uid())) cal->addJournal(journal); c = icalcomponent_get_next_component(calendar,ICAL_VJOURNAL_COMPONENT); } #if 0 initPropIterator(&i, vcal); // go through all the vobjects in the vcal while (moreIteration(&i)) { curVO = nextVObject(&i); /************************************************************************/ // now, check to see that the object is an event or todo. if (strcmp(vObjectName(curVO), VCEventProp) == 0) { if ((curVOProp = isAPropertyOf(curVO, KPilotStatusProp)) != 0) { char *s; s = fakeCString(vObjectUStringZValue(curVOProp)); // check to see if event was deleted by the kpilot conduit if (atoi(s) == Event::SYNCDEL) { deleteStr(s); goto SKIP; } deleteStr(s); } // this code checks to see if we are trying to read in an event // that we already find to be in the calendar. If we find this // to be the case, we skip the event. if ((curVOProp = isAPropertyOf(curVO, VCUniqueStringProp)) != 0) { char *s = fakeCString(vObjectUStringZValue(curVOProp)); QString tmpStr(s); deleteStr(s); if (cal->event(tmpStr)) { goto SKIP; } if (cal->todo(tmpStr)) { goto SKIP; } } if ((!(curVOProp = isAPropertyOf(curVO, VCDTstartProp))) && (!(curVOProp = isAPropertyOf(curVO, VCDTendProp)))) { kdDebug(5800) << "found a VEvent with no DTSTART and no DTEND! Skipping..." << endl; goto SKIP; } anEvent = VEventToEvent(curVO); // we now use addEvent instead of insertEvent so that the // signal/slot get connected. if (anEvent) cal->addEvent(anEvent); else { // some sort of error must have occurred while in translation. goto SKIP; } } else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) { anEvent = VTodoToEvent(curVO); cal->addTodo(anEvent); } else if ((strcmp(vObjectName(curVO), VCVersionProp) == 0) || (strcmp(vObjectName(curVO), VCProdIdProp) == 0) || (strcmp(vObjectName(curVO), VCTimeZoneProp) == 0)) { // do nothing, we know these properties and we want to skip them. // we have either already processed them or are ignoring them. ; } else { ; } SKIP: ; } // while #endif // Post-Process list of events with relations, put Event objects in relation Event *ev; for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) { Incidence * inc = cal->event(ev->relatedToUid()); if ( inc ) ev->setRelatedTo( inc ); } Todo *todo; for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) { Incidence * inc = cal->todo(todo->relatedToUid()); if ( inc ) todo->setRelatedTo( inc ); } return true; } QString ICalFormatImpl::extractErrorProperty(icalcomponent *c) { // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " // << icalcomponent_as_ical_string(c) << endl; QString errorMessage; icalproperty *error; error = icalcomponent_get_first_property(c,ICAL_XLICERROR_PROPERTY); while(error) { errorMessage += icalproperty_get_xlicerror(error); errorMessage += "\n"; error = icalcomponent_get_next_property(c,ICAL_XLICERROR_PROPERTY); } // kdDebug(5800) << "ICalFormatImpl:extractErrorProperty: " << errorMessage << endl; return errorMessage; } void ICalFormatImpl::dumpIcalRecurrence(icalrecurrencetype r) { int i; if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Day: "; while((i = r.by_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Month Day: "; while((i = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Year Day: "; while((i = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Month: "; while((i = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } if (r.by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX) { int index = 0; QString out = " By Set Pos: "; while((i = r.by_set_pos[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { out.append(QString::number(i) + " "); } } } icalcomponent *ICalFormatImpl::createScheduleComponent(IncidenceBase *incidence, Scheduler::Method method) { icalcomponent *message = createCalendarComponent(); icalproperty_method icalmethod = ICAL_METHOD_NONE; switch (method) { case Scheduler::Publish: icalmethod = ICAL_METHOD_PUBLISH; break; case Scheduler::Request: icalmethod = ICAL_METHOD_REQUEST; break; case Scheduler::Refresh: icalmethod = ICAL_METHOD_REFRESH; break; case Scheduler::Cancel: icalmethod = ICAL_METHOD_CANCEL; break; case Scheduler::Add: icalmethod = ICAL_METHOD_ADD; break; case Scheduler::Reply: icalmethod = ICAL_METHOD_REPLY; break; case Scheduler::Counter: icalmethod = ICAL_METHOD_COUNTER; break; case Scheduler::Declinecounter: icalmethod = ICAL_METHOD_DECLINECOUNTER; break; default: return message; } icalcomponent_add_property(message,icalproperty_new_method(icalmethod)); // TODO: check, if dynamic cast is required - if(incidence->type() == "Todo") { + if(incidence->typeID() == todoID ) { Todo *todo = static_cast<Todo *>(incidence); icalcomponent_add_component(message,writeTodo(todo)); } - if(incidence->type() == "Event") { + if(incidence->typeID() == eventID ) { Event *event = static_cast<Event *>(incidence); icalcomponent_add_component(message,writeEvent(event)); } - if(incidence->type() == "FreeBusy") { + if(incidence->typeID() == freebusyID) { FreeBusy *freebusy = static_cast<FreeBusy *>(incidence); icalcomponent_add_component(message,writeFreeBusy(freebusy, method)); } return message; } diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp index 762103f..f446197 100644 --- a/libkcal/incidence.cpp +++ b/libkcal/incidence.cpp @@ -1,744 +1,744 @@ /* This file is part of libkcal. Copyright (c) 2001 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 <kglobal.h> #include <klocale.h> #include <kdebug.h> #include "calformat.h" #include "incidence.h" #include "todo.h" using namespace KCal; Incidence::Incidence() : IncidenceBase(), mRelatedTo(0), mSecrecy(SecrecyPublic), mPriority(3) { mRecurrence = new Recurrence(this); mCancelled = false; recreate(); mHasStartDate = true; mAlarms.setAutoDelete(true); mAttachments.setAutoDelete(true); mHasRecurrenceID = false; mHoliday = false; mBirthday = false; mAnniversary = false; } Incidence::Incidence( const Incidence &i ) : IncidenceBase( i ) { // TODO: reenable attributes currently commented out. mRevision = i.mRevision; mCreated = i.mCreated; mDescription = i.mDescription; mSummary = i.mSummary; mCategories = i.mCategories; // Incidence *mRelatedTo; Incidence *mRelatedTo; mRelatedTo = 0; mRelatedToUid = i.mRelatedToUid; // QPtrList<Incidence> mRelations; QPtrList<Incidence> mRelations; mExDates = i.mExDates; mAttachments = i.mAttachments; mResources = i.mResources; mSecrecy = i.mSecrecy; mPriority = i.mPriority; mLocation = i.mLocation; mCancelled = i.mCancelled; mHasStartDate = i.mHasStartDate; QPtrListIterator<Alarm> it( i.mAlarms ); const Alarm *a; while( (a = it.current()) ) { Alarm *b = new Alarm( *a ); b->setParent( this ); mAlarms.append( b ); ++it; } mAlarms.setAutoDelete(true); mHasRecurrenceID = i.mHasRecurrenceID; mRecurrenceID = i.mRecurrenceID; mRecurrence = new Recurrence( *(i.mRecurrence), this ); mHoliday = i.mHoliday ; mBirthday = i.mBirthday; mAnniversary = i.mAnniversary; } Incidence::~Incidence() { Incidence *ev; QPtrList<Incidence> Relations = relations(); for (ev=Relations.first();ev;ev=Relations.next()) { if (ev->relatedTo() == this) ev->setRelatedTo(0); } if (relatedTo()) relatedTo()->removeRelation(this); delete mRecurrence; } bool Incidence::isHoliday() const { return mHoliday; } bool Incidence::isBirthday() const { return mBirthday ; } bool Incidence::isAnniversary() const { return mAnniversary ; } bool Incidence::hasRecurrenceID() const { return mHasRecurrenceID; } void Incidence::setHasRecurrenceID( bool b ) { mHasRecurrenceID = b; } void Incidence::setRecurrenceID(QDateTime d) { mRecurrenceID = d; mHasRecurrenceID = true; updated(); } QDateTime Incidence::recurrenceID () const { return mRecurrenceID; } bool Incidence::cancelled() const { return mCancelled; } void Incidence::setCancelled( bool b ) { mCancelled = b; updated(); } bool Incidence::hasStartDate() const { return mHasStartDate; } void Incidence::setHasStartDate(bool f) { if (mReadOnly) return; mHasStartDate = f; updated(); } // A string comparison that considers that null and empty are the same static bool stringCompare( const QString& s1, const QString& s2 ) { if ( s1.isEmpty() && s2.isEmpty() ) return true; return s1 == s2; } bool KCal::operator==( const Incidence& i1, const Incidence& i2 ) { if( i1.alarms().count() != i2.alarms().count() ) { return false; // no need to check further } if ( i1.alarms().count() > 0 ) { if ( !( *(i1.alarms().first()) == *(i2.alarms().first())) ) { qDebug("alarm not equal "); return false; } } #if 0 QPtrListIterator<Alarm> a1( i1.alarms() ); QPtrListIterator<Alarm> a2( i2.alarms() ); for( ; a1.current() && a2.current(); ++a1, ++a2 ) { if( *a1.current() == *a2.current() ) { continue; } else { return false; } } #endif if ( i1.hasRecurrenceID() == i2.hasRecurrenceID() ) { if ( i1.hasRecurrenceID() ) { if ( i1.recurrenceID() != i2.recurrenceID() ) return false; } } else { return false; } if ( ! operator==( (const IncidenceBase&)i1, (const IncidenceBase&)i2 ) ) return false; if ( i1.hasStartDate() == i2.hasStartDate() ) { if ( i1.hasStartDate() ) { if ( i1.dtStart() != i2.dtStart() ) return false; } } else { return false; } if (!( *i1.recurrence() == *i2.recurrence()) ) { qDebug("recurrence is NOT equal "); return false; } return // i1.created() == i2.created() && stringCompare( i1.description(), i2.description() ) && stringCompare( i1.summary(), i2.summary() ) && i1.categories() == i2.categories() && // no need to compare mRelatedTo stringCompare( i1.relatedToUid(), i2.relatedToUid() ) && // i1.relations() == i2.relations() && i1.exDates() == i2.exDates() && i1.attachments() == i2.attachments() && i1.resources() == i2.resources() && i1.secrecy() == i2.secrecy() && i1.priority() == i2.priority() && i1.cancelled() == i2.cancelled() && stringCompare( i1.location(), i2.location() ); } Incidence* Incidence::recreateCloneException( QDate d ) { Incidence* newInc = clone(); newInc->recreate(); if ( doesRecur() ) { addExDate( d ); newInc->recurrence()->unsetRecurs(); - if ( type() == "Event") { + if ( typeID() == eventID ) { int len = dtStart().secsTo( ((Event*)this)->dtEnd()); QTime tim = dtStart().time(); newInc->setDtStart( QDateTime(d, tim) ); ((Event*)newInc)->setDtEnd( newInc->dtStart().addSecs( len ) ); } else { int len = dtStart().secsTo( ((Todo*)this)->dtDue()); QTime tim = ((Todo*)this)->dtDue().time(); ((Todo*)newInc)->setDtDue( QDateTime(d, tim) ); ((Todo*)newInc)->setDtStart( ((Todo*)newInc)->dtDue().addSecs( -len ) ); ((Todo*)this)->setRecurDates(); } newInc->setExDates( DateList () ); } return newInc; } void Incidence::recreate() { setCreated(QDateTime::currentDateTime()); setUid(CalFormat::createUniqueId()); setRevision(0); setIDStr( ":" ); setLastModified(QDateTime::currentDateTime()); } void Incidence::cloneRelations( Incidence * newInc ) { // newInc is already a clone of this incidence Incidence * inc; Incidence * cloneInc; QPtrList<Incidence> Relations = relations(); for (inc=Relations.first();inc;inc=Relations.next()) { cloneInc = inc->clone(); cloneInc->recreate(); cloneInc->setRelatedTo( newInc ); inc->cloneRelations( cloneInc ); } } void Incidence::setReadOnly( bool readOnly ) { IncidenceBase::setReadOnly( readOnly ); recurrence()->setRecurReadOnly( readOnly); } void Incidence::setCreated(QDateTime created) { if (mReadOnly) return; mCreated = getEvenTime(created); } QDateTime Incidence::created() const { return mCreated; } void Incidence::setRevision(int rev) { if (mReadOnly) return; mRevision = rev; updated(); } int Incidence::revision() const { return mRevision; } void Incidence::setDtStart(const QDateTime &dtStart) { QDateTime dt = getEvenTime(dtStart); recurrence()->setRecurStart( dt); IncidenceBase::setDtStart( dt ); } void Incidence::setDescription(const QString &description) { if (mReadOnly) return; mDescription = description; updated(); } QString Incidence::description() const { return mDescription; } void Incidence::setSummary(const QString &summary) { if (mReadOnly) return; mSummary = summary; updated(); } QString Incidence::summary() const { return mSummary; } void Incidence::checkCategories() { mHoliday = mCategories.contains("Holiday") || mCategories.contains(i18n("Holiday")); mBirthday = mCategories.contains("Birthday") || mCategories.contains(i18n("Birthday")); mAnniversary = mCategories.contains("Anniversary") || mCategories.contains(i18n("Anniversary")); } void Incidence::addCategories(const QStringList &categories, bool addToRelations ) //addToRelations = false { if (mReadOnly) return; int i; for( i = 0; i < categories.count(); ++i ) { if ( !mCategories.contains (categories[i])) mCategories.append( categories[i] ); } checkCategories(); updated(); if ( addToRelations ) { Incidence * inc; QPtrList<Incidence> Relations = relations(); for (inc=Relations.first();inc;inc=Relations.next()) { inc->addCategories( categories, true ); } } } void Incidence::setCategories(const QStringList &categories, bool setForRelations ) //setForRelations = false { if (mReadOnly) return; mCategories = categories; checkCategories(); updated(); if ( setForRelations ) { Incidence * inc; QPtrList<Incidence> Relations = relations(); for (inc=Relations.first();inc;inc=Relations.next()) { inc->setCategories( categories, true ); } } } // TODO: remove setCategories(QString) function void Incidence::setCategories(const QString &catStr) { if (mReadOnly) return; mCategories.clear(); if (catStr.isEmpty()) return; mCategories = QStringList::split(",",catStr); QStringList::Iterator it; for(it = mCategories.begin();it != mCategories.end(); ++it) { *it = (*it).stripWhiteSpace(); } checkCategories(); updated(); } QStringList Incidence::categories() const { return mCategories; } QString Incidence::categoriesStr() { return mCategories.join(","); } QString Incidence::categoriesStrWithSpace() { return mCategories.join(", "); } void Incidence::setRelatedToUid(const QString &relatedToUid) { if (mReadOnly) return; mRelatedToUid = relatedToUid; } QString Incidence::relatedToUid() const { return mRelatedToUid; } void Incidence::setRelatedTo(Incidence *relatedTo) { //qDebug("Incidence::setRelatedTo %d ", relatedTo); //qDebug("setRelatedTo(Incidence *relatedTo) %s %s", summary().latin1(), relatedTo->summary().latin1() ); if (mReadOnly || mRelatedTo == relatedTo) return; if(mRelatedTo) { // updated(); mRelatedTo->removeRelation(this); } mRelatedTo = relatedTo; if (mRelatedTo) { mRelatedTo->addRelation(this); mRelatedToUid = mRelatedTo->uid(); } else { mRelatedToUid = ""; } } Incidence *Incidence::relatedTo() const { return mRelatedTo; } QPtrList<Incidence> Incidence::relations() const { return mRelations; } void Incidence::addRelation(Incidence *event) { if( mRelations.findRef( event ) == -1 ) { mRelations.append(event); //updated(); } } void Incidence::removeRelation(Incidence *event) { mRelations.removeRef(event); // if (event->getRelatedTo() == this) event->setRelatedTo(0); } bool Incidence::recursOn(const QDate &qd) const { if (recurrence()->recursOnPure(qd) && !isException(qd)) return true; else return false; } void Incidence::setExDates(const DateList &exDates) { if (mReadOnly) return; mExDates = exDates; recurrence()->setRecurExDatesCount(mExDates.count()); updated(); } void Incidence::addExDate(const QDate &date) { if (mReadOnly) return; mExDates.append(date); recurrence()->setRecurExDatesCount(mExDates.count()); updated(); } DateList Incidence::exDates() const { return mExDates; } bool Incidence::isException(const QDate &date) const { DateList::ConstIterator it; for( it = mExDates.begin(); it != mExDates.end(); ++it ) { if ( (*it) == date ) { return true; } } return false; } void Incidence::addAttachment(Attachment *attachment) { if (mReadOnly || !attachment) return; mAttachments.append(attachment); updated(); } void Incidence::deleteAttachment(Attachment *attachment) { mAttachments.removeRef(attachment); } void Incidence::deleteAttachments(const QString& mime) { Attachment *at = mAttachments.first(); while (at) { if (at->mimeType() == mime) mAttachments.remove(); else at = mAttachments.next(); } } QPtrList<Attachment> Incidence::attachments() const { return mAttachments; } QPtrList<Attachment> Incidence::attachments(const QString& mime) const { QPtrList<Attachment> attachments; QPtrListIterator<Attachment> it( mAttachments ); Attachment *at; while ( (at = it.current()) ) { if (at->mimeType() == mime) attachments.append(at); ++it; } return attachments; } void Incidence::setResources(const QStringList &resources) { if (mReadOnly) return; mResources = resources; updated(); } QStringList Incidence::resources() const { return mResources; } void Incidence::setPriority(int priority) { if (mReadOnly) return; mPriority = priority; updated(); } int Incidence::priority() const { return mPriority; } void Incidence::setSecrecy(int sec) { if (mReadOnly) return; mSecrecy = sec; updated(); } int Incidence::secrecy() const { return mSecrecy; } QString Incidence::secrecyStr() const { return secrecyName(mSecrecy); } QString Incidence::secrecyName(int secrecy) { switch (secrecy) { case SecrecyPublic: return i18n("Public"); break; case SecrecyPrivate: return i18n("Private"); break; case SecrecyConfidential: return i18n("Confidential"); break; default: return i18n("Undefined"); break; } } QStringList Incidence::secrecyList() { QStringList list; list << secrecyName(SecrecyPublic); list << secrecyName(SecrecyPrivate); list << secrecyName(SecrecyConfidential); return list; } QPtrList<Alarm> Incidence::alarms() const { return mAlarms; } Alarm* Incidence::newAlarm() { Alarm* alarm = new Alarm(this); mAlarms.append(alarm); // updated(); return alarm; } void Incidence::addAlarm(Alarm *alarm) { mAlarms.append(alarm); updated(); } void Incidence::removeAlarm(Alarm *alarm) { mAlarms.removeRef(alarm); updated(); } void Incidence::clearAlarms() { mAlarms.clear(); updated(); } bool Incidence::isAlarmEnabled() const { Alarm* alarm; for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { if (alarm->enabled()) return true; } return false; } Recurrence *Incidence::recurrence() const { return mRecurrence; } void Incidence::setRecurrence( Recurrence * r) { delete mRecurrence; mRecurrence = r; } void Incidence::setLocation(const QString &location) { if (mReadOnly) return; mLocation = location; updated(); } QString Incidence::location() const { return mLocation; } ushort Incidence::doesRecur() const { if ( mRecurrence ) return mRecurrence->doesRecur(); else return Recurrence::rNone; } QDateTime Incidence::getNextOccurence( const QDateTime& dt, bool* ok ) const { QDateTime incidenceStart = dt; *ok = false; if ( doesRecur() ) { bool last; recurrence()->getPreviousDateTime( incidenceStart , &last ); int count = 0; if ( !last ) { while ( !last ) { ++count; incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last ); if ( recursOn( incidenceStart.date() ) ) { last = true; // exit while llop } else { if ( last ) { // no alarm on last recurrence return QDateTime (); } int year = incidenceStart.date().year(); // workaround for bug in recurrence if ( count == 100 || year < 1000 || year > 5000 ) { return QDateTime (); } incidenceStart = incidenceStart.addSecs( 1 ); } } } else { return QDateTime (); } } else { if ( hasStartDate () ) { incidenceStart = dtStart(); } - if ( type() =="Todo" ) { + if ( typeID() == todoID ) { if ( ((Todo*)this)->hasDueDate() ) incidenceStart = ((Todo*)this)->dtDue(); } } if ( incidenceStart > dt ) *ok = true; return incidenceStart; } QDateTime Incidence::dtStart() const { if ( doesRecur() ) { - if ( type() == "Todo" ) { + if ( typeID() == todoID ) { ((Todo*)this)->checkSetCompletedFalse(); } } return mDtStart; } diff --git a/libkcal/incidencebase.h b/libkcal/incidencebase.h index 8624786..05209e0 100644 --- a/libkcal/incidencebase.h +++ b/libkcal/incidencebase.h @@ -1,172 +1,174 @@ /* This file is part of libkcal. Copyright (c) 2001 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. */ #ifndef KCAL_INCIDENCEBASE_H #define KCAL_INCIDENCEBASE_H // // Incidence - base class of calendaring components // #include <qdatetime.h> #include <qstringlist.h> #include <qvaluelist.h> #include <qptrlist.h> #include "customproperties.h" #include "attendee.h" namespace KCal { typedef QValueList<QDate> DateList; + enum IncTypeID { eventID,todoID,journalID,freebusyID }; /** This class provides the base class common to all calendar components. */ class IncidenceBase : public CustomProperties { public: class Observer { public: virtual void incidenceUpdated( IncidenceBase * ) = 0; }; IncidenceBase(); IncidenceBase(const IncidenceBase &); virtual ~IncidenceBase(); virtual QCString type() const = 0; + virtual IncTypeID typeID() const = 0; /** Set the unique id for the event */ void setUid(const QString &); /** Return the unique id for the event */ QString uid() const; /** Sets the time the incidence was last modified. */ void setLastModified(const QDateTime &lm); /** Return the time the incidence was last modified. */ QDateTime lastModified() const; /** sets the organizer for the event */ void setOrganizer(const QString &o); QString organizer() const; /** Set readonly status. */ virtual void setReadOnly( bool ); /** Return if the object is read-only. */ bool isReadOnly() const { return mReadOnly; } /** for setting the event's starting date/time with a QDateTime. */ virtual void setDtStart(const QDateTime &dtStart); /** returns an event's starting date/time as a QDateTime. */ virtual QDateTime dtStart() const; /** returns an event's starting time as a string formatted according to the users locale settings */ QString dtStartTimeStr() const; /** returns an event's starting date as a string formatted according to the users locale settings */ QString dtStartDateStr(bool shortfmt=true) const; /** returns an event's starting date and time as a string formatted according to the users locale settings */ QString dtStartStr(bool shortfmt=true) const; virtual void setDuration(int seconds); int duration() const; void setHasDuration(bool); bool hasDuration() const; /** Return true or false depending on whether the incidence "floats," * i.e. has a date but no time attached to it. */ bool doesFloat() const; /** Set whether the incidence floats, i.e. has a date but no time attached to it. */ void setFloats(bool f); /** Add Attendee to this incidence. IncidenceBase takes ownership of the Attendee object. */ bool addAttendee(Attendee *a, bool doupdate=true ); // void removeAttendee(Attendee *a); // void removeAttendee(const char *n); /** Remove all Attendees. */ void clearAttendees(); /** Return list of attendees. */ QPtrList<Attendee> attendees() const { return mAttendees; }; /** Return number of attendees. */ int attendeeCount() const { return mAttendees.count(); }; /** Return the Attendee with this email */ Attendee* attendeeByMail(const QString &); /** Return first Attendee with one of this emails */ Attendee* attendeeByMails(const QStringList &, const QString& email = QString::null); /** pilot syncronization states */ enum { SYNCNONE = 0, SYNCMOD = 1, SYNCDEL = 3 }; /** Set synchronisation satus. */ void setSyncStatus(int stat); /** Return synchronisation status. */ int syncStatus() const; /** Set Pilot Id. */ void setPilotId(int id); /** Return Pilot Id. */ int pilotId() const; void setTempSyncStat(int id); int tempSyncStat() const; void setIDStr( const QString & ); QString IDStr() const; void setID( const QString &, const QString & ); QString getID( const QString & ); void setCsum( const QString &, const QString & ); QString getCsum( const QString & ); void removeID(const QString &); void registerObserver( Observer * ); void unRegisterObserver( Observer * ); void updated(); protected: QDateTime mDtStart; bool mReadOnly; QDateTime getEvenTime( QDateTime ); private: // base components QString mOrganizer; QString mUid; QDateTime mLastModified; QPtrList<Attendee> mAttendees; bool mFloats; int mDuration; bool mHasDuration; QString mExternalId; int mTempSyncStat; // PILOT SYNCHRONIZATION STUFF int mPilotId; // unique id for pilot sync int mSyncStatus; // status (for sync) QPtrList<Observer> mObservers; }; bool operator==( const IncidenceBase&, const IncidenceBase& ); } #endif diff --git a/libkcal/journal.h b/libkcal/journal.h index 2c1d7ea..1cd0a22 100644 --- a/libkcal/journal.h +++ b/libkcal/journal.h @@ -1,50 +1,51 @@ /* This file is part of libkcal. Copyright (c) 2001 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. */ #ifndef JOURNAL_H #define JOURNAL_H // // Journal component, representing a VJOURNAL object // #include "incidence.h" namespace KCal { /** This class provides a Journal in the sense of RFC2445. */ class Journal : public Incidence { public: Journal(); ~Journal(); QCString type() const { return "Journal"; } + IncTypeID typeID() const { return journalID; } Incidence *clone(); QDateTime getNextAlarmDateTime( bool * ok, int * offset ,QDateTime start_dt ) const; private: bool accept(Visitor &v) { return v.visit(this); } }; bool operator==( const Journal&, const Journal& ); } #endif diff --git a/libkcal/kincidenceformatter.cpp b/libkcal/kincidenceformatter.cpp index 7d61b7f..d1ace4f 100644 --- a/libkcal/kincidenceformatter.cpp +++ b/libkcal/kincidenceformatter.cpp @@ -1,422 +1,422 @@ #include "kincidenceformatter.h" #include <kstaticdeleter.h> #include <kglobal.h> #include <klocale.h> #ifdef DEKTOP_VERSION #include <kabc/stdaddressbook.h> #define size count #endif KIncidenceFormatter* KIncidenceFormatter::mInstance = 0; static KStaticDeleter<KIncidenceFormatter> insd; QString KIncidenceFormatter::getFormattedText( Incidence * inc, bool details, bool created , bool modified ) { // #ifndef QT_NO_INPUTDIALOG // return QInputDialog::getItem( caption, label, items, current, editable ); // #else // return QString::null; // #endif mDetails = details; mCreated = created ; mModified = modified; mText = ""; - if ( inc->type() == "Event" ) + if ( inc->typeID() == eventID ) setEvent((Event *) inc ); - else if ( inc->type() == "Todo" ) + else if ( inc->typeID() == todoID ) setTodo((Todo *) inc ); return mText; } KIncidenceFormatter* KIncidenceFormatter::instance() { if (!mInstance) { mInstance = insd.setObject(new KIncidenceFormatter()); } return mInstance; } KIncidenceFormatter::~KIncidenceFormatter() { if (mInstance == this) mInstance = insd.setObject(0); //qDebug("KIncidenceFormatter::~KIncidenceFormatter "); } KIncidenceFormatter::KIncidenceFormatter() { mColorMode = 0; } void KIncidenceFormatter::setEvent(Event *event) { int mode = 0; mCurrentIncidence = event; bool shortDate = true; if ( mode == 0 ) { addTag("h3",deTag(event->summary())); } else { if ( mColorMode == 1 ) { mText +="<font color=\"#00A000\">"; } if ( mColorMode == 2 ) { mText +="<font color=\"#C00000\">"; } // mText +="<font color=\"#F00000\">" + i18n("O-due!") + "</font>"; if ( mode == 1 ) { addTag("h2",i18n( "Local: " ) +deTag(event->summary())); } else { addTag("h2",i18n( "Remote: " ) +deTag(event->summary())); } addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) ); if ( mColorMode ) mText += "</font>"; } if (event->cancelled ()) { mText +="<font color=\"#B00000\">"; addTag("i",i18n("This event has been cancelled!")); mText.append("<br>"); mText += "</font>"; } if (event->doesFloat()) { if (event->isMultiDay()) { mText.append(i18n("<p><b>From:</b> %1 </p><p><b>To:</b> %2</p>") .arg(event->dtStartDateStr(shortDate)) .arg(event->dtEndDateStr(shortDate))); } else { mText.append(i18n("<p><b>On:</b> %1</p>").arg(event->dtStartDateStr( shortDate ))); } } else { if (event->isMultiDay()) { mText.append(i18n("<p><b>From:</b> %1</p> ") .arg(event->dtStartStr( shortDate))); mText.append(i18n("<p><b>To:</b> %1</p>") .arg(event->dtEndStr(shortDate))); } else { mText.append(i18n("<p><b>From:</b> %1 <b>To:</b> %2</p>") .arg(event->dtStartTimeStr()) .arg(event->dtEndTimeStr())); mText.append(i18n("<p><b>On:</b> %1</p> ") .arg(event->dtStartDateStr( shortDate ))); } } if (!event->location().isEmpty()) { addTag("b",i18n("Location: ")); mText.append(deTag(event->location())+"<br>"); } if (event->recurrence()->doesRecur()) { QString recurText = event->recurrence()->recurrenceText(); addTag("p","<em>" + i18n("This is a %1 recurring event.").arg(recurText ) + "</em>"); bool ok; QDate start = QDate::currentDate(); QDateTime next; next = event->getNextOccurence( QDateTime::currentDateTime() , &ok ); if ( ok ) { addTag("p",i18n("<b>Next recurrence is on:</b>") ); addTag("p", KGlobal::locale()->formatDate( next.date(), shortDate )); } else { bool last; QDate nextd; nextd = event->recurrence()->getPreviousDate( QDate::currentDate() , &last ); if ( last ) { addTag("p",i18n("<b>Last recurrence was on:</b>") ); addTag("p", KGlobal::locale()->formatDate( nextd, shortDate )); } } } if (event->isAlarmEnabled()) { Alarm *alarm =event->alarms().first() ; QDateTime t = alarm->time(); QString s =i18n("( %1 before )").arg( alarm->offsetText() ); addTag("p",i18n("<b>Alarm on: </b>") + s + ": "+KGlobal::locale()->formatDateTime( t, shortDate )); //addTag("p", KGlobal::locale()->formatDateTime( t, shortDate )); //addTag("p",s); } addTag("p",i18n("<b>Access: </b>") +event->secrecyStr() ); // mText.append(event->secrecyStr()+"<br>"); formatCategories(event); formatReadOnly(event); formatAttendees(event); if ( mCreated ) { #ifdef DESKTOP_VERSION addTag("p",i18n("<b>Created: ") +" </b>"+KGlobal::locale()->formatDateTime( event->created(), shortDate )); #else addTag("p",i18n("<b>Created: ") +" </b>"); addTag("p", KGlobal::locale()->formatDateTime( event->created(), shortDate )); #endif } if ( mModified ) { #ifdef DESKTOP_VERSION addTag("p",i18n("<b>Last modified: ") +" </b>"+KGlobal::locale()->formatDateTime( event->lastModified(), shortDate )); #else addTag("p",i18n("<b>Last modified: ") +" </b>"); addTag("p", KGlobal::locale()->formatDateTime( event->lastModified(), shortDate )); #endif } if ( mDetails ) { if (!event->description().isEmpty()) { addTag("p",i18n("<b>Details: </b>")); addTag("p",deTag(event->description())); } } } void KIncidenceFormatter::setTodo(Todo *event ) { int mode = 0; mCurrentIncidence = event; bool shortDate = true; if (mode == 0 ) addTag("h3",deTag(event->summary())); else { if ( mColorMode == 1 ) { mText +="<font color=\"#00A000\">"; } if ( mColorMode == 2 ) { mText +="<font color=\"#B00000\">"; } if ( mode == 1 ) { addTag("h2",i18n( "Local: " ) +deTag(event->summary())); } else { addTag("h2",i18n( "Remote: " ) +deTag(event->summary())); } addTag("h3",i18n( "Last modified: " ) + KGlobal::locale()->formatDateTime(event->lastModified(),shortDate, true ) ); if ( mColorMode ) mText += "</font>"; } if ( event->percentComplete() == 100 && event->hasCompletedDate() ) { mText +="<font color=\"#B00000\">"; addTag("i", i18n("<p><i>Completed on %1</i></p>").arg( event->completedStr(shortDate) ) ); mText += "</font>"; } else { mText.append(i18n("<p><i>%1 % completed</i></p>") .arg(event->percentComplete())); } if (event->cancelled ()) { mText +="<font color=\"#B00000\">"; addTag("i",i18n("This todo has been cancelled!")); mText.append("<br>"); mText += "</font>"; } if (event->recurrence()->doesRecur()) { QString recurText = event->recurrence()->recurrenceText(); addTag("p","<em>" + i18n("This is a %1 recurring todo.").arg(recurText ) + "</em>"); } if (event->hasStartDate()) { mText.append(i18n("<p><b>Start on:</b> %1</p>").arg(event->dtStartStr(shortDate))); } if (event->hasDueDate()) { mText.append(i18n("<p><b>Due on:</b> %1</p>").arg(event->dtDueStr(shortDate))); } if (!event->location().isEmpty()) { addTag("b",i18n("Location: ")); mText.append(deTag(event->location())+"<br>"); } mText.append(i18n("<p><b>Priority:</b> %2</p>") .arg(QString::number(event->priority()))); if (event->isAlarmEnabled()) { Alarm *alarm =event->alarms().first() ; QDateTime t = alarm->time(); QString s =i18n("( %1 before )").arg( alarm->offsetText() ); addTag("p",i18n("<b>Alarm on: ") + s +" </b>"); addTag("p", KGlobal::locale()->formatDateTime( t, shortDate )); //addTag("p",s); } addTag("p",i18n("<b>Access: </b>") +event->secrecyStr() ); formatCategories(event); formatReadOnly(event); formatAttendees(event); if ( mCreated ) { #ifdef DESKTOP_VERSION addTag("p",i18n("<b>Created: ") +" </b>"+KGlobal::locale()->formatDateTime( event->created(), shortDate )); #else addTag("p",i18n("<b>Created: ") +" </b>"); addTag("p", KGlobal::locale()->formatDateTime( event->created(), shortDate )); #endif } if ( mModified ) { #ifdef DESKTOP_VERSION addTag("p",i18n("<b>Last modified: ") +" </b>"+KGlobal::locale()->formatDateTime( event->lastModified(), shortDate )); #else addTag("p",i18n("<b>Last modified: ") +" </b>"); addTag("p", KGlobal::locale()->formatDateTime( event->lastModified(), shortDate )); #endif } if ( mDetails ) { if (!event->description().isEmpty()) { addTag("p",i18n("<b>Details: </b>")); addTag("p",deTag(event->description())); } } } void KIncidenceFormatter::setJournal(Journal* ) { } void KIncidenceFormatter::formatCategories(Incidence *event) { if (!event->categoriesStr().isEmpty()) { addTag("p",i18n("<b>Categories: </b>")+event->categoriesStrWithSpace() ); //mText.append(event->categoriesStr()); } } void KIncidenceFormatter::addTag(const QString & tag,const QString & text) { int number=text.contains("\n"); QString str = "<" + tag + ">"; QString tmpText=text; QString tmpStr=str; if(number !=-1) { if (number > 0) { int pos=0; QString tmp; for(int i=0;i<=number;i++) { pos=tmpText.find("\n"); tmp=tmpText.left(pos); tmpText=tmpText.right(tmpText.length()-pos-1); tmpStr+=tmp+"<br>"; } } else tmpStr += tmpText; tmpStr+="</" + tag + ">"; mText.append(tmpStr); } else { str += text + "</" + tag + ">"; mText.append(str); } } void KIncidenceFormatter::formatAttendees(Incidence *event) { QPtrList<Attendee> attendees = event->attendees(); if (attendees.count()) { QString iconPath = KGlobal::iconLoader()->iconPath("mailappt",KIcon::Small); QString NOiconPath = KGlobal::iconLoader()->iconPath("nomailappt",KIcon::Small); addTag("h3",i18n("Organizer")); mText.append("<ul><li>"); #if 0 //ndef KORG_NOKABC KABC::AddressBook *add_book = KABC::StdAddressBook::self(); KABC::Addressee::List addressList; addressList = add_book->findByEmail(event->organizer()); KABC::Addressee o = addressList.first(); if (!o.isEmpty() && addressList.size()<2) { mText += "<a href=\"uid:" + o.uid() + "\">"; mText += o.formattedName(); mText += "</a>\n"; } else { mText.append(event->organizer()); } #else mText.append(event->organizer()); #endif if (iconPath) { mText += " <a href=\"mailto:" + event->organizer() + "\">"; mText += "<IMG src=\"" + iconPath + "\">"; mText += "</a>\n"; } mText.append("</li></ul>"); addTag("h3",i18n("Attendees")); Attendee *a; mText.append("<ul>"); for(a=attendees.first();a;a=attendees.next()) { #if 0 //ndef KORG_NOKABC if (a->name().isEmpty()) { addressList = add_book->findByEmail(a->email()); KABC::Addressee o = addressList.first(); if (!o.isEmpty() && addressList.size()<2) { mText += "<a href=\"uid:" + o.uid() + "\">"; mText += o.formattedName(); mText += "</a>\n"; } else { mText += "<li>"; mText.append(a->email()); mText += "\n"; } } else { mText += "<li><a href=\"uid:" + a->uid() + "\">"; if (!a->name().isEmpty()) mText += a->name(); else mText += a->email(); mText += "</a>\n"; } #else //qDebug("nokabc "); mText += "<li><a href=\"uid:" + a->uid() + "\">"; if (!a->name().isEmpty()) mText += a->name(); else mText += a->email(); mText += "</a>\n"; #endif if (!a->email().isEmpty()) { if (iconPath) { mText += "<a href=\"mailto:" + a->name() +" "+ "<" + a->email() + ">" + "\">"; if ( a->RSVP() ) mText += "<IMG src=\"" + iconPath + "\">"; else mText += "<IMG src=\"" + NOiconPath + "\">"; mText += "</a>\n"; } } if (a->status() != Attendee::NeedsAction ) mText +="[" + a->statusStr() + "] "; if (a->role() == Attendee::Chair ) mText +="(" + a->roleStr().left(1) + ".)"; } mText.append("</li></ul>"); } } void KIncidenceFormatter::formatReadOnly(Incidence *event) { if (event->isReadOnly()) { addTag("p","<em>(" + i18n("read-only") + ")</em>"); } } QString KIncidenceFormatter::deTag(QString text) { #if QT_VERSION >= 0x030000 text.replace( '<' , "<" ); text.replace( '>' , ">" ); #else if ( text.find ('<') >= 0 ) { text.replace( QRegExp("<") , "<" ); } if ( text.find ('>') >= 0 ) { text.replace( QRegExp(">") , ">" ); } #endif return text; } diff --git a/libkcal/todo.cpp b/libkcal/todo.cpp index 38ba2c7..c97a61e 100644 --- a/libkcal/todo.cpp +++ b/libkcal/todo.cpp @@ -1,580 +1,581 @@ /* This file is part of libkcal. Copyright (c) 2001 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 <kglobal.h> #include <kglobalsettings.h> #include <klocale.h> #include <kdebug.h> #include <qregexp.h> #include <qfileinfo.h> #include "calendarlocal.h" #include "icalformat.h" #include "todo.h" using namespace KCal; Todo::Todo(): QObject(), Incidence() { // mStatus = TENTATIVE; mHasDueDate = false; setHasStartDate( false ); mCompleted = getEvenTime(QDateTime::currentDateTime()); mHasCompletedDate = false; mPercentComplete = 0; mRunning = false; mRunSaveTimer = 0; } Todo::Todo(const Todo &t) : QObject(),Incidence(t) { mDtDue = t.mDtDue; mHasDueDate = t.mHasDueDate; mCompleted = t.mCompleted; mHasCompletedDate = t.mHasCompletedDate; mPercentComplete = t.mPercentComplete; mRunning = false; mRunSaveTimer = 0; } Todo::~Todo() { setRunning( false ); //qDebug("Todo::~Todo() "); } void Todo::setRunningFalse( QString s ) { if ( ! mRunning ) return; mRunning = false; mRunSaveTimer->stop(); saveRunningInfoToFile( s ); } void Todo::setRunning( bool run ) { if ( run == mRunning ) return; //qDebug("Todo::setRunning %d ", run); if ( !mRunSaveTimer ) { mRunSaveTimer = new QTimer ( this ); connect ( mRunSaveTimer, SIGNAL( timeout() ), this , SLOT ( saveRunningInfoToFile() ) ); } mRunning = run; if ( mRunning ) { mRunSaveTimer->start( 1000 * 60 * 5 ); // 5 min mRunStart = QDateTime::currentDateTime(); } else { mRunSaveTimer->stop(); saveRunningInfoToFile(); } } void Todo::saveRunningInfoToFile( QString comment ) { //qDebug("Todo::saveRunningInfoToFile() %s", summary().latin1()); if ( mRunStart.secsTo ( QDateTime::currentDateTime() ) < 30 ) { qDebug("Running time < 30 seconds. Skipped. "); return; } QString dir = KGlobalSettings::timeTrackerDir(); //qDebug("%s ", dir.latin1()); QString file = "%1%2%3-%4%5%6-"; file = file.arg( mRunStart.date().year(), 4).arg( mRunStart.date().month(),2 ).arg( mRunStart.date().day(), 2 ).arg( mRunStart.time().hour(),2 ).arg( mRunStart.time().minute(),2 ).arg( mRunStart.time().second(),2 ); file.replace ( QRegExp (" "), "0" ); file += uid(); //qDebug("File %s ",file.latin1() ); CalendarLocal cal; cal.setLocalTime(); Todo * to = (Todo*) clone(); to->setFloats( false ); to->setDtStart( mRunStart ); to->setHasStartDate( true ); to->setDtDue( QDateTime::currentDateTime() ); to->setHasDueDate( true ); to->setUid( file ); if ( !comment.isEmpty() ) { QString des = to->description(); if ( des.isEmpty () ) to->setDescription( "TT-Note: " + comment ); else to->setDescription( "TT-Note: " + comment +"\n" + des ); } cal.addIncidence( to ); ICalFormat format; file = dir +"/" +file +".ics"; format.save( &cal, file ); saveParents(); } void Todo::saveParents() { if (!relatedTo() ) return; Incidence * inc = relatedTo(); - if ( inc->type() != "Todo" ) + if ( inc->typeID() != todoID ) return; Todo* to = (Todo*)inc; bool saveTodo = false; QString file = KGlobalSettings::timeTrackerDir() + "/"+ to->uid() + ".ics"; QFileInfo fi ( file ); if ( fi.exists() ) { if ( fi.lastModified () < to->lastModified ()) saveTodo = true; } else { saveTodo = true; } if ( saveTodo ) { CalendarLocal cal; cal.setLocalTime(); Todo * par = (Todo *) to->clone(); cal.addIncidence( par ); ICalFormat format; format.save( &cal, file ); } to->saveParents(); } int Todo::runTime() { if ( !mRunning ) return 0; return mRunStart.secsTo( QDateTime::currentDateTime() ); } bool Todo::hasRunningSub() { if ( mRunning ) return true; Incidence *aTodo; for (aTodo = mRelations.first(); aTodo; aTodo = mRelations.next()) { if ( ((Todo*)aTodo)->hasRunningSub() ) return true; } return false; } Incidence *Todo::clone() { return new Todo(*this); } bool Todo::contains ( Todo* from ) { if ( !from->summary().isEmpty() ) if ( !summary().startsWith( from->summary() )) return false; if ( from->hasStartDate() ) { if ( !hasStartDate() ) return false; if ( from->dtStart() != dtStart()) return false; } if ( from->hasDueDate() ){ if ( !hasDueDate() ) return false; if ( from->dtDue() != dtDue()) return false; } if ( !from->location().isEmpty() ) if ( !location().startsWith( from->location() ) ) return false; if ( !from->description().isEmpty() ) if ( !description().startsWith( from->description() )) return false; if ( from->alarms().count() ) { Alarm *a = from->alarms().first(); if ( a->enabled() ){ if ( !alarms().count() ) return false; Alarm *b = alarms().first(); if( ! b->enabled() ) return false; if ( ! (a->offset() == b->offset() )) return false; } } QStringList cat = categories(); QStringList catFrom = from->categories(); QString nCat; unsigned int iii; for ( iii = 0; iii < catFrom.count();++iii ) { nCat = catFrom[iii]; if ( !nCat.isEmpty() ) if ( !cat.contains( nCat )) { return false; } } if ( from->isCompleted() ) { if ( !isCompleted() ) return false; } if( priority() != from->priority() ) return false; return true; } bool KCal::operator==( const Todo& t1, const Todo& t2 ) { bool ret = operator==( (const Incidence&)t1, (const Incidence&)t2 ); if ( ! ret ) return false; if ( t1.hasDueDate() == t2.hasDueDate() ) { if ( t1.hasDueDate() ) { if ( t1.doesFloat() == t2.doesFloat() ) { if ( t1.doesFloat() ) { if ( t1.dtDue().date() != t2.dtDue().date() ) return false; } else if ( t1.dtDue() != t2.dtDue() ) return false; } else return false;// float != } } else return false; if ( t1.percentComplete() != t2.percentComplete() ) return false; if ( t1.isCompleted() ) { if ( t1.hasCompletedDate() == t2.hasCompletedDate() ) { if ( t1.hasCompletedDate() ) { if ( t1.completed() != t2.completed() ) return false; } } else return false; } return true; } void Todo::setDtDue(const QDateTime &dtDue) { //int diffsecs = mDtDue.secsTo(dtDue); /*if (mReadOnly) return; const QPtrList<Alarm>& alarms = alarms(); for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) { if (alarm->enabled()) { alarm->setTime(alarm->time().addSecs(diffsecs)); } }*/ mDtDue = getEvenTime(dtDue); //kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl; /*const QPtrList<Alarm>& alarms = alarms(); for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) alarm->setAlarmStart(mDtDue);*/ updated(); } QDateTime Todo::dtDue() const { return mDtDue; } QString Todo::dtDueTimeStr() const { return KGlobal::locale()->formatTime(mDtDue.time()); } QString Todo::dtDueDateStr(bool shortfmt) const { return KGlobal::locale()->formatDate(mDtDue.date(),shortfmt); } QString Todo::dtDueStr(bool shortfmt) const { if ( doesFloat() ) return KGlobal::locale()->formatDate(mDtDue.date(),shortfmt); return KGlobal::locale()->formatDateTime(mDtDue, shortfmt); } // retval 0 : no found // 1 : due for date found // 2 : overdue for date found int Todo::hasDueSubTodoForDate( const QDate & date, bool checkSubtodos ) { int retval = 0; if ( isCompleted() ) return 0; if ( hasDueDate() ) { if ( dtDue().date() < date ) return 2; // we do not return, because we may find an overdue sub todo if ( dtDue().date() == date ) retval = 1; } if ( checkSubtodos ) { Incidence *aTodo; for (aTodo = mRelations.first(); aTodo; aTodo = mRelations.next()) { int ret = ((Todo*)aTodo)->hasDueSubTodoForDate( date ,checkSubtodos ); if ( ret == 2 ) return 2; if ( ret == 1) retval = 1; } } return retval; } int Todo::hasDueSubTodo( bool checkSubtodos ) //= true { return hasDueSubTodoForDate(QDate::currentDate(), checkSubtodos ); } bool Todo::hasDueDate() const { return mHasDueDate; } void Todo::setHasDueDate(bool f) { if (mReadOnly) return; mHasDueDate = f; updated(); } #if 0 void Todo::setStatus(const QString &statStr) { if (mReadOnly) return; QString ss(statStr.upper()); if (ss == "X-ACTION") mStatus = NEEDS_ACTION; else if (ss == "NEEDS ACTION") mStatus = NEEDS_ACTION; else if (ss == "ACCEPTED") mStatus = ACCEPTED; else if (ss == "SENT") mStatus = SENT; else if (ss == "TENTATIVE") mStatus = TENTATIVE; else if (ss == "CONFIRMED") mStatus = CONFIRMED; else if (ss == "DECLINED") mStatus = DECLINED; else if (ss == "COMPLETED") mStatus = COMPLETED; else if (ss == "DELEGATED") mStatus = DELEGATED; updated(); } void Todo::setStatus(int status) { if (mReadOnly) return; mStatus = status; updated(); } int Todo::status() const { return mStatus; } QString Todo::statusStr() const { switch(mStatus) { case NEEDS_ACTION: return QString("NEEDS ACTION"); break; case ACCEPTED: return QString("ACCEPTED"); break; case SENT: return QString("SENT"); break; case TENTATIVE: return QString("TENTATIVE"); break; case CONFIRMED: return QString("CONFIRMED"); break; case DECLINED: return QString("DECLINED"); break; case COMPLETED: return QString("COMPLETED"); break; case DELEGATED: return QString("DELEGATED"); break; } return QString(""); } #endif bool Todo::isCompleted() const { if (mPercentComplete == 100) { return true; } else return false; } void Todo::setCompleted(bool completed) { if ( mHasRecurrenceID && completed && mPercentComplete != 100 ) { if ( !setRecurDates() ) completed = false; } if (completed) mPercentComplete = 100; else { mPercentComplete = 0; mHasCompletedDate = false; } updated(); } QDateTime Todo::completed() const { return mCompleted; } QString Todo::completedStr( bool shortF ) const { return KGlobal::locale()->formatDateTime(mCompleted, shortF); } void Todo::setCompleted(const QDateTime &completed) { //qDebug("Todo::setCompleted "); if ( mHasCompletedDate ) { // qDebug("has completed data - return "); return; } mHasCompletedDate = true; mPercentComplete = 100; mCompleted = getEvenTime(completed); updated(); } bool Todo::hasCompletedDate() const { return mHasCompletedDate; } int Todo::percentComplete() const { return mPercentComplete; } bool Todo::setRecurDates() { if ( !mHasRecurrenceID ) return true; int secs = mDtStart.secsTo( dtDue() ); bool ok; qDebug("T:setRecurDates() "); //qDebug("%s %s %s ",mDtStart.toString().latin1(), dtDue().toString().latin1(),mRecurrenceID.toString().latin1() ); QDateTime next = getNextOccurence( mRecurrenceID, &ok ); if ( ok ) { mRecurrenceID = next; mDtStart = next; setDtDue( next.addSecs( secs ) ); if ( QDateTime::currentDateTime() > next) return false; } else { setHasRecurrenceID( false ); recurrence()->unsetRecurs(); } return true; } void Todo::setPercentComplete(int v) { if ( mHasRecurrenceID && v == 100 && mPercentComplete != 100 ) { if ( !setRecurDates() ) v = 0; } mPercentComplete = v; if ( v != 100 ) mHasCompletedDate = false; updated(); } QDateTime Todo::getNextAlarmDateTime( bool * ok, int * offset, QDateTime start_dt ) const { if ( isCompleted() || ! hasDueDate() || cancelled() ) { *ok = false; return QDateTime (); } QDateTime incidenceStart; incidenceStart = dtDue(); bool enabled = false; Alarm* alarm; int off = 0; QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );; // if ( QDateTime::currentDateTime() > incidenceStart ){ // *ok = false; // return incidenceStart; // } for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { if (alarm->enabled()) { if ( alarm->hasTime () ) { if ( alarm->time() < alarmStart ) { alarmStart = alarm->time(); enabled = true; off = alarmStart.secsTo( incidenceStart ); } } else { int secs = alarm->startOffset().asSeconds(); if ( incidenceStart.addSecs( secs ) < alarmStart ) { alarmStart = incidenceStart.addSecs( secs ); enabled = true; off = -secs; } } } } if ( enabled ) { if ( alarmStart > start_dt ) { *ok = true; * offset = off; return alarmStart; } } *ok = false; return QDateTime (); } void Todo::checkSetCompletedFalse() { - if ( !hasRecurrenceID() ) { + if ( !mHasRecurrenceID ) { qDebug("ERROR 1 in Todo::checkSetCompletedFalse"); + return; } // qDebug("Todo::checkSetCompletedFalse()"); //qDebug("%s %s %s ",mDtStart.toString().latin1(), dtDue().toString().latin1(),mRecurrenceID.toString().latin1() ); if ( mPercentComplete == 100 ) { QDateTime dt = QDateTime::currentDateTime(); if ( dt > mDtStart && dt > mRecurrenceID ) { qDebug("start: %s --due: %s --recID: %s ",mDtStart.toString().latin1(), dtDue().toString().latin1(),mRecurrenceID.toString().latin1() ); setCompleted( false ); qDebug("Todo::checkSetCompletedFalse "); } } } diff --git a/libkcal/todo.h b/libkcal/todo.h index ab8fdf1..501c2ba 100644 --- a/libkcal/todo.h +++ b/libkcal/todo.h @@ -1,150 +1,151 @@ /* This file is part of libkcal. Copyright (c) 2001 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. */ #ifndef TODO_H #define TODO_H // // Todo component, representing a VTODO object // #include "incidence.h" #include <qtimer.h> namespace KCal { /** This class provides a Todo in the sense of RFC2445. */ class Todo : public QObject,public Incidence { Q_OBJECT public: Todo(); Todo(const Todo &); ~Todo(); typedef ListBase<Todo> List; QCString type() const { return "Todo"; } + IncTypeID typeID() const { return todoID; } /** Return an exact copy of this todo. */ Incidence *clone(); QDateTime getNextAlarmDateTime( bool * ok, int * offset, QDateTime start_dt ) const; /** for setting the todo's due date/time with a QDateTime. */ void setDtDue(const QDateTime &dtDue); /** returns an event's Due date/time as a QDateTime. */ QDateTime dtDue() const; /** returns an event's due time as a string formatted according to the users locale settings */ QString dtDueTimeStr() const; /** returns an event's due date as a string formatted according to the users locale settings */ QString dtDueDateStr(bool shortfmt=true) const; /** returns an event's due date and time as a string formatted according to the users locale settings */ QString dtDueStr(bool shortfmt=true) const; /** returns TRUE or FALSE depending on whether the todo has a due date */ bool hasDueDate() const; /** sets the event's hasDueDate value. */ void setHasDueDate(bool f); /* Looks for a subtodo (including itself ) which is not complete and is - overdue, or - due today. It returns 0 for nothing found, 1 for found a todo which is due today and no overdue found 2 for found a overdue todo */ int hasDueSubTodo( bool checkSubtodos = true ); /* same as above, but a specific date can be specified*/ int hasDueSubTodoForDate( const QDate & date, bool checkSubtodos ); /** sets the event's status to the string specified. The string * must be a recognized value for the status field, i.e. a string * equivalent of the possible status enumerations previously described. */ // void setStatus(const QString &statStr); /** sets the event's status to the value specified. See the enumeration * above for possible values. */ // void setStatus(int); /** return the event's status. */ // int status() const; /** return the event's status in string format. */ // QString statusStr() const; /** return, if this todo is completed */ bool isCompleted() const; /** set completed state of this todo */ void setCompleted(bool); /** Return how many percent of the task are completed. Returns a value between 0 and 100. */ int percentComplete() const; /** Set how many percent of the task are completed. Valid values are in the range from 0 to 100. */ void setPercentComplete(int); /** return date and time when todo was completed */ QDateTime completed() const; QString completedStr(bool shortF = true) const; /** set date and time of completion */ void setCompleted(const QDateTime &completed); /** Return true, if todo has a date associated with completion */ bool hasCompletedDate() const; bool contains ( Todo*); void checkSetCompletedFalse(); bool setRecurDates(); bool isRunning() {return mRunning;} bool hasRunningSub(); void setRunning( bool ); void setRunningFalse( QString ); int runTime(); QDateTime runStart () const { return mRunStart;} public slots: void saveRunningInfoToFile( QString st = QString::null ); void saveParents(); private: bool mRunning; QTimer * mRunSaveTimer; QDateTime mRunStart; bool accept(Visitor &v) { return v.visit(this); } QDateTime mDtDue; // due date of todo bool mHasDueDate; // if todo has associated due date // int mStatus; // confirmed/delegated/tentative/etc QDateTime mCompleted; bool mHasCompletedDate; int mPercentComplete; }; bool operator==( const Todo&, const Todo& ); } #endif |