-rw-r--r-- | libkcal/phoneformat.cpp | 194 | ||||
-rw-r--r-- | libkcal/phoneformat.h | 4 |
2 files changed, 165 insertions, 33 deletions
diff --git a/libkcal/phoneformat.cpp b/libkcal/phoneformat.cpp index b8fed47..e43a507 100644 --- a/libkcal/phoneformat.cpp +++ b/libkcal/phoneformat.cpp @@ -51,77 +51,75 @@ 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; - QString completedString = "no"; 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 ); - completedString = "yes"; } 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 ); @@ -153,76 +151,66 @@ public: 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 ***************************************** - QStringList attList; uint cSum; - if ( todo->hasDueDate() ) - attList << dtToString ( todo->dtDue() ); - attList << QString::number( id ); - attList << todo->summary(); - attList << completedString; - attList << QString::number( todo->priority() ); - attList << alarmString; - attList << todo->categoriesStr(); - attList << todo->secrecyStr(); - cSum = PhoneFormat::getCsum(attList ); + 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; @@ -431,128 +419,117 @@ public: } 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 ); - QString alarmString = "na"; // 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 ); - alarmString = QString::number( 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 ***************************************** - QStringList attList; + uint cSum; - attList << dtToString ( event->dtStart() ); - attList << dtToString ( event->dtEnd() ); - attList << QString::number( id ); - attList << event->summary(); - attList << event->location(); - attList << alarmString; - attList << recurString; - attList << event->categoriesStr(); - attList << event->secrecyStr(); - cSum = PhoneFormat::getCsum(attList ); + 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; } - QString dtToString( const QDateTime& dti, bool useTZ = false ) + 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; @@ -600,64 +577,195 @@ PhoneFormat::PhoneFormat(QString profileName, QString device,QString connection, 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; @@ -769,166 +877,188 @@ void PhoneFormat::todo2GSM( Todo* todo, GSM_ToDoEntry *gsm ) 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 } +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 DTM 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->AddCalendar(&s, &Note); + 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 )); + //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 ) ); + 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->AddToDo(&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 )); + //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; diff --git a/libkcal/phoneformat.h b/libkcal/phoneformat.h index 1472880..7b7dd04 100644 --- a/libkcal/phoneformat.h +++ b/libkcal/phoneformat.h @@ -18,46 +18,48 @@ 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 "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: 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 |