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