summaryrefslogtreecommitdiffabout
path: root/libkcal
authorzautrix <zautrix>2005-02-18 09:36:33 (UTC)
committer zautrix <zautrix>2005-02-18 09:36:33 (UTC)
commit59a00e603e2ba14885e81c09daf3bb89859ff176 (patch) (unidiff)
treee257e5b0e338675c5448f9d4c57eadf68ed5e76b /libkcal
parentb1e885da3b0a083121f940485d9c0eea53ff5139 (diff)
downloadkdepimpi-59a00e603e2ba14885e81c09daf3bb89859ff176.zip
kdepimpi-59a00e603e2ba14885e81c09daf3bb89859ff176.tar.gz
kdepimpi-59a00e603e2ba14885e81c09daf3bb89859ff176.tar.bz2
recur fixes
Diffstat (limited to 'libkcal') (more/less context) (ignore whitespace changes)
-rw-r--r--libkcal/recurrence.cpp12
1 files changed, 9 insertions, 3 deletions
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp
index 5181eaf..8a175c9 100644
--- a/libkcal/recurrence.cpp
+++ b/libkcal/recurrence.cpp
@@ -1,980 +1,986 @@
1/* 1/*
2 This file is part of libkcal. 2 This file is part of libkcal.
3 Copyright (c) 1998 Preston Brown 3 Copyright (c) 1998 Preston Brown
4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org> 4 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (c) 2002 David Jarvie <software@astrojar.org.uk> 5 Copyright (c) 2002 David Jarvie <software@astrojar.org.uk>
6 6
7 This library is free software; you can redistribute it and/or 7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public 8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either 9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version. 10 version 2 of the License, or (at your option) any later version.
11 11
12 This library is distributed in the hope that it will be useful, 12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details. 15 Library General Public License for more details.
16 16
17 You should have received a copy of the GNU Library General Public License 17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to 18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. 20 Boston, MA 02111-1307, USA.
21*/ 21*/
22 22
23#include <limits.h> 23#include <limits.h>
24 24
25#include <kdebug.h> 25#include <kdebug.h>
26#include <kglobal.h> 26#include <kglobal.h>
27#include <klocale.h> 27#include <klocale.h>
28 28
29#include "incidence.h" 29#include "incidence.h"
30 30
31#include "recurrence.h" 31#include "recurrence.h"
32 32
33using namespace KCal; 33using namespace KCal;
34 34
35Recurrence::Feb29Type Recurrence::mFeb29YearlyDefaultType = Recurrence::rMar1; 35Recurrence::Feb29Type Recurrence::mFeb29YearlyDefaultType = Recurrence::rMar1;
36 36
37 37
38Recurrence::Recurrence(Incidence *parent, int compatVersion) 38Recurrence::Recurrence(Incidence *parent, int compatVersion)
39: recurs(rNone), // by default, it's not a recurring event 39: recurs(rNone), // by default, it's not a recurring event
40 rWeekStart(1), // default is Monday 40 rWeekStart(1), // default is Monday
41 rDays(7), 41 rDays(7),
42 mFloats(parent ? parent->doesFloat() : false), 42 mFloats(parent ? parent->doesFloat() : false),
43 mRecurReadOnly(false), 43 mRecurReadOnly(false),
44 mRecurExDatesCount(0), 44 mRecurExDatesCount(0),
45 mFeb29YearlyType(mFeb29YearlyDefaultType), 45 mFeb29YearlyType(mFeb29YearlyDefaultType),
46 mCompatVersion(compatVersion ? compatVersion : INT_MAX), 46 mCompatVersion(compatVersion ? compatVersion : INT_MAX),
47 mCompatRecurs(rNone), 47 mCompatRecurs(rNone),
48 mCompatDuration(0), 48 mCompatDuration(0),
49 mParent(parent) 49 mParent(parent)
50{ 50{
51 rMonthDays.setAutoDelete( true ); 51 rMonthDays.setAutoDelete( true );
52 rMonthPositions.setAutoDelete( true ); 52 rMonthPositions.setAutoDelete( true );
53 rYearNums.setAutoDelete( true ); 53 rYearNums.setAutoDelete( true );
54} 54}
55 55
56Recurrence::Recurrence(const Recurrence &r, Incidence *parent) 56Recurrence::Recurrence(const Recurrence &r, Incidence *parent)
57: recurs(r.recurs), 57: recurs(r.recurs),
58 rWeekStart(r.rWeekStart), 58 rWeekStart(r.rWeekStart),
59 rDays(r.rDays.copy()), 59 rDays(r.rDays.copy()),
60 rFreq(r.rFreq), 60 rFreq(r.rFreq),
61 rDuration(r.rDuration), 61 rDuration(r.rDuration),
62 rEndDateTime(r.rEndDateTime), 62 rEndDateTime(r.rEndDateTime),
63 mRecurStart(r.mRecurStart), 63 mRecurStart(r.mRecurStart),
64 mFloats(r.mFloats), 64 mFloats(r.mFloats),
65 mRecurReadOnly(r.mRecurReadOnly), 65 mRecurReadOnly(r.mRecurReadOnly),
66 mRecurExDatesCount(r.mRecurExDatesCount), 66 mRecurExDatesCount(r.mRecurExDatesCount),
67 mFeb29YearlyType(r.mFeb29YearlyType), 67 mFeb29YearlyType(r.mFeb29YearlyType),
68 mCompatVersion(r.mCompatVersion), 68 mCompatVersion(r.mCompatVersion),
69 mCompatRecurs(r.mCompatRecurs), 69 mCompatRecurs(r.mCompatRecurs),
70 mCompatDuration(r.mCompatDuration), 70 mCompatDuration(r.mCompatDuration),
71 mParent(parent) 71 mParent(parent)
72{ 72{
73 for (QPtrListIterator<rMonthPos> mp(r.rMonthPositions); mp.current(); ++mp) { 73 for (QPtrListIterator<rMonthPos> mp(r.rMonthPositions); mp.current(); ++mp) {
74 rMonthPos *tmp = new rMonthPos; 74 rMonthPos *tmp = new rMonthPos;
75 tmp->rPos = mp.current()->rPos; 75 tmp->rPos = mp.current()->rPos;
76 tmp->negative = mp.current()->negative; 76 tmp->negative = mp.current()->negative;
77 tmp->rDays = mp.current()->rDays.copy(); 77 tmp->rDays = mp.current()->rDays.copy();
78 rMonthPositions.append(tmp); 78 rMonthPositions.append(tmp);
79 } 79 }
80 for (QPtrListIterator<int> md(r.rMonthDays); md.current(); ++md) { 80 for (QPtrListIterator<int> md(r.rMonthDays); md.current(); ++md) {
81 int *tmp = new int; 81 int *tmp = new int;
82 *tmp = *md.current(); 82 *tmp = *md.current();
83 rMonthDays.append(tmp); 83 rMonthDays.append(tmp);
84 } 84 }
85 for (QPtrListIterator<int> yn(r.rYearNums); yn.current(); ++yn) { 85 for (QPtrListIterator<int> yn(r.rYearNums); yn.current(); ++yn) {
86 int *tmp = new int; 86 int *tmp = new int;
87 *tmp = *yn.current(); 87 *tmp = *yn.current();
88 rYearNums.append(tmp); 88 rYearNums.append(tmp);
89 } 89 }
90 rMonthDays.setAutoDelete( true ); 90 rMonthDays.setAutoDelete( true );
91 rMonthPositions.setAutoDelete( true ); 91 rMonthPositions.setAutoDelete( true );
92 rYearNums.setAutoDelete( true ); 92 rYearNums.setAutoDelete( true );
93} 93}
94 94
95Recurrence::~Recurrence() 95Recurrence::~Recurrence()
96{ 96{
97} 97}
98 98
99 99
100bool Recurrence::operator==( const Recurrence& r2 ) const 100bool Recurrence::operator==( const Recurrence& r2 ) const
101{ 101{
102 102
103 // the following line is obvious 103 // the following line is obvious
104 if ( recurs == rNone && r2.recurs == rNone ) 104 if ( recurs == rNone && r2.recurs == rNone )
105 return true; 105 return true;
106 // we need the above line, because two non recurring events may 106 // we need the above line, because two non recurring events may
107 // differ in the other settings, because one (or both) 107 // differ in the other settings, because one (or both)
108 // may be not initialized properly 108 // may be not initialized properly
109 109
110 if ( recurs != r2.recurs 110 if ( recurs != r2.recurs
111 || rFreq != r2.rFreq 111 || rFreq != r2.rFreq
112 || rDuration != r2.rDuration 112 || rDuration != r2.rDuration
113 || !rDuration && rEndDateTime != r2.rEndDateTime 113 || !rDuration && rEndDateTime != r2.rEndDateTime
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;
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("monthly");
207 else if ( recurs == Recurrence::rYearlyMonth ) 207 else if ( recurs == Recurrence::rYearlyMonth )
208 recurText = i18n("month-yearly"); 208 recurText = i18n("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 if ( !recurText.isEmpty() ) {
214 if ( rFreq > 1 ){
215 recurText = i18n("(%1) ").arg(rFreq ) + recurText;
216 }
217 } else
218 recurText = i18n("No");
213 return recurText; 219 return recurText;
214} 220}
215 221
216void Recurrence::setCompatVersion(int version) 222void Recurrence::setCompatVersion(int version)
217{ 223{
218 mCompatVersion = version ? version : INT_MAX; 224 mCompatVersion = version ? version : INT_MAX;
219} 225}
220 226
221ushort Recurrence::doesRecur() const 227ushort Recurrence::doesRecur() const
222{ 228{
223 return recurs; 229 return recurs;
224} 230}
225 231
226bool Recurrence::recursOnPure(const QDate &qd) const 232bool Recurrence::recursOnPure(const QDate &qd) const
227{ 233{
228 switch(recurs) { 234 switch(recurs) {
229 case rMinutely: 235 case rMinutely:
230 return recursSecondly(qd, rFreq*60); 236 return recursSecondly(qd, rFreq*60);
231 case rHourly: 237 case rHourly:
232 return recursSecondly(qd, rFreq*3600); 238 return recursSecondly(qd, rFreq*3600);
233 case rDaily: 239 case rDaily:
234 return recursDaily(qd); 240 return recursDaily(qd);
235 case rWeekly: 241 case rWeekly:
236 return recursWeekly(qd); 242 return recursWeekly(qd);
237 case rMonthlyPos: 243 case rMonthlyPos:
238 case rMonthlyDay: 244 case rMonthlyDay:
239 return recursMonthly(qd); 245 return recursMonthly(qd);
240 case rYearlyMonth: 246 case rYearlyMonth:
241 return recursYearlyByMonth(qd); 247 return recursYearlyByMonth(qd);
242 case rYearlyDay: 248 case rYearlyDay:
243 return recursYearlyByDay(qd); 249 return recursYearlyByDay(qd);
244 case rYearlyPos: 250 case rYearlyPos:
245 return recursYearlyByPos(qd); 251 return recursYearlyByPos(qd);
246 default: 252 default:
247 return false; 253 return false;
248 case rNone: 254 case rNone:
249 return false; 255 return false;
250 } // case 256 } // case
251 return false; 257 return false;
252} 258}
253 259
254bool Recurrence::recursAtPure(const QDateTime &dt) const 260bool Recurrence::recursAtPure(const QDateTime &dt) const
255{ 261{
256 switch(recurs) { 262 switch(recurs) {
257 case rMinutely: 263 case rMinutely:
258 return recursMinutelyAt(dt, rFreq); 264 return recursMinutelyAt(dt, rFreq);
259 case rHourly: 265 case rHourly:
260 return recursMinutelyAt(dt, rFreq*60); 266 return recursMinutelyAt(dt, rFreq*60);
261 default: 267 default:
262 if (dt.time() != mRecurStart.time()) 268 if (dt.time() != mRecurStart.time())
263 return false; 269 return false;
264 switch(recurs) { 270 switch(recurs) {
265 case rDaily: 271 case rDaily:
266 return recursDaily(dt.date()); 272 return recursDaily(dt.date());
267 case rWeekly: 273 case rWeekly:
268 return recursWeekly(dt.date()); 274 return recursWeekly(dt.date());
269 case rMonthlyPos: 275 case rMonthlyPos:
270 case rMonthlyDay: 276 case rMonthlyDay:
271 return recursMonthly(dt.date()); 277 return recursMonthly(dt.date());
272 case rYearlyMonth: 278 case rYearlyMonth:
273 return recursYearlyByMonth(dt.date()); 279 return recursYearlyByMonth(dt.date());
274 case rYearlyDay: 280 case rYearlyDay:
275 return recursYearlyByDay(dt.date()); 281 return recursYearlyByDay(dt.date());
276 case rYearlyPos: 282 case rYearlyPos:
277 return recursYearlyByPos(dt.date()); 283 return recursYearlyByPos(dt.date());
278 default: 284 default:
279 return false; 285 return false;
280 case rNone: 286 case rNone:
281 return false; 287 return false;
282 } 288 }
283 } // case 289 } // case
284 return false; 290 return false;
285} 291}
286 292
287QDate Recurrence::endDate() const 293QDate Recurrence::endDate() const
288{ 294{
289 int count = 0; 295 int count = 0;
290 QDate end; 296 QDate end;
291 if (recurs != rNone) { 297 if (recurs != rNone) {
292 if (rDuration < 0) 298 if (rDuration < 0)
293 return QDate(); // infinite recurrence 299 return QDate(); // infinite recurrence
294 if (rDuration == 0) 300 if (rDuration == 0)
295 return rEndDateTime.date(); 301 return rEndDateTime.date();
296 302
297 // The end date is determined by the recurrence count 303 // The end date is determined by the recurrence count
298 QDate dStart = mRecurStart.date(); 304 QDate dStart = mRecurStart.date();
299 switch (recurs) 305 switch (recurs)
300 { 306 {
301 case rMinutely: 307 case rMinutely:
302 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date(); 308 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60).date();
303 case rHourly: 309 case rHourly:
304 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date(); 310 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600).date();
305 case rDaily: 311 case rDaily:
306 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); 312 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
307 313
308 case rWeekly: 314 case rWeekly:
309 count = weeklyCalc(END_DATE_AND_COUNT, end); 315 count = weeklyCalc(END_DATE_AND_COUNT, end);
310 break; 316 break;
311 case rMonthlyPos: 317 case rMonthlyPos:
312 case rMonthlyDay: 318 case rMonthlyDay:
313 count = monthlyCalc(END_DATE_AND_COUNT, end); 319 count = monthlyCalc(END_DATE_AND_COUNT, end);
314 break; 320 break;
315 case rYearlyMonth: 321 case rYearlyMonth:
316 count = yearlyMonthCalc(END_DATE_AND_COUNT, end); 322 count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
317 break; 323 break;
318 case rYearlyDay: 324 case rYearlyDay:
319 count = yearlyDayCalc(END_DATE_AND_COUNT, end); 325 count = yearlyDayCalc(END_DATE_AND_COUNT, end);
320 break; 326 break;
321 case rYearlyPos: 327 case rYearlyPos:
322 count = yearlyPosCalc(END_DATE_AND_COUNT, end); 328 count = yearlyPosCalc(END_DATE_AND_COUNT, end);
323 break; 329 break;
324 default: 330 default:
325 // catch-all. Should never get here. 331 // catch-all. Should never get here.
326 kdDebug(5800) << "Control should never reach here in endDate()!" << endl; 332 kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
327 break; 333 break;
328 } 334 }
329 } 335 }
330 if (!count) 336 if (!count)
331 return QDate(); // error - there is no recurrence 337 return QDate(); // error - there is no recurrence
332 return end; 338 return end;
333} 339}
334 340
335QDateTime Recurrence::endDateTime() const 341QDateTime Recurrence::endDateTime() const
336{ 342{
337 int count = 0; 343 int count = 0;
338 QDate end; 344 QDate end;
339 if (recurs != rNone) { 345 if (recurs != rNone) {
340 if (rDuration < 0) 346 if (rDuration < 0)
341 return QDateTime(); // infinite recurrence 347 return QDateTime(); // infinite recurrence
342 if (rDuration == 0) 348 if (rDuration == 0)
343 return rEndDateTime; 349 return rEndDateTime;
344 350
345 // The end date is determined by the recurrence count 351 // The end date is determined by the recurrence count
346 QDate dStart = mRecurStart.date(); 352 QDate dStart = mRecurStart.date();
347 switch (recurs) 353 switch (recurs)
348 { 354 {
349 case rMinutely: 355 case rMinutely:
350 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60); 356 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*60);
351 case rHourly: 357 case rHourly:
352 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600); 358 return mRecurStart.addSecs((rDuration-1+mRecurExDatesCount)*rFreq*3600);
353 case rDaily: 359 case rDaily:
354 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq); 360 return dStart.addDays((rDuration-1+mRecurExDatesCount)*rFreq);
355 361
356 case rWeekly: 362 case rWeekly:
357 count = weeklyCalc(END_DATE_AND_COUNT, end); 363 count = weeklyCalc(END_DATE_AND_COUNT, end);
358 break; 364 break;
359 case rMonthlyPos: 365 case rMonthlyPos:
360 case rMonthlyDay: 366 case rMonthlyDay:
361 count = monthlyCalc(END_DATE_AND_COUNT, end); 367 count = monthlyCalc(END_DATE_AND_COUNT, end);
362 break; 368 break;
363 case rYearlyMonth: 369 case rYearlyMonth:
364 count = yearlyMonthCalc(END_DATE_AND_COUNT, end); 370 count = yearlyMonthCalc(END_DATE_AND_COUNT, end);
365 break; 371 break;
366 case rYearlyDay: 372 case rYearlyDay:
367 count = yearlyDayCalc(END_DATE_AND_COUNT, end); 373 count = yearlyDayCalc(END_DATE_AND_COUNT, end);
368 break; 374 break;
369 case rYearlyPos: 375 case rYearlyPos:
370 count = yearlyPosCalc(END_DATE_AND_COUNT, end); 376 count = yearlyPosCalc(END_DATE_AND_COUNT, end);
371 break; 377 break;
372 default: 378 default:
373 // catch-all. Should never get here. 379 // catch-all. Should never get here.
374 kdDebug(5800) << "Control should never reach here in endDate()!" << endl; 380 kdDebug(5800) << "Control should never reach here in endDate()!" << endl;
375 break; 381 break;
376 } 382 }
377 } 383 }
378 if (!count) 384 if (!count)
379 return QDateTime(); // error - there is no recurrence 385 return QDateTime(); // error - there is no recurrence
380 return QDateTime(end, mRecurStart.time()); 386 return QDateTime(end, mRecurStart.time());
381} 387}
382 388
383int Recurrence::durationTo(const QDate &date) const 389int Recurrence::durationTo(const QDate &date) const
384{ 390{
385 QDate d = date; 391 QDate d = date;
386 return recurCalc(COUNT_TO_DATE, d); 392 return recurCalc(COUNT_TO_DATE, d);
387} 393}
388 394
389int Recurrence::durationTo(const QDateTime &datetime) const 395int Recurrence::durationTo(const QDateTime &datetime) const
390{ 396{
391 QDateTime dt = datetime; 397 QDateTime dt = datetime;
392 return recurCalc(COUNT_TO_DATE, dt); 398 return recurCalc(COUNT_TO_DATE, dt);
393} 399}
394 400
395void Recurrence::unsetRecurs() 401void Recurrence::unsetRecurs()
396{ 402{
397 if (mRecurReadOnly) return; 403 if (mRecurReadOnly) return;
398 recurs = rNone; 404 recurs = rNone;
399 rMonthPositions.clear(); 405 rMonthPositions.clear();
400 rMonthDays.clear(); 406 rMonthDays.clear();
401 rYearNums.clear(); 407 rYearNums.clear();
402} 408}
403 409
404void Recurrence::setRecurStart(const QDateTime &start) 410void Recurrence::setRecurStart(const QDateTime &start)
405{ 411{
406 mRecurStart = start; 412 mRecurStart = start;
407 mFloats = false; 413 mFloats = false;
408 switch (recurs) 414 switch (recurs)
409 { 415 {
410 case rMinutely: 416 case rMinutely:
411 case rHourly: 417 case rHourly:
412 break; 418 break;
413 case rDaily: 419 case rDaily:
414 case rWeekly: 420 case rWeekly:
415 case rMonthlyPos: 421 case rMonthlyPos:
416 case rMonthlyDay: 422 case rMonthlyDay:
417 case rYearlyMonth: 423 case rYearlyMonth:
418 case rYearlyDay: 424 case rYearlyDay:
419 case rYearlyPos: 425 case rYearlyPos:
420 default: 426 default:
421 rEndDateTime.setTime(start.time()); 427 rEndDateTime.setTime(start.time());
422 break; 428 break;
423 } 429 }
424} 430}
425 431
426void Recurrence::setRecurStart(const QDate &start) 432void Recurrence::setRecurStart(const QDate &start)
427{ 433{
428 mRecurStart.setDate(start); 434 mRecurStart.setDate(start);
429 mRecurStart.setTime(QTime(0,0,0)); 435 mRecurStart.setTime(QTime(0,0,0));
430 switch (recurs) 436 switch (recurs)
431 { 437 {
432 case rMinutely: 438 case rMinutely:
433 case rHourly: 439 case rHourly:
434 break; 440 break;
435 case rDaily: 441 case rDaily:
436 case rWeekly: 442 case rWeekly:
437 case rMonthlyPos: 443 case rMonthlyPos:
438 case rMonthlyDay: 444 case rMonthlyDay:
439 case rYearlyMonth: 445 case rYearlyMonth:
440 case rYearlyDay: 446 case rYearlyDay:
441 case rYearlyPos: 447 case rYearlyPos:
442 default: 448 default:
443 mFloats = true; 449 mFloats = true;
444 break; 450 break;
445 } 451 }
446} 452}
447 453
448void Recurrence::setFloats(bool f) 454void Recurrence::setFloats(bool f)
449{ 455{
450 switch (recurs) 456 switch (recurs)
451 { 457 {
452 case rDaily: 458 case rDaily:
453 case rWeekly: 459 case rWeekly:
454 case rMonthlyPos: 460 case rMonthlyPos:
455 case rMonthlyDay: 461 case rMonthlyDay:
456 case rYearlyMonth: 462 case rYearlyMonth:
457 case rYearlyDay: 463 case rYearlyDay:
458 case rYearlyPos: 464 case rYearlyPos:
459 break; 465 break;
460 case rMinutely: 466 case rMinutely:
461 case rHourly: 467 case rHourly:
462 default: 468 default:
463 return; // can't set sub-daily to floating 469 return; // can't set sub-daily to floating
464 } 470 }
465 mFloats = f; 471 mFloats = f;
466 if (f) { 472 if (f) {
467 mRecurStart.setTime(QTime(0,0,0)); 473 mRecurStart.setTime(QTime(0,0,0));
468 rEndDateTime.setTime(QTime(0,0,0)); 474 rEndDateTime.setTime(QTime(0,0,0));
469 } 475 }
470} 476}
471 477
472int Recurrence::frequency() const 478int Recurrence::frequency() const
473{ 479{
474 return rFreq; 480 return rFreq;
475} 481}
476 482
477int Recurrence::duration() const 483int Recurrence::duration() const
478{ 484{
479 return rDuration; 485 return rDuration;
480} 486}
481 487
482void Recurrence::setDuration(int _rDuration) 488void Recurrence::setDuration(int _rDuration)
483{ 489{
484 if (mRecurReadOnly) return; 490 if (mRecurReadOnly) return;
485 if (_rDuration > 0) { 491 if (_rDuration > 0) {
486 rDuration = _rDuration; 492 rDuration = _rDuration;
487 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl, 493 // Compatibility mode is only needed when reading the calendar in ICalFormatImpl,
488 // so explicitly setting the duration means no backwards compatibility is needed. 494 // so explicitly setting the duration means no backwards compatibility is needed.
489 mCompatDuration = 0; 495 mCompatDuration = 0;
490 } 496 }
491} 497}
492 498
493QString Recurrence::endDateStr(bool shortfmt) const 499QString Recurrence::endDateStr(bool shortfmt) const
494{ 500{
495 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt); 501 return KGlobal::locale()->formatDate(rEndDateTime.date(),shortfmt);
496} 502}
497 503
498const QBitArray &Recurrence::days() const 504const QBitArray &Recurrence::days() const
499{ 505{
500 return rDays; 506 return rDays;
501} 507}
502 508
503const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const 509const QPtrList<Recurrence::rMonthPos> &Recurrence::monthPositions() const
504{ 510{
505 return rMonthPositions; 511 return rMonthPositions;
506} 512}
507 513
508const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const 514const QPtrList<Recurrence::rMonthPos> &Recurrence::yearMonthPositions() const
509{ 515{
510 return rMonthPositions; 516 return rMonthPositions;
511} 517}
512 518
513const QPtrList<int> &Recurrence::monthDays() const 519const QPtrList<int> &Recurrence::monthDays() const
514{ 520{
515 return rMonthDays; 521 return rMonthDays;
516} 522}
517 523
518void Recurrence::setMinutely(int _rFreq, int _rDuration) 524void Recurrence::setMinutely(int _rFreq, int _rDuration)
519{ 525{
520 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 526 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
521 return; 527 return;
522 setDailySub(rMinutely, _rFreq, _rDuration); 528 setDailySub(rMinutely, _rFreq, _rDuration);
523} 529}
524 530
525void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime) 531void Recurrence::setMinutely(int _rFreq, const QDateTime &_rEndDateTime)
526{ 532{
527 if (mRecurReadOnly) return; 533 if (mRecurReadOnly) return;
528 rEndDateTime = _rEndDateTime; 534 rEndDateTime = _rEndDateTime;
529 setDailySub(rMinutely, _rFreq, 0); 535 setDailySub(rMinutely, _rFreq, 0);
530} 536}
531 537
532void Recurrence::setHourly(int _rFreq, int _rDuration) 538void Recurrence::setHourly(int _rFreq, int _rDuration)
533{ 539{
534 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 540 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
535 return; 541 return;
536 setDailySub(rHourly, _rFreq, _rDuration); 542 setDailySub(rHourly, _rFreq, _rDuration);
537} 543}
538 544
539void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime) 545void Recurrence::setHourly(int _rFreq, const QDateTime &_rEndDateTime)
540{ 546{
541 if (mRecurReadOnly) return; 547 if (mRecurReadOnly) return;
542 rEndDateTime = _rEndDateTime; 548 rEndDateTime = _rEndDateTime;
543 setDailySub(rHourly, _rFreq, 0); 549 setDailySub(rHourly, _rFreq, 0);
544} 550}
545 551
546void Recurrence::setDaily(int _rFreq, int _rDuration) 552void Recurrence::setDaily(int _rFreq, int _rDuration)
547{ 553{
548 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 554 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
549 return; 555 return;
550 setDailySub(rDaily, _rFreq, _rDuration); 556 setDailySub(rDaily, _rFreq, _rDuration);
551} 557}
552 558
553void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate) 559void Recurrence::setDaily(int _rFreq, const QDate &_rEndDate)
554{ 560{
555 if (mRecurReadOnly) return; 561 if (mRecurReadOnly) return;
556 rEndDateTime.setDate(_rEndDate); 562 rEndDateTime.setDate(_rEndDate);
557 rEndDateTime.setTime(mRecurStart.time()); 563 rEndDateTime.setTime(mRecurStart.time());
558 setDailySub(rDaily, _rFreq, 0); 564 setDailySub(rDaily, _rFreq, 0);
559} 565}
560 566
561void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 567void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
562 int _rDuration, int _rWeekStart) 568 int _rDuration, int _rWeekStart)
563{ 569{
564 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 570 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
565 return; 571 return;
566 recurs = rWeekly; 572 recurs = rWeekly;
567 573
568 rFreq = _rFreq; 574 rFreq = _rFreq;
569 rDays = _rDays; 575 rDays = _rDays;
570 rWeekStart = _rWeekStart; 576 rWeekStart = _rWeekStart;
571 rDuration = _rDuration; 577 rDuration = _rDuration;
572 if (mCompatVersion < 310 && _rDuration > 0) { 578 if (mCompatVersion < 310 && _rDuration > 0) {
573 // Backwards compatibility for KDE < 3.1. 579 // Backwards compatibility for KDE < 3.1.
574 // rDuration was set to the number of time periods to recur, 580 // rDuration was set to the number of time periods to recur,
575 // with week start always on a Monday. 581 // with week start always on a Monday.
576 // Convert this to the number of occurrences. 582 // Convert this to the number of occurrences.
577 mCompatDuration = _rDuration; 583 mCompatDuration = _rDuration;
578 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek()); 584 int weeks = ((mCompatDuration-1+mRecurExDatesCount)*7) + (7 - mRecurStart.date().dayOfWeek());
579 QDate end(mRecurStart.date().addDays(weeks * rFreq)); 585 QDate end(mRecurStart.date().addDays(weeks * rFreq));
580 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly 586 rDuration = INT_MAX; // ensure that weeklyCalc() does its job correctly
581 rDuration = weeklyCalc(COUNT_TO_DATE, end); 587 rDuration = weeklyCalc(COUNT_TO_DATE, end);
582 } else { 588 } else {
583 mCompatDuration = 0; 589 mCompatDuration = 0;
584 } 590 }
585 rMonthPositions.clear(); 591 rMonthPositions.clear();
586 rMonthDays.clear(); 592 rMonthDays.clear();
587 if (mParent) mParent->updated(); 593 if (mParent) mParent->updated();
588} 594}
589 595
590void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays, 596void Recurrence::setWeekly(int _rFreq, const QBitArray &_rDays,
591 const QDate &_rEndDate, int _rWeekStart) 597 const QDate &_rEndDate, int _rWeekStart)
592{ 598{
593 if (mRecurReadOnly) return; 599 if (mRecurReadOnly) return;
594 recurs = rWeekly; 600 recurs = rWeekly;
595 601
596 rFreq = _rFreq; 602 rFreq = _rFreq;
597 rDays = _rDays; 603 rDays = _rDays;
598 rWeekStart = _rWeekStart; 604 rWeekStart = _rWeekStart;
599 rEndDateTime.setDate(_rEndDate); 605 rEndDateTime.setDate(_rEndDate);
600 rEndDateTime.setTime(mRecurStart.time()); 606 rEndDateTime.setTime(mRecurStart.time());
601 rDuration = 0; // set to 0 because there is an end date 607 rDuration = 0; // set to 0 because there is an end date
602 mCompatDuration = 0; 608 mCompatDuration = 0;
603 rMonthPositions.clear(); 609 rMonthPositions.clear();
604 rMonthDays.clear(); 610 rMonthDays.clear();
605 rYearNums.clear(); 611 rYearNums.clear();
606 if (mParent) mParent->updated(); 612 if (mParent) mParent->updated();
607} 613}
608 614
609void Recurrence::setMonthly(short type, int _rFreq, int _rDuration) 615void Recurrence::setMonthly(short type, int _rFreq, int _rDuration)
610{ 616{
611 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 617 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
612 return; 618 return;
613 recurs = type; 619 recurs = type;
614 620
615 rFreq = _rFreq; 621 rFreq = _rFreq;
616 rDuration = _rDuration; 622 rDuration = _rDuration;
617 if (mCompatVersion < 310) 623 if (mCompatVersion < 310)
618 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 624 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
619 rYearNums.clear(); 625 rYearNums.clear();
620 if (mParent) mParent->updated(); 626 if (mParent) mParent->updated();
621} 627}
622 628
623void Recurrence::setMonthly(short type, int _rFreq, 629void Recurrence::setMonthly(short type, int _rFreq,
624 const QDate &_rEndDate) 630 const QDate &_rEndDate)
625{ 631{
626 if (mRecurReadOnly) return; 632 if (mRecurReadOnly) return;
627 recurs = type; 633 recurs = type;
628 634
629 rFreq = _rFreq; 635 rFreq = _rFreq;
630 rEndDateTime.setDate(_rEndDate); 636 rEndDateTime.setDate(_rEndDate);
631 rEndDateTime.setTime(mRecurStart.time()); 637 rEndDateTime.setTime(mRecurStart.time());
632 rDuration = 0; // set to 0 because there is an end date 638 rDuration = 0; // set to 0 because there is an end date
633 mCompatDuration = 0; 639 mCompatDuration = 0;
634 rYearNums.clear(); 640 rYearNums.clear();
635 if (mParent) mParent->updated(); 641 if (mParent) mParent->updated();
636} 642}
637 643
638void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays) 644void Recurrence::addMonthlyPos(short _rPos, const QBitArray &_rDays)
639{ 645{
640 if (recurs == rMonthlyPos) 646 if (recurs == rMonthlyPos)
641 addMonthlyPos_(_rPos, _rDays); 647 addMonthlyPos_(_rPos, _rDays);
642} 648}
643 649
644void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays) 650void Recurrence::addMonthlyPos_(short _rPos, const QBitArray &_rDays)
645{ 651{
646 if (mRecurReadOnly 652 if (mRecurReadOnly
647 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number 653 || _rPos == 0 || _rPos > 5 || _rPos < -5) // invalid week number
648 return; 654 return;
649 655
650 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) { 656 for (rMonthPos* it = rMonthPositions.first(); it; it = rMonthPositions.next()) {
651 int itPos = it->negative ? -it->rPos : it->rPos; 657 int itPos = it->negative ? -it->rPos : it->rPos;
652 if (_rPos == itPos) { 658 if (_rPos == itPos) {
653 // This week is already in the list. 659 // This week is already in the list.
654 // Combine the specified days with those in the list. 660 // Combine the specified days with those in the list.
655 it->rDays |= _rDays; 661 it->rDays |= _rDays;
656 if (mParent) mParent->updated(); 662 if (mParent) mParent->updated();
657 return; 663 return;
658 } 664 }
659 } 665 }
660 // Add the new position to the list 666 // Add the new position to the list
661 rMonthPos *tmpPos = new rMonthPos; 667 rMonthPos *tmpPos = new rMonthPos;
662 if (_rPos > 0) { 668 if (_rPos > 0) {
663 tmpPos->rPos = _rPos; 669 tmpPos->rPos = _rPos;
664 tmpPos->negative = false; 670 tmpPos->negative = false;
665 } else { 671 } else {
666 tmpPos->rPos = -_rPos; // take abs() 672 tmpPos->rPos = -_rPos; // take abs()
667 tmpPos->negative = true; 673 tmpPos->negative = true;
668 } 674 }
669 tmpPos->rDays = _rDays; 675 tmpPos->rDays = _rDays;
670 tmpPos->rDays.detach(); 676 tmpPos->rDays.detach();
671 rMonthPositions.append(tmpPos); 677 rMonthPositions.append(tmpPos);
672 678
673 if (mCompatVersion < 310 && mCompatDuration > 0) { 679 if (mCompatVersion < 310 && mCompatDuration > 0) {
674 // Backwards compatibility for KDE < 3.1. 680 // Backwards compatibility for KDE < 3.1.
675 // rDuration was set to the number of time periods to recur. 681 // rDuration was set to the number of time periods to recur.
676 // Convert this to the number of occurrences. 682 // Convert this to the number of occurrences.
677 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 683 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
678 int month = mRecurStart.date().month() - 1 + monthsAhead; 684 int month = mRecurStart.date().month() - 1 + monthsAhead;
679 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 685 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
680 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 686 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
681 rDuration = recurCalc(COUNT_TO_DATE, end); 687 rDuration = recurCalc(COUNT_TO_DATE, end);
682 } 688 }
683 689
684 if (mParent) mParent->updated(); 690 if (mParent) mParent->updated();
685} 691}
686 692
687void Recurrence::addMonthlyDay(short _rDay) 693void Recurrence::addMonthlyDay(short _rDay)
688{ 694{
689 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth) 695 if (mRecurReadOnly || (recurs != rMonthlyDay && recurs != rYearlyMonth)
690 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number 696 || _rDay == 0 || _rDay > 31 || _rDay < -31) // invalid day number
691 return; 697 return;
692 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) { 698 for (int* it = rMonthDays.first(); it; it = rMonthDays.next()) {
693 if (_rDay == *it) 699 if (_rDay == *it)
694 return; // this day is already in the list - avoid duplication 700 return; // this day is already in the list - avoid duplication
695 } 701 }
696 int *tmpDay = new int; 702 int *tmpDay = new int;
697 *tmpDay = _rDay; 703 *tmpDay = _rDay;
698 rMonthDays.append(tmpDay); 704 rMonthDays.append(tmpDay);
699 705
700 if (mCompatVersion < 310 && mCompatDuration > 0) { 706 if (mCompatVersion < 310 && mCompatDuration > 0) {
701 // Backwards compatibility for KDE < 3.1. 707 // Backwards compatibility for KDE < 3.1.
702 // rDuration was set to the number of time periods to recur. 708 // rDuration was set to the number of time periods to recur.
703 // Convert this to the number of occurrences. 709 // Convert this to the number of occurrences.
704 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq; 710 int monthsAhead = (mCompatDuration-1+mRecurExDatesCount) * rFreq;
705 int month = mRecurStart.date().month() - 1 + monthsAhead; 711 int month = mRecurStart.date().month() - 1 + monthsAhead;
706 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31); 712 QDate end(mRecurStart.date().year() + month/12, month%12 + 1, 31);
707 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 713 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
708 rDuration = recurCalc(COUNT_TO_DATE, end); 714 rDuration = recurCalc(COUNT_TO_DATE, end);
709 } 715 }
710 716
711 if (mParent) mParent->updated(); 717 if (mParent) mParent->updated();
712} 718}
713 719
714void Recurrence::setYearly(int type, int _rFreq, int _rDuration) 720void Recurrence::setYearly(int type, int _rFreq, int _rDuration)
715{ 721{
716 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 722 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
717 return; 723 return;
718 if (mCompatVersion < 310) 724 if (mCompatVersion < 310)
719 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 725 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
720 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration); 726 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, _rDuration);
721} 727}
722 728
723void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate) 729void Recurrence::setYearly(int type, int _rFreq, const QDate &_rEndDate)
724{ 730{
725 if (mRecurReadOnly) return; 731 if (mRecurReadOnly) return;
726 rEndDateTime.setDate(_rEndDate); 732 rEndDateTime.setDate(_rEndDate);
727 rEndDateTime.setTime(mRecurStart.time()); 733 rEndDateTime.setTime(mRecurStart.time());
728 mCompatDuration = 0; 734 mCompatDuration = 0;
729 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0); 735 setYearly_(type, mFeb29YearlyDefaultType, _rFreq, 0);
730} 736}
731 737
732void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration) 738void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, int _rDuration)
733{ 739{
734 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1) 740 if (mRecurReadOnly || _rDuration == 0 || _rDuration < -1)
735 return; 741 return;
736 if (mCompatVersion < 310) 742 if (mCompatVersion < 310)
737 mCompatDuration = (_rDuration > 0) ? _rDuration : 0; 743 mCompatDuration = (_rDuration > 0) ? _rDuration : 0;
738 setYearly_(rYearlyMonth, type, _rFreq, _rDuration); 744 setYearly_(rYearlyMonth, type, _rFreq, _rDuration);
739} 745}
740 746
741void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate) 747void Recurrence::setYearlyByDate(Feb29Type type, int _rFreq, const QDate &_rEndDate)
742{ 748{
743 if (mRecurReadOnly) return; 749 if (mRecurReadOnly) return;
744 rEndDateTime.setDate(_rEndDate); 750 rEndDateTime.setDate(_rEndDate);
745 rEndDateTime.setTime(mRecurStart.time()); 751 rEndDateTime.setTime(mRecurStart.time());
746 mCompatDuration = 0; 752 mCompatDuration = 0;
747 setYearly_(rYearlyMonth, type, _rFreq, 0); 753 setYearly_(rYearlyMonth, type, _rFreq, 0);
748} 754}
749 755
750void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays) 756void Recurrence::addYearlyMonthPos(short _rPos, const QBitArray &_rDays)
751{ 757{
752 if (recurs == rYearlyPos) 758 if (recurs == rYearlyPos)
753 addMonthlyPos_(_rPos, _rDays); 759 addMonthlyPos_(_rPos, _rDays);
754} 760}
755 761
756const QPtrList<int> &Recurrence::yearNums() const 762const QPtrList<int> &Recurrence::yearNums() const
757{ 763{
758 return rYearNums; 764 return rYearNums;
759} 765}
760void Recurrence::addYearlyMonth(short _rPos ) 766void Recurrence::addYearlyMonth(short _rPos )
761{ 767{
762 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number 768 if (mRecurReadOnly || recurs != rYearlyMonth) // invalid day/month number
763 return; 769 return;
764 rMonthPos *tmpPos = new rMonthPos; 770 rMonthPos *tmpPos = new rMonthPos;
765 if ( _rPos > 0) { 771 if ( _rPos > 0) {
766 tmpPos->rPos = _rPos; 772 tmpPos->rPos = _rPos;
767 tmpPos->negative = false; 773 tmpPos->negative = false;
768 } else { 774 } else {
769 tmpPos->rPos = -_rPos; // take abs() 775 tmpPos->rPos = -_rPos; // take abs()
770 tmpPos->negative = true; 776 tmpPos->negative = true;
771 } 777 }
772 rMonthPositions.append(tmpPos); 778 rMonthPositions.append(tmpPos);
773} 779}
774void Recurrence::addYearlyNum(short _rNum) 780void Recurrence::addYearlyNum(short _rNum)
775{ 781{
776 if (mRecurReadOnly 782 if (mRecurReadOnly
777 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos) 783 || (recurs != rYearlyMonth && recurs != rYearlyDay && recurs != rYearlyPos)
778 || _rNum <= 0) // invalid day/month number 784 || _rNum <= 0) // invalid day/month number
779 return; 785 return;
780 786
781 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) { 787 if (mCompatVersion < 310 && mCompatRecurs == rYearlyDay) {
782 // Backwards compatibility for KDE < 3.1. 788 // Backwards compatibility for KDE < 3.1.
783 // Dates were stored as day numbers, with a fiddle to take account of leap years. 789 // Dates were stored as day numbers, with a fiddle to take account of leap years.
784 // Convert the day number to a month. 790 // Convert the day number to a month.
785 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366)) 791 if (_rNum <= 0 || _rNum > 366 || (_rNum == 366 && mRecurStart.date().daysInYear() < 366))
786 return; // invalid day number 792 return; // invalid day number
787 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month(); 793 _rNum = QDate(mRecurStart.date().year(), 1, 1).addDays(_rNum - 1).month();
788 } else 794 } else
789 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12 795 if ((recurs == rYearlyMonth || recurs == rYearlyPos) && _rNum > 12
790 || recurs == rYearlyDay && _rNum > 366) 796 || recurs == rYearlyDay && _rNum > 366)
791 return; // invalid day number 797 return; // invalid day number
792 798
793 uint i = 0; 799 uint i = 0;
794 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) { 800 for (int* it = rYearNums.first(); it && _rNum >= *it; it = rYearNums.next()) {
795 if (_rNum == *it) 801 if (_rNum == *it)
796 return; // this day/month is already in the list - avoid duplication 802 return; // this day/month is already in the list - avoid duplication
797 ++i; 803 ++i;
798 } 804 }
799 805
800 int *tmpNum = new int; 806 int *tmpNum = new int;
801 *tmpNum = _rNum; 807 *tmpNum = _rNum;
802 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position 808 rYearNums.insert(i, tmpNum); // insert the day/month in a sorted position
803 809
804 if (mCompatVersion < 310 && mCompatDuration > 0) { 810 if (mCompatVersion < 310 && mCompatDuration > 0) {
805 // Backwards compatibility for KDE < 3.1. 811 // Backwards compatibility for KDE < 3.1.
806 // rDuration was set to the number of time periods to recur. 812 // rDuration was set to the number of time periods to recur.
807 // Convert this to the number of occurrences. 813 // Convert this to the number of occurrences.
808 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31); 814 QDate end(mRecurStart.date().year() + (mCompatDuration-1+mRecurExDatesCount)*rFreq, 12, 31);
809 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly 815 rDuration = INT_MAX; // ensure that recurCalc() does its job correctly
810 rDuration = recurCalc(COUNT_TO_DATE, end); 816 rDuration = recurCalc(COUNT_TO_DATE, end);
811 } 817 }
812 818
813 if (mParent) mParent->updated(); 819 if (mParent) mParent->updated();
814} 820}
815 821
816 822
817QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const 823QDateTime Recurrence::getNextDateTime(const QDateTime &preDateTime, bool *last) const
818{ 824{
819 if (last) 825 if (last)
820 *last = false; 826 *last = false;
821 int freq; 827 int freq;
822 switch (recurs) 828 switch (recurs)
823 { 829 {
824 case rMinutely: 830 case rMinutely:
825 freq = rFreq * 60; 831 freq = rFreq * 60;
826 break; 832 break;
827 case rHourly: 833 case rHourly:
828 freq = rFreq * 3600; 834 freq = rFreq * 3600;
829 break; 835 break;
830 case rDaily: 836 case rDaily:
831 case rWeekly: 837 case rWeekly:
832 case rMonthlyPos: 838 case rMonthlyPos:
833 case rMonthlyDay: 839 case rMonthlyDay:
834 case rYearlyMonth: 840 case rYearlyMonth:
835 case rYearlyDay: 841 case rYearlyDay:
836 case rYearlyPos: { 842 case rYearlyPos: {
837 QDate preDate = preDateTime.date(); 843 QDate preDate = preDateTime.date();
838 if (!mFloats && mRecurStart.time() > preDateTime.time()) 844 if (!mFloats && mRecurStart.time() > preDateTime.time())
839 preDate = preDate.addDays(-1); 845 preDate = preDate.addDays(-1);
840 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time()); 846 return QDateTime(getNextDateNoTime(preDate, last), mRecurStart.time());
841 } 847 }
842 default: 848 default:
843 return QDateTime(); 849 return QDateTime();
844 } 850 }
845 851
846 // It's a sub-daily recurrence 852 // It's a sub-daily recurrence
847 if (preDateTime < mRecurStart) 853 if (preDateTime < mRecurStart)
848 return mRecurStart; 854 return mRecurStart;
849 int count = mRecurStart.secsTo(preDateTime) / freq + 2; 855 int count = mRecurStart.secsTo(preDateTime) / freq + 2;
850 if (rDuration > 0) { 856 if (rDuration > 0) {
851 if (count > rDuration) 857 if (count > rDuration)
852 return QDateTime(); 858 return QDateTime();
853 if (last && count == rDuration) 859 if (last && count == rDuration)
854 *last = true; 860 *last = true;
855 } 861 }
856 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 862 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
857 if (rDuration == 0) { 863 if (rDuration == 0) {
858 if (endtime > rEndDateTime) 864 if (endtime > rEndDateTime)
859 return QDateTime(); 865 return QDateTime();
860 if (last && endtime == rEndDateTime) 866 if (last && endtime == rEndDateTime)
861 *last = true; 867 *last = true;
862 } 868 }
863 return endtime; 869 return endtime;
864} 870}
865 871
866QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const 872QDate Recurrence::getNextDate(const QDate &preDate, bool *last) const
867{ 873{
868 if (last) 874 if (last)
869 *last = false; 875 *last = false;
870 switch (recurs) 876 switch (recurs)
871 { 877 {
872 case rMinutely: 878 case rMinutely:
873 case rHourly: 879 case rHourly:
874 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date(); 880 return getNextDateTime(QDateTime(preDate, QTime(23,59,59)), last).date();
875 case rDaily: 881 case rDaily:
876 case rWeekly: 882 case rWeekly:
877 case rMonthlyPos: 883 case rMonthlyPos:
878 case rMonthlyDay: 884 case rMonthlyDay:
879 case rYearlyMonth: 885 case rYearlyMonth:
880 case rYearlyDay: 886 case rYearlyDay:
881 case rYearlyPos: 887 case rYearlyPos:
882 qDebug("Recurrence::getNextDate: MAY BE BROKEN "); 888 qDebug("Recurrence::getNextDate: MAY BE BROKEN ");
883 return getNextDateNoTime(preDate, last); 889 return getNextDateNoTime(preDate, last);
884 default: 890 default:
885 return QDate(); 891 return QDate();
886 } 892 }
887} 893}
888 894
889 895
890QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const 896QDateTime Recurrence::getPreviousDateTime(const QDateTime &afterDateTime, bool *last) const
891{ 897{
892 if (last) 898 if (last)
893 *last = false; 899 *last = false;
894 int freq; 900 int freq;
895 switch (recurs) 901 switch (recurs)
896 { 902 {
897 case rMinutely: 903 case rMinutely:
898 freq = rFreq * 60; 904 freq = rFreq * 60;
899 break; 905 break;
900 case rHourly: 906 case rHourly:
901 freq = rFreq * 3600; 907 freq = rFreq * 3600;
902 break; 908 break;
903 case rDaily: 909 case rDaily:
904 case rWeekly: 910 case rWeekly:
905 case rMonthlyPos: 911 case rMonthlyPos:
906 case rMonthlyDay: 912 case rMonthlyDay:
907 case rYearlyMonth: 913 case rYearlyMonth:
908 case rYearlyDay: 914 case rYearlyDay:
909 case rYearlyPos: { 915 case rYearlyPos: {
910 QDate afterDate = afterDateTime.date(); 916 QDate afterDate = afterDateTime.date();
911 if (!mFloats && mRecurStart.time() < afterDateTime.time()) 917 if (!mFloats && mRecurStart.time() < afterDateTime.time())
912 afterDate = afterDate.addDays(1); 918 afterDate = afterDate.addDays(1);
913 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time()); 919 return QDateTime(getPreviousDateNoTime(afterDate, last), mRecurStart.time());
914 } 920 }
915 default: 921 default:
916 return QDateTime(); 922 return QDateTime();
917 } 923 }
918 924
919 // It's a sub-daily recurrence 925 // It's a sub-daily recurrence
920 if (afterDateTime <= mRecurStart) 926 if (afterDateTime <= mRecurStart)
921 return QDateTime(); 927 return QDateTime();
922 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1; 928 int count = (mRecurStart.secsTo(afterDateTime) - 1) / freq + 1;
923 if (rDuration > 0) { 929 if (rDuration > 0) {
924 if (count > rDuration) 930 if (count > rDuration)
925 count = rDuration; 931 count = rDuration;
926 if (last && count == rDuration) 932 if (last && count == rDuration)
927 *last = true; 933 *last = true;
928 } 934 }
929 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq); 935 QDateTime endtime = mRecurStart.addSecs((count - 1)*freq);
930 if (rDuration == 0) { 936 if (rDuration == 0) {
931 if (endtime > rEndDateTime) 937 if (endtime > rEndDateTime)
932 endtime = rEndDateTime; 938 endtime = rEndDateTime;
933 if (last && endtime == rEndDateTime) 939 if (last && endtime == rEndDateTime)
934 *last = true; 940 *last = true;
935 } 941 }
936 return endtime; 942 return endtime;
937} 943}
938 944
939QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const 945QDate Recurrence::getPreviousDate(const QDate &afterDate, bool *last) const
940{ 946{
941 if (last) 947 if (last)
942 *last = false; 948 *last = false;
943 switch (recurs) 949 switch (recurs)
944 { 950 {
945 case rMinutely: 951 case rMinutely:
946 case rHourly: 952 case rHourly:
947 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date(); 953 return getPreviousDateTime(QDateTime(afterDate, QTime(0,0,0)), last).date();
948 case rDaily: 954 case rDaily:
949 case rWeekly: 955 case rWeekly:
950 case rMonthlyPos: 956 case rMonthlyPos:
951 case rMonthlyDay: 957 case rMonthlyDay:
952 case rYearlyMonth: 958 case rYearlyMonth:
953 case rYearlyDay: 959 case rYearlyDay:
954 case rYearlyPos: 960 case rYearlyPos:
955 return getPreviousDateNoTime(afterDate, last); 961 return getPreviousDateNoTime(afterDate, last);
956 default: 962 default:
957 return QDate(); 963 return QDate();
958 } 964 }
959} 965}
960 966
961 967
962/***************************** PROTECTED FUNCTIONS ***************************/ 968/***************************** PROTECTED FUNCTIONS ***************************/
963 969
964bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const 970bool Recurrence::recursSecondly(const QDate &qd, int secondFreq) const
965{ 971{
966 if ((qd >= mRecurStart.date()) && 972 if ((qd >= mRecurStart.date()) &&
967 ((rDuration > 0) && (qd <= endDate()) || 973 ((rDuration > 0) && (qd <= endDate()) ||
968 ((rDuration == 0) && (qd <= rEndDateTime.date())) || 974 ((rDuration == 0) && (qd <= rEndDateTime.date())) ||
969 (rDuration == -1))) { 975 (rDuration == -1))) {
970 // The date queried falls within the range of the event. 976 // The date queried falls within the range of the event.
971 if (secondFreq < 24*3600) 977 if (secondFreq < 24*3600)
972 return true; // the event recurs at least once each day 978 return true; // the event recurs at least once each day
973 int after = mRecurStart.secsTo(QDateTime(qd)); 979 int after = mRecurStart.secsTo(QDateTime(qd));
974 if (after / secondFreq != (after + 24*3600) / secondFreq) 980 if (after / secondFreq != (after + 24*3600) / secondFreq)
975 return true; 981 return true;
976 } 982 }
977 return false; 983 return false;
978} 984}
979 985
980bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const 986bool Recurrence::recursMinutelyAt(const QDateTime &dt, int minuteFreq) const