-rw-r--r-- | libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp | 29 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessxml.cpp | 30 |
2 files changed, 57 insertions, 2 deletions
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp index bc51996..24b69fe 100644 --- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp +++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp | |||
@@ -1,555 +1,582 @@ | |||
1 | #include <errno.h> | 1 | #include <errno.h> |
2 | #include <fcntl.h> | 2 | #include <fcntl.h> |
3 | 3 | ||
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | #include <stdlib.h> | 5 | #include <stdlib.h> |
6 | 6 | ||
7 | #include <sys/types.h> | 7 | #include <sys/types.h> |
8 | #include <sys/mman.h> | 8 | #include <sys/mman.h> |
9 | #include <sys/stat.h> | 9 | #include <sys/stat.h> |
10 | 10 | ||
11 | #include <unistd.h> | 11 | #include <unistd.h> |
12 | 12 | ||
13 | #include <qasciidict.h> | 13 | #include <qasciidict.h> |
14 | #include <qfile.h> | 14 | #include <qfile.h> |
15 | 15 | ||
16 | #include <qtopia/global.h> | 16 | #include <qtopia/global.h> |
17 | #include <qtopia/stringutil.h> | 17 | #include <qtopia/stringutil.h> |
18 | #include <qtopia/timeconversion.h> | 18 | #include <qtopia/timeconversion.h> |
19 | 19 | ||
20 | #include "opimnotifymanager.h" | 20 | #include "opimnotifymanager.h" |
21 | #include "orecur.h" | 21 | #include "orecur.h" |
22 | #include "otimezone.h" | 22 | #include "otimezone.h" |
23 | #include "odatebookaccessbackend_xml.h" | 23 | #include "odatebookaccessbackend_xml.h" |
24 | 24 | ||
25 | namespace { | 25 | namespace { |
26 | // FROM TT again | ||
27 | char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) | ||
28 | { | ||
29 | char needleChar; | ||
30 | char haystackChar; | ||
31 | if (!needle || !haystack || !hLen || !nLen) | ||
32 | return 0; | ||
33 | |||
34 | const char* hsearch = haystack; | ||
35 | |||
36 | if ((needleChar = *needle++) != 0) { | ||
37 | nLen--; //(to make up for needle++) | ||
38 | do { | ||
39 | do { | ||
40 | if ((haystackChar = *hsearch++) == 0) | ||
41 | return (0); | ||
42 | if (hsearch >= haystack + hLen) | ||
43 | return (0); | ||
44 | } while (haystackChar != needleChar); | ||
45 | } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); | ||
46 | hsearch--; | ||
47 | } | ||
48 | return ((char *)hsearch); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | namespace { | ||
26 | time_t start, end, created, rp_end; | 53 | time_t start, end, created, rp_end; |
27 | ORecur* rec; | 54 | ORecur* rec; |
28 | ORecur* recur() { | 55 | ORecur* recur() { |
29 | if (!rec) | 56 | if (!rec) |
30 | rec = new ORecur; | 57 | rec = new ORecur; |
31 | 58 | ||
32 | return rec; | 59 | return rec; |
33 | } | 60 | } |
34 | int alarmTime; | 61 | int alarmTime; |
35 | int snd; | 62 | int snd; |
36 | enum Attribute{ | 63 | enum Attribute{ |
37 | FDescription = 0, | 64 | FDescription = 0, |
38 | FLocation, | 65 | FLocation, |
39 | FCategories, | 66 | FCategories, |
40 | FUid, | 67 | FUid, |
41 | FType, | 68 | FType, |
42 | FAlarm, | 69 | FAlarm, |
43 | FSound, | 70 | FSound, |
44 | FRType, | 71 | FRType, |
45 | FRWeekdays, | 72 | FRWeekdays, |
46 | FRPosition, | 73 | FRPosition, |
47 | FRFreq, | 74 | FRFreq, |
48 | FRHasEndDate, | 75 | FRHasEndDate, |
49 | FREndDate, | 76 | FREndDate, |
50 | FRStart, | 77 | FRStart, |
51 | FREnd, | 78 | FREnd, |
52 | FNote, | 79 | FNote, |
53 | FCreated, | 80 | FCreated, |
54 | FTimeZone, | 81 | FTimeZone, |
55 | FRecParent, | 82 | FRecParent, |
56 | FRecChildren, | 83 | FRecChildren, |
57 | FExceptions | 84 | FExceptions |
58 | }; | 85 | }; |
59 | inline void save( const OEvent& ev, QString& buf ) { | 86 | inline void save( const OEvent& ev, QString& buf ) { |
60 | buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\""; | 87 | buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\""; |
61 | if (!ev.location().isEmpty() ) | 88 | if (!ev.location().isEmpty() ) |
62 | buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\""; | 89 | buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\""; |
63 | 90 | ||
64 | buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\""; | 91 | buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\""; |
65 | buf += " uid=\"" + QString::number( ev.uid() ) + "\""; | 92 | buf += " uid=\"" + QString::number( ev.uid() ) + "\""; |
66 | 93 | ||
67 | if (ev.isAllDay() ) | 94 | if (ev.isAllDay() ) |
68 | buf += " type=\"AllDay\""; | 95 | buf += " type=\"AllDay\""; |
69 | 96 | ||
70 | if (ev.hasNotifiers() ) { | 97 | if (ev.hasNotifiers() ) { |
71 | OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first | 98 | OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first |
72 | int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60; | 99 | int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60; |
73 | buf += " alarm=\"" + QString::number(minutes) + "\" sound=\""; | 100 | buf += " alarm=\"" + QString::number(minutes) + "\" sound=\""; |
74 | if ( alarm.sound() == OPimAlarm::Loud ) | 101 | if ( alarm.sound() == OPimAlarm::Loud ) |
75 | buf += "loud"; | 102 | buf += "loud"; |
76 | else | 103 | else |
77 | buf += "silent"; | 104 | buf += "silent"; |
78 | buf += "\""; | 105 | buf += "\""; |
79 | } | 106 | } |
80 | if ( ev.hasRecurrence() ) { | 107 | if ( ev.hasRecurrence() ) { |
81 | buf += ev.recurrence().toString(); | 108 | buf += ev.recurrence().toString(); |
82 | } | 109 | } |
83 | 110 | ||
84 | /* | 111 | /* |
85 | * fscking timezones :) well, we'll first convert | 112 | * fscking timezones :) well, we'll first convert |
86 | * the QDateTime to a QDateTime in UTC time | 113 | * the QDateTime to a QDateTime in UTC time |
87 | * and then we'll create a nice time_t | 114 | * and then we'll create a nice time_t |
88 | */ | 115 | */ |
89 | OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); | 116 | OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); |
90 | buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\""; | 117 | buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\""; |
91 | buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\""; | 118 | buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\""; |
92 | if (!ev.note().isEmpty() ) { | 119 | if (!ev.note().isEmpty() ) { |
93 | buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\""; | 120 | buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\""; |
94 | } | 121 | } |
95 | 122 | ||
96 | buf += " timezone=\""; | 123 | buf += " timezone=\""; |
97 | if ( ev.timeZone().isEmpty() ) | 124 | if ( ev.timeZone().isEmpty() ) |
98 | buf += "None"; | 125 | buf += "None"; |
99 | else | 126 | else |
100 | buf += ev.timeZone(); | 127 | buf += ev.timeZone(); |
101 | 128 | ||
102 | if (ev.parent() != 0 ) { | 129 | if (ev.parent() != 0 ) { |
103 | buf += " recparent=\""+QString::number(ev.parent() )+"\""; | 130 | buf += " recparent=\""+QString::number(ev.parent() )+"\""; |
104 | } | 131 | } |
105 | 132 | ||
106 | if (ev.children().count() != 0 ) { | 133 | if (ev.children().count() != 0 ) { |
107 | QArray<int> children = ev.children(); | 134 | QArray<int> children = ev.children(); |
108 | buf += " recchildren=\""; | 135 | buf += " recchildren=\""; |
109 | for ( uint i = 0; i < children.count(); i++ ) { | 136 | for ( uint i = 0; i < children.count(); i++ ) { |
110 | if ( i != 0 ) buf += " "; | 137 | if ( i != 0 ) buf += " "; |
111 | buf += QString::number( children[i] ); | 138 | buf += QString::number( children[i] ); |
112 | } | 139 | } |
113 | buf+= "\""; | 140 | buf+= "\""; |
114 | } | 141 | } |
115 | 142 | ||
116 | // skip custom writing | 143 | // skip custom writing |
117 | } | 144 | } |
118 | 145 | ||
119 | inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) { | 146 | inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) { |
120 | QMap<int, OEvent>::ConstIterator it; | 147 | QMap<int, OEvent>::ConstIterator it; |
121 | QString buf; | 148 | QString buf; |
122 | QCString str; | 149 | QCString str; |
123 | int total_written; | 150 | int total_written; |
124 | for ( it = list.begin(); it != list.end(); ++it ) { | 151 | for ( it = list.begin(); it != list.end(); ++it ) { |
125 | buf = "<event"; | 152 | buf = "<event"; |
126 | save( it.data(), buf ); | 153 | save( it.data(), buf ); |
127 | buf += " />\n"; | 154 | buf += " />\n"; |
128 | str = buf.utf8(); | 155 | str = buf.utf8(); |
129 | 156 | ||
130 | total_written = file.writeBlock(str.data(), str.length() ); | 157 | total_written = file.writeBlock(str.data(), str.length() ); |
131 | if ( total_written != int(str.length() ) ) | 158 | if ( total_written != int(str.length() ) ) |
132 | return false; | 159 | return false; |
133 | } | 160 | } |
134 | return true; | 161 | return true; |
135 | } | 162 | } |
136 | } | 163 | } |
137 | 164 | ||
138 | ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , | 165 | ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , |
139 | const QString& fileName ) | 166 | const QString& fileName ) |
140 | : ODateBookAccessBackend() { | 167 | : ODateBookAccessBackend() { |
141 | m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; | 168 | m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; |
142 | m_changed = false; | 169 | m_changed = false; |
143 | } | 170 | } |
144 | ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { | 171 | ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { |
145 | } | 172 | } |
146 | bool ODateBookAccessBackend_XML::load() { | 173 | bool ODateBookAccessBackend_XML::load() { |
147 | return loadFile(); | 174 | return loadFile(); |
148 | } | 175 | } |
149 | bool ODateBookAccessBackend_XML::reload() { | 176 | bool ODateBookAccessBackend_XML::reload() { |
150 | clear(); | 177 | clear(); |
151 | return load(); | 178 | return load(); |
152 | } | 179 | } |
153 | bool ODateBookAccessBackend_XML::save() { | 180 | bool ODateBookAccessBackend_XML::save() { |
154 | if (!m_changed) return true; | 181 | if (!m_changed) return true; |
155 | 182 | ||
156 | int total_written; | 183 | int total_written; |
157 | QString strFileNew = m_name + ".new"; | 184 | QString strFileNew = m_name + ".new"; |
158 | 185 | ||
159 | QFile f( strFileNew ); | 186 | QFile f( strFileNew ); |
160 | if (!f.open( IO_WriteOnly | IO_Raw ) ) return false; | 187 | if (!f.open( IO_WriteOnly | IO_Raw ) ) return false; |
161 | 188 | ||
162 | QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); | 189 | QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); |
163 | buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n"; | 190 | buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n"; |
164 | buf += "<events>\n"; | 191 | buf += "<events>\n"; |
165 | QCString str = buf.utf8(); | 192 | QCString str = buf.utf8(); |
166 | total_written = f.writeBlock( str.data(), str.length() ); | 193 | total_written = f.writeBlock( str.data(), str.length() ); |
167 | if ( total_written != int(str.length() ) ) { | 194 | if ( total_written != int(str.length() ) ) { |
168 | f.close(); | 195 | f.close(); |
169 | QFile::remove( strFileNew ); | 196 | QFile::remove( strFileNew ); |
170 | return false; | 197 | return false; |
171 | } | 198 | } |
172 | 199 | ||
173 | if (!forAll( m_raw, f ) ) { | 200 | if (!forAll( m_raw, f ) ) { |
174 | f.close(); | 201 | f.close(); |
175 | QFile::remove( strFileNew ); | 202 | QFile::remove( strFileNew ); |
176 | return false; | 203 | return false; |
177 | } | 204 | } |
178 | if (!forAll( m_rep, f ) ) { | 205 | if (!forAll( m_rep, f ) ) { |
179 | f.close(); | 206 | f.close(); |
180 | QFile::remove( strFileNew ); | 207 | QFile::remove( strFileNew ); |
181 | return false; | 208 | return false; |
182 | } | 209 | } |
183 | 210 | ||
184 | buf = "</events>\n</DATEBOOK>\n"; | 211 | buf = "</events>\n</DATEBOOK>\n"; |
185 | str = buf.utf8(); | 212 | str = buf.utf8(); |
186 | total_written = f.writeBlock( str.data(), str.length() ); | 213 | total_written = f.writeBlock( str.data(), str.length() ); |
187 | if ( total_written != int(str.length() ) ) { | 214 | if ( total_written != int(str.length() ) ) { |
188 | f.close(); | 215 | f.close(); |
189 | QFile::remove( strFileNew ); | 216 | QFile::remove( strFileNew ); |
190 | return false; | 217 | return false; |
191 | } | 218 | } |
192 | f.close(); | 219 | f.close(); |
193 | 220 | ||
194 | if ( ::rename( strFileNew, m_name ) < 0 ) { | 221 | if ( ::rename( strFileNew, m_name ) < 0 ) { |
195 | QFile::remove( strFileNew ); | 222 | QFile::remove( strFileNew ); |
196 | return false; | 223 | return false; |
197 | } | 224 | } |
198 | 225 | ||
199 | m_changed = false; | 226 | m_changed = false; |
200 | return true; | 227 | return true; |
201 | } | 228 | } |
202 | QArray<int> ODateBookAccessBackend_XML::allRecords()const { | 229 | QArray<int> ODateBookAccessBackend_XML::allRecords()const { |
203 | QArray<int> ints( m_raw.count()+ m_rep.count() ); | 230 | QArray<int> ints( m_raw.count()+ m_rep.count() ); |
204 | uint i = 0; | 231 | uint i = 0; |
205 | QMap<int, OEvent>::ConstIterator it; | 232 | QMap<int, OEvent>::ConstIterator it; |
206 | 233 | ||
207 | for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { | 234 | for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { |
208 | ints[i] = it.key(); | 235 | ints[i] = it.key(); |
209 | i++; | 236 | i++; |
210 | } | 237 | } |
211 | for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { | 238 | for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { |
212 | ints[i] = it.key(); | 239 | ints[i] = it.key(); |
213 | i++; | 240 | i++; |
214 | } | 241 | } |
215 | 242 | ||
216 | return ints; | 243 | return ints; |
217 | } | 244 | } |
218 | QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { | 245 | QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { |
219 | return QArray<int>(); | 246 | return QArray<int>(); |
220 | } | 247 | } |
221 | void ODateBookAccessBackend_XML::clear() { | 248 | void ODateBookAccessBackend_XML::clear() { |
222 | m_raw.clear(); | 249 | m_raw.clear(); |
223 | m_rep.clear(); | 250 | m_rep.clear(); |
224 | } | 251 | } |
225 | OEvent ODateBookAccessBackend_XML::find( int uid ) const{ | 252 | OEvent ODateBookAccessBackend_XML::find( int uid ) const{ |
226 | if ( m_raw.contains( uid ) ) | 253 | if ( m_raw.contains( uid ) ) |
227 | return m_raw[uid]; | 254 | return m_raw[uid]; |
228 | else | 255 | else |
229 | return m_rep[uid]; | 256 | return m_rep[uid]; |
230 | } | 257 | } |
231 | bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { | 258 | bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { |
232 | m_changed = true; | 259 | m_changed = true; |
233 | if (ev.hasRecurrence() ) | 260 | if (ev.hasRecurrence() ) |
234 | m_rep.insert( ev.uid(), ev ); | 261 | m_rep.insert( ev.uid(), ev ); |
235 | else | 262 | else |
236 | m_raw.insert( ev.uid(), ev ); | 263 | m_raw.insert( ev.uid(), ev ); |
237 | 264 | ||
238 | return true; | 265 | return true; |
239 | } | 266 | } |
240 | bool ODateBookAccessBackend_XML::remove( int uid ) { | 267 | bool ODateBookAccessBackend_XML::remove( int uid ) { |
241 | m_changed = true; | 268 | m_changed = true; |
242 | m_rep.remove( uid ); | 269 | m_rep.remove( uid ); |
243 | m_rep.remove( uid ); | 270 | m_rep.remove( uid ); |
244 | 271 | ||
245 | return true; | 272 | return true; |
246 | } | 273 | } |
247 | bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { | 274 | bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { |
248 | replace( ev.uid() ); | 275 | replace( ev.uid() ); |
249 | return add( ev ); | 276 | return add( ev ); |
250 | } | 277 | } |
251 | QArray<int> ODateBookAccessBackend_XML::rawEvents()const { | 278 | QArray<int> ODateBookAccessBackend_XML::rawEvents()const { |
252 | return allRecords(); | 279 | return allRecords(); |
253 | } | 280 | } |
254 | QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { | 281 | QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { |
255 | QArray<int> ints( m_rep.count() ); | 282 | QArray<int> ints( m_rep.count() ); |
256 | uint i = 0; | 283 | uint i = 0; |
257 | QMap<int, OEvent>::ConstIterator it; | 284 | QMap<int, OEvent>::ConstIterator it; |
258 | 285 | ||
259 | for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { | 286 | for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { |
260 | ints[i] = it.key(); | 287 | ints[i] = it.key(); |
261 | i++; | 288 | i++; |
262 | } | 289 | } |
263 | 290 | ||
264 | return ints; | 291 | return ints; |
265 | } | 292 | } |
266 | QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { | 293 | QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { |
267 | QArray<int> ints( m_raw.count() ); | 294 | QArray<int> ints( m_raw.count() ); |
268 | uint i = 0; | 295 | uint i = 0; |
269 | QMap<int, OEvent>::ConstIterator it; | 296 | QMap<int, OEvent>::ConstIterator it; |
270 | 297 | ||
271 | for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { | 298 | for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { |
272 | ints[i] = it.key(); | 299 | ints[i] = it.key(); |
273 | i++; | 300 | i++; |
274 | } | 301 | } |
275 | 302 | ||
276 | return ints; | 303 | return ints; |
277 | } | 304 | } |
278 | OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { | 305 | OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { |
279 | OEvent::ValueList list; | 306 | OEvent::ValueList list; |
280 | QMap<int, OEvent>::ConstIterator it; | 307 | QMap<int, OEvent>::ConstIterator it; |
281 | for (it = m_raw.begin(); it != m_raw.end(); ++it ) | 308 | for (it = m_raw.begin(); it != m_raw.end(); ++it ) |
282 | list.append( it.data() ); | 309 | list.append( it.data() ); |
283 | 310 | ||
284 | return list; | 311 | return list; |
285 | } | 312 | } |
286 | OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { | 313 | OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { |
287 | OEvent::ValueList list; | 314 | OEvent::ValueList list; |
288 | QMap<int, OEvent>::ConstIterator it; | 315 | QMap<int, OEvent>::ConstIterator it; |
289 | for (it = m_rep.begin(); it != m_rep.end(); ++it ) | 316 | for (it = m_rep.begin(); it != m_rep.end(); ++it ) |
290 | list.append( it.data() ); | 317 | list.append( it.data() ); |
291 | 318 | ||
292 | return list; | 319 | return list; |
293 | } | 320 | } |
294 | bool ODateBookAccessBackend_XML::loadFile() { | 321 | bool ODateBookAccessBackend_XML::loadFile() { |
295 | m_changed = false; | 322 | m_changed = false; |
296 | 323 | ||
297 | int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); | 324 | int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); |
298 | if ( fd < 0 ) return false; | 325 | if ( fd < 0 ) return false; |
299 | 326 | ||
300 | struct stat attribute; | 327 | struct stat attribute; |
301 | if ( ::fstat(fd, &attribute ) == -1 ) { | 328 | if ( ::fstat(fd, &attribute ) == -1 ) { |
302 | ::close( fd ); | 329 | ::close( fd ); |
303 | return false; | 330 | return false; |
304 | } | 331 | } |
305 | void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); | 332 | void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); |
306 | if ( map_addr == ( (caddr_t)-1) ) { | 333 | if ( map_addr == ( (caddr_t)-1) ) { |
307 | ::close( fd ); | 334 | ::close( fd ); |
308 | return false; | 335 | return false; |
309 | } | 336 | } |
310 | 337 | ||
311 | ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); | 338 | ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); |
312 | ::close( fd ); | 339 | ::close( fd ); |
313 | 340 | ||
314 | QAsciiDict<int> dict(FExceptions+1); | 341 | QAsciiDict<int> dict(FExceptions+1); |
315 | dict.setAutoDelete( true ); | 342 | dict.setAutoDelete( true ); |
316 | dict.insert( "description", new int(FDescription) ); | 343 | dict.insert( "description", new int(FDescription) ); |
317 | dict.insert( "location", new int(FLocation) ); | 344 | dict.insert( "location", new int(FLocation) ); |
318 | dict.insert( "categories", new int(FCategories) ); | 345 | dict.insert( "categories", new int(FCategories) ); |
319 | dict.insert( "uid", new int(FUid) ); | 346 | dict.insert( "uid", new int(FUid) ); |
320 | dict.insert( "type", new int(FType) ); | 347 | dict.insert( "type", new int(FType) ); |
321 | dict.insert( "alarm", new int(FAlarm) ); | 348 | dict.insert( "alarm", new int(FAlarm) ); |
322 | dict.insert( "sound", new int(FSound) ); | 349 | dict.insert( "sound", new int(FSound) ); |
323 | dict.insert( "rtype", new int(FRType) ); | 350 | dict.insert( "rtype", new int(FRType) ); |
324 | dict.insert( "rweekdays", new int(FRWeekdays) ); | 351 | dict.insert( "rweekdays", new int(FRWeekdays) ); |
325 | dict.insert( "rposition", new int(FRPosition) ); | 352 | dict.insert( "rposition", new int(FRPosition) ); |
326 | dict.insert( "rfreq", new int(FRFreq) ); | 353 | dict.insert( "rfreq", new int(FRFreq) ); |
327 | dict.insert( "rhasenddate", new int(FRHasEndDate) ); | 354 | dict.insert( "rhasenddate", new int(FRHasEndDate) ); |
328 | dict.insert( "enddt", new int(FREndDate) ); | 355 | dict.insert( "enddt", new int(FREndDate) ); |
329 | dict.insert( "start", new int(FRStart) ); | 356 | dict.insert( "start", new int(FRStart) ); |
330 | dict.insert( "end", new int(FREnd) ); | 357 | dict.insert( "end", new int(FREnd) ); |
331 | dict.insert( "note", new int(FNote) ); | 358 | dict.insert( "note", new int(FNote) ); |
332 | dict.insert( "created", new int(FCreated) ); | 359 | dict.insert( "created", new int(FCreated) ); |
333 | dict.insert( "recparent", new int(FRecParent) ); | 360 | dict.insert( "recparent", new int(FRecParent) ); |
334 | dict.insert( "recchildren", new int(FRecChildren) ); | 361 | dict.insert( "recchildren", new int(FRecChildren) ); |
335 | dict.insert( "exceptions", new int(FExceptions) ); | 362 | dict.insert( "exceptions", new int(FExceptions) ); |
336 | dict.insert( "timezone", new int(FTimeZone) ); | 363 | dict.insert( "timezone", new int(FTimeZone) ); |
337 | 364 | ||
338 | char* dt = (char*)map_addr; | 365 | char* dt = (char*)map_addr; |
339 | int len = attribute.st_size; | 366 | int len = attribute.st_size; |
340 | int i = 0; | 367 | int i = 0; |
341 | char* point; | 368 | char* point; |
342 | const char* collectionString = "<event "; | 369 | const char* collectionString = "<event "; |
343 | int strLen = ::strlen(collectionString); | 370 | int strLen = ::strlen(collectionString); |
344 | int *find; | 371 | int *find; |
345 | while ( dt + 1 != 0 && (( point = ::strstr( dt+i, collectionString ) ) != 0 ) ) { | 372 | while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) { |
346 | i = point -dt; | 373 | i = point -dt; |
347 | i+= strLen; | 374 | i+= strLen; |
348 | 375 | ||
349 | alarmTime = -1; | 376 | alarmTime = -1; |
350 | snd = 0; // silent | 377 | snd = 0; // silent |
351 | 378 | ||
352 | OEvent ev; | 379 | OEvent ev; |
353 | rec = 0; | 380 | rec = 0; |
354 | 381 | ||
355 | while ( TRUE ) { | 382 | while ( TRUE ) { |
356 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) | 383 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) |
357 | ++i; | 384 | ++i; |
358 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) | 385 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) |
359 | break; | 386 | break; |
360 | 387 | ||
361 | 388 | ||
362 | // we have another attribute, read it. | 389 | // we have another attribute, read it. |
363 | int j = i; | 390 | int j = i; |
364 | while ( j < len && dt[j] != '=' ) | 391 | while ( j < len && dt[j] != '=' ) |
365 | ++j; | 392 | ++j; |
366 | QCString attr( dt+i, j-i+1); | 393 | QCString attr( dt+i, j-i+1); |
367 | 394 | ||
368 | i = ++j; // skip = | 395 | i = ++j; // skip = |
369 | 396 | ||
370 | // find the start of quotes | 397 | // find the start of quotes |
371 | while ( i < len && dt[i] != '"' ) | 398 | while ( i < len && dt[i] != '"' ) |
372 | ++i; | 399 | ++i; |
373 | j = ++i; | 400 | j = ++i; |
374 | 401 | ||
375 | bool haveUtf = FALSE; | 402 | bool haveUtf = FALSE; |
376 | bool haveEnt = FALSE; | 403 | bool haveEnt = FALSE; |
377 | while ( j < len && dt[j] != '"' ) { | 404 | while ( j < len && dt[j] != '"' ) { |
378 | if ( ((unsigned char)dt[j]) > 0x7f ) | 405 | if ( ((unsigned char)dt[j]) > 0x7f ) |
379 | haveUtf = TRUE; | 406 | haveUtf = TRUE; |
380 | if ( dt[j] == '&' ) | 407 | if ( dt[j] == '&' ) |
381 | haveEnt = TRUE; | 408 | haveEnt = TRUE; |
382 | ++j; | 409 | ++j; |
383 | } | 410 | } |
384 | if ( i == j ) { | 411 | if ( i == j ) { |
385 | // empty value | 412 | // empty value |
386 | i = j + 1; | 413 | i = j + 1; |
387 | continue; | 414 | continue; |
388 | } | 415 | } |
389 | 416 | ||
390 | QCString value( dt+i, j-i+1 ); | 417 | QCString value( dt+i, j-i+1 ); |
391 | i = j + 1; | 418 | i = j + 1; |
392 | 419 | ||
393 | QString str = (haveUtf ? QString::fromUtf8( value ) | 420 | QString str = (haveUtf ? QString::fromUtf8( value ) |
394 | : QString::fromLatin1( value ) ); | 421 | : QString::fromLatin1( value ) ); |
395 | if ( haveEnt ) | 422 | if ( haveEnt ) |
396 | str = Qtopia::plainString( str ); | 423 | str = Qtopia::plainString( str ); |
397 | 424 | ||
398 | /* | 425 | /* |
399 | * add key + value | 426 | * add key + value |
400 | */ | 427 | */ |
401 | find = dict[attr.data()]; | 428 | find = dict[attr.data()]; |
402 | if (!find) | 429 | if (!find) |
403 | ev.setCustomField( attr, value ); | 430 | ev.setCustomField( attr, value ); |
404 | else { | 431 | else { |
405 | setField( ev, *find, value ); | 432 | setField( ev, *find, value ); |
406 | } | 433 | } |
407 | } | 434 | } |
408 | /* time to finalize */ | 435 | /* time to finalize */ |
409 | finalizeRecord( ev ); | 436 | finalizeRecord( ev ); |
410 | add( ev ); | 437 | add( ev ); |
411 | delete rec; | 438 | delete rec; |
412 | } | 439 | } |
413 | ::munmap(map_addr, attribute.st_size ); | 440 | ::munmap(map_addr, attribute.st_size ); |
414 | m_changed = false; // changed during add | 441 | m_changed = false; // changed during add |
415 | 442 | ||
416 | return true; | 443 | return true; |
417 | } | 444 | } |
418 | void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { | 445 | void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { |
419 | /* AllDay is alway in UTC */ | 446 | /* AllDay is alway in UTC */ |
420 | if ( ev.isAllDay() ) { | 447 | if ( ev.isAllDay() ) { |
421 | OTimeZone utc = OTimeZone::utc(); | 448 | OTimeZone utc = OTimeZone::utc(); |
422 | ev.setStartDateTime( utc.fromUTCDateTime( start ) ); | 449 | ev.setStartDateTime( utc.fromUTCDateTime( start ) ); |
423 | ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); | 450 | ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); |
424 | ev.setTimeZone( "UTC"); // make sure it is really utc | 451 | ev.setTimeZone( "UTC"); // make sure it is really utc |
425 | }else { | 452 | }else { |
426 | /* to current date time */ | 453 | /* to current date time */ |
427 | OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); | 454 | OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); |
428 | QDateTime date = zone.toDateTime( start ); | 455 | QDateTime date = zone.toDateTime( start ); |
429 | ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) ); | 456 | ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) ); |
430 | 457 | ||
431 | date = zone.toDateTime( end ); | 458 | date = zone.toDateTime( end ); |
432 | ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) ); | 459 | ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) ); |
433 | } | 460 | } |
434 | if ( rec && rec->doesRecur() ) { | 461 | if ( rec && rec->doesRecur() ) { |
435 | OTimeZone utc = OTimeZone::utc(); | 462 | OTimeZone utc = OTimeZone::utc(); |
436 | ORecur recu( *rec ); // call copy c'tor; | 463 | ORecur recu( *rec ); // call copy c'tor; |
437 | recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); | 464 | recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); |
438 | recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); | 465 | recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); |
439 | recu.setStart( ev.startDateTime().date() ); | 466 | recu.setStart( ev.startDateTime().date() ); |
440 | ev.setRecurrence( recu ); | 467 | ev.setRecurrence( recu ); |
441 | } | 468 | } |
442 | 469 | ||
443 | if (alarmTime != -1 ) { | 470 | if (alarmTime != -1 ) { |
444 | QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); | 471 | QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); |
445 | OPimAlarm al( snd , dt ); | 472 | OPimAlarm al( snd , dt ); |
446 | ev.notifiers().add( al ); | 473 | ev.notifiers().add( al ); |
447 | } | 474 | } |
448 | if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { | 475 | if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { |
449 | ev.setUid( 1 ); | 476 | ev.setUid( 1 ); |
450 | } | 477 | } |
451 | if ( ev.hasRecurrence() ) | 478 | if ( ev.hasRecurrence() ) |
452 | m_rep.insert( ev.uid(), ev ); | 479 | m_rep.insert( ev.uid(), ev ); |
453 | else | 480 | else |
454 | m_raw.insert( ev.uid(), ev ); | 481 | m_raw.insert( ev.uid(), ev ); |
455 | 482 | ||
456 | } | 483 | } |
457 | void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { | 484 | void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { |
458 | // qWarning(" setting %s", value.latin1() ); | 485 | // qWarning(" setting %s", value.latin1() ); |
459 | switch( id ) { | 486 | switch( id ) { |
460 | case FDescription: | 487 | case FDescription: |
461 | e.setDescription( value ); | 488 | e.setDescription( value ); |
462 | break; | 489 | break; |
463 | case FLocation: | 490 | case FLocation: |
464 | e.setLocation( value ); | 491 | e.setLocation( value ); |
465 | break; | 492 | break; |
466 | case FCategories: | 493 | case FCategories: |
467 | e.setCategories( e.idsFromString( value ) ); | 494 | e.setCategories( e.idsFromString( value ) ); |
468 | break; | 495 | break; |
469 | case FUid: | 496 | case FUid: |
470 | e.setUid( value.toInt() ); | 497 | e.setUid( value.toInt() ); |
471 | break; | 498 | break; |
472 | case FType: | 499 | case FType: |
473 | if ( value == "AllDay" ) { | 500 | if ( value == "AllDay" ) { |
474 | e.setAllDay( true ); | 501 | e.setAllDay( true ); |
475 | e.setTimeZone( "UTC" ); | 502 | e.setTimeZone( "UTC" ); |
476 | } | 503 | } |
477 | break; | 504 | break; |
478 | case FAlarm: | 505 | case FAlarm: |
479 | alarmTime = value.toInt(); | 506 | alarmTime = value.toInt(); |
480 | break; | 507 | break; |
481 | case FSound: | 508 | case FSound: |
482 | snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; | 509 | snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; |
483 | break; | 510 | break; |
484 | // recurrence stuff | 511 | // recurrence stuff |
485 | case FRType: | 512 | case FRType: |
486 | if ( value == "Daily" ) | 513 | if ( value == "Daily" ) |
487 | recur()->setType( ORecur::Daily ); | 514 | recur()->setType( ORecur::Daily ); |
488 | else if ( value == "Weekly" ) | 515 | else if ( value == "Weekly" ) |
489 | recur()->setType( ORecur::Weekly); | 516 | recur()->setType( ORecur::Weekly); |
490 | else if ( value == "MonthlyDay" ) | 517 | else if ( value == "MonthlyDay" ) |
491 | recur()->setType( ORecur::MonthlyDay ); | 518 | recur()->setType( ORecur::MonthlyDay ); |
492 | else if ( value == "MonthlyDate" ) | 519 | else if ( value == "MonthlyDate" ) |
493 | recur()->setType( ORecur::MonthlyDate ); | 520 | recur()->setType( ORecur::MonthlyDate ); |
494 | else if ( value == "Yearly" ) | 521 | else if ( value == "Yearly" ) |
495 | recur()->setType( ORecur::Yearly ); | 522 | recur()->setType( ORecur::Yearly ); |
496 | else | 523 | else |
497 | recur()->setType( ORecur::NoRepeat ); | 524 | recur()->setType( ORecur::NoRepeat ); |
498 | break; | 525 | break; |
499 | case FRWeekdays: | 526 | case FRWeekdays: |
500 | recur()->setDays( value.toInt() ); | 527 | recur()->setDays( value.toInt() ); |
501 | break; | 528 | break; |
502 | case FRPosition: | 529 | case FRPosition: |
503 | recur()->setPosition( value.toInt() ); | 530 | recur()->setPosition( value.toInt() ); |
504 | break; | 531 | break; |
505 | case FRFreq: | 532 | case FRFreq: |
506 | recur()->setFrequency( value.toInt() ); | 533 | recur()->setFrequency( value.toInt() ); |
507 | break; | 534 | break; |
508 | case FRHasEndDate: | 535 | case FRHasEndDate: |
509 | recur()->setHasEndDate( value.toInt() ); | 536 | recur()->setHasEndDate( value.toInt() ); |
510 | break; | 537 | break; |
511 | case FREndDate: { | 538 | case FREndDate: { |
512 | rp_end = (time_t) value.toLong(); | 539 | rp_end = (time_t) value.toLong(); |
513 | break; | 540 | break; |
514 | } | 541 | } |
515 | case FRStart: { | 542 | case FRStart: { |
516 | start = (time_t) value.toLong(); | 543 | start = (time_t) value.toLong(); |
517 | break; | 544 | break; |
518 | } | 545 | } |
519 | case FREnd: { | 546 | case FREnd: { |
520 | end = ( (time_t) value.toLong() ); | 547 | end = ( (time_t) value.toLong() ); |
521 | break; | 548 | break; |
522 | } | 549 | } |
523 | case FNote: | 550 | case FNote: |
524 | e.setNote( value ); | 551 | e.setNote( value ); |
525 | break; | 552 | break; |
526 | case FCreated: | 553 | case FCreated: |
527 | created = value.toInt(); | 554 | created = value.toInt(); |
528 | break; | 555 | break; |
529 | case FRecParent: | 556 | case FRecParent: |
530 | e.setParent( value.toInt() ); | 557 | e.setParent( value.toInt() ); |
531 | break; | 558 | break; |
532 | case FRecChildren:{ | 559 | case FRecChildren:{ |
533 | QStringList list = QStringList::split(' ', value ); | 560 | QStringList list = QStringList::split(' ', value ); |
534 | for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { | 561 | for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { |
535 | e.addChild( (*it).toInt() ); | 562 | e.addChild( (*it).toInt() ); |
536 | } | 563 | } |
537 | } | 564 | } |
538 | break; | 565 | break; |
539 | case FExceptions:{ | 566 | case FExceptions:{ |
540 | QStringList list = QStringList::split(' ', value ); | 567 | QStringList list = QStringList::split(' ', value ); |
541 | for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { | 568 | for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { |
542 | QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() ); | 569 | QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() ); |
543 | qWarning("adding exception %s", date.toString().latin1() ); | 570 | qWarning("adding exception %s", date.toString().latin1() ); |
544 | recur()->exceptions().append( date ); | 571 | recur()->exceptions().append( date ); |
545 | } | 572 | } |
546 | } | 573 | } |
547 | break; | 574 | break; |
548 | case FTimeZone: | 575 | case FTimeZone: |
549 | if ( value != "None" ) | 576 | if ( value != "None" ) |
550 | e.setTimeZone( value ); | 577 | e.setTimeZone( value ); |
551 | break; | 578 | break; |
552 | default: | 579 | default: |
553 | break; | 580 | break; |
554 | } | 581 | } |
555 | } | 582 | } |
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp index 22b2469..cda300b 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.cpp +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp | |||
@@ -1,647 +1,675 @@ | |||
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 "otodoaccessxml.h" | 18 | #include "otodoaccessxml.h" |
19 | 19 | ||
20 | namespace { | ||
21 | // FROM TT again | ||
22 | char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) | ||
23 | { | ||
24 | char needleChar; | ||
25 | char haystackChar; | ||
26 | if (!needle || !haystack || !hLen || !nLen) | ||
27 | return 0; | ||
28 | |||
29 | const char* hsearch = haystack; | ||
30 | |||
31 | if ((needleChar = *needle++) != 0) { | ||
32 | nLen--; //(to make up for needle++) | ||
33 | do { | ||
34 | do { | ||
35 | if ((haystackChar = *hsearch++) == 0) | ||
36 | return (0); | ||
37 | if (hsearch >= haystack + hLen) | ||
38 | return (0); | ||
39 | } while (haystackChar != needleChar); | ||
40 | } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); | ||
41 | hsearch--; | ||
42 | } | ||
43 | return ((char *)hsearch); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | |||
20 | OTodoAccessXML::OTodoAccessXML( const QString& appName, | 48 | OTodoAccessXML::OTodoAccessXML( const QString& appName, |
21 | const QString& fileName ) | 49 | const QString& fileName ) |
22 | : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) | 50 | : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) |
23 | { | 51 | { |
24 | if (!fileName.isEmpty() ) | 52 | if (!fileName.isEmpty() ) |
25 | m_file = fileName; | 53 | m_file = fileName; |
26 | else | 54 | else |
27 | m_file = Global::applicationFileName( "todolist", "todolist.xml" ); | 55 | m_file = Global::applicationFileName( "todolist", "todolist.xml" ); |
28 | } | 56 | } |
29 | OTodoAccessXML::~OTodoAccessXML() { | 57 | OTodoAccessXML::~OTodoAccessXML() { |
30 | 58 | ||
31 | } | 59 | } |
32 | bool OTodoAccessXML::load() { | 60 | bool OTodoAccessXML::load() { |
33 | m_opened = true; | 61 | m_opened = true; |
34 | m_changed = false; | 62 | m_changed = false; |
35 | /* initialize dict */ | 63 | /* initialize dict */ |
36 | /* | 64 | /* |
37 | * UPDATE dict if you change anything!!! | 65 | * UPDATE dict if you change anything!!! |
38 | */ | 66 | */ |
39 | QAsciiDict<int> dict(21); | 67 | QAsciiDict<int> dict(21); |
40 | dict.setAutoDelete( TRUE ); | 68 | dict.setAutoDelete( TRUE ); |
41 | dict.insert("Categories" , new int(OTodo::Category) ); | 69 | dict.insert("Categories" , new int(OTodo::Category) ); |
42 | dict.insert("Uid" , new int(OTodo::Uid) ); | 70 | dict.insert("Uid" , new int(OTodo::Uid) ); |
43 | dict.insert("HasDate" , new int(OTodo::HasDate) ); | 71 | dict.insert("HasDate" , new int(OTodo::HasDate) ); |
44 | dict.insert("Completed" , new int(OTodo::Completed) ); | 72 | dict.insert("Completed" , new int(OTodo::Completed) ); |
45 | dict.insert("Description" , new int(OTodo::Description) ); | 73 | dict.insert("Description" , new int(OTodo::Description) ); |
46 | dict.insert("Summary" , new int(OTodo::Summary) ); | 74 | dict.insert("Summary" , new int(OTodo::Summary) ); |
47 | dict.insert("Priority" , new int(OTodo::Priority) ); | 75 | dict.insert("Priority" , new int(OTodo::Priority) ); |
48 | dict.insert("DateDay" , new int(OTodo::DateDay) ); | 76 | dict.insert("DateDay" , new int(OTodo::DateDay) ); |
49 | dict.insert("DateMonth" , new int(OTodo::DateMonth) ); | 77 | dict.insert("DateMonth" , new int(OTodo::DateMonth) ); |
50 | dict.insert("DateYear" , new int(OTodo::DateYear) ); | 78 | dict.insert("DateYear" , new int(OTodo::DateYear) ); |
51 | dict.insert("Progress" , new int(OTodo::Progress) ); | 79 | dict.insert("Progress" , new int(OTodo::Progress) ); |
52 | dict.insert("Completed", new int(OTodo::Completed) ); | 80 | dict.insert("Completed", new int(OTodo::Completed) ); |
53 | dict.insert("CrossReference", new int(OTodo::CrossReference) ); | 81 | dict.insert("CrossReference", new int(OTodo::CrossReference) ); |
54 | dict.insert("State", new int(OTodo::State) ); | 82 | dict.insert("State", new int(OTodo::State) ); |
55 | dict.insert("Recurrence", new int(OTodo::Recurrence) ); | 83 | dict.insert("Recurrence", new int(OTodo::Recurrence) ); |
56 | dict.insert("Alarms", new int(OTodo::Alarms) ); | 84 | dict.insert("Alarms", new int(OTodo::Alarms) ); |
57 | dict.insert("Reminders", new int(OTodo::Reminders) ); | 85 | dict.insert("Reminders", new int(OTodo::Reminders) ); |
58 | dict.insert("Notifiers", new int(OTodo::Notifiers) ); | 86 | dict.insert("Notifiers", new int(OTodo::Notifiers) ); |
59 | dict.insert("Maintainer", new int(OTodo::Maintainer) ); | 87 | dict.insert("Maintainer", new int(OTodo::Maintainer) ); |
60 | 88 | ||
61 | // here the custom XML parser from TT it's GPL | 89 | // here the custom XML parser from TT it's GPL |
62 | // but we want to push OpiePIM... to TT..... | 90 | // but we want to push OpiePIM... to TT..... |
63 | // mmap part from zecke :) | 91 | // mmap part from zecke :) |
64 | int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); | 92 | int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); |
65 | struct stat attribut; | 93 | struct stat attribut; |
66 | if ( fd < 0 ) return false; | 94 | if ( fd < 0 ) return false; |
67 | 95 | ||
68 | if ( fstat(fd, &attribut ) == -1 ) { | 96 | if ( fstat(fd, &attribut ) == -1 ) { |
69 | ::close( fd ); | 97 | ::close( fd ); |
70 | return false; | 98 | return false; |
71 | } | 99 | } |
72 | void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); | 100 | void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); |
73 | if ( map_addr == ( (caddr_t)-1) ) { | 101 | if ( map_addr == ( (caddr_t)-1) ) { |
74 | ::close(fd ); | 102 | ::close(fd ); |
75 | return false; | 103 | return false; |
76 | } | 104 | } |
77 | /* advise the kernel who we want to read it */ | 105 | /* advise the kernel who we want to read it */ |
78 | ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); | 106 | ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); |
79 | /* we do not the file any more */ | 107 | /* we do not the file any more */ |
80 | ::close( fd ); | 108 | ::close( fd ); |
81 | 109 | ||
82 | char* dt = (char*)map_addr; | 110 | char* dt = (char*)map_addr; |
83 | int len = attribut.st_size; | 111 | int len = attribut.st_size; |
84 | int i = 0; | 112 | int i = 0; |
85 | char *point; | 113 | char *point; |
86 | const char* collectionString = "<Task "; | 114 | const char* collectionString = "<Task "; |
87 | int strLen = strlen(collectionString); | 115 | int strLen = strlen(collectionString); |
88 | while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { | 116 | while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) { |
89 | i = point -dt; | 117 | i = point -dt; |
90 | i+= strLen; | 118 | i+= strLen; |
91 | qWarning("Found a start at %d %d", i, (point-dt) ); | 119 | qWarning("Found a start at %d %d", i, (point-dt) ); |
92 | 120 | ||
93 | OTodo ev; | 121 | OTodo ev; |
94 | m_year = m_month = m_day = 0; | 122 | m_year = m_month = m_day = 0; |
95 | 123 | ||
96 | while ( TRUE ) { | 124 | while ( TRUE ) { |
97 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) | 125 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) |
98 | ++i; | 126 | ++i; |
99 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) | 127 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) |
100 | break; | 128 | break; |
101 | 129 | ||
102 | // we have another attribute, read it. | 130 | // we have another attribute, read it. |
103 | int j = i; | 131 | int j = i; |
104 | while ( j < len && dt[j] != '=' ) | 132 | while ( j < len && dt[j] != '=' ) |
105 | ++j; | 133 | ++j; |
106 | QCString attr( dt+i, j-i+1); | 134 | QCString attr( dt+i, j-i+1); |
107 | 135 | ||
108 | i = ++j; // skip = | 136 | i = ++j; // skip = |
109 | 137 | ||
110 | // find the start of quotes | 138 | // find the start of quotes |
111 | while ( i < len && dt[i] != '"' ) | 139 | while ( i < len && dt[i] != '"' ) |
112 | ++i; | 140 | ++i; |
113 | j = ++i; | 141 | j = ++i; |
114 | 142 | ||
115 | bool haveUtf = FALSE; | 143 | bool haveUtf = FALSE; |
116 | bool haveEnt = FALSE; | 144 | bool haveEnt = FALSE; |
117 | while ( j < len && dt[j] != '"' ) { | 145 | while ( j < len && dt[j] != '"' ) { |
118 | if ( ((unsigned char)dt[j]) > 0x7f ) | 146 | if ( ((unsigned char)dt[j]) > 0x7f ) |
119 | haveUtf = TRUE; | 147 | haveUtf = TRUE; |
120 | if ( dt[j] == '&' ) | 148 | if ( dt[j] == '&' ) |
121 | haveEnt = TRUE; | 149 | haveEnt = TRUE; |
122 | ++j; | 150 | ++j; |
123 | } | 151 | } |
124 | if ( i == j ) { | 152 | if ( i == j ) { |
125 | // empty value | 153 | // empty value |
126 | i = j + 1; | 154 | i = j + 1; |
127 | continue; | 155 | continue; |
128 | } | 156 | } |
129 | 157 | ||
130 | QCString value( dt+i, j-i+1 ); | 158 | QCString value( dt+i, j-i+1 ); |
131 | i = j + 1; | 159 | i = j + 1; |
132 | 160 | ||
133 | QString str = (haveUtf ? QString::fromUtf8( value ) | 161 | QString str = (haveUtf ? QString::fromUtf8( value ) |
134 | : QString::fromLatin1( value ) ); | 162 | : QString::fromLatin1( value ) ); |
135 | if ( haveEnt ) | 163 | if ( haveEnt ) |
136 | str = Qtopia::plainString( str ); | 164 | str = Qtopia::plainString( str ); |
137 | 165 | ||
138 | /* | 166 | /* |
139 | * add key + value | 167 | * add key + value |
140 | */ | 168 | */ |
141 | todo( &dict, ev, attr, str ); | 169 | todo( &dict, ev, attr, str ); |
142 | 170 | ||
143 | } | 171 | } |
144 | /* | 172 | /* |
145 | * now add it | 173 | * now add it |
146 | */ | 174 | */ |
147 | qWarning("End at %d", i ); | 175 | qWarning("End at %d", i ); |
148 | if (m_events.contains( ev.uid() ) || ev.uid() == 0) { | 176 | if (m_events.contains( ev.uid() ) || ev.uid() == 0) { |
149 | ev.setUid( 1 ); | 177 | ev.setUid( 1 ); |
150 | m_changed = true; | 178 | m_changed = true; |
151 | } | 179 | } |
152 | if ( ev.hasDueDate() ) { | 180 | if ( ev.hasDueDate() ) { |
153 | ev.setDueDate( QDate(m_year, m_month, m_day) ); | 181 | ev.setDueDate( QDate(m_year, m_month, m_day) ); |
154 | } | 182 | } |
155 | m_events.insert(ev.uid(), ev ); | 183 | m_events.insert(ev.uid(), ev ); |
156 | m_year = m_month = m_day = -1; | 184 | m_year = m_month = m_day = -1; |
157 | } | 185 | } |
158 | 186 | ||
159 | munmap(map_addr, attribut.st_size ); | 187 | munmap(map_addr, attribut.st_size ); |
160 | 188 | ||
161 | qWarning("counts %d records loaded!", m_events.count() ); | 189 | qWarning("counts %d records loaded!", m_events.count() ); |
162 | return true; | 190 | return true; |
163 | } | 191 | } |
164 | bool OTodoAccessXML::reload() { | 192 | bool OTodoAccessXML::reload() { |
165 | m_events.clear(); | 193 | m_events.clear(); |
166 | return load(); | 194 | return load(); |
167 | } | 195 | } |
168 | bool OTodoAccessXML::save() { | 196 | bool OTodoAccessXML::save() { |
169 | // qWarning("saving"); | 197 | // qWarning("saving"); |
170 | if (!m_opened || !m_changed ) { | 198 | if (!m_opened || !m_changed ) { |
171 | // qWarning("not saving"); | 199 | // qWarning("not saving"); |
172 | return true; | 200 | return true; |
173 | } | 201 | } |
174 | QString strNewFile = m_file + ".new"; | 202 | QString strNewFile = m_file + ".new"; |
175 | QFile f( strNewFile ); | 203 | QFile f( strNewFile ); |
176 | if (!f.open( IO_WriteOnly|IO_Raw ) ) | 204 | if (!f.open( IO_WriteOnly|IO_Raw ) ) |
177 | return false; | 205 | return false; |
178 | 206 | ||
179 | int written; | 207 | int written; |
180 | QString out; | 208 | QString out; |
181 | out = "<!DOCTYPE Tasks>\n<Tasks>\n"; | 209 | out = "<!DOCTYPE Tasks>\n<Tasks>\n"; |
182 | 210 | ||
183 | // for all todos | 211 | // for all todos |
184 | QMap<int, OTodo>::Iterator it; | 212 | QMap<int, OTodo>::Iterator it; |
185 | for (it = m_events.begin(); it != m_events.end(); ++it ) { | 213 | for (it = m_events.begin(); it != m_events.end(); ++it ) { |
186 | out+= "<Task " + toString( (*it) ) + " />\n"; | 214 | out+= "<Task " + toString( (*it) ) + " />\n"; |
187 | QCString cstr = out.utf8(); | 215 | QCString cstr = out.utf8(); |
188 | written = f.writeBlock( cstr.data(), cstr.length() ); | 216 | written = f.writeBlock( cstr.data(), cstr.length() ); |
189 | 217 | ||
190 | /* less written then we wanted */ | 218 | /* less written then we wanted */ |
191 | if ( written != (int)cstr.length() ) { | 219 | if ( written != (int)cstr.length() ) { |
192 | f.close(); | 220 | f.close(); |
193 | QFile::remove( strNewFile ); | 221 | QFile::remove( strNewFile ); |
194 | return false; | 222 | return false; |
195 | } | 223 | } |
196 | out = QString::null; | 224 | out = QString::null; |
197 | } | 225 | } |
198 | 226 | ||
199 | out += "</Tasks>"; | 227 | out += "</Tasks>"; |
200 | QCString cstr = out.utf8(); | 228 | QCString cstr = out.utf8(); |
201 | written = f.writeBlock( cstr.data(), cstr.length() ); | 229 | written = f.writeBlock( cstr.data(), cstr.length() ); |
202 | 230 | ||
203 | if ( written != (int)cstr.length() ) { | 231 | if ( written != (int)cstr.length() ) { |
204 | f.close(); | 232 | f.close(); |
205 | QFile::remove( strNewFile ); | 233 | QFile::remove( strNewFile ); |
206 | return false; | 234 | return false; |
207 | } | 235 | } |
208 | /* flush before renaming */ | 236 | /* flush before renaming */ |
209 | f.close(); | 237 | f.close(); |
210 | 238 | ||
211 | if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { | 239 | if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { |
212 | // qWarning("error renaming"); | 240 | // qWarning("error renaming"); |
213 | QFile::remove( strNewFile ); | 241 | QFile::remove( strNewFile ); |
214 | } | 242 | } |
215 | 243 | ||
216 | m_changed = false; | 244 | m_changed = false; |
217 | return true; | 245 | return true; |
218 | } | 246 | } |
219 | QArray<int> OTodoAccessXML::allRecords()const { | 247 | QArray<int> OTodoAccessXML::allRecords()const { |
220 | QArray<int> ids( m_events.count() ); | 248 | QArray<int> ids( m_events.count() ); |
221 | QMap<int, OTodo>::ConstIterator it; | 249 | QMap<int, OTodo>::ConstIterator it; |
222 | int i = 0; | 250 | int i = 0; |
223 | 251 | ||
224 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 252 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
225 | ids[i] = it.key(); | 253 | ids[i] = it.key(); |
226 | i++; | 254 | i++; |
227 | } | 255 | } |
228 | return ids; | 256 | return ids; |
229 | } | 257 | } |
230 | QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { | 258 | QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { |
231 | QArray<int> ids(0); | 259 | QArray<int> ids(0); |
232 | return ids; | 260 | return ids; |
233 | } | 261 | } |
234 | OTodo OTodoAccessXML::find( int uid )const { | 262 | OTodo OTodoAccessXML::find( int uid )const { |
235 | OTodo todo; | 263 | OTodo todo; |
236 | todo.setUid( 0 ); // isEmpty() | 264 | todo.setUid( 0 ); // isEmpty() |
237 | QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); | 265 | QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); |
238 | if ( it != m_events.end() ) | 266 | if ( it != m_events.end() ) |
239 | todo = it.data(); | 267 | todo = it.data(); |
240 | 268 | ||
241 | return todo; | 269 | return todo; |
242 | } | 270 | } |
243 | void OTodoAccessXML::clear() { | 271 | void OTodoAccessXML::clear() { |
244 | if (m_opened ) | 272 | if (m_opened ) |
245 | m_changed = true; | 273 | m_changed = true; |
246 | 274 | ||
247 | m_events.clear(); | 275 | m_events.clear(); |
248 | } | 276 | } |
249 | bool OTodoAccessXML::add( const OTodo& todo ) { | 277 | bool OTodoAccessXML::add( const OTodo& todo ) { |
250 | // qWarning("add"); | 278 | // qWarning("add"); |
251 | m_changed = true; | 279 | m_changed = true; |
252 | m_events.insert( todo.uid(), todo ); | 280 | m_events.insert( todo.uid(), todo ); |
253 | 281 | ||
254 | return true; | 282 | return true; |
255 | } | 283 | } |
256 | bool OTodoAccessXML::remove( int uid ) { | 284 | bool OTodoAccessXML::remove( int uid ) { |
257 | m_changed = true; | 285 | m_changed = true; |
258 | m_events.remove( uid ); | 286 | m_events.remove( uid ); |
259 | 287 | ||
260 | return true; | 288 | return true; |
261 | } | 289 | } |
262 | bool OTodoAccessXML::replace( const OTodo& todo) { | 290 | bool OTodoAccessXML::replace( const OTodo& todo) { |
263 | m_changed = true; | 291 | m_changed = true; |
264 | m_events.replace( todo.uid(), todo ); | 292 | m_events.replace( todo.uid(), todo ); |
265 | 293 | ||
266 | return true; | 294 | return true; |
267 | } | 295 | } |
268 | QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, | 296 | QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, |
269 | const QDate& end, | 297 | const QDate& end, |
270 | bool includeNoDates ) { | 298 | bool includeNoDates ) { |
271 | QArray<int> ids( m_events.count() ); | 299 | QArray<int> ids( m_events.count() ); |
272 | QMap<int, OTodo>::Iterator it; | 300 | QMap<int, OTodo>::Iterator it; |
273 | 301 | ||
274 | int i = 0; | 302 | int i = 0; |
275 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 303 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
276 | if ( !it.data().hasDueDate() ) { | 304 | if ( !it.data().hasDueDate() ) { |
277 | if ( includeNoDates ) { | 305 | if ( includeNoDates ) { |
278 | ids[i] = it.key(); | 306 | ids[i] = it.key(); |
279 | i++; | 307 | i++; |
280 | } | 308 | } |
281 | }else if ( it.data().dueDate() >= start && | 309 | }else if ( it.data().dueDate() >= start && |
282 | it.data().dueDate() <= end ) { | 310 | it.data().dueDate() <= end ) { |
283 | ids[i] = it.key(); | 311 | ids[i] = it.key(); |
284 | i++; | 312 | i++; |
285 | } | 313 | } |
286 | } | 314 | } |
287 | ids.resize( i ); | 315 | ids.resize( i ); |
288 | return ids; | 316 | return ids; |
289 | } | 317 | } |
290 | QArray<int> OTodoAccessXML::overDue() { | 318 | QArray<int> OTodoAccessXML::overDue() { |
291 | QArray<int> ids( m_events.count() ); | 319 | QArray<int> ids( m_events.count() ); |
292 | int i = 0; | 320 | int i = 0; |
293 | 321 | ||
294 | QMap<int, OTodo>::Iterator it; | 322 | QMap<int, OTodo>::Iterator it; |
295 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 323 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
296 | if ( it.data().isOverdue() ) { | 324 | if ( it.data().isOverdue() ) { |
297 | ids[i] = it.key(); | 325 | ids[i] = it.key(); |
298 | i++; | 326 | i++; |
299 | } | 327 | } |
300 | } | 328 | } |
301 | ids.resize( i ); | 329 | ids.resize( i ); |
302 | return ids; | 330 | return ids; |
303 | } | 331 | } |
304 | 332 | ||
305 | 333 | ||
306 | /* private */ | 334 | /* private */ |
307 | void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, | 335 | void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, |
308 | const QCString& attr, const QString& val) { | 336 | const QCString& attr, const QString& val) { |
309 | // qWarning("parse to do from XMLElement" ); | 337 | // qWarning("parse to do from XMLElement" ); |
310 | 338 | ||
311 | int *find=0; | 339 | int *find=0; |
312 | 340 | ||
313 | find = (*dict)[ attr.data() ]; | 341 | find = (*dict)[ attr.data() ]; |
314 | if (!find ) { | 342 | if (!find ) { |
315 | // qWarning("Unknown option" + it.key() ); | 343 | // qWarning("Unknown option" + it.key() ); |
316 | ev.setCustomField( attr, val ); | 344 | ev.setCustomField( attr, val ); |
317 | return; | 345 | return; |
318 | } | 346 | } |
319 | 347 | ||
320 | switch( *find ) { | 348 | switch( *find ) { |
321 | case OTodo::Uid: | 349 | case OTodo::Uid: |
322 | ev.setUid( val.toInt() ); | 350 | ev.setUid( val.toInt() ); |
323 | break; | 351 | break; |
324 | case OTodo::Category: | 352 | case OTodo::Category: |
325 | ev.setCategories( ev.idsFromString( val ) ); | 353 | ev.setCategories( ev.idsFromString( val ) ); |
326 | break; | 354 | break; |
327 | case OTodo::HasDate: | 355 | case OTodo::HasDate: |
328 | ev.setHasDueDate( val.toInt() ); | 356 | ev.setHasDueDate( val.toInt() ); |
329 | break; | 357 | break; |
330 | case OTodo::Completed: | 358 | case OTodo::Completed: |
331 | ev.setCompleted( val.toInt() ); | 359 | ev.setCompleted( val.toInt() ); |
332 | break; | 360 | break; |
333 | case OTodo::Description: | 361 | case OTodo::Description: |
334 | ev.setDescription( val ); | 362 | ev.setDescription( val ); |
335 | break; | 363 | break; |
336 | case OTodo::Summary: | 364 | case OTodo::Summary: |
337 | ev.setSummary( val ); | 365 | ev.setSummary( val ); |
338 | break; | 366 | break; |
339 | case OTodo::Priority: | 367 | case OTodo::Priority: |
340 | ev.setPriority( val.toInt() ); | 368 | ev.setPriority( val.toInt() ); |
341 | break; | 369 | break; |
342 | case OTodo::DateDay: | 370 | case OTodo::DateDay: |
343 | m_day = val.toInt(); | 371 | m_day = val.toInt(); |
344 | break; | 372 | break; |
345 | case OTodo::DateMonth: | 373 | case OTodo::DateMonth: |
346 | m_month = val.toInt(); | 374 | m_month = val.toInt(); |
347 | break; | 375 | break; |
348 | case OTodo::DateYear: | 376 | case OTodo::DateYear: |
349 | m_year = val.toInt(); | 377 | m_year = val.toInt(); |
350 | break; | 378 | break; |
351 | case OTodo::Progress: | 379 | case OTodo::Progress: |
352 | ev.setProgress( val.toInt() ); | 380 | ev.setProgress( val.toInt() ); |
353 | break; | 381 | break; |
354 | case OTodo::CrossReference: | 382 | case OTodo::CrossReference: |
355 | { | 383 | { |
356 | /* | 384 | /* |
357 | * A cross refernce looks like | 385 | * A cross refernce looks like |
358 | * appname,id;appname,id | 386 | * appname,id;appname,id |
359 | * we need to split it up | 387 | * we need to split it up |
360 | */ | 388 | */ |
361 | QStringList refs = QStringList::split(';', val ); | 389 | QStringList refs = QStringList::split(';', val ); |
362 | QStringList::Iterator strIt; | 390 | QStringList::Iterator strIt; |
363 | for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { | 391 | for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { |
364 | int pos = (*strIt).find(','); | 392 | int pos = (*strIt).find(','); |
365 | if ( pos > -1 ) | 393 | if ( pos > -1 ) |
366 | ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); | 394 | ; // ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); |
367 | 395 | ||
368 | } | 396 | } |
369 | break; | 397 | break; |
370 | } | 398 | } |
371 | default: | 399 | default: |
372 | break; | 400 | break; |
373 | } | 401 | } |
374 | } | 402 | } |
375 | QString OTodoAccessXML::toString( const OTodo& ev )const { | 403 | QString OTodoAccessXML::toString( const OTodo& ev )const { |
376 | QString str; | 404 | QString str; |
377 | 405 | ||
378 | str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; | 406 | str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; |
379 | str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; | 407 | str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; |
380 | str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; | 408 | str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; |
381 | str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; | 409 | str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; |
382 | 410 | ||
383 | str += "Categories=\"" + toString( ev.categories() ) + "\" "; | 411 | str += "Categories=\"" + toString( ev.categories() ) + "\" "; |
384 | str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; | 412 | str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; |
385 | str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; | 413 | str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; |
386 | 414 | ||
387 | if ( ev.hasDueDate() ) { | 415 | if ( ev.hasDueDate() ) { |
388 | str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; | 416 | str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; |
389 | str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; | 417 | str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; |
390 | str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; | 418 | str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; |
391 | } | 419 | } |
392 | // qWarning( "Uid %d", ev.uid() ); | 420 | // qWarning( "Uid %d", ev.uid() ); |
393 | str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; | 421 | str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; |
394 | 422 | ||
395 | // append the extra options | 423 | // append the extra options |
396 | /* FIXME Qtopia::Record this is currently not | 424 | /* FIXME Qtopia::Record this is currently not |
397 | * possible you can set custom fields | 425 | * possible you can set custom fields |
398 | * but don' iterate over the list | 426 | * but don' iterate over the list |
399 | * I may do #define private protected | 427 | * I may do #define private protected |
400 | * for this case - cough --zecke | 428 | * for this case - cough --zecke |
401 | */ | 429 | */ |
402 | /* | 430 | /* |
403 | QMap<QString, QString> extras = ev.extras(); | 431 | QMap<QString, QString> extras = ev.extras(); |
404 | QMap<QString, QString>::Iterator extIt; | 432 | QMap<QString, QString>::Iterator extIt; |
405 | for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) | 433 | for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) |
406 | str += extIt.key() + "=\"" + extIt.data() + "\" "; | 434 | str += extIt.key() + "=\"" + extIt.data() + "\" "; |
407 | */ | 435 | */ |
408 | // cross refernce | 436 | // cross refernce |
409 | 437 | ||
410 | 438 | ||
411 | return str; | 439 | return str; |
412 | } | 440 | } |
413 | QString OTodoAccessXML::toString( const QArray<int>& ints ) const { | 441 | QString OTodoAccessXML::toString( const QArray<int>& ints ) const { |
414 | return Qtopia::Record::idsToString( ints ); | 442 | return Qtopia::Record::idsToString( ints ); |
415 | } | 443 | } |
416 | 444 | ||
417 | /* internal class for sorting | 445 | /* internal class for sorting |
418 | * | 446 | * |
419 | * Inspired by todoxmlio.cpp from TT | 447 | * Inspired by todoxmlio.cpp from TT |
420 | */ | 448 | */ |
421 | 449 | ||
422 | struct OTodoXMLContainer { | 450 | struct OTodoXMLContainer { |
423 | OTodo todo; | 451 | OTodo todo; |
424 | }; | 452 | }; |
425 | 453 | ||
426 | namespace { | 454 | namespace { |
427 | inline QString string( const OTodo& todo) { | 455 | inline QString string( const OTodo& todo) { |
428 | return todo.summary().isEmpty() ? | 456 | return todo.summary().isEmpty() ? |
429 | todo.description().left(20 ) : | 457 | todo.description().left(20 ) : |
430 | todo.summary(); | 458 | todo.summary(); |
431 | } | 459 | } |
432 | inline int completed( const OTodo& todo1, const OTodo& todo2) { | 460 | inline int completed( const OTodo& todo1, const OTodo& todo2) { |
433 | int ret = 0; | 461 | int ret = 0; |
434 | if ( todo1.isCompleted() ) ret++; | 462 | if ( todo1.isCompleted() ) ret++; |
435 | if ( todo2.isCompleted() ) ret--; | 463 | if ( todo2.isCompleted() ) ret--; |
436 | return ret; | 464 | return ret; |
437 | } | 465 | } |
438 | inline int priority( const OTodo& t1, const OTodo& t2) { | 466 | inline int priority( const OTodo& t1, const OTodo& t2) { |
439 | return ( t1.priority() - t2.priority() ); | 467 | return ( t1.priority() - t2.priority() ); |
440 | } | 468 | } |
441 | inline int description( const OTodo& t1, const OTodo& t2) { | 469 | inline int description( const OTodo& t1, const OTodo& t2) { |
442 | return QString::compare( string(t1), string(t2) ); | 470 | return QString::compare( string(t1), string(t2) ); |
443 | } | 471 | } |
444 | inline int deadline( const OTodo& t1, const OTodo& t2) { | 472 | inline int deadline( const OTodo& t1, const OTodo& t2) { |
445 | int ret = 0; | 473 | int ret = 0; |
446 | if ( t1.hasDueDate() && | 474 | if ( t1.hasDueDate() && |
447 | t2.hasDueDate() ) | 475 | t2.hasDueDate() ) |
448 | ret = t2.dueDate().daysTo( t1.dueDate() ); | 476 | ret = t2.dueDate().daysTo( t1.dueDate() ); |
449 | else if ( t1.hasDueDate() ) | 477 | else if ( t1.hasDueDate() ) |
450 | ret = -1; | 478 | ret = -1; |
451 | else if ( t2.hasDueDate() ) | 479 | else if ( t2.hasDueDate() ) |
452 | ret = 1; | 480 | ret = 1; |
453 | else | 481 | else |
454 | ret = 0; | 482 | ret = 0; |
455 | 483 | ||
456 | return ret; | 484 | return ret; |
457 | } | 485 | } |
458 | 486 | ||
459 | }; | 487 | }; |
460 | 488 | ||
461 | /* | 489 | /* |
462 | * Returns: | 490 | * Returns: |
463 | * 0 if item1 == item2 | 491 | * 0 if item1 == item2 |
464 | * | 492 | * |
465 | * non-zero if item1 != item2 | 493 | * non-zero if item1 != item2 |
466 | * | 494 | * |
467 | * This function returns int rather than bool so that reimplementations | 495 | * This function returns int rather than bool so that reimplementations |
468 | * can return one of three values and use it to sort by: | 496 | * can return one of three values and use it to sort by: |
469 | * | 497 | * |
470 | * 0 if item1 == item2 | 498 | * 0 if item1 == item2 |
471 | * | 499 | * |
472 | * > 0 (positive integer) if item1 > item2 | 500 | * > 0 (positive integer) if item1 > item2 |
473 | * | 501 | * |
474 | * < 0 (negative integer) if item1 < item2 | 502 | * < 0 (negative integer) if item1 < item2 |
475 | * | 503 | * |
476 | */ | 504 | */ |
477 | class OTodoXMLVector : public QVector<OTodoXMLContainer> { | 505 | class OTodoXMLVector : public QVector<OTodoXMLContainer> { |
478 | public: | 506 | public: |
479 | OTodoXMLVector(int size, bool asc, int sort) | 507 | OTodoXMLVector(int size, bool asc, int sort) |
480 | : QVector<OTodoXMLContainer>( size ) | 508 | : QVector<OTodoXMLContainer>( size ) |
481 | { | 509 | { |
482 | setAutoDelete( true ); | 510 | setAutoDelete( true ); |
483 | m_asc = asc; | 511 | m_asc = asc; |
484 | m_sort = sort; | 512 | m_sort = sort; |
485 | } | 513 | } |
486 | /* return the summary/description */ | 514 | /* return the summary/description */ |
487 | QString string( const OTodo& todo) { | 515 | QString string( const OTodo& todo) { |
488 | return todo.summary().isEmpty() ? | 516 | return todo.summary().isEmpty() ? |
489 | todo.description().left(20 ) : | 517 | todo.description().left(20 ) : |
490 | todo.summary(); | 518 | todo.summary(); |
491 | } | 519 | } |
492 | /** | 520 | /** |
493 | * we take the sortorder( switch on it ) | 521 | * we take the sortorder( switch on it ) |
494 | * | 522 | * |
495 | */ | 523 | */ |
496 | int compareItems( Item d1, Item d2 ) { | 524 | int compareItems( Item d1, Item d2 ) { |
497 | bool seComp, sePrio, seDesc, seDeadline; | 525 | bool seComp, sePrio, seDesc, seDeadline; |
498 | seComp = sePrio = seDeadline = seDesc = false; | 526 | seComp = sePrio = seDeadline = seDesc = false; |
499 | int ret =0; | 527 | int ret =0; |
500 | OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; | 528 | OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; |
501 | OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; | 529 | OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; |
502 | 530 | ||
503 | /* same item */ | 531 | /* same item */ |
504 | if ( con1->todo.uid() == con2->todo.uid() ) | 532 | if ( con1->todo.uid() == con2->todo.uid() ) |
505 | return 0; | 533 | return 0; |
506 | 534 | ||
507 | switch ( m_sort ) { | 535 | switch ( m_sort ) { |
508 | /* completed */ | 536 | /* completed */ |
509 | case 0: { | 537 | case 0: { |
510 | ret = completed( con1->todo, con2->todo ); | 538 | ret = completed( con1->todo, con2->todo ); |
511 | seComp = TRUE; | 539 | seComp = TRUE; |
512 | break; | 540 | break; |
513 | } | 541 | } |
514 | /* priority */ | 542 | /* priority */ |
515 | case 1: { | 543 | case 1: { |
516 | ret = priority( con1->todo, con2->todo ); | 544 | ret = priority( con1->todo, con2->todo ); |
517 | sePrio = TRUE; | 545 | sePrio = TRUE; |
518 | break; | 546 | break; |
519 | } | 547 | } |
520 | /* description */ | 548 | /* description */ |
521 | case 2: { | 549 | case 2: { |
522 | ret = description( con1->todo, con2->todo ); | 550 | ret = description( con1->todo, con2->todo ); |
523 | seDesc = TRUE; | 551 | seDesc = TRUE; |
524 | break; | 552 | break; |
525 | } | 553 | } |
526 | /* deadline */ | 554 | /* deadline */ |
527 | case 3: { | 555 | case 3: { |
528 | ret = deadline( con1->todo, con2->todo ); | 556 | ret = deadline( con1->todo, con2->todo ); |
529 | seDeadline = TRUE; | 557 | seDeadline = TRUE; |
530 | break; | 558 | break; |
531 | } | 559 | } |
532 | default: | 560 | default: |
533 | ret = 0; | 561 | ret = 0; |
534 | break; | 562 | break; |
535 | }; | 563 | }; |
536 | /* | 564 | /* |
537 | * FIXME do better sorting if the first sort criteria | 565 | * FIXME do better sorting if the first sort criteria |
538 | * ret equals 0 start with complete and so on... | 566 | * ret equals 0 start with complete and so on... |
539 | */ | 567 | */ |
540 | 568 | ||
541 | /* twist it we're not ascending*/ | 569 | /* twist it we're not ascending*/ |
542 | if (!m_asc) | 570 | if (!m_asc) |
543 | ret = ret * -1; | 571 | ret = ret * -1; |
544 | 572 | ||
545 | if ( ret ) | 573 | if ( ret ) |
546 | return ret; | 574 | return ret; |
547 | 575 | ||
548 | // default did not gave difference let's try it other way around | 576 | // default did not gave difference let's try it other way around |
549 | /* | 577 | /* |
550 | * General try if already checked if not test | 578 | * General try if already checked if not test |
551 | * and return | 579 | * and return |
552 | * 1.Completed | 580 | * 1.Completed |
553 | * 2.Priority | 581 | * 2.Priority |
554 | * 3.Description | 582 | * 3.Description |
555 | * 4.DueDate | 583 | * 4.DueDate |
556 | */ | 584 | */ |
557 | if (!seComp ) { | 585 | if (!seComp ) { |
558 | if ( (ret = completed( con1->todo, con2->todo ) ) ) { | 586 | if ( (ret = completed( con1->todo, con2->todo ) ) ) { |
559 | if (!m_asc ) ret *= -1; | 587 | if (!m_asc ) ret *= -1; |
560 | return ret; | 588 | return ret; |
561 | } | 589 | } |
562 | } | 590 | } |
563 | if (!sePrio ) { | 591 | if (!sePrio ) { |
564 | if ( (ret = priority( con1->todo, con2->todo ) ) ) { | 592 | if ( (ret = priority( con1->todo, con2->todo ) ) ) { |
565 | if (!m_asc ) ret *= -1; | 593 | if (!m_asc ) ret *= -1; |
566 | return ret; | 594 | return ret; |
567 | } | 595 | } |
568 | } | 596 | } |
569 | if (!seDesc ) { | 597 | if (!seDesc ) { |
570 | if ( (ret = description(con1->todo, con2->todo ) ) ) { | 598 | if ( (ret = description(con1->todo, con2->todo ) ) ) { |
571 | if (!m_asc) ret *= -1; | 599 | if (!m_asc) ret *= -1; |
572 | return ret; | 600 | return ret; |
573 | } | 601 | } |
574 | } | 602 | } |
575 | if (!seDeadline) { | 603 | if (!seDeadline) { |
576 | if ( (ret = deadline( con1->todo, con2->todo ) ) ) { | 604 | if ( (ret = deadline( con1->todo, con2->todo ) ) ) { |
577 | if (!m_asc) ret *= -1; | 605 | if (!m_asc) ret *= -1; |
578 | return ret; | 606 | return ret; |
579 | } | 607 | } |
580 | } | 608 | } |
581 | 609 | ||
582 | return 0; | 610 | return 0; |
583 | } | 611 | } |
584 | private: | 612 | private: |
585 | bool m_asc; | 613 | bool m_asc; |
586 | int m_sort; | 614 | int m_sort; |
587 | 615 | ||
588 | }; | 616 | }; |
589 | 617 | ||
590 | QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, | 618 | QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, |
591 | int sortFilter, int cat ) { | 619 | int sortFilter, int cat ) { |
592 | qWarning("sorted! %d cat", cat); | 620 | qWarning("sorted! %d cat", cat); |
593 | OTodoXMLVector vector(m_events.count(), asc,sortOrder ); | 621 | OTodoXMLVector vector(m_events.count(), asc,sortOrder ); |
594 | QMap<int, OTodo>::Iterator it; | 622 | QMap<int, OTodo>::Iterator it; |
595 | int item = 0; | 623 | int item = 0; |
596 | 624 | ||
597 | bool bCat = sortFilter & 1 ? true : false; | 625 | bool bCat = sortFilter & 1 ? true : false; |
598 | bool bOnly = sortFilter & 2 ? true : false; | 626 | bool bOnly = sortFilter & 2 ? true : false; |
599 | bool comp = sortFilter & 4 ? true : false; | 627 | bool comp = sortFilter & 4 ? true : false; |
600 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 628 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
601 | 629 | ||
602 | /* show category */ | 630 | /* show category */ |
603 | if ( bCat && cat != 0) | 631 | if ( bCat && cat != 0) |
604 | if (!(*it).categories().contains( cat ) ) { | 632 | if (!(*it).categories().contains( cat ) ) { |
605 | qWarning("category mis match"); | 633 | qWarning("category mis match"); |
606 | continue; | 634 | continue; |
607 | } | 635 | } |
608 | /* isOverdue but we should not show overdue - why?*/ | 636 | /* isOverdue but we should not show overdue - why?*/ |
609 | /* if ( (*it).isOverdue() && !bOnly ) { | 637 | /* if ( (*it).isOverdue() && !bOnly ) { |
610 | qWarning("item is overdue but !bOnly"); | 638 | qWarning("item is overdue but !bOnly"); |
611 | continue; | 639 | continue; |
612 | } | 640 | } |
613 | */ | 641 | */ |
614 | if ( !(*it).isOverdue() && bOnly ) { | 642 | if ( !(*it).isOverdue() && bOnly ) { |
615 | qWarning("item is not overdue but bOnly checked"); | 643 | qWarning("item is not overdue but bOnly checked"); |
616 | continue; | 644 | continue; |
617 | } | 645 | } |
618 | 646 | ||
619 | if ((*it).isCompleted() && comp ) { | 647 | if ((*it).isCompleted() && comp ) { |
620 | qWarning("completed continue!"); | 648 | qWarning("completed continue!"); |
621 | continue; | 649 | continue; |
622 | } | 650 | } |
623 | 651 | ||
624 | 652 | ||
625 | OTodoXMLContainer* con = new OTodoXMLContainer(); | 653 | OTodoXMLContainer* con = new OTodoXMLContainer(); |
626 | con->todo = (*it); | 654 | con->todo = (*it); |
627 | vector.insert(item, con ); | 655 | vector.insert(item, con ); |
628 | item++; | 656 | item++; |
629 | } | 657 | } |
630 | qWarning("XXX %d Items added", item); | 658 | qWarning("XXX %d Items added", item); |
631 | vector.resize( item ); | 659 | vector.resize( item ); |
632 | /* sort it now */ | 660 | /* sort it now */ |
633 | vector.sort(); | 661 | vector.sort(); |
634 | /* now get the uids */ | 662 | /* now get the uids */ |
635 | QArray<int> array( vector.count() ); | 663 | QArray<int> array( vector.count() ); |
636 | for (uint i= 0; i < vector.count(); i++ ) { | 664 | for (uint i= 0; i < vector.count(); i++ ) { |
637 | array[i] = ( vector.at(i) )->todo.uid(); | 665 | array[i] = ( vector.at(i) )->todo.uid(); |
638 | } | 666 | } |
639 | qWarning("array count = %d %d", array.count(), vector.count() ); | 667 | qWarning("array count = %d %d", array.count(), vector.count() ); |
640 | return array; | 668 | return array; |
641 | }; | 669 | }; |
642 | void OTodoAccessXML::removeAllCompleted() { | 670 | void OTodoAccessXML::removeAllCompleted() { |
643 | for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { | 671 | for ( QMap<int, OTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { |
644 | if ( (*it).isCompleted() ) | 672 | if ( (*it).isCompleted() ) |
645 | m_events.remove( it ); | 673 | m_events.remove( it ); |
646 | } | 674 | } |
647 | } | 675 | } |