-rw-r--r-- | libopie/pim/otodoaccessxml.cpp | 120 | ||||
-rw-r--r-- | libopie2/opiepim/backend/otodoaccessxml.cpp | 120 |
2 files changed, 188 insertions, 52 deletions
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp index 385fd27..591e467 100644 --- a/libopie/pim/otodoaccessxml.cpp +++ b/libopie/pim/otodoaccessxml.cpp | |||
@@ -26,541 +26,609 @@ bool OTodoAccessXML::load() { | |||
26 | m_changed = false; | 26 | m_changed = false; |
27 | /* initialize dict */ | 27 | /* initialize dict */ |
28 | /* | 28 | /* |
29 | * UPDATE dict if you change anything!!! | 29 | * UPDATE dict if you change anything!!! |
30 | */ | 30 | */ |
31 | QAsciiDict<int> dict(15); | 31 | QAsciiDict<int> dict(15); |
32 | dict.setAutoDelete( TRUE ); | 32 | dict.setAutoDelete( TRUE ); |
33 | dict.insert("Categories" , new int(OTodo::Category) ); | 33 | dict.insert("Categories" , new int(OTodo::Category) ); |
34 | dict.insert("Uid" , new int(OTodo::Uid) ); | 34 | dict.insert("Uid" , new int(OTodo::Uid) ); |
35 | dict.insert("HasDate" , new int(OTodo::HasDate) ); | 35 | dict.insert("HasDate" , new int(OTodo::HasDate) ); |
36 | dict.insert("Completed" , new int(OTodo::Completed) ); | 36 | dict.insert("Completed" , new int(OTodo::Completed) ); |
37 | dict.insert("Description" , new int(OTodo::Description) ); | 37 | dict.insert("Description" , new int(OTodo::Description) ); |
38 | dict.insert("Summary" , new int(OTodo::Summary) ); | 38 | dict.insert("Summary" , new int(OTodo::Summary) ); |
39 | dict.insert("Priority" , new int(OTodo::Priority) ); | 39 | dict.insert("Priority" , new int(OTodo::Priority) ); |
40 | dict.insert("DateDay" , new int(OTodo::DateDay) ); | 40 | dict.insert("DateDay" , new int(OTodo::DateDay) ); |
41 | dict.insert("DateMonth" , new int(OTodo::DateMonth) ); | 41 | dict.insert("DateMonth" , new int(OTodo::DateMonth) ); |
42 | dict.insert("DateYear" , new int(OTodo::DateYear) ); | 42 | dict.insert("DateYear" , new int(OTodo::DateYear) ); |
43 | dict.insert("Progress" , new int(OTodo::Progress) ); | 43 | dict.insert("Progress" , new int(OTodo::Progress) ); |
44 | dict.insert("Completed", new int(OTodo::Completed) ); | 44 | dict.insert("Completed", new int(OTodo::Completed) ); |
45 | dict.insert("CrossReference", new int(OTodo::CrossReference) ); | 45 | dict.insert("CrossReference", new int(OTodo::CrossReference) ); |
46 | dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); | 46 | dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); |
47 | dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); | 47 | dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); |
48 | 48 | ||
49 | // here the custom XML parser from TT it's GPL | 49 | // here the custom XML parser from TT it's GPL |
50 | // but we want to push that to TT..... | 50 | // but we want to push that to TT..... |
51 | QFile f(m_file ); | 51 | QFile f(m_file ); |
52 | if (!f.open(IO_ReadOnly) ) | 52 | if (!f.open(IO_ReadOnly) ) |
53 | return false; | 53 | return false; |
54 | 54 | ||
55 | QByteArray ba = f.readAll(); | 55 | QByteArray ba = f.readAll(); |
56 | f.close(); | 56 | f.close(); |
57 | char* dt = ba.data(); | 57 | char* dt = ba.data(); |
58 | int len = ba.size(); | 58 | int len = ba.size(); |
59 | int i = 0; | 59 | int i = 0; |
60 | char *point; | 60 | char *point; |
61 | const char* collectionString = "<Task "; | 61 | const char* collectionString = "<Task "; |
62 | while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { | 62 | while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { |
63 | i = point -dt; | 63 | i = point -dt; |
64 | i+= strlen(collectionString); | 64 | i+= strlen(collectionString); |
65 | OTodo ev; | 65 | OTodo ev; |
66 | m_year = m_month = m_day = 0; | 66 | m_year = m_month = m_day = 0; |
67 | 67 | ||
68 | while ( TRUE ) { | 68 | while ( TRUE ) { |
69 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) | 69 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) |
70 | ++i; | 70 | ++i; |
71 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) | 71 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) |
72 | break; | 72 | break; |
73 | 73 | ||
74 | // we have another attribute, read it. | 74 | // we have another attribute, read it. |
75 | int j = i; | 75 | int j = i; |
76 | while ( j < len && dt[j] != '=' ) | 76 | while ( j < len && dt[j] != '=' ) |
77 | ++j; | 77 | ++j; |
78 | QCString attr( dt+i, j-i+1); | 78 | QCString attr( dt+i, j-i+1); |
79 | 79 | ||
80 | i = ++j; // skip = | 80 | i = ++j; // skip = |
81 | 81 | ||
82 | // find the start of quotes | 82 | // find the start of quotes |
83 | while ( i < len && dt[i] != '"' ) | 83 | while ( i < len && dt[i] != '"' ) |
84 | ++i; | 84 | ++i; |
85 | j = ++i; | 85 | j = ++i; |
86 | 86 | ||
87 | bool haveUtf = FALSE; | 87 | bool haveUtf = FALSE; |
88 | bool haveEnt = FALSE; | 88 | bool haveEnt = FALSE; |
89 | while ( j < len && dt[j] != '"' ) { | 89 | while ( j < len && dt[j] != '"' ) { |
90 | if ( ((unsigned char)dt[j]) > 0x7f ) | 90 | if ( ((unsigned char)dt[j]) > 0x7f ) |
91 | haveUtf = TRUE; | 91 | haveUtf = TRUE; |
92 | if ( dt[j] == '&' ) | 92 | if ( dt[j] == '&' ) |
93 | haveEnt = TRUE; | 93 | haveEnt = TRUE; |
94 | ++j; | 94 | ++j; |
95 | } | 95 | } |
96 | if ( i == j ) { | 96 | if ( i == j ) { |
97 | // empty value | 97 | // empty value |
98 | i = j + 1; | 98 | i = j + 1; |
99 | continue; | 99 | continue; |
100 | } | 100 | } |
101 | 101 | ||
102 | QCString value( dt+i, j-i+1 ); | 102 | QCString value( dt+i, j-i+1 ); |
103 | i = j + 1; | 103 | i = j + 1; |
104 | 104 | ||
105 | QString str = (haveUtf ? QString::fromUtf8( value ) | 105 | QString str = (haveUtf ? QString::fromUtf8( value ) |
106 | : QString::fromLatin1( value ) ); | 106 | : QString::fromLatin1( value ) ); |
107 | if ( haveEnt ) | 107 | if ( haveEnt ) |
108 | str = Qtopia::plainString( str ); | 108 | str = Qtopia::plainString( str ); |
109 | 109 | ||
110 | /* | 110 | /* |
111 | * add key + value | 111 | * add key + value |
112 | */ | 112 | */ |
113 | todo( &dict, ev, attr, str ); | 113 | todo( &dict, ev, attr, str ); |
114 | 114 | ||
115 | } | 115 | } |
116 | /* | 116 | /* |
117 | * now add it | 117 | * now add it |
118 | */ | 118 | */ |
119 | if (m_events.contains( ev.uid() ) || ev.uid() == 0) { | 119 | if (m_events.contains( ev.uid() ) || ev.uid() == 0) { |
120 | ev.setUid( 1 ); | 120 | ev.setUid( 1 ); |
121 | m_changed = true; | 121 | m_changed = true; |
122 | } | 122 | } |
123 | if ( ev.hasDueDate() ) { | 123 | if ( ev.hasDueDate() ) { |
124 | ev.setDueDate( QDate(m_year, m_month, m_day) ); | 124 | ev.setDueDate( QDate(m_year, m_month, m_day) ); |
125 | } | 125 | } |
126 | m_events.insert(ev.uid(), ev ); | 126 | m_events.insert(ev.uid(), ev ); |
127 | m_year = m_month = m_day = -1; | 127 | m_year = m_month = m_day = -1; |
128 | } | 128 | } |
129 | 129 | ||
130 | qWarning("counts %d records loaded!", m_events.count() ); | 130 | qWarning("counts %d records loaded!", m_events.count() ); |
131 | return true; | 131 | return true; |
132 | } | 132 | } |
133 | bool OTodoAccessXML::reload() { | 133 | bool OTodoAccessXML::reload() { |
134 | return load(); | 134 | return load(); |
135 | } | 135 | } |
136 | bool OTodoAccessXML::save() { | 136 | bool OTodoAccessXML::save() { |
137 | // qWarning("saving"); | 137 | // qWarning("saving"); |
138 | if (!m_opened || !m_changed ) { | 138 | if (!m_opened || !m_changed ) { |
139 | // qWarning("not saving"); | 139 | // qWarning("not saving"); |
140 | return true; | 140 | return true; |
141 | } | 141 | } |
142 | QString strNewFile = m_file + ".new"; | 142 | QString strNewFile = m_file + ".new"; |
143 | QFile f( strNewFile ); | 143 | QFile f( strNewFile ); |
144 | if (!f.open( IO_WriteOnly|IO_Raw ) ) | 144 | if (!f.open( IO_WriteOnly|IO_Raw ) ) |
145 | return false; | 145 | return false; |
146 | 146 | ||
147 | int written; | 147 | int written; |
148 | QString out; | 148 | QString out; |
149 | out = "<!DOCTYPE Tasks>\n<Tasks>\n"; | 149 | out = "<!DOCTYPE Tasks>\n<Tasks>\n"; |
150 | 150 | ||
151 | // for all todos | 151 | // for all todos |
152 | QMap<int, OTodo>::Iterator it; | 152 | QMap<int, OTodo>::Iterator it; |
153 | for (it = m_events.begin(); it != m_events.end(); ++it ) { | 153 | for (it = m_events.begin(); it != m_events.end(); ++it ) { |
154 | out+= "<Task " + toString( (*it) ) + " />\n"; | 154 | out+= "<Task " + toString( (*it) ) + " />\n"; |
155 | QCString cstr = out.utf8(); | 155 | QCString cstr = out.utf8(); |
156 | written = f.writeBlock( cstr.data(), cstr.length() ); | 156 | written = f.writeBlock( cstr.data(), cstr.length() ); |
157 | 157 | ||
158 | /* less written then we wanted */ | 158 | /* less written then we wanted */ |
159 | if ( written != (int)cstr.length() ) { | 159 | if ( written != (int)cstr.length() ) { |
160 | f.close(); | 160 | f.close(); |
161 | QFile::remove( strNewFile ); | 161 | QFile::remove( strNewFile ); |
162 | return false; | 162 | return false; |
163 | } | 163 | } |
164 | out = QString::null; | 164 | out = QString::null; |
165 | } | 165 | } |
166 | 166 | ||
167 | out += "</Tasks>"; | 167 | out += "</Tasks>"; |
168 | QCString cstr = out.utf8(); | 168 | QCString cstr = out.utf8(); |
169 | written = f.writeBlock( cstr.data(), cstr.length() ); | 169 | written = f.writeBlock( cstr.data(), cstr.length() ); |
170 | 170 | ||
171 | if ( written != (int)cstr.length() ) { | 171 | if ( written != (int)cstr.length() ) { |
172 | f.close(); | 172 | f.close(); |
173 | QFile::remove( strNewFile ); | 173 | QFile::remove( strNewFile ); |
174 | return false; | 174 | return false; |
175 | } | 175 | } |
176 | /* flush before renaming */ | 176 | /* flush before renaming */ |
177 | f.close(); | 177 | f.close(); |
178 | 178 | ||
179 | if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { | 179 | if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { |
180 | // qWarning("error renaming"); | 180 | // qWarning("error renaming"); |
181 | QFile::remove( strNewFile ); | 181 | QFile::remove( strNewFile ); |
182 | } | 182 | } |
183 | 183 | ||
184 | m_changed = false; | 184 | m_changed = false; |
185 | return true; | 185 | return true; |
186 | } | 186 | } |
187 | QArray<int> OTodoAccessXML::allRecords()const { | 187 | QArray<int> OTodoAccessXML::allRecords()const { |
188 | QArray<int> ids( m_events.count() ); | 188 | QArray<int> ids( m_events.count() ); |
189 | QMap<int, OTodo>::ConstIterator it; | 189 | QMap<int, OTodo>::ConstIterator it; |
190 | int i = 0; | 190 | int i = 0; |
191 | 191 | ||
192 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 192 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
193 | ids[i] = it.key(); | 193 | ids[i] = it.key(); |
194 | i++; | 194 | i++; |
195 | } | 195 | } |
196 | return ids; | 196 | return ids; |
197 | } | 197 | } |
198 | QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { | 198 | QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { |
199 | QArray<int> ids(0); | 199 | QArray<int> ids(0); |
200 | return ids; | 200 | return ids; |
201 | } | 201 | } |
202 | OTodo OTodoAccessXML::find( int uid )const { | 202 | OTodo OTodoAccessXML::find( int uid )const { |
203 | OTodo todo; | 203 | OTodo todo; |
204 | todo.setUid( 0 ); // isEmpty() | 204 | todo.setUid( 0 ); // isEmpty() |
205 | QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); | 205 | QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); |
206 | if ( it != m_events.end() ) | 206 | if ( it != m_events.end() ) |
207 | todo = it.data(); | 207 | todo = it.data(); |
208 | 208 | ||
209 | return todo; | 209 | return todo; |
210 | } | 210 | } |
211 | void OTodoAccessXML::clear() { | 211 | void OTodoAccessXML::clear() { |
212 | if (m_opened ) | 212 | if (m_opened ) |
213 | m_changed = true; | 213 | m_changed = true; |
214 | 214 | ||
215 | m_events.clear(); | 215 | m_events.clear(); |
216 | } | 216 | } |
217 | bool OTodoAccessXML::add( const OTodo& todo ) { | 217 | bool OTodoAccessXML::add( const OTodo& todo ) { |
218 | // qWarning("add"); | 218 | // qWarning("add"); |
219 | m_changed = true; | 219 | m_changed = true; |
220 | m_events.insert( todo.uid(), todo ); | 220 | m_events.insert( todo.uid(), todo ); |
221 | 221 | ||
222 | return true; | 222 | return true; |
223 | } | 223 | } |
224 | bool OTodoAccessXML::remove( int uid ) { | 224 | bool OTodoAccessXML::remove( int uid ) { |
225 | m_changed = true; | 225 | m_changed = true; |
226 | m_events.remove( uid ); | 226 | m_events.remove( uid ); |
227 | 227 | ||
228 | return true; | 228 | return true; |
229 | } | 229 | } |
230 | bool OTodoAccessXML::replace( const OTodo& todo) { | 230 | bool OTodoAccessXML::replace( const OTodo& todo) { |
231 | m_changed = true; | 231 | m_changed = true; |
232 | m_events.replace( todo.uid(), todo ); | 232 | m_events.replace( todo.uid(), todo ); |
233 | 233 | ||
234 | return true; | 234 | return true; |
235 | } | 235 | } |
236 | QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, | 236 | QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, |
237 | const QDate& end, | 237 | const QDate& end, |
238 | bool includeNoDates ) { | 238 | bool includeNoDates ) { |
239 | QArray<int> ids( m_events.count() ); | 239 | QArray<int> ids( m_events.count() ); |
240 | QMap<int, OTodo>::Iterator it; | 240 | QMap<int, OTodo>::Iterator it; |
241 | 241 | ||
242 | int i = 0; | 242 | int i = 0; |
243 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 243 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
244 | if ( !it.data().hasDueDate() ) { | 244 | if ( !it.data().hasDueDate() ) { |
245 | if ( includeNoDates ) { | 245 | if ( includeNoDates ) { |
246 | ids[i] = it.key(); | 246 | ids[i] = it.key(); |
247 | i++; | 247 | i++; |
248 | } | 248 | } |
249 | }else if ( it.data().dueDate() >= start && | 249 | }else if ( it.data().dueDate() >= start && |
250 | it.data().dueDate() <= end ) { | 250 | it.data().dueDate() <= end ) { |
251 | ids[i] = it.key(); | 251 | ids[i] = it.key(); |
252 | i++; | 252 | i++; |
253 | } | 253 | } |
254 | } | 254 | } |
255 | ids.resize( i ); | 255 | ids.resize( i ); |
256 | return ids; | 256 | return ids; |
257 | } | 257 | } |
258 | QArray<int> OTodoAccessXML::overDue() { | 258 | QArray<int> OTodoAccessXML::overDue() { |
259 | QArray<int> ids( m_events.count() ); | 259 | QArray<int> ids( m_events.count() ); |
260 | int i = 0; | 260 | int i = 0; |
261 | 261 | ||
262 | QMap<int, OTodo>::Iterator it; | 262 | QMap<int, OTodo>::Iterator it; |
263 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 263 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
264 | if ( it.data().isOverdue() ) { | 264 | if ( it.data().isOverdue() ) { |
265 | ids[i] = it.key(); | 265 | ids[i] = it.key(); |
266 | i++; | 266 | i++; |
267 | } | 267 | } |
268 | } | 268 | } |
269 | ids.resize( i ); | 269 | ids.resize( i ); |
270 | return ids; | 270 | return ids; |
271 | } | 271 | } |
272 | 272 | ||
273 | 273 | ||
274 | /* private */ | 274 | /* private */ |
275 | void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, | 275 | void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, |
276 | const QCString& attr, const QString& val) { | 276 | const QCString& attr, const QString& val) { |
277 | // qWarning("parse to do from XMLElement" ); | 277 | // qWarning("parse to do from XMLElement" ); |
278 | 278 | ||
279 | int *find=0; | 279 | int *find=0; |
280 | 280 | ||
281 | find = (*dict)[ attr.data() ]; | 281 | find = (*dict)[ attr.data() ]; |
282 | if (!find ) { | 282 | if (!find ) { |
283 | // qWarning("Unknown option" + it.key() ); | 283 | // qWarning("Unknown option" + it.key() ); |
284 | ev.setCustomField( attr, val ); | 284 | ev.setCustomField( attr, val ); |
285 | return; | 285 | return; |
286 | } | 286 | } |
287 | 287 | ||
288 | switch( *find ) { | 288 | switch( *find ) { |
289 | case OTodo::Uid: | 289 | case OTodo::Uid: |
290 | ev.setUid( val.toInt() ); | 290 | ev.setUid( val.toInt() ); |
291 | break; | 291 | break; |
292 | case OTodo::Category: | 292 | case OTodo::Category: |
293 | ev.setCategories( ev.idsFromString( val ) ); | 293 | ev.setCategories( ev.idsFromString( val ) ); |
294 | break; | 294 | break; |
295 | case OTodo::HasDate: | 295 | case OTodo::HasDate: |
296 | ev.setHasDueDate( val.toInt() ); | 296 | ev.setHasDueDate( val.toInt() ); |
297 | break; | 297 | break; |
298 | case OTodo::Completed: | 298 | case OTodo::Completed: |
299 | ev.setCompleted( val.toInt() ); | 299 | ev.setCompleted( val.toInt() ); |
300 | break; | 300 | break; |
301 | case OTodo::Description: | 301 | case OTodo::Description: |
302 | ev.setDescription( val ); | 302 | ev.setDescription( val ); |
303 | break; | 303 | break; |
304 | case OTodo::Summary: | 304 | case OTodo::Summary: |
305 | ev.setSummary( val ); | 305 | ev.setSummary( val ); |
306 | break; | 306 | break; |
307 | case OTodo::Priority: | 307 | case OTodo::Priority: |
308 | ev.setPriority( val.toInt() ); | 308 | ev.setPriority( val.toInt() ); |
309 | break; | 309 | break; |
310 | case OTodo::DateDay: | 310 | case OTodo::DateDay: |
311 | m_day = val.toInt(); | 311 | m_day = val.toInt(); |
312 | break; | 312 | break; |
313 | case OTodo::DateMonth: | 313 | case OTodo::DateMonth: |
314 | m_month = val.toInt(); | 314 | m_month = val.toInt(); |
315 | break; | 315 | break; |
316 | case OTodo::DateYear: | 316 | case OTodo::DateYear: |
317 | m_year = val.toInt(); | 317 | m_year = val.toInt(); |
318 | break; | 318 | break; |
319 | case OTodo::Progress: | 319 | case OTodo::Progress: |
320 | ev.setProgress( val.toInt() ); | 320 | ev.setProgress( val.toInt() ); |
321 | break; | 321 | break; |
322 | case OTodo::CrossReference: | 322 | case OTodo::CrossReference: |
323 | { | 323 | { |
324 | /* | 324 | /* |
325 | * A cross refernce looks like | 325 | * A cross refernce looks like |
326 | * appname,id;appname,id | 326 | * appname,id;appname,id |
327 | * we need to split it up | 327 | * we need to split it up |
328 | */ | 328 | */ |
329 | QStringList refs = QStringList::split(';', val ); | 329 | QStringList refs = QStringList::split(';', val ); |
330 | QStringList::Iterator strIt; | 330 | QStringList::Iterator strIt; |
331 | for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { | 331 | for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { |
332 | int pos = (*strIt).find(','); | 332 | int pos = (*strIt).find(','); |
333 | if ( pos > -1 ) | 333 | if ( pos > -1 ) |
334 | ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); | 334 | ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); |
335 | 335 | ||
336 | } | 336 | } |
337 | break; | 337 | break; |
338 | } | 338 | } |
339 | case OTodo::HasAlarmDateTime: | 339 | case OTodo::HasAlarmDateTime: |
340 | ev.setHasAlarmDateTime( val.toInt() ); | 340 | ev.setHasAlarmDateTime( val.toInt() ); |
341 | break; | 341 | break; |
342 | case OTodo::AlarmDateTime: { | 342 | case OTodo::AlarmDateTime: { |
343 | /* this sounds better ;) zecke */ | 343 | /* this sounds better ;) zecke */ |
344 | ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); | 344 | ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); |
345 | break; | 345 | break; |
346 | } | 346 | } |
347 | default: | 347 | default: |
348 | break; | 348 | break; |
349 | } | 349 | } |
350 | } | 350 | } |
351 | QString OTodoAccessXML::toString( const OTodo& ev )const { | 351 | QString OTodoAccessXML::toString( const OTodo& ev )const { |
352 | QString str; | 352 | QString str; |
353 | 353 | ||
354 | str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; | 354 | str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; |
355 | str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; | 355 | str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; |
356 | str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; | 356 | str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; |
357 | str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; | 357 | str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; |
358 | 358 | ||
359 | str += "Categories=\"" + toString( ev.categories() ) + "\" "; | 359 | str += "Categories=\"" + toString( ev.categories() ) + "\" "; |
360 | str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; | 360 | str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; |
361 | str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; | 361 | str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; |
362 | 362 | ||
363 | if ( ev.hasDueDate() ) { | 363 | if ( ev.hasDueDate() ) { |
364 | str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; | 364 | str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; |
365 | str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; | 365 | str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; |
366 | str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; | 366 | str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; |
367 | } | 367 | } |
368 | // qWarning( "Uid %d", ev.uid() ); | 368 | // qWarning( "Uid %d", ev.uid() ); |
369 | str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; | 369 | str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; |
370 | 370 | ||
371 | // append the extra options | 371 | // append the extra options |
372 | /* FIXME Qtopia::Record this is currently not | 372 | /* FIXME Qtopia::Record this is currently not |
373 | * possible you can set custom fields | 373 | * possible you can set custom fields |
374 | * but don' iterate over the list | 374 | * but don' iterate over the list |
375 | * I may do #define private protected | 375 | * I may do #define private protected |
376 | * for this case - cough --zecke | 376 | * for this case - cough --zecke |
377 | */ | 377 | */ |
378 | /* | 378 | /* |
379 | QMap<QString, QString> extras = ev.extras(); | 379 | QMap<QString, QString> extras = ev.extras(); |
380 | QMap<QString, QString>::Iterator extIt; | 380 | QMap<QString, QString>::Iterator extIt; |
381 | for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) | 381 | for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) |
382 | str += extIt.key() + "=\"" + extIt.data() + "\" "; | 382 | str += extIt.key() + "=\"" + extIt.data() + "\" "; |
383 | */ | 383 | */ |
384 | // cross refernce | 384 | // cross refernce |
385 | QStringList list = ev.relatedApps(); | 385 | QStringList list = ev.relatedApps(); |
386 | QStringList::Iterator listIt; | 386 | QStringList::Iterator listIt; |
387 | QString refs; | 387 | QString refs; |
388 | str += "CrossReference=\""; | 388 | str += "CrossReference=\""; |
389 | bool added = false; | 389 | bool added = false; |
390 | for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { | 390 | for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { |
391 | added = true; | 391 | added = true; |
392 | QArray<int> ints = ev.relations( (*listIt) ); | 392 | QArray<int> ints = ev.relations( (*listIt) ); |
393 | for ( uint i = 0; i< ints.count(); i++ ) { | 393 | for ( uint i = 0; i< ints.count(); i++ ) { |
394 | str += (*listIt) + "," + QString::number( i ) + ";"; | 394 | str += (*listIt) + "," + QString::number( i ) + ";"; |
395 | } | 395 | } |
396 | } | 396 | } |
397 | if ( added ) | 397 | if ( added ) |
398 | str = str.remove( str.length()-1, 1 ); | 398 | str = str.remove( str.length()-1, 1 ); |
399 | 399 | ||
400 | str += "\" "; | 400 | str += "\" "; |
401 | 401 | ||
402 | str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; | 402 | str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; |
403 | 403 | ||
404 | return str; | 404 | return str; |
405 | } | 405 | } |
406 | QString OTodoAccessXML::toString( const QArray<int>& ints ) const { | 406 | QString OTodoAccessXML::toString( const QArray<int>& ints ) const { |
407 | return Qtopia::Record::idsToString( ints ); | 407 | return Qtopia::Record::idsToString( ints ); |
408 | } | 408 | } |
409 | 409 | ||
410 | /* internal class for sorting */ | 410 | /* internal class for sorting |
411 | * | ||
412 | * Inspired by todoxmlio.cpp from TT | ||
413 | */ | ||
411 | 414 | ||
412 | struct OTodoXMLContainer { | 415 | struct OTodoXMLContainer { |
413 | OTodo todo; | 416 | OTodo todo; |
414 | }; | 417 | }; |
415 | /* | 418 | |
419 | namespace { | ||
420 | inline QString string( const OTodo& todo) { | ||
421 | return todo.summary().isEmpty() ? | ||
422 | todo.description().left(20 ) : | ||
423 | todo.summary(); | ||
424 | } | ||
425 | inline int completed( const OTodo& todo1, const OTodo& todo2) { | ||
426 | int ret = 0; | ||
427 | if ( todo1.isCompleted() ) ret++; | ||
428 | if ( todo2.isCompleted() ) ret--; | ||
429 | return ret; | ||
430 | } | ||
431 | inline int priority( const OTodo& t1, const OTodo& t2) { | ||
432 | return ( t1.priority() - t2.priority() ); | ||
433 | } | ||
434 | inline int description( const OTodo& t1, const OTodo& t2) { | ||
435 | return QString::compare( string(t1), string(t2) ); | ||
436 | } | ||
437 | inline int deadline( const OTodo& t1, const OTodo& t2) { | ||
438 | int ret = 0; | ||
439 | if ( t1.hasDueDate() && | ||
440 | t2.hasDueDate() ) | ||
441 | ret = t2.dueDate().daysTo( t1.dueDate() ); | ||
442 | else if ( t1.hasDueDate() ) | ||
443 | ret = -1; | ||
444 | else if ( t2.hasDueDate() ) | ||
445 | ret = 1; | ||
446 | else | ||
447 | ret = 0; | ||
448 | |||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | }; | ||
453 | |||
454 | /* | ||
416 | * Returns: | 455 | * Returns: |
417 | * 0 if item1 == item2 | 456 | * 0 if item1 == item2 |
418 | * | 457 | * |
419 | * non-zero if item1 != item2 | 458 | * non-zero if item1 != item2 |
420 | * | 459 | * |
421 | * This function returns int rather than bool so that reimplementations | 460 | * This function returns int rather than bool so that reimplementations |
422 | * can return one of three values and use it to sort by: | 461 | * can return one of three values and use it to sort by: |
423 | * | 462 | * |
424 | * 0 if item1 == item2 | 463 | * 0 if item1 == item2 |
425 | * | 464 | * |
426 | * > 0 (positive integer) if item1 > item2 | 465 | * > 0 (positive integer) if item1 > item2 |
427 | * | 466 | * |
428 | * < 0 (negative integer) if item1 < item2 | 467 | * < 0 (negative integer) if item1 < item2 |
429 | * | 468 | * |
430 | */ | 469 | */ |
431 | class OTodoXMLVector : public QVector<OTodoXMLContainer> { | 470 | class OTodoXMLVector : public QVector<OTodoXMLContainer> { |
432 | public: | 471 | public: |
433 | OTodoXMLVector(int size, bool asc, int sort) | 472 | OTodoXMLVector(int size, bool asc, int sort) |
434 | : QVector<OTodoXMLContainer>( size ) | 473 | : QVector<OTodoXMLContainer>( size ) |
435 | { | 474 | { |
436 | setAutoDelete( true ); | 475 | setAutoDelete( true ); |
437 | m_asc = asc; | 476 | m_asc = asc; |
438 | m_sort = sort; | 477 | m_sort = sort; |
439 | } | 478 | } |
440 | /* return the summary/description */ | 479 | /* return the summary/description */ |
441 | QString string( const OTodo& todo) { | 480 | QString string( const OTodo& todo) { |
442 | return todo.summary().isEmpty() ? | 481 | return todo.summary().isEmpty() ? |
443 | todo.description().left(20 ) : | 482 | todo.description().left(20 ) : |
444 | todo.summary(); | 483 | todo.summary(); |
445 | } | 484 | } |
446 | /** | 485 | /** |
447 | * we take the sortorder( switch on it ) | 486 | * we take the sortorder( switch on it ) |
448 | * | 487 | * |
449 | */ | 488 | */ |
450 | int compareItems( Item d1, Item d2 ) { | 489 | int compareItems( Item d1, Item d2 ) { |
490 | bool seComp, sePrio, seDesc, seDeadline; | ||
491 | seComp = sePrio = seDeadline = seDesc = false; | ||
451 | int ret =0; | 492 | int ret =0; |
452 | OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; | 493 | OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; |
453 | OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; | 494 | OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; |
454 | 495 | ||
455 | /* same item */ | 496 | /* same item */ |
456 | if ( con1->todo.uid() == con2->todo.uid() ) | 497 | if ( con1->todo.uid() == con2->todo.uid() ) |
457 | return 0; | 498 | return 0; |
458 | 499 | ||
459 | switch ( m_sort ) { | 500 | switch ( m_sort ) { |
460 | /* completed */ | 501 | /* completed */ |
461 | case 0: { | 502 | case 0: { |
462 | ret = 0; | 503 | ret = completed( con1->todo, con2->todo ); |
463 | if ( con1->todo.isCompleted() ) ret++; | 504 | seComp = TRUE; |
464 | if ( con2->todo.isCompleted() ) ret--; | ||
465 | break; | 505 | break; |
466 | } | 506 | } |
467 | /* priority */ | 507 | /* priority */ |
468 | case 1: { | 508 | case 1: { |
469 | ret = con1->todo.priority() - con2->todo.priority(); | 509 | ret = priority( con1->todo, con2->todo ); |
470 | qWarning(" priority %d %d %d", ret, | 510 | sePrio = TRUE; |
471 | con1->todo.priority(), | ||
472 | con2->todo.priority() | ||
473 | ); | ||
474 | break; | 511 | break; |
475 | } | 512 | } |
476 | /* description */ | 513 | /* description */ |
477 | case 2: { | 514 | case 2: { |
478 | QString str1 = string( con1->todo ); | 515 | ret = description( con1->todo, con2->todo ); |
479 | QString str2 = string( con2->todo ); | 516 | seDesc = TRUE; |
480 | ret = QString::compare( str1, str2 ); | ||
481 | break; | 517 | break; |
482 | } | 518 | } |
483 | /* deadline */ | 519 | /* deadline */ |
484 | case 3: { | 520 | case 3: { |
485 | /* either bot got a dueDate | 521 | ret = deadline( con1->todo, con2->todo ); |
486 | * or one of them got one | 522 | seDeadline = TRUE; |
487 | */ | ||
488 | if ( con1->todo.hasDueDate() && | ||
489 | con2->todo.hasDueDate() ) | ||
490 | ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() ); | ||
491 | |||
492 | |||
493 | else if ( con1->todo.hasDueDate() ) | ||
494 | ret = -1; | ||
495 | else if ( con2->todo.hasDueDate() ) | ||
496 | ret = 0; | ||
497 | break; | 523 | break; |
498 | } | 524 | } |
499 | default: | 525 | default: |
500 | ret = 0; | 526 | ret = 0; |
501 | break; | 527 | break; |
502 | }; | 528 | }; |
529 | /* | ||
530 | * FIXME do better sorting if the first sort criteria | ||
531 | * ret equals 0 start with complete and so on... | ||
532 | */ | ||
503 | 533 | ||
504 | /* twist it we're not ascending*/ | 534 | /* twist it we're not ascending*/ |
505 | if (!m_asc) | 535 | if (!m_asc) |
506 | ret = ret * -1; | 536 | ret = ret * -1; |
507 | return ret; | 537 | |
538 | if ( ret ) | ||
539 | return ret; | ||
540 | |||
541 | // default did not gave difference let's try it other way around | ||
542 | /* | ||
543 | * General try if already checked if not test | ||
544 | * and return | ||
545 | * 1.Completed | ||
546 | * 2.Priority | ||
547 | * 3.Description | ||
548 | * 4.DueDate | ||
549 | */ | ||
550 | if (!seComp ) { | ||
551 | if ( (ret = completed( con1->todo, con2->todo ) ) ) { | ||
552 | if (!m_asc ) ret *= -1; | ||
553 | return ret; | ||
554 | } | ||
555 | } | ||
556 | if (!sePrio ) { | ||
557 | if ( (ret = priority( con1->todo, con2->todo ) ) ) { | ||
558 | if (!m_asc ) ret *= -1; | ||
559 | return ret; | ||
560 | } | ||
561 | } | ||
562 | if (!seDesc ) { | ||
563 | if ( (ret = description(con1->todo, con2->todo ) ) ) { | ||
564 | if (!m_asc) ret *= -1; | ||
565 | return ret; | ||
566 | } | ||
567 | } | ||
568 | if (!seDeadline) { | ||
569 | if ( (ret = deadline( con1->todo, con2->todo ) ) ) { | ||
570 | if (!m_asc) ret *= -1; | ||
571 | return ret; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | return 0; | ||
508 | } | 576 | } |
509 | private: | 577 | private: |
510 | bool m_asc; | 578 | bool m_asc; |
511 | int m_sort; | 579 | int m_sort; |
512 | 580 | ||
513 | }; | 581 | }; |
514 | 582 | ||
515 | QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, | 583 | QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, |
516 | int sortFilter, int cat ) { | 584 | int sortFilter, int cat ) { |
517 | qWarning("sorted! %d cat", cat); | 585 | qWarning("sorted! %d cat", cat); |
518 | OTodoXMLVector vector(m_events.count(), asc,sortOrder ); | 586 | OTodoXMLVector vector(m_events.count(), asc,sortOrder ); |
519 | QMap<int, OTodo>::Iterator it; | 587 | QMap<int, OTodo>::Iterator it; |
520 | int item = 0; | 588 | int item = 0; |
521 | 589 | ||
522 | bool bCat = sortFilter & 1 ? true : false; | 590 | bool bCat = sortFilter & 1 ? true : false; |
523 | bool bOnly = sortFilter & 2 ? true : false; | 591 | bool bOnly = sortFilter & 2 ? true : false; |
524 | bool comp = sortFilter & 4 ? true : false; | 592 | bool comp = sortFilter & 4 ? true : false; |
525 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 593 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
526 | 594 | ||
527 | /* show category */ | 595 | /* show category */ |
528 | if ( bCat && cat != 0) | 596 | if ( bCat && cat != 0) |
529 | if (!(*it).categories().contains( cat ) ) { | 597 | if (!(*it).categories().contains( cat ) ) { |
530 | qWarning("category mis match"); | 598 | qWarning("category mis match"); |
531 | continue; | 599 | continue; |
532 | } | 600 | } |
533 | /* isOverdue but we should not show overdue - why?*/ | 601 | /* isOverdue but we should not show overdue - why?*/ |
534 | /* if ( (*it).isOverdue() && !bOnly ) { | 602 | /* if ( (*it).isOverdue() && !bOnly ) { |
535 | qWarning("item is overdue but !bOnly"); | 603 | qWarning("item is overdue but !bOnly"); |
536 | continue; | 604 | continue; |
537 | } | 605 | } |
538 | */ | 606 | */ |
539 | if ( !(*it).isOverdue() && bOnly ) { | 607 | if ( !(*it).isOverdue() && bOnly ) { |
540 | qWarning("item is not overdue but bOnly checked"); | 608 | qWarning("item is not overdue but bOnly checked"); |
541 | continue; | 609 | continue; |
542 | } | 610 | } |
543 | 611 | ||
544 | if ((*it).isCompleted() && comp ) { | 612 | if ((*it).isCompleted() && comp ) { |
545 | qWarning("completed continue!"); | 613 | qWarning("completed continue!"); |
546 | continue; | 614 | continue; |
547 | } | 615 | } |
548 | 616 | ||
549 | 617 | ||
550 | OTodoXMLContainer* con = new OTodoXMLContainer(); | 618 | OTodoXMLContainer* con = new OTodoXMLContainer(); |
551 | con->todo = (*it); | 619 | con->todo = (*it); |
552 | vector.insert(item, con ); | 620 | vector.insert(item, con ); |
553 | item++; | 621 | item++; |
554 | } | 622 | } |
555 | qWarning("XXX %d Items added", item); | 623 | qWarning("XXX %d Items added", item); |
556 | vector.resize( item ); | 624 | vector.resize( item ); |
557 | /* sort it now */ | 625 | /* sort it now */ |
558 | vector.sort(); | 626 | vector.sort(); |
559 | /* now get the uids */ | 627 | /* now get the uids */ |
560 | QArray<int> array( vector.count() ); | 628 | QArray<int> array( vector.count() ); |
561 | for (uint i= 0; i < vector.count(); i++ ) { | 629 | for (uint i= 0; i < vector.count(); i++ ) { |
562 | array[i] = ( vector.at(i) )->todo.uid(); | 630 | array[i] = ( vector.at(i) )->todo.uid(); |
563 | } | 631 | } |
564 | qWarning("array count = %d %d", array.count(), vector.count() ); | 632 | qWarning("array count = %d %d", array.count(), vector.count() ); |
565 | return array; | 633 | return array; |
566 | }; | 634 | }; |
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp index 385fd27..591e467 100644 --- a/libopie2/opiepim/backend/otodoaccessxml.cpp +++ b/libopie2/opiepim/backend/otodoaccessxml.cpp | |||
@@ -26,541 +26,609 @@ bool OTodoAccessXML::load() { | |||
26 | m_changed = false; | 26 | m_changed = false; |
27 | /* initialize dict */ | 27 | /* initialize dict */ |
28 | /* | 28 | /* |
29 | * UPDATE dict if you change anything!!! | 29 | * UPDATE dict if you change anything!!! |
30 | */ | 30 | */ |
31 | QAsciiDict<int> dict(15); | 31 | QAsciiDict<int> dict(15); |
32 | dict.setAutoDelete( TRUE ); | 32 | dict.setAutoDelete( TRUE ); |
33 | dict.insert("Categories" , new int(OTodo::Category) ); | 33 | dict.insert("Categories" , new int(OTodo::Category) ); |
34 | dict.insert("Uid" , new int(OTodo::Uid) ); | 34 | dict.insert("Uid" , new int(OTodo::Uid) ); |
35 | dict.insert("HasDate" , new int(OTodo::HasDate) ); | 35 | dict.insert("HasDate" , new int(OTodo::HasDate) ); |
36 | dict.insert("Completed" , new int(OTodo::Completed) ); | 36 | dict.insert("Completed" , new int(OTodo::Completed) ); |
37 | dict.insert("Description" , new int(OTodo::Description) ); | 37 | dict.insert("Description" , new int(OTodo::Description) ); |
38 | dict.insert("Summary" , new int(OTodo::Summary) ); | 38 | dict.insert("Summary" , new int(OTodo::Summary) ); |
39 | dict.insert("Priority" , new int(OTodo::Priority) ); | 39 | dict.insert("Priority" , new int(OTodo::Priority) ); |
40 | dict.insert("DateDay" , new int(OTodo::DateDay) ); | 40 | dict.insert("DateDay" , new int(OTodo::DateDay) ); |
41 | dict.insert("DateMonth" , new int(OTodo::DateMonth) ); | 41 | dict.insert("DateMonth" , new int(OTodo::DateMonth) ); |
42 | dict.insert("DateYear" , new int(OTodo::DateYear) ); | 42 | dict.insert("DateYear" , new int(OTodo::DateYear) ); |
43 | dict.insert("Progress" , new int(OTodo::Progress) ); | 43 | dict.insert("Progress" , new int(OTodo::Progress) ); |
44 | dict.insert("Completed", new int(OTodo::Completed) ); | 44 | dict.insert("Completed", new int(OTodo::Completed) ); |
45 | dict.insert("CrossReference", new int(OTodo::CrossReference) ); | 45 | dict.insert("CrossReference", new int(OTodo::CrossReference) ); |
46 | dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); | 46 | dict.insert("HasAlarmDateTime",new int(OTodo::HasAlarmDateTime) ); |
47 | dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); | 47 | dict.insert("AlarmDateTime", new int(OTodo::AlarmDateTime) ); |
48 | 48 | ||
49 | // here the custom XML parser from TT it's GPL | 49 | // here the custom XML parser from TT it's GPL |
50 | // but we want to push that to TT..... | 50 | // but we want to push that to TT..... |
51 | QFile f(m_file ); | 51 | QFile f(m_file ); |
52 | if (!f.open(IO_ReadOnly) ) | 52 | if (!f.open(IO_ReadOnly) ) |
53 | return false; | 53 | return false; |
54 | 54 | ||
55 | QByteArray ba = f.readAll(); | 55 | QByteArray ba = f.readAll(); |
56 | f.close(); | 56 | f.close(); |
57 | char* dt = ba.data(); | 57 | char* dt = ba.data(); |
58 | int len = ba.size(); | 58 | int len = ba.size(); |
59 | int i = 0; | 59 | int i = 0; |
60 | char *point; | 60 | char *point; |
61 | const char* collectionString = "<Task "; | 61 | const char* collectionString = "<Task "; |
62 | while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { | 62 | while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { |
63 | i = point -dt; | 63 | i = point -dt; |
64 | i+= strlen(collectionString); | 64 | i+= strlen(collectionString); |
65 | OTodo ev; | 65 | OTodo ev; |
66 | m_year = m_month = m_day = 0; | 66 | m_year = m_month = m_day = 0; |
67 | 67 | ||
68 | while ( TRUE ) { | 68 | while ( TRUE ) { |
69 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) | 69 | while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) |
70 | ++i; | 70 | ++i; |
71 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) | 71 | if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) |
72 | break; | 72 | break; |
73 | 73 | ||
74 | // we have another attribute, read it. | 74 | // we have another attribute, read it. |
75 | int j = i; | 75 | int j = i; |
76 | while ( j < len && dt[j] != '=' ) | 76 | while ( j < len && dt[j] != '=' ) |
77 | ++j; | 77 | ++j; |
78 | QCString attr( dt+i, j-i+1); | 78 | QCString attr( dt+i, j-i+1); |
79 | 79 | ||
80 | i = ++j; // skip = | 80 | i = ++j; // skip = |
81 | 81 | ||
82 | // find the start of quotes | 82 | // find the start of quotes |
83 | while ( i < len && dt[i] != '"' ) | 83 | while ( i < len && dt[i] != '"' ) |
84 | ++i; | 84 | ++i; |
85 | j = ++i; | 85 | j = ++i; |
86 | 86 | ||
87 | bool haveUtf = FALSE; | 87 | bool haveUtf = FALSE; |
88 | bool haveEnt = FALSE; | 88 | bool haveEnt = FALSE; |
89 | while ( j < len && dt[j] != '"' ) { | 89 | while ( j < len && dt[j] != '"' ) { |
90 | if ( ((unsigned char)dt[j]) > 0x7f ) | 90 | if ( ((unsigned char)dt[j]) > 0x7f ) |
91 | haveUtf = TRUE; | 91 | haveUtf = TRUE; |
92 | if ( dt[j] == '&' ) | 92 | if ( dt[j] == '&' ) |
93 | haveEnt = TRUE; | 93 | haveEnt = TRUE; |
94 | ++j; | 94 | ++j; |
95 | } | 95 | } |
96 | if ( i == j ) { | 96 | if ( i == j ) { |
97 | // empty value | 97 | // empty value |
98 | i = j + 1; | 98 | i = j + 1; |
99 | continue; | 99 | continue; |
100 | } | 100 | } |
101 | 101 | ||
102 | QCString value( dt+i, j-i+1 ); | 102 | QCString value( dt+i, j-i+1 ); |
103 | i = j + 1; | 103 | i = j + 1; |
104 | 104 | ||
105 | QString str = (haveUtf ? QString::fromUtf8( value ) | 105 | QString str = (haveUtf ? QString::fromUtf8( value ) |
106 | : QString::fromLatin1( value ) ); | 106 | : QString::fromLatin1( value ) ); |
107 | if ( haveEnt ) | 107 | if ( haveEnt ) |
108 | str = Qtopia::plainString( str ); | 108 | str = Qtopia::plainString( str ); |
109 | 109 | ||
110 | /* | 110 | /* |
111 | * add key + value | 111 | * add key + value |
112 | */ | 112 | */ |
113 | todo( &dict, ev, attr, str ); | 113 | todo( &dict, ev, attr, str ); |
114 | 114 | ||
115 | } | 115 | } |
116 | /* | 116 | /* |
117 | * now add it | 117 | * now add it |
118 | */ | 118 | */ |
119 | if (m_events.contains( ev.uid() ) || ev.uid() == 0) { | 119 | if (m_events.contains( ev.uid() ) || ev.uid() == 0) { |
120 | ev.setUid( 1 ); | 120 | ev.setUid( 1 ); |
121 | m_changed = true; | 121 | m_changed = true; |
122 | } | 122 | } |
123 | if ( ev.hasDueDate() ) { | 123 | if ( ev.hasDueDate() ) { |
124 | ev.setDueDate( QDate(m_year, m_month, m_day) ); | 124 | ev.setDueDate( QDate(m_year, m_month, m_day) ); |
125 | } | 125 | } |
126 | m_events.insert(ev.uid(), ev ); | 126 | m_events.insert(ev.uid(), ev ); |
127 | m_year = m_month = m_day = -1; | 127 | m_year = m_month = m_day = -1; |
128 | } | 128 | } |
129 | 129 | ||
130 | qWarning("counts %d records loaded!", m_events.count() ); | 130 | qWarning("counts %d records loaded!", m_events.count() ); |
131 | return true; | 131 | return true; |
132 | } | 132 | } |
133 | bool OTodoAccessXML::reload() { | 133 | bool OTodoAccessXML::reload() { |
134 | return load(); | 134 | return load(); |
135 | } | 135 | } |
136 | bool OTodoAccessXML::save() { | 136 | bool OTodoAccessXML::save() { |
137 | // qWarning("saving"); | 137 | // qWarning("saving"); |
138 | if (!m_opened || !m_changed ) { | 138 | if (!m_opened || !m_changed ) { |
139 | // qWarning("not saving"); | 139 | // qWarning("not saving"); |
140 | return true; | 140 | return true; |
141 | } | 141 | } |
142 | QString strNewFile = m_file + ".new"; | 142 | QString strNewFile = m_file + ".new"; |
143 | QFile f( strNewFile ); | 143 | QFile f( strNewFile ); |
144 | if (!f.open( IO_WriteOnly|IO_Raw ) ) | 144 | if (!f.open( IO_WriteOnly|IO_Raw ) ) |
145 | return false; | 145 | return false; |
146 | 146 | ||
147 | int written; | 147 | int written; |
148 | QString out; | 148 | QString out; |
149 | out = "<!DOCTYPE Tasks>\n<Tasks>\n"; | 149 | out = "<!DOCTYPE Tasks>\n<Tasks>\n"; |
150 | 150 | ||
151 | // for all todos | 151 | // for all todos |
152 | QMap<int, OTodo>::Iterator it; | 152 | QMap<int, OTodo>::Iterator it; |
153 | for (it = m_events.begin(); it != m_events.end(); ++it ) { | 153 | for (it = m_events.begin(); it != m_events.end(); ++it ) { |
154 | out+= "<Task " + toString( (*it) ) + " />\n"; | 154 | out+= "<Task " + toString( (*it) ) + " />\n"; |
155 | QCString cstr = out.utf8(); | 155 | QCString cstr = out.utf8(); |
156 | written = f.writeBlock( cstr.data(), cstr.length() ); | 156 | written = f.writeBlock( cstr.data(), cstr.length() ); |
157 | 157 | ||
158 | /* less written then we wanted */ | 158 | /* less written then we wanted */ |
159 | if ( written != (int)cstr.length() ) { | 159 | if ( written != (int)cstr.length() ) { |
160 | f.close(); | 160 | f.close(); |
161 | QFile::remove( strNewFile ); | 161 | QFile::remove( strNewFile ); |
162 | return false; | 162 | return false; |
163 | } | 163 | } |
164 | out = QString::null; | 164 | out = QString::null; |
165 | } | 165 | } |
166 | 166 | ||
167 | out += "</Tasks>"; | 167 | out += "</Tasks>"; |
168 | QCString cstr = out.utf8(); | 168 | QCString cstr = out.utf8(); |
169 | written = f.writeBlock( cstr.data(), cstr.length() ); | 169 | written = f.writeBlock( cstr.data(), cstr.length() ); |
170 | 170 | ||
171 | if ( written != (int)cstr.length() ) { | 171 | if ( written != (int)cstr.length() ) { |
172 | f.close(); | 172 | f.close(); |
173 | QFile::remove( strNewFile ); | 173 | QFile::remove( strNewFile ); |
174 | return false; | 174 | return false; |
175 | } | 175 | } |
176 | /* flush before renaming */ | 176 | /* flush before renaming */ |
177 | f.close(); | 177 | f.close(); |
178 | 178 | ||
179 | if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { | 179 | if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { |
180 | // qWarning("error renaming"); | 180 | // qWarning("error renaming"); |
181 | QFile::remove( strNewFile ); | 181 | QFile::remove( strNewFile ); |
182 | } | 182 | } |
183 | 183 | ||
184 | m_changed = false; | 184 | m_changed = false; |
185 | return true; | 185 | return true; |
186 | } | 186 | } |
187 | QArray<int> OTodoAccessXML::allRecords()const { | 187 | QArray<int> OTodoAccessXML::allRecords()const { |
188 | QArray<int> ids( m_events.count() ); | 188 | QArray<int> ids( m_events.count() ); |
189 | QMap<int, OTodo>::ConstIterator it; | 189 | QMap<int, OTodo>::ConstIterator it; |
190 | int i = 0; | 190 | int i = 0; |
191 | 191 | ||
192 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 192 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
193 | ids[i] = it.key(); | 193 | ids[i] = it.key(); |
194 | i++; | 194 | i++; |
195 | } | 195 | } |
196 | return ids; | 196 | return ids; |
197 | } | 197 | } |
198 | QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { | 198 | QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { |
199 | QArray<int> ids(0); | 199 | QArray<int> ids(0); |
200 | return ids; | 200 | return ids; |
201 | } | 201 | } |
202 | OTodo OTodoAccessXML::find( int uid )const { | 202 | OTodo OTodoAccessXML::find( int uid )const { |
203 | OTodo todo; | 203 | OTodo todo; |
204 | todo.setUid( 0 ); // isEmpty() | 204 | todo.setUid( 0 ); // isEmpty() |
205 | QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); | 205 | QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); |
206 | if ( it != m_events.end() ) | 206 | if ( it != m_events.end() ) |
207 | todo = it.data(); | 207 | todo = it.data(); |
208 | 208 | ||
209 | return todo; | 209 | return todo; |
210 | } | 210 | } |
211 | void OTodoAccessXML::clear() { | 211 | void OTodoAccessXML::clear() { |
212 | if (m_opened ) | 212 | if (m_opened ) |
213 | m_changed = true; | 213 | m_changed = true; |
214 | 214 | ||
215 | m_events.clear(); | 215 | m_events.clear(); |
216 | } | 216 | } |
217 | bool OTodoAccessXML::add( const OTodo& todo ) { | 217 | bool OTodoAccessXML::add( const OTodo& todo ) { |
218 | // qWarning("add"); | 218 | // qWarning("add"); |
219 | m_changed = true; | 219 | m_changed = true; |
220 | m_events.insert( todo.uid(), todo ); | 220 | m_events.insert( todo.uid(), todo ); |
221 | 221 | ||
222 | return true; | 222 | return true; |
223 | } | 223 | } |
224 | bool OTodoAccessXML::remove( int uid ) { | 224 | bool OTodoAccessXML::remove( int uid ) { |
225 | m_changed = true; | 225 | m_changed = true; |
226 | m_events.remove( uid ); | 226 | m_events.remove( uid ); |
227 | 227 | ||
228 | return true; | 228 | return true; |
229 | } | 229 | } |
230 | bool OTodoAccessXML::replace( const OTodo& todo) { | 230 | bool OTodoAccessXML::replace( const OTodo& todo) { |
231 | m_changed = true; | 231 | m_changed = true; |
232 | m_events.replace( todo.uid(), todo ); | 232 | m_events.replace( todo.uid(), todo ); |
233 | 233 | ||
234 | return true; | 234 | return true; |
235 | } | 235 | } |
236 | QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, | 236 | QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, |
237 | const QDate& end, | 237 | const QDate& end, |
238 | bool includeNoDates ) { | 238 | bool includeNoDates ) { |
239 | QArray<int> ids( m_events.count() ); | 239 | QArray<int> ids( m_events.count() ); |
240 | QMap<int, OTodo>::Iterator it; | 240 | QMap<int, OTodo>::Iterator it; |
241 | 241 | ||
242 | int i = 0; | 242 | int i = 0; |
243 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 243 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
244 | if ( !it.data().hasDueDate() ) { | 244 | if ( !it.data().hasDueDate() ) { |
245 | if ( includeNoDates ) { | 245 | if ( includeNoDates ) { |
246 | ids[i] = it.key(); | 246 | ids[i] = it.key(); |
247 | i++; | 247 | i++; |
248 | } | 248 | } |
249 | }else if ( it.data().dueDate() >= start && | 249 | }else if ( it.data().dueDate() >= start && |
250 | it.data().dueDate() <= end ) { | 250 | it.data().dueDate() <= end ) { |
251 | ids[i] = it.key(); | 251 | ids[i] = it.key(); |
252 | i++; | 252 | i++; |
253 | } | 253 | } |
254 | } | 254 | } |
255 | ids.resize( i ); | 255 | ids.resize( i ); |
256 | return ids; | 256 | return ids; |
257 | } | 257 | } |
258 | QArray<int> OTodoAccessXML::overDue() { | 258 | QArray<int> OTodoAccessXML::overDue() { |
259 | QArray<int> ids( m_events.count() ); | 259 | QArray<int> ids( m_events.count() ); |
260 | int i = 0; | 260 | int i = 0; |
261 | 261 | ||
262 | QMap<int, OTodo>::Iterator it; | 262 | QMap<int, OTodo>::Iterator it; |
263 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 263 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
264 | if ( it.data().isOverdue() ) { | 264 | if ( it.data().isOverdue() ) { |
265 | ids[i] = it.key(); | 265 | ids[i] = it.key(); |
266 | i++; | 266 | i++; |
267 | } | 267 | } |
268 | } | 268 | } |
269 | ids.resize( i ); | 269 | ids.resize( i ); |
270 | return ids; | 270 | return ids; |
271 | } | 271 | } |
272 | 272 | ||
273 | 273 | ||
274 | /* private */ | 274 | /* private */ |
275 | void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, | 275 | void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, |
276 | const QCString& attr, const QString& val) { | 276 | const QCString& attr, const QString& val) { |
277 | // qWarning("parse to do from XMLElement" ); | 277 | // qWarning("parse to do from XMLElement" ); |
278 | 278 | ||
279 | int *find=0; | 279 | int *find=0; |
280 | 280 | ||
281 | find = (*dict)[ attr.data() ]; | 281 | find = (*dict)[ attr.data() ]; |
282 | if (!find ) { | 282 | if (!find ) { |
283 | // qWarning("Unknown option" + it.key() ); | 283 | // qWarning("Unknown option" + it.key() ); |
284 | ev.setCustomField( attr, val ); | 284 | ev.setCustomField( attr, val ); |
285 | return; | 285 | return; |
286 | } | 286 | } |
287 | 287 | ||
288 | switch( *find ) { | 288 | switch( *find ) { |
289 | case OTodo::Uid: | 289 | case OTodo::Uid: |
290 | ev.setUid( val.toInt() ); | 290 | ev.setUid( val.toInt() ); |
291 | break; | 291 | break; |
292 | case OTodo::Category: | 292 | case OTodo::Category: |
293 | ev.setCategories( ev.idsFromString( val ) ); | 293 | ev.setCategories( ev.idsFromString( val ) ); |
294 | break; | 294 | break; |
295 | case OTodo::HasDate: | 295 | case OTodo::HasDate: |
296 | ev.setHasDueDate( val.toInt() ); | 296 | ev.setHasDueDate( val.toInt() ); |
297 | break; | 297 | break; |
298 | case OTodo::Completed: | 298 | case OTodo::Completed: |
299 | ev.setCompleted( val.toInt() ); | 299 | ev.setCompleted( val.toInt() ); |
300 | break; | 300 | break; |
301 | case OTodo::Description: | 301 | case OTodo::Description: |
302 | ev.setDescription( val ); | 302 | ev.setDescription( val ); |
303 | break; | 303 | break; |
304 | case OTodo::Summary: | 304 | case OTodo::Summary: |
305 | ev.setSummary( val ); | 305 | ev.setSummary( val ); |
306 | break; | 306 | break; |
307 | case OTodo::Priority: | 307 | case OTodo::Priority: |
308 | ev.setPriority( val.toInt() ); | 308 | ev.setPriority( val.toInt() ); |
309 | break; | 309 | break; |
310 | case OTodo::DateDay: | 310 | case OTodo::DateDay: |
311 | m_day = val.toInt(); | 311 | m_day = val.toInt(); |
312 | break; | 312 | break; |
313 | case OTodo::DateMonth: | 313 | case OTodo::DateMonth: |
314 | m_month = val.toInt(); | 314 | m_month = val.toInt(); |
315 | break; | 315 | break; |
316 | case OTodo::DateYear: | 316 | case OTodo::DateYear: |
317 | m_year = val.toInt(); | 317 | m_year = val.toInt(); |
318 | break; | 318 | break; |
319 | case OTodo::Progress: | 319 | case OTodo::Progress: |
320 | ev.setProgress( val.toInt() ); | 320 | ev.setProgress( val.toInt() ); |
321 | break; | 321 | break; |
322 | case OTodo::CrossReference: | 322 | case OTodo::CrossReference: |
323 | { | 323 | { |
324 | /* | 324 | /* |
325 | * A cross refernce looks like | 325 | * A cross refernce looks like |
326 | * appname,id;appname,id | 326 | * appname,id;appname,id |
327 | * we need to split it up | 327 | * we need to split it up |
328 | */ | 328 | */ |
329 | QStringList refs = QStringList::split(';', val ); | 329 | QStringList refs = QStringList::split(';', val ); |
330 | QStringList::Iterator strIt; | 330 | QStringList::Iterator strIt; |
331 | for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { | 331 | for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { |
332 | int pos = (*strIt).find(','); | 332 | int pos = (*strIt).find(','); |
333 | if ( pos > -1 ) | 333 | if ( pos > -1 ) |
334 | ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); | 334 | ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); |
335 | 335 | ||
336 | } | 336 | } |
337 | break; | 337 | break; |
338 | } | 338 | } |
339 | case OTodo::HasAlarmDateTime: | 339 | case OTodo::HasAlarmDateTime: |
340 | ev.setHasAlarmDateTime( val.toInt() ); | 340 | ev.setHasAlarmDateTime( val.toInt() ); |
341 | break; | 341 | break; |
342 | case OTodo::AlarmDateTime: { | 342 | case OTodo::AlarmDateTime: { |
343 | /* this sounds better ;) zecke */ | 343 | /* this sounds better ;) zecke */ |
344 | ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); | 344 | ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); |
345 | break; | 345 | break; |
346 | } | 346 | } |
347 | default: | 347 | default: |
348 | break; | 348 | break; |
349 | } | 349 | } |
350 | } | 350 | } |
351 | QString OTodoAccessXML::toString( const OTodo& ev )const { | 351 | QString OTodoAccessXML::toString( const OTodo& ev )const { |
352 | QString str; | 352 | QString str; |
353 | 353 | ||
354 | str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; | 354 | str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; |
355 | str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; | 355 | str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; |
356 | str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; | 356 | str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; |
357 | str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; | 357 | str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; |
358 | 358 | ||
359 | str += "Categories=\"" + toString( ev.categories() ) + "\" "; | 359 | str += "Categories=\"" + toString( ev.categories() ) + "\" "; |
360 | str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; | 360 | str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; |
361 | str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; | 361 | str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; |
362 | 362 | ||
363 | if ( ev.hasDueDate() ) { | 363 | if ( ev.hasDueDate() ) { |
364 | str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; | 364 | str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; |
365 | str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; | 365 | str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; |
366 | str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; | 366 | str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; |
367 | } | 367 | } |
368 | // qWarning( "Uid %d", ev.uid() ); | 368 | // qWarning( "Uid %d", ev.uid() ); |
369 | str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; | 369 | str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; |
370 | 370 | ||
371 | // append the extra options | 371 | // append the extra options |
372 | /* FIXME Qtopia::Record this is currently not | 372 | /* FIXME Qtopia::Record this is currently not |
373 | * possible you can set custom fields | 373 | * possible you can set custom fields |
374 | * but don' iterate over the list | 374 | * but don' iterate over the list |
375 | * I may do #define private protected | 375 | * I may do #define private protected |
376 | * for this case - cough --zecke | 376 | * for this case - cough --zecke |
377 | */ | 377 | */ |
378 | /* | 378 | /* |
379 | QMap<QString, QString> extras = ev.extras(); | 379 | QMap<QString, QString> extras = ev.extras(); |
380 | QMap<QString, QString>::Iterator extIt; | 380 | QMap<QString, QString>::Iterator extIt; |
381 | for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) | 381 | for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) |
382 | str += extIt.key() + "=\"" + extIt.data() + "\" "; | 382 | str += extIt.key() + "=\"" + extIt.data() + "\" "; |
383 | */ | 383 | */ |
384 | // cross refernce | 384 | // cross refernce |
385 | QStringList list = ev.relatedApps(); | 385 | QStringList list = ev.relatedApps(); |
386 | QStringList::Iterator listIt; | 386 | QStringList::Iterator listIt; |
387 | QString refs; | 387 | QString refs; |
388 | str += "CrossReference=\""; | 388 | str += "CrossReference=\""; |
389 | bool added = false; | 389 | bool added = false; |
390 | for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { | 390 | for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { |
391 | added = true; | 391 | added = true; |
392 | QArray<int> ints = ev.relations( (*listIt) ); | 392 | QArray<int> ints = ev.relations( (*listIt) ); |
393 | for ( uint i = 0; i< ints.count(); i++ ) { | 393 | for ( uint i = 0; i< ints.count(); i++ ) { |
394 | str += (*listIt) + "," + QString::number( i ) + ";"; | 394 | str += (*listIt) + "," + QString::number( i ) + ";"; |
395 | } | 395 | } |
396 | } | 396 | } |
397 | if ( added ) | 397 | if ( added ) |
398 | str = str.remove( str.length()-1, 1 ); | 398 | str = str.remove( str.length()-1, 1 ); |
399 | 399 | ||
400 | str += "\" "; | 400 | str += "\" "; |
401 | 401 | ||
402 | str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; | 402 | str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; |
403 | 403 | ||
404 | return str; | 404 | return str; |
405 | } | 405 | } |
406 | QString OTodoAccessXML::toString( const QArray<int>& ints ) const { | 406 | QString OTodoAccessXML::toString( const QArray<int>& ints ) const { |
407 | return Qtopia::Record::idsToString( ints ); | 407 | return Qtopia::Record::idsToString( ints ); |
408 | } | 408 | } |
409 | 409 | ||
410 | /* internal class for sorting */ | 410 | /* internal class for sorting |
411 | * | ||
412 | * Inspired by todoxmlio.cpp from TT | ||
413 | */ | ||
411 | 414 | ||
412 | struct OTodoXMLContainer { | 415 | struct OTodoXMLContainer { |
413 | OTodo todo; | 416 | OTodo todo; |
414 | }; | 417 | }; |
415 | /* | 418 | |
419 | namespace { | ||
420 | inline QString string( const OTodo& todo) { | ||
421 | return todo.summary().isEmpty() ? | ||
422 | todo.description().left(20 ) : | ||
423 | todo.summary(); | ||
424 | } | ||
425 | inline int completed( const OTodo& todo1, const OTodo& todo2) { | ||
426 | int ret = 0; | ||
427 | if ( todo1.isCompleted() ) ret++; | ||
428 | if ( todo2.isCompleted() ) ret--; | ||
429 | return ret; | ||
430 | } | ||
431 | inline int priority( const OTodo& t1, const OTodo& t2) { | ||
432 | return ( t1.priority() - t2.priority() ); | ||
433 | } | ||
434 | inline int description( const OTodo& t1, const OTodo& t2) { | ||
435 | return QString::compare( string(t1), string(t2) ); | ||
436 | } | ||
437 | inline int deadline( const OTodo& t1, const OTodo& t2) { | ||
438 | int ret = 0; | ||
439 | if ( t1.hasDueDate() && | ||
440 | t2.hasDueDate() ) | ||
441 | ret = t2.dueDate().daysTo( t1.dueDate() ); | ||
442 | else if ( t1.hasDueDate() ) | ||
443 | ret = -1; | ||
444 | else if ( t2.hasDueDate() ) | ||
445 | ret = 1; | ||
446 | else | ||
447 | ret = 0; | ||
448 | |||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | }; | ||
453 | |||
454 | /* | ||
416 | * Returns: | 455 | * Returns: |
417 | * 0 if item1 == item2 | 456 | * 0 if item1 == item2 |
418 | * | 457 | * |
419 | * non-zero if item1 != item2 | 458 | * non-zero if item1 != item2 |
420 | * | 459 | * |
421 | * This function returns int rather than bool so that reimplementations | 460 | * This function returns int rather than bool so that reimplementations |
422 | * can return one of three values and use it to sort by: | 461 | * can return one of three values and use it to sort by: |
423 | * | 462 | * |
424 | * 0 if item1 == item2 | 463 | * 0 if item1 == item2 |
425 | * | 464 | * |
426 | * > 0 (positive integer) if item1 > item2 | 465 | * > 0 (positive integer) if item1 > item2 |
427 | * | 466 | * |
428 | * < 0 (negative integer) if item1 < item2 | 467 | * < 0 (negative integer) if item1 < item2 |
429 | * | 468 | * |
430 | */ | 469 | */ |
431 | class OTodoXMLVector : public QVector<OTodoXMLContainer> { | 470 | class OTodoXMLVector : public QVector<OTodoXMLContainer> { |
432 | public: | 471 | public: |
433 | OTodoXMLVector(int size, bool asc, int sort) | 472 | OTodoXMLVector(int size, bool asc, int sort) |
434 | : QVector<OTodoXMLContainer>( size ) | 473 | : QVector<OTodoXMLContainer>( size ) |
435 | { | 474 | { |
436 | setAutoDelete( true ); | 475 | setAutoDelete( true ); |
437 | m_asc = asc; | 476 | m_asc = asc; |
438 | m_sort = sort; | 477 | m_sort = sort; |
439 | } | 478 | } |
440 | /* return the summary/description */ | 479 | /* return the summary/description */ |
441 | QString string( const OTodo& todo) { | 480 | QString string( const OTodo& todo) { |
442 | return todo.summary().isEmpty() ? | 481 | return todo.summary().isEmpty() ? |
443 | todo.description().left(20 ) : | 482 | todo.description().left(20 ) : |
444 | todo.summary(); | 483 | todo.summary(); |
445 | } | 484 | } |
446 | /** | 485 | /** |
447 | * we take the sortorder( switch on it ) | 486 | * we take the sortorder( switch on it ) |
448 | * | 487 | * |
449 | */ | 488 | */ |
450 | int compareItems( Item d1, Item d2 ) { | 489 | int compareItems( Item d1, Item d2 ) { |
490 | bool seComp, sePrio, seDesc, seDeadline; | ||
491 | seComp = sePrio = seDeadline = seDesc = false; | ||
451 | int ret =0; | 492 | int ret =0; |
452 | OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; | 493 | OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; |
453 | OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; | 494 | OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; |
454 | 495 | ||
455 | /* same item */ | 496 | /* same item */ |
456 | if ( con1->todo.uid() == con2->todo.uid() ) | 497 | if ( con1->todo.uid() == con2->todo.uid() ) |
457 | return 0; | 498 | return 0; |
458 | 499 | ||
459 | switch ( m_sort ) { | 500 | switch ( m_sort ) { |
460 | /* completed */ | 501 | /* completed */ |
461 | case 0: { | 502 | case 0: { |
462 | ret = 0; | 503 | ret = completed( con1->todo, con2->todo ); |
463 | if ( con1->todo.isCompleted() ) ret++; | 504 | seComp = TRUE; |
464 | if ( con2->todo.isCompleted() ) ret--; | ||
465 | break; | 505 | break; |
466 | } | 506 | } |
467 | /* priority */ | 507 | /* priority */ |
468 | case 1: { | 508 | case 1: { |
469 | ret = con1->todo.priority() - con2->todo.priority(); | 509 | ret = priority( con1->todo, con2->todo ); |
470 | qWarning(" priority %d %d %d", ret, | 510 | sePrio = TRUE; |
471 | con1->todo.priority(), | ||
472 | con2->todo.priority() | ||
473 | ); | ||
474 | break; | 511 | break; |
475 | } | 512 | } |
476 | /* description */ | 513 | /* description */ |
477 | case 2: { | 514 | case 2: { |
478 | QString str1 = string( con1->todo ); | 515 | ret = description( con1->todo, con2->todo ); |
479 | QString str2 = string( con2->todo ); | 516 | seDesc = TRUE; |
480 | ret = QString::compare( str1, str2 ); | ||
481 | break; | 517 | break; |
482 | } | 518 | } |
483 | /* deadline */ | 519 | /* deadline */ |
484 | case 3: { | 520 | case 3: { |
485 | /* either bot got a dueDate | 521 | ret = deadline( con1->todo, con2->todo ); |
486 | * or one of them got one | 522 | seDeadline = TRUE; |
487 | */ | ||
488 | if ( con1->todo.hasDueDate() && | ||
489 | con2->todo.hasDueDate() ) | ||
490 | ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() ); | ||
491 | |||
492 | |||
493 | else if ( con1->todo.hasDueDate() ) | ||
494 | ret = -1; | ||
495 | else if ( con2->todo.hasDueDate() ) | ||
496 | ret = 0; | ||
497 | break; | 523 | break; |
498 | } | 524 | } |
499 | default: | 525 | default: |
500 | ret = 0; | 526 | ret = 0; |
501 | break; | 527 | break; |
502 | }; | 528 | }; |
529 | /* | ||
530 | * FIXME do better sorting if the first sort criteria | ||
531 | * ret equals 0 start with complete and so on... | ||
532 | */ | ||
503 | 533 | ||
504 | /* twist it we're not ascending*/ | 534 | /* twist it we're not ascending*/ |
505 | if (!m_asc) | 535 | if (!m_asc) |
506 | ret = ret * -1; | 536 | ret = ret * -1; |
507 | return ret; | 537 | |
538 | if ( ret ) | ||
539 | return ret; | ||
540 | |||
541 | // default did not gave difference let's try it other way around | ||
542 | /* | ||
543 | * General try if already checked if not test | ||
544 | * and return | ||
545 | * 1.Completed | ||
546 | * 2.Priority | ||
547 | * 3.Description | ||
548 | * 4.DueDate | ||
549 | */ | ||
550 | if (!seComp ) { | ||
551 | if ( (ret = completed( con1->todo, con2->todo ) ) ) { | ||
552 | if (!m_asc ) ret *= -1; | ||
553 | return ret; | ||
554 | } | ||
555 | } | ||
556 | if (!sePrio ) { | ||
557 | if ( (ret = priority( con1->todo, con2->todo ) ) ) { | ||
558 | if (!m_asc ) ret *= -1; | ||
559 | return ret; | ||
560 | } | ||
561 | } | ||
562 | if (!seDesc ) { | ||
563 | if ( (ret = description(con1->todo, con2->todo ) ) ) { | ||
564 | if (!m_asc) ret *= -1; | ||
565 | return ret; | ||
566 | } | ||
567 | } | ||
568 | if (!seDeadline) { | ||
569 | if ( (ret = deadline( con1->todo, con2->todo ) ) ) { | ||
570 | if (!m_asc) ret *= -1; | ||
571 | return ret; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | return 0; | ||
508 | } | 576 | } |
509 | private: | 577 | private: |
510 | bool m_asc; | 578 | bool m_asc; |
511 | int m_sort; | 579 | int m_sort; |
512 | 580 | ||
513 | }; | 581 | }; |
514 | 582 | ||
515 | QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, | 583 | QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, |
516 | int sortFilter, int cat ) { | 584 | int sortFilter, int cat ) { |
517 | qWarning("sorted! %d cat", cat); | 585 | qWarning("sorted! %d cat", cat); |
518 | OTodoXMLVector vector(m_events.count(), asc,sortOrder ); | 586 | OTodoXMLVector vector(m_events.count(), asc,sortOrder ); |
519 | QMap<int, OTodo>::Iterator it; | 587 | QMap<int, OTodo>::Iterator it; |
520 | int item = 0; | 588 | int item = 0; |
521 | 589 | ||
522 | bool bCat = sortFilter & 1 ? true : false; | 590 | bool bCat = sortFilter & 1 ? true : false; |
523 | bool bOnly = sortFilter & 2 ? true : false; | 591 | bool bOnly = sortFilter & 2 ? true : false; |
524 | bool comp = sortFilter & 4 ? true : false; | 592 | bool comp = sortFilter & 4 ? true : false; |
525 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { | 593 | for ( it = m_events.begin(); it != m_events.end(); ++it ) { |
526 | 594 | ||
527 | /* show category */ | 595 | /* show category */ |
528 | if ( bCat && cat != 0) | 596 | if ( bCat && cat != 0) |
529 | if (!(*it).categories().contains( cat ) ) { | 597 | if (!(*it).categories().contains( cat ) ) { |
530 | qWarning("category mis match"); | 598 | qWarning("category mis match"); |
531 | continue; | 599 | continue; |
532 | } | 600 | } |
533 | /* isOverdue but we should not show overdue - why?*/ | 601 | /* isOverdue but we should not show overdue - why?*/ |
534 | /* if ( (*it).isOverdue() && !bOnly ) { | 602 | /* if ( (*it).isOverdue() && !bOnly ) { |
535 | qWarning("item is overdue but !bOnly"); | 603 | qWarning("item is overdue but !bOnly"); |
536 | continue; | 604 | continue; |
537 | } | 605 | } |
538 | */ | 606 | */ |
539 | if ( !(*it).isOverdue() && bOnly ) { | 607 | if ( !(*it).isOverdue() && bOnly ) { |
540 | qWarning("item is not overdue but bOnly checked"); | 608 | qWarning("item is not overdue but bOnly checked"); |
541 | continue; | 609 | continue; |
542 | } | 610 | } |
543 | 611 | ||
544 | if ((*it).isCompleted() && comp ) { | 612 | if ((*it).isCompleted() && comp ) { |
545 | qWarning("completed continue!"); | 613 | qWarning("completed continue!"); |
546 | continue; | 614 | continue; |
547 | } | 615 | } |
548 | 616 | ||
549 | 617 | ||
550 | OTodoXMLContainer* con = new OTodoXMLContainer(); | 618 | OTodoXMLContainer* con = new OTodoXMLContainer(); |
551 | con->todo = (*it); | 619 | con->todo = (*it); |
552 | vector.insert(item, con ); | 620 | vector.insert(item, con ); |
553 | item++; | 621 | item++; |
554 | } | 622 | } |
555 | qWarning("XXX %d Items added", item); | 623 | qWarning("XXX %d Items added", item); |
556 | vector.resize( item ); | 624 | vector.resize( item ); |
557 | /* sort it now */ | 625 | /* sort it now */ |
558 | vector.sort(); | 626 | vector.sort(); |
559 | /* now get the uids */ | 627 | /* now get the uids */ |
560 | QArray<int> array( vector.count() ); | 628 | QArray<int> array( vector.count() ); |
561 | for (uint i= 0; i < vector.count(); i++ ) { | 629 | for (uint i= 0; i < vector.count(); i++ ) { |
562 | array[i] = ( vector.at(i) )->todo.uid(); | 630 | array[i] = ( vector.at(i) )->todo.uid(); |
563 | } | 631 | } |
564 | qWarning("array count = %d %d", array.count(), vector.count() ); | 632 | qWarning("array count = %d %d", array.count(), vector.count() ); |
565 | return array; | 633 | return array; |
566 | }; | 634 | }; |