-rw-r--r-- | library/datebookdb.cpp | 1121 |
1 files changed, 1121 insertions, 0 deletions
diff --git a/library/datebookdb.cpp b/library/datebookdb.cpp new file mode 100644 index 0000000..bf7fd94 --- a/dev/null +++ b/library/datebookdb.cpp | |||
@@ -0,0 +1,1121 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2000 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | #include <qasciidict.h> | ||
22 | #include <qfile.h> | ||
23 | #include <qmessagebox.h> | ||
24 | #include <qstring.h> | ||
25 | #include <qtextcodec.h> | ||
26 | #include <qtextstream.h> | ||
27 | #include <qtl.h> | ||
28 | |||
29 | #include <qpe/alarmserver.h> | ||
30 | #include <qpe/global.h> | ||
31 | #include "datebookdb.h" | ||
32 | #include <qpe/stringutil.h> | ||
33 | #include <qpe/timeconversion.h> | ||
34 | |||
35 | #include <errno.h> | ||
36 | #include <stdlib.h> | ||
37 | |||
38 | |||
39 | class DateBookDBPrivate | ||
40 | { | ||
41 | public: | ||
42 | bool clean; // indcate whether we need to write to disk... | ||
43 | }; | ||
44 | |||
45 | |||
46 | // Helper functions | ||
47 | |||
48 | static QString dateBookJournalFile() | ||
49 | { | ||
50 | QString str = getenv("HOME"); | ||
51 | return QString( str +"/.caljournal" ); | ||
52 | } | ||
53 | |||
54 | static QString dateBookFilename() | ||
55 | { | ||
56 | return Global::applicationFileName("datebook","datebook.xml"); | ||
57 | } | ||
58 | |||
59 | /* Calculating the next event of a recuring event is actually | ||
60 | computationally inexpensive, esp. compared to checking each day | ||
61 | individually. There are bad worse cases for say the 29th of | ||
62 | february or the 31st of some other months. However | ||
63 | these are still bounded */ | ||
64 | bool nextOccurance(const Event &e, const QDate &from, QDateTime &next) | ||
65 | { | ||
66 | // easy checks, first are we too far in the future or too far in the past? | ||
67 | QDate tmpDate; | ||
68 | int freq = e.repeatPattern().frequency; | ||
69 | int diff, diff2, a; | ||
70 | int iday, imonth, iyear; | ||
71 | int dayOfWeek = 0; | ||
72 | int firstOfWeek = 0; | ||
73 | int weekOfMonth; | ||
74 | |||
75 | |||
76 | if (e.repeatPattern().hasEndDate && e.repeatPattern().endDate() < from) | ||
77 | return FALSE; | ||
78 | |||
79 | if (e.start() >= from) { | ||
80 | next = e.start(); | ||
81 | return TRUE; | ||
82 | } | ||
83 | |||
84 | switch ( e.repeatPattern().type ) { | ||
85 | case Event::Weekly: | ||
86 | /* weekly is just daily by 7 */ | ||
87 | /* first convert the repeatPattern.Days() mask to the next | ||
88 | day of week valid after from */ | ||
89 | dayOfWeek = from.dayOfWeek(); | ||
90 | dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ | ||
91 | |||
92 | /* this is done in case freq > 1 and from in week not | ||
93 | for this round */ | ||
94 | // firstOfWeek = 0; this is already done at decl. | ||
95 | while(!((1 << firstOfWeek) & e.repeatPattern().days)) | ||
96 | firstOfWeek++; | ||
97 | |||
98 | /* there is at least one 'day', or there would be no event */ | ||
99 | while(!((1 << (dayOfWeek % 7)) & e.repeatPattern().days)) | ||
100 | dayOfWeek++; | ||
101 | |||
102 | dayOfWeek = dayOfWeek % 7; /* the actual day of week */ | ||
103 | dayOfWeek -= e.start().date().dayOfWeek() -1; | ||
104 | |||
105 | firstOfWeek = firstOfWeek % 7; /* the actual first of week */ | ||
106 | firstOfWeek -= e.start().date().dayOfWeek() -1; | ||
107 | |||
108 | // dayOfWeek may be negitive now | ||
109 | // day of week is number of days to add to start day | ||
110 | |||
111 | freq *= 7; | ||
112 | // FALL-THROUGH !!!!! | ||
113 | case Event::Daily: | ||
114 | // the add is for the possible fall through from weekly */ | ||
115 | if(e.start().date().addDays(dayOfWeek) > from) { | ||
116 | /* first week exception */ | ||
117 | next = QDateTime(e.start().date().addDays(dayOfWeek), | ||
118 | e.start().time()); | ||
119 | if ((next.date() > e.repeatPattern().endDate()) | ||
120 | && e.repeatPattern().hasEndDate) | ||
121 | return FALSE; | ||
122 | return TRUE; | ||
123 | } | ||
124 | /* if from is middle of a non-week */ | ||
125 | |||
126 | diff = e.start().date().addDays(dayOfWeek).daysTo(from) % freq; | ||
127 | diff2 = e.start().date().addDays(firstOfWeek).daysTo(from) % freq; | ||
128 | |||
129 | if(diff != 0) | ||
130 | diff = freq - diff; | ||
131 | if(diff2 != 0) | ||
132 | diff2 = freq - diff2; | ||
133 | diff = QMIN(diff, diff2); | ||
134 | |||
135 | next = QDateTime(from.addDays(diff), e.start().time()); | ||
136 | if ( (next.date() > e.repeatPattern().endDate()) | ||
137 | && e.repeatPattern().hasEndDate ) | ||
138 | return FALSE; | ||
139 | return TRUE; | ||
140 | case Event::MonthlyDay: | ||
141 | iday = from.day(); | ||
142 | iyear = from.year(); | ||
143 | imonth = from.month(); | ||
144 | /* find equivelent day of month for this month */ | ||
145 | dayOfWeek = e.start().date().dayOfWeek(); | ||
146 | weekOfMonth = (e.start().date().day() - 1) / 7; | ||
147 | |||
148 | /* work out when the next valid month is */ | ||
149 | a = from.year() - e.start().date().year(); | ||
150 | a *= 12; | ||
151 | a = a + (imonth - e.start().date().month()); | ||
152 | /* a is e.start()monthsFrom(from); */ | ||
153 | if(a % freq) { | ||
154 | a = freq - (a % freq); | ||
155 | imonth = from.month() + a; | ||
156 | if (imonth > 12) { | ||
157 | imonth--; | ||
158 | iyear += imonth / 12; | ||
159 | imonth = imonth % 12; | ||
160 | imonth++; | ||
161 | } | ||
162 | } | ||
163 | /* imonth is now the first month after or on | ||
164 | from that matches the frequency given */ | ||
165 | |||
166 | /* find for this month */ | ||
167 | tmpDate = QDate( iyear, imonth, 1 ); | ||
168 | |||
169 | iday = 1; | ||
170 | iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; | ||
171 | iday += 7 * weekOfMonth; | ||
172 | while (iday > tmpDate.daysInMonth()) { | ||
173 | imonth += freq; | ||
174 | if (imonth > 12) { | ||
175 | imonth--; | ||
176 | iyear += imonth / 12; | ||
177 | imonth = imonth % 12; | ||
178 | imonth++; | ||
179 | } | ||
180 | tmpDate = QDate( iyear, imonth, 1 ); | ||
181 | /* these loops could go for a while, check end case now */ | ||
182 | if ((tmpDate > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
183 | return FALSE; | ||
184 | iday = 1; | ||
185 | iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; | ||
186 | iday += 7 * weekOfMonth; | ||
187 | } | ||
188 | tmpDate = QDate(iyear, imonth, iday); | ||
189 | |||
190 | if (tmpDate >= from) { | ||
191 | next = QDateTime(tmpDate, e.start().time()); | ||
192 | if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
193 | return FALSE; | ||
194 | return TRUE; | ||
195 | } | ||
196 | |||
197 | /* need to find the next iteration */ | ||
198 | do { | ||
199 | imonth += freq; | ||
200 | if (imonth > 12) { | ||
201 | imonth--; | ||
202 | iyear += imonth / 12; | ||
203 | imonth = imonth % 12; | ||
204 | imonth++; | ||
205 | } | ||
206 | tmpDate = QDate( iyear, imonth, 1 ); | ||
207 | /* these loops could go for a while, check end case now */ | ||
208 | if ((tmpDate > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
209 | return FALSE; | ||
210 | iday = 1; | ||
211 | iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; | ||
212 | iday += 7 * weekOfMonth; | ||
213 | } while (iday > tmpDate.daysInMonth()); | ||
214 | tmpDate = QDate(iyear, imonth, iday); | ||
215 | |||
216 | next = QDateTime(tmpDate, e.start().time()); | ||
217 | if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
218 | return FALSE; | ||
219 | return TRUE; | ||
220 | case Event::MonthlyDate: | ||
221 | iday = e.start().date().day(); | ||
222 | iyear = from.year(); | ||
223 | imonth = from.month(); | ||
224 | |||
225 | a = from.year() - e.start().date().year(); | ||
226 | a *= 12; | ||
227 | a = a + (imonth - e.start().date().month()); | ||
228 | /* a is e.start()monthsFrom(from); */ | ||
229 | if(a % freq) { | ||
230 | a = freq - (a % freq); | ||
231 | imonth = from.month() + a; | ||
232 | if (imonth > 12) { | ||
233 | imonth--; | ||
234 | iyear += imonth / 12; | ||
235 | imonth = imonth % 12; | ||
236 | imonth++; | ||
237 | } | ||
238 | } | ||
239 | /* imonth is now the first month after or on | ||
240 | from that matches the frequencey given */ | ||
241 | |||
242 | /* this could go for a while, worse case, 4*12 iterations, probably */ | ||
243 | while(!QDate::isValid(iyear, imonth, iday) ) { | ||
244 | imonth += freq; | ||
245 | if (imonth > 12) { | ||
246 | imonth--; | ||
247 | iyear += imonth / 12; | ||
248 | imonth = imonth % 12; | ||
249 | imonth++; | ||
250 | } | ||
251 | /* these loops could go for a while, check end case now */ | ||
252 | if ((QDate(iyear, imonth, 1) > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
253 | return FALSE; | ||
254 | } | ||
255 | |||
256 | if(QDate(iyear, imonth, iday) >= from) { | ||
257 | /* done */ | ||
258 | next = QDateTime(QDate(iyear, imonth, iday), | ||
259 | e.start().time()); | ||
260 | if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
261 | return FALSE; | ||
262 | return TRUE; | ||
263 | } | ||
264 | |||
265 | /* ok, need to cycle */ | ||
266 | imonth += freq; | ||
267 | imonth--; | ||
268 | iyear += imonth / 12; | ||
269 | imonth = imonth % 12; | ||
270 | imonth++; | ||
271 | |||
272 | while(!QDate::isValid(iyear, imonth, iday) ) { | ||
273 | imonth += freq; | ||
274 | imonth--; | ||
275 | iyear += imonth / 12; | ||
276 | imonth = imonth % 12; | ||
277 | imonth++; | ||
278 | if ((QDate(iyear, imonth, 1) > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
279 | return FALSE; | ||
280 | } | ||
281 | |||
282 | next = QDateTime(QDate(iyear, imonth, iday), e.start().time()); | ||
283 | if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
284 | return FALSE; | ||
285 | return TRUE; | ||
286 | case Event::Yearly: | ||
287 | iday = e.start().date().day(); | ||
288 | imonth = e.start().date().month(); | ||
289 | iyear = from.year(); // after all, we want to start in this year | ||
290 | |||
291 | diff = 1; | ||
292 | if(imonth == 2 && iday > 28) { | ||
293 | /* leap year, and it counts, calculate actual frequency */ | ||
294 | if(freq % 4) | ||
295 | if (freq % 2) | ||
296 | freq = freq * 4; | ||
297 | else | ||
298 | freq = freq * 2; | ||
299 | /* else divides by 4 already, leave freq alone */ | ||
300 | diff = 4; | ||
301 | } | ||
302 | |||
303 | a = from.year() - e.start().date().year(); | ||
304 | if(a % freq) { | ||
305 | a = freq - (a % freq); | ||
306 | iyear = iyear + a; | ||
307 | } | ||
308 | |||
309 | /* under the assumption we won't hit one of the special not-leap years twice */ | ||
310 | if(!QDate::isValid(iyear, imonth, iday)) { | ||
311 | /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ | ||
312 | iyear += freq; | ||
313 | } | ||
314 | |||
315 | if(QDate(iyear, imonth, iday) >= from) { | ||
316 | next = QDateTime(QDate(iyear, imonth, iday), | ||
317 | e.start().time()); | ||
318 | if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
319 | return FALSE; | ||
320 | return TRUE; | ||
321 | } | ||
322 | /* iyear == from.year(), need to advance again */ | ||
323 | iyear += freq; | ||
324 | /* under the assumption we won't hit one of the special not-leap years twice */ | ||
325 | if(!QDate::isValid(iyear, imonth, iday)) { | ||
326 | /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ | ||
327 | iyear += freq; | ||
328 | } | ||
329 | |||
330 | next = QDateTime(QDate(iyear, imonth, iday), e.start().time()); | ||
331 | if ((next.date() > e.repeatPattern().endDate()) && e.repeatPattern().hasEndDate) | ||
332 | return FALSE; | ||
333 | return TRUE; | ||
334 | default: | ||
335 | return FALSE; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | static bool nextAlarm( const Event &ev, QDateTime& when, int& warn) | ||
340 | { | ||
341 | QDateTime now = QDateTime::currentDateTime(); | ||
342 | if ( ev.hasRepeat() ) { | ||
343 | QDateTime ralarm; | ||
344 | if (nextOccurance(ev, now.date(), ralarm)) { | ||
345 | ralarm = ralarm.addSecs(-ev.alarmTime()*60); | ||
346 | if ( ralarm > now ) { | ||
347 | when = ralarm; | ||
348 | warn = ev.alarmTime(); | ||
349 | } else if ( nextOccurance(ev, now.date().addDays(1), ralarm) ) { | ||
350 | ralarm = ralarm.addSecs( -ev.alarmTime()*60 ); | ||
351 | if ( ralarm > now ) { | ||
352 | when = ralarm; | ||
353 | warn = ev.alarmTime(); | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | } else { | ||
358 | warn = ev.alarmTime(); | ||
359 | when = ev.start().addSecs( -ev.alarmTime()*60 ); | ||
360 | } | ||
361 | return when > now; | ||
362 | } | ||
363 | |||
364 | static void addEventAlarm( const Event &ev ) | ||
365 | { | ||
366 | QDateTime when; | ||
367 | int warn; | ||
368 | if ( nextAlarm(ev,when,warn) ) | ||
369 | AlarmServer::addAlarm( when, | ||
370 | "QPE/Application/datebook", | ||
371 | "alarm(QDateTime,int)", warn ); | ||
372 | } | ||
373 | |||
374 | static void delEventAlarm( const Event &ev ) | ||
375 | { | ||
376 | QDateTime when; | ||
377 | int warn; | ||
378 | if ( nextAlarm(ev,when,warn) ) | ||
379 | AlarmServer::deleteAlarm( when, | ||
380 | "QPE/Application/datebook", | ||
381 | "alarm(QDateTime,int)", warn ); | ||
382 | } | ||
383 | |||
384 | |||
385 | DateBookDB::DateBookDB() | ||
386 | { | ||
387 | init(); | ||
388 | } | ||
389 | |||
390 | DateBookDB::~DateBookDB() | ||
391 | { | ||
392 | save(); | ||
393 | eventList.clear(); | ||
394 | repeatEvents.clear(); | ||
395 | } | ||
396 | |||
397 | |||
398 | //#### Why is this code duplicated in getEffectiveEvents ????? | ||
399 | //#### Addendum. Don't use this function, lets faze it out if we can. | ||
400 | QValueList<Event> DateBookDB::getEvents( const QDate &from, const QDate &to ) | ||
401 | { | ||
402 | QValueList<Event> tmpList; | ||
403 | tmpList = getNonRepeatingEvents( from, to ); | ||
404 | |||
405 | // check for repeating events... | ||
406 | for (QValueList<Event>::ConstIterator it = repeatEvents.begin(); | ||
407 | it != repeatEvents.end(); ++it) { | ||
408 | QDate itDate = from; | ||
409 | QDateTime due; | ||
410 | |||
411 | /* create a false end date, to short circuit on hard | ||
412 | MonthlyDay recurences */ | ||
413 | Event dummy_event = *it; | ||
414 | Event::RepeatPattern r = dummy_event.repeatPattern(); | ||
415 | if ( !r.hasEndDate || r.endDate() > to ) { | ||
416 | r.setEndDate( to ); | ||
417 | r.hasEndDate = TRUE; | ||
418 | } | ||
419 | dummy_event.setRepeat(TRUE, r); | ||
420 | |||
421 | while (nextOccurance(dummy_event, itDate, due)) { | ||
422 | if (due.date() > to) | ||
423 | break; | ||
424 | Event newEvent = *it; | ||
425 | newEvent.setStart(due); | ||
426 | newEvent.setEnd(due.addSecs((*it).start().secsTo((*it).end()))); | ||
427 | |||
428 | tmpList.append(newEvent); | ||
429 | itDate = due.date().addDays(1); /* the next event */ | ||
430 | } | ||
431 | } | ||
432 | qHeapSort(tmpList); | ||
433 | return tmpList; | ||
434 | } | ||
435 | |||
436 | QValueList<Event> DateBookDB::getEvents( const QDateTime &start ) | ||
437 | { | ||
438 | QValueList<Event> day = getEvents(start.date(),start.date()); | ||
439 | |||
440 | QValueListConstIterator<Event> it; | ||
441 | QDateTime dtTmp; | ||
442 | QValueList<Event> tmpList; | ||
443 | for (it = day.begin(); it != day.end(); ++it ) { | ||
444 | dtTmp = (*it).start(TRUE); | ||
445 | if ( dtTmp == start ) | ||
446 | tmpList.append( *it ); | ||
447 | } | ||
448 | return tmpList; | ||
449 | } | ||
450 | |||
451 | //#### Why is this code duplicated in getEvents ????? | ||
452 | |||
453 | QValueList<EffectiveEvent> DateBookDB::getEffectiveEvents( const QDate &from, | ||
454 | const QDate &to ) | ||
455 | { | ||
456 | QValueList<EffectiveEvent> tmpList; | ||
457 | QValueListIterator<Event> it; | ||
458 | |||
459 | EffectiveEvent effEv; | ||
460 | QDateTime dtTmp, | ||
461 | dtEnd; | ||
462 | |||
463 | for (it = eventList.begin(); it != eventList.end(); ++it ) { | ||
464 | dtTmp = (*it).start(TRUE); | ||
465 | dtEnd = (*it).end(TRUE); | ||
466 | |||
467 | if ( dtTmp.date() >= from && dtTmp.date() <= to ) { | ||
468 | Event tmpEv = *it; | ||
469 | effEv.setEvent(tmpEv); | ||
470 | effEv.setDate( dtTmp.date() ); | ||
471 | effEv.setStart( dtTmp.time() ); | ||
472 | if ( dtTmp.date() != dtEnd.date() ) | ||
473 | effEv.setEnd( QTime(23, 59, 0) ); | ||
474 | else | ||
475 | effEv.setEnd( dtEnd.time() ); | ||
476 | tmpList.append( effEv ); | ||
477 | } | ||
478 | // we must also check for end date information... | ||
479 | if ( dtEnd.date() != dtTmp.date() && dtEnd.date() >= from ) { | ||
480 | QDateTime dt = dtTmp.addDays( 1 ); | ||
481 | dt.setTime( QTime(0, 0, 0) ); | ||
482 | QDateTime dtStop; | ||
483 | if ( dtEnd > to ) { | ||
484 | dtStop = to; | ||
485 | } else | ||
486 | dtStop = dtEnd; | ||
487 | while ( dt <= dtStop ) { | ||
488 | Event tmpEv = *it; | ||
489 | effEv.setEvent( tmpEv ); | ||
490 | effEv.setDate( dt.date() ); | ||
491 | if ( dt >= from ) { | ||
492 | effEv.setStart( QTime(0, 0, 0) ); | ||
493 | if ( dt.date() == dtEnd.date() ) | ||
494 | effEv.setEnd( dtEnd.time() ); | ||
495 | else | ||
496 | effEv.setEnd( QTime(23, 59, 59) ); | ||
497 | tmpList.append( effEv ); | ||
498 | } | ||
499 | dt = dt.addDays( 1 ); | ||
500 | } | ||
501 | } | ||
502 | } | ||
503 | // check for repeating events... | ||
504 | QDateTime repeat; | ||
505 | for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) { | ||
506 | |||
507 | /* create a false end date, to short circuit on hard | ||
508 | MonthlyDay recurences */ | ||
509 | Event dummy_event = *it; | ||
510 | int duration = (*it).start().date().daysTo( (*it).end().date() ); | ||
511 | QDate itDate = from.addDays(-duration); | ||
512 | |||
513 | Event::RepeatPattern r = dummy_event.repeatPattern(); | ||
514 | if ( !r.hasEndDate || r.endDate() > to ) { | ||
515 | r.setEndDate( to ); | ||
516 | r.hasEndDate = TRUE; | ||
517 | } | ||
518 | dummy_event.setRepeat(TRUE, r); | ||
519 | |||
520 | while (nextOccurance(dummy_event, itDate, repeat)) { | ||
521 | if(repeat.date() > to) | ||
522 | break; | ||
523 | effEv.setDate( repeat.date() ); | ||
524 | if ((*it).type() == Event::AllDay) { | ||
525 | effEv.setStart( QTime(0,0,0) ); | ||
526 | effEv.setEnd( QTime(23,59,59) ); | ||
527 | } else { | ||
528 | /* we only occur by days, not hours/minutes/seconds. Hence | ||
529 | the actual end and start times will be the same for | ||
530 | every repeated event. For multi day events this is | ||
531 | fixed up later if on wronge day span */ | ||
532 | effEv.setStart( (*it).start().time() ); | ||
533 | effEv.setEnd( (*it).end().time() ); | ||
534 | } | ||
535 | if ( duration != 0 ) { | ||
536 | // multi-day repeating events | ||
537 | QDate sub_it = QMAX( repeat.date(), from ); | ||
538 | QDate startDate = repeat.date(); | ||
539 | QDate endDate = startDate.addDays( duration ); | ||
540 | |||
541 | while ( sub_it <= endDate && sub_it <= to ) { | ||
542 | EffectiveEvent tmpEffEv = effEv; | ||
543 | Event tmpEv = *it; | ||
544 | tmpEffEv.setEvent( tmpEv ); | ||
545 | |||
546 | if ( sub_it != startDate ) | ||
547 | tmpEffEv.setStart( QTime(0,0,0) ); | ||
548 | if ( sub_it != endDate ) | ||
549 | tmpEffEv.setEnd( QTime(23,59,59) ); | ||
550 | tmpEffEv.setDate( sub_it ); | ||
551 | tmpEffEv.setEffectiveDates( startDate, endDate ); | ||
552 | tmpList.append( tmpEffEv ); | ||
553 | sub_it = sub_it.addDays( 1 ); | ||
554 | } | ||
555 | itDate = endDate; | ||
556 | } else { | ||
557 | Event tmpEv = *it; | ||
558 | effEv.setEvent( tmpEv ); | ||
559 | tmpList.append( effEv ); | ||
560 | itDate = repeat.date().addDays( 1 ); | ||
561 | } | ||
562 | } | ||
563 | } | ||
564 | |||
565 | qHeapSort( tmpList ); | ||
566 | return tmpList; | ||
567 | } | ||
568 | |||
569 | QValueList<EffectiveEvent> DateBookDB::getEffectiveEvents( const QDateTime &dt) | ||
570 | { | ||
571 | QValueList<EffectiveEvent> day = getEffectiveEvents(dt.date(), dt.date()); | ||
572 | QValueListConstIterator<EffectiveEvent> it; | ||
573 | QValueList<EffectiveEvent> tmpList; | ||
574 | QDateTime dtTmp; | ||
575 | |||
576 | for (it = day.begin(); it != day.end(); ++it ) { | ||
577 | dtTmp = QDateTime( (*it).date(), (*it).start() ); | ||
578 | // at the moment we don't have second granularity, be nice about that.. | ||
579 | if ( QABS(dt.secsTo(dtTmp)) < 60 ) | ||
580 | tmpList.append( *it ); | ||
581 | } | ||
582 | return tmpList; | ||
583 | } | ||
584 | |||
585 | |||
586 | void DateBookDB::addEvent( const Event &ev, bool doalarm ) | ||
587 | { | ||
588 | // write to the journal... | ||
589 | saveJournalEntry( ev, ACTION_ADD, -1, false ); | ||
590 | addJFEvent( ev, doalarm ); | ||
591 | d->clean = false; | ||
592 | } | ||
593 | |||
594 | void DateBookDB::addJFEvent( const Event &ev, bool doalarm ) | ||
595 | { | ||
596 | if ( doalarm && ev.hasAlarm() ) | ||
597 | addEventAlarm( ev ); | ||
598 | if ( ev.hasRepeat() ) | ||
599 | repeatEvents.append( ev ); | ||
600 | else | ||
601 | eventList.append( ev ); | ||
602 | } | ||
603 | |||
604 | void DateBookDB::editEvent( const Event &old, Event &editedEv ) | ||
605 | { | ||
606 | int oldIndex=0; | ||
607 | bool oldHadRepeat = old.hasRepeat(); | ||
608 | Event orig; | ||
609 | |||
610 | // write to the journal... | ||
611 | if ( oldHadRepeat ) { | ||
612 | if ( origRepeat( old, orig ) ) // should work always... | ||
613 | oldIndex = repeatEvents.findIndex( orig ); | ||
614 | } else | ||
615 | oldIndex = eventList.findIndex( old ); | ||
616 | saveJournalEntry( editedEv, ACTION_REPLACE, oldIndex, oldHadRepeat ); | ||
617 | |||
618 | if ( old.hasAlarm() ) | ||
619 | delEventAlarm( old ); | ||
620 | if ( oldHadRepeat ) { | ||
621 | if ( oldHadRepeat && editedEv.hasRepeat() ) { | ||
622 | // assumption, when someone edits a repeating event, they | ||
623 | // want to change them all, maybe not perfect, but it works | ||
624 | // for the moment... | ||
625 | repeatEvents.remove( orig ); | ||
626 | } else | ||
627 | removeRepeat( old ); | ||
628 | } else { | ||
629 | QValueList<Event>::Iterator it = eventList.find( old ); | ||
630 | if ( it != eventList.end() ) | ||
631 | eventList.remove( it ); | ||
632 | } | ||
633 | if ( editedEv.hasAlarm() ) | ||
634 | addEventAlarm( editedEv ); | ||
635 | if ( editedEv.hasRepeat() ) | ||
636 | repeatEvents.append( editedEv ); | ||
637 | else | ||
638 | eventList.append( editedEv ); | ||
639 | d->clean = false; | ||
640 | } | ||
641 | |||
642 | void DateBookDB::removeEvent( const Event &ev ) | ||
643 | { | ||
644 | // write to the journal... | ||
645 | saveJournalEntry( ev, ACTION_REMOVE, -1, false ); | ||
646 | removeJFEvent( ev ); | ||
647 | d->clean = false; | ||
648 | } | ||
649 | |||
650 | void DateBookDB::removeJFEvent( const Event&ev ) | ||
651 | { | ||
652 | if ( ev.hasAlarm() ) | ||
653 | delEventAlarm( ev ); | ||
654 | if ( ev.hasRepeat() ) { | ||
655 | removeRepeat( ev ); | ||
656 | } else { | ||
657 | QValueList<Event>::Iterator it = eventList.find( ev ); | ||
658 | if ( it != eventList.end() ) | ||
659 | eventList.remove( it ); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | // also handles journaling... | ||
664 | void DateBookDB::loadFile( const QString &strFile ) | ||
665 | { | ||
666 | |||
667 | QFile f( strFile ); | ||
668 | if ( !f.open( IO_ReadOnly ) ) | ||
669 | return; | ||
670 | |||
671 | enum Attribute { | ||
672 | FDescription = 0, | ||
673 | FLocation, | ||
674 | FCategories, | ||
675 | FUid, | ||
676 | FType, | ||
677 | FAlarm, | ||
678 | FSound, | ||
679 | FRType, | ||
680 | FRWeekdays, | ||
681 | FRPosition, | ||
682 | FRFreq, | ||
683 | FRHasEndDate, | ||
684 | FREndDate, | ||
685 | FRStart, | ||
686 | FREnd, | ||
687 | FNote, | ||
688 | FCreated, | ||
689 | FAction, | ||
690 | FActionKey, | ||
691 | FJournalOrigHadRepeat | ||
692 | }; | ||
693 | |||
694 | QAsciiDict<int> dict( 97 ); | ||
695 | dict.setAutoDelete( TRUE ); | ||
696 | dict.insert( "description", new int(FDescription) ); | ||
697 | dict.insert( "location", new int(FLocation) ); | ||
698 | dict.insert( "categories", new int(FCategories) ); | ||
699 | dict.insert( "uid", new int(FUid) ); | ||
700 | dict.insert( "type", new int(FType) ); | ||
701 | dict.insert( "alarm", new int(FAlarm) ); | ||
702 | dict.insert( "sound", new int(FSound) ); | ||
703 | dict.insert( "rtype", new int(FRType) ); | ||
704 | dict.insert( "rweekdays", new int(FRWeekdays) ); | ||
705 | dict.insert( "rposition", new int(FRPosition) ); | ||
706 | dict.insert( "rfreq", new int(FRFreq) ); | ||
707 | dict.insert( "rhasenddate", new int(FRHasEndDate) ); | ||
708 | dict.insert( "enddt", new int(FREndDate) ); | ||
709 | dict.insert( "start", new int(FRStart) ); | ||
710 | dict.insert( "end", new int(FREnd) ); | ||
711 | dict.insert( "note", new int(FNote) ); | ||
712 | dict.insert( "created", new int(FCreated) ); | ||
713 | dict.insert( "action", new int(FAction) ); | ||
714 | dict.insert( "actionkey", new int(FActionKey) ); | ||
715 | dict.insert( "actionorig", new int (FJournalOrigHadRepeat) ); | ||
716 | |||
717 | |||
718 | QByteArray ba = f.readAll(); | ||
719 | char* dt = ba.data(); | ||
720 | int len = ba.size(); | ||
721 | int currentAction, | ||
722 | journalKey, | ||
723 | origHadRepeat; // should be bool, but we need tri-state(not being used) | ||
724 | |||
725 | int i = 0; | ||
726 | char *point; | ||
727 | while ( ( point = strstr( dt+i, "<event " ) ) != 0 ) { | ||
728 | i = point - dt; | ||
729 | // if we are reading in events in the general case, | ||
730 | // we are just adding them, so let the actions represent that... | ||
731 | currentAction = ACTION_ADD; | ||
732 | journalKey = -1; | ||
733 | origHadRepeat = -1; | ||
734 | // some temporary variables for dates and times ... | ||
735 | //int startY = 0, startM = 0, startD = 0, starth = 0, startm = 0, starts = 0; | ||
736 | //int endY = 0, endM = 0, endD = 0, endh = 0, endm = 0, ends = 0; | ||
737 | //int enddtY = 0, enddtM = 0, enddtD = 0; | ||
738 | |||
739 | // ... for the alarm settings ... | ||
740 | int alarmTime = -1; Event::SoundTypeChoice alarmSound = Event::Silent; | ||
741 | // ... and for the recurrence | ||
742 | Event::RepeatPattern rp; | ||
743 | Event e; | ||
744 | |||
745 | i += 7; | ||
746 | |||
747 | while( 1 ) { | ||
748 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) | ||
749 | ++i; | ||
750 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) | ||
751 | break; | ||
752 | // we have another attribute, read it. | ||
753 | int j = i; | ||
754 | while ( j < len && dt[j] != '=' ) | ||
755 | ++j; | ||
756 | char *attr = dt+i; | ||
757 | dt[j] = '\0'; | ||
758 | i = ++j; // skip = | ||
759 | while ( i < len && dt[i] != '"' ) | ||
760 | ++i; | ||
761 | j = ++i; | ||
762 | bool haveAmp = FALSE; | ||
763 | bool haveUtf = FALSE; | ||
764 | while ( j < len && dt[j] != '"' ) { | ||
765 | if ( dt[j] == '&' ) | ||
766 | haveAmp = TRUE; | ||
767 | if ( ((unsigned char)dt[j]) > 0x7f ) | ||
768 | haveUtf = TRUE; | ||
769 | ++j; | ||
770 | } | ||
771 | |||
772 | if ( i == j ) { | ||
773 | // leave out empty attributes | ||
774 | i = j + 1; | ||
775 | continue; | ||
776 | } | ||
777 | |||
778 | QString value = haveUtf ? QString::fromUtf8( dt+i, j-i ) | ||
779 | : QString::fromLatin1( dt+i, j-i ); | ||
780 | if ( haveAmp ) | ||
781 | value = Qtopia::plainString( value ); | ||
782 | i = j + 1; | ||
783 | |||
784 | //qDebug("attr='%s' value='%s'", attr.data(), value.latin1() ); | ||
785 | int * find = dict[ attr ]; | ||
786 | #if 1 | ||
787 | if ( !find ) { | ||
788 | // custom field | ||
789 | e.setCustomField(attr, value); | ||
790 | continue; | ||
791 | } | ||
792 | |||
793 | switch( *find ) { | ||
794 | case FDescription: | ||
795 | e.setDescription( value ); | ||
796 | break; | ||
797 | case FLocation: | ||
798 | e.setLocation( value ); | ||
799 | break; | ||
800 | case FCategories: | ||
801 | e.setCategories( Qtopia::Record::idsFromString( value ) ); | ||
802 | break; | ||
803 | case FUid: | ||
804 | e.setUid( value.toInt() ); | ||
805 | break; | ||
806 | case FType: | ||
807 | if ( value == "AllDay" ) | ||
808 | e.setType( Event::AllDay ); | ||
809 | else | ||
810 | e.setType( Event::Normal ); | ||
811 | break; | ||
812 | case FAlarm: | ||
813 | alarmTime = value.toInt(); | ||
814 | break; | ||
815 | case FSound: | ||
816 | alarmSound = value == "loud" ? Event::Loud : Event::Silent; | ||
817 | break; | ||
818 | // recurrence stuff | ||
819 | case FRType: | ||
820 | if ( value == "Daily" ) | ||
821 | rp.type = Event::Daily; | ||
822 | else if ( value == "Weekly" ) | ||
823 | rp.type = Event::Weekly; | ||
824 | else if ( value == "MonthlyDay" ) | ||
825 | rp.type = Event::MonthlyDay; | ||
826 | else if ( value == "MonthlyDate" ) | ||
827 | rp.type = Event::MonthlyDate; | ||
828 | else if ( value == "Yearly" ) | ||
829 | rp.type = Event::Yearly; | ||
830 | else | ||
831 | rp.type = Event::NoRepeat; | ||
832 | break; | ||
833 | case FRWeekdays: | ||
834 | rp.days = value.toInt(); | ||
835 | break; | ||
836 | case FRPosition: | ||
837 | rp.position = value.toInt(); | ||
838 | break; | ||
839 | case FRFreq: | ||
840 | rp.frequency = value.toInt(); | ||
841 | break; | ||
842 | case FRHasEndDate: | ||
843 | rp.hasEndDate = value.toInt(); | ||
844 | break; | ||
845 | case FREndDate: { | ||
846 | rp.endDateUTC = (time_t) value.toLong(); | ||
847 | break; | ||
848 | } | ||
849 | case FRStart: { | ||
850 | e.setStart( (time_t) value.toLong() ); | ||
851 | break; | ||
852 | } | ||
853 | case FREnd: { | ||
854 | e.setEnd( (time_t) value.toLong() ); | ||
855 | break; | ||
856 | } | ||
857 | case FNote: | ||
858 | e.setNotes( value ); | ||
859 | break; | ||
860 | case FCreated: | ||
861 | rp.createTime = value.toInt(); | ||
862 | break; | ||
863 | case FAction: | ||
864 | currentAction = value.toInt(); | ||
865 | break; | ||
866 | case FActionKey: | ||
867 | journalKey = value.toInt(); | ||
868 | break; | ||
869 | case FJournalOrigHadRepeat: | ||
870 | origHadRepeat = value.toInt(); | ||
871 | break; | ||
872 | default: | ||
873 | qDebug( "huh??? missing enum? -- attr.: %s", attr ); | ||
874 | break; | ||
875 | } | ||
876 | #endif | ||
877 | } | ||
878 | // "post processing" (dates, times, alarm, recurrence) | ||
879 | // start date/time | ||
880 | e.setRepeat( rp.type != Event::NoRepeat, rp ); | ||
881 | |||
882 | if ( alarmTime != -1 ) | ||
883 | e.setAlarm( TRUE, alarmTime, alarmSound ); | ||
884 | |||
885 | // now do our action based on the current action... | ||
886 | switch ( currentAction ) { | ||
887 | case ACTION_ADD: | ||
888 | addJFEvent( e ); | ||
889 | break; | ||
890 | case ACTION_REMOVE: | ||
891 | removeJFEvent( e ); | ||
892 | break; | ||
893 | case ACTION_REPLACE: | ||
894 | // be a little bit careful, | ||
895 | // in case of a messed up journal... | ||
896 | if ( journalKey > -1 && origHadRepeat > -1 ) { | ||
897 | // get the original from proper list... | ||
898 | if ( origHadRepeat ) | ||
899 | removeJFEvent( *(repeatEvents.at(journalKey)) ); | ||
900 | else | ||
901 | removeJFEvent( *(eventList.at(journalKey)) ); | ||
902 | addJFEvent( e ); | ||
903 | } | ||
904 | break; | ||
905 | default: | ||
906 | break; | ||
907 | } | ||
908 | } | ||
909 | f.close(); | ||
910 | } | ||
911 | |||
912 | void DateBookDB::init() | ||
913 | { | ||
914 | d = new DateBookDBPrivate; | ||
915 | d->clean = false; | ||
916 | QString str = dateBookFilename(); | ||
917 | if ( str.isNull() ) { | ||
918 | QMessageBox::warning( 0, QObject::tr("Out of Space"), | ||
919 | QObject::tr("Unable to create start up files\n" | ||
920 | "Please free up some space\n" | ||
921 | "before entering data") ); | ||
922 | } | ||
923 | // continuing along, we call this datebook filename again, | ||
924 | // because they may fix it before continuing, though it seems | ||
925 | // pretty unlikely... | ||
926 | loadFile( dateBookFilename() ); | ||
927 | |||
928 | if ( QFile::exists( dateBookJournalFile() ) ) { | ||
929 | // merge the journal | ||
930 | loadFile( dateBookJournalFile() ); | ||
931 | // save in our changes and remove the journal... | ||
932 | save(); | ||
933 | } | ||
934 | d->clean = true; | ||
935 | } | ||
936 | |||
937 | bool DateBookDB::save() | ||
938 | { | ||
939 | if ( d->clean == true ) | ||
940 | return true; | ||
941 | QValueListIterator<Event> it; | ||
942 | int total_written; | ||
943 | QString strFileNew = dateBookFilename() + ".new"; | ||
944 | |||
945 | QFile f( strFileNew ); | ||
946 | if ( !f.open( IO_WriteOnly|IO_Raw ) ) | ||
947 | return FALSE; | ||
948 | |||
949 | QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); | ||
950 | buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n"; | ||
951 | buf += "<events>\n"; | ||
952 | QCString str = buf.utf8(); | ||
953 | total_written = f.writeBlock( str.data(), str.length() ); | ||
954 | if ( total_written != int(str.length()) ) { | ||
955 | f.close(); | ||
956 | QFile::remove( strFileNew ); | ||
957 | return false; | ||
958 | } | ||
959 | |||
960 | for ( it = eventList.begin(); it != eventList.end(); ++it ) { | ||
961 | buf = "<event"; | ||
962 | (*it).save( buf ); | ||
963 | buf += " />\n"; | ||
964 | str = buf.utf8(); | ||
965 | total_written = f.writeBlock( str.data(), str.length() ); | ||
966 | if ( total_written != int(str.length()) ) { | ||
967 | f.close(); | ||
968 | QFile::remove( strFileNew ); | ||
969 | return false; | ||
970 | } | ||
971 | } | ||
972 | for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) { | ||
973 | buf = "<event"; | ||
974 | (*it).save( buf ); | ||
975 | buf += " />\n"; | ||
976 | str = buf.utf8(); | ||
977 | total_written = f.writeBlock( str.data(), str.length() ); | ||
978 | if ( total_written != int(str.length()) ) { | ||
979 | f.close(); | ||
980 | QFile::remove( strFileNew ); | ||
981 | return false; | ||
982 | } | ||
983 | } | ||
984 | buf = "</events>\n</DATEBOOK>\n"; | ||
985 | str = buf.utf8(); | ||
986 | total_written = f.writeBlock( str.data(), str.length() ); | ||
987 | if ( total_written != int(str.length()) ) { | ||
988 | f.close(); | ||
989 | QFile::remove( strFileNew ); | ||
990 | return false; | ||
991 | } | ||
992 | f.close(); | ||
993 | |||
994 | // now rename... I like to use the systemcall | ||
995 | if ( ::rename( strFileNew, dateBookFilename() ) < 0 ) { | ||
996 | qWarning( "problem renaming file %s to %s errno %d", | ||
997 | strFileNew.latin1(), dateBookFilename().latin1(), errno ); | ||
998 | // remove the file, otherwise it will just stick around... | ||
999 | QFile::remove( strFileNew ); | ||
1000 | } | ||
1001 | |||
1002 | // may as well remove the journal file... | ||
1003 | QFile::remove( dateBookJournalFile() ); | ||
1004 | d->clean = true; | ||
1005 | return true; | ||
1006 | } | ||
1007 | |||
1008 | void DateBookDB::reload() | ||
1009 | { | ||
1010 | QValueList<Event>::Iterator it = eventList.begin(); | ||
1011 | for ( ; it != eventList.end(); ++it ) { | ||
1012 | if ( (*it).hasAlarm() ) | ||
1013 | delEventAlarm( *it ); | ||
1014 | if ( (*it).hasRepeat() ) | ||
1015 | removeRepeat( *it ); | ||
1016 | } | ||
1017 | eventList.clear(); | ||
1018 | repeatEvents.clear(); // should be a NOP | ||
1019 | init(); | ||
1020 | } | ||
1021 | |||
1022 | bool DateBookDB::removeRepeat( const Event &ev ) | ||
1023 | { | ||
1024 | time_t removeMe = ev.repeatPattern().createTime; | ||
1025 | QValueListIterator<Event> it; | ||
1026 | for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) { | ||
1027 | if ( removeMe == (*it).repeatPattern().createTime ) { | ||
1028 | repeatEvents.remove( *it ); | ||
1029 | // best break, or we are going into undefined territory! | ||
1030 | return TRUE; | ||
1031 | } | ||
1032 | } | ||
1033 | return FALSE; | ||
1034 | } | ||
1035 | |||
1036 | bool DateBookDB::origRepeat( const Event &ev, Event &orig ) const | ||
1037 | { | ||
1038 | time_t removeMe = ev.repeatPattern().createTime; | ||
1039 | QValueListConstIterator<Event> it; | ||
1040 | for ( it = repeatEvents.begin(); it != repeatEvents.end(); ++it ) { | ||
1041 | if ( removeMe == (*it).repeatPattern().createTime ) { | ||
1042 | orig = (*it); | ||
1043 | return TRUE; | ||
1044 | } | ||
1045 | } | ||
1046 | return FALSE; | ||
1047 | } | ||
1048 | |||
1049 | void DateBookDB::saveJournalEntry( const Event &ev, journal_action action ) | ||
1050 | { | ||
1051 | saveJournalEntry( ev, action, -1, false ); | ||
1052 | } | ||
1053 | |||
1054 | bool DateBookDB::saveJournalEntry( const Event &evOld, journal_action action, | ||
1055 | int key, bool origHadRepeat ) | ||
1056 | { | ||
1057 | bool status = false; | ||
1058 | Event ev = evOld; | ||
1059 | // write our log based on the action | ||
1060 | QFile f( dateBookJournalFile() ); | ||
1061 | if ( !f.open( IO_WriteOnly|IO_Append ) ) | ||
1062 | return false; | ||
1063 | QString buf = "<event"; | ||
1064 | ev.save( buf ); | ||
1065 | buf += " action="; | ||
1066 | buf += "\"" + QString::number(action) + "\""; | ||
1067 | buf += " actionkey=\"" + QString::number(key) + "\""; | ||
1068 | buf += " actionorig=\"" + QString::number(origHadRepeat) +"\""; | ||
1069 | buf += " />\n"; | ||
1070 | QString str = buf.utf8(); | ||
1071 | status = ( f.writeBlock( str.data(), str.length() ) == int(str.length()) ); | ||
1072 | f.close(); | ||
1073 | return status; | ||
1074 | } | ||
1075 | |||
1076 | QValueList<Event> DateBookDB::getRawRepeats() const | ||
1077 | { | ||
1078 | return repeatEvents; | ||
1079 | } | ||
1080 | |||
1081 | QValueList<Event> DateBookDB::getNonRepeatingEvents( const QDate &from, | ||
1082 | const QDate &to ) const | ||
1083 | { | ||
1084 | QValueListConstIterator<Event> it; | ||
1085 | QDateTime dtTmp, dtEnd; | ||
1086 | QValueList<Event> tmpList; | ||
1087 | for (it = eventList.begin(); it != eventList.end(); ++it ) { | ||
1088 | dtTmp = (*it).start(TRUE); | ||
1089 | dtEnd = (*it).end(TRUE); | ||
1090 | |||
1091 | if ( dtTmp.date() >= from && dtTmp.date() <= to ) { | ||
1092 | Event e = *it; | ||
1093 | if ( dtTmp.date() != dtEnd.date() ) | ||
1094 | e.setEnd( QDateTime(dtTmp.date(), QTime(23, 59, 0)) ); | ||
1095 | tmpList.append( e ); | ||
1096 | } | ||
1097 | // we must also check for end date information... | ||
1098 | if ( dtEnd.date() != dtTmp.date() && dtEnd.date() >= from ) { | ||
1099 | QDateTime dt = dtTmp.addDays( 1 ); | ||
1100 | dt.setTime( QTime(0, 0, 0) ); | ||
1101 | QDateTime dtStop; | ||
1102 | if ( dtEnd > to ) { | ||
1103 | dtStop = to; | ||
1104 | } else | ||
1105 | dtStop = dtEnd; | ||
1106 | while ( dt <= dtStop ) { | ||
1107 | Event ev = *it; | ||
1108 | if ( dt >= from ) { | ||
1109 | ev.setStart( QDateTime(dt.date(), QTime(0, 0, 0)) ); | ||
1110 | if ( dt.date() == dtEnd.date() ) | ||
1111 | ev.setEnd( QDateTime(dt.date(), dtEnd.time()) ); | ||
1112 | else | ||
1113 | ev.setEnd( QDateTime(dt.date(), QTime(23, 59, 0)) ); | ||
1114 | tmpList.append( ev ); | ||
1115 | } | ||
1116 | dt = dt.addDays( 1 ); | ||
1117 | } | ||
1118 | } | ||
1119 | } | ||
1120 | return tmpList; | ||
1121 | } | ||