summaryrefslogtreecommitdiff
authorzecke <zecke>2002-10-18 03:07:09 (UTC)
committer zecke <zecke>2002-10-18 03:07:09 (UTC)
commit86b3550348cf896b568e98d21da577c3f35a1a4a (patch) (unidiff)
tree865a24eb260564d502b933a9af105871d2da6d0f
parent218bc4583c545db50f3475930d61b1c76aca3fbd (diff)
downloadopie-86b3550348cf896b568e98d21da577c3f35a1a4a.zip
opie-86b3550348cf896b568e98d21da577c3f35a1a4a.tar.gz
opie-86b3550348cf896b568e98d21da577c3f35a1a4a.tar.bz2
Hi Stefan,
this commit should fix your problems... The XML todo backend was doing some stuff wrong with sorted Records. I even have a Comment describing this behaviour which is from the current POV wrong.. need to check my brain what I though this should do
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/otodoaccessxml.cpp24
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp24
2 files changed, 38 insertions, 10 deletions
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index 3b4cab2..7a55c67 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -1,549 +1,563 @@
1#include <qfile.h> 1#include <qfile.h>
2#include <qvector.h> 2#include <qvector.h>
3 3
4#include <qpe/global.h> 4#include <qpe/global.h>
5#include <qpe/stringutil.h> 5#include <qpe/stringutil.h>
6#include <qpe/timeconversion.h> 6#include <qpe/timeconversion.h>
7 7
8#include <opie/xmltree.h> 8#include <opie/xmltree.h>
9 9
10#include "otodoaccessxml.h" 10#include "otodoaccessxml.h"
11 11
12OTodoAccessXML::OTodoAccessXML( const QString& appName, 12OTodoAccessXML::OTodoAccessXML( const QString& appName,
13 const QString& fileName ) 13 const QString& fileName )
14 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 14 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
15{ 15{
16 if (!fileName.isEmpty() ) 16 if (!fileName.isEmpty() )
17 m_file = fileName; 17 m_file = fileName;
18 else 18 else
19 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 19 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
20} 20}
21OTodoAccessXML::~OTodoAccessXML() { 21OTodoAccessXML::~OTodoAccessXML() {
22 22
23} 23}
24bool OTodoAccessXML::load() { 24bool OTodoAccessXML::load() {
25 m_opened = true; 25 m_opened = true;
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 m_events.insert(ev.uid(), ev ); 119 m_events.insert(ev.uid(), ev );
120 } 120 }
121 121
122 qWarning("counts %d", m_events.count() ); 122 qWarning("counts %d records loaded!", m_events.count() );
123 return true; 123 return true;
124} 124}
125bool OTodoAccessXML::reload() { 125bool OTodoAccessXML::reload() {
126 return load(); 126 return load();
127} 127}
128bool OTodoAccessXML::save() { 128bool OTodoAccessXML::save() {
129// qWarning("saving"); 129// qWarning("saving");
130 if (!m_opened || !m_changed ) { 130 if (!m_opened || !m_changed ) {
131// qWarning("not saving"); 131// qWarning("not saving");
132 return true; 132 return true;
133 } 133 }
134 QString strNewFile = m_file + ".new"; 134 QString strNewFile = m_file + ".new";
135 QFile f( strNewFile ); 135 QFile f( strNewFile );
136 if (!f.open( IO_WriteOnly|IO_Raw ) ) 136 if (!f.open( IO_WriteOnly|IO_Raw ) )
137 return false; 137 return false;
138 138
139 int written; 139 int written;
140 QString out; 140 QString out;
141 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 141 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
142 142
143 // for all todos 143 // for all todos
144 QMap<int, OTodo>::Iterator it; 144 QMap<int, OTodo>::Iterator it;
145 for (it = m_events.begin(); it != m_events.end(); ++it ) { 145 for (it = m_events.begin(); it != m_events.end(); ++it ) {
146 out+= "<Task " + toString( (*it) ) + " />\n"; 146 out+= "<Task " + toString( (*it) ) + " />\n";
147 QCString cstr = out.utf8(); 147 QCString cstr = out.utf8();
148 written = f.writeBlock( cstr.data(), cstr.length() ); 148 written = f.writeBlock( cstr.data(), cstr.length() );
149 149
150 /* less written then we wanted */ 150 /* less written then we wanted */
151 if ( written != (int)cstr.length() ) { 151 if ( written != (int)cstr.length() ) {
152 f.close(); 152 f.close();
153 QFile::remove( strNewFile ); 153 QFile::remove( strNewFile );
154 return false; 154 return false;
155 } 155 }
156 out = QString::null; 156 out = QString::null;
157 } 157 }
158 158
159 out += "</Tasks>"; 159 out += "</Tasks>";
160 QCString cstr = out.utf8(); 160 QCString cstr = out.utf8();
161 written = f.writeBlock( cstr.data(), cstr.length() ); 161 written = f.writeBlock( cstr.data(), cstr.length() );
162 162
163 if ( written != (int)cstr.length() ) { 163 if ( written != (int)cstr.length() ) {
164 f.close(); 164 f.close();
165 QFile::remove( strNewFile ); 165 QFile::remove( strNewFile );
166 return false; 166 return false;
167 } 167 }
168 /* flush before renaming */ 168 /* flush before renaming */
169 f.close(); 169 f.close();
170 170
171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
172// qWarning("error renaming"); 172// qWarning("error renaming");
173 QFile::remove( strNewFile ); 173 QFile::remove( strNewFile );
174 } 174 }
175 175
176 m_changed = false; 176 m_changed = false;
177 return true; 177 return true;
178} 178}
179QArray<int> OTodoAccessXML::allRecords()const { 179QArray<int> OTodoAccessXML::allRecords()const {
180 QArray<int> ids( m_events.count() ); 180 QArray<int> ids( m_events.count() );
181 QMap<int, OTodo>::ConstIterator it; 181 QMap<int, OTodo>::ConstIterator it;
182 int i = 0; 182 int i = 0;
183 183
184 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 184 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
185 ids[i] = it.key(); 185 ids[i] = it.key();
186 i++; 186 i++;
187 } 187 }
188 return ids; 188 return ids;
189} 189}
190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { 190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
191 QArray<int> ids(0); 191 QArray<int> ids(0);
192 return ids; 192 return ids;
193} 193}
194OTodo OTodoAccessXML::find( int uid )const { 194OTodo OTodoAccessXML::find( int uid )const {
195 OTodo todo; 195 OTodo todo;
196 todo.setUid( 0 ); // isEmpty() 196 todo.setUid( 0 ); // isEmpty()
197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
198 if ( it != m_events.end() ) 198 if ( it != m_events.end() )
199 todo = it.data(); 199 todo = it.data();
200 200
201 return todo; 201 return todo;
202} 202}
203void OTodoAccessXML::clear() { 203void OTodoAccessXML::clear() {
204 if (m_opened ) 204 if (m_opened )
205 m_changed = true; 205 m_changed = true;
206 206
207 m_events.clear(); 207 m_events.clear();
208} 208}
209bool OTodoAccessXML::add( const OTodo& todo ) { 209bool OTodoAccessXML::add( const OTodo& todo ) {
210// qWarning("add"); 210// qWarning("add");
211 m_changed = true; 211 m_changed = true;
212 m_events.insert( todo.uid(), todo ); 212 m_events.insert( todo.uid(), todo );
213 213
214 return true; 214 return true;
215} 215}
216bool OTodoAccessXML::remove( int uid ) { 216bool OTodoAccessXML::remove( int uid ) {
217 m_changed = true; 217 m_changed = true;
218 m_events.remove( uid ); 218 m_events.remove( uid );
219 219
220 return true; 220 return true;
221} 221}
222bool OTodoAccessXML::replace( const OTodo& todo) { 222bool OTodoAccessXML::replace( const OTodo& todo) {
223 m_changed = true; 223 m_changed = true;
224 m_events.replace( todo.uid(), todo ); 224 m_events.replace( todo.uid(), todo );
225 225
226 return true; 226 return true;
227} 227}
228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
229 const QDate& end, 229 const QDate& end,
230 bool includeNoDates ) { 230 bool includeNoDates ) {
231 QArray<int> ids( m_events.count() ); 231 QArray<int> ids( m_events.count() );
232 QMap<int, OTodo>::Iterator it; 232 QMap<int, OTodo>::Iterator it;
233 233
234 int i = 0; 234 int i = 0;
235 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 235 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
236 if ( !it.data().hasDueDate() ) { 236 if ( !it.data().hasDueDate() ) {
237 if ( includeNoDates ) { 237 if ( includeNoDates ) {
238 ids[i] = it.key(); 238 ids[i] = it.key();
239 i++; 239 i++;
240 } 240 }
241 }else if ( it.data().dueDate() >= start && 241 }else if ( it.data().dueDate() >= start &&
242 it.data().dueDate() <= end ) { 242 it.data().dueDate() <= end ) {
243 ids[i] = it.key(); 243 ids[i] = it.key();
244 i++; 244 i++;
245 } 245 }
246 } 246 }
247 ids.resize( i ); 247 ids.resize( i );
248 return ids; 248 return ids;
249} 249}
250QArray<int> OTodoAccessXML::overDue() { 250QArray<int> OTodoAccessXML::overDue() {
251 QArray<int> ids( m_events.count() ); 251 QArray<int> ids( m_events.count() );
252 int i = 0; 252 int i = 0;
253 253
254 QMap<int, OTodo>::Iterator it; 254 QMap<int, OTodo>::Iterator it;
255 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 255 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
256 if ( it.data().isOverdue() ) { 256 if ( it.data().isOverdue() ) {
257 ids[i] = it.key(); 257 ids[i] = it.key();
258 i++; 258 i++;
259 } 259 }
260 } 260 }
261 ids.resize( i ); 261 ids.resize( i );
262 return ids; 262 return ids;
263} 263}
264 264
265 265
266/* private */ 266/* private */
267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
268 const QCString& attr, const QString& val) { 268 const QCString& attr, const QString& val) {
269// qWarning("parse to do from XMLElement" ); 269// qWarning("parse to do from XMLElement" );
270 270
271 int *find=0; 271 int *find=0;
272 272
273 find = (*dict)[ attr.data() ]; 273 find = (*dict)[ attr.data() ];
274 if (!find ) { 274 if (!find ) {
275// qWarning("Unknown option" + it.key() ); 275// qWarning("Unknown option" + it.key() );
276 ev.setCustomField( attr, val ); 276 ev.setCustomField( attr, val );
277 return; 277 return;
278 } 278 }
279 279
280 switch( *find ) { 280 switch( *find ) {
281 case OTodo::Uid: 281 case OTodo::Uid:
282 ev.setUid( val.toInt() ); 282 ev.setUid( val.toInt() );
283 break; 283 break;
284 case OTodo::Category: 284 case OTodo::Category:
285 ev.setCategories( ev.idsFromString( val ) ); 285 ev.setCategories( ev.idsFromString( val ) );
286 break; 286 break;
287 case OTodo::HasDate: 287 case OTodo::HasDate:
288 ev.setHasDueDate( val.toInt() ); 288 ev.setHasDueDate( val.toInt() );
289 break; 289 break;
290 case OTodo::Completed: 290 case OTodo::Completed:
291 ev.setCompleted( val.toInt() ); 291 ev.setCompleted( val.toInt() );
292 break; 292 break;
293 case OTodo::Description: 293 case OTodo::Description:
294 ev.setDescription( val ); 294 ev.setDescription( val );
295 break; 295 break;
296 case OTodo::Summary: 296 case OTodo::Summary:
297 ev.setSummary( val ); 297 ev.setSummary( val );
298 break; 298 break;
299 case OTodo::Priority: 299 case OTodo::Priority:
300 ev.setPriority( val.toInt() ); 300 ev.setPriority( val.toInt() );
301 break; 301 break;
302 case OTodo::DateDay: 302 case OTodo::DateDay:
303 m_day = val.toInt(); 303 m_day = val.toInt();
304 break; 304 break;
305 case OTodo::DateMonth: 305 case OTodo::DateMonth:
306 m_month = val.toInt(); 306 m_month = val.toInt();
307 break; 307 break;
308 case OTodo::DateYear: 308 case OTodo::DateYear:
309 m_year = val.toInt(); 309 m_year = val.toInt();
310 break; 310 break;
311 case OTodo::Progress: 311 case OTodo::Progress:
312 ev.setProgress( val.toInt() ); 312 ev.setProgress( val.toInt() );
313 break; 313 break;
314 case OTodo::CrossReference: 314 case OTodo::CrossReference:
315 { 315 {
316 /* 316 /*
317 * A cross refernce looks like 317 * A cross refernce looks like
318 * appname,id;appname,id 318 * appname,id;appname,id
319 * we need to split it up 319 * we need to split it up
320 */ 320 */
321 QStringList refs = QStringList::split(';', val ); 321 QStringList refs = QStringList::split(';', val );
322 QStringList::Iterator strIt; 322 QStringList::Iterator strIt;
323 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 323 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
324 int pos = (*strIt).find(','); 324 int pos = (*strIt).find(',');
325 if ( pos > -1 ) 325 if ( pos > -1 )
326 ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); 326 ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
327 327
328 } 328 }
329 break; 329 break;
330 } 330 }
331 case OTodo::HasAlarmDateTime: 331 case OTodo::HasAlarmDateTime:
332 ev.setHasAlarmDateTime( val.toInt() ); 332 ev.setHasAlarmDateTime( val.toInt() );
333 break; 333 break;
334 case OTodo::AlarmDateTime: { 334 case OTodo::AlarmDateTime: {
335 /* this sounds better ;) zecke */ 335 /* this sounds better ;) zecke */
336 ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); 336 ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) );
337 break; 337 break;
338 } 338 }
339 default: 339 default:
340 break; 340 break;
341 } 341 }
342 342
343 if ( ev.hasDueDate() ) { 343 if ( ev.hasDueDate() ) {
344 QDate date( m_year, m_month, m_day ); 344 QDate date( m_year, m_month, m_day );
345 ev.setDueDate( date ); 345 ev.setDueDate( date );
346 } 346 }
347} 347}
348QString OTodoAccessXML::toString( const OTodo& ev )const { 348QString OTodoAccessXML::toString( const OTodo& ev )const {
349 QString str; 349 QString str;
350 350
351 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 351 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
352 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 352 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
353 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 353 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
354 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 354 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
355 355
356 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 356 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
357 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 357 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
358 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 358 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
359 359
360 if ( ev.hasDueDate() ) { 360 if ( ev.hasDueDate() ) {
361 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 361 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
362 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 362 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
363 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 363 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
364 } 364 }
365// qWarning( "Uid %d", ev.uid() ); 365// qWarning( "Uid %d", ev.uid() );
366 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 366 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
367 367
368// append the extra options 368// append the extra options
369 /* FIXME Qtopia::Record this is currently not 369 /* FIXME Qtopia::Record this is currently not
370 * possible you can set custom fields 370 * possible you can set custom fields
371 * but don' iterate over the list 371 * but don' iterate over the list
372 * I may do #define private protected 372 * I may do #define private protected
373 * for this case - cough --zecke 373 * for this case - cough --zecke
374 */ 374 */
375 /* 375 /*
376 QMap<QString, QString> extras = ev.extras(); 376 QMap<QString, QString> extras = ev.extras();
377 QMap<QString, QString>::Iterator extIt; 377 QMap<QString, QString>::Iterator extIt;
378 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 378 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
379 str += extIt.key() + "=\"" + extIt.data() + "\" "; 379 str += extIt.key() + "=\"" + extIt.data() + "\" ";
380 */ 380 */
381 // cross refernce 381 // cross refernce
382 QStringList list = ev.relatedApps(); 382 QStringList list = ev.relatedApps();
383 QStringList::Iterator listIt; 383 QStringList::Iterator listIt;
384 QString refs; 384 QString refs;
385 str += "CrossReference=\""; 385 str += "CrossReference=\"";
386 bool added = false; 386 bool added = false;
387 for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { 387 for ( listIt = list.begin(); listIt != list.end(); ++listIt ) {
388 added = true; 388 added = true;
389 QArray<int> ints = ev.relations( (*listIt) ); 389 QArray<int> ints = ev.relations( (*listIt) );
390 for ( uint i = 0; i< ints.count(); i++ ) { 390 for ( uint i = 0; i< ints.count(); i++ ) {
391 str += (*listIt) + "," + QString::number( i ) + ";"; 391 str += (*listIt) + "," + QString::number( i ) + ";";
392 } 392 }
393 } 393 }
394 if ( added ) 394 if ( added )
395 str = str.remove( str.length()-1, 1 ); 395 str = str.remove( str.length()-1, 1 );
396 396
397 str += "\" "; 397 str += "\" ";
398 398
399 str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; 399 str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" ";
400 400
401 return str; 401 return str;
402} 402}
403QString OTodoAccessXML::toString( const QArray<int>& ints ) const { 403QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
404 return Qtopia::Record::idsToString( ints ); 404 return Qtopia::Record::idsToString( ints );
405} 405}
406 406
407/* internal class for sorting */ 407/* internal class for sorting */
408 408
409struct OTodoXMLContainer { 409struct OTodoXMLContainer {
410 OTodo todo; 410 OTodo todo;
411}; 411};
412 /* 412 /*
413 * Returns: 413 * Returns:
414 * 0 if item1 == item2 414 * 0 if item1 == item2
415 * 415 *
416 * non-zero if item1 != item2 416 * non-zero if item1 != item2
417 * 417 *
418 * This function returns int rather than bool so that reimplementations 418 * This function returns int rather than bool so that reimplementations
419 * can return one of three values and use it to sort by: 419 * can return one of three values and use it to sort by:
420 * 420 *
421 * 0 if item1 == item2 421 * 0 if item1 == item2
422 * 422 *
423 * > 0 (positive integer) if item1 > item2 423 * > 0 (positive integer) if item1 > item2
424 * 424 *
425 * < 0 (negative integer) if item1 < item2 425 * < 0 (negative integer) if item1 < item2
426 * 426 *
427 */ 427 */
428class OTodoXMLVector : public QVector<OTodoXMLContainer> { 428class OTodoXMLVector : public QVector<OTodoXMLContainer> {
429public: 429public:
430 OTodoXMLVector(int size, bool asc, int sort) 430 OTodoXMLVector(int size, bool asc, int sort)
431 : QVector<OTodoXMLContainer>( size ) 431 : QVector<OTodoXMLContainer>( size )
432 { 432 {
433 setAutoDelete( true ); 433 setAutoDelete( true );
434 m_asc = asc; 434 m_asc = asc;
435 m_sort = sort; 435 m_sort = sort;
436 } 436 }
437 /* return the summary/description */ 437 /* return the summary/description */
438 QString string( const OTodo& todo) { 438 QString string( const OTodo& todo) {
439 return todo.summary().isEmpty() ? 439 return todo.summary().isEmpty() ?
440 todo.description().left(20 ) : 440 todo.description().left(20 ) :
441 todo.summary(); 441 todo.summary();
442 } 442 }
443 /** 443 /**
444 * we take the sortorder( switch on it ) 444 * we take the sortorder( switch on it )
445 * 445 *
446 */ 446 */
447 int compareItems( Item d1, Item d2 ) { 447 int compareItems( Item d1, Item d2 ) {
448 int ret =0; 448 int ret =0;
449 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; 449 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
450 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; 450 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
451 451
452 /* same item */ 452 /* same item */
453 if ( con1->todo.uid() == con2->todo.uid() ) 453 if ( con1->todo.uid() == con2->todo.uid() )
454 return 0; 454 return 0;
455 455
456 switch ( m_sort ) { 456 switch ( m_sort ) {
457 /* completed */ 457 /* completed */
458 case 0: { 458 case 0: {
459 ret = 0; 459 ret = 0;
460 if ( con1->todo.isCompleted() ) ret++; 460 if ( con1->todo.isCompleted() ) ret++;
461 if ( con2->todo.isCompleted() ) ret--; 461 if ( con2->todo.isCompleted() ) ret--;
462 break; 462 break;
463 } 463 }
464 /* priority */ 464 /* priority */
465 case 1: { 465 case 1: {
466 ret = con1->todo.priority() - con2->todo.priority(); 466 ret = con1->todo.priority() - con2->todo.priority();
467 qWarning(" priority %d %d %d", ret, 467 qWarning(" priority %d %d %d", ret,
468 con1->todo.priority(), 468 con1->todo.priority(),
469 con2->todo.priority() 469 con2->todo.priority()
470 ); 470 );
471 break; 471 break;
472 } 472 }
473 /* description */ 473 /* description */
474 case 2: { 474 case 2: {
475 QString str1 = string( con1->todo ); 475 QString str1 = string( con1->todo );
476 QString str2 = string( con2->todo ); 476 QString str2 = string( con2->todo );
477 ret = QString::compare( str1, str2 ); 477 ret = QString::compare( str1, str2 );
478 break; 478 break;
479 } 479 }
480 /* deadline */ 480 /* deadline */
481 case 3: { 481 case 3: {
482 /* either bot got a dueDate 482 /* either bot got a dueDate
483 * or one of them got one 483 * or one of them got one
484 */ 484 */
485 if ( con1->todo.hasDueDate() && 485 if ( con1->todo.hasDueDate() &&
486 con2->todo.hasDueDate() ) 486 con2->todo.hasDueDate() )
487 ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() ); 487 ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() );
488 488
489 489
490 else if ( con1->todo.hasDueDate() ) 490 else if ( con1->todo.hasDueDate() )
491 ret = -1; 491 ret = -1;
492 else if ( con2->todo.hasDueDate() ) 492 else if ( con2->todo.hasDueDate() )
493 ret = 0; 493 ret = 0;
494 break; 494 break;
495 } 495 }
496 default: 496 default:
497 ret = 0; 497 ret = 0;
498 break; 498 break;
499 }; 499 };
500 500
501 /* twist it we're not ascending*/ 501 /* twist it we're not ascending*/
502 if (!m_asc) 502 if (!m_asc)
503 ret = ret * -1; 503 ret = ret * -1;
504 return ret; 504 return ret;
505 } 505 }
506 private: 506 private:
507 bool m_asc; 507 bool m_asc;
508 int m_sort; 508 int m_sort;
509 509
510}; 510};
511 511
512QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, 512QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
513 int sortFilter, int cat ) { 513 int sortFilter, int cat ) {
514 qWarning("sorted! %d cat", cat); 514 qWarning("sorted! %d cat", cat);
515 OTodoXMLVector vector(m_events.count(), asc,sortOrder ); 515 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
516 QMap<int, OTodo>::Iterator it; 516 QMap<int, OTodo>::Iterator it;
517 int item = 0; 517 int item = 0;
518 518
519 bool bCat = sortFilter & 1 ? true : false; 519 bool bCat = sortFilter & 1 ? true : false;
520 bool bOnly = sortFilter & 2 ? true : false; 520 bool bOnly = sortFilter & 2 ? true : false;
521 bool comp = sortFilter & 4 ? true : false;
521 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 522 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
522 523
523 /* show category */ 524 /* show category */
524 if ( bCat && cat != 0) 525 if ( bCat && cat != 0)
525 if (!(*it).categories().contains( cat ) ) 526 if (!(*it).categories().contains( cat ) ) {
527 qWarning("category mis match");
526 continue; 528 continue;
527 /* isOverdue but we should not show overdue */ 529 }
528 if ( (*it).isOverdue() && !bOnly ) 530 /* isOverdue but we should not show overdue - why?*/
531/* if ( (*it).isOverdue() && !bOnly ) {
532 qWarning("item is overdue but !bOnly");
533 continue;
534 }
535*/
536 if ( !(*it).isOverdue() && bOnly ) {
537 qWarning("item is not overdue but bOnly checked");
529 continue; 538 continue;
530 if ( !(*it).isOverdue() && bOnly ) 539 }
540
541 if ((*it).isCompleted() && comp ) {
542 qWarning("completed continue!");
531 continue; 543 continue;
544 }
532 545
533 546
534 OTodoXMLContainer* con = new OTodoXMLContainer(); 547 OTodoXMLContainer* con = new OTodoXMLContainer();
535 con->todo = (*it); 548 con->todo = (*it);
536 vector.insert(item, con ); 549 vector.insert(item, con );
537 item++; 550 item++;
538 } 551 }
552 qWarning("XXX %d Items added", item);
539 vector.resize( item ); 553 vector.resize( item );
540 /* sort it now */ 554 /* sort it now */
541 vector.sort(); 555 vector.sort();
542 /* now get the uids */ 556 /* now get the uids */
543 QArray<int> array( vector.count() ); 557 QArray<int> array( vector.count() );
544 for (uint i= 0; i < vector.count(); i++ ) { 558 for (uint i= 0; i < vector.count(); i++ ) {
545 array[i] = ( vector.at(i) )->todo.uid(); 559 array[i] = ( vector.at(i) )->todo.uid();
546 } 560 }
547 qWarning("array count = %d %d", array.count(), vector.count() ); 561 qWarning("array count = %d %d", array.count(), vector.count() );
548 return array; 562 return array;
549}; 563};
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp
index 3b4cab2..7a55c67 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.cpp
+++ b/libopie2/opiepim/backend/otodoaccessxml.cpp
@@ -1,549 +1,563 @@
1#include <qfile.h> 1#include <qfile.h>
2#include <qvector.h> 2#include <qvector.h>
3 3
4#include <qpe/global.h> 4#include <qpe/global.h>
5#include <qpe/stringutil.h> 5#include <qpe/stringutil.h>
6#include <qpe/timeconversion.h> 6#include <qpe/timeconversion.h>
7 7
8#include <opie/xmltree.h> 8#include <opie/xmltree.h>
9 9
10#include "otodoaccessxml.h" 10#include "otodoaccessxml.h"
11 11
12OTodoAccessXML::OTodoAccessXML( const QString& appName, 12OTodoAccessXML::OTodoAccessXML( const QString& appName,
13 const QString& fileName ) 13 const QString& fileName )
14 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 14 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
15{ 15{
16 if (!fileName.isEmpty() ) 16 if (!fileName.isEmpty() )
17 m_file = fileName; 17 m_file = fileName;
18 else 18 else
19 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 19 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
20} 20}
21OTodoAccessXML::~OTodoAccessXML() { 21OTodoAccessXML::~OTodoAccessXML() {
22 22
23} 23}
24bool OTodoAccessXML::load() { 24bool OTodoAccessXML::load() {
25 m_opened = true; 25 m_opened = true;
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 m_events.insert(ev.uid(), ev ); 119 m_events.insert(ev.uid(), ev );
120 } 120 }
121 121
122 qWarning("counts %d", m_events.count() ); 122 qWarning("counts %d records loaded!", m_events.count() );
123 return true; 123 return true;
124} 124}
125bool OTodoAccessXML::reload() { 125bool OTodoAccessXML::reload() {
126 return load(); 126 return load();
127} 127}
128bool OTodoAccessXML::save() { 128bool OTodoAccessXML::save() {
129// qWarning("saving"); 129// qWarning("saving");
130 if (!m_opened || !m_changed ) { 130 if (!m_opened || !m_changed ) {
131// qWarning("not saving"); 131// qWarning("not saving");
132 return true; 132 return true;
133 } 133 }
134 QString strNewFile = m_file + ".new"; 134 QString strNewFile = m_file + ".new";
135 QFile f( strNewFile ); 135 QFile f( strNewFile );
136 if (!f.open( IO_WriteOnly|IO_Raw ) ) 136 if (!f.open( IO_WriteOnly|IO_Raw ) )
137 return false; 137 return false;
138 138
139 int written; 139 int written;
140 QString out; 140 QString out;
141 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 141 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
142 142
143 // for all todos 143 // for all todos
144 QMap<int, OTodo>::Iterator it; 144 QMap<int, OTodo>::Iterator it;
145 for (it = m_events.begin(); it != m_events.end(); ++it ) { 145 for (it = m_events.begin(); it != m_events.end(); ++it ) {
146 out+= "<Task " + toString( (*it) ) + " />\n"; 146 out+= "<Task " + toString( (*it) ) + " />\n";
147 QCString cstr = out.utf8(); 147 QCString cstr = out.utf8();
148 written = f.writeBlock( cstr.data(), cstr.length() ); 148 written = f.writeBlock( cstr.data(), cstr.length() );
149 149
150 /* less written then we wanted */ 150 /* less written then we wanted */
151 if ( written != (int)cstr.length() ) { 151 if ( written != (int)cstr.length() ) {
152 f.close(); 152 f.close();
153 QFile::remove( strNewFile ); 153 QFile::remove( strNewFile );
154 return false; 154 return false;
155 } 155 }
156 out = QString::null; 156 out = QString::null;
157 } 157 }
158 158
159 out += "</Tasks>"; 159 out += "</Tasks>";
160 QCString cstr = out.utf8(); 160 QCString cstr = out.utf8();
161 written = f.writeBlock( cstr.data(), cstr.length() ); 161 written = f.writeBlock( cstr.data(), cstr.length() );
162 162
163 if ( written != (int)cstr.length() ) { 163 if ( written != (int)cstr.length() ) {
164 f.close(); 164 f.close();
165 QFile::remove( strNewFile ); 165 QFile::remove( strNewFile );
166 return false; 166 return false;
167 } 167 }
168 /* flush before renaming */ 168 /* flush before renaming */
169 f.close(); 169 f.close();
170 170
171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 171 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
172// qWarning("error renaming"); 172// qWarning("error renaming");
173 QFile::remove( strNewFile ); 173 QFile::remove( strNewFile );
174 } 174 }
175 175
176 m_changed = false; 176 m_changed = false;
177 return true; 177 return true;
178} 178}
179QArray<int> OTodoAccessXML::allRecords()const { 179QArray<int> OTodoAccessXML::allRecords()const {
180 QArray<int> ids( m_events.count() ); 180 QArray<int> ids( m_events.count() );
181 QMap<int, OTodo>::ConstIterator it; 181 QMap<int, OTodo>::ConstIterator it;
182 int i = 0; 182 int i = 0;
183 183
184 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 184 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
185 ids[i] = it.key(); 185 ids[i] = it.key();
186 i++; 186 i++;
187 } 187 }
188 return ids; 188 return ids;
189} 189}
190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { 190QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
191 QArray<int> ids(0); 191 QArray<int> ids(0);
192 return ids; 192 return ids;
193} 193}
194OTodo OTodoAccessXML::find( int uid )const { 194OTodo OTodoAccessXML::find( int uid )const {
195 OTodo todo; 195 OTodo todo;
196 todo.setUid( 0 ); // isEmpty() 196 todo.setUid( 0 ); // isEmpty()
197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 197 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
198 if ( it != m_events.end() ) 198 if ( it != m_events.end() )
199 todo = it.data(); 199 todo = it.data();
200 200
201 return todo; 201 return todo;
202} 202}
203void OTodoAccessXML::clear() { 203void OTodoAccessXML::clear() {
204 if (m_opened ) 204 if (m_opened )
205 m_changed = true; 205 m_changed = true;
206 206
207 m_events.clear(); 207 m_events.clear();
208} 208}
209bool OTodoAccessXML::add( const OTodo& todo ) { 209bool OTodoAccessXML::add( const OTodo& todo ) {
210// qWarning("add"); 210// qWarning("add");
211 m_changed = true; 211 m_changed = true;
212 m_events.insert( todo.uid(), todo ); 212 m_events.insert( todo.uid(), todo );
213 213
214 return true; 214 return true;
215} 215}
216bool OTodoAccessXML::remove( int uid ) { 216bool OTodoAccessXML::remove( int uid ) {
217 m_changed = true; 217 m_changed = true;
218 m_events.remove( uid ); 218 m_events.remove( uid );
219 219
220 return true; 220 return true;
221} 221}
222bool OTodoAccessXML::replace( const OTodo& todo) { 222bool OTodoAccessXML::replace( const OTodo& todo) {
223 m_changed = true; 223 m_changed = true;
224 m_events.replace( todo.uid(), todo ); 224 m_events.replace( todo.uid(), todo );
225 225
226 return true; 226 return true;
227} 227}
228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 228QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
229 const QDate& end, 229 const QDate& end,
230 bool includeNoDates ) { 230 bool includeNoDates ) {
231 QArray<int> ids( m_events.count() ); 231 QArray<int> ids( m_events.count() );
232 QMap<int, OTodo>::Iterator it; 232 QMap<int, OTodo>::Iterator it;
233 233
234 int i = 0; 234 int i = 0;
235 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 235 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
236 if ( !it.data().hasDueDate() ) { 236 if ( !it.data().hasDueDate() ) {
237 if ( includeNoDates ) { 237 if ( includeNoDates ) {
238 ids[i] = it.key(); 238 ids[i] = it.key();
239 i++; 239 i++;
240 } 240 }
241 }else if ( it.data().dueDate() >= start && 241 }else if ( it.data().dueDate() >= start &&
242 it.data().dueDate() <= end ) { 242 it.data().dueDate() <= end ) {
243 ids[i] = it.key(); 243 ids[i] = it.key();
244 i++; 244 i++;
245 } 245 }
246 } 246 }
247 ids.resize( i ); 247 ids.resize( i );
248 return ids; 248 return ids;
249} 249}
250QArray<int> OTodoAccessXML::overDue() { 250QArray<int> OTodoAccessXML::overDue() {
251 QArray<int> ids( m_events.count() ); 251 QArray<int> ids( m_events.count() );
252 int i = 0; 252 int i = 0;
253 253
254 QMap<int, OTodo>::Iterator it; 254 QMap<int, OTodo>::Iterator it;
255 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 255 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
256 if ( it.data().isOverdue() ) { 256 if ( it.data().isOverdue() ) {
257 ids[i] = it.key(); 257 ids[i] = it.key();
258 i++; 258 i++;
259 } 259 }
260 } 260 }
261 ids.resize( i ); 261 ids.resize( i );
262 return ids; 262 return ids;
263} 263}
264 264
265 265
266/* private */ 266/* private */
267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 267void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
268 const QCString& attr, const QString& val) { 268 const QCString& attr, const QString& val) {
269// qWarning("parse to do from XMLElement" ); 269// qWarning("parse to do from XMLElement" );
270 270
271 int *find=0; 271 int *find=0;
272 272
273 find = (*dict)[ attr.data() ]; 273 find = (*dict)[ attr.data() ];
274 if (!find ) { 274 if (!find ) {
275// qWarning("Unknown option" + it.key() ); 275// qWarning("Unknown option" + it.key() );
276 ev.setCustomField( attr, val ); 276 ev.setCustomField( attr, val );
277 return; 277 return;
278 } 278 }
279 279
280 switch( *find ) { 280 switch( *find ) {
281 case OTodo::Uid: 281 case OTodo::Uid:
282 ev.setUid( val.toInt() ); 282 ev.setUid( val.toInt() );
283 break; 283 break;
284 case OTodo::Category: 284 case OTodo::Category:
285 ev.setCategories( ev.idsFromString( val ) ); 285 ev.setCategories( ev.idsFromString( val ) );
286 break; 286 break;
287 case OTodo::HasDate: 287 case OTodo::HasDate:
288 ev.setHasDueDate( val.toInt() ); 288 ev.setHasDueDate( val.toInt() );
289 break; 289 break;
290 case OTodo::Completed: 290 case OTodo::Completed:
291 ev.setCompleted( val.toInt() ); 291 ev.setCompleted( val.toInt() );
292 break; 292 break;
293 case OTodo::Description: 293 case OTodo::Description:
294 ev.setDescription( val ); 294 ev.setDescription( val );
295 break; 295 break;
296 case OTodo::Summary: 296 case OTodo::Summary:
297 ev.setSummary( val ); 297 ev.setSummary( val );
298 break; 298 break;
299 case OTodo::Priority: 299 case OTodo::Priority:
300 ev.setPriority( val.toInt() ); 300 ev.setPriority( val.toInt() );
301 break; 301 break;
302 case OTodo::DateDay: 302 case OTodo::DateDay:
303 m_day = val.toInt(); 303 m_day = val.toInt();
304 break; 304 break;
305 case OTodo::DateMonth: 305 case OTodo::DateMonth:
306 m_month = val.toInt(); 306 m_month = val.toInt();
307 break; 307 break;
308 case OTodo::DateYear: 308 case OTodo::DateYear:
309 m_year = val.toInt(); 309 m_year = val.toInt();
310 break; 310 break;
311 case OTodo::Progress: 311 case OTodo::Progress:
312 ev.setProgress( val.toInt() ); 312 ev.setProgress( val.toInt() );
313 break; 313 break;
314 case OTodo::CrossReference: 314 case OTodo::CrossReference:
315 { 315 {
316 /* 316 /*
317 * A cross refernce looks like 317 * A cross refernce looks like
318 * appname,id;appname,id 318 * appname,id;appname,id
319 * we need to split it up 319 * we need to split it up
320 */ 320 */
321 QStringList refs = QStringList::split(';', val ); 321 QStringList refs = QStringList::split(';', val );
322 QStringList::Iterator strIt; 322 QStringList::Iterator strIt;
323 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 323 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
324 int pos = (*strIt).find(','); 324 int pos = (*strIt).find(',');
325 if ( pos > -1 ) 325 if ( pos > -1 )
326 ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() ); 326 ev.addRelation( (*strIt).left(pos), (*strIt).mid(pos+1).toInt() );
327 327
328 } 328 }
329 break; 329 break;
330 } 330 }
331 case OTodo::HasAlarmDateTime: 331 case OTodo::HasAlarmDateTime:
332 ev.setHasAlarmDateTime( val.toInt() ); 332 ev.setHasAlarmDateTime( val.toInt() );
333 break; 333 break;
334 case OTodo::AlarmDateTime: { 334 case OTodo::AlarmDateTime: {
335 /* this sounds better ;) zecke */ 335 /* this sounds better ;) zecke */
336 ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) ); 336 ev.setAlarmDateTime( TimeConversion::fromISO8601( val.local8Bit() ) );
337 break; 337 break;
338 } 338 }
339 default: 339 default:
340 break; 340 break;
341 } 341 }
342 342
343 if ( ev.hasDueDate() ) { 343 if ( ev.hasDueDate() ) {
344 QDate date( m_year, m_month, m_day ); 344 QDate date( m_year, m_month, m_day );
345 ev.setDueDate( date ); 345 ev.setDueDate( date );
346 } 346 }
347} 347}
348QString OTodoAccessXML::toString( const OTodo& ev )const { 348QString OTodoAccessXML::toString( const OTodo& ev )const {
349 QString str; 349 QString str;
350 350
351 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 351 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
352 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 352 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
353 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 353 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
354 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 354 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
355 355
356 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 356 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
357 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 357 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
358 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 358 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
359 359
360 if ( ev.hasDueDate() ) { 360 if ( ev.hasDueDate() ) {
361 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 361 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
362 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 362 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
363 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 363 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
364 } 364 }
365// qWarning( "Uid %d", ev.uid() ); 365// qWarning( "Uid %d", ev.uid() );
366 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 366 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
367 367
368// append the extra options 368// append the extra options
369 /* FIXME Qtopia::Record this is currently not 369 /* FIXME Qtopia::Record this is currently not
370 * possible you can set custom fields 370 * possible you can set custom fields
371 * but don' iterate over the list 371 * but don' iterate over the list
372 * I may do #define private protected 372 * I may do #define private protected
373 * for this case - cough --zecke 373 * for this case - cough --zecke
374 */ 374 */
375 /* 375 /*
376 QMap<QString, QString> extras = ev.extras(); 376 QMap<QString, QString> extras = ev.extras();
377 QMap<QString, QString>::Iterator extIt; 377 QMap<QString, QString>::Iterator extIt;
378 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 378 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
379 str += extIt.key() + "=\"" + extIt.data() + "\" "; 379 str += extIt.key() + "=\"" + extIt.data() + "\" ";
380 */ 380 */
381 // cross refernce 381 // cross refernce
382 QStringList list = ev.relatedApps(); 382 QStringList list = ev.relatedApps();
383 QStringList::Iterator listIt; 383 QStringList::Iterator listIt;
384 QString refs; 384 QString refs;
385 str += "CrossReference=\""; 385 str += "CrossReference=\"";
386 bool added = false; 386 bool added = false;
387 for ( listIt = list.begin(); listIt != list.end(); ++listIt ) { 387 for ( listIt = list.begin(); listIt != list.end(); ++listIt ) {
388 added = true; 388 added = true;
389 QArray<int> ints = ev.relations( (*listIt) ); 389 QArray<int> ints = ev.relations( (*listIt) );
390 for ( uint i = 0; i< ints.count(); i++ ) { 390 for ( uint i = 0; i< ints.count(); i++ ) {
391 str += (*listIt) + "," + QString::number( i ) + ";"; 391 str += (*listIt) + "," + QString::number( i ) + ";";
392 } 392 }
393 } 393 }
394 if ( added ) 394 if ( added )
395 str = str.remove( str.length()-1, 1 ); 395 str = str.remove( str.length()-1, 1 );
396 396
397 str += "\" "; 397 str += "\" ";
398 398
399 str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" "; 399 str += "AlarmDateTime=\"" + TimeConversion::toISO8601( ev.alarmDateTime() ) + "\" ";
400 400
401 return str; 401 return str;
402} 402}
403QString OTodoAccessXML::toString( const QArray<int>& ints ) const { 403QString OTodoAccessXML::toString( const QArray<int>& ints ) const {
404 return Qtopia::Record::idsToString( ints ); 404 return Qtopia::Record::idsToString( ints );
405} 405}
406 406
407/* internal class for sorting */ 407/* internal class for sorting */
408 408
409struct OTodoXMLContainer { 409struct OTodoXMLContainer {
410 OTodo todo; 410 OTodo todo;
411}; 411};
412 /* 412 /*
413 * Returns: 413 * Returns:
414 * 0 if item1 == item2 414 * 0 if item1 == item2
415 * 415 *
416 * non-zero if item1 != item2 416 * non-zero if item1 != item2
417 * 417 *
418 * This function returns int rather than bool so that reimplementations 418 * This function returns int rather than bool so that reimplementations
419 * can return one of three values and use it to sort by: 419 * can return one of three values and use it to sort by:
420 * 420 *
421 * 0 if item1 == item2 421 * 0 if item1 == item2
422 * 422 *
423 * > 0 (positive integer) if item1 > item2 423 * > 0 (positive integer) if item1 > item2
424 * 424 *
425 * < 0 (negative integer) if item1 < item2 425 * < 0 (negative integer) if item1 < item2
426 * 426 *
427 */ 427 */
428class OTodoXMLVector : public QVector<OTodoXMLContainer> { 428class OTodoXMLVector : public QVector<OTodoXMLContainer> {
429public: 429public:
430 OTodoXMLVector(int size, bool asc, int sort) 430 OTodoXMLVector(int size, bool asc, int sort)
431 : QVector<OTodoXMLContainer>( size ) 431 : QVector<OTodoXMLContainer>( size )
432 { 432 {
433 setAutoDelete( true ); 433 setAutoDelete( true );
434 m_asc = asc; 434 m_asc = asc;
435 m_sort = sort; 435 m_sort = sort;
436 } 436 }
437 /* return the summary/description */ 437 /* return the summary/description */
438 QString string( const OTodo& todo) { 438 QString string( const OTodo& todo) {
439 return todo.summary().isEmpty() ? 439 return todo.summary().isEmpty() ?
440 todo.description().left(20 ) : 440 todo.description().left(20 ) :
441 todo.summary(); 441 todo.summary();
442 } 442 }
443 /** 443 /**
444 * we take the sortorder( switch on it ) 444 * we take the sortorder( switch on it )
445 * 445 *
446 */ 446 */
447 int compareItems( Item d1, Item d2 ) { 447 int compareItems( Item d1, Item d2 ) {
448 int ret =0; 448 int ret =0;
449 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1; 449 OTodoXMLContainer* con1 = (OTodoXMLContainer*)d1;
450 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2; 450 OTodoXMLContainer* con2 = (OTodoXMLContainer*)d2;
451 451
452 /* same item */ 452 /* same item */
453 if ( con1->todo.uid() == con2->todo.uid() ) 453 if ( con1->todo.uid() == con2->todo.uid() )
454 return 0; 454 return 0;
455 455
456 switch ( m_sort ) { 456 switch ( m_sort ) {
457 /* completed */ 457 /* completed */
458 case 0: { 458 case 0: {
459 ret = 0; 459 ret = 0;
460 if ( con1->todo.isCompleted() ) ret++; 460 if ( con1->todo.isCompleted() ) ret++;
461 if ( con2->todo.isCompleted() ) ret--; 461 if ( con2->todo.isCompleted() ) ret--;
462 break; 462 break;
463 } 463 }
464 /* priority */ 464 /* priority */
465 case 1: { 465 case 1: {
466 ret = con1->todo.priority() - con2->todo.priority(); 466 ret = con1->todo.priority() - con2->todo.priority();
467 qWarning(" priority %d %d %d", ret, 467 qWarning(" priority %d %d %d", ret,
468 con1->todo.priority(), 468 con1->todo.priority(),
469 con2->todo.priority() 469 con2->todo.priority()
470 ); 470 );
471 break; 471 break;
472 } 472 }
473 /* description */ 473 /* description */
474 case 2: { 474 case 2: {
475 QString str1 = string( con1->todo ); 475 QString str1 = string( con1->todo );
476 QString str2 = string( con2->todo ); 476 QString str2 = string( con2->todo );
477 ret = QString::compare( str1, str2 ); 477 ret = QString::compare( str1, str2 );
478 break; 478 break;
479 } 479 }
480 /* deadline */ 480 /* deadline */
481 case 3: { 481 case 3: {
482 /* either bot got a dueDate 482 /* either bot got a dueDate
483 * or one of them got one 483 * or one of them got one
484 */ 484 */
485 if ( con1->todo.hasDueDate() && 485 if ( con1->todo.hasDueDate() &&
486 con2->todo.hasDueDate() ) 486 con2->todo.hasDueDate() )
487 ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() ); 487 ret = con1->todo.dueDate().daysTo( con2->todo.dueDate() );
488 488
489 489
490 else if ( con1->todo.hasDueDate() ) 490 else if ( con1->todo.hasDueDate() )
491 ret = -1; 491 ret = -1;
492 else if ( con2->todo.hasDueDate() ) 492 else if ( con2->todo.hasDueDate() )
493 ret = 0; 493 ret = 0;
494 break; 494 break;
495 } 495 }
496 default: 496 default:
497 ret = 0; 497 ret = 0;
498 break; 498 break;
499 }; 499 };
500 500
501 /* twist it we're not ascending*/ 501 /* twist it we're not ascending*/
502 if (!m_asc) 502 if (!m_asc)
503 ret = ret * -1; 503 ret = ret * -1;
504 return ret; 504 return ret;
505 } 505 }
506 private: 506 private:
507 bool m_asc; 507 bool m_asc;
508 int m_sort; 508 int m_sort;
509 509
510}; 510};
511 511
512QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder, 512QArray<int> OTodoAccessXML::sorted( bool asc, int sortOrder,
513 int sortFilter, int cat ) { 513 int sortFilter, int cat ) {
514 qWarning("sorted! %d cat", cat); 514 qWarning("sorted! %d cat", cat);
515 OTodoXMLVector vector(m_events.count(), asc,sortOrder ); 515 OTodoXMLVector vector(m_events.count(), asc,sortOrder );
516 QMap<int, OTodo>::Iterator it; 516 QMap<int, OTodo>::Iterator it;
517 int item = 0; 517 int item = 0;
518 518
519 bool bCat = sortFilter & 1 ? true : false; 519 bool bCat = sortFilter & 1 ? true : false;
520 bool bOnly = sortFilter & 2 ? true : false; 520 bool bOnly = sortFilter & 2 ? true : false;
521 bool comp = sortFilter & 4 ? true : false;
521 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 522 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
522 523
523 /* show category */ 524 /* show category */
524 if ( bCat && cat != 0) 525 if ( bCat && cat != 0)
525 if (!(*it).categories().contains( cat ) ) 526 if (!(*it).categories().contains( cat ) ) {
527 qWarning("category mis match");
526 continue; 528 continue;
527 /* isOverdue but we should not show overdue */ 529 }
528 if ( (*it).isOverdue() && !bOnly ) 530 /* isOverdue but we should not show overdue - why?*/
531/* if ( (*it).isOverdue() && !bOnly ) {
532 qWarning("item is overdue but !bOnly");
533 continue;
534 }
535*/
536 if ( !(*it).isOverdue() && bOnly ) {
537 qWarning("item is not overdue but bOnly checked");
529 continue; 538 continue;
530 if ( !(*it).isOverdue() && bOnly ) 539 }
540
541 if ((*it).isCompleted() && comp ) {
542 qWarning("completed continue!");
531 continue; 543 continue;
544 }
532 545
533 546
534 OTodoXMLContainer* con = new OTodoXMLContainer(); 547 OTodoXMLContainer* con = new OTodoXMLContainer();
535 con->todo = (*it); 548 con->todo = (*it);
536 vector.insert(item, con ); 549 vector.insert(item, con );
537 item++; 550 item++;
538 } 551 }
552 qWarning("XXX %d Items added", item);
539 vector.resize( item ); 553 vector.resize( item );
540 /* sort it now */ 554 /* sort it now */
541 vector.sort(); 555 vector.sort();
542 /* now get the uids */ 556 /* now get the uids */
543 QArray<int> array( vector.count() ); 557 QArray<int> array( vector.count() );
544 for (uint i= 0; i < vector.count(); i++ ) { 558 for (uint i= 0; i < vector.count(); i++ ) {
545 array[i] = ( vector.at(i) )->todo.uid(); 559 array[i] = ( vector.at(i) )->todo.uid();
546 } 560 }
547 qWarning("array count = %d %d", array.count(), vector.count() ); 561 qWarning("array count = %d %d", array.count(), vector.count() );
548 return array; 562 return array;
549}; 563};