summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/otodoaccessxml.cpp1
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp1
2 files changed, 2 insertions, 0 deletions
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index 21f93a0..c3416cb 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -1,358 +1,359 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <sys/mman.h> 4#include <sys/mman.h>
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/types.h> 6#include <sys/types.h>
7 7
8#include <unistd.h> 8#include <unistd.h>
9 9
10 10
11#include <qfile.h> 11#include <qfile.h>
12#include <qvector.h> 12#include <qvector.h>
13 13
14#include <qpe/global.h> 14#include <qpe/global.h>
15#include <qpe/stringutil.h> 15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h> 16#include <qpe/timeconversion.h>
17 17
18#include <opie/xmltree.h> 18#include <opie/xmltree.h>
19 19
20#include "otodoaccessxml.h" 20#include "otodoaccessxml.h"
21 21
22OTodoAccessXML::OTodoAccessXML( const QString& appName, 22OTodoAccessXML::OTodoAccessXML( const QString& appName,
23 const QString& fileName ) 23 const QString& fileName )
24 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 24 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
25{ 25{
26 if (!fileName.isEmpty() ) 26 if (!fileName.isEmpty() )
27 m_file = fileName; 27 m_file = fileName;
28 else 28 else
29 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 29 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
30} 30}
31OTodoAccessXML::~OTodoAccessXML() { 31OTodoAccessXML::~OTodoAccessXML() {
32 32
33} 33}
34bool OTodoAccessXML::load() { 34bool OTodoAccessXML::load() {
35 m_opened = true; 35 m_opened = true;
36 m_changed = false; 36 m_changed = false;
37 /* initialize dict */ 37 /* initialize dict */
38 /* 38 /*
39 * UPDATE dict if you change anything!!! 39 * UPDATE dict if you change anything!!!
40 */ 40 */
41 QAsciiDict<int> dict(21); 41 QAsciiDict<int> dict(21);
42 dict.setAutoDelete( TRUE ); 42 dict.setAutoDelete( TRUE );
43 dict.insert("Categories" , new int(OTodo::Category) ); 43 dict.insert("Categories" , new int(OTodo::Category) );
44 dict.insert("Uid" , new int(OTodo::Uid) ); 44 dict.insert("Uid" , new int(OTodo::Uid) );
45 dict.insert("HasDate" , new int(OTodo::HasDate) ); 45 dict.insert("HasDate" , new int(OTodo::HasDate) );
46 dict.insert("Completed" , new int(OTodo::Completed) ); 46 dict.insert("Completed" , new int(OTodo::Completed) );
47 dict.insert("Description" , new int(OTodo::Description) ); 47 dict.insert("Description" , new int(OTodo::Description) );
48 dict.insert("Summary" , new int(OTodo::Summary) ); 48 dict.insert("Summary" , new int(OTodo::Summary) );
49 dict.insert("Priority" , new int(OTodo::Priority) ); 49 dict.insert("Priority" , new int(OTodo::Priority) );
50 dict.insert("DateDay" , new int(OTodo::DateDay) ); 50 dict.insert("DateDay" , new int(OTodo::DateDay) );
51 dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 51 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
52 dict.insert("DateYear" , new int(OTodo::DateYear) ); 52 dict.insert("DateYear" , new int(OTodo::DateYear) );
53 dict.insert("Progress" , new int(OTodo::Progress) ); 53 dict.insert("Progress" , new int(OTodo::Progress) );
54 dict.insert("Completed", new int(OTodo::Completed) ); 54 dict.insert("Completed", new int(OTodo::Completed) );
55 dict.insert("CrossReference", new int(OTodo::CrossReference) ); 55 dict.insert("CrossReference", new int(OTodo::CrossReference) );
56 dict.insert("State", new int(OTodo::State) ); 56 dict.insert("State", new int(OTodo::State) );
57 dict.insert("Recurrence", new int(OTodo::Recurrence) ); 57 dict.insert("Recurrence", new int(OTodo::Recurrence) );
58 dict.insert("Alarms", new int(OTodo::Alarms) ); 58 dict.insert("Alarms", new int(OTodo::Alarms) );
59 dict.insert("Reminders", new int(OTodo::Reminders) ); 59 dict.insert("Reminders", new int(OTodo::Reminders) );
60 dict.insert("Notifiers", new int(OTodo::Notifiers) ); 60 dict.insert("Notifiers", new int(OTodo::Notifiers) );
61 dict.insert("Maintainer", new int(OTodo::Maintainer) ); 61 dict.insert("Maintainer", new int(OTodo::Maintainer) );
62 62
63 // here the custom XML parser from TT it's GPL 63 // here the custom XML parser from TT it's GPL
64 // but we want to push OpiePIM... to TT..... 64 // but we want to push OpiePIM... to TT.....
65 // mmap part from zecke :) 65 // mmap part from zecke :)
66 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); 66 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
67 struct stat attribut; 67 struct stat attribut;
68 if ( fd < 0 ) return false; 68 if ( fd < 0 ) return false;
69 69
70 if ( fstat(fd, &attribut ) == -1 ) { 70 if ( fstat(fd, &attribut ) == -1 ) {
71 ::close( fd ); 71 ::close( fd );
72 return false; 72 return false;
73 } 73 }
74 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 74 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
75 if ( map_addr == ( (caddr_t)-1) ) { 75 if ( map_addr == ( (caddr_t)-1) ) {
76 ::close(fd ); 76 ::close(fd );
77 return false; 77 return false;
78 } 78 }
79 /* advise the kernel who we want to read it */ 79 /* advise the kernel who we want to read it */
80 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); 80 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
81 /* we do not the file any more */ 81 /* we do not the file any more */
82 ::close( fd ); 82 ::close( fd );
83 83
84 char* dt = (char*)map_addr; 84 char* dt = (char*)map_addr;
85 int len = attribut.st_size; 85 int len = attribut.st_size;
86 int i = 0; 86 int i = 0;
87 char *point; 87 char *point;
88 const char* collectionString = "<Task "; 88 const char* collectionString = "<Task ";
89 int strLen = strlen(collectionString); 89 int strLen = strlen(collectionString);
90 while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { 90 while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) {
91 i = point -dt; 91 i = point -dt;
92 i+= strLen; 92 i+= strLen;
93 qWarning("Found a start at %d %d", i, (point-dt) ); 93 qWarning("Found a start at %d %d", i, (point-dt) );
94 94
95 OTodo ev; 95 OTodo ev;
96 m_year = m_month = m_day = 0; 96 m_year = m_month = m_day = 0;
97 97
98 while ( TRUE ) { 98 while ( TRUE ) {
99 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 99 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
100 ++i; 100 ++i;
101 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 101 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
102 break; 102 break;
103 103
104 // we have another attribute, read it. 104 // we have another attribute, read it.
105 int j = i; 105 int j = i;
106 while ( j < len && dt[j] != '=' ) 106 while ( j < len && dt[j] != '=' )
107 ++j; 107 ++j;
108 QCString attr( dt+i, j-i+1); 108 QCString attr( dt+i, j-i+1);
109 109
110 i = ++j; // skip = 110 i = ++j; // skip =
111 111
112 // find the start of quotes 112 // find the start of quotes
113 while ( i < len && dt[i] != '"' ) 113 while ( i < len && dt[i] != '"' )
114 ++i; 114 ++i;
115 j = ++i; 115 j = ++i;
116 116
117 bool haveUtf = FALSE; 117 bool haveUtf = FALSE;
118 bool haveEnt = FALSE; 118 bool haveEnt = FALSE;
119 while ( j < len && dt[j] != '"' ) { 119 while ( j < len && dt[j] != '"' ) {
120 if ( ((unsigned char)dt[j]) > 0x7f ) 120 if ( ((unsigned char)dt[j]) > 0x7f )
121 haveUtf = TRUE; 121 haveUtf = TRUE;
122 if ( dt[j] == '&' ) 122 if ( dt[j] == '&' )
123 haveEnt = TRUE; 123 haveEnt = TRUE;
124 ++j; 124 ++j;
125 } 125 }
126 if ( i == j ) { 126 if ( i == j ) {
127 // empty value 127 // empty value
128 i = j + 1; 128 i = j + 1;
129 continue; 129 continue;
130 } 130 }
131 131
132 QCString value( dt+i, j-i+1 ); 132 QCString value( dt+i, j-i+1 );
133 i = j + 1; 133 i = j + 1;
134 134
135 QString str = (haveUtf ? QString::fromUtf8( value ) 135 QString str = (haveUtf ? QString::fromUtf8( value )
136 : QString::fromLatin1( value ) ); 136 : QString::fromLatin1( value ) );
137 if ( haveEnt ) 137 if ( haveEnt )
138 str = Qtopia::plainString( str ); 138 str = Qtopia::plainString( str );
139 139
140 /* 140 /*
141 * add key + value 141 * add key + value
142 */ 142 */
143 todo( &dict, ev, attr, str ); 143 todo( &dict, ev, attr, str );
144 144
145 } 145 }
146 /* 146 /*
147 * now add it 147 * now add it
148 */ 148 */
149 qWarning("End at %d", i ); 149 qWarning("End at %d", i );
150 if (m_events.contains( ev.uid() ) || ev.uid() == 0) { 150 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
151 ev.setUid( 1 ); 151 ev.setUid( 1 );
152 m_changed = true; 152 m_changed = true;
153 } 153 }
154 if ( ev.hasDueDate() ) { 154 if ( ev.hasDueDate() ) {
155 ev.setDueDate( QDate(m_year, m_month, m_day) ); 155 ev.setDueDate( QDate(m_year, m_month, m_day) );
156 } 156 }
157 m_events.insert(ev.uid(), ev ); 157 m_events.insert(ev.uid(), ev );
158 m_year = m_month = m_day = -1; 158 m_year = m_month = m_day = -1;
159 } 159 }
160 160
161 munmap(map_addr, attribut.st_size ); 161 munmap(map_addr, attribut.st_size );
162 162
163 qWarning("counts %d records loaded!", m_events.count() ); 163 qWarning("counts %d records loaded!", m_events.count() );
164 return true; 164 return true;
165} 165}
166bool OTodoAccessXML::reload() { 166bool OTodoAccessXML::reload() {
167 m_events.clear();
167 return load(); 168 return load();
168} 169}
169bool OTodoAccessXML::save() { 170bool OTodoAccessXML::save() {
170// qWarning("saving"); 171// qWarning("saving");
171 if (!m_opened || !m_changed ) { 172 if (!m_opened || !m_changed ) {
172// qWarning("not saving"); 173// qWarning("not saving");
173 return true; 174 return true;
174 } 175 }
175 QString strNewFile = m_file + ".new"; 176 QString strNewFile = m_file + ".new";
176 QFile f( strNewFile ); 177 QFile f( strNewFile );
177 if (!f.open( IO_WriteOnly|IO_Raw ) ) 178 if (!f.open( IO_WriteOnly|IO_Raw ) )
178 return false; 179 return false;
179 180
180 int written; 181 int written;
181 QString out; 182 QString out;
182 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 183 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
183 184
184 // for all todos 185 // for all todos
185 QMap<int, OTodo>::Iterator it; 186 QMap<int, OTodo>::Iterator it;
186 for (it = m_events.begin(); it != m_events.end(); ++it ) { 187 for (it = m_events.begin(); it != m_events.end(); ++it ) {
187 out+= "<Task " + toString( (*it) ) + " />\n"; 188 out+= "<Task " + toString( (*it) ) + " />\n";
188 QCString cstr = out.utf8(); 189 QCString cstr = out.utf8();
189 written = f.writeBlock( cstr.data(), cstr.length() ); 190 written = f.writeBlock( cstr.data(), cstr.length() );
190 191
191 /* less written then we wanted */ 192 /* less written then we wanted */
192 if ( written != (int)cstr.length() ) { 193 if ( written != (int)cstr.length() ) {
193 f.close(); 194 f.close();
194 QFile::remove( strNewFile ); 195 QFile::remove( strNewFile );
195 return false; 196 return false;
196 } 197 }
197 out = QString::null; 198 out = QString::null;
198 } 199 }
199 200
200 out += "</Tasks>"; 201 out += "</Tasks>";
201 QCString cstr = out.utf8(); 202 QCString cstr = out.utf8();
202 written = f.writeBlock( cstr.data(), cstr.length() ); 203 written = f.writeBlock( cstr.data(), cstr.length() );
203 204
204 if ( written != (int)cstr.length() ) { 205 if ( written != (int)cstr.length() ) {
205 f.close(); 206 f.close();
206 QFile::remove( strNewFile ); 207 QFile::remove( strNewFile );
207 return false; 208 return false;
208 } 209 }
209 /* flush before renaming */ 210 /* flush before renaming */
210 f.close(); 211 f.close();
211 212
212 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 213 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
213// qWarning("error renaming"); 214// qWarning("error renaming");
214 QFile::remove( strNewFile ); 215 QFile::remove( strNewFile );
215 } 216 }
216 217
217 m_changed = false; 218 m_changed = false;
218 return true; 219 return true;
219} 220}
220QArray<int> OTodoAccessXML::allRecords()const { 221QArray<int> OTodoAccessXML::allRecords()const {
221 QArray<int> ids( m_events.count() ); 222 QArray<int> ids( m_events.count() );
222 QMap<int, OTodo>::ConstIterator it; 223 QMap<int, OTodo>::ConstIterator it;
223 int i = 0; 224 int i = 0;
224 225
225 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 226 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
226 ids[i] = it.key(); 227 ids[i] = it.key();
227 i++; 228 i++;
228 } 229 }
229 return ids; 230 return ids;
230} 231}
231QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { 232QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
232 QArray<int> ids(0); 233 QArray<int> ids(0);
233 return ids; 234 return ids;
234} 235}
235OTodo OTodoAccessXML::find( int uid )const { 236OTodo OTodoAccessXML::find( int uid )const {
236 OTodo todo; 237 OTodo todo;
237 todo.setUid( 0 ); // isEmpty() 238 todo.setUid( 0 ); // isEmpty()
238 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 239 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
239 if ( it != m_events.end() ) 240 if ( it != m_events.end() )
240 todo = it.data(); 241 todo = it.data();
241 242
242 return todo; 243 return todo;
243} 244}
244void OTodoAccessXML::clear() { 245void OTodoAccessXML::clear() {
245 if (m_opened ) 246 if (m_opened )
246 m_changed = true; 247 m_changed = true;
247 248
248 m_events.clear(); 249 m_events.clear();
249} 250}
250bool OTodoAccessXML::add( const OTodo& todo ) { 251bool OTodoAccessXML::add( const OTodo& todo ) {
251// qWarning("add"); 252// qWarning("add");
252 m_changed = true; 253 m_changed = true;
253 m_events.insert( todo.uid(), todo ); 254 m_events.insert( todo.uid(), todo );
254 255
255 return true; 256 return true;
256} 257}
257bool OTodoAccessXML::remove( int uid ) { 258bool OTodoAccessXML::remove( int uid ) {
258 m_changed = true; 259 m_changed = true;
259 m_events.remove( uid ); 260 m_events.remove( uid );
260 261
261 return true; 262 return true;
262} 263}
263bool OTodoAccessXML::replace( const OTodo& todo) { 264bool OTodoAccessXML::replace( const OTodo& todo) {
264 m_changed = true; 265 m_changed = true;
265 m_events.replace( todo.uid(), todo ); 266 m_events.replace( todo.uid(), todo );
266 267
267 return true; 268 return true;
268} 269}
269QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 270QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
270 const QDate& end, 271 const QDate& end,
271 bool includeNoDates ) { 272 bool includeNoDates ) {
272 QArray<int> ids( m_events.count() ); 273 QArray<int> ids( m_events.count() );
273 QMap<int, OTodo>::Iterator it; 274 QMap<int, OTodo>::Iterator it;
274 275
275 int i = 0; 276 int i = 0;
276 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 277 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
277 if ( !it.data().hasDueDate() ) { 278 if ( !it.data().hasDueDate() ) {
278 if ( includeNoDates ) { 279 if ( includeNoDates ) {
279 ids[i] = it.key(); 280 ids[i] = it.key();
280 i++; 281 i++;
281 } 282 }
282 }else if ( it.data().dueDate() >= start && 283 }else if ( it.data().dueDate() >= start &&
283 it.data().dueDate() <= end ) { 284 it.data().dueDate() <= end ) {
284 ids[i] = it.key(); 285 ids[i] = it.key();
285 i++; 286 i++;
286 } 287 }
287 } 288 }
288 ids.resize( i ); 289 ids.resize( i );
289 return ids; 290 return ids;
290} 291}
291QArray<int> OTodoAccessXML::overDue() { 292QArray<int> OTodoAccessXML::overDue() {
292 QArray<int> ids( m_events.count() ); 293 QArray<int> ids( m_events.count() );
293 int i = 0; 294 int i = 0;
294 295
295 QMap<int, OTodo>::Iterator it; 296 QMap<int, OTodo>::Iterator it;
296 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 297 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
297 if ( it.data().isOverdue() ) { 298 if ( it.data().isOverdue() ) {
298 ids[i] = it.key(); 299 ids[i] = it.key();
299 i++; 300 i++;
300 } 301 }
301 } 302 }
302 ids.resize( i ); 303 ids.resize( i );
303 return ids; 304 return ids;
304} 305}
305 306
306 307
307/* private */ 308/* private */
308void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 309void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
309 const QCString& attr, const QString& val) { 310 const QCString& attr, const QString& val) {
310// qWarning("parse to do from XMLElement" ); 311// qWarning("parse to do from XMLElement" );
311 312
312 int *find=0; 313 int *find=0;
313 314
314 find = (*dict)[ attr.data() ]; 315 find = (*dict)[ attr.data() ];
315 if (!find ) { 316 if (!find ) {
316// qWarning("Unknown option" + it.key() ); 317// qWarning("Unknown option" + it.key() );
317 ev.setCustomField( attr, val ); 318 ev.setCustomField( attr, val );
318 return; 319 return;
319 } 320 }
320 321
321 switch( *find ) { 322 switch( *find ) {
322 case OTodo::Uid: 323 case OTodo::Uid:
323 ev.setUid( val.toInt() ); 324 ev.setUid( val.toInt() );
324 break; 325 break;
325 case OTodo::Category: 326 case OTodo::Category:
326 ev.setCategories( ev.idsFromString( val ) ); 327 ev.setCategories( ev.idsFromString( val ) );
327 break; 328 break;
328 case OTodo::HasDate: 329 case OTodo::HasDate:
329 ev.setHasDueDate( val.toInt() ); 330 ev.setHasDueDate( val.toInt() );
330 break; 331 break;
331 case OTodo::Completed: 332 case OTodo::Completed:
332 ev.setCompleted( val.toInt() ); 333 ev.setCompleted( val.toInt() );
333 break; 334 break;
334 case OTodo::Description: 335 case OTodo::Description:
335 ev.setDescription( val ); 336 ev.setDescription( val );
336 break; 337 break;
337 case OTodo::Summary: 338 case OTodo::Summary:
338 ev.setSummary( val ); 339 ev.setSummary( val );
339 break; 340 break;
340 case OTodo::Priority: 341 case OTodo::Priority:
341 ev.setPriority( val.toInt() ); 342 ev.setPriority( val.toInt() );
342 break; 343 break;
343 case OTodo::DateDay: 344 case OTodo::DateDay:
344 m_day = val.toInt(); 345 m_day = val.toInt();
345 break; 346 break;
346 case OTodo::DateMonth: 347 case OTodo::DateMonth:
347 m_month = val.toInt(); 348 m_month = val.toInt();
348 break; 349 break;
349 case OTodo::DateYear: 350 case OTodo::DateYear:
350 m_year = val.toInt(); 351 m_year = val.toInt();
351 break; 352 break;
352 case OTodo::Progress: 353 case OTodo::Progress:
353 ev.setProgress( val.toInt() ); 354 ev.setProgress( val.toInt() );
354 break; 355 break;
355 case OTodo::CrossReference: 356 case OTodo::CrossReference:
356 { 357 {
357 /* 358 /*
358 * A cross refernce looks like 359 * A cross refernce looks like
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp
index 21f93a0..c3416cb 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.cpp
+++ b/libopie2/opiepim/backend/otodoaccessxml.cpp
@@ -1,358 +1,359 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <sys/mman.h> 4#include <sys/mman.h>
5#include <sys/stat.h> 5#include <sys/stat.h>
6#include <sys/types.h> 6#include <sys/types.h>
7 7
8#include <unistd.h> 8#include <unistd.h>
9 9
10 10
11#include <qfile.h> 11#include <qfile.h>
12#include <qvector.h> 12#include <qvector.h>
13 13
14#include <qpe/global.h> 14#include <qpe/global.h>
15#include <qpe/stringutil.h> 15#include <qpe/stringutil.h>
16#include <qpe/timeconversion.h> 16#include <qpe/timeconversion.h>
17 17
18#include <opie/xmltree.h> 18#include <opie/xmltree.h>
19 19
20#include "otodoaccessxml.h" 20#include "otodoaccessxml.h"
21 21
22OTodoAccessXML::OTodoAccessXML( const QString& appName, 22OTodoAccessXML::OTodoAccessXML( const QString& appName,
23 const QString& fileName ) 23 const QString& fileName )
24 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false ) 24 : OTodoAccessBackend(), m_app( appName ), m_opened( false ), m_changed( false )
25{ 25{
26 if (!fileName.isEmpty() ) 26 if (!fileName.isEmpty() )
27 m_file = fileName; 27 m_file = fileName;
28 else 28 else
29 m_file = Global::applicationFileName( "todolist", "todolist.xml" ); 29 m_file = Global::applicationFileName( "todolist", "todolist.xml" );
30} 30}
31OTodoAccessXML::~OTodoAccessXML() { 31OTodoAccessXML::~OTodoAccessXML() {
32 32
33} 33}
34bool OTodoAccessXML::load() { 34bool OTodoAccessXML::load() {
35 m_opened = true; 35 m_opened = true;
36 m_changed = false; 36 m_changed = false;
37 /* initialize dict */ 37 /* initialize dict */
38 /* 38 /*
39 * UPDATE dict if you change anything!!! 39 * UPDATE dict if you change anything!!!
40 */ 40 */
41 QAsciiDict<int> dict(21); 41 QAsciiDict<int> dict(21);
42 dict.setAutoDelete( TRUE ); 42 dict.setAutoDelete( TRUE );
43 dict.insert("Categories" , new int(OTodo::Category) ); 43 dict.insert("Categories" , new int(OTodo::Category) );
44 dict.insert("Uid" , new int(OTodo::Uid) ); 44 dict.insert("Uid" , new int(OTodo::Uid) );
45 dict.insert("HasDate" , new int(OTodo::HasDate) ); 45 dict.insert("HasDate" , new int(OTodo::HasDate) );
46 dict.insert("Completed" , new int(OTodo::Completed) ); 46 dict.insert("Completed" , new int(OTodo::Completed) );
47 dict.insert("Description" , new int(OTodo::Description) ); 47 dict.insert("Description" , new int(OTodo::Description) );
48 dict.insert("Summary" , new int(OTodo::Summary) ); 48 dict.insert("Summary" , new int(OTodo::Summary) );
49 dict.insert("Priority" , new int(OTodo::Priority) ); 49 dict.insert("Priority" , new int(OTodo::Priority) );
50 dict.insert("DateDay" , new int(OTodo::DateDay) ); 50 dict.insert("DateDay" , new int(OTodo::DateDay) );
51 dict.insert("DateMonth" , new int(OTodo::DateMonth) ); 51 dict.insert("DateMonth" , new int(OTodo::DateMonth) );
52 dict.insert("DateYear" , new int(OTodo::DateYear) ); 52 dict.insert("DateYear" , new int(OTodo::DateYear) );
53 dict.insert("Progress" , new int(OTodo::Progress) ); 53 dict.insert("Progress" , new int(OTodo::Progress) );
54 dict.insert("Completed", new int(OTodo::Completed) ); 54 dict.insert("Completed", new int(OTodo::Completed) );
55 dict.insert("CrossReference", new int(OTodo::CrossReference) ); 55 dict.insert("CrossReference", new int(OTodo::CrossReference) );
56 dict.insert("State", new int(OTodo::State) ); 56 dict.insert("State", new int(OTodo::State) );
57 dict.insert("Recurrence", new int(OTodo::Recurrence) ); 57 dict.insert("Recurrence", new int(OTodo::Recurrence) );
58 dict.insert("Alarms", new int(OTodo::Alarms) ); 58 dict.insert("Alarms", new int(OTodo::Alarms) );
59 dict.insert("Reminders", new int(OTodo::Reminders) ); 59 dict.insert("Reminders", new int(OTodo::Reminders) );
60 dict.insert("Notifiers", new int(OTodo::Notifiers) ); 60 dict.insert("Notifiers", new int(OTodo::Notifiers) );
61 dict.insert("Maintainer", new int(OTodo::Maintainer) ); 61 dict.insert("Maintainer", new int(OTodo::Maintainer) );
62 62
63 // here the custom XML parser from TT it's GPL 63 // here the custom XML parser from TT it's GPL
64 // but we want to push OpiePIM... to TT..... 64 // but we want to push OpiePIM... to TT.....
65 // mmap part from zecke :) 65 // mmap part from zecke :)
66 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); 66 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
67 struct stat attribut; 67 struct stat attribut;
68 if ( fd < 0 ) return false; 68 if ( fd < 0 ) return false;
69 69
70 if ( fstat(fd, &attribut ) == -1 ) { 70 if ( fstat(fd, &attribut ) == -1 ) {
71 ::close( fd ); 71 ::close( fd );
72 return false; 72 return false;
73 } 73 }
74 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 74 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
75 if ( map_addr == ( (caddr_t)-1) ) { 75 if ( map_addr == ( (caddr_t)-1) ) {
76 ::close(fd ); 76 ::close(fd );
77 return false; 77 return false;
78 } 78 }
79 /* advise the kernel who we want to read it */ 79 /* advise the kernel who we want to read it */
80 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); 80 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
81 /* we do not the file any more */ 81 /* we do not the file any more */
82 ::close( fd ); 82 ::close( fd );
83 83
84 char* dt = (char*)map_addr; 84 char* dt = (char*)map_addr;
85 int len = attribut.st_size; 85 int len = attribut.st_size;
86 int i = 0; 86 int i = 0;
87 char *point; 87 char *point;
88 const char* collectionString = "<Task "; 88 const char* collectionString = "<Task ";
89 int strLen = strlen(collectionString); 89 int strLen = strlen(collectionString);
90 while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) { 90 while ( dt+i != 0 && ( point = strstr( dt+i, collectionString ) ) != 0l ) {
91 i = point -dt; 91 i = point -dt;
92 i+= strLen; 92 i+= strLen;
93 qWarning("Found a start at %d %d", i, (point-dt) ); 93 qWarning("Found a start at %d %d", i, (point-dt) );
94 94
95 OTodo ev; 95 OTodo ev;
96 m_year = m_month = m_day = 0; 96 m_year = m_month = m_day = 0;
97 97
98 while ( TRUE ) { 98 while ( TRUE ) {
99 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 99 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
100 ++i; 100 ++i;
101 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 101 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
102 break; 102 break;
103 103
104 // we have another attribute, read it. 104 // we have another attribute, read it.
105 int j = i; 105 int j = i;
106 while ( j < len && dt[j] != '=' ) 106 while ( j < len && dt[j] != '=' )
107 ++j; 107 ++j;
108 QCString attr( dt+i, j-i+1); 108 QCString attr( dt+i, j-i+1);
109 109
110 i = ++j; // skip = 110 i = ++j; // skip =
111 111
112 // find the start of quotes 112 // find the start of quotes
113 while ( i < len && dt[i] != '"' ) 113 while ( i < len && dt[i] != '"' )
114 ++i; 114 ++i;
115 j = ++i; 115 j = ++i;
116 116
117 bool haveUtf = FALSE; 117 bool haveUtf = FALSE;
118 bool haveEnt = FALSE; 118 bool haveEnt = FALSE;
119 while ( j < len && dt[j] != '"' ) { 119 while ( j < len && dt[j] != '"' ) {
120 if ( ((unsigned char)dt[j]) > 0x7f ) 120 if ( ((unsigned char)dt[j]) > 0x7f )
121 haveUtf = TRUE; 121 haveUtf = TRUE;
122 if ( dt[j] == '&' ) 122 if ( dt[j] == '&' )
123 haveEnt = TRUE; 123 haveEnt = TRUE;
124 ++j; 124 ++j;
125 } 125 }
126 if ( i == j ) { 126 if ( i == j ) {
127 // empty value 127 // empty value
128 i = j + 1; 128 i = j + 1;
129 continue; 129 continue;
130 } 130 }
131 131
132 QCString value( dt+i, j-i+1 ); 132 QCString value( dt+i, j-i+1 );
133 i = j + 1; 133 i = j + 1;
134 134
135 QString str = (haveUtf ? QString::fromUtf8( value ) 135 QString str = (haveUtf ? QString::fromUtf8( value )
136 : QString::fromLatin1( value ) ); 136 : QString::fromLatin1( value ) );
137 if ( haveEnt ) 137 if ( haveEnt )
138 str = Qtopia::plainString( str ); 138 str = Qtopia::plainString( str );
139 139
140 /* 140 /*
141 * add key + value 141 * add key + value
142 */ 142 */
143 todo( &dict, ev, attr, str ); 143 todo( &dict, ev, attr, str );
144 144
145 } 145 }
146 /* 146 /*
147 * now add it 147 * now add it
148 */ 148 */
149 qWarning("End at %d", i ); 149 qWarning("End at %d", i );
150 if (m_events.contains( ev.uid() ) || ev.uid() == 0) { 150 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
151 ev.setUid( 1 ); 151 ev.setUid( 1 );
152 m_changed = true; 152 m_changed = true;
153 } 153 }
154 if ( ev.hasDueDate() ) { 154 if ( ev.hasDueDate() ) {
155 ev.setDueDate( QDate(m_year, m_month, m_day) ); 155 ev.setDueDate( QDate(m_year, m_month, m_day) );
156 } 156 }
157 m_events.insert(ev.uid(), ev ); 157 m_events.insert(ev.uid(), ev );
158 m_year = m_month = m_day = -1; 158 m_year = m_month = m_day = -1;
159 } 159 }
160 160
161 munmap(map_addr, attribut.st_size ); 161 munmap(map_addr, attribut.st_size );
162 162
163 qWarning("counts %d records loaded!", m_events.count() ); 163 qWarning("counts %d records loaded!", m_events.count() );
164 return true; 164 return true;
165} 165}
166bool OTodoAccessXML::reload() { 166bool OTodoAccessXML::reload() {
167 m_events.clear();
167 return load(); 168 return load();
168} 169}
169bool OTodoAccessXML::save() { 170bool OTodoAccessXML::save() {
170// qWarning("saving"); 171// qWarning("saving");
171 if (!m_opened || !m_changed ) { 172 if (!m_opened || !m_changed ) {
172// qWarning("not saving"); 173// qWarning("not saving");
173 return true; 174 return true;
174 } 175 }
175 QString strNewFile = m_file + ".new"; 176 QString strNewFile = m_file + ".new";
176 QFile f( strNewFile ); 177 QFile f( strNewFile );
177 if (!f.open( IO_WriteOnly|IO_Raw ) ) 178 if (!f.open( IO_WriteOnly|IO_Raw ) )
178 return false; 179 return false;
179 180
180 int written; 181 int written;
181 QString out; 182 QString out;
182 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 183 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
183 184
184 // for all todos 185 // for all todos
185 QMap<int, OTodo>::Iterator it; 186 QMap<int, OTodo>::Iterator it;
186 for (it = m_events.begin(); it != m_events.end(); ++it ) { 187 for (it = m_events.begin(); it != m_events.end(); ++it ) {
187 out+= "<Task " + toString( (*it) ) + " />\n"; 188 out+= "<Task " + toString( (*it) ) + " />\n";
188 QCString cstr = out.utf8(); 189 QCString cstr = out.utf8();
189 written = f.writeBlock( cstr.data(), cstr.length() ); 190 written = f.writeBlock( cstr.data(), cstr.length() );
190 191
191 /* less written then we wanted */ 192 /* less written then we wanted */
192 if ( written != (int)cstr.length() ) { 193 if ( written != (int)cstr.length() ) {
193 f.close(); 194 f.close();
194 QFile::remove( strNewFile ); 195 QFile::remove( strNewFile );
195 return false; 196 return false;
196 } 197 }
197 out = QString::null; 198 out = QString::null;
198 } 199 }
199 200
200 out += "</Tasks>"; 201 out += "</Tasks>";
201 QCString cstr = out.utf8(); 202 QCString cstr = out.utf8();
202 written = f.writeBlock( cstr.data(), cstr.length() ); 203 written = f.writeBlock( cstr.data(), cstr.length() );
203 204
204 if ( written != (int)cstr.length() ) { 205 if ( written != (int)cstr.length() ) {
205 f.close(); 206 f.close();
206 QFile::remove( strNewFile ); 207 QFile::remove( strNewFile );
207 return false; 208 return false;
208 } 209 }
209 /* flush before renaming */ 210 /* flush before renaming */
210 f.close(); 211 f.close();
211 212
212 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 213 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
213// qWarning("error renaming"); 214// qWarning("error renaming");
214 QFile::remove( strNewFile ); 215 QFile::remove( strNewFile );
215 } 216 }
216 217
217 m_changed = false; 218 m_changed = false;
218 return true; 219 return true;
219} 220}
220QArray<int> OTodoAccessXML::allRecords()const { 221QArray<int> OTodoAccessXML::allRecords()const {
221 QArray<int> ids( m_events.count() ); 222 QArray<int> ids( m_events.count() );
222 QMap<int, OTodo>::ConstIterator it; 223 QMap<int, OTodo>::ConstIterator it;
223 int i = 0; 224 int i = 0;
224 225
225 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 226 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
226 ids[i] = it.key(); 227 ids[i] = it.key();
227 i++; 228 i++;
228 } 229 }
229 return ids; 230 return ids;
230} 231}
231QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { 232QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) {
232 QArray<int> ids(0); 233 QArray<int> ids(0);
233 return ids; 234 return ids;
234} 235}
235OTodo OTodoAccessXML::find( int uid )const { 236OTodo OTodoAccessXML::find( int uid )const {
236 OTodo todo; 237 OTodo todo;
237 todo.setUid( 0 ); // isEmpty() 238 todo.setUid( 0 ); // isEmpty()
238 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 239 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
239 if ( it != m_events.end() ) 240 if ( it != m_events.end() )
240 todo = it.data(); 241 todo = it.data();
241 242
242 return todo; 243 return todo;
243} 244}
244void OTodoAccessXML::clear() { 245void OTodoAccessXML::clear() {
245 if (m_opened ) 246 if (m_opened )
246 m_changed = true; 247 m_changed = true;
247 248
248 m_events.clear(); 249 m_events.clear();
249} 250}
250bool OTodoAccessXML::add( const OTodo& todo ) { 251bool OTodoAccessXML::add( const OTodo& todo ) {
251// qWarning("add"); 252// qWarning("add");
252 m_changed = true; 253 m_changed = true;
253 m_events.insert( todo.uid(), todo ); 254 m_events.insert( todo.uid(), todo );
254 255
255 return true; 256 return true;
256} 257}
257bool OTodoAccessXML::remove( int uid ) { 258bool OTodoAccessXML::remove( int uid ) {
258 m_changed = true; 259 m_changed = true;
259 m_events.remove( uid ); 260 m_events.remove( uid );
260 261
261 return true; 262 return true;
262} 263}
263bool OTodoAccessXML::replace( const OTodo& todo) { 264bool OTodoAccessXML::replace( const OTodo& todo) {
264 m_changed = true; 265 m_changed = true;
265 m_events.replace( todo.uid(), todo ); 266 m_events.replace( todo.uid(), todo );
266 267
267 return true; 268 return true;
268} 269}
269QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 270QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
270 const QDate& end, 271 const QDate& end,
271 bool includeNoDates ) { 272 bool includeNoDates ) {
272 QArray<int> ids( m_events.count() ); 273 QArray<int> ids( m_events.count() );
273 QMap<int, OTodo>::Iterator it; 274 QMap<int, OTodo>::Iterator it;
274 275
275 int i = 0; 276 int i = 0;
276 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 277 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
277 if ( !it.data().hasDueDate() ) { 278 if ( !it.data().hasDueDate() ) {
278 if ( includeNoDates ) { 279 if ( includeNoDates ) {
279 ids[i] = it.key(); 280 ids[i] = it.key();
280 i++; 281 i++;
281 } 282 }
282 }else if ( it.data().dueDate() >= start && 283 }else if ( it.data().dueDate() >= start &&
283 it.data().dueDate() <= end ) { 284 it.data().dueDate() <= end ) {
284 ids[i] = it.key(); 285 ids[i] = it.key();
285 i++; 286 i++;
286 } 287 }
287 } 288 }
288 ids.resize( i ); 289 ids.resize( i );
289 return ids; 290 return ids;
290} 291}
291QArray<int> OTodoAccessXML::overDue() { 292QArray<int> OTodoAccessXML::overDue() {
292 QArray<int> ids( m_events.count() ); 293 QArray<int> ids( m_events.count() );
293 int i = 0; 294 int i = 0;
294 295
295 QMap<int, OTodo>::Iterator it; 296 QMap<int, OTodo>::Iterator it;
296 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 297 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
297 if ( it.data().isOverdue() ) { 298 if ( it.data().isOverdue() ) {
298 ids[i] = it.key(); 299 ids[i] = it.key();
299 i++; 300 i++;
300 } 301 }
301 } 302 }
302 ids.resize( i ); 303 ids.resize( i );
303 return ids; 304 return ids;
304} 305}
305 306
306 307
307/* private */ 308/* private */
308void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev, 309void OTodoAccessXML::todo( QAsciiDict<int>* dict, OTodo& ev,
309 const QCString& attr, const QString& val) { 310 const QCString& attr, const QString& val) {
310// qWarning("parse to do from XMLElement" ); 311// qWarning("parse to do from XMLElement" );
311 312
312 int *find=0; 313 int *find=0;
313 314
314 find = (*dict)[ attr.data() ]; 315 find = (*dict)[ attr.data() ];
315 if (!find ) { 316 if (!find ) {
316// qWarning("Unknown option" + it.key() ); 317// qWarning("Unknown option" + it.key() );
317 ev.setCustomField( attr, val ); 318 ev.setCustomField( attr, val );
318 return; 319 return;
319 } 320 }
320 321
321 switch( *find ) { 322 switch( *find ) {
322 case OTodo::Uid: 323 case OTodo::Uid:
323 ev.setUid( val.toInt() ); 324 ev.setUid( val.toInt() );
324 break; 325 break;
325 case OTodo::Category: 326 case OTodo::Category:
326 ev.setCategories( ev.idsFromString( val ) ); 327 ev.setCategories( ev.idsFromString( val ) );
327 break; 328 break;
328 case OTodo::HasDate: 329 case OTodo::HasDate:
329 ev.setHasDueDate( val.toInt() ); 330 ev.setHasDueDate( val.toInt() );
330 break; 331 break;
331 case OTodo::Completed: 332 case OTodo::Completed:
332 ev.setCompleted( val.toInt() ); 333 ev.setCompleted( val.toInt() );
333 break; 334 break;
334 case OTodo::Description: 335 case OTodo::Description:
335 ev.setDescription( val ); 336 ev.setDescription( val );
336 break; 337 break;
337 case OTodo::Summary: 338 case OTodo::Summary:
338 ev.setSummary( val ); 339 ev.setSummary( val );
339 break; 340 break;
340 case OTodo::Priority: 341 case OTodo::Priority:
341 ev.setPriority( val.toInt() ); 342 ev.setPriority( val.toInt() );
342 break; 343 break;
343 case OTodo::DateDay: 344 case OTodo::DateDay:
344 m_day = val.toInt(); 345 m_day = val.toInt();
345 break; 346 break;
346 case OTodo::DateMonth: 347 case OTodo::DateMonth:
347 m_month = val.toInt(); 348 m_month = val.toInt();
348 break; 349 break;
349 case OTodo::DateYear: 350 case OTodo::DateYear:
350 m_year = val.toInt(); 351 m_year = val.toInt();
351 break; 352 break;
352 case OTodo::Progress: 353 case OTodo::Progress:
353 ev.setProgress( val.toInt() ); 354 ev.setProgress( val.toInt() );
354 break; 355 break;
355 case OTodo::CrossReference: 356 case OTodo::CrossReference:
356 { 357 {
357 /* 358 /*
358 * A cross refernce looks like 359 * A cross refernce looks like