summaryrefslogtreecommitdiff
authorzecke <zecke>2003-02-22 16:11:16 (UTC)
committer zecke <zecke>2003-02-22 16:11:16 (UTC)
commit397a7b1635488deda02b36df70692e27f59bb3e0 (patch) (unidiff)
tree1232b1b7e8ac84c5d48df79b635ba61acbdf0f62
parente7981098a5c373748d98158e8a6c59750bb0d7dc (diff)
downloadopie-397a7b1635488deda02b36df70692e27f59bb3e0.zip
opie-397a7b1635488deda02b36df70692e27f59bb3e0.tar.gz
opie-397a7b1635488deda02b36df70692e27f59bb3e0.tar.bz2
Implement saving of events
Implement the ExceptionList Add Children and parent to OEvent Make ORecur honor exceptions Extend the test app to add and save
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,395 +1,557 @@
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();
96} 226}
97OEvent ODateBookAccessBackend_XML::find( int uid ) const{ 227OEvent ODateBookAccessBackend_XML::find( int uid ) const{
98 if ( m_raw.contains( uid ) ) 228 if ( m_raw.contains( uid ) )
99 return m_raw[uid]; 229 return m_raw[uid];
100 else 230 else
101 return m_rep[uid]; 231 return m_rep[uid];
102} 232}
103bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { 233bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
104 m_changed = true; 234 m_changed = true;
105 if (ev.hasRecurrence() ) 235 if (ev.hasRecurrence() )
106 m_rep.insert( ev.uid(), ev ); 236 m_rep.insert( ev.uid(), ev );
107 else 237 else
108 m_raw.insert( ev.uid(), ev ); 238 m_raw.insert( ev.uid(), ev );
109 239
110 return true; 240 return true;
111} 241}
112bool ODateBookAccessBackend_XML::remove( int uid ) { 242bool ODateBookAccessBackend_XML::remove( int uid ) {
113 m_changed = true; 243 m_changed = true;
114 m_rep.remove( uid ); 244 m_rep.remove( uid );
115 m_rep.remove( uid ); 245 m_rep.remove( uid );
116 246
117 return true; 247 return true;
118} 248}
119bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { 249bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
120 replace( ev.uid() ); 250 replace( ev.uid() );
121 return add( ev ); 251 return add( ev );
122} 252}
123QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 253QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
124 return allRecords(); 254 return allRecords();
125} 255}
126QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 256QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
127 QArray<int> ints( m_rep.count() ); 257 QArray<int> ints( m_rep.count() );
128 uint i = 0; 258 uint i = 0;
129 QMap<int, OEvent>::ConstIterator it; 259 QMap<int, OEvent>::ConstIterator it;
130 260
131 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 261 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
132 ints[i] = it.key(); 262 ints[i] = it.key();
133 i++; 263 i++;
134 } 264 }
135 265
136 return ints; 266 return ints;
137} 267}
138QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 268QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
139 QArray<int> ints( m_raw.count() ); 269 QArray<int> ints( m_raw.count() );
140 uint i = 0; 270 uint i = 0;
141 QMap<int, OEvent>::ConstIterator it; 271 QMap<int, OEvent>::ConstIterator it;
142 272
143 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 273 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
144 ints[i] = it.key(); 274 ints[i] = it.key();
145 i++; 275 i++;
146 } 276 }
147 277
148 return ints; 278 return ints;
149} 279}
150OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { 280OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
151 OEvent::ValueList list; 281 OEvent::ValueList list;
152 QMap<int, OEvent>::ConstIterator it; 282 QMap<int, OEvent>::ConstIterator it;
153 for (it = m_raw.begin(); it != m_raw.end(); ++it ) 283 for (it = m_raw.begin(); it != m_raw.end(); ++it )
154 list.append( it.data() ); 284 list.append( it.data() );
155 285
156 return list; 286 return list;
157} 287}
158OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { 288OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
159 OEvent::ValueList list; 289 OEvent::ValueList list;
160 QMap<int, OEvent>::ConstIterator it; 290 QMap<int, OEvent>::ConstIterator it;
161 for (it = m_rep.begin(); it != m_rep.end(); ++it ) 291 for (it = m_rep.begin(); it != m_rep.end(); ++it )
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
229 363
230 // we have another attribute, read it. 364 // we have another attribute, read it.
231 int j = i; 365 int j = i;
232 while ( j < len && dt[j] != '=' ) 366 while ( j < len && dt[j] != '=' )
233 ++j; 367 ++j;
234 QCString attr( dt+i, j-i+1); 368 QCString attr( dt+i, j-i+1);
235 369
236 i = ++j; // skip = 370 i = ++j; // skip =
237 371
238 // find the start of quotes 372 // find the start of quotes
239 while ( i < len && dt[i] != '"' ) 373 while ( i < len && dt[i] != '"' )
240 ++i; 374 ++i;
241 j = ++i; 375 j = ++i;
242 376
243 bool haveUtf = FALSE; 377 bool haveUtf = FALSE;
244 bool haveEnt = FALSE; 378 bool haveEnt = FALSE;
245 while ( j < len && dt[j] != '"' ) { 379 while ( j < len && dt[j] != '"' ) {
246 if ( ((unsigned char)dt[j]) > 0x7f ) 380 if ( ((unsigned char)dt[j]) > 0x7f )
247 haveUtf = TRUE; 381 haveUtf = TRUE;
248 if ( dt[j] == '&' ) 382 if ( dt[j] == '&' )
249 haveEnt = TRUE; 383 haveEnt = TRUE;
250 ++j; 384 ++j;
251 } 385 }
252 if ( i == j ) { 386 if ( i == j ) {
253 // empty value 387 // empty value
254 i = j + 1; 388 i = j + 1;
255 continue; 389 continue;
256 } 390 }
257 391
258 QCString value( dt+i, j-i+1 ); 392 QCString value( dt+i, j-i+1 );
259 i = j + 1; 393 i = j + 1;
260 394
261 QString str = (haveUtf ? QString::fromUtf8( value ) 395 QString str = (haveUtf ? QString::fromUtf8( value )
262 : QString::fromLatin1( value ) ); 396 : QString::fromLatin1( value ) );
263 if ( haveEnt ) 397 if ( haveEnt )
264 str = Qtopia::plainString( str ); 398 str = Qtopia::plainString( str );
265 399
266 /* 400 /*
267 * add key + value 401 * add key + value
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}
320void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { 459void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
321// qWarning(" setting %s", value.latin1() ); 460// qWarning(" setting %s", value.latin1() );
322 switch( id ) { 461 switch( id ) {
323 case FDescription: 462 case FDescription:
324 e.setDescription( value ); 463 e.setDescription( value );
325 break; 464 break;
326 case FLocation: 465 case FLocation:
327 e.setLocation( value ); 466 e.setLocation( value );
328 break; 467 break;
329 case FCategories: 468 case FCategories:
330 e.setCategories( e.idsFromString( value ) ); 469 e.setCategories( e.idsFromString( value ) );
331 break; 470 break;
332 case FUid: 471 case FUid:
333 e.setUid( value.toInt() ); 472 e.setUid( value.toInt() );
334 break; 473 break;
335 case FType: 474 case FType:
336 if ( value == "AllDay" ) { 475 if ( value == "AllDay" ) {
337 e.setAllDay( true ); 476 e.setAllDay( true );
338 e.setTimeZone( "UTC" ); 477 e.setTimeZone( "UTC" );
339 } 478 }
340 break; 479 break;
341 case FAlarm: 480 case FAlarm:
342 alarmTime = value.toInt(); 481 alarmTime = value.toInt();
343 break; 482 break;
344 case FSound: 483 case FSound:
345 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; 484 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
346 break; 485 break;
347 // recurrence stuff 486 // recurrence stuff
348 case FRType: 487 case FRType:
349 if ( value == "Daily" ) 488 if ( value == "Daily" )
350 recur()->setType( ORecur::Daily ); 489 recur()->setType( ORecur::Daily );
351 else if ( value == "Weekly" ) 490 else if ( value == "Weekly" )
352 recur()->setType( ORecur::Weekly); 491 recur()->setType( ORecur::Weekly);
353 else if ( value == "MonthlyDay" ) 492 else if ( value == "MonthlyDay" )
354 recur()->setType( ORecur::MonthlyDay ); 493 recur()->setType( ORecur::MonthlyDay );
355 else if ( value == "MonthlyDate" ) 494 else if ( value == "MonthlyDate" )
356 recur()->setType( ORecur::MonthlyDate ); 495 recur()->setType( ORecur::MonthlyDate );
357 else if ( value == "Yearly" ) 496 else if ( value == "Yearly" )
358 recur()->setType( ORecur::Yearly ); 497 recur()->setType( ORecur::Yearly );
359 else 498 else
360 recur()->setType( ORecur::NoRepeat ); 499 recur()->setType( ORecur::NoRepeat );
361 break; 500 break;
362 case FRWeekdays: 501 case FRWeekdays:
363 recur()->setDays( value.toInt() ); 502 recur()->setDays( value.toInt() );
364 break; 503 break;
365 case FRPosition: 504 case FRPosition:
366 recur()->setPosition( value.toInt() ); 505 recur()->setPosition( value.toInt() );
367 break; 506 break;
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
@@ -1,431 +1,489 @@
1#include <qshared.h> 1#include <qshared.h>
2 2
3#include <qpe/palmtopuidgen.h> 3#include <qpe/palmtopuidgen.h>
4#include <qpe/categories.h> 4#include <qpe/categories.h>
5 5
6#include "orecur.h" 6#include "orecur.h"
7#include "opimresolver.h" 7#include "opimresolver.h"
8#include "opimnotifymanager.h" 8#include "opimnotifymanager.h"
9 9
10#include "oevent.h" 10#include "oevent.h"
11 11
12int OCalendarHelper::week( const QDate& date) { 12int OCalendarHelper::week( const QDate& date) {
13 // Calculates the week this date is in within that 13 // Calculates the week this date is in within that
14 // month. Equals the "row" is is in in the month view 14 // month. Equals the "row" is is in in the month view
15 int week = 1; 15 int week = 1;
16 QDate tmp( date.year(), date.month(), 1 ); 16 QDate tmp( date.year(), date.month(), 1 );
17 if ( date.dayOfWeek() < tmp.dayOfWeek() ) 17 if ( date.dayOfWeek() < tmp.dayOfWeek() )
18 ++week; 18 ++week;
19 19
20 week += ( date.day() - 1 ) / 7; 20 week += ( date.day() - 1 ) / 7;
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;
140} 150}
141QDateTime OEvent::createdDateTime()const { 151QDateTime OEvent::createdDateTime()const {
142 return data->created; 152 return data->created;
143} 153}
144void OEvent::setCreatedDateTime( const QDateTime& time ) { 154void OEvent::setCreatedDateTime( const QDateTime& time ) {
145 changeOrModify(); 155 changeOrModify();
146 data->created = time; 156 data->created = time;
147} 157}
148QDateTime OEvent::startDateTime()const { 158QDateTime OEvent::startDateTime()const {
149 if ( data->isAllDay ) 159 if ( data->isAllDay )
150 return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); 160 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
151 return data->start; 161 return data->start;
152} 162}
153QDateTime OEvent::startDateTimeInZone()const { 163QDateTime OEvent::startDateTimeInZone()const {
154 /* if no timezone, or all day event or if the current and this timeZone match... */ 164 /* if no timezone, or all day event or if the current and this timeZone match... */
155 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); 165 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
156 166
157 OTimeZone zone(data->timezone ); 167 OTimeZone zone(data->timezone );
158 return zone.toDateTime( data->start, OTimeZone::current() ); 168 return zone.toDateTime( data->start, OTimeZone::current() );
159} 169}
160void OEvent::setStartDateTime( const QDateTime& dt ) { 170void OEvent::setStartDateTime( const QDateTime& dt ) {
161 changeOrModify(); 171 changeOrModify();
162 data->start = dt; 172 data->start = dt;
163} 173}
164QDateTime OEvent::endDateTime()const { 174QDateTime OEvent::endDateTime()const {
165 /* 175 /*
166 * if all Day event the end time needs 176 * if all Day event the end time needs
167 * to be on the same day as the start 177 * to be on the same day as the start
168 */ 178 */
169 if ( data->isAllDay ) 179 if ( data->isAllDay )
170 return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); 180 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
171 return data->end; 181 return data->end;
172} 182}
173QDateTime OEvent::endDateTimeInZone()const { 183QDateTime OEvent::endDateTimeInZone()const {
174 /* if no timezone, or all day event or if the current and this timeZone match... */ 184 /* if no timezone, or all day event or if the current and this timeZone match... */
175 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); 185 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
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
285 data->start = QTime( 0, 0, 0 ); 343 data->start = QTime( 0, 0, 0 );
286 344
287 if ( pos & End ) 345 if ( pos & End )
288 data->end = ev.endDateTime().time(); 346 data->end = ev.endDateTime().time();
289 else 347 else
290 data->end = QTime( 23, 59, 59 ); 348 data->end = QTime( 23, 59, 59 );
291 349
292 data->dates = false; 350 data->dates = false;
293} 351}
294OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { 352OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
295 data = ev.data; 353 data = ev.data;
296 data->ref(); 354 data->ref();
297} 355}
298OEffectiveEvent::~OEffectiveEvent() { 356OEffectiveEvent::~OEffectiveEvent() {
299 if ( data->deref() ) { 357 if ( data->deref() ) {
300 delete data; 358 delete data;
301 data = 0; 359 data = 0;
302 } 360 }
303} 361}
304OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { 362OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
305 if ( *this == ev ) return *this; 363 if ( *this == ev ) return *this;
306 364
307 ev.data->ref(); 365 ev.data->ref();
308 deref(); 366 deref();
309 data = ev.data; 367 data = ev.data;
310 368
311 return *this; 369 return *this;
312} 370}
313 371
314void OEffectiveEvent::setStartTime( const QTime& ti) { 372void OEffectiveEvent::setStartTime( const QTime& ti) {
315 changeOrModify(); 373 changeOrModify();
316 data->start = ti; 374 data->start = ti;
317} 375}
318void OEffectiveEvent::setEndTime( const QTime& en) { 376void OEffectiveEvent::setEndTime( const QTime& en) {
319 changeOrModify(); 377 changeOrModify();
320 data->end = en; 378 data->end = en;
321} 379}
322void OEffectiveEvent::setEvent( const OEvent& ev) { 380void OEffectiveEvent::setEvent( const OEvent& ev) {
323 changeOrModify(); 381 changeOrModify();
324 data->event = ev; 382 data->event = ev;
325} 383}
326void OEffectiveEvent::setDate( const QDate& da) { 384void OEffectiveEvent::setDate( const QDate& da) {
327 changeOrModify(); 385 changeOrModify();
328 data->date = da; 386 data->date = da;
329} 387}
330void OEffectiveEvent::setEffectiveDates( const QDate& from, 388void OEffectiveEvent::setEffectiveDates( const QDate& from,
331 const QDate& to ) { 389 const QDate& to ) {
332 if (!from.isValid() ) { 390 if (!from.isValid() ) {
333 data->dates = false; 391 data->dates = false;
334 return; 392 return;
335 } 393 }
336 394
337 data->startDate = from; 395 data->startDate = from;
338 data->endDate = to; 396 data->endDate = to;
339} 397}
340QString OEffectiveEvent::description()const { 398QString OEffectiveEvent::description()const {
341 return data->event.description(); 399 return data->event.description();
342} 400}
343QString OEffectiveEvent::location()const { 401QString OEffectiveEvent::location()const {
344 return data->event.location(); 402 return data->event.location();
345} 403}
346QString OEffectiveEvent::note()const { 404QString OEffectiveEvent::note()const {
347 return data->event.note(); 405 return data->event.note();
348} 406}
349OEvent OEffectiveEvent::event()const { 407OEvent OEffectiveEvent::event()const {
350 return data->event; 408 return data->event;
351} 409}
352QTime OEffectiveEvent::startTime()const { 410QTime OEffectiveEvent::startTime()const {
353 return data->start; 411 return data->start;
354} 412}
355QTime OEffectiveEvent::endTime()const { 413QTime OEffectiveEvent::endTime()const {
356 return data->end; 414 return data->end;
357} 415}
358QDate OEffectiveEvent::date()const { 416QDate OEffectiveEvent::date()const {
359 return data->date; 417 return data->date;
360} 418}
361int OEffectiveEvent::length()const { 419int OEffectiveEvent::length()const {
362 return (data->end.hour() * 60 - data->start.hour() * 60) 420 return (data->end.hour() * 60 - data->start.hour() * 60)
363 + QABS(data->start.minute() - data->end.minute() ); 421 + QABS(data->start.minute() - data->end.minute() );
364} 422}
365int OEffectiveEvent::size()const { 423int OEffectiveEvent::size()const {
366 return ( data->end.hour() - data->start.hour() ) * 3600 424 return ( data->end.hour() - data->start.hour() ) * 3600
367 + (data->end.minute() - data->start.minute() * 60 425 + (data->end.minute() - data->start.minute() * 60
368 + data->end.second() - data->start.second() ); 426 + data->end.second() - data->start.second() );
369} 427}
370QDate OEffectiveEvent::startDate()const { 428QDate OEffectiveEvent::startDate()const {
371 if ( data->dates ) 429 if ( data->dates )
372 return data->startDate; 430 return data->startDate;
373 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer 431 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
374 return data->date; 432 return data->date;
375 else 433 else
376 return data->event.startDateTime().date(); 434 return data->event.startDateTime().date();
377} 435}
378QDate OEffectiveEvent::endDate()const { 436QDate OEffectiveEvent::endDate()const {
379 if ( data->dates ) 437 if ( data->dates )
380 return data->endDate; 438 return data->endDate;
381 else if ( data->event.hasRecurrence() ) 439 else if ( data->event.hasRecurrence() )
382 return data->date; 440 return data->date;
383 else 441 else
384 return data->event.endDateTime().date(); 442 return data->event.endDateTime().date();
385} 443}
386void OEffectiveEvent::deref() { 444void OEffectiveEvent::deref() {
387 if ( data->deref() ) { 445 if ( data->deref() ) {
388 delete data; 446 delete data;
389 data = 0; 447 data = 0;
390 } 448 }
391} 449}
392void OEffectiveEvent::changeOrModify() { 450void OEffectiveEvent::changeOrModify() {
393 if ( data->count != 1 ) { 451 if ( data->count != 1 ) {
394 data->deref(); 452 data->deref();
395 Data* d2 = new Data; 453 Data* d2 = new Data;
396 d2->event = data->event; 454 d2->event = data->event;
397 d2->date = data->date; 455 d2->date = data->date;
398 d2->start = data->start; 456 d2->start = data->start;
399 d2->end = data->end; 457 d2->end = data->end;
400 d2->startDate = data->startDate; 458 d2->startDate = data->startDate;
401 d2->endDate = data->endDate; 459 d2->endDate = data->endDate;
402 d2->dates = data->dates; 460 d2->dates = data->dates;
403 data = d2; 461 data = d2;
404 } 462 }
405} 463}
406bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{ 464bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
407 if ( data->date < e.date() ) 465 if ( data->date < e.date() )
408 return TRUE; 466 return TRUE;
409 if ( data->date == e.date() ) 467 if ( data->date == e.date() )
410 return ( startTime() < e.startTime() ); 468 return ( startTime() < e.startTime() );
411 else 469 else
412 return FALSE; 470 return FALSE;
413} 471}
414bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ 472bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
415 return (data->date <= e.date() ); 473 return (data->date <= e.date() );
416} 474}
417bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { 475bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
418 return ( date() == e.date() 476 return ( date() == e.date()
419 && startTime() == e.startTime() 477 && startTime() == e.startTime()
420 && endTime()== e.endTime() 478 && endTime()== e.endTime()
421 && event() == e.event() ); 479 && event() == e.event() );
422} 480}
423bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { 481bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
424 return !(*this == e ); 482 return !(*this == e );
425} 483}
426bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { 484bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
427 return !(*this <= e ); 485 return !(*this <= e );
428} 486}
429bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { 487bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
430 return !(*this < e); 488 return !(*this < e);
431} 489}
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
@@ -1,198 +1,206 @@
1// CONTAINS GPLed code of TT 1// CONTAINS GPLed code of TT
2 2
3#ifndef OPIE_PIM_EVENT_H 3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H 4#define OPIE_PIM_EVENT_H
5 5
6#include <qstring.h> 6#include <qstring.h>
7#include <qdatetime.h> 7#include <qdatetime.h>
8#include <qvaluelist.h> 8#include <qvaluelist.h>
9 9
10#include <qpe/recordfields.h> 10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h> 11#include <qpe/palmtopuidgen.h>
12 12
13#include "otimezone.h" 13#include "otimezone.h"
14#include "opimrecord.h" 14#include "opimrecord.h"
15 15
16struct OCalendarHelper { 16struct OCalendarHelper {
17 /** calculate the week number of the date */ 17 /** calculate the week number of the date */
18 static int week( const QDate& ); 18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */ 19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& ); 20 static int ocurrence( const QDate& );
21 21
22 // returns the dayOfWeek for the *first* day it finds (ignores 22 // returns the dayOfWeek for the *first* day it finds (ignores
23 // any further days!). Returns 1 (Monday) if there isn't any day found 23 // any further days!). Returns 1 (Monday) if there isn't any day found
24 static int dayOfWeek( char day ); 24 static int dayOfWeek( char day );
25 25
26 /** returns the diff of month */ 26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second ); 27 static int monthDiff( const QDate& first, const QDate& second );
28 28
29}; 29};
30 30
31class OPimNotifyManager; 31class OPimNotifyManager;
32class ORecur; 32class ORecur;
33class OEvent : public OPimRecord { 33class OEvent : public OPimRecord {
34public: 34public:
35 typedef QValueList<OEvent> ValueList; 35 typedef QValueList<OEvent> ValueList;
36 enum RecordFields { 36 enum RecordFields {
37 Uid = Qtopia::UID_ID, 37 Uid = Qtopia::UID_ID,
38 Category = Qtopia::CATEGORY_ID, 38 Category = Qtopia::CATEGORY_ID,
39 Description, 39 Description,
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:
127 inline void changeOrModify(); 135 inline void changeOrModify();
128 void deref(); 136 void deref();
129 struct Data; 137 struct Data;
130 Data* data; 138 Data* data;
131 class Private; 139 class Private;
132 Private* priv; 140 Private* priv;
133 141
134}; 142};
135 143
136/** 144/**
137 * AN Event can span through multiple days. We split up a multiday eve 145 * AN Event can span through multiple days. We split up a multiday eve
138 */ 146 */
139 147
140class OEffectiveEvent { 148class OEffectiveEvent {
141public: 149public:
142 typedef QValueList<OEffectiveEvent> ValueList; 150 typedef QValueList<OEffectiveEvent> ValueList;
143 enum Position { MidWay, Start, End, StartEnd }; 151 enum Position { MidWay, Start, End, StartEnd };
144 // If we calculate the effective event of a multi-day event 152 // If we calculate the effective event of a multi-day event
145 // we have to figure out whether we are at the first day, 153 // we have to figure out whether we are at the first day,
146 // at the end, or anywhere else ("middle"). This is important 154 // at the end, or anywhere else ("middle"). This is important
147 // for the start/end times (00:00/23:59) 155 // for the start/end times (00:00/23:59)
148 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- 156 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
149 // day event 157 // day event
150 // Start: start time -> 23:59 158 // Start: start time -> 23:59
151 // End: 00:00 -> end time 159 // End: 00:00 -> end time
152 // Start | End == StartEnd: for single-day events (default) 160 // Start | End == StartEnd: for single-day events (default)
153 // here we draw start time -> end time 161 // here we draw start time -> end time
154 OEffectiveEvent(); 162 OEffectiveEvent();
155 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); 163 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
156 OEffectiveEvent( const OEffectiveEvent& ); 164 OEffectiveEvent( const OEffectiveEvent& );
157 OEffectiveEvent &operator=(const OEffectiveEvent& ); 165 OEffectiveEvent &operator=(const OEffectiveEvent& );
158 ~OEffectiveEvent(); 166 ~OEffectiveEvent();
159 167
160 void setStartTime( const QTime& ); 168 void setStartTime( const QTime& );
161 void setEndTime( const QTime& ); 169 void setEndTime( const QTime& );
162 void setEvent( const OEvent& ); 170 void setEvent( const OEvent& );
163 void setDate( const QDate& ); 171 void setDate( const QDate& );
164 172
165 void setEffectiveDates( const QDate& from, const QDate& to ); 173 void setEffectiveDates( const QDate& from, const QDate& to );
166 174
167 QString description()const; 175 QString description()const;
168 QString location()const; 176 QString location()const;
169 QString note()const; 177 QString note()const;
170 OEvent event()const; 178 OEvent event()const;
171 QTime startTime()const; 179 QTime startTime()const;
172 QTime endTime()const; 180 QTime endTime()const;
173 QDate date()const; 181 QDate date()const;
174 182
175 /* return the length in hours */ 183 /* return the length in hours */
176 int length()const; 184 int length()const;
177 int size()const; 185 int size()const;
178 186
179 QDate startDate()const; 187 QDate startDate()const;
180 QDate endDate()const; 188 QDate endDate()const;
181 189
182 bool operator<( const OEffectiveEvent &e ) const; 190 bool operator<( const OEffectiveEvent &e ) const;
183 bool operator<=( const OEffectiveEvent &e ) const; 191 bool operator<=( const OEffectiveEvent &e ) const;
184 bool operator==( const OEffectiveEvent &e ) const; 192 bool operator==( const OEffectiveEvent &e ) const;
185 bool operator!=( const OEffectiveEvent &e ) const; 193 bool operator!=( const OEffectiveEvent &e ) const;
186 bool operator>( const OEffectiveEvent &e ) const; 194 bool operator>( const OEffectiveEvent &e ) const;
187 bool operator>= ( const OEffectiveEvent &e ) const; 195 bool operator>= ( const OEffectiveEvent &e ) const;
188 196
189private: 197private:
190 void deref(); 198 void deref();
191 inline void changeOrModify(); 199 inline void changeOrModify();
192 class Private; 200 class Private;
193 Private* priv; 201 Private* priv;
194 struct Data; 202 struct Data;
195 Data* data; 203 Data* data;
196 204
197}; 205};
198#endif 206#endif
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,446 +1,510 @@
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};
29 32
30 33
31ORecur::ORecur() { 34ORecur::ORecur() {
32 data = new Data; 35 data = new Data;
33} 36}
34ORecur::ORecur( const ORecur& rec) 37ORecur::ORecur( const ORecur& rec)
35 : data( rec.data ) 38 : data( rec.data )
36{ 39{
37 data->ref(); 40 data->ref();
38} 41}
39ORecur::~ORecur() { 42ORecur::~ORecur() {
40 if ( data->deref() ) { 43 if ( data->deref() ) {
41 delete data; 44 delete data;
42 data = 0l; 45 data = 0l;
43 } 46 }
44} 47}
45void ORecur::deref() { 48void ORecur::deref() {
46 if ( data->deref() ) { 49 if ( data->deref() ) {
47 delete data; 50 delete data;
48 data = 0l; 51 data = 0l;
49 } 52 }
50} 53}
51bool ORecur::operator==( const ORecur& )const { 54bool ORecur::operator==( const ORecur& )const {
52 return false; 55 return false;
53} 56}
54ORecur &ORecur::operator=( const ORecur& re) { 57ORecur &ORecur::operator=( const ORecur& re) {
55 if ( *this == re ) return *this; 58 if ( *this == re ) return *this;
56 59
57 re.data->ref(); 60 re.data->ref();
58 deref(); 61 deref();
59 data = re.data; 62 data = re.data;
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;
123 134
124 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
125 firstOfWeek -= start().dayOfWeek() -1; 136 firstOfWeek -= start().dayOfWeek() -1;
126 137
127 // dayOfWeek may be negitive now 138 // dayOfWeek may be negitive now
128 // day of week is number of days to add to start day 139 // day of week is number of days to add to start day
129 140
130 freq *= 7; 141 freq *= 7;
131 // FALL-THROUGH !!!!! 142 // FALL-THROUGH !!!!!
132 case Daily: 143 case Daily:
133 // the add is for the possible fall through from weekly */ 144 // the add is for the possible fall through from weekly */
134 if(start().addDays(dayOfWeek) > from) { 145 if(start().addDays(dayOfWeek) > from) {
135 /* first week exception */ 146 /* first week exception */
136 next = QDate(start().addDays(dayOfWeek) ); 147 next = QDate(start().addDays(dayOfWeek) );
137 if ((next > endDate()) 148 if ((next > endDate())
138 && hasEndDate() ) 149 && hasEndDate() )
139 return FALSE; 150 return FALSE;
140 return TRUE; 151 return TRUE;
141 } 152 }
142 /* if from is middle of a non-week */ 153 /* if from is middle of a non-week */
143 154
144 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 155 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
145 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
146 157
147 if(diff != 0) 158 if(diff != 0)
148 diff = freq - diff; 159 diff = freq - diff;
149 if(diff2 != 0) 160 if(diff2 != 0)
150 diff2 = freq - diff2; 161 diff2 = freq - diff2;
151 diff = QMIN(diff, diff2); 162 diff = QMIN(diff, diff2);
152 163
153 next = QDate(from.addDays(diff)); 164 next = QDate(from.addDays(diff));
154 if ( (next > endDate()) 165 if ( (next > endDate())
155 && hasEndDate() ) 166 && hasEndDate() )
156 return FALSE; 167 return FALSE;
157 return TRUE; 168 return TRUE;
158 case MonthlyDay: 169 case MonthlyDay:
159 iday = from.day(); 170 iday = from.day();
160 iyear = from.year(); 171 iyear = from.year();
161 imonth = from.month(); 172 imonth = from.month();
162 /* find equivelent day of month for this month */ 173 /* find equivelent day of month for this month */
163 dayOfWeek = start().dayOfWeek(); 174 dayOfWeek = start().dayOfWeek();
164 weekOfMonth = (start().day() - 1) / 7; 175 weekOfMonth = (start().day() - 1) / 7;
165 176
166 /* work out when the next valid month is */ 177 /* work out when the next valid month is */
167 a = from.year() - start().year(); 178 a = from.year() - start().year();
168 a *= 12; 179 a *= 12;
169 a = a + (imonth - start().month()); 180 a = a + (imonth - start().month());
170 /* a is e.start()monthsFrom(from); */ 181 /* a is e.start()monthsFrom(from); */
171 if(a % freq) { 182 if(a % freq) {
172 a = freq - (a % freq); 183 a = freq - (a % freq);
173 imonth = from.month() + a; 184 imonth = from.month() + a;
174 if (imonth > 12) { 185 if (imonth > 12) {
175 imonth--; 186 imonth--;
176 iyear += imonth / 12; 187 iyear += imonth / 12;
177 imonth = imonth % 12; 188 imonth = imonth % 12;
178 imonth++; 189 imonth++;
179 } 190 }
180 } 191 }
181 /* imonth is now the first month after or on 192 /* imonth is now the first month after or on
182 from that matches the frequency given */ 193 from that matches the frequency given */
183 194
184 /* find for this month */ 195 /* find for this month */
185 tmpDate = QDate( iyear, imonth, 1 ); 196 tmpDate = QDate( iyear, imonth, 1 );
186 197
187 iday = 1; 198 iday = 1;
188 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
189 iday += 7 * weekOfMonth; 200 iday += 7 * weekOfMonth;
190 while (iday > tmpDate.daysInMonth()) { 201 while (iday > tmpDate.daysInMonth()) {
191 imonth += freq; 202 imonth += freq;
192 if (imonth > 12) { 203 if (imonth > 12) {
193 imonth--; 204 imonth--;
194 iyear += imonth / 12; 205 iyear += imonth / 12;
195 imonth = imonth % 12; 206 imonth = imonth % 12;
196 imonth++; 207 imonth++;
197 } 208 }
198 tmpDate = QDate( iyear, imonth, 1 ); 209 tmpDate = QDate( iyear, imonth, 1 );
199 /* these loops could go for a while, check end case now */ 210 /* these loops could go for a while, check end case now */
200 if ((tmpDate > endDate()) && hasEndDate() ) 211 if ((tmpDate > endDate()) && hasEndDate() )
201 return FALSE; 212 return FALSE;
202 iday = 1; 213 iday = 1;
203 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
204 iday += 7 * weekOfMonth; 215 iday += 7 * weekOfMonth;
205 } 216 }
206 tmpDate = QDate(iyear, imonth, iday); 217 tmpDate = QDate(iyear, imonth, iday);
207 218
208 if (tmpDate >= from) { 219 if (tmpDate >= from) {
209 next = tmpDate; 220 next = tmpDate;
210 if ((next > endDate() ) && hasEndDate() ) 221 if ((next > endDate() ) && hasEndDate() )
211 return FALSE; 222 return FALSE;
212 return TRUE; 223 return TRUE;
213 } 224 }
214 225
215 /* need to find the next iteration */ 226 /* need to find the next iteration */
216 do { 227 do {
217 imonth += freq; 228 imonth += freq;
218 if (imonth > 12) { 229 if (imonth > 12) {
219 imonth--; 230 imonth--;
220 iyear += imonth / 12; 231 iyear += imonth / 12;
221 imonth = imonth % 12; 232 imonth = imonth % 12;
222 imonth++; 233 imonth++;
223 } 234 }
224 tmpDate = QDate( iyear, imonth, 1 ); 235 tmpDate = QDate( iyear, imonth, 1 );
225 /* these loops could go for a while, check end case now */ 236 /* these loops could go for a while, check end case now */
226 if ((tmpDate > endDate()) && hasEndDate() ) 237 if ((tmpDate > endDate()) && hasEndDate() )
227 return FALSE; 238 return FALSE;
228 iday = 1; 239 iday = 1;
229 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
230 iday += 7 * weekOfMonth; 241 iday += 7 * weekOfMonth;
231 } while (iday > tmpDate.daysInMonth()); 242 } while (iday > tmpDate.daysInMonth());
232 tmpDate = QDate(iyear, imonth, iday); 243 tmpDate = QDate(iyear, imonth, iday);
233 244
234 next = tmpDate; 245 next = tmpDate;
235 if ((next > endDate()) && hasEndDate() ) 246 if ((next > endDate()) && hasEndDate() )
236 return FALSE; 247 return FALSE;
237 return TRUE; 248 return TRUE;
238 case MonthlyDate: 249 case MonthlyDate:
239 iday = start().day(); 250 iday = start().day();
240 iyear = from.year(); 251 iyear = from.year();
241 imonth = from.month(); 252 imonth = from.month();
242 253
243 a = from.year() - start().year(); 254 a = from.year() - start().year();
244 a *= 12; 255 a *= 12;
245 a = a + (imonth - start().month()); 256 a = a + (imonth - start().month());
246 /* a is e.start()monthsFrom(from); */ 257 /* a is e.start()monthsFrom(from); */
247 if(a % freq) { 258 if(a % freq) {
248 a = freq - (a % freq); 259 a = freq - (a % freq);
249 imonth = from.month() + a; 260 imonth = from.month() + a;
250 if (imonth > 12) { 261 if (imonth > 12) {
251 imonth--; 262 imonth--;
252 iyear += imonth / 12; 263 iyear += imonth / 12;
253 imonth = imonth % 12; 264 imonth = imonth % 12;
254 imonth++; 265 imonth++;
255 } 266 }
256 } 267 }
257 /* imonth is now the first month after or on 268 /* imonth is now the first month after or on
258 from that matches the frequencey given */ 269 from that matches the frequencey given */
259 270
260 /* this could go for a while, worse case, 4*12 iterations, probably */ 271 /* this could go for a while, worse case, 4*12 iterations, probably */
261 while(!QDate::isValid(iyear, imonth, iday) ) { 272 while(!QDate::isValid(iyear, imonth, iday) ) {
262 imonth += freq; 273 imonth += freq;
263 if (imonth > 12) { 274 if (imonth > 12) {
264 imonth--; 275 imonth--;
265 iyear += imonth / 12; 276 iyear += imonth / 12;
266 imonth = imonth % 12; 277 imonth = imonth % 12;
267 imonth++; 278 imonth++;
268 } 279 }
269 /* these loops could go for a while, check end case now */ 280 /* these loops could go for a while, check end case now */
270 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
271 return FALSE; 282 return FALSE;
272 } 283 }
273 284
274 if(QDate(iyear, imonth, iday) >= from) { 285 if(QDate(iyear, imonth, iday) >= from) {
275 /* done */ 286 /* done */
276 next = QDate(iyear, imonth, iday); 287 next = QDate(iyear, imonth, iday);
277 if ((next > endDate()) && hasEndDate() ) 288 if ((next > endDate()) && hasEndDate() )
278 return FALSE; 289 return FALSE;
279 return TRUE; 290 return TRUE;
280 } 291 }
281 292
282 /* ok, need to cycle */ 293 /* ok, need to cycle */
283 imonth += freq; 294 imonth += freq;
284 imonth--; 295 imonth--;
285 iyear += imonth / 12; 296 iyear += imonth / 12;
286 imonth = imonth % 12; 297 imonth = imonth % 12;
287 imonth++; 298 imonth++;
288 299
289 while(!QDate::isValid(iyear, imonth, iday) ) { 300 while(!QDate::isValid(iyear, imonth, iday) ) {
290 imonth += freq; 301 imonth += freq;
291 imonth--; 302 imonth--;
292 iyear += imonth / 12; 303 iyear += imonth / 12;
293 imonth = imonth % 12; 304 imonth = imonth % 12;
294 imonth++; 305 imonth++;
295 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 306 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
296 return FALSE; 307 return FALSE;
297 } 308 }
298 309
299 next = QDate(iyear, imonth, iday); 310 next = QDate(iyear, imonth, iday);
300 if ((next > endDate()) && hasEndDate() ) 311 if ((next > endDate()) && hasEndDate() )
301 return FALSE; 312 return FALSE;
302 return TRUE; 313 return TRUE;
303 case Yearly: 314 case Yearly:
304 iday = start().day(); 315 iday = start().day();
305 imonth = start().month(); 316 imonth = start().month();
306 iyear = from.year(); // after all, we want to start in this year 317 iyear = from.year(); // after all, we want to start in this year
307 318
308 diff = 1; 319 diff = 1;
309 if(imonth == 2 && iday > 28) { 320 if(imonth == 2 && iday > 28) {
310 /* leap year, and it counts, calculate actual frequency */ 321 /* leap year, and it counts, calculate actual frequency */
311 if(freq % 4) 322 if(freq % 4)
312 if (freq % 2) 323 if (freq % 2)
313 freq = freq * 4; 324 freq = freq * 4;
314 else 325 else
315 freq = freq * 2; 326 freq = freq * 2;
316 /* else divides by 4 already, leave freq alone */ 327 /* else divides by 4 already, leave freq alone */
317 diff = 4; 328 diff = 4;
318 } 329 }
319 330
320 a = from.year() - start().year(); 331 a = from.year() - start().year();
321 if(a % freq) { 332 if(a % freq) {
322 a = freq - (a % freq); 333 a = freq - (a % freq);
323 iyear = iyear + a; 334 iyear = iyear + a;
324 } 335 }
325 336
326 /* under the assumption we won't hit one of the special not-leap years twice */ 337 /* under the assumption we won't hit one of the special not-leap years twice */
327 if(!QDate::isValid(iyear, imonth, iday)) { 338 if(!QDate::isValid(iyear, imonth, iday)) {
328 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 339 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
329 iyear += freq; 340 iyear += freq;
330 } 341 }
331 342
332 if(QDate(iyear, imonth, iday) >= from) { 343 if(QDate(iyear, imonth, iday) >= from) {
333 next = QDate(iyear, imonth, iday); 344 next = QDate(iyear, imonth, iday);
334 345
335 if ((next > endDate()) && hasEndDate() ) 346 if ((next > endDate()) && hasEndDate() )
336 return FALSE; 347 return FALSE;
337 return TRUE; 348 return TRUE;
338 } 349 }
339 /* iyear == from.year(), need to advance again */ 350 /* iyear == from.year(), need to advance again */
340 iyear += freq; 351 iyear += freq;
341 /* under the assumption we won't hit one of the special not-leap years twice */ 352 /* under the assumption we won't hit one of the special not-leap years twice */
342 if(!QDate::isValid(iyear, imonth, iday)) { 353 if(!QDate::isValid(iyear, imonth, iday)) {
343 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 354 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
344 iyear += freq; 355 iyear += freq;
345 } 356 }
346 357
347 next = QDate(iyear, imonth, iday); 358 next = QDate(iyear, imonth, iday);
348 if ((next > endDate()) && hasEndDate() ) 359 if ((next > endDate()) && hasEndDate() )
349 return FALSE; 360 return FALSE;
350 return TRUE; 361 return TRUE;
351 default: 362 default:
352 return FALSE; 363 return FALSE;
353 } 364 }
354} 365}
355ORecur::RepeatType ORecur::type()const{ 366ORecur::RepeatType ORecur::type()const{
356 return data->type; 367 return data->type;
357} 368}
358int ORecur::frequency()const { 369int ORecur::frequency()const {
359 return data->freq; 370 return data->freq;
360} 371}
361int ORecur::position()const { 372int ORecur::position()const {
362 return data->pos; 373 return data->pos;
363} 374}
364char ORecur::days() const{ 375char ORecur::days() const{
365 return data->days; 376 return data->days;
366} 377}
367bool ORecur::hasEndDate()const { 378bool ORecur::hasEndDate()const {
368 return data->hasEnd; 379 return data->hasEnd;
369} 380}
370QDate ORecur::endDate()const { 381QDate ORecur::endDate()const {
371 return data->end; 382 return data->end;
372} 383}
373QDate ORecur::start()const{ 384QDate ORecur::start()const{
374 return data->start; 385 return data->start;
375} 386}
376QDateTime ORecur::createdDateTime()const { 387QDateTime ORecur::createdDateTime()const {
377 return data->create; 388 return data->create;
378} 389}
379int ORecur::repetition()const { 390int ORecur::repetition()const {
380 return data->rep; 391 return data->rep;
381} 392}
382QString ORecur::service()const { 393QString ORecur::service()const {
383 return data->app; 394 return data->app;
384} 395}
385ORecur::ExceptionList& ORecur::exceptions() { 396ORecur::ExceptionList& ORecur::exceptions() {
386 return data->list; 397 return data->list;
387} 398}
388void ORecur::setType( const RepeatType& z) { 399void ORecur::setType( const RepeatType& z) {
389 checkOrModify(); 400 checkOrModify();
390 data->type = z; 401 data->type = z;
391} 402}
392void ORecur::setFrequency( int freq ) { 403void ORecur::setFrequency( int freq ) {
393 checkOrModify(); 404 checkOrModify();
394 data->freq = freq; 405 data->freq = freq;
395} 406}
396void ORecur::setPosition( int pos ) { 407void ORecur::setPosition( int pos ) {
397 checkOrModify(); 408 checkOrModify();
398 data->pos = pos; 409 data->pos = pos;
399} 410}
400void ORecur::setDays( char c ) { 411void ORecur::setDays( char c ) {
401 checkOrModify(); 412 checkOrModify();
402 data->days = c; 413 data->days = c;
403} 414}
404void ORecur::setEndDate( const QDate& dt) { 415void ORecur::setEndDate( const QDate& dt) {
405 checkOrModify(); 416 checkOrModify();
406 data->end = dt; 417 data->end = dt;
407} 418}
408void ORecur::setCreatedDateTime( const QDateTime& t) { 419void ORecur::setCreatedDateTime( const QDateTime& t) {
409 checkOrModify(); 420 checkOrModify();
410 data->create = t; 421 data->create = t;
411} 422}
412void ORecur::setHasEndDate( bool b) { 423void ORecur::setHasEndDate( bool b) {
413 checkOrModify(); 424 checkOrModify();
414 data->hasEnd = b; 425 data->hasEnd = b;
415} 426}
416void ORecur::setRepitition( int rep ) { 427void ORecur::setRepitition( int rep ) {
417 checkOrModify(); 428 checkOrModify();
418 data->rep = rep; 429 data->rep = rep;
419} 430}
420void ORecur::setService( const QString& app ) { 431void ORecur::setService( const QString& app ) {
421 checkOrModify(); 432 checkOrModify();
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
@@ -1,87 +1,91 @@
1/* 1/*
2 * GPL from TT 2 * GPL from TT
3 */ 3 */
4 4
5#ifndef OPIE_RECUR_H 5#ifndef OPIE_RECUR_H
6#define OPIE_RECUR_H 6#define OPIE_RECUR_H
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9 9
10#include <qdatetime.h> 10#include <qdatetime.h>
11#include <qvaluelist.h> 11#include <qvaluelist.h>
12 12
13 13
14class ORecur { 14class ORecur {
15public: 15public:
16 typedef QValueList<QDate> ExceptionList; 16 typedef QValueList<QDate> ExceptionList;
17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay, 17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
18 MonthlyDate, Yearly }; 18 MonthlyDate, Yearly };
19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, 19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
20 FRI = 0x10, SAT = 0x20, SUN = 0x40 }; 20 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
21 ORecur(); 21 ORecur();
22 ORecur( const ORecur& ); 22 ORecur( const ORecur& );
23 ~ORecur(); 23 ~ORecur();
24 24
25 ORecur &operator=( const ORecur& ); 25 ORecur &operator=( const ORecur& );
26 bool operator==(const ORecur& )const; 26 bool operator==(const ORecur& )const;
27 27
28 bool doesRecur()const; 28 bool doesRecur()const;
29 /* if it recurrs on that day */ 29 /* if it recurrs on that day */
30 bool doesRecur( const QDate& ); 30 bool doesRecur( const QDate& );
31 RepeatType type()const; 31 RepeatType type()const;
32 int frequency()const; 32 int frequency()const;
33 int position()const; 33 int position()const;
34 char days()const; 34 char days()const;
35 bool hasEndDate()const; 35 bool hasEndDate()const;
36 QDate start()const; 36 QDate start()const;
37 QDate endDate()const; 37 QDate endDate()const;
38 QDateTime createdDateTime()const; 38 QDateTime createdDateTime()const;
39 /** 39 /**
40 * starting on monday=0, sunday=6 40 * starting on monday=0, sunday=6
41 * for convience 41 * for convience
42 */ 42 */
43 bool repeatOnWeekDay( int day )const; 43 bool repeatOnWeekDay( int day )const;
44 44
45 /** 45 /**
46 * FromWhereToStart is not included!!! 46 * FromWhereToStart is not included!!!
47 */ 47 */
48 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); 48 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
49 49
50 /** 50 /**
51 * The module this ORecur belongs to 51 * The module this ORecur belongs to
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,395 +1,557 @@
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();
96} 226}
97OEvent ODateBookAccessBackend_XML::find( int uid ) const{ 227OEvent ODateBookAccessBackend_XML::find( int uid ) const{
98 if ( m_raw.contains( uid ) ) 228 if ( m_raw.contains( uid ) )
99 return m_raw[uid]; 229 return m_raw[uid];
100 else 230 else
101 return m_rep[uid]; 231 return m_rep[uid];
102} 232}
103bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { 233bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
104 m_changed = true; 234 m_changed = true;
105 if (ev.hasRecurrence() ) 235 if (ev.hasRecurrence() )
106 m_rep.insert( ev.uid(), ev ); 236 m_rep.insert( ev.uid(), ev );
107 else 237 else
108 m_raw.insert( ev.uid(), ev ); 238 m_raw.insert( ev.uid(), ev );
109 239
110 return true; 240 return true;
111} 241}
112bool ODateBookAccessBackend_XML::remove( int uid ) { 242bool ODateBookAccessBackend_XML::remove( int uid ) {
113 m_changed = true; 243 m_changed = true;
114 m_rep.remove( uid ); 244 m_rep.remove( uid );
115 m_rep.remove( uid ); 245 m_rep.remove( uid );
116 246
117 return true; 247 return true;
118} 248}
119bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { 249bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
120 replace( ev.uid() ); 250 replace( ev.uid() );
121 return add( ev ); 251 return add( ev );
122} 252}
123QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 253QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
124 return allRecords(); 254 return allRecords();
125} 255}
126QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 256QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
127 QArray<int> ints( m_rep.count() ); 257 QArray<int> ints( m_rep.count() );
128 uint i = 0; 258 uint i = 0;
129 QMap<int, OEvent>::ConstIterator it; 259 QMap<int, OEvent>::ConstIterator it;
130 260
131 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 261 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
132 ints[i] = it.key(); 262 ints[i] = it.key();
133 i++; 263 i++;
134 } 264 }
135 265
136 return ints; 266 return ints;
137} 267}
138QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 268QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
139 QArray<int> ints( m_raw.count() ); 269 QArray<int> ints( m_raw.count() );
140 uint i = 0; 270 uint i = 0;
141 QMap<int, OEvent>::ConstIterator it; 271 QMap<int, OEvent>::ConstIterator it;
142 272
143 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 273 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
144 ints[i] = it.key(); 274 ints[i] = it.key();
145 i++; 275 i++;
146 } 276 }
147 277
148 return ints; 278 return ints;
149} 279}
150OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { 280OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
151 OEvent::ValueList list; 281 OEvent::ValueList list;
152 QMap<int, OEvent>::ConstIterator it; 282 QMap<int, OEvent>::ConstIterator it;
153 for (it = m_raw.begin(); it != m_raw.end(); ++it ) 283 for (it = m_raw.begin(); it != m_raw.end(); ++it )
154 list.append( it.data() ); 284 list.append( it.data() );
155 285
156 return list; 286 return list;
157} 287}
158OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { 288OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
159 OEvent::ValueList list; 289 OEvent::ValueList list;
160 QMap<int, OEvent>::ConstIterator it; 290 QMap<int, OEvent>::ConstIterator it;
161 for (it = m_rep.begin(); it != m_rep.end(); ++it ) 291 for (it = m_rep.begin(); it != m_rep.end(); ++it )
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
229 363
230 // we have another attribute, read it. 364 // we have another attribute, read it.
231 int j = i; 365 int j = i;
232 while ( j < len && dt[j] != '=' ) 366 while ( j < len && dt[j] != '=' )
233 ++j; 367 ++j;
234 QCString attr( dt+i, j-i+1); 368 QCString attr( dt+i, j-i+1);
235 369
236 i = ++j; // skip = 370 i = ++j; // skip =
237 371
238 // find the start of quotes 372 // find the start of quotes
239 while ( i < len && dt[i] != '"' ) 373 while ( i < len && dt[i] != '"' )
240 ++i; 374 ++i;
241 j = ++i; 375 j = ++i;
242 376
243 bool haveUtf = FALSE; 377 bool haveUtf = FALSE;
244 bool haveEnt = FALSE; 378 bool haveEnt = FALSE;
245 while ( j < len && dt[j] != '"' ) { 379 while ( j < len && dt[j] != '"' ) {
246 if ( ((unsigned char)dt[j]) > 0x7f ) 380 if ( ((unsigned char)dt[j]) > 0x7f )
247 haveUtf = TRUE; 381 haveUtf = TRUE;
248 if ( dt[j] == '&' ) 382 if ( dt[j] == '&' )
249 haveEnt = TRUE; 383 haveEnt = TRUE;
250 ++j; 384 ++j;
251 } 385 }
252 if ( i == j ) { 386 if ( i == j ) {
253 // empty value 387 // empty value
254 i = j + 1; 388 i = j + 1;
255 continue; 389 continue;
256 } 390 }
257 391
258 QCString value( dt+i, j-i+1 ); 392 QCString value( dt+i, j-i+1 );
259 i = j + 1; 393 i = j + 1;
260 394
261 QString str = (haveUtf ? QString::fromUtf8( value ) 395 QString str = (haveUtf ? QString::fromUtf8( value )
262 : QString::fromLatin1( value ) ); 396 : QString::fromLatin1( value ) );
263 if ( haveEnt ) 397 if ( haveEnt )
264 str = Qtopia::plainString( str ); 398 str = Qtopia::plainString( str );
265 399
266 /* 400 /*
267 * add key + value 401 * add key + value
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}
320void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { 459void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
321// qWarning(" setting %s", value.latin1() ); 460// qWarning(" setting %s", value.latin1() );
322 switch( id ) { 461 switch( id ) {
323 case FDescription: 462 case FDescription:
324 e.setDescription( value ); 463 e.setDescription( value );
325 break; 464 break;
326 case FLocation: 465 case FLocation:
327 e.setLocation( value ); 466 e.setLocation( value );
328 break; 467 break;
329 case FCategories: 468 case FCategories:
330 e.setCategories( e.idsFromString( value ) ); 469 e.setCategories( e.idsFromString( value ) );
331 break; 470 break;
332 case FUid: 471 case FUid:
333 e.setUid( value.toInt() ); 472 e.setUid( value.toInt() );
334 break; 473 break;
335 case FType: 474 case FType:
336 if ( value == "AllDay" ) { 475 if ( value == "AllDay" ) {
337 e.setAllDay( true ); 476 e.setAllDay( true );
338 e.setTimeZone( "UTC" ); 477 e.setTimeZone( "UTC" );
339 } 478 }
340 break; 479 break;
341 case FAlarm: 480 case FAlarm:
342 alarmTime = value.toInt(); 481 alarmTime = value.toInt();
343 break; 482 break;
344 case FSound: 483 case FSound:
345 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; 484 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
346 break; 485 break;
347 // recurrence stuff 486 // recurrence stuff
348 case FRType: 487 case FRType:
349 if ( value == "Daily" ) 488 if ( value == "Daily" )
350 recur()->setType( ORecur::Daily ); 489 recur()->setType( ORecur::Daily );
351 else if ( value == "Weekly" ) 490 else if ( value == "Weekly" )
352 recur()->setType( ORecur::Weekly); 491 recur()->setType( ORecur::Weekly);
353 else if ( value == "MonthlyDay" ) 492 else if ( value == "MonthlyDay" )
354 recur()->setType( ORecur::MonthlyDay ); 493 recur()->setType( ORecur::MonthlyDay );
355 else if ( value == "MonthlyDate" ) 494 else if ( value == "MonthlyDate" )
356 recur()->setType( ORecur::MonthlyDate ); 495 recur()->setType( ORecur::MonthlyDate );
357 else if ( value == "Yearly" ) 496 else if ( value == "Yearly" )
358 recur()->setType( ORecur::Yearly ); 497 recur()->setType( ORecur::Yearly );
359 else 498 else
360 recur()->setType( ORecur::NoRepeat ); 499 recur()->setType( ORecur::NoRepeat );
361 break; 500 break;
362 case FRWeekdays: 501 case FRWeekdays:
363 recur()->setDays( value.toInt() ); 502 recur()->setDays( value.toInt() );
364 break; 503 break;
365 case FRPosition: 504 case FRPosition:
366 recur()->setPosition( value.toInt() ); 505 recur()->setPosition( value.toInt() );
367 break; 506 break;
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,446 +1,510 @@
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};
29 32
30 33
31ORecur::ORecur() { 34ORecur::ORecur() {
32 data = new Data; 35 data = new Data;
33} 36}
34ORecur::ORecur( const ORecur& rec) 37ORecur::ORecur( const ORecur& rec)
35 : data( rec.data ) 38 : data( rec.data )
36{ 39{
37 data->ref(); 40 data->ref();
38} 41}
39ORecur::~ORecur() { 42ORecur::~ORecur() {
40 if ( data->deref() ) { 43 if ( data->deref() ) {
41 delete data; 44 delete data;
42 data = 0l; 45 data = 0l;
43 } 46 }
44} 47}
45void ORecur::deref() { 48void ORecur::deref() {
46 if ( data->deref() ) { 49 if ( data->deref() ) {
47 delete data; 50 delete data;
48 data = 0l; 51 data = 0l;
49 } 52 }
50} 53}
51bool ORecur::operator==( const ORecur& )const { 54bool ORecur::operator==( const ORecur& )const {
52 return false; 55 return false;
53} 56}
54ORecur &ORecur::operator=( const ORecur& re) { 57ORecur &ORecur::operator=( const ORecur& re) {
55 if ( *this == re ) return *this; 58 if ( *this == re ) return *this;
56 59
57 re.data->ref(); 60 re.data->ref();
58 deref(); 61 deref();
59 data = re.data; 62 data = re.data;
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;
123 134
124 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
125 firstOfWeek -= start().dayOfWeek() -1; 136 firstOfWeek -= start().dayOfWeek() -1;
126 137
127 // dayOfWeek may be negitive now 138 // dayOfWeek may be negitive now
128 // day of week is number of days to add to start day 139 // day of week is number of days to add to start day
129 140
130 freq *= 7; 141 freq *= 7;
131 // FALL-THROUGH !!!!! 142 // FALL-THROUGH !!!!!
132 case Daily: 143 case Daily:
133 // the add is for the possible fall through from weekly */ 144 // the add is for the possible fall through from weekly */
134 if(start().addDays(dayOfWeek) > from) { 145 if(start().addDays(dayOfWeek) > from) {
135 /* first week exception */ 146 /* first week exception */
136 next = QDate(start().addDays(dayOfWeek) ); 147 next = QDate(start().addDays(dayOfWeek) );
137 if ((next > endDate()) 148 if ((next > endDate())
138 && hasEndDate() ) 149 && hasEndDate() )
139 return FALSE; 150 return FALSE;
140 return TRUE; 151 return TRUE;
141 } 152 }
142 /* if from is middle of a non-week */ 153 /* if from is middle of a non-week */
143 154
144 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 155 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
145 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
146 157
147 if(diff != 0) 158 if(diff != 0)
148 diff = freq - diff; 159 diff = freq - diff;
149 if(diff2 != 0) 160 if(diff2 != 0)
150 diff2 = freq - diff2; 161 diff2 = freq - diff2;
151 diff = QMIN(diff, diff2); 162 diff = QMIN(diff, diff2);
152 163
153 next = QDate(from.addDays(diff)); 164 next = QDate(from.addDays(diff));
154 if ( (next > endDate()) 165 if ( (next > endDate())
155 && hasEndDate() ) 166 && hasEndDate() )
156 return FALSE; 167 return FALSE;
157 return TRUE; 168 return TRUE;
158 case MonthlyDay: 169 case MonthlyDay:
159 iday = from.day(); 170 iday = from.day();
160 iyear = from.year(); 171 iyear = from.year();
161 imonth = from.month(); 172 imonth = from.month();
162 /* find equivelent day of month for this month */ 173 /* find equivelent day of month for this month */
163 dayOfWeek = start().dayOfWeek(); 174 dayOfWeek = start().dayOfWeek();
164 weekOfMonth = (start().day() - 1) / 7; 175 weekOfMonth = (start().day() - 1) / 7;
165 176
166 /* work out when the next valid month is */ 177 /* work out when the next valid month is */
167 a = from.year() - start().year(); 178 a = from.year() - start().year();
168 a *= 12; 179 a *= 12;
169 a = a + (imonth - start().month()); 180 a = a + (imonth - start().month());
170 /* a is e.start()monthsFrom(from); */ 181 /* a is e.start()monthsFrom(from); */
171 if(a % freq) { 182 if(a % freq) {
172 a = freq - (a % freq); 183 a = freq - (a % freq);
173 imonth = from.month() + a; 184 imonth = from.month() + a;
174 if (imonth > 12) { 185 if (imonth > 12) {
175 imonth--; 186 imonth--;
176 iyear += imonth / 12; 187 iyear += imonth / 12;
177 imonth = imonth % 12; 188 imonth = imonth % 12;
178 imonth++; 189 imonth++;
179 } 190 }
180 } 191 }
181 /* imonth is now the first month after or on 192 /* imonth is now the first month after or on
182 from that matches the frequency given */ 193 from that matches the frequency given */
183 194
184 /* find for this month */ 195 /* find for this month */
185 tmpDate = QDate( iyear, imonth, 1 ); 196 tmpDate = QDate( iyear, imonth, 1 );
186 197
187 iday = 1; 198 iday = 1;
188 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
189 iday += 7 * weekOfMonth; 200 iday += 7 * weekOfMonth;
190 while (iday > tmpDate.daysInMonth()) { 201 while (iday > tmpDate.daysInMonth()) {
191 imonth += freq; 202 imonth += freq;
192 if (imonth > 12) { 203 if (imonth > 12) {
193 imonth--; 204 imonth--;
194 iyear += imonth / 12; 205 iyear += imonth / 12;
195 imonth = imonth % 12; 206 imonth = imonth % 12;
196 imonth++; 207 imonth++;
197 } 208 }
198 tmpDate = QDate( iyear, imonth, 1 ); 209 tmpDate = QDate( iyear, imonth, 1 );
199 /* these loops could go for a while, check end case now */ 210 /* these loops could go for a while, check end case now */
200 if ((tmpDate > endDate()) && hasEndDate() ) 211 if ((tmpDate > endDate()) && hasEndDate() )
201 return FALSE; 212 return FALSE;
202 iday = 1; 213 iday = 1;
203 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
204 iday += 7 * weekOfMonth; 215 iday += 7 * weekOfMonth;
205 } 216 }
206 tmpDate = QDate(iyear, imonth, iday); 217 tmpDate = QDate(iyear, imonth, iday);
207 218
208 if (tmpDate >= from) { 219 if (tmpDate >= from) {
209 next = tmpDate; 220 next = tmpDate;
210 if ((next > endDate() ) && hasEndDate() ) 221 if ((next > endDate() ) && hasEndDate() )
211 return FALSE; 222 return FALSE;
212 return TRUE; 223 return TRUE;
213 } 224 }
214 225
215 /* need to find the next iteration */ 226 /* need to find the next iteration */
216 do { 227 do {
217 imonth += freq; 228 imonth += freq;
218 if (imonth > 12) { 229 if (imonth > 12) {
219 imonth--; 230 imonth--;
220 iyear += imonth / 12; 231 iyear += imonth / 12;
221 imonth = imonth % 12; 232 imonth = imonth % 12;
222 imonth++; 233 imonth++;
223 } 234 }
224 tmpDate = QDate( iyear, imonth, 1 ); 235 tmpDate = QDate( iyear, imonth, 1 );
225 /* these loops could go for a while, check end case now */ 236 /* these loops could go for a while, check end case now */
226 if ((tmpDate > endDate()) && hasEndDate() ) 237 if ((tmpDate > endDate()) && hasEndDate() )
227 return FALSE; 238 return FALSE;
228 iday = 1; 239 iday = 1;
229 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
230 iday += 7 * weekOfMonth; 241 iday += 7 * weekOfMonth;
231 } while (iday > tmpDate.daysInMonth()); 242 } while (iday > tmpDate.daysInMonth());
232 tmpDate = QDate(iyear, imonth, iday); 243 tmpDate = QDate(iyear, imonth, iday);
233 244
234 next = tmpDate; 245 next = tmpDate;
235 if ((next > endDate()) && hasEndDate() ) 246 if ((next > endDate()) && hasEndDate() )
236 return FALSE; 247 return FALSE;
237 return TRUE; 248 return TRUE;
238 case MonthlyDate: 249 case MonthlyDate:
239 iday = start().day(); 250 iday = start().day();
240 iyear = from.year(); 251 iyear = from.year();
241 imonth = from.month(); 252 imonth = from.month();
242 253
243 a = from.year() - start().year(); 254 a = from.year() - start().year();
244 a *= 12; 255 a *= 12;
245 a = a + (imonth - start().month()); 256 a = a + (imonth - start().month());
246 /* a is e.start()monthsFrom(from); */ 257 /* a is e.start()monthsFrom(from); */
247 if(a % freq) { 258 if(a % freq) {
248 a = freq - (a % freq); 259 a = freq - (a % freq);
249 imonth = from.month() + a; 260 imonth = from.month() + a;
250 if (imonth > 12) { 261 if (imonth > 12) {
251 imonth--; 262 imonth--;
252 iyear += imonth / 12; 263 iyear += imonth / 12;
253 imonth = imonth % 12; 264 imonth = imonth % 12;
254 imonth++; 265 imonth++;
255 } 266 }
256 } 267 }
257 /* imonth is now the first month after or on 268 /* imonth is now the first month after or on
258 from that matches the frequencey given */ 269 from that matches the frequencey given */
259 270
260 /* this could go for a while, worse case, 4*12 iterations, probably */ 271 /* this could go for a while, worse case, 4*12 iterations, probably */
261 while(!QDate::isValid(iyear, imonth, iday) ) { 272 while(!QDate::isValid(iyear, imonth, iday) ) {
262 imonth += freq; 273 imonth += freq;
263 if (imonth > 12) { 274 if (imonth > 12) {
264 imonth--; 275 imonth--;
265 iyear += imonth / 12; 276 iyear += imonth / 12;
266 imonth = imonth % 12; 277 imonth = imonth % 12;
267 imonth++; 278 imonth++;
268 } 279 }
269 /* these loops could go for a while, check end case now */ 280 /* these loops could go for a while, check end case now */
270 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
271 return FALSE; 282 return FALSE;
272 } 283 }
273 284
274 if(QDate(iyear, imonth, iday) >= from) { 285 if(QDate(iyear, imonth, iday) >= from) {
275 /* done */ 286 /* done */
276 next = QDate(iyear, imonth, iday); 287 next = QDate(iyear, imonth, iday);
277 if ((next > endDate()) && hasEndDate() ) 288 if ((next > endDate()) && hasEndDate() )
278 return FALSE; 289 return FALSE;
279 return TRUE; 290 return TRUE;
280 } 291 }
281 292
282 /* ok, need to cycle */ 293 /* ok, need to cycle */
283 imonth += freq; 294 imonth += freq;
284 imonth--; 295 imonth--;
285 iyear += imonth / 12; 296 iyear += imonth / 12;
286 imonth = imonth % 12; 297 imonth = imonth % 12;
287 imonth++; 298 imonth++;
288 299
289 while(!QDate::isValid(iyear, imonth, iday) ) { 300 while(!QDate::isValid(iyear, imonth, iday) ) {
290 imonth += freq; 301 imonth += freq;
291 imonth--; 302 imonth--;
292 iyear += imonth / 12; 303 iyear += imonth / 12;
293 imonth = imonth % 12; 304 imonth = imonth % 12;
294 imonth++; 305 imonth++;
295 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 306 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
296 return FALSE; 307 return FALSE;
297 } 308 }
298 309
299 next = QDate(iyear, imonth, iday); 310 next = QDate(iyear, imonth, iday);
300 if ((next > endDate()) && hasEndDate() ) 311 if ((next > endDate()) && hasEndDate() )
301 return FALSE; 312 return FALSE;
302 return TRUE; 313 return TRUE;
303 case Yearly: 314 case Yearly:
304 iday = start().day(); 315 iday = start().day();
305 imonth = start().month(); 316 imonth = start().month();
306 iyear = from.year(); // after all, we want to start in this year 317 iyear = from.year(); // after all, we want to start in this year
307 318
308 diff = 1; 319 diff = 1;
309 if(imonth == 2 && iday > 28) { 320 if(imonth == 2 && iday > 28) {
310 /* leap year, and it counts, calculate actual frequency */ 321 /* leap year, and it counts, calculate actual frequency */
311 if(freq % 4) 322 if(freq % 4)
312 if (freq % 2) 323 if (freq % 2)
313 freq = freq * 4; 324 freq = freq * 4;
314 else 325 else
315 freq = freq * 2; 326 freq = freq * 2;
316 /* else divides by 4 already, leave freq alone */ 327 /* else divides by 4 already, leave freq alone */
317 diff = 4; 328 diff = 4;
318 } 329 }
319 330
320 a = from.year() - start().year(); 331 a = from.year() - start().year();
321 if(a % freq) { 332 if(a % freq) {
322 a = freq - (a % freq); 333 a = freq - (a % freq);
323 iyear = iyear + a; 334 iyear = iyear + a;
324 } 335 }
325 336
326 /* under the assumption we won't hit one of the special not-leap years twice */ 337 /* under the assumption we won't hit one of the special not-leap years twice */
327 if(!QDate::isValid(iyear, imonth, iday)) { 338 if(!QDate::isValid(iyear, imonth, iday)) {
328 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 339 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
329 iyear += freq; 340 iyear += freq;
330 } 341 }
331 342
332 if(QDate(iyear, imonth, iday) >= from) { 343 if(QDate(iyear, imonth, iday) >= from) {
333 next = QDate(iyear, imonth, iday); 344 next = QDate(iyear, imonth, iday);
334 345
335 if ((next > endDate()) && hasEndDate() ) 346 if ((next > endDate()) && hasEndDate() )
336 return FALSE; 347 return FALSE;
337 return TRUE; 348 return TRUE;
338 } 349 }
339 /* iyear == from.year(), need to advance again */ 350 /* iyear == from.year(), need to advance again */
340 iyear += freq; 351 iyear += freq;
341 /* under the assumption we won't hit one of the special not-leap years twice */ 352 /* under the assumption we won't hit one of the special not-leap years twice */
342 if(!QDate::isValid(iyear, imonth, iday)) { 353 if(!QDate::isValid(iyear, imonth, iday)) {
343 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 354 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
344 iyear += freq; 355 iyear += freq;
345 } 356 }
346 357
347 next = QDate(iyear, imonth, iday); 358 next = QDate(iyear, imonth, iday);
348 if ((next > endDate()) && hasEndDate() ) 359 if ((next > endDate()) && hasEndDate() )
349 return FALSE; 360 return FALSE;
350 return TRUE; 361 return TRUE;
351 default: 362 default:
352 return FALSE; 363 return FALSE;
353 } 364 }
354} 365}
355ORecur::RepeatType ORecur::type()const{ 366ORecur::RepeatType ORecur::type()const{
356 return data->type; 367 return data->type;
357} 368}
358int ORecur::frequency()const { 369int ORecur::frequency()const {
359 return data->freq; 370 return data->freq;
360} 371}
361int ORecur::position()const { 372int ORecur::position()const {
362 return data->pos; 373 return data->pos;
363} 374}
364char ORecur::days() const{ 375char ORecur::days() const{
365 return data->days; 376 return data->days;
366} 377}
367bool ORecur::hasEndDate()const { 378bool ORecur::hasEndDate()const {
368 return data->hasEnd; 379 return data->hasEnd;
369} 380}
370QDate ORecur::endDate()const { 381QDate ORecur::endDate()const {
371 return data->end; 382 return data->end;
372} 383}
373QDate ORecur::start()const{ 384QDate ORecur::start()const{
374 return data->start; 385 return data->start;
375} 386}
376QDateTime ORecur::createdDateTime()const { 387QDateTime ORecur::createdDateTime()const {
377 return data->create; 388 return data->create;
378} 389}
379int ORecur::repetition()const { 390int ORecur::repetition()const {
380 return data->rep; 391 return data->rep;
381} 392}
382QString ORecur::service()const { 393QString ORecur::service()const {
383 return data->app; 394 return data->app;
384} 395}
385ORecur::ExceptionList& ORecur::exceptions() { 396ORecur::ExceptionList& ORecur::exceptions() {
386 return data->list; 397 return data->list;
387} 398}
388void ORecur::setType( const RepeatType& z) { 399void ORecur::setType( const RepeatType& z) {
389 checkOrModify(); 400 checkOrModify();
390 data->type = z; 401 data->type = z;
391} 402}
392void ORecur::setFrequency( int freq ) { 403void ORecur::setFrequency( int freq ) {
393 checkOrModify(); 404 checkOrModify();
394 data->freq = freq; 405 data->freq = freq;
395} 406}
396void ORecur::setPosition( int pos ) { 407void ORecur::setPosition( int pos ) {
397 checkOrModify(); 408 checkOrModify();
398 data->pos = pos; 409 data->pos = pos;
399} 410}
400void ORecur::setDays( char c ) { 411void ORecur::setDays( char c ) {
401 checkOrModify(); 412 checkOrModify();
402 data->days = c; 413 data->days = c;
403} 414}
404void ORecur::setEndDate( const QDate& dt) { 415void ORecur::setEndDate( const QDate& dt) {
405 checkOrModify(); 416 checkOrModify();
406 data->end = dt; 417 data->end = dt;
407} 418}
408void ORecur::setCreatedDateTime( const QDateTime& t) { 419void ORecur::setCreatedDateTime( const QDateTime& t) {
409 checkOrModify(); 420 checkOrModify();
410 data->create = t; 421 data->create = t;
411} 422}
412void ORecur::setHasEndDate( bool b) { 423void ORecur::setHasEndDate( bool b) {
413 checkOrModify(); 424 checkOrModify();
414 data->hasEnd = b; 425 data->hasEnd = b;
415} 426}
416void ORecur::setRepitition( int rep ) { 427void ORecur::setRepitition( int rep ) {
417 checkOrModify(); 428 checkOrModify();
418 data->rep = rep; 429 data->rep = rep;
419} 430}
420void ORecur::setService( const QString& app ) { 431void ORecur::setService( const QString& app ) {
421 checkOrModify(); 432 checkOrModify();
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
@@ -1,87 +1,91 @@
1/* 1/*
2 * GPL from TT 2 * GPL from TT
3 */ 3 */
4 4
5#ifndef OPIE_RECUR_H 5#ifndef OPIE_RECUR_H
6#define OPIE_RECUR_H 6#define OPIE_RECUR_H
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9 9
10#include <qdatetime.h> 10#include <qdatetime.h>
11#include <qvaluelist.h> 11#include <qvaluelist.h>
12 12
13 13
14class ORecur { 14class ORecur {
15public: 15public:
16 typedef QValueList<QDate> ExceptionList; 16 typedef QValueList<QDate> ExceptionList;
17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay, 17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
18 MonthlyDate, Yearly }; 18 MonthlyDate, Yearly };
19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, 19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
20 FRI = 0x10, SAT = 0x20, SUN = 0x40 }; 20 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
21 ORecur(); 21 ORecur();
22 ORecur( const ORecur& ); 22 ORecur( const ORecur& );
23 ~ORecur(); 23 ~ORecur();
24 24
25 ORecur &operator=( const ORecur& ); 25 ORecur &operator=( const ORecur& );
26 bool operator==(const ORecur& )const; 26 bool operator==(const ORecur& )const;
27 27
28 bool doesRecur()const; 28 bool doesRecur()const;
29 /* if it recurrs on that day */ 29 /* if it recurrs on that day */
30 bool doesRecur( const QDate& ); 30 bool doesRecur( const QDate& );
31 RepeatType type()const; 31 RepeatType type()const;
32 int frequency()const; 32 int frequency()const;
33 int position()const; 33 int position()const;
34 char days()const; 34 char days()const;
35 bool hasEndDate()const; 35 bool hasEndDate()const;
36 QDate start()const; 36 QDate start()const;
37 QDate endDate()const; 37 QDate endDate()const;
38 QDateTime createdDateTime()const; 38 QDateTime createdDateTime()const;
39 /** 39 /**
40 * starting on monday=0, sunday=6 40 * starting on monday=0, sunday=6
41 * for convience 41 * for convience
42 */ 42 */
43 bool repeatOnWeekDay( int day )const; 43 bool repeatOnWeekDay( int day )const;
44 44
45 /** 45 /**
46 * FromWhereToStart is not included!!! 46 * FromWhereToStart is not included!!!
47 */ 47 */
48 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); 48 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
49 49
50 /** 50 /**
51 * The module this ORecur belongs to 51 * The module this ORecur belongs to
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
@@ -1,431 +1,489 @@
1#include <qshared.h> 1#include <qshared.h>
2 2
3#include <qpe/palmtopuidgen.h> 3#include <qpe/palmtopuidgen.h>
4#include <qpe/categories.h> 4#include <qpe/categories.h>
5 5
6#include "orecur.h" 6#include "orecur.h"
7#include "opimresolver.h" 7#include "opimresolver.h"
8#include "opimnotifymanager.h" 8#include "opimnotifymanager.h"
9 9
10#include "oevent.h" 10#include "oevent.h"
11 11
12int OCalendarHelper::week( const QDate& date) { 12int OCalendarHelper::week( const QDate& date) {
13 // Calculates the week this date is in within that 13 // Calculates the week this date is in within that
14 // month. Equals the "row" is is in in the month view 14 // month. Equals the "row" is is in in the month view
15 int week = 1; 15 int week = 1;
16 QDate tmp( date.year(), date.month(), 1 ); 16 QDate tmp( date.year(), date.month(), 1 );
17 if ( date.dayOfWeek() < tmp.dayOfWeek() ) 17 if ( date.dayOfWeek() < tmp.dayOfWeek() )
18 ++week; 18 ++week;
19 19
20 week += ( date.day() - 1 ) / 7; 20 week += ( date.day() - 1 ) / 7;
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;
140} 150}
141QDateTime OEvent::createdDateTime()const { 151QDateTime OEvent::createdDateTime()const {
142 return data->created; 152 return data->created;
143} 153}
144void OEvent::setCreatedDateTime( const QDateTime& time ) { 154void OEvent::setCreatedDateTime( const QDateTime& time ) {
145 changeOrModify(); 155 changeOrModify();
146 data->created = time; 156 data->created = time;
147} 157}
148QDateTime OEvent::startDateTime()const { 158QDateTime OEvent::startDateTime()const {
149 if ( data->isAllDay ) 159 if ( data->isAllDay )
150 return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); 160 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
151 return data->start; 161 return data->start;
152} 162}
153QDateTime OEvent::startDateTimeInZone()const { 163QDateTime OEvent::startDateTimeInZone()const {
154 /* if no timezone, or all day event or if the current and this timeZone match... */ 164 /* if no timezone, or all day event or if the current and this timeZone match... */
155 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); 165 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
156 166
157 OTimeZone zone(data->timezone ); 167 OTimeZone zone(data->timezone );
158 return zone.toDateTime( data->start, OTimeZone::current() ); 168 return zone.toDateTime( data->start, OTimeZone::current() );
159} 169}
160void OEvent::setStartDateTime( const QDateTime& dt ) { 170void OEvent::setStartDateTime( const QDateTime& dt ) {
161 changeOrModify(); 171 changeOrModify();
162 data->start = dt; 172 data->start = dt;
163} 173}
164QDateTime OEvent::endDateTime()const { 174QDateTime OEvent::endDateTime()const {
165 /* 175 /*
166 * if all Day event the end time needs 176 * if all Day event the end time needs
167 * to be on the same day as the start 177 * to be on the same day as the start
168 */ 178 */
169 if ( data->isAllDay ) 179 if ( data->isAllDay )
170 return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); 180 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
171 return data->end; 181 return data->end;
172} 182}
173QDateTime OEvent::endDateTimeInZone()const { 183QDateTime OEvent::endDateTimeInZone()const {
174 /* if no timezone, or all day event or if the current and this timeZone match... */ 184 /* if no timezone, or all day event or if the current and this timeZone match... */
175 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); 185 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
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
285 data->start = QTime( 0, 0, 0 ); 343 data->start = QTime( 0, 0, 0 );
286 344
287 if ( pos & End ) 345 if ( pos & End )
288 data->end = ev.endDateTime().time(); 346 data->end = ev.endDateTime().time();
289 else 347 else
290 data->end = QTime( 23, 59, 59 ); 348 data->end = QTime( 23, 59, 59 );
291 349
292 data->dates = false; 350 data->dates = false;
293} 351}
294OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { 352OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
295 data = ev.data; 353 data = ev.data;
296 data->ref(); 354 data->ref();
297} 355}
298OEffectiveEvent::~OEffectiveEvent() { 356OEffectiveEvent::~OEffectiveEvent() {
299 if ( data->deref() ) { 357 if ( data->deref() ) {
300 delete data; 358 delete data;
301 data = 0; 359 data = 0;
302 } 360 }
303} 361}
304OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { 362OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
305 if ( *this == ev ) return *this; 363 if ( *this == ev ) return *this;
306 364
307 ev.data->ref(); 365 ev.data->ref();
308 deref(); 366 deref();
309 data = ev.data; 367 data = ev.data;
310 368
311 return *this; 369 return *this;
312} 370}
313 371
314void OEffectiveEvent::setStartTime( const QTime& ti) { 372void OEffectiveEvent::setStartTime( const QTime& ti) {
315 changeOrModify(); 373 changeOrModify();
316 data->start = ti; 374 data->start = ti;
317} 375}
318void OEffectiveEvent::setEndTime( const QTime& en) { 376void OEffectiveEvent::setEndTime( const QTime& en) {
319 changeOrModify(); 377 changeOrModify();
320 data->end = en; 378 data->end = en;
321} 379}
322void OEffectiveEvent::setEvent( const OEvent& ev) { 380void OEffectiveEvent::setEvent( const OEvent& ev) {
323 changeOrModify(); 381 changeOrModify();
324 data->event = ev; 382 data->event = ev;
325} 383}
326void OEffectiveEvent::setDate( const QDate& da) { 384void OEffectiveEvent::setDate( const QDate& da) {
327 changeOrModify(); 385 changeOrModify();
328 data->date = da; 386 data->date = da;
329} 387}
330void OEffectiveEvent::setEffectiveDates( const QDate& from, 388void OEffectiveEvent::setEffectiveDates( const QDate& from,
331 const QDate& to ) { 389 const QDate& to ) {
332 if (!from.isValid() ) { 390 if (!from.isValid() ) {
333 data->dates = false; 391 data->dates = false;
334 return; 392 return;
335 } 393 }
336 394
337 data->startDate = from; 395 data->startDate = from;
338 data->endDate = to; 396 data->endDate = to;
339} 397}
340QString OEffectiveEvent::description()const { 398QString OEffectiveEvent::description()const {
341 return data->event.description(); 399 return data->event.description();
342} 400}
343QString OEffectiveEvent::location()const { 401QString OEffectiveEvent::location()const {
344 return data->event.location(); 402 return data->event.location();
345} 403}
346QString OEffectiveEvent::note()const { 404QString OEffectiveEvent::note()const {
347 return data->event.note(); 405 return data->event.note();
348} 406}
349OEvent OEffectiveEvent::event()const { 407OEvent OEffectiveEvent::event()const {
350 return data->event; 408 return data->event;
351} 409}
352QTime OEffectiveEvent::startTime()const { 410QTime OEffectiveEvent::startTime()const {
353 return data->start; 411 return data->start;
354} 412}
355QTime OEffectiveEvent::endTime()const { 413QTime OEffectiveEvent::endTime()const {
356 return data->end; 414 return data->end;
357} 415}
358QDate OEffectiveEvent::date()const { 416QDate OEffectiveEvent::date()const {
359 return data->date; 417 return data->date;
360} 418}
361int OEffectiveEvent::length()const { 419int OEffectiveEvent::length()const {
362 return (data->end.hour() * 60 - data->start.hour() * 60) 420 return (data->end.hour() * 60 - data->start.hour() * 60)
363 + QABS(data->start.minute() - data->end.minute() ); 421 + QABS(data->start.minute() - data->end.minute() );
364} 422}
365int OEffectiveEvent::size()const { 423int OEffectiveEvent::size()const {
366 return ( data->end.hour() - data->start.hour() ) * 3600 424 return ( data->end.hour() - data->start.hour() ) * 3600
367 + (data->end.minute() - data->start.minute() * 60 425 + (data->end.minute() - data->start.minute() * 60
368 + data->end.second() - data->start.second() ); 426 + data->end.second() - data->start.second() );
369} 427}
370QDate OEffectiveEvent::startDate()const { 428QDate OEffectiveEvent::startDate()const {
371 if ( data->dates ) 429 if ( data->dates )
372 return data->startDate; 430 return data->startDate;
373 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer 431 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
374 return data->date; 432 return data->date;
375 else 433 else
376 return data->event.startDateTime().date(); 434 return data->event.startDateTime().date();
377} 435}
378QDate OEffectiveEvent::endDate()const { 436QDate OEffectiveEvent::endDate()const {
379 if ( data->dates ) 437 if ( data->dates )
380 return data->endDate; 438 return data->endDate;
381 else if ( data->event.hasRecurrence() ) 439 else if ( data->event.hasRecurrence() )
382 return data->date; 440 return data->date;
383 else 441 else
384 return data->event.endDateTime().date(); 442 return data->event.endDateTime().date();
385} 443}
386void OEffectiveEvent::deref() { 444void OEffectiveEvent::deref() {
387 if ( data->deref() ) { 445 if ( data->deref() ) {
388 delete data; 446 delete data;
389 data = 0; 447 data = 0;
390 } 448 }
391} 449}
392void OEffectiveEvent::changeOrModify() { 450void OEffectiveEvent::changeOrModify() {
393 if ( data->count != 1 ) { 451 if ( data->count != 1 ) {
394 data->deref(); 452 data->deref();
395 Data* d2 = new Data; 453 Data* d2 = new Data;
396 d2->event = data->event; 454 d2->event = data->event;
397 d2->date = data->date; 455 d2->date = data->date;
398 d2->start = data->start; 456 d2->start = data->start;
399 d2->end = data->end; 457 d2->end = data->end;
400 d2->startDate = data->startDate; 458 d2->startDate = data->startDate;
401 d2->endDate = data->endDate; 459 d2->endDate = data->endDate;
402 d2->dates = data->dates; 460 d2->dates = data->dates;
403 data = d2; 461 data = d2;
404 } 462 }
405} 463}
406bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{ 464bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
407 if ( data->date < e.date() ) 465 if ( data->date < e.date() )
408 return TRUE; 466 return TRUE;
409 if ( data->date == e.date() ) 467 if ( data->date == e.date() )
410 return ( startTime() < e.startTime() ); 468 return ( startTime() < e.startTime() );
411 else 469 else
412 return FALSE; 470 return FALSE;
413} 471}
414bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ 472bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
415 return (data->date <= e.date() ); 473 return (data->date <= e.date() );
416} 474}
417bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { 475bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
418 return ( date() == e.date() 476 return ( date() == e.date()
419 && startTime() == e.startTime() 477 && startTime() == e.startTime()
420 && endTime()== e.endTime() 478 && endTime()== e.endTime()
421 && event() == e.event() ); 479 && event() == e.event() );
422} 480}
423bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { 481bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
424 return !(*this == e ); 482 return !(*this == e );
425} 483}
426bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { 484bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
427 return !(*this <= e ); 485 return !(*this <= e );
428} 486}
429bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { 487bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
430 return !(*this < e); 488 return !(*this < e);
431} 489}
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
@@ -1,198 +1,206 @@
1// CONTAINS GPLed code of TT 1// CONTAINS GPLed code of TT
2 2
3#ifndef OPIE_PIM_EVENT_H 3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H 4#define OPIE_PIM_EVENT_H
5 5
6#include <qstring.h> 6#include <qstring.h>
7#include <qdatetime.h> 7#include <qdatetime.h>
8#include <qvaluelist.h> 8#include <qvaluelist.h>
9 9
10#include <qpe/recordfields.h> 10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h> 11#include <qpe/palmtopuidgen.h>
12 12
13#include "otimezone.h" 13#include "otimezone.h"
14#include "opimrecord.h" 14#include "opimrecord.h"
15 15
16struct OCalendarHelper { 16struct OCalendarHelper {
17 /** calculate the week number of the date */ 17 /** calculate the week number of the date */
18 static int week( const QDate& ); 18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */ 19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& ); 20 static int ocurrence( const QDate& );
21 21
22 // returns the dayOfWeek for the *first* day it finds (ignores 22 // returns the dayOfWeek for the *first* day it finds (ignores
23 // any further days!). Returns 1 (Monday) if there isn't any day found 23 // any further days!). Returns 1 (Monday) if there isn't any day found
24 static int dayOfWeek( char day ); 24 static int dayOfWeek( char day );
25 25
26 /** returns the diff of month */ 26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second ); 27 static int monthDiff( const QDate& first, const QDate& second );
28 28
29}; 29};
30 30
31class OPimNotifyManager; 31class OPimNotifyManager;
32class ORecur; 32class ORecur;
33class OEvent : public OPimRecord { 33class OEvent : public OPimRecord {
34public: 34public:
35 typedef QValueList<OEvent> ValueList; 35 typedef QValueList<OEvent> ValueList;
36 enum RecordFields { 36 enum RecordFields {
37 Uid = Qtopia::UID_ID, 37 Uid = Qtopia::UID_ID,
38 Category = Qtopia::CATEGORY_ID, 38 Category = Qtopia::CATEGORY_ID,
39 Description, 39 Description,
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:
127 inline void changeOrModify(); 135 inline void changeOrModify();
128 void deref(); 136 void deref();
129 struct Data; 137 struct Data;
130 Data* data; 138 Data* data;
131 class Private; 139 class Private;
132 Private* priv; 140 Private* priv;
133 141
134}; 142};
135 143
136/** 144/**
137 * AN Event can span through multiple days. We split up a multiday eve 145 * AN Event can span through multiple days. We split up a multiday eve
138 */ 146 */
139 147
140class OEffectiveEvent { 148class OEffectiveEvent {
141public: 149public:
142 typedef QValueList<OEffectiveEvent> ValueList; 150 typedef QValueList<OEffectiveEvent> ValueList;
143 enum Position { MidWay, Start, End, StartEnd }; 151 enum Position { MidWay, Start, End, StartEnd };
144 // If we calculate the effective event of a multi-day event 152 // If we calculate the effective event of a multi-day event
145 // we have to figure out whether we are at the first day, 153 // we have to figure out whether we are at the first day,
146 // at the end, or anywhere else ("middle"). This is important 154 // at the end, or anywhere else ("middle"). This is important
147 // for the start/end times (00:00/23:59) 155 // for the start/end times (00:00/23:59)
148 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- 156 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
149 // day event 157 // day event
150 // Start: start time -> 23:59 158 // Start: start time -> 23:59
151 // End: 00:00 -> end time 159 // End: 00:00 -> end time
152 // Start | End == StartEnd: for single-day events (default) 160 // Start | End == StartEnd: for single-day events (default)
153 // here we draw start time -> end time 161 // here we draw start time -> end time
154 OEffectiveEvent(); 162 OEffectiveEvent();
155 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); 163 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
156 OEffectiveEvent( const OEffectiveEvent& ); 164 OEffectiveEvent( const OEffectiveEvent& );
157 OEffectiveEvent &operator=(const OEffectiveEvent& ); 165 OEffectiveEvent &operator=(const OEffectiveEvent& );
158 ~OEffectiveEvent(); 166 ~OEffectiveEvent();
159 167
160 void setStartTime( const QTime& ); 168 void setStartTime( const QTime& );
161 void setEndTime( const QTime& ); 169 void setEndTime( const QTime& );
162 void setEvent( const OEvent& ); 170 void setEvent( const OEvent& );
163 void setDate( const QDate& ); 171 void setDate( const QDate& );
164 172
165 void setEffectiveDates( const QDate& from, const QDate& to ); 173 void setEffectiveDates( const QDate& from, const QDate& to );
166 174
167 QString description()const; 175 QString description()const;
168 QString location()const; 176 QString location()const;
169 QString note()const; 177 QString note()const;
170 OEvent event()const; 178 OEvent event()const;
171 QTime startTime()const; 179 QTime startTime()const;
172 QTime endTime()const; 180 QTime endTime()const;
173 QDate date()const; 181 QDate date()const;
174 182
175 /* return the length in hours */ 183 /* return the length in hours */
176 int length()const; 184 int length()const;
177 int size()const; 185 int size()const;
178 186
179 QDate startDate()const; 187 QDate startDate()const;
180 QDate endDate()const; 188 QDate endDate()const;
181 189
182 bool operator<( const OEffectiveEvent &e ) const; 190 bool operator<( const OEffectiveEvent &e ) const;
183 bool operator<=( const OEffectiveEvent &e ) const; 191 bool operator<=( const OEffectiveEvent &e ) const;
184 bool operator==( const OEffectiveEvent &e ) const; 192 bool operator==( const OEffectiveEvent &e ) const;
185 bool operator!=( const OEffectiveEvent &e ) const; 193 bool operator!=( const OEffectiveEvent &e ) const;
186 bool operator>( const OEffectiveEvent &e ) const; 194 bool operator>( const OEffectiveEvent &e ) const;
187 bool operator>= ( const OEffectiveEvent &e ) const; 195 bool operator>= ( const OEffectiveEvent &e ) const;
188 196
189private: 197private:
190 void deref(); 198 void deref();
191 inline void changeOrModify(); 199 inline void changeOrModify();
192 class Private; 200 class Private;
193 Private* priv; 201 Private* priv;
194 struct Data; 202 struct Data;
195 Data* data; 203 Data* data;
196 204
197}; 205};
198#endif 206#endif