summaryrefslogtreecommitdiff
path: root/libopie/pim/ocontactaccessbackend_xml.cpp
Unidiff
Diffstat (limited to 'libopie/pim/ocontactaccessbackend_xml.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.cpp171
1 files changed, 88 insertions, 83 deletions
diff --git a/libopie/pim/ocontactaccessbackend_xml.cpp b/libopie/pim/ocontactaccessbackend_xml.cpp
index c5a7820..661cd51 100644
--- a/libopie/pim/ocontactaccessbackend_xml.cpp
+++ b/libopie/pim/ocontactaccessbackend_xml.cpp
@@ -8,24 +8,29 @@
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * ToDo: XML-Backend: Automatic reload if something was changed... 12 * ToDo: XML-Backend: Automatic reload if something was changed...
13 * 13 *
14 * 14 *
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.5 2003/04/13 18:07:10 zecke
21 * More API doc
22 * QString -> const QString&
23 * QString = 0l -> QString::null
24 *
20 * Revision 1.4 2003/03/21 14:32:54 mickeyl 25 * Revision 1.4 2003/03/21 14:32:54 mickeyl
21 * g++ compliance fix: default arguments belong into the declaration, but not the definition 26 * g++ compliance fix: default arguments belong into the declaration, but not the definition
22 * 27 *
23 * Revision 1.3 2003/03/21 12:26:28 eilers 28 * Revision 1.3 2003/03/21 12:26:28 eilers
24 * Fixing small bug: If we search a birthday from today to today, it returned 29 * Fixing small bug: If we search a birthday from today to today, it returned
25 * every contact .. 30 * every contact ..
26 * 31 *
27 * Revision 1.2 2003/03/21 10:33:09 eilers 32 * Revision 1.2 2003/03/21 10:33:09 eilers
28 * Merged speed optimized xml backend for contacts to main. 33 * Merged speed optimized xml backend for contacts to main.
29 * Added QDateTime to querybyexample. For instance, it is now possible to get 34 * Added QDateTime to querybyexample. For instance, it is now possible to get
30 * all Birthdays/Anniversaries between two dates. This should be used 35 * all Birthdays/Anniversaries between two dates. This should be used
31 * to show all birthdays in the datebook.. 36 * to show all birthdays in the datebook..
@@ -84,73 +89,73 @@
84 * 89 *
85 */ 90 */
86 91
87#include "ocontactaccessbackend_xml.h" 92#include "ocontactaccessbackend_xml.h"
88 93
89#include <qasciidict.h> 94#include <qasciidict.h>
90#include <qdatetime.h> 95#include <qdatetime.h>
91#include <qfile.h> 96#include <qfile.h>
92#include <qfileinfo.h> 97#include <qfileinfo.h>
93#include <qregexp.h> 98#include <qregexp.h>
94#include <qarray.h> 99#include <qarray.h>
95#include <qmap.h> 100#include <qmap.h>
96#include <qdatetime.h> 101#include <qdatetime.h>
97 102
98#include <qpe/global.h> 103#include <qpe/global.h>
99 104
100#include <opie/xmltree.h> 105#include <opie/xmltree.h>
101#include "ocontactaccessbackend.h" 106#include "ocontactaccessbackend.h"
102#include "ocontactaccess.h" 107#include "ocontactaccess.h"
103 108
104#include <stdlib.h> 109#include <stdlib.h>
105#include <errno.h> 110#include <errno.h>
106 111
107using namespace Opie; 112using namespace Opie;
108 113
109 114
110OContactAccessBackend_XML::OContactAccessBackend_XML ( QString appname, QString filename ): 115OContactAccessBackend_XML::OContactAccessBackend_XML ( const QString& appname, const QString& filename ):
111 m_changed( false ) 116 m_changed( false )
112{ 117{
113 // Just m_contactlist should call delete if an entry 118 // Just m_contactlist should call delete if an entry
114 // is removed. 119 // is removed.
115 m_contactList.setAutoDelete( true ); 120 m_contactList.setAutoDelete( true );
116 m_uidToContact.setAutoDelete( false ); 121 m_uidToContact.setAutoDelete( false );
117 122
118 m_appName = appname; 123 m_appName = appname;
119 124
120 /* Set journalfile name ... */ 125 /* Set journalfile name ... */
121 m_journalName = getenv("HOME"); 126 m_journalName = getenv("HOME");
122 m_journalName +="/.abjournal" + appname; 127 m_journalName +="/.abjournal" + appname;
123 128
124 /* Expecting to access the default filename if nothing else is set */ 129 /* Expecting to access the default filename if nothing else is set */
125 if ( filename.isEmpty() ){ 130 if ( filename.isEmpty() ){
126 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 131 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
127 } else 132 } else
128 m_fileName = filename; 133 m_fileName = filename;
129 134
130 /* Load Database now */ 135 /* Load Database now */
131 load (); 136 load ();
132} 137}
133 138
134bool OContactAccessBackend_XML::save() 139bool OContactAccessBackend_XML::save()
135{ 140{
136 141
137 if ( !m_changed ) 142 if ( !m_changed )
138 return true; 143 return true;
139 144
140 QString strNewFile = m_fileName + ".new"; 145 QString strNewFile = m_fileName + ".new";
141 QFile f( strNewFile ); 146 QFile f( strNewFile );
142 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 147 if ( !f.open( IO_WriteOnly|IO_Raw ) )
143 return false; 148 return false;
144 149
145 int total_written; 150 int total_written;
146 int idx_offset = 0; 151 int idx_offset = 0;
147 QString out; 152 QString out;
148 153
149 // Write Header 154 // Write Header
150 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 155 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
151 " <Groups>\n" 156 " <Groups>\n"
152 " </Groups>\n" 157 " </Groups>\n"
153 " <Contacts>\n"; 158 " <Contacts>\n";
154 QCString cstr = out.utf8(); 159 QCString cstr = out.utf8();
155 f.writeBlock( cstr.data(), cstr.length() ); 160 f.writeBlock( cstr.data(), cstr.length() );
156 idx_offset += cstr.length(); 161 idx_offset += cstr.length();
@@ -165,212 +170,212 @@ bool OContactAccessBackend_XML::save()
165 out += "/>\n"; 170 out += "/>\n";
166 cstr = out.utf8(); 171 cstr = out.utf8();
167 total_written = f.writeBlock( cstr.data(), cstr.length() ); 172 total_written = f.writeBlock( cstr.data(), cstr.length() );
168 idx_offset += cstr.length(); 173 idx_offset += cstr.length();
169 if ( total_written != int(cstr.length()) ) { 174 if ( total_written != int(cstr.length()) ) {
170 f.close(); 175 f.close();
171 QFile::remove( strNewFile ); 176 QFile::remove( strNewFile );
172 return false; 177 return false;
173 } 178 }
174 out = ""; 179 out = "";
175 } 180 }
176 out += " </Contacts>\n</AddressBook>\n"; 181 out += " </Contacts>\n</AddressBook>\n";
177 182
178 // Write Footer 183 // Write Footer
179 cstr = out.utf8(); 184 cstr = out.utf8();
180 total_written = f.writeBlock( cstr.data(), cstr.length() ); 185 total_written = f.writeBlock( cstr.data(), cstr.length() );
181 if ( total_written != int( cstr.length() ) ) { 186 if ( total_written != int( cstr.length() ) ) {
182 f.close(); 187 f.close();
183 QFile::remove( strNewFile ); 188 QFile::remove( strNewFile );
184 return false; 189 return false;
185 } 190 }
186 f.close(); 191 f.close();
187 192
188 // move the file over, I'm just going to use the system call 193 // move the file over, I'm just going to use the system call
189 // because, I don't feel like using QDir. 194 // because, I don't feel like using QDir.
190 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 195 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
191 qWarning( "problem renaming file %s to %s, errno: %d", 196 qWarning( "problem renaming file %s to %s, errno: %d",
192 strNewFile.latin1(), m_journalName.latin1(), errno ); 197 strNewFile.latin1(), m_journalName.latin1(), errno );
193 // remove the tmp file... 198 // remove the tmp file...
194 QFile::remove( strNewFile ); 199 QFile::remove( strNewFile );
195 } 200 }
196 201
197 /* The journalfile should be removed now... */ 202 /* The journalfile should be removed now... */
198 removeJournal(); 203 removeJournal();
199 204
200 m_changed = false; 205 m_changed = false;
201 return true; 206 return true;
202} 207}
203 208
204bool OContactAccessBackend_XML::load () 209bool OContactAccessBackend_XML::load ()
205{ 210{
206 m_contactList.clear(); 211 m_contactList.clear();
207 m_uidToContact.clear(); 212 m_uidToContact.clear();
208 213
209 /* Load XML-File and journal if it exists */ 214 /* Load XML-File and journal if it exists */
210 if ( !load ( m_fileName, false ) ) 215 if ( !load ( m_fileName, false ) )
211 return false; 216 return false;
212 /* The returncode of the journalfile is ignored due to the 217 /* The returncode of the journalfile is ignored due to the
213 * fact that it does not exist when this class is instantiated ! 218 * fact that it does not exist when this class is instantiated !
214 * But there may such a file exist, if the application crashed. 219 * But there may such a file exist, if the application crashed.
215 * Therefore we try to load it to get the changes before the # 220 * Therefore we try to load it to get the changes before the #
216 * crash happened... 221 * crash happened...
217 */ 222 */
218 load (m_journalName, true); 223 load (m_journalName, true);
219 224
220 return true; 225 return true;
221} 226}
222 227
223void OContactAccessBackend_XML::clear () 228void OContactAccessBackend_XML::clear ()
224{ 229{
225 m_contactList.clear(); 230 m_contactList.clear();
226 m_uidToContact.clear(); 231 m_uidToContact.clear();
227 232
228 m_changed = false; 233 m_changed = false;
229} 234}
230 235
231bool OContactAccessBackend_XML::wasChangedExternally() 236bool OContactAccessBackend_XML::wasChangedExternally()
232{ 237{
233 QFileInfo fi( m_fileName ); 238 QFileInfo fi( m_fileName );
234 239
235 QDateTime lastmod = fi.lastModified (); 240 QDateTime lastmod = fi.lastModified ();
236 241
237 return (lastmod != m_readtime); 242 return (lastmod != m_readtime);
238} 243}
239 244
240QArray<int> OContactAccessBackend_XML::allRecords() const 245QArray<int> OContactAccessBackend_XML::allRecords() const
241{ 246{
242 QArray<int> uid_list( m_contactList.count() ); 247 QArray<int> uid_list( m_contactList.count() );
243 248
244 uint counter = 0; 249 uint counter = 0;
245 QListIterator<OContact> it( m_contactList ); 250 QListIterator<OContact> it( m_contactList );
246 for( ; it.current(); ++it ){ 251 for( ; it.current(); ++it ){
247 uid_list[counter++] = (*it)->uid(); 252 uid_list[counter++] = (*it)->uid();
248 } 253 }
249 254
250 return ( uid_list ); 255 return ( uid_list );
251} 256}
252 257
253OContact OContactAccessBackend_XML::find ( int uid ) const 258OContact OContactAccessBackend_XML::find ( int uid ) const
254{ 259{
255 OContact foundContact; //Create empty contact 260 OContact foundContact; //Create empty contact
256 261
257 OContact* found = m_uidToContact.find( QString().setNum( uid ) ); 262 OContact* found = m_uidToContact.find( QString().setNum( uid ) );
258 263
259 if ( found ){ 264 if ( found ){
260 foundContact = *found; 265 foundContact = *found;
261 } 266 }
262 267
263 return ( foundContact ); 268 return ( foundContact );
264} 269}
265 270
266QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings, 271QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
267 const QDateTime& d ) 272 const QDateTime& d )
268{ 273{
269 274
270 QArray<int> m_currentQuery( m_contactList.count() ); 275 QArray<int> m_currentQuery( m_contactList.count() );
271 QListIterator<OContact> it( m_contactList ); 276 QListIterator<OContact> it( m_contactList );
272 uint arraycounter = 0; 277 uint arraycounter = 0;
273 278
274 for( ; it.current(); ++it ){ 279 for( ; it.current(); ++it ){
275 /* Search all fields and compare them with query object. Store them into list 280 /* Search all fields and compare them with query object. Store them into list
276 * if all fields matches. 281 * if all fields matches.
277 */ 282 */
278 QDate* queryDate = 0l; 283 QDate* queryDate = 0l;
279 QDate* checkDate = 0l; 284 QDate* checkDate = 0l;
280 bool allcorrect = true; 285 bool allcorrect = true;
281 for ( int i = 0; i < Qtopia::Groups; i++ ) { 286 for ( int i = 0; i < Qtopia::Groups; i++ ) {
282 // Birthday and anniversary are special nonstring fields and should 287 // Birthday and anniversary are special nonstring fields and should
283 // be handled specially 288 // be handled specially
284 switch ( i ){ 289 switch ( i ){
285 case Qtopia::Birthday: 290 case Qtopia::Birthday:
286 queryDate = new QDate( query.birthday() ); 291 queryDate = new QDate( query.birthday() );
287 checkDate = new QDate( (*it)->birthday() ); 292 checkDate = new QDate( (*it)->birthday() );
288 case Qtopia::Anniversary: 293 case Qtopia::Anniversary:
289 if ( queryDate == 0l ){ 294 if ( queryDate == 0l ){
290 queryDate = new QDate( query.anniversary() ); 295 queryDate = new QDate( query.anniversary() );
291 checkDate = new QDate( (*it)->anniversary() ); 296 checkDate = new QDate( (*it)->anniversary() );
292 } 297 }
293 298
294 if ( queryDate->isValid() ){ 299 if ( queryDate->isValid() ){
295 if( checkDate->isValid() ){ 300 if( checkDate->isValid() ){
296 if ( settings & OContactAccess::DateYear ){ 301 if ( settings & OContactAccess::DateYear ){
297 if ( queryDate->year() != checkDate->year() ) 302 if ( queryDate->year() != checkDate->year() )
298 allcorrect = false; 303 allcorrect = false;
299 } 304 }
300 if ( settings & OContactAccess::DateMonth ){ 305 if ( settings & OContactAccess::DateMonth ){
301 if ( queryDate->month() != checkDate->month() ) 306 if ( queryDate->month() != checkDate->month() )
302 allcorrect = false; 307 allcorrect = false;
303 } 308 }
304 if ( settings & OContactAccess::DateDay ){ 309 if ( settings & OContactAccess::DateDay ){
305 if ( queryDate->day() != checkDate->day() ) 310 if ( queryDate->day() != checkDate->day() )
306 allcorrect = false; 311 allcorrect = false;
307 } 312 }
308 if ( settings & OContactAccess::DateDiff ) { 313 if ( settings & OContactAccess::DateDiff ) {
309 QDate current; 314 QDate current;
310 // If we get an additional date, we 315 // If we get an additional date, we
311 // will take this date instead of 316 // will take this date instead of
312 // the current one.. 317 // the current one..
313 if ( !d.date().isValid() ) 318 if ( !d.date().isValid() )
314 current = QDate::currentDate(); 319 current = QDate::currentDate();
315 else 320 else
316 current = d.date(); 321 current = d.date();
317 322
318 // We have to equalize the year, otherwise 323 // We have to equalize the year, otherwise
319 // the search will fail.. 324 // the search will fail..
320 checkDate->setYMD( current.year(), 325 checkDate->setYMD( current.year(),
321 checkDate->month(), 326 checkDate->month(),
322 checkDate->day() ); 327 checkDate->day() );
323 if ( *checkDate < current ) 328 if ( *checkDate < current )
324 checkDate->setYMD( current.year()+1, 329 checkDate->setYMD( current.year()+1,
325 checkDate->month(), 330 checkDate->month(),
326 checkDate->day() ); 331 checkDate->day() );
327 332
328 // Check whether the birthday/anniversary date is between 333 // Check whether the birthday/anniversary date is between
329 // the current/given date and the maximum date 334 // the current/given date and the maximum date
330 // ( maximum time range ) ! 335 // ( maximum time range ) !
331 qWarning("Checking if %s is between %s and %s ! ", 336 qWarning("Checking if %s is between %s and %s ! ",
332 checkDate->toString().latin1(), 337 checkDate->toString().latin1(),
333 current.toString().latin1(), 338 current.toString().latin1(),
334 queryDate->toString().latin1() ); 339 queryDate->toString().latin1() );
335 if ( current.daysTo( *queryDate ) >= 0 ){ 340 if ( current.daysTo( *queryDate ) >= 0 ){
336 if ( !( ( *checkDate >= current ) && 341 if ( !( ( *checkDate >= current ) &&
337 ( *checkDate <= *queryDate ) ) ){ 342 ( *checkDate <= *queryDate ) ) ){
338 allcorrect = false; 343 allcorrect = false;
339 qWarning (" Nope!.."); 344 qWarning (" Nope!..");
340 } 345 }
341 } 346 }
342 } 347 }
343 } else{ 348 } else{
344 // checkDate is invalid. Therefore this entry is always rejected 349 // checkDate is invalid. Therefore this entry is always rejected
345 allcorrect = false; 350 allcorrect = false;
346 } 351 }
347 } 352 }
348 353
349 delete queryDate; 354 delete queryDate;
350 queryDate = 0l; 355 queryDate = 0l;
351 delete checkDate; 356 delete checkDate;
352 checkDate = 0l; 357 checkDate = 0l;
353 break; 358 break;
354 default: 359 default:
355 /* Just compare fields which are not empty in the query object */ 360 /* Just compare fields which are not empty in the query object */
356 if ( !query.field(i).isEmpty() ){ 361 if ( !query.field(i).isEmpty() ){
357 switch ( settings & ~( OContactAccess::IgnoreCase 362 switch ( settings & ~( OContactAccess::IgnoreCase
358 | OContactAccess::DateDiff 363 | OContactAccess::DateDiff
359 | OContactAccess::DateYear 364 | OContactAccess::DateYear
360 | OContactAccess::DateMonth 365 | OContactAccess::DateMonth
361 | OContactAccess::DateDay 366 | OContactAccess::DateDay
362 | OContactAccess::MatchOne 367 | OContactAccess::MatchOne
363 ) ){ 368 ) ){
364 369
365 case OContactAccess::RegExp:{ 370 case OContactAccess::RegExp:{
366 QRegExp expr ( query.field(i), 371 QRegExp expr ( query.field(i),
367 !(settings & OContactAccess::IgnoreCase), 372 !(settings & OContactAccess::IgnoreCase),
368 false ); 373 false );
369 if ( expr.find ( (*it)->field(i), 0 ) == -1 ) 374 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
370 allcorrect = false; 375 allcorrect = false;
371 } 376 }
372 break; 377 break;
373 case OContactAccess::WildCards:{ 378 case OContactAccess::WildCards:{
374 QRegExp expr ( query.field(i), 379 QRegExp expr ( query.field(i),
375 !(settings & OContactAccess::IgnoreCase), 380 !(settings & OContactAccess::IgnoreCase),
376 true ); 381 true );
@@ -388,156 +393,156 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
388 allcorrect = false; 393 allcorrect = false;
389 } 394 }
390 } 395 }
391 break; 396 break;
392 } 397 }
393 } 398 }
394 } 399 }
395 } 400 }
396 if ( allcorrect ){ 401 if ( allcorrect ){
397 m_currentQuery[arraycounter++] = (*it)->uid(); 402 m_currentQuery[arraycounter++] = (*it)->uid();
398 } 403 }
399 } 404 }
400 405
401 // Shrink to fit.. 406 // Shrink to fit..
402 m_currentQuery.resize(arraycounter); 407 m_currentQuery.resize(arraycounter);
403 408
404 return m_currentQuery; 409 return m_currentQuery;
405} 410}
406 411
407QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const 412QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
408{ 413{
409 QArray<int> m_currentQuery( m_contactList.count() ); 414 QArray<int> m_currentQuery( m_contactList.count() );
410 QListIterator<OContact> it( m_contactList ); 415 QListIterator<OContact> it( m_contactList );
411 uint arraycounter = 0; 416 uint arraycounter = 0;
412 417
413 for( ; it.current(); ++it ){ 418 for( ; it.current(); ++it ){
414 if ( (*it)->match( r ) ){ 419 if ( (*it)->match( r ) ){
415 m_currentQuery[arraycounter++] = (*it)->uid(); 420 m_currentQuery[arraycounter++] = (*it)->uid();
416 } 421 }
417 422
418 } 423 }
419 // Shrink to fit.. 424 // Shrink to fit..
420 m_currentQuery.resize(arraycounter); 425 m_currentQuery.resize(arraycounter);
421 426
422 return m_currentQuery; 427 return m_currentQuery;
423} 428}
424 429
425const uint OContactAccessBackend_XML::querySettings() 430const uint OContactAccessBackend_XML::querySettings()
426{ 431{
427 return ( OContactAccess::WildCards 432 return ( OContactAccess::WildCards
428 | OContactAccess::IgnoreCase 433 | OContactAccess::IgnoreCase
429 | OContactAccess::RegExp 434 | OContactAccess::RegExp
430 | OContactAccess::ExactMatch 435 | OContactAccess::ExactMatch
431 | OContactAccess::DateDiff 436 | OContactAccess::DateDiff
432 | OContactAccess::DateYear 437 | OContactAccess::DateYear
433 | OContactAccess::DateMonth 438 | OContactAccess::DateMonth
434 | OContactAccess::DateDay 439 | OContactAccess::DateDay
435 ); 440 );
436} 441}
437 442
438bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const 443bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
439{ 444{
440 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay 445 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
441 * may be added with any of the other settings. IgnoreCase should never used alone. 446 * may be added with any of the other settings. IgnoreCase should never used alone.
442 * Wildcards, RegExp, ExactMatch should never used at the same time... 447 * Wildcards, RegExp, ExactMatch should never used at the same time...
443 */ 448 */
444 449
445 if ( querySettings == OContactAccess::IgnoreCase ) 450 if ( querySettings == OContactAccess::IgnoreCase )
446 return false; 451 return false;
447 452
448 switch ( querySettings & ~( OContactAccess::IgnoreCase 453 switch ( querySettings & ~( OContactAccess::IgnoreCase
449 | OContactAccess::DateDiff 454 | OContactAccess::DateDiff
450 | OContactAccess::DateYear 455 | OContactAccess::DateYear
451 | OContactAccess::DateMonth 456 | OContactAccess::DateMonth
452 | OContactAccess::DateDay 457 | OContactAccess::DateDay
453 ) 458 )
454 ){ 459 ){
455 case OContactAccess::RegExp: 460 case OContactAccess::RegExp:
456 return ( true ); 461 return ( true );
457 case OContactAccess::WildCards: 462 case OContactAccess::WildCards:
458 return ( true ); 463 return ( true );
459 case OContactAccess::ExactMatch: 464 case OContactAccess::ExactMatch:
460 return ( true ); 465 return ( true );
461 default: 466 default:
462 return ( false ); 467 return ( false );
463 } 468 }
464} 469}
465 470
466// Currently only asc implemented.. 471// Currently only asc implemented..
467QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int ) 472QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
468{ 473{
469 QMap<QString, int> nameToUid; 474 QMap<QString, int> nameToUid;
470 QStringList names; 475 QStringList names;
471 QArray<int> m_currentQuery( m_contactList.count() ); 476 QArray<int> m_currentQuery( m_contactList.count() );
472 477
473 // First fill map and StringList with all Names 478 // First fill map and StringList with all Names
474 // Afterwards sort namelist and use map to fill array to return.. 479 // Afterwards sort namelist and use map to fill array to return..
475 QListIterator<OContact> it( m_contactList ); 480 QListIterator<OContact> it( m_contactList );
476 for( ; it.current(); ++it ){ 481 for( ; it.current(); ++it ){
477 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) ); 482 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
478 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() ); 483 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
479 } 484 }
480 names.sort(); 485 names.sort();
481 486
482 int i = 0; 487 int i = 0;
483 if ( asc ){ 488 if ( asc ){
484 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) 489 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
485 m_currentQuery[i++] = nameToUid[ (*it) ]; 490 m_currentQuery[i++] = nameToUid[ (*it) ];
486 }else{ 491 }else{
487 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it ) 492 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
488 m_currentQuery[i++] = nameToUid[ (*it) ]; 493 m_currentQuery[i++] = nameToUid[ (*it) ];
489 } 494 }
490 495
491 return m_currentQuery; 496 return m_currentQuery;
492 497
493} 498}
494 499
495bool OContactAccessBackend_XML::add ( const OContact &newcontact ) 500bool OContactAccessBackend_XML::add ( const OContact &newcontact )
496{ 501{
497 //qWarning("odefaultbackend: ACTION::ADD"); 502 //qWarning("odefaultbackend: ACTION::ADD");
498 updateJournal (newcontact, ACTION_ADD); 503 updateJournal (newcontact, ACTION_ADD);
499 addContact_p( newcontact ); 504 addContact_p( newcontact );
500 505
501 m_changed = true; 506 m_changed = true;
502 507
503 return true; 508 return true;
504} 509}
505 510
506bool OContactAccessBackend_XML::replace ( const OContact &contact ) 511bool OContactAccessBackend_XML::replace ( const OContact &contact )
507{ 512{
508 m_changed = true; 513 m_changed = true;
509 514
510 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) ); 515 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
511 516
512 if ( found ) { 517 if ( found ) {
513 OContact* newCont = new OContact( contact ); 518 OContact* newCont = new OContact( contact );
514 519
515 updateJournal ( *newCont, ACTION_REPLACE); 520 updateJournal ( *newCont, ACTION_REPLACE);
516 m_contactList.removeRef ( found ); 521 m_contactList.removeRef ( found );
517 m_contactList.append ( newCont ); 522 m_contactList.append ( newCont );
518 m_uidToContact.remove( QString().setNum( contact.uid() ) ); 523 m_uidToContact.remove( QString().setNum( contact.uid() ) );
519 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont ); 524 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
520 525
521 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid()); 526 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
522 527
523 return true; 528 return true;
524 } else 529 } else
525 return false; 530 return false;
526} 531}
527 532
528bool OContactAccessBackend_XML::remove ( int uid ) 533bool OContactAccessBackend_XML::remove ( int uid )
529{ 534{
530 m_changed = true; 535 m_changed = true;
531 536
532 OContact* found = m_uidToContact.find ( QString().setNum( uid ) ); 537 OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
533 538
534 if ( found ) { 539 if ( found ) {
535 updateJournal ( *found, ACTION_REMOVE); 540 updateJournal ( *found, ACTION_REMOVE);
536 m_contactList.removeRef ( found ); 541 m_contactList.removeRef ( found );
537 m_uidToContact.remove( QString().setNum( uid ) ); 542 m_uidToContact.remove( QString().setNum( uid ) );
538 543
539 return true; 544 return true;
540 } else 545 } else
541 return false; 546 return false;
542} 547}
543 548
@@ -546,46 +551,46 @@ bool OContactAccessBackend_XML::reload(){
546 return ( load() ); 551 return ( load() );
547} 552}
548 553
549void OContactAccessBackend_XML::addContact_p( const OContact &newcontact ) 554void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
550{ 555{
551 OContact* contRef = new OContact( newcontact ); 556 OContact* contRef = new OContact( newcontact );
552 557
553 m_contactList.append ( contRef ); 558 m_contactList.append ( contRef );
554 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef ); 559 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
555} 560}
556 561
557/* This function loads the xml-database and the journalfile */ 562/* This function loads the xml-database and the journalfile */
558bool OContactAccessBackend_XML::load( const QString filename, bool isJournal ) 563bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
559{ 564{
560 565
561 /* We use the time of the last read to check if the file was 566 /* We use the time of the last read to check if the file was
562 * changed externally. 567 * changed externally.
563 */ 568 */
564 if ( !isJournal ){ 569 if ( !isJournal ){
565 QFileInfo fi( filename ); 570 QFileInfo fi( filename );
566 m_readtime = fi.lastModified (); 571 m_readtime = fi.lastModified ();
567 } 572 }
568 573
569 const int JOURNALACTION = Qtopia::Notes + 1; 574 const int JOURNALACTION = Qtopia::Notes + 1;
570 const int JOURNALROW = JOURNALACTION + 1; 575 const int JOURNALROW = JOURNALACTION + 1;
571 576
572 bool foundAction = false; 577 bool foundAction = false;
573 journal_action action = ACTION_ADD; 578 journal_action action = ACTION_ADD;
574 int journalKey = 0; 579 int journalKey = 0;
575 QMap<int, QString> contactMap; 580 QMap<int, QString> contactMap;
576 QMap<QString, QString> customMap; 581 QMap<QString, QString> customMap;
577 QMap<QString, QString>::Iterator customIt; 582 QMap<QString, QString>::Iterator customIt;
578 QAsciiDict<int> dict( 47 ); 583 QAsciiDict<int> dict( 47 );
579 584
580 dict.setAutoDelete( TRUE ); 585 dict.setAutoDelete( TRUE );
581 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 586 dict.insert( "Uid", new int(Qtopia::AddressUid) );
582 dict.insert( "Title", new int(Qtopia::Title) ); 587 dict.insert( "Title", new int(Qtopia::Title) );
583 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 588 dict.insert( "FirstName", new int(Qtopia::FirstName) );
584 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 589 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
585 dict.insert( "LastName", new int(Qtopia::LastName) ); 590 dict.insert( "LastName", new int(Qtopia::LastName) );
586 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 591 dict.insert( "Suffix", new int(Qtopia::Suffix) );
587 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 592 dict.insert( "FileAs", new int(Qtopia::FileAs) );
588 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 593 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
589 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 594 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
590 dict.insert( "Emails", new int(Qtopia::Emails) ); 595 dict.insert( "Emails", new int(Qtopia::Emails) );
591 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 596 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
@@ -614,36 +619,36 @@ bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
614 dict.insert( "Profession", new int(Qtopia::Profession) ); 619 dict.insert( "Profession", new int(Qtopia::Profession) );
615 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 620 dict.insert( "Assistant", new int(Qtopia::Assistant) );
616 dict.insert( "Manager", new int(Qtopia::Manager) ); 621 dict.insert( "Manager", new int(Qtopia::Manager) );
617 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 622 dict.insert( "Spouse", new int(Qtopia::Spouse) );
618 dict.insert( "Children", new int(Qtopia::Children) ); 623 dict.insert( "Children", new int(Qtopia::Children) );
619 dict.insert( "Gender", new int(Qtopia::Gender) ); 624 dict.insert( "Gender", new int(Qtopia::Gender) );
620 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 625 dict.insert( "Birthday", new int(Qtopia::Birthday) );
621 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 626 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
622 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 627 dict.insert( "Nickname", new int(Qtopia::Nickname) );
623 dict.insert( "Notes", new int(Qtopia::Notes) ); 628 dict.insert( "Notes", new int(Qtopia::Notes) );
624 dict.insert( "action", new int(JOURNALACTION) ); 629 dict.insert( "action", new int(JOURNALACTION) );
625 dict.insert( "actionrow", new int(JOURNALROW) ); 630 dict.insert( "actionrow", new int(JOURNALROW) );
626 631
627 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); 632 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
628 633
629 XMLElement *root = XMLElement::load( filename ); 634 XMLElement *root = XMLElement::load( filename );
630 if(root != 0l ){ // start parsing 635 if(root != 0l ){ // start parsing
631 /* Parse all XML-Elements and put the data into the 636 /* Parse all XML-Elements and put the data into the
632 * Contact-Class 637 * Contact-Class
633 */ 638 */
634 XMLElement *element = root->firstChild(); 639 XMLElement *element = root->firstChild();
635 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); 640 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
636 element = element->firstChild(); 641 element = element->firstChild();
637 642
638 /* Search Tag "Contacts" which is the parent of all Contacts */ 643 /* Search Tag "Contacts" which is the parent of all Contacts */
639 while( element && !isJournal ){ 644 while( element && !isJournal ){
640 if( element->tagName() != QString::fromLatin1("Contacts") ){ 645 if( element->tagName() != QString::fromLatin1("Contacts") ){
641 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", 646 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
642 // element->tagName().latin1()); 647 // element->tagName().latin1());
643 element = element->nextChild(); 648 element = element->nextChild();
644 } else { 649 } else {
645 element = element->firstChild(); 650 element = element->firstChild();
646 break; 651 break;
647 } 652 }
648 } 653 }
649 /* Parse all Contacts and ignore unknown tags */ 654 /* Parse all Contacts and ignore unknown tags */
@@ -652,41 +657,41 @@ bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
652 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", 657 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
653 // element->tagName().latin1()); 658 // element->tagName().latin1());
654 element = element->nextChild(); 659 element = element->nextChild();
655 continue; 660 continue;
656 } 661 }
657 /* Found alement with tagname "contact", now parse and store all 662 /* Found alement with tagname "contact", now parse and store all
658 * attributes contained 663 * attributes contained
659 */ 664 */
660 //qWarning("OContactDefBack::load element tagName() : %s", 665 //qWarning("OContactDefBack::load element tagName() : %s",
661 // element->tagName().latin1() ); 666 // element->tagName().latin1() );
662 QString dummy; 667 QString dummy;
663 foundAction = false; 668 foundAction = false;
664 669
665 XMLElement::AttributeMap aMap = element->attributes(); 670 XMLElement::AttributeMap aMap = element->attributes();
666 XMLElement::AttributeMap::Iterator it; 671 XMLElement::AttributeMap::Iterator it;
667 contactMap.clear(); 672 contactMap.clear();
668 customMap.clear(); 673 customMap.clear();
669 for( it = aMap.begin(); it != aMap.end(); ++it ){ 674 for( it = aMap.begin(); it != aMap.end(); ++it ){
670 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); 675 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
671 676
672 int *find = dict[ it.key() ]; 677 int *find = dict[ it.key() ];
673 /* Unknown attributes will be stored as "Custom" elements */ 678 /* Unknown attributes will be stored as "Custom" elements */
674 if ( !find ) { 679 if ( !find ) {
675 qWarning("Attribute %s not known.", it.key().latin1()); 680 qWarning("Attribute %s not known.", it.key().latin1());
676 //contact.setCustomField(it.key(), it.data()); 681 //contact.setCustomField(it.key(), it.data());
677 customMap.insert( it.key(), it.data() ); 682 customMap.insert( it.key(), it.data() );
678 continue; 683 continue;
679 } 684 }
680 685
681 /* Check if special conversion is needed and add attribute 686 /* Check if special conversion is needed and add attribute
682 * into Contact class 687 * into Contact class
683 */ 688 */
684 switch( *find ) { 689 switch( *find ) {
685 /* 690 /*
686 case Qtopia::AddressUid: 691 case Qtopia::AddressUid:
687 contact.setUid( it.data().toInt() ); 692 contact.setUid( it.data().toInt() );
688 break; 693 break;
689 case Qtopia::AddressCategory: 694 case Qtopia::AddressCategory:
690 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 695 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
691 break; 696 break;
692 */ 697 */
@@ -696,86 +701,86 @@ bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
696 qWarning ("ODefBack(journal)::ACTION found: %d", action); 701 qWarning ("ODefBack(journal)::ACTION found: %d", action);
697 break; 702 break;
698 case JOURNALROW: 703 case JOURNALROW:
699 journalKey = it.data().toInt(); 704 journalKey = it.data().toInt();
700 break; 705 break;
701 default: // no conversion needed add them to the map 706 default: // no conversion needed add them to the map
702 contactMap.insert( *find, it.data() ); 707 contactMap.insert( *find, it.data() );
703 break; 708 break;
704 } 709 }
705 } 710 }
706 /* now generate the Contact contact */ 711 /* now generate the Contact contact */
707 OContact contact( contactMap ); 712 OContact contact( contactMap );
708 713
709 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { 714 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
710 contact.setCustomField( customIt.key(), customIt.data() ); 715 contact.setCustomField( customIt.key(), customIt.data() );
711 } 716 }
712 717
713 if (foundAction){ 718 if (foundAction){
714 foundAction = false; 719 foundAction = false;
715 switch ( action ) { 720 switch ( action ) {
716 case ACTION_ADD: 721 case ACTION_ADD:
717 addContact_p (contact); 722 addContact_p (contact);
718 break; 723 break;
719 case ACTION_REMOVE: 724 case ACTION_REMOVE:
720 if ( !remove (contact.uid()) ) 725 if ( !remove (contact.uid()) )
721 qWarning ("ODefBack(journal)::Unable to remove uid: %d", 726 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
722 contact.uid() ); 727 contact.uid() );
723 break; 728 break;
724 case ACTION_REPLACE: 729 case ACTION_REPLACE:
725 if ( !replace ( contact ) ) 730 if ( !replace ( contact ) )
726 qWarning ("ODefBack(journal)::Unable to replace uid: %d", 731 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
727 contact.uid() ); 732 contact.uid() );
728 break; 733 break;
729 default: 734 default:
730 qWarning ("Unknown action: ignored !"); 735 qWarning ("Unknown action: ignored !");
731 break; 736 break;
732 } 737 }
733 }else{ 738 }else{
734 /* Add contact to list */ 739 /* Add contact to list */
735 addContact_p (contact); 740 addContact_p (contact);
736 } 741 }
737 742
738 /* Move to next element */ 743 /* Move to next element */
739 element = element->nextChild(); 744 element = element->nextChild();
740 } 745 }
741 }else { 746 }else {
742 qWarning("ODefBack::could not load"); 747 qWarning("ODefBack::could not load");
743 } 748 }
744 delete root; 749 delete root;
745 qWarning("returning from loading" ); 750 qWarning("returning from loading" );
746 return true; 751 return true;
747} 752}
748 753
749 754
750void OContactAccessBackend_XML::updateJournal( const OContact& cnt, 755void OContactAccessBackend_XML::updateJournal( const OContact& cnt,
751 journal_action action ) 756 journal_action action )
752{ 757{
753 QFile f( m_journalName ); 758 QFile f( m_journalName );
754 bool created = !f.exists(); 759 bool created = !f.exists();
755 if ( !f.open(IO_WriteOnly|IO_Append) ) 760 if ( !f.open(IO_WriteOnly|IO_Append) )
756 return; 761 return;
757 762
758 QString buf; 763 QString buf;
759 QCString str; 764 QCString str;
760 765
761 // if the file was created, we have to set the Tag "<CONTACTS>" to 766 // if the file was created, we have to set the Tag "<CONTACTS>" to
762 // get a XML-File which is readable by our parser. 767 // get a XML-File which is readable by our parser.
763 // This is just a cheat, but better than rewrite the parser. 768 // This is just a cheat, but better than rewrite the parser.
764 if ( created ){ 769 if ( created ){
765 buf = "<Contacts>"; 770 buf = "<Contacts>";
766 QCString cstr = buf.utf8(); 771 QCString cstr = buf.utf8();
767 f.writeBlock( cstr.data(), cstr.length() ); 772 f.writeBlock( cstr.data(), cstr.length() );
768 } 773 }
769 774
770 buf = "<Contact "; 775 buf = "<Contact ";
771 cnt.save( buf ); 776 cnt.save( buf );
772 buf += " action=\"" + QString::number( (int)action ) + "\" "; 777 buf += " action=\"" + QString::number( (int)action ) + "\" ";
773 buf += "/>\n"; 778 buf += "/>\n";
774 QCString cstr = buf.utf8(); 779 QCString cstr = buf.utf8();
775 f.writeBlock( cstr.data(), cstr.length() ); 780 f.writeBlock( cstr.data(), cstr.length() );
776} 781}
777 782
778void OContactAccessBackend_XML::removeJournal() 783void OContactAccessBackend_XML::removeJournal()
779{ 784{
780 QFile f ( m_journalName ); 785 QFile f ( m_journalName );
781 if ( f.exists() ) 786 if ( f.exists() )