-rw-r--r-- | libkcal/incidence.cpp | 5 | ||||
-rw-r--r-- | libkcal/incidence.h | 2 | ||||
-rw-r--r-- | libkcal/phoneformat.cpp | 1464 | ||||
-rw-r--r-- | libkcal/phoneformat.h | 14 | ||||
-rw-r--r-- | libkcal/vcalformat.cpp | 5 | ||||
-rw-r--r-- | libkcal/vcalformat.h | 5 |
6 files changed, 194 insertions, 1301 deletions
diff --git a/libkcal/incidence.cpp b/libkcal/incidence.cpp index d9bda64..56c9801 100644 --- a/libkcal/incidence.cpp +++ b/libkcal/incidence.cpp @@ -489,96 +489,101 @@ QStringList Incidence::secrecyList() } QPtrList<Alarm> Incidence::alarms() const { return mAlarms; } Alarm* Incidence::newAlarm() { Alarm* alarm = new Alarm(this); mAlarms.append(alarm); // updated(); return alarm; } void Incidence::addAlarm(Alarm *alarm) { mAlarms.append(alarm); updated(); } void Incidence::removeAlarm(Alarm *alarm) { mAlarms.removeRef(alarm); updated(); } void Incidence::clearAlarms() { mAlarms.clear(); updated(); } bool Incidence::isAlarmEnabled() const { Alarm* alarm; for (QPtrListIterator<Alarm> it(mAlarms); (alarm = it.current()) != 0; ++it) { if (alarm->enabled()) return true; } return false; } Recurrence *Incidence::recurrence() const { return mRecurrence; } +void Incidence::setRecurrence( Recurrence * r) +{ + delete mRecurrence; + mRecurrence = r; +} void Incidence::setLocation(const QString &location) { if (mReadOnly) return; mLocation = location; updated(); } QString Incidence::location() const { return mLocation; } ushort Incidence::doesRecur() const { if ( mRecurrence ) return mRecurrence->doesRecur(); else return Recurrence::rNone; } QDateTime Incidence::getNextOccurence( const QDateTime& dt, bool* ok ) const { QDateTime incidenceStart = dt; *ok = false; if ( doesRecur() ) { bool last; recurrence()->getPreviousDateTime( incidenceStart , &last ); int count = 0; if ( !last ) { while ( !last ) { ++count; incidenceStart = recurrence()->getNextDateTime( incidenceStart, &last ); if ( recursOn( incidenceStart.date() ) ) { last = true; // exit while llop } else { if ( last ) { // no alarm on last recurrence return QDateTime (); } int year = incidenceStart.date().year(); // workaround for bug in recurrence if ( count == 100 || year < 1980 || year > 5000 ) { return QDateTime (); } incidenceStart = incidenceStart.addSecs( 1 ); } } } else { return QDateTime (); } diff --git a/libkcal/incidence.h b/libkcal/incidence.h index d1972cb..7dc6f10 100644 --- a/libkcal/incidence.h +++ b/libkcal/incidence.h @@ -200,97 +200,97 @@ class Incidence : public IncidenceBase QPtrList<Attachment> attachments(const QString& mime) const; /** sets the event's status the value specified. See the enumeration * above for possible values. */ void setSecrecy(int); /** return the event's secrecy. */ int secrecy() const; /** return the event's secrecy in string format. */ QString secrecyStr() const; /** return list of all availbale secrecy classes */ static QStringList secrecyList(); /** return human-readable name of secrecy class */ static QString secrecyName(int); /** returns TRUE if the date specified is one on which the event will * recur. */ bool recursOn(const QDate &qd) const; // VEVENT and VTODO, but not VJOURNAL (move to EventBase class?): /** set resources used, such as Office, Car, etc. */ void setResources(const QStringList &resources); /** return list of current resources */ QStringList resources() const; /** set the event's priority, 0 is undefined, 1 highest (decreasing order) */ void setPriority(int priority); /** get the event's priority */ int priority() const; /** All alarms that are associated with this incidence */ QPtrList<Alarm> alarms() const; /** Create a new alarm which is associated with this incidence */ Alarm* newAlarm(); /** Add an alarm which is associated with this incidence */ void addAlarm(Alarm*); /** Remove an alarm that is associated with this incidence */ void removeAlarm(Alarm*); /** Remove all alarms that are associated with this incidence */ void clearAlarms(); /** return whether any alarm associated with this incidence is enabled */ bool isAlarmEnabled() const; /** Return the recurrence rule associated with this incidence. If there is none, returns an appropriate (non-0) object. */ Recurrence *recurrence() const; - + void setRecurrence(Recurrence * r); /** Forward to Recurrence::doesRecur(). */ ushort doesRecur() const; /** set the event's/todo's location. Do _not_ use it with journal */ void setLocation(const QString &location); /** return the event's/todo's location. Do _not_ use it with journal */ QString location() const; /** returns TRUE or FALSE depending on whether the todo has a start date */ bool hasStartDate() const; /** sets the event's hasStartDate value. */ void setHasStartDate(bool f); QDateTime getNextOccurence( const QDateTime& dt, bool* yes ) const; bool cancelled() const; void setCancelled( bool b ); protected: QPtrList<Alarm> mAlarms; private: int mRevision; bool mCancelled; // base components of jounal, event and todo QDateTime mCreated; QString mDescription; QString mSummary; QStringList mCategories; Incidence *mRelatedTo; QString mRelatedToUid; QPtrList<Incidence> mRelations; DateList mExDates; QPtrList<Attachment> mAttachments; QStringList mResources; bool mHasStartDate; // if todo has associated start date int mSecrecy; int mPriority; // 1 = highest, 2 = less, etc. //QPtrList<Alarm> mAlarms; Recurrence *mRecurrence; QString mLocation; }; bool operator==( const Incidence&, const Incidence& ); } diff --git a/libkcal/phoneformat.cpp b/libkcal/phoneformat.cpp index 1769b37..0bc9125 100644 --- a/libkcal/phoneformat.cpp +++ b/libkcal/phoneformat.cpp @@ -1,662 +1,168 @@ /* This file is part of libkcal. - Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> + 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 <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 ) { + PhoneParser( ) { ; } - 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 = 5; break; - case GSM_Priority_Medium : priority = 3; break; - case GSM_Priority_High : priority = 1; 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 )); - - } - //Note->Entries[i].Date.Hour = 5; - 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 cat = event->categories(); - QString nCat = getCategory( Note ); - - if ( !nCat.isEmpty() ) - if ( !cat.contains( nCat )) { - cat << nCat; - event->setCategories( cat ); - } - - 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 = false ) { - 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() { } +#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; 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" ); @@ -726,966 +232,350 @@ ulong PhoneFormat::getCsumEvent( Event* event ) 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("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("Reading phone...") ); - 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 ) + QString fileName; +#ifdef _WIN32_ + fileName = locateLocal("data", "korganizer") + "\\tempfile.vcs"; +#else + fileName = "/tmp/kdepimtemp.vcs"; +#endif + QString command ="./kammu --backup " + fileName + " -yes"; + int ret = system ( command.latin1() ); + if ( ret != 0 ) 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(" Reading 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,¬e,start); - if (error == ERR_EMPTY) break; - start = false; - handler.readEvent( existingCal, ¬e ); - qDebug("Org loc %d ",note.Location); - //note.Location = 0; - error=Phone->SetCalendar(&s,¬e); - qDebug("new loc %d ",note.Location); + VCalFormat vfload; + vfload.setLocalTime ( true ); + if ( ! vfload.load( calendar, fileName ) ) + return false; + QPtrList<Event> er = calendar->rawEvents(); + Event* ev = er.first(); + while ( 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(); + } + { + 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(); + Todo *event; + event = existingCal->todo( mProfileName ,QString::number( id ) ); + if ( event ) { + 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(); + } } - - start = true; - GSM_ToDoEntry ToDo; - ccc = 0; - message = i18n(" Reading todo # "); - procCount = 0; - while (!gshutdown && ccc++ < 10) { - 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; } -#include <qcstring.h> -void PhoneFormat::event2GSM( Calendar *cal,Event* ev, GSM_CalendarEntry*Note ) +void PhoneFormat::copyEvent( Event* to, Event* from ) { - QString eText = vfconverter.eventToString( ev, cal ); - int pos = 0; - GSM_ToDoEntry dummy; - qDebug( "Convert event"); - QByteArray ba; - QDataStream s ( ba, IO_WriteOnly ); - s << eText.utf8(); - GSM_DecodeVCALENDAR_VTODO( (unsigned char*) ba.data(), &pos, Note , &dummy, Nokia_VCalendar, Nokia_VToDo ); - qDebug( "Convert event done"); - Note->Location = 0; - QString loc = ev->getID(mProfileName); - if ( !loc.isEmpty() ){ - Note->Location = loc.toInt(); + 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() ); + + QPtrListIterator<Alarm> it( from->alarms() ); + to->clearAlarms(); + const Alarm *a; + while( (a = it.current()) ) { + Alarm *b = new Alarm( *a ); + b->setParent( to ); + to->addAlarm( b ); + ++it; + } + 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 ) ; + } -void PhoneFormat::todo2GSM( Calendar *cal, Todo* todo, GSM_ToDoEntry *gsmTodo ) +void PhoneFormat::copyTodo( Todo* to, Todo* from ) { - qDebug( "Convert todo1"); - QString tText = vfconverter.todoToString( todo, cal ); - int pos = 0; - GSM_CalendarEntry dummy; - QByteArray ba; - QDataStream s ( ba, IO_WriteOnly ); - s << tText.utf8(); - GSM_DecodeVCALENDAR_VTODO( (unsigned char*) ba.data(), &pos, &dummy, gsmTodo, Nokia_VCalendar, Nokia_VToDo ); - qDebug( "Convert todo done "); - gsmTodo->Location = 0; - QString loc = todo->getID(mProfileName); - if ( !loc.isEmpty() ){ - gsmTodo->Location = loc.toInt(); + if ( from->dtStart().isValid() ) + to->setDtStart( from->dtStart() ); + if ( from->dtDue().isValid() ) + 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() ); + + QPtrListIterator<Alarm> it( from->alarms() ); + to->clearAlarms(); + const Alarm *a; + while( (a = it.current()) ) { + Alarm *b = new Alarm( *a ); + b->setParent( to ); + to->addAlarm( b ); + ++it; + } + 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()); + } + to->setPriority(from->priority()); + } +#include <qcstring.h> + void PhoneFormat::afterSave( Incidence* inc) { 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->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(" 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(); - - 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(" Deleting event # "); - int procCount = 0; - int diffProc = 0; - bool setPossible = true; + QString message; #ifdef _WIN32_ QString fileName = locateLocal("data", "korganizer") + "\\tempfile.vcs"; #else QString fileName = "/tmp/kdepimtemp.vcs"; #endif - //algo 1 delete event - while ( ev ) { - 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(); - qDebug("del event1 %d ", procCount); - //event2GSM( calendar, ev, &Note ); - if ( ev->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete - QString loc = ev->getID(mProfileName); - if ( !loc.isEmpty() ){ - Note.Location = loc.toInt(); - } else { - qDebug("error: loc is empty "); - } - error = Phone->DeleteCalendar(&s, &Note); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - qDebug(" e error delete1 planB %d ", error); - break; - } - } - else if ( ev->getID(mProfileName).isEmpty() ) { // add new - // we have to do this later after deleting - - } - else { // change existing + // 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 { - QString loc = ev->getID(mProfileName); - if ( !loc.isEmpty() ){ - Note.Location = loc.toInt(); - } else { - qDebug("error3: loc is empty "); - } - error = Phone->DeleteCalendar(&s, &Note); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - qDebug(" e error delete2 planB %d ", error); - break; - } - ev->removeID( mProfileName ); - } - } + } ev = er.next(); } - //algo 1 delete todo - GSM_ToDoEntry ToDoEntry; + // 2 remove todos which should be deleted QPtrList<Todo> tl = calendar->rawTodos(); Todo* to = tl.first(); - message = i18n(" Deleting todo # "); - procCount = 0; while ( to ) { - if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) { - qDebug("todo3 %d ", procCount); - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - qDebug("todo5 %d ", procCount); - // todo2GSM( calendar, to, &ToDoEntry ); - QString loc = to->getID(mProfileName); - if ( !loc.isEmpty() ){ - ToDoEntry.Location = loc.toInt(); - } else { - qDebug("error2: loc is empty "); - } - if ( to->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete - error=Phone->DeleteToDo(&s,&ToDoEntry); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - qDebug("delete planB %d ", error); - } - } - else if ( to->getID(mProfileName).isEmpty() ) { // add new - ; - } - else { // change existing - error=Phone->DeleteToDo(&s,&ToDoEntry); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - qDebug("set planB %d ", error); - } - to->removeID( mProfileName ); - } + if ( to->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { + calendar->deleteTodo( to ); } to = tl.next(); } - //algo 2 add event - ev = er.first(); - QString filec; - message = i18n(" Preparing event # "); - procCount = 0; - 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(); - filec += vfconverter.eventToString( ev, calendar )+ "\n"; - afterSave ( ev ); - - } - } - ev = er.next(); - } - //algo 2 add todo - to = tl.first(); - procCount = 0; - message = i18n(" Preparing todo # "); - while ( to ) { - qDebug("todo2 %d ", procCount); - if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && to->tempSyncStat() != SYNC_TEMPSTATE_DELETE) { - qDebug("todo4 %d ", procCount); - if ( to->getID(mProfileName).isEmpty() ) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - filec += vfconverter.todoToString( to, calendar )+ "\n"; - afterSave ( to ); - } - } - to = tl.next(); - } - if ( filec.isEmpty() ) { - qDebug("Nothing to write back.Finished. "); - error=GSM_TerminateConnection(&s); - return true; - } - //algo 3 saving file - message = i18n(" Saving temp file ... "); - status.setText ( message ); - qApp->processEvents(); - QFile file( fileName ); - if (!file.open( IO_WriteOnly ) ) { - qDebug("error open file "); - error=GSM_TerminateConnection(&s); + // 3 save file + VCalFormat vfsave; + vfsave.setLocalTime ( true ); + if ( ! vfsave.save( calendar, fileName ) ) return false; - } - QTextStream ts( &file ); - ts.setCodec( QTextCodec::codecForName("utf8") ); - ts << filec ; - file.close(); - - - message = i18n(" Parsing temp file ... "); - status.setText ( message ); - qApp->processEvents(); - GSM_Backup Backup; - error=GSM_ReadBackupFile( (char*) fileName.latin1() ,&Backup); - qDebug("Read file result %d ",error ); - //algo 4 writing event - int max, i; - procCount = 0; - message = i18n(" Writing event # "); - if (Backup.Calendar[0] != NULL) { - max = 0; - while (Backup.Calendar[max]!=NULL) max++; - - GSM_DateTime* dtp; - - for (i=0;i<max;i++) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - Note = *Backup.Calendar[i]; - -#if 0 - int j; - for (j=0;j<Note.EntriesNum;j++) { - //qDebug(" for ev"); - switch (Note.Entries[j].EntryType) { - case CAL_START_DATETIME: - //Note->Entries[i].Date.Hour = 5; - dtp = &Note.Entries[j].Date; - qDebug("start event %d %d %d - %d %d %d", dtp->Year, dtp->Month, dtp->Day, dtp->Hour, dtp->Minute, dtp->Second ); - break; - case CAL_END_DATETIME: - dtp = &Note.Entries[j].Date; - qDebug("end event %d %d %d - %d %d %d", dtp->Year, dtp->Month, dtp->Day, dtp->Hour, dtp->Minute, dtp->Second ); - break; - } - } - int type = Note.Type; - qDebug(" event type %d - %d %d - %d %d %d",type, GSM_CAL_CALL , GSM_CAL_MEETING ,GSM_CAL_BIRTHDAY, GSM_CAL_MEMO ,GSM_CAL_ALARM ); -#endif - - Note.Type = GSM_CAL_MEETING; - // pending: fix in gammu GSM_ReadBackupFile the type settings - int loc = Note.Location; - Note.Location = 0; - error=Phone->AddCalendar(&s,&Note); - qDebug("add event %d %d %d", error, Note.Location, loc ); - } - } - //algo 4 writing todo - procCount = 0; - message = i18n(" Writing todo # "); - if (Backup.ToDo[0] != NULL) { - max = 0; - while (Backup.ToDo[max]!=NULL) max++; - for (i=0;i<max;i++) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - ToDoEntry = *Backup.ToDo[i]; - error = Phone->AddToDo(&s,&ToDoEntry); - qDebug("add todo %d ", error); - } - } - //algo 5 reread + // 4 call kammu + QString command ="./kammu --restore " + fileName ; + int ret = system ( command.latin1() ); + if ( ret != 0 ) + return false; + // 5 reread data message = i18n(" Rereading all data ... "); status.setText ( message ); qApp->processEvents(); - error=GSM_TerminateConnection(&s); 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 +//algo 6 compare event + er = calendar->rawEvents(); ev = er.first(); message = i18n(" Comparing event # "); QPtrList<Event> er1 = calendarTemp->rawEvents(); Event* ev1; - procCount = 0; + int procCount = 0; while ( ev ) { - if ( ev->tempSyncStat() == SYNC_TEMPSTATE_NEW_ID) { qDebug("event new ID "); status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); QString cSum = ev->getCsum(mProfileName); ev1 = er1.first(); while ( ev1 ) { if ( ev1->getCsum( mProfileName ) == cSum ) { er1.remove( ev1 ); + afterSave( ev ); ev->setID(mProfileName, ev1->getID(mProfileName) ); break; } ev1 = er1.next(); } if ( ! ev1 ) { ev->removeID(mProfileName); qDebug("ERROR: No event found on phone for %s ", ev->summary().latin1()); - qDebug("Probably writing back of events not supported "); } - } + ev = er.next(); } //algo 6 compare todo to = tl.first(); procCount = 0; QPtrList<Todo> tl1 = calendarTemp->rawTodos(); Todo* to1 ; message = i18n(" Comparing todo # "); while ( to ) { qDebug("todo2 %d ", procCount); - if ( to->tempSyncStat() == SYNC_TEMPSTATE_NEW_ID) { status.setText ( message + QString::number ( ++procCount ) ); qApp->processEvents(); QString cSum = to->getCsum(mProfileName); Todo* to1 = tl1.first(); while ( to1 ) { if ( to1->getCsum( mProfileName ) == cSum ) { 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()); - qDebug("Probably writing back of todos not supported "); } - } + to = tl.next(); } delete calendarTemp; return true; - // ******************************************************************* - // ******************************************************************* - // ******************************************************************* -#if 0 - while ( ev && ! planB) { - 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(); - qDebug("event1 %d ", procCount); - event2GSM( calendar, ev, &Note ); - if ( ev->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete - error = Phone->DeleteCalendar(&s, &Note); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - planB = true; - qDebug(" e delete1 planB %d ", error); - break; - } - } - else if ( ev->getID(mProfileName).isEmpty() ) { // add new - // we have to do this later after deleting - - } - else { // change existing - if ( setPossible ) { - error = Phone->SetCalendar(&s, &Note); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - setPossible = false; - ++diffProc; - qDebug("Set cal not supported %d ", error); - break; - } - } - if ( ! setPossible) { - ++diffProc; - error = Phone->DeleteCalendar(&s, &Note); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - planB = true; - qDebug(" e delete2 planB %d ", error); - break; - } - ev->removeID( mProfileName ); - } - qDebug("Change Calendar. Location %d status: %d",Note.Location, error ); - } - } - ev = er.next(); - } - ev = er.first(); - // pending get empty slots - int loc = 0; - procCount -= diffProc; - while ( ev && ! planB) { - if ( ev->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && ev->tempSyncStat() != SYNC_TEMPSTATE_DELETE) { - qDebug("event2 %d ", procCount); - if ( ev->getID(mProfileName).isEmpty() ) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - //int newID ;//= pending - //ev->setID(mProfileName, QString::number( newID )); - event2GSM( calendar, ev, &Note ); - ++loc; - Note.Location = loc; - error = Phone->AddCalendar(&s, &Note); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - planB = true; - qDebug(" e add planB %d ", error); - break; - } - ev->setID( mProfileName, QString::number( Note.Location ) ); - qDebug("New Calendar. Location %d stat %d %d",Note.Location ,error, ERR_UNKNOWN); - afterSave( ev ); - } else { - afterSave( ev ); // setting temp sync stat for changed items - } - } - ev = er.next(); - } - if ( planB ) { - qDebug("delete all calendar..."); - status.setText ( i18n("Deleting all calendar...")); - qApp->processEvents(); - error=Phone->DeleteAllCalendar(&s); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - message = i18n(" Deleting event # "); - procCount = 0; - while (1) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - qDebug("deleting event ... %d", procCount); - error = Phone->GetNextCalendar(&s,&Note,true); - if (error != ERR_NONE) break; - error = Phone->DeleteCalendar(&s,&Note); - } - qDebug("deleting calendar ... finished"); - } else { - status.setText ( i18n("All calendar deleted!")); - qDebug("all cal deleted"); - } - bool planC = false; - ev = er.first(); - procCount = 0; - message = i18n(" Writing event # "); - while ( ev && ! planC) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - event2GSM( calendar, ev, &Note ); - Note.Location = procCount; - error=Phone->AddCalendar(&s,&Note); - if (error != ERR_NONE ) { - // we have currently no planC :-( - // planC = true; - //qDebug("add planC %d ", error); - //break; - // we remove the ID such that this todo is not deleted after next sync - ev->removeID(mProfileName); - ev->setTempSyncStat( SYNC_TEMPSTATE_NEW_ID ); - qDebug("error :cal adding loc %d planB stat %d ", Note.Location ,error); - } else { - qDebug("cal adding loc %d planB stat %d ", Note.Location ,error); - ev->setID(mProfileName, QString::number( Note.Location )); - afterSave( ev ); - } - ev = er.next(); - } - if ( planC ) { - qDebug("writing cal went wrong..."); - // we have currently no planC :-( - } - } - GSM_ToDoEntry ToDoEntry; - QPtrList<Todo> tl = calendar->rawTodos(); - Todo* to = tl.first(); - - message = i18n(" Processing todo # "); - procCount = 0; - planB = false; - while ( to && ! planB ) { - if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL ) { - qDebug("todo3 %d ", procCount); - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - qDebug("todo5 %d ", procCount); - todo2GSM( calendar, to, &ToDoEntry ); - if ( to->tempSyncStat() == SYNC_TEMPSTATE_DELETE ) { // delete - error=Phone->DeleteToDo(&s,&ToDoEntry); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - planB = true; - qDebug("delete planB %d ", error); - } - } - else if ( to->getID(mProfileName).isEmpty() ) { // add new - ; - } - else { // change existing - error=Phone->SetToDo(&s,&ToDoEntry); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - planB = true; - qDebug("set planB %d ", error); - } - qDebug("Old Todo. Location %d %d",ToDoEntry.Location , error ); - } - } - to = tl.next(); - } - - // pending get empty slots - to = tl.first(); - while ( to && ! planB ) { - qDebug("todo2 %d ", procCount); - if ( to->tempSyncStat() != SYNC_TEMPSTATE_NEW_EXTERNAL && to->tempSyncStat() != SYNC_TEMPSTATE_DELETE) { - qDebug("todo4 %d ", procCount); - if ( to->getID(mProfileName).isEmpty() ) { - status.setText ( message + QString::number ( ++procCount ) ); - qApp->processEvents(); - //int newID ;//= pending - //to->setID(mProfileName, QString::number( newID )); - todo2GSM( calendar,to, &ToDoEntry ); - ToDoEntry.Location = 0; - error=Phone->AddToDo(&s,&ToDoEntry); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - planB = true; - qDebug("new planB %d ", error); - } - to->setID(mProfileName, QString::number( ToDoEntry.Location )); - afterSave( to ); - qDebug("New Todo. Location %d %d",ToDoEntry.Location, error ); - } else { - afterSave( to ); - } - } - to = tl.next(); - } - if ( planB ) { - qDebug("delete all ..."); - error=Phone->DeleteAllToDo(&s); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - while (1) { - qDebug("deleting todo ..."); - error = Phone->GetNextToDo(&s,&ToDoEntry,true); - if (error != ERR_NONE) break; - error = Phone->DeleteToDo(&s,&ToDoEntry); - } - qDebug("deleting todo ... finished"); - } else { - qDebug("all todo deleted"); - } - bool planC = false; - to = tl.first(); - while ( to && ! planC ) { - todo2GSM( calendar,to, &ToDoEntry ); - ToDoEntry.Location = 0; - error=Phone->AddToDo(&s,&ToDoEntry); - if (error == ERR_NOTSUPPORTED || error == ERR_NOTIMPLEMENTED) { - // we have currently no planC :-( - // planC = true; - //qDebug("add planC %d ", error); - //break; - // we remove the ID such that this todo is not deleted after next sync - to->removeID(mProfileName); - to->setTempSyncStat( SYNC_TEMPSTATE_NEW_ID ); - } else { - qDebug("adding %d planB %d ", ToDoEntry.Location ,error); - to->setID(mProfileName, QString::number( ToDoEntry.Location )); - afterSave( to ); - } - to = tl.next(); - } - if ( planC ) { - // we have currently no planC :-( - } - } - return true; -#endif -} -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 2c2e51c..8286098 100644 --- a/libkcal/phoneformat.h +++ b/libkcal/phoneformat.h @@ -1,67 +1,61 @@ /* 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( Calendar *, Event* ev, GSM_CalendarEntry*Note ); - void todo2GSM( Calendar *, Todo* ev, GSM_ToDoEntry *ToDo ); - int initDevice(GSM_StateMachine *s); - QString getEventString( Event* ); - QString getTodoString( Todo* ); - QString dtToGSM( const QDateTime& dt, bool useTZ = true ); + void copyEvent( Event* to, Event* from ); + void copyTodo( Todo* to, Todo* from ); + //int initDevice(GSM_StateMachine *s); QString mProfileName, mDevice, mConnection, mModel; void afterSave( Incidence* ); }; } #endif diff --git a/libkcal/vcalformat.cpp b/libkcal/vcalformat.cpp index 0ebd7d1..4727a7a 100644 --- a/libkcal/vcalformat.cpp +++ b/libkcal/vcalformat.cpp @@ -9,100 +9,103 @@ 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(); 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(); diff --git a/libkcal/vcalformat.h b/libkcal/vcalformat.h index 848be78..5bef7ed 100644 --- a/libkcal/vcalformat.h +++ b/libkcal/vcalformat.h @@ -2,110 +2,111 @@ 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); + 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); + bool save(Calendar *,const QString &fileName ); /** Parse string and populate calendar with that information. */ bool fromString( Calendar *, const QString & ); /** Return calendar information as string. */ + void setLocalTime ( bool ); QString toString( Calendar * ); QString eventToString( Event *, Calendar *calendar, bool useLocalTime = true ); QString todoToString( Todo * ,Calendar *calendar, bool useLocalTime = true ); 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; bool useLocalTime; QPtrList<Event> mEventsRelate; // events with relations QPtrList<Todo> mTodosRelate; // todos with relations }; } #endif |