summaryrefslogtreecommitdiffabout
path: root/libkcal
Side-by-side diff
Diffstat (limited to 'libkcal') (more/less context) (show whitespace changes)
-rw-r--r--libkcal/phoneformat.cpp60
-rw-r--r--libkcal/phoneformat.h2
-rw-r--r--libkcal/vcalformat.cpp19
-rw-r--r--libkcal/vcalformat.h2
4 files changed, 32 insertions, 51 deletions
diff --git a/libkcal/phoneformat.cpp b/libkcal/phoneformat.cpp
index 11c68c5..e6d4879 100644
--- a/libkcal/phoneformat.cpp
+++ b/libkcal/phoneformat.cpp
@@ -1,1308 +1,1266 @@
/*
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.
*/
#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 <qxml.h>
#include <qlabel.h>
#include <kdebug.h>
#include <klocale.h>
#include <kglobal.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( Calendar *calendar, QString profileName ) : mCalendar( calendar ), mProfileName ( profileName ) {
;
}
bool readTodo( Calendar *existingCalendar,GSM_ToDoEntry *ToDo, GSM_StateMachine* s)
{
int id = ToDo->Location;
Todo *todo;
todo = existingCalendar->todo( mProfileName ,QString::number( id ) );
if (todo )
todo = (Todo *)todo->clone();
else
todo = new Todo;
todo->setID( mProfileName,QString::number( id ) );
todo->setTempSyncStat(SYNC_TEMPSTATE_NEW_EXTERNAL );
int priority;
switch (ToDo->Priority) {
case GSM_Priority_Low : priority = 1; break;
case GSM_Priority_Medium : priority = 3; break;
case GSM_Priority_High : priority = 5; break;
default :priority = 3 ; break;
}
todo->setPriority( priority );
GSM_Phone_Functions *Phone;
Phone=s->Phone.Functions;
int j;
GSM_DateTime* dtp;
bool alarm = false;
QDateTime alarmDt;
GSM_Category Category;
int error;
for (j=0;j<ToDo->EntriesNum;j++) {
//qDebug(" for todo %d",ToDo->Location );
switch (ToDo->Entries[j].EntryType) {
case TODO_END_DATETIME:
dtp = &ToDo->Entries[j].Date ;
todo->setDtDue (fromGSM ( dtp ));
break;
case TODO_COMPLETED:
if ( ToDo->Entries[j].Number == 1 ) {
todo->setCompleted( true );
}
else {
todo->setCompleted( false );
}
break;
case TODO_ALARM_DATETIME:
dtp = &ToDo->Entries[j].Date ;
alarm = true;
alarmDt = fromGSM ( dtp );
break;
case TODO_SILENT_ALARM_DATETIME:
dtp = &ToDo->Entries[j].Date ;
alarm = true;
alarmDt = fromGSM ( dtp );
break;
case TODO_TEXT:
//qDebug(" text *%s* ", (const char*) DecodeUnicodeConsole(ToDo->Entries[j].Text ));
todo->setSummary( QString::fromUtf8 ( (const char*)DecodeUnicodeConsole(ToDo->Entries[j].Text )));
break;
case TODO_PRIVATE:
if ( ToDo->Entries[j].Number == 1 )
todo->setSecrecy( Incidence::SecrecyPrivate );
else
todo->setSecrecy( Incidence::SecrecyPublic );
break;
case TODO_CATEGORY:
Category.Location = ToDo->Entries[j].Number;
Category.Type = Category_ToDo;
error=Phone->GetCategory(s, &Category);
if (error == ERR_NONE) {
QStringList cat = todo->categories();
QString nCat = QString ( (const char*)Category.Name );
if ( !nCat.isEmpty() )
if ( !cat.contains( nCat )) {
cat << nCat;
todo->setCategories( cat );
}
}
break;
case TODO_CONTACTID:
#if 0
// not supported
entry.Location = ToDo->Entries[j].Number;
entry.MemoryType = MEM_ME;
error=Phone->GetMemory(s, &entry);
if (error == ERR_NONE) {
name = GSM_PhonebookGetEntryName(&entry);
if (name != NULL) {
printmsg("Contact ID : \"%s\" (%d)\n", DecodeUnicodeConsole(name), ToDo->Entries[j].Number);
} else {
printmsg("Contact ID : %d\n",ToDo->Entries[j].Number);
}
} else {
printmsg("Contact : %d\n",ToDo->Entries[j].Number);
}
#endif
break;
case TODO_PHONE:
#if 0
// not supported
printmsg("Phone : \"%s\"\n",DecodeUnicodeConsole(ToDo->Entries[j].Text));
#endif
break;
}
}
QString alarmString = "na";
if ( alarm ) {
Alarm *alarm;
if ( todo->alarms().count() > 0 )
alarm = todo->alarms().first();
else {
alarm = new Alarm( todo );
todo->addAlarm( alarm );
}
alarm->setType( Alarm::Audio );
alarm->setEnabled( true );
int alarmOffset = alarmDt.secsTo( todo->dtStart() );
alarm->setStartOffset( -alarmOffset );
alarmString = QString::number( alarmOffset );
} else {
Alarm *alarm;
if ( todo->alarms().count() > 0 ) {
alarm = todo->alarms().first();
alarm->setType( Alarm::Audio );
alarm->setStartOffset( -60*15 );
alarm->setEnabled( false );
}
}
// csum *****************************************
uint cSum;
cSum = PhoneFormat::getCsumTodo( todo );
todo->setCsum( mProfileName, QString::number( cSum ));
todo->setTempSyncStat( SYNC_TEMPSTATE_NEW_EXTERNAL );
mCalendar->addTodo( todo);
return true;
}
bool readEvent( Calendar *existingCalendar, GSM_CalendarEntry* Note)
{
int id = Note->Location;
Event *event;
event = existingCalendar->event( mProfileName ,QString::number( id ) );
if ( event )
event = (Event*)event->clone();
else
event = new Event;
event->setID( mProfileName,QString::number( id ) );
event->setTempSyncStat(SYNC_TEMPSTATE_NEW_EXTERNAL );
int i = 0;
bool repeating = false;
int repeat_dayofweek = -1;
int repeat_day = -1;
int repeat_weekofmonth = -1;
int repeat_month = -1;
int repeat_frequency = -1;
int rec_type = -1;
GSM_DateTime repeat_startdate = {0,0,0,0,0,0,0};
GSM_DateTime repeat_stopdate = {0,0,0,0,0,0,0};
GSM_DateTime* dtp;
bool alarm = false;
QDateTime alarmDt;
repeat_startdate.Day = 0;
repeat_stopdate.Day = 0;
for (i=0;i<Note->EntriesNum;i++) {
//qDebug(" for ev");
switch (Note->Entries[i].EntryType) {
case CAL_START_DATETIME:
dtp = &Note->Entries[i].Date ;
if ( dtp->Hour > 24 ) {
event->setFloats( true );
event->setDtStart( QDateTime (datefromGSM ( dtp ), QTime(0,0,0 )));
} else {
event->setDtStart (fromGSM ( dtp ));
}
break;
case CAL_END_DATETIME:
dtp = &Note->Entries[i].Date ;
if ( dtp->Hour > 24 ) {
event->setFloats( true );
event->setDtEnd( QDateTime (datefromGSM ( dtp ), QTime(0,0,0 )));
} else {
event->setDtEnd (fromGSM ( dtp ));
}
break;
case CAL_ALARM_DATETIME:
dtp = &Note->Entries[i].Date ;
alarm = true;
alarmDt = fromGSM ( dtp );
break;
case CAL_SILENT_ALARM_DATETIME:
dtp = &Note->Entries[i].Date ;
alarm = true;
alarmDt = fromGSM ( dtp );
break;
case CAL_RECURRANCE:
rec_type = Note->Entries[i].Number;
//printmsg("Repeat : %d day%s\n",Note->Entries[i].Number/24,((Note->Entries[i].Number/24)>1) ? "s":"" );
break;
case CAL_TEXT:
//qDebug(" ev text %s", DecodeUnicodeConsole(Note->Entries[i].Text) );
event->setSummary( QString::fromUtf8 ( (const char*)DecodeUnicodeConsole( Note->Entries[i].Text )));
break;
case CAL_LOCATION:
event->setLocation(QString::fromUtf8 ((const char*) DecodeUnicodeConsole(Note->Entries[i].Text) ));
break;
case CAL_PHONE:
//printmsg("Phone : \"%s\"\n",DecodeUnicodeConsole(Note->Entries[i].Text));
break;
case CAL_PRIVATE:
if ( Note->Entries[i].Number == 1 )
event->setSecrecy( Incidence::SecrecyPrivate );
else
event->setSecrecy( Incidence::SecrecyPublic );
break;
case CAL_CONTACTID:
#if 0
entry.Location = Note->Entries[i].Number;
entry.MemoryType = MEM_ME;
error=Phone->GetMemory(&s, &entry);
if (error == ERR_NONE) {
name = GSM_PhonebookGetEntryName(&entry);
if (name != NULL) {
//printmsg("Contact ID : \"%s\" (%d)\n", DecodeUnicodeConsole(name), Note->Entries[i].Number);
} else {
//printmsg("Contact ID : %d\n",Note->Entries[i].Number);
}
} else {
//printmsg("Contact ID : %d\n",Note->Entries[i].Number);
}
#endif
break;
case CAL_REPEAT_DAYOFWEEK:
repeat_dayofweek = Note->Entries[i].Number;
repeating = true;
break;
case CAL_REPEAT_DAY:
repeat_day = Note->Entries[i].Number;
repeating = true;
break;
case CAL_REPEAT_WEEKOFMONTH:
repeat_weekofmonth = Note->Entries[i].Number;
repeating = true;
break;
case CAL_REPEAT_MONTH:
repeat_month = Note->Entries[i].Number;
repeating = true;
break;
case CAL_REPEAT_FREQUENCY:
repeat_frequency = Note->Entries[i].Number;
repeating = true;
break;
case CAL_REPEAT_STARTDATE:
repeat_startdate = Note->Entries[i].Date;
repeating = true;
break;
case CAL_REPEAT_STOPDATE:
repeat_stopdate = Note->Entries[i].Date;
repeating = true;
break;
}
}
#if 0
event->setDescription( attList[4] );
bool repeating = false;
int repeat_dayofweek = -1;
int repeat_day = -1;
int repeat_weekofmonth = -1;
int repeat_month = -1;
int repeat_frequency = -1;
GSM_DateTime repeat_startdate = {0,0,0,0,0,0,0};
GSM_DateTime repeat_stopdate = {0,0,0,0,0,0,0};
#endif
QString recurString = "no";
if ( repeating && repeat_frequency != -1) {
recurString = "y";
if ( repeat_dayofweek >= 0 )
recurString += "dow" + QString::number (repeat_dayofweek);
if ( repeat_day >= 0 )
recurString += "d" + QString::number (repeat_day);
if ( repeat_weekofmonth >= 0 )
recurString += "w" + QString::number (repeat_weekofmonth);
if ( repeat_month >= 0 )
recurString += "m" + QString::number ( repeat_month );
if ( repeat_frequency >= 0 )
recurString += "f" + QString::number (repeat_frequency );
int rtype = 0;
// qDebug("recurs ");
QDate startDate, endDate;
if ( repeat_startdate.Day > 0 ) {
startDate = datefromGSM ( &repeat_startdate );
event->setDtStart(QDateTime ( startDate, event->dtStart().time()));
} else {
startDate = event->dtStart().date();
}
int freq = repeat_frequency;
bool hasEndDate = false;
if ( repeat_stopdate.Day > 0 ) {
endDate = datefromGSM ( &repeat_stopdate );
hasEndDate = true;
}
uint weekDaysNum = repeat_dayofweek ;
// 1 == monday, 7 == sunday
QBitArray weekDays( 7 );
int i;
int bb = 1;
for( i = 1; i <= 7; ++i ) {
weekDays.setBit( i - 1, ( bb & weekDaysNum ));
bb = 2 << (i-1);
//qDebug(" %d bit %d ",i-1,weekDays.at(i-1) );
}
// qDebug("next ");
int pos = 0;
Recurrence *r = event->recurrence();
/*
0 daily;
1 weekly;x
2 monthpos;x
3 monthlyday;
4 rYearlyMont
bool repeating = false;
int repeat_dayofweek = -1;
int repeat_day = -1;
int repeat_weekofmonth = -1;
int repeat_month = -1;
int repeat_frequency = -1;
*/
int dayOfWeek = startDate.dayOfWeek();
if ( repeat_weekofmonth >= 0 ) {
rtype = 2; // ************************ 2 MonthlyPos
pos = repeat_weekofmonth;
if ( repeat_dayofweek >= 0 )
dayOfWeek = repeat_dayofweek;
if (repeat_month > 0) {
if ( repeat_month != event->dtStart().date().month() ) {
QDate date (event->dtStart().date().year(),repeat_month,event->dtStart().date().day() );
event->setDtStart(QDateTime ( date , event->dtStart().time()) );
}
if ( freq == 1 )
freq = 12;
}
} else if ( repeat_dayofweek >= 0 ) {
rtype = 1;// ************************ 1 Weekly
} else if ( repeat_day >= 0 ) {
if ( repeat_month > 0) {
rtype = 4;
} else {
rtype = 3;
}
} else {
rtype = 0 ;
}
if ( rtype == 0 ) {
if ( hasEndDate ) r->setDaily( freq, endDate );
else r->setDaily( freq, -1 );
} else if ( rtype == 1 ) {
if ( hasEndDate ) r->setWeekly( freq, weekDays, endDate );
else r->setWeekly( freq, weekDays, -1 );
} else if ( rtype == 3 ) {
if ( hasEndDate )
r->setMonthly( Recurrence::rMonthlyDay, freq, endDate );
else
r->setMonthly( Recurrence::rMonthlyDay, freq, -1 );
r->addMonthlyDay( startDate.day() );
} else if ( rtype == 2 ) {
if ( hasEndDate )
r->setMonthly( Recurrence::rMonthlyPos, freq, endDate );
else
r->setMonthly( Recurrence::rMonthlyPos, freq, -1 );
QBitArray days( 7 );
days.fill( false );
days.setBit( dayOfWeek - 1 );
r->addMonthlyPos( pos, days );
} else if ( rtype == 4 ) {
if ( hasEndDate )
r->setYearly( Recurrence::rYearlyMonth, freq, endDate );
else
r->setYearly( Recurrence::rYearlyMonth, freq, -1 );
r->addYearlyNum( startDate.month() );
}
} else {
event->recurrence()->unsetRecurs();
}
QStringList categoryList;
categoryList << getCategory( Note );
event->setCategories( categoryList );
// strange 0 semms to mean: alarm enabled
if ( alarm ) {
Alarm *alarm;
if ( event->alarms().count() > 0 )
alarm = event->alarms().first();
else {
alarm = new Alarm( event );
event->addAlarm( alarm );
}
alarm->setType( Alarm::Audio );
alarm->setEnabled( true );
int alarmOffset = alarmDt.secsTo( event->dtStart() );
alarm->setStartOffset( -alarmOffset );
} else {
Alarm *alarm;
if ( event->alarms().count() > 0 ) {
alarm = event->alarms().first();
alarm->setType( Alarm::Audio );
alarm->setStartOffset( -60*15 );
alarm->setEnabled( false );
}
}
// csum *****************************************
uint cSum;
cSum = PhoneFormat::getCsumEvent( event );
event->setCsum( mProfileName, QString::number( cSum ));
event->setTempSyncStat( SYNC_TEMPSTATE_NEW_EXTERNAL );
mCalendar->addEvent( event);
return true;
}
QDateTime fromGSM ( GSM_DateTime* dtp, bool useTz = true ) {
QDateTime dt;
int y,m,t,h,min,sec;
y = dtp->Year;
m = dtp->Month;
t = dtp->Day;
h = dtp->Hour;
min = dtp->Minute;
sec = dtp->Second;
dt = QDateTime(QDate(y,m,t), QTime(h,min,sec));
// dtp->Timezone: offset in hours
int offset = KGlobal::locale()->localTimeOffset( dt );
if ( useTz )
dt = dt.addSecs ( offset*60);
return dt;
}
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;
}
QDate datefromGSM ( GSM_DateTime* dtp ) {
return QDate ( dtp->Year, dtp->Month, dtp->Day );
}
QString getCategory( GSM_CalendarEntry* Note)
{
QString CATEGORY;
switch (Note->Type) {
case GSM_CAL_REMINDER : CATEGORY = QString("Reminder"); break;
case GSM_CAL_CALL : CATEGORY = QString("Call"); break;
case GSM_CAL_MEETING : CATEGORY = QString("Meeting"); break;
case GSM_CAL_BIRTHDAY : CATEGORY = QString("Birthday"); break;
case GSM_CAL_MEMO : CATEGORY = QString("Memo"); break;
case GSM_CAL_TRAVEL : CATEGORY = QString("Travel"); break;
case GSM_CAL_VACATION : CATEGORY = QString("Vacation"); break;
case GSM_CAL_ALARM : CATEGORY = QString("Alarm"); break;
case GSM_CAL_DAILY_ALARM : CATEGORY = QString("Daily alarm"); break;
case GSM_CAL_T_ATHL : CATEGORY = QString("Training/Athletism"); break;
case GSM_CAL_T_BALL : CATEGORY = QString("Training/Ball Games"); break;
case GSM_CAL_T_CYCL : CATEGORY = QString("Training/Cycling"); break;
case GSM_CAL_T_BUDO : CATEGORY = QString("Training/Budo"); break;
case GSM_CAL_T_DANC : CATEGORY = QString("Training/Dance"); break;
case GSM_CAL_T_EXTR : CATEGORY = QString("Training/Extreme Sports"); break;
case GSM_CAL_T_FOOT : CATEGORY = QString("Training/Football"); break;
case GSM_CAL_T_GOLF : CATEGORY = QString("Training/Golf"); break;
case GSM_CAL_T_GYM : CATEGORY = QString("Training/Gym"); break;
case GSM_CAL_T_HORS : CATEGORY = QString("Training/Horse Races"); break;
case GSM_CAL_T_HOCK : CATEGORY = QString("Training/Hockey"); break;
case GSM_CAL_T_RACE : CATEGORY = QString("Training/Races"); break;
case GSM_CAL_T_RUGB : CATEGORY = QString("Training/Rugby"); break;
case GSM_CAL_T_SAIL : CATEGORY = QString("Training/Sailing"); break;
case GSM_CAL_T_STRE : CATEGORY = QString("Training/Street Games"); break;
case GSM_CAL_T_SWIM : CATEGORY = QString("Training/Swimming"); break;
case GSM_CAL_T_TENN : CATEGORY = QString("Training/Tennis"); break;
case GSM_CAL_T_TRAV : CATEGORY = QString("Training/Travels"); break;
case GSM_CAL_T_WINT : CATEGORY = QString("Training/Winter Games"); break;
default : CATEGORY = QString("");
}
return CATEGORY;
}
protected:
private:
Calendar *mCalendar;
QString mProfileName ;
};
PhoneFormat::PhoneFormat(QString profileName, QString device,QString connection, QString model )
{
mProfileName = profileName;
mDevice = device;
mConnection = connection;
mModel = model;
}
PhoneFormat::~PhoneFormat()
{
}
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;
}
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;
attList << QString::number( todo->priority() );
QString alarmString = "na";
Alarm *alarm;
if ( todo->alarms().count() > 0 ) {
alarm = todo->alarms().first();
if ( alarm->enabled() ) {
alarmString = QString::number(alarm->startOffset().asSeconds() );
}
}
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->startOffset().asSeconds() );
}
}
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();
attList << event->secrecyStr();
return PhoneFormat::getCsum(attList );
}
ulong PhoneFormat::getCsum( const QStringList & attList)
{
int max = attList.count() -1;
ulong cSum = 0;
int j,k,i;
int add;
for ( i = 1; 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;
add = add * mul *i*i*i;
cSum += add;
}
}
}
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)
{
GSM_StateMachine s;
qDebug(" load ");
s.opened = false;
s.msg = NULL;
s.ConfigNum = 0;
QLabel status ( i18n("Reading data. Opening device ..."), 0 );
int w = status.sizeHint().width()+20 ;
if ( w < 200 ) w = 200;
int h = status.sizeHint().height()+20 ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
status.setCaption(i18n("Reading Phone Data") );
status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
status.show();
status.raise();
qApp->processEvents();
#if 0
static char *cp;
static INI_Section *cfg = NULL;
cfg=GSM_FindGammuRC();
int i;
for (i = 0; i <= MAX_CONFIG_NUM; i++) {
if (cfg!=NULL) {
cp = (char *)INI_GetValue(cfg, (unsigned char*) "gammu", (unsigned char*)"gammucoding", false);
if (cp) di.coding = cp;
s.Config[i].Localize = (char *)INI_GetValue(cfg, (unsigned char*) "gammu", (unsigned char*) "gammuloc", false);
if (s.Config[i].Localize) {
s.msg=INI_ReadFile(s.Config[i].Localize, true);
} else {
#if !defined(WIN32) && defined(LOCALE_PATH)
locale = setlocale(LC_MESSAGES, NULL);
if (locale != NULL) {
snprintf(locale_file, 200, "%s/gammu_%c%c.txt",
LOCALE_PATH,
tolower(locale[0]),
tolower(locale[1]));
s.msg = INI_ReadFile(locale_file, true);
}
#endif
}
}
/* Wanted user specific configuration? */
if (!GSM_ReadConfig(cfg, &s.Config[i], i) && i != 0) break;
s.ConfigNum++;
/* We want to use only one file descriptor for global and state machine debug output */
s.Config[i].UseGlobalDebugFile = true;
/* We wanted to read just user specified configuration. */
{break;}
}
#endif
int error=initDevice(&s);
qDebug("GSM Init %d (no error is %d)", error, ERR_NONE);
if ( error != ERR_NONE )
return false;
GSM_Phone_Functions *Phone;
GSM_CalendarEntry note;
bool start = true;
Phone=s.Phone.Functions;
bool gshutdown = false;
PhoneParser handler( calendar, mProfileName );
int ccc = 0;
QString message = i18n("Processing event # ");
int procCount = 0;
qDebug("Debug: only 10 calender items are downloaded ");
while (!gshutdown && ccc++ < 10) {
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
qDebug("readEvent %d ", ccc);
error=Phone->GetNextCalendar(&s,&note,start);
if (error == ERR_EMPTY) break;
start = false;
handler.readEvent( existingCal, &note );
}
start = true;
GSM_ToDoEntry ToDo;
ccc = 0;
message = i18n("Processing todo # ");
procCount = 0;
while (!gshutdown) {
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
error = Phone->GetNextToDo(&s, &ToDo, start);
if (error == ERR_EMPTY) break;
start = false;
qDebug("ReadTodo %d ", ++ccc);
handler.readTodo( existingCal, &ToDo, &s);
}
error=GSM_TerminateConnection(&s);
return true;
}
void PhoneFormat::event2GSM( Event* ev, GSM_CalendarEntry*Note )
{
-
+ QString eText = vfconverter.eventToString( ev );
+ int pos = 0;
+ GSM_ToDoEntry dummy;
+ GSM_DecodeVCALENDAR_VTODO( (unsigned char*)eText.latin1(), &pos, Note , &dummy, Nokia_VCalendar, Nokia_VToDo );
}
-void PhoneFormat::todo2GSM( Todo* todo, GSM_ToDoEntry *gsm )
+void PhoneFormat::todo2GSM( Todo* todo, GSM_ToDoEntry *gsmTodo )
{
-#if 0
- QStringList list;
- list.append( QString::number( todo->zaurusId() ) );
- list.append( todo->categories().join(",") );
-
- if ( todo->hasStartDate() ) {
- list.append( dtToString( todo->dtStart()) );
- } else
- list.append( QString() );
-
- if ( todo->hasDueDate() ) {
- QTime tim;
- if ( todo->doesFloat()) {
- list.append( dtToString( QDateTime(todo->dtDue().date(),QTime( 0,0,0 )), false)) ;
- } else {
- list.append( dtToString(todo->dtDue() ) );
- }
- } else
- list.append( QString() );
-
- if ( todo->isCompleted() ) {
- list.append( dtToString( todo->completed()) );
- list.append( "0" ); // yes 0 == completed
- } else {
- list.append( dtToString( todo->completed()) );
- list.append( "1" );
- }
- list.append( QString::number( todo->priority() ));
- if( ! todo->summary().isEmpty() )
- list.append( todo->summary() );
- else
- list.append( "" );
- if (! todo->description().isEmpty() )
- list.append( todo->description() );
- else
- list.append( "" );
- for(QStringList::Iterator it=list.begin();
- it!=list.end(); ++it){
- QString& s = (*it);
- s.replace(QRegExp("\""), "\"\"");
- if(s.contains(QRegExp("[,\"\r\n]")) || s.stripWhiteSpace() != s){
- s.prepend('\"');
- s.append('\"');
- } else if(s.isEmpty() && !s.isNull()){
- s = "\"\"";
- }
- }
- return list.join(",");
-#endif
+ QString tText = vfconverter.todoToString( todo );
+ int pos = 0;
+ GSM_CalendarEntry dummy;
+ GSM_DecodeVCALENDAR_VTODO( (unsigned char*)tText.latin1(), &pos, &dummy, gsmTodo, Nokia_VCalendar, Nokia_VToDo );
}
void PhoneFormat::afterSave( Incidence* inc)
{
uint csum;
if ( inc->type() == "Event")
csum = PhoneFormat::getCsumEvent( (Event*) inc );
else
csum = PhoneFormat::getCsumTodo( (Todo*) inc );
inc->setCsum( mProfileName, QString::number( csum ));
inc->setTempSyncStat( SYNC_TEMPSTATE_NEW_ID );
}
bool PhoneFormat::save( Calendar *calendar)
{
GSM_StateMachine s;
qDebug(" save ");
s.opened = false;
s.msg = NULL;
s.ConfigNum = 0;
QLabel status ( i18n("Writing data. Opening device ..."), 0 );
int w = status.sizeHint().width()+20 ;
if ( w < 200 ) w = 200;
int h = status.sizeHint().height()+20 ;
int dw = QApplication::desktop()->width();
int dh = QApplication::desktop()->height();
status.setCaption(i18n("Writing Phone Data") );
status.setGeometry( (dw-w)/2, (dh - h )/2 ,w,h );
status.show();
status.raise();
qApp->processEvents();
int error=initDevice(&s);
qDebug("GSM Init %d (no error is %d)", error, ERR_NONE);
if ( error != ERR_NONE )
return false;
GSM_Phone_Functions *Phone;
GSM_CalendarEntry Note;
bool start = true;
Phone=s.Phone.Functions;
bool gshutdown = false;
QPtrList<Event> er = calendar->rawEvents();
Event* ev = er.first();
QString message = i18n("Processing event # ");
int procCount = 0;
while ( ev ) {
//qDebug("i %d ", ++i);
if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) { // event was changed during sync or is a new one
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
event2GSM( ev, &Note );
if ( ev->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete
error = Phone->DeleteCalendar(&s, &Note);
}
else if ( ev->getID(mProfileName).isEmpty() ) { // add new
// we have to do this later after deleting
}
else { // change existing
error = Phone->SetCalendar(&s, &Note);
}
}
ev = er.next();
}
ev = er.first();
// pending get empty slots
while ( ev ) {
if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && ev->tempSyncStat() != SYNC_TEMPSTATE_DELETE) {
if ( ev->getID(mProfileName).isEmpty() ) {
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
//int newID ;//= pending
//ev->setID(mProfileName, QString::number( newID ));
event2GSM( ev, &Note );
Note.Location = 0;
error = Phone->AddCalendar(&s, &Note);
ev->setID( mProfileName, QString::number( Note.Location ) );
qDebug("New Calendar. Location %d ",Note.Location );
afterSave( ev );
} else {
afterSave( ev ); // setting temp sync stat for changed items
}
}
ev = er.next();
}
GSM_ToDoEntry ToDoEntry;
QPtrList<Todo> tl = calendar->rawTodos();
Todo* to = tl.first();
message = i18n("Processing todo # ");
procCount = 0;
while ( to ) {
if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) {
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
todo2GSM( to, &ToDoEntry );
if ( to->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete
error=Phone->DeleteToDo(&s,&ToDoEntry);
}
else if ( to->getID("Sharp_DTM").isEmpty() ) { // add new
;
}
else { // change existing
error=Phone->SetToDo(&s,&ToDoEntry);
}
}
to = tl.next();
}
// pending get empty slots
to = tl.first();
while ( to ) {
if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && to->tempSyncStat() != SYNC_TEMPSTATE_DELETE) {
if ( to->getID(mProfileName).isEmpty() ) {
status.setText ( message + QString::number ( ++procCount ) );
qApp->processEvents();
//int newID ;//= pending
//to->setID(mProfileName, QString::number( newID ));
todo2GSM( to, &ToDoEntry );
ToDoEntry.Location = 0;
error=Phone->AddToDo(&s,&ToDoEntry);
to->setID(mProfileName, QString::number( ToDoEntry.Location ));
afterSave( to );
qDebug("New Todo. Location %d ",ToDoEntry.Location );
} else {
afterSave( to );
}
}
to = tl.next();
}
return true;
}
QString PhoneFormat::dtToGSM( const QDateTime& dti, bool useTZ )
{
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;
}
QString PhoneFormat::getEventString( Event* event )
{
#if 0
QStringList list;
list.append( QString::number(event->zaurusId() ) );
list.append( event->categories().join(",") );
if ( !event->summary().isEmpty() )
list.append( event->summary() );
else
list.append("" );
if ( !event->location().isEmpty() )
list.append( event->location() );
else
list.append("" );
if ( !event->description().isEmpty() )
list.append( event->description() );
else
list.append( "" );
if ( event->doesFloat () ) {
list.append( dtToString( QDateTime(event->dtStart().date(), QTime(0,0,0)), false ));
list.append( dtToString( QDateTime(event->dtEnd().date(),QTime(23,59,59)), false )); //6
list.append( "1" );
}
else {
list.append( dtToString( event->dtStart()) );
list.append( dtToString( event->dtEnd()) ); //6
list.append( "0" );
}
bool noAlarm = true;
if ( event->alarms().count() > 0 ) {
Alarm * al = event->alarms().first();
if ( al->enabled() ) {
noAlarm = false;
list.append( "0" ); // yes, 0 == alarm
list.append( QString::number( al->startOffset().asSeconds()/(-60) ) );
if ( al->type() == Alarm::Audio )
list.append( "1" ); // type audio
else
list.append( "0" ); // type silent
}
}
if ( noAlarm ) {
list.append( "1" ); // yes, 1 == no alarm
list.append( "0" ); // no alarm offset
list.append( "1" ); // type
}
// next is: 11
// next is: 11-16 are recurrence
Recurrence* rec = event->recurrence();
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( dtToString( rec->endDate()) );
} else {
list.append( "0" );
list.append( "20991231T000000" );
}
}
if ( event->doesFloat () ) {
list.append( dtToString( event->dtStart(), false ).left( 8 ));
list.append( dtToString( event->dtEnd(), false ).left( 8 )); //6
}
else {
list.append( QString() );
list.append( QString() );
}
if (event->dtStart().date() == event->dtEnd().date() )
list.append( "0" );
else
list.append( "1" );
for(QStringList::Iterator it=list.begin();
it!=list.end(); ++it){
QString& s = (*it);
s.replace(QRegExp("\""), "\"\"");
if(s.contains(QRegExp("[,\"\r\n]")) || s.stripWhiteSpace() != s){
s.prepend('\"');
s.append('\"');
} else if(s.isEmpty() && !s.isNull()){
s = "\"\"";
}
}
return list.join(",");
#endif
return QString();
}
QString PhoneFormat::getTodoString( Todo* todo )
{
#if 0
QStringList list;
list.append( QString::number( todo->zaurusId() ) );
list.append( todo->categories().join(",") );
if ( todo->hasStartDate() ) {
list.append( dtToString( todo->dtStart()) );
} else
list.append( QString() );
if ( todo->hasDueDate() ) {
QTime tim;
if ( todo->doesFloat()) {
list.append( dtToString( QDateTime(todo->dtDue().date(),QTime( 0,0,0 )), false)) ;
} else {
list.append( dtToString(todo->dtDue() ) );
}
} else
list.append( QString() );
if ( todo->isCompleted() ) {
list.append( dtToString( todo->completed()) );
list.append( "0" ); // yes 0 == completed
} else {
list.append( dtToString( todo->completed()) );
list.append( "1" );
}
list.append( QString::number( todo->priority() ));
if( ! todo->summary().isEmpty() )
list.append( todo->summary() );
else
list.append( "" );
if (! todo->description().isEmpty() )
list.append( todo->description() );
else
list.append( "" );
for(QStringList::Iterator it=list.begin();
it!=list.end(); ++it){
QString& s = (*it);
s.replace(QRegExp("\""), "\"\"");
if(s.contains(QRegExp("[,\"\r\n]")) || s.stripWhiteSpace() != s){
s.prepend('\"');
s.append('\"');
} else if(s.isEmpty() && !s.isNull()){
s = "\"\"";
}
}
return list.join(",");
#endif
return QString();
}
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 7b7dd04..33b2091 100644
--- a/libkcal/phoneformat.h
+++ b/libkcal/phoneformat.h
@@ -1,65 +1,67 @@
/*
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"
extern "C" {
#include "../gammu/emb/common/gammu.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 );
private:
+ VCalFormat vfconverter;
void event2GSM( Event* ev, GSM_CalendarEntry*Note );
void todo2GSM( Todo* ev, GSM_ToDoEntry *ToDo );
int initDevice(GSM_StateMachine *s);
QString getEventString( Event* );
QString getTodoString( Todo* );
QString dtToGSM( const QDateTime& dt, bool useTZ = true );
QString mProfileName, mDevice, mConnection, mModel;
void afterSave( Incidence* );
};
}
#endif
diff --git a/libkcal/vcalformat.cpp b/libkcal/vcalformat.cpp
index 72a781a..1167e58 100644
--- a/libkcal/vcalformat.cpp
+++ b/libkcal/vcalformat.cpp
@@ -1,1678 +1,1697 @@
/*
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 <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()
{
}
VCalFormat::~VCalFormat()
{
}
bool VCalFormat::load(Calendar *calendar, const QString &fileName)
{
mCalendar = calendar;
clearException();
kdDebug(5800) << "VCalFormat::load() " << fileName << endl;
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;
QString tmpStr;
VObject *vcal, *vo;
kdDebug(5800) << "VCalFormat::save(): " << fileName << endl;
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)) {
kdDebug(5800) << "No error" << endl;
return true;
} else {
kdDebug(5800) << "Error" << endl;
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 {
kdDebug(5800) << "VCalFormat::fromString(): Unknown object type." << endl;
deleteVObject( vcal );
return false;
}
deleteVObject( vcal );
return true;
}
+QString VCalFormat::eventToString( Event * event)
+{
+ if ( !event ) return QString::null;
+ VObject *vevent = eventToVEvent( event );
+ char *buf = writeMemVObject( 0, 0, vevent );
+ QString result( buf );
+ cleanVObject( vevent );
+ return result;
+}
+QString VCalFormat::todoToString( Todo * todo )
+{
+ if ( !todo ) return QString::null;
+ VObject *vevent = eventToVTodo( todo );
+ char *buf = writeMemVObject( 0, 0, vevent );
+ QString result( buf );
+ cleanVObject( vevent );
+ 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 = addProp(vtodo, VCDAlarmProp);
tmpStr = qDateTimeToISO(alarm->time());
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCDisplayStringProp, "beep!");
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()));
}
}
}
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))
tmpStr += dayFromNum(i);
}
break;
case Recurrence::rMonthlyPos:
tmpStr.sprintf("MP%i ", anEvent->recurrence()->frequency());
// write out all rMonthPos's
tmpPositions = anEvent->recurrence()->monthPositions();
for (tmpPos = tmpPositions.first();
tmpPos;
tmpPos = tmpPositions.next()) {
tmpStr2.sprintf("%i", tmpPos->rPos);
if (tmpPos->negative)
tmpStr2 += "- ";
else
tmpStr2 += "+ ";
tmpStr += tmpStr2;
for (i = 0; i < 7; i++) {
if (tmpPos->rDays.testBit(i))
tmpStr += dayFromNum(i);
}
} // loop for all rMonthPos's
break;
case Recurrence::rMonthlyDay:
tmpStr.sprintf("MD%i ", anEvent->recurrence()->frequency());
// write out all rMonthDays;
tmpDays = anEvent->recurrence()->monthDays();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
tmpStr2.sprintf("%i ", *tmpDay);
tmpStr += tmpStr2;
}
break;
case Recurrence::rYearlyMonth:
tmpStr.sprintf("YM%i ", anEvent->recurrence()->frequency());
// write out all the rYearNums;
tmpDays = anEvent->recurrence()->yearNums();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
tmpStr2.sprintf("%i ", *tmpDay);
tmpStr += tmpStr2;
}
break;
case Recurrence::rYearlyDay:
tmpStr.sprintf("YD%i ", anEvent->recurrence()->frequency());
// write out all the rYearNums;
tmpDays = anEvent->recurrence()->yearNums();
for (tmpDay = tmpDays.first();
tmpDay;
tmpDay = tmpDays.next()) {
tmpStr2.sprintf("%i ", *tmpDay);
tmpStr += tmpStr2;
}
break;
default:
kdDebug(5800) << "ERROR, it should never get here in eventToVEvent!" << endl;
break;
} // switch
if (anEvent->recurrence()->duration() > 0) {
tmpStr2.sprintf("#%i",anEvent->recurrence()->duration());
tmpStr += tmpStr2;
} else if (anEvent->recurrence()->duration() == -1) {
tmpStr += "#0"; // defined as repeat forever
} else {
tmpStr += qDateTimeToISO(anEvent->recurrence()->endDate(), FALSE);
}
addPropValue(vevent,VCRRuleProp, tmpStr.local8Bit());
} // event repeats
// exceptions to recurrence
DateList dateList = anEvent->exDates();
DateList::ConstIterator it;
QString tmpStr2;
for (it = dateList.begin(); it != dateList.end(); ++it) {
tmpStr = qDateToISO(*it) + ";";
tmpStr2 += tmpStr;
}
if (!tmpStr2.isEmpty()) {
tmpStr2.truncate(tmpStr2.length()-1);
addPropValue(vevent, VCExpDateProp, tmpStr2.local8Bit());
}
// description
if (!anEvent->description().isEmpty()) {
VObject *d = addPropValue(vevent, VCDescriptionProp,
anEvent->description().local8Bit());
if (anEvent->description().find('\n') != -1)
addProp(d, VCQuotedPrintableProp);
}
// summary
if (!anEvent->summary().isEmpty())
addPropValue(vevent, VCSummaryProp, anEvent->summary().local8Bit());
if (!anEvent->location().isEmpty())
addPropValue(vevent, VCLocationProp, anEvent->location().local8Bit());
// status
// TODO: define Event status
// addPropValue(vevent, VCStatusProp, anEvent->statusStr().local8Bit());
// secrecy
const char *text = 0;
switch (anEvent->secrecy()) {
case Incidence::SecrecyPublic:
text = "PUBLIC";
break;
case Incidence::SecrecyPrivate:
text = "PRIVATE";
break;
case Incidence::SecrecyConfidential:
text = "CONFIDENTIAL";
break;
}
if (text) {
addPropValue(vevent, VCClassProp, text);
}
// 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(vevent, VCCategoriesProp, tmpStr.local8Bit());
}
// attachments
// TODO: handle binary attachments!
QPtrList<Attachment> attachments = anEvent->attachments();
for ( Attachment *at = attachments.first(); at; at = attachments.next() )
addPropValue(vevent, VCAttachProp, at->uri().local8Bit());
// resources
tmpStrList = anEvent->resources();
tmpStr = tmpStrList.join(";");
if (!tmpStr.isEmpty())
addPropValue(vevent, VCResourcesProp, tmpStr.local8Bit());
// alarm stuff
QPtrList<Alarm> alarms = anEvent->alarms();
Alarm* alarm;
for (alarm = alarms.first(); alarm; alarm = alarms.next()) {
if (alarm->enabled()) {
VObject *a = addProp(vevent, VCDAlarmProp);
tmpStr = qDateTimeToISO(alarm->time());
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCDisplayStringProp, "beep!");
if (alarm->type() == Alarm::Audio) {
a = addProp(vevent, VCAAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCAudioContentProp, QFile::encodeName(alarm->audioFile()));
}
if (alarm->type() == Alarm::Procedure) {
a = addProp(vevent, VCPAlarmProp);
addPropValue(a, VCRunTimeProp, tmpStr.local8Bit());
addPropValue(a, VCRepeatCountProp, "1");
addPropValue(a, VCProcedureNameProp, QFile::encodeName(alarm->programFile()));
}
}
}
// priority
tmpStr.sprintf("%i",anEvent->priority());
addPropValue(vevent, VCPriorityProp, tmpStr.local8Bit());
// transparency
tmpStr.sprintf("%i",anEvent->transparency());
addPropValue(vevent, VCTranspProp, tmpStr.local8Bit());
// related event
if (anEvent->relatedTo()) {
addPropValue(vevent, VCRelatedToProp,
anEvent->relatedTo()->uid().local8Bit());
}
if (anEvent->pilotId()) {
// pilot sync stuff
tmpStr.sprintf("%i",anEvent->pilotId());
addPropValue(vevent, XPilotIdProp, tmpStr.local8Bit());
tmpStr.sprintf("%i",anEvent->syncStatus());
addPropValue(vevent, XPilotStatusProp, tmpStr.local8Bit());
}
return vevent;
}
Todo *VCalFormat::VTodoToEvent(VObject *vtodo)
{
VObject *vo;
VObjectIterator voi;
char *s;
Todo *anEvent = new Todo;
// creation date
if ((vo = isAPropertyOf(vtodo, VCDCreatedProp)) != 0) {
anEvent->setCreated(ISOToQDateTime(s = fakeCString(vObjectUStringZValue(vo))));
deleteStr(s);
}
// unique id
vo = isAPropertyOf(vtodo, 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);
}
// last modification date
if ((vo = isAPropertyOf(vtodo, 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(vtodo, ICOrganizerProp)) != 0) {
anEvent->setOrganizer(s = fakeCString(vObjectUStringZValue(vo)));
deleteStr(s);
} else {
anEvent->setOrganizer(mCalendar->getEmail());
}
// attendees.
initPropIterator(&voi, vtodo);
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);
}
}
// description for todo
if ((vo = isAPropertyOf(vtodo, VCDescriptionProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setDescription(QString::fromLocal8Bit(s));
deleteStr(s);
}
// summary
if ((vo = isAPropertyOf(vtodo, VCSummaryProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setSummary(QString::fromLocal8Bit(s));
deleteStr(s);
}
if ((vo = isAPropertyOf(vtodo, VCLocationProp))) {
s = fakeCString(vObjectUStringZValue(vo));
anEvent->setLocation(QString::fromLocal8Bit(s));
deleteStr(s);
}
// completed
// was: status
if ((vo = isAPropertyOf(vtodo, VCStatusProp)) != 0) {
s = fakeCString(vObjectUStringZValue(vo));
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);
}
}
/*********************** 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);
}
} else {
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) {
QDateTime tmpDT(qdt);
tmpDT = tmpDT.addSecs(60*(-mCalendar->getTimeZone())); // correct to GMT.
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(60*mCalendar->getTimeZone());
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);
}
// 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;
}
}
diff --git a/libkcal/vcalformat.h b/libkcal/vcalformat.h
index d4cecbc..8490125 100644
--- a/libkcal/vcalformat.h
+++ b/libkcal/vcalformat.h
@@ -1,108 +1,110 @@
/*
This file is part of libkcal.
Copyright (c) 1998 Preston Brown
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 _VCALFORMAT_H
#define _VCALFORMAT_H
#include "calformat.h"
#define _VCAL_VERSION "1.0"
class VObject;
namespace KCal {
/**
This class implements the vCalendar format. It provides methods for
loading/saving/converting vCalendar format data into the internal KOrganizer
representation as Calendar and Events.
@short vCalendar format implementation
*/
class VCalFormat : public CalFormat {
public:
VCalFormat();
virtual ~VCalFormat();
/** loads a calendar on disk in vCalendar format into the current calendar.
* any information already present is lost. Returns TRUE if successful,
* else returns FALSE.
* @param fileName the name of the calendar on disk.
*/
bool load(Calendar *,const QString &fileName);
/** writes out the calendar to disk in vCalendar format. Returns true if
* successful and false on error.
* @param fileName the name of the file
*/
bool save(Calendar *,const QString &fileName);
/**
Parse string and populate calendar with that information.
*/
bool fromString( Calendar *, const QString & );
/**
Return calendar information as string.
*/
QString toString( Calendar * );
+ QString eventToString( Event * );
+ QString todoToString( Todo * );
protected:
/** translates a VObject of the TODO type into a Event */
Todo *VTodoToEvent(VObject *vtodo);
/** translates a VObject into a Event and returns a pointer to it. */
Event *VEventToEvent(VObject *vevent);
/** translate a Event into a VTodo-type VObject and return pointer */
VObject *eventToVTodo(const Todo *anEvent);
/** translate a Event into a VObject and returns a pointer to it. */
VObject* eventToVEvent(const Event *anEvent);
/** takes a QDate and returns a string in the format YYYYMMDDTHHMMSS */
QString qDateToISO(const QDate &);
/** takes a QDateTime and returns a string in format YYYYMMDDTHHMMSS */
QString qDateTimeToISO(const QDateTime &, bool zulu=TRUE);
/** takes a string in the format YYYYMMDDTHHMMSS and returns a
* valid QDateTime. */
QDateTime ISOToQDateTime(const QString & dtStr);
/** takes a string in the format YYYYMMDD and returns a
* valid QDate. */
QDate ISOToQDate(const QString & dtStr);
/** takes a vCalendar tree of VObjects, and puts all of them that have
* the "event" property into the dictionary, todos in the todo-list, etc. */
void populate(VObject *vcal);
/** takes a number 0 - 6 and returns the two letter string of that day,
* i.e. MO, TU, WE, etc. */
const char *dayFromNum(int day);
/** the reverse of the above function. */
int numFromDay(const QString &day);
Attendee::PartStat readStatus(const char *s) const;
QCString writeStatus(Attendee::PartStat status) const;
private:
Calendar *mCalendar;
QPtrList<Event> mEventsRelate; // events with relations
QPtrList<Todo> mTodosRelate; // todos with relations
};
}
#endif