00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qasciidict.h>
00022 #include <qmessagebox.h>
00023 #include <qtl.h>
00024
00025 #include <qpe/alarmserver.h>
00026 #include <qpe/global.h>
00027 #include "datebookdb.h"
00028 #include <qpe/stringutil.h>
00029
00030 #include <errno.h>
00031 #include <stdlib.h>
00032
00033
00034 class DateBookDBPrivate
00035 {
00036 public:
00037 bool clean;
00038 };
00039
00040
00041
00042
00043 static QString dateBookJournalFile()
00044 {
00045 QString str = getenv("HOME");
00046 return QString( str +"/.caljournal" );
00047 }
00048
00049 static QString dateBookFilename()
00050 {
00051 return Global::applicationFileName("datebook","datebook.xml");
00052 }
00053
00054
00055
00056
00057
00058
00059 bool nextOccurance(const Event &e, const QDate &from, QDateTime &next)
00060 {
00061
00062 QDate tmpDate;
00063 int freq = e.repeatPattern().frequency;
00064 int diff, diff2, a;
00065 int iday, imonth, iyear;
00066 int dayOfWeek = 0;
00067 int firstOfWeek = 0;
00068 int weekOfMonth;
00069
00070
00071 if (e.repeatPattern().hasEndDate && e.repeatPattern().endDate() < from)
00072 return FALSE;
00073
00074 if (e.start() >= from) {
00075 next = e.start();
00076 return TRUE;
00077 }
00078
00079 switch ( e.repeatPattern().type ) {
00080 case Event::Weekly:
00081
00082
00083
00084 dayOfWeek = from.dayOfWeek();
00085 dayOfWeek--;
00086
00087
00088
00089
00090 while(!((1 << firstOfWeek) & e.repeatPattern().days))
00091 firstOfWeek++;
00092
00093
00094
00095
00096 while(!((1 << (dayOfWeek % 7)) & e.repeatPattern().days))
00097 dayOfWeek++;
00098
00099
00100 dayOfWeek = dayOfWeek % 7;
00101 dayOfWeek -= e.start().date().dayOfWeek() -1;
00102
00103 firstOfWeek = firstOfWeek % 7;
00104 firstOfWeek -= e.start().date().dayOfWeek() -1;
00105
00106
00107
00108
00109 freq *= 7;
00110
00111 case Event::Daily:
00112
00113 if(e.start().date().addDays(dayOfWeek) > from) {
00114
00115 next = QDateTime(e.start().date().addDays(dayOfWeek),
00116 e.start().time());
00117 if ((next.date() > e.repeatPattern().endDate())
00118 && e.repeatPattern().hasEndDate)
00119 return FALSE;
00120 return TRUE;
00121 }
00122
00123
00124 diff = e.start().date().addDays(dayOfWeek).daysTo(from) % freq;
00125 diff2 = e.start().date().addDays(firstOfWeek).daysTo(from) % freq;
00126
00127 if(diff != 0)
00128 diff = freq - diff;
00129 if(diff2 != 0)
00130 diff2 = freq - diff2;
00131 diff = QMIN(diff, diff2);
00132
00133 next = QDateTime(from.addDays(diff), e.start().time());
00134 if ( (next.date() > e.repeatPattern().endDate())
00135 && e.repeatPattern().hasEndDate )
00136 return FALSE;
00137 return TRUE;
00138 case Event::MonthlyDay:
00139 iday = from.day();
00140 iyear = from.year();
00141 imonth = from.month();
00142
00143 dayOfWeek = e.start().date().dayOfWeek();
00144 weekOfMonth = (e.start().date().day() - 1) / 7;
00145
00146
00147 a = from.year() - e.start().date().year();
00148 a *= 12;
00149 a = a + (imonth - e.start().date().month());
00150
00151 if(a % freq) {
00152 a = freq - (a % freq);
00153 imonth = from.month() + a;
00154 if (imonth > 12) {
00155 imonth--;
00156 iyear += imonth / 12;
00157 imonth = imonth % 12;
00158 imonth++;
00159 }
00160 }
00161
00162
00163
00164
00165 tmpDate = QDate( iyear, imonth, 1 );
00166
00167 iday = 1;
00168 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
00169 iday += 7 * weekOfMonth;
00170 while (iday > tmpDate.daysInMonth()) {
00171 imonth += freq;
00172 if (imonth > 12) {
00173 imonth--;
00174 iyear += imonth / 12;
00175 imonth = imonth % 12;
00176 imonth++;
00177 }
00178 tmpDate = QDate( iyear, imonth, 1 );
00179
00180 if ((tmpDate > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00181 return FALSE;
00182 iday = 1;
00183 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
00184 iday += 7 * weekOfMonth;
00185 }
00186 tmpDate = QDate(iyear, imonth, iday);
00187
00188 if (tmpDate >= from) {
00189 next = QDateTime(tmpDate, e.start().time());
00190 if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00191 return FALSE;
00192 return TRUE;
00193 }
00194
00195
00196 do {
00197 imonth += freq;
00198 if (imonth > 12) {
00199 imonth--;
00200 iyear += imonth / 12;
00201 imonth = imonth % 12;
00202 imonth++;
00203 }
00204 tmpDate = QDate( iyear, imonth, 1 );
00205
00206 if ((tmpDate > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00207 return FALSE;
00208 iday = 1;
00209 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
00210 iday += 7 * weekOfMonth;
00211 } while (iday > tmpDate.daysInMonth());
00212 tmpDate = QDate(iyear, imonth, iday);
00213
00214 next = QDateTime(tmpDate, e.start().time());
00215 if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00216 return FALSE;
00217 return TRUE;
00218 case Event::MonthlyDate:
00219 iday = e.start().date().day();
00220 iyear = from.year();
00221 imonth = from.month();
00222
00223 a = from.year() - e.start().date().year();
00224 a *= 12;
00225 a = a + (imonth - e.start().date().month());
00226
00227 if(a % freq) {
00228 a = freq - (a % freq);
00229 imonth = from.month() + a;
00230 if (imonth > 12) {
00231 imonth--;
00232 iyear += imonth / 12;
00233 imonth = imonth % 12;
00234 imonth++;
00235 }
00236 }
00237
00238
00239
00240
00241 while(!QDate::isValid(iyear, imonth, iday) ) {
00242 imonth += freq;
00243 if (imonth > 12) {
00244 imonth--;
00245 iyear += imonth / 12;
00246 imonth = imonth % 12;
00247 imonth++;
00248 }
00249
00250 if ((QDate(iyear, imonth, 1) > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00251 return FALSE;
00252 }
00253
00254 if(QDate(iyear, imonth, iday) >= from) {
00255
00256 next = QDateTime(QDate(iyear, imonth, iday),
00257 e.start().time());
00258 if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00259 return FALSE;
00260 return TRUE;
00261 }
00262
00263
00264 imonth += freq;
00265 imonth--;
00266 iyear += imonth / 12;
00267 imonth = imonth % 12;
00268 imonth++;
00269
00270 while(!QDate::isValid(iyear, imonth, iday) ) {
00271 imonth += freq;
00272 imonth--;
00273 iyear += imonth / 12;
00274 imonth = imonth % 12;
00275 imonth++;
00276 if ((QDate(iyear, imonth, 1) > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00277 return FALSE;
00278 }
00279
00280 next = QDateTime(QDate(iyear, imonth, iday), e.start().time());
00281 if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00282 return FALSE;
00283 return TRUE;
00284 case Event::Yearly:
00285 iday = e.start().date().day();
00286 imonth = e.start().date().month();
00287 iyear = from.year();
00288
00289 diff = 1;
00290 if(imonth == 2 && iday > 28) {
00291
00292 if(freq % 4)
00293 if (freq % 2)
00294 freq = freq * 4;
00295 else
00296 freq = freq * 2;
00297
00298 diff = 4;
00299 }
00300
00301 a = from.year() - e.start().date().year();
00302 if(a % freq) {
00303 a = freq - (a % freq);
00304 iyear = iyear + a;
00305 }
00306
00307
00308 if(!QDate::isValid(iyear, imonth, iday)) {
00309
00310 iyear += freq;
00311 }
00312
00313 if(QDate(iyear, imonth, iday) >= from) {
00314 next = QDateTime(QDate(iyear, imonth, iday),
00315 e.start().time());
00316 if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00317 return FALSE;
00318 return TRUE;
00319 }
00320
00321 iyear += freq;
00322
00323 if(!QDate::isValid(iyear, imonth, iday)) {
00324
00325 iyear += freq;
00326 }
00327
00328 next = QDateTime(QDate(iyear, imonth, iday), e.start().time());
00329 if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate)
00330 return FALSE;
00331 return TRUE;
00332 default:
00333 return FALSE;
00334 }
00335 }
00336
00337 static bool nextAlarm( const Event &ev, QDateTime& when, int& warn)
00338 {
00339 QDateTime now = QDateTime::currentDateTime();
00340 if ( ev.hasRepeat() ) {
00341 QDateTime ralarm;
00342 if (nextOccurance(ev, now.date(), ralarm)) {
00343 ralarm = ralarm.addSecs(-ev.alarmTime()*60);
00344 if ( ralarm > now ) {
00345 when = ralarm;
00346 warn = ev.alarmTime();
00347 } else if ( nextOccurance(ev, now.date().addDays(1), ralarm) ) {
00348 ralarm = ralarm.addSecs( -ev.alarmTime()*60 );
00349 if ( ralarm > now ) {
00350 when = ralarm;
00351 warn = ev.alarmTime();
00352 }
00353 }
00354 }
00355 } else {
00356 warn = ev.alarmTime();
00357 when = ev.start().addSecs( -ev.alarmTime()*60 );
00358 }
00359 return when > now;
00360 }
00361
00362 static void addEventAlarm( const Event &ev )
00363 {
00364 QDateTime when;
00365 int warn;
00366 if ( nextAlarm(ev,when,warn) )
00367 AlarmServer::addAlarm( when,
00368 "QPE/Application/datebook",
00369 "alarm(QDateTime,int)", warn );
00370 }
00371
00372 static void delEventAlarm( const Event &ev )
00373 {
00374 QDateTime when;
00375 int warn;
00376 if ( nextAlarm(ev,when,warn) )
00377 AlarmServer::deleteAlarm( when,
00378 "QPE/Application/datebook",
00379 "alarm(QDateTime,int)", warn );
00380 }
00381
00382
00383 DateBookDB::DateBookDB()
00384 {
00385 init();
00386 }
00387
00388 DateBookDB::~DateBookDB()
00389 {
00390 save();
00391 eventList.clear();
00392 repeatEvents.clear();
00393
00394 delete d;
00395 d=0;
00396 }
00397
00398
00399
00400
00401 QValueList<Event> DateBookDB::getEvents( const QDate &from, const QDate &to )
00402 {
00403 QValueList<Event> tmpList;
00404 tmpList = getNonRepeatingEvents( from, to );
00405
00406
00407 for (QValueList<Event>::ConstIterator it = repeatEvents.begin();
00408 it != repeatEvents.end(); ++it) {
00409 QDate itDate = from;
00410 QDateTime due;
00411
00412
00413
00414 Event dummy_event = *it;
00415 Event::RepeatPattern r = dummy_event.repeatPattern();
00416 if ( !r.hasEndDate || r.endDate() > to ) {
00417 r.setEndDate( to );
00418 r.hasEndDate = TRUE;
00419 }
00420 dummy_event.setRepeat(TRUE, r);
00421
00422 while (nextOccurance(dummy_event, itDate, due)) {
00423 if (due.date() > to)
00424 break;
00425 Event newEvent = *it;
00426 newEvent.setStart(due);
00427 newEvent.setEnd(due.addSecs((*it).start().secsTo((*it).end())));
00428
00429 tmpList.append(newEvent);
00430 itDate = due.date().addDays(1);
00431 }
00432 }
00433 qHeapSort(tmpList);
00434 return tmpList;
00435 }
00436
00437 QValueList<Event> DateBookDB::getEvents( const QDateTime &start )
00438 {
00439 QValueList<Event> day = getEvents(start.date(),start.date());
00440
00441 QValueListConstIterator<Event> it;
00442 QDateTime dtTmp;
00443 QValueList<Event> tmpList;
00444 for (it = day.begin(); it != day.end(); ++it ) {
00445 dtTmp = (*it).start(TRUE);
00446 if ( dtTmp == start )
00447 tmpList.append( *it );
00448 }
00449 return tmpList;
00450 }
00451
00452
00453
00454 QValueList<EffectiveEvent> DateBookDB::getEffectiveEvents( const QDate &from,
00455 const QDate &to )
00456 {
00457 QValueList<EffectiveEvent> tmpList;
00458 QValueListIterator<Event> it;
00459
00460 EffectiveEvent effEv;
00461 QDateTime dtTmp,
00462 dtEnd;
00463
00464 for (it = eventList.begin(); it != eventList.end(); ++it ) {
00465 if (!(*it).isValidUid())
00466 (*it).assignUid();
00467
00468 dtTmp = (*it).start(TRUE);
00469 dtEnd = (*it).end(TRUE);
00470
00471 if ( dtTmp.date() >= from && dtTmp.date() <= to ) {
00472 Event tmpEv = *it;
00473 effEv.setEvent(tmpEv);
00474 effEv.setDate( dtTmp.date() );
00475 effEv.setStart( dtTmp.time() );
00476 if ( dtTmp.date() != dtEnd.date() )
00477 effEv.setEnd( QTime(23, 59, 0) );
00478 else
00479 effEv.setEnd( dtEnd.time() );
00480 tmpList.append( effEv );
00481 }
00482
00483 if ( dtEnd.date() != dtTmp.date() && dtEnd.date() >= from ) {
00484 QDateTime dt = dtTmp.addDays( 1 );
00485 dt.setTime( QTime(0, 0, 0) );
00486 QDateTime dtStop;
00487 if ( dtEnd > to ) {
00488 dtStop = to;
00489 } else
00490 dtStop = dtEnd;
00491 while ( dt <= dtStop ) {
00492 Event tmpEv = *it;
00493 effEv.setEvent( tmpEv );
00494 effEv.setDate( dt.date() );
00495 if ( dt >= from ) {
00496 effEv.setStart( QTime(0, 0, 0) );
00497 if ( dt.date() == dtEnd.date() )
00498 effEv.setEnd( dtEnd.time() );
00499 else
00500 effEv.setEnd( QTime(23, 59, 59) );
00501 tmpList.append( effEv );
00502 }
00503 dt = dt.addDays( 1 );
00504 }
00505 }
00506 }
00507
00508 QDateTime repeat;
00509 for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) {
00510 if (!(*it).isValidUid())
00511 (*it).assignUid();
00512
00513
00514
00515 Event dummy_event = *it;
00516 int duration = (*it).start().date().daysTo( (*it).end().date() );
00517 QDate itDate = from.addDays(-duration);
00518
00519 Event::RepeatPattern r = dummy_event.repeatPattern();
00520 if ( !r.hasEndDate || r.endDate() > to ) {
00521 r.setEndDate( to );
00522 r.hasEndDate = TRUE;
00523 }
00524 dummy_event.setRepeat(TRUE, r);
00525
00526 while (nextOccurance(dummy_event, itDate, repeat)) {
00527 if(repeat.date() > to)
00528 break;
00529 effEv.setDate( repeat.date() );
00530 if ((*it).type() == Event::AllDay) {
00531 effEv.setStart( QTime(0,0,0) );
00532 effEv.setEnd( QTime(23,59,59) );
00533 } else {
00534
00535
00536
00537
00538 effEv.setStart( (*it).start().time() );
00539 effEv.setEnd( (*it).end().time() );
00540 }
00541 if ( duration != 0 ) {
00542
00543 QDate sub_it = QMAX( repeat.date(), from );
00544 QDate startDate = repeat.date();
00545 QDate endDate = startDate.addDays( duration );
00546
00547 while ( sub_it <= endDate && sub_it <= to ) {
00548 EffectiveEvent tmpEffEv = effEv;
00549 Event tmpEv = *it;
00550 tmpEffEv.setEvent( tmpEv );
00551
00552 if ( sub_it != startDate )
00553 tmpEffEv.setStart( QTime(0,0,0) );
00554 if ( sub_it != endDate )
00555 tmpEffEv.setEnd( QTime(23,59,59) );
00556 tmpEffEv.setDate( sub_it );
00557 tmpEffEv.setEffectiveDates( startDate, endDate );
00558 tmpList.append( tmpEffEv );
00559 sub_it = sub_it.addDays( 1 );
00560 }
00561 itDate = endDate;
00562 } else {
00563 Event tmpEv = *it;
00564 effEv.setEvent( tmpEv );
00565 tmpList.append( effEv );
00566 itDate = repeat.date().addDays( 1 );
00567 }
00568 }
00569 }
00570
00571 qHeapSort( tmpList );
00572 return tmpList;
00573 }
00574
00575 QValueList<EffectiveEvent> DateBookDB::getEffectiveEvents( const QDateTime &dt)
00576 {
00577 QValueList<EffectiveEvent> day = getEffectiveEvents(dt.date(), dt.date());
00578 QValueListConstIterator<EffectiveEvent> it;
00579 QValueList<EffectiveEvent> tmpList;
00580 QDateTime dtTmp;
00581
00582 for (it = day.begin(); it != day.end(); ++it ) {
00583 dtTmp = QDateTime( (*it).date(), (*it).start() );
00584
00585 if ( QABS(dt.secsTo(dtTmp)) < 60 )
00586 tmpList.append( *it );
00587 }
00588 return tmpList;
00589 }
00590
00591 void DateBookDB::addEvent( const Event &ev, bool doalarm )
00592 {
00593
00594 saveJournalEntry( ev, ACTION_ADD, -1, false );
00595 addJFEvent( ev, doalarm );
00596 d->clean = false;
00597 }
00598
00599 void DateBookDB::addJFEvent( const Event &ev, bool doalarm )
00600 {
00601 if ( doalarm && ev.hasAlarm() )
00602 addEventAlarm( ev );
00603 if ( ev.hasRepeat() )
00604 repeatEvents.append( ev );
00605 else
00606 eventList.append( ev );
00607 }
00608
00609 void DateBookDB::editEvent( const Event &old, Event &editedEv )
00610 {
00611 int oldIndex=0;
00612 bool oldHadRepeat = old.hasRepeat();
00613 Event orig;
00614
00615
00616 if ( oldHadRepeat ) {
00617 if ( origRepeat( old, orig ) )
00618 oldIndex = repeatEvents.findIndex( orig );
00619 } else
00620 oldIndex = eventList.findIndex( old );
00621 saveJournalEntry( editedEv, ACTION_REPLACE, oldIndex, oldHadRepeat );
00622
00623
00624 if ( old.hasAlarm() )
00625 delEventAlarm( old );
00626 if ( oldHadRepeat ) {
00627 if ( editedEv.hasRepeat() ) {
00628
00629
00630
00631
00632 repeatEvents.remove( orig );
00633 } else
00634 removeRepeat( old );
00635 } else {
00636 QValueList<Event>::Iterator it = eventList.find( old );
00637 if ( it != eventList.end() )
00638 eventList.remove( it );
00639 }
00640
00641
00642 if ( editedEv.hasAlarm() )
00643 addEventAlarm( editedEv );
00644 if ( editedEv.hasRepeat() )
00645 repeatEvents.append( editedEv );
00646 else
00647 eventList.append( editedEv );
00648
00649 d->clean = false;
00650 }
00651
00652 void DateBookDB::removeEvent( const Event &ev )
00653 {
00654
00655 saveJournalEntry( ev, ACTION_REMOVE, -1, false );
00656 removeJFEvent( ev );
00657 d->clean = false;
00658 }
00659
00660 void DateBookDB::removeJFEvent( const Event&ev )
00661 {
00662 if ( ev.hasAlarm() )
00663 delEventAlarm( ev );
00664 if ( ev.hasRepeat() ) {
00665 removeRepeat( ev );
00666 } else {
00667 QValueList<Event>::Iterator it = eventList.find( ev );
00668 if ( it != eventList.end() )
00669 eventList.remove( it );
00670 }
00671 }
00672
00673
00674 void DateBookDB::loadFile( const QString &strFile )
00675 {
00676
00677 QFile f( strFile );
00678 if ( !f.open( IO_ReadOnly ) )
00679 return;
00680
00681 enum Attribute {
00682 FDescription = 0,
00683 FLocation,
00684 FCategories,
00685 FUid,
00686 FType,
00687 FAlarm,
00688 FSound,
00689 FRType,
00690 FRWeekdays,
00691 FRPosition,
00692 FRFreq,
00693 FRHasEndDate,
00694 FREndDate,
00695 FRStart,
00696 FREnd,
00697 FNote,
00698 FCreated,
00699 FAction,
00700 FActionKey,
00701 FJournalOrigHadRepeat
00702 };
00703
00704 QAsciiDict<int> dict( 97 );
00705 dict.setAutoDelete( TRUE );
00706 dict.insert( "description", new int(FDescription) );
00707 dict.insert( "location", new int(FLocation) );
00708 dict.insert( "categories", new int(FCategories) );
00709 dict.insert( "uid", new int(FUid) );
00710 dict.insert( "type", new int(FType) );
00711 dict.insert( "alarm", new int(FAlarm) );
00712 dict.insert( "sound", new int(FSound) );
00713 dict.insert( "rtype", new int(FRType) );
00714 dict.insert( "rweekdays", new int(FRWeekdays) );
00715 dict.insert( "rposition", new int(FRPosition) );
00716 dict.insert( "rfreq", new int(FRFreq) );
00717 dict.insert( "rhasenddate", new int(FRHasEndDate) );
00718 dict.insert( "enddt", new int(FREndDate) );
00719 dict.insert( "start", new int(FRStart) );
00720 dict.insert( "end", new int(FREnd) );
00721 dict.insert( "note", new int(FNote) );
00722 dict.insert( "created", new int(FCreated) );
00723 dict.insert( "action", new int(FAction) );
00724 dict.insert( "actionkey", new int(FActionKey) );
00725 dict.insert( "actionorig", new int (FJournalOrigHadRepeat) );
00726
00727
00728 QByteArray ba = f.readAll();
00729 char* dt = ba.data();
00730 int len = ba.size();
00731 int currentAction,
00732 journalKey,
00733 origHadRepeat;
00734
00735 int i = 0;
00736 char *point;
00737
00738 while ( (dt+i != 0) && (( point = strstr( dt+i, "<event " ) ) != 0 )) {
00739 i = point - dt;
00740
00741
00742 currentAction = ACTION_ADD;
00743 journalKey = -1;
00744 origHadRepeat = -1;
00745
00746
00747
00748
00749
00750
00751 int alarmTime = -1; Event::SoundTypeChoice alarmSound = Event::Silent;
00752
00753 Event::RepeatPattern rp;
00754 Event e;
00755
00756 i += 7;
00757
00758 while( 1 ) {
00759 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
00760 ++i;
00761 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
00762 break;
00763
00764 int j = i;
00765 while ( j < len && dt[j] != '=' )
00766 ++j;
00767 char *attr = dt+i;
00768 dt[j] = '\0';
00769 i = ++j;
00770 while ( i < len && dt[i] != '"' )
00771 ++i;
00772 j = ++i;
00773 bool haveAmp = FALSE;
00774 bool haveUtf = FALSE;
00775 while ( j < len && dt[j] != '"' ) {
00776 if ( dt[j] == '&' )
00777 haveAmp = TRUE;
00778 if ( ((unsigned char)dt[j]) > 0x7f )
00779 haveUtf = TRUE;
00780 ++j;
00781 }
00782
00783 if ( i == j ) {
00784
00785 i = j + 1;
00786 continue;
00787 }
00788
00789 QString value = haveUtf ? QString::fromUtf8( dt+i, j-i )
00790 : QString::fromLatin1( dt+i, j-i );
00791 if ( haveAmp )
00792 value = Qtopia::plainString( value );
00793 i = j + 1;
00794
00795
00796 int * find = dict[ attr ];
00797 #if 1
00798 if ( !find ) {
00799
00800 e.setCustomField(attr, value);
00801 continue;
00802 }
00803
00804 switch( *find ) {
00805 case FDescription:
00806 e.setDescription( value );
00807 break;
00808 case FLocation:
00809 e.setLocation( value );
00810 break;
00811 case FCategories:
00812 e.setCategories( Qtopia::Record::idsFromString( value ) );
00813 break;
00814 case FUid:
00815 e.setUid( value.toInt() );
00816 break;
00817 case FType:
00818 if ( value == "AllDay" )
00819 e.setType( Event::AllDay );
00820 else
00821 e.setType( Event::Normal );
00822 break;
00823 case FAlarm:
00824 alarmTime = value.toInt();
00825 break;
00826 case FSound:
00827 alarmSound = value == "loud" ? Event::Loud : Event::Silent;
00828 break;
00829
00830 case FRType:
00831 if ( value == "Daily" )
00832 rp.type = Event::Daily;
00833 else if ( value == "Weekly" )
00834 rp.type = Event::Weekly;
00835 else if ( value == "MonthlyDay" )
00836 rp.type = Event::MonthlyDay;
00837 else if ( value == "MonthlyDate" )
00838 rp.type = Event::MonthlyDate;
00839 else if ( value == "Yearly" )
00840 rp.type = Event::Yearly;
00841 else
00842 rp.type = Event::NoRepeat;
00843 break;
00844 case FRWeekdays:
00845
00846
00847 if ( value.toInt() != 0 )
00848 rp.days = value.toInt();
00849 else
00850 rp.days = 1;
00851 break;
00852 case FRPosition:
00853 rp.position = value.toInt();
00854 break;
00855 case FRFreq:
00856 rp.frequency = value.toInt();
00857 break;
00858 case FRHasEndDate:
00859 rp.hasEndDate = value.toInt();
00860 break;
00861 case FREndDate: {
00862 rp.endDateUTC = (time_t) value.toLong();
00863 break;
00864 }
00865 case FRStart: {
00866 e.setStart( (time_t) value.toLong() );
00867 break;
00868 }
00869 case FREnd: {
00870 e.setEnd( (time_t) value.toLong() );
00871 break;
00872 }
00873 case FNote:
00874 e.setNotes( value );
00875 break;
00876 case FCreated:
00877 rp.createTime = value.toInt();
00878 break;
00879 case FAction:
00880 currentAction = value.toInt();
00881 break;
00882 case FActionKey:
00883 journalKey = value.toInt();
00884 break;
00885 case FJournalOrigHadRepeat:
00886 origHadRepeat = value.toInt();
00887 break;
00888 default:
00889 qDebug( "huh??? missing enum? -- attr.: %s", attr );
00890 break;
00891 }
00892 #endif
00893 }
00894
00895
00896
00897
00898 if ( rp.type == Event::Weekly && rp.days == 0 )
00899 rp.days = Event::day( e.start().date().dayOfWeek() );
00900
00901
00902
00903 e.setRepeat( rp.type != Event::NoRepeat, rp );
00904
00905 if ( alarmTime != -1 )
00906 e.setAlarm( TRUE, alarmTime, alarmSound );
00907
00908
00909 switch ( currentAction ) {
00910 case ACTION_ADD:
00911 addJFEvent( e );
00912 break;
00913 case ACTION_REMOVE:
00914 removeJFEvent( e );
00915 break;
00916 case ACTION_REPLACE:
00917
00918
00919 if ( journalKey > -1 && origHadRepeat > -1 ) {
00920
00921 if ( origHadRepeat )
00922 removeJFEvent( *(repeatEvents.at(journalKey)) );
00923 else
00924 removeJFEvent( *(eventList.at(journalKey)) );
00925 addJFEvent( e );
00926 }
00927 break;
00928 default:
00929 break;
00930 }
00931 }
00932 f.close();
00933 }
00934
00935 void DateBookDB::init()
00936 {
00937 d = new DateBookDBPrivate;
00938 d->clean = false;
00939 QString str = dateBookFilename();
00940 if ( str.isNull() ) {
00941 QMessageBox::warning( 0, QObject::tr("Out of Space"),
00942 QObject::tr("Unable to create start up files\n"
00943 "Please free up some space\n"
00944 "before entering data") );
00945 }
00946
00947
00948
00949 loadFile( dateBookFilename() );
00950
00951 if ( QFile::exists( dateBookJournalFile() ) ) {
00952
00953 loadFile( dateBookJournalFile() );
00954
00955 save();
00956 }
00957 d->clean = true;
00958 }
00959
00960 bool DateBookDB::save()
00961 {
00962 if ( d->clean == true )
00963 return true;
00964 QValueListIterator<Event> it;
00965 int total_written;
00966 QString strFileNew = dateBookFilename() + ".new";
00967
00968 QFile f( strFileNew );
00969 if ( !f.open( IO_WriteOnly|IO_Raw ) )
00970 return FALSE;
00971
00972 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
00973 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
00974 buf += "<events>\n";
00975 QCString str = buf.utf8();
00976 total_written = f.writeBlock( str.data(), str.length() );
00977 if ( total_written != int(str.length()) ) {
00978 f.close();
00979 QFile::remove( strFileNew );
00980 return false;
00981 }
00982
00983 for ( it = eventList.begin(); it != eventList.end(); ++it ) {
00984 buf = "<event";
00985 (*it).save( buf );
00986 buf += " />\n";
00987 str = buf.utf8();
00988 total_written = f.writeBlock( str.data(), str.length() );
00989 if ( total_written != int(str.length()) ) {
00990 f.close();
00991 QFile::remove( strFileNew );
00992 return false;
00993 }
00994 }
00995 for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) {
00996 buf = "<event";
00997 (*it).save( buf );
00998 buf += " />\n";
00999 str = buf.utf8();
01000 total_written = f.writeBlock( str.data(), str.length() );
01001 if ( total_written != int(str.length()) ) {
01002 f.close();
01003 QFile::remove( strFileNew );
01004 return false;
01005 }
01006 }
01007 buf = "</events>\n</DATEBOOK>\n";
01008 str = buf.utf8();
01009 total_written = f.writeBlock( str.data(), str.length() );
01010 if ( total_written != int(str.length()) ) {
01011 f.close();
01012 QFile::remove( strFileNew );
01013 return false;
01014 }
01015 f.close();
01016
01017
01018 if ( ::rename( strFileNew, dateBookFilename() ) < 0 ) {
01019 qWarning( "problem renaming file %s to %s errno %d",
01020 strFileNew.latin1(), dateBookFilename().latin1(), errno );
01021
01022 QFile::remove( strFileNew );
01023 }
01024
01025
01026 QFile::remove( dateBookJournalFile() );
01027 d->clean = true;
01028 return true;
01029 }
01030
01031 void DateBookDB::reload()
01032 {
01033 QValueList<Event>::Iterator it = eventList.begin();
01034 for ( ; it != eventList.end(); ++it ) {
01035 if ( (*it).hasAlarm() )
01036 delEventAlarm( *it );
01037 if ( (*it).hasRepeat() )
01038 removeRepeat( *it );
01039 }
01040 eventList.clear();
01041 repeatEvents.clear();
01042 init();
01043 }
01044
01045 bool DateBookDB::removeRepeat( const Event &ev )
01046 {
01047 time_t removeMe = ev.repeatPattern().createTime;
01048 QValueListIterator<Event> it;
01049 for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) {
01050 if ( removeMe == (*it).repeatPattern().createTime ) {
01051 (void)repeatEvents.remove( it );
01052
01053 return TRUE;
01054 }
01055 }
01056 return FALSE;
01057 }
01058
01059 bool DateBookDB::origRepeat( const Event &ev, Event &orig ) const
01060 {
01061 time_t removeMe = ev.repeatPattern().createTime;
01062 QValueListConstIterator<Event> it;
01063 for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) {
01064 if ( removeMe == (*it).repeatPattern().createTime ) {
01065 orig = (*it);
01066 return TRUE;
01067 }
01068 }
01069 return FALSE;
01070 }
01071
01072 void DateBookDB::saveJournalEntry( const Event &ev, journal_action action )
01073 {
01074 saveJournalEntry( ev, action, -1, false );
01075 }
01076
01077 bool DateBookDB::saveJournalEntry( const Event &evOld, journal_action action,
01078 int key, bool origHadRepeat )
01079 {
01080 bool status = false;
01081 Event ev = evOld;
01082
01083 QFile f( dateBookJournalFile() );
01084 if ( !f.open( IO_WriteOnly|IO_Append ) )
01085 return false;
01086 QString buf = "<event";
01087 ev.save( buf );
01088 buf += " action=";
01089 buf += "\"" + QString::number(action) + "\"";
01090 buf += " actionkey=\"" + QString::number(key) + "\"";
01091 buf += " actionorig=\"" + QString::number(origHadRepeat) +"\"";
01092 buf += " />\n";
01093 QString str = buf.utf8();
01094 status = ( f.writeBlock( str.data(), str.length() ) == int(str.length()) );
01095 f.close();
01096 return status;
01097 }
01098
01099 QValueList<Event> DateBookDB::getRawRepeats() const
01100 {
01101 return repeatEvents;
01102 }
01103
01104 QValueList<Event> DateBookDB::getNonRepeatingEvents( const QDate &from,
01105 const QDate &to ) const
01106 {
01107 QValueListConstIterator<Event> it;
01108 QDateTime dtTmp, dtEnd;
01109 QValueList<Event> tmpList;
01110 for (it = eventList.begin(); it != eventList.end(); ++it ) {
01111 dtTmp = (*it).start(TRUE);
01112 dtEnd = (*it).end(TRUE);
01113
01114 if ( dtTmp.date() >= from && dtTmp.date() <= to ) {
01115 Event e = *it;
01116 if ( dtTmp.date() != dtEnd.date() )
01117 e.setEnd( QDateTime(dtTmp.date(), QTime(23, 59, 0)) );
01118 tmpList.append( e );
01119 }
01120
01121 if ( dtEnd.date() != dtTmp.date() && dtEnd.date() >= from ) {
01122 QDateTime dt = dtTmp.addDays( 1 );
01123 dt.setTime( QTime(0, 0, 0) );
01124 QDateTime dtStop;
01125 if ( dtEnd > to ) {
01126 dtStop = to;
01127 } else
01128 dtStop = dtEnd;
01129 while ( dt <= dtStop ) {
01130 Event ev = *it;
01131 if ( dt >= from ) {
01132 ev.setStart( QDateTime(dt.date(), QTime(0, 0, 0)) );
01133 if ( dt.date() == dtEnd.date() )
01134 ev.setEnd( QDateTime(dt.date(), dtEnd.time()) );
01135 else
01136 ev.setEnd( QDateTime(dt.date(), QTime(23, 59, 0)) );
01137 tmpList.append( ev );
01138 }
01139 dt = dt.addDays( 1 );
01140 }
01141 }
01142 }
01143 return tmpList;
01144 }