diff --git a/kcal/calfilter.cpp b/kcal/calfilter.cpp index 52dd174e5..1bfa05d28 100644 --- a/kcal/calfilter.cpp +++ b/kcal/calfilter.cpp @@ -1,164 +1,164 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "calfilter.h" using namespace KCal; CalFilter::CalFilter() { mEnabled = true; mCriteria = 0; } CalFilter::CalFilter(const QString &name) { mName = name; } CalFilter::~CalFilter() { } void CalFilter::apply( Event::List *eventlist ) { if ( !mEnabled ) return; // kdDebug(5800) << "CalFilter::apply()" << endl; Event::List::Iterator it = eventlist->begin(); while( it != eventlist->end() ) { if ( !filterEvent( *it ) ) { eventlist->remove( it ); } else { ++it; } } // kdDebug(5800) << "CalFilter::apply() done" << endl; } // TODO: avoid duplicating apply() code void CalFilter::apply( Todo::List *eventlist ) { if ( !mEnabled ) return; // kdDebug(5800) << "CalFilter::apply()" << endl; Todo::List::Iterator it = eventlist->begin(); while( it != eventlist->end() ) { if ( !filterTodo( *it ) ) { it = eventlist->remove( it ); } else { ++it; } } // kdDebug(5800) << "CalFilter::apply() done" << endl; } bool CalFilter::filterEvent(Event *event) { // kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl; if (mCriteria & HideRecurring) { - if (event->recurrence()->doesRecur()) return false; + if (event->doesRecur()) return false; } return filterIncidence(event); } bool CalFilter::filterTodo(Todo *todo) { // kdDebug(5800) << "CalFilter::filterEvent(): " << event->getSummary() << endl; if (mCriteria & HideCompleted) { if (todo->isCompleted()) return false; } return filterIncidence(todo); } bool CalFilter::filterIncidence(Incidence *incidence) { // 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/kcal/event.cpp b/kcal/event.cpp index 1ffc6d79f..203896567 100644 --- a/kcal/event.cpp +++ b/kcal/event.cpp @@ -1,130 +1,131 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "event.h" using namespace KCal; Event::Event() : mHasEndDate( false ), mTransparency( Opaque ) { } Event::Event(const Event &e) : Incidence(e) { mDtEnd = e.mDtEnd; mHasEndDate = e.mHasEndDate; mTransparency = e.mTransparency; } Event::~Event() { } Event *Event::clone() { kdDebug(5800) << "Event::clone()" << endl; return new Event(*this); } -bool KCal::operator==( const Event& e1, const Event& e2 ) +bool Event::operator==( const Event& e2 ) const { - return operator==( (const Incidence&)e1, (const Incidence&)e2 ) && - e1.dtEnd() == e2.dtEnd() && - e1.hasEndDate() == e2.hasEndDate() && - e1.transparency() == e2.transparency(); + return + static_cast(*this) == static_cast(e2) && + dtEnd() == e2.dtEnd() && + hasEndDate() == e2.hasEndDate() && + transparency() == e2.transparency(); } void Event::setDtEnd(const QDateTime &dtEnd) { if (mReadOnly) return; mDtEnd = dtEnd; setHasEndDate(true); setHasDuration(false); updated(); } QDateTime Event::dtEnd() const { if (hasEndDate()) return mDtEnd; if (hasDuration()) return dtStart().addSecs(duration()); kdDebug(5800) << "Warning! Event '" << summary() << "' does have neither end date nor duration." << endl; return dtStart(); } QString Event::dtEndTimeStr() const { return KGlobal::locale()->formatTime(mDtEnd.time()); } QString Event::dtEndDateStr(bool shortfmt) const { return KGlobal::locale()->formatDate(mDtEnd.date(),shortfmt); } QString Event::dtEndStr() const { return KGlobal::locale()->formatDateTime(mDtEnd); } void Event::setHasEndDate(bool b) { mHasEndDate = b; } bool Event::hasEndDate() const { return mHasEndDate; } bool Event::isMultiDay() const { bool multi = !(dtStart().date() == dtEnd().date()); return multi; } void Event::setTransparency(Event::Transparency transparency) { if (mReadOnly) return; mTransparency = transparency; updated(); } Event::Transparency Event::transparency() const { return mTransparency; } void Event::setDuration(int seconds) { setHasEndDate(false); Incidence::setDuration(seconds); } diff --git a/kcal/event.h b/kcal/event.h index 5020c3d9a..beaee5fc2 100644 --- a/kcal/event.h +++ b/kcal/event.h @@ -1,89 +1,87 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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 List; Event(); Event(const Event &); ~Event(); + bool operator==( const Event& ) const; QCString type() const { return "Event"; } Event *clone(); /** 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() 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); 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/kcal/freebusy.cpp b/kcal/freebusy.cpp index 716f7ccd3..a699aef91 100644 --- a/kcal/freebusy.cpp +++ b/kcal/freebusy.cpp @@ -1,186 +1,186 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "freebusy.h" using namespace KCal; FreeBusy::FreeBusy() { } FreeBusy::FreeBusy(const QDateTime &start, const QDateTime &end) { setDtStart(start); setDtEnd(end); } FreeBusy::FreeBusy( Calendar *calendar, const QDateTime &start, const QDateTime &end ) { kdDebug() << "FreeBusy::FreeBusy" << endl; mCalendar = calendar; setDtStart(start); setDtEnd(end); // Get all the events in the calendar Event::List eventList = mCalendar->events(); int extraDays, i, x, duration; duration = start.daysTo(end); QDate day; QDateTime tmpStart; QDateTime tmpEnd; // Loops through every event in the calendar Event::List::ConstIterator it; for( it = eventList.begin(); it != eventList.end(); ++it ) { Event *event = *it; // This whole for loop is for recurring events, it loops through // each of the days of the freebusy request // First check if this is transparent. If it is, it shouldn't be in the // freebusy list if ( event->transparency() == Event::Transparent ) // Transparent continue; for(i=0; i<=duration; i++) { day=(start.addDays(i).date()); tmpStart.setDate(day); tmpEnd.setDate(day); - if( (*(event->recurrence())).doesRecur() ) { + if( event->doesRecur() ) { if ( event->isMultiDay() ) { extraDays = event->dtStart().date().daysTo(event->dtEnd().date()); for (x=0; x<=extraDays; x++) { if ( event->recursOn(day.addDays(-x))) { tmpStart.setDate(day.addDays(-x)); tmpStart.setTime(event->dtStart().time()); tmpEnd=tmpStart.addSecs( (event->duration()) ); addLocalPeriod( tmpStart, tmpEnd ); break; } } } else { if (event->recursOn(day)) { tmpStart.setTime(event->dtStart().time()); tmpEnd.setTime(event->dtEnd().time()); addLocalPeriod (tmpStart, tmpEnd); } } } } // Non-recurring events addLocalPeriod(event->dtStart(), event->dtEnd()); } sortList(); } FreeBusy::~FreeBusy() { } bool FreeBusy::setDtEnd( const QDateTime &end ) { mDtEnd = end; return true; } QDateTime FreeBusy::dtEnd() const { return mDtEnd; } QValueList FreeBusy::busyPeriods() const { return mBusyPeriods; } bool FreeBusy::addLocalPeriod(const QDateTime &eventStart, const QDateTime &eventEnd ) { QDateTime tmpStart; QDateTime tmpEnd; //Check to see if the start *or* end of the event is //between the start and end of the freebusy dates. if (!((((this->dtStart()).secsTo(eventStart)>=0)&&(eventStart.secsTo(this->dtEnd())>=0)) ||(((this->dtStart()).secsTo(eventEnd) >= 0)&&(eventEnd.secsTo(this->dtEnd()) >= 0)))) return false; if ( eventStart.secsTo(this->dtStart())>=0) { tmpStart = this->dtStart(); } else { tmpStart = eventStart; } if ( eventEnd.secsTo(this->dtEnd())<=0 ) { tmpEnd = this->dtEnd(); } else { tmpEnd = eventEnd; } Period p(tmpStart, tmpEnd); mBusyPeriods.append( p ); return true; } FreeBusy::FreeBusy(QValueList busyPeriods) { mBusyPeriods = busyPeriods; } void FreeBusy::sortList() { typedef QValueList PeriodList; PeriodList::Iterator tmpPeriod, earlyPeriod; PeriodList sortedList; QDateTime earlyTime; while( mBusyPeriods.count() > 0 ) { earlyTime=(*mBusyPeriods.begin()).start(); for (tmpPeriod=mBusyPeriods.begin(); tmpPeriod!=mBusyPeriods.end(); tmpPeriod++) { if (earlyTime.secsTo((*tmpPeriod).start()) <= 0) { earlyTime=(*tmpPeriod).start(); earlyPeriod=tmpPeriod; } } //Move tmpPeriod to sortedList Period tmpPeriod( (*earlyPeriod).start(), (*earlyPeriod).end() ); sortedList.append( tmpPeriod ); mBusyPeriods.remove( earlyPeriod ); } mBusyPeriods=sortedList; } void FreeBusy::addPeriod(const QDateTime &start, const QDateTime &end) { Period p(start, end); mBusyPeriods.append( p ); sortList(); } diff --git a/kcal/icalformatimpl.cpp b/kcal/icalformatimpl.cpp index 256a81dd4..ec147d8e4 100644 --- a/kcal/icalformatimpl.cpp +++ b/kcal/icalformatimpl.cpp @@ -1,2139 +1,2138 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include extern "C" { #include #include #include #include } #include "calendar.h" #include "journal.h" #include "icalformat.h" #include "icalformatimpl.h" #include "compat.h" #define _ICAL_VERSION "2.0" using namespace KCal; const int gSecondsPerMinute = 60; const int gSecondsPerHour = gSecondsPerMinute * 60; const int gSecondsPerDay = gSecondsPerHour * 24; const int gSecondsPerWeek = gSecondsPerDay * 7; ICalFormatImpl::ICalFormatImpl( ICalFormat *parent ) : mParent( parent ), mCalendarVersion( 0 ) { mCompat = new Compat; } ICalFormatImpl::~ICalFormatImpl() { delete mCompat; } class ToStringVisitor : public Incidence::Visitor { public: ToStringVisitor( ICalFormatImpl *impl ) : mImpl( impl ), mComponent( 0 ) {} bool visit( Event *e ) { mComponent = mImpl->writeEvent( e ); return true; } bool visit( Todo *e ) { mComponent = mImpl->writeTodo( e ); return true; } bool visit( Journal *e ) { mComponent = mImpl->writeJournal( e ); return true; } icalcomponent *component() { return mComponent; } private: ICalFormatImpl *mImpl; icalcomponent *mComponent; }; icalcomponent *ICalFormatImpl::writeIncidence(Incidence *incidence) { ToStringVisitor v( this ); incidence->accept(v); return v.component(); } icalcomponent *ICalFormatImpl::writeTodo(Todo *todo) { QString tmpStr; QStringList tmpStrList; icalcomponent *vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT); writeIncidence(vtodo,todo); // due date if (todo->hasDueDate()) { icaltimetype due; if (todo->doesFloat()) { due = writeICalDate(todo->dtDue().date()); } else { due = writeICalDateTime(todo->dtDue()); } icalcomponent_add_property(vtodo,icalproperty_new_due(due)); } // start time if (todo->hasStartDate()) { icaltimetype start; if (todo->doesFloat()) { // kdDebug(5800) << "§§ Incidence " << todo->summary() << " floats." << endl; start = writeICalDate(todo->dtStart().date()); } else { // kdDebug(5800) << "§§ incidence " << todo->summary() << " has time." << endl; start = writeICalDateTime(todo->dtStart()); } icalcomponent_add_property(vtodo,icalproperty_new_dtstart(start)); } // completion date if (todo->isCompleted()) { if (!todo->hasCompletedDate()) { // If todo was created by KOrganizer <2.2 it has no correct completion // date. Set it to now. todo->setCompleted(QDateTime::currentDateTime()); } icaltimetype completed = writeICalDateTime(todo->completed()); icalcomponent_add_property(vtodo,icalproperty_new_completed(completed)); } icalcomponent_add_property(vtodo, icalproperty_new_percentcomplete(todo->percentComplete())); return vtodo; } icalcomponent *ICalFormatImpl::writeEvent(Event *event) { kdDebug(5800) << "Write Event '" << event->summary() << "' (" << event->uid() << ")" << endl; QString tmpStr; QStringList tmpStrList; icalcomponent *vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT); writeIncidence(vevent,event); // start time icaltimetype start; if (event->doesFloat()) { // kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; start = writeICalDate(event->dtStart().date()); } else { // kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; start = writeICalDateTime(event->dtStart()); } icalcomponent_add_property(vevent,icalproperty_new_dtstart(start)); if (event->hasEndDate()) { // end time icaltimetype end; if (event->doesFloat()) { // kdDebug(5800) << "§§ Event " << event->summary() << " floats." << endl; // +1 day because end date is non-inclusive. end = writeICalDate( event->dtEnd().date().addDays( 1 ) ); } else { // kdDebug(5800) << "§§ Event " << event->summary() << " has time." << endl; end = writeICalDateTime(event->dtEnd()); } icalcomponent_add_property(vevent,icalproperty_new_dtend(end)); } // TODO: attachments, resources #if 0 // attachments tmpStrList = anEvent->attachments(); for ( QStringList::Iterator it = tmpStrList.begin(); it != tmpStrList.end(); ++it ) addPropValue(vevent, VCAttachProp, (*it).utf8()); // resources tmpStrList = anEvent->resources(); tmpStr = tmpStrList.join(";"); if (!tmpStr.isEmpty()) addPropValue(vevent, VCResourcesProp, tmpStr.utf8()); #endif // Transparency switch( event->transparency() ) { case Event::Transparent: icalcomponent_add_property(vevent, icalproperty_new_transp("TRANSPARENT")); break; case Event::Opaque: icalcomponent_add_property(vevent, icalproperty_new_transp("OPAQUE")); break; } return vevent; } icalcomponent *ICalFormatImpl::writeFreeBusy(FreeBusy *freebusy, Scheduler::Method method) { #if QT_VERSION >= 300 kdDebug(5800) << "icalformatimpl: writeFreeBusy: startDate: " << freebusy->dtStart().toString("ddd MMMM d yyyy: h:m:s ap") << " End Date: " << freebusy->dtEnd().toString("ddd MMMM d yyyy: h:m:s ap") << endl; #endif icalcomponent *vfreebusy = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT); writeIncidenceBase(vfreebusy,freebusy); icalcomponent_add_property(vfreebusy, icalproperty_new_dtstart( writeICalDateTime(freebusy->dtStart()))); icalcomponent_add_property(vfreebusy, icalproperty_new_dtend( writeICalDateTime(freebusy->dtEnd()))); if (method == Scheduler::Request) { icalcomponent_add_property(vfreebusy,icalproperty_new_uid( freebusy->uid().utf8())); } //Loops through all the periods in the freebusy object QValueList list = freebusy->busyPeriods(); QValueList::Iterator it; icalperiodtype period; for (it = list.begin(); it!= list.end(); ++it) { period.start = writeICalDateTime((*it).start()); period.end = writeICalDateTime((*it).end()); icalcomponent_add_property(vfreebusy, icalproperty_new_freebusy(period) ); } return vfreebusy; } icalcomponent *ICalFormatImpl::writeJournal(Journal *journal) { icalcomponent *vjournal = icalcomponent_new(ICAL_VJOURNAL_COMPONENT); writeIncidence(vjournal,journal); // start time if (journal->dtStart().isValid()) { icaltimetype start; if (journal->doesFloat()) { // kdDebug(5800) << "§§ Incidence " << event->summary() << " floats." << endl; start = writeICalDate(journal->dtStart().date()); } else { // kdDebug(5800) << "§§ incidence " << event->summary() << " has time." << endl; start = writeICalDateTime(journal->dtStart()); } icalcomponent_add_property(vjournal,icalproperty_new_dtstart(start)); } return vjournal; } void ICalFormatImpl::writeIncidence(icalcomponent *parent,Incidence *incidence) { // pilot sync stuff // TODO: move this application-specific code to kpilot if (incidence->pilotId()) { incidence->setNonKDECustomProperty("X-PILOTID", QString::number(incidence->pilotId())); incidence->setNonKDECustomProperty("X-PILOTSTAT", QString::number(incidence->syncStatus())); } writeIncidenceBase(parent,incidence); // creation date icalcomponent_add_property(parent,icalproperty_new_created( writeICalDateTime(incidence->created()))); // unique id icalcomponent_add_property(parent,icalproperty_new_uid( incidence->uid().utf8())); // revision icalcomponent_add_property(parent,icalproperty_new_sequence( incidence->revision())); // last modification date icalcomponent_add_property(parent,icalproperty_new_lastmodified( writeICalDateTime(incidence->lastModified()))); // description if (!incidence->description().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_description( incidence->description().utf8())); } // summary if (!incidence->summary().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_summary( incidence->summary().utf8())); } // location if (!incidence->location().isEmpty()) { icalcomponent_add_property(parent,icalproperty_new_location( incidence->location().utf8())); } // TODO: // status // addPropValue(parent, VCStatusProp, incidence->getStatusStr().utf8()); // secrecy const char *classStr; switch (incidence->secrecy()) { case Incidence::SecrecyPublic: classStr = "PUBLIC"; break; case Incidence::SecrecyConfidential: classStr = "CONFIDENTIAL"; break; case Incidence::SecrecyPrivate: default: classStr = "PRIVATE"; break; } icalcomponent_add_property(parent,icalproperty_new_class(classStr)); // priority icalcomponent_add_property(parent,icalproperty_new_priority( incidence->priority())); // categories QStringList categories = incidence->categories(); QStringList::Iterator it; for(it = categories.begin(); it != categories.end(); ++it ) { icalcomponent_add_property(parent,icalproperty_new_categories((*it).utf8())); } // TODO: Ensure correct concatenation of categories properties. /* // categories tmpStrList = incidence->getCategories(); tmpStr = ""; QString catStr; for ( QStringList::Iterator it = tmpStrList.begin(); it != tmpStrList.end(); ++it ) { catStr = *it; if (catStr[0] == ' ') tmpStr += catStr.mid(1); else tmpStr += catStr; // this must be a ';' character as the vCalendar specification requires! // vcc.y has been hacked to translate the ';' to a ',' when the vcal is // read in. tmpStr += ";"; } if (!tmpStr.isEmpty()) { tmpStr.truncate(tmpStr.length()-1); icalcomponent_add_property(parent,icalproperty_new_categories( writeText(incidence->getCategories().join(";")))); } */ // related event if (incidence->relatedTo()) { icalcomponent_add_property(parent,icalproperty_new_relatedto( incidence->relatedTo()->uid().utf8())); } // recurrence rule stuff - Recurrence *recur = incidence->recurrence(); - if (recur->doesRecur()) { + if (incidence->doesRecur()) { kdDebug(5800) << "Write recurrence for '" << incidence->summary() << "' (" << incidence->uid() << ")" << endl; - icalcomponent_add_property(parent,writeRecurrenceRule(recur)); + icalcomponent_add_property(parent,writeRecurrenceRule(incidence->recurrence())); } // recurrence excpetion dates DateList dateList = incidence->exDates(); DateList::ConstIterator exIt; for(exIt = dateList.begin(); exIt != dateList.end(); ++exIt) { icalcomponent_add_property(parent,icalproperty_new_exdate( writeICalDate(*exIt))); } // attachments Attachment::List attachments = incidence->attachments(); for (Attachment *at = attachments.first(); at; at = attachments.next()) icalcomponent_add_property(parent,writeAttachment(at)); // alarms Alarm::List::ConstIterator alarmIt; for ( alarmIt = incidence->alarms().begin(); alarmIt != incidence->alarms().end(); ++alarmIt ) { if ( (*alarmIt)->enabled() ) { kdDebug(5800) << "WralarmIte alarm for " << incidence->summary() << endl; icalcomponent_add_component( parent, writeAlarm( *alarmIt ) ); } } // duration // turned off as it always is set to PTS0 (and must not occur together with DTEND // if (incidence->hasDuration()) { // icaldurationtype duration; // duration = writeICalDuration(incidence->duration()); // icalcomponent_add_property(parent,icalproperty_new_duration(duration)); // } } void ICalFormatImpl::writeIncidenceBase( icalcomponent *parent, IncidenceBase * incidenceBase ) { icalcomponent_add_property( parent, icalproperty_new_dtstamp( writeICalDateTime( QDateTime::currentDateTime() ) ) ); // organizer stuff icalcomponent_add_property( parent, icalproperty_new_organizer( ( "MAILTO:" + incidenceBase->organizer() ).utf8() ) ); // attendees if ( incidenceBase->attendeeCount() > 0 ) { Attendee::List::ConstIterator it; for( it = incidenceBase->attendees().begin(); it != incidenceBase->attendees().end(); ++it ) { icalcomponent_add_property( parent, writeAttendee( *it ) ); } } // custom properties writeCustomProperties( parent, incidenceBase ); } void ICalFormatImpl::writeCustomProperties(icalcomponent *parent,CustomProperties *properties) { QMap custom = properties->customProperties(); for (QMap::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(parent,p); } } icalproperty *ICalFormatImpl::writeAttendee(Attendee *attendee) { icalproperty *p = icalproperty_new_attendee("mailto:" + attendee->email().utf8()); if (!attendee->name().isEmpty()) { icalproperty_add_parameter(p,icalparameter_new_cn(attendee->name().utf8())); } icalproperty_add_parameter(p,icalparameter_new_rsvp( attendee->RSVP() ? ICAL_RSVP_TRUE : ICAL_RSVP_FALSE )); icalparameter_partstat status = ICAL_PARTSTAT_NEEDSACTION; switch (attendee->status()) { default: case Attendee::NeedsAction: status = ICAL_PARTSTAT_NEEDSACTION; break; case Attendee::Accepted: status = ICAL_PARTSTAT_ACCEPTED; break; case Attendee::Declined: status = ICAL_PARTSTAT_DECLINED; break; case Attendee::Tentative: status = ICAL_PARTSTAT_TENTATIVE; break; case Attendee::Delegated: status = ICAL_PARTSTAT_DELEGATED; break; case Attendee::Completed: status = ICAL_PARTSTAT_COMPLETED; break; case Attendee::InProcess: status = ICAL_PARTSTAT_INPROCESS; break; } icalproperty_add_parameter(p,icalparameter_new_partstat(status)); icalparameter_role role = ICAL_ROLE_REQPARTICIPANT; switch (attendee->role()) { case Attendee::Chair: role = ICAL_ROLE_CHAIR; break; default: case Attendee::ReqParticipant: role = ICAL_ROLE_REQPARTICIPANT; break; case Attendee::OptParticipant: role = ICAL_ROLE_OPTPARTICIPANT; break; case Attendee::NonParticipant: role = ICAL_ROLE_NONPARTICIPANT; break; } icalproperty_add_parameter(p,icalparameter_new_role(role)); if (!attendee->uid().isEmpty()) { icalparameter* icalparameter_uid = icalparameter_new_x(attendee->uid().utf8()); icalparameter_set_xname(icalparameter_uid,"X-UID"); icalproperty_add_parameter(p,icalparameter_uid); } return p; } icalproperty *ICalFormatImpl::writeAttachment(Attachment *att) { icalattachtype* attach = icalattachtype_new(); if (att->isURI()) icalattachtype_set_url(attach, att->uri().utf8().data()); else icalattachtype_set_base64(attach, att->data(), 0); icalproperty *p = icalproperty_new_attach(attach); if (!att->mimeType().isEmpty()) icalproperty_add_parameter(p,icalparameter_new_fmttype(att->mimeType().utf8().data())); if (att->isBinary()) { icalproperty_add_parameter(p,icalparameter_new_value(ICAL_VALUE_BINARY)); icalproperty_add_parameter(p,icalparameter_new_encoding(ICAL_ENCODING_BASE64)); } return p; } icalproperty *ICalFormatImpl::writeRecurrenceRule(Recurrence *recur) { // kdDebug(5800) << "ICalFormatImpl::writeRecurrenceRule()" << endl; icalrecurrencetype r; icalrecurrencetype_clear(&r); int index = 0; int index2 = 0; QPtrList tmpPositions; QPtrList tmpDays; int *tmpDay; Recurrence::rMonthPos *tmpPos; bool datetime = false; int day; int i; switch(recur->doesRecur()) { case Recurrence::rMinutely: r.freq = ICAL_MINUTELY_RECURRENCE; datetime = true; break; case Recurrence::rHourly: r.freq = ICAL_HOURLY_RECURRENCE; datetime = true; break; case Recurrence::rDaily: r.freq = ICAL_DAILY_RECURRENCE; break; case Recurrence::rWeekly: r.freq = ICAL_WEEKLY_RECURRENCE; r.week_start = static_cast(recur->weekStart()%7 + 1); for (i = 0; i < 7; i++) { if (recur->days().testBit(i)) { day = (i + 1)%7 + 1; // convert from Monday=0 to Sunday=1 r.by_day[index++] = icalrecurrencetype_day_day_of_week(day); } } // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; case Recurrence::rMonthlyPos: r.freq = ICAL_MONTHLY_RECURRENCE; 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[index++] = day; } } } // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; case Recurrence::rMonthlyDay: r.freq = ICAL_MONTHLY_RECURRENCE; tmpDays = recur->monthDays(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_month_day[index++] = icalrecurrencetype_day_position(*tmpDay*8); } // r.by_day[index] = ICAL_RECURRENCE_ARRAY_MAX; break; case Recurrence::rYearlyMonth: case Recurrence::rYearlyPos: r.freq = ICAL_YEARLY_RECURRENCE; tmpDays = recur->yearNums(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_month[index++] = *tmpDay; } // 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; } else { tmpDays = recur->monthDays(); for (tmpDay = tmpDays.first(); tmpDay; tmpDay = tmpDays.next()) { r.by_month_day[index2++] = icalrecurrencetype_day_position(*tmpDay*8); } // r.by_month_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; icalattachtype *attach = 0; switch (alarm->type()) { case Alarm::Procedure: action = ICAL_ACTION_PROCEDURE; attach = icalattachtype_new(); icalattachtype_set_url(attach,QFile::encodeName(alarm->programFile()).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); icalattachtype_free(attach); if (!alarm->programArguments().isEmpty()) { icalcomponent_add_property(a,icalproperty_new_description(alarm->programArguments().utf8())); } break; case Alarm::Audio: action = ICAL_ACTION_AUDIO; if (!alarm->audioFile().isEmpty()) { attach = icalattachtype_new(); icalattachtype_set_url(attach,QFile::encodeName( alarm->audioFile() ).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); icalattachtype_free(attach); } break; case Alarm::Email: { action = ICAL_ACTION_EMAIL; QValueList addresses = alarm->mailAddresses(); for (QValueList::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 = icalattachtype_new(); icalattachtype_set_url(attach,QFile::encodeName( *at ).data()); icalcomponent_add_property(a,icalproperty_new_attach(attach)); icalattachtype_free(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 custom = alarm->customProperties(); for (QMap::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: // related event (parent) event->setRelatedToUid(QString::fromUtf8(icalproperty_get_relatedto(p))); mEventsRelate.append(event); break; case ICAL_TRANSP_PROPERTY: // Transparency transparency = QString::fromUtf8(icalproperty_get_transp(p)); if( transparency == "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) { icalattachtype *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); if (v == ICAL_VALUE_BINARY && e == ICAL_ENCODING_BASE64) attachment = new Attachment(icalattachtype_get_base64(a)); else if ((v == ICAL_VALUE_NONE || v == ICAL_VALUE_URI) && (e == ICAL_ENCODING_NONE || e == ICAL_ENCODING_8BIT)) { attachment = new Attachment(QString(icalattachtype_get_url(a))); } else { kdWarning(5800) << "Unsupported attachment format, discarding it!" << endl; return 0; } icalparameter *p = icalproperty_get_first_parameter(attach, ICAL_FMTTYPE_PARAMETER); if (p) attachment->setMimeType(QString(icalparameter_get_fmttype(p))); return attachment; } void ICalFormatImpl::readIncidence(icalcomponent *parent,Incidence *incidence) { readIncidenceBase(parent,incidence); icalproperty *p = icalcomponent_get_first_property(parent,ICAL_ANY_PROPERTY); const char *text; int intvalue; icaltimetype icaltime; icaldurationtype icalduration; 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_LOCATION_PROPERTY: // location text = icalproperty_get_location(p); incidence->setLocation(QString::fromUtf8(text)); 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: readRecurrenceRule(p,incidence); break; case ICAL_EXDATE_PROPERTY: icaltime = icalproperty_get_exdate(p); incidence->addExDate(readICalDate(icaltime)); break; case ICAL_CLASS_PROPERTY: text = icalproperty_get_class(p); if (strcmp(text,"PUBLIC") == 0) { incidence->setSecrecy(Incidence::SecrecyPublic); } else if (strcmp(text,"CONFIDENTIAL") == 0) { 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); } // 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()); } // Now that recurrence and exception stuff is completely set up, // do any backwards compatibility adjustments. mCompat->fixRecurrence( incidence ); // 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 customProperties; icalproperty *p = icalcomponent_get_first_property(parent,ICAL_X_PROPERTY); while (p) { QString value = QString::fromUtf8(icalproperty_get_x(p)); customProperties[icalproperty_get_name(p)] = value; p = icalcomponent_get_next_property(parent,ICAL_X_PROPERTY); } properties->setCustomProperties(customProperties); } void ICalFormatImpl::readRecurrenceRule(icalproperty *rrule,Incidence *incidence) { // kdDebug(5800) << "Read recurrence for " << incidence->summary() << endl; Recurrence *recur = incidence->recurrence(); recur->setCompatVersion(mCalendarVersion); recur->unsetRecurs(); struct icalrecurrencetype r = icalproperty_get_rrule(rrule); dumpIcalRecurrence(r); readRecurrence( r, recur ); } void ICalFormatImpl::readRecurrence( const struct icalrecurrencetype &r, Recurrence* recur ) { int wkst; int index = 0; short day = 0; QBitArray qba(7); switch (r.freq) { case ICAL_MINUTELY_RECURRENCE: if (!icaltime_is_null_time(r.until)) { recur->setMinutely(r.interval,readICalDateTime(r.until)); } else { if (r.count == 0) recur->setMinutely(r.interval,-1); else recur->setMinutely(r.interval,r.count); } break; case ICAL_HOURLY_RECURRENCE: if (!icaltime_is_null_time(r.until)) { recur->setHourly(r.interval,readICalDateTime(r.until)); } else { if (r.count == 0) recur->setHourly(r.interval,-1); else recur->setHourly(r.interval,r.count); } break; case ICAL_DAILY_RECURRENCE: if (!icaltime_is_null_time(r.until)) { recur->setDaily(r.interval,readICalDate(r.until)); } else { if (r.count == 0) recur->setDaily(r.interval,-1); else recur->setDaily(r.interval,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(r.interval,qba,readICalDate(r.until),wkst); } else { if (r.count == 0) recur->setWeekly(r.interval,qba,-1,wkst); else recur->setWeekly(r.interval,qba,r.count,wkst); } 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,r.interval, readICalDate(r.until)); } else { if (r.count == 0) recur->setMonthly(Recurrence::rMonthlyPos,r.interval,-1); else recur->setMonthly(Recurrence::rMonthlyPos,r.interval,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,r.interval, readICalDate(r.until)); } else { if (r.count == 0) recur->setMonthly(Recurrence::rMonthlyDay,r.interval,-1); else recur->setMonthly(Recurrence::rMonthlyDay,r.interval,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) { if (!icaltime_is_null_time(r.until)) { recur->setYearly(Recurrence::rYearlyDay,r.interval, readICalDate(r.until)); } else { if (r.count == 0) recur->setYearly(Recurrence::rYearlyDay,r.interval,-1); else recur->setYearly(Recurrence::rYearlyDay,r.interval,r.count); } while((day = r.by_year_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { recur->addYearlyNum(day); } } if (r.by_month[0] != ICAL_RECURRENCE_ARRAY_MAX) { if (r.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX) { if (!icaltime_is_null_time(r.until)) { recur->setYearly(Recurrence::rYearlyPos,r.interval, readICalDate(r.until)); } else { if (r.count == 0) recur->setYearly(Recurrence::rYearlyPos,r.interval,-1); else recur->setYearly(Recurrence::rYearlyPos,r.interval,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 { if (!icaltime_is_null_time(r.until)) { recur->setYearly(Recurrence::rYearlyMonth,r.interval, readICalDate(r.until)); } else { if (r.count == 0) recur->setYearly(Recurrence::rYearlyMonth,r.interval,-1); else recur->setYearly(Recurrence::rYearlyMonth,r.interval,r.count); } while((day = r.by_month_day[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { recur->addMonthlyDay(day); } } index = 0; while((day = r.by_month[index++]) != ICAL_RECURRENCE_ARRAY_MAX) { recur->addYearlyNum(day); } } break; default: kdDebug(5800) << "Unknown type of recurrence: " << r.freq << endl; 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); Alarm::Type type = Alarm::Display; icalproperty_action action; if ( !p ) { kdDebug(5800) << "Unknown type of alarm, using default" << endl; // return; } else { action = icalproperty_get_action(p); 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: kdDebug(5800) << "Unknown type of alarm: " << action << endl; // type = Alarm::Invalid; } } 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: { icalattachtype *attach = icalproperty_get_attach(p); QString url = QFile::decodeName(icalattachtype_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 &datetime) { icaltimetype t; 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(); t.is_date = 0; t.zone = 0; t.is_utc = 0; if ( mParent->utc() ) { 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) { /* kdDebug(5800) << "ICalFormatImpl::readICalDateTime()" << endl; kdDebug(5800) << "--- Y: " << t.year << " M: " << t.month << " D: " << t.day << endl; kdDebug(5800) << "--- H: " << t.hour << " M: " << t.minute << " S: " << t.second << endl; kdDebug(5800) << "--- isDate: " << t.is_date << endl; */ if (t.is_utc) { // kdDebug(5800) << "--- Converting time to zone '" << cal->timeZoneId() << "'." << endl; if (mParent->timeZoneId().isEmpty()) t = icaltime_as_zone(t, 0); else t = icaltime_as_zone(t,mParent->timeZoneId().local8Bit()); } return QDateTime(QDate(t.year,t.month,t.day), QTime(t.hour,t.minute,t.second)); } QDate ICalFormatImpl::readICalDate(icaltimetype t) { return QDate(t.year,t.month,t.day); } icaldurationtype ICalFormatImpl::writeICalDuration(int seconds) { icaldurationtype d; d.weeks = seconds % gSecondsPerWeek; seconds -= d.weeks * gSecondsPerWeek; d.days = seconds % gSecondsPerDay; seconds -= d.days * gSecondsPerDay; d.hours = seconds % gSecondsPerHour; seconds -= d.hours * gSecondsPerHour; d.minutes = seconds % gSecondsPerMinute; seconds -= d.minutes * gSecondsPerMinute; d.seconds = seconds; d.is_neg = 0; 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(_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) { kdDebug(5800) << "No PRODID property found" << endl; // 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.latin1()); kdDebug(5800) << "VCALENDAR prodid: '" << mLoadedProductId << "'" << endl; 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) { kdDebug(5800) << "No VERSION property found" << endl; mParent->setException(new ErrorFormat(ErrorFormat::CalVersionUnknown)); return false; } else { const char *version = icalproperty_get_version(p); kdDebug(5800) << "VCALENDAR version: '" << version << "'" << endl; if (strcmp(version,"1.0") == 0) { kdDebug(5800) << "Expected iCalendar, got vCalendar" << endl; mParent->setException(new ErrorFormat(ErrorFormat::CalVersion1, i18n("Expected iCalendar format"))); return false; } else if (strcmp(version,"2.0") != 0) { kdDebug(5800) << "Expected iCalendar, got unknown format" << endl; 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); kdDebug(5800) << "skipping pilot-deleted event" << endl; 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 { kdDebug(5800) << "Ignoring unknown vObject \"" << vObjectName(curVO) << "\"" << endl; } SKIP: ; } // while #endif // Post-Process list of events with relations, put Event objects in relation Event::List::ConstIterator eIt; for ( eIt = mEventsRelate.begin(); eIt != mEventsRelate.end(); ++eIt ) { (*eIt)->setRelatedTo( cal->event( (*eIt)->relatedToUid() ) ); } Todo::List::ConstIterator tIt; for ( tIt = mTodosRelate.begin(); tIt != mTodosRelate.end(); ++tIt ) { (*tIt)->setRelatedTo( cal->todo( (*tIt)->relatedToUid() ) ); } 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; kdDebug(5800) << " Freq: " << r.freq << endl; kdDebug(5800) << " Until: " << icaltime_as_ctime(r.until) << endl; kdDebug(5800) << " Count: " << r.count << endl; 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) + " "); } kdDebug(5800) << out << endl; } 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) + " "); } kdDebug(5800) << out << endl; } 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) + " "); } kdDebug(5800) << out << endl; } 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) + " "); } kdDebug(5800) << out << endl; } 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) { kdDebug(5800) << "========= " << i << endl; out.append(QString::number(i) + " "); } kdDebug(5800) << out << endl; } } 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: kdDebug(5800) << "ICalFormat::createScheduleMessage(): Unknow method" << endl; return message; } icalcomponent_add_property(message,icalproperty_new_method(icalmethod)); // TODO: check, if dynamic cast is required if(incidence->type() == "Todo") { Todo *todo = static_cast(incidence); icalcomponent_add_component(message,writeTodo(todo)); } if(incidence->type() == "Event") { Event *event = static_cast(incidence); icalcomponent_add_component(message,writeEvent(event)); } if(incidence->type() == "FreeBusy") { FreeBusy *freebusy = static_cast(incidence); icalcomponent_add_component(message,writeFreeBusy(freebusy, method)); } return message; } diff --git a/kcal/incidence.cpp b/kcal/incidence.cpp index 58aa6e348..2941ea084 100644 --- a/kcal/incidence.cpp +++ b/kcal/incidence.cpp @@ -1,490 +1,507 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "calformat.h" #include "incidence.h" using namespace KCal; Incidence::Incidence() : IncidenceBase(), - mRelatedTo(0), mSecrecy(SecrecyPublic), mPriority(3) + mRelatedTo(0), mSecrecy(SecrecyPublic), mPriority(3), mRecurrence(0) { - mRecurrence = new Recurrence(this); - recreate(); mAlarms.setAutoDelete(true); mAttachments.setAutoDelete(true); } 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; // Incidence::List mRelations; Incidence::List mRelations; mExDates = i.mExDates; mAttachments = i.mAttachments; mResources = i.mResources; mSecrecy = i.mSecrecy; mPriority = i.mPriority; mLocation = i.mLocation; Alarm::List::ConstIterator it; for( it = i.mAlarms.begin(); it != i.mAlarms.end(); ++it ) { Alarm *b = new Alarm( **it ); b->setParent( this ); mAlarms.append( b ); } mAlarms.setAutoDelete(true); - mRecurrence = new Recurrence( *(i.mRecurrence), this ); + if (i.mRecurrence) + mRecurrence = new Recurrence( *(i.mRecurrence), this ); + else + mRecurrence = 0; } Incidence::~Incidence() { List::ConstIterator it; for ( it = mRelations.begin(); it != mRelations.end(); ++it ) { if ( (*it)->relatedTo() == this ) (*it)->setRelatedTo( 0 ); } if ( relatedTo() ) relatedTo()->removeRelation( this ); delete mRecurrence; } // 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 ) +bool Incidence::operator==( const Incidence& i2 ) const { - if( i1.alarms().count() != i2.alarms().count() ) { + if( alarms().count() != i2.alarms().count() ) { return false; // no need to check further } - Alarm::List::ConstIterator a1 = i1.alarms().begin(); + Alarm::List::ConstIterator a1 = alarms().begin(); Alarm::List::ConstIterator a2 = i2.alarms().begin(); - for( ; a1 != i1.alarms().end() && a2 != i2.alarms().end(); ++a1, ++a2 ) + for( ; a1 != alarms().end() && a2 != i2.alarms().end(); ++a1, ++a2 ) if( **a1 == **a2 ) continue; else { return false; } - if ( ! operator==( (const IncidenceBase&)i1, (const IncidenceBase&)i2 ) ) + if ( !( static_cast(*this) == static_cast(i2) ) ) return false; + bool recurrenceEqual = ( mRecurrence == 0 && i2.mRecurrence == 0 ); + if ( !recurrenceEqual ) + { + recurrenceEqual = mRecurrence != 0 && + i2.mRecurrence != 0 && + *mRecurrence == *i2.mRecurrence; + } + return - i1.created() == i2.created() && - stringCompare( i1.description(), i2.description() ) && - stringCompare( i1.summary(), i2.summary() ) && - i1.categories() == i2.categories() && + recurrenceEqual && + created() == i2.created() && + stringCompare( description(), i2.description() ) && + stringCompare( summary(), i2.summary() ) && + 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.recurrence() == *i2.recurrence() && - stringCompare( i1.location(), i2.location() ); + stringCompare( relatedToUid(), i2.relatedToUid() ) && + relations() == i2.relations() && + exDates() == i2.exDates() && + attachments() == i2.attachments() && + resources() == i2.resources() && + secrecy() == i2.secrecy() && + priority() == i2.priority() && + stringCompare( location(), i2.location() ); } void Incidence::recreate() { setCreated(QDateTime::currentDateTime()); setUid(CalFormat::createUniqueId()); setRevision(0); setLastModified(QDateTime::currentDateTime()); } void Incidence::setReadOnly( bool readOnly ) { IncidenceBase::setReadOnly( readOnly ); - recurrence()->setRecurReadOnly( readOnly); + if (mRecurrence) + mRecurrence->setRecurReadOnly(readOnly); } void Incidence::setCreated(QDateTime created) { if (mReadOnly) return; mCreated = 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) { - recurrence()->setRecurStart( dtStart); + if (mRecurrence) + mRecurrence->setRecurStart( dtStart); IncidenceBase::setDtStart( dtStart ); } 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::setCategories(const QStringList &categories) { if (mReadOnly) return; mCategories = categories; updated(); } // 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(); } updated(); } QStringList Incidence::categories() const { return mCategories; } QString Incidence::categoriesStr() { 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) { if (mReadOnly || mRelatedTo == relatedTo) return; if(mRelatedTo) mRelatedTo->removeRelation(this); mRelatedTo = relatedTo; if (mRelatedTo) mRelatedTo->addRelation(this); } Incidence *Incidence::relatedTo() const { return mRelatedTo; } Incidence::List Incidence::relations() const { return mRelations; } void Incidence::addRelation( Incidence *event ) { if ( mRelations.find( event ) == mRelations.end() ) { 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; + return (mRecurrence && mRecurrence->recursOnPure(qd) && !isException(qd)); } void Incidence::setExDates(const DateList &exDates) { if (mReadOnly) return; mExDates = exDates; updated(); } void Incidence::addExDate(const QDate &date) { if (mReadOnly) return; mExDates.append(date); 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(); } } Attachment::List Incidence::attachments() const { return mAttachments; } Attachment::List Incidence::attachments(const QString& mime) const { Attachment::List attachments; QPtrListIterator 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; } const Alarm::List &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::List::ConstIterator it; for( it = mAlarms.begin(); it != mAlarms.end(); ++it ) { if ( (*it)->enabled() ) return true; } return false; } Recurrence *Incidence::recurrence() const { + if (!mRecurrence) + { + const_cast(this)->mRecurrence = new Recurrence(const_cast(this)); + mRecurrence->setRecurReadOnly(mReadOnly); + mRecurrence->setRecurStart(dtStart()); + } + return mRecurrence; } 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; } diff --git a/kcal/incidence.h b/kcal/incidence.h index c2b29395b..88443e32f 100644 --- a/kcal/incidence.h +++ b/kcal/incidence.h @@ -1,307 +1,307 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef INCIDENCE_H #define INCIDENCE_H // // Incidence - base class of calendaring components // #include #include #include #include "recurrence.h" #include "alarm.h" #include "attachment.h" #include "incidencebase.h" namespace KCal { class Event; class Todo; class Journal; /** This class provides the base class common to all calendar components. */ class Incidence : public IncidenceBase { public: /** This class provides the interface for a visitor of calendar components. It serves as base class for concrete visitors, which implement certain actions on calendar components. It allows to add functions, which operate on the concrete types of calendar components, without changing the calendar component classes. */ class Visitor { public: /** Destruct Incidence::Visitor */ virtual ~Visitor() {} /** Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions on an Event object. */ virtual bool visit(Event *) { return false; } /** Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions on an Todo object. */ virtual bool visit(Todo *) { return false; } /** Reimplement this function in your concrete subclass of IncidenceVisitor to perform actions on an Journal object. */ virtual bool visit(Journal *) { return false; } protected: /** Constructor is protected to prevent direct creation of visitor base class. */ Visitor() {} }; /** This class implements a visitor for adding an Incidence to a resource supporting addEvent(), addTodo() and addJournal() calls. */ template class AddVisitor : public Visitor { public: AddVisitor( T *r ) : mResource( r ) {} bool visit( Event *e ) { return mResource->addEvent( e ); } bool visit( Todo *t ) { return mResource->addTodo( t ); } bool visit( Journal *j ) { return mResource->addJournal( j ); } private: T *mResource; }; /** This class implements a visitor for deleting an Incidence from a resource supporting deleteEvent(), deleteTodo() and deleteJournal() calls. */ template class DeleteVisitor : public Visitor { public: DeleteVisitor( T *r ) : mResource( r ) {} bool visit( Event *e ) { mResource->deleteEvent( e ); return true; } bool visit( Todo *t ) { mResource->deleteTodo( t ); return true; } bool visit( Journal *j ) { mResource->deleteJournal( j ); return true; } private: T *mResource; }; /** enumeration for describing an event's secrecy. */ enum { SecrecyPublic = 0, SecrecyPrivate = 1, SecrecyConfidential = 2 }; typedef ListBase List; Incidence(); Incidence(const Incidence &); ~Incidence(); + bool operator==( const Incidence& ) const; + /** Accept IncidenceVisitor. A class taking part in the visitor mechanism has to provide this implementation:
         bool accept(Visitor &v) { return v.visit(this); }
       
*/ virtual bool accept(Visitor &) { return false; } virtual Incidence *clone() = 0; void setReadOnly( bool ); /** Recreate event. The event is made a new unique event, but already stored event information is preserved. Sets uniquie id, creation date, last modification date and revision number. */ void recreate(); /** set creation date */ void setCreated(QDateTime); /** return time and date of cration. */ QDateTime created() const; /** set the number of revisions this event has seen */ void setRevision(int rev); /** return the number of revisions this event has seen */ int revision() const; /** Set starting date/time. */ virtual void setDtStart(const QDateTime &dtStart); /** Return the incidence's ending date/time as a QDateTime. */ virtual QDateTime dtEnd() const { return QDateTime(); } /** sets the event's lengthy description. */ void setDescription(const QString &description); /** returns a reference to the event's description. */ QString description() const; /** sets the event's short summary. */ void setSummary(const QString &summary); /** returns a reference to the event's summary. */ QString summary() const; /** set event's applicable categories */ void setCategories(const QStringList &categories); /** set event's categories based on a comma delimited string */ void setCategories(const QString &catStr); /** return categories in a list */ QStringList categories() const; /** return categories as a comma separated string */ QString categoriesStr(); /** point at some other event to which the event relates. This function should * only be used when constructing a calendar before the related Event * exists. */ void setRelatedToUid(const QString &); /** what event does this one relate to? This function should * only be used when constructing a calendar before the related Event * exists. */ QString relatedToUid() const; /** point at some other event to which the event relates */ void setRelatedTo(Incidence *relatedTo); /** what event does this one relate to? */ Incidence *relatedTo() const; /** All events that are related to this event */ Incidence::List relations() const; /** Add an event which is related to this event */ void addRelation(Incidence *); /** Remove event that is related to this event */ void removeRelation(Incidence *); /** returns the list of dates which are exceptions to the recurrence rule */ DateList exDates() const; /** sets the list of dates which are exceptions to the recurrence rule */ void setExDates(const DateList &_exDates); void setExDates(const char *dates); /** Add a date to the list of exceptions of the recurrence rule. */ void addExDate(const QDate &date); /** returns true if there is an exception for this date in the recurrence rule set, or false otherwise. */ bool isException(const QDate &qd) const; /** add attachment to this event */ void addAttachment(Attachment *attachment); /** remove and delete a specific attachment */ void deleteAttachment(Attachment *attachment); /** remove and delete all attachments with this mime type */ void deleteAttachments(const QString& mime); /** return list of all associated attachments */ Attachment::List attachments() const; /** find a list of attachments with this mime type */ Attachment::List attachments(const QString& mime) const; /** sets the event's status the value specified. See the enumeration * above for possible values. */ void setSecrecy(int); /** return the event's secrecy. */ int secrecy() const; /** return the event's secrecy in string format. */ QString secrecyStr() const; /** return list of all availbale secrecy classes */ static QStringList secrecyList(); /** return human-readable name of secrecy class */ static QString secrecyName(int); /** returns TRUE if the date specified is one on which the event will * recur. */ bool recursOn(const QDate &qd) const; // VEVENT and VTODO, but not VJOURNAL (move to EventBase class?): /** set resources used, such as Office, Car, etc. */ void setResources(const QStringList &resources); /** return list of current resources */ QStringList resources() const; /** set the event's priority, 0 is undefined, 1 highest (decreasing order) */ void setPriority(int priority); /** get the event's priority */ int priority() const; /** All alarms that are associated with this incidence */ const Alarm::List &alarms() const; /** Create a new alarm which is associated with this incidence */ Alarm *newAlarm(); /** Add an alarm which is associated with this incidence */ void addAlarm( Alarm * ); /** Remove an alarm that is associated with this incidence */ void removeAlarm( Alarm * ); /** Remove all alarms that are associated with this incidence */ void clearAlarms(); /** return whether any alarm associated with this incidence is enabled */ bool isAlarmEnabled() const; /** Return the recurrence rule associated with this incidence. If there is none, returns an appropriate (non-0) object. */ Recurrence *recurrence() const; /** Forward to Recurrence::doesRecur(). */ ushort doesRecur() const; /** set the event's/todo's location. Do _not_ use it with journal */ void setLocation(const QString &location); /** return the event's/todo's location. Do _not_ use it with journal */ QString location() const; private: int mRevision; // base components of jounal, event and todo QDateTime mCreated; QString mDescription; QString mSummary; QStringList mCategories; Incidence *mRelatedTo; QString mRelatedToUid; Incidence::List mRelations; DateList mExDates; Attachment::List mAttachments; QStringList mResources; int mSecrecy; int mPriority; // 1 = highest, 2 = less, etc. Alarm::List mAlarms; Recurrence *mRecurrence; QString mLocation; }; -bool operator==( const Incidence&, const Incidence& ); - } #endif diff --git a/kcal/incidencebase.cpp b/kcal/incidencebase.cpp index 4ebca4fb6..412ce1823 100644 --- a/kcal/incidencebase.cpp +++ b/kcal/incidencebase.cpp @@ -1,317 +1,317 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "calformat.h" #include "incidencebase.h" using namespace KCal; IncidenceBase::IncidenceBase() : mReadOnly(false), mFloats(true), mDuration(0), mHasDuration(false), mPilotId(0), mSyncStatus(SYNCMOD) { setUid(CalFormat::createUniqueId()); mAttendees.setAutoDelete( true ); } IncidenceBase::IncidenceBase(const IncidenceBase &i) : CustomProperties( i ) { mReadOnly = i.mReadOnly; mDtStart = i.mDtStart; mDuration = i.mDuration; mHasDuration = i.mHasDuration; mOrganizer = i.mOrganizer; mUid = i.mUid; Attendee::List attendees = i.attendees(); Attendee::List::ConstIterator it; for( it = attendees.begin(); it != attendees.end(); ++it ) { mAttendees.append( new Attendee( *(*it) ) ); } mFloats = i.mFloats; mLastModified = i.mLastModified; mPilotId = i.mPilotId; mSyncStatus = i.mSyncStatus; // The copied object is a new one, so it isn't observed by the observer // of the original object. mObservers.clear(); mAttendees.setAutoDelete( true ); } IncidenceBase::~IncidenceBase() { } -bool KCal::operator==( const IncidenceBase& i1, const IncidenceBase& i2 ) +bool IncidenceBase::operator==( const IncidenceBase& i2 ) const { - if( i1.attendees().count() != i2.attendees().count() ) { + if( attendees().count() != i2.attendees().count() ) { return false; // no need to check further } - Attendee::List al1 = i1.attendees(); + Attendee::List al1 = attendees(); Attendee::List al2 = i2.attendees(); Attendee::List::ConstIterator a1 = al1.begin(); Attendee::List::ConstIterator a2 = al2.begin(); for( ; a1 != al1.end() && a2 != al2.end(); ++a1, ++a2 ) if( **a1 == **a2 ) continue; else { return false; } - return ( i1.dtStart() == i2.dtStart() && - i1.organizer() == i2.organizer() && - i1.uid() == i2.uid() && + return ( dtStart() == i2.dtStart() && + organizer() == i2.organizer() && + uid() == i2.uid() && // Don't compare lastModified, otherwise the operator is not // of much use. We are not comparing for identity, after all. - i1.doesFloat() == i2.doesFloat() && - i1.duration() == i2.duration() && - i1.hasDuration() == i2.hasDuration() && - i1.pilotId() == i2.pilotId() && - i1.syncStatus() == i2.syncStatus() ); + doesFloat() == i2.doesFloat() && + duration() == i2.duration() && + hasDuration() == i2.hasDuration() && + pilotId() == i2.pilotId() && + syncStatus() == i2.syncStatus() ); // no need to compare mObserver } void IncidenceBase::setUid(const QString &uid) { mUid = uid; updated(); } QString IncidenceBase::uid() const { return mUid; } void IncidenceBase::setLastModified(const QDateTime &lm) { // DON'T! updated() because we call this from // Calendar::updateEvent(). mLastModified = lm; } QDateTime IncidenceBase::lastModified() const { return mLastModified; } void IncidenceBase::setOrganizer(const QString &o) { // we don't check for readonly here, because it is // possible that by setting the organizer we are changing // the event's readonly status... mOrganizer = o; if (mOrganizer.left(7).upper() == "MAILTO:") mOrganizer = mOrganizer.remove(0,7); updated(); } QString IncidenceBase::organizer() const { return mOrganizer; } void IncidenceBase::setReadOnly( bool readOnly ) { mReadOnly = readOnly; } void IncidenceBase::setDtStart(const QDateTime &dtStart) { // if (mReadOnly) return; mDtStart = dtStart; updated(); } QDateTime IncidenceBase::dtStart() const { return mDtStart; } QString IncidenceBase::dtStartTimeStr() const { return KGlobal::locale()->formatTime(dtStart().time()); } QString IncidenceBase::dtStartDateStr(bool shortfmt) const { return KGlobal::locale()->formatDate(dtStart().date(),shortfmt); } QString IncidenceBase::dtStartStr() const { return KGlobal::locale()->formatDateTime(dtStart()); } bool IncidenceBase::doesFloat() const { return mFloats; } void IncidenceBase::setFloats(bool f) { if (mReadOnly) return; mFloats = f; updated(); } void IncidenceBase::addAttendee(Attendee *a, bool doupdate) { // kdDebug(5800) << "IncidenceBase::addAttendee()" << endl; if (mReadOnly) return; // kdDebug(5800) << "IncidenceBase::addAttendee() weiter" << endl; if (a->name().left(7).upper() == "MAILTO:") a->setName(a->name().remove(0,7)); mAttendees.append(a); if (doupdate) updated(); } #if 0 void IncidenceBase::removeAttendee(Attendee *a) { if (mReadOnly) return; mAttendees.removeRef(a); updated(); } void IncidenceBase::removeAttendee(const char *n) { Attendee *a; if (mReadOnly) return; for (a = mAttendees.first(); a; a = mAttendees.next()) if (a->getName() == n) { mAttendees.remove(); break; } } #endif void IncidenceBase::clearAttendees() { if (mReadOnly) return; mAttendees.clear(); } Attendee *IncidenceBase::attendeeByMail( const QString &email ) { Attendee::List::ConstIterator it; for( it = mAttendees.begin(); it != mAttendees.end(); ++it ) { if ( (*it)->email() == email ) return *it; } return 0; } Attendee *IncidenceBase::attendeeByMails( const QStringList &emails, const QString& email) { QStringList mails = emails; if ( !email.isEmpty() ) mails.append( email ); Attendee::List::ConstIterator itA; for( itA = mAttendees.begin(); itA != mAttendees.end(); ++itA ) { for ( QStringList::Iterator it = mails.begin(); it != mails.end(); ++it ) { if ( (*itA)->email() == email ) return *itA; } } return 0; } void IncidenceBase::setDuration(int seconds) { mDuration = seconds; setHasDuration(true); } int IncidenceBase::duration() const { return mDuration; } void IncidenceBase::setHasDuration(bool) { mHasDuration = true; } bool IncidenceBase::hasDuration() const { return mHasDuration; } void IncidenceBase::setSyncStatus(int stat) { if (mReadOnly) return; mSyncStatus = stat; } int IncidenceBase::syncStatus() const { return mSyncStatus; } void IncidenceBase::setPilotId( int id ) { if (mReadOnly) return; mPilotId = id; } int IncidenceBase::pilotId() const { return mPilotId; } void IncidenceBase::registerObserver( IncidenceBase::Observer *observer ) { if( !mObservers.contains(observer) ) mObservers.append( observer ); } void IncidenceBase::unRegisterObserver( IncidenceBase::Observer *observer ) { mObservers.remove( observer ); } void IncidenceBase::updated() { QPtrListIterator it(mObservers); while( it.current() ) { Observer *o = it.current(); ++it; o->incidenceUpdated( this ); } } diff --git a/kcal/incidencebase.h b/kcal/incidencebase.h index 56c62cfa9..24abe8489 100644 --- a/kcal/incidencebase.h +++ b/kcal/incidencebase.h @@ -1,160 +1,160 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef KCAL_INCIDENCEBASE_H #define KCAL_INCIDENCEBASE_H // // Incidence - base class of calendaring components // #include #include #include #include #include "customproperties.h" #include "attendee.h" namespace KCal { typedef QValueList DateList; typedef QValueList DateTimeList; /** 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(); + bool operator==( const IncidenceBase& ) const; virtual QCString type() 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. */ 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() 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. */ void addAttendee(Attendee *a, bool doupdate=true ); // void removeAttendee(Attendee *a); // void removeAttendee(const char *n); /** Remove all Attendees. */ void clearAttendees(); /** Return list of attendees. */ const Attendee::List &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 registerObserver( Observer * ); void unRegisterObserver( Observer * ); void updated(); protected: bool mReadOnly; private: // base components QDateTime mDtStart; QString mOrganizer; QString mUid; QDateTime mLastModified; Attendee::List mAttendees; bool mFloats; int mDuration; bool mHasDuration; // PILOT SYNCHRONIZATION STUFF int mPilotId; // unique id for pilot sync int mSyncStatus; // status (for sync) QPtrList mObservers; }; -bool operator==( const IncidenceBase&, const IncidenceBase& ); } #endif diff --git a/kcal/journal.cpp b/kcal/journal.cpp index 90a4b9407..6cd37e1c2 100644 --- a/kcal/journal.cpp +++ b/kcal/journal.cpp @@ -1,43 +1,43 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "journal.h" using namespace KCal; Journal::Journal() { } Journal::~Journal() { } Journal *Journal::clone() { return new Journal( *this ); } -bool KCal::operator==( const Journal& j1, const Journal& j2 ) +bool Journal::operator==( const Journal& j2 ) const { - return operator==( (const Incidence&)j1, (const Incidence&)j2 ); + return static_cast(*this) == static_cast(j2); } diff --git a/kcal/journal.h b/kcal/journal.h index 00a138008..129650a11 100644 --- a/kcal/journal.h +++ b/kcal/journal.h @@ -1,49 +1,49 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #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: typedef ListBase List; Journal(); ~Journal(); + bool operator==( const Journal& ) const; QCString type() const { return "Journal"; } Journal *clone(); }; - bool operator==( const Journal&, const Journal& ); } #endif diff --git a/kcal/scheduler.cpp b/kcal/scheduler.cpp index 26e27ca61..ad432e4c9 100644 --- a/kcal/scheduler.cpp +++ b/kcal/scheduler.cpp @@ -1,357 +1,357 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include "event.h" #include "todo.h" #include "freebusy.h" #include "icalformat.h" #include "calendar.h" #include "scheduler.h" using namespace KCal; ScheduleMessage::ScheduleMessage(IncidenceBase *incidence,int method,ScheduleMessage::Status status) { mIncidence = incidence; mMethod = method; mStatus = status; } QString ScheduleMessage::statusName(ScheduleMessage::Status status) { switch (status) { case PublishNew: return i18n("Publish"); case Obsolete: return i18n("Obsolete"); case RequestNew: return i18n("New Request"); case RequestUpdate: return i18n("Updated Request"); default: return i18n("Unknown Status: %1").arg(QString::number(status)); } } Scheduler::Scheduler(Calendar *calendar) { mCalendar = calendar; mFormat = new ICalFormat(); } Scheduler::~Scheduler() { delete mFormat; } bool Scheduler::acceptTransaction(IncidenceBase *incidence,Method method,ScheduleMessage::Status status) { kdDebug() << "Scheduler::acceptTransaction " << endl; switch (method) { case Publish: return acceptPublish(incidence, status, method); case Request: return acceptRequest(incidence, status); case Add: return acceptAdd(incidence, status); case Cancel: return acceptCancel(incidence, status); case Declinecounter: return acceptDeclineCounter(incidence, status); case Reply: return acceptReply(incidence, status, method); case Refresh: return acceptRefresh(incidence, status); case Counter: return acceptCounter(incidence, status); default: deleteTransaction(incidence); return false; } deleteTransaction(incidence); return false; } QString Scheduler::methodName(Method method) { switch (method) { case Publish: return QString::fromLatin1("Publish"); case Request: return QString::fromLatin1("Request"); case Refresh: return QString::fromLatin1("Refresh"); case Cancel: return QString::fromLatin1("Cancel"); case Add: return QString::fromLatin1("Add"); case Reply: return QString::fromLatin1("Reply"); case Counter: return QString::fromLatin1("Counter"); case Declinecounter: return QString::fromLatin1("Decline Counter"); default: return QString::fromLatin1("Unknown"); } } QString Scheduler::translatedMethodName(Method method) { switch (method) { case Publish: return i18n("Publish"); case Request: return i18n("Request"); case Refresh: return i18n("Refresh"); case Cancel: return i18n("Cancel"); case Add: return i18n("Add"); case Reply: return i18n("Reply"); case Counter: return i18n("counter proposal","Counter"); case Declinecounter: return i18n("decline counter proposal","Decline Counter"); default: return i18n("Unknown"); } } bool Scheduler::deleteTransaction(IncidenceBase *) { return true; } bool Scheduler::acceptPublish(IncidenceBase *incidence,ScheduleMessage::Status status, Method method) { if(incidence->type()=="FreeBusy") { return acceptFreeBusy(incidence, method); } switch (status) { case ScheduleMessage::Unknown: case ScheduleMessage::PublishNew: if (!mCalendar->event(incidence->uid())) { Incidence *inc = static_cast(incidence); mCalendar->addIncidence(inc); deleteTransaction(incidence); } return true; case ScheduleMessage::Obsolete: return true; default: deleteTransaction(incidence); return false; } deleteTransaction(incidence); return false; } -bool Scheduler::acceptRequest(IncidenceBase *incidence,ScheduleMessage::Status status) +bool Scheduler::acceptRequest(IncidenceBase *incidence,ScheduleMessage::Status /* status */) { Incidence *inc = static_cast(incidence); if (inc->type()=="FreeBusy") { // reply to this request is handled in korganizer's incomingdialog return true; } else { Event *even = mCalendar->event(incidence->uid()); if (even) { if ( even->revision()<=inc->revision() ) { if ( even->revision()==inc->revision() && even->lastModified()>inc->lastModified()) { deleteTransaction(incidence); return false; } mCalendar->deleteEvent(even); } else { deleteTransaction(incidence); return false; } } else { Todo *todo = mCalendar->todo(incidence->uid()); if (todo) { if ( todo->revision()<=inc->revision() ) { if ( todo->revision()==inc->revision() && todo->lastModified()>inc->lastModified()) { deleteTransaction(incidence); return false; } mCalendar->deleteTodo(todo); } else { deleteTransaction(incidence); return false; } } } } mCalendar->addIncidence(inc); deleteTransaction(incidence); return true; } -bool Scheduler::acceptAdd(IncidenceBase *incidence,ScheduleMessage::Status status) +bool Scheduler::acceptAdd(IncidenceBase *incidence,ScheduleMessage::Status /* status */) { deleteTransaction(incidence); return false; } -bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status status) +bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status /* status */) { bool ret = false; Event *even = mCalendar->event(incidence->uid()); if (even) { mCalendar->deleteEvent(even); ret = true; } else { Todo *todo = mCalendar->todo(incidence->uid()); if (todo) { mCalendar->deleteTodo(todo); ret = true; } } deleteTransaction(incidence); return ret; } -bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status status) +bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */) { deleteTransaction(incidence); return false; } //bool Scheduler::acceptFreeBusy(Incidence *incidence,ScheduleMessage::Status status) //{ // deleteTransaction(incidence); // return false; //} -bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status status, Method method) +bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status /* status */, Method method) { if(incidence->type()=="FreeBusy") { return acceptFreeBusy(incidence, method); } bool ret = false; Event *ev = mCalendar->event(incidence->uid()); Todo *to = mCalendar->todo(incidence->uid()); if (ev || to) { //get matching attendee in calendar kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl; Attendee::List attendeesIn = incidence->attendees(); Attendee::List attendeesEv; if (ev) attendeesEv = ev->attendees(); if (to) attendeesEv = to->attendees(); Attendee::List::ConstIterator inIt; Attendee::List::ConstIterator evIt; for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) { Attendee *attIn = *inIt; for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) { Attendee *attEv = *evIt;; if (attIn->email()==attEv->email()) { //update attendee-info kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl; attEv->setStatus(attIn->status()); attEv->setRSVP(false); // better to not update the sequence number with replys //if (ev) ev->setRevision(ev->revision()+1); //if (to) to->setRevision(to->revision()+1); ret = true; } } } } if (ret) deleteTransaction(incidence); return ret; } -bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status status) +bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status /* status */) { // handled in korganizer's IncomingDialog deleteTransaction(incidence); return false; } -bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status status) +bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */) { deleteTransaction(incidence); return false; } bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method) { FreeBusy *freebusy = static_cast(incidence); QString freeBusyDirName = locateLocal("appdata","freebusy"); kdDebug() << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDirName << endl; QString from; if(method == Scheduler::Publish) { from = freebusy->organizer(); } if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) { Attendee *attendee = freebusy->attendees().first(); from = attendee->email(); } QDir freeBusyDir(freeBusyDirName); if (!freeBusyDir.exists()) { kdDebug() << "Directory " << freeBusyDirName << " does not exist!" << endl; kdDebug() << "Creating directory: " << freeBusyDirName << endl; if(!freeBusyDir.mkdir(freeBusyDirName, TRUE)) { kdDebug() << "Could not create directory: " << freeBusyDirName << endl; return false; } } QString filename(freeBusyDirName); filename += "/"; filename += from; filename += ".ifb"; QFile f(filename); kdDebug() << "acceptFreeBusy: filename" << filename << endl; freebusy->clearAttendees(); freebusy->setOrganizer(from); QString messageText = mFormat->createScheduleMessage(freebusy, Publish); if (!f.open(IO_ReadWrite)) { kdDebug() << "acceptFreeBusy: Can't open:" << filename << " for writing" << endl; return false; } QTextStream t(&f); t << messageText; f.close(); deleteTransaction(incidence); return true; } diff --git a/kcal/todo.cpp b/kcal/todo.cpp index bb667b737..fb6dc3730 100644 --- a/kcal/todo.cpp +++ b/kcal/todo.cpp @@ -1,258 +1,259 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "todo.h" using namespace KCal; Todo::Todo() { // mStatus = TENTATIVE; mHasDueDate = false; mHasStartDate = false; mHasCompletedDate = false; mPercentComplete = 0; } Todo::Todo(const Todo &t) : Incidence(t) { mDtDue = t.mDtDue; mHasDueDate = t.mHasDueDate; mHasStartDate = t.mHasStartDate; mCompleted = t.mCompleted; mHasCompletedDate = t.mHasCompletedDate; mPercentComplete = t.mPercentComplete; } Todo::~Todo() { } Todo *Todo::clone() { return new Todo( *this ); } -bool KCal::operator==( const Todo& t1, const Todo& t2 ) +bool Todo::operator==( const Todo& t2 ) const { - return operator==( (const Incidence&)t1, (const Incidence&)t2 ) && - t1.dtDue() == t2.dtDue() && - t1.hasDueDate() == t2.hasDueDate() && - t1.hasStartDate() == t2.hasStartDate() && - t1.completed() == t2.completed() && - t1.hasCompletedDate() == t2.hasCompletedDate() && - t1.percentComplete() == t2.percentComplete(); + return + static_cast(*this) == static_cast(t2) && + dtDue() == t2.dtDue() && + hasDueDate() == t2.hasDueDate() && + hasStartDate() == t2.hasStartDate() && + completed() == t2.completed() && + hasCompletedDate() == t2.hasCompletedDate() && + percentComplete() == t2.percentComplete(); } void Todo::setDtDue(const QDateTime &dtDue) { //int diffsecs = mDtDue.secsTo(dtDue); /*if (mReadOnly) return; const Alarm::List& alarms = alarms(); for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) { if (alarm->enabled()) { alarm->setTime(alarm->time().addSecs(diffsecs)); } }*/ mDtDue = dtDue; //kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl; /*const Alarm::List& 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() const { return KGlobal::locale()->formatDateTime(mDtDue); } bool Todo::hasDueDate() const { return mHasDueDate; } void Todo::setHasDueDate(bool f) { if (mReadOnly) return; mHasDueDate = f; updated(); } bool Todo::hasStartDate() const { return mHasStartDate; } void Todo::setHasStartDate(bool f) { if (mReadOnly) return; mHasStartDate = 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; else kdDebug(5800) << "error setting status, unknown status!" << endl; 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 (completed) mPercentComplete = 100; else mPercentComplete = 0; updated(); } QDateTime Todo::completed() const { return mCompleted; } QString Todo::completedStr() const { return KGlobal::locale()->formatDateTime(mCompleted); } void Todo::setCompleted(const QDateTime &completed) { mHasCompletedDate = true; mPercentComplete = 100; mCompleted = completed; updated(); } bool Todo::hasCompletedDate() const { return mHasCompletedDate; } int Todo::percentComplete() const { return mPercentComplete; } void Todo::setPercentComplete(int v) { mPercentComplete = v; updated(); } diff --git a/kcal/todo.h b/kcal/todo.h index 169ca7926..300b78a3b 100644 --- a/kcal/todo.h +++ b/kcal/todo.h @@ -1,127 +1,127 @@ /* This file is part of libkcal. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef TODO_H #define TODO_H // // Todo component, representing a VTODO object // #include "incidence.h" namespace KCal { /** This class provides a Todo in the sense of RFC2445. */ class Todo : public Incidence { public: typedef ListBase List; Todo(); Todo(const Todo &); ~Todo(); + bool operator==( const Todo& ) const; QCString type() const { return "Todo"; } /** Return an exact copy of this todo. */ Todo *clone(); /** 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() 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); /** returns TRUE or FALSE depending on whether the todo has a start date */ bool hasStartDate() const; /** sets the event's hasStartDate value. */ void setHasStartDate(bool f); /** 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() 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; private: bool accept(Visitor &v) { return v.visit(this); } QDateTime mDtDue; // due date of todo bool mHasDueDate; // if todo has associated due date bool mHasStartDate; // if todo has associated start date // int mStatus; // confirmed/delegated/tentative/etc QDateTime mCompleted; bool mHasCompletedDate; int mPercentComplete; }; - bool operator==( const Todo&, const Todo& ); } #endif