diff --git a/kcal/event.cpp b/kcal/event.cpp index 44e5b6efe..4a1e90ae7 100644 --- a/kcal/event.cpp +++ b/kcal/event.cpp @@ -1,278 +1,277 @@ /* This file is part of the kcal library. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and defines the Event class. @brief This class provides an Event in the sense of RFC2445. @author Cornelius Schumacher \ */ #include "event.h" +#include "incidenceformatter.h" #include #include #include #include using namespace KCal; /** Private class that helps to provide binary compatibility between releases. @internal */ //@cond PRIVATE class KCal::Event::Private { public: Private() : mHasEndDate( false ), mTransparency( Opaque ) {} Private( const KCal::Event::Private &other ) : mDtEnd( other.mDtEnd ), mHasEndDate( other.mHasEndDate ), mTransparency( other.mTransparency ) {} KDateTime mDtEnd; bool mHasEndDate; Transparency mTransparency; }; //@endcond Event::Event() : d( new KCal::Event::Private ) { } Event::Event( const Event &other ) : Incidence( other ), d( new KCal::Event::Private( *other.d ) ) { } Event::~Event() { delete d; } Event *Event::clone() { return new Event( *this ); } Event &Event::operator=( const Event &other ) { // check for self assignment if ( &other == this ) { return *this; } Incidence::operator=( other ); *d = *other.d; return *this; } bool Event::operator==( const Event &event ) const { return static_cast( *this ) == static_cast( event ) && dtEnd() == event.dtEnd() && hasEndDate() == event.hasEndDate() && transparency() == event.transparency(); } QByteArray Event::type() const { return "Event"; } void Event::setDtEnd( const KDateTime &dtEnd ) { if ( mReadOnly ) { return; } d->mDtEnd = dtEnd; setHasEndDate( true ); setHasDuration( false ); updated(); } KDateTime Event::dtEnd() const { if ( hasEndDate() ) { return d->mDtEnd; } if ( hasDuration() ) { if ( allDay() ) { // For all day events, dtEnd is always inclusive KDateTime end = duration().end( dtStart() ).addDays( -1 ); return end >= dtStart() ? end : dtStart(); } else { return duration().end( dtStart() ); } } // It is valid for a VEVENT to be without a DTEND. See RFC2445, Sect4.6.1. // Be careful to use Event::dateEnd() as appropriate due to this possibility. return dtStart(); } QDate Event::dateEnd() const { KDateTime end = dtEnd().toTimeSpec( dtStart() ); if ( allDay() ) { return end.date(); } else { return end.addSecs(-1).date(); } } QString Event::dtEndTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } - return KGlobal::locale()->formatTime( dtEnd().toTimeSpec( spec ).time(), !shortfmt ) - + timeZone; + return KGlobal::locale()->formatTime( + dtEnd().toTimeSpec( spec ).time(), !shortfmt ) + timeZone; } else { return KGlobal::locale()->formatTime( dtEnd().time(), !shortfmt ); } } QString Event::dtEndDateStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } return KGlobal::locale()->formatDate( dtEnd().toTimeSpec( spec ).date(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { return KGlobal::locale()->formatDate( dtEnd().date(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } QString Event::dtEndStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( allDay() ) { - return dtEndDateStr( shortfmt, spec ); + return IncidenceFormatter::dateToString( dtEnd(), shortfmt, spec ); } if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } return KGlobal::locale()->formatDateTime( dtEnd().toTimeSpec( spec ).dateTime(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { return KGlobal::locale()->formatDateTime( dtEnd().dateTime(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } void Event::setHasEndDate( bool b ) { d->mHasEndDate = b; } bool Event::hasEndDate() const { return d->mHasEndDate; } bool Event::isMultiDay( const KDateTime::Spec &spec ) const { // End date is non inclusive, so subtract 1 second... KDateTime start, end; if ( spec.isValid() ) { start = dtStart().toTimeSpec( spec ); end = dtEnd().toTimeSpec( spec ); } else { start = dtStart(); end = dtEnd(); } if ( !allDay() ) { end = end.addSecs( -1 ); } bool multi = ( start.date() != end.date() && start <= end ); return multi; } void Event::shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec ) { Incidence::shiftTimes( oldSpec, newSpec ); if ( hasEndDate() ) { d->mDtEnd = d->mDtEnd.toTimeSpec( oldSpec ); d->mDtEnd.setTimeSpec( newSpec ); } } void Event::setTransparency( Event::Transparency transparency ) { if ( mReadOnly ) { return; } d->mTransparency = transparency; updated(); } Event::Transparency Event::transparency() const { return d->mTransparency; } void Event::setDuration( const Duration &duration ) { setHasEndDate( false ); Incidence::setDuration( duration ); } KDateTime Event::endDateRecurrenceBase() const { return dtEnd(); } diff --git a/kcal/event.h b/kcal/event.h index 68d55bd13..0c19ea25d 100644 --- a/kcal/event.h +++ b/kcal/event.h @@ -1,210 +1,217 @@ /* This file is part of the kcal library. Copyright (c) 2001-2003 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and defines the Event class. @author Cornelius Schumacher \ */ #ifndef KCAL_EVENT_H #define KCAL_EVENT_H #include "incidence.h" #include namespace KCal { /** @brief This class provides an Event in the sense of RFC2445. */ class KCAL_EXPORT Event : public Incidence { public: /** The different Event transparency types. */ enum Transparency { Opaque, /**< Event appears in free/busy time */ Transparent /**< Event does @b not appear in free/busy time */ }; /** List of events. */ typedef ListBase List; /** Constructs an event. */ Event(); /** Copy constructor. @param other is the event to copy. */ Event( const Event &other ); /** Destroys the event. */ ~Event(); /** Assignment operator. + @param other is the event to assign. */ Event &operator=( const Event &other ); /** Compares two events for equality. - @param event is the event to compare + @param event is the event to compare. */ bool operator==( const Event &event ) const; /** Returns the Incidence type, as a QByteArray. */ QByteArray type() const; /** Returns an exact copy of this Event. The caller owns the returned object. */ Event *clone(); /** Sets the event end date and time. @param dtEnd is a KDateTime specifying when the event ends. @see dtEnd(), dateEnd(). */ void setDtEnd( const KDateTime &dtEnd ); /** Returns the event end date and time. @see setDtEnd(). */ virtual KDateTime dtEnd() const; /** Returns the date when the event ends. This might be different from dtEnd().date, since the end date/time is non-inclusive. So timed events ending at 0:00 have their end date on the day before. */ QDate dateEnd() const; /** Returns the event end time as a string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param spec If set, return the time in the given spec, else use the event's current spec. + + @deprecated use IncidenceFormatter::timeToString() */ - QString dtEndTimeStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtEndTimeStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns the event end date as a string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param spec If set, return the date in the given spec, else use the event's current spec. + + @deprecated use IncidenceFormatter::dateToString() */ - QString dtEndDateStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtEndDateStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns the event end date/time as string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param spec If set, return the date/time in the given spec, else use the event's current spec. + + @deprecated use IncidenceFormatter::dateTimeToString() */ - QString dtEndStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtEndStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Sets whether the event has an end date/time. @param b If set, indicates the event has an end date. */ void setHasEndDate( bool b ); /** Returns whether the event has an end date/time. */ bool hasEndDate() const; /** Returns true if the event spans multiple days, otherwise return false. @param spec If set, looks if the event is multiday for the given spec. If not set, looks if event this multiday for its spec. */ bool isMultiDay( const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** @copydoc IncidenceBase::shiftTimes() */ virtual void shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec ); /** Sets the event's time transparency level. @param transparency is the event Transparency level. */ void setTransparency( Transparency transparency ); /** Returns the event's time transparency level. */ Transparency transparency() const; /** Sets the duration of this event. @param duration is the event Duration. */ void setDuration( const Duration &duration ); protected: /** Returns the end date/time of the base incidence. */ virtual KDateTime endDateRecurrenceBase() const; private: /** @copydoc IncidenceBase::accept() */ bool accept( Visitor &v ) { return v.visit( this ); } //@cond PRIVATE class Private; Private *const d; //@endcond }; } #endif diff --git a/kcal/incidencebase.cpp b/kcal/incidencebase.cpp index 12ac849ee..d932a3ff2 100644 --- a/kcal/incidencebase.cpp +++ b/kcal/incidencebase.cpp @@ -1,531 +1,532 @@ /* This file is part of the kcal library. Copyright (c) 2001,2004 Cornelius Schumacher Copyright (C) 2003-2004 Reinhold Kainhofer 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and defines the IncidenceBase class. @brief An abstract base class that provides a common base for all calendar incidence classes. @author Cornelius Schumacher \ @author Reinhold Kainhofer \ */ #include "incidencebase.h" #include "calformat.h" +#include "incidenceformatter.h" #include #include #include #include #include #include using namespace KCal; /** Private class that helps to provide binary compatibility between releases. @internal */ //@cond PRIVATE class KCal::IncidenceBase::Private { public: Private() : mUpdateGroupLevel( 0 ), mUpdatedPending( false ), mAllDay( true ), mHasDuration( false ) { mAttendees.setAutoDelete( true ); } Private( const Private &other ) : mUpdateGroupLevel( 0 ), mUpdatedPending( false ), mAllDay( true ), mHasDuration( false ) { mAttendees.setAutoDelete( true ); init( other ); } void init( const Private &other ); KDateTime mLastModified; // incidence last modified date KDateTime mDtStart; // incidence start time Person mOrganizer; // incidence person (owner) QString mUid; // incidence unique id Duration mDuration; // incidence duration int mUpdateGroupLevel; // if non-zero, suppresses update() calls bool mUpdatedPending; // true if an update has occurred since startUpdates() bool mAllDay; // true if the incidence is all-day bool mHasDuration; // true if the incidence has a duration Attendee::List mAttendees; // list of incidence attendees QStringList mComments; // list of incidence comments QList mObservers; // list of incidence observers }; void IncidenceBase::Private::init( const Private &other ) { mLastModified = other.mLastModified; mDtStart = other.mDtStart; mOrganizer = other.mOrganizer; mUid = other.mUid; mDuration = other.mDuration; mAllDay = other.mAllDay; mHasDuration = other.mHasDuration; mComments = other.mComments; mAttendees.clearAll(); Attendee::List::ConstIterator it; for ( it = other.mAttendees.begin(); it != other.mAttendees.end(); ++it ) { mAttendees.append( new Attendee( *(*it) ) ); } } //@endcond IncidenceBase::IncidenceBase() : d( new KCal::IncidenceBase::Private ) { mReadOnly = false; setUid( CalFormat::createUniqueId() ); } IncidenceBase::IncidenceBase( const IncidenceBase &i ) : CustomProperties( i ), d( new KCal::IncidenceBase::Private( *i.d ) ) { mReadOnly = i.mReadOnly; } IncidenceBase::~IncidenceBase() { delete d; } IncidenceBase &IncidenceBase::operator=( const IncidenceBase &other ) { // check for self assignment if ( &other == this ) { return *this; } CustomProperties::operator=( other ); d->init( *other.d ); mReadOnly = other.mReadOnly; return *this; } bool IncidenceBase::operator==( const IncidenceBase &i2 ) const { if ( attendees().count() != i2.attendees().count() ) { return false; // no need to check further } Attendee::List al1 = attendees(); Attendee::List al2 = i2.attendees(); Attendee::List::ConstIterator a1 = al1.constBegin(); Attendee::List::ConstIterator a2 = al2.constBegin(); //TODO Does the order of attendees in the list really matter? //Please delete this comment if you know it's ok, kthx for ( ; a1 != al1.constEnd() && a2 != al2.constEnd(); ++a1, ++a2 ) { if ( !( **a1 == **a2 ) ) { return false; } } if ( !CustomProperties::operator == (i2) ) { return false; } 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. allDay() == i2.allDay() && duration() == i2.duration() && hasDuration() == i2.hasDuration(); // no need to compare mObserver } void IncidenceBase::setUid( const QString &uid ) { d->mUid = uid; updated(); } QString IncidenceBase::uid() const { return d->mUid; } void IncidenceBase::setLastModified( const KDateTime &lm ) { // DON'T! updated() because we call this from // Calendar::updateEvent(). // Convert to UTC and remove milliseconds part. KDateTime current = lm.toUtc(); QTime t = current.time(); t.setHMS( t.hour(), t.minute(), t.second(), 0 ); current.setTime( t ); d->mLastModified = current; } KDateTime IncidenceBase::lastModified() const { return d->mLastModified; } void IncidenceBase::setOrganizer( const Person &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... d->mOrganizer = o; updated(); } void IncidenceBase::setOrganizer( const QString &o ) { QString mail( o ); if ( mail.startsWith( QLatin1String( "MAILTO:" ), Qt::CaseInsensitive ) ) { mail = mail.remove( 0, 7 ); } // split the string into full name plus email. const Person organizer = Person::fromFullName( mail ); setOrganizer( organizer ); } Person IncidenceBase::organizer() const { return d->mOrganizer; } void IncidenceBase::setReadOnly( bool readOnly ) { mReadOnly = readOnly; } void IncidenceBase::setDtStart( const KDateTime &dtStart ) { // if ( mReadOnly ) return; d->mDtStart = dtStart; d->mAllDay = dtStart.isDateOnly(); updated(); } KDateTime IncidenceBase::dtStart() const { return d->mDtStart; } QString IncidenceBase::dtStartTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } - return KGlobal::locale()->formatTime( dtStart().toTimeSpec( spec ).time(), !shortfmt ) - + timeZone; + return KGlobal::locale()->formatTime( + dtStart().toTimeSpec( spec ).time(), !shortfmt ) + timeZone; } else { return KGlobal::locale()->formatTime( dtStart().time(), !shortfmt ); } } QString IncidenceBase::dtStartDateStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } return KGlobal::locale()->formatDate( - dtStart().toTimeSpec( spec ).date(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + dtStart().toTimeSpec( spec ).date(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { return KGlobal::locale()->formatDate( dtStart().date(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } QString IncidenceBase::dtStartStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( allDay() ) { - return dtStartDateStr( shortfmt, spec ); + return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec ); } if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } return KGlobal::locale()->formatDateTime( dtStart().toTimeSpec( spec ).dateTime(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { return KGlobal::locale()->formatDateTime( dtStart().dateTime(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } bool IncidenceBase::allDay() const { return d->mAllDay; } void IncidenceBase::setAllDay( bool f ) { if ( mReadOnly || f == d->mAllDay ) { return; } d->mAllDay = f; updated(); } void IncidenceBase::shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec ) { d->mDtStart = d->mDtStart.toTimeSpec( oldSpec ); d->mDtStart.setTimeSpec( newSpec ); updated(); } void IncidenceBase::addComment( const QString &comment ) { d->mComments += comment; } bool IncidenceBase::removeComment( const QString &comment ) { bool found = false; QStringList::Iterator i; for ( i = d->mComments.begin(); !found && i != d->mComments.end(); ++i ) { if ( (*i) == comment ) { found = true; d->mComments.erase( i ); } } return found; } void IncidenceBase::clearComments() { d->mComments.clear(); } QStringList IncidenceBase::comments() const { return d->mComments; } void IncidenceBase::addAttendee( Attendee *a, bool doupdate ) { if ( !a || mReadOnly ) { return; } if ( a->name().left(7).toUpper() == "MAILTO:" ) { a->setName( a->name().remove( 0, 7 ) ); } d->mAttendees.append( a ); if ( doupdate ) { updated(); } } const Attendee::List &IncidenceBase::attendees() const { return d->mAttendees; } int IncidenceBase::attendeeCount() const { return d->mAttendees.count(); } void IncidenceBase::clearAttendees() { if ( mReadOnly ) { return; } qDeleteAll( d->mAttendees ); d->mAttendees.clear(); } Attendee *IncidenceBase::attendeeByMail( const QString &email ) const { Attendee::List::ConstIterator it; for ( it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it ) { if ( (*it)->email() == email ) { return *it; } } return 0; } Attendee *IncidenceBase::attendeeByMails( const QStringList &emails, const QString &email ) const { QStringList mails = emails; if ( !email.isEmpty() ) { mails.append( email ); } Attendee::List::ConstIterator itA; for ( itA = d->mAttendees.constBegin(); itA != d->mAttendees.constEnd(); ++itA ) { for ( QStringList::const_iterator it = mails.constBegin(); it != mails.constEnd(); ++it ) { if ( (*itA)->email() == (*it) ) { return *itA; } } } return 0; } Attendee *IncidenceBase::attendeeByUid( const QString &uid ) const { Attendee::List::ConstIterator it; for ( it = d->mAttendees.constBegin(); it != d->mAttendees.constEnd(); ++it ) { if ( (*it)->uid() == uid ) { return *it; } } return 0; } void IncidenceBase::setDuration( const Duration &duration ) { d->mDuration = duration; setHasDuration( true ); updated(); } Duration IncidenceBase::duration() const { return d->mDuration; } void IncidenceBase::setHasDuration( bool hasDuration ) { d->mHasDuration = hasDuration; } bool IncidenceBase::hasDuration() const { return d->mHasDuration; } void IncidenceBase::registerObserver( IncidenceBase::IncidenceObserver *observer ) { if ( !d->mObservers.contains( observer ) ) { d->mObservers.append( observer ); } } void IncidenceBase::unRegisterObserver( IncidenceBase::IncidenceObserver *observer ) { d->mObservers.removeAll( observer ); } void IncidenceBase::updated() { if ( d->mUpdateGroupLevel ) { d->mUpdatedPending = true; } else { foreach ( IncidenceObserver *o, d->mObservers ) { o->incidenceUpdated( this ); } } } void IncidenceBase::startUpdates() { ++d->mUpdateGroupLevel; } void IncidenceBase::endUpdates() { if ( d->mUpdateGroupLevel > 0 ) { if ( --d->mUpdateGroupLevel == 0 && d->mUpdatedPending ) { d->mUpdatedPending = false; updated(); } } } void IncidenceBase::customPropertyUpdated() { updated(); } KUrl IncidenceBase::uri() const { return KUrl( QString( "urn:x-ical:" ) + uid() ); } bool IncidenceBase::Visitor::visit( Event *event ) { Q_UNUSED( event ); return false; } bool IncidenceBase::Visitor::visit( Todo *todo ) { Q_UNUSED( todo ); return false; } bool IncidenceBase::Visitor::visit( Journal *journal ) { Q_UNUSED( journal ); return false; } bool IncidenceBase::Visitor::visit( FreeBusy *freebusy ) { Q_UNUSED( freebusy ); return false; } diff --git a/kcal/incidencebase.h b/kcal/incidencebase.h index 59a2ef571..b8d930fb0 100644 --- a/kcal/incidencebase.h +++ b/kcal/incidencebase.h @@ -1,562 +1,568 @@ /* This file is part of the kcal library. Copyright (c) 2001-2003 Cornelius Schumacher Copyright (c) 2003-2004 Reinhold Kainhofer Copyright (c) 2005 Rafal Rzepecki 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and defines the IncidenceBase class. @author Cornelius Schumacher \ @author Reinhold Kainhofer \ @author Rafal Rzepecki \ @glossary @anchor incidence @b incidence: General term for a calendar component. Examples are events, to-dos, and journals. @glossary @anchor event @b event: An @ref incidence that has a start and end time, typically representing some occurrence of social or personal importance. May be recurring. Examples are appointments, meetings, or holidays. @glossary @anchor to-do @b to-do: An @ref incidence that has an optional start time and an optional due time typically representing some undertaking to be performed. May be recurring. Examples are "fix the bug" or "pay the bills". @glossary @anchor todo @b todo: See @ref to-do. @glossary @anchor journal @b journal: An @ref incidence with a start date that represents a diary or daily record of one's activities. May @b not be recurring. */ #ifndef KCAL_INCIDENCEBASE_H #define KCAL_INCIDENCEBASE_H #include "attendee.h" #include "customproperties.h" #include "duration.h" #include "sortablelist.h" #include #include #include class KUrl; namespace KCal { /** List of dates */ typedef SortableList DateList; /** List of times */ typedef SortableList DateTimeList; class Event; class Todo; class Journal; class FreeBusy; /** @brief An abstract class that provides a common base for all calendar incidence classes. define: organizer (person) define: uid (same as the attendee uid?) Several properties are not allowed for VFREEBUSY objects (see rfc:2445), so they are not in IncidenceBase. The hierarchy is: IncidenceBase - FreeBusy - Incidence - Event - Todo - Journal So IncidenceBase contains all properties that are common to all classes, and Incidence contains all additional properties that are common to Events, Todos and Journals, but are not allowed for FreeBusy entries. */ class KCAL_EXPORT IncidenceBase : public CustomProperties { 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 KCAL_EXPORT Visitor //krazy:exclude=dpointer { public: /** Destruct Incidence::Visitor */ virtual ~Visitor() {} /** Reimplement this function in your concrete subclass of IncidenceBase::Visitor to perform actions on an Event object. @param event is a pointer to a valid Event object. */ virtual bool visit( Event *event ); /** Reimplement this function in your concrete subclass of IncidenceBase::Visitor to perform actions on a Todo object. @param todo is a pointer to a valid Todo object. */ virtual bool visit( Todo *todo ); /** Reimplement this function in your concrete subclass of IncidenceBase::Visitor to perform actions on an Journal object. @param journal is a pointer to a valid Journal object. */ virtual bool visit( Journal *journal ); /** Reimplement this function in your concrete subclass of IncidenceBase::Visitor to perform actions on a FreeBusy object. @param freebusy is a pointer to a valid FreeBusy object. */ virtual bool visit( FreeBusy *freebusy ); protected: /** Constructor is protected to prevent direct creation of visitor base class. */ Visitor() {} }; /** The IncidenceObserver class. */ class IncidenceObserver { public: /** Destroys the IncidenceObserver. */ virtual ~IncidenceObserver() {} /** The IncidenceObserver interface. @param incidenceBase is a pointer to an IncidenceBase object. */ virtual void incidenceUpdated( IncidenceBase *incidenceBase ) = 0; }; /** Constructs an empty IncidenceBase. */ IncidenceBase(); /** Constructs an IncidenceBase as a copy of another IncidenceBase object. @param ib is the IncidenceBase to copy. */ IncidenceBase( const IncidenceBase &ib ); /** Destroys the IncidenceBase. */ virtual ~IncidenceBase(); /** Assignment operator. + @param other is the IncidenceBase to assign. */ IncidenceBase &operator=( const IncidenceBase &other ); /** Compares this with IncidenceBase @p ib for equality. - @param ib is the IncidenceBase to compare. */ bool operator==( const IncidenceBase &ib ) const; /** Accept IncidenceVisitor. A class taking part in the visitor mechanism has to provide this implementation:
         bool accept(Visitor &v) { return v.visit(this); }
       
@param v is a reference to a Visitor object. */ virtual bool accept( Visitor &v ) { Q_UNUSED( v ); return false; } /** Prints the type of Incidence as a string. */ virtual QByteArray type() const = 0; /** Sets the unique id for the incidence to @p uid. @param uid is the string containing the incidence @ref uid. @see uid() */ void setUid( const QString &uid ); /** Returns the unique id (@ref uid) for the incidence. @see setUid() */ QString uid() const; /** Returns the uri for the incidence, of form urn:x-ical:\ */ KUrl uri() const; /** Sets the time the incidence was last modified to @p lm. It is stored as a UTC date/time. @param lm is the KDateTime when the incidence was last modified. @see lastModified() */ void setLastModified( const KDateTime &lm ); /** Returns the time the incidence was last modified. @see setLastModified() */ KDateTime lastModified() const; /** Sets the organizer for the incidence. @param organizer is a Person to use as the incidence @ref organizer. @see organizer(), setOrganizer(const QString &) */ void setOrganizer( const Person &organizer ); /** Sets the incidence organizer to any string @p organizer. @param organizer is a string to use as the incidence @ref organizer. @see organizer(), setOrganizer(const Person &) */ void setOrganizer( const QString &organizer ); /** Returns the Person associated with this incidence. @see setOrganizer(const QString &), setOrganizer(const Person &) */ Person organizer() const; /** Sets readonly status. @param readOnly if set, the incidence is read-only; else the incidence can be modified. @see isReadOnly(). */ virtual void setReadOnly( bool readOnly ); /** Returns true the object is read-only; false otherwise. @see setReadOnly() */ bool isReadOnly() const { return mReadOnly; } /** Sets the incidence's starting date/time with a KDateTime. The incidence's all-day status is set according to whether @p dtStart is a date/time (not all-day) or date-only (all-day). @param dtStart is the incidence start date/time. @see dtStart(). */ virtual void setDtStart( const KDateTime &dtStart ); /** Returns an incidence's starting date/time as a KDateTime. @see setDtStart(). */ virtual KDateTime dtStart() const; /** Returns an incidence's starting time as a string formatted according to the user's locale settings. @param shortfmt If set to true, use short date format, if set to false use long format. @param spec If set, return the time in the given spec, else use the incidence's current spec. + + @deprecated use IncidenceFormatter::timeToString() */ - virtual QString dtStartTimeStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + virtual KDE_DEPRECATED QString dtStartTimeStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns an incidence's starting date as a string formatted according to the user's locale settings. @param shortfmt If set to true, use short date format, if set to false use long format. @param spec If set, return the date in the given spec, else use the incidence's current spec. + + @deprecated use IncidenceFormatter::dateToString() */ - virtual QString dtStartDateStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + virtual KDE_DEPRECATED QString dtStartDateStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns an incidence's starting date and time as a string formatted according to the user's locale settings. @param shortfmt If set to true, use short date format, if set to false use long format. @param spec If set, return the date and time in the given spec, else use the incidence's current spec. + + @deprecated use IncidenceFormatter::dateTimeToString() */ - virtual QString dtStartStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + virtual KDE_DEPRECATED QString dtStartStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Sets the incidence duration. @param duration the incidence duration @see duration() */ virtual void setDuration( const Duration &duration ); /** Returns the length of the incidence duration. @see setDuration() */ Duration duration() const; /** Sets if the incidence has a duration. @param hasDuration true if the incidence has a duration; false otherwise. @see hasDuration() */ void setHasDuration( bool hasDuration ); /** Returns true if the incidence has a duration; false otherwise. @see setHasDuration() */ bool hasDuration() const; /** Returns true or false depending on whether the incidence is all-day. i.e. has a date but no time attached to it. @see setAllDay() */ bool allDay() const; /** Sets whether the incidence is all-day, i.e. has a date but no time attached to it. @param allDay sets whether the incidence is all-day. @see allDay() */ void setAllDay( bool allDay ); /** Shift the times of the incidence so that they appear at the same clock time as before but in a new time zone. The shift is done from a viewing time zone rather than from the actual incidence time zone. For example, shifting an incidence whose start time is 09:00 America/New York, using an old viewing time zone (@p oldSpec) of Europe/London, to a new time zone (@p newSpec) of Europe/Paris, will result in the time being shifted from 14:00 (which is the London time of the incidence start) to 14:00 Paris time. @param oldSpec the time specification which provides the clock times @param newSpec the new time specification */ virtual void shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec ); /** Adds a comment to thieincidence. Does not add a linefeed character; simply appends the text as specified. @param comment is the QString containing the comment to add. @see removeComment(). */ void addComment( const QString &comment ); /** Removes a comment from the incidence. Removes the first comment whose string is an exact match for the specified string in @p comment. @param comment is the QString containing the comment to remove. @return true if match found, false otherwise. @see addComment(). */ bool removeComment( const QString &comment ); /** Deletes all incidence comments. */ void clearComments(); /** Returns all incidence comments as a list of strings. */ QStringList comments() const; /** Add Attendee to this incidence. IncidenceBase takes ownership of the Attendee object. @param attendee a pointer to the attendee to add @param doUpdate If true the Observers are notified, if false they are not. */ void addAttendee( Attendee *attendee, bool doUpdate = true ); /** Removes all attendees from the incidence. */ void clearAttendees(); /** Returns a list of incidence attendees. */ const Attendee::List &attendees() const; /** Returns the number of incidence attendees. */ int attendeeCount() const; /** Returns the attendee with the specified email address. @param email is a QString containing an email address of the form "FirstName LastName ". @see attendeeByMails(), attendeesByUid(). */ Attendee *attendeeByMail( const QString &email ) const; /** Returns the first incidence attendee with one of the specified email addresses. @param emails is a list of QStrings containing email addresses of the form "FirstName LastName ". @param email is a QString containing a single email address to search in addition to the list specified in @p emails. @see attendeeByMail(), attendeesByUid(). */ Attendee *attendeeByMails( const QStringList &emails, const QString &email = QString() ) const; /** Returns the incidence attendee with the specified attendee @acronym UID. @param uid is a QString containing an attendee @acronym UID. @see attendeeByMail(), attendeeByMails(). */ Attendee *attendeeByUid( const QString &uid ) const; /** Register observer. The observer is notified when the observed object changes. @param observer is a pointer to an IncidenceObserver object that will be watching this incidence. @see unRegisterObserver() */ void registerObserver( IncidenceObserver *observer ); /** Unregister observer. It isn't notified anymore about changes. @param observer is a pointer to an IncidenceObserver object that will be watching this incidence. @see registerObserver(). */ void unRegisterObserver( IncidenceObserver *observer ); /** Call this to notify the observers after the IncidenceBase object has changed. */ void updated(); /** Call this when a group of updates is going to be made. This suppresses change notifications until endUpdates() is called, at which point updated() will automatically be called. */ void startUpdates(); /** Call this when a group of updates is complete, to notify observers that the instance has changed. This should be called in conjunction with startUpdates(). */ void endUpdates(); protected: /** @copydoc CustomProperties::customPropertyUpdated() */ virtual void customPropertyUpdated(); /** Identifies a read-only incidence. */ bool mReadOnly; private: //@cond PRIVATE class Private; Private *const d; //@endcond }; } #endif diff --git a/kcal/incidenceformatter.h b/kcal/incidenceformatter.h index ba0b72472..f3f105b81 100644 --- a/kcal/incidenceformatter.h +++ b/kcal/incidenceformatter.h @@ -1,210 +1,210 @@ /* This file is part of the kcal library. Copyright (c) 2001-2003 Cornelius Schumacher Copyright (c) 2004 Reinhold Kainhofer 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and provides static functions for formatting Incidences for various purposes. @author Cornelius Schumacher \ @author Reinhold Kainhofer \ */ #ifndef KCAL_INCIDENCEFORMATTER_H #define KCAL_INCIDENCEFORMATTER_H #include "kcal_export.h" #include #include namespace KCal { class Calendar; class Incidence; class IncidenceBase; class KCAL_EXPORT InvitationFormatterHelper { public: InvitationFormatterHelper() : d( 0 ) {} virtual ~InvitationFormatterHelper(){} virtual QString generateLinkURL( const QString &id ); virtual QString makeLink( const QString &id, const QString &text ); virtual Calendar *calendar() const; private: //@cond PRIVATE Q_DISABLE_COPY( InvitationFormatterHelper ) class Private; Private *const d; //@endcond }; /** @brief Provides methods to format Incidences in various ways for display purposes. Helpers that provides several static methods to format an Incidence in different ways: like an HTML representation for KMail, a representation for tool tips, or a representation for a viewer widget. */ namespace IncidenceFormatter { /** Create a QString representation of an Incidence in a nice format suitable for using in a tooltip. @param incidence is a pointer to the Incidence to be formatted. @param richText if yes, the QString will be created as RichText. @param spec is an optional time specification which, when specified, will shift the Incidence times to different timezones. @since 4.2 */ KCAL_EXPORT QString toolTipStr( IncidenceBase *incidence, bool richText=true, KDateTime::Spec spec=KDateTime::Spec() ); /** Create a QString representation of an Incidence in a nice format suitable for using in a tooltip. @param incidence is a pointer to the Incidence to be formatted. @param richText if yes, the QString will be created as RichText. @deprecated use toolTipStr( IncidenceBase *, bool, KDateTime::Spec) */ KCAL_EXPORT KDE_DEPRECATED QString toolTipString( IncidenceBase *incidence, bool richText=true ); /** Create a RichText QString representation of an Incidence in a nice format suitable for using in a viewer widget. @param incidence is a pointer to the Incidence to be formatted. @param spec is an optional time specification which, when specified, will shift the Incidence times to different timezones. @since 4.2 */ KCAL_EXPORT QString extensiveDisplayStr( IncidenceBase *incidence, KDateTime::Spec spec=KDateTime::Spec() ); /** Create a RichText QString representation of an Incidence in a nice format suitable for using in a viewer widget. @param incidence is a pointer to the Incidence to be formatted. @deprecated use extensiveDisplayStr( IncidenceBase *, KDateTime::Spec ) */ KCAL_EXPORT KDE_DEPRECATED QString extensiveDisplayString( IncidenceBase *incidence ); /** Create a QString representation of an Incidence in format suitable for including inside a mail message. @param incidence is a pointer to the Incidence to be formatted. @param spec is an optional time specification which, when specified, will shift the Incidence times to different timezones. @since 4.2 */ KCAL_EXPORT QString mailBodyStr( IncidenceBase *incidence, KDateTime::Spec spec=KDateTime::Spec() ); /** Create a QString representation of an Incidence in format suitable for including inside a mail message. @param incidence is a pointer to the Incidence to be formatted. @deprecated use mailBodyStr( IncidenceBase *, KDateTime::Spec ) */ KCAL_EXPORT KDE_DEPRECATED QString mailBodyString( IncidenceBase *incidence ); /** Deliver an HTML formatted string displaying an invitation. Use the time zone from mCalendar. */ KCAL_EXPORT QString formatICalInvitation( QString invitation, Calendar *mCalendar, InvitationFormatterHelper *helper ); /** @since 4.2 */ KCAL_EXPORT QString formatICalInvitationNoHtml( QString invitation, Calendar *mCalendar, InvitationFormatterHelper *helper ); /** Format a TNEF attachment to an HTML mail @since 4.1 */ KCAL_EXPORT QString formatTNEFInvitation( const QByteArray &tnef, Calendar *mCalendar, InvitationFormatterHelper *helper ); /** Transform a TNEF attachment to an iCal or vCard @since 4.1 */ KCAL_EXPORT QString msTNEFToVPart( const QByteArray &tnef ); /** Build a pretty QString representation of an Incidence's recurrence info. @param incidence is a pointer to the Incidence whose recurrence info is to be formatted. @since 4.1 */ KCAL_EXPORT QString recurrenceString( Incidence *incidence ); /** Build a QString time representation of a KDateTime object. @param date The date to be formatted. @param shortfmt If true, display info in short format. @param spec Time spec to use. @see dateToString(), dateTimeToString(). @since 4.3 */ KCAL_EXPORT QString timeToString( const KDateTime &date, bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ); /** Build a QString date representation of a KDateTime object. @param date The date to be formatted. @param shortfmt If true, display info in short format. @param spec Time spec to use. @see dateToString(), dateTimeToString(). @since 4.3 */ KCAL_EXPORT QString dateToString( const KDateTime &date, bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ); /** Build a QString date/time representation of a KDateTime object. - @param datetime The date to be formatted. + @param date The date to be formatted. @param dateOnly If true, don't print the time fields; print the date fields only. @param shortfmt If true, display info in short format. @param spec Time spec to use. @see dateToString(), timeToString(). @since 4.3 */ KCAL_EXPORT QString dateTimeToString( const KDateTime &date, bool dateOnly = false, bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ); class EventViewerVisitor; class ScheduleMessageVisitor; class InvitationHeaderVisitor; class InvitationBodyVisitor; class IncidenceCompareVisitor; class ToolTipVisitor; class MailBodyVisitor; } } #endif diff --git a/kcal/todo.cpp b/kcal/todo.cpp index 16dd1a7db..492815a3c 100644 --- a/kcal/todo.cpp +++ b/kcal/todo.cpp @@ -1,535 +1,550 @@ /* This file is part of the kcal library. Copyright (c) 2001-2003 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and defines the Todo class. @brief Provides a To-do in the sense of RFC2445. @author Cornelius Schumacher \ */ #include "todo.h" +#include "incidenceformatter.h" #include #include #include #include using namespace KCal; /** Private class that helps to provide binary compatibility between releases. @internal */ //@cond PRIVATE class KCal::Todo::Private { public: Private() : mPercentComplete( 0 ), mHasDueDate( false ), mHasStartDate( false ), mHasCompletedDate( false ) {} Private( const KCal::Todo::Private &other ) { init( other ); } void init( const KCal::Todo::Private &other ); KDateTime mDtDue; // to-do due date (if there is one) // ALSO the first occurrence of a recurring to-do KDateTime mDtRecurrence; // next occurrence (for recurring to-dos) KDateTime mCompleted; // to-do completion date (if it has been completed) int mPercentComplete; // to-do percent complete [0,100] bool mHasDueDate; // true if the to-do has a due date bool mHasStartDate; // true if the to-do has a starting date bool mHasCompletedDate; // true if the to-do has a completion date /** Returns true if the todo got a new date, else false will be returned. */ bool recurTodo( Todo *todo ); }; void KCal::Todo::Private::init( const KCal::Todo::Private &other ) { mDtDue = other.mDtDue; mDtRecurrence = other.mDtRecurrence; mCompleted = other.mCompleted; mPercentComplete = other.mPercentComplete; mHasDueDate = other.mHasDueDate; mHasStartDate = other.mHasStartDate; mHasCompletedDate = other.mHasCompletedDate; } //@endcond Todo::Todo() : d( new KCal::Todo::Private ) { } Todo::Todo( const Todo &other ) : Incidence( other ), d( new KCal::Todo::Private( *other.d ) ) { } Todo::~Todo() { delete d; } Todo *Todo::clone() { return new Todo( *this ); } Todo &Todo::operator=( const Todo &other ) { // check for self assignment if ( &other == this ) { return *this; } Incidence::operator=( other ); d->init( *other.d ); return *this; } bool Todo::operator==( const Todo &todo ) const { return static_cast( *this ) == static_cast( todo ) && dtDue() == todo.dtDue() && hasDueDate() == todo.hasDueDate() && hasStartDate() == todo.hasStartDate() && completed() == todo.completed() && hasCompletedDate() == todo.hasCompletedDate() && percentComplete() == todo.percentComplete(); } QByteArray Todo::type() const { return "Todo"; } void Todo::setDtDue( const KDateTime &dtDue, bool first ) { //int diffsecs = d->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)); } }*/ if ( recurs() && !first ) { d->mDtRecurrence = dtDue; } else { d->mDtDue = dtDue; // TODO: This doesn't seem right... recurrence()->setStartDateTime( dtDue ); recurrence()->setAllDay( allDay() ); } if ( recurs() && dtDue < recurrence()->startDateTime() ) { setDtStart( dtDue ); } - //kDebug() << "setDtDue says date is" << d->mDtDue.toString(); - /*const Alarm::List& alarms = alarms(); for (Alarm *alarm = alarms.first(); alarm; alarm = alarms.next()) alarm->setAlarmStart(d->mDtDue);*/ updated(); } KDateTime Todo::dtDue( bool first ) const { if ( !hasDueDate() ) { return KDateTime(); } if ( recurs() && !first && d->mDtRecurrence.isValid() ) { return d->mDtRecurrence; } return d->mDtDue; } QString Todo::dtDueTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } - return KGlobal::locale()->formatTime( dtDue( !recurs() ).toTimeSpec( spec ).time(), !shortfmt ) - + timeZone; + return KGlobal::locale()->formatTime( + dtDue( !recurs() ).toTimeSpec( spec ).time(), !shortfmt ) + timeZone; } else { - return KGlobal::locale()->formatTime( dtDue( !recurs() ).time(), !shortfmt ); + return KGlobal::locale()->formatTime( + dtDue( !recurs() ).time(), !shortfmt ); } } QString Todo::dtDueDateStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } return KGlobal::locale()->formatDate( dtDue( !recurs() ).toTimeSpec( spec ).date(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { return KGlobal::locale()->formatDate( dtDue( !recurs() ).date(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } QString Todo::dtDueStr( bool shortfmt, const KDateTime::Spec &spec ) const { if ( allDay() ) { - return dtDueDateStr( shortfmt, spec ); + return IncidenceFormatter::dateToString( dtDue(), shortfmt, spec ); } if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } return KGlobal::locale()->formatDateTime( dtDue( !recurs() ).toTimeSpec( spec ).dateTime(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { return KGlobal::locale()->formatDateTime( dtDue( !recurs() ).dateTime(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } bool Todo::hasDueDate() const { return d->mHasDueDate; } void Todo::setHasDueDate( bool f ) { if ( mReadOnly ) { return; } d->mHasDueDate = f; updated(); } bool Todo::hasStartDate() const { return d->mHasStartDate; } void Todo::setHasStartDate( bool f ) { if ( mReadOnly ) { return; } if ( recurs() && !f ) { if ( !comments().filter( "NoStartDate" ).count() ) { addComment( "NoStartDate" ); //TODO: --> custom flag? } } else { QString s( "NoStartDate" ); removeComment( s ); } d->mHasStartDate = f; updated(); } KDateTime Todo::dtStart() const { return dtStart( false ); } KDateTime Todo::dtStart( bool first ) const { if ( !hasStartDate() ) { return KDateTime(); } if ( recurs() && !first ) { return d->mDtRecurrence.addDays( dtDue( true ).daysTo( IncidenceBase::dtStart() ) ); } else { return IncidenceBase::dtStart(); } } void Todo::setDtStart( const KDateTime &dtStart ) { // TODO: This doesn't seem right (rfc 2445/6 says, recurrence is calculated from the dtstart...) if ( recurs() ) { recurrence()->setStartDateTime( d->mDtDue ); recurrence()->setAllDay( allDay() ); } IncidenceBase::setDtStart( dtStart ); } QString Todo::dtStartTimeStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } - return KGlobal::locale()->formatTime( dtStart( first ).toTimeSpec( spec ).time(), !shortfmt ) - + timeZone; + return KGlobal::locale()->formatTime( + dtStart( first ).toTimeSpec( spec ).time(), !shortfmt ) + timeZone; } else { - return KGlobal::locale()->formatTime( dtStart( first ).time(), !shortfmt ); + return KGlobal::locale()->formatTime( + dtStart( first ).time(), !shortfmt ); } } QString Todo::dtStartTimeStr( bool shortfmt, const KDateTime::Spec &spec ) const { - return Incidence::dtStartTimeStr( shortfmt, spec ); + return IncidenceFormatter::timeToString( dtStart(), shortfmt, spec ); } QString Todo::dtStartDateStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const { if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } - return - KGlobal::locale()->formatDate( dtStart( first ).toTimeSpec( spec ).date(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + return KGlobal::locale()->formatDate( + dtStart( first ).toTimeSpec( spec ).date(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { - return - KGlobal::locale()->formatDate( dtStart( first ).date(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); + return KGlobal::locale()->formatDate( + dtStart( first ).date(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } QString Todo::dtStartDateStr( bool shortfmt, const KDateTime::Spec &spec ) const { - return Incidence::dtStartDateStr( shortfmt, spec ); + return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec ); } QString Todo::dtStartStr( bool shortfmt, bool first, const KDateTime::Spec &spec ) const { if ( allDay() ) { - return dtStartDateStr( shortfmt, spec ); + return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec ); } if ( spec.isValid() ) { QString timeZone; if ( spec.timeZone() != KSystemTimeZones::local() ) { timeZone = ' ' + spec.timeZone().name(); } - return - KGlobal::locale()->formatDateTime( dtStart( first ).toTimeSpec( spec ).dateTime(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) - + timeZone; + return KGlobal::locale()->formatDateTime( + dtStart( first ).toTimeSpec( spec ).dateTime(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; } else { - return - KGlobal::locale()->formatDateTime( dtStart( first ).dateTime(), - ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); + return KGlobal::locale()->formatDateTime( + dtStart( first ).dateTime(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } } QString Todo::dtStartStr( bool shortfmt, const KDateTime::Spec &spec ) const { - return Incidence::dtStartStr( shortfmt, spec ); + if ( allDay() ) { + return IncidenceFormatter::dateToString( dtStart(), shortfmt, spec ); + } + + if ( spec.isValid() ) { + + QString timeZone; + if ( spec.timeZone() != KSystemTimeZones::local() ) { + timeZone = ' ' + spec.timeZone().name(); + } + + return KGlobal::locale()->formatDateTime( + dtStart().toTimeSpec( spec ).dateTime(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ) + timeZone; + } else { + return KGlobal::locale()->formatDateTime( + dtStart().dateTime(), + ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); + } } bool Todo::isCompleted() const { if ( d->mPercentComplete == 100 ) { return true; } else { return false; } } void Todo::setCompleted( bool completed ) { if ( completed ) { d->mPercentComplete = 100; } else { d->mPercentComplete = 0; d->mHasCompletedDate = false; d->mCompleted = KDateTime(); } updated(); } KDateTime Todo::completed() const { if ( hasCompletedDate() ) { return d->mCompleted; } else { return KDateTime(); } } QString Todo::completedStr( bool shortfmt ) const { return KGlobal::locale()->formatDateTime( d->mCompleted.dateTime(), ( shortfmt ? KLocale::ShortDate : KLocale::LongDate ) ); } void Todo::setCompleted( const KDateTime &completed ) { if ( !d->recurTodo( this ) ) { d->mHasCompletedDate = true; d->mPercentComplete = 100; d->mCompleted = completed.toUtc(); } updated(); } bool Todo::hasCompletedDate() const { return d->mHasCompletedDate; } int Todo::percentComplete() const { return d->mPercentComplete; } void Todo::setPercentComplete( int percent ) { //TODO: (?) assert percent between 0 and 100, inclusive d->mPercentComplete = percent; if ( percent != 100 ) { d->mHasCompletedDate = false; } updated(); } void Todo::shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec ) { Incidence::shiftTimes( oldSpec, newSpec ); d->mDtDue = d->mDtDue.toTimeSpec( oldSpec ); d->mDtDue.setTimeSpec( newSpec ); if ( recurs() ) { d->mDtRecurrence = d->mDtRecurrence.toTimeSpec( oldSpec ); d->mDtRecurrence.setTimeSpec( newSpec ); } if ( d->mHasCompletedDate ) { d->mCompleted = d->mCompleted.toTimeSpec( oldSpec ); d->mCompleted.setTimeSpec( newSpec ); } } void Todo::setDtRecurrence( const KDateTime &dt ) { d->mDtRecurrence = dt; } KDateTime Todo::dtRecurrence() const { return d->mDtRecurrence.isValid() ? d->mDtRecurrence : d->mDtDue; } bool Todo::recursOn( const QDate &date, const KDateTime::Spec &timeSpec ) const { QDate today = QDate::currentDate(); return Incidence::recursOn( date, timeSpec ) && !( date < today && d->mDtRecurrence.date() < today && d->mDtRecurrence > recurrence()->startDateTime() ); } bool Todo::isOverdue() const { if ( !dtDue().isValid() ) { return false; // if it's never due, it can't be overdue } bool inPast = allDay() ? dtDue().date() < QDate::currentDate() : dtDue() < KDateTime::currentUtcDateTime(); return inPast && !isCompleted(); } KDateTime Todo::endDateRecurrenceBase() const { return dtDue(); } //@cond PRIVATE bool Todo::Private::recurTodo( Todo *todo ) { if ( todo->recurs() ) { Recurrence *r = todo->recurrence(); KDateTime endDateTime = r->endDateTime(); KDateTime nextDate = r->getNextDateTime( todo->dtDue() ); if ( ( r->duration() == -1 || ( nextDate.isValid() && endDateTime.isValid() && nextDate <= endDateTime ) ) ) { while ( !todo->recursAt( nextDate ) || nextDate <= KDateTime::currentUtcDateTime() ) { if ( !nextDate.isValid() || - ( nextDate > endDateTime && r->duration() != -1 ) ) { + ( nextDate > endDateTime && r->duration() != -1 ) ) { return false; } nextDate = r->getNextDateTime( nextDate ); } todo->setDtDue( nextDate ); todo->setCompleted( false ); todo->setRevision( todo->revision() + 1 ); return true; } } return false; } //@endcond diff --git a/kcal/todo.h b/kcal/todo.h index f5fb5a50c..4b4df1204 100644 --- a/kcal/todo.h +++ b/kcal/todo.h @@ -1,373 +1,385 @@ /* This file is part of the kcal library. Copyright (c) 2001-2003 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** @file This file is part of the API for handling calendar data and defines the Todo class. @author Cornelius Schumacher \ */ #ifndef KCAL_TODO_H #define KCAL_TODO_H #include "incidence.h" #include namespace KCal { /** @brief Provides a To-do in the sense of RFC2445. */ class KCAL_EXPORT Todo : public Incidence { public: /** List of to-dos. */ typedef ListBase List; /** Constructs an empty to-do. */ Todo(); /** Copy constructor. @param other is the to-do to copy. */ Todo( const Todo &other ); /** Destroys a to-do. */ ~Todo(); /** @copydoc IncidenceBase::type() */ QByteArray type() const; /** Returns an exact copy of this todo. The returned object is owned by the caller. */ Todo *clone(); /** Sets due date and time. @param dtDue The due date/time. @param first If true and the todo recurs, the due date of the first occurrence will be returned. If false and recurrent, the date of the current occurrence will be returned. If non-recurrent, the normal due date will be returned. */ void setDtDue( const KDateTime &dtDue, bool first = false ); /** Returns due date and time. @param first If true and the todo recurs, the due date of the first occurrence will be returned. If false and recurrent, the date of the current occurrence will be returned. If non-recurrent, the normal due date will be returned. */ KDateTime dtDue( bool first = false ) const; /** Returns due time as string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param spec If set, return the time in the given spec, else use the todo's current spec. + + @deprecated use IncidenceFormatter::timeToString() */ - QString dtDueTimeStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtDueTimeStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns due date as string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param spec If set, return the date in the given spec, else use the todo's current spec. + + @deprecated use IncidenceFormatter::dateToString() */ - QString dtDueDateStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtDueDateStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns due date and time as string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param spec If set, return the date/time in the given spec, else use the todo's current spec. + + @deprecated use IncidenceFormatter::dateTimeToString() */ - QString dtDueStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtDueStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns true if the todo has a due date, otherwise return false. */ bool hasDueDate() const; /** Sets if the todo has a due date. @param hasDueDate true if todo has a due date, otherwise false */ void setHasDueDate( bool hasDueDate ); /** Returns true if the todo has a start date, otherwise return false. */ bool hasStartDate() const; /** Sets if the todo has a start date. @param hasStartDate true if todo has a start date, otherwise false */ void setHasStartDate( bool hasStartDate ); /** @copydoc IncidenceBase::dtStart() */ virtual KDateTime dtStart() const; /** Returns the start date of the todo. @param first If true, the start date of the todo will be returned. If the todo recurs, the start date of the first occurrence will be returned. If false and the todo recurs, the relative start date will be returned, based on the date returned by dtRecurrence(). */ KDateTime dtStart( bool first ) const; /** Sets the start date of the todo. @param dtStart is the to-do start date. */ void setDtStart( const KDateTime &dtStart ); /** Returns a todo's starting time as a string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param first If true, the start date of the todo will be returned. If the todo recurs, the start date of the first occurrence will be returned. If false and the todo recurs, the relative start date will be returned, based on the date returned by dtRecurrence(). @param spec If set, returns the time in the given spec, else use the todo's current spec. + + @deprecated use IncidenceFormatter::timeToString() */ - QString dtStartTimeStr( bool shortfmt, bool first, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtStartTimeStr( + bool shortfmt, bool first, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** @copydoc IncidenceBase::dtStartTimeStr() */ - virtual QString dtStartTimeStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + virtual KDE_DEPRECATED QString dtStartTimeStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns a todo's starting date as a string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param first If true, the start date of the todo will be returned. If the todo recurs, the start date of the first occurrence will be returned. If false and the todo recurs, the relative start date will be returned, based on the date returned by dtRecurrence(). @param spec If set, returns the date in the given spec, else use the todo's current spec. + + @deprecated use IncidenceFormatter::dateToString() */ - QString dtStartDateStr( bool shortfmt, bool first, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtStartDateStr( + bool shortfmt, bool first, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** @copydoc IncidenceBase::dtStartDateStr() */ - virtual QString dtStartDateStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + virtual KDE_DEPRECATED QString dtStartDateStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns a todo's starting date and time as a string formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. @param first If true, the start date of the todo will be returned. If the todo recurs, the start date of the first occurrence will be returned. If false and the todo recurs, the relative start date will be returned, based on the date returned by dtRecurrence(). @param spec If set, returns the date and time in the given spec, else use the todo's current spec. + + @deprecated use IncidenceFormatter::dateTimeToString() */ - QString dtStartStr( bool shortfmt, bool first, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + KDE_DEPRECATED QString dtStartStr( + bool shortfmt, bool first, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** @copydoc IncidenceBase::dtStartStr() */ - virtual QString dtStartStr( bool shortfmt = true, - const KDateTime::Spec &spec = KDateTime::Spec() ) const; + virtual KDE_DEPRECATED QString dtStartStr( + bool shortfmt = true, const KDateTime::Spec &spec = KDateTime::Spec() ) const; /** Returns true if the todo is 100% completed, otherwise return false. @see setCompleted(), percentComplete() */ bool isCompleted() const; /** Sets completed state. @param completed If true set completed state to 100%, if false set completed state to 0%. @see isCompleted(), percentComplete() */ void setCompleted( bool completed ); /** Returns what percentage of the to-do is completed. Returns a value between 0 and 100. */ int percentComplete() const; /** Sets what percentage of the to-do is completed. Valid values are in the range from 0 to 100. @param percent is the completion percentage, which as integer value between 0 and 100, inclusive. @see isCompleted(), setCompleted() */ void setPercentComplete( int percent ); /** Returns date and time when todo was completed. */ KDateTime completed() const; /** Returns string contaiting date and time when the todo was completed formatted according to the user's locale settings. @param shortfmt If set, use short date format; else use long format. */ QString completedStr( bool shortfmt = false ) const; /** Sets date and time of completion. @param completeDate is the to-do completion date. */ void setCompleted( const KDateTime &completeDate ); /** Returns true, if todo has a date associated with completion, otherwise return false. */ bool hasCompletedDate() const; /** @copydoc IncidenceBase::shiftTimes() */ virtual void shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec ); /** Sets the due date/time of the current occurrence if recurrent. @param dt is the */ void setDtRecurrence( const KDateTime &dt ); /** Returns the due date/time of the current occurrence if recurrent. */ KDateTime dtRecurrence() const; /** Returns true if the @p date specified is one on which the to-do will recur. Todos are a special case, hence the overload. It adds an extra check, which make it return false if there's an occurrence between the recur start and today. @param date is the date to check. @param timeSpec is the */ virtual bool recursOn( const QDate &date, const KDateTime::Spec &timeSpec ) const; /** Returns true if this todo is overdue (e.g. due date is lower than today and not completed), else false. */ bool isOverdue() const; /** Assignment operator. + @param other is the to-do to assign. */ Todo &operator=( const Todo &other ); /** Compare this with @p todo for equality. - @param todo is the to-do to compare. */ bool operator==( const Todo &todo ) const; protected: /** Returns the end date/time of the base incidence. */ virtual KDateTime endDateRecurrenceBase() const; private: /** @copydoc IncidenceBase::accept() */ bool accept( Visitor &v ) { return v.visit( this ); } //@cond PRIVATE class Private; Private *const d; //@endcond }; } #endif