summaryrefslogtreecommitdiffabout
path: root/libkcal/recurrence.cpp
Unidiff
Diffstat (limited to 'libkcal/recurrence.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/recurrence.cpp2
1 files changed, 2 insertions, 0 deletions
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp
index e84f672..5181eaf 100644
--- a/libkcal/recurrence.cpp
+++ b/libkcal/recurrence.cpp
@@ -114,1823 +114,1825 @@ bool Recurrence::operator==( const Recurrence& r2 ) const
114 || mRecurStart != r2.mRecurStart 114 || mRecurStart != r2.mRecurStart
115 || mFloats != r2.mFloats 115 || mFloats != r2.mFloats
116 || mRecurReadOnly != r2.mRecurReadOnly 116 || mRecurReadOnly != r2.mRecurReadOnly
117 || mRecurExDatesCount != r2.mRecurExDatesCount ) 117 || mRecurExDatesCount != r2.mRecurExDatesCount )
118 return false; 118 return false;
119 // no need to compare mCompat* and mParent 119 // no need to compare mCompat* and mParent
120 // OK to compare the pointers 120 // OK to compare the pointers
121 switch ( recurs ) 121 switch ( recurs )
122 { 122 {
123 case rWeekly: 123 case rWeekly:
124 return rDays == r2.rDays 124 return rDays == r2.rDays
125 && rWeekStart == r2.rWeekStart; 125 && rWeekStart == r2.rWeekStart;
126 case rMonthlyPos: { 126 case rMonthlyPos: {
127 QPtrList<rMonthPos> MonthPositions = rMonthPositions; 127 QPtrList<rMonthPos> MonthPositions = rMonthPositions;
128 QPtrList<rMonthPos> MonthPositions2 = r2.rMonthPositions; 128 QPtrList<rMonthPos> MonthPositions2 = r2.rMonthPositions;
129 if ( !MonthPositions.count() ) 129 if ( !MonthPositions.count() )
130 return false; 130 return false;
131 if ( !MonthPositions2.count() ) 131 if ( !MonthPositions2.count() )
132 return false; 132 return false;
133 return MonthPositions.first()->rPos == MonthPositions2.first()->rPos; 133 return MonthPositions.first()->rPos == MonthPositions2.first()->rPos;
134 } 134 }
135 case rMonthlyDay: { 135 case rMonthlyDay: {
136 QPtrList<int> MonthDays = rMonthDays ; 136 QPtrList<int> MonthDays = rMonthDays ;
137 QPtrList<int> MonthDays2 = r2.rMonthDays ; 137 QPtrList<int> MonthDays2 = r2.rMonthDays ;
138 if ( !MonthDays.count() ) 138 if ( !MonthDays.count() )
139 return false; 139 return false;
140 if ( !MonthDays2.count() ) 140 if ( !MonthDays2.count() )
141 return false; 141 return false;
142 return *MonthDays.first() == *MonthDays2.first() ; 142 return *MonthDays.first() == *MonthDays2.first() ;
143 } 143 }
144 case rYearlyPos: { 144 case rYearlyPos: {
145 145
146 QPtrList<int> YearNums = rYearNums; 146 QPtrList<int> YearNums = rYearNums;
147 QPtrList<int> YearNums2 = r2.rYearNums; 147 QPtrList<int> YearNums2 = r2.rYearNums;
148 if ( *YearNums.first() != *YearNums2.first() ) 148 if ( *YearNums.first() != *YearNums2.first() )
149 return false; 149 return false;
150 QPtrList<rMonthPos> MonthPositions = rMonthPositions; 150 QPtrList<rMonthPos> MonthPositions = rMonthPositions;
151 QPtrList<rMonthPos> MonthPositions2 = r2.rMonthPositions; 151 QPtrList<rMonthPos> MonthPositions2 = r2.rMonthPositions;
152 if ( !MonthPositions.count() ) 152 if ( !MonthPositions.count() )
153 return false; 153 return false;
154 if ( !MonthPositions2.count() ) 154 if ( !MonthPositions2.count() )
155 return false; 155 return false;
156 return MonthPositions.first()->rPos == MonthPositions2.first()->rPos; 156 return MonthPositions.first()->rPos == MonthPositions2.first()->rPos;
157 157
158 } 158 }
159 case rYearlyMonth: { 159 case rYearlyMonth: {
160 QPtrList<int> YearNums = rYearNums; 160 QPtrList<int> YearNums = rYearNums;
161 QPtrList<int> YearNums2 = r2.rYearNums; 161 QPtrList<int> YearNums2 = r2.rYearNums;
162 return ( *YearNums.first() == *YearNums2.first() && mFeb29YearlyType == r2.mFeb29YearlyType); 162 return ( *YearNums.first() == *YearNums2.first() && mFeb29YearlyType == r2.mFeb29YearlyType);
163 } 163 }
164 case rYearlyDay: { 164 case rYearlyDay: {
165 QPtrList<int> YearNums = rYearNums; 165 QPtrList<int> YearNums = rYearNums;
166 QPtrList<int> YearNums2 = r2.rYearNums; 166 QPtrList<int> YearNums2 = r2.rYearNums;
167 return ( *YearNums.first() == *YearNums2.first() ); 167 return ( *YearNums.first() == *YearNums2.first() );
168 } 168 }
169 case rNone: 169 case rNone:
170 case rMinutely: 170 case rMinutely:
171 case rHourly: 171 case rHourly:
172 case rDaily: 172 case rDaily:
173 default: 173 default:
174 return true; 174 return true;
175 } 175 }
176} 176}
177/* 177/*
178bool Recurrence::compareLists( const QPtrList<int> &l1 ,const QPtrList<int> &l2) 178bool Recurrence::compareLists( const QPtrList<int> &l1 ,const QPtrList<int> &l2)
179{ 179{
180 if ( l1.count() != l2.count() ) 180 if ( l1.count() != l2.count() )
181 return false; 181 return false;
182 int count = l1.count(); 182 int count = l1.count();
183 int i; 183 int i;
184 for ( i = 0; i < count ; ++i ) { 184 for ( i = 0; i < count ; ++i ) {
185 // if ( l1.at(i) != l2.at(i) ) 185 // if ( l1.at(i) != l2.at(i) )
186 return false; 186 return false;
187 qDebug("compüare "); 187 qDebug("compüare ");
188 } 188 }
189 return true; 189 return true;
190} 190}
191*/ 191*/
192QString Recurrence::recurrenceText() const 192QString Recurrence::recurrenceText() const
193{ 193{
194 QString recurText = i18n("No"); 194 QString recurText = i18n("No");
195 if ( recurs == Recurrence::rMinutely ) 195 if ( recurs == Recurrence::rMinutely )
196 recurText = i18n("minutely"); 196 recurText = i18n("minutely");
197 else if ( recurs == Recurrence::rHourly ) 197 else if ( recurs == Recurrence::rHourly )
198 recurText = i18n("hourly"); 198 recurText = i18n("hourly");
199 else if ( recurs == Recurrence::rDaily ) 199 else if ( recurs == Recurrence::rDaily )
200 recurText = i18n("daily"); 200 recurText = i18n("daily");
201 else if ( recurs == Recurrence::rWeekly ) 201 else if ( recurs == Recurrence::rWeekly )
202 recurText = i18n("weekly"); 202 recurText = i18n("weekly");
203 else if ( recurs == Recurrence::rMonthlyPos ) 203 else if ( recurs == Recurrence::rMonthlyPos )
204 recurText = i18n("monthly"); 204 recurText = i18n("monthly");
205 else if ( recurs == Recurrence::rMonthlyDay ) 205 else if ( recurs == Recurrence::rMonthlyDay )
206 recurText = i18n("day-monthly"); 206 recurText = i18n("day-monthly");
207 else if ( recurs == Recurrence::rYearlyMonth ) 207 else if ( recurs == Recurrence::rYearlyMonth )
208 recurText = i18n("month-yearly"); 208 recurText = i18n("month-yearly");
209 else if ( recurs == Recurrence::rYearlyDay ) 209 else if ( recurs == Recurrence::rYearlyDay )
210 recurText = i18n("day-yearly"); 210 recurText = i18n("day-yearly");
211 else if ( recurs == Recurrence::rYearlyPos ) 211 else if ( recurs == Recurrence::rYearlyPos )
212 recurText = i18n("position-yearly"); 212 recurText = i18n("position-yearly");
213 return recurText; 213 return recurText;
214} 214}
215 215
216void Recurrence::setCompatVersion(int version) 216void Recurrence::setCompatVersion(int version)
217{ 217{
218 mCompatVersion = version ? version : INT_MAX; 218 mCompatVersion = version ? version : INT_MAX;
219} 219}
220 220
221ushort Recurrence::doesRecur() const 221ushort Recurrence::doesRecur() const
222{ 222{
223 return recurs; 223 return recurs;
224} 224}
225 225
226bool Recurrence::recursOnPure(const QDate &qd) const 226bool Recurrence::recursOnPure(const QDate &qd) const
227{ 227{
228 switch(recurs) { 228 switch(recurs) {
229 case rMinutely: 229 case rMinutely:
230 return recursSecondly(qd, rFreq*60); 230 return recursSecondly(qd, rFreq*60);
231 case rHourly: 231 case rHourly:
232 return recursSecondly(qd, rFreq*3600); 232 return recursSecondly(qd, rFreq*3600);
233 case rDaily: 233 case rDaily:
234 return recursDaily(qd); 234 return recursDaily(qd);
235 case rWeekly: 235 case rWeekly:
236 return recursWeekly(qd); 236 return recursWeekly(qd);
237 case rMonthlyPos: 237 case rMonthlyPos:
238 case rMonthlyDay: 238 case rMonthlyDay:
239 return recursMonthly(qd); 239 return recursMonthly(qd);
240 case rYearlyMonth: 240 case rYearlyMonth:
241 return recursYearlyByMonth(qd); 241 return recursYearlyByMonth(qd);
242 case rYearlyDay: 242 case rYearlyDay:
243 return recursYearlyByDay(qd); 243 return recursYearlyByDay(qd);
244 case rYearlyPos: 244 case rYearlyPos:
245 return recursYearlyByPos(qd); 245 return recursYearlyByPos(qd);
246 default: 246 default:
247 return false; 247 return false;
248 case rNone: 248 case rNone:
249 return false; 249 return false;
250 } // case 250 } // case
251 return false; 251 return false;
252} 252}
253 253
254bool Recurrence::recursAtPure(const QDateTime &dt) const 254bool Recurrence::recursAtPure(const QDateTime &dt) const
255{ 255{
256 switch(recurs) { 256 switch(recurs) {
257 case rMinutely: 257 case rMinutely:
258 return recursMinutelyAt(dt, rFreq); 258 return recursMinutelyAt(dt, rFreq);
259 case rHourly: 259 case rHourly:
260 return recursMinutelyAt(dt, rFreq*60); 260 return recursMinutelyAt(dt, rFreq*60);
261 default: 261 default:
262 if (dt.time() != mRecurStart.time()) 262 if (dt.time() != mRecurStart.time())
263 return false; 263 return false;
264 switch(recurs) { 264 switch(recurs) {
265 case rDaily: 265 case rDaily:
266 return recursDaily(dt.date()); 266 return recursDaily(dt.date());
267 case rWeekly: 267 case rWeekly:
268 return recursWeekly(dt.date()); 268 return recursWeekly(dt.date());
269 case rMonthlyPos: 269 case rMonthlyPos:
270 case rMonthlyDay: 270 case rMonthlyDay:
271 return recursMonthly(dt.date()); 271 return recursMonthly(dt.date());
272 case rYearlyMonth: 272 case rYearlyMonth:
273 return recursYearlyByMonth(dt.date()); 273 return recursYearlyByMonth(dt.date());
274 case rYearlyDay: 274 case rYearlyDay:
275 return recursYearlyByDay(dt.date()); 275 return recursYearlyByDay(dt.date());
276 case rYearlyPos: 276 case rYearlyPos:
277 return recursYearlyByPos(dt.date()); 277 return recursYearlyByPos(dt.date());
278 default: 278 default:
279 return false; 279 return false;
280 case rNone: 280 case rNone:
281 return false; 281 return false;
282 } 282 }
283 } // case 283 } // case
284 return false; 284 return false;
285} 285}
286 286
287QDate Recurrence::endDate() const 287QDate Recurrence::endDate() const
288{ 288{
289 int count = 0; 289 int count = 0;
290 QDate end; 290 QDate end;
291 if (recurs != rNone) { 291 if (recurs != rNone) {
292 if (rDuration < 0) 292 if (rDuration < 0)
293 return QDate(); // infinite recurrence 293 return QDate(); // infinite recurrence
294 if (rDuration == 0) 294 if (rDuration == 0)
295 return rEndDateTime.date(); 295 return rEndDateTime.date();
296 296
297 // The end date is determined by the recurrence count 297 // The end date is determined by the recurrence count
298 QDate dStart = mRecurStart.date(); 298 QDate dStart = mRecurStart.date();
299 switch (recurs) 299 switch (recurs)
300 { 300 {
301 case rMinutely: 301 case rMinutely:
302 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date(); 302 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date();
303 case rHourly: 303 case rHourly:
304 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date(); 304 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date();
305 case rDaily: 305 case rDaily:
306 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); 306 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
307 307
308 case rWeekly: 308 case rWeekly:
309 count = weeklyCalc(END_DATE_AND_COUNT, end); 309 count = weeklyCalc(END_DATE_AND_COUNT, end);
310 break; 310 break;
311 case rMonthlyPos: 311 case rMonthlyPos:
312 case rMonthlyDay: 312 case rMonthlyDay:
313 count = monthlyCalc(END_DATE_AND_COUNT, end); 313 count = monthlyCalc(END_DATE_AND_COUNT, end);
314 break; 314 break;
315 case rYearlyMonth: 315 case rYearlyMonth:
316 count = yearlyMonthCalc(END_DATE_AND_COUNT, end); 316 count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
317 break; 317 break;
318 case rYearlyDay: 318 case rYearlyDay:
319 count = yearlyDayCalc(END_DATE_AND_COUNT, end); 319 count = yearlyDayCalc(END_DATE_AND_COUNT, end);
320 break; 320 break;
321 case rYearlyPos: 321 case rYearlyPos:
322 count = yearlyPosCalc(END_DATE_AND_COUNT, end); 322 count = yearlyPosCalc(END_DATE_AND_COUNT, end);
323 break; 323 break;
324 default: 324 default:
325 // catch-all. Should never get here. 325 // catch-all. Should never get here.
326 kdDebug(5800) << "Control should never reach here in endDate()!" << endl; 326 kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
327 break; 327 break;
328 } 328 }
329 } 329 }
330 if (!count) 330 if (!count)
331 return QDate(); // error - there is no recurrence 331 return QDate(); // error - there is no recurrence
332 return end; 332 return end;
333} 333}
334 334
335QDateTime Recurrence::endDateTime() const 335QDateTime Recurrence::endDateTime() const
336{ 336{
337 int count = 0; 337 int count = 0;
338 QDate end; 338 QDate end;
339 if (recurs != rNone) { 339 if (recurs != rNone) {
340 if (rDuration < 0) 340 if (rDuration < 0)
341 return QDateTime(); // infinite recurrence 341 return QDateTime(); // infinite recurrence
342 if (rDuration == 0) 342 if (rDuration == 0)
343 return rEndDateTime; 343 return rEndDateTime;
344 344
345 // The end date is determined by the recurrence count 345 // The end date is determined by the recurrence count
346 QDate dStart = mRecurStart.date(); 346 QDate dStart = mRecurStart.date();
347 switch (recurs) 347 switch (recurs)
348 { 348 {
349 case rMinutely: 349 case rMinutely:
350 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60); 350 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60);
351 case rHourly: 351 case rHourly:
352 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600); 352 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600);
353 case rDaily: 353 case rDaily:
354 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); 354 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
355 355
356 case rWeekly: 356 case rWeekly:
357 count = weeklyCalc(END_DATE_AND_COUNT, end); 357 count = weeklyCalc(END_DATE_AND_COUNT, end);
358 break; 358 break;
359 case rMonthlyPos: 359 case rMonthlyPos:
360 case rMonthlyDay: 360 case rMonthlyDay:
361 count = monthlyCalc(END_DATE_AND_COUNT, end); 361 count = monthlyCalc(END_DATE_AND_COUNT, end);
362 break; 362 break;
363 case rYearlyMonth: 363 case rYearlyMonth:
364 count = yearlyMonthCalc(END_DATE_AND_COUNT, end); 364 count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
365 break; 365 break;
366 case rYearlyDay: 366 case rYearlyDay:
367 count = yearlyDayCalc(END_DATE_AND_COUNT, end); 367 count = yearlyDayCalc(END_DATE_AND_COUNT, end);
368 break; 368 break;
369 case rYearlyPos: 369 case rYearlyPos:
370 count = yearlyPosCalc(END_DATE_AND_COUNT, end); 370 count = yearlyPosCalc(END_DATE_AND_COUNT, end);
371 break; 371 break;
372 default: 372 default:
373 // catch-all. Should never get here. 373 // catch-all. Should never get here.
374 kdDebug(5800) << "Control should never reach here in endDate()!" << endl; 374 kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
375 break; 375 break;
376 } 376 }
377 } 377 }
378 if (!count) 378 if (!count)
379 return QDateTime(); // error - there is no recurrence 379 return QDateTime(); // error - there is no recurrence
380 return QDateTime(end, mRecurStart.time()); 380 return QDateTime(end, mRecurStart.time());
381} 381}
382 382
383int Recurrence::durationTo(const QDate &date) const 383int Recurrence::durationTo(const QDate &date) const
384{ 384{
385 QDate d = date; 385 QDate d = date;
386 return recurCalc(COUNT_TO_DATE, d); 386 return recurCalc(COUNT_TO_DATE, d);
387} 387}
388 388
389int Recurrence::durationTo(const QDateTime &datetime) const 389int Recurrence::durationTo(const QDateTime &datetime) const
390{ 390{
391 QDateTime dt = datetime; 391 QDateTime dt = datetime;
392 return recurCalc(COUNT_TO_DATE, dt); 392 return recurCalc(COUNT_TO_DATE, dt);
393} 393}
394 394
395void Recurrence::unsetRecurs() 395void Recurrence::unsetRecurs()
396{ 396{
397 if (mRecurReadOnly) return; 397 if (mRecurReadOnly) return;
398 recurs = rNone; 398 recurs = rNone;
399 rMonthPositions.clear(); 399 rMonthPositions.clear();
400 rMonthDays.clear(); 400 rMonthDays.clear();
401 rYearNums.clear(); 401 rYearNums.clear();
402} 402}
403 403
404void Recurrence::setRecurStart(const QDateTime &start) 404void Recurrence::setRecurStart(const QDateTime &start)
405{ 405{
406 mRecurStart = start; 406 mRecurStart = start;
407 mFloats = false; 407 mFloats = false;
408 switch (recurs) 408 switch (recurs)
409 { 409 {
410 case rMinutely: 410 case rMinutely:
411 case rHourly: 411 case rHourly:
412 break; 412 break;
413 case rDaily: 413 case rDaily:
414 case rWeekly: 414 case rWeekly:
415 case rMonthlyPos: 415 case rMonthlyPos:
416 case rMonthlyDay: 416 case rMonthlyDay:
417 case rYearlyMonth: 417 case rYearlyMonth:
418 case rYearlyDay: 418 case rYearlyDay:
419 case rYearlyPos: 419 case rYearlyPos:
420 default: 420 default:
421 rEndDateTime.setTime(start.time()); 421 rEndDateTime.setTime(start.time());
422 break; 422 break;
423 } 423 }
424} 424}
425 425
426void Recurrence::setRecurStart(const QDate &start) 426void Recurrence::setRecurStart(const QDate &start)
427{ 427{
428 mRecurStart.setDate(start); 428 mRecurStart.setDate(start);
429 mRecurStart.setTime(QTime(0,0,0)); 429 mRecurStart.setTime(QTime(0,0,0));
430 switch (recurs) 430 switch (recurs)
431 { 431 {
432 case rMinutely: 432 case rMinutely:
433 case rHourly: 433 case rHourly:
434 break; 434 break;
435 case rDaily: 435 case rDaily:
436 case rWeekly: 436 case rWeekly:
437 case rMonthlyPos: 437 case rMonthlyPos:
438 case rMonthlyDay: 438 case rMonthlyDay:
439 case rYearlyMonth: 439 case rYearlyMonth:
440 case rYearlyDay: 440 case rYearlyDay:
441 case rYearlyPos: 441 case rYearlyPos:
442 default: 442 default:
443 mFloats = true; 443 mFloats = true;
444 break; 444 break;
445 } 445 }
446} 446}
447 447
448void Recurrence::setFloats(bool f) 448void Recurrence::setFloats(bool f)
449{ 449{
450 switch (recurs) 450 switch (recurs)
451 { 451 {
452 case rDaily: 452 case rDaily:
453 case rWeekly: 453 case rWeekly:
454 case rMonthlyPos: 454 case rMonthlyPos:
455 case rMonthlyDay: 455 case rMonthlyDay:
456 case rYearlyMonth: 456 case rYearlyMonth:
457 case rYearlyDay: 457 case rYearlyDay:
458 case rYearlyPos: 458 case rYearlyPos:
459 break; 459 break;
460 case rMinutely: 460 case rMinutely:
461 case rHourly: 461 case rHourly:
462 default: 462 default:
463 return; // can't set sub-daily to floating 463 return; // can't set sub-daily to floating
464 } 464 }
465 mFloats = f; 465 mFloats = f;
466 if (f) { 466 if (f) {
467 mRecurStart.setTime(QTime(0,0,0)); 467 mRecurStart.setTime(QTime(0,0,0));
468 rEndDateTime.setTime(QTime(0,0,0)); 468 rEndDateTime.setTime(QTime(0,0,0));
469 } 469 }
470} 470}
471 471
472int Recurrence::frequency() const 472int Recurrence::frequency() const
473{ 473{
474 return rFreq; 474 return rFreq;
475} 475}
476 476
477int Recurrence::duration() const 477int Recurrence::duration() const
478{ 478{
479 return rDuration; 479 return rDuration;
480} 480}
481 481
482void Recurrence::setDuration(int _rDuration) 482void Recurrence::setDuration(int _rDuration)
483{ 483{
484 if (mRecurReadOnly) return; 484 if (mRecurReadOnly) return;
485 if (_rDuration > 0) { 485 if (_rDuration > 0) {
486 rDuration = _rDuration; 486 rDuration = _rDuration;
487 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl, 487 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl,
488 // so explicitly setting the duration means no backwards compatibility is needed. 488 // so explicitly setting the duration means no backwards compatibility is needed.
489 mCompatDuration = 0; 489 mCompatDuration = 0;
490 } 490 }
491} 491}
492 492
493QString Recurrence::endDateStr(bool shortfmt) const 493QString Recurrence::endDateStr(bool shortfmt) const
494{ 494{
495 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt); 495 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt);
496} 496}
497 497
498const QBitArray &Recurrence::days() const 498const QBitArray &Recurrence::days() const
499{ 499{
500 return rDays; 500 return rDays;
501} 501}
502 502
503const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const 503const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const
504{ 504{
505 return rMonthPositions; 505 return rMonthPositions;
506} 506}
507 507
508const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const 508const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const
509{ 509{
510 return rMonthPositions; 510 return rMonthPositions;
511} 511}
512 512
513const QPtrList<int> &Recurrence::monthDays() const 513const QPtrList<int> &Recurrence::monthDays() const
514{ 514{
515 return rMonthDays; 515 return rMonthDays;
516} 516}
517 517
518void Recurrence::setMinutely(int _rFreq, int _rDuration) 518void Recurrence::setMinutely(int _rFreq, int _rDuration)
519{ 519{
520 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 520 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
521 return; 521 return;
522 setDailySub(rMinutely, _rFreq, _rDuration); 522 setDailySub(rMinutely, _rFreq, _rDuration);
523} 523}
524 524
525void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime) 525void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime)
526{ 526{
527 if (mRecurReadOnly) return; 527 if (mRecurReadOnly) return;
528 rEndDateTime = _rEndDateTime; 528 rEndDateTime = _rEndDateTime;
529 setDailySub(rMinutely, _rFreq, 0); 529 setDailySub(rMinutely, _rFreq, 0);
530} 530}
531 531
532void Recurrence::setHourly(int _rFreq, int _rDuration) 532void Recurrence::setHourly(int _rFreq, int _rDuration)
533{ 533{
534 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 534 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
535 return; 535 return;
536 setDailySub(rHourly, _rFreq, _rDuration); 536 setDailySub(rHourly, _rFreq, _rDuration);
537} 537}
538 538
539void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime) 539void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime)
540{ 540{
541 if (mRecurReadOnly) return; 541 if (mRecurReadOnly) return;
542 rEndDateTime = _rEndDateTime; 542 rEndDateTime = _rEndDateTime;
543 setDailySub(rHourly, _rFreq, 0); 543 setDailySub(rHourly, _rFreq, 0);
544} 544}
545 545
546void Recurrence::setDaily(int _rFreq, int _rDuration) 546void Recurrence::setDaily(int _rFreq, int _rDuration)
547{ 547{
548 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 548 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
549 return; 549 return;
550 setDailySub(rDaily, _rFreq, _rDuration); 550 setDailySub(rDaily, _rFreq, _rDuration);
551} 551}
552 552
553void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate) 553void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate)
554{ 554{
555 if (mRecurReadOnly) return; 555 if (mRecurReadOnly) return;
556 rEndDateTime.setDate(_rEndDate); 556 rEndDateTime.setDate(_rEndDate);
557 rEndDateTime.setTime(mRecurStart.time()); 557 rEndDateTime.setTime(mRecurStart.time());
558 setDailySub(rDaily, _rFreq, 0); 558 setDailySub(rDaily, _rFreq, 0);
559} 559}
560 560
561void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 561void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
562 int _rDuration, int _rWeekStart) 562 int _rDuration, int _rWeekStart)
563{ 563{
564 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 564 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
565 return; 565 return;
566 recurs = rWeekly; 566 recurs = rWeekly;
567 567
568 rFreq = _rFreq; 568 rFreq = _rFreq;
569 rDays = _rDays; 569 rDays = _rDays;
570 rWeekStart = _rWeekStart; 570 rWeekStart = _rWeekStart;
571 rDuration = _rDuration; 571 rDuration = _rDuration;
572 if (mCompatVersion < 310 && _rDuration > 0) { 572 if (mCompatVersion < 310 && _rDuration > 0) {
573 // Backwards compatibility for KDE < 3.1. 573 // Backwards compatibility for KDE < 3.1.
574 // rDuration was set to the number of time periods to recur, 574 // rDuration was set to the number of time periods to recur,
575 // with week start always on a Monday. 575 // with week start always on a Monday.
576 // Convert this to the number of occurrences. 576 // Convert this to the number of occurrences.
577 mCompatDuration = _rDuration; 577 mCompatDuration = _rDuration;
578 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek()); 578 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek());
579 QDate end(mRecurStart.date().addDays(weeks * rFreq)); 579 QDate end(mRecurStart.date().addDays(weeks * rFreq));
580 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly 580 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly
581 rDuration = weeklyCalc(COUNT_TO_DATE, end); 581 rDuration = weeklyCalc(COUNT_TO_DATE, end);
582 } else { 582 } else {
583 mCompatDuration = 0; 583 mCompatDuration = 0;
584 } 584 }
585 rMonthPositions.clear(); 585 rMonthPositions.clear();
586 rMonthDays.clear(); 586 rMonthDays.clear();
587 if (mParent) mParent->updated(); 587 if (mParent) mParent->updated();
588} 588}
589 589
590void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 590void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
591 const QDate &_rEndDate, int _rWeekStart) 591 const QDate &_rEndDate, int _rWeekStart)
592{ 592{
593 if (mRecurReadOnly) return; 593 if (mRecurReadOnly) return;
594 recurs = rWeekly; 594 recurs = rWeekly;
595 595
596 rFreq = _rFreq; 596 rFreq = _rFreq;
597 rDays = _rDays; 597 rDays = _rDays;
598 rWeekStart = _rWeekStart; 598 rWeekStart = _rWeekStart;
599 rEndDateTime.setDate(_rEndDate); 599 rEndDateTime.setDate(_rEndDate);
600 rEndDateTime.setTime(mRecurStart.time()); 600 rEndDateTime.setTime(mRecurStart.time());
601 rDuration = 0; // set to 0 because there is an end date 601 rDuration = 0; // set to 0 because there is an end date
602 mCompatDuration = 0; 602 mCompatDuration = 0;
603 rMonthPositions.clear(); 603 rMonthPositions.clear();
604 rMonthDays.clear(); 604 rMonthDays.clear();
605 rYearNums.clear(); 605 rYearNums.clear();
606 if (mParent) mParent->updated(); 606 if (mParent) mParent->updated();
607} 607}
608 608
609void Recurrence::setMonthly(short type, int _rFreq, int _rDuration) 609void Recurrence::setMonthly(short type, int _rFreq, int _rDuration)
610{ 610{
611 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 611 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
612 return; 612 return;
613 recurs = type; 613 recurs = type;
614 614
615 rFreq = _rFreq; 615 rFreq = _rFreq;
616 rDuration = _rDuration; 616 rDuration = _rDuration;
617 if (mCompatVersion < 310) 617 if (mCompatVersion < 310)
618 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 618 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
619 rYearNums.clear(); 619 rYearNums.clear();
620 if (mParent) mParent->updated(); 620 if (mParent) mParent->updated();
621} 621}
622 622
623void Recurrence::setMonthly(short type, int _rFreq, 623void Recurrence::setMonthly(short type, int _rFreq,
624 const QDate &_rEndDate) 624 const QDate &_rEndDate)
625{ 625{
626 if (mRecurReadOnly) return; 626 if (mRecurReadOnly) return;
627 recurs = type; 627 recurs = type;
628 628
629 rFreq = _rFreq; 629 rFreq = _rFreq;
630 rEndDateTime.setDate(_rEndDate); 630 rEndDateTime.setDate(_rEndDate);
631 rEndDateTime.setTime(mRecurStart.time()); 631 rEndDateTime.setTime(mRecurStart.time());
632 rDuration = 0; // set to 0 because there is an end date 632 rDuration = 0; // set to 0 because there is an end date
633 mCompatDuration = 0; 633 mCompatDuration = 0;
634 rYearNums.clear(); 634 rYearNums.clear();
635 if (mParent) mParent->updated(); 635 if (mParent) mParent->updated();
636} 636}
637 637
638void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays) 638void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays)
639{ 639{
640 if (recurs == rMonthlyPos) 640 if (recurs == rMonthlyPos)
641 addMonthlyPos_(_rPos, _rDays); 641 addMonthlyPos_(_rPos, _rDays);
642} 642}
643 643
644void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays) 644void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays)
645{ 645{
646 if (mRecurReadOnly 646 if (mRecurReadOnly
647 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number 647 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number
648 return; 648 return;
649 649
650 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) { 650 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) {
651 int itPos = it->negative ? -it->rPos : it->rPos; 651 int itPos = it->negative ? -it->rPos : it->rPos;
652 if (_rPos == itPos) { 652 if (_rPos == itPos) {
653 // This week is already in the list. 653 // This week is already in the list.
654 // Combine the specified days with those in the list. 654 // Combine the specified days with those in the list.
655 it->rDays |= _rDays; 655 it->rDays |= _rDays;
656 if (mParent) mParent->updated(); 656 if (mParent) mParent->updated();
657 return; 657 return;
658 } 658 }
659 } 659 }
660 // Add the new position to the list 660 // Add the new position to the list
661 rMonthPos *tmpPos = new rMonthPos; 661 rMonthPos *tmpPos = new rMonthPos;
662 if (_rPos > 0) { 662 if (_rPos > 0) {
663 tmpPos->rPos = _rPos; 663 tmpPos->rPos = _rPos;
664 tmpPos->negative = false; 664 tmpPos->negative = false;
665 } else { 665 } else {
666 tmpPos->rPos = -_rPos; // take abs() 666 tmpPos->rPos = -_rPos; // take abs()
667 tmpPos->negative = true; 667 tmpPos->negative = true;
668 } 668 }
669 tmpPos->rDays = _rDays; 669 tmpPos->rDays = _rDays;
670 tmpPos->rDays.detach(); 670 tmpPos->rDays.detach();
671 rMonthPositions.append(tmpPos); 671 rMonthPositions.append(tmpPos);
672 672
673 if (mCompatVersion < 310 && mCompatDuration > 0) { 673 if (mCompatVersion < 310 && mCompatDuration > 0) {
674 // Backwards compatibility for KDE < 3.1. 674 // Backwards compatibility for KDE < 3.1.
675 // rDuration was set to the number of time periods to recur. 675 // rDuration was set to the number of time periods to recur.
676 // Convert this to the number of occurrences. 676 // Convert this to the number of occurrences.
677 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 677 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
678 int month = mRecurStart.date().month() - 1 + monthsAhead; 678 int month = mRecurStart.date().month() - 1 + monthsAhead;
679 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 679 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
680 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 680 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
681 rDuration = recurCalc(COUNT_TO_DATE, end); 681 rDuration = recurCalc(COUNT_TO_DATE, end);
682 } 682 }
683 683
684 if (mParent) mParent->updated(); 684 if (mParent) mParent->updated();
685} 685}
686 686
687void Recurrence::addMonthlyDay(short _rDay) 687void Recurrence::addMonthlyDay(short _rDay)
688{ 688{
689 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth) 689 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth)
690 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number 690 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number
691 return; 691 return;
692 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) { 692 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) {
693 if (_rDay == *it) 693 if (_rDay == *it)
694 return; // this day is already in the list - avoid duplication 694 return; // this day is already in the list - avoid duplication
695 } 695 }
696 int *tmpDay = new int; 696 int *tmpDay = new int;
697 *tmpDay = _rDay; 697 *tmpDay = _rDay;
698 rMonthDays.append(tmpDay); 698 rMonthDays.append(tmpDay);
699 699
700 if (mCompatVersion < 310 && mCompatDuration > 0) { 700 if (mCompatVersion < 310 && mCompatDuration > 0) {
701 // Backwards compatibility for KDE < 3.1. 701 // Backwards compatibility for KDE < 3.1.
702 // rDuration was set to the number of time periods to recur. 702 // rDuration was set to the number of time periods to recur.
703 // Convert this to the number of occurrences. 703 // Convert this to the number of occurrences.
704 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 704 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
705 int month = mRecurStart.date().month() - 1 + monthsAhead; 705 int month = mRecurStart.date().month() - 1 + monthsAhead;
706 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 706 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
707 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 707 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
708 rDuration = recurCalc(COUNT_TO_DATE, end); 708 rDuration = recurCalc(COUNT_TO_DATE, end);
709 } 709 }
710 710
711 if (mParent) mParent->updated(); 711 if (mParent) mParent->updated();
712} 712}
713 713
714void Recurrence::setYearly(int type, int _rFreq, int _rDuration) 714void Recurrence::setYearly(int type, int _rFreq, int _rDuration)
715{ 715{
716 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 716 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
717 return; 717 return;
718 if (mCompatVersion < 310) 718 if (mCompatVersion < 310)
719 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 719 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
720 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration); 720 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration);
721} 721}
722 722
723void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate) 723void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate)
724{ 724{
725 if (mRecurReadOnly) return; 725 if (mRecurReadOnly) return;
726 rEndDateTime.setDate(_rEndDate); 726 rEndDateTime.setDate(_rEndDate);
727 rEndDateTime.setTime(mRecurStart.time()); 727 rEndDateTime.setTime(mRecurStart.time());
728 mCompatDuration = 0; 728 mCompatDuration = 0;
729 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0); 729 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0);
730} 730}
731 731
732void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration) 732void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration)
733{ 733{
734 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 734 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
735 return; 735 return;
736 if (mCompatVersion < 310) 736 if (mCompatVersion < 310)
737 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 737 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
738 setYearly_(rYearlyMonth, type, _rFreq, _rDuration); 738 setYearly_(rYearlyMonth, type, _rFreq, _rDuration);
739} 739}
740 740
741void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate) 741void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate)
742{ 742{
743 if (mRecurReadOnly) return; 743 if (mRecurReadOnly) return;
744 rEndDateTime.setDate(_rEndDate); 744 rEndDateTime.setDate(_rEndDate);
745 rEndDateTime.setTime(mRecurStart.time()); 745 rEndDateTime.setTime(mRecurStart.time());
746 mCompatDuration = 0; 746 mCompatDuration = 0;
747 setYearly_(rYearlyMonth, type, _rFreq, 0); 747 setYearly_(rYearlyMonth, type, _rFreq, 0);
748} 748}
749 749
750void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays) 750void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays)
751{ 751{
752 if (recurs == rYearlyPos) 752 if (recurs == rYearlyPos)
753 addMonthlyPos_(_rPos, _rDays); 753 addMonthlyPos_(_rPos, _rDays);
754} 754}
755 755
756const QPtrList<int> &Recurrence::yearNums() const 756const QPtrList<int> &Recurrence::yearNums() const
757{ 757{
758 return rYearNums; 758 return rYearNums;
759} 759}
760void Recurrence::addYearlyMonth(short _rPos ) 760void Recurrence::addYearlyMonth(short _rPos )
761{ 761{
762 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number 762 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number
763 return; 763 return;
764 rMonthPos *tmpPos = new rMonthPos; 764 rMonthPos *tmpPos = new rMonthPos;
765 if ( _rPos > 0) { 765 if ( _rPos > 0) {
766 tmpPos->rPos = _rPos; 766 tmpPos->rPos = _rPos;
767 tmpPos->negative = false; 767 tmpPos->negative = false;
768 } else { 768 } else {
769 tmpPos->rPos = -_rPos; // take abs() 769 tmpPos->rPos = -_rPos; // take abs()
770 tmpPos->negative = true; 770 tmpPos->negative = true;
771 } 771 }
772 rMonthPositions.append(tmpPos); 772 rMonthPositions.append(tmpPos);
773} 773}
774void Recurrence::addYearlyNum(short _rNum) 774void Recurrence::addYearlyNum(short _rNum)
775{ 775{
776 if (mRecurReadOnly 776 if (mRecurReadOnly
777 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos) 777 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos)
778 || _rNum <= 0) // invalid day/month number 778 || _rNum <= 0) // invalid day/month number
779 return; 779 return;
780 780
781 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) { 781 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) {
782 // Backwards compatibility for KDE < 3.1. 782 // Backwards compatibility for KDE < 3.1.
783 // Dates were stored as day numbers, with a fiddle to take account of leap years. 783 // Dates were stored as day numbers, with a fiddle to take account of leap years.
784 // Convert the day number to a month. 784 // Convert the day number to a month.
785 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366)) 785 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366))
786 return; // invalid day number 786 return; // invalid day number
787 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month(); 787 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month();
788 } else 788 } else
789 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12 789 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12
790 || recurs == rYearlyDay && _rNum > 366) 790 || recurs == rYearlyDay && _rNum > 366)
791 return; // invalid day number 791 return; // invalid day number
792 792
793 uint i = 0; 793 uint i = 0;
794 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) { 794 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) {
795 if (_rNum == *it) 795 if (_rNum == *it)
796 return; // this day/month is already in the list - avoid duplication 796 return; // this day/month is already in the list - avoid duplication
797 ++i; 797 ++i;
798 } 798 }
799 799
800 int *tmpNum = new int; 800 int *tmpNum = new int;
801 *tmpNum = _rNum; 801 *tmpNum = _rNum;
802 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position 802 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position
803 803
804 if (mCompatVersion < 310 && mCompatDuration > 0) { 804 if (mCompatVersion < 310 && mCompatDuration > 0) {
805 // Backwards compatibility for KDE < 3.1. 805 // Backwards compatibility for KDE < 3.1.
806 // rDuration was set to the number of time periods to recur. 806 // rDuration was set to the number of time periods to recur.
807 // Convert this to the number of occurrences. 807 // Convert this to the number of occurrences.
808 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31); 808 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31);
809 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 809 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
810 rDuration = recurCalc(COUNT_TO_DATE, end); 810 rDuration = recurCalc(COUNT_TO_DATE, end);
811 } 811 }
812 812
813 if (mParent) mParent->updated(); 813 if (mParent) mParent->updated();
814} 814}
815 815
816 816
817QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const 817QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const
818{ 818{
819 if (last) 819 if (last)
820 *last = false; 820 *last = false;
821 int freq; 821 int freq;
822 switch (recurs) 822 switch (recurs)
823 { 823 {
824 case rMinutely: 824 case rMinutely:
825 freq = rFreq * 60; 825 freq = rFreq * 60;
826 break; 826 break;
827 case rHourly: 827 case rHourly:
828 freq = rFreq * 3600; 828 freq = rFreq * 3600;
829 break; 829 break;
830 case rDaily: 830 case rDaily:
831 case rWeekly: 831 case rWeekly:
832 case rMonthlyPos: 832 case rMonthlyPos:
833 case rMonthlyDay: 833 case rMonthlyDay:
834 case rYearlyMonth: 834 case rYearlyMonth:
835 case rYearlyDay: 835 case rYearlyDay:
836 case rYearlyPos: { 836 case rYearlyPos: {
837 QDate preDate = preDateTime.date(); 837 QDate preDate = preDateTime.date();
838 if (!mFloats && mRecurStart.time() > preDateTime.time()) 838 if (!mFloats && mRecurStart.time() > preDateTime.time())
839 preDate = preDate.addDays(-1); 839 preDate = preDate.addDays(-1);
840 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time()); 840 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time());
841 } 841 }
842 default: 842 default:
843 return QDateTime(); 843 return QDateTime();
844 } 844 }
845 845
846 // It's a sub-daily recurrence 846 // It's a sub-daily recurrence
847 if (preDateTime < mRecurStart) 847 if (preDateTime < mRecurStart)
848 return mRecurStart; 848 return mRecurStart;
849 int count = mRecurStart.secsTo(preDateTime) / freq + 2; 849 int count = mRecurStart.secsTo(preDateTime) / freq + 2;
850 if (rDuration > 0) { 850 if (rDuration > 0) {
851 if (count > rDuration) 851 if (count > rDuration)
852 return QDateTime(); 852 return QDateTime();
853 if (last && count == rDuration) 853 if (last && count == rDuration)
854 *last = true; 854 *last = true;
855 } 855 }
856 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 856 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
857 if (rDuration == 0) { 857 if (rDuration == 0) {
858 if (endtime > rEndDateTime) 858 if (endtime > rEndDateTime)
859 return QDateTime(); 859 return QDateTime();
860 if (last && endtime == rEndDateTime) 860 if (last && endtime == rEndDateTime)
861 *last = true; 861 *last = true;
862 } 862 }
863 return endtime; 863 return endtime;
864} 864}
865 865
866QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const 866QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const
867{ 867{
868 if (last) 868 if (last)
869 *last = false; 869 *last = false;
870 switch (recurs) 870 switch (recurs)
871 { 871 {
872 case rMinutely: 872 case rMinutely:
873 case rHourly: 873 case rHourly:
874 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date(); 874 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date();
875 case rDaily: 875 case rDaily:
876 case rWeekly: 876 case rWeekly:
877 case rMonthlyPos: 877 case rMonthlyPos:
878 case rMonthlyDay: 878 case rMonthlyDay:
879 case rYearlyMonth: 879 case rYearlyMonth:
880 case rYearlyDay: 880 case rYearlyDay:
881 case rYearlyPos: 881 case rYearlyPos:
882 qDebug("Recurrence::getNextDate: MAY BE BROKEN ");
882 return getNextDateNoTime(preDate, last); 883 return getNextDateNoTime(preDate, last);
883 default: 884 default:
884 return QDate(); 885 return QDate();
885 } 886 }
886} 887}
887 888
888 889
889QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const 890QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const
890{ 891{
891 if (last) 892 if (last)
892 *last = false; 893 *last = false;
893 int freq; 894 int freq;
894 switch (recurs) 895 switch (recurs)
895 { 896 {
896 case rMinutely: 897 case rMinutely:
897 freq = rFreq * 60; 898 freq = rFreq * 60;
898 break; 899 break;
899 case rHourly: 900 case rHourly:
900 freq = rFreq * 3600; 901 freq = rFreq * 3600;
901 break; 902 break;
902 case rDaily: 903 case rDaily:
903 case rWeekly: 904 case rWeekly:
904 case rMonthlyPos: 905 case rMonthlyPos:
905 case rMonthlyDay: 906 case rMonthlyDay:
906 case rYearlyMonth: 907 case rYearlyMonth:
907 case rYearlyDay: 908 case rYearlyDay:
908 case rYearlyPos: { 909 case rYearlyPos: {
909 QDate afterDate = afterDateTime.date(); 910 QDate afterDate = afterDateTime.date();
910 if (!mFloats && mRecurStart.time() < afterDateTime.time()) 911 if (!mFloats && mRecurStart.time() < afterDateTime.time())
911 afterDate = afterDate.addDays(1); 912 afterDate = afterDate.addDays(1);
912 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time()); 913 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time());
913 } 914 }
914 default: 915 default:
915 return QDateTime(); 916 return QDateTime();
916 } 917 }
917 918
918 // It's a sub-daily recurrence 919 // It's a sub-daily recurrence
919 if (afterDateTime <= mRecurStart) 920 if (afterDateTime <= mRecurStart)
920 return QDateTime(); 921 return QDateTime();
921 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1; 922 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1;
922 if (rDuration > 0) { 923 if (rDuration > 0) {
923 if (count > rDuration) 924 if (count > rDuration)
924 count = rDuration; 925 count = rDuration;
925 if (last && count == rDuration) 926 if (last && count == rDuration)
926 *last = true; 927 *last = true;
927 } 928 }
928 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 929 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
929 if (rDuration == 0) { 930 if (rDuration == 0) {
930 if (endtime > rEndDateTime) 931 if (endtime > rEndDateTime)
931 endtime = rEndDateTime; 932 endtime = rEndDateTime;
932 if (last && endtime == rEndDateTime) 933 if (last && endtime == rEndDateTime)
933 *last = true; 934 *last = true;
934 } 935 }
935 return endtime; 936 return endtime;
936} 937}
937 938
938QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const 939QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const
939{ 940{
940 if (last) 941 if (last)
941 *last = false; 942 *last = false;
942 switch (recurs) 943 switch (recurs)
943 { 944 {
944 case rMinutely: 945 case rMinutely:
945 case rHourly: 946 case rHourly:
946 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date(); 947 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date();
947 case rDaily: 948 case rDaily:
948 case rWeekly: 949 case rWeekly:
949 case rMonthlyPos: 950 case rMonthlyPos:
950 case rMonthlyDay: 951 case rMonthlyDay:
951 case rYearlyMonth: 952 case rYearlyMonth:
952 case rYearlyDay: 953 case rYearlyDay:
953 case rYearlyPos: 954 case rYearlyPos:
954 return getPreviousDateNoTime(afterDate, last); 955 return getPreviousDateNoTime(afterDate, last);
955 default: 956 default:
956 return QDate(); 957 return QDate();
957 } 958 }
958} 959}
959 960
960 961
961/***************************** PROTECTED FUNCTIONS ***************************/ 962/***************************** PROTECTED FUNCTIONS ***************************/
962 963
963bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const 964bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const
964{ 965{
965 if ((qd >= mRecurStart.date()) && 966 if ((qd >= mRecurStart.date()) &&
966 ((rDuration > 0) && (qd <= endDate()) || 967 ((rDuration > 0) && (qd <= endDate()) ||
967 ((rDuration == 0) && (qd <= rEndDateTime.date())) || 968 ((rDuration == 0) && (qd <= rEndDateTime.date())) ||
968 (rDuration == -1))) { 969 (rDuration == -1))) {
969 // The date queried falls within the range of the event. 970 // The date queried falls within the range of the event.
970 if (secondFreq < 24*3600) 971 if (secondFreq < 24*3600)
971 return true; // the event recurs at least once each day 972 return true; // the event recurs at least once each day
972 int after = mRecurStart.secsTo(QDateTime(qd)); 973 int after = mRecurStart.secsTo(QDateTime(qd));
973 if (after / secondFreq != (after + 24*3600) / secondFreq) 974 if (after / secondFreq != (after + 24*3600) / secondFreq)
974 return true; 975 return true;
975 } 976 }
976 return false; 977 return false;
977} 978}
978 979
979bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const 980bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const
980{ 981{
981 if ((dt >= mRecurStart) && 982 if ((dt >= mRecurStart) &&
982 ((rDuration > 0) && (dt <= endDateTime()) || 983 ((rDuration > 0) && (dt <= endDateTime()) ||
983 ((rDuration == 0) && (dt <= rEndDateTime)) || 984 ((rDuration == 0) && (dt <= rEndDateTime)) ||
984 (rDuration == -1))) { 985 (rDuration == -1))) {
985 // The time queried falls within the range of the event. 986 // The time queried falls within the range of the event.
986 if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0) 987 if (((mRecurStart.secsTo(dt) / 60) % minuteFreq) == 0)
987 return true; 988 return true;
988 } 989 }
989 return false; 990 return false;
990} 991}
991 992
992bool Recurrence::recursDaily(const QDate &qd) const 993bool Recurrence::recursDaily(const QDate &qd) const
993{ 994{
994 QDate dStart = mRecurStart.date(); 995 QDate dStart = mRecurStart.date();
995 if ((dStart.daysTo(qd) % rFreq) == 0) { 996 if ((dStart.daysTo(qd) % rFreq) == 0) {
996 // The date is a day which recurs 997 // The date is a day which recurs
997 if (qd >= dStart 998 if (qd >= dStart
998 && ((rDuration > 0 && qd <= endDate()) || 999 && ((rDuration > 0 && qd <= endDate()) ||
999 (rDuration == 0 && qd <= rEndDateTime.date()) || 1000 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1000 rDuration == -1)) { 1001 rDuration == -1)) {
1001 // The date queried falls within the range of the event. 1002 // The date queried falls within the range of the event.
1002 return true; 1003 return true;
1003 } 1004 }
1004 } 1005 }
1005 return false; 1006 return false;
1006} 1007}
1007 1008
1008bool Recurrence::recursWeekly(const QDate &qd) const 1009bool Recurrence::recursWeekly(const QDate &qd) const
1009{ 1010{
1010 QDate dStart = mRecurStart.date(); 1011 QDate dStart = mRecurStart.date();
1011 if ((dStart.daysTo(qd)/7) % rFreq == 0) { 1012 if ((dStart.daysTo(qd)/7) % rFreq == 0) {
1012 // The date is in a week which recurs 1013 // The date is in a week which recurs
1013 if (qd >= dStart 1014 if (qd >= dStart
1014 && ((rDuration > 0 && qd <= endDate()) || 1015 && ((rDuration > 0 && qd <= endDate()) ||
1015 (rDuration == 0 && qd <= rEndDateTime.date()) || 1016 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1016 rDuration == -1)) { 1017 rDuration == -1)) {
1017 // The date queried falls within the range of the event. 1018 // The date queried falls within the range of the event.
1018 // check if the bits set match today. 1019 // check if the bits set match today.
1019 int i = qd.dayOfWeek()-1; 1020 int i = qd.dayOfWeek()-1;
1020 if (rDays.testBit((uint) i)) 1021 if (rDays.testBit((uint) i))
1021 return true; 1022 return true;
1022 } 1023 }
1023 } 1024 }
1024 return false; 1025 return false;
1025} 1026}
1026 1027
1027bool Recurrence::recursMonthly(const QDate &qd) const 1028bool Recurrence::recursMonthly(const QDate &qd) const
1028{ 1029{
1029 QDate dStart = mRecurStart.date(); 1030 QDate dStart = mRecurStart.date();
1030 int year = qd.year(); 1031 int year = qd.year();
1031 int month = qd.month(); 1032 int month = qd.month();
1032 int day = qd.day(); 1033 int day = qd.day();
1033 // calculate how many months ahead this date is from the original 1034 // calculate how many months ahead this date is from the original
1034 // event's date 1035 // event's date
1035 int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month()); 1036 int monthsAhead = (year - dStart.year()) * 12 + (month - dStart.month());
1036 if ((monthsAhead % rFreq) == 0) { 1037 if ((monthsAhead % rFreq) == 0) {
1037 // The date is in a month which recurs 1038 // The date is in a month which recurs
1038 if (qd >= dStart 1039 if (qd >= dStart
1039 && ((rDuration > 0 && qd <= endDate()) || 1040 && ((rDuration > 0 && qd <= endDate()) ||
1040 (rDuration == 0 && qd <= rEndDateTime.date()) || 1041 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1041 rDuration == -1)) { 1042 rDuration == -1)) {
1042 // The date queried falls within the range of the event. 1043 // The date queried falls within the range of the event.
1043 QValueList<int> days; 1044 QValueList<int> days;
1044 int daysInMonth = qd.daysInMonth(); 1045 int daysInMonth = qd.daysInMonth();
1045 if (recurs == rMonthlyDay) 1046 if (recurs == rMonthlyDay)
1046 getMonthlyDayDays(days, daysInMonth); 1047 getMonthlyDayDays(days, daysInMonth);
1047 else if (recurs == rMonthlyPos) 1048 else if (recurs == rMonthlyPos)
1048 getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek()); 1049 getMonthlyPosDays(days, daysInMonth, QDate(year, month, 1).dayOfWeek());
1049 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { 1050 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
1050 if (*it == day) 1051 if (*it == day)
1051 return true; 1052 return true;
1052 } 1053 }
1053 // no dates matched 1054 // no dates matched
1054 } 1055 }
1055 } 1056 }
1056 return false; 1057 return false;
1057} 1058}
1058 1059
1059bool Recurrence::recursYearlyByMonth(const QDate &qd) const 1060bool Recurrence::recursYearlyByMonth(const QDate &qd) const
1060{ 1061{
1061 QDate dStart = mRecurStart.date(); 1062 QDate dStart = mRecurStart.date();
1062 int startDay = dStart.day(); 1063 int startDay = dStart.day();
1063 int qday = qd.day(); 1064 int qday = qd.day();
1064 int qmonth = qd.month(); 1065 int qmonth = qd.month();
1065 int qyear = qd.year(); 1066 int qyear = qd.year();
1066 bool match = (qday == startDay); 1067 bool match = (qday == startDay);
1067 if (!match && startDay == 29 && dStart.month() == 2) { 1068 if (!match && startDay == 29 && dStart.month() == 2) {
1068 // It's a recurrence on February 29th 1069 // It's a recurrence on February 29th
1069 switch (mFeb29YearlyType) { 1070 switch (mFeb29YearlyType) {
1070 case rFeb28: 1071 case rFeb28:
1071 if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear)) 1072 if (qday == 28 && qmonth == 2 && !QDate::leapYear(qyear))
1072 match = true; 1073 match = true;
1073 break; 1074 break;
1074 case rMar1: 1075 case rMar1:
1075 if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) { 1076 if (qday == 1 && qmonth == 3 && !QDate::leapYear(qyear)) {
1076 qmonth = 2; 1077 qmonth = 2;
1077 match = true; 1078 match = true;
1078 } 1079 }
1079 break; 1080 break;
1080 case rFeb29: 1081 case rFeb29:
1081 break; 1082 break;
1082 } 1083 }
1083 } 1084 }
1084 1085
1085 if (match) { 1086 if (match) {
1086 // The day of the month matches. Calculate how many years ahead 1087 // The day of the month matches. Calculate how many years ahead
1087 // this date is from the original event's date. 1088 // this date is from the original event's date.
1088 int yearsAhead = (qyear - dStart.year()); 1089 int yearsAhead = (qyear - dStart.year());
1089 if (yearsAhead % rFreq == 0) { 1090 if (yearsAhead % rFreq == 0) {
1090 // The date is in a year which recurs 1091 // The date is in a year which recurs
1091 if (qd >= dStart 1092 if (qd >= dStart
1092 && ((rDuration > 0 && qd <= endDate()) || 1093 && ((rDuration > 0 && qd <= endDate()) ||
1093 (rDuration == 0 && qd <= rEndDateTime.date()) || 1094 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1094 rDuration == -1)) { 1095 rDuration == -1)) {
1095 // The date queried falls within the range of the event. 1096 // The date queried falls within the range of the event.
1096 int i = qmonth; 1097 int i = qmonth;
1097 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1098 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1098 if (i == *qlin.current()) 1099 if (i == *qlin.current())
1099 return true; 1100 return true;
1100 } 1101 }
1101 } 1102 }
1102 } 1103 }
1103 } 1104 }
1104 return false; 1105 return false;
1105} 1106}
1106 1107
1107bool Recurrence::recursYearlyByPos(const QDate &qd) const 1108bool Recurrence::recursYearlyByPos(const QDate &qd) const
1108{ 1109{
1109 QDate dStart = mRecurStart.date(); 1110 QDate dStart = mRecurStart.date();
1110 int year = qd.year(); 1111 int year = qd.year();
1111 int month = qd.month(); 1112 int month = qd.month();
1112 int day = qd.day(); 1113 int day = qd.day();
1113 // calculate how many years ahead this date is from the original 1114 // calculate how many years ahead this date is from the original
1114 // event's date 1115 // event's date
1115 int yearsAhead = (year - dStart.year()); 1116 int yearsAhead = (year - dStart.year());
1116 if (yearsAhead % rFreq == 0) { 1117 if (yearsAhead % rFreq == 0) {
1117 // The date is in a year which recurs 1118 // The date is in a year which recurs
1118 if (qd >= dStart 1119 if (qd >= dStart
1119 && ((rDuration > 0 && qd <= endDate()) || 1120 && ((rDuration > 0 && qd <= endDate()) ||
1120 (rDuration == 0 && qd <= rEndDateTime.date()) || 1121 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1121 rDuration == -1)) { 1122 rDuration == -1)) {
1122 // The date queried falls within the range of the event. 1123 // The date queried falls within the range of the event.
1123 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1124 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1124 if (month == *qlin.current()) { 1125 if (month == *qlin.current()) {
1125 // The month recurs 1126 // The month recurs
1126 QValueList<int> days; 1127 QValueList<int> days;
1127 getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek()); 1128 getMonthlyPosDays(days, qd.daysInMonth(), QDate(year, month, 1).dayOfWeek());
1128 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) { 1129 for (QValueList<int>::Iterator it = days.begin(); it != days.end(); ++it) {
1129 if (*it == day) 1130 if (*it == day)
1130 return true; 1131 return true;
1131 } 1132 }
1132 } 1133 }
1133 } 1134 }
1134 } 1135 }
1135 } 1136 }
1136 return false; 1137 return false;
1137} 1138}
1138 1139
1139bool Recurrence::recursYearlyByDay(const QDate &qd) const 1140bool Recurrence::recursYearlyByDay(const QDate &qd) const
1140{ 1141{
1141 QDate dStart = mRecurStart.date(); 1142 QDate dStart = mRecurStart.date();
1142 // calculate how many years ahead this date is from the original 1143 // calculate how many years ahead this date is from the original
1143 // event's date 1144 // event's date
1144 int yearsAhead = (qd.year() - dStart.year()); 1145 int yearsAhead = (qd.year() - dStart.year());
1145 if (yearsAhead % rFreq == 0) { 1146 if (yearsAhead % rFreq == 0) {
1146 // The date is in a year which recurs 1147 // The date is in a year which recurs
1147 if (qd >= dStart 1148 if (qd >= dStart
1148 && ((rDuration > 0 && qd <= endDate()) || 1149 && ((rDuration > 0 && qd <= endDate()) ||
1149 (rDuration == 0 && qd <= rEndDateTime.date()) || 1150 (rDuration == 0 && qd <= rEndDateTime.date()) ||
1150 rDuration == -1)) { 1151 rDuration == -1)) {
1151 // The date queried falls within the range of the event. 1152 // The date queried falls within the range of the event.
1152 int i = qd.dayOfYear(); 1153 int i = qd.dayOfYear();
1153 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) { 1154 for (QPtrListIterator<int> qlin(rYearNums); qlin.current(); ++qlin) {
1154 if (i == *qlin.current()) 1155 if (i == *qlin.current())
1155 return true; 1156 return true;
1156 } 1157 }
1157 } 1158 }
1158 } 1159 }
1159 return false; 1160 return false;
1160} 1161}
1161 1162
1162/* Get the date of the next recurrence, after the specified date. 1163/* Get the date of the next recurrence, after the specified date.
1163 * If 'last' is non-null, '*last' is set to true if the next recurrence is the 1164 * If 'last' is non-null, '*last' is set to true if the next recurrence is the
1164 * last recurrence, else false. 1165 * last recurrence, else false.
1165 * Reply = date of next recurrence, or invalid date if none. 1166 * Reply = date of next recurrence, or invalid date if none.
1166 */ 1167 */
1167QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const 1168QDate Recurrence::getNextDateNoTime(const QDate &preDate, bool *last) const
1168{ 1169{
1170
1169 if (last) 1171 if (last)
1170 *last = false; 1172 *last = false;
1171 QDate dStart = mRecurStart.date(); 1173 QDate dStart = mRecurStart.date();
1172 if (preDate < dStart) 1174 if (preDate < dStart)
1173 return dStart; 1175 return dStart;
1174 QDate earliestDate = preDate.addDays(1); 1176 QDate earliestDate = preDate.addDays(1);
1175 QDate nextDate; 1177 QDate nextDate;
1176 1178
1177 switch (recurs) { 1179 switch (recurs) {
1178 case rDaily: 1180 case rDaily:
1179 nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq); 1181 nextDate = dStart.addDays((dStart.daysTo(preDate)/rFreq + 1) * rFreq);
1180 break; 1182 break;
1181 1183
1182 case rWeekly: { 1184 case rWeekly: {
1183 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart 1185 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart
1184 int earliestDayOfWeek = earliestDate.dayOfWeek(); 1186 int earliestDayOfWeek = earliestDate.dayOfWeek();
1185 int weeksAhead = start.daysTo(earliestDate) / 7; 1187 int weeksAhead = start.daysTo(earliestDate) / 7;
1186 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week 1188 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
1187 weeksAhead -= notThisWeek; // latest week which recurred 1189 weeksAhead -= notThisWeek; // latest week which recurred
1188 int weekday = 0; 1190 int weekday = 0;
1189 // First check for any remaining day this week, if this week is a recurring week 1191 // First check for any remaining day this week, if this week is a recurring week
1190 if (!notThisWeek) 1192 if (!notThisWeek)
1191 weekday = getFirstDayInWeek(earliestDayOfWeek); 1193 weekday = getFirstDayInWeek(earliestDayOfWeek);
1192 // Check for a day in the next scheduled week 1194 // Check for a day in the next scheduled week
1193 if (!weekday && earliestDayOfWeek > 1) 1195 if (!weekday && earliestDayOfWeek > 1)
1194 weekday = getFirstDayInWeek(rWeekStart) + rFreq*7; 1196 weekday = getFirstDayInWeek(rWeekStart) + rFreq*7;
1195 if (weekday) 1197 if (weekday)
1196 nextDate = start.addDays(weeksAhead*7 + weekday - 1); 1198 nextDate = start.addDays(weeksAhead*7 + weekday - 1);
1197 break; 1199 break;
1198 } 1200 }
1199 case rMonthlyDay: 1201 case rMonthlyDay:
1200 case rMonthlyPos: { 1202 case rMonthlyPos: {
1201 int startYear = dStart.year(); 1203 int startYear = dStart.year();
1202 int startMonth = dStart.month(); // 1..12 1204 int startMonth = dStart.month(); // 1..12
1203 int earliestYear = earliestDate.year(); 1205 int earliestYear = earliestDate.year();
1204 int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth; 1206 int monthsAhead = (earliestYear - startYear)*12 + earliestDate.month() - startMonth;
1205 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month 1207 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
1206 monthsAhead -= notThisMonth; // latest month which recurred 1208 monthsAhead -= notThisMonth; // latest month which recurred
1207 // Check for the first later day in the current month 1209 // Check for the first later day in the current month
1208 if (!notThisMonth) 1210 if (!notThisMonth)
1209 nextDate = getFirstDateInMonth(earliestDate); 1211 nextDate = getFirstDateInMonth(earliestDate);
1210 if (!nextDate.isValid() && earliestDate.day() > 1) { 1212 if (!nextDate.isValid() && earliestDate.day() > 1) {
1211 // Check for a day in the next scheduled month 1213 // Check for a day in the next scheduled month
1212 int months = startMonth - 1 + monthsAhead + rFreq; 1214 int months = startMonth - 1 + monthsAhead + rFreq;
1213 nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1)); 1215 nextDate = getFirstDateInMonth(QDate(startYear + months/12, months%12 + 1, 1));
1214 } 1216 }
1215 break; 1217 break;
1216 } 1218 }
1217 case rYearlyMonth: 1219 case rYearlyMonth:
1218 case rYearlyPos: 1220 case rYearlyPos:
1219 case rYearlyDay: { 1221 case rYearlyDay: {
1220 int startYear = dStart.year(); 1222 int startYear = dStart.year();
1221 int yearsAhead = earliestDate.year() - startYear; 1223 int yearsAhead = earliestDate.year() - startYear;
1222 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year 1224 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
1223 yearsAhead -= notThisYear; // latest year which recurred 1225 yearsAhead -= notThisYear; // latest year which recurred
1224 // Check for the first later date in the current year 1226 // Check for the first later date in the current year
1225 if (!notThisYear) 1227 if (!notThisYear)
1226 nextDate = getFirstDateInYear(earliestDate); 1228 nextDate = getFirstDateInYear(earliestDate);
1227 // Check for a date in the next scheduled year 1229 // Check for a date in the next scheduled year
1228 if (!nextDate.isValid() && earliestDate.dayOfYear() > 1) 1230 if (!nextDate.isValid() && earliestDate.dayOfYear() > 1)
1229 nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1)); 1231 nextDate = getFirstDateInYear(QDate(startYear + yearsAhead + rFreq, 1, 1));
1230 break; 1232 break;
1231 } 1233 }
1232 case rNone: 1234 case rNone:
1233 default: 1235 default:
1234 return QDate(); 1236 return QDate();
1235 } 1237 }
1236 1238
1237 if (rDuration >= 0 && nextDate.isValid()) { 1239 if (rDuration >= 0 && nextDate.isValid()) {
1238 // Check that the date found is within the range of the recurrence 1240 // Check that the date found is within the range of the recurrence
1239 QDate end = endDate(); 1241 QDate end = endDate();
1240 if (nextDate > end) 1242 if (nextDate > end)
1241 return QDate(); 1243 return QDate();
1242 if (last && nextDate == end) 1244 if (last && nextDate == end)
1243 *last = true; 1245 *last = true;
1244 } 1246 }
1245 return nextDate; 1247 return nextDate;
1246} 1248}
1247 1249
1248/* Get the date of the last previous recurrence, before the specified date. 1250/* Get the date of the last previous recurrence, before the specified date.
1249 * Reply = date of previous recurrence, or invalid date if none. 1251 * Reply = date of previous recurrence, or invalid date if none.
1250 */ 1252 */
1251QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const 1253QDate Recurrence::getPreviousDateNoTime(const QDate &afterDate, bool *last) const
1252{ 1254{
1253 if (last) 1255 if (last)
1254 *last = false; 1256 *last = false;
1255 QDate dStart = mRecurStart.date(); 1257 QDate dStart = mRecurStart.date();
1256 QDate latestDate = afterDate.addDays(-1); 1258 QDate latestDate = afterDate.addDays(-1);
1257 if (latestDate < dStart) 1259 if (latestDate < dStart)
1258 return QDate(); 1260 return QDate();
1259 QDate prevDate; 1261 QDate prevDate;
1260 1262
1261 switch (recurs) { 1263 switch (recurs) {
1262 case rDaily: 1264 case rDaily:
1263 prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq); 1265 prevDate = dStart.addDays((dStart.daysTo(latestDate) / rFreq) * rFreq);
1264 break; 1266 break;
1265 1267
1266 case rWeekly: { 1268 case rWeekly: {
1267 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart 1269 QDate start = dStart.addDays(1 - dStart.dayOfWeek()); // start of week for dStart
1268 int latestDayOfWeek = latestDate.dayOfWeek(); 1270 int latestDayOfWeek = latestDate.dayOfWeek();
1269 int weeksAhead = start.daysTo(latestDate) / 7; 1271 int weeksAhead = start.daysTo(latestDate) / 7;
1270 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week 1272 int notThisWeek = weeksAhead % rFreq; // zero if this week is a recurring week
1271 weeksAhead -= notThisWeek; // latest week which recurred 1273 weeksAhead -= notThisWeek; // latest week which recurred
1272 int weekday = 0; 1274 int weekday = 0;
1273 // First check for any previous day this week, if this week is a recurring week 1275 // First check for any previous day this week, if this week is a recurring week
1274 if (!notThisWeek) 1276 if (!notThisWeek)
1275 weekday = getLastDayInWeek(latestDayOfWeek); 1277 weekday = getLastDayInWeek(latestDayOfWeek);
1276 // Check for a day in the previous scheduled week 1278 // Check for a day in the previous scheduled week
1277 if (!weekday) { 1279 if (!weekday) {
1278 int weekEnd = (rWeekStart + 5)%7 + 1; 1280 int weekEnd = (rWeekStart + 5)%7 + 1;
1279 if (latestDayOfWeek < weekEnd) { 1281 if (latestDayOfWeek < weekEnd) {
1280 if (!notThisWeek) 1282 if (!notThisWeek)
1281 weeksAhead -= rFreq; 1283 weeksAhead -= rFreq;
1282 weekday = getLastDayInWeek(weekEnd); 1284 weekday = getLastDayInWeek(weekEnd);
1283 } 1285 }
1284 } 1286 }
1285 if (weekday) 1287 if (weekday)
1286 prevDate = start.addDays(weeksAhead*7 + weekday - 1); 1288 prevDate = start.addDays(weeksAhead*7 + weekday - 1);
1287 break; 1289 break;
1288 } 1290 }
1289 case rMonthlyDay: 1291 case rMonthlyDay:
1290 case rMonthlyPos: { 1292 case rMonthlyPos: {
1291 int startYear = dStart.year(); 1293 int startYear = dStart.year();
1292 int startMonth = dStart.month(); // 1..12 1294 int startMonth = dStart.month(); // 1..12
1293 int latestYear = latestDate.year(); 1295 int latestYear = latestDate.year();
1294 int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth; 1296 int monthsAhead = (latestYear - startYear)*12 + latestDate.month() - startMonth;
1295 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month 1297 int notThisMonth = monthsAhead % rFreq; // zero if this month is a recurring month
1296 monthsAhead -= notThisMonth; // latest month which recurred 1298 monthsAhead -= notThisMonth; // latest month which recurred
1297 // Check for the last earlier day in the current month 1299 // Check for the last earlier day in the current month
1298 if (!notThisMonth) 1300 if (!notThisMonth)
1299 prevDate = getLastDateInMonth(latestDate); 1301 prevDate = getLastDateInMonth(latestDate);
1300 if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) { 1302 if (!prevDate.isValid() && latestDate.day() < latestDate.daysInMonth()) {
1301 // Check for a day in the previous scheduled month 1303 // Check for a day in the previous scheduled month
1302 if (!notThisMonth) 1304 if (!notThisMonth)
1303 monthsAhead -= rFreq; 1305 monthsAhead -= rFreq;
1304 int months = startMonth + monthsAhead; // get the month after the one that recurs 1306 int months = startMonth + monthsAhead; // get the month after the one that recurs
1305 prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1)); 1307 prevDate = getLastDateInMonth(QDate(startYear + months/12, months%12 + 1, 1).addDays(-1));
1306 } 1308 }
1307 break; 1309 break;
1308 } 1310 }
1309 case rYearlyMonth: 1311 case rYearlyMonth:
1310 case rYearlyPos: 1312 case rYearlyPos:
1311 case rYearlyDay: { 1313 case rYearlyDay: {
1312 int startYear = dStart.year(); 1314 int startYear = dStart.year();
1313 int yearsAhead = latestDate.year() - startYear; 1315 int yearsAhead = latestDate.year() - startYear;
1314 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year 1316 int notThisYear = yearsAhead % rFreq; // zero if this year is a recurring year
1315 yearsAhead -= notThisYear; // latest year which recurred 1317 yearsAhead -= notThisYear; // latest year which recurred
1316 // Check for the first later date in the current year 1318 // Check for the first later date in the current year
1317 if (!notThisYear) 1319 if (!notThisYear)
1318 prevDate = getLastDateInYear(latestDate); 1320 prevDate = getLastDateInYear(latestDate);
1319 if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) { 1321 if (!prevDate.isValid() && latestDate.dayOfYear() < latestDate.daysInYear()) {
1320 // Check for a date in the next scheduled year 1322 // Check for a date in the next scheduled year
1321 if (!notThisYear) 1323 if (!notThisYear)
1322 yearsAhead -= rFreq; 1324 yearsAhead -= rFreq;
1323 prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31)); 1325 prevDate = getLastDateInYear(QDate(startYear + yearsAhead, 12, 31));
1324 } 1326 }
1325 break; 1327 break;
1326 } 1328 }
1327 case rNone: 1329 case rNone:
1328 default: 1330 default:
1329 return QDate(); 1331 return QDate();
1330 } 1332 }
1331 1333
1332 if (prevDate.isValid()) { 1334 if (prevDate.isValid()) {
1333 // Check that the date found is within the range of the recurrence 1335 // Check that the date found is within the range of the recurrence
1334 if (prevDate < dStart) 1336 if (prevDate < dStart)
1335 return QDate(); 1337 return QDate();
1336 if (rDuration >= 0) { 1338 if (rDuration >= 0) {
1337 QDate end = endDate(); 1339 QDate end = endDate();
1338 if (prevDate >= end) { 1340 if (prevDate >= end) {
1339 if (last) 1341 if (last)
1340 *last = true; 1342 *last = true;
1341 return end; 1343 return end;
1342 } 1344 }
1343 } 1345 }
1344 } 1346 }
1345 return prevDate; 1347 return prevDate;
1346} 1348}
1347 1349
1348void Recurrence::setDailySub(short type, int freq, int duration) 1350void Recurrence::setDailySub(short type, int freq, int duration)
1349{ 1351{
1350 recurs = type; 1352 recurs = type;
1351 rFreq = freq; 1353 rFreq = freq;
1352 rDuration = duration; 1354 rDuration = duration;
1353 rMonthPositions.clear(); 1355 rMonthPositions.clear();
1354 rMonthDays.clear(); 1356 rMonthDays.clear();
1355 rYearNums.clear(); 1357 rYearNums.clear();
1356 if (type != rDaily) 1358 if (type != rDaily)
1357 mFloats = false; // sub-daily types can't be floating 1359 mFloats = false; // sub-daily types can't be floating
1358 1360
1359 if (mParent) mParent->updated(); 1361 if (mParent) mParent->updated();
1360} 1362}
1361 1363
1362void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration) 1364void Recurrence::setYearly_(short type, Feb29Type feb29type, int freq, int duration)
1363{ 1365{
1364 recurs = type; 1366 recurs = type;
1365 if (mCompatVersion < 310 && type == rYearlyDay) { 1367 if (mCompatVersion < 310 && type == rYearlyDay) {
1366 mCompatRecurs = rYearlyDay; 1368 mCompatRecurs = rYearlyDay;
1367 recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month 1369 recurs = rYearlyMonth; // convert old yearly-by-day to yearly-by-month
1368 feb29type = rMar1; // retain the same day number in the year 1370 feb29type = rMar1; // retain the same day number in the year
1369 } 1371 }
1370 1372
1371 mFeb29YearlyType = feb29type; 1373 mFeb29YearlyType = feb29type;
1372 rFreq = freq; 1374 rFreq = freq;
1373 rDuration = duration; 1375 rDuration = duration;
1374 if (type != rYearlyPos) 1376 if (type != rYearlyPos)
1375 rMonthPositions.clear(); 1377 rMonthPositions.clear();
1376 rMonthDays.clear(); 1378 rMonthDays.clear();
1377 if (mParent) mParent->updated(); 1379 if (mParent) mParent->updated();
1378} 1380}
1379 1381
1380int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const 1382int Recurrence::recurCalc(PeriodFunc func, QDateTime &endtime) const
1381{ 1383{
1382 QDate enddate = endtime.date(); 1384 QDate enddate = endtime.date();
1383 switch (func) { 1385 switch (func) {
1384 case END_DATE_AND_COUNT: 1386 case END_DATE_AND_COUNT:
1385 if (rDuration < 0) { 1387 if (rDuration < 0) {
1386 endtime = QDateTime(); 1388 endtime = QDateTime();
1387 return 0; // infinite recurrence 1389 return 0; // infinite recurrence
1388 } 1390 }
1389 if (rDuration == 0) { 1391 if (rDuration == 0) {
1390 endtime = rEndDateTime; 1392 endtime = rEndDateTime;
1391 func = COUNT_TO_DATE; 1393 func = COUNT_TO_DATE;
1392 } 1394 }
1393 break; 1395 break;
1394 case COUNT_TO_DATE: 1396 case COUNT_TO_DATE:
1395 // Count recurrences up to and including the specified date/time. 1397 // Count recurrences up to and including the specified date/time.
1396 if (endtime < mRecurStart) 1398 if (endtime < mRecurStart)
1397 return 0; 1399 return 0;
1398 if (rDuration == 0 && endtime > rEndDateTime) 1400 if (rDuration == 0 && endtime > rEndDateTime)
1399 enddate = rEndDateTime.date(); 1401 enddate = rEndDateTime.date();
1400 else if (!mFloats && mRecurStart.time() > endtime.time()) 1402 else if (!mFloats && mRecurStart.time() > endtime.time())
1401 enddate = enddate.addDays(-1); 1403 enddate = enddate.addDays(-1);
1402 break; 1404 break;
1403 case NEXT_AFTER_DATE: 1405 case NEXT_AFTER_DATE:
1404 // Find next recurrence AFTER endtime 1406 // Find next recurrence AFTER endtime
1405 if (endtime < mRecurStart) { 1407 if (endtime < mRecurStart) {
1406 endtime = mRecurStart; 1408 endtime = mRecurStart;
1407 return 1; 1409 return 1;
1408 } 1410 }
1409 if (rDuration == 0 && endtime >= rEndDateTime) { 1411 if (rDuration == 0 && endtime >= rEndDateTime) {
1410 endtime = QDateTime(); 1412 endtime = QDateTime();
1411 return 0; 1413 return 0;
1412 } 1414 }
1413 if (!mFloats && mRecurStart.time() > endtime.time()) 1415 if (!mFloats && mRecurStart.time() > endtime.time())
1414 enddate = enddate.addDays(-1); 1416 enddate = enddate.addDays(-1);
1415 break; 1417 break;
1416 default: 1418 default:
1417 endtime = QDateTime(); 1419 endtime = QDateTime();
1418 return 0; 1420 return 0;
1419 } 1421 }
1420 1422
1421 int count = 0; // default = error 1423 int count = 0; // default = error
1422 bool timed = false; 1424 bool timed = false;
1423 switch (recurs) { 1425 switch (recurs) {
1424 case rMinutely: 1426 case rMinutely:
1425 timed = true; 1427 timed = true;
1426 count = secondlyCalc(func, endtime, rFreq*60); 1428 count = secondlyCalc(func, endtime, rFreq*60);
1427 break; 1429 break;
1428 case rHourly: 1430 case rHourly:
1429 timed = true; 1431 timed = true;
1430 count = secondlyCalc(func, endtime, rFreq*3600); 1432 count = secondlyCalc(func, endtime, rFreq*3600);
1431 break; 1433 break;
1432 case rDaily: 1434 case rDaily:
1433 count = dailyCalc(func, enddate); 1435 count = dailyCalc(func, enddate);
1434 break; 1436 break;
1435 case rWeekly: 1437 case rWeekly:
1436 count = weeklyCalc(func, enddate); 1438 count = weeklyCalc(func, enddate);
1437 break; 1439 break;
1438 case rMonthlyPos: 1440 case rMonthlyPos:
1439 case rMonthlyDay: 1441 case rMonthlyDay:
1440 count = monthlyCalc(func, enddate); 1442 count = monthlyCalc(func, enddate);
1441 break; 1443 break;
1442 case rYearlyMonth: 1444 case rYearlyMonth:
1443 count = yearlyMonthCalc(func, enddate); 1445 count = yearlyMonthCalc(func, enddate);
1444 break; 1446 break;
1445 case rYearlyPos: 1447 case rYearlyPos:
1446 count = yearlyPosCalc(func, enddate); 1448 count = yearlyPosCalc(func, enddate);
1447 break; 1449 break;
1448 case rYearlyDay: 1450 case rYearlyDay:
1449 count = yearlyDayCalc(func, enddate); 1451 count = yearlyDayCalc(func, enddate);
1450 break; 1452 break;
1451 default: 1453 default:
1452 break; 1454 break;
1453 } 1455 }
1454 1456
1455 switch (func) { 1457 switch (func) {
1456 case END_DATE_AND_COUNT: 1458 case END_DATE_AND_COUNT:
1457 case NEXT_AFTER_DATE: 1459 case NEXT_AFTER_DATE:
1458 if (count == 0) 1460 if (count == 0)
1459 endtime = QDateTime(); 1461 endtime = QDateTime();
1460 else if (!timed) { 1462 else if (!timed) {
1461 endtime.setDate(enddate); 1463 endtime.setDate(enddate);
1462 endtime.setTime(mRecurStart.time()); 1464 endtime.setTime(mRecurStart.time());
1463 } 1465 }
1464 break; 1466 break;
1465 case COUNT_TO_DATE: 1467 case COUNT_TO_DATE:
1466 break; 1468 break;
1467 } 1469 }
1468 return count; 1470 return count;
1469} 1471}
1470 1472
1471int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const 1473int Recurrence::recurCalc(PeriodFunc func, QDate &enddate) const
1472{ 1474{
1473 QDateTime endtime(enddate, QTime(23,59,59)); 1475 QDateTime endtime(enddate, QTime(23,59,59));
1474 switch (func) { 1476 switch (func) {
1475 case END_DATE_AND_COUNT: 1477 case END_DATE_AND_COUNT:
1476 if (rDuration < 0) { 1478 if (rDuration < 0) {
1477 enddate = QDate(); 1479 enddate = QDate();
1478 return 0; // infinite recurrence 1480 return 0; // infinite recurrence
1479 } 1481 }
1480 if (rDuration == 0) { 1482 if (rDuration == 0) {
1481 enddate = rEndDateTime.date(); 1483 enddate = rEndDateTime.date();
1482 func = COUNT_TO_DATE; 1484 func = COUNT_TO_DATE;
1483 } 1485 }
1484 break; 1486 break;
1485 case COUNT_TO_DATE: 1487 case COUNT_TO_DATE:
1486 // Count recurrences up to and including the specified date. 1488 // Count recurrences up to and including the specified date.
1487 if (enddate < mRecurStart.date()) 1489 if (enddate < mRecurStart.date())
1488 return 0; 1490 return 0;
1489 if (rDuration == 0 && enddate > rEndDateTime.date()) { 1491 if (rDuration == 0 && enddate > rEndDateTime.date()) {
1490 enddate = rEndDateTime.date(); 1492 enddate = rEndDateTime.date();
1491 endtime.setDate(enddate); 1493 endtime.setDate(enddate);
1492 } 1494 }
1493 break; 1495 break;
1494 case NEXT_AFTER_DATE: 1496 case NEXT_AFTER_DATE:
1495 if (enddate < mRecurStart.date()) { 1497 if (enddate < mRecurStart.date()) {
1496 enddate = mRecurStart.date(); 1498 enddate = mRecurStart.date();
1497 return 1; 1499 return 1;
1498 } 1500 }
1499 if (rDuration == 0 && enddate >= rEndDateTime.date()) { 1501 if (rDuration == 0 && enddate >= rEndDateTime.date()) {
1500 enddate = QDate(); 1502 enddate = QDate();
1501 return 0; 1503 return 0;
1502 } 1504 }
1503 break; 1505 break;
1504 default: 1506 default:
1505 enddate = QDate(); 1507 enddate = QDate();
1506 return 0; 1508 return 0;
1507 } 1509 }
1508 1510
1509 int count = 0; // default = error 1511 int count = 0; // default = error
1510 bool timed = false; 1512 bool timed = false;
1511 switch (recurs) { 1513 switch (recurs) {
1512 case rMinutely: 1514 case rMinutely:
1513 timed = true; 1515 timed = true;
1514 count = secondlyCalc(func, endtime, rFreq*60); 1516 count = secondlyCalc(func, endtime, rFreq*60);
1515 break; 1517 break;
1516 case rHourly: 1518 case rHourly:
1517 timed = true; 1519 timed = true;
1518 count = secondlyCalc(func, endtime, rFreq*3600); 1520 count = secondlyCalc(func, endtime, rFreq*3600);
1519 break; 1521 break;
1520 case rDaily: 1522 case rDaily:
1521 count = dailyCalc(func, enddate); 1523 count = dailyCalc(func, enddate);
1522 break; 1524 break;
1523 case rWeekly: 1525 case rWeekly:
1524 count = weeklyCalc(func, enddate); 1526 count = weeklyCalc(func, enddate);
1525 break; 1527 break;
1526 case rMonthlyPos: 1528 case rMonthlyPos:
1527 case rMonthlyDay: 1529 case rMonthlyDay:
1528 count = monthlyCalc(func, enddate); 1530 count = monthlyCalc(func, enddate);
1529 break; 1531 break;
1530 case rYearlyMonth: 1532 case rYearlyMonth:
1531 count = yearlyMonthCalc(func, enddate); 1533 count = yearlyMonthCalc(func, enddate);
1532 break; 1534 break;
1533 case rYearlyPos: 1535 case rYearlyPos:
1534 count = yearlyPosCalc(func, enddate); 1536 count = yearlyPosCalc(func, enddate);
1535 break; 1537 break;
1536 case rYearlyDay: 1538 case rYearlyDay:
1537 count = yearlyDayCalc(func, enddate); 1539 count = yearlyDayCalc(func, enddate);
1538 break; 1540 break;
1539 default: 1541 default:
1540 break; 1542 break;
1541 } 1543 }
1542 1544
1543 switch (func) { 1545 switch (func) {
1544 case END_DATE_AND_COUNT: 1546 case END_DATE_AND_COUNT:
1545 case NEXT_AFTER_DATE: 1547 case NEXT_AFTER_DATE:
1546 if (count == 0) 1548 if (count == 0)
1547 endtime = QDate(); 1549 endtime = QDate();
1548 else if (timed) 1550 else if (timed)
1549 enddate = endtime.date(); 1551 enddate = endtime.date();
1550 break; 1552 break;
1551 case COUNT_TO_DATE: 1553 case COUNT_TO_DATE:
1552 break; 1554 break;
1553 } 1555 }
1554 return count; 1556 return count;
1555} 1557}
1556 1558
1557/* Find count and, depending on 'func', the end date/time of a secondly recurrence. 1559/* Find count and, depending on 'func', the end date/time of a secondly recurrence.
1558 * Reply = total number of occurrences up to 'endtime', or 0 if error. 1560 * Reply = total number of occurrences up to 'endtime', or 0 if error.
1559 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the 1561 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'endtime' is updated to the
1560 * recurrence end date/time. 1562 * recurrence end date/time.
1561 */ 1563 */
1562int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const 1564int Recurrence::secondlyCalc(PeriodFunc func, QDateTime &endtime, int freq) const
1563{ 1565{
1564 switch (func) { 1566 switch (func) {
1565 case END_DATE_AND_COUNT: 1567 case END_DATE_AND_COUNT:
1566 endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq); 1568 endtime = mRecurStart.addSecs((rDuration + mRecurExDatesCount - 1) * freq);
1567 return rDuration + mRecurExDatesCount; 1569 return rDuration + mRecurExDatesCount;
1568 case COUNT_TO_DATE: { 1570 case COUNT_TO_DATE: {
1569 int n = mRecurStart.secsTo(endtime)/freq + 1; 1571 int n = mRecurStart.secsTo(endtime)/freq + 1;
1570 if (rDuration > 0 && n > rDuration + mRecurExDatesCount) 1572 if (rDuration > 0 && n > rDuration + mRecurExDatesCount)
1571 return rDuration + mRecurExDatesCount; 1573 return rDuration + mRecurExDatesCount;
1572 return n; 1574 return n;
1573 } 1575 }
1574 case NEXT_AFTER_DATE: { 1576 case NEXT_AFTER_DATE: {
1575 int count = mRecurStart.secsTo(endtime) / freq + 2; 1577 int count = mRecurStart.secsTo(endtime) / freq + 2;
1576 if (rDuration > 0 && count > rDuration) 1578 if (rDuration > 0 && count > rDuration)
1577 return 0; 1579 return 0;
1578 endtime = mRecurStart.addSecs((count - 1)*freq); 1580 endtime = mRecurStart.addSecs((count - 1)*freq);
1579 return count; 1581 return count;
1580 } 1582 }
1581 } 1583 }
1582 return 0; 1584 return 0;
1583} 1585}
1584 1586
1585/* Find count and, depending on 'func', the end date of a daily recurrence. 1587/* Find count and, depending on 'func', the end date of a daily recurrence.
1586 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1588 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1587 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1589 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1588 * recurrence end date. 1590 * recurrence end date.
1589 */ 1591 */
1590int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const 1592int Recurrence::dailyCalc(PeriodFunc func, QDate &enddate) const
1591{ 1593{
1592 QDate dStart = mRecurStart.date(); 1594 QDate dStart = mRecurStart.date();
1593 switch (func) { 1595 switch (func) {
1594 case END_DATE_AND_COUNT: 1596 case END_DATE_AND_COUNT:
1595 enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq); 1597 enddate = dStart.addDays((rDuration + mRecurExDatesCount - 1) * rFreq);
1596 return rDuration + mRecurExDatesCount; 1598 return rDuration + mRecurExDatesCount;
1597 case COUNT_TO_DATE: { 1599 case COUNT_TO_DATE: {
1598 int n = dStart.daysTo(enddate)/rFreq + 1; 1600 int n = dStart.daysTo(enddate)/rFreq + 1;
1599 if (rDuration > 0 && n > rDuration + mRecurExDatesCount) 1601 if (rDuration > 0 && n > rDuration + mRecurExDatesCount)
1600 return rDuration + mRecurExDatesCount; 1602 return rDuration + mRecurExDatesCount;
1601 return n; 1603 return n;
1602 } 1604 }
1603 case NEXT_AFTER_DATE: { 1605 case NEXT_AFTER_DATE: {
1604 int count = dStart.daysTo(enddate) / rFreq + 2; 1606 int count = dStart.daysTo(enddate) / rFreq + 2;
1605 if (rDuration > 0 && count > rDuration) 1607 if (rDuration > 0 && count > rDuration)
1606 return 0; 1608 return 0;
1607 enddate = dStart.addDays((count - 1)*rFreq); 1609 enddate = dStart.addDays((count - 1)*rFreq);
1608 return count; 1610 return count;
1609 } 1611 }
1610 } 1612 }
1611 return 0; 1613 return 0;
1612} 1614}
1613 1615
1614/* Find count and, depending on 'func', the end date of a weekly recurrence. 1616/* Find count and, depending on 'func', the end date of a weekly recurrence.
1615 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1617 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1616 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1618 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1617 * recurrence end date. 1619 * recurrence end date.
1618 */ 1620 */
1619int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const 1621int Recurrence::weeklyCalc(PeriodFunc func, QDate &enddate) const
1620{ 1622{
1621 int daysPerWeek = 0; 1623 int daysPerWeek = 0;
1622 for (int i = 0; i < 7; ++i) { 1624 for (int i = 0; i < 7; ++i) {
1623 if (rDays.testBit((uint)i)) 1625 if (rDays.testBit((uint)i))
1624 ++daysPerWeek; 1626 ++daysPerWeek;
1625 } 1627 }
1626 if (!daysPerWeek) 1628 if (!daysPerWeek)
1627 return 0; // there are no days to recur on 1629 return 0; // there are no days to recur on
1628 1630
1629 switch (func) { 1631 switch (func) {
1630 case END_DATE_AND_COUNT: 1632 case END_DATE_AND_COUNT:
1631 return weeklyCalcEndDate(enddate, daysPerWeek); 1633 return weeklyCalcEndDate(enddate, daysPerWeek);
1632 case COUNT_TO_DATE: 1634 case COUNT_TO_DATE:
1633 return weeklyCalcToDate(enddate, daysPerWeek); 1635 return weeklyCalcToDate(enddate, daysPerWeek);
1634 case NEXT_AFTER_DATE: 1636 case NEXT_AFTER_DATE:
1635 return weeklyCalcNextAfter(enddate, daysPerWeek); 1637 return weeklyCalcNextAfter(enddate, daysPerWeek);
1636 } 1638 }
1637 return 0; 1639 return 0;
1638} 1640}
1639 1641
1640int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const 1642int Recurrence::weeklyCalcEndDate(QDate &enddate, int daysPerWeek) const
1641{ 1643{
1642 int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7 1644 int startDayOfWeek = mRecurStart.date().dayOfWeek(); // 1..7
1643 int countGone = 0; 1645 int countGone = 0;
1644 int daysGone = 0; 1646 int daysGone = 0;
1645 uint countTogo = rDuration + mRecurExDatesCount; 1647 uint countTogo = rDuration + mRecurExDatesCount;
1646 if (startDayOfWeek != rWeekStart) { 1648 if (startDayOfWeek != rWeekStart) {
1647 // Check what remains of the start week 1649 // Check what remains of the start week
1648 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1650 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1649 ++daysGone; 1651 ++daysGone;
1650 if (rDays.testBit((uint)i)) { 1652 if (rDays.testBit((uint)i)) {
1651 ++countGone; 1653 ++countGone;
1652 if (--countTogo == 0) 1654 if (--countTogo == 0)
1653 break; 1655 break;
1654 } 1656 }
1655 } 1657 }
1656 daysGone += 7 * (rFreq - 1); 1658 daysGone += 7 * (rFreq - 1);
1657 } 1659 }
1658 if (countTogo) { 1660 if (countTogo) {
1659 // Skip the remaining whole weeks 1661 // Skip the remaining whole weeks
1660 // Leave at least 1 recurrence remaining, in order to get its date 1662 // Leave at least 1 recurrence remaining, in order to get its date
1661 int wholeWeeks = (countTogo - 1) / daysPerWeek; 1663 int wholeWeeks = (countTogo - 1) / daysPerWeek;
1662 daysGone += wholeWeeks * 7 * rFreq; 1664 daysGone += wholeWeeks * 7 * rFreq;
1663 countGone += wholeWeeks * daysPerWeek; 1665 countGone += wholeWeeks * daysPerWeek;
1664 countTogo -= wholeWeeks * daysPerWeek; 1666 countTogo -= wholeWeeks * daysPerWeek;
1665 // Check the last week in the recurrence 1667 // Check the last week in the recurrence
1666 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1668 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1667 ++daysGone; 1669 ++daysGone;
1668 if (rDays.testBit((uint)i)) { 1670 if (rDays.testBit((uint)i)) {
1669 ++countGone; 1671 ++countGone;
1670 if (--countTogo == 0) 1672 if (--countTogo == 0)
1671 break; 1673 break;
1672 } 1674 }
1673 } 1675 }
1674 } 1676 }
1675 enddate = mRecurStart.date().addDays(daysGone); 1677 enddate = mRecurStart.date().addDays(daysGone);
1676 return countGone; 1678 return countGone;
1677} 1679}
1678 1680
1679int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const 1681int Recurrence::weeklyCalcToDate(const QDate &enddate, int daysPerWeek) const
1680{ 1682{
1681 QDate dStart = mRecurStart.date(); 1683 QDate dStart = mRecurStart.date();
1682 int startDayOfWeek = dStart.dayOfWeek(); // 1..7 1684 int startDayOfWeek = dStart.dayOfWeek(); // 1..7
1683 int countGone = 0; 1685 int countGone = 0;
1684 int daysGone = 0; 1686 int daysGone = 0;
1685 int totalDays = dStart.daysTo(enddate) + 1; 1687 int totalDays = dStart.daysTo(enddate) + 1;
1686 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 1688 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
1687 1689
1688 if (startDayOfWeek != rWeekStart) { 1690 if (startDayOfWeek != rWeekStart) {
1689 // Check what remains of the start week 1691 // Check what remains of the start week
1690 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1692 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1691 if (rDays.testBit((uint)i)) { 1693 if (rDays.testBit((uint)i)) {
1692 if (++countGone >= countMax) 1694 if (++countGone >= countMax)
1693 return countMax; 1695 return countMax;
1694 } 1696 }
1695 if (++daysGone == totalDays) 1697 if (++daysGone == totalDays)
1696 return countGone; 1698 return countGone;
1697 } 1699 }
1698 daysGone += 7 * (rFreq - 1); 1700 daysGone += 7 * (rFreq - 1);
1699 if (daysGone >= totalDays) 1701 if (daysGone >= totalDays)
1700 return countGone; 1702 return countGone;
1701 } 1703 }
1702 // Skip the remaining whole weeks 1704 // Skip the remaining whole weeks
1703 int wholeWeeks = (totalDays - daysGone) / 7; 1705 int wholeWeeks = (totalDays - daysGone) / 7;
1704 countGone += (wholeWeeks / rFreq) * daysPerWeek; 1706 countGone += (wholeWeeks / rFreq) * daysPerWeek;
1705 if (countGone >= countMax) 1707 if (countGone >= countMax)
1706 return countMax; 1708 return countMax;
1707 daysGone += wholeWeeks * 7; 1709 daysGone += wholeWeeks * 7;
1708 if (daysGone >= totalDays // have we reached the end date? 1710 if (daysGone >= totalDays // have we reached the end date?
1709 || wholeWeeks % rFreq) // is end week a recurrence week? 1711 || wholeWeeks % rFreq) // is end week a recurrence week?
1710 return countGone; 1712 return countGone;
1711 1713
1712 // Check the last week in the recurrence 1714 // Check the last week in the recurrence
1713 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1715 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1714 if (rDays.testBit((uint)i)) { 1716 if (rDays.testBit((uint)i)) {
1715 if (++countGone >= countMax) 1717 if (++countGone >= countMax)
1716 return countMax; 1718 return countMax;
1717 } 1719 }
1718 if (++daysGone == totalDays) 1720 if (++daysGone == totalDays)
1719 return countGone; 1721 return countGone;
1720 } 1722 }
1721 return countGone; 1723 return countGone;
1722} 1724}
1723 1725
1724int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const 1726int Recurrence::weeklyCalcNextAfter(QDate &enddate, int daysPerWeek) const
1725{ 1727{
1726 QDate dStart = mRecurStart.date(); 1728 QDate dStart = mRecurStart.date();
1727 int startDayOfWeek = dStart.dayOfWeek(); // 1..7 1729 int startDayOfWeek = dStart.dayOfWeek(); // 1..7
1728 int totalDays = dStart.daysTo(enddate) + 1; 1730 int totalDays = dStart.daysTo(enddate) + 1;
1729 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX; 1731 uint countTogo = (rDuration > 0) ? rDuration + mRecurExDatesCount : UINT_MAX;
1730 int countGone = 0; 1732 int countGone = 0;
1731 int daysGone = 0; 1733 int daysGone = 0;
1732 int recurWeeks; 1734 int recurWeeks;
1733 1735
1734 if (startDayOfWeek != rWeekStart) { 1736 if (startDayOfWeek != rWeekStart) {
1735 // Check what remains of the start week 1737 // Check what remains of the start week
1736 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) { 1738 for (int i = startDayOfWeek - 1; i != rWeekStart - 1; i = (i + 1) % 7) {
1737 ++daysGone; 1739 ++daysGone;
1738 if (rDays.testBit((uint)i)) { 1740 if (rDays.testBit((uint)i)) {
1739 ++countGone; 1741 ++countGone;
1740 if (daysGone > totalDays) 1742 if (daysGone > totalDays)
1741 goto ex; 1743 goto ex;
1742 if (--countTogo == 0) 1744 if (--countTogo == 0)
1743 return 0; 1745 return 0;
1744 } 1746 }
1745 } 1747 }
1746 daysGone += 7 * (rFreq - 1); 1748 daysGone += 7 * (rFreq - 1);
1747 } 1749 }
1748 1750
1749 // Skip the remaining whole weeks 1751 // Skip the remaining whole weeks
1750 recurWeeks = (totalDays - daysGone) / (7 * rFreq); 1752 recurWeeks = (totalDays - daysGone) / (7 * rFreq);
1751 if (recurWeeks) { 1753 if (recurWeeks) {
1752 int n = recurWeeks * daysPerWeek; 1754 int n = recurWeeks * daysPerWeek;
1753 if (static_cast<uint>(n) > countTogo) 1755 if (static_cast<uint>(n) > countTogo)
1754 return 0; // reached end of recurrence 1756 return 0; // reached end of recurrence
1755 countGone += n; 1757 countGone += n;
1756 countTogo -= n; 1758 countTogo -= n;
1757 daysGone += recurWeeks * 7 * rFreq; 1759 daysGone += recurWeeks * 7 * rFreq;
1758 } 1760 }
1759 1761
1760 // Check the last week or two in the recurrence 1762 // Check the last week or two in the recurrence
1761 for ( ; ; ) { 1763 for ( ; ; ) {
1762 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) { 1764 for (int i = rWeekStart - 1; ; i = (i + 1) % 7) {
1763 ++daysGone; 1765 ++daysGone;
1764 if (rDays.testBit((uint)i)) { 1766 if (rDays.testBit((uint)i)) {
1765 ++countGone; 1767 ++countGone;
1766 if (daysGone > totalDays) 1768 if (daysGone > totalDays)
1767 goto ex; 1769 goto ex;
1768 if (--countTogo == 0) 1770 if (--countTogo == 0)
1769 return 0; 1771 return 0;
1770 } 1772 }
1771 } 1773 }
1772 daysGone += 7 * (rFreq - 1); 1774 daysGone += 7 * (rFreq - 1);
1773 } 1775 }
1774ex: 1776ex:
1775 enddate = dStart.addDays(daysGone); 1777 enddate = dStart.addDays(daysGone);
1776 return countGone; 1778 return countGone;
1777} 1779}
1778 1780
1779/* Find count and, depending on 'func', the end date of a monthly recurrence. 1781/* Find count and, depending on 'func', the end date of a monthly recurrence.
1780 * Reply = total number of occurrences up to 'enddate', or 0 if error. 1782 * Reply = total number of occurrences up to 'enddate', or 0 if error.
1781 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the 1783 * If 'func' = END_DATE_AND_COUNT or NEXT_AFTER_DATE, 'enddate' is updated to the
1782 * recurrence end date. 1784 * recurrence end date.
1783 */ 1785 */
1784struct Recurrence::MonthlyData { 1786struct Recurrence::MonthlyData {
1785 const Recurrence *recurrence; 1787 const Recurrence *recurrence;
1786 int year; // current year 1788 int year; // current year
1787 int month; // current month 0..11 1789 int month; // current month 0..11
1788 int day; // current day of month 1..31 1790 int day; // current day of month 1..31
1789 bool varies; // true if recurring days vary between different months 1791 bool varies; // true if recurring days vary between different months
1790 private: 1792 private:
1791 QValueList<int> days28, days29, days30, days31; // recurring days in months of each length 1793 QValueList<int> days28, days29, days30, days31; // recurring days in months of each length
1792 QValueList<int> *recurDays[4]; 1794 QValueList<int> *recurDays[4];
1793 public: 1795 public:
1794 MonthlyData(const Recurrence* r, const QDate &date) 1796 MonthlyData(const Recurrence* r, const QDate &date)
1795 : recurrence(r), year(date.year()), month(date.month()-1), day(date.day()) 1797 : recurrence(r), year(date.year()), month(date.month()-1), day(date.day())
1796 { recurDays[0] = &days28; 1798 { recurDays[0] = &days28;
1797 recurDays[1] = &days29; 1799 recurDays[1] = &days29;
1798 recurDays[2] = &days30; 1800 recurDays[2] = &days30;
1799 recurDays[3] = &days31; 1801 recurDays[3] = &days31;
1800 varies = (recurrence->recurs == rMonthlyPos) 1802 varies = (recurrence->recurs == rMonthlyPos)
1801 ? true : recurrence->getMonthlyDayDays(days31, 31); 1803 ? true : recurrence->getMonthlyDayDays(days31, 31);
1802 } 1804 }
1803 const QValueList<int>* dayList() const { 1805 const QValueList<int>* dayList() const {
1804 if (!varies) 1806 if (!varies)
1805 return &days31; 1807 return &days31;
1806 QDate startOfMonth(year, month + 1, 1); 1808 QDate startOfMonth(year, month + 1, 1);
1807 int daysInMonth = startOfMonth.daysInMonth(); 1809 int daysInMonth = startOfMonth.daysInMonth();
1808 QValueList<int>* days = recurDays[daysInMonth - 28]; 1810 QValueList<int>* days = recurDays[daysInMonth - 28];
1809 if (recurrence->recurs == rMonthlyPos) 1811 if (recurrence->recurs == rMonthlyPos)
1810 recurrence->getMonthlyPosDays(*days, daysInMonth, startOfMonth.dayOfWeek()); 1812 recurrence->getMonthlyPosDays(*days, daysInMonth, startOfMonth.dayOfWeek());
1811 else if (days->isEmpty()) 1813 else if (days->isEmpty())
1812 recurrence->getMonthlyDayDays(*days, daysInMonth); 1814 recurrence->getMonthlyDayDays(*days, daysInMonth);
1813 return days; 1815 return days;
1814 } 1816 }
1815 int yearMonth() const { return year*12 + month; } 1817 int yearMonth() const { return year*12 + month; }
1816 void addMonths(int diff) { month += diff; year += month / 12; month %= 12; } 1818 void addMonths(int diff) { month += diff; year += month / 12; month %= 12; }
1817 QDate date() const { return QDate(year, month + 1, day); } 1819 QDate date() const { return QDate(year, month + 1, day); }
1818}; 1820};
1819 1821
1820int Recurrence::monthlyCalc(PeriodFunc func, QDate &enddate) const 1822int Recurrence::monthlyCalc(PeriodFunc func, QDate &enddate) const
1821{ 1823{
1822 if (recurs == rMonthlyPos && rMonthPositions.isEmpty() 1824 if (recurs == rMonthlyPos && rMonthPositions.isEmpty()
1823 || recurs == rMonthlyDay && rMonthDays.isEmpty()) 1825 || recurs == rMonthlyDay && rMonthDays.isEmpty())
1824 return 0; 1826 return 0;
1825 1827
1826 MonthlyData data(this, mRecurStart.date()); 1828 MonthlyData data(this, mRecurStart.date());
1827 switch (func) { 1829 switch (func) {
1828 case END_DATE_AND_COUNT: 1830 case END_DATE_AND_COUNT:
1829 return monthlyCalcEndDate(enddate, data); 1831 return monthlyCalcEndDate(enddate, data);
1830 case COUNT_TO_DATE: 1832 case COUNT_TO_DATE:
1831 return monthlyCalcToDate(enddate, data); 1833 return monthlyCalcToDate(enddate, data);
1832 case NEXT_AFTER_DATE: 1834 case NEXT_AFTER_DATE:
1833 return monthlyCalcNextAfter(enddate, data); 1835 return monthlyCalcNextAfter(enddate, data);
1834 } 1836 }
1835 return 0; 1837 return 0;
1836} 1838}
1837 1839
1838int Recurrence::monthlyCalcEndDate(QDate &enddate, MonthlyData &data) const 1840int Recurrence::monthlyCalcEndDate(QDate &enddate, MonthlyData &data) const
1839{ 1841{
1840 uint countTogo = rDuration + mRecurExDatesCount; 1842 uint countTogo = rDuration + mRecurExDatesCount;
1841 int countGone = 0; 1843 int countGone = 0;
1842 QValueList<int>::ConstIterator it; 1844 QValueList<int>::ConstIterator it;
1843 const QValueList<int>* days = data.dayList(); 1845 const QValueList<int>* days = data.dayList();
1844 1846
1845 if (data.day > 1) { 1847 if (data.day > 1) {
1846 // Check what remains of the start month 1848 // Check what remains of the start month
1847 for (it = days->begin(); it != days->end(); ++it) { 1849 for (it = days->begin(); it != days->end(); ++it) {
1848 if (*it >= data.day) { 1850 if (*it >= data.day) {
1849 ++countGone; 1851 ++countGone;
1850 if (--countTogo == 0) { 1852 if (--countTogo == 0) {
1851 data.day = *it; 1853 data.day = *it;
1852 break; 1854 break;
1853 } 1855 }
1854 } 1856 }
1855 } 1857 }
1856 if (countTogo) { 1858 if (countTogo) {
1857 data.day = 1; 1859 data.day = 1;
1858 data.addMonths(rFreq); 1860 data.addMonths(rFreq);
1859 } 1861 }
1860 } 1862 }
1861 if (countTogo) { 1863 if (countTogo) {
1862 if (data.varies) { 1864 if (data.varies) {
1863 // The number of recurrence days varies from month to month, 1865 // The number of recurrence days varies from month to month,
1864 // so we need to check month by month. 1866 // so we need to check month by month.
1865 for ( ; ; ) { 1867 for ( ; ; ) {
1866 days = data.dayList(); 1868 days = data.dayList();
1867 uint n = days->count(); // number of recurrence days in this month 1869 uint n = days->count(); // number of recurrence days in this month
1868 if (n >= countTogo) 1870 if (n >= countTogo)
1869 break; 1871 break;
1870 countTogo -= n; 1872 countTogo -= n;
1871 countGone += n; 1873 countGone += n;
1872 data.addMonths(rFreq); 1874 data.addMonths(rFreq);
1873 } 1875 }
1874 } else { 1876 } else {
1875 // The number of recurrences is the same every month, 1877 // The number of recurrences is the same every month,
1876 // so skip the month-by-month check. 1878 // so skip the month-by-month check.
1877 // Skip the remaining whole months, but leave at least 1879 // Skip the remaining whole months, but leave at least
1878 // 1 recurrence remaining, in order to get its date. 1880 // 1 recurrence remaining, in order to get its date.
1879 int daysPerMonth = days->count(); 1881 int daysPerMonth = days->count();
1880 int wholeMonths = (countTogo - 1) / daysPerMonth; 1882 int wholeMonths = (countTogo - 1) / daysPerMonth;
1881 data.addMonths(wholeMonths * rFreq); 1883 data.addMonths(wholeMonths * rFreq);
1882 countGone += wholeMonths * daysPerMonth; 1884 countGone += wholeMonths * daysPerMonth;
1883 countTogo -= wholeMonths * daysPerMonth; 1885 countTogo -= wholeMonths * daysPerMonth;
1884 } 1886 }
1885 if (countTogo) { 1887 if (countTogo) {
1886 // Check the last month in the recurrence 1888 // Check the last month in the recurrence
1887 for (it = days->begin(); it != days->end(); ++it) { 1889 for (it = days->begin(); it != days->end(); ++it) {
1888 ++countGone; 1890 ++countGone;
1889 if (--countTogo == 0) { 1891 if (--countTogo == 0) {
1890 data.day = *it; 1892 data.day = *it;
1891 break; 1893 break;
1892 } 1894 }
1893 } 1895 }
1894 } 1896 }
1895 } 1897 }
1896 enddate = data.date(); 1898 enddate = data.date();
1897 return countGone; 1899 return countGone;
1898} 1900}
1899 1901
1900int Recurrence::monthlyCalcToDate(const QDate &enddate, MonthlyData &data) const 1902int Recurrence::monthlyCalcToDate(const QDate &enddate, MonthlyData &data) const
1901{ 1903{
1902 int countGone = 0; 1904 int countGone = 0;
1903 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX; 1905 int countMax = (rDuration > 0) ? rDuration + mRecurExDatesCount : INT_MAX;
1904 int endYear = enddate.year(); 1906 int endYear = enddate.year();
1905 int endMonth = enddate.month() - 1; // zero-based 1907 int endMonth = enddate.month() - 1; // zero-based
1906 int endDay = enddate.day(); 1908 int endDay = enddate.day();
1907 int endYearMonth = endYear*12 + endMonth; 1909 int endYearMonth = endYear*12 + endMonth;
1908 QValueList<int>::ConstIterator it; 1910 QValueList<int>::ConstIterator it;
1909 const QValueList<int>* days = data.dayList(); 1911 const QValueList<int>* days = data.dayList();
1910 1912
1911 if (data.day > 1) { 1913 if (data.day > 1) {
1912 // Check what remains of the start month 1914 // Check what remains of the start month
1913 for (it = days->begin(); it != days->end(); ++it) { 1915 for (it = days->begin(); it != days->end(); ++it) {
1914 if (*it >= data.day) { 1916 if (*it >= data.day) {
1915 if (data.yearMonth() == endYearMonth && *it > endDay) 1917 if (data.yearMonth() == endYearMonth && *it > endDay)
1916 return countGone; 1918 return countGone;
1917 if (++countGone >= countMax) 1919 if (++countGone >= countMax)
1918 return countMax; 1920 return countMax;
1919 } 1921 }
1920 } 1922 }
1921 data.day = 1; 1923 data.day = 1;
1922 data.addMonths(rFreq); 1924 data.addMonths(rFreq);
1923 } 1925 }
1924 1926
1925 if (data.varies) { 1927 if (data.varies) {
1926 // The number of recurrence days varies from month to month, 1928 // The number of recurrence days varies from month to month,
1927 // so we need to check month by month. 1929 // so we need to check month by month.
1928 while (data.yearMonth() < endYearMonth) { 1930 while (data.yearMonth() < endYearMonth) {
1929 countGone += data.dayList()->count(); 1931 countGone += data.dayList()->count();
1930 if (countGone >= countMax) 1932 if (countGone >= countMax)
1931 return countMax; 1933 return countMax;
1932 data.addMonths(rFreq); 1934 data.addMonths(rFreq);
1933 } 1935 }
1934 days = data.dayList(); 1936 days = data.dayList();
1935 } else { 1937 } else {
1936 // The number of recurrences is the same every month, 1938 // The number of recurrences is the same every month,