summaryrefslogtreecommitdiff
authorzecke <zecke>2002-11-02 13:00:32 (UTC)
committer zecke <zecke>2002-11-02 13:00:32 (UTC)
commit87504764286a40162d74b03f26e040d4142c0cab (patch) (side-by-side diff)
treed2dd2ccee3d42a8818a5adc2d63c609403ea04b3
parentffd0a764e4ac7f9bf29edf3b9b4d341e153ecf4a (diff)
downloadopie-87504764286a40162d74b03f26e040d4142c0cab.zip
opie-87504764286a40162d74b03f26e040d4142c0cab.tar.gz
opie-87504764286a40162d74b03f26e040d4142c0cab.tar.bz2
Until Opie is compatible to RFC2445 we will beam
vCal Events in local time. So lousy handys (my Nokia6210) gets the dates 'right'
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/backend/event.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/library/backend/event.cpp b/library/backend/event.cpp
index 7cac314..7ccf16b 100644
--- a/library/backend/event.cpp
+++ b/library/backend/event.cpp
@@ -582,742 +582,776 @@ const QString &Event::location() const
\internal
*/
Event::Type Event::type() const
{
return typ;
}
/*
QDateTime Event::start() const {
return start( TRUE );
}
*/
/*!
\internal
*/
QDateTime Event::start( bool actual ) const
{
QDateTime dt = (startUTC > 0) ? TimeConversion::fromUTC( startUTC ) : QDateTime::currentDateTime();
if ( actual && typ == AllDay ) {
QTime t = dt.time();
t.setHMS( 0, 0, 0 );
dt.setTime( t );
}
return dt;
}
/*
QDateTime Event::end() const {
return end( TRUE );
}
*/
/*!
\internal
*/
QDateTime Event::end( bool actual ) const
{
QDateTime dt = (endUTC > 0) ? TimeConversion::fromUTC( endUTC ) : QDateTime::currentDateTime();
if ( actual && typ == AllDay ) {
QTime t = dt.time();
t.setHMS( 23, 59, 59 );
dt.setTime( t );
}
return dt;
}
/*!
\internal
*/
const QString &Event::timeZone() const
{
return tz;
}
/*!
\internal
*/
bool Event::hasAlarm() const
{
return hAlarm;
}
/*!
\internal
*/
int Event::alarmTime() const
{
return aMinutes;
}
/*!
Returns the sound type for the alarm of this event.
*/
Event::SoundTypeChoice Event::alarmSound() const
{
return aSound;
}
/*!
\internal
*/
bool Event::hasRepeat() const
{
return doRepeat();
}
/*!
\internal
*/
const Event::RepeatPattern &Event::repeatPattern() const
{
return pattern;
}
/*!
\internal
*/
Event::RepeatPattern &Event::repeatPattern()
{
return pattern;
}
/*!
Returns the notes for the event.
*/
const QString &Event::notes() const
{
return note;
}
/*!
\internal
*/
bool Event::operator==( const Event &e ) const
{
if ( uid() && e.uid() == uid() )
return TRUE;
return ( e.descript == descript &&
e.locat == locat &&
e.categ == categ &&
e.typ == typ &&
e.startUTC == startUTC &&
e.endUTC == endUTC &&
e.tz == tz &&
e.hAlarm == hAlarm &&
e.aMinutes == aMinutes &&
e.aSound == aSound &&
e.hRepeat == hRepeat &&
e.pattern == pattern &&
e.note == note );
}
/*!
\internal
Appends the contact information to \a buf.
*/
void Event::save( QString& buf )
{
buf += " description=\"" + Qtopia::escapeString(descript) + "\"";
if ( !locat.isEmpty() )
buf += " location=\"" + Qtopia::escapeString(locat) + "\"";
// save the categoies differently....
QString strCats = idsToString( categories() );
buf += " categories=\"" + Qtopia::escapeString(strCats) + "\"";
buf += " uid=\"" + QString::number( uid() ) + "\"";
if ( (Type)typ != Normal )
buf += " type=\"AllDay\"";
if ( hAlarm ) {
buf += " alarm=\"" + QString::number( aMinutes ) + "\" sound=\"";
if ( aSound == Event::Loud )
buf += "loud";
else
buf += "silent";
buf += "\"";
}
if ( hRepeat )
write( buf, pattern );
buf += " start=\""
+ QString::number( startUTC )
+ "\"";
buf += " end=\""
+ QString::number( endUTC )
+ "\"";
if ( !note.isEmpty() )
buf += " note=\"" + Qtopia::escapeString( note ) + "\"";
buf += customToXml();
}
/*!
\internal
*/
bool Event::RepeatPattern::operator==( const Event::RepeatPattern &right ) const
{
// *sigh*
return ( type == right.type
&& frequency == right.frequency
&& position == right.position
&& days == right.days
&& hasEndDate == right.hasEndDate
&& endDateUTC == right.endDateUTC
&& createTime == right.createTime );
}
/*!
\class EffectiveEvent
\brief The EffectiveEvent class the data for a single occurance of an event.
This class describes the event for a single occurance of it. For example if
an Event occurs every week, the effective event might represent the third
occurance of this Event.
\ingroup qtopiaemb
\ingroup qtopiadesktop
\warning This class will be phased out in Qtopia 3.x
*/
/*!
\enum EffectiveEvent::Position
\internal
*/
/*!
\fn EffectiveEvent &EffectiveEvent::operator=(const EffectiveEvent &)
\internal
*/
class EffectiveEventPrivate
{
public:
//currently the existence of the d pointer means multi-day repeating,
//msut be changed if we use the d pointer for anything else.
QDate startDate;
QDate endDate;
};
/*!
\internal
*/
EffectiveEvent::EffectiveEvent()
{
mDate = QDate::currentDate();
mStart = mEnd = QTime::currentTime();
d = 0;
}
/*!
\internal
*/
EffectiveEvent::EffectiveEvent( const Event &e, const QDate &date, Position pos )
{
mEvent = e;
mDate = date;
if ( pos & Start )
mStart = e.start( TRUE ).time();
else
mStart = QTime( 0, 0, 0 );
if ( pos & End )
mEnd = e.end( TRUE ).time();
else
mEnd = QTime( 23, 59, 59 );
d = 0;
}
/*!
\internal
*/
EffectiveEvent::~EffectiveEvent()
{
delete d;
}
/*!
\internal
*/
EffectiveEvent::EffectiveEvent( const EffectiveEvent &e )
{
d = 0;
*this = e;
}
EffectiveEvent& EffectiveEvent::operator=( const EffectiveEvent & e )
{
if ( &e == this )
return *this;
delete d;
if ( e.d ) {
d = new EffectiveEventPrivate;
d->startDate = e.d->startDate;
d->endDate = e.d->endDate;
} else {
d = 0;
}
mEvent = e.mEvent;
mDate = e.mDate;
mStart = e.mStart;
mEnd = e.mEnd;
return *this;
}
// QString EffectiveEvent::category() const
// {
// return mEvent.category();
// }
/*!
Returns the description of the event for this effective event.
*/
const QString &EffectiveEvent::description( ) const
{
return mEvent.description();
}
/*!
\internal
*/
const QString &EffectiveEvent::location( ) const
{
return mEvent.location();
}
/*!
\internal
*/
const QString &EffectiveEvent::notes() const
{
return mEvent.notes();
}
/*!
Returns the event associated with this effective event.
*/
const Event &EffectiveEvent::event() const
{
return mEvent;
}
/*!
\internal
*/
const QTime &EffectiveEvent::end() const
{
return mEnd;
}
/*!
\internal
*/
const QTime &EffectiveEvent::start() const
{
return mStart;
}
/*!
Returns the date the effective event occurs on.
*/
const QDate &EffectiveEvent::date() const
{
return mDate;
}
/*!
\internal
*/
int EffectiveEvent::length() const
{
return (mEnd.hour() * 60 - mStart.hour() * 60)
+ QABS(mStart.minute() - mEnd.minute() );
}
/*!
\internal
*/
void EffectiveEvent::setDate( const QDate &dt )
{
mDate = dt;
}
/*!
\internal
*/
void EffectiveEvent::setStart( const QTime &start )
{
mStart = start;
}
/*!
\internal
*/
void EffectiveEvent::setEnd( const QTime &end )
{
mEnd = end;
}
/*!
\internal
*/
void EffectiveEvent::setEvent( Event e )
{
mEvent = e;
}
/*!
\internal
*/
bool EffectiveEvent::operator<( const EffectiveEvent &e ) const
{
if ( mDate < e.date() )
return TRUE;
if ( mDate == e.date() )
return ( mStart < e.start() );
else
return FALSE;
}
/*!
\internal
*/
bool EffectiveEvent::operator<=( const EffectiveEvent &e ) const
{
return (mDate <= e.date() );
}
/*!
\internal
*/
bool EffectiveEvent::operator==( const EffectiveEvent &e ) const
{
return ( mDate == e.date()
&& mStart == e.start()
&& mEnd == e.end()
&& mEvent == e.event() );
}
/*!
\internal
*/
bool EffectiveEvent::operator!=( const EffectiveEvent &e ) const
{
return !(*this == e);
}
/*!
\internal
*/
bool EffectiveEvent::operator>( const EffectiveEvent &e ) const
{
return !(*this <= e );
}
/*!
\internal
*/
bool EffectiveEvent::operator>=(const EffectiveEvent &e) const
{
return !(*this < e);
}
/*!
\internal
*/
void EffectiveEvent::setEffectiveDates( const QDate &from, const QDate &to )
{
if ( !from.isValid() ) {
delete d;
d = 0;
return;
}
if ( !d )
d = new EffectiveEventPrivate;
d->startDate = from;
d->endDate = to;
}
/*!
\internal
*/
QDate EffectiveEvent::startDate() const
{
if ( d )
return d->startDate;
else if ( mEvent.hasRepeat() )
return mDate; // single day, since multi-day should have a d pointer
else
return mEvent.start().date();
}
/*!
\internal
*/
QDate EffectiveEvent::endDate() const
{
if ( d )
return d->endDate;
else if ( mEvent.hasRepeat() )
return mDate; // single day, since multi-day should have a d pointer
else
return mEvent.end().date();
}
/*!
\internal
*/
int EffectiveEvent::size() const
{
return ( mEnd.hour() - mStart.hour() ) * 3600
+ (mEnd.minute() - mStart.minute() * 60
+ mEnd.second() - mStart.second() );
}
// vcal conversion code
static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
{
VObject *ret = 0;
if ( o && !value.isEmpty() )
ret = addPropValue( o, prop, value.latin1() );
return ret;
}
static inline VObject *safeAddProp( VObject *o, const char *prop)
{
VObject *ret = 0;
if ( o )
ret = addProp( o, prop );
return ret;
}
+/*
+ * Until we support vCal/iCal right
+ * we will make DTSTART and other things
+ * be floating in the sense of
+ * RFC 2445
+ */
+namespace {
+/*
+ * Convert QDateTime to iso8601 but take
+ * local time and do not use the Z at the end
+ *
+ */
+ QCString toISOLocal( const QDateTime& dt ) {
+ QCString str;
+ /*
+ * year month day T Hour Minute Second
+ * 4 2 2 2 2 2 digits
+ */
+ str.sprintf("%04d%02d%02dT%02d%02d%02d",
+ dt.date().year(),
+ dt.date().month(),
+ dt.date().year(),
+ dt.time().hour(),
+ dt.time().minute(),
+ dt.time().second() );
+
+
+
+ return str;
+ }
+
+
+};
+
static VObject *createVObject( const Event &e )
{
VObject *vcal = newVObject( VCCalProp );
safeAddPropValue( vcal, VCVersionProp, "1.0" );
VObject *event = safeAddProp( vcal, VCEventProp );
safeAddPropValue( event, VCDTstartProp, TimeConversion::toISO8601( e.start() ) );
safeAddPropValue( event, VCDTendProp, TimeConversion::toISO8601( e.end() ) );
safeAddPropValue( event, "X-Qtopia-NOTES", e.description() );
safeAddPropValue( event, VCDescriptionProp, e.description() );
safeAddPropValue( event, VCLocationProp, e.location() );
if ( e.hasAlarm() ) {
VObject *alarm = safeAddProp( event, VCAAlarmProp );
QDateTime dt = e.start();
dt = dt.addSecs( -e.alarmTime()*60 );
safeAddPropValue( alarm, VCRunTimeProp, TimeConversion::toISO8601( dt ) );
safeAddPropValue( alarm, VCAudioContentProp,
(e.alarmSound() == Event::Silent ? "silent" : "alarm" ) );
}
safeAddPropValue( event, "X-Qtopia-TIMEZONE", e.timeZone() );
if ( e.type() == Event::AllDay )
safeAddPropValue( event, "X-Qtopia-AllDay", e.timeZone() );
// ### repeat missing
// ### categories missing
return vcal;
}
static Event parseVObject( VObject *obj )
{
Event e;
bool haveAlarm = FALSE;
bool haveStart = FALSE;
bool haveEnd = FALSE;
QDateTime alarmTime;
Event::SoundTypeChoice soundType = Event::Silent;
VObjectIterator it;
initPropIterator( &it, obj );
while( moreIteration( &it ) ) {
VObject *o = nextVObject( &it );
QCString name = vObjectName( o );
QCString value = vObjectStringZValue( o );
if ( name == VCDTstartProp ) {
e.setStart( TimeConversion::fromISO8601( value ) );
haveStart = TRUE;
}
else if ( name == VCDTendProp ) {
e.setEnd( TimeConversion::fromISO8601( value ) );
haveEnd = TRUE;
}
else if ( name == "X-Qtopia-NOTES" ) {
e.setNotes( value );
}
else if ( name == VCDescriptionProp ) {
e.setDescription( value );
}
else if ( name == VCLocationProp ) {
e.setLocation( value );
}
else if ( name == VCAudioContentProp ) {
haveAlarm = TRUE;
VObjectIterator nit;
initPropIterator( &nit, o );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectName( o );
QCString value = vObjectStringZValue( o );
if ( name == VCRunTimeProp )
alarmTime = TimeConversion::fromISO8601( value );
else if ( name == VCAudioContentProp ) {
if ( value == "silent" )
soundType = Event::Silent;
else
soundType = Event::Loud;
}
}
}
else if ( name == "X-Qtopia-TIMEZONE") {
e.setTimeZone( value );
}
else if ( name == "X-Qtopia-AllDay" ) {
e.setType( Event::AllDay );
}
#if 0
else {
printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
VObjectIterator nit;
initPropIterator( &nit, o );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectName( o );
QString value = vObjectStringZValue( o );
printf(" subprop: %s = %s\n", name.data(), value.latin1() );
}
}
#endif
}
if ( !haveStart && !haveEnd )
e.setStart( QDateTime::currentDateTime() );
if ( !haveEnd ) {
e.setType( Event::AllDay );
e.setEnd( e.start() );
}
if ( haveAlarm ) {
int minutes = alarmTime.secsTo( e.start() ) / 60;
e.setAlarm( TRUE, minutes, soundType );
}
return e;
}
/*!
Writes the list of \a events as a set of VCards to the file \a filename.
*/
void Event::writeVCalendar( const QString &filename, const QValueList<Event> &events)
{
QFileDirect f( filename.utf8().data() );
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vcard write");
return;
}
QValueList<Event>::ConstIterator it;
for( it = events.begin(); it != events.end(); ++it ) {
VObject *obj = createVObject( *it );
writeVObject( f.directHandle() , obj );
cleanVObject( obj );
}
cleanStrTbl();
}
/*!
Writes \a event as a VCard to the file \a filename.
*/
void Event::writeVCalendar( const QString &filename, const Event &event)
{
QFileDirect f( filename.utf8().data() );
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vcard write");
return;
}
VObject *obj = createVObject( event );
writeVObject( f.directHandle() , obj );
cleanVObject( obj );
cleanStrTbl();
}
/*!
Returns the set of events read as VCards from the file \a filename.
*/
QValueList<Event> Event::readVCalendar( const QString &filename )
{
VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
QValueList<Event> events;
while ( obj ) {
QCString name = vObjectName( obj );
if ( name == VCCalProp ) {
VObjectIterator nit;
initPropIterator( &nit, obj );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectName( o );
if ( name == VCEventProp )
events.append( parseVObject( o ) );
}
} else if ( name == VCEventProp ) {
// shouldn't happen, but just to be sure
events.append( parseVObject( obj ) );
}
VObject *t = obj;
obj = nextVObjectInList(obj);
cleanVObject( t );
}
return events;
}
bool Event::match( const QRegExp &r ) const
{
bool returnMe;
returnMe = false;
if ( descript.find( r ) > -1 )
returnMe = true;
else if ( locat.find( r ) > -1 )
returnMe = true;
else if ( TimeConversion::fromUTC( startUTC ).toString().find( r ) > -1 )
returnMe = true;
else if ( TimeConversion::fromUTC( endUTC ).toString().find( r ) > -1 )
returnMe = true;
else if ( tz.find( r ) > -1 )
returnMe = true;
else if ( note.find( r ) > -1 )
returnMe = true;
else if ( doRepeat() ) {
if ( pattern.hasEndDate )
if ( TimeConversion::fromUTC( pattern.endDateUTC ).toString().find(r) > -1 )
returnMe = true;
}
return returnMe;
}