summaryrefslogtreecommitdiff
authorzecke <zecke>2003-05-07 17:49:07 (UTC)
committer zecke <zecke>2003-05-07 17:49:07 (UTC)
commitc13ada0f5e418b25b177e132ff2e1dfe7821577f (patch) (unidiff)
tree40e8d6cc67a1de638ef3c278fd827ba0cbea5b76
parentac895871f93dce9734189daf9cb95dbbda605096 (diff)
downloadopie-c13ada0f5e418b25b177e132ff2e1dfe7821577f.zip
opie-c13ada0f5e418b25b177e132ff2e1dfe7821577f.tar.gz
opie-c13ada0f5e418b25b177e132ff2e1dfe7821577f.tar.bz2
implement loading of Recurrence
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/opimnotifymanager.cpp3
-rw-r--r--libopie/pim/opimnotifymanager.h3
-rw-r--r--libopie/pim/orecur.cpp2
-rw-r--r--libopie/pim/otodoaccessxml.cpp72
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp72
-rw-r--r--libopie2/opiepim/core/opimnotifymanager.cpp3
-rw-r--r--libopie2/opiepim/core/opimnotifymanager.h3
-rw-r--r--libopie2/opiepim/core/orecur.cpp2
8 files changed, 152 insertions, 8 deletions
diff --git a/libopie/pim/opimnotifymanager.cpp b/libopie/pim/opimnotifymanager.cpp
index be4a1c2..49af757 100644
--- a/libopie/pim/opimnotifymanager.cpp
+++ b/libopie/pim/opimnotifymanager.cpp
@@ -1,69 +1,72 @@
1#include "opimnotifymanager.h" 1#include "opimnotifymanager.h"
2 2
3OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al) 3OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al)
4 : m_rem( rem ), m_al( al ) 4 : m_rem( rem ), m_al( al )
5{} 5{}
6OPimNotifyManager::~OPimNotifyManager() { 6OPimNotifyManager::~OPimNotifyManager() {
7} 7}
8/* use static_cast and type instead of dynamic... */ 8/* use static_cast and type instead of dynamic... */
9void OPimNotifyManager::add( const OPimNotify& noti) { 9void OPimNotifyManager::add( const OPimNotify& noti) {
10 if ( noti.type() == QString::fromLatin1("OPimReminder") ) { 10 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
11 const OPimReminder& rem = static_cast<const OPimReminder&>(noti); 11 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
12 m_rem.append( rem ); 12 m_rem.append( rem );
13 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { 13 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
14 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); 14 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
15 m_al.append( al ); 15 m_al.append( al );
16 } 16 }
17} 17}
18void OPimNotifyManager::remove( const OPimNotify& noti) { 18void OPimNotifyManager::remove( const OPimNotify& noti) {
19 if ( noti.type() == QString::fromLatin1("OPimReminder") ) { 19 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
20 const OPimReminder& rem = static_cast<const OPimReminder&>(noti); 20 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
21 m_rem.remove( rem ); 21 m_rem.remove( rem );
22 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { 22 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
23 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); 23 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
24 m_al.remove( al ); 24 m_al.remove( al );
25 } 25 }
26} 26}
27void OPimNotifyManager::replace( const OPimNotify& noti) { 27void OPimNotifyManager::replace( const OPimNotify& noti) {
28 if ( noti.type() == QString::fromLatin1("OPimReminder") ) { 28 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
29 const OPimReminder& rem = static_cast<const OPimReminder&>(noti); 29 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
30 m_rem.remove( rem ); 30 m_rem.remove( rem );
31 m_rem.append( rem ); 31 m_rem.append( rem );
32 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { 32 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
33 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); 33 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
34 m_al.remove( al ); 34 m_al.remove( al );
35 m_al.append( al ); 35 m_al.append( al );
36 } 36 }
37} 37}
38OPimNotifyManager::Reminders OPimNotifyManager::reminders()const { 38OPimNotifyManager::Reminders OPimNotifyManager::reminders()const {
39 return m_rem; 39 return m_rem;
40} 40}
41OPimNotifyManager::Alarms OPimNotifyManager::alarms()const { 41OPimNotifyManager::Alarms OPimNotifyManager::alarms()const {
42 return m_al; 42 return m_al;
43} 43}
44void OPimNotifyManager::setAlarms( const Alarms& al) { 44void OPimNotifyManager::setAlarms( const Alarms& al) {
45 m_al = al; 45 m_al = al;
46} 46}
47void OPimNotifyManager::setReminders( const Reminders& rem) { 47void OPimNotifyManager::setReminders( const Reminders& rem) {
48 m_rem = rem; 48 m_rem = rem;
49} 49}
50/* FIXME!!! */ 50/* FIXME!!! */
51/** 51/**
52 * The idea is to check if the provider for our service 52 * The idea is to check if the provider for our service
53 * is online 53 * is online
54 * if it is we will use QCOP 54 * if it is we will use QCOP
55 * if not the Factory to get the backend... 55 * if not the Factory to get the backend...
56 * Qtopia1.6 services would be kewl to have here.... 56 * Qtopia1.6 services would be kewl to have here....
57 */ 57 */
58void OPimNotifyManager::registerNotify( const OPimNotify& ) { 58void OPimNotifyManager::registerNotify( const OPimNotify& ) {
59 59
60} 60}
61/* FIXME!!! */ 61/* FIXME!!! */
62/** 62/**
63 * same as above... 63 * same as above...
64 * Also implement Url model 64 * Also implement Url model
65 * have a MainWindow.... 65 * have a MainWindow....
66 */ 66 */
67void OPimNotifyManager::deregister( const OPimNotify& ) { 67void OPimNotifyManager::deregister( const OPimNotify& ) {
68 68
69} 69}
70bool OPimNotifyManager::isEmpty()const {
71 return ( m_rem.isEmpty() && m_al.isEmpty() );
72}
diff --git a/libopie/pim/opimnotifymanager.h b/libopie/pim/opimnotifymanager.h
index 0eebc9b..0ac30a1 100644
--- a/libopie/pim/opimnotifymanager.h
+++ b/libopie/pim/opimnotifymanager.h
@@ -1,51 +1,54 @@
1#ifndef OPIE_PIM_NOTIFY_MANAGER_H 1#ifndef OPIE_PIM_NOTIFY_MANAGER_H
2#define OPIE_PIM_NOTIFY_MANAGER_H 2#define OPIE_PIM_NOTIFY_MANAGER_H
3 3
4#include <qvaluelist.h> 4#include <qvaluelist.h>
5 5
6#include <opie/opimnotify.h> 6#include <opie/opimnotify.h>
7 7
8/** 8/**
9 * The notify manager keeps track of the Notifiers.... 9 * The notify manager keeps track of the Notifiers....
10 */ 10 */
11class OPimNotifyManager { 11class OPimNotifyManager {
12public: 12public:
13 typedef QValueList<OPimReminder> Reminders; 13 typedef QValueList<OPimReminder> Reminders;
14 typedef QValueList<OPimAlarm> Alarms; 14 typedef QValueList<OPimAlarm> Alarms;
15 OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() ); 15 OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() );
16 ~OPimNotifyManager(); 16 ~OPimNotifyManager();
17 17
18 /* we will cast it for you ;) */ 18 /* we will cast it for you ;) */
19 void add( const OPimNotify& ); 19 void add( const OPimNotify& );
20 void remove( const OPimNotify& ); 20 void remove( const OPimNotify& );
21 /* replaces all with this one! */ 21 /* replaces all with this one! */
22 void replace( const OPimNotify& ); 22 void replace( const OPimNotify& );
23 23
24 Reminders reminders()const; 24 Reminders reminders()const;
25 Alarms alarms()const; 25 Alarms alarms()const;
26 26
27 void setAlarms( const Alarms& ); 27 void setAlarms( const Alarms& );
28 void setReminders( const Reminders& ); 28 void setReminders( const Reminders& );
29 29
30 /* register is a Ansi C keyword... */ 30 /* register is a Ansi C keyword... */
31 /** 31 /**
32 * This function will register the Notify to the Alarm Server 32 * This function will register the Notify to the Alarm Server
33 * or datebook depending on the type of the notify 33 * or datebook depending on the type of the notify
34 */ 34 */
35 void registerNotify( const OPimNotify& ); 35 void registerNotify( const OPimNotify& );
36 36
37 /** 37 /**
38 * this will do the opposite.. 38 * this will do the opposite..
39 */ 39 */
40 void deregister( const OPimNotify& ); 40 void deregister( const OPimNotify& );
41 41
42
43 bool isEmpty()const;
44
42private: 45private:
43 Reminders m_rem; 46 Reminders m_rem;
44 Alarms m_al; 47 Alarms m_al;
45 48
46 class Private; 49 class Private;
47 Private *d; 50 Private *d;
48 51
49}; 52};
50 53
51#endif 54#endif
diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp
index e3b45b4..eae1fdc 100644
--- a/libopie/pim/orecur.cpp
+++ b/libopie/pim/orecur.cpp
@@ -123,388 +123,388 @@ bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
123 for this round */ 123 for this round */
124 // firstOfWeek = 0; this is already done at decl. 124 // firstOfWeek = 0; this is already done at decl.
125 while(!((1 << firstOfWeek) & days() )) 125 while(!((1 << firstOfWeek) & days() ))
126 firstOfWeek++; 126 firstOfWeek++;
127 127
128 /* there is at least one 'day', or there would be no event */ 128 /* there is at least one 'day', or there would be no event */
129 while(!((1 << (dayOfWeek % 7)) & days() )) 129 while(!((1 << (dayOfWeek % 7)) & days() ))
130 dayOfWeek++; 130 dayOfWeek++;
131 131
132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
133 dayOfWeek -= start().dayOfWeek() -1; 133 dayOfWeek -= start().dayOfWeek() -1;
134 134
135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
136 firstOfWeek -= start().dayOfWeek() -1; 136 firstOfWeek -= start().dayOfWeek() -1;
137 137
138 // dayOfWeek may be negitive now 138 // dayOfWeek may be negitive now
139 // day of week is number of days to add to start day 139 // day of week is number of days to add to start day
140 140
141 freq *= 7; 141 freq *= 7;
142 // FALL-THROUGH !!!!! 142 // FALL-THROUGH !!!!!
143 case Daily: 143 case Daily:
144 // the add is for the possible fall through from weekly */ 144 // the add is for the possible fall through from weekly */
145 if(start().addDays(dayOfWeek) > from) { 145 if(start().addDays(dayOfWeek) > from) {
146 /* first week exception */ 146 /* first week exception */
147 next = QDate(start().addDays(dayOfWeek) ); 147 next = QDate(start().addDays(dayOfWeek) );
148 if ((next > endDate()) 148 if ((next > endDate())
149 && hasEndDate() ) 149 && hasEndDate() )
150 return FALSE; 150 return FALSE;
151 return TRUE; 151 return TRUE;
152 } 152 }
153 /* if from is middle of a non-week */ 153 /* if from is middle of a non-week */
154 154
155 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 155 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
157 157
158 if(diff != 0) 158 if(diff != 0)
159 diff = freq - diff; 159 diff = freq - diff;
160 if(diff2 != 0) 160 if(diff2 != 0)
161 diff2 = freq - diff2; 161 diff2 = freq - diff2;
162 diff = QMIN(diff, diff2); 162 diff = QMIN(diff, diff2);
163 163
164 next = QDate(from.addDays(diff)); 164 next = QDate(from.addDays(diff));
165 if ( (next > endDate()) 165 if ( (next > endDate())
166 && hasEndDate() ) 166 && hasEndDate() )
167 return FALSE; 167 return FALSE;
168 return TRUE; 168 return TRUE;
169 case MonthlyDay: 169 case MonthlyDay:
170 iday = from.day(); 170 iday = from.day();
171 iyear = from.year(); 171 iyear = from.year();
172 imonth = from.month(); 172 imonth = from.month();
173 /* find equivelent day of month for this month */ 173 /* find equivelent day of month for this month */
174 dayOfWeek = start().dayOfWeek(); 174 dayOfWeek = start().dayOfWeek();
175 weekOfMonth = (start().day() - 1) / 7; 175 weekOfMonth = (start().day() - 1) / 7;
176 176
177 /* work out when the next valid month is */ 177 /* work out when the next valid month is */
178 a = from.year() - start().year(); 178 a = from.year() - start().year();
179 a *= 12; 179 a *= 12;
180 a = a + (imonth - start().month()); 180 a = a + (imonth - start().month());
181 /* a is e.start()monthsFrom(from); */ 181 /* a is e.start()monthsFrom(from); */
182 if(a % freq) { 182 if(a % freq) {
183 a = freq - (a % freq); 183 a = freq - (a % freq);
184 imonth = from.month() + a; 184 imonth = from.month() + a;
185 if (imonth > 12) { 185 if (imonth > 12) {
186 imonth--; 186 imonth--;
187 iyear += imonth / 12; 187 iyear += imonth / 12;
188 imonth = imonth % 12; 188 imonth = imonth % 12;
189 imonth++; 189 imonth++;
190 } 190 }
191 } 191 }
192 /* imonth is now the first month after or on 192 /* imonth is now the first month after or on
193 from that matches the frequency given */ 193 from that matches the frequency given */
194 194
195 /* find for this month */ 195 /* find for this month */
196 tmpDate = QDate( iyear, imonth, 1 ); 196 tmpDate = QDate( iyear, imonth, 1 );
197 197
198 iday = 1; 198 iday = 1;
199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
200 iday += 7 * weekOfMonth; 200 iday += 7 * weekOfMonth;
201 while (iday > tmpDate.daysInMonth()) { 201 while (iday > tmpDate.daysInMonth()) {
202 imonth += freq; 202 imonth += freq;
203 if (imonth > 12) { 203 if (imonth > 12) {
204 imonth--; 204 imonth--;
205 iyear += imonth / 12; 205 iyear += imonth / 12;
206 imonth = imonth % 12; 206 imonth = imonth % 12;
207 imonth++; 207 imonth++;
208 } 208 }
209 tmpDate = QDate( iyear, imonth, 1 ); 209 tmpDate = QDate( iyear, imonth, 1 );
210 /* these loops could go for a while, check end case now */ 210 /* these loops could go for a while, check end case now */
211 if ((tmpDate > endDate()) && hasEndDate() ) 211 if ((tmpDate > endDate()) && hasEndDate() )
212 return FALSE; 212 return FALSE;
213 iday = 1; 213 iday = 1;
214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
215 iday += 7 * weekOfMonth; 215 iday += 7 * weekOfMonth;
216 } 216 }
217 tmpDate = QDate(iyear, imonth, iday); 217 tmpDate = QDate(iyear, imonth, iday);
218 218
219 if (tmpDate >= from) { 219 if (tmpDate >= from) {
220 next = tmpDate; 220 next = tmpDate;
221 if ((next > endDate() ) && hasEndDate() ) 221 if ((next > endDate() ) && hasEndDate() )
222 return FALSE; 222 return FALSE;
223 return TRUE; 223 return TRUE;
224 } 224 }
225 225
226 /* need to find the next iteration */ 226 /* need to find the next iteration */
227 do { 227 do {
228 imonth += freq; 228 imonth += freq;
229 if (imonth > 12) { 229 if (imonth > 12) {
230 imonth--; 230 imonth--;
231 iyear += imonth / 12; 231 iyear += imonth / 12;
232 imonth = imonth % 12; 232 imonth = imonth % 12;
233 imonth++; 233 imonth++;
234 } 234 }
235 tmpDate = QDate( iyear, imonth, 1 ); 235 tmpDate = QDate( iyear, imonth, 1 );
236 /* these loops could go for a while, check end case now */ 236 /* these loops could go for a while, check end case now */
237 if ((tmpDate > endDate()) && hasEndDate() ) 237 if ((tmpDate > endDate()) && hasEndDate() )
238 return FALSE; 238 return FALSE;
239 iday = 1; 239 iday = 1;
240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
241 iday += 7 * weekOfMonth; 241 iday += 7 * weekOfMonth;
242 } while (iday > tmpDate.daysInMonth()); 242 } while (iday > tmpDate.daysInMonth());
243 tmpDate = QDate(iyear, imonth, iday); 243 tmpDate = QDate(iyear, imonth, iday);
244 244
245 next = tmpDate; 245 next = tmpDate;
246 if ((next > endDate()) && hasEndDate() ) 246 if ((next > endDate()) && hasEndDate() )
247 return FALSE; 247 return FALSE;
248 return TRUE; 248 return TRUE;
249 case MonthlyDate: 249 case MonthlyDate:
250 iday = start().day(); 250 iday = start().day();
251 iyear = from.year(); 251 iyear = from.year();
252 imonth = from.month(); 252 imonth = from.month();
253 253
254 a = from.year() - start().year(); 254 a = from.year() - start().year();
255 a *= 12; 255 a *= 12;
256 a = a + (imonth - start().month()); 256 a = a + (imonth - start().month());
257 /* a is e.start()monthsFrom(from); */ 257 /* a is e.start()monthsFrom(from); */
258 if(a % freq) { 258 if(a % freq) {
259 a = freq - (a % freq); 259 a = freq - (a % freq);
260 imonth = from.month() + a; 260 imonth = from.month() + a;
261 if (imonth > 12) { 261 if (imonth > 12) {
262 imonth--; 262 imonth--;
263 iyear += imonth / 12; 263 iyear += imonth / 12;
264 imonth = imonth % 12; 264 imonth = imonth % 12;
265 imonth++; 265 imonth++;
266 } 266 }
267 } 267 }
268 /* imonth is now the first month after or on 268 /* imonth is now the first month after or on
269 from that matches the frequencey given */ 269 from that matches the frequencey given */
270 270
271 /* this could go for a while, worse case, 4*12 iterations, probably */ 271 /* this could go for a while, worse case, 4*12 iterations, probably */
272 while(!QDate::isValid(iyear, imonth, iday) ) { 272 while(!QDate::isValid(iyear, imonth, iday) ) {
273 imonth += freq; 273 imonth += freq;
274 if (imonth > 12) { 274 if (imonth > 12) {
275 imonth--; 275 imonth--;
276 iyear += imonth / 12; 276 iyear += imonth / 12;
277 imonth = imonth % 12; 277 imonth = imonth % 12;
278 imonth++; 278 imonth++;
279 } 279 }
280 /* these loops could go for a while, check end case now */ 280 /* these loops could go for a while, check end case now */
281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
282 return FALSE; 282 return FALSE;
283 } 283 }
284 284
285 if(QDate(iyear, imonth, iday) >= from) { 285 if(QDate(iyear, imonth, iday) >= from) {
286 /* done */ 286 /* done */
287 next = QDate(iyear, imonth, iday); 287 next = QDate(iyear, imonth, iday);
288 if ((next > endDate()) && hasEndDate() ) 288 if ((next > endDate()) && hasEndDate() )
289 return FALSE; 289 return FALSE;
290 return TRUE; 290 return TRUE;
291 } 291 }
292 292
293 /* ok, need to cycle */ 293 /* ok, need to cycle */
294 imonth += freq; 294 imonth += freq;
295 imonth--; 295 imonth--;
296 iyear += imonth / 12; 296 iyear += imonth / 12;
297 imonth = imonth % 12; 297 imonth = imonth % 12;
298 imonth++; 298 imonth++;
299 299
300 while(!QDate::isValid(iyear, imonth, iday) ) { 300 while(!QDate::isValid(iyear, imonth, iday) ) {
301 imonth += freq; 301 imonth += freq;
302 imonth--; 302 imonth--;
303 iyear += imonth / 12; 303 iyear += imonth / 12;
304 imonth = imonth % 12; 304 imonth = imonth % 12;
305 imonth++; 305 imonth++;
306 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 306 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
307 return FALSE; 307 return FALSE;
308 } 308 }
309 309
310 next = QDate(iyear, imonth, iday); 310 next = QDate(iyear, imonth, iday);
311 if ((next > endDate()) && hasEndDate() ) 311 if ((next > endDate()) && hasEndDate() )
312 return FALSE; 312 return FALSE;
313 return TRUE; 313 return TRUE;
314 case Yearly: 314 case Yearly:
315 iday = start().day(); 315 iday = start().day();
316 imonth = start().month(); 316 imonth = start().month();
317 iyear = from.year(); // after all, we want to start in this year 317 iyear = from.year(); // after all, we want to start in this year
318 318
319 diff = 1; 319 diff = 1;
320 if(imonth == 2 && iday > 28) { 320 if(imonth == 2 && iday > 28) {
321 /* leap year, and it counts, calculate actual frequency */ 321 /* leap year, and it counts, calculate actual frequency */
322 if(freq % 4) 322 if(freq % 4)
323 if (freq % 2) 323 if (freq % 2)
324 freq = freq * 4; 324 freq = freq * 4;
325 else 325 else
326 freq = freq * 2; 326 freq = freq * 2;
327 /* else divides by 4 already, leave freq alone */ 327 /* else divides by 4 already, leave freq alone */
328 diff = 4; 328 diff = 4;
329 } 329 }
330 330
331 a = from.year() - start().year(); 331 a = from.year() - start().year();
332 if(a % freq) { 332 if(a % freq) {
333 a = freq - (a % freq); 333 a = freq - (a % freq);
334 iyear = iyear + a; 334 iyear = iyear + a;
335 } 335 }
336 336
337 /* under the assumption we won't hit one of the special not-leap years twice */ 337 /* under the assumption we won't hit one of the special not-leap years twice */
338 if(!QDate::isValid(iyear, imonth, iday)) { 338 if(!QDate::isValid(iyear, imonth, iday)) {
339 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 339 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
340 iyear += freq; 340 iyear += freq;
341 } 341 }
342 342
343 if(QDate(iyear, imonth, iday) >= from) { 343 if(QDate(iyear, imonth, iday) >= from) {
344 next = QDate(iyear, imonth, iday); 344 next = QDate(iyear, imonth, iday);
345 345
346 if ((next > endDate()) && hasEndDate() ) 346 if ((next > endDate()) && hasEndDate() )
347 return FALSE; 347 return FALSE;
348 return TRUE; 348 return TRUE;
349 } 349 }
350 /* iyear == from.year(), need to advance again */ 350 /* iyear == from.year(), need to advance again */
351 iyear += freq; 351 iyear += freq;
352 /* under the assumption we won't hit one of the special not-leap years twice */ 352 /* under the assumption we won't hit one of the special not-leap years twice */
353 if(!QDate::isValid(iyear, imonth, iday)) { 353 if(!QDate::isValid(iyear, imonth, iday)) {
354 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 354 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
355 iyear += freq; 355 iyear += freq;
356 } 356 }
357 357
358 next = QDate(iyear, imonth, iday); 358 next = QDate(iyear, imonth, iday);
359 if ((next > endDate()) && hasEndDate() ) 359 if ((next > endDate()) && hasEndDate() )
360 return FALSE; 360 return FALSE;
361 return TRUE; 361 return TRUE;
362 default: 362 default:
363 return FALSE; 363 return FALSE;
364 } 364 }
365} 365}
366ORecur::RepeatType ORecur::type()const{ 366ORecur::RepeatType ORecur::type()const{
367 return data->type; 367 return data->type;
368} 368}
369int ORecur::frequency()const { 369int ORecur::frequency()const {
370 return data->freq; 370 return data->freq;
371} 371}
372int ORecur::position()const { 372int ORecur::position()const {
373 return data->pos; 373 return data->pos;
374} 374}
375char ORecur::days() const{ 375char ORecur::days() const{
376 return data->days; 376 return data->days;
377} 377}
378bool ORecur::hasEndDate()const { 378bool ORecur::hasEndDate()const {
379 return data->hasEnd; 379 return data->hasEnd;
380} 380}
381QDate ORecur::endDate()const { 381QDate ORecur::endDate()const {
382 return data->end; 382 return data->end;
383} 383}
384QDate ORecur::start()const{ 384QDate ORecur::start()const{
385 return data->start; 385 return data->start;
386} 386}
387QDateTime ORecur::createdDateTime()const { 387QDateTime ORecur::createdDateTime()const {
388 return data->create; 388 return data->create;
389} 389}
390int ORecur::repetition()const { 390int ORecur::repetition()const {
391 return data->rep; 391 return data->rep;
392} 392}
393QString ORecur::service()const { 393QString ORecur::service()const {
394 return data->app; 394 return data->app;
395} 395}
396ORecur::ExceptionList& ORecur::exceptions() { 396ORecur::ExceptionList& ORecur::exceptions() {
397 return data->list; 397 return data->list;
398} 398}
399void ORecur::setType( const RepeatType& z) { 399void ORecur::setType( const RepeatType& z) {
400 checkOrModify(); 400 checkOrModify();
401 data->type = z; 401 data->type = z;
402} 402}
403void ORecur::setFrequency( int freq ) { 403void ORecur::setFrequency( int freq ) {
404 checkOrModify(); 404 checkOrModify();
405 data->freq = freq; 405 data->freq = freq;
406} 406}
407void ORecur::setPosition( int pos ) { 407void ORecur::setPosition( int pos ) {
408 checkOrModify(); 408 checkOrModify();
409 data->pos = pos; 409 data->pos = pos;
410} 410}
411void ORecur::setDays( char c ) { 411void ORecur::setDays( char c ) {
412 checkOrModify(); 412 checkOrModify();
413 data->days = c; 413 data->days = c;
414} 414}
415void ORecur::setEndDate( const QDate& dt) { 415void ORecur::setEndDate( const QDate& dt) {
416 checkOrModify(); 416 checkOrModify();
417 data->end = dt; 417 data->end = dt;
418} 418}
419void ORecur::setCreatedDateTime( const QDateTime& t) { 419void ORecur::setCreatedDateTime( const QDateTime& t) {
420 checkOrModify(); 420 checkOrModify();
421 data->create = t; 421 data->create = t;
422} 422}
423void ORecur::setHasEndDate( bool b) { 423void ORecur::setHasEndDate( bool b) {
424 checkOrModify(); 424 checkOrModify();
425 data->hasEnd = b; 425 data->hasEnd = b;
426} 426}
427void ORecur::setRepitition( int rep ) { 427void ORecur::setRepitition( int rep ) {
428 checkOrModify(); 428 checkOrModify();
429 data->rep = rep; 429 data->rep = rep;
430} 430}
431void ORecur::setService( const QString& app ) { 431void ORecur::setService( const QString& app ) {
432 checkOrModify(); 432 checkOrModify();
433 data->app = app; 433 data->app = app;
434} 434}
435void ORecur::setStart( const QDate& dt ) { 435void ORecur::setStart( const QDate& dt ) {
436 checkOrModify(); 436 checkOrModify();
437 data->start = dt; 437 data->start = dt;
438} 438}
439void ORecur::checkOrModify() { 439void ORecur::checkOrModify() {
440 if ( data->count != 1 ) { 440 if ( data->count != 1 ) {
441 data->deref(); 441 data->deref();
442 Data* d2 = new Data; 442 Data* d2 = new Data;
443 d2->days = data->days; 443 d2->days = data->days;
444 d2->type = data->type; 444 d2->type = data->type;
445 d2->freq = data->freq; 445 d2->freq = data->freq;
446 d2->pos = data->pos; 446 d2->pos = data->pos;
447 d2->hasEnd = data->hasEnd; 447 d2->hasEnd = data->hasEnd;
448 d2->end = data->end; 448 d2->end = data->end;
449 d2->create = data->create; 449 d2->create = data->create;
450 d2->rep = data->rep; 450 d2->rep = data->rep;
451 d2->app = data->app; 451 d2->app = data->app;
452 d2->list = data->list; 452 d2->list = data->list;
453 d2->start = data->start; 453 d2->start = data->start;
454 data = d2; 454 data = d2;
455 } 455 }
456} 456}
457QString ORecur::toString()const { 457QString ORecur::toString()const {
458 QString buf; 458 QString buf;
459 459
460 buf += " rtype=\""; 460 buf += " rtype=\"";
461 switch ( data->type ) { 461 switch ( data->type ) {
462 case ORecur::Daily: 462 case ORecur::Daily:
463 buf += "Daily"; 463 buf += "Daily";
464 break; 464 break;
465 case ORecur::Weekly: 465 case ORecur::Weekly:
466 buf += "Weekly"; 466 buf += "Weekly";
467 break; 467 break;
468 case ORecur::MonthlyDay: 468 case ORecur::MonthlyDay:
469 buf += "MonthlyDay"; 469 buf += "MonthlyDay";
470 break; 470 break;
471 case ORecur::MonthlyDate: 471 case ORecur::MonthlyDate:
472 buf += "MonthlyDate"; 472 buf += "MonthlyDate";
473 break; 473 break;
474 case ORecur::Yearly: 474 case ORecur::Yearly:
475 buf += "Yearly"; 475 buf += "Yearly";
476 break; 476 break;
477 default: 477 default:
478 buf += "NoRepeat"; 478 buf += "NoRepeat";
479 break; 479 break;
480 } 480 }
481 buf += "\""; 481 buf += "\"";
482 if (data->days > 0 ) 482 if (data->days > 0 )
483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\""; 483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\"";
484 if ( data->pos != 0 ) 484 if ( data->pos != 0 )
485 buf += " rposition=\"" + QString::number(data->pos ) + "\""; 485 buf += " rposition=\"" + QString::number(data->pos ) + "\"";
486 486
487 buf += " rfreq=\"" + QString::number( data->freq ) + "\""; 487 buf += " rfreq=\"" + QString::number( data->freq ) + "\"";
488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\""; 488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\"";
489 if ( data->hasEnd ) 489 if ( data->hasEnd )
490 buf += " enddt=\"" 490 buf += " enddt=\""
491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) 491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) )
492 + "\""; 492 + "\"";
493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\""; 493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\"";
494 494
495 if ( data->list.isEmpty() ) return buf; 495 if ( data->list.isEmpty() ) return buf;
496 // save exceptions list here!! 496 // save exceptions list here!!
497 ExceptionList::ConstIterator it; 497 ExceptionList::ConstIterator it;
498 ExceptionList list = data->list; 498 ExceptionList list = data->list;
499 buf += " exceptions=\""; 499 buf += " exceptions=\"";
500 QDate date; 500 QDate date;
501 for ( it = list.begin(); it != list.end(); ++it ) { 501 for ( it = list.begin(); it != list.end(); ++it ) {
502 date = (*it); 502 date = (*it);
503 if ( it != list.begin() ) buf += " "; 503 if ( it != list.begin() ) buf += " ";
504 504
505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() ); 505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
506 } 506 }
507 buf += "\""; 507 buf += "\" ";
508 508
509 return buf; 509 return buf;
510} 510}
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index c0d8dfc..71b6a7e 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -1,691 +1,757 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <sys/mman.h> 4#include <sys/mman.h>
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/types.h> 6#include <sys/types.h>
7 7
8#include <unistd.h> 8#include <unistd.h>
9 9
10 10
11#include <qfile.h> 11#include <qfile.h>
12#include <qvector.h> 12#include <qvector.h>
13 13
14#include <qpe/global.h> 14#include <qpe/global.h>
15#include <qpe/stringutil.h> 15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h> 16#include <qpe/timeconversion.h>
17 17
18#include "otimezone.h"
18#include "orecur.h" 19#include "orecur.h"
19#include "otodoaccessxml.h" 20#include "otodoaccessxml.h"
20 21
21namespace { 22namespace {
23 time_t rp_end;
24 ORecur* rec;
25 ORecur *recur() {
26 if (!rec ) rec = new ORecur;
27 return rec;
28 }
29 int snd;
30 enum MoreAttributes {
31 FRType = OTodo::CompletedDate + 2,
32 FRWeekdays,
33 FRPosition,
34 FRFreq,
35 FRHasEndDate,
36 FREndDate,
37 FRStart,
38 FREnd
39 };
22 // FROM TT again 40 // FROM TT again
23char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) 41char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
24{ 42{
25 char needleChar; 43 char needleChar;
26 char haystackChar; 44 char haystackChar;
27 if (!needle || !haystack || !hLen || !nLen) 45 if (!needle || !haystack || !hLen || !nLen)
28 return 0; 46 return 0;
29 47
30 const char* hsearch = haystack; 48 const char* hsearch = haystack;
31 49
32 if ((needleChar = *needle++) != 0) { 50 if ((needleChar = *needle++) != 0) {
33 nLen--; //(to make up for needle++) 51 nLen--; //(to make up for needle++)
34 do { 52 do {
35 do { 53 do {
36 if ((haystackChar = *hsearch++) == 0) 54 if ((haystackChar = *hsearch++) == 0)
37 return (0); 55 return (0);
38 if (hsearch >= haystack + hLen) 56 if (hsearch >= haystack + hLen)
39 return (0); 57 return (0);
40 } while (haystackChar != needleChar); 58 } while (haystackChar != needleChar);
41 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); 59 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
42 hsearch--; 60 hsearch--;
43 } 61 }
44 return ((char *)hsearch); 62 return ((char *)hsearch);
45} 63}
46} 64}
47 65
48 66
49OTodoAccessXML::OTodoAccessXML( const QString& appName, 67OTodoAccessXML::OTodoAccessXML( const QString& appName,
50 const QString& fileName ) 68 const QString& fileName )
51 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 69 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
52{ 70{
53 if (!fileName.isEmpty() ) 71 if (!fileName.isEmpty() )
54 m_file = fileName; 72 m_file = fileName;
55 else 73 else
56 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 74 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
57} 75}
58OTodoAccessXML::~OTodoAccessXML() { 76OTodoAccessXML::~OTodoAccessXML() {
59 77
60} 78}
61bool OTodoAccessXML::load() { 79bool OTodoAccessXML::load() {
80 rec = 0;
62 m_opened = true; 81 m_opened = true;
63 m_changed = false; 82 m_changed = false;
64 /* initialize dict */ 83 /* initialize dict */
65 /* 84 /*
66 * UPDATE dict if you change anything!!! 85 * UPDATE dict if you change anything!!!
67 */ 86 */
68 QAsciiDict<int> dict(21); 87 QAsciiDict<int> dict(21);
69 dict.setAutoDelete( TRUE ); 88 dict.setAutoDelete( TRUE );
70 dict.insert("Categories" , new int(OTodo::Category) ); 89 dict.insert("Categories" , new int(OTodo::Category) );
71 dict.insert("Uid" , new int(OTodo::Uid) ); 90 dict.insert("Uid" , new int(OTodo::Uid) );
72 dict.insert("HasDate" , new int(OTodo::HasDate) ); 91 dict.insert("HasDate" , new int(OTodo::HasDate) );
73 dict.insert("Completed" , new int(OTodo::Completed) ); 92 dict.insert("Completed" , new int(OTodo::Completed) );
74 dict.insert("Description" , new int(OTodo::Description) ); 93 dict.insert("Description" , new int(OTodo::Description) );
75 dict.insert("Summary" , new int(OTodo::Summary) ); 94 dict.insert("Summary" , new int(OTodo::Summary) );
76 dict.insert("Priority" , new int(OTodo::Priority) ); 95 dict.insert("Priority" , new int(OTodo::Priority) );
77 dict.insert("DateDay" , new int(OTodo::DateDay) ); 96 dict.insert("DateDay" , new int(OTodo::DateDay) );
78 dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 97 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
79 dict.insert("DateYear" , new int(OTodo::DateYear) ); 98 dict.insert("DateYear" , new int(OTodo::DateYear) );
80 dict.insert("Progress" , new int(OTodo::Progress) ); 99 dict.insert("Progress" , new int(OTodo::Progress) );
81 dict.insert("Completed", new int(OTodo::Completed) ); 100 dict.insert("CompletedDate", new int(OTodo::CompletedDate) );
82 dict.insert("CrossReference", new int(OTodo::CrossReference) ); 101 dict.insert("CrossReference", new int(OTodo::CrossReference) );
83 dict.insert("State", new int(OTodo::State) ); 102 dict.insert("State", new int(OTodo::State) );
84 dict.insert("Recurrence", new int(OTodo::Recurrence) );
85 dict.insert("Alarms", new int(OTodo::Alarms) ); 103 dict.insert("Alarms", new int(OTodo::Alarms) );
86 dict.insert("Reminders", new int(OTodo::Reminders) ); 104 dict.insert("Reminders", new int(OTodo::Reminders) );
87 dict.insert("Notifiers", new int(OTodo::Notifiers) ); 105 dict.insert("Notifiers", new int(OTodo::Notifiers) );
88 dict.insert("Maintainer", new int(OTodo::Maintainer) ); 106 dict.insert("Maintainer", new int(OTodo::Maintainer) );
107 dict.insert("rtype", new int(FRType) );
108 dict.insert("rweekdays", new int(FRWeekdays) );
109 dict.insert("rposition", new int(FRPosition) );
110 dict.insert("rfreq", new int(FRFreq) );
111 dict.insert("start", new int(FRStart) );
112 dict.insert("rhasenddate", new int(FRHasEndDate) );
113 dict.insert("enddt", new int(FREndDate) );
89 114
90 // here the custom XML parser from TT it's GPL 115 // here the custom XML parser from TT it's GPL
91 // but we want to push OpiePIM... to TT..... 116 // but we want to push OpiePIM... to TT.....
92 // mmap part from zecke :) 117 // mmap part from zecke :)
93 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); 118 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
94 struct stat attribut; 119 struct stat attribut;
95 if ( fd < 0 ) return false; 120 if ( fd < 0 ) return false;
96 121
97 if ( fstat(fd, &attribut ) == -1 ) { 122 if ( fstat(fd, &attribut ) == -1 ) {
98 ::close( fd ); 123 ::close( fd );
99 return false; 124 return false;
100 } 125 }
101 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 126 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
102 if ( map_addr == ( (caddr_t)-1) ) { 127 if ( map_addr == ( (caddr_t)-1) ) {
103 ::close(fd ); 128 ::close(fd );
104 return false; 129 return false;
105 } 130 }
106 /* advise the kernel who we want to read it */ 131 /* advise the kernel who we want to read it */
107 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); 132 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
108 /* we do not the file any more */ 133 /* we do not the file any more */
109 ::close( fd ); 134 ::close( fd );
110 135
111 char* dt = (char*)map_addr; 136 char* dt = (char*)map_addr;
112 int len = attribut.st_size; 137 int len = attribut.st_size;
113 int i = 0; 138 int i = 0;
114 char *point; 139 char *point;
115 const char* collectionString = "<Task "; 140 const char* collectionString = "<Task ";
116 int strLen = strlen(collectionString); 141 int strLen = strlen(collectionString);
117 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) { 142 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
118 i = point -dt; 143 i = point -dt;
119 i+= strLen; 144 i+= strLen;
120 qWarning("Found a start at %d %d", i, (point-dt) ); 145 qWarning("Found a start at %d %d", i, (point-dt) );
121 146
122 OTodo ev; 147 OTodo ev;
123 m_year = m_month = m_day = 0; 148 m_year = m_month = m_day = 0;
124 149
125 while ( TRUE ) { 150 while ( TRUE ) {
126 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 151 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
127 ++i; 152 ++i;
128 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 153 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
129 break; 154 break;
130 155
131 // we have another attribute, read it. 156 // we have another attribute, read it.
132 int j = i; 157 int j = i;
133 while ( j < len && dt[j] != '=' ) 158 while ( j < len && dt[j] != '=' )
134 ++j; 159 ++j;
135 QCString attr( dt+i, j-i+1); 160 QCString attr( dt+i, j-i+1);
136 161
137 i = ++j; // skip = 162 i = ++j; // skip =
138 163
139 // find the start of quotes 164 // find the start of quotes
140 while ( i < len && dt[i] != '"' ) 165 while ( i < len && dt[i] != '"' )
141 ++i; 166 ++i;
142 j = ++i; 167 j = ++i;
143 168
144 bool haveUtf = FALSE; 169 bool haveUtf = FALSE;
145 bool haveEnt = FALSE; 170 bool haveEnt = FALSE;
146 while ( j < len && dt[j] != '"' ) { 171 while ( j < len && dt[j] != '"' ) {
147 if ( ((unsigned char)dt[j]) > 0x7f ) 172 if ( ((unsigned char)dt[j]) > 0x7f )
148 haveUtf = TRUE; 173 haveUtf = TRUE;
149 if ( dt[j] == '&' ) 174 if ( dt[j] == '&' )
150 haveEnt = TRUE; 175 haveEnt = TRUE;
151 ++j; 176 ++j;
152 } 177 }
153 if ( i == j ) { 178 if ( i == j ) {
154 // empty value 179 // empty value
155 i = j + 1; 180 i = j + 1;
156 continue; 181 continue;
157 } 182 }
158 183
159 QCString value( dt+i, j-i+1 ); 184 QCString value( dt+i, j-i+1 );
160 i = j + 1; 185 i = j + 1;
161 186
162 QString str = (haveUtf ? QString::fromUtf8( value ) 187 QString str = (haveUtf ? QString::fromUtf8( value )
163 : QString::fromLatin1( value ) ); 188 : QString::fromLatin1( value ) );
164 if ( haveEnt ) 189 if ( haveEnt )
165 str = Qtopia::plainString( str ); 190 str = Qtopia::plainString( str );
166 191
167 /* 192 /*
168 * add key + value 193 * add key + value
169 */ 194 */
170 todo( &dict, ev, attr, str ); 195 todo( &dict, ev, attr, str );
171 196
172 } 197 }
173 /* 198 /*
174 * now add it 199 * now add it
175 */ 200 */
176 qWarning("End at %d", i ); 201 qWarning("End at %d", i );
177 if (m_events.contains( ev.uid() ) || ev.uid() == 0) { 202 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
178 ev.setUid( 1 ); 203 ev.setUid( 1 );
179 m_changed = true; 204 m_changed = true;
180 } 205 }
181 if ( ev.hasDueDate() ) { 206 if ( ev.hasDueDate() ) {
182 ev.setDueDate( QDate(m_year, m_month, m_day) ); 207 ev.setDueDate( QDate(m_year, m_month, m_day) );
183 } 208 }
209 if ( rec && rec->doesRecur() ) {
210 OTimeZone utc = OTimeZone::utc();
211 ORecur recu( *rec ); // call copy c'tor
212 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
213 recu.setStart( ev.dueDate() );
214 ev.setRecurrence( recu );
215 }
184 m_events.insert(ev.uid(), ev ); 216 m_events.insert(ev.uid(), ev );
185 m_year = m_month = m_day = -1; 217 m_year = m_month = m_day = -1;
218 delete rec;
219 rec = 0;
186 } 220 }
187 221
188 munmap(map_addr, attribut.st_size ); 222 munmap(map_addr, attribut.st_size );
189 223
190 qWarning("counts %d records loaded!", m_events.count() ); 224 qWarning("counts %d records loaded!", m_events.count() );
191 return true; 225 return true;
192} 226}
193bool OTodoAccessXML::reload() { 227bool OTodoAccessXML::reload() {
194 m_events.clear(); 228 m_events.clear();
195 return load(); 229 return load();
196} 230}
197bool OTodoAccessXML::save() { 231bool OTodoAccessXML::save() {
198// qWarning("saving"); 232// qWarning("saving");
199 if (!m_opened || !m_changed ) { 233 if (!m_opened || !m_changed ) {
200// qWarning("not saving"); 234// qWarning("not saving");
201 return true; 235 return true;
202 } 236 }
203 QString strNewFile = m_file + ".new"; 237 QString strNewFile = m_file + ".new";
204 QFile f( strNewFile ); 238 QFile f( strNewFile );
205 if (!f.open( IO_WriteOnly|IO_Raw ) ) 239 if (!f.open( IO_WriteOnly|IO_Raw ) )
206 return false; 240 return false;
207 241
208 int written; 242 int written;
209 QString out; 243 QString out;
210 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 244 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
211 245
212 // for all todos 246 // for all todos
213 QMap<int, OTodo>::Iterator it; 247 QMap<int, OTodo>::Iterator it;
214 for (it = m_events.begin(); it != m_events.end(); ++it ) { 248 for (it = m_events.begin(); it != m_events.end(); ++it ) {
215 out+= "<Task " + toString( (*it) ) + " />\n"; 249 out+= "<Task " + toString( (*it) ) + " />\n";
216 QCString cstr = out.utf8(); 250 QCString cstr = out.utf8();
217 written = f.writeBlock( cstr.data(), cstr.length() ); 251 written = f.writeBlock( cstr.data(), cstr.length() );
218 252
219 /* less written then we wanted */ 253 /* less written then we wanted */
220 if ( written != (int)cstr.length() ) { 254 if ( written != (int)cstr.length() ) {
221 f.close(); 255 f.close();
222 QFile::remove( strNewFile ); 256 QFile::remove( strNewFile );
223 return false; 257 return false;
224 } 258 }
225 out = QString::null; 259 out = QString::null;
226 } 260 }
227 261
228 out += "</Tasks>"; 262 out += "</Tasks>";
229 QCString cstr = out.utf8(); 263 QCString cstr = out.utf8();
230 written = f.writeBlock( cstr.data(), cstr.length() ); 264 written = f.writeBlock( cstr.data(), cstr.length() );
231 265
232 if ( written != (int)cstr.length() ) { 266 if ( written != (int)cstr.length() ) {
233 f.close(); 267 f.close();
234 QFile::remove( strNewFile ); 268 QFile::remove( strNewFile );
235 return false; 269 return false;
236 } 270 }
237 /* flush before renaming */ 271 /* flush before renaming */
238 f.close(); 272 f.close();
239 273
240 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 274 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
241// qWarning("error renaming"); 275// qWarning("error renaming");
242 QFile::remove( strNewFile ); 276 QFile::remove( strNewFile );
243 } 277 }
244 278
245 m_changed = false; 279 m_changed = false;
246 return true; 280 return true;
247} 281}
248QArray<int> OTodoAccessXML::allRecords()const { 282QArray<int> OTodoAccessXML::allRecords()const {
249 QArray<int> ids( m_events.count() ); 283 QArray<int> ids( m_events.count() );
250 QMap<int, OTodo>::ConstIterator it; 284 QMap<int, OTodo>::ConstIterator it;
251 int i = 0; 285 int i = 0;
252 286
253 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 287 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
254 ids[i] = it.key(); 288 ids[i] = it.key();
255 i++; 289 i++;
256 } 290 }
257 return ids; 291 return ids;
258} 292}
259QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) { 293QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
260 QArray<int> ids(0); 294 QArray<int> ids(0);
261 return ids; 295 return ids;
262} 296}
263OTodo OTodoAccessXML::find( int uid )const { 297OTodo OTodoAccessXML::find( int uid )const {
264 OTodo todo; 298 OTodo todo;
265 todo.setUid( 0 ); // isEmpty() 299 todo.setUid( 0 ); // isEmpty()
266 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 300 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
267 if ( it != m_events.end() ) 301 if ( it != m_events.end() )
268 todo = it.data(); 302 todo = it.data();
269 303
270 return todo; 304 return todo;
271} 305}
272void OTodoAccessXML::clear() { 306void OTodoAccessXML::clear() {
273 if (m_opened ) 307 if (m_opened )
274 m_changed = true; 308 m_changed = true;
275 309
276 m_events.clear(); 310 m_events.clear();
277} 311}
278bool OTodoAccessXML::add( const OTodo& todo ) { 312bool OTodoAccessXML::add( const OTodo& todo ) {
279// qWarning("add"); 313// qWarning("add");
280 m_changed = true; 314 m_changed = true;
281 m_events.insert( todo.uid(), todo ); 315 m_events.insert( todo.uid(), todo );
282 316
283 return true; 317 return true;
284} 318}
285bool OTodoAccessXML::remove( int uid ) { 319bool OTodoAccessXML::remove( int uid ) {
286 m_changed = true; 320 m_changed = true;
287 m_events.remove( uid ); 321 m_events.remove( uid );
288 322
289 return true; 323 return true;
290} 324}
291bool OTodoAccessXML::replace( const OTodo& todo) { 325bool OTodoAccessXML::replace( const OTodo& todo) {
292 m_changed = true; 326 m_changed = true;
293 m_events.replace( todo.uid(), todo ); 327 m_events.replace( todo.uid(), todo );
294 328
295 return true; 329 return true;
296} 330}
297QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 331QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
298 const QDate& end, 332 const QDate& end,
299 bool includeNoDates ) { 333 bool includeNoDates ) {
300 QArray<int> ids( m_events.count() ); 334 QArray<int> ids( m_events.count() );
301 QMap<int, OTodo>::Iterator it; 335 QMap<int, OTodo>::Iterator it;
302 336
303 int i = 0; 337 int i = 0;
304 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 338 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
305 if ( !it.data().hasDueDate() ) { 339 if ( !it.data().hasDueDate() ) {
306 if ( includeNoDates ) { 340 if ( includeNoDates ) {
307 ids[i] = it.key(); 341 ids[i] = it.key();
308 i++; 342 i++;
309 } 343 }
310 }else if ( it.data().dueDate() >= start && 344 }else if ( it.data().dueDate() >= start &&
311 it.data().dueDate() <= end ) { 345 it.data().dueDate() <= end ) {
312 ids[i] = it.key(); 346 ids[i] = it.key();
313 i++; 347 i++;
314 } 348 }
315 } 349 }
316 ids.resize( i ); 350 ids.resize( i );
317 return ids; 351 return ids;
318} 352}
319QArray<int> OTodoAccessXML::overDue() { 353QArray<int> OTodoAccessXML::overDue() {
320 QArray<int> ids( m_events.count() ); 354 QArray<int> ids( m_events.count() );
321 int i = 0; 355 int i = 0;
322 356
323 QMap<int, OTodo>::Iterator it; 357 QMap<int, OTodo>::Iterator it;
324 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 358 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
325 if ( it.data().isOverdue() ) { 359 if ( it.data().isOverdue() ) {
326 ids[i] = it.key(); 360 ids[i] = it.key();
327 i++; 361 i++;
328 } 362 }
329 } 363 }
330 ids.resize( i ); 364 ids.resize( i );
331 return ids; 365 return ids;
332} 366}
333 367
334 368
335/* private */ 369/* private */
336void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 370void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
337 const QCString& attr, const QString& val) { 371 const QCString& attr, const QString& val) {
338// qWarning("parse to do from XMLElement" ); 372// qWarning("parse to do from XMLElement" );
339 373
340 int *find=0; 374 int *find=0;
341 375
342 find = (*dict)[ attr.data() ]; 376 find = (*dict)[ attr.data() ];
343 if (!find ) { 377 if (!find ) {
344// qWarning("Unknown option" + it.key() ); 378// qWarning("Unknown option" + it.key() );
345 ev.setCustomField( attr, val ); 379 ev.setCustomField( attr, val );
346 return; 380 return;
347 } 381 }
348 382
349 switch( *find ) { 383 switch( *find ) {
350 case OTodo::Uid: 384 case OTodo::Uid:
351 ev.setUid( val.toInt() ); 385 ev.setUid( val.toInt() );
352 break; 386 break;
353 case OTodo::Category: 387 case OTodo::Category:
354 ev.setCategories( ev.idsFromString( val ) ); 388 ev.setCategories( ev.idsFromString( val ) );
355 break; 389 break;
356 case OTodo::HasDate: 390 case OTodo::HasDate:
357 ev.setHasDueDate( val.toInt() ); 391 ev.setHasDueDate( val.toInt() );
358 break; 392 break;
359 case OTodo::Completed: 393 case OTodo::Completed:
360 ev.setCompleted( val.toInt() ); 394 ev.setCompleted( val.toInt() );
361 break; 395 break;
362 case OTodo::Description: 396 case OTodo::Description:
363 ev.setDescription( val ); 397 ev.setDescription( val );
364 break; 398 break;
365 case OTodo::Summary: 399 case OTodo::Summary:
366 ev.setSummary( val ); 400 ev.setSummary( val );
367 break; 401 break;
368 case OTodo::Priority: 402 case OTodo::Priority:
369 ev.setPriority( val.toInt() ); 403 ev.setPriority( val.toInt() );
370 break; 404 break;
371 case OTodo::DateDay: 405 case OTodo::DateDay:
372 m_day = val.toInt(); 406 m_day = val.toInt();
373 break; 407 break;
374 case OTodo::DateMonth: 408 case OTodo::DateMonth:
375 m_month = val.toInt(); 409 m_month = val.toInt();
376 break; 410 break;
377 case OTodo::DateYear: 411 case OTodo::DateYear:
378 m_year = val.toInt(); 412 m_year = val.toInt();
379 break; 413 break;
380 case OTodo::Progress: 414 case OTodo::Progress:
381 ev.setProgress( val.toInt() ); 415 ev.setProgress( val.toInt() );
382 break; 416 break;
383 case OTodo::CrossReference: 417 case OTodo::CrossReference:
384 { 418 {
385 /* 419 /*
386 * A cross refernce looks like 420 * A cross refernce looks like
387 * appname,id;appname,id 421 * appname,id;appname,id
388 * we need to split it up 422 * we need to split it up
389 */ 423 */
390 QStringList refs = QStringList::split(';', val ); 424 QStringList refs = QStringList::split(';', val );
391 QStringList::Iterator strIt; 425 QStringList::Iterator strIt;
392 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 426 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
393 int pos = (*strIt).find(','); 427 int pos = (*strIt).find(',');
394 if ( pos > -1 ) 428 if ( pos > -1 )
395 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); 429 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
396 430
397 } 431 }
398 break; 432 break;
399 } 433 }
434 /* Recurrence stuff below + post processing later */
435 case FRType:
436 if ( val == "Daily" )
437 recur()->setType( ORecur::Daily );
438 else if ( val == "Weekly" )
439 recur()->setType( ORecur::Weekly);
440 else if ( val == "MonthlyDay" )
441 recur()->setType( ORecur::MonthlyDay );
442 else if ( val == "MonthlyDate" )
443 recur()->setType( ORecur::MonthlyDate );
444 else if ( val == "Yearly" )
445 recur()->setType( ORecur::Yearly );
446 else
447 recur()->setType( ORecur::NoRepeat );
448 break;
449 case FRWeekdays:
450 recur()->setDays( val.toInt() );
451 break;
452 case FRPosition:
453 recur()->setPosition( val.toInt() );
454 break;
455 case FRFreq:
456 recur()->setFrequency( val.toInt() );
457 break;
458 case FRHasEndDate:
459 recur()->setHasEndDate( val.toInt() );
460 break;
461 case FREndDate: {
462 rp_end = (time_t) val.toLong();
463 break;
464 }
400 default: 465 default:
401 break; 466 break;
402 } 467 }
403} 468}
404QString OTodoAccessXML::toString( const OTodo& ev )const { 469QString OTodoAccessXML::toString( const OTodo& ev )const {
405 QString str; 470 QString str;
406 471
407 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 472 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
408 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 473 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
409 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 474 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
410 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 475 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
411 476
412 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 477 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
413 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 478 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
414 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 479 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
415 480
416 if ( ev.hasDueDate() ) { 481 if ( ev.hasDueDate() ) {
417 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 482 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
418 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 483 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
419 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 484 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
420 } 485 }
421// qWarning( "Uid %d", ev.uid() ); 486// qWarning( "Uid %d", ev.uid() );
422 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 487 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
423 488
424// append the extra options 489// append the extra options
425 /* FIXME Qtopia::Record this is currently not 490 /* FIXME Qtopia::Record this is currently not
426 * possible you can set custom fields 491 * possible you can set custom fields
427 * but don' iterate over the list 492 * but don' iterate over the list
428 * I may do #define private protected 493 * I may do #define private protected
429 * for this case - cough --zecke 494 * for this case - cough --zecke
430 */ 495 */
431 /* 496 /*
432 QMap<QString, QString> extras = ev.extras(); 497 QMap<QString, QString> extras = ev.extras();
433 QMap<QString, QString>::Iterator extIt; 498 QMap<QString, QString>::Iterator extIt;
434 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 499 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
435 str += extIt.key() + "=\"" + extIt.data() + "\" "; 500 str += extIt.key() + "=\"" + extIt.data() + "\" ";
436 */ 501 */
437 // cross refernce 502 // cross refernce
438 if ( ev.hasRecurrence() ) 503 if ( ev.hasRecurrence() ) {
439 str += ev.recurrence().toString(); 504 str += ev.recurrence().toString();
505 }
440 506
441 return str; 507 return str;
442} 508}
443QString OTodoAccessXML::toString( const QArray<int>& ints ) const { 509QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
444 return Qtopia::Record::idsToString( ints ); 510 return Qtopia::Record::idsToString( ints );
445} 511}
446 512
447/* internal class for sorting 513/* internal class for sorting
448 * 514 *
449 * Inspired by todoxmlio.cpp from TT 515 * Inspired by todoxmlio.cpp from TT
450 */ 516 */
451 517
452struct OTodoXMLContainer { 518struct OTodoXMLContainer {
453 OTodo todo; 519 OTodo todo;
454}; 520};
455 521
456namespace { 522namespace {
457 inline QString string( const OTodo& todo) { 523 inline QString string( const OTodo& todo) {
458 return todo.summary().isEmpty() ? 524 return todo.summary().isEmpty() ?
459 todo.description().left(20 ) : 525 todo.description().left(20 ) :
460 todo.summary(); 526 todo.summary();
461 } 527 }
462 inline int completed( const OTodo& todo1, const OTodo& todo2) { 528 inline int completed( const OTodo& todo1, const OTodo& todo2) {
463 int ret = 0; 529 int ret = 0;
464 if ( todo1.isCompleted() ) ret++; 530 if ( todo1.isCompleted() ) ret++;
465 if ( todo2.isCompleted() ) ret--; 531 if ( todo2.isCompleted() ) ret--;
466 return ret; 532 return ret;
467 } 533 }
468 inline int priority( const OTodo& t1, const OTodo& t2) { 534 inline int priority( const OTodo& t1, const OTodo& t2) {
469 return ( t1.priority() - t2.priority() ); 535 return ( t1.priority() - t2.priority() );
470 } 536 }
471 inline int description( const OTodo& t1, const OTodo& t2) { 537 inline int description( const OTodo& t1, const OTodo& t2) {
472 return QString::compare( string(t1), string(t2) ); 538 return QString::compare( string(t1), string(t2) );
473 } 539 }
474 inline int deadline( const OTodo& t1, const OTodo& t2) { 540 inline int deadline( const OTodo& t1, const OTodo& t2) {
475 int ret = 0; 541 int ret = 0;
476 if ( t1.hasDueDate() && 542 if ( t1.hasDueDate() &&
477 t2.hasDueDate() ) 543 t2.hasDueDate() )
478 ret = t2.dueDate().daysTo( t1.dueDate() ); 544 ret = t2.dueDate().daysTo( t1.dueDate() );
479 else if ( t1.hasDueDate() ) 545 else if ( t1.hasDueDate() )
480 ret = -1; 546 ret = -1;
481 else if ( t2.hasDueDate() ) 547 else if ( t2.hasDueDate() )
482 ret = 1; 548 ret = 1;
483 else 549 else
484 ret = 0; 550 ret = 0;
485 551
486 return ret; 552 return ret;
487 } 553 }
488 554
489}; 555};
490 556
491/* 557/*
492 * Returns: 558 * Returns:
493 * 0 if item1 == item2 559 * 0 if item1 == item2
494 * 560 *
495 * non-zero if item1 != item2 561 * non-zero if item1 != item2
496 * 562 *
497 * This function returns int rather than bool so that reimplementations 563 * This function returns int rather than bool so that reimplementations
498 * can return one of three values and use it to sort by: 564 * can return one of three values and use it to sort by:
499 * 565 *
500 * 0 if item1 == item2 566 * 0 if item1 == item2
501 * 567 *
502 * > 0 (positive integer) if item1 > item2 568 * > 0 (positive integer) if item1 > item2
503 * 569 *
504 * < 0 (negative integer) if item1 < item2 570 * < 0 (negative integer) if item1 < item2
505 * 571 *
506 */ 572 */
507class OTodoXMLVector : public QVector<OTodoXMLContainer> { 573class OTodoXMLVector : public QVector<OTodoXMLContainer> {
508public: 574public:
509 OTodoXMLVector(int size, bool asc, int sort) 575 OTodoXMLVector(int size, bool asc, int sort)
510 : QVector<OTodoXMLContainer>( size ) 576 : QVector<OTodoXMLContainer>( size )
511 { 577 {
512 setAutoDelete( true ); 578 setAutoDelete( true );
513 m_asc = asc; 579 m_asc = asc;
514 m_sort = sort; 580 m_sort = sort;
515 } 581 }
516 /* return the summary/description */ 582 /* return the summary/description */
517 QString string( const OTodo& todo) { 583 QString string( const OTodo& todo) {
518 return todo.summary().isEmpty() ? 584 return todo.summary().isEmpty() ?
519 todo.description().left(20 ) : 585 todo.description().left(20 ) :
520 todo.summary(); 586 todo.summary();
521 } 587 }
522 /** 588 /**
523 * we take the sortorder( switch on it ) 589 * we take the sortorder( switch on it )
524 * 590 *
525 */ 591 */
526 int compareItems( Item d1, Item d2 ) { 592 int compareItems( Item d1, Item d2 ) {
527 bool seComp, sePrio, seDesc, seDeadline; 593 bool seComp, sePrio, seDesc, seDeadline;
528 seComp = sePrio = seDeadline = seDesc = false; 594 seComp = sePrio = seDeadline = seDesc = false;
529 int ret =0; 595 int ret =0;
530 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; 596 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
531 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; 597 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
532 598
533 /* same item */ 599 /* same item */
534 if ( con1->todo.uid() == con2->todo.uid() ) 600 if ( con1->todo.uid() == con2->todo.uid() )
535 return 0; 601 return 0;
536 602
537 switch ( m_sort ) { 603 switch ( m_sort ) {
538 /* completed */ 604 /* completed */
539 case 0: { 605 case 0: {
540 ret = completed( con1->todo, con2->todo ); 606 ret = completed( con1->todo, con2->todo );
541 seComp = TRUE; 607 seComp = TRUE;
542 break; 608 break;
543 } 609 }
544 /* priority */ 610 /* priority */
545 case 1: { 611 case 1: {
546 ret = priority( con1->todo, con2->todo ); 612 ret = priority( con1->todo, con2->todo );
547 sePrio = TRUE; 613 sePrio = TRUE;
548 break; 614 break;
549 } 615 }
550 /* description */ 616 /* description */
551 case 2: { 617 case 2: {
552 ret = description( con1->todo, con2->todo ); 618 ret = description( con1->todo, con2->todo );
553 seDesc = TRUE; 619 seDesc = TRUE;
554 break; 620 break;
555 } 621 }
556 /* deadline */ 622 /* deadline */
557 case 3: { 623 case 3: {
558 ret = deadline( con1->todo, con2->todo ); 624 ret = deadline( con1->todo, con2->todo );
559 seDeadline = TRUE; 625 seDeadline = TRUE;
560 break; 626 break;
561 } 627 }
562 default: 628 default:
563 ret = 0; 629 ret = 0;
564 break; 630 break;
565 }; 631 };
566 /* 632 /*
567 * FIXME do better sorting if the first sort criteria 633 * FIXME do better sorting if the first sort criteria
568 * ret equals 0 start with complete and so on... 634 * ret equals 0 start with complete and so on...
569 */ 635 */
570 636
571 /* twist it we're not ascending*/ 637 /* twist it we're not ascending*/
572 if (!m_asc) 638 if (!m_asc)
573 ret = ret * -1; 639 ret = ret * -1;
574 640
575 if ( ret ) 641 if ( ret )
576 return ret; 642 return ret;
577 643
578 // default did not gave difference let's try it other way around 644 // default did not gave difference let's try it other way around
579 /* 645 /*
580 * General try if already checked if not test 646 * General try if already checked if not test
581 * and return 647 * and return
582 * 1.Completed 648 * 1.Completed
583 * 2.Priority 649 * 2.Priority
584 * 3.Description 650 * 3.Description
585 * 4.DueDate 651 * 4.DueDate
586 */ 652 */
587 if (!seComp ) { 653 if (!seComp ) {
588 if ( (ret = completed( con1->todo, con2->todo ) ) ) { 654 if ( (ret = completed( con1->todo, con2->todo ) ) ) {
589 if (!m_asc ) ret *= -1; 655 if (!m_asc ) ret *= -1;
590 return ret; 656 return ret;
591 } 657 }
592 } 658 }
593 if (!sePrio ) { 659 if (!sePrio ) {
594 if ( (ret = priority( con1->todo, con2->todo ) ) ) { 660 if ( (ret = priority( con1->todo, con2->todo ) ) ) {
595 if (!m_asc ) ret *= -1; 661 if (!m_asc ) ret *= -1;
596 return ret; 662 return ret;
597 } 663 }
598 } 664 }
599 if (!seDesc ) { 665 if (!seDesc ) {
600 if ( (ret = description(con1->todo, con2->todo ) ) ) { 666 if ( (ret = description(con1->todo, con2->todo ) ) ) {
601 if (!m_asc) ret *= -1; 667 if (!m_asc) ret *= -1;
602 return ret; 668 return ret;
603 } 669 }
604 } 670 }
605 if (!seDeadline) { 671 if (!seDeadline) {
606 if ( (ret = deadline( con1->todo, con2->todo ) ) ) { 672 if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
607 if (!m_asc) ret *= -1; 673 if (!m_asc) ret *= -1;
608 return ret; 674 return ret;
609 } 675 }
610 } 676 }
611 677
612 return 0; 678 return 0;
613 } 679 }
614 private: 680 private:
615 bool m_asc; 681 bool m_asc;
616 int m_sort; 682 int m_sort;
617 683
618}; 684};
619 685
620QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, 686QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
621 int sortFilter, int cat ) { 687 int sortFilter, int cat ) {
622 qWarning("sorted! %d cat", cat); 688 qWarning("sorted! %d cat", cat);
623 OTodoXMLVector vector(m_events.count(), asc,sortOrder ); 689 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
624 QMap<int, OTodo>::Iterator it; 690 QMap<int, OTodo>::Iterator it;
625 int item = 0; 691 int item = 0;
626 692
627 bool bCat = sortFilter & 1 ? true : false; 693 bool bCat = sortFilter & 1 ? true : false;
628 bool bOnly = sortFilter & 2 ? true : false; 694 bool bOnly = sortFilter & 2 ? true : false;
629 bool comp = sortFilter & 4 ? true : false; 695 bool comp = sortFilter & 4 ? true : false;
630 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 696 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
631 697
632 /* show category */ 698 /* show category */
633 if ( bCat && cat != 0) 699 if ( bCat && cat != 0)
634 if (!(*it).categories().contains( cat ) ) { 700 if (!(*it).categories().contains( cat ) ) {
635 qWarning("category mis match"); 701 qWarning("category mis match");
636 continue; 702 continue;
637 } 703 }
638 /* isOverdue but we should not show overdue - why?*/ 704 /* isOverdue but we should not show overdue - why?*/
639/* if ( (*it).isOverdue() && !bOnly ) { 705/* if ( (*it).isOverdue() && !bOnly ) {
640 qWarning("item is overdue but !bOnly"); 706 qWarning("item is overdue but !bOnly");
641 continue; 707 continue;
642 } 708 }
643*/ 709*/
644 if ( !(*it).isOverdue() && bOnly ) { 710 if ( !(*it).isOverdue() && bOnly ) {
645 qWarning("item is not overdue but bOnly checked"); 711 qWarning("item is not overdue but bOnly checked");
646 continue; 712 continue;
647 } 713 }
648 714
649 if ((*it).isCompleted() && comp ) { 715 if ((*it).isCompleted() && comp ) {
650 qWarning("completed continue!"); 716 qWarning("completed continue!");
651 continue; 717 continue;
652 } 718 }
653 719
654 720
655 OTodoXMLContainer* con = new OTodoXMLContainer(); 721 OTodoXMLContainer* con = new OTodoXMLContainer();
656 con->todo = (*it); 722 con->todo = (*it);
657 vector.insert(item, con ); 723 vector.insert(item, con );
658 item++; 724 item++;
659 } 725 }
660 qWarning("XXX %d Items added", item); 726 qWarning("XXX %d Items added", item);
661 vector.resize( item ); 727 vector.resize( item );
662 /* sort it now */ 728 /* sort it now */
663 vector.sort(); 729 vector.sort();
664 /* now get the uids */ 730 /* now get the uids */
665 QArray<int> array( vector.count() ); 731 QArray<int> array( vector.count() );
666 for (uint i= 0; i < vector.count(); i++ ) { 732 for (uint i= 0; i < vector.count(); i++ ) {
667 array[i] = ( vector.at(i) )->todo.uid(); 733 array[i] = ( vector.at(i) )->todo.uid();
668 } 734 }
669 return array; 735 return array;
670}; 736};
671void OTodoAccessXML::removeAllCompleted() { 737void OTodoAccessXML::removeAllCompleted() {
672 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { 738 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
673 if ( (*it).isCompleted() ) 739 if ( (*it).isCompleted() )
674 m_events.remove( it ); 740 m_events.remove( it );
675 } 741 }
676} 742}
677QBitArray OTodoAccessXML::supports()const { 743QBitArray OTodoAccessXML::supports()const {
678 static QBitArray ar = sup(); 744 static QBitArray ar = sup();
679 return ar; 745 return ar;
680} 746}
681QBitArray OTodoAccessXML::sup() { 747QBitArray OTodoAccessXML::sup() {
682 QBitArray ar( OTodo::CompletedDate +1 ); 748 QBitArray ar( OTodo::CompletedDate +1 );
683 ar.fill( true ); 749 ar.fill( true );
684 ar[OTodo::CrossReference] = false; 750 ar[OTodo::CrossReference] = false;
685 ar[OTodo::State ] = false; 751 ar[OTodo::State ] = false;
686 ar[OTodo::Reminders] = false; 752 ar[OTodo::Reminders] = false;
687 ar[OTodo::Notifiers] = false; 753 ar[OTodo::Notifiers] = false;
688 ar[OTodo::Maintainer] = false; 754 ar[OTodo::Maintainer] = false;
689 755
690 return ar; 756 return ar;
691} 757}
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp
index c0d8dfc..71b6a7e 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.cpp
+++ b/libopie2/opiepim/backend/otodoaccessxml.cpp
@@ -1,691 +1,757 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <sys/mman.h> 4#include <sys/mman.h>
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/types.h> 6#include <sys/types.h>
7 7
8#include <unistd.h> 8#include <unistd.h>
9 9
10 10
11#include <qfile.h> 11#include <qfile.h>
12#include <qvector.h> 12#include <qvector.h>
13 13
14#include <qpe/global.h> 14#include <qpe/global.h>
15#include <qpe/stringutil.h> 15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h> 16#include <qpe/timeconversion.h>
17 17
18#include "otimezone.h"
18#include "orecur.h" 19#include "orecur.h"
19#include "otodoaccessxml.h" 20#include "otodoaccessxml.h"
20 21
21namespace { 22namespace {
23 time_t rp_end;
24 ORecur* rec;
25 ORecur *recur() {
26 if (!rec ) rec = new ORecur;
27 return rec;
28 }
29 int snd;
30 enum MoreAttributes {
31 FRType = OTodo::CompletedDate + 2,
32 FRWeekdays,
33 FRPosition,
34 FRFreq,
35 FRHasEndDate,
36 FREndDate,
37 FRStart,
38 FREnd
39 };
22 // FROM TT again 40 // FROM TT again
23char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) 41char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
24{ 42{
25 char needleChar; 43 char needleChar;
26 char haystackChar; 44 char haystackChar;
27 if (!needle || !haystack || !hLen || !nLen) 45 if (!needle || !haystack || !hLen || !nLen)
28 return 0; 46 return 0;
29 47
30 const char* hsearch = haystack; 48 const char* hsearch = haystack;
31 49
32 if ((needleChar = *needle++) != 0) { 50 if ((needleChar = *needle++) != 0) {
33 nLen--; //(to make up for needle++) 51 nLen--; //(to make up for needle++)
34 do { 52 do {
35 do { 53 do {
36 if ((haystackChar = *hsearch++) == 0) 54 if ((haystackChar = *hsearch++) == 0)
37 return (0); 55 return (0);
38 if (hsearch >= haystack + hLen) 56 if (hsearch >= haystack + hLen)
39 return (0); 57 return (0);
40 } while (haystackChar != needleChar); 58 } while (haystackChar != needleChar);
41 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); 59 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
42 hsearch--; 60 hsearch--;
43 } 61 }
44 return ((char *)hsearch); 62 return ((char *)hsearch);
45} 63}
46} 64}
47 65
48 66
49OTodoAccessXML::OTodoAccessXML( const QString& appName, 67OTodoAccessXML::OTodoAccessXML( const QString& appName,
50 const QString& fileName ) 68 const QString& fileName )
51 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 69 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
52{ 70{
53 if (!fileName.isEmpty() ) 71 if (!fileName.isEmpty() )
54 m_file = fileName; 72 m_file = fileName;
55 else 73 else
56 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 74 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
57} 75}
58OTodoAccessXML::~OTodoAccessXML() { 76OTodoAccessXML::~OTodoAccessXML() {
59 77
60} 78}
61bool OTodoAccessXML::load() { 79bool OTodoAccessXML::load() {
80 rec = 0;
62 m_opened = true; 81 m_opened = true;
63 m_changed = false; 82 m_changed = false;
64 /* initialize dict */ 83 /* initialize dict */
65 /* 84 /*
66 * UPDATE dict if you change anything!!! 85 * UPDATE dict if you change anything!!!
67 */ 86 */
68 QAsciiDict<int> dict(21); 87 QAsciiDict<int> dict(21);
69 dict.setAutoDelete( TRUE ); 88 dict.setAutoDelete( TRUE );
70 dict.insert("Categories" , new int(OTodo::Category) ); 89 dict.insert("Categories" , new int(OTodo::Category) );
71 dict.insert("Uid" , new int(OTodo::Uid) ); 90 dict.insert("Uid" , new int(OTodo::Uid) );
72 dict.insert("HasDate" , new int(OTodo::HasDate) ); 91 dict.insert("HasDate" , new int(OTodo::HasDate) );
73 dict.insert("Completed" , new int(OTodo::Completed) ); 92 dict.insert("Completed" , new int(OTodo::Completed) );
74 dict.insert("Description" , new int(OTodo::Description) ); 93 dict.insert("Description" , new int(OTodo::Description) );
75 dict.insert("Summary" , new int(OTodo::Summary) ); 94 dict.insert("Summary" , new int(OTodo::Summary) );
76 dict.insert("Priority" , new int(OTodo::Priority) ); 95 dict.insert("Priority" , new int(OTodo::Priority) );
77 dict.insert("DateDay" , new int(OTodo::DateDay) ); 96 dict.insert("DateDay" , new int(OTodo::DateDay) );
78 dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 97 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
79 dict.insert("DateYear" , new int(OTodo::DateYear) ); 98 dict.insert("DateYear" , new int(OTodo::DateYear) );
80 dict.insert("Progress" , new int(OTodo::Progress) ); 99 dict.insert("Progress" , new int(OTodo::Progress) );
81 dict.insert("Completed", new int(OTodo::Completed) ); 100 dict.insert("CompletedDate", new int(OTodo::CompletedDate) );
82 dict.insert("CrossReference", new int(OTodo::CrossReference) ); 101 dict.insert("CrossReference", new int(OTodo::CrossReference) );
83 dict.insert("State", new int(OTodo::State) ); 102 dict.insert("State", new int(OTodo::State) );
84 dict.insert("Recurrence", new int(OTodo::Recurrence) );
85 dict.insert("Alarms", new int(OTodo::Alarms) ); 103 dict.insert("Alarms", new int(OTodo::Alarms) );
86 dict.insert("Reminders", new int(OTodo::Reminders) ); 104 dict.insert("Reminders", new int(OTodo::Reminders) );
87 dict.insert("Notifiers", new int(OTodo::Notifiers) ); 105 dict.insert("Notifiers", new int(OTodo::Notifiers) );
88 dict.insert("Maintainer", new int(OTodo::Maintainer) ); 106 dict.insert("Maintainer", new int(OTodo::Maintainer) );
107 dict.insert("rtype", new int(FRType) );
108 dict.insert("rweekdays", new int(FRWeekdays) );
109 dict.insert("rposition", new int(FRPosition) );
110 dict.insert("rfreq", new int(FRFreq) );
111 dict.insert("start", new int(FRStart) );
112 dict.insert("rhasenddate", new int(FRHasEndDate) );
113 dict.insert("enddt", new int(FREndDate) );
89 114
90 // here the custom XML parser from TT it's GPL 115 // here the custom XML parser from TT it's GPL
91 // but we want to push OpiePIM... to TT..... 116 // but we want to push OpiePIM... to TT.....
92 // mmap part from zecke :) 117 // mmap part from zecke :)
93 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); 118 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
94 struct stat attribut; 119 struct stat attribut;
95 if ( fd < 0 ) return false; 120 if ( fd < 0 ) return false;
96 121
97 if ( fstat(fd, &attribut ) == -1 ) { 122 if ( fstat(fd, &attribut ) == -1 ) {
98 ::close( fd ); 123 ::close( fd );
99 return false; 124 return false;
100 } 125 }
101 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 126 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
102 if ( map_addr == ( (caddr_t)-1) ) { 127 if ( map_addr == ( (caddr_t)-1) ) {
103 ::close(fd ); 128 ::close(fd );
104 return false; 129 return false;
105 } 130 }
106 /* advise the kernel who we want to read it */ 131 /* advise the kernel who we want to read it */
107 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); 132 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
108 /* we do not the file any more */ 133 /* we do not the file any more */
109 ::close( fd ); 134 ::close( fd );
110 135
111 char* dt = (char*)map_addr; 136 char* dt = (char*)map_addr;
112 int len = attribut.st_size; 137 int len = attribut.st_size;
113 int i = 0; 138 int i = 0;
114 char *point; 139 char *point;
115 const char* collectionString = "<Task "; 140 const char* collectionString = "<Task ";
116 int strLen = strlen(collectionString); 141 int strLen = strlen(collectionString);
117 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) { 142 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
118 i = point -dt; 143 i = point -dt;
119 i+= strLen; 144 i+= strLen;
120 qWarning("Found a start at %d %d", i, (point-dt) ); 145 qWarning("Found a start at %d %d", i, (point-dt) );
121 146
122 OTodo ev; 147 OTodo ev;
123 m_year = m_month = m_day = 0; 148 m_year = m_month = m_day = 0;
124 149
125 while ( TRUE ) { 150 while ( TRUE ) {
126 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 151 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
127 ++i; 152 ++i;
128 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 153 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
129 break; 154 break;
130 155
131 // we have another attribute, read it. 156 // we have another attribute, read it.
132 int j = i; 157 int j = i;
133 while ( j < len && dt[j] != '=' ) 158 while ( j < len && dt[j] != '=' )
134 ++j; 159 ++j;
135 QCString attr( dt+i, j-i+1); 160 QCString attr( dt+i, j-i+1);
136 161
137 i = ++j; // skip = 162 i = ++j; // skip =
138 163
139 // find the start of quotes 164 // find the start of quotes
140 while ( i < len && dt[i] != '"' ) 165 while ( i < len && dt[i] != '"' )
141 ++i; 166 ++i;
142 j = ++i; 167 j = ++i;
143 168
144 bool haveUtf = FALSE; 169 bool haveUtf = FALSE;
145 bool haveEnt = FALSE; 170 bool haveEnt = FALSE;
146 while ( j < len && dt[j] != '"' ) { 171 while ( j < len && dt[j] != '"' ) {
147 if ( ((unsigned char)dt[j]) > 0x7f ) 172 if ( ((unsigned char)dt[j]) > 0x7f )
148 haveUtf = TRUE; 173 haveUtf = TRUE;
149 if ( dt[j] == '&' ) 174 if ( dt[j] == '&' )
150 haveEnt = TRUE; 175 haveEnt = TRUE;
151 ++j; 176 ++j;
152 } 177 }
153 if ( i == j ) { 178 if ( i == j ) {
154 // empty value 179 // empty value
155 i = j + 1; 180 i = j + 1;
156 continue; 181 continue;
157 } 182 }
158 183
159 QCString value( dt+i, j-i+1 ); 184 QCString value( dt+i, j-i+1 );
160 i = j + 1; 185 i = j + 1;
161 186
162 QString str = (haveUtf ? QString::fromUtf8( value ) 187 QString str = (haveUtf ? QString::fromUtf8( value )
163 : QString::fromLatin1( value ) ); 188 : QString::fromLatin1( value ) );
164 if ( haveEnt ) 189 if ( haveEnt )
165 str = Qtopia::plainString( str ); 190 str = Qtopia::plainString( str );
166 191
167 /* 192 /*
168 * add key + value 193 * add key + value
169 */ 194 */
170 todo( &dict, ev, attr, str ); 195 todo( &dict, ev, attr, str );
171 196
172 } 197 }
173 /* 198 /*
174 * now add it 199 * now add it
175 */ 200 */
176 qWarning("End at %d", i ); 201 qWarning("End at %d", i );
177 if (m_events.contains( ev.uid() ) || ev.uid() == 0) { 202 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
178 ev.setUid( 1 ); 203 ev.setUid( 1 );
179 m_changed = true; 204 m_changed = true;
180 } 205 }
181 if ( ev.hasDueDate() ) { 206 if ( ev.hasDueDate() ) {
182 ev.setDueDate( QDate(m_year, m_month, m_day) ); 207 ev.setDueDate( QDate(m_year, m_month, m_day) );
183 } 208 }
209 if ( rec && rec->doesRecur() ) {
210 OTimeZone utc = OTimeZone::utc();
211 ORecur recu( *rec ); // call copy c'tor
212 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
213 recu.setStart( ev.dueDate() );
214 ev.setRecurrence( recu );
215 }
184 m_events.insert(ev.uid(), ev ); 216 m_events.insert(ev.uid(), ev );
185 m_year = m_month = m_day = -1; 217 m_year = m_month = m_day = -1;
218 delete rec;
219 rec = 0;
186 } 220 }
187 221
188 munmap(map_addr, attribut.st_size ); 222 munmap(map_addr, attribut.st_size );
189 223
190 qWarning("counts %d records loaded!", m_events.count() ); 224 qWarning("counts %d records loaded!", m_events.count() );
191 return true; 225 return true;
192} 226}
193bool OTodoAccessXML::reload() { 227bool OTodoAccessXML::reload() {
194 m_events.clear(); 228 m_events.clear();
195 return load(); 229 return load();
196} 230}
197bool OTodoAccessXML::save() { 231bool OTodoAccessXML::save() {
198// qWarning("saving"); 232// qWarning("saving");
199 if (!m_opened || !m_changed ) { 233 if (!m_opened || !m_changed ) {
200// qWarning("not saving"); 234// qWarning("not saving");
201 return true; 235 return true;
202 } 236 }
203 QString strNewFile = m_file + ".new"; 237 QString strNewFile = m_file + ".new";
204 QFile f( strNewFile ); 238 QFile f( strNewFile );
205 if (!f.open( IO_WriteOnly|IO_Raw ) ) 239 if (!f.open( IO_WriteOnly|IO_Raw ) )
206 return false; 240 return false;
207 241
208 int written; 242 int written;
209 QString out; 243 QString out;
210 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 244 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
211 245
212 // for all todos 246 // for all todos
213 QMap<int, OTodo>::Iterator it; 247 QMap<int, OTodo>::Iterator it;
214 for (it = m_events.begin(); it != m_events.end(); ++it ) { 248 for (it = m_events.begin(); it != m_events.end(); ++it ) {
215 out+= "<Task " + toString( (*it) ) + " />\n"; 249 out+= "<Task " + toString( (*it) ) + " />\n";
216 QCString cstr = out.utf8(); 250 QCString cstr = out.utf8();
217 written = f.writeBlock( cstr.data(), cstr.length() ); 251 written = f.writeBlock( cstr.data(), cstr.length() );
218 252
219 /* less written then we wanted */ 253 /* less written then we wanted */
220 if ( written != (int)cstr.length() ) { 254 if ( written != (int)cstr.length() ) {
221 f.close(); 255 f.close();
222 QFile::remove( strNewFile ); 256 QFile::remove( strNewFile );
223 return false; 257 return false;
224 } 258 }
225 out = QString::null; 259 out = QString::null;
226 } 260 }
227 261
228 out += "</Tasks>"; 262 out += "</Tasks>";
229 QCString cstr = out.utf8(); 263 QCString cstr = out.utf8();
230 written = f.writeBlock( cstr.data(), cstr.length() ); 264 written = f.writeBlock( cstr.data(), cstr.length() );
231 265
232 if ( written != (int)cstr.length() ) { 266 if ( written != (int)cstr.length() ) {
233 f.close(); 267 f.close();
234 QFile::remove( strNewFile ); 268 QFile::remove( strNewFile );
235 return false; 269 return false;
236 } 270 }
237 /* flush before renaming */ 271 /* flush before renaming */
238 f.close(); 272 f.close();
239 273
240 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 274 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
241// qWarning("error renaming"); 275// qWarning("error renaming");
242 QFile::remove( strNewFile ); 276 QFile::remove( strNewFile );
243 } 277 }
244 278
245 m_changed = false; 279 m_changed = false;
246 return true; 280 return true;
247} 281}
248QArray<int> OTodoAccessXML::allRecords()const { 282QArray<int> OTodoAccessXML::allRecords()const {
249 QArray<int> ids( m_events.count() ); 283 QArray<int> ids( m_events.count() );
250 QMap<int, OTodo>::ConstIterator it; 284 QMap<int, OTodo>::ConstIterator it;
251 int i = 0; 285 int i = 0;
252 286
253 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 287 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
254 ids[i] = it.key(); 288 ids[i] = it.key();
255 i++; 289 i++;
256 } 290 }
257 return ids; 291 return ids;
258} 292}
259QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) { 293QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
260 QArray<int> ids(0); 294 QArray<int> ids(0);
261 return ids; 295 return ids;
262} 296}
263OTodo OTodoAccessXML::find( int uid )const { 297OTodo OTodoAccessXML::find( int uid )const {
264 OTodo todo; 298 OTodo todo;
265 todo.setUid( 0 ); // isEmpty() 299 todo.setUid( 0 ); // isEmpty()
266 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 300 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
267 if ( it != m_events.end() ) 301 if ( it != m_events.end() )
268 todo = it.data(); 302 todo = it.data();
269 303
270 return todo; 304 return todo;
271} 305}
272void OTodoAccessXML::clear() { 306void OTodoAccessXML::clear() {
273 if (m_opened ) 307 if (m_opened )
274 m_changed = true; 308 m_changed = true;
275 309
276 m_events.clear(); 310 m_events.clear();
277} 311}
278bool OTodoAccessXML::add( const OTodo& todo ) { 312bool OTodoAccessXML::add( const OTodo& todo ) {
279// qWarning("add"); 313// qWarning("add");
280 m_changed = true; 314 m_changed = true;
281 m_events.insert( todo.uid(), todo ); 315 m_events.insert( todo.uid(), todo );
282 316
283 return true; 317 return true;
284} 318}
285bool OTodoAccessXML::remove( int uid ) { 319bool OTodoAccessXML::remove( int uid ) {
286 m_changed = true; 320 m_changed = true;
287 m_events.remove( uid ); 321 m_events.remove( uid );
288 322
289 return true; 323 return true;
290} 324}
291bool OTodoAccessXML::replace( const OTodo& todo) { 325bool OTodoAccessXML::replace( const OTodo& todo) {
292 m_changed = true; 326 m_changed = true;
293 m_events.replace( todo.uid(), todo ); 327 m_events.replace( todo.uid(), todo );
294 328
295 return true; 329 return true;
296} 330}
297QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 331QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
298 const QDate& end, 332 const QDate& end,
299 bool includeNoDates ) { 333 bool includeNoDates ) {
300 QArray<int> ids( m_events.count() ); 334 QArray<int> ids( m_events.count() );
301 QMap<int, OTodo>::Iterator it; 335 QMap<int, OTodo>::Iterator it;
302 336
303 int i = 0; 337 int i = 0;
304 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 338 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
305 if ( !it.data().hasDueDate() ) { 339 if ( !it.data().hasDueDate() ) {
306 if ( includeNoDates ) { 340 if ( includeNoDates ) {
307 ids[i] = it.key(); 341 ids[i] = it.key();
308 i++; 342 i++;
309 } 343 }
310 }else if ( it.data().dueDate() >= start && 344 }else if ( it.data().dueDate() >= start &&
311 it.data().dueDate() <= end ) { 345 it.data().dueDate() <= end ) {
312 ids[i] = it.key(); 346 ids[i] = it.key();
313 i++; 347 i++;
314 } 348 }
315 } 349 }
316 ids.resize( i ); 350 ids.resize( i );
317 return ids; 351 return ids;
318} 352}
319QArray<int> OTodoAccessXML::overDue() { 353QArray<int> OTodoAccessXML::overDue() {
320 QArray<int> ids( m_events.count() ); 354 QArray<int> ids( m_events.count() );
321 int i = 0; 355 int i = 0;
322 356
323 QMap<int, OTodo>::Iterator it; 357 QMap<int, OTodo>::Iterator it;
324 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 358 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
325 if ( it.data().isOverdue() ) { 359 if ( it.data().isOverdue() ) {
326 ids[i] = it.key(); 360 ids[i] = it.key();
327 i++; 361 i++;
328 } 362 }
329 } 363 }
330 ids.resize( i ); 364 ids.resize( i );
331 return ids; 365 return ids;
332} 366}
333 367
334 368
335/* private */ 369/* private */
336void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 370void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
337 const QCString& attr, const QString& val) { 371 const QCString& attr, const QString& val) {
338// qWarning("parse to do from XMLElement" ); 372// qWarning("parse to do from XMLElement" );
339 373
340 int *find=0; 374 int *find=0;
341 375
342 find = (*dict)[ attr.data() ]; 376 find = (*dict)[ attr.data() ];
343 if (!find ) { 377 if (!find ) {
344// qWarning("Unknown option" + it.key() ); 378// qWarning("Unknown option" + it.key() );
345 ev.setCustomField( attr, val ); 379 ev.setCustomField( attr, val );
346 return; 380 return;
347 } 381 }
348 382
349 switch( *find ) { 383 switch( *find ) {
350 case OTodo::Uid: 384 case OTodo::Uid:
351 ev.setUid( val.toInt() ); 385 ev.setUid( val.toInt() );
352 break; 386 break;
353 case OTodo::Category: 387 case OTodo::Category:
354 ev.setCategories( ev.idsFromString( val ) ); 388 ev.setCategories( ev.idsFromString( val ) );
355 break; 389 break;
356 case OTodo::HasDate: 390 case OTodo::HasDate:
357 ev.setHasDueDate( val.toInt() ); 391 ev.setHasDueDate( val.toInt() );
358 break; 392 break;
359 case OTodo::Completed: 393 case OTodo::Completed:
360 ev.setCompleted( val.toInt() ); 394 ev.setCompleted( val.toInt() );
361 break; 395 break;
362 case OTodo::Description: 396 case OTodo::Description:
363 ev.setDescription( val ); 397 ev.setDescription( val );
364 break; 398 break;
365 case OTodo::Summary: 399 case OTodo::Summary:
366 ev.setSummary( val ); 400 ev.setSummary( val );
367 break; 401 break;
368 case OTodo::Priority: 402 case OTodo::Priority:
369 ev.setPriority( val.toInt() ); 403 ev.setPriority( val.toInt() );
370 break; 404 break;
371 case OTodo::DateDay: 405 case OTodo::DateDay:
372 m_day = val.toInt(); 406 m_day = val.toInt();
373 break; 407 break;
374 case OTodo::DateMonth: 408 case OTodo::DateMonth:
375 m_month = val.toInt(); 409 m_month = val.toInt();
376 break; 410 break;
377 case OTodo::DateYear: 411 case OTodo::DateYear:
378 m_year = val.toInt(); 412 m_year = val.toInt();
379 break; 413 break;
380 case OTodo::Progress: 414 case OTodo::Progress:
381 ev.setProgress( val.toInt() ); 415 ev.setProgress( val.toInt() );
382 break; 416 break;
383 case OTodo::CrossReference: 417 case OTodo::CrossReference:
384 { 418 {
385 /* 419 /*
386 * A cross refernce looks like 420 * A cross refernce looks like
387 * appname,id;appname,id 421 * appname,id;appname,id
388 * we need to split it up 422 * we need to split it up
389 */ 423 */
390 QStringList refs = QStringList::split(';', val ); 424 QStringList refs = QStringList::split(';', val );
391 QStringList::Iterator strIt; 425 QStringList::Iterator strIt;
392 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 426 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
393 int pos = (*strIt).find(','); 427 int pos = (*strIt).find(',');
394 if ( pos > -1 ) 428 if ( pos > -1 )
395 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); 429 ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
396 430
397 } 431 }
398 break; 432 break;
399 } 433 }
434 /* Recurrence stuff below + post processing later */
435 case FRType:
436 if ( val == "Daily" )
437 recur()->setType( ORecur::Daily );
438 else if ( val == "Weekly" )
439 recur()->setType( ORecur::Weekly);
440 else if ( val == "MonthlyDay" )
441 recur()->setType( ORecur::MonthlyDay );
442 else if ( val == "MonthlyDate" )
443 recur()->setType( ORecur::MonthlyDate );
444 else if ( val == "Yearly" )
445 recur()->setType( ORecur::Yearly );
446 else
447 recur()->setType( ORecur::NoRepeat );
448 break;
449 case FRWeekdays:
450 recur()->setDays( val.toInt() );
451 break;
452 case FRPosition:
453 recur()->setPosition( val.toInt() );
454 break;
455 case FRFreq:
456 recur()->setFrequency( val.toInt() );
457 break;
458 case FRHasEndDate:
459 recur()->setHasEndDate( val.toInt() );
460 break;
461 case FREndDate: {
462 rp_end = (time_t) val.toLong();
463 break;
464 }
400 default: 465 default:
401 break; 466 break;
402 } 467 }
403} 468}
404QString OTodoAccessXML::toString( const OTodo& ev )const { 469QString OTodoAccessXML::toString( const OTodo& ev )const {
405 QString str; 470 QString str;
406 471
407 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 472 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
408 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 473 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
409 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 474 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
410 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 475 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
411 476
412 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 477 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
413 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 478 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
414 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 479 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
415 480
416 if ( ev.hasDueDate() ) { 481 if ( ev.hasDueDate() ) {
417 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 482 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
418 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 483 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
419 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 484 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
420 } 485 }
421// qWarning( "Uid %d", ev.uid() ); 486// qWarning( "Uid %d", ev.uid() );
422 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 487 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
423 488
424// append the extra options 489// append the extra options
425 /* FIXME Qtopia::Record this is currently not 490 /* FIXME Qtopia::Record this is currently not
426 * possible you can set custom fields 491 * possible you can set custom fields
427 * but don' iterate over the list 492 * but don' iterate over the list
428 * I may do #define private protected 493 * I may do #define private protected
429 * for this case - cough --zecke 494 * for this case - cough --zecke
430 */ 495 */
431 /* 496 /*
432 QMap<QString, QString> extras = ev.extras(); 497 QMap<QString, QString> extras = ev.extras();
433 QMap<QString, QString>::Iterator extIt; 498 QMap<QString, QString>::Iterator extIt;
434 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 499 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
435 str += extIt.key() + "=\"" + extIt.data() + "\" "; 500 str += extIt.key() + "=\"" + extIt.data() + "\" ";
436 */ 501 */
437 // cross refernce 502 // cross refernce
438 if ( ev.hasRecurrence() ) 503 if ( ev.hasRecurrence() ) {
439 str += ev.recurrence().toString(); 504 str += ev.recurrence().toString();
505 }
440 506
441 return str; 507 return str;
442} 508}
443QString OTodoAccessXML::toString( const QArray<int>& ints ) const { 509QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
444 return Qtopia::Record::idsToString( ints ); 510 return Qtopia::Record::idsToString( ints );
445} 511}
446 512
447/* internal class for sorting 513/* internal class for sorting
448 * 514 *
449 * Inspired by todoxmlio.cpp from TT 515 * Inspired by todoxmlio.cpp from TT
450 */ 516 */
451 517
452struct OTodoXMLContainer { 518struct OTodoXMLContainer {
453 OTodo todo; 519 OTodo todo;
454}; 520};
455 521
456namespace { 522namespace {
457 inline QString string( const OTodo& todo) { 523 inline QString string( const OTodo& todo) {
458 return todo.summary().isEmpty() ? 524 return todo.summary().isEmpty() ?
459 todo.description().left(20 ) : 525 todo.description().left(20 ) :
460 todo.summary(); 526 todo.summary();
461 } 527 }
462 inline int completed( const OTodo& todo1, const OTodo& todo2) { 528 inline int completed( const OTodo& todo1, const OTodo& todo2) {
463 int ret = 0; 529 int ret = 0;
464 if ( todo1.isCompleted() ) ret++; 530 if ( todo1.isCompleted() ) ret++;
465 if ( todo2.isCompleted() ) ret--; 531 if ( todo2.isCompleted() ) ret--;
466 return ret; 532 return ret;
467 } 533 }
468 inline int priority( const OTodo& t1, const OTodo& t2) { 534 inline int priority( const OTodo& t1, const OTodo& t2) {
469 return ( t1.priority() - t2.priority() ); 535 return ( t1.priority() - t2.priority() );
470 } 536 }
471 inline int description( const OTodo& t1, const OTodo& t2) { 537 inline int description( const OTodo& t1, const OTodo& t2) {
472 return QString::compare( string(t1), string(t2) ); 538 return QString::compare( string(t1), string(t2) );
473 } 539 }
474 inline int deadline( const OTodo& t1, const OTodo& t2) { 540 inline int deadline( const OTodo& t1, const OTodo& t2) {
475 int ret = 0; 541 int ret = 0;
476 if ( t1.hasDueDate() && 542 if ( t1.hasDueDate() &&
477 t2.hasDueDate() ) 543 t2.hasDueDate() )
478 ret = t2.dueDate().daysTo( t1.dueDate() ); 544 ret = t2.dueDate().daysTo( t1.dueDate() );
479 else if ( t1.hasDueDate() ) 545 else if ( t1.hasDueDate() )
480 ret = -1; 546 ret = -1;
481 else if ( t2.hasDueDate() ) 547 else if ( t2.hasDueDate() )
482 ret = 1; 548 ret = 1;
483 else 549 else
484 ret = 0; 550 ret = 0;
485 551
486 return ret; 552 return ret;
487 } 553 }
488 554
489}; 555};
490 556
491/* 557/*
492 * Returns: 558 * Returns:
493 * 0 if item1 == item2 559 * 0 if item1 == item2
494 * 560 *
495 * non-zero if item1 != item2 561 * non-zero if item1 != item2
496 * 562 *
497 * This function returns int rather than bool so that reimplementations 563 * This function returns int rather than bool so that reimplementations
498 * can return one of three values and use it to sort by: 564 * can return one of three values and use it to sort by:
499 * 565 *
500 * 0 if item1 == item2 566 * 0 if item1 == item2
501 * 567 *
502 * > 0 (positive integer) if item1 > item2 568 * > 0 (positive integer) if item1 > item2
503 * 569 *
504 * < 0 (negative integer) if item1 < item2 570 * < 0 (negative integer) if item1 < item2
505 * 571 *
506 */ 572 */
507class OTodoXMLVector : public QVector<OTodoXMLContainer> { 573class OTodoXMLVector : public QVector<OTodoXMLContainer> {
508public: 574public:
509 OTodoXMLVector(int size, bool asc, int sort) 575 OTodoXMLVector(int size, bool asc, int sort)
510 : QVector<OTodoXMLContainer>( size ) 576 : QVector<OTodoXMLContainer>( size )
511 { 577 {
512 setAutoDelete( true ); 578 setAutoDelete( true );
513 m_asc = asc; 579 m_asc = asc;
514 m_sort = sort; 580 m_sort = sort;
515 } 581 }
516 /* return the summary/description */ 582 /* return the summary/description */
517 QString string( const OTodo& todo) { 583 QString string( const OTodo& todo) {
518 return todo.summary().isEmpty() ? 584 return todo.summary().isEmpty() ?
519 todo.description().left(20 ) : 585 todo.description().left(20 ) :
520 todo.summary(); 586 todo.summary();
521 } 587 }
522 /** 588 /**
523 * we take the sortorder( switch on it ) 589 * we take the sortorder( switch on it )
524 * 590 *
525 */ 591 */
526 int compareItems( Item d1, Item d2 ) { 592 int compareItems( Item d1, Item d2 ) {
527 bool seComp, sePrio, seDesc, seDeadline; 593 bool seComp, sePrio, seDesc, seDeadline;
528 seComp = sePrio = seDeadline = seDesc = false; 594 seComp = sePrio = seDeadline = seDesc = false;
529 int ret =0; 595 int ret =0;
530 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; 596 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
531 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; 597 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
532 598
533 /* same item */ 599 /* same item */
534 if ( con1->todo.uid() == con2->todo.uid() ) 600 if ( con1->todo.uid() == con2->todo.uid() )
535 return 0; 601 return 0;
536 602
537 switch ( m_sort ) { 603 switch ( m_sort ) {
538 /* completed */ 604 /* completed */
539 case 0: { 605 case 0: {
540 ret = completed( con1->todo, con2->todo ); 606 ret = completed( con1->todo, con2->todo );
541 seComp = TRUE; 607 seComp = TRUE;
542 break; 608 break;
543 } 609 }
544 /* priority */ 610 /* priority */
545 case 1: { 611 case 1: {
546 ret = priority( con1->todo, con2->todo ); 612 ret = priority( con1->todo, con2->todo );
547 sePrio = TRUE; 613 sePrio = TRUE;
548 break; 614 break;
549 } 615 }
550 /* description */ 616 /* description */
551 case 2: { 617 case 2: {
552 ret = description( con1->todo, con2->todo ); 618 ret = description( con1->todo, con2->todo );
553 seDesc = TRUE; 619 seDesc = TRUE;
554 break; 620 break;
555 } 621 }
556 /* deadline */ 622 /* deadline */
557 case 3: { 623 case 3: {
558 ret = deadline( con1->todo, con2->todo ); 624 ret = deadline( con1->todo, con2->todo );
559 seDeadline = TRUE; 625 seDeadline = TRUE;
560 break; 626 break;
561 } 627 }
562 default: 628 default:
563 ret = 0; 629 ret = 0;
564 break; 630 break;
565 }; 631 };
566 /* 632 /*
567 * FIXME do better sorting if the first sort criteria 633 * FIXME do better sorting if the first sort criteria
568 * ret equals 0 start with complete and so on... 634 * ret equals 0 start with complete and so on...
569 */ 635 */
570 636
571 /* twist it we're not ascending*/ 637 /* twist it we're not ascending*/
572 if (!m_asc) 638 if (!m_asc)
573 ret = ret * -1; 639 ret = ret * -1;
574 640
575 if ( ret ) 641 if ( ret )
576 return ret; 642 return ret;
577 643
578 // default did not gave difference let's try it other way around 644 // default did not gave difference let's try it other way around
579 /* 645 /*
580 * General try if already checked if not test 646 * General try if already checked if not test
581 * and return 647 * and return
582 * 1.Completed 648 * 1.Completed
583 * 2.Priority 649 * 2.Priority
584 * 3.Description 650 * 3.Description
585 * 4.DueDate 651 * 4.DueDate
586 */ 652 */
587 if (!seComp ) { 653 if (!seComp ) {
588 if ( (ret = completed( con1->todo, con2->todo ) ) ) { 654 if ( (ret = completed( con1->todo, con2->todo ) ) ) {
589 if (!m_asc ) ret *= -1; 655 if (!m_asc ) ret *= -1;
590 return ret; 656 return ret;
591 } 657 }
592 } 658 }
593 if (!sePrio ) { 659 if (!sePrio ) {
594 if ( (ret = priority( con1->todo, con2->todo ) ) ) { 660 if ( (ret = priority( con1->todo, con2->todo ) ) ) {
595 if (!m_asc ) ret *= -1; 661 if (!m_asc ) ret *= -1;
596 return ret; 662 return ret;
597 } 663 }
598 } 664 }
599 if (!seDesc ) { 665 if (!seDesc ) {
600 if ( (ret = description(con1->todo, con2->todo ) ) ) { 666 if ( (ret = description(con1->todo, con2->todo ) ) ) {
601 if (!m_asc) ret *= -1; 667 if (!m_asc) ret *= -1;
602 return ret; 668 return ret;
603 } 669 }
604 } 670 }
605 if (!seDeadline) { 671 if (!seDeadline) {
606 if ( (ret = deadline( con1->todo, con2->todo ) ) ) { 672 if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
607 if (!m_asc) ret *= -1; 673 if (!m_asc) ret *= -1;
608 return ret; 674 return ret;
609 } 675 }
610 } 676 }
611 677
612 return 0; 678 return 0;
613 } 679 }
614 private: 680 private:
615 bool m_asc; 681 bool m_asc;
616 int m_sort; 682 int m_sort;
617 683
618}; 684};
619 685
620QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, 686QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
621 int sortFilter, int cat ) { 687 int sortFilter, int cat ) {
622 qWarning("sorted! %d cat", cat); 688 qWarning("sorted! %d cat", cat);
623 OTodoXMLVector vector(m_events.count(), asc,sortOrder ); 689 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
624 QMap<int, OTodo>::Iterator it; 690 QMap<int, OTodo>::Iterator it;
625 int item = 0; 691 int item = 0;
626 692
627 bool bCat = sortFilter & 1 ? true : false; 693 bool bCat = sortFilter & 1 ? true : false;
628 bool bOnly = sortFilter & 2 ? true : false; 694 bool bOnly = sortFilter & 2 ? true : false;
629 bool comp = sortFilter & 4 ? true : false; 695 bool comp = sortFilter & 4 ? true : false;
630 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 696 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
631 697
632 /* show category */ 698 /* show category */
633 if ( bCat && cat != 0) 699 if ( bCat && cat != 0)
634 if (!(*it).categories().contains( cat ) ) { 700 if (!(*it).categories().contains( cat ) ) {
635 qWarning("category mis match"); 701 qWarning("category mis match");
636 continue; 702 continue;
637 } 703 }
638 /* isOverdue but we should not show overdue - why?*/ 704 /* isOverdue but we should not show overdue - why?*/
639/* if ( (*it).isOverdue() && !bOnly ) { 705/* if ( (*it).isOverdue() && !bOnly ) {
640 qWarning("item is overdue but !bOnly"); 706 qWarning("item is overdue but !bOnly");
641 continue; 707 continue;
642 } 708 }
643*/ 709*/
644 if ( !(*it).isOverdue() && bOnly ) { 710 if ( !(*it).isOverdue() && bOnly ) {
645 qWarning("item is not overdue but bOnly checked"); 711 qWarning("item is not overdue but bOnly checked");
646 continue; 712 continue;
647 } 713 }
648 714
649 if ((*it).isCompleted() && comp ) { 715 if ((*it).isCompleted() && comp ) {
650 qWarning("completed continue!"); 716 qWarning("completed continue!");
651 continue; 717 continue;
652 } 718 }
653 719
654 720
655 OTodoXMLContainer* con = new OTodoXMLContainer(); 721 OTodoXMLContainer* con = new OTodoXMLContainer();
656 con->todo = (*it); 722 con->todo = (*it);
657 vector.insert(item, con ); 723 vector.insert(item, con );
658 item++; 724 item++;
659 } 725 }
660 qWarning("XXX %d Items added", item); 726 qWarning("XXX %d Items added", item);
661 vector.resize( item ); 727 vector.resize( item );
662 /* sort it now */ 728 /* sort it now */
663 vector.sort(); 729 vector.sort();
664 /* now get the uids */ 730 /* now get the uids */
665 QArray<int> array( vector.count() ); 731 QArray<int> array( vector.count() );
666 for (uint i= 0; i < vector.count(); i++ ) { 732 for (uint i= 0; i < vector.count(); i++ ) {
667 array[i] = ( vector.at(i) )->todo.uid(); 733 array[i] = ( vector.at(i) )->todo.uid();
668 } 734 }
669 return array; 735 return array;
670}; 736};
671void OTodoAccessXML::removeAllCompleted() { 737void OTodoAccessXML::removeAllCompleted() {
672 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { 738 for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
673 if ( (*it).isCompleted() ) 739 if ( (*it).isCompleted() )
674 m_events.remove( it ); 740 m_events.remove( it );
675 } 741 }
676} 742}
677QBitArray OTodoAccessXML::supports()const { 743QBitArray OTodoAccessXML::supports()const {
678 static QBitArray ar = sup(); 744 static QBitArray ar = sup();
679 return ar; 745 return ar;
680} 746}
681QBitArray OTodoAccessXML::sup() { 747QBitArray OTodoAccessXML::sup() {
682 QBitArray ar( OTodo::CompletedDate +1 ); 748 QBitArray ar( OTodo::CompletedDate +1 );
683 ar.fill( true ); 749 ar.fill( true );
684 ar[OTodo::CrossReference] = false; 750 ar[OTodo::CrossReference] = false;
685 ar[OTodo::State ] = false; 751 ar[OTodo::State ] = false;
686 ar[OTodo::Reminders] = false; 752 ar[OTodo::Reminders] = false;
687 ar[OTodo::Notifiers] = false; 753 ar[OTodo::Notifiers] = false;
688 ar[OTodo::Maintainer] = false; 754 ar[OTodo::Maintainer] = false;
689 755
690 return ar; 756 return ar;
691} 757}
diff --git a/libopie2/opiepim/core/opimnotifymanager.cpp b/libopie2/opiepim/core/opimnotifymanager.cpp
index be4a1c2..49af757 100644
--- a/libopie2/opiepim/core/opimnotifymanager.cpp
+++ b/libopie2/opiepim/core/opimnotifymanager.cpp
@@ -1,69 +1,72 @@
1#include "opimnotifymanager.h" 1#include "opimnotifymanager.h"
2 2
3OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al) 3OPimNotifyManager::OPimNotifyManager( const Reminders& rem, const Alarms& al)
4 : m_rem( rem ), m_al( al ) 4 : m_rem( rem ), m_al( al )
5{} 5{}
6OPimNotifyManager::~OPimNotifyManager() { 6OPimNotifyManager::~OPimNotifyManager() {
7} 7}
8/* use static_cast and type instead of dynamic... */ 8/* use static_cast and type instead of dynamic... */
9void OPimNotifyManager::add( const OPimNotify& noti) { 9void OPimNotifyManager::add( const OPimNotify& noti) {
10 if ( noti.type() == QString::fromLatin1("OPimReminder") ) { 10 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
11 const OPimReminder& rem = static_cast<const OPimReminder&>(noti); 11 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
12 m_rem.append( rem ); 12 m_rem.append( rem );
13 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { 13 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
14 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); 14 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
15 m_al.append( al ); 15 m_al.append( al );
16 } 16 }
17} 17}
18void OPimNotifyManager::remove( const OPimNotify& noti) { 18void OPimNotifyManager::remove( const OPimNotify& noti) {
19 if ( noti.type() == QString::fromLatin1("OPimReminder") ) { 19 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
20 const OPimReminder& rem = static_cast<const OPimReminder&>(noti); 20 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
21 m_rem.remove( rem ); 21 m_rem.remove( rem );
22 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { 22 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
23 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); 23 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
24 m_al.remove( al ); 24 m_al.remove( al );
25 } 25 }
26} 26}
27void OPimNotifyManager::replace( const OPimNotify& noti) { 27void OPimNotifyManager::replace( const OPimNotify& noti) {
28 if ( noti.type() == QString::fromLatin1("OPimReminder") ) { 28 if ( noti.type() == QString::fromLatin1("OPimReminder") ) {
29 const OPimReminder& rem = static_cast<const OPimReminder&>(noti); 29 const OPimReminder& rem = static_cast<const OPimReminder&>(noti);
30 m_rem.remove( rem ); 30 m_rem.remove( rem );
31 m_rem.append( rem ); 31 m_rem.append( rem );
32 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) { 32 }else if ( noti.type() == QString::fromLatin1("OPimAlarm") ) {
33 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti); 33 const OPimAlarm& al = static_cast<const OPimAlarm&>(noti);
34 m_al.remove( al ); 34 m_al.remove( al );
35 m_al.append( al ); 35 m_al.append( al );
36 } 36 }
37} 37}
38OPimNotifyManager::Reminders OPimNotifyManager::reminders()const { 38OPimNotifyManager::Reminders OPimNotifyManager::reminders()const {
39 return m_rem; 39 return m_rem;
40} 40}
41OPimNotifyManager::Alarms OPimNotifyManager::alarms()const { 41OPimNotifyManager::Alarms OPimNotifyManager::alarms()const {
42 return m_al; 42 return m_al;
43} 43}
44void OPimNotifyManager::setAlarms( const Alarms& al) { 44void OPimNotifyManager::setAlarms( const Alarms& al) {
45 m_al = al; 45 m_al = al;
46} 46}
47void OPimNotifyManager::setReminders( const Reminders& rem) { 47void OPimNotifyManager::setReminders( const Reminders& rem) {
48 m_rem = rem; 48 m_rem = rem;
49} 49}
50/* FIXME!!! */ 50/* FIXME!!! */
51/** 51/**
52 * The idea is to check if the provider for our service 52 * The idea is to check if the provider for our service
53 * is online 53 * is online
54 * if it is we will use QCOP 54 * if it is we will use QCOP
55 * if not the Factory to get the backend... 55 * if not the Factory to get the backend...
56 * Qtopia1.6 services would be kewl to have here.... 56 * Qtopia1.6 services would be kewl to have here....
57 */ 57 */
58void OPimNotifyManager::registerNotify( const OPimNotify& ) { 58void OPimNotifyManager::registerNotify( const OPimNotify& ) {
59 59
60} 60}
61/* FIXME!!! */ 61/* FIXME!!! */
62/** 62/**
63 * same as above... 63 * same as above...
64 * Also implement Url model 64 * Also implement Url model
65 * have a MainWindow.... 65 * have a MainWindow....
66 */ 66 */
67void OPimNotifyManager::deregister( const OPimNotify& ) { 67void OPimNotifyManager::deregister( const OPimNotify& ) {
68 68
69} 69}
70bool OPimNotifyManager::isEmpty()const {
71 return ( m_rem.isEmpty() && m_al.isEmpty() );
72}
diff --git a/libopie2/opiepim/core/opimnotifymanager.h b/libopie2/opiepim/core/opimnotifymanager.h
index 0eebc9b..0ac30a1 100644
--- a/libopie2/opiepim/core/opimnotifymanager.h
+++ b/libopie2/opiepim/core/opimnotifymanager.h
@@ -1,51 +1,54 @@
1#ifndef OPIE_PIM_NOTIFY_MANAGER_H 1#ifndef OPIE_PIM_NOTIFY_MANAGER_H
2#define OPIE_PIM_NOTIFY_MANAGER_H 2#define OPIE_PIM_NOTIFY_MANAGER_H
3 3
4#include <qvaluelist.h> 4#include <qvaluelist.h>
5 5
6#include <opie/opimnotify.h> 6#include <opie/opimnotify.h>
7 7
8/** 8/**
9 * The notify manager keeps track of the Notifiers.... 9 * The notify manager keeps track of the Notifiers....
10 */ 10 */
11class OPimNotifyManager { 11class OPimNotifyManager {
12public: 12public:
13 typedef QValueList<OPimReminder> Reminders; 13 typedef QValueList<OPimReminder> Reminders;
14 typedef QValueList<OPimAlarm> Alarms; 14 typedef QValueList<OPimAlarm> Alarms;
15 OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() ); 15 OPimNotifyManager( const Reminders& rems = Reminders(), const Alarms& alarms = Alarms() );
16 ~OPimNotifyManager(); 16 ~OPimNotifyManager();
17 17
18 /* we will cast it for you ;) */ 18 /* we will cast it for you ;) */
19 void add( const OPimNotify& ); 19 void add( const OPimNotify& );
20 void remove( const OPimNotify& ); 20 void remove( const OPimNotify& );
21 /* replaces all with this one! */ 21 /* replaces all with this one! */
22 void replace( const OPimNotify& ); 22 void replace( const OPimNotify& );
23 23
24 Reminders reminders()const; 24 Reminders reminders()const;
25 Alarms alarms()const; 25 Alarms alarms()const;
26 26
27 void setAlarms( const Alarms& ); 27 void setAlarms( const Alarms& );
28 void setReminders( const Reminders& ); 28 void setReminders( const Reminders& );
29 29
30 /* register is a Ansi C keyword... */ 30 /* register is a Ansi C keyword... */
31 /** 31 /**
32 * This function will register the Notify to the Alarm Server 32 * This function will register the Notify to the Alarm Server
33 * or datebook depending on the type of the notify 33 * or datebook depending on the type of the notify
34 */ 34 */
35 void registerNotify( const OPimNotify& ); 35 void registerNotify( const OPimNotify& );
36 36
37 /** 37 /**
38 * this will do the opposite.. 38 * this will do the opposite..
39 */ 39 */
40 void deregister( const OPimNotify& ); 40 void deregister( const OPimNotify& );
41 41
42
43 bool isEmpty()const;
44
42private: 45private:
43 Reminders m_rem; 46 Reminders m_rem;
44 Alarms m_al; 47 Alarms m_al;
45 48
46 class Private; 49 class Private;
47 Private *d; 50 Private *d;
48 51
49}; 52};
50 53
51#endif 54#endif
diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp
index e3b45b4..eae1fdc 100644
--- a/libopie2/opiepim/core/orecur.cpp
+++ b/libopie2/opiepim/core/orecur.cpp
@@ -123,388 +123,388 @@ bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
123 for this round */ 123 for this round */
124 // firstOfWeek = 0; this is already done at decl. 124 // firstOfWeek = 0; this is already done at decl.
125 while(!((1 << firstOfWeek) & days() )) 125 while(!((1 << firstOfWeek) & days() ))
126 firstOfWeek++; 126 firstOfWeek++;
127 127
128 /* there is at least one 'day', or there would be no event */ 128 /* there is at least one 'day', or there would be no event */
129 while(!((1 << (dayOfWeek % 7)) & days() )) 129 while(!((1 << (dayOfWeek % 7)) & days() ))
130 dayOfWeek++; 130 dayOfWeek++;
131 131
132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
133 dayOfWeek -= start().dayOfWeek() -1; 133 dayOfWeek -= start().dayOfWeek() -1;
134 134
135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
136 firstOfWeek -= start().dayOfWeek() -1; 136 firstOfWeek -= start().dayOfWeek() -1;
137 137
138 // dayOfWeek may be negitive now 138 // dayOfWeek may be negitive now
139 // day of week is number of days to add to start day 139 // day of week is number of days to add to start day
140 140
141 freq *= 7; 141 freq *= 7;
142 // FALL-THROUGH !!!!! 142 // FALL-THROUGH !!!!!
143 case Daily: 143 case Daily:
144 // the add is for the possible fall through from weekly */ 144 // the add is for the possible fall through from weekly */
145 if(start().addDays(dayOfWeek) > from) { 145 if(start().addDays(dayOfWeek) > from) {
146 /* first week exception */ 146 /* first week exception */
147 next = QDate(start().addDays(dayOfWeek) ); 147 next = QDate(start().addDays(dayOfWeek) );
148 if ((next > endDate()) 148 if ((next > endDate())
149 && hasEndDate() ) 149 && hasEndDate() )
150 return FALSE; 150 return FALSE;
151 return TRUE; 151 return TRUE;
152 } 152 }
153 /* if from is middle of a non-week */ 153 /* if from is middle of a non-week */
154 154
155 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 155 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
157 157
158 if(diff != 0) 158 if(diff != 0)
159 diff = freq - diff; 159 diff = freq - diff;
160 if(diff2 != 0) 160 if(diff2 != 0)
161 diff2 = freq - diff2; 161 diff2 = freq - diff2;
162 diff = QMIN(diff, diff2); 162 diff = QMIN(diff, diff2);
163 163
164 next = QDate(from.addDays(diff)); 164 next = QDate(from.addDays(diff));
165 if ( (next > endDate()) 165 if ( (next > endDate())
166 && hasEndDate() ) 166 && hasEndDate() )
167 return FALSE; 167 return FALSE;
168 return TRUE; 168 return TRUE;
169 case MonthlyDay: 169 case MonthlyDay:
170 iday = from.day(); 170 iday = from.day();
171 iyear = from.year(); 171 iyear = from.year();
172 imonth = from.month(); 172 imonth = from.month();
173 /* find equivelent day of month for this month */ 173 /* find equivelent day of month for this month */
174 dayOfWeek = start().dayOfWeek(); 174 dayOfWeek = start().dayOfWeek();
175 weekOfMonth = (start().day() - 1) / 7; 175 weekOfMonth = (start().day() - 1) / 7;
176 176
177 /* work out when the next valid month is */ 177 /* work out when the next valid month is */
178 a = from.year() - start().year(); 178 a = from.year() - start().year();
179 a *= 12; 179 a *= 12;
180 a = a + (imonth - start().month()); 180 a = a + (imonth - start().month());
181 /* a is e.start()monthsFrom(from); */ 181 /* a is e.start()monthsFrom(from); */
182 if(a % freq) { 182 if(a % freq) {
183 a = freq - (a % freq); 183 a = freq - (a % freq);
184 imonth = from.month() + a; 184 imonth = from.month() + a;
185 if (imonth > 12) { 185 if (imonth > 12) {
186 imonth--; 186 imonth--;
187 iyear += imonth / 12; 187 iyear += imonth / 12;
188 imonth = imonth % 12; 188 imonth = imonth % 12;
189 imonth++; 189 imonth++;
190 } 190 }
191 } 191 }
192 /* imonth is now the first month after or on 192 /* imonth is now the first month after or on
193 from that matches the frequency given */ 193 from that matches the frequency given */
194 194
195 /* find for this month */ 195 /* find for this month */
196 tmpDate = QDate( iyear, imonth, 1 ); 196 tmpDate = QDate( iyear, imonth, 1 );
197 197
198 iday = 1; 198 iday = 1;
199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
200 iday += 7 * weekOfMonth; 200 iday += 7 * weekOfMonth;
201 while (iday > tmpDate.daysInMonth()) { 201 while (iday > tmpDate.daysInMonth()) {
202 imonth += freq; 202 imonth += freq;
203 if (imonth > 12) { 203 if (imonth > 12) {
204 imonth--; 204 imonth--;
205 iyear += imonth / 12; 205 iyear += imonth / 12;
206 imonth = imonth % 12; 206 imonth = imonth % 12;
207 imonth++; 207 imonth++;
208 } 208 }
209 tmpDate = QDate( iyear, imonth, 1 ); 209 tmpDate = QDate( iyear, imonth, 1 );
210 /* these loops could go for a while, check end case now */ 210 /* these loops could go for a while, check end case now */
211 if ((tmpDate > endDate()) && hasEndDate() ) 211 if ((tmpDate > endDate()) && hasEndDate() )
212 return FALSE; 212 return FALSE;
213 iday = 1; 213 iday = 1;
214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
215 iday += 7 * weekOfMonth; 215 iday += 7 * weekOfMonth;
216 } 216 }
217 tmpDate = QDate(iyear, imonth, iday); 217 tmpDate = QDate(iyear, imonth, iday);
218 218
219 if (tmpDate >= from) { 219 if (tmpDate >= from) {
220 next = tmpDate; 220 next = tmpDate;
221 if ((next > endDate() ) && hasEndDate() ) 221 if ((next > endDate() ) && hasEndDate() )
222 return FALSE; 222 return FALSE;
223 return TRUE; 223 return TRUE;
224 } 224 }
225 225
226 /* need to find the next iteration */ 226 /* need to find the next iteration */
227 do { 227 do {
228 imonth += freq; 228 imonth += freq;
229 if (imonth > 12) { 229 if (imonth > 12) {
230 imonth--; 230 imonth--;
231 iyear += imonth / 12; 231 iyear += imonth / 12;
232 imonth = imonth % 12; 232 imonth = imonth % 12;
233 imonth++; 233 imonth++;
234 } 234 }
235 tmpDate = QDate( iyear, imonth, 1 ); 235 tmpDate = QDate( iyear, imonth, 1 );
236 /* these loops could go for a while, check end case now */ 236 /* these loops could go for a while, check end case now */
237 if ((tmpDate > endDate()) && hasEndDate() ) 237 if ((tmpDate > endDate()) && hasEndDate() )
238 return FALSE; 238 return FALSE;
239 iday = 1; 239 iday = 1;
240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
241 iday += 7 * weekOfMonth; 241 iday += 7 * weekOfMonth;
242 } while (iday > tmpDate.daysInMonth()); 242 } while (iday > tmpDate.daysInMonth());
243 tmpDate = QDate(iyear, imonth, iday); 243 tmpDate = QDate(iyear, imonth, iday);
244 244
245 next = tmpDate; 245 next = tmpDate;
246 if ((next > endDate()) && hasEndDate() ) 246 if ((next > endDate()) && hasEndDate() )
247 return FALSE; 247 return FALSE;
248 return TRUE; 248 return TRUE;
249 case MonthlyDate: 249 case MonthlyDate:
250 iday = start().day(); 250 iday = start().day();
251 iyear = from.year(); 251 iyear = from.year();
252 imonth = from.month(); 252 imonth = from.month();
253 253
254 a = from.year() - start().year(); 254 a = from.year() - start().year();
255 a *= 12; 255 a *= 12;
256 a = a + (imonth - start().month()); 256 a = a + (imonth - start().month());
257 /* a is e.start()monthsFrom(from); */ 257 /* a is e.start()monthsFrom(from); */
258 if(a % freq) { 258 if(a % freq) {
259 a = freq - (a % freq); 259 a = freq - (a % freq);
260 imonth = from.month() + a; 260 imonth = from.month() + a;
261 if (imonth > 12) { 261 if (imonth > 12) {
262 imonth--; 262 imonth--;
263 iyear += imonth / 12; 263 iyear += imonth / 12;
264 imonth = imonth % 12; 264 imonth = imonth % 12;
265 imonth++; 265 imonth++;
266 } 266 }
267 } 267 }
268 /* imonth is now the first month after or on 268 /* imonth is now the first month after or on
269 from that matches the frequencey given */ 269 from that matches the frequencey given */
270 270
271 /* this could go for a while, worse case, 4*12 iterations, probably */ 271 /* this could go for a while, worse case, 4*12 iterations, probably */
272 while(!QDate::isValid(iyear, imonth, iday) ) { 272 while(!QDate::isValid(iyear, imonth, iday) ) {
273 imonth += freq; 273 imonth += freq;
274 if (imonth > 12) { 274 if (imonth > 12) {
275 imonth--; 275 imonth--;
276 iyear += imonth / 12; 276 iyear += imonth / 12;
277 imonth = imonth % 12; 277 imonth = imonth % 12;
278 imonth++; 278 imonth++;
279 } 279 }
280 /* these loops could go for a while, check end case now */ 280 /* these loops could go for a while, check end case now */
281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
282 return FALSE; 282 return FALSE;
283 } 283 }
284 284
285 if(QDate(iyear, imonth, iday) >= from) { 285 if(QDate(iyear, imonth, iday) >= from) {
286 /* done */ 286 /* done */
287 next = QDate(iyear, imonth, iday); 287 next = QDate(iyear, imonth, iday);
288 if ((next > endDate()) && hasEndDate() ) 288 if ((next > endDate()) && hasEndDate() )
289 return FALSE; 289 return FALSE;
290 return TRUE; 290 return TRUE;
291 } 291 }
292 292
293 /* ok, need to cycle */ 293 /* ok, need to cycle */
294 imonth += freq; 294 imonth += freq;
295 imonth--; 295 imonth--;
296 iyear += imonth / 12; 296 iyear += imonth / 12;
297 imonth = imonth % 12; 297 imonth = imonth % 12;
298 imonth++; 298 imonth++;
299 299
300 while(!QDate::isValid(iyear, imonth, iday) ) { 300 while(!QDate::isValid(iyear, imonth, iday) ) {
301 imonth += freq; 301 imonth += freq;
302 imonth--; 302 imonth--;
303 iyear += imonth / 12; 303 iyear += imonth / 12;
304 imonth = imonth % 12; 304 imonth = imonth % 12;
305 imonth++; 305 imonth++;
306 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 306 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
307 return FALSE; 307 return FALSE;
308 } 308 }
309 309
310 next = QDate(iyear, imonth, iday); 310 next = QDate(iyear, imonth, iday);
311 if ((next > endDate()) && hasEndDate() ) 311 if ((next > endDate()) && hasEndDate() )
312 return FALSE; 312 return FALSE;
313 return TRUE; 313 return TRUE;
314 case Yearly: 314 case Yearly:
315 iday = start().day(); 315 iday = start().day();
316 imonth = start().month(); 316 imonth = start().month();
317 iyear = from.year(); // after all, we want to start in this year 317 iyear = from.year(); // after all, we want to start in this year
318 318
319 diff = 1; 319 diff = 1;
320 if(imonth == 2 && iday > 28) { 320 if(imonth == 2 && iday > 28) {
321 /* leap year, and it counts, calculate actual frequency */ 321 /* leap year, and it counts, calculate actual frequency */
322 if(freq % 4) 322 if(freq % 4)
323 if (freq % 2) 323 if (freq % 2)
324 freq = freq * 4; 324 freq = freq * 4;
325 else 325 else
326 freq = freq * 2; 326 freq = freq * 2;
327 /* else divides by 4 already, leave freq alone */ 327 /* else divides by 4 already, leave freq alone */
328 diff = 4; 328 diff = 4;
329 } 329 }
330 330
331 a = from.year() - start().year(); 331 a = from.year() - start().year();
332 if(a % freq) { 332 if(a % freq) {
333 a = freq - (a % freq); 333 a = freq - (a % freq);
334 iyear = iyear + a; 334 iyear = iyear + a;
335 } 335 }
336 336
337 /* under the assumption we won't hit one of the special not-leap years twice */ 337 /* under the assumption we won't hit one of the special not-leap years twice */
338 if(!QDate::isValid(iyear, imonth, iday)) { 338 if(!QDate::isValid(iyear, imonth, iday)) {
339 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 339 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
340 iyear += freq; 340 iyear += freq;
341 } 341 }
342 342
343 if(QDate(iyear, imonth, iday) >= from) { 343 if(QDate(iyear, imonth, iday) >= from) {
344 next = QDate(iyear, imonth, iday); 344 next = QDate(iyear, imonth, iday);
345 345
346 if ((next > endDate()) && hasEndDate() ) 346 if ((next > endDate()) && hasEndDate() )
347 return FALSE; 347 return FALSE;
348 return TRUE; 348 return TRUE;
349 } 349 }
350 /* iyear == from.year(), need to advance again */ 350 /* iyear == from.year(), need to advance again */
351 iyear += freq; 351 iyear += freq;
352 /* under the assumption we won't hit one of the special not-leap years twice */ 352 /* under the assumption we won't hit one of the special not-leap years twice */
353 if(!QDate::isValid(iyear, imonth, iday)) { 353 if(!QDate::isValid(iyear, imonth, iday)) {
354 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 354 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
355 iyear += freq; 355 iyear += freq;
356 } 356 }
357 357
358 next = QDate(iyear, imonth, iday); 358 next = QDate(iyear, imonth, iday);
359 if ((next > endDate()) && hasEndDate() ) 359 if ((next > endDate()) && hasEndDate() )
360 return FALSE; 360 return FALSE;
361 return TRUE; 361 return TRUE;
362 default: 362 default:
363 return FALSE; 363 return FALSE;
364 } 364 }
365} 365}
366ORecur::RepeatType ORecur::type()const{ 366ORecur::RepeatType ORecur::type()const{
367 return data->type; 367 return data->type;
368} 368}
369int ORecur::frequency()const { 369int ORecur::frequency()const {
370 return data->freq; 370 return data->freq;
371} 371}
372int ORecur::position()const { 372int ORecur::position()const {
373 return data->pos; 373 return data->pos;
374} 374}
375char ORecur::days() const{ 375char ORecur::days() const{
376 return data->days; 376 return data->days;
377} 377}
378bool ORecur::hasEndDate()const { 378bool ORecur::hasEndDate()const {
379 return data->hasEnd; 379 return data->hasEnd;
380} 380}
381QDate ORecur::endDate()const { 381QDate ORecur::endDate()const {
382 return data->end; 382 return data->end;
383} 383}
384QDate ORecur::start()const{ 384QDate ORecur::start()const{
385 return data->start; 385 return data->start;
386} 386}
387QDateTime ORecur::createdDateTime()const { 387QDateTime ORecur::createdDateTime()const {
388 return data->create; 388 return data->create;
389} 389}
390int ORecur::repetition()const { 390int ORecur::repetition()const {
391 return data->rep; 391 return data->rep;
392} 392}
393QString ORecur::service()const { 393QString ORecur::service()const {
394 return data->app; 394 return data->app;
395} 395}
396ORecur::ExceptionList& ORecur::exceptions() { 396ORecur::ExceptionList& ORecur::exceptions() {
397 return data->list; 397 return data->list;
398} 398}
399void ORecur::setType( const RepeatType& z) { 399void ORecur::setType( const RepeatType& z) {
400 checkOrModify(); 400 checkOrModify();
401 data->type = z; 401 data->type = z;
402} 402}
403void ORecur::setFrequency( int freq ) { 403void ORecur::setFrequency( int freq ) {
404 checkOrModify(); 404 checkOrModify();
405 data->freq = freq; 405 data->freq = freq;
406} 406}
407void ORecur::setPosition( int pos ) { 407void ORecur::setPosition( int pos ) {
408 checkOrModify(); 408 checkOrModify();
409 data->pos = pos; 409 data->pos = pos;
410} 410}
411void ORecur::setDays( char c ) { 411void ORecur::setDays( char c ) {
412 checkOrModify(); 412 checkOrModify();
413 data->days = c; 413 data->days = c;
414} 414}
415void ORecur::setEndDate( const QDate& dt) { 415void ORecur::setEndDate( const QDate& dt) {
416 checkOrModify(); 416 checkOrModify();
417 data->end = dt; 417 data->end = dt;
418} 418}
419void ORecur::setCreatedDateTime( const QDateTime& t) { 419void ORecur::setCreatedDateTime( const QDateTime& t) {
420 checkOrModify(); 420 checkOrModify();
421 data->create = t; 421 data->create = t;
422} 422}
423void ORecur::setHasEndDate( bool b) { 423void ORecur::setHasEndDate( bool b) {
424 checkOrModify(); 424 checkOrModify();
425 data->hasEnd = b; 425 data->hasEnd = b;
426} 426}
427void ORecur::setRepitition( int rep ) { 427void ORecur::setRepitition( int rep ) {
428 checkOrModify(); 428 checkOrModify();
429 data->rep = rep; 429 data->rep = rep;
430} 430}
431void ORecur::setService( const QString& app ) { 431void ORecur::setService( const QString& app ) {
432 checkOrModify(); 432 checkOrModify();
433 data->app = app; 433 data->app = app;
434} 434}
435void ORecur::setStart( const QDate& dt ) { 435void ORecur::setStart( const QDate& dt ) {
436 checkOrModify(); 436 checkOrModify();
437 data->start = dt; 437 data->start = dt;
438} 438}
439void ORecur::checkOrModify() { 439void ORecur::checkOrModify() {
440 if ( data->count != 1 ) { 440 if ( data->count != 1 ) {
441 data->deref(); 441 data->deref();
442 Data* d2 = new Data; 442 Data* d2 = new Data;
443 d2->days = data->days; 443 d2->days = data->days;
444 d2->type = data->type; 444 d2->type = data->type;
445 d2->freq = data->freq; 445 d2->freq = data->freq;
446 d2->pos = data->pos; 446 d2->pos = data->pos;
447 d2->hasEnd = data->hasEnd; 447 d2->hasEnd = data->hasEnd;
448 d2->end = data->end; 448 d2->end = data->end;
449 d2->create = data->create; 449 d2->create = data->create;
450 d2->rep = data->rep; 450 d2->rep = data->rep;
451 d2->app = data->app; 451 d2->app = data->app;
452 d2->list = data->list; 452 d2->list = data->list;
453 d2->start = data->start; 453 d2->start = data->start;
454 data = d2; 454 data = d2;
455 } 455 }
456} 456}
457QString ORecur::toString()const { 457QString ORecur::toString()const {
458 QString buf; 458 QString buf;
459 459
460 buf += " rtype=\""; 460 buf += " rtype=\"";
461 switch ( data->type ) { 461 switch ( data->type ) {
462 case ORecur::Daily: 462 case ORecur::Daily:
463 buf += "Daily"; 463 buf += "Daily";
464 break; 464 break;
465 case ORecur::Weekly: 465 case ORecur::Weekly:
466 buf += "Weekly"; 466 buf += "Weekly";
467 break; 467 break;
468 case ORecur::MonthlyDay: 468 case ORecur::MonthlyDay:
469 buf += "MonthlyDay"; 469 buf += "MonthlyDay";
470 break; 470 break;
471 case ORecur::MonthlyDate: 471 case ORecur::MonthlyDate:
472 buf += "MonthlyDate"; 472 buf += "MonthlyDate";
473 break; 473 break;
474 case ORecur::Yearly: 474 case ORecur::Yearly:
475 buf += "Yearly"; 475 buf += "Yearly";
476 break; 476 break;
477 default: 477 default:
478 buf += "NoRepeat"; 478 buf += "NoRepeat";
479 break; 479 break;
480 } 480 }
481 buf += "\""; 481 buf += "\"";
482 if (data->days > 0 ) 482 if (data->days > 0 )
483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\""; 483 buf += " rweekdays=\"" + QString::number( static_cast<int>( data->days ) ) + "\"";
484 if ( data->pos != 0 ) 484 if ( data->pos != 0 )
485 buf += " rposition=\"" + QString::number(data->pos ) + "\""; 485 buf += " rposition=\"" + QString::number(data->pos ) + "\"";
486 486
487 buf += " rfreq=\"" + QString::number( data->freq ) + "\""; 487 buf += " rfreq=\"" + QString::number( data->freq ) + "\"";
488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\""; 488 buf += " rhasenddate=\"" + QString::number( static_cast<int>( data->hasEnd ) ) + "\"";
489 if ( data->hasEnd ) 489 if ( data->hasEnd )
490 buf += " enddt=\"" 490 buf += " enddt=\""
491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) ) 491 + QString::number( OTimeZone::utc().fromUTCDateTime( QDateTime( data->end, QTime(12,0,0) ) ) )
492 + "\""; 492 + "\"";
493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\""; 493 buf += " created=\"" + QString::number( OTimeZone::utc().fromUTCDateTime( data->create ) ) + "\"";
494 494
495 if ( data->list.isEmpty() ) return buf; 495 if ( data->list.isEmpty() ) return buf;
496 // save exceptions list here!! 496 // save exceptions list here!!
497 ExceptionList::ConstIterator it; 497 ExceptionList::ConstIterator it;
498 ExceptionList list = data->list; 498 ExceptionList list = data->list;
499 buf += " exceptions=\""; 499 buf += " exceptions=\"";
500 QDate date; 500 QDate date;
501 for ( it = list.begin(); it != list.end(); ++it ) { 501 for ( it = list.begin(); it != list.end(); ++it ) {
502 date = (*it); 502 date = (*it);
503 if ( it != list.begin() ) buf += " "; 503 if ( it != list.begin() ) buf += " ";
504 504
505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() ); 505 buf += QCString().sprintf("%04d%02d%02d", date.year(), date.month(), date.day() );
506 } 506 }
507 buf += "\""; 507 buf += "\" ";
508 508
509 return buf; 509 return buf;
510} 510}