summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.cpp184
-rw-r--r--libopie/pim/oevent.cpp64
-rw-r--r--libopie/pim/oevent.h10
-rw-r--r--libopie/pim/orecur.cpp66
-rw-r--r--libopie/pim/orecur.h4
-rw-r--r--libopie/pim/test/oevent_test.cpp10
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp184
-rw-r--r--libopie2/opiepim/core/orecur.cpp66
-rw-r--r--libopie2/opiepim/core/orecur.h4
-rw-r--r--libopie2/opiepim/oevent.cpp64
-rw-r--r--libopie2/opiepim/oevent.h10
11 files changed, 631 insertions, 35 deletions
diff --git a/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp
index a4c514b..5239d84 100644
--- a/libopie/pim/odatebookaccessbackend_xml.cpp
+++ b/libopie/pim/odatebookaccessbackend_xml.cpp
@@ -1,95 +1,225 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <stdio.h>
5#include <stdlib.h>
6
4#include <sys/types.h> 7#include <sys/types.h>
5#include <sys/mman.h> 8#include <sys/mman.h>
6#include <sys/stat.h> 9#include <sys/stat.h>
7 10
8#include <unistd.h> 11#include <unistd.h>
9 12
10#include <qasciidict.h> 13#include <qasciidict.h>
11#include <qfile.h> 14#include <qfile.h>
12 15
13#include <qtopia/global.h> 16#include <qtopia/global.h>
14#include <qtopia/stringutil.h> 17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h>
15 19
16#include "opimnotifymanager.h" 20#include "opimnotifymanager.h"
17#include "orecur.h" 21#include "orecur.h"
18#include "otimezone.h" 22#include "otimezone.h"
19#include "odatebookaccessbackend_xml.h" 23#include "odatebookaccessbackend_xml.h"
20 24
21namespace { 25namespace {
22 time_t start, end, created, rp_end; 26 time_t start, end, created, rp_end;
23 ORecur* rec; 27 ORecur* rec;
24 ORecur* recur() { 28 ORecur* recur() {
25 if (!rec) 29 if (!rec)
26 rec = new ORecur; 30 rec = new ORecur;
27 31
28 return rec; 32 return rec;
29 } 33 }
30 int alarmTime; 34 int alarmTime;
31 int snd; 35 int snd;
32 enum Attribute{ 36 enum Attribute{
33 FDescription = 0, 37 FDescription = 0,
34 FLocation, 38 FLocation,
35 FCategories, 39 FCategories,
36 FUid, 40 FUid,
37 FType, 41 FType,
38 FAlarm, 42 FAlarm,
39 FSound, 43 FSound,
40 FRType, 44 FRType,
41 FRWeekdays, 45 FRWeekdays,
42 FRPosition, 46 FRPosition,
43 FRFreq, 47 FRFreq,
44 FRHasEndDate, 48 FRHasEndDate,
45 FREndDate, 49 FREndDate,
46 FRStart, 50 FRStart,
47 FREnd, 51 FREnd,
48 FNote, 52 FNote,
49 FCreated 53 FCreated,
54 FTimeZone,
55 FRecParent,
56 FRecChildren,
57 FExceptions
50 }; 58 };
59 inline void save( const OEvent& ev, QString& buf ) {
60 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
61 if (!ev.location().isEmpty() )
62 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
63
64 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
65 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
66
67 if (ev.isAllDay() )
68 buf += " type=\"AllDay\"";
69
70 if (ev.hasNotifiers() ) {
71 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
72 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
73 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
74 if ( alarm.sound() == OPimAlarm::Loud )
75 buf += "loud";
76 else
77 buf += "silent";
78 buf += "\"";
79 }
80 if ( ev.hasRecurrence() ) {
81 buf += ev.recurrence().toString();
82 }
83
84 /*
85 * fscking timezones :) well, we'll first convert
86 * the QDateTime to a QDateTime in UTC time
87 * and then we'll create a nice time_t
88 */
89 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
90 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
91 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
92 if (!ev.note().isEmpty() ) {
93 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
94 }
95
96 buf += " timezone=\"";
97 if ( ev.timeZone().isEmpty() )
98 buf += "None";
99 else
100 buf += ev.timeZone();
101
102 if (ev.parent() != 0 ) {
103 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
104 }
105
106 if (ev.children().count() != 0 ) {
107 QArray<int> children = ev.children();
108 buf += " recchildren=\"";
109 for ( uint i = 0; i < children.count(); i++ ) {
110 if ( i != 0 ) buf += " ";
111 buf += QString::number( children[i] );
112 }
113 buf+= "\"";
114 }
115
116 // skip custom writing
117 }
118
119 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
120 QMap<int, OEvent>::ConstIterator it;
121 QString buf;
122 QCString str;
123 int total_written;
124 for ( it = list.begin(); it != list.end(); ++it ) {
125 buf = "<event";
126 save( it.data(), buf );
127 buf += " />\n";
128 str = buf.utf8();
129
130 total_written = file.writeBlock(str.data(), str.length() );
131 if ( total_written != int(str.length() ) )
132 return false;
133 }
134 return true;
135 }
51} 136}
52 137
53ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , 138ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
54 const QString& fileName ) 139 const QString& fileName )
55 : ODateBookAccessBackend() { 140 : ODateBookAccessBackend() {
56 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; 141 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
57 m_changed = false; 142 m_changed = false;
58} 143}
59ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { 144ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
60} 145}
61bool ODateBookAccessBackend_XML::load() { 146bool ODateBookAccessBackend_XML::load() {
62 return loadFile(); 147 return loadFile();
63} 148}
64bool ODateBookAccessBackend_XML::reload() { 149bool ODateBookAccessBackend_XML::reload() {
65 clear(); 150 clear();
66 return load(); 151 return load();
67} 152}
68bool ODateBookAccessBackend_XML::save() { 153bool ODateBookAccessBackend_XML::save() {
69 if (!m_changed) return true; 154 qWarning("going to save now");
70 m_changed = false; 155// if (!m_changed) return true;
156
157 int total_written;
158 QString strFileNew = m_name + ".new";
159
160 QFile f( strFileNew );
161 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
162
163 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
164 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
165 buf += "<events>\n";
166 QCString str = buf.utf8();
167 total_written = f.writeBlock( str.data(), str.length() );
168 if ( total_written != int(str.length() ) ) {
169 f.close();
170 QFile::remove( strFileNew );
171 return false;
172 }
71 173
174 if (!forAll( m_raw, f ) ) {
175 f.close();
176 QFile::remove( strFileNew );
177 return false;
178 }
179 if (!forAll( m_rep, f ) ) {
180 f.close();
181 QFile::remove( strFileNew );
182 return false;
183 }
184
185 buf = "</events>\n</DATEBOOK>\n";
186 str = buf.utf8();
187 total_written = f.writeBlock( str.data(), str.length() );
188 if ( total_written != int(str.length() ) ) {
189 f.close();
190 QFile::remove( strFileNew );
191 return false;
192 }
193 f.close();
194
195 exit(0);
196 if ( ::rename( strFileNew, m_name ) < 0 ) {
197 QFile::remove( strFileNew );
198 return false;
199 }
200
201 m_changed = false;
72 return true; 202 return true;
73} 203}
74QArray<int> ODateBookAccessBackend_XML::allRecords()const { 204QArray<int> ODateBookAccessBackend_XML::allRecords()const {
75 QArray<int> ints( m_raw.count()+ m_rep.count() ); 205 QArray<int> ints( m_raw.count()+ m_rep.count() );
76 uint i = 0; 206 uint i = 0;
77 QMap<int, OEvent>::ConstIterator it; 207 QMap<int, OEvent>::ConstIterator it;
78 208
79 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 209 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
80 ints[i] = it.key(); 210 ints[i] = it.key();
81 i++; 211 i++;
82 } 212 }
83 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 213 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
84 ints[i] = it.key(); 214 ints[i] = it.key();
85 i++; 215 i++;
86 } 216 }
87 217
88 return ints; 218 return ints;
89} 219}
90QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { 220QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) {
91 return QArray<int>(); 221 return QArray<int>();
92} 222}
93void ODateBookAccessBackend_XML::clear() { 223void ODateBookAccessBackend_XML::clear() {
94 m_raw.clear(); 224 m_raw.clear();
95 m_rep.clear(); 225 m_rep.clear();
@@ -162,67 +292,71 @@ OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
162 list.append( it.data() ); 292 list.append( it.data() );
163 293
164 return list; 294 return list;
165} 295}
166bool ODateBookAccessBackend_XML::loadFile() { 296bool ODateBookAccessBackend_XML::loadFile() {
167 m_changed = false; 297 m_changed = false;
168 298
169 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); 299 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
170 if ( fd < 0 ) return false; 300 if ( fd < 0 ) return false;
171 301
172 struct stat attribute; 302 struct stat attribute;
173 if ( ::fstat(fd, &attribute ) == -1 ) { 303 if ( ::fstat(fd, &attribute ) == -1 ) {
174 ::close( fd ); 304 ::close( fd );
175 return false; 305 return false;
176 } 306 }
177 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 307 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
178 if ( map_addr == ( (caddr_t)-1) ) { 308 if ( map_addr == ( (caddr_t)-1) ) {
179 ::close( fd ); 309 ::close( fd );
180 return false; 310 return false;
181 } 311 }
182 312
183 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); 313 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
184 ::close( fd ); 314 ::close( fd );
185 315
186 QAsciiDict<int> dict(FCreated+1); 316 QAsciiDict<int> dict(FExceptions+1);
187 dict.setAutoDelete( true ); 317 dict.setAutoDelete( true );
188 dict.insert( "description", new int(FDescription) ); 318 dict.insert( "description", new int(FDescription) );
189 dict.insert( "location", new int(FLocation) ); 319 dict.insert( "location", new int(FLocation) );
190 dict.insert( "categories", new int(FCategories) ); 320 dict.insert( "categories", new int(FCategories) );
191 dict.insert( "uid", new int(FUid) ); 321 dict.insert( "uid", new int(FUid) );
192 dict.insert( "type", new int(FType) ); 322 dict.insert( "type", new int(FType) );
193 dict.insert( "alarm", new int(FAlarm) ); 323 dict.insert( "alarm", new int(FAlarm) );
194 dict.insert( "sound", new int(FSound) ); 324 dict.insert( "sound", new int(FSound) );
195 dict.insert( "rtype", new int(FRType) ); 325 dict.insert( "rtype", new int(FRType) );
196 dict.insert( "rweekdays", new int(FRWeekdays) ); 326 dict.insert( "rweekdays", new int(FRWeekdays) );
197 dict.insert( "rposition", new int(FRPosition) ); 327 dict.insert( "rposition", new int(FRPosition) );
198 dict.insert( "rfreq", new int(FRFreq) ); 328 dict.insert( "rfreq", new int(FRFreq) );
199 dict.insert( "rhasenddate", new int(FRHasEndDate) ); 329 dict.insert( "rhasenddate", new int(FRHasEndDate) );
200 dict.insert( "enddt", new int(FREndDate) ); 330 dict.insert( "enddt", new int(FREndDate) );
201 dict.insert( "start", new int(FRStart) ); 331 dict.insert( "start", new int(FRStart) );
202 dict.insert( "end", new int(FREnd) ); 332 dict.insert( "end", new int(FREnd) );
203 dict.insert( "note", new int(FNote) ); 333 dict.insert( "note", new int(FNote) );
204 dict.insert( "created", new int(FCreated) ); 334 dict.insert( "created", new int(FCreated) );
335 dict.insert( "recparent", new int(FRecParent) );
336 dict.insert( "recchildren", new int(FRecChildren) );
337 dict.insert( "exceptions", new int(FExceptions) );
338 dict.insert( "timezone", new int(FTimeZone) );
205 339
206 char* dt = (char*)map_addr; 340 char* dt = (char*)map_addr;
207 int len = attribute.st_size; 341 int len = attribute.st_size;
208 int i = 0; 342 int i = 0;
209 char* point; 343 char* point;
210 const char* collectionString = "<event "; 344 const char* collectionString = "<event ";
211 int strLen = ::strlen(collectionString); 345 int strLen = ::strlen(collectionString);
212 int *find; 346 int *find;
213 while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) { 347 while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) {
214 i = point -dt; 348 i = point -dt;
215 i+= strLen; 349 i+= strLen;
216 350
217 alarmTime = -1; 351 alarmTime = -1;
218 snd = 0; // silent 352 snd = 0; // silent
219 353
220 OEvent ev; 354 OEvent ev;
221 rec = 0; 355 rec = 0;
222 356
223 while ( TRUE ) { 357 while ( TRUE ) {
224 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 358 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
225 ++i; 359 ++i;
226 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 360 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
227 break; 361 break;
228 362
@@ -268,52 +402,57 @@ bool ODateBookAccessBackend_XML::loadFile() {
268 */ 402 */
269 find = dict[attr.data()]; 403 find = dict[attr.data()];
270 if (!find) 404 if (!find)
271 ev.setCustomField( attr, value ); 405 ev.setCustomField( attr, value );
272 else { 406 else {
273 setField( ev, *find, value ); 407 setField( ev, *find, value );
274 } 408 }
275 } 409 }
276 /* time to finalize */ 410 /* time to finalize */
277 finalizeRecord( ev ); 411 finalizeRecord( ev );
278 add( ev ); 412 add( ev );
279 delete rec; 413 delete rec;
280 } 414 }
281 ::munmap(map_addr, attribute.st_size ); 415 ::munmap(map_addr, attribute.st_size );
282 m_changed = false; // changed during add 416 m_changed = false; // changed during add
283 417
284 return true; 418 return true;
285} 419}
286void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { 420void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
287 /* AllDay is alway in UTC */ 421 /* AllDay is alway in UTC */
288 if ( ev.isAllDay() ) { 422 if ( ev.isAllDay() ) {
289 OTimeZone utc = OTimeZone::utc(); 423 OTimeZone utc = OTimeZone::utc();
290 ev.setStartDateTime( utc.fromUTCDateTime( start ) ); 424 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
291 ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); 425 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
426 ev.setTimeZone( "UTC"); // make sure it is really utc
292 }else { 427 }else {
428 /* to current date time */
293 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 429 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
294 ev.setStartDateTime( zone.toDateTime( start ) ); 430 QDateTime date = zone.toDateTime( start );
295 ev.setEndDateTime ( zone.toDateTime( end ) ); 431 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
432
433 date = zone.toDateTime( end );
434 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
296 } 435 }
297 if ( rec && rec->doesRecur() ) { 436 if ( rec && rec->doesRecur() ) {
298 OTimeZone utc = OTimeZone::utc(); 437 OTimeZone utc = OTimeZone::utc();
299 ORecur recu( *rec ); // call copy c'tor; 438 ORecur recu( *rec ); // call copy c'tor;
300 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); 439 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
301 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); 440 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
302 recu.setStart( ev.startDateTime().date() ); 441 recu.setStart( ev.startDateTime().date() );
303 ev.setRecurrence( recu ); 442 ev.setRecurrence( recu );
304 } 443 }
305 444
306 if (alarmTime != -1 ) { 445 if (alarmTime != -1 ) {
307 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); 446 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
308 OPimAlarm al( snd , dt ); 447 OPimAlarm al( snd , dt );
309 ev.notifiers().add( al ); 448 ev.notifiers().add( al );
310 } 449 }
311 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { 450 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
312 ev.setUid( 1 ); 451 ev.setUid( 1 );
313 } 452 }
314 if ( ev.hasRecurrence() ) 453 if ( ev.hasRecurrence() )
315 m_rep.insert( ev.uid(), ev ); 454 m_rep.insert( ev.uid(), ev );
316 else 455 else
317 m_raw.insert( ev.uid(), ev ); 456 m_raw.insert( ev.uid(), ev );
318 457
319} 458}
@@ -368,28 +507,51 @@ void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& val
368 case FRFreq: 507 case FRFreq:
369 recur()->setFrequency( value.toInt() ); 508 recur()->setFrequency( value.toInt() );
370 break; 509 break;
371 case FRHasEndDate: 510 case FRHasEndDate:
372 recur()->setHasEndDate( value.toInt() ); 511 recur()->setHasEndDate( value.toInt() );
373 break; 512 break;
374 case FREndDate: { 513 case FREndDate: {
375 rp_end = (time_t) value.toLong(); 514 rp_end = (time_t) value.toLong();
376 break; 515 break;
377 } 516 }
378 case FRStart: { 517 case FRStart: {
379 start = (time_t) value.toLong(); 518 start = (time_t) value.toLong();
380 break; 519 break;
381 } 520 }
382 case FREnd: { 521 case FREnd: {
383 end = ( (time_t) value.toLong() ); 522 end = ( (time_t) value.toLong() );
384 break; 523 break;
385 } 524 }
386 case FNote: 525 case FNote:
387 e.setNote( value ); 526 e.setNote( value );
388 break; 527 break;
389 case FCreated: 528 case FCreated:
390 created = value.toInt(); 529 created = value.toInt();
391 break; 530 break;
531 case FRecParent:
532 e.setParent( value.toInt() );
533 break;
534 case FRecChildren:{
535 QStringList list = QStringList::split(' ', value );
536 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
537 e.addChild( (*it).toInt() );
538 }
539 }
540 break;
541 case FExceptions:{
542 QStringList list = QStringList::split(' ', value );
543 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
544 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
545 qWarning("adding exception %s", date.toString().latin1() );
546 recur()->exceptions().append( date );
547 }
548 }
549 break;
550 case FTimeZone:
551 if ( value != "None" )
552 e.setTimeZone( value );
553 break;
392 default: 554 default:
393 break; 555 break;
394 } 556 }
395} 557}
diff --git a/libopie/pim/oevent.cpp b/libopie/pim/oevent.cpp
index ada596c..c3eeee2 100644
--- a/libopie/pim/oevent.cpp
+++ b/libopie/pim/oevent.cpp
@@ -21,119 +21,129 @@ int OCalendarHelper::week( const QDate& date) {
21 21
22 return week; 22 return week;
23} 23}
24int OCalendarHelper::ocurrence( const QDate& date) { 24int OCalendarHelper::ocurrence( const QDate& date) {
25 // calculates the number of occurrances of this day of the 25 // calculates the number of occurrances of this day of the
26 // week till the given date (e.g 3rd Wednesday of the month) 26 // week till the given date (e.g 3rd Wednesday of the month)
27 return ( date.day() - 1 ) / 7 + 1; 27 return ( date.day() - 1 ) / 7 + 1;
28} 28}
29int OCalendarHelper::dayOfWeek( char day ) { 29int OCalendarHelper::dayOfWeek( char day ) {
30 int dayOfWeek = 1; 30 int dayOfWeek = 1;
31 char i = ORecur::MON; 31 char i = ORecur::MON;
32 while ( !( i & day ) && i <= ORecur::SUN ) { 32 while ( !( i & day ) && i <= ORecur::SUN ) {
33 i <<= 1; 33 i <<= 1;
34 ++dayOfWeek; 34 ++dayOfWeek;
35 } 35 }
36 return dayOfWeek; 36 return dayOfWeek;
37} 37}
38int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) { 38int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
39 return ( second.year() - first.year() ) * 12 + 39 return ( second.year() - first.year() ) * 12 +
40 second.month() - first.month(); 40 second.month() - first.month();
41} 41}
42 42
43struct OEvent::Data : public QShared { 43struct OEvent::Data : public QShared {
44 Data() : QShared() { 44 Data() : QShared() {
45 child = 0;
45 recur = 0; 46 recur = 0;
46 manager = 0; 47 manager = 0;
47 isAllDay = false; 48 isAllDay = false;
49 parent = 0;
48 } 50 }
49 ~Data() { 51 ~Data() {
50 delete manager; 52 delete manager;
51 delete recur; 53 delete recur;
52 } 54 }
53 QString description; 55 QString description;
54 QString location; 56 QString location;
55 OPimNotifyManager* manager; 57 OPimNotifyManager* manager;
56 ORecur* recur; 58 ORecur* recur;
57 QString note; 59 QString note;
58 QDateTime created; 60 QDateTime created;
59 QDateTime start; 61 QDateTime start;
60 QDateTime end; 62 QDateTime end;
61 bool isAllDay : 1; 63 bool isAllDay : 1;
62 QString timezone; 64 QString timezone;
65 QArray<int>* child;
66 int parent;
63}; 67};
64 68
65OEvent::OEvent( int uid ) 69OEvent::OEvent( int uid )
66 : OPimRecord( uid ) { 70 : OPimRecord( uid ) {
67 data = new Data; 71 data = new Data;
68} 72}
69OEvent::OEvent( const OEvent& ev) 73OEvent::OEvent( const OEvent& ev)
70 : OPimRecord( ev ), data( ev.data ) 74 : OPimRecord( ev ), data( ev.data )
71{ 75{
72 data->ref(); 76 data->ref();
73} 77}
74OEvent::~OEvent() { 78OEvent::~OEvent() {
75 if ( data->deref() ) { 79 if ( data->deref() ) {
76 delete data; 80 delete data;
77 data = 0; 81 data = 0;
78 } 82 }
79} 83}
80OEvent& OEvent::operator=( const OEvent& ev) { 84OEvent& OEvent::operator=( const OEvent& ev) {
81 if ( *this == ev ) return *this; 85 if ( *this == ev ) return *this;
82 86
83 OPimRecord::operator=( ev ); 87 OPimRecord::operator=( ev );
84 ev.data->ref(); 88 ev.data->ref();
85 deref(); 89 deref();
86 data = ev.data; 90 data = ev.data;
87 91
88 92
89 return *this; 93 return *this;
90} 94}
91QString OEvent::description()const { 95QString OEvent::description()const {
92 return data->description; 96 return data->description;
93} 97}
94void OEvent::setDescription( const QString& description ) { 98void OEvent::setDescription( const QString& description ) {
95 changeOrModify(); 99 changeOrModify();
96 data->description = description; 100 data->description = description;
97} 101}
98void OEvent::setLocation( const QString& loc ) { 102void OEvent::setLocation( const QString& loc ) {
99 changeOrModify(); 103 changeOrModify();
100 data->location = loc; 104 data->location = loc;
101} 105}
102QString OEvent::location()const { 106QString OEvent::location()const {
103 return data->location; 107 return data->location;
104} 108}
105OPimNotifyManager &OEvent::notifiers() { 109OPimNotifyManager &OEvent::notifiers()const {
106 // I hope we can skip the changeOrModify here 110 // I hope we can skip the changeOrModify here
107 // the notifier should take care of it 111 // the notifier should take care of it
108 // and OPimNotify is shared too 112 // and OPimNotify is shared too
109 if (!data->manager ) 113 if (!data->manager )
110 data->manager = new OPimNotifyManager; 114 data->manager = new OPimNotifyManager;
111 115
112 return *data->manager; 116 return *data->manager;
113} 117}
114bool OEvent::hasNotifiers()const { 118bool OEvent::hasNotifiers()const {
115 return ( data->manager); 119 if (!data->manager )
120 return false;
121 if (data->manager->reminders().isEmpty() &&
122 data->manager->alarms().isEmpty() )
123 return false;
124
125 return true;
116} 126}
117ORecur OEvent::recurrence()const { 127ORecur OEvent::recurrence()const {
118 if (!data->recur) 128 if (!data->recur)
119 data->recur = new ORecur; 129 data->recur = new ORecur;
120 130
121 return *data->recur; 131 return *data->recur;
122} 132}
123void OEvent::setRecurrence( const ORecur& rec) { 133void OEvent::setRecurrence( const ORecur& rec) {
124 changeOrModify(); 134 changeOrModify();
125 if (data->recur ) 135 if (data->recur )
126 (*data->recur) = rec; 136 (*data->recur) = rec;
127 else 137 else
128 data->recur = new ORecur( rec ); 138 data->recur = new ORecur( rec );
129} 139}
130bool OEvent::hasRecurrence()const { 140bool OEvent::hasRecurrence()const {
131 if (!data->recur ) return false; 141 if (!data->recur ) return false;
132 return data->recur->doesRecur(); 142 return data->recur->doesRecur();
133} 143}
134QString OEvent::note()const { 144QString OEvent::note()const {
135 return data->note; 145 return data->note;
136} 146}
137void OEvent::setNote( const QString& note ) { 147void OEvent::setNote( const QString& note ) {
138 changeOrModify(); 148 changeOrModify();
139 data->note = note; 149 data->note = note;
@@ -176,109 +186,157 @@ QDateTime OEvent::endDateTimeInZone()const {
176 186
177 OTimeZone zone(data->timezone ); 187 OTimeZone zone(data->timezone );
178 return zone.toDateTime( data->end, OTimeZone::current() ); 188 return zone.toDateTime( data->end, OTimeZone::current() );
179} 189}
180void OEvent::setEndDateTime( const QDateTime& dt ) { 190void OEvent::setEndDateTime( const QDateTime& dt ) {
181 changeOrModify(); 191 changeOrModify();
182 data->end = dt; 192 data->end = dt;
183} 193}
184bool OEvent::isMultipleDay()const { 194bool OEvent::isMultipleDay()const {
185 return data->end.date().day() - data->start.date().day(); 195 return data->end.date().day() - data->start.date().day();
186} 196}
187bool OEvent::isAllDay()const { 197bool OEvent::isAllDay()const {
188 return data->isAllDay; 198 return data->isAllDay;
189} 199}
190void OEvent::setAllDay( bool allDay ) { 200void OEvent::setAllDay( bool allDay ) {
191 changeOrModify(); 201 changeOrModify();
192 data->isAllDay = allDay; 202 data->isAllDay = allDay;
193 if (allDay ) data->timezone = "UTC"; 203 if (allDay ) data->timezone = "UTC";
194} 204}
195void OEvent::setTimeZone( const QString& tz ) { 205void OEvent::setTimeZone( const QString& tz ) {
196 changeOrModify(); 206 changeOrModify();
197 data->timezone = tz; 207 data->timezone = tz;
198} 208}
199QString OEvent::timeZone()const { 209QString OEvent::timeZone()const {
210 if (data->isAllDay ) return QString::fromLatin1("UTC");
200 return data->timezone; 211 return data->timezone;
201} 212}
202bool OEvent::match( const QRegExp& )const { 213bool OEvent::match( const QRegExp& )const {
203 // FIXME 214 // FIXME
204 return false; 215 return false;
205} 216}
206QString OEvent::toRichText()const { 217QString OEvent::toRichText()const {
207 // FIXME 218 // FIXME
208 return "OEvent test"; 219 return "OEvent test";
209} 220}
210QString OEvent::toShortText()const { 221QString OEvent::toShortText()const {
211 return "OEvent shotText"; 222 return "OEvent shotText";
212} 223}
213QString OEvent::type()const { 224QString OEvent::type()const {
214 return QString::fromLatin1("OEvent"); 225 return QString::fromLatin1("OEvent");
215} 226}
216QString OEvent::recordField( int /*id */ )const { 227QString OEvent::recordField( int /*id */ )const {
217 return QString::null; 228 return QString::null;
218} 229}
219int OEvent::rtti() { 230int OEvent::rtti() {
220 return OPimResolver::DateBook; 231 return OPimResolver::DateBook;
221} 232}
222bool OEvent::loadFromStream( QDataStream& ) { 233bool OEvent::loadFromStream( QDataStream& ) {
223 return true; 234 return true;
224} 235}
225bool OEvent::saveToStream( QDataStream& )const { 236bool OEvent::saveToStream( QDataStream& )const {
226 return true; 237 return true;
227} 238}
228void OEvent::changeOrModify() { 239void OEvent::changeOrModify() {
229 if ( data->count != 1 ) { 240 if ( data->count != 1 ) {
230 data->deref(); 241 data->deref();
231 Data* d2 = new Data; 242 Data* d2 = new Data;
232 d2->description = data->description; 243 d2->description = data->description;
233 d2->location = data->location; 244 d2->location = data->location;
234 d2->manager = data->manager; 245 d2->manager = data->manager;
235 d2->recur = data->recur; 246 d2->recur = data->recur;
236 d2->note = data->note; 247 d2->note = data->note;
237 d2->created = data->created; 248 d2->created = data->created;
238 d2->start = data->start; 249 d2->start = data->start;
239 d2->end = data->end; 250 d2->end = data->end;
240 d2->isAllDay = data->isAllDay; 251 d2->isAllDay = data->isAllDay;
241 d2->timezone = data->timezone; 252 d2->timezone = data->timezone;
253 d2->parent = data->parent;
254 d2->child = data->child;
255
256 if (d2->child )
257 d2->child->detach();
242 258
243 data = d2; 259 data = d2;
244 } 260 }
245} 261}
246void OEvent::deref() { 262void OEvent::deref() {
247 if ( data->deref() ) { 263 if ( data->deref() ) {
248 delete data; 264 delete data;
249 data = 0; 265 data = 0;
250 } 266 }
251} 267}
252// FIXME 268// FIXME
253QMap<int, QString> OEvent::toMap()const { 269QMap<int, QString> OEvent::toMap()const {
254 return QMap<int, QString>(); 270 return QMap<int, QString>();
255} 271}
256QMap<QString, QString> OEvent::toExtraMap()const { 272QMap<QString, QString> OEvent::toExtraMap()const {
257 return QMap<QString, QString>(); 273 return QMap<QString, QString>();
258} 274}
275int OEvent::parent()const {
276 return data->parent;
277}
278void OEvent::setParent( int uid ) {
279 changeOrModify();
280 data->parent = uid;
281}
282QArray<int> OEvent::children() const{
283 if (!data->child) return QArray<int>();
284 else
285 return data->child->copy();
286}
287void OEvent::setChildren( const QArray<int>& arr ) {
288 changeOrModify();
289 if (data->child) delete data->child;
259 290
260 291 data->child = new QArray<int>( arr );
292 data->child->detach();
293}
294void OEvent::addChild( int uid ) {
295 changeOrModify();
296 if (!data->child ) {
297 data->child = new QArray<int>(1);
298 (*data->child)[0] = uid;
299 }else{
300 int count = data->child->count();
301 data->child->resize( count + 1 );
302 (*data->child)[count] = uid;
303 }
304}
305void OEvent::removeChild( int uid ) {
306 if (!data->child || !data->child->contains( uid ) ) return;
307 changeOrModify();
308 QArray<int> newAr( data->child->count() - 1 );
309 int j = 0;
310 uint count = data->child->count();
311 for ( uint i = 0; i < count; i++ ) {
312 if ( (*data->child)[i] != uid ) {
313 newAr[j] = (*data->child)[i];
314 j++;
315 }
316 }
317 (*data->child) = newAr;
318}
261struct OEffectiveEvent::Data : public QShared { 319struct OEffectiveEvent::Data : public QShared {
262 Data() : QShared() { 320 Data() : QShared() {
263 } 321 }
264 OEvent event; 322 OEvent event;
265 QDate date; 323 QDate date;
266 QTime start, end; 324 QTime start, end;
267 QDate startDate, endDate; 325 QDate startDate, endDate;
268 bool dates : 1; 326 bool dates : 1;
269}; 327};
270 328
271OEffectiveEvent::OEffectiveEvent() { 329OEffectiveEvent::OEffectiveEvent() {
272 data = new Data; 330 data = new Data;
273 data->date = QDate::currentDate(); 331 data->date = QDate::currentDate();
274 data->start = data->end = QTime::currentTime(); 332 data->start = data->end = QTime::currentTime();
275 data->dates = false; 333 data->dates = false;
276} 334}
277OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, 335OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
278 Position pos ) { 336 Position pos ) {
279 data = new Data; 337 data = new Data;
280 data->event = ev; 338 data->event = ev;
281 data->date = startDate; 339 data->date = startDate;
282 if ( pos & Start ) 340 if ( pos & Start )
283 data->start = ev.startDateTime().time(); 341 data->start = ev.startDateTime().time();
284 else 342 else
diff --git a/libopie/pim/oevent.h b/libopie/pim/oevent.h
index c718e2e..585515c 100644
--- a/libopie/pim/oevent.h
+++ b/libopie/pim/oevent.h
@@ -40,87 +40,95 @@ public:
40 Location, 40 Location,
41 Alarm, 41 Alarm,
42 Reminder, 42 Reminder,
43 Recurrence, 43 Recurrence,
44 Note, 44 Note,
45 Created, 45 Created,
46 StartDate, 46 StartDate,
47 EndDate, 47 EndDate,
48 AllDay, 48 AllDay,
49 TimeZone 49 TimeZone
50 }; 50 };
51 51
52 OEvent(int uid = 0); 52 OEvent(int uid = 0);
53 OEvent( const OEvent& ); 53 OEvent( const OEvent& );
54 ~OEvent(); 54 ~OEvent();
55 OEvent &operator=( const OEvent& ); 55 OEvent &operator=( const OEvent& );
56 56
57 QString description()const; 57 QString description()const;
58 void setDescription( const QString& description ); 58 void setDescription( const QString& description );
59 59
60 QString location()const; 60 QString location()const;
61 void setLocation( const QString& loc ); 61 void setLocation( const QString& loc );
62 62
63 bool hasNotifiers()const; 63 bool hasNotifiers()const;
64 OPimNotifyManager &notifiers(); 64 OPimNotifyManager &notifiers()const;
65 65
66 ORecur recurrence()const; 66 ORecur recurrence()const;
67 void setRecurrence( const ORecur& ); 67 void setRecurrence( const ORecur& );
68 bool hasRecurrence()const; 68 bool hasRecurrence()const;
69 69
70 QString note()const; 70 QString note()const;
71 void setNote( const QString& note ); 71 void setNote( const QString& note );
72 72
73 73
74 QDateTime createdDateTime()const; 74 QDateTime createdDateTime()const;
75 void setCreatedDateTime( const QDateTime& dt); 75 void setCreatedDateTime( const QDateTime& dt);
76 76
77 /** set the date to dt. dt is the QDateTime in localtime */ 77 /** set the date to dt. dt is the QDateTime in localtime */
78 void setStartDateTime( const QDateTime& ); 78 void setStartDateTime( const QDateTime& );
79 /** returns the datetime in the local timeZone */ 79 /** returns the datetime in the local timeZone */
80 QDateTime startDateTime()const; 80 QDateTime startDateTime()const;
81 81
82 /** returns the start datetime in the current zone */ 82 /** returns the start datetime in the current zone */
83 QDateTime startDateTimeInZone()const; 83 QDateTime startDateTimeInZone()const;
84 84
85 /** in current timezone */ 85 /** in current timezone */
86 void setEndDateTime( const QDateTime& ); 86 void setEndDateTime( const QDateTime& );
87 /** in current timezone */ 87 /** in current timezone */
88 QDateTime endDateTime()const; 88 QDateTime endDateTime()const;
89 QDateTime endDateTimeInZone()const; 89 QDateTime endDateTimeInZone()const;
90 90
91 bool isMultipleDay()const; 91 bool isMultipleDay()const;
92 bool isAllDay()const; 92 bool isAllDay()const;
93 void setAllDay( bool isAllDay ); 93 void setAllDay( bool isAllDay );
94 94
95 /* pin this event to a timezone! FIXME */ 95 /* pin this event to a timezone! FIXME */
96 void setTimeZone( const QString& timeZone ); 96 void setTimeZone( const QString& timeZone );
97 QString timeZone()const; 97 QString timeZone()const;
98 98
99 99
100 bool match( const QRegExp& )const; 100 bool match( const QRegExp& )const;
101 101
102 /** For exception to recurrence here is a list of children... */
103 QArray<int> children()const;
104 void setChildren( const QArray<int>& );
105 void addChild( int uid );
106 void removeChild( int uid );
102 107
108 /** return the parent OEvent */
109 int parent()const;
110 void setParent( int uid );
103 111
104 112
105 /* needed reimp */ 113 /* needed reimp */
106 QString toRichText()const; 114 QString toRichText()const;
107 QString toShortText()const; 115 QString toShortText()const;
108 QString type()const; 116 QString type()const;
109 117
110 QMap<int, QString> toMap()const; 118 QMap<int, QString> toMap()const;
111 QMap<QString, QString> toExtraMap()const; 119 QMap<QString, QString> toExtraMap()const;
112 QString recordField(int )const; 120 QString recordField(int )const;
113 121
114 static int rtti(); 122 static int rtti();
115 123
116 bool loadFromStream( QDataStream& ); 124 bool loadFromStream( QDataStream& );
117 bool saveToStream( QDataStream& )const; 125 bool saveToStream( QDataStream& )const;
118 126
119/* bool operator==( const OEvent& ); 127/* bool operator==( const OEvent& );
120 bool operator!=( const OEvent& ); 128 bool operator!=( const OEvent& );
121 bool operator<( const OEvent& ); 129 bool operator<( const OEvent& );
122 bool operator<=( const OEvent& ); 130 bool operator<=( const OEvent& );
123 bool operator>( const OEvent& ); 131 bool operator>( const OEvent& );
124 bool operator>=(const OEvent& ); 132 bool operator>=(const OEvent& );
125*/ 133*/
126private: 134private:
diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp
index e6a4787..e3b45b4 100644
--- a/libopie/pim/orecur.cpp
+++ b/libopie/pim/orecur.cpp
@@ -1,28 +1,31 @@
1#include <time.h>
2
1#include <qshared.h> 3#include <qshared.h>
2 4
3#include <qtopia/timeconversion.h> 5#include <qtopia/timeconversion.h>
4 6
7#include "otimezone.h"
5#include "orecur.h" 8#include "orecur.h"
6 9
7struct ORecur::Data : public QShared { 10struct ORecur::Data : public QShared {
8 Data() : QShared() { 11 Data() : QShared() {
9 type = ORecur::NoRepeat; 12 type = ORecur::NoRepeat;
10 freq = -1; 13 freq = -1;
11 days = 0; 14 days = 0;
12 pos = 0; 15 pos = 0;
13 create = QDateTime::currentDateTime(); 16 create = QDateTime::currentDateTime();
14 hasEnd = FALSE; 17 hasEnd = FALSE;
15 end = QDate::currentDate(); 18 end = QDate::currentDate();
16 } 19 }
17 char days; // Q_UINT8 for 8 seven days;) 20 char days; // Q_UINT8 for 8 seven days;)
18 ORecur::RepeatType type; 21 ORecur::RepeatType type;
19 int freq; 22 int freq;
20 int pos; 23 int pos;
21 bool hasEnd : 1; 24 bool hasEnd : 1;
22 QDate end; 25 QDate end;
23 QDateTime create; 26 QDateTime create;
24 int rep; 27 int rep;
25 QString app; 28 QString app;
26 ExceptionList list; 29 ExceptionList list;
27 QDate start; 30 QDate start;
28}; 31};
@@ -60,63 +63,71 @@ ORecur &ORecur::operator=( const ORecur& re) {
60 63
61 return *this; 64 return *this;
62} 65}
63bool ORecur::doesRecur()const { 66bool ORecur::doesRecur()const {
64 return !( type() == NoRepeat ); 67 return !( type() == NoRepeat );
65} 68}
66/* 69/*
67 * we try to be smart here 70 * we try to be smart here
68 * 71 *
69 */ 72 */
70bool ORecur::doesRecur( const QDate& date ) { 73bool ORecur::doesRecur( const QDate& date ) {
71 /* the day before the recurrance */ 74 /* the day before the recurrance */
72 QDate da = date.addDays(-1); 75 QDate da = date.addDays(-1);
73 76
74 QDate recur; 77 QDate recur;
75 if (!nextOcurrence( da, recur ) ) 78 if (!nextOcurrence( da, recur ) )
76 return false; 79 return false;
77 80
78 return (recur == date); 81 return (recur == date);
79} 82}
80// FIXME unuglify! 83// FIXME unuglify!
81// GPL from Datebookdb.cpp 84// GPL from Datebookdb.cpp
82// FIXME exception list! 85// FIXME exception list!
83bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { 86bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
87 bool stillLooking;
88 stillLooking = p_nextOccurrence( from, next );
89 while ( stillLooking && data->list.contains(next) )
90 stillLooking = p_nextOccurrence( next.addDays(1), next );
91
92 return stillLooking;
93}
94bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
84 95
85 // easy checks, first are we too far in the future or too far in the past? 96 // easy checks, first are we too far in the future or too far in the past?
86 QDate tmpDate; 97 QDate tmpDate;
87 int freq = frequency(); 98 int freq = frequency();
88 int diff, diff2, a; 99 int diff, diff2, a;
89 int iday, imonth, iyear; 100 int iday, imonth, iyear;
90 int dayOfWeek = 0; 101 int dayOfWeek = 0;
91 int firstOfWeek = 0; 102 int firstOfWeek = 0;
92 int weekOfMonth; 103 int weekOfMonth;
93 104
94 105
95 if (hasEndDate() && endDate() < from) 106 if (hasEndDate() && endDate() < from)
96 return FALSE; 107 return FALSE;
97 108
98 if (start() >= from) { 109 if (start() >= from ) {
99 next = start(); 110 next = start();
100 return TRUE; 111 return TRUE;
101 } 112 }
102 113
103 switch ( type() ) { 114 switch ( type() ) {
104 case Weekly: 115 case Weekly:
105 /* weekly is just daily by 7 */ 116 /* weekly is just daily by 7 */
106 /* first convert the repeatPattern.Days() mask to the next 117 /* first convert the repeatPattern.Days() mask to the next
107 day of week valid after from */ 118 day of week valid after from */
108 dayOfWeek = from.dayOfWeek(); 119 dayOfWeek = from.dayOfWeek();
109 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ 120 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
110 121
111 /* this is done in case freq > 1 and from in week not 122 /* this is done in case freq > 1 and from in week not
112 for this round */ 123 for this round */
113 // firstOfWeek = 0; this is already done at decl. 124 // firstOfWeek = 0; this is already done at decl.
114 while(!((1 << firstOfWeek) & days() )) 125 while(!((1 << firstOfWeek) & days() ))
115 firstOfWeek++; 126 firstOfWeek++;
116 127
117 /* there is at least one 'day', or there would be no event */ 128 /* there is at least one 'day', or there would be no event */
118 while(!((1 << (dayOfWeek % 7)) & days() )) 129 while(!((1 << (dayOfWeek % 7)) & days() ))
119 dayOfWeek++; 130 dayOfWeek++;
120 131
121 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
122 dayOfWeek -= start().dayOfWeek() -1; 133 dayOfWeek -= start().dayOfWeek() -1;
@@ -422,25 +433,78 @@ void ORecur::setService( const QString& app ) {
422 data->app = app; 433 data->app = app;
423} 434}
424void ORecur::setStart( const QDate& dt ) { 435void ORecur::setStart( const QDate& dt ) {
425 checkOrModify(); 436 checkOrModify();
426 data->start = dt; 437 data->start = dt;
427} 438}
428void ORecur::checkOrModify() { 439void ORecur::checkOrModify() {
429 if ( data->count != 1 ) { 440 if ( data->count != 1 ) {
430 data->deref(); 441 data->deref();
431 Data* d2 = new Data; 442 Data* d2 = new Data;
432 d2->days = data->days; 443 d2->days = data->days;
433 d2->type = data->type; 444 d2->type = data->type;
434 d2->freq = data->freq; 445 d2->freq = data->freq;
435 d2->pos = data->pos; 446 d2->pos = data->pos;
436 d2->hasEnd = data->hasEnd; 447 d2->hasEnd = data->hasEnd;
437 d2->end = data->end; 448 d2->end = data->end;
438 d2->create = data->create; 449 d2->create = data->create;
439 d2->rep = data->rep; 450 d2->rep = data->rep;
440 d2->app = data->app; 451 d2->app = data->app;
441 d2->list = data->list; 452 d2->list = data->list;
442 d2->start = data->start; 453 d2->start = data->start;
443 data = d2; 454 data = d2;
444 } 455 }
445} 456}
457QString ORecur::toString()const {
458 QString buf;
459
460 buf += " rtype=\"";
461 switch ( data->type ) {
462 case ORecur::Daily:
463 buf += "Daily";
464 break;
465 case ORecur::Weekly:
466 buf += "Weekly";
467 break;
468 case ORecur::MonthlyDay:
469 buf += "MonthlyDay";
470 break;
471 case ORecur::MonthlyDate:
472 buf += "MonthlyDate";
473 break;
474 case ORecur::Yearly:
475 buf += "Yearly";
476 break;
477 default:
478 buf += "NoRepeat";
479 break;
480 }
481 buf += "\"";
482 if (data->days > 0 )
483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\"";
484 if ( data->pos != 0 )
485 buf += " rposition=\"" + QString::number(data->pos ) + "\"";
486
487 buf += " rfreq=\"" + QString::number( data->freq ) + "\"";
488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\"";
489 if ( data->hasEnd )
490 buf += " enddt=\""
491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) )
492 + "\"";
493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\"";
494
495 if ( data->list.isEmpty() ) return buf;
496 // save exceptions list here!!
497 ExceptionList::ConstIterator it;
498 ExceptionList list = data->list;
499 buf += " exceptions=\"";
500 QDate date;
501 for ( it = list.begin(); it != list.end(); ++it ) {
502 date = (*it);
503 if ( it != list.begin() ) buf += " ";
504
505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
506 }
507 buf += "\"";
446 508
509 return buf;
510}
diff --git a/libopie/pim/orecur.h b/libopie/pim/orecur.h
index 1e0014b..b214b3f 100644
--- a/libopie/pim/orecur.h
+++ b/libopie/pim/orecur.h
@@ -52,36 +52,40 @@ public:
52 */ 52 */
53 QString service()const; 53 QString service()const;
54 54
55 /* 55 /*
56 * reference to the exception list 56 * reference to the exception list
57 */ 57 */
58 ExceptionList &exceptions(); 58 ExceptionList &exceptions();
59 59
60 /** 60 /**
61 * the current repetition 61 * the current repetition
62 */ 62 */
63 int repetition()const; 63 int repetition()const;
64 64
65 void setType( const RepeatType& ); 65 void setType( const RepeatType& );
66 void setFrequency( int freq ); 66 void setFrequency( int freq );
67 void setPosition( int pos ); 67 void setPosition( int pos );
68 void setDays( char c); 68 void setDays( char c);
69 void setEndDate( const QDate& dt ); 69 void setEndDate( const QDate& dt );
70 void setStart( const QDate& dt ); 70 void setStart( const QDate& dt );
71 void setCreatedDateTime( const QDateTime& ); 71 void setCreatedDateTime( const QDateTime& );
72 void setHasEndDate( bool b ); 72 void setHasEndDate( bool b );
73 void setRepitition(int ); 73 void setRepitition(int );
74 74
75 void setService( const QString& ser ); 75 void setService( const QString& ser );
76
77 /* almost internal */
78 QString toString()const;
76private: 79private:
80 bool p_nextOccurrence( const QDate& from, QDate& next );
77 void deref(); 81 void deref();
78 inline void checkOrModify(); 82 inline void checkOrModify();
79 83
80 84
81 class Data; 85 class Data;
82 Data* data; 86 Data* data;
83 class ORecurPrivate; 87 class ORecurPrivate;
84 ORecurPrivate *d; 88 ORecurPrivate *d;
85}; 89};
86 90
87#endif 91#endif
diff --git a/libopie/pim/test/oevent_test.cpp b/libopie/pim/test/oevent_test.cpp
index 6f04995..247b83b 100644
--- a/libopie/pim/test/oevent_test.cpp
+++ b/libopie/pim/test/oevent_test.cpp
@@ -1,50 +1,54 @@
1#include <qdatetime.h> 1#include <qdatetime.h>
2 2
3#include "../oevent.h" 3#include "../oevent.h"
4#include "../odatebookaccess.h" 4#include "../odatebookaccess.h"
5 5
6int main(int argc, char* argv ) { 6int main(int argc, char* argv ) {
7 OEvent ev; 7 OEvent ev;
8 ev.setUid( 20 ); 8// ev.setUid( 20 );
9 9
10 ev.setDescription( "Foo" ); 10 ev.setDescription( "Foo Descsfewrf" );
11 11
12 OEvent ev2 = ev; 12 OEvent ev2 = ev;
13 ev2.setDescription("Foo2"); 13 ev2.setDescription("Foo3");
14 qWarning("%s", ev2.description().latin1() ); 14 qWarning("%s", ev2.description().latin1() );
15 qWarning("%s", ev.description().latin1() ); 15 qWarning("%s", ev.description().latin1() );
16 16
17 QDateTime time = QDateTime::currentDateTime(); 17 QDateTime time = QDateTime::currentDateTime();
18 ev2.setStartDateTime( time ); 18 ev2.setStartDateTime( time );
19 ev2.setTimeZone( "Europe/London" ); 19 ev2.setTimeZone( "Europe/London" );
20 20
21 qWarning("%s", ev2.startDateTime().toString().latin1() ); 21 qWarning("%s", ev2.startDateTime().toString().latin1() );
22 qWarning("%s", ev2.startDateTimeInZone().toString().latin1() ); 22 qWarning("%s", ev2.startDateTimeInZone().toString().latin1() );
23 qWarning("%d %d", ev.isAllDay(), ev2.isAllDay() );
23 24
24 ODateBookAccess acc; 25 ODateBookAccess acc;
25 if(!acc.load() ) qWarning("could not load"); 26 if(!acc.load() ) qWarning("could not load");
26 27
27 ODateBookAccess::List::Iterator it; 28 ODateBookAccess::List::Iterator it;
28 ODateBookAccess::List list = acc.allRecords(); 29 ODateBookAccess::List list = acc.allRecords();
29 30
30 for( it = list.begin(); it != list.end(); ++it ){ 31 for( it = list.begin(); it != list.end(); ++it ){
31 OEvent ev = (*it); 32 OEvent ev = (*it);
32 qWarning("Summary: %s",ev.description().latin1() ); 33 qWarning("Summary: %s",ev.description().latin1() );
33 qWarning("Start: %s End: %s",ev.startDateTime().toString().latin1(), ev.endDateTime().toString().latin1() ); 34 qWarning("Start: %s End: %s",ev.startDateTime().toString().latin1(), ev.endDateTime().toString().latin1() );
34 qWarning("All Day: %d",ev.isAllDay() ); 35 qWarning("All Day: %d",ev.isAllDay() );
35 36
36 } 37 }
37 QDate date1(2003,02,01 ); 38 QDate date1(2003,02,01 );
38 QDate date2(2003,03,01 ); 39 QDate date2(2003,03,01 );
39 40
40 OEffectiveEvent::ValueList effList = acc.effectiveEvents( date1,date2 ); 41 OEffectiveEvent::ValueList effList = acc.effectiveEvents( date1,date2 );
41 OEffectiveEvent::ValueList::Iterator effIt; 42 OEffectiveEvent::ValueList::Iterator effIt;
42 43
43 for( effIt = effList.begin(); effIt != effList.end(); ++effIt ){ 44 for( effIt = effList.begin(); effIt != effList.end(); ++effIt ){
44 OEffectiveEvent ef = (*effIt); 45 OEffectiveEvent ef = (*effIt);
45 qWarning("Summary: %s", ef.description().latin1() ); 46 qWarning("Summary: %s", ef.description().latin1() );
46 qWarning("Date: %s", ef.date().toString().latin1() ); 47 qWarning("Date: %s", ef.date().toString().latin1() );
47 } 48 }
49 ev.setUid( 1 );
50 acc.add( ev );
51 acc.save();
48 52
49 return 0; 53 return 0;
50} 54}
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index a4c514b..5239d84 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -1,95 +1,225 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <stdio.h>
5#include <stdlib.h>
6
4#include <sys/types.h> 7#include <sys/types.h>
5#include <sys/mman.h> 8#include <sys/mman.h>
6#include <sys/stat.h> 9#include <sys/stat.h>
7 10
8#include <unistd.h> 11#include <unistd.h>
9 12
10#include <qasciidict.h> 13#include <qasciidict.h>
11#include <qfile.h> 14#include <qfile.h>
12 15
13#include <qtopia/global.h> 16#include <qtopia/global.h>
14#include <qtopia/stringutil.h> 17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h>
15 19
16#include "opimnotifymanager.h" 20#include "opimnotifymanager.h"
17#include "orecur.h" 21#include "orecur.h"
18#include "otimezone.h" 22#include "otimezone.h"
19#include "odatebookaccessbackend_xml.h" 23#include "odatebookaccessbackend_xml.h"
20 24
21namespace { 25namespace {
22 time_t start, end, created, rp_end; 26 time_t start, end, created, rp_end;
23 ORecur* rec; 27 ORecur* rec;
24 ORecur* recur() { 28 ORecur* recur() {
25 if (!rec) 29 if (!rec)
26 rec = new ORecur; 30 rec = new ORecur;
27 31
28 return rec; 32 return rec;
29 } 33 }
30 int alarmTime; 34 int alarmTime;
31 int snd; 35 int snd;
32 enum Attribute{ 36 enum Attribute{
33 FDescription = 0, 37 FDescription = 0,
34 FLocation, 38 FLocation,
35 FCategories, 39 FCategories,
36 FUid, 40 FUid,
37 FType, 41 FType,
38 FAlarm, 42 FAlarm,
39 FSound, 43 FSound,
40 FRType, 44 FRType,
41 FRWeekdays, 45 FRWeekdays,
42 FRPosition, 46 FRPosition,
43 FRFreq, 47 FRFreq,
44 FRHasEndDate, 48 FRHasEndDate,
45 FREndDate, 49 FREndDate,
46 FRStart, 50 FRStart,
47 FREnd, 51 FREnd,
48 FNote, 52 FNote,
49 FCreated 53 FCreated,
54 FTimeZone,
55 FRecParent,
56 FRecChildren,
57 FExceptions
50 }; 58 };
59 inline void save( const OEvent& ev, QString& buf ) {
60 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
61 if (!ev.location().isEmpty() )
62 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
63
64 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
65 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
66
67 if (ev.isAllDay() )
68 buf += " type=\"AllDay\"";
69
70 if (ev.hasNotifiers() ) {
71 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
72 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
73 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
74 if ( alarm.sound() == OPimAlarm::Loud )
75 buf += "loud";
76 else
77 buf += "silent";
78 buf += "\"";
79 }
80 if ( ev.hasRecurrence() ) {
81 buf += ev.recurrence().toString();
82 }
83
84 /*
85 * fscking timezones :) well, we'll first convert
86 * the QDateTime to a QDateTime in UTC time
87 * and then we'll create a nice time_t
88 */
89 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
90 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
91 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
92 if (!ev.note().isEmpty() ) {
93 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
94 }
95
96 buf += " timezone=\"";
97 if ( ev.timeZone().isEmpty() )
98 buf += "None";
99 else
100 buf += ev.timeZone();
101
102 if (ev.parent() != 0 ) {
103 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
104 }
105
106 if (ev.children().count() != 0 ) {
107 QArray<int> children = ev.children();
108 buf += " recchildren=\"";
109 for ( uint i = 0; i < children.count(); i++ ) {
110 if ( i != 0 ) buf += " ";
111 buf += QString::number( children[i] );
112 }
113 buf+= "\"";
114 }
115
116 // skip custom writing
117 }
118
119 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
120 QMap<int, OEvent>::ConstIterator it;
121 QString buf;
122 QCString str;
123 int total_written;
124 for ( it = list.begin(); it != list.end(); ++it ) {
125 buf = "<event";
126 save( it.data(), buf );
127 buf += " />\n";
128 str = buf.utf8();
129
130 total_written = file.writeBlock(str.data(), str.length() );
131 if ( total_written != int(str.length() ) )
132 return false;
133 }
134 return true;
135 }
51} 136}
52 137
53ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , 138ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
54 const QString& fileName ) 139 const QString& fileName )
55 : ODateBookAccessBackend() { 140 : ODateBookAccessBackend() {
56 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; 141 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
57 m_changed = false; 142 m_changed = false;
58} 143}
59ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { 144ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
60} 145}
61bool ODateBookAccessBackend_XML::load() { 146bool ODateBookAccessBackend_XML::load() {
62 return loadFile(); 147 return loadFile();
63} 148}
64bool ODateBookAccessBackend_XML::reload() { 149bool ODateBookAccessBackend_XML::reload() {
65 clear(); 150 clear();
66 return load(); 151 return load();
67} 152}
68bool ODateBookAccessBackend_XML::save() { 153bool ODateBookAccessBackend_XML::save() {
69 if (!m_changed) return true; 154 qWarning("going to save now");
70 m_changed = false; 155// if (!m_changed) return true;
156
157 int total_written;
158 QString strFileNew = m_name + ".new";
159
160 QFile f( strFileNew );
161 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
162
163 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
164 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
165 buf += "<events>\n";
166 QCString str = buf.utf8();
167 total_written = f.writeBlock( str.data(), str.length() );
168 if ( total_written != int(str.length() ) ) {
169 f.close();
170 QFile::remove( strFileNew );
171 return false;
172 }
71 173
174 if (!forAll( m_raw, f ) ) {
175 f.close();
176 QFile::remove( strFileNew );
177 return false;
178 }
179 if (!forAll( m_rep, f ) ) {
180 f.close();
181 QFile::remove( strFileNew );
182 return false;
183 }
184
185 buf = "</events>\n</DATEBOOK>\n";
186 str = buf.utf8();
187 total_written = f.writeBlock( str.data(), str.length() );
188 if ( total_written != int(str.length() ) ) {
189 f.close();
190 QFile::remove( strFileNew );
191 return false;
192 }
193 f.close();
194
195 exit(0);
196 if ( ::rename( strFileNew, m_name ) < 0 ) {
197 QFile::remove( strFileNew );
198 return false;
199 }
200
201 m_changed = false;
72 return true; 202 return true;
73} 203}
74QArray<int> ODateBookAccessBackend_XML::allRecords()const { 204QArray<int> ODateBookAccessBackend_XML::allRecords()const {
75 QArray<int> ints( m_raw.count()+ m_rep.count() ); 205 QArray<int> ints( m_raw.count()+ m_rep.count() );
76 uint i = 0; 206 uint i = 0;
77 QMap<int, OEvent>::ConstIterator it; 207 QMap<int, OEvent>::ConstIterator it;
78 208
79 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 209 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
80 ints[i] = it.key(); 210 ints[i] = it.key();
81 i++; 211 i++;
82 } 212 }
83 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 213 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
84 ints[i] = it.key(); 214 ints[i] = it.key();
85 i++; 215 i++;
86 } 216 }
87 217
88 return ints; 218 return ints;
89} 219}
90QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { 220QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) {
91 return QArray<int>(); 221 return QArray<int>();
92} 222}
93void ODateBookAccessBackend_XML::clear() { 223void ODateBookAccessBackend_XML::clear() {
94 m_raw.clear(); 224 m_raw.clear();
95 m_rep.clear(); 225 m_rep.clear();
@@ -162,67 +292,71 @@ OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
162 list.append( it.data() ); 292 list.append( it.data() );
163 293
164 return list; 294 return list;
165} 295}
166bool ODateBookAccessBackend_XML::loadFile() { 296bool ODateBookAccessBackend_XML::loadFile() {
167 m_changed = false; 297 m_changed = false;
168 298
169 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); 299 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
170 if ( fd < 0 ) return false; 300 if ( fd < 0 ) return false;
171 301
172 struct stat attribute; 302 struct stat attribute;
173 if ( ::fstat(fd, &attribute ) == -1 ) { 303 if ( ::fstat(fd, &attribute ) == -1 ) {
174 ::close( fd ); 304 ::close( fd );
175 return false; 305 return false;
176 } 306 }
177 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 307 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
178 if ( map_addr == ( (caddr_t)-1) ) { 308 if ( map_addr == ( (caddr_t)-1) ) {
179 ::close( fd ); 309 ::close( fd );
180 return false; 310 return false;
181 } 311 }
182 312
183 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); 313 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
184 ::close( fd ); 314 ::close( fd );
185 315
186 QAsciiDict<int> dict(FCreated+1); 316 QAsciiDict<int> dict(FExceptions+1);
187 dict.setAutoDelete( true ); 317 dict.setAutoDelete( true );
188 dict.insert( "description", new int(FDescription) ); 318 dict.insert( "description", new int(FDescription) );
189 dict.insert( "location", new int(FLocation) ); 319 dict.insert( "location", new int(FLocation) );
190 dict.insert( "categories", new int(FCategories) ); 320 dict.insert( "categories", new int(FCategories) );
191 dict.insert( "uid", new int(FUid) ); 321 dict.insert( "uid", new int(FUid) );
192 dict.insert( "type", new int(FType) ); 322 dict.insert( "type", new int(FType) );
193 dict.insert( "alarm", new int(FAlarm) ); 323 dict.insert( "alarm", new int(FAlarm) );
194 dict.insert( "sound", new int(FSound) ); 324 dict.insert( "sound", new int(FSound) );
195 dict.insert( "rtype", new int(FRType) ); 325 dict.insert( "rtype", new int(FRType) );
196 dict.insert( "rweekdays", new int(FRWeekdays) ); 326 dict.insert( "rweekdays", new int(FRWeekdays) );
197 dict.insert( "rposition", new int(FRPosition) ); 327 dict.insert( "rposition", new int(FRPosition) );
198 dict.insert( "rfreq", new int(FRFreq) ); 328 dict.insert( "rfreq", new int(FRFreq) );
199 dict.insert( "rhasenddate", new int(FRHasEndDate) ); 329 dict.insert( "rhasenddate", new int(FRHasEndDate) );
200 dict.insert( "enddt", new int(FREndDate) ); 330 dict.insert( "enddt", new int(FREndDate) );
201 dict.insert( "start", new int(FRStart) ); 331 dict.insert( "start", new int(FRStart) );
202 dict.insert( "end", new int(FREnd) ); 332 dict.insert( "end", new int(FREnd) );
203 dict.insert( "note", new int(FNote) ); 333 dict.insert( "note", new int(FNote) );
204 dict.insert( "created", new int(FCreated) ); 334 dict.insert( "created", new int(FCreated) );
335 dict.insert( "recparent", new int(FRecParent) );
336 dict.insert( "recchildren", new int(FRecChildren) );
337 dict.insert( "exceptions", new int(FExceptions) );
338 dict.insert( "timezone", new int(FTimeZone) );
205 339
206 char* dt = (char*)map_addr; 340 char* dt = (char*)map_addr;
207 int len = attribute.st_size; 341 int len = attribute.st_size;
208 int i = 0; 342 int i = 0;
209 char* point; 343 char* point;
210 const char* collectionString = "<event "; 344 const char* collectionString = "<event ";
211 int strLen = ::strlen(collectionString); 345 int strLen = ::strlen(collectionString);
212 int *find; 346 int *find;
213 while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) { 347 while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) {
214 i = point -dt; 348 i = point -dt;
215 i+= strLen; 349 i+= strLen;
216 350
217 alarmTime = -1; 351 alarmTime = -1;
218 snd = 0; // silent 352 snd = 0; // silent
219 353
220 OEvent ev; 354 OEvent ev;
221 rec = 0; 355 rec = 0;
222 356
223 while ( TRUE ) { 357 while ( TRUE ) {
224 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 358 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
225 ++i; 359 ++i;
226 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 360 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
227 break; 361 break;
228 362
@@ -268,52 +402,57 @@ bool ODateBookAccessBackend_XML::loadFile() {
268 */ 402 */
269 find = dict[attr.data()]; 403 find = dict[attr.data()];
270 if (!find) 404 if (!find)
271 ev.setCustomField( attr, value ); 405 ev.setCustomField( attr, value );
272 else { 406 else {
273 setField( ev, *find, value ); 407 setField( ev, *find, value );
274 } 408 }
275 } 409 }
276 /* time to finalize */ 410 /* time to finalize */
277 finalizeRecord( ev ); 411 finalizeRecord( ev );
278 add( ev ); 412 add( ev );
279 delete rec; 413 delete rec;
280 } 414 }
281 ::munmap(map_addr, attribute.st_size ); 415 ::munmap(map_addr, attribute.st_size );
282 m_changed = false; // changed during add 416 m_changed = false; // changed during add
283 417
284 return true; 418 return true;
285} 419}
286void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { 420void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
287 /* AllDay is alway in UTC */ 421 /* AllDay is alway in UTC */
288 if ( ev.isAllDay() ) { 422 if ( ev.isAllDay() ) {
289 OTimeZone utc = OTimeZone::utc(); 423 OTimeZone utc = OTimeZone::utc();
290 ev.setStartDateTime( utc.fromUTCDateTime( start ) ); 424 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
291 ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); 425 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
426 ev.setTimeZone( "UTC"); // make sure it is really utc
292 }else { 427 }else {
428 /* to current date time */
293 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 429 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
294 ev.setStartDateTime( zone.toDateTime( start ) ); 430 QDateTime date = zone.toDateTime( start );
295 ev.setEndDateTime ( zone.toDateTime( end ) ); 431 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
432
433 date = zone.toDateTime( end );
434 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
296 } 435 }
297 if ( rec && rec->doesRecur() ) { 436 if ( rec && rec->doesRecur() ) {
298 OTimeZone utc = OTimeZone::utc(); 437 OTimeZone utc = OTimeZone::utc();
299 ORecur recu( *rec ); // call copy c'tor; 438 ORecur recu( *rec ); // call copy c'tor;
300 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); 439 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
301 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); 440 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
302 recu.setStart( ev.startDateTime().date() ); 441 recu.setStart( ev.startDateTime().date() );
303 ev.setRecurrence( recu ); 442 ev.setRecurrence( recu );
304 } 443 }
305 444
306 if (alarmTime != -1 ) { 445 if (alarmTime != -1 ) {
307 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); 446 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
308 OPimAlarm al( snd , dt ); 447 OPimAlarm al( snd , dt );
309 ev.notifiers().add( al ); 448 ev.notifiers().add( al );
310 } 449 }
311 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { 450 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
312 ev.setUid( 1 ); 451 ev.setUid( 1 );
313 } 452 }
314 if ( ev.hasRecurrence() ) 453 if ( ev.hasRecurrence() )
315 m_rep.insert( ev.uid(), ev ); 454 m_rep.insert( ev.uid(), ev );
316 else 455 else
317 m_raw.insert( ev.uid(), ev ); 456 m_raw.insert( ev.uid(), ev );
318 457
319} 458}
@@ -368,28 +507,51 @@ void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& val
368 case FRFreq: 507 case FRFreq:
369 recur()->setFrequency( value.toInt() ); 508 recur()->setFrequency( value.toInt() );
370 break; 509 break;
371 case FRHasEndDate: 510 case FRHasEndDate:
372 recur()->setHasEndDate( value.toInt() ); 511 recur()->setHasEndDate( value.toInt() );
373 break; 512 break;
374 case FREndDate: { 513 case FREndDate: {
375 rp_end = (time_t) value.toLong(); 514 rp_end = (time_t) value.toLong();
376 break; 515 break;
377 } 516 }
378 case FRStart: { 517 case FRStart: {
379 start = (time_t) value.toLong(); 518 start = (time_t) value.toLong();
380 break; 519 break;
381 } 520 }
382 case FREnd: { 521 case FREnd: {
383 end = ( (time_t) value.toLong() ); 522 end = ( (time_t) value.toLong() );
384 break; 523 break;
385 } 524 }
386 case FNote: 525 case FNote:
387 e.setNote( value ); 526 e.setNote( value );
388 break; 527 break;
389 case FCreated: 528 case FCreated:
390 created = value.toInt(); 529 created = value.toInt();
391 break; 530 break;
531 case FRecParent:
532 e.setParent( value.toInt() );
533 break;
534 case FRecChildren:{
535 QStringList list = QStringList::split(' ', value );
536 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
537 e.addChild( (*it).toInt() );
538 }
539 }
540 break;
541 case FExceptions:{
542 QStringList list = QStringList::split(' ', value );
543 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
544 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
545 qWarning("adding exception %s", date.toString().latin1() );
546 recur()->exceptions().append( date );
547 }
548 }
549 break;
550 case FTimeZone:
551 if ( value != "None" )
552 e.setTimeZone( value );
553 break;
392 default: 554 default:
393 break; 555 break;
394 } 556 }
395} 557}
diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp
index e6a4787..e3b45b4 100644
--- a/libopie2/opiepim/core/orecur.cpp
+++ b/libopie2/opiepim/core/orecur.cpp
@@ -1,28 +1,31 @@
1#include <time.h>
2
1#include <qshared.h> 3#include <qshared.h>
2 4
3#include <qtopia/timeconversion.h> 5#include <qtopia/timeconversion.h>
4 6
7#include "otimezone.h"
5#include "orecur.h" 8#include "orecur.h"
6 9
7struct ORecur::Data : public QShared { 10struct ORecur::Data : public QShared {
8 Data() : QShared() { 11 Data() : QShared() {
9 type = ORecur::NoRepeat; 12 type = ORecur::NoRepeat;
10 freq = -1; 13 freq = -1;
11 days = 0; 14 days = 0;
12 pos = 0; 15 pos = 0;
13 create = QDateTime::currentDateTime(); 16 create = QDateTime::currentDateTime();
14 hasEnd = FALSE; 17 hasEnd = FALSE;
15 end = QDate::currentDate(); 18 end = QDate::currentDate();
16 } 19 }
17 char days; // Q_UINT8 for 8 seven days;) 20 char days; // Q_UINT8 for 8 seven days;)
18 ORecur::RepeatType type; 21 ORecur::RepeatType type;
19 int freq; 22 int freq;
20 int pos; 23 int pos;
21 bool hasEnd : 1; 24 bool hasEnd : 1;
22 QDate end; 25 QDate end;
23 QDateTime create; 26 QDateTime create;
24 int rep; 27 int rep;
25 QString app; 28 QString app;
26 ExceptionList list; 29 ExceptionList list;
27 QDate start; 30 QDate start;
28}; 31};
@@ -60,63 +63,71 @@ ORecur &ORecur::operator=( const ORecur& re) {
60 63
61 return *this; 64 return *this;
62} 65}
63bool ORecur::doesRecur()const { 66bool ORecur::doesRecur()const {
64 return !( type() == NoRepeat ); 67 return !( type() == NoRepeat );
65} 68}
66/* 69/*
67 * we try to be smart here 70 * we try to be smart here
68 * 71 *
69 */ 72 */
70bool ORecur::doesRecur( const QDate& date ) { 73bool ORecur::doesRecur( const QDate& date ) {
71 /* the day before the recurrance */ 74 /* the day before the recurrance */
72 QDate da = date.addDays(-1); 75 QDate da = date.addDays(-1);
73 76
74 QDate recur; 77 QDate recur;
75 if (!nextOcurrence( da, recur ) ) 78 if (!nextOcurrence( da, recur ) )
76 return false; 79 return false;
77 80
78 return (recur == date); 81 return (recur == date);
79} 82}
80// FIXME unuglify! 83// FIXME unuglify!
81// GPL from Datebookdb.cpp 84// GPL from Datebookdb.cpp
82// FIXME exception list! 85// FIXME exception list!
83bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { 86bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
87 bool stillLooking;
88 stillLooking = p_nextOccurrence( from, next );
89 while ( stillLooking && data->list.contains(next) )
90 stillLooking = p_nextOccurrence( next.addDays(1), next );
91
92 return stillLooking;
93}
94bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
84 95
85 // easy checks, first are we too far in the future or too far in the past? 96 // easy checks, first are we too far in the future or too far in the past?
86 QDate tmpDate; 97 QDate tmpDate;
87 int freq = frequency(); 98 int freq = frequency();
88 int diff, diff2, a; 99 int diff, diff2, a;
89 int iday, imonth, iyear; 100 int iday, imonth, iyear;
90 int dayOfWeek = 0; 101 int dayOfWeek = 0;
91 int firstOfWeek = 0; 102 int firstOfWeek = 0;
92 int weekOfMonth; 103 int weekOfMonth;
93 104
94 105
95 if (hasEndDate() && endDate() < from) 106 if (hasEndDate() && endDate() < from)
96 return FALSE; 107 return FALSE;
97 108
98 if (start() >= from) { 109 if (start() >= from ) {
99 next = start(); 110 next = start();
100 return TRUE; 111 return TRUE;
101 } 112 }
102 113
103 switch ( type() ) { 114 switch ( type() ) {
104 case Weekly: 115 case Weekly:
105 /* weekly is just daily by 7 */ 116 /* weekly is just daily by 7 */
106 /* first convert the repeatPattern.Days() mask to the next 117 /* first convert the repeatPattern.Days() mask to the next
107 day of week valid after from */ 118 day of week valid after from */
108 dayOfWeek = from.dayOfWeek(); 119 dayOfWeek = from.dayOfWeek();
109 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ 120 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
110 121
111 /* this is done in case freq > 1 and from in week not 122 /* this is done in case freq > 1 and from in week not
112 for this round */ 123 for this round */
113 // firstOfWeek = 0; this is already done at decl. 124 // firstOfWeek = 0; this is already done at decl.
114 while(!((1 << firstOfWeek) & days() )) 125 while(!((1 << firstOfWeek) & days() ))
115 firstOfWeek++; 126 firstOfWeek++;
116 127
117 /* there is at least one 'day', or there would be no event */ 128 /* there is at least one 'day', or there would be no event */
118 while(!((1 << (dayOfWeek % 7)) & days() )) 129 while(!((1 << (dayOfWeek % 7)) & days() ))
119 dayOfWeek++; 130 dayOfWeek++;
120 131
121 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
122 dayOfWeek -= start().dayOfWeek() -1; 133 dayOfWeek -= start().dayOfWeek() -1;
@@ -422,25 +433,78 @@ void ORecur::setService( const QString& app ) {
422 data->app = app; 433 data->app = app;
423} 434}
424void ORecur::setStart( const QDate& dt ) { 435void ORecur::setStart( const QDate& dt ) {
425 checkOrModify(); 436 checkOrModify();
426 data->start = dt; 437 data->start = dt;
427} 438}
428void ORecur::checkOrModify() { 439void ORecur::checkOrModify() {
429 if ( data->count != 1 ) { 440 if ( data->count != 1 ) {
430 data->deref(); 441 data->deref();
431 Data* d2 = new Data; 442 Data* d2 = new Data;
432 d2->days = data->days; 443 d2->days = data->days;
433 d2->type = data->type; 444 d2->type = data->type;
434 d2->freq = data->freq; 445 d2->freq = data->freq;
435 d2->pos = data->pos; 446 d2->pos = data->pos;
436 d2->hasEnd = data->hasEnd; 447 d2->hasEnd = data->hasEnd;
437 d2->end = data->end; 448 d2->end = data->end;
438 d2->create = data->create; 449 d2->create = data->create;
439 d2->rep = data->rep; 450 d2->rep = data->rep;
440 d2->app = data->app; 451 d2->app = data->app;
441 d2->list = data->list; 452 d2->list = data->list;
442 d2->start = data->start; 453 d2->start = data->start;
443 data = d2; 454 data = d2;
444 } 455 }
445} 456}
457QString ORecur::toString()const {
458 QString buf;
459
460 buf += " rtype=\"";
461 switch ( data->type ) {
462 case ORecur::Daily:
463 buf += "Daily";
464 break;
465 case ORecur::Weekly:
466 buf += "Weekly";
467 break;
468 case ORecur::MonthlyDay:
469 buf += "MonthlyDay";
470 break;
471 case ORecur::MonthlyDate:
472 buf += "MonthlyDate";
473 break;
474 case ORecur::Yearly:
475 buf += "Yearly";
476 break;
477 default:
478 buf += "NoRepeat";
479 break;
480 }
481 buf += "\"";
482 if (data->days > 0 )
483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\"";
484 if ( data->pos != 0 )
485 buf += " rposition=\"" + QString::number(data->pos ) + "\"";
486
487 buf += " rfreq=\"" + QString::number( data->freq ) + "\"";
488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\"";
489 if ( data->hasEnd )
490 buf += " enddt=\""
491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) )
492 + "\"";
493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\"";
494
495 if ( data->list.isEmpty() ) return buf;
496 // save exceptions list here!!
497 ExceptionList::ConstIterator it;
498 ExceptionList list = data->list;
499 buf += " exceptions=\"";
500 QDate date;
501 for ( it = list.begin(); it != list.end(); ++it ) {
502 date = (*it);
503 if ( it != list.begin() ) buf += " ";
504
505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
506 }
507 buf += "\"";
446 508
509 return buf;
510}
diff --git a/libopie2/opiepim/core/orecur.h b/libopie2/opiepim/core/orecur.h
index 1e0014b..b214b3f 100644
--- a/libopie2/opiepim/core/orecur.h
+++ b/libopie2/opiepim/core/orecur.h
@@ -52,36 +52,40 @@ public:
52 */ 52 */
53 QString service()const; 53 QString service()const;
54 54
55 /* 55 /*
56 * reference to the exception list 56 * reference to the exception list
57 */ 57 */
58 ExceptionList &exceptions(); 58 ExceptionList &exceptions();
59 59
60 /** 60 /**
61 * the current repetition 61 * the current repetition
62 */ 62 */
63 int repetition()const; 63 int repetition()const;
64 64
65 void setType( const RepeatType& ); 65 void setType( const RepeatType& );
66 void setFrequency( int freq ); 66 void setFrequency( int freq );
67 void setPosition( int pos ); 67 void setPosition( int pos );
68 void setDays( char c); 68 void setDays( char c);
69 void setEndDate( const QDate& dt ); 69 void setEndDate( const QDate& dt );
70 void setStart( const QDate& dt ); 70 void setStart( const QDate& dt );
71 void setCreatedDateTime( const QDateTime& ); 71 void setCreatedDateTime( const QDateTime& );
72 void setHasEndDate( bool b ); 72 void setHasEndDate( bool b );
73 void setRepitition(int ); 73 void setRepitition(int );
74 74
75 void setService( const QString& ser ); 75 void setService( const QString& ser );
76
77 /* almost internal */
78 QString toString()const;
76private: 79private:
80 bool p_nextOccurrence( const QDate& from, QDate& next );
77 void deref(); 81 void deref();
78 inline void checkOrModify(); 82 inline void checkOrModify();
79 83
80 84
81 class Data; 85 class Data;
82 Data* data; 86 Data* data;
83 class ORecurPrivate; 87 class ORecurPrivate;
84 ORecurPrivate *d; 88 ORecurPrivate *d;
85}; 89};
86 90
87#endif 91#endif
diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp
index ada596c..c3eeee2 100644
--- a/libopie2/opiepim/oevent.cpp
+++ b/libopie2/opiepim/oevent.cpp
@@ -21,119 +21,129 @@ int OCalendarHelper::week( const QDate& date) {
21 21
22 return week; 22 return week;
23} 23}
24int OCalendarHelper::ocurrence( const QDate& date) { 24int OCalendarHelper::ocurrence( const QDate& date) {
25 // calculates the number of occurrances of this day of the 25 // calculates the number of occurrances of this day of the
26 // week till the given date (e.g 3rd Wednesday of the month) 26 // week till the given date (e.g 3rd Wednesday of the month)
27 return ( date.day() - 1 ) / 7 + 1; 27 return ( date.day() - 1 ) / 7 + 1;
28} 28}
29int OCalendarHelper::dayOfWeek( char day ) { 29int OCalendarHelper::dayOfWeek( char day ) {
30 int dayOfWeek = 1; 30 int dayOfWeek = 1;
31 char i = ORecur::MON; 31 char i = ORecur::MON;
32 while ( !( i & day ) && i <= ORecur::SUN ) { 32 while ( !( i & day ) && i <= ORecur::SUN ) {
33 i <<= 1; 33 i <<= 1;
34 ++dayOfWeek; 34 ++dayOfWeek;
35 } 35 }
36 return dayOfWeek; 36 return dayOfWeek;
37} 37}
38int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) { 38int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
39 return ( second.year() - first.year() ) * 12 + 39 return ( second.year() - first.year() ) * 12 +
40 second.month() - first.month(); 40 second.month() - first.month();
41} 41}
42 42
43struct OEvent::Data : public QShared { 43struct OEvent::Data : public QShared {
44 Data() : QShared() { 44 Data() : QShared() {
45 child = 0;
45 recur = 0; 46 recur = 0;
46 manager = 0; 47 manager = 0;
47 isAllDay = false; 48 isAllDay = false;
49 parent = 0;
48 } 50 }
49 ~Data() { 51 ~Data() {
50 delete manager; 52 delete manager;
51 delete recur; 53 delete recur;
52 } 54 }
53 QString description; 55 QString description;
54 QString location; 56 QString location;
55 OPimNotifyManager* manager; 57 OPimNotifyManager* manager;
56 ORecur* recur; 58 ORecur* recur;
57 QString note; 59 QString note;
58 QDateTime created; 60 QDateTime created;
59 QDateTime start; 61 QDateTime start;
60 QDateTime end; 62 QDateTime end;
61 bool isAllDay : 1; 63 bool isAllDay : 1;
62 QString timezone; 64 QString timezone;
65 QArray<int>* child;
66 int parent;
63}; 67};
64 68
65OEvent::OEvent( int uid ) 69OEvent::OEvent( int uid )
66 : OPimRecord( uid ) { 70 : OPimRecord( uid ) {
67 data = new Data; 71 data = new Data;
68} 72}
69OEvent::OEvent( const OEvent& ev) 73OEvent::OEvent( const OEvent& ev)
70 : OPimRecord( ev ), data( ev.data ) 74 : OPimRecord( ev ), data( ev.data )
71{ 75{
72 data->ref(); 76 data->ref();
73} 77}
74OEvent::~OEvent() { 78OEvent::~OEvent() {
75 if ( data->deref() ) { 79 if ( data->deref() ) {
76 delete data; 80 delete data;
77 data = 0; 81 data = 0;
78 } 82 }
79} 83}
80OEvent& OEvent::operator=( const OEvent& ev) { 84OEvent& OEvent::operator=( const OEvent& ev) {
81 if ( *this == ev ) return *this; 85 if ( *this == ev ) return *this;
82 86
83 OPimRecord::operator=( ev ); 87 OPimRecord::operator=( ev );
84 ev.data->ref(); 88 ev.data->ref();
85 deref(); 89 deref();
86 data = ev.data; 90 data = ev.data;
87 91
88 92
89 return *this; 93 return *this;
90} 94}
91QString OEvent::description()const { 95QString OEvent::description()const {
92 return data->description; 96 return data->description;
93} 97}
94void OEvent::setDescription( const QString& description ) { 98void OEvent::setDescription( const QString& description ) {
95 changeOrModify(); 99 changeOrModify();
96 data->description = description; 100 data->description = description;
97} 101}
98void OEvent::setLocation( const QString& loc ) { 102void OEvent::setLocation( const QString& loc ) {
99 changeOrModify(); 103 changeOrModify();
100 data->location = loc; 104 data->location = loc;
101} 105}
102QString OEvent::location()const { 106QString OEvent::location()const {
103 return data->location; 107 return data->location;
104} 108}
105OPimNotifyManager &OEvent::notifiers() { 109OPimNotifyManager &OEvent::notifiers()const {
106 // I hope we can skip the changeOrModify here 110 // I hope we can skip the changeOrModify here
107 // the notifier should take care of it 111 // the notifier should take care of it
108 // and OPimNotify is shared too 112 // and OPimNotify is shared too
109 if (!data->manager ) 113 if (!data->manager )
110 data->manager = new OPimNotifyManager; 114 data->manager = new OPimNotifyManager;
111 115
112 return *data->manager; 116 return *data->manager;
113} 117}
114bool OEvent::hasNotifiers()const { 118bool OEvent::hasNotifiers()const {
115 return ( data->manager); 119 if (!data->manager )
120 return false;
121 if (data->manager->reminders().isEmpty() &&
122 data->manager->alarms().isEmpty() )
123 return false;
124
125 return true;
116} 126}
117ORecur OEvent::recurrence()const { 127ORecur OEvent::recurrence()const {
118 if (!data->recur) 128 if (!data->recur)
119 data->recur = new ORecur; 129 data->recur = new ORecur;
120 130
121 return *data->recur; 131 return *data->recur;
122} 132}
123void OEvent::setRecurrence( const ORecur& rec) { 133void OEvent::setRecurrence( const ORecur& rec) {
124 changeOrModify(); 134 changeOrModify();
125 if (data->recur ) 135 if (data->recur )
126 (*data->recur) = rec; 136 (*data->recur) = rec;
127 else 137 else
128 data->recur = new ORecur( rec ); 138 data->recur = new ORecur( rec );
129} 139}
130bool OEvent::hasRecurrence()const { 140bool OEvent::hasRecurrence()const {
131 if (!data->recur ) return false; 141 if (!data->recur ) return false;
132 return data->recur->doesRecur(); 142 return data->recur->doesRecur();
133} 143}
134QString OEvent::note()const { 144QString OEvent::note()const {
135 return data->note; 145 return data->note;
136} 146}
137void OEvent::setNote( const QString& note ) { 147void OEvent::setNote( const QString& note ) {
138 changeOrModify(); 148 changeOrModify();
139 data->note = note; 149 data->note = note;
@@ -176,109 +186,157 @@ QDateTime OEvent::endDateTimeInZone()const {
176 186
177 OTimeZone zone(data->timezone ); 187 OTimeZone zone(data->timezone );
178 return zone.toDateTime( data->end, OTimeZone::current() ); 188 return zone.toDateTime( data->end, OTimeZone::current() );
179} 189}
180void OEvent::setEndDateTime( const QDateTime& dt ) { 190void OEvent::setEndDateTime( const QDateTime& dt ) {
181 changeOrModify(); 191 changeOrModify();
182 data->end = dt; 192 data->end = dt;
183} 193}
184bool OEvent::isMultipleDay()const { 194bool OEvent::isMultipleDay()const {
185 return data->end.date().day() - data->start.date().day(); 195 return data->end.date().day() - data->start.date().day();
186} 196}
187bool OEvent::isAllDay()const { 197bool OEvent::isAllDay()const {
188 return data->isAllDay; 198 return data->isAllDay;
189} 199}
190void OEvent::setAllDay( bool allDay ) { 200void OEvent::setAllDay( bool allDay ) {
191 changeOrModify(); 201 changeOrModify();
192 data->isAllDay = allDay; 202 data->isAllDay = allDay;
193 if (allDay ) data->timezone = "UTC"; 203 if (allDay ) data->timezone = "UTC";
194} 204}
195void OEvent::setTimeZone( const QString& tz ) { 205void OEvent::setTimeZone( const QString& tz ) {
196 changeOrModify(); 206 changeOrModify();
197 data->timezone = tz; 207 data->timezone = tz;
198} 208}
199QString OEvent::timeZone()const { 209QString OEvent::timeZone()const {
210 if (data->isAllDay ) return QString::fromLatin1("UTC");
200 return data->timezone; 211 return data->timezone;
201} 212}
202bool OEvent::match( const QRegExp& )const { 213bool OEvent::match( const QRegExp& )const {
203 // FIXME 214 // FIXME
204 return false; 215 return false;
205} 216}
206QString OEvent::toRichText()const { 217QString OEvent::toRichText()const {
207 // FIXME 218 // FIXME
208 return "OEvent test"; 219 return "OEvent test";
209} 220}
210QString OEvent::toShortText()const { 221QString OEvent::toShortText()const {
211 return "OEvent shotText"; 222 return "OEvent shotText";
212} 223}
213QString OEvent::type()const { 224QString OEvent::type()const {
214 return QString::fromLatin1("OEvent"); 225 return QString::fromLatin1("OEvent");
215} 226}
216QString OEvent::recordField( int /*id */ )const { 227QString OEvent::recordField( int /*id */ )const {
217 return QString::null; 228 return QString::null;
218} 229}
219int OEvent::rtti() { 230int OEvent::rtti() {
220 return OPimResolver::DateBook; 231 return OPimResolver::DateBook;
221} 232}
222bool OEvent::loadFromStream( QDataStream& ) { 233bool OEvent::loadFromStream( QDataStream& ) {
223 return true; 234 return true;
224} 235}
225bool OEvent::saveToStream( QDataStream& )const { 236bool OEvent::saveToStream( QDataStream& )const {
226 return true; 237 return true;
227} 238}
228void OEvent::changeOrModify() { 239void OEvent::changeOrModify() {
229 if ( data->count != 1 ) { 240 if ( data->count != 1 ) {
230 data->deref(); 241 data->deref();
231 Data* d2 = new Data; 242 Data* d2 = new Data;
232 d2->description = data->description; 243 d2->description = data->description;
233 d2->location = data->location; 244 d2->location = data->location;
234 d2->manager = data->manager; 245 d2->manager = data->manager;
235 d2->recur = data->recur; 246 d2->recur = data->recur;
236 d2->note = data->note; 247 d2->note = data->note;
237 d2->created = data->created; 248 d2->created = data->created;
238 d2->start = data->start; 249 d2->start = data->start;
239 d2->end = data->end; 250 d2->end = data->end;
240 d2->isAllDay = data->isAllDay; 251 d2->isAllDay = data->isAllDay;
241 d2->timezone = data->timezone; 252 d2->timezone = data->timezone;
253 d2->parent = data->parent;
254 d2->child = data->child;
255
256 if (d2->child )
257 d2->child->detach();
242 258
243 data = d2; 259 data = d2;
244 } 260 }
245} 261}
246void OEvent::deref() { 262void OEvent::deref() {
247 if ( data->deref() ) { 263 if ( data->deref() ) {
248 delete data; 264 delete data;
249 data = 0; 265 data = 0;
250 } 266 }
251} 267}
252// FIXME 268// FIXME
253QMap<int, QString> OEvent::toMap()const { 269QMap<int, QString> OEvent::toMap()const {
254 return QMap<int, QString>(); 270 return QMap<int, QString>();
255} 271}
256QMap<QString, QString> OEvent::toExtraMap()const { 272QMap<QString, QString> OEvent::toExtraMap()const {
257 return QMap<QString, QString>(); 273 return QMap<QString, QString>();
258} 274}
275int OEvent::parent()const {
276 return data->parent;
277}
278void OEvent::setParent( int uid ) {
279 changeOrModify();
280 data->parent = uid;
281}
282QArray<int> OEvent::children() const{
283 if (!data->child) return QArray<int>();
284 else
285 return data->child->copy();
286}
287void OEvent::setChildren( const QArray<int>& arr ) {
288 changeOrModify();
289 if (data->child) delete data->child;
259 290
260 291 data->child = new QArray<int>( arr );
292 data->child->detach();
293}
294void OEvent::addChild( int uid ) {
295 changeOrModify();
296 if (!data->child ) {
297 data->child = new QArray<int>(1);
298 (*data->child)[0] = uid;
299 }else{
300 int count = data->child->count();
301 data->child->resize( count + 1 );
302 (*data->child)[count] = uid;
303 }
304}
305void OEvent::removeChild( int uid ) {
306 if (!data->child || !data->child->contains( uid ) ) return;
307 changeOrModify();
308 QArray<int> newAr( data->child->count() - 1 );
309 int j = 0;
310 uint count = data->child->count();
311 for ( uint i = 0; i < count; i++ ) {
312 if ( (*data->child)[i] != uid ) {
313 newAr[j] = (*data->child)[i];
314 j++;
315 }
316 }
317 (*data->child) = newAr;
318}
261struct OEffectiveEvent::Data : public QShared { 319struct OEffectiveEvent::Data : public QShared {
262 Data() : QShared() { 320 Data() : QShared() {
263 } 321 }
264 OEvent event; 322 OEvent event;
265 QDate date; 323 QDate date;
266 QTime start, end; 324 QTime start, end;
267 QDate startDate, endDate; 325 QDate startDate, endDate;
268 bool dates : 1; 326 bool dates : 1;
269}; 327};
270 328
271OEffectiveEvent::OEffectiveEvent() { 329OEffectiveEvent::OEffectiveEvent() {
272 data = new Data; 330 data = new Data;
273 data->date = QDate::currentDate(); 331 data->date = QDate::currentDate();
274 data->start = data->end = QTime::currentTime(); 332 data->start = data->end = QTime::currentTime();
275 data->dates = false; 333 data->dates = false;
276} 334}
277OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, 335OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
278 Position pos ) { 336 Position pos ) {
279 data = new Data; 337 data = new Data;
280 data->event = ev; 338 data->event = ev;
281 data->date = startDate; 339 data->date = startDate;
282 if ( pos & Start ) 340 if ( pos & Start )
283 data->start = ev.startDateTime().time(); 341 data->start = ev.startDateTime().time();
284 else 342 else
diff --git a/libopie2/opiepim/oevent.h b/libopie2/opiepim/oevent.h
index c718e2e..585515c 100644
--- a/libopie2/opiepim/oevent.h
+++ b/libopie2/opiepim/oevent.h
@@ -40,87 +40,95 @@ public:
40 Location, 40 Location,
41 Alarm, 41 Alarm,
42 Reminder, 42 Reminder,
43 Recurrence, 43 Recurrence,
44 Note, 44 Note,
45 Created, 45 Created,
46 StartDate, 46 StartDate,
47 EndDate, 47 EndDate,
48 AllDay, 48 AllDay,
49 TimeZone 49 TimeZone
50 }; 50 };
51 51
52 OEvent(int uid = 0); 52 OEvent(int uid = 0);
53 OEvent( const OEvent& ); 53 OEvent( const OEvent& );
54 ~OEvent(); 54 ~OEvent();
55 OEvent &operator=( const OEvent& ); 55 OEvent &operator=( const OEvent& );
56 56
57 QString description()const; 57 QString description()const;
58 void setDescription( const QString& description ); 58 void setDescription( const QString& description );
59 59
60 QString location()const; 60 QString location()const;
61 void setLocation( const QString& loc ); 61 void setLocation( const QString& loc );
62 62
63 bool hasNotifiers()const; 63 bool hasNotifiers()const;
64 OPimNotifyManager &notifiers(); 64 OPimNotifyManager &notifiers()const;
65 65
66 ORecur recurrence()const; 66 ORecur recurrence()const;
67 void setRecurrence( const ORecur& ); 67 void setRecurrence( const ORecur& );
68 bool hasRecurrence()const; 68 bool hasRecurrence()const;
69 69
70 QString note()const; 70 QString note()const;
71 void setNote( const QString& note ); 71 void setNote( const QString& note );
72 72
73 73
74 QDateTime createdDateTime()const; 74 QDateTime createdDateTime()const;
75 void setCreatedDateTime( const QDateTime& dt); 75 void setCreatedDateTime( const QDateTime& dt);
76 76
77 /** set the date to dt. dt is the QDateTime in localtime */ 77 /** set the date to dt. dt is the QDateTime in localtime */
78 void setStartDateTime( const QDateTime& ); 78 void setStartDateTime( const QDateTime& );
79 /** returns the datetime in the local timeZone */ 79 /** returns the datetime in the local timeZone */
80 QDateTime startDateTime()const; 80 QDateTime startDateTime()const;
81 81
82 /** returns the start datetime in the current zone */ 82 /** returns the start datetime in the current zone */
83 QDateTime startDateTimeInZone()const; 83 QDateTime startDateTimeInZone()const;
84 84
85 /** in current timezone */ 85 /** in current timezone */
86 void setEndDateTime( const QDateTime& ); 86 void setEndDateTime( const QDateTime& );
87 /** in current timezone */ 87 /** in current timezone */
88 QDateTime endDateTime()const; 88 QDateTime endDateTime()const;
89 QDateTime endDateTimeInZone()const; 89 QDateTime endDateTimeInZone()const;
90 90
91 bool isMultipleDay()const; 91 bool isMultipleDay()const;
92 bool isAllDay()const; 92 bool isAllDay()const;
93 void setAllDay( bool isAllDay ); 93 void setAllDay( bool isAllDay );
94 94
95 /* pin this event to a timezone! FIXME */ 95 /* pin this event to a timezone! FIXME */
96 void setTimeZone( const QString& timeZone ); 96 void setTimeZone( const QString& timeZone );
97 QString timeZone()const; 97 QString timeZone()const;
98 98
99 99
100 bool match( const QRegExp& )const; 100 bool match( const QRegExp& )const;
101 101
102 /** For exception to recurrence here is a list of children... */
103 QArray<int> children()const;
104 void setChildren( const QArray<int>& );
105 void addChild( int uid );
106 void removeChild( int uid );
102 107
108 /** return the parent OEvent */
109 int parent()const;
110 void setParent( int uid );
103 111
104 112
105 /* needed reimp */ 113 /* needed reimp */
106 QString toRichText()const; 114 QString toRichText()const;
107 QString toShortText()const; 115 QString toShortText()const;
108 QString type()const; 116 QString type()const;
109 117
110 QMap<int, QString> toMap()const; 118 QMap<int, QString> toMap()const;
111 QMap<QString, QString> toExtraMap()const; 119 QMap<QString, QString> toExtraMap()const;
112 QString recordField(int )const; 120 QString recordField(int )const;
113 121
114 static int rtti(); 122 static int rtti();
115 123
116 bool loadFromStream( QDataStream& ); 124 bool loadFromStream( QDataStream& );
117 bool saveToStream( QDataStream& )const; 125 bool saveToStream( QDataStream& )const;
118 126
119/* bool operator==( const OEvent& ); 127/* bool operator==( const OEvent& );
120 bool operator!=( const OEvent& ); 128 bool operator!=( const OEvent& );
121 bool operator<( const OEvent& ); 129 bool operator<( const OEvent& );
122 bool operator<=( const OEvent& ); 130 bool operator<=( const OEvent& );
123 bool operator>( const OEvent& ); 131 bool operator>( const OEvent& );
124 bool operator>=(const OEvent& ); 132 bool operator>=(const OEvent& );
125*/ 133*/
126private: 134private: