summaryrefslogtreecommitdiffabout
path: root/libkcal
Side-by-side diff
Diffstat (limited to 'libkcal') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/event.cpp46
-rw-r--r--libkcal/event.h2
-rw-r--r--libkcal/phoneformat.cpp104
-rw-r--r--libkcal/phoneformat.h2
-rw-r--r--libkcal/todo.cpp58
-rw-r--r--libkcal/todo.h1
-rw-r--r--libkcal/vcalformat.cpp141
7 files changed, 227 insertions, 127 deletions
diff --git a/libkcal/event.cpp b/libkcal/event.cpp
index dfa265b..7256f05 100644
--- a/libkcal/event.cpp
+++ b/libkcal/event.cpp
@@ -1,177 +1,223 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include "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()
{
}
Incidence *Event::clone()
{
return new Event(*this);
}
bool KCal::operator==( const Event& e1, const Event& e2 )
{
return operator==( (const Incidence&)e1, (const Incidence&)e2 ) &&
e1.dtEnd() == e2.dtEnd() &&
e1.hasEndDate() == e2.hasEndDate() &&
e1.transparency() == e2.transparency();
}
+bool Event::contains ( Event* from )
+{
+
+ if ( !from->summary().isEmpty() )
+ if ( !summary().startsWith( from->summary() ))
+ return false;
+ if ( from->dtStart().isValid() )
+ if (dtStart() != from->dtStart() )
+ return false;
+ if ( from->dtEnd().isValid() )
+ if ( dtEnd() != from->dtEnd() )
+ return false;
+ if ( !from->location().isEmpty() )
+ if ( !location().startsWith( from->location() ) )
+ return false;
+ if ( !from->description().isEmpty() )
+ if ( !description().startsWith( from->description() ))
+ return false;
+ if ( from->alarms().count() ) {
+ Alarm *a = from->alarms().first();
+ if ( a->enabled() ){
+ if ( !alarms().count() )
+ return false;
+ Alarm *b = alarms().first();
+ if( ! b->enabled() )
+ return false;
+ if ( ! (a->offset() == b->offset() ))
+ return false;
+ }
+ }
+ QStringList cat = categories();
+ QStringList catFrom = from->categories();
+ QString nCat;
+ int iii;
+ for ( iii = 0; iii < catFrom.count();++iii ) {
+ nCat = catFrom[iii];
+ if ( !nCat.isEmpty() )
+ if ( !cat.contains( nCat )) {
+ return false;
+ }
+ }
+ if ( from->doesRecur() )
+ if ( from->doesRecur() != doesRecur() && ! (from->doesRecur()== Recurrence::rYearlyMonth && doesRecur()== Recurrence::rYearlyDay) )
+ return false;
+ return true;
+}
void Event::setDtEnd(const QDateTime &dtEnd)
{
if (mReadOnly) return;
mDtEnd = getEvenTime( 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(bool shortfmt) const
{
return KGlobal::locale()->formatDateTime(mDtEnd, shortfmt);
}
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);
}
QDateTime Event::getNextAlarmDateTime( bool * ok, int * offset ) const
{
bool yes;
QDateTime incidenceStart = getNextOccurence( QDateTime::currentDateTime(), &yes );
if ( ! yes || cancelled() ) {
*ok = false;
return QDateTime ();
}
bool enabled = false;
Alarm* alarm;
int off;
QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );;
// if ( QDateTime::currentDateTime() > incidenceStart ){
// *ok = false;
// return incidenceStart;
// }
for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) {
if (alarm->enabled()) {
if ( alarm->hasTime () ) {
if ( alarm->time() < alarmStart ) {
alarmStart = alarm->time();
enabled = true;
off = alarmStart.secsTo( incidenceStart );
}
} else {
int secs = alarm->startOffset().asSeconds();
if ( incidenceStart.addSecs( secs ) < alarmStart ) {
alarmStart = incidenceStart.addSecs( secs );
enabled = true;
off = -secs;
}
}
}
}
if ( enabled ) {
if ( alarmStart > QDateTime::currentDateTime() ) {
*ok = true;
* offset = off;
return alarmStart;
}
}
*ok = false;
return QDateTime ();
}
diff --git a/libkcal/event.h b/libkcal/event.h
index 2a8bd95..3bc8adc 100644
--- a/libkcal/event.h
+++ b/libkcal/event.h
@@ -1,88 +1,90 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef EVENT_H
#define EVENT_H
//
// Event component, representing a VEVENT object
//
#include "incidence.h"
namespace KCal {
/**
This class provides an Event in the sense of RFC2445.
*/
class Event : public Incidence
{
public:
enum Transparency { Opaque, Transparent };
typedef ListBase<Event> List;
Event();
Event(const Event &);
~Event();
QCString type() const { return "Event"; }
Incidence *clone();
QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const;
/** for setting an event's ending date/time with a QDateTime. */
void setDtEnd(const QDateTime &dtEnd);
/** Return the event's ending date/time as a QDateTime. */
virtual QDateTime dtEnd() const;
/** returns an event's end time as a string formatted according to the
users locale settings */
QString dtEndTimeStr() const;
/** returns an event's end date as a string formatted according to the
users locale settings */
QString dtEndDateStr(bool shortfmt=true) const;
/** returns an event's end date and time as a string formatted according
to the users locale settings */
QString dtEndStr(bool shortfmt=true) const;
void setHasEndDate(bool);
/** Return whether the event has an end date/time. */
bool hasEndDate() const;
/** Return true if the event spans multiple days, otherwise return false. */
bool isMultiDay() const;
/** set the event's time transparency level. */
void setTransparency(Transparency transparency);
/** get the event's time transparency level. */
Transparency transparency() const;
void setDuration(int seconds);
+ bool contains ( Event*);
+
private:
bool accept(Visitor &v) { return v.visit(this); }
QDateTime mDtEnd;
bool mHasEndDate;
Transparency mTransparency;
};
bool operator==( const Event&, const Event& );
}
#endif
diff --git a/libkcal/phoneformat.cpp b/libkcal/phoneformat.cpp
index 281434e..101db57 100644
--- a/libkcal/phoneformat.cpp
+++ b/libkcal/phoneformat.cpp
@@ -1,634 +1,620 @@
/*
This file is part of libkcal.
Copyright (c) 2004 Lutz Rogowski <rogowski@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <qdatetime.h>
#include <qstring.h>
#include <qapplication.h>
#include <qptrlist.h>
#include <qregexp.h>
#include <qmessagebox.h>
#include <qclipboard.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qtextcodec.h>
#include <qdir.h>
#include <qlabel.h>
#include <kdebug.h>
#include <klocale.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <phoneaccess.h>
#include "calendar.h"
#include "alarm.h"
#include "recurrence.h"
#include "calendarlocal.h"
#include "phoneformat.h"
#include "syncdefines.h"
using namespace KCal;
class PhoneParser : public QObject
{
public:
PhoneParser( ) {
;
}
static QString dtToString( const QDateTime& dti, bool useTZ = false )
{
QString datestr;
QString timestr;
int offset = KGlobal::locale()->localTimeOffset( dti );
QDateTime dt;
if (useTZ)
dt = dti.addSecs ( -(offset*60));
else
dt = dti;
if(dt.date().isValid()){
const QDate& date = dt.date();
datestr.sprintf("%04d%02d%02d",
date.year(), date.month(), date.day());
}
if(dt.time().isValid()){
const QTime& time = dt.time();
timestr.sprintf("T%02d%02d%02d",
time.hour(), time.minute(), time.second());
}
return datestr + timestr;
}
};
PhoneFormat::PhoneFormat(QString profileName, QString device,QString connection, QString model )
{
mProfileName = profileName;
PhoneAccess::writeConfig( device, connection, model );
}
PhoneFormat::~PhoneFormat()
{
}
#if 0
int PhoneFormat::initDevice(GSM_StateMachine *s)
{
GSM_ReadConfig(NULL, &s->Config[0], 0);
s->ConfigNum = 1;
GSM_Config *cfg = &s->Config[0];
if ( ! mConnection.isEmpty() ) {
cfg->Connection = strdup(mConnection.latin1());
cfg->DefaultConnection = false;
qDebug("Connection set %s ", cfg->Connection );
}
if ( ! mDevice.isEmpty() ) {
cfg->Device = strdup(mDevice.latin1());
cfg->DefaultDevice = false;
qDebug("Device set %s ", cfg->Device);
}
if ( ! mModel.isEmpty() ) {
strcpy(cfg->Model,mModel.latin1() );
cfg->DefaultModel = false;
qDebug("Model set %s ",cfg->Model );
}
int error=GSM_InitConnection(s,3);
return error;
}
#endif
ulong PhoneFormat::getCsumTodo( Todo* todo )
{
QStringList attList;
if ( todo->hasDueDate() )
attList << PhoneParser::dtToString ( todo->dtDue() );
attList << todo->summary();
QString completedString = "no";
if ( todo->isCompleted() )
completedString = "yes";
attList << completedString;
int prio = todo->priority();
if( prio == 2 ) prio = 1;
if (prio == 4 ) prio = 5 ;
attList << QString::number( prio );
QString alarmString = "na";
Alarm *alarm;
if ( todo->alarms().count() > 0 ) {
alarm = todo->alarms().first();
if ( alarm->enabled() ) {
alarmString = QString::number(alarm->offset() );
}
}
attList << alarmString;
attList << todo->categoriesStr();
attList << todo->secrecyStr();
return PhoneFormat::getCsum(attList );
}
ulong PhoneFormat::getCsumEvent( Event* event )
{
QStringList attList;
attList << PhoneParser::dtToString ( event->dtStart() );
attList << PhoneParser::dtToString ( event->dtEnd() );
attList << event->summary();
attList << event->location();
QString alarmString = "na";
Alarm *alarm;
if ( event->alarms().count() > 0 ) {
alarm = event->alarms().first();
if ( alarm->enabled() ) {
alarmString = QString::number( alarm->offset() );
}
}
attList << alarmString;
Recurrence* rec = event->recurrence();
QStringList list;
bool writeEndDate = false;
switch ( rec->doesRecur() )
{
case Recurrence::rDaily: // 0
list.append( "0" );
list.append( QString::number( rec->frequency() ));//12
list.append( "0" );
list.append( "0" );
writeEndDate = true;
break;
case Recurrence::rWeekly:// 1
list.append( "1" );
list.append( QString::number( rec->frequency()) );//12
list.append( "0" );
{
int days = 0;
QBitArray weekDays = rec->days();
int i;
for( i = 1; i <= 7; ++i ) {
if ( weekDays[i-1] ) {
days += 1 << (i-1);
}
}
list.append( QString::number( days ) );
}
//pending weekdays
writeEndDate = true;
break;
case Recurrence::rMonthlyPos:// 2
list.append( "2" );
list.append( QString::number( rec->frequency()) );//12
writeEndDate = true;
{
int count = 1;
QPtrList<Recurrence::rMonthPos> rmp;
rmp = rec->monthPositions();
if ( rmp.first()->negative )
count = 5 - rmp.first()->rPos - 1;
else
count = rmp.first()->rPos - 1;
list.append( QString::number( count ) );
}
list.append( "0" );
break;
case Recurrence::rMonthlyDay:// 3
list.append( "3" );
list.append( QString::number( rec->frequency()) );//12
list.append( "0" );
list.append( "0" );
writeEndDate = true;
break;
case Recurrence::rYearlyMonth://4
list.append( "4" );
list.append( QString::number( rec->frequency()) );//12
list.append( "0" );
list.append( "0" );
writeEndDate = true;
break;
default:
list.append( "255" );
list.append( QString() );
list.append( "0" );
list.append( QString() );
list.append( "0" );
list.append( "20991231T000000" );
break;
}
if ( writeEndDate ) {
if ( rec->endDate().isValid() ) { // 15 + 16
list.append( "1" );
list.append( PhoneParser::dtToString( rec->endDate()) );
} else {
list.append( "0" );
list.append( "20991231T000000" );
}
}
attList << list.join("");
attList << event->categoriesStr();
//qDebug("csum cat %s", event->categoriesStr().latin1());
attList << event->secrecyStr();
return PhoneFormat::getCsum(attList );
}
ulong PhoneFormat::getCsum( const QStringList & attList)
{
int max = attList.count();
ulong cSum = 0;
int j,k,i;
int add;
for ( i = 0; i < max ; ++i ) {
QString s = attList[i];
if ( ! s.isEmpty() ){
j = s.length();
for ( k = 0; k < j; ++k ) {
int mul = k +1;
add = s[k].unicode ();
if ( k < 16 )
mul = mul * mul;
int ii = i+1;
add = add * mul *ii*ii*ii;
cSum += add;
}
}
}
//QString dump = attList.join(",");
//qDebug("csum: %d %s", cSum,dump.latin1());
return cSum;
}
//extern "C" GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum);
#include <stdlib.h>
#define DEBUGMODE false
bool PhoneFormat::load( Calendar *calendar, Calendar *existingCal)
{
QString fileName;
#ifdef _WIN32_
fileName = locateLocal("tmp", "phonefile.vcs");
#else
fileName = "/tmp/phonefile.vcs";
#endif
QString command;
if ( ! PhoneAccess::readFromPhone( fileName )) {
return false;
}
VCalFormat vfload;
vfload.setLocalTime ( true );
qDebug("loading file ...");
if ( ! vfload.load( calendar, fileName ) )
return false;
QPtrList<Event> er = calendar->rawEvents();
Event* ev = er.first();
qDebug("reading events... ");
while ( ev ) {
QStringList cat = ev->categories();
if ( cat.contains( "MeetingDEF" )) {
ev->setCategories( QStringList() );
+ } else
+ if ( cat.contains( "Birthday" )) {
+ ev->setFloats( true );
+ QDate da = ev->dtStart().date();
+ ev->setDtStart( QDateTime( da) );
+ ev->setDtEnd( QDateTime( da.addDays(1)) );
+
}
+ uint cSum;
+ cSum = PhoneFormat::getCsumEvent( ev );
int id = ev->pilotId();
Event *event;
event = existingCal->event( mProfileName ,QString::number( id ) );
if ( event ) {
event = (Event*)event->clone();
copyEvent( event, ev );
calendar->deleteEvent( ev );
calendar->addEvent( event);
}
else
event = ev;
- uint cSum;
- cSum = PhoneFormat::getCsumEvent( event );
event->setCsum( mProfileName, QString::number( cSum ));
event->setTempSyncStat( SYNC_TEMPSTATE_NEW_EXTERNAL );
event->setID( mProfileName,QString::number( id ) );
ev = er.next();
}
{
qDebug("reading todos... ");
QPtrList<Todo> tr = calendar->rawTodos();
Todo* ev = tr.first();
while ( ev ) {
QStringList cat = ev->categories();
if ( cat.contains( "MeetingDEF" )) {
ev->setCategories( QStringList() );
}
int id = ev->pilotId();
+ uint cSum;
+ cSum = PhoneFormat::getCsumTodo( ev );
Todo *event;
event = existingCal->todo( mProfileName ,QString::number( id ) );
if ( event ) {
//qDebug("copy todo %s ", event->summary().latin1());
event = (Todo*)event->clone();
copyTodo( event, ev );
calendar->deleteTodo( ev );
calendar->addTodo( event);
}
else
event = ev;
- uint cSum;
- cSum = PhoneFormat::getCsumTodo( event );
event->setCsum( mProfileName, QString::number( cSum ));
event->setTempSyncStat( SYNC_TEMPSTATE_NEW_EXTERNAL );
event->setID( mProfileName,QString::number( id ) );
ev = tr.next();
}
}
return true;
}
void PhoneFormat::copyEvent( Event* to, Event* from )
{
if ( from->dtStart().isValid() )
to->setDtStart( from->dtStart() );
if ( from->dtEnd().isValid() )
to->setDtEnd( from->dtEnd() );
if ( !from->location().isEmpty() )
to->setLocation( from->location() );
if ( !from->description().isEmpty() )
to->setDescription( from->description() );
if ( !from->summary().isEmpty() )
to->setSummary( from->summary() );
if ( from->alarms().count() ) {
to->clearAlarms();
Alarm *a = from->alarms().first();
Alarm *b = to->newAlarm( );
b->setEnabled( a->enabled() );
- if ( a->hasStartOffset() ) {
- b->setStartOffset( a->startOffset() );
- }
- if ( a->hasTime() )
- b->setTime( a->time() );
+ b->setStartOffset(Duration( a->offset() ) );
}
QStringList cat = to->categories();
QStringList catFrom = from->categories();
QString nCat;
int iii;
for ( iii = 0; iii < catFrom.count();++iii ) {
nCat = catFrom[iii];
if ( !nCat.isEmpty() )
if ( !cat.contains( nCat )) {
cat << nCat;
}
}
to->setCategories( cat );
- Recurrence * r = new Recurrence( *from->recurrence(),to);
- to->setRecurrence( r ) ;
+ if ( from->doesRecur() ) {
+ Recurrence * r = new Recurrence( *from->recurrence(),to);
+ to->setRecurrence( r ) ;
+ }
}
void PhoneFormat::copyTodo( Todo* to, Todo* from )
{
- if ( from->dtStart().isValid() )
+ if ( from->hasStartDate() ) {
+ to->setHasStartDate( true );
to->setDtStart( from->dtStart() );
- if ( from->dtDue().isValid() )
+ }
+ if ( from->hasDueDate() ){
+ to->setHasDueDate( true );
to->setDtDue( from->dtDue() );
+ }
if ( !from->location().isEmpty() )
to->setLocation( from->location() );
if ( !from->description().isEmpty() )
to->setDescription( from->description() );
if ( !from->summary().isEmpty() )
to->setSummary( from->summary() );
if ( from->alarms().count() ) {
to->clearAlarms();
Alarm *a = from->alarms().first();
Alarm *b = to->newAlarm( );
b->setEnabled( a->enabled() );
- if ( a->hasStartOffset() )
- b->setStartOffset( a->startOffset() );
- if ( a->hasTime() )
- b->setTime( a->time() );
+ b->setStartOffset(Duration( a->offset() ) );
}
QStringList cat = to->categories();
QStringList catFrom = from->categories();
QString nCat;
int iii;
for ( iii = 0; iii < catFrom.count();++iii ) {
nCat = catFrom[iii];
if ( !nCat.isEmpty() )
if ( !cat.contains( nCat )) {
cat << nCat;
}
}
to->setCategories( cat );
if ( from->isCompleted() ) {
to->setCompleted( true );
if( from->completed().isValid() )
to->setCompleted( from->completed() );
} else {
// set percentcomplete only, if to->isCompleted()
if ( to->isCompleted() )
to->setPercentComplete(from->percentComplete());
}
if( to->priority() == 2 && from->priority() == 1 )
; //skip
else if (to->priority() == 4 && from->priority() == 5 )
;
else
to->setPriority(from->priority());
}
#include <qcstring.h>
-void PhoneFormat::afterSave( Incidence* inc)
+void PhoneFormat::afterSave( Incidence* inc,const QString& id ,const QString& csum)
{
- uint csum;
- inc->removeID( mProfileName );
- if ( inc->type() == "Event")
- csum = PhoneFormat::getCsumEvent( (Event*) inc );
- else
- csum = PhoneFormat::getCsumTodo( (Todo*) inc );
- inc->setCsum( mProfileName, QString::number( csum ));
-
+ inc->setID( mProfileName, id );
+ inc->setCsum( mProfileName, csum);
inc->setTempSyncStat( SYNC_TEMPSTATE_NEW_ID );
}
bool PhoneFormat::writeToPhone( Calendar * calendar)
{
#ifdef _WIN32_
- QString fileName = locateLocal("tmp", "tempfile.vcs");
+ QString fileName = locateLocal("tmp", "phonefile.vcs");
#else
- QString fileName = "/tmp/kdepimtemp.vcs";
+ QString fileName = "/tmp/phonefile.vcs";
#endif
VCalFormat vfsave;
vfsave.setLocalTime ( true );
QString id = calendar->timeZoneId();
calendar->setLocalTime();
if ( ! vfsave.save( calendar, fileName ) )
return false;
calendar->setTimeZoneId( id );
return PhoneAccess::writeToPhone( fileName );
}
bool PhoneFormat::save( Calendar *calendar)
{
- QLabel status ( i18n(" Opening device ..."), 0 );
- int w = status.sizeHint().width()+20 ;
- if ( w < 200 ) w = 230;
- int h = status.sizeHint().height()+20 ;
- int dw = QApplication::desktop()->width();
- int dh = QApplication::desktop()->height();
- status.setCaption(i18n("Writing to phone...") );
- status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
- status.show();
- status.raise();
- qApp->processEvents();
- QString message;
+
// 1 remove events which should be deleted
QPtrList<Event> er = calendar->rawEvents();
Event* ev = er.first();
while ( ev ) {
if ( ev->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) {
calendar->deleteEvent( ev );
} else {
}
ev = er.next();
}
// 2 remove todos which should be deleted
QPtrList<Todo> tl = calendar->rawTodos();
Todo* to = tl.first();
while ( to ) {
if ( to->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) {
calendar->deleteTodo( to );
} else {
if ( to->isCompleted()) {
calendar->deleteTodo( to );
}
}
to = tl.next();
}
// 3 save file
if ( !writeToPhone( calendar ) )
return false;
-
+ QLabel status ( i18n(" Opening device ..."), 0 );
+ int w = status.sizeHint().width()+20 ;
+ if ( w < 200 ) w = 230;
+ int h = status.sizeHint().height()+20 ;
+ int dw = QApplication::desktop()->width();
+ int dh = QApplication::desktop()->height();
+ status.setCaption(i18n("Writing to phone...") );
+ status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
+ QString message;
+ status.show();
+ status.raise();
+ qApp->processEvents();
// 5 reread data
message = i18n(" Rereading all data ... ");
status.setText ( message );
qApp->processEvents();
CalendarLocal* calendarTemp = new CalendarLocal();
calendarTemp->setTimeZoneId( calendar->timeZoneId());
if ( ! load( calendarTemp,calendar) ){
qDebug("error reloading calendar ");
delete calendarTemp;
return false;
}
// 6 compare data
//algo 6 compare event
er = calendar->rawEvents();
ev = er.first();
message = i18n(" Comparing event # ");
QPtrList<Event> er1 = calendarTemp->rawEvents();
Event* ev1;
int procCount = 0;
while ( ev ) {
//qDebug("event new ID %s",ev->summary().latin1());
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
- uint csum;
- csum = PhoneFormat::getCsumEvent( ev );
- QString cSum = QString::number( csum );
- //ev->setCsum( mProfileName, cSum );
- //qDebug("Event cSum %s ", cSum.latin1());
ev1 = er1.first();
while ( ev1 ) {
- if ( ev1->getCsum( mProfileName ) == cSum ) {
+ if ( ev->contains( ev1 ) ) {
+ afterSave( ev ,ev1->getID(mProfileName),ev1->getCsum(mProfileName));
er1.remove( ev1 );
- afterSave( ev );
- ev->setID(mProfileName, ev1->getID(mProfileName) );
- //qDebug("Event found on phone for %s ", ev->summary().latin1());
-
break;
}
ev1 = er1.next();
}
if ( ! ev1 ) {
// ev->removeID(mProfileName);
qDebug("ERROR: No event found on phone for %s ", ev->summary().latin1());
}
ev = er.next();
}
//algo 6 compare todo
tl = calendar->rawTodos();
to = tl.first();
procCount = 0;
QPtrList<Todo> tl1 = calendarTemp->rawTodos();
Todo* to1 ;
message = i18n(" Comparing todo # ");
while ( to ) {
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
- uint csum;
- csum = PhoneFormat::getCsumTodo( to );
- QString cSum = QString::number( csum );
- //to->setCsum( mProfileName, cSum );
- //qDebug("Todo cSum %s ", cSum.latin1());
Todo* to1 = tl1.first();
while ( to1 ) {
- if ( to1->getCsum( mProfileName ) == cSum ) {
+ if ( to->contains( to1 ) ) {
+ afterSave( to ,to1->getID(mProfileName),to1->getCsum(mProfileName));
tl1.remove( to1 );
- afterSave( to );
- to->setID(mProfileName, to1->getID(mProfileName) );
break;
}
to1 = tl1.next();
}
if ( ! to1 ) {
//to->removeID(mProfileName);
qDebug("ERROR: No todo found on phone for %s ", to->summary().latin1());
}
to = tl.next();
}
delete calendarTemp;
return true;
}
QString PhoneFormat::toString( Calendar * )
{
return QString::null;
}
bool PhoneFormat::fromString( Calendar *calendar, const QString & text)
{
return false;
}
diff --git a/libkcal/phoneformat.h b/libkcal/phoneformat.h
index 001fd81..d11f68b 100644
--- a/libkcal/phoneformat.h
+++ b/libkcal/phoneformat.h
@@ -1,62 +1,62 @@
/*
This file is part of libkcal.
Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef PHONEFORMAT_H
#define PHONEFORMAT_H
#include <qstring.h>
#include "scheduler.h"
#include "vcalformat.h"
#include "calformat.h"
namespace KCal {
/**
This class implements the calendar format used by Phone.
*/
class Event;
class Todo;
class PhoneFormat : public QObject {
public:
/** Create new iCalendar format. */
PhoneFormat(QString profileName, QString device,QString connection, QString model);
virtual ~PhoneFormat();
bool load( Calendar * ,Calendar * );
bool save( Calendar * );
bool fromString( Calendar *, const QString & );
QString toString( Calendar * );
static ulong getCsum( const QStringList & );
static ulong getCsumTodo( Todo* to );
static ulong getCsumEvent( Event* ev );
static bool writeToPhone( Calendar * );
private:
void copyEvent( Event* to, Event* from );
void copyTodo( Todo* to, Todo* from );
//int initDevice(GSM_StateMachine *s);
QString mProfileName;
- void afterSave( Incidence* );
+ void afterSave( Incidence* ,const QString&,const QString&);
};
}
#endif
diff --git a/libkcal/todo.cpp b/libkcal/todo.cpp
index 0c1e3e4..3d2de61 100644
--- a/libkcal/todo.cpp
+++ b/libkcal/todo.cpp
@@ -1,316 +1,374 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <kglobal.h>
#include <klocale.h>
#include <kdebug.h>
#include "todo.h"
using namespace KCal;
Todo::Todo(): Incidence()
{
// mStatus = TENTATIVE;
mHasDueDate = false;
setHasStartDate( false );
mCompleted = getEvenTime(QDateTime::currentDateTime());
mHasCompletedDate = false;
mPercentComplete = 0;
}
Todo::Todo(const Todo &t) : Incidence(t)
{
mDtDue = t.mDtDue;
mHasDueDate = t.mHasDueDate;
mCompleted = t.mCompleted;
mHasCompletedDate = t.mHasCompletedDate;
mPercentComplete = t.mPercentComplete;
}
Todo::~Todo()
{
}
Incidence *Todo::clone()
{
return new Todo(*this);
}
+bool Todo::contains ( Todo* from )
+{
+ if ( !from->summary().isEmpty() )
+ if ( !summary().startsWith( from->summary() ))
+ return false;
+ if ( from->hasStartDate() ) {
+ if ( !hasStartDate() )
+ return false;
+ if ( from->dtStart() != dtStart())
+ return false;
+ }
+ if ( from->hasDueDate() ){
+ if ( !hasDueDate() )
+ return false;
+ if ( from->dtDue() != dtDue())
+ return false;
+ }
+ if ( !from->location().isEmpty() )
+ if ( !location().startsWith( from->location() ) )
+ return false;
+ if ( !from->description().isEmpty() )
+ if ( !description().startsWith( from->description() ))
+ return false;
+ if ( from->alarms().count() ) {
+ Alarm *a = from->alarms().first();
+ if ( a->enabled() ){
+ if ( !alarms().count() )
+ return false;
+ Alarm *b = alarms().first();
+ if( ! b->enabled() )
+ return false;
+ if ( ! (a->offset() == b->offset() ))
+ return false;
+ }
+ }
+
+ QStringList cat = categories();
+ QStringList catFrom = from->categories();
+ QString nCat;
+ int iii;
+ for ( iii = 0; iii < catFrom.count();++iii ) {
+ nCat = catFrom[iii];
+ if ( !nCat.isEmpty() )
+ if ( !cat.contains( nCat )) {
+ return false;
+ }
+ }
+ if ( from->isCompleted() ) {
+ if ( !isCompleted() )
+ return false;
+ }
+ if( priority() != from->priority() )
+ return false;
+
+
+ return true;
+
+}
bool KCal::operator==( const Todo& t1, const Todo& t2 )
{
bool ret = operator==( (const Incidence&)t1, (const Incidence&)t2 );
if ( ! ret )
return false;
if ( t1.hasDueDate() == t2.hasDueDate() ) {
if ( t1.hasDueDate() ) {
if ( t1.doesFloat() == t2.doesFloat() ) {
if ( t1.doesFloat() ) {
if ( t1.dtDue().date() != t2.dtDue().date() )
return false;
} else
if ( t1.dtDue() != t2.dtDue() )
return false;
} else
return false;// float !=
}
} else
return false;
if ( t1.percentComplete() != t2.percentComplete() )
return false;
if ( t1.isCompleted() ) {
if ( t1.hasCompletedDate() == t2.hasCompletedDate() ) {
if ( t1.hasCompletedDate() ) {
if ( t1.completed() != t2.completed() )
return false;
}
} else
return false;
}
return true;
}
void Todo::setDtDue(const QDateTime &dtDue)
{
//int diffsecs = mDtDue.secsTo(dtDue);
/*if (mReadOnly) return;
const QPtrList<Alarm>& alarms = alarms();
for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next()) {
if (alarm->enabled()) {
alarm->setTime(alarm->time().addSecs(diffsecs));
}
}*/
mDtDue = getEvenTime(dtDue);
//kdDebug(5800) << "setDtDue says date is " << mDtDue.toString() << endl;
/*const QPtrList<Alarm>& alarms = alarms();
for (Alarm* alarm = alarms.first(); alarm; alarm = alarms.next())
alarm->setAlarmStart(mDtDue);*/
updated();
}
QDateTime Todo::dtDue() const
{
return mDtDue;
}
QString Todo::dtDueTimeStr() const
{
return KGlobal::locale()->formatTime(mDtDue.time());
}
QString Todo::dtDueDateStr(bool shortfmt) const
{
return KGlobal::locale()->formatDate(mDtDue.date(),shortfmt);
}
QString Todo::dtDueStr(bool shortfmt) const
{
return KGlobal::locale()->formatDateTime(mDtDue, shortfmt);
}
bool Todo::hasDueDate() const
{
return mHasDueDate;
}
void Todo::setHasDueDate(bool f)
{
if (mReadOnly) return;
mHasDueDate = f;
updated();
}
#if 0
void Todo::setStatus(const QString &statStr)
{
if (mReadOnly) return;
QString ss(statStr.upper());
if (ss == "X-ACTION")
mStatus = NEEDS_ACTION;
else if (ss == "NEEDS ACTION")
mStatus = NEEDS_ACTION;
else if (ss == "ACCEPTED")
mStatus = ACCEPTED;
else if (ss == "SENT")
mStatus = SENT;
else if (ss == "TENTATIVE")
mStatus = TENTATIVE;
else if (ss == "CONFIRMED")
mStatus = CONFIRMED;
else if (ss == "DECLINED")
mStatus = DECLINED;
else if (ss == "COMPLETED")
mStatus = COMPLETED;
else if (ss == "DELEGATED")
mStatus = DELEGATED;
updated();
}
void Todo::setStatus(int status)
{
if (mReadOnly) return;
mStatus = status;
updated();
}
int Todo::status() const
{
return mStatus;
}
QString Todo::statusStr() const
{
switch(mStatus) {
case NEEDS_ACTION:
return QString("NEEDS ACTION");
break;
case ACCEPTED:
return QString("ACCEPTED");
break;
case SENT:
return QString("SENT");
break;
case TENTATIVE:
return QString("TENTATIVE");
break;
case CONFIRMED:
return QString("CONFIRMED");
break;
case DECLINED:
return QString("DECLINED");
break;
case COMPLETED:
return QString("COMPLETED");
break;
case DELEGATED:
return QString("DELEGATED");
break;
}
return QString("");
}
#endif
bool Todo::isCompleted() const
{
if (mPercentComplete == 100) return true;
else return false;
}
void Todo::setCompleted(bool completed)
{
if (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 = getEvenTime(completed);
updated();
}
bool Todo::hasCompletedDate() const
{
return mHasCompletedDate;
}
int Todo::percentComplete() const
{
return mPercentComplete;
}
void Todo::setPercentComplete(int v)
{
mPercentComplete = v;
updated();
}
QDateTime Todo::getNextAlarmDateTime( bool * ok, int * offset ) const
{
if ( isCompleted() || ! hasDueDate() || cancelled() ) {
*ok = false;
return QDateTime ();
}
QDateTime incidenceStart;
incidenceStart = dtDue();
bool enabled = false;
Alarm* alarm;
int off;
QDateTime alarmStart = QDateTime::currentDateTime().addDays( 3650 );;
// if ( QDateTime::currentDateTime() > incidenceStart ){
// *ok = false;
// return incidenceStart;
// }
for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) {
if (alarm->enabled()) {
if ( alarm->hasTime () ) {
if ( alarm->time() < alarmStart ) {
alarmStart = alarm->time();
enabled = true;
off = alarmStart.secsTo( incidenceStart );
}
} else {
int secs = alarm->startOffset().asSeconds();
if ( incidenceStart.addSecs( secs ) < alarmStart ) {
alarmStart = incidenceStart.addSecs( secs );
enabled = true;
off = -secs;
}
}
}
}
if ( enabled ) {
if ( alarmStart > QDateTime::currentDateTime() ) {
*ok = true;
* offset = off;
return alarmStart;
}
}
*ok = false;
return QDateTime ();
}
diff --git a/libkcal/todo.h b/libkcal/todo.h
index 9aa92f8..0f22c59 100644
--- a/libkcal/todo.h
+++ b/libkcal/todo.h
@@ -1,121 +1,122 @@
/*
This file is part of libkcal.
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef TODO_H
#define TODO_H
//
// Todo component, representing a VTODO object
//
#include "incidence.h"
namespace KCal {
/**
This class provides a Todo in the sense of RFC2445.
*/
class Todo : public Incidence
{
public:
Todo();
Todo(const Todo &);
~Todo();
typedef ListBase<Todo> List;
QCString type() const { return "Todo"; }
/** Return an exact copy of this todo. */
Incidence *clone();
QDateTime getNextAlarmDateTime( bool * ok, int * offset ) const;
/** for setting the todo's due date/time with a QDateTime. */
void setDtDue(const QDateTime &dtDue);
/** returns an event's Due date/time as a QDateTime. */
QDateTime dtDue() const;
/** returns an event's due time as a string formatted according to the
users locale settings */
QString dtDueTimeStr() const;
/** returns an event's due date as a string formatted according to the
users locale settings */
QString dtDueDateStr(bool shortfmt=true) const;
/** returns an event's due date and time as a string formatted according
to the users locale settings */
QString dtDueStr(bool shortfmt=true) const;
/** returns TRUE or FALSE depending on whether the todo has a due date */
bool hasDueDate() const;
/** sets the event's hasDueDate value. */
void setHasDueDate(bool f);
/** 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;
+ bool contains ( Todo*);
private:
bool accept(Visitor &v) { return v.visit(this); }
QDateTime mDtDue; // due date of todo
bool mHasDueDate; // if todo has associated due date
// int mStatus; // confirmed/delegated/tentative/etc
QDateTime mCompleted;
bool mHasCompletedDate;
int mPercentComplete;
};
bool operator==( const Todo&, const Todo& );
}
#endif
diff --git a/libkcal/vcalformat.cpp b/libkcal/vcalformat.cpp
index a6ae1bc..df93209 100644
--- a/libkcal/vcalformat.cpp
+++ b/libkcal/vcalformat.cpp
@@ -1,477 +1,479 @@
/*
This file is part of libkcal.
Copyright (c) 1998 Preston Brwon
Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <qapplication.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>
#include <qregexp.h>
#include <qclipboard.h>
#include <qdialog.h>
#include <qfile.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kmessagebox.h>
#include <kiconloader.h>
#include <klocale.h>
#include "vcc.h"
#include "vobject.h"
#include "vcaldrag.h"
#include "calendar.h"
#include "vcalformat.h"
using namespace KCal;
VCalFormat::VCalFormat()
{
mCalendar = 0;
useLocalTime = false;
}
VCalFormat::~VCalFormat()
{
}
void VCalFormat::setLocalTime ( bool b )
{
useLocalTime = b;
}
bool VCalFormat::load(Calendar *calendar, const QString &fileName)
{
mCalendar = calendar;
clearException();
- useLocalTime = mCalendar->isLocalTime();
+ if ( ! useLocalTime )
+ useLocalTime = mCalendar->isLocalTime();
VObject *vcal = 0;
// this is not necessarily only 1 vcal. Could be many vcals, or include
// a vcard...
vcal = Parse_MIME_FromFileName(const_cast<char *>(QFile::encodeName(fileName).data()));
if (!vcal) {
setException(new ErrorFormat(ErrorFormat::CalVersionUnknown));
return FALSE;
}
// any other top-level calendar stuff should be added/initialized here
// put all vobjects into their proper places
populate(vcal);
// clean up from vcal API stuff
cleanVObjects(vcal);
cleanStrTbl();
return true;
}
bool VCalFormat::save(Calendar *calendar, const QString &fileName)
{
mCalendar = calendar;
- useLocalTime = mCalendar->isLocalTime();
+ if ( ! useLocalTime )
+ useLocalTime = mCalendar->isLocalTime();
QString tmpStr;
VObject *vcal, *vo;
vcal = newVObject(VCCalProp);
// addPropValue(vcal,VCLocationProp, "0.0");
addPropValue(vcal,VCProdIdProp, productId());
tmpStr = mCalendar->getTimeZoneStr();
//qDebug("mCalendar->getTimeZoneStr() %s",tmpStr.latin1() );
addPropValue(vcal,VCTimeZoneProp, tmpStr.local8Bit());
addPropValue(vcal,VCVersionProp, _VCAL_VERSION);
// TODO STUFF
QPtrList<Todo> todoList = mCalendar->rawTodos();
QPtrListIterator<Todo> qlt(todoList);
for (; qlt.current(); ++qlt) {
vo = eventToVTodo(qlt.current());
addVObjectProp(vcal, vo);
}
// EVENT STUFF
QPtrList<Event> events = mCalendar->rawEvents();
Event *ev;
for(ev=events.first();ev;ev=events.next()) {
vo = eventToVEvent(ev);
addVObjectProp(vcal, vo);
}
writeVObjectToFile(QFile::encodeName(fileName).data() ,vcal);
cleanVObjects(vcal);
cleanStrTbl();
if (QFile::exists(fileName)) {
return true;
} else {
return false; // error
}
}
bool VCalFormat::fromString( Calendar *calendar, const QString &text )
{
// TODO: Factor out VCalFormat::fromString()
QCString data = text.utf8();
if ( !data.size() ) return false;
VObject *vcal = Parse_MIME( data.data(), data.size());
if ( !vcal ) return false;
VObjectIterator i;
VObject *curvo;
initPropIterator( &i, vcal );
// we only take the first object. TODO: parse all incidences.
do {
curvo = nextVObject( &i );
} while ( strcmp( vObjectName( curvo ), VCEventProp ) &&
strcmp( vObjectName( curvo ), VCTodoProp ) );
if ( strcmp( vObjectName( curvo ), VCEventProp ) == 0 ) {
Event *event = VEventToEvent( curvo );
calendar->addEvent( event );
} else {
qDebug("VCalFormat::fromString(): Unknown object type. ");
deleteVObject( vcal );
return false;
}
deleteVObject( vcal );
return true;
}
QString VCalFormat::eventToString( Event * event, Calendar *calendar, bool useLocal)
{
if ( !event ) return QString::null;
bool useL = useLocalTime;
useLocalTime = useLocal;
mCalendar = calendar;
VObject *vevent = eventToVEvent( event );
char *buf = writeMemVObject( 0, 0, vevent );
QString result( buf );
cleanVObject( vevent );
useLocalTime = useL;
return result;
}
QString VCalFormat::todoToString( Todo * todo, Calendar *calendar, bool useLocal )
{
if ( !todo ) return QString::null;
bool useL = useLocalTime;
useLocalTime = useLocal;
mCalendar = calendar;
VObject *vevent = eventToVTodo( todo );
char *buf = writeMemVObject( 0, 0, vevent );
QString result( buf );
cleanVObject( vevent );
useLocalTime = useL;
return result;
}
QString VCalFormat::toString( Calendar *calendar )
{
// TODO: Factor out VCalFormat::asString()
VObject *vcal = newVObject(VCCalProp);
addPropValue( vcal, VCProdIdProp, CalFormat::productId() );
QString tmpStr = mCalendar->getTimeZoneStr();
addPropValue( vcal, VCTimeZoneProp, tmpStr.local8Bit() );
addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
// TODO: Use all data.
QPtrList<Event> events = calendar->events();
Event *event = events.first();
if ( !event ) return QString::null;
VObject *vevent = eventToVEvent( event );
addVObjectProp( vcal, vevent );
char *buf = writeMemVObject( 0, 0, vcal );
QString result( buf );
cleanVObject( vcal );
return result;
}
VObject *VCalFormat::eventToVTodo(const Todo *anEvent)
{
VObject *vtodo;
QString tmpStr;
QStringList tmpStrList;
vtodo = newVObject(VCTodoProp);
// due date
if (anEvent->hasDueDate()) {
tmpStr = qDateTimeToISO(anEvent->dtDue(),
!anEvent->doesFloat());
addPropValue(vtodo, VCDueProp, tmpStr.local8Bit());
}
// start date
if (anEvent->hasStartDate()) {
tmpStr = qDateTimeToISO(anEvent->dtStart(),
!anEvent->doesFloat());
addPropValue(vtodo, VCDTstartProp, tmpStr.local8Bit());
}
// creation date
tmpStr = qDateTimeToISO(anEvent->created());
addPropValue(vtodo, VCDCreatedProp, tmpStr.local8Bit());
// unique id
addPropValue(vtodo, VCUniqueStringProp,
anEvent->uid().local8Bit());
// revision
tmpStr.sprintf("%i", anEvent->revision());
addPropValue(vtodo, VCSequenceProp, tmpStr.local8Bit());
// last modification date
tmpStr = qDateTimeToISO(anEvent->lastModified());
addPropValue(vtodo, VCLastModifiedProp, tmpStr.local8Bit());
// organizer stuff
tmpStr = "MAILTO:" + anEvent->organizer();
addPropValue(vtodo, ICOrganizerProp, tmpStr.local8Bit());
// attendees
if (anEvent->attendeeCount() != 0) {
QPtrList<Attendee> al = anEvent->attendees();
QPtrListIterator<Attendee> ai(al);
Attendee *curAttendee;
for (; ai.current(); ++ai) {
curAttendee = ai.current();
if (!curAttendee->email().isEmpty() &&
!curAttendee->name().isEmpty())
tmpStr = "MAILTO:" + curAttendee->name() + " <" +
curAttendee->email() + ">";
else if (curAttendee->name().isEmpty())
tmpStr = "MAILTO: " + curAttendee->email();
else if (curAttendee->email().isEmpty())
tmpStr = "MAILTO: " + curAttendee->name();
else if (curAttendee->name().isEmpty() &&
curAttendee->email().isEmpty())
kdDebug(5800) << "warning! this Event has an attendee w/o name or email!" << endl;
VObject *aProp = addPropValue(vtodo, VCAttendeeProp, tmpStr.local8Bit());
addPropValue(aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE");
addPropValue(aProp, VCStatusProp, writeStatus(curAttendee->status()));
}
}
// description BL:
if (!anEvent->description().isEmpty()) {
VObject *d = addPropValue(vtodo, VCDescriptionProp,
anEvent->description().local8Bit());
if (anEvent->description().find('\n') != -1)
addProp(d, VCQuotedPrintableProp);
}
// summary
if (!anEvent->summary().isEmpty())
addPropValue(vtodo, VCSummaryProp, anEvent->summary().local8Bit());
if (!anEvent->location().isEmpty())
addPropValue(vtodo, VCLocationProp, anEvent->location().local8Bit());
// completed
// status
// backward compatibility, KOrganizer used to interpret only these two values
addPropValue(vtodo, VCStatusProp, anEvent->isCompleted() ? "COMPLETED" :
"NEEDS_ACTION");
// completion date
if (anEvent->hasCompletedDate()) {
tmpStr = qDateTimeToISO(anEvent->completed());
addPropValue(vtodo, VCCompletedProp, tmpStr.local8Bit());
}
// priority
tmpStr.sprintf("%i",anEvent->priority());
addPropValue(vtodo, VCPriorityProp, tmpStr.local8Bit());
// related event
if (anEvent->relatedTo()) {
addPropValue(vtodo, VCRelatedToProp,
anEvent->relatedTo()->uid().local8Bit());
}
// categories
tmpStrList = anEvent->categories();
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);
addPropValue(vtodo, VCCategoriesProp, tmpStr.local8Bit());
}
// alarm stuff
kdDebug(5800) << "vcalformat::eventToVTodo was called" << endl;
QPtrList<Alarm> alarms = anEvent->alarms();
Alarm* alarm;
for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
if (alarm->enabled()) {
VObject *a;
tmpStr = qDateTimeToISO(alarm->time());
if (alarm->type() == Alarm::Audio) {
a = addProp(vtodo, VCAAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCAudioContentProp, QFile::encodeName(alarm->audioFile()));
}
else if (alarm->type() == Alarm::Procedure) {
a = addProp(vtodo, VCPAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCProcedureNameProp, QFile::encodeName(alarm->programFile()));
} else {
a = addProp(vtodo, VCDAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCDisplayStringProp, "beep!");
}
}
}
if (anEvent->pilotId()) {
// pilot sync stuff
tmpStr.sprintf("%i",anEvent->pilotId());
addPropValue(vtodo, XPilotIdProp, tmpStr.local8Bit());
tmpStr.sprintf("%i",anEvent->syncStatus());
addPropValue(vtodo, XPilotStatusProp, tmpStr.local8Bit());
}
return vtodo;
}
VObject* VCalFormat::eventToVEvent(const Event *anEvent)
{
VObject *vevent;
QString tmpStr;
QStringList tmpStrList;
vevent = newVObject(VCEventProp);
// start and end time
tmpStr = qDateTimeToISO(anEvent->dtStart(),
!anEvent->doesFloat());
addPropValue(vevent, VCDTstartProp, tmpStr.local8Bit());
// events that have time associated but take up no time should
// not have both DTSTART and DTEND.
if (anEvent->dtStart() != anEvent->dtEnd()) {
tmpStr = qDateTimeToISO(anEvent->dtEnd(),
!anEvent->doesFloat());
addPropValue(vevent, VCDTendProp, tmpStr.local8Bit());
}
// creation date
tmpStr = qDateTimeToISO(anEvent->created());
addPropValue(vevent, VCDCreatedProp, tmpStr.local8Bit());
// unique id
addPropValue(vevent, VCUniqueStringProp,
anEvent->uid().local8Bit());
// revision
tmpStr.sprintf("%i", anEvent->revision());
addPropValue(vevent, VCSequenceProp, tmpStr.local8Bit());
// last modification date
tmpStr = qDateTimeToISO(anEvent->lastModified());
addPropValue(vevent, VCLastModifiedProp, tmpStr.local8Bit());
// attendee and organizer stuff
tmpStr = "MAILTO:" + anEvent->organizer();
addPropValue(vevent, ICOrganizerProp, tmpStr.local8Bit());
if (anEvent->attendeeCount() != 0) {
QPtrList<Attendee> al = anEvent->attendees();
QPtrListIterator<Attendee> ai(al);
Attendee *curAttendee;
// TODO: Put this functionality into Attendee class
for (; ai.current(); ++ai) {
curAttendee = ai.current();
if (!curAttendee->email().isEmpty() &&
!curAttendee->name().isEmpty())
tmpStr = "MAILTO:" + curAttendee->name() + " <" +
curAttendee->email() + ">";
else if (curAttendee->name().isEmpty())
tmpStr = "MAILTO: " + curAttendee->email();
else if (curAttendee->email().isEmpty())
tmpStr = "MAILTO: " + curAttendee->name();
else if (curAttendee->name().isEmpty() &&
curAttendee->email().isEmpty())
kdDebug(5800) << "warning! this Event has an attendee w/o name or email!" << endl;
VObject *aProp = addPropValue(vevent, VCAttendeeProp, tmpStr.local8Bit());
addPropValue(aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE");;
addPropValue(aProp, VCStatusProp, writeStatus(curAttendee->status()));
}
}
// recurrence rule stuff
if (anEvent->recurrence()->doesRecur()) {
// some more variables
QPtrList<Recurrence::rMonthPos> tmpPositions;
QPtrList<int> tmpDays;
int *tmpDay;
Recurrence::rMonthPos *tmpPos;
QString tmpStr2;
int i;
switch(anEvent->recurrence()->doesRecur()) {
case Recurrence::rDaily:
tmpStr.sprintf("D%i ",anEvent->recurrence()->frequency());
// if (anEvent->rDuration > 0)
// tmpStr += "#";
break;
case Recurrence::rWeekly:
tmpStr.sprintf("W%i ",anEvent->recurrence()->frequency());
for (i = 0; i < 7; i++) {
if (anEvent->recurrence()->days().testBit(i))
@@ -791,923 +793,928 @@ Todo *VCalFormat::VTodoToEvent(VObject *vtodo)
if (strcmp(s,"COMPLETED") == 0) {
anEvent->setCompleted(true);
} else {
anEvent->setCompleted(false);
}
deleteStr(s);
}
else
anEvent->setCompleted(false);
// completion date
if ((vo = isAPropertyOf(vtodo, VCCompletedProp)) != 0) {
anEvent->setCompleted(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// priority
if ((vo = isAPropertyOf(vtodo, VCPriorityProp))) {
anEvent->setPriority(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// due date
if ((vo = isAPropertyOf(vtodo, VCDueProp)) != 0) {
anEvent->setDtDue(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
anEvent->setHasDueDate(true);
} else {
anEvent->setHasDueDate(false);
}
// start time
if ((vo = isAPropertyOf(vtodo, VCDTstartProp)) != 0) {
anEvent->setDtStart(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
// kdDebug(5800) << "s is " << // s << ", ISO is " << ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))).toString() << endl;
deleteStr(s);
anEvent->setHasStartDate(true);
} else {
anEvent->setHasStartDate(false);
}
/* alarm stuff */
//kdDebug(5800) << "vcalformat::VTodoToEvent called" << endl;
if ((vo = isAPropertyOf(vtodo, VCDAlarmProp))) {
Alarm* alarm = anEvent->newAlarm();
VObject *a;
if ((a = isAPropertyOf(vo, VCRunTimeProp))) {
alarm->setTime(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(a))));
deleteStr(s);
}
alarm->setEnabled(true);
if ((vo = isAPropertyOf(vtodo, VCPAlarmProp))) {
if ((a = isAPropertyOf(vo, VCProcedureNameProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setProcedureAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
if ((vo = isAPropertyOf(vtodo, VCAAlarmProp))) {
if ((a = isAPropertyOf(vo, VCAudioContentProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setAudioAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
}
// related todo
if ((vo = isAPropertyOf(vtodo, VCRelatedToProp)) != 0) {
anEvent->setRelatedToUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
mTodosRelate.append(anEvent);
}
// categories
QStringList tmpStrList;
int index1 = 0;
int index2 = 0;
if ((vo = isAPropertyOf(vtodo, VCCategoriesProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
QString categories = QString::fromLocal8Bit(s);
deleteStr(s);
//const char* category;
QString category;
while ((index2 = categories.find(',', index1)) != -1) {
//category = (const char *) categories.mid(index1, (index2 - index1));
category = categories.mid(index1, (index2 - index1));
tmpStrList.append(category);
index1 = index2+1;
}
// get last category
category = categories.mid(index1, (categories.length()-index1));
tmpStrList.append(category);
anEvent->setCategories(tmpStrList);
}
/* PILOT SYNC STUFF */
if ((vo = isAPropertyOf(vtodo, XPilotIdProp))) {
anEvent->setPilotId(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setPilotId(0);
if ((vo = isAPropertyOf(vtodo, XPilotStatusProp))) {
anEvent->setSyncStatus(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setSyncStatus(Event::SYNCMOD);
return anEvent;
}
Event* VCalFormat::VEventToEvent(VObject *vevent)
{
VObject *vo;
VObjectIterator voi;
char *s;
Event *anEvent = new Event;
// creation date
if ((vo = isAPropertyOf(vevent, VCDCreatedProp)) != 0) {
anEvent->setCreated(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// unique id
vo = isAPropertyOf(vevent, VCUniqueStringProp);
// while the UID property is preferred, it is not required. We'll use the
// default Event UID if none is given.
if (vo) {
anEvent->setUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
}
// revision
// again NSCAL doesn't give us much to work with, so we improvise...
if ((vo = isAPropertyOf(vevent, VCSequenceProp)) != 0) {
anEvent->setRevision(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setRevision(0);
// last modification date
if ((vo = isAPropertyOf(vevent, VCLastModifiedProp)) != 0) {
anEvent->setLastModified(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setLastModified(QDateTime(QDate::currentDate(),
QTime::currentTime()));
// organizer
// if our extension property for the event's ORGANIZER exists, add it.
if ((vo = isAPropertyOf(vevent, ICOrganizerProp)) != 0) {
anEvent->setOrganizer(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
} else {
anEvent->setOrganizer(mCalendar->getEmail());
}
// deal with attendees.
initPropIterator(&voi, vevent);
while (moreIteration(&voi)) {
vo = nextVObject(&voi);
if (strcmp(vObjectName(vo), VCAttendeeProp) == 0) {
Attendee *a;
VObject *vp;
s = fakeCString(vObjectUStringZValue(vo));
QString tmpStr = QString::fromLocal8Bit(s);
deleteStr(s);
tmpStr = tmpStr.simplifyWhiteSpace();
int emailPos1, emailPos2;
if ((emailPos1 = tmpStr.find('<')) > 0) {
// both email address and name
emailPos2 = tmpStr.findRev('>');
a = new Attendee(tmpStr.left(emailPos1 - 1),
tmpStr.mid(emailPos1 + 1,
emailPos2 - (emailPos1 + 1)));
} else if (tmpStr.find('@') > 0) {
// just an email address
a = new Attendee(0, tmpStr);
} else {
// just a name
QString email = tmpStr.replace( QRegExp(" "), "." );
a = new Attendee(tmpStr,email);
}
// is there an RSVP property?
if ((vp = isAPropertyOf(vo, VCRSVPProp)) != 0)
a->setRSVP(vObjectStringZValue(vp));
// is there a status property?
if ((vp = isAPropertyOf(vo, VCStatusProp)) != 0)
a->setStatus(readStatus(vObjectStringZValue(vp)));
// add the attendee
anEvent->addAttendee(a);
}
}
// This isn't strictly true. An event that doesn't have a start time
// or an end time doesn't "float", it has an anchor in time but it doesn't
// "take up" any time.
/*if ((isAPropertyOf(vevent, VCDTstartProp) == 0) ||
(isAPropertyOf(vevent, VCDTendProp) == 0)) {
anEvent->setFloats(TRUE);
} else {
}*/
anEvent->setFloats(FALSE);
// start time
if ((vo = isAPropertyOf(vevent, VCDTstartProp)) != 0) {
anEvent->setDtStart(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
// kdDebug(5800) << "s is " << // s << ", ISO is " << ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))).toString() << endl;
deleteStr(s);
if (anEvent->dtStart().time().isNull())
anEvent->setFloats(TRUE);
}
// stop time
if ((vo = isAPropertyOf(vevent, VCDTendProp)) != 0) {
anEvent->setDtEnd(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
if (anEvent->dtEnd().time().isNull())
anEvent->setFloats(TRUE);
}
// 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 (!(vo = isAPropertyOf(vevent, VCDTstartProp)))
anEvent->setDtStart(anEvent->dtEnd());
if (!(vo = isAPropertyOf(vevent, VCDTendProp)))
anEvent->setDtEnd(anEvent->dtStart());
///////////////////////////////////////////////////////////////////////////
// repeat stuff
if ((vo = isAPropertyOf(vevent, VCRRuleProp)) != 0) {
QString tmpStr = (s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
tmpStr.simplifyWhiteSpace();
tmpStr = tmpStr.upper();
/********************************* DAILY ******************************/
if (tmpStr.left(1) == "D") {
int index = tmpStr.find(' ');
int rFreq = tmpStr.mid(1, (index-1)).toInt();
index = tmpStr.findRev(' ') + 1; // advance to last field
if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setDaily(rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0) // VEvents set this to 0 forever, we use -1
anEvent->recurrence()->setDaily(rFreq, -1);
else
anEvent->recurrence()->setDaily(rFreq, rDuration);
}
}
/********************************* WEEKLY ******************************/
else if (tmpStr.left(1) == "W") {
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(1, (index-1)).toInt();
index += 1; // advance to beginning of stuff after freq
QBitArray qba(7);
QString dayStr;
if( index == last ) {
// e.g. W1 #0
qba.setBit(anEvent->dtStart().date().dayOfWeek() - 1);
}
else {
// e.g. W1 SU #0
while (index < last) {
dayStr = tmpStr.mid(index, 3);
int dayNum = numFromDay(dayStr);
qba.setBit(dayNum);
index += 3; // advance to next day, or possibly "#"
}
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setWeekly(rFreq, qba, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setWeekly(rFreq, qba, -1);
else
anEvent->recurrence()->setWeekly(rFreq, qba, rDuration);
}
}
/**************************** MONTHLY-BY-POS ***************************/
else if (tmpStr.left(2) == "MP") {
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(2, (index-1)).toInt();
index += 1; // advance to beginning of stuff after freq
QBitArray qba(7);
short tmpPos;
if( index == last ) {
// e.g. MP1 #0
tmpPos = anEvent->dtStart().date().day()/7 + 1;
if( tmpPos == 5 )
tmpPos = -1;
qba.setBit(anEvent->dtStart().date().dayOfWeek() - 1);
anEvent->recurrence()->addMonthlyPos(tmpPos, qba);
}
else {
// e.g. MP1 1+ SU #0
while (index < last) {
tmpPos = tmpStr.mid(index,1).toShort();
index += 1;
if (tmpStr.mid(index,1) == "-")
// convert tmpPos to negative
tmpPos = 0 - tmpPos;
index += 2; // advance to day(s)
while (numFromDay(tmpStr.mid(index,3)) >= 0) {
int dayNum = numFromDay(tmpStr.mid(index,3));
qba.setBit(dayNum);
index += 3; // advance to next day, or possibly pos or "#"
}
anEvent->recurrence()->addMonthlyPos(tmpPos, qba);
qba.detach();
qba.fill(FALSE); // clear out
} // while != "#"
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length() -
index))).date();
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, -1);
else
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyPos, rFreq, rDuration);
}
}
/**************************** MONTHLY-BY-DAY ***************************/
else if (tmpStr.left(2) == "MD") {
int index = tmpStr.find(' ');
int last = tmpStr.findRev(' ') + 1;
int rFreq = tmpStr.mid(2, (index-1)).toInt();
index += 1;
short tmpDay;
if( index == last ) {
// e.g. MD1 #0
tmpDay = anEvent->dtStart().date().day();
anEvent->recurrence()->addMonthlyDay(tmpDay);
}
else {
// e.g. MD1 3 #0
while (index < last) {
int index2 = tmpStr.find(' ', index);
tmpDay = tmpStr.mid(index, (index2-index)).toShort();
index = index2-1;
if (tmpStr.mid(index, 1) == "-")
tmpDay = 0 - tmpDay;
index += 2; // advance the index;
anEvent->recurrence()->addMonthlyDay(tmpDay);
} // while != #
}
index = last; if (tmpStr.mid(index,1) == "#") index++;
if (tmpStr.find('T', index) != -1) {
QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, rEndDate);
} else {
int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
if (rDuration == 0)
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, -1);
else
anEvent->recurrence()->setMonthly(Recurrence::rMonthlyDay, rFreq, rDuration);
}
}
/*********************** YEARLY-BY-MONTH *******************************/
else if (tmpStr.left(2) == "YM") {
- int index = tmpStr.find(' ');
- int last = tmpStr.findRev(' ') + 1;
- int rFreq = tmpStr.mid(2, (index-1)).toInt();
- index += 1;
- short tmpMonth;
- if( index == last ) {
- // e.g. YM1 #0
- tmpMonth = anEvent->dtStart().date().month();
- anEvent->recurrence()->addYearlyNum(tmpMonth);
- }
- else {
- // e.g. YM1 3 #0
- while (index < last) {
- int index2 = tmpStr.find(' ', index);
- tmpMonth = tmpStr.mid(index, (index2-index)).toShort();
- index = index2+1;
- anEvent->recurrence()->addYearlyNum(tmpMonth);
- } // while != #
- }
- index = last; if (tmpStr.mid(index,1) == "#") index++;
- if (tmpStr.find('T', index) != -1) {
- QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
- anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rEndDate);
- } else {
- int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
- if (rDuration == 0)
- anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, -1);
- else
- anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rDuration);
- }
+ // we have to set this such that recurrence accepts addYearlyNum(tmpDay);
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, 1, -1);
+ int index = tmpStr.find(' ');
+ int last = tmpStr.findRev(' ') + 1;
+ int rFreq = tmpStr.mid(2, (index-1)).toInt();
+ index += 1;
+ short tmpMonth;
+ if( index == last ) {
+ // e.g. YM1 #0
+ tmpMonth = anEvent->dtStart().date().month();
+ anEvent->recurrence()->addYearlyNum(tmpMonth);
+ }
+ else {
+ // e.g. YM1 3 #0
+ while (index < last) {
+ int index2 = tmpStr.find(' ', index);
+ tmpMonth = tmpStr.mid(index, (index2-index)).toShort();
+ index = index2+1;
+ anEvent->recurrence()->addYearlyNum(tmpMonth);
+ } // while != #
+ }
+ index = last; if (tmpStr.mid(index,1) == "#") index++;
+ if (tmpStr.find('T', index) != -1) {
+ QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rEndDate);
+ } else {
+ int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
+ if (rDuration == 0)
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, -1);
+ else
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyMonth, rFreq, rDuration);
+ }
}
/*********************** YEARLY-BY-DAY *********************************/
else if (tmpStr.left(2) == "YD") {
- int index = tmpStr.find(' ');
- int last = tmpStr.findRev(' ') + 1;
- int rFreq = tmpStr.mid(2, (index-1)).toInt();
- index += 1;
- short tmpDay;
- if( index == last ) {
- // e.g. YD1 #0
- tmpDay = anEvent->dtStart().date().dayOfYear();
- anEvent->recurrence()->addYearlyNum(tmpDay);
- }
- else {
- // e.g. YD1 123 #0
- while (index < last) {
- int index2 = tmpStr.find(' ', index);
- tmpDay = tmpStr.mid(index, (index2-index)).toShort();
- index = index2+1;
- anEvent->recurrence()->addYearlyNum(tmpDay);
- } // while != #
- }
- index = last; if (tmpStr.mid(index,1) == "#") index++;
- if (tmpStr.find('T', index) != -1) {
- QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
- anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rEndDate);
- } else {
- int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
- if (rDuration == 0)
- anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, -1);
- else
- anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rDuration);
- }
+ // we have to set this such that recurrence accepts addYearlyNum(tmpDay);
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, 1, -1);
+ int index = tmpStr.find(' ');
+ int last = tmpStr.findRev(' ') + 1;
+ int rFreq = tmpStr.mid(2, (index-1)).toInt();
+ index += 1;
+ short tmpDay;
+ if( index == last ) {
+ // e.g. YD1 #0
+ tmpDay = anEvent->dtStart().date().dayOfYear();
+ anEvent->recurrence()->addYearlyNum(tmpDay);
+ }
+ else {
+ // e.g. YD1 123 #0
+ while (index < last) {
+ int index2 = tmpStr.find(' ', index);
+ tmpDay = tmpStr.mid(index, (index2-index)).toShort();
+ index = index2+1;
+ anEvent->recurrence()->addYearlyNum(tmpDay);
+ } // while != #
+ }
+ index = last; if (tmpStr.mid(index,1) == "#") index++;
+ if (tmpStr.find('T', index) != -1) {
+ QDate rEndDate = (ISOToQDateTime(tmpStr.mid(index, tmpStr.length()-index))).date();
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rEndDate);
+ } else {
+ int rDuration = tmpStr.mid(index, tmpStr.length()-index).toInt();
+ if (rDuration == 0)
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, -1);
+ else
+ anEvent->recurrence()->setYearly(Recurrence::rYearlyDay, rFreq, rDuration);
+ }
} else {
- kdDebug(5800) << "we don't understand this type of recurrence!" << endl;
+ kdDebug(5800) << "we don't understand this type of recurrence!" << endl;
} // if
} // repeats
// recurrence exceptions
if ((vo = isAPropertyOf(vevent, VCExpDateProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
QStringList exDates = QStringList::split(",",s);
QStringList::ConstIterator it;
for(it = exDates.begin(); it != exDates.end(); ++it ) {
anEvent->addExDate(ISOToQDate(*it));
}
deleteStr(s);
}
// summary
if ((vo = isAPropertyOf(vevent, VCSummaryProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setSummary(QString::fromLocal8Bit(s));
deleteStr(s);
}
if ((vo = isAPropertyOf(vevent, VCLocationProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setLocation(QString::fromLocal8Bit(s));
deleteStr(s);
}
// description
if ((vo = isAPropertyOf(vevent, VCDescriptionProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
if (!anEvent->description().isEmpty()) {
anEvent->setDescription(anEvent->description() + "\n" +
QString::fromLocal8Bit(s));
} else {
anEvent->setDescription(QString::fromLocal8Bit(s));
}
deleteStr(s);
}
// some stupid vCal exporters ignore the standard and use Description
// instead of Summary for the default field. Correct for this.
if (anEvent->summary().isEmpty() &&
!(anEvent->description().isEmpty())) {
QString tmpStr = anEvent->description().simplifyWhiteSpace();
anEvent->setDescription("");
anEvent->setSummary(tmpStr);
}
#if 0
// status
if ((vo = isAPropertyOf(vevent, VCStatusProp)) != 0) {
QString tmpStr(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
// TODO: Define Event status
// anEvent->setStatus(tmpStr);
}
else
// anEvent->setStatus("NEEDS ACTION");
#endif
// secrecy
int secrecy = Incidence::SecrecyPublic;
if ((vo = isAPropertyOf(vevent, VCClassProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
if (strcmp(s,"PRIVATE") == 0) {
secrecy = Incidence::SecrecyPrivate;
} else if (strcmp(s,"CONFIDENTIAL") == 0) {
secrecy = Incidence::SecrecyConfidential;
}
deleteStr(s);
}
anEvent->setSecrecy(secrecy);
// categories
QStringList tmpStrList;
int index1 = 0;
int index2 = 0;
if ((vo = isAPropertyOf(vevent, VCCategoriesProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
QString categories = QString::fromLocal8Bit(s);
deleteStr(s);
//const char* category;
QString category;
while ((index2 = categories.find(',', index1)) != -1) {
//category = (const char *) categories.mid(index1, (index2 - index1));
category = categories.mid(index1, (index2 - index1));
tmpStrList.append(category);
index1 = index2+1;
}
// get last category
category = categories.mid(index1, (categories.length()-index1));
tmpStrList.append(category);
anEvent->setCategories(tmpStrList);
}
// attachments
tmpStrList.clear();
initPropIterator(&voi, vevent);
while (moreIteration(&voi)) {
vo = nextVObject(&voi);
if (strcmp(vObjectName(vo), VCAttachProp) == 0) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->addAttachment(new Attachment(QString(s)));
deleteStr(s);
}
}
// 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);
}
/* alarm stuff */
if ((vo = isAPropertyOf(vevent, VCDAlarmProp))) {
Alarm* alarm = anEvent->newAlarm();
VObject *a;
if ((a = isAPropertyOf(vo, VCRunTimeProp))) {
alarm->setTime(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(a))));
deleteStr(s);
}
alarm->setEnabled(true);
if ((vo = isAPropertyOf(vevent, VCPAlarmProp))) {
if ((a = isAPropertyOf(vo, VCProcedureNameProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setProcedureAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
if ((vo = isAPropertyOf(vevent, VCAAlarmProp))) {
if ((a = isAPropertyOf(vo, VCAudioContentProp))) {
s = fakeCString(vObjectUStringZValue(a));
alarm->setAudioAlarm(QFile::decodeName(s));
deleteStr(s);
}
}
}
// priority
if ((vo = isAPropertyOf(vevent, VCPriorityProp))) {
anEvent->setPriority(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// transparency
if ((vo = isAPropertyOf(vevent, VCTranspProp)) != 0) {
int i = atoi(s = fakeCString(vObjectUStringZValue(vo)));
anEvent->setTransparency( i == 1 ? Event::Transparent : Event::Opaque );
deleteStr(s);
}
// related event
if ((vo = isAPropertyOf(vevent, VCRelatedToProp)) != 0) {
anEvent->setRelatedToUid(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
mEventsRelate.append(anEvent);
}
/* PILOT SYNC STUFF */
if ((vo = isAPropertyOf(vevent, XPilotIdProp))) {
anEvent->setPilotId(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setPilotId(0);
if ((vo = isAPropertyOf(vevent, XPilotStatusProp))) {
anEvent->setSyncStatus(atoi(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
else
anEvent->setSyncStatus(Event::SYNCMOD);
return anEvent;
}
QString VCalFormat::qDateToISO(const QDate &qd)
{
QString tmpStr;
ASSERT(qd.isValid());
tmpStr.sprintf("%.2d%.2d%.2d",
qd.year(), qd.month(), qd.day());
return tmpStr;
}
QString VCalFormat::qDateTimeToISO(const QDateTime &qdt, bool zulu)
{
QString tmpStr;
ASSERT(qdt.date().isValid());
ASSERT(qdt.time().isValid());
if (zulu && !useLocalTime ) {
QDateTime tmpDT = qdt.addSecs ( -KGlobal::locale()->localTimeOffset( qdt )*60);
tmpStr.sprintf("%.2d%.2d%.2dT%.2d%.2d%.2dZ",
tmpDT.date().year(), tmpDT.date().month(),
tmpDT.date().day(), tmpDT.time().hour(),
tmpDT.time().minute(), tmpDT.time().second());
} else {
tmpStr.sprintf("%.2d%.2d%.2dT%.2d%.2d%.2d",
qdt.date().year(), qdt.date().month(),
qdt.date().day(), qdt.time().hour(),
qdt.time().minute(), qdt.time().second());
}
return tmpStr;
}
QDateTime VCalFormat::ISOToQDateTime(const QString & dtStr)
{
QDate tmpDate;
QTime tmpTime;
QString tmpStr;
int year, month, day, hour, minute, second;
tmpStr = dtStr;
year = tmpStr.left(4).toInt();
month = tmpStr.mid(4,2).toInt();
day = tmpStr.mid(6,2).toInt();
hour = tmpStr.mid(9,2).toInt();
minute = tmpStr.mid(11,2).toInt();
second = tmpStr.mid(13,2).toInt();
tmpDate.setYMD(year, month, day);
tmpTime.setHMS(hour, minute, second);
ASSERT(tmpDate.isValid());
ASSERT(tmpTime.isValid());
QDateTime tmpDT(tmpDate, tmpTime);
// correct for GMT if string is in Zulu format
if (dtStr.at(dtStr.length()-1) == 'Z')
tmpDT = tmpDT.addSecs (KGlobal::locale()->localTimeOffset( tmpDT )*60);
return tmpDT;
}
QDate VCalFormat::ISOToQDate(const QString &dateStr)
{
int year, month, day;
year = dateStr.left(4).toInt();
month = dateStr.mid(4,2).toInt();
day = dateStr.mid(6,2).toInt();
return(QDate(year, month, day));
}
// take a raw vcalendar (i.e. from a file on disk, clipboard, etc. etc.
// and break it down from it's tree-like format into the dictionary format
// that is used internally in the VCalFormat.
void VCalFormat::populate(VObject *vcal)
{
// this function will populate the caldict dictionary and other event
// lists. It turns vevents into Events and then inserts them.
VObjectIterator i;
VObject *curVO, *curVOProp;
Event *anEvent;
if ((curVO = isAPropertyOf(vcal, ICMethodProp)) != 0) {
char *methodType = 0;
methodType = fakeCString(vObjectUStringZValue(curVO));
kdDebug() << "This calendar is an iTIP transaction of type '"
<< methodType << "'" << endl;
delete methodType;
}
// warn the user that we might have trouble reading non-known calendar.
if ((curVO = isAPropertyOf(vcal, VCProdIdProp)) != 0) {
char *s = fakeCString(vObjectUStringZValue(curVO));
if (strcmp(productId().local8Bit(), s) != 0)
kdDebug() << "This vCalendar file was not created by KOrganizer "
"or any other product we support. Loading anyway..." << endl;
mLoadedProductId = s;
deleteStr(s);
}
// 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)
kdDebug() << "This vCalendar file has version " << s
<< "We only support " << _VCAL_VERSION << endl;
deleteStr(s);
}
// set the time zone
if ((curVO = isAPropertyOf(vcal, VCTimeZoneProp)) != 0) {
- char *s = fakeCString(vObjectUStringZValue(curVO));
- mCalendar->setTimeZone(s);
- deleteStr(s);
+ if ( vObjectUStringZValue(curVO) != 0 ) {
+ char *s = fakeCString(vObjectUStringZValue(curVO));
+ mCalendar->setTimeZone(s);
+ deleteStr(s);
+ }
}
-
// Store all events with a relatedTo property in a list for post-processing
mEventsRelate.clear();
mTodosRelate.clear();
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, XPilotStatusProp)) != 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 (mCalendar->event(tmpStr)) {
goto SKIP;
}
if (mCalendar->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) {
if ( !anEvent->dtStart().isValid() || !anEvent->dtEnd().isValid() ) {
kdDebug() << "VCalFormat::populate(): Event has invalid dates."
<< endl;
} else {
mCalendar->addEvent(anEvent);
}
} else {
// some sort of error must have occurred while in translation.
goto SKIP;
}
} else if (strcmp(vObjectName(curVO), VCTodoProp) == 0) {
Todo *aTodo = VTodoToEvent(curVO);
mCalendar->addTodo(aTodo);
} 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
// Post-Process list of events with relations, put Event objects in relation
Event *ev;
for ( ev=mEventsRelate.first(); ev != 0; ev=mEventsRelate.next() ) {
ev->setRelatedTo(mCalendar->event(ev->relatedToUid()));
}
Todo *todo;
for ( todo=mTodosRelate.first(); todo != 0; todo=mTodosRelate.next() ) {
todo->setRelatedTo(mCalendar->todo(todo->relatedToUid()));
}
}
const char *VCalFormat::dayFromNum(int day)
{
const char *days[7] = { "MO ", "TU ", "WE ", "TH ", "FR ", "SA ", "SU " };
return days[day];
}
int VCalFormat::numFromDay(const QString &day)
{
if (day == "MO ") return 0;
if (day == "TU ") return 1;
if (day == "WE ") return 2;
if (day == "TH ") return 3;
if (day == "FR ") return 4;
if (day == "SA ") return 5;
if (day == "SU ") return 6;
return -1; // something bad happened. :)
}
Attendee::PartStat VCalFormat::readStatus(const char *s) const
{
QString statStr = s;
statStr = statStr.upper();
Attendee::PartStat status;
if (statStr == "X-ACTION")
status = Attendee::NeedsAction;
else if (statStr == "NEEDS ACTION")
status = Attendee::NeedsAction;
else if (statStr== "ACCEPTED")
status = Attendee::Accepted;
else if (statStr== "SENT")
status = Attendee::NeedsAction;
else if (statStr== "TENTATIVE")
status = Attendee::Tentative;
else if (statStr== "CONFIRMED")
status = Attendee::Accepted;
else if (statStr== "DECLINED")
status = Attendee::Declined;
else if (statStr== "COMPLETED")
status = Attendee::Completed;
else if (statStr== "DELEGATED")
status = Attendee::Delegated;
else {
kdDebug(5800) << "error setting attendee mStatus, unknown mStatus!" << endl;
status = Attendee::NeedsAction;
}
return status;
}
QCString VCalFormat::writeStatus(Attendee::PartStat status) const
{
switch(status) {
default:
case Attendee::NeedsAction:
return "NEEDS ACTION";
break;
case Attendee::Accepted:
return "ACCEPTED";
break;
case Attendee::Declined:
return "DECLINED";
break;
case Attendee::Tentative:
return "TENTATIVE";
break;
case Attendee::Delegated:
return "DELEGATED";
break;
case Attendee::Completed:
return "COMPLETED";
break;
case Attendee::InProcess:
return "NEEDS ACTION";
break;
}
}