summaryrefslogtreecommitdiff
authoreilers <eilers>2002-11-13 15:02:46 (UTC)
committer eilers <eilers>2002-11-13 15:02:46 (UTC)
commit2bc05c54b2ff1a9b2af7d6bd4d55428cfe0d8db3 (patch) (unidiff)
tree8fdc9e49e0a85927fee9497b9d8c5e34e96b049e
parent2255284b2e80bdc2881ab9106e9afa614a08c140 (diff)
downloadopie-2bc05c54b2ff1a9b2af7d6bd4d55428cfe0d8db3.zip
opie-2bc05c54b2ff1a9b2af7d6bd4d55428cfe0d8db3.tar.gz
opie-2bc05c54b2ff1a9b2af7d6bd4d55428cfe0d8db3.tar.bz2
Small Bug in sorted fixed
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h9
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.h9
2 files changed, 12 insertions, 6 deletions
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 8b95102..adc8dc3 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -1,634 +1,637 @@
1/* 1/*
2 * XML Backend for the OPIE-Contact Database. 2 * XML Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
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.7 2002/11/13 15:02:46 eilers
21 * Small Bug in sorted fixed
22 *
20 * Revision 1.6 2002/11/13 14:14:51 eilers 23 * Revision 1.6 2002/11/13 14:14:51 eilers
21 * Added sorted for Contacts.. 24 * Added sorted for Contacts..
22 * 25 *
23 * Revision 1.5 2002/11/01 15:10:42 eilers 26 * Revision 1.5 2002/11/01 15:10:42 eilers
24 * Added regExp-search in database for all fields in a contact. 27 * Added regExp-search in database for all fields in a contact.
25 * 28 *
26 * Revision 1.4 2002/10/16 10:52:40 eilers 29 * Revision 1.4 2002/10/16 10:52:40 eilers
27 * Added some docu to the interface and now using the cache infrastucture by zecke.. :) 30 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
28 * 31 *
29 * Revision 1.3 2002/10/14 16:21:54 eilers 32 * Revision 1.3 2002/10/14 16:21:54 eilers
30 * Some minor interface updates 33 * Some minor interface updates
31 * 34 *
32 * Revision 1.2 2002/10/07 17:34:24 eilers 35 * Revision 1.2 2002/10/07 17:34:24 eilers
33 * added OBackendFactory for advanced backend access 36 * added OBackendFactory for advanced backend access
34 * 37 *
35 * Revision 1.1 2002/09/27 17:11:44 eilers 38 * Revision 1.1 2002/09/27 17:11:44 eilers
36 * Added API for accessing the Contact-Database ! It is compiling, but 39 * Added API for accessing the Contact-Database ! It is compiling, but
37 * please do not expect that anything is working ! 40 * please do not expect that anything is working !
38 * I will debug that stuff in the next time .. 41 * I will debug that stuff in the next time ..
39 * Please read README_COMPILE for compiling ! 42 * Please read README_COMPILE for compiling !
40 * 43 *
41 * 44 *
42 */ 45 */
43 46
44#ifndef _OContactAccessBackend_XML_ 47#ifndef _OContactAccessBackend_XML_
45#define _OContactAccessBackend_XML_ 48#define _OContactAccessBackend_XML_
46 49
47#include <qasciidict.h> 50#include <qasciidict.h>
48#include <qdatetime.h> 51#include <qdatetime.h>
49#include <qfile.h> 52#include <qfile.h>
50#include <qfileinfo.h> 53#include <qfileinfo.h>
51#include <qregexp.h> 54#include <qregexp.h>
52#include <qarray.h> 55#include <qarray.h>
53#include <qmap.h> 56#include <qmap.h>
54 57
55#include <qpe/global.h> 58#include <qpe/global.h>
56 59
57#include <opie/xmltree.h> 60#include <opie/xmltree.h>
58#include "ocontactaccessbackend.h" 61#include "ocontactaccessbackend.h"
59#include "ocontactaccess.h" 62#include "ocontactaccess.h"
60 63
61#include <stdlib.h> 64#include <stdlib.h>
62#include <errno.h> 65#include <errno.h>
63 66
64using namespace Opie; 67using namespace Opie;
65 68
66/* the default xml implementation */ 69/* the default xml implementation */
67class OContactAccessBackend_XML : public OContactAccessBackend { 70class OContactAccessBackend_XML : public OContactAccessBackend {
68 public: 71 public:
69 OContactAccessBackend_XML ( QString appname, QString filename = 0l ): 72 OContactAccessBackend_XML ( QString appname, QString filename = 0l ):
70 m_changed( false ) 73 m_changed( false )
71 { 74 {
72 m_appName = appname; 75 m_appName = appname;
73 76
74 /* Set journalfile name ... */ 77 /* Set journalfile name ... */
75 m_journalName = getenv("HOME"); 78 m_journalName = getenv("HOME");
76 m_journalName +="/.abjournal" + appname; 79 m_journalName +="/.abjournal" + appname;
77 80
78 /* Expecting to access the default filename if nothing else is set */ 81 /* Expecting to access the default filename if nothing else is set */
79 if ( filename.isEmpty() ){ 82 if ( filename.isEmpty() ){
80 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 83 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
81 } else 84 } else
82 m_fileName = filename; 85 m_fileName = filename;
83 86
84 /* Load Database now */ 87 /* Load Database now */
85 load (); 88 load ();
86 } 89 }
87 90
88 bool save() { 91 bool save() {
89 92
90 if ( !m_changed ) 93 if ( !m_changed )
91 return true; 94 return true;
92 95
93 QString strNewFile = m_fileName + ".new"; 96 QString strNewFile = m_fileName + ".new";
94 QFile f( strNewFile ); 97 QFile f( strNewFile );
95 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 98 if ( !f.open( IO_WriteOnly|IO_Raw ) )
96 return false; 99 return false;
97 100
98 int total_written; 101 int total_written;
99 QString out; 102 QString out;
100 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 103 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
101 " <Groups>\n" 104 " <Groups>\n"
102 " </Groups>\n" 105 " </Groups>\n"
103 " <Contacts>\n"; 106 " <Contacts>\n";
104 //QValueList<Contact>::iterator it; 107 //QValueList<Contact>::iterator it;
105 QValueListConstIterator<OContact> it; 108 QValueListConstIterator<OContact> it;
106 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 109 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
107 out += "<Contact "; 110 out += "<Contact ";
108 (*it).save( out ); 111 (*it).save( out );
109 out += "/>\n"; 112 out += "/>\n";
110 QCString cstr = out.utf8(); 113 QCString cstr = out.utf8();
111 total_written = f.writeBlock( cstr.data(), cstr.length() ); 114 total_written = f.writeBlock( cstr.data(), cstr.length() );
112 if ( total_written != int(cstr.length()) ) { 115 if ( total_written != int(cstr.length()) ) {
113 f.close(); 116 f.close();
114 QFile::remove( strNewFile ); 117 QFile::remove( strNewFile );
115 return false; 118 return false;
116 } 119 }
117 out = ""; 120 out = "";
118 } 121 }
119 out += " </Contacts>\n</AddressBook>\n"; 122 out += " </Contacts>\n</AddressBook>\n";
120 123
121 QCString cstr = out.utf8(); 124 QCString cstr = out.utf8();
122 total_written = f.writeBlock( cstr.data(), cstr.length() ); 125 total_written = f.writeBlock( cstr.data(), cstr.length() );
123 if ( total_written != int( cstr.length() ) ) { 126 if ( total_written != int( cstr.length() ) ) {
124 f.close(); 127 f.close();
125 QFile::remove( strNewFile ); 128 QFile::remove( strNewFile );
126 return false; 129 return false;
127 } 130 }
128 f.close(); 131 f.close();
129 132
130 // move the file over, I'm just going to use the system call 133 // move the file over, I'm just going to use the system call
131 // because, I don't feel like using QDir. 134 // because, I don't feel like using QDir.
132 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 135 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
133 qWarning( "problem renaming file %s to %s, errno: %d", 136 qWarning( "problem renaming file %s to %s, errno: %d",
134 strNewFile.latin1(), m_journalName.latin1(), errno ); 137 strNewFile.latin1(), m_journalName.latin1(), errno );
135 // remove the tmp file... 138 // remove the tmp file...
136 QFile::remove( strNewFile ); 139 QFile::remove( strNewFile );
137 } 140 }
138 141
139 /* The journalfile should be removed now... */ 142 /* The journalfile should be removed now... */
140 removeJournal(); 143 removeJournal();
141 144
142 m_changed = false; 145 m_changed = false;
143 return true; 146 return true;
144 } 147 }
145 148
146 bool load () { 149 bool load () {
147 m_contactList.clear(); 150 m_contactList.clear();
148 151
149 /* Load XML-File and journal if it exists */ 152 /* Load XML-File and journal if it exists */
150 if ( !load ( m_fileName, false ) ) 153 if ( !load ( m_fileName, false ) )
151 return false; 154 return false;
152 /* The returncode of the journalfile is ignored due to the 155 /* The returncode of the journalfile is ignored due to the
153 * fact that it does not exist when this class is instantiated ! 156 * fact that it does not exist when this class is instantiated !
154 * But there may such a file exist, if the application crashed. 157 * But there may such a file exist, if the application crashed.
155 * Therefore we try to load it to get the changes before the # 158 * Therefore we try to load it to get the changes before the #
156 * crash happened... 159 * crash happened...
157 */ 160 */
158 load (m_journalName, true); 161 load (m_journalName, true);
159 162
160 return true; 163 return true;
161 } 164 }
162 165
163 void clear () { 166 void clear () {
164 m_contactList.clear(); 167 m_contactList.clear();
165 m_changed = false; 168 m_changed = false;
166 169
167 } 170 }
168 171
169 bool wasChangedExternally() 172 bool wasChangedExternally()
170 { 173 {
171 QFileInfo fi( m_fileName ); 174 QFileInfo fi( m_fileName );
172 175
173 QDateTime lastmod = fi.lastModified (); 176 QDateTime lastmod = fi.lastModified ();
174 177
175 return (lastmod != m_readtime); 178 return (lastmod != m_readtime);
176 } 179 }
177 180
178 QArray<int> allRecords() const { 181 QArray<int> allRecords() const {
179 QArray<int> uid_list( m_contactList.count() ); 182 QArray<int> uid_list( m_contactList.count() );
180 183
181 uint counter = 0; 184 uint counter = 0;
182 QValueListConstIterator<OContact> it; 185 QValueListConstIterator<OContact> it;
183 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 186 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
184 uid_list[counter++] = (*it).uid(); 187 uid_list[counter++] = (*it).uid();
185 } 188 }
186 189
187 return ( uid_list ); 190 return ( uid_list );
188 } 191 }
189 192
190 OContact find ( int uid ) const 193 OContact find ( int uid ) const
191 { 194 {
192 bool found = false; 195 bool found = false;
193 OContact foundContact; //Create empty contact 196 OContact foundContact; //Create empty contact
194 197
195 QValueListConstIterator<OContact> it; 198 QValueListConstIterator<OContact> it;
196 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 199 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
197 if ((*it).uid() == uid){ 200 if ((*it).uid() == uid){
198 found = true; 201 found = true;
199 break; 202 break;
200 } 203 }
201 } 204 }
202 if ( found ){ 205 if ( found ){
203 foundContact = *it; 206 foundContact = *it;
204 } 207 }
205 208
206 return ( foundContact ); 209 return ( foundContact );
207 } 210 }
208 211
209 QArray<int> queryByExample ( const OContact &query, int settings ){ 212 QArray<int> queryByExample ( const OContact &query, int settings ){
210 213
211 QArray<int> m_currentQuery( m_contactList.count() ); 214 QArray<int> m_currentQuery( m_contactList.count() );
212 QValueListConstIterator<OContact> it; 215 QValueListConstIterator<OContact> it;
213 uint arraycounter = 0; 216 uint arraycounter = 0;
214 217
215 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 218 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
216 /* Search all fields and compare them with query object. Store them into list 219 /* Search all fields and compare them with query object. Store them into list
217 * if all fields matches. 220 * if all fields matches.
218 */ 221 */
219 bool allcorrect = true; 222 bool allcorrect = true;
220 for ( int i = 0; i < Qtopia::rid; i++ ) { 223 for ( int i = 0; i < Qtopia::rid; i++ ) {
221 /* Just compare fields which are not empty in the query object */ 224 /* Just compare fields which are not empty in the query object */
222 if ( !query.field(i).isEmpty() ){ 225 if ( !query.field(i).isEmpty() ){
223 switch ( settings & ~OContactAccess::IgnoreCase ){ 226 switch ( settings & ~OContactAccess::IgnoreCase ){
224 case OContactAccess::RegExp:{ 227 case OContactAccess::RegExp:{
225 QRegExp expr ( query.field(i), 228 QRegExp expr ( query.field(i),
226 !(settings & OContactAccess::IgnoreCase), 229 !(settings & OContactAccess::IgnoreCase),
227 false ); 230 false );
228 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 231 if ( expr.find ( (*it).field(i), 0 ) == -1 )
229 allcorrect = false; 232 allcorrect = false;
230 } 233 }
231 break; 234 break;
232 case OContactAccess::WildCards:{ 235 case OContactAccess::WildCards:{
233 QRegExp expr ( query.field(i), 236 QRegExp expr ( query.field(i),
234 !(settings & OContactAccess::IgnoreCase), 237 !(settings & OContactAccess::IgnoreCase),
235 true ); 238 true );
236 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 239 if ( expr.find ( (*it).field(i), 0 ) == -1 )
237 allcorrect = false; 240 allcorrect = false;
238 } 241 }
239 break; 242 break;
240 case OContactAccess::ExactMatch:{ 243 case OContactAccess::ExactMatch:{
241 if (settings & OContactAccess::IgnoreCase){ 244 if (settings & OContactAccess::IgnoreCase){
242 if ( query.field(i).upper() != 245 if ( query.field(i).upper() !=
243 (*it).field(i).upper() ) 246 (*it).field(i).upper() )
244 allcorrect = false; 247 allcorrect = false;
245 }else{ 248 }else{
246 if ( query.field(i) != (*it).field(i) ) 249 if ( query.field(i) != (*it).field(i) )
247 allcorrect = false; 250 allcorrect = false;
248 } 251 }
249 } 252 }
250 break; 253 break;
251 } 254 }
252 } 255 }
253 } 256 }
254 if ( allcorrect ){ 257 if ( allcorrect ){
255 m_currentQuery[arraycounter++] = (*it).uid(); 258 m_currentQuery[arraycounter++] = (*it).uid();
256 } 259 }
257 } 260 }
258 261
259 // Shrink to fit.. 262 // Shrink to fit..
260 m_currentQuery.resize(arraycounter); 263 m_currentQuery.resize(arraycounter);
261 264
262 return m_currentQuery; 265 return m_currentQuery;
263 } 266 }
264 267
265 QArray<int> matchRegexp( const QRegExp &r ) const{ 268 QArray<int> matchRegexp( const QRegExp &r ) const{
266 QArray<int> m_currentQuery( m_contactList.count() ); 269 QArray<int> m_currentQuery( m_contactList.count() );
267 QValueListConstIterator<OContact> it; 270 QValueListConstIterator<OContact> it;
268 uint arraycounter = 0; 271 uint arraycounter = 0;
269 272
270 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 273 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
271 if ( (*it).match( r ) ){ 274 if ( (*it).match( r ) ){
272 m_currentQuery[arraycounter++] = (*it).uid(); 275 m_currentQuery[arraycounter++] = (*it).uid();
273 } 276 }
274 277
275 } 278 }
276 // Shrink to fit.. 279 // Shrink to fit..
277 m_currentQuery.resize(arraycounter); 280 m_currentQuery.resize(arraycounter);
278 281
279 return m_currentQuery; 282 return m_currentQuery;
280 } 283 }
281 284
282 const uint querySettings() 285 const uint querySettings()
283 { 286 {
284 return ( OContactAccess::WildCards 287 return ( OContactAccess::WildCards
285 & OContactAccess::IgnoreCase 288 & OContactAccess::IgnoreCase
286 & OContactAccess::RegExp 289 & OContactAccess::RegExp
287 & OContactAccess::ExactMatch ); 290 & OContactAccess::ExactMatch );
288 } 291 }
289 292
290 bool hasQuerySettings (uint querySettings) const 293 bool hasQuerySettings (uint querySettings) const
291 { 294 {
292 /* OContactAccess::IgnoreCase may be added with one 295 /* OContactAccess::IgnoreCase may be added with one
293 * of the other settings, but never used alone. 296 * of the other settings, but never used alone.
294 * The other settings are just valid alone... 297 * The other settings are just valid alone...
295 */ 298 */
296 switch ( querySettings & ~OContactAccess::IgnoreCase ){ 299 switch ( querySettings & ~OContactAccess::IgnoreCase ){
297 case OContactAccess::RegExp: 300 case OContactAccess::RegExp:
298 return ( true ); 301 return ( true );
299 case OContactAccess::WildCards: 302 case OContactAccess::WildCards:
300 return ( true ); 303 return ( true );
301 case OContactAccess::ExactMatch: 304 case OContactAccess::ExactMatch:
302 return ( true ); 305 return ( true );
303 default: 306 default:
304 return ( false ); 307 return ( false );
305 } 308 }
306 } 309 }
307 310
308 // Currently only asc implemented.. 311 // Currently only asc implemented..
309 QArray<int> sorted( bool asc, int , int , int ) 312 QArray<int> sorted( bool asc, int , int , int )
310 { 313 {
311 QMap<QString, int> nameToUid; 314 QMap<QString, int> nameToUid;
312 QStringList names; 315 QStringList names;
313 QArray<int> m_currentQuery( m_contactList.count() ); 316 QArray<int> m_currentQuery( m_contactList.count() );
314 317
315 // First fill map and StringList with all Names ( better LastNames ? ) 318 // First fill map and StringList with all Names
316 // Afterwards sort namelist and use map to fill array to return.. 319 // Afterwards sort namelist and use map to fill array to return..
317 QValueListConstIterator<OContact> it; 320 QValueListConstIterator<OContact> it;
318 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 321 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
319 names.append( (*it).lastName() ); 322 names.append( (*it).fileAs() );
320 nameToUid.insert( (*it).lastName(), (*it).uid() ); 323 nameToUid.insert( (*it).fileAs(), (*it).uid() );
321 } 324 }
322 names.sort(); 325 names.sort();
323 326
324 int i = 0; 327 int i = 0;
325 if ( asc ){ 328 if ( asc ){
326 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) 329 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
327 m_currentQuery[i++] = nameToUid[ (*it) ]; 330 m_currentQuery[i++] = nameToUid[ (*it) ];
328 }else{ 331 }else{
329 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it ) 332 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
330 m_currentQuery[i++] = nameToUid[ (*it) ]; 333 m_currentQuery[i++] = nameToUid[ (*it) ];
331 } 334 }
332 335
333 return m_currentQuery; 336 return m_currentQuery;
334 337
335 } 338 }
336 bool add ( const OContact &newcontact ) 339 bool add ( const OContact &newcontact )
337 { 340 {
338 //qWarning("odefaultbackend: ACTION::ADD"); 341 //qWarning("odefaultbackend: ACTION::ADD");
339 updateJournal (newcontact, OContact::ACTION_ADD); 342 updateJournal (newcontact, OContact::ACTION_ADD);
340 addContact_p( newcontact ); 343 addContact_p( newcontact );
341 344
342 m_changed = true; 345 m_changed = true;
343 346
344 return true; 347 return true;
345 } 348 }
346 349
347 bool replace ( const OContact &contact ) 350 bool replace ( const OContact &contact )
348 { 351 {
349 m_changed = true; 352 m_changed = true;
350 353
351 bool found = false; 354 bool found = false;
352 355
353 QValueListIterator<OContact> it; 356 QValueListIterator<OContact> it;
354 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 357 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
355 if ( (*it).uid() == contact.uid() ){ 358 if ( (*it).uid() == contact.uid() ){
356 found = true; 359 found = true;
357 break; 360 break;
358 } 361 }
359 } 362 }
360 if (found) { 363 if (found) {
361 updateJournal (contact, OContact::ACTION_REPLACE); 364 updateJournal (contact, OContact::ACTION_REPLACE);
362 m_contactList.remove (it); 365 m_contactList.remove (it);
363 m_contactList.append (contact); 366 m_contactList.append (contact);
364 return true; 367 return true;
365 } else 368 } else
366 return false; 369 return false;
367 } 370 }
368 371
369 bool remove ( int uid ) 372 bool remove ( int uid )
370 { 373 {
371 m_changed = true; 374 m_changed = true;
372 375
373 bool found = false; 376 bool found = false;
374 QValueListIterator<OContact> it; 377 QValueListIterator<OContact> it;
375 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 378 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
376 if ((*it).uid() == uid){ 379 if ((*it).uid() == uid){
377 found = true; 380 found = true;
378 break; 381 break;
379 } 382 }
380 } 383 }
381 if (found) { 384 if (found) {
382 updateJournal ( *it, OContact::ACTION_REMOVE); 385 updateJournal ( *it, OContact::ACTION_REMOVE);
383 m_contactList.remove (it); 386 m_contactList.remove (it);
384 return true; 387 return true;
385 } else 388 } else
386 return false; 389 return false;
387 } 390 }
388 391
389 bool reload(){ 392 bool reload(){
390 /* Reload is the same as load in this implementation */ 393 /* Reload is the same as load in this implementation */
391 return ( load() ); 394 return ( load() );
392 } 395 }
393 396
394 private: 397 private:
395 void addContact_p( const OContact &newcontact ){ 398 void addContact_p( const OContact &newcontact ){
396 m_contactList.append (newcontact); 399 m_contactList.append (newcontact);
397 } 400 }
398 401
399 /* This function loads the xml-database and the journalfile */ 402 /* This function loads the xml-database and the journalfile */
400 bool load( const QString filename, bool isJournal ) { 403 bool load( const QString filename, bool isJournal ) {
401 404
402 /* We use the time of the last read to check if the file was 405 /* We use the time of the last read to check if the file was
403 * changed externally. 406 * changed externally.
404 */ 407 */
405 if ( !isJournal ){ 408 if ( !isJournal ){
406 QFileInfo fi( filename ); 409 QFileInfo fi( filename );
407 m_readtime = fi.lastModified (); 410 m_readtime = fi.lastModified ();
408 } 411 }
409 412
410 const int JOURNALACTION = Qtopia::Notes + 1; 413 const int JOURNALACTION = Qtopia::Notes + 1;
411 const int JOURNALROW = JOURNALACTION + 1; 414 const int JOURNALROW = JOURNALACTION + 1;
412 415
413 bool foundAction = false; 416 bool foundAction = false;
414 OContact::journal_action action = OContact::ACTION_ADD; 417 OContact::journal_action action = OContact::ACTION_ADD;
415 int journalKey = 0; 418 int journalKey = 0;
416 QMap<int, QString> contactMap; 419 QMap<int, QString> contactMap;
417 QMap<QString, QString> customMap; 420 QMap<QString, QString> customMap;
418 QMap<QString, QString>::Iterator customIt; 421 QMap<QString, QString>::Iterator customIt;
419 QAsciiDict<int> dict( 47 ); 422 QAsciiDict<int> dict( 47 );
420 423
421 dict.setAutoDelete( TRUE ); 424 dict.setAutoDelete( TRUE );
422 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 425 dict.insert( "Uid", new int(Qtopia::AddressUid) );
423 dict.insert( "Title", new int(Qtopia::Title) ); 426 dict.insert( "Title", new int(Qtopia::Title) );
424 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 427 dict.insert( "FirstName", new int(Qtopia::FirstName) );
425 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 428 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
426 dict.insert( "LastName", new int(Qtopia::LastName) ); 429 dict.insert( "LastName", new int(Qtopia::LastName) );
427 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 430 dict.insert( "Suffix", new int(Qtopia::Suffix) );
428 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 431 dict.insert( "FileAs", new int(Qtopia::FileAs) );
429 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 432 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
430 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 433 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
431 dict.insert( "Emails", new int(Qtopia::Emails) ); 434 dict.insert( "Emails", new int(Qtopia::Emails) );
432 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 435 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
433 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 436 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
434 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 437 dict.insert( "HomeState", new int(Qtopia::HomeState) );
435 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 438 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
436 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 439 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
437 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 440 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
438 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 441 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
439 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 442 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
440 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 443 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
441 dict.insert( "Company", new int(Qtopia::Company) ); 444 dict.insert( "Company", new int(Qtopia::Company) );
442 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 445 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
443 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 446 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
444 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 447 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
445 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 448 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
446 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 449 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
447 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 450 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
448 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 451 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
449 dict.insert( "Department", new int(Qtopia::Department) ); 452 dict.insert( "Department", new int(Qtopia::Department) );
450 dict.insert( "Office", new int(Qtopia::Office) ); 453 dict.insert( "Office", new int(Qtopia::Office) );
451 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 454 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
452 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 455 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
453 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 456 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
454 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 457 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
455 dict.insert( "Profession", new int(Qtopia::Profession) ); 458 dict.insert( "Profession", new int(Qtopia::Profession) );
456 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 459 dict.insert( "Assistant", new int(Qtopia::Assistant) );
457 dict.insert( "Manager", new int(Qtopia::Manager) ); 460 dict.insert( "Manager", new int(Qtopia::Manager) );
458 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 461 dict.insert( "Spouse", new int(Qtopia::Spouse) );
459 dict.insert( "Children", new int(Qtopia::Children) ); 462 dict.insert( "Children", new int(Qtopia::Children) );
460 dict.insert( "Gender", new int(Qtopia::Gender) ); 463 dict.insert( "Gender", new int(Qtopia::Gender) );
461 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 464 dict.insert( "Birthday", new int(Qtopia::Birthday) );
462 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 465 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
463 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 466 dict.insert( "Nickname", new int(Qtopia::Nickname) );
464 dict.insert( "Notes", new int(Qtopia::Notes) ); 467 dict.insert( "Notes", new int(Qtopia::Notes) );
465 dict.insert( "action", new int(JOURNALACTION) ); 468 dict.insert( "action", new int(JOURNALACTION) );
466 dict.insert( "actionrow", new int(JOURNALROW) ); 469 dict.insert( "actionrow", new int(JOURNALROW) );
467 470
468 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); 471 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
469 472
470 XMLElement *root = XMLElement::load( filename ); 473 XMLElement *root = XMLElement::load( filename );
471 if(root != 0l ){ // start parsing 474 if(root != 0l ){ // start parsing
472 /* Parse all XML-Elements and put the data into the 475 /* Parse all XML-Elements and put the data into the
473 * Contact-Class 476 * Contact-Class
474 */ 477 */
475 XMLElement *element = root->firstChild(); 478 XMLElement *element = root->firstChild();
476 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); 479 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
477 element = element->firstChild(); 480 element = element->firstChild();
478 481
479 /* Search Tag "Contacts" which is the parent of all Contacts */ 482 /* Search Tag "Contacts" which is the parent of all Contacts */
480 while( element && !isJournal ){ 483 while( element && !isJournal ){
481 if( element->tagName() != QString::fromLatin1("Contacts") ){ 484 if( element->tagName() != QString::fromLatin1("Contacts") ){
482 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", 485 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
483 // element->tagName().latin1()); 486 // element->tagName().latin1());
484 element = element->nextChild(); 487 element = element->nextChild();
485 } else { 488 } else {
486 element = element->firstChild(); 489 element = element->firstChild();
487 break; 490 break;
488 } 491 }
489 } 492 }
490 /* Parse all Contacts and ignore unknown tags */ 493 /* Parse all Contacts and ignore unknown tags */
491 while( element ){ 494 while( element ){
492 if( element->tagName() != QString::fromLatin1("Contact") ){ 495 if( element->tagName() != QString::fromLatin1("Contact") ){
493 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", 496 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
494 // element->tagName().latin1()); 497 // element->tagName().latin1());
495 element = element->nextChild(); 498 element = element->nextChild();
496 continue; 499 continue;
497 } 500 }
498 /* Found alement with tagname "contact", now parse and store all 501 /* Found alement with tagname "contact", now parse and store all
499 * attributes contained 502 * attributes contained
500 */ 503 */
501 //qWarning("OContactDefBack::load element tagName() : %s", 504 //qWarning("OContactDefBack::load element tagName() : %s",
502 // element->tagName().latin1() ); 505 // element->tagName().latin1() );
503 QString dummy; 506 QString dummy;
504 foundAction = false; 507 foundAction = false;
505 508
506 XMLElement::AttributeMap aMap = element->attributes(); 509 XMLElement::AttributeMap aMap = element->attributes();
507 XMLElement::AttributeMap::Iterator it; 510 XMLElement::AttributeMap::Iterator it;
508 contactMap.clear(); 511 contactMap.clear();
509 customMap.clear(); 512 customMap.clear();
510 for( it = aMap.begin(); it != aMap.end(); ++it ){ 513 for( it = aMap.begin(); it != aMap.end(); ++it ){
511 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); 514 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
512 515
513 int *find = dict[ it.key() ]; 516 int *find = dict[ it.key() ];
514 /* Unknown attributes will be stored as "Custom" elements */ 517 /* Unknown attributes will be stored as "Custom" elements */
515 if ( !find ) { 518 if ( !find ) {
516 qWarning("Attribute %s not known.", it.key().latin1()); 519 qWarning("Attribute %s not known.", it.key().latin1());
517 //contact.setCustomField(it.key(), it.data()); 520 //contact.setCustomField(it.key(), it.data());
518 customMap.insert( it.key(), it.data() ); 521 customMap.insert( it.key(), it.data() );
519 continue; 522 continue;
520 } 523 }
521 524
522 /* Check if special conversion is needed and add attribute 525 /* Check if special conversion is needed and add attribute
523 * into Contact class 526 * into Contact class
524 */ 527 */
525 switch( *find ) { 528 switch( *find ) {
526 /* 529 /*
527 case Qtopia::AddressUid: 530 case Qtopia::AddressUid:
528 contact.setUid( it.data().toInt() ); 531 contact.setUid( it.data().toInt() );
529 break; 532 break;
530 case Qtopia::AddressCategory: 533 case Qtopia::AddressCategory:
531 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 534 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
532 break; 535 break;
533 */ 536 */
534 case JOURNALACTION: 537 case JOURNALACTION:
535 action = OContact::journal_action(it.data().toInt()); 538 action = OContact::journal_action(it.data().toInt());
536 foundAction = true; 539 foundAction = true;
537 qWarning ("ODefBack(journal)::ACTION found: %d", action); 540 qWarning ("ODefBack(journal)::ACTION found: %d", action);
538 break; 541 break;
539 case JOURNALROW: 542 case JOURNALROW:
540 journalKey = it.data().toInt(); 543 journalKey = it.data().toInt();
541 break; 544 break;
542 default: // no conversion needed add them to the map 545 default: // no conversion needed add them to the map
543 contactMap.insert( *find, it.data() ); 546 contactMap.insert( *find, it.data() );
544 break; 547 break;
545 } 548 }
546 } 549 }
547 /* now generate the Contact contact */ 550 /* now generate the Contact contact */
548 OContact contact( contactMap ); 551 OContact contact( contactMap );
549 552
550 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { 553 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
551 contact.setCustomField( customIt.key(), customIt.data() ); 554 contact.setCustomField( customIt.key(), customIt.data() );
552 } 555 }
553 556
554 if (foundAction){ 557 if (foundAction){
555 foundAction = false; 558 foundAction = false;
556 switch ( action ) { 559 switch ( action ) {
557 case OContact::ACTION_ADD: 560 case OContact::ACTION_ADD:
558 addContact_p (contact); 561 addContact_p (contact);
559 break; 562 break;
560 case OContact::ACTION_REMOVE: 563 case OContact::ACTION_REMOVE:
561 if ( !remove (contact.uid()) ) 564 if ( !remove (contact.uid()) )
562 qWarning ("ODefBack(journal)::Unable to remove uid: %d", 565 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
563 contact.uid() ); 566 contact.uid() );
564 break; 567 break;
565 case OContact::ACTION_REPLACE: 568 case OContact::ACTION_REPLACE:
566 if ( !replace ( contact ) ) 569 if ( !replace ( contact ) )
567 qWarning ("ODefBack(journal)::Unable to replace uid: %d", 570 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
568 contact.uid() ); 571 contact.uid() );
569 break; 572 break;
570 default: 573 default:
571 qWarning ("Unknown action: ignored !"); 574 qWarning ("Unknown action: ignored !");
572 break; 575 break;
573 } 576 }
574 }else{ 577 }else{
575 /* Add contact to list */ 578 /* Add contact to list */
576 addContact_p (contact); 579 addContact_p (contact);
577 } 580 }
578 581
579 /* Move to next element */ 582 /* Move to next element */
580 element = element->nextChild(); 583 element = element->nextChild();
581 } 584 }
582 }else { 585 }else {
583 qWarning("ODefBack::could not load"); 586 qWarning("ODefBack::could not load");
584 } 587 }
585 delete root; 588 delete root;
586 qWarning("returning from loading" ); 589 qWarning("returning from loading" );
587 return true; 590 return true;
588 } 591 }
589 592
590 593
591 void updateJournal( const OContact& cnt, 594 void updateJournal( const OContact& cnt,
592 OContact::journal_action action ) { 595 OContact::journal_action action ) {
593 QFile f( m_journalName ); 596 QFile f( m_journalName );
594 bool created = !f.exists(); 597 bool created = !f.exists();
595 if ( !f.open(IO_WriteOnly|IO_Append) ) 598 if ( !f.open(IO_WriteOnly|IO_Append) )
596 return; 599 return;
597 600
598 QString buf; 601 QString buf;
599 QCString str; 602 QCString str;
600 603
601 // if the file was created, we have to set the Tag "<CONTACTS>" to 604 // if the file was created, we have to set the Tag "<CONTACTS>" to
602 // get a XML-File which is readable by our parser. 605 // get a XML-File which is readable by our parser.
603 // This is just a cheat, but better than rewrite the parser. 606 // This is just a cheat, but better than rewrite the parser.
604 if ( created ){ 607 if ( created ){
605 buf = "<Contacts>"; 608 buf = "<Contacts>";
606 QCString cstr = buf.utf8(); 609 QCString cstr = buf.utf8();
607 f.writeBlock( cstr.data(), cstr.length() ); 610 f.writeBlock( cstr.data(), cstr.length() );
608 } 611 }
609 612
610 buf = "<Contact "; 613 buf = "<Contact ";
611 cnt.save( buf ); 614 cnt.save( buf );
612 buf += " action=\"" + QString::number( (int)action ) + "\" "; 615 buf += " action=\"" + QString::number( (int)action ) + "\" ";
613 buf += "/>\n"; 616 buf += "/>\n";
614 QCString cstr = buf.utf8(); 617 QCString cstr = buf.utf8();
615 f.writeBlock( cstr.data(), cstr.length() ); 618 f.writeBlock( cstr.data(), cstr.length() );
616 } 619 }
617 620
618 void removeJournal() 621 void removeJournal()
619 { 622 {
620 QFile f ( m_journalName ); 623 QFile f ( m_journalName );
621 if ( f.exists() ) 624 if ( f.exists() )
622 f.remove(); 625 f.remove();
623 } 626 }
624 627
625 protected: 628 protected:
626 bool m_changed; 629 bool m_changed;
627 QString m_journalName; 630 QString m_journalName;
628 QString m_fileName; 631 QString m_fileName;
629 QString m_appName; 632 QString m_appName;
630 QValueList<OContact> m_contactList; 633 QValueList<OContact> m_contactList;
631 QDateTime m_readtime; 634 QDateTime m_readtime;
632}; 635};
633 636
634#endif 637#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
index 8b95102..adc8dc3 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
@@ -1,634 +1,637 @@
1/* 1/*
2 * XML Backend for the OPIE-Contact Database. 2 * XML Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
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.7 2002/11/13 15:02:46 eilers
21 * Small Bug in sorted fixed
22 *
20 * Revision 1.6 2002/11/13 14:14:51 eilers 23 * Revision 1.6 2002/11/13 14:14:51 eilers
21 * Added sorted for Contacts.. 24 * Added sorted for Contacts..
22 * 25 *
23 * Revision 1.5 2002/11/01 15:10:42 eilers 26 * Revision 1.5 2002/11/01 15:10:42 eilers
24 * Added regExp-search in database for all fields in a contact. 27 * Added regExp-search in database for all fields in a contact.
25 * 28 *
26 * Revision 1.4 2002/10/16 10:52:40 eilers 29 * Revision 1.4 2002/10/16 10:52:40 eilers
27 * Added some docu to the interface and now using the cache infrastucture by zecke.. :) 30 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
28 * 31 *
29 * Revision 1.3 2002/10/14 16:21:54 eilers 32 * Revision 1.3 2002/10/14 16:21:54 eilers
30 * Some minor interface updates 33 * Some minor interface updates
31 * 34 *
32 * Revision 1.2 2002/10/07 17:34:24 eilers 35 * Revision 1.2 2002/10/07 17:34:24 eilers
33 * added OBackendFactory for advanced backend access 36 * added OBackendFactory for advanced backend access
34 * 37 *
35 * Revision 1.1 2002/09/27 17:11:44 eilers 38 * Revision 1.1 2002/09/27 17:11:44 eilers
36 * Added API for accessing the Contact-Database ! It is compiling, but 39 * Added API for accessing the Contact-Database ! It is compiling, but
37 * please do not expect that anything is working ! 40 * please do not expect that anything is working !
38 * I will debug that stuff in the next time .. 41 * I will debug that stuff in the next time ..
39 * Please read README_COMPILE for compiling ! 42 * Please read README_COMPILE for compiling !
40 * 43 *
41 * 44 *
42 */ 45 */
43 46
44#ifndef _OContactAccessBackend_XML_ 47#ifndef _OContactAccessBackend_XML_
45#define _OContactAccessBackend_XML_ 48#define _OContactAccessBackend_XML_
46 49
47#include <qasciidict.h> 50#include <qasciidict.h>
48#include <qdatetime.h> 51#include <qdatetime.h>
49#include <qfile.h> 52#include <qfile.h>
50#include <qfileinfo.h> 53#include <qfileinfo.h>
51#include <qregexp.h> 54#include <qregexp.h>
52#include <qarray.h> 55#include <qarray.h>
53#include <qmap.h> 56#include <qmap.h>
54 57
55#include <qpe/global.h> 58#include <qpe/global.h>
56 59
57#include <opie/xmltree.h> 60#include <opie/xmltree.h>
58#include "ocontactaccessbackend.h" 61#include "ocontactaccessbackend.h"
59#include "ocontactaccess.h" 62#include "ocontactaccess.h"
60 63
61#include <stdlib.h> 64#include <stdlib.h>
62#include <errno.h> 65#include <errno.h>
63 66
64using namespace Opie; 67using namespace Opie;
65 68
66/* the default xml implementation */ 69/* the default xml implementation */
67class OContactAccessBackend_XML : public OContactAccessBackend { 70class OContactAccessBackend_XML : public OContactAccessBackend {
68 public: 71 public:
69 OContactAccessBackend_XML ( QString appname, QString filename = 0l ): 72 OContactAccessBackend_XML ( QString appname, QString filename = 0l ):
70 m_changed( false ) 73 m_changed( false )
71 { 74 {
72 m_appName = appname; 75 m_appName = appname;
73 76
74 /* Set journalfile name ... */ 77 /* Set journalfile name ... */
75 m_journalName = getenv("HOME"); 78 m_journalName = getenv("HOME");
76 m_journalName +="/.abjournal" + appname; 79 m_journalName +="/.abjournal" + appname;
77 80
78 /* Expecting to access the default filename if nothing else is set */ 81 /* Expecting to access the default filename if nothing else is set */
79 if ( filename.isEmpty() ){ 82 if ( filename.isEmpty() ){
80 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 83 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
81 } else 84 } else
82 m_fileName = filename; 85 m_fileName = filename;
83 86
84 /* Load Database now */ 87 /* Load Database now */
85 load (); 88 load ();
86 } 89 }
87 90
88 bool save() { 91 bool save() {
89 92
90 if ( !m_changed ) 93 if ( !m_changed )
91 return true; 94 return true;
92 95
93 QString strNewFile = m_fileName + ".new"; 96 QString strNewFile = m_fileName + ".new";
94 QFile f( strNewFile ); 97 QFile f( strNewFile );
95 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 98 if ( !f.open( IO_WriteOnly|IO_Raw ) )
96 return false; 99 return false;
97 100
98 int total_written; 101 int total_written;
99 QString out; 102 QString out;
100 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 103 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
101 " <Groups>\n" 104 " <Groups>\n"
102 " </Groups>\n" 105 " </Groups>\n"
103 " <Contacts>\n"; 106 " <Contacts>\n";
104 //QValueList<Contact>::iterator it; 107 //QValueList<Contact>::iterator it;
105 QValueListConstIterator<OContact> it; 108 QValueListConstIterator<OContact> it;
106 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 109 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
107 out += "<Contact "; 110 out += "<Contact ";
108 (*it).save( out ); 111 (*it).save( out );
109 out += "/>\n"; 112 out += "/>\n";
110 QCString cstr = out.utf8(); 113 QCString cstr = out.utf8();
111 total_written = f.writeBlock( cstr.data(), cstr.length() ); 114 total_written = f.writeBlock( cstr.data(), cstr.length() );
112 if ( total_written != int(cstr.length()) ) { 115 if ( total_written != int(cstr.length()) ) {
113 f.close(); 116 f.close();
114 QFile::remove( strNewFile ); 117 QFile::remove( strNewFile );
115 return false; 118 return false;
116 } 119 }
117 out = ""; 120 out = "";
118 } 121 }
119 out += " </Contacts>\n</AddressBook>\n"; 122 out += " </Contacts>\n</AddressBook>\n";
120 123
121 QCString cstr = out.utf8(); 124 QCString cstr = out.utf8();
122 total_written = f.writeBlock( cstr.data(), cstr.length() ); 125 total_written = f.writeBlock( cstr.data(), cstr.length() );
123 if ( total_written != int( cstr.length() ) ) { 126 if ( total_written != int( cstr.length() ) ) {
124 f.close(); 127 f.close();
125 QFile::remove( strNewFile ); 128 QFile::remove( strNewFile );
126 return false; 129 return false;
127 } 130 }
128 f.close(); 131 f.close();
129 132
130 // move the file over, I'm just going to use the system call 133 // move the file over, I'm just going to use the system call
131 // because, I don't feel like using QDir. 134 // because, I don't feel like using QDir.
132 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 135 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
133 qWarning( "problem renaming file %s to %s, errno: %d", 136 qWarning( "problem renaming file %s to %s, errno: %d",
134 strNewFile.latin1(), m_journalName.latin1(), errno ); 137 strNewFile.latin1(), m_journalName.latin1(), errno );
135 // remove the tmp file... 138 // remove the tmp file...
136 QFile::remove( strNewFile ); 139 QFile::remove( strNewFile );
137 } 140 }
138 141
139 /* The journalfile should be removed now... */ 142 /* The journalfile should be removed now... */
140 removeJournal(); 143 removeJournal();
141 144
142 m_changed = false; 145 m_changed = false;
143 return true; 146 return true;
144 } 147 }
145 148
146 bool load () { 149 bool load () {
147 m_contactList.clear(); 150 m_contactList.clear();
148 151
149 /* Load XML-File and journal if it exists */ 152 /* Load XML-File and journal if it exists */
150 if ( !load ( m_fileName, false ) ) 153 if ( !load ( m_fileName, false ) )
151 return false; 154 return false;
152 /* The returncode of the journalfile is ignored due to the 155 /* The returncode of the journalfile is ignored due to the
153 * fact that it does not exist when this class is instantiated ! 156 * fact that it does not exist when this class is instantiated !
154 * But there may such a file exist, if the application crashed. 157 * But there may such a file exist, if the application crashed.
155 * Therefore we try to load it to get the changes before the # 158 * Therefore we try to load it to get the changes before the #
156 * crash happened... 159 * crash happened...
157 */ 160 */
158 load (m_journalName, true); 161 load (m_journalName, true);
159 162
160 return true; 163 return true;
161 } 164 }
162 165
163 void clear () { 166 void clear () {
164 m_contactList.clear(); 167 m_contactList.clear();
165 m_changed = false; 168 m_changed = false;
166 169
167 } 170 }
168 171
169 bool wasChangedExternally() 172 bool wasChangedExternally()
170 { 173 {
171 QFileInfo fi( m_fileName ); 174 QFileInfo fi( m_fileName );
172 175
173 QDateTime lastmod = fi.lastModified (); 176 QDateTime lastmod = fi.lastModified ();
174 177
175 return (lastmod != m_readtime); 178 return (lastmod != m_readtime);
176 } 179 }
177 180
178 QArray<int> allRecords() const { 181 QArray<int> allRecords() const {
179 QArray<int> uid_list( m_contactList.count() ); 182 QArray<int> uid_list( m_contactList.count() );
180 183
181 uint counter = 0; 184 uint counter = 0;
182 QValueListConstIterator<OContact> it; 185 QValueListConstIterator<OContact> it;
183 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 186 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
184 uid_list[counter++] = (*it).uid(); 187 uid_list[counter++] = (*it).uid();
185 } 188 }
186 189
187 return ( uid_list ); 190 return ( uid_list );
188 } 191 }
189 192
190 OContact find ( int uid ) const 193 OContact find ( int uid ) const
191 { 194 {
192 bool found = false; 195 bool found = false;
193 OContact foundContact; //Create empty contact 196 OContact foundContact; //Create empty contact
194 197
195 QValueListConstIterator<OContact> it; 198 QValueListConstIterator<OContact> it;
196 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 199 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
197 if ((*it).uid() == uid){ 200 if ((*it).uid() == uid){
198 found = true; 201 found = true;
199 break; 202 break;
200 } 203 }
201 } 204 }
202 if ( found ){ 205 if ( found ){
203 foundContact = *it; 206 foundContact = *it;
204 } 207 }
205 208
206 return ( foundContact ); 209 return ( foundContact );
207 } 210 }
208 211
209 QArray<int> queryByExample ( const OContact &query, int settings ){ 212 QArray<int> queryByExample ( const OContact &query, int settings ){
210 213
211 QArray<int> m_currentQuery( m_contactList.count() ); 214 QArray<int> m_currentQuery( m_contactList.count() );
212 QValueListConstIterator<OContact> it; 215 QValueListConstIterator<OContact> it;
213 uint arraycounter = 0; 216 uint arraycounter = 0;
214 217
215 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 218 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
216 /* Search all fields and compare them with query object. Store them into list 219 /* Search all fields and compare them with query object. Store them into list
217 * if all fields matches. 220 * if all fields matches.
218 */ 221 */
219 bool allcorrect = true; 222 bool allcorrect = true;
220 for ( int i = 0; i < Qtopia::rid; i++ ) { 223 for ( int i = 0; i < Qtopia::rid; i++ ) {
221 /* Just compare fields which are not empty in the query object */ 224 /* Just compare fields which are not empty in the query object */
222 if ( !query.field(i).isEmpty() ){ 225 if ( !query.field(i).isEmpty() ){
223 switch ( settings & ~OContactAccess::IgnoreCase ){ 226 switch ( settings & ~OContactAccess::IgnoreCase ){
224 case OContactAccess::RegExp:{ 227 case OContactAccess::RegExp:{
225 QRegExp expr ( query.field(i), 228 QRegExp expr ( query.field(i),
226 !(settings & OContactAccess::IgnoreCase), 229 !(settings & OContactAccess::IgnoreCase),
227 false ); 230 false );
228 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 231 if ( expr.find ( (*it).field(i), 0 ) == -1 )
229 allcorrect = false; 232 allcorrect = false;
230 } 233 }
231 break; 234 break;
232 case OContactAccess::WildCards:{ 235 case OContactAccess::WildCards:{
233 QRegExp expr ( query.field(i), 236 QRegExp expr ( query.field(i),
234 !(settings & OContactAccess::IgnoreCase), 237 !(settings & OContactAccess::IgnoreCase),
235 true ); 238 true );
236 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 239 if ( expr.find ( (*it).field(i), 0 ) == -1 )
237 allcorrect = false; 240 allcorrect = false;
238 } 241 }
239 break; 242 break;
240 case OContactAccess::ExactMatch:{ 243 case OContactAccess::ExactMatch:{
241 if (settings & OContactAccess::IgnoreCase){ 244 if (settings & OContactAccess::IgnoreCase){
242 if ( query.field(i).upper() != 245 if ( query.field(i).upper() !=
243 (*it).field(i).upper() ) 246 (*it).field(i).upper() )
244 allcorrect = false; 247 allcorrect = false;
245 }else{ 248 }else{
246 if ( query.field(i) != (*it).field(i) ) 249 if ( query.field(i) != (*it).field(i) )
247 allcorrect = false; 250 allcorrect = false;
248 } 251 }
249 } 252 }
250 break; 253 break;
251 } 254 }
252 } 255 }
253 } 256 }
254 if ( allcorrect ){ 257 if ( allcorrect ){
255 m_currentQuery[arraycounter++] = (*it).uid(); 258 m_currentQuery[arraycounter++] = (*it).uid();
256 } 259 }
257 } 260 }
258 261
259 // Shrink to fit.. 262 // Shrink to fit..
260 m_currentQuery.resize(arraycounter); 263 m_currentQuery.resize(arraycounter);
261 264
262 return m_currentQuery; 265 return m_currentQuery;
263 } 266 }
264 267
265 QArray<int> matchRegexp( const QRegExp &r ) const{ 268 QArray<int> matchRegexp( const QRegExp &r ) const{
266 QArray<int> m_currentQuery( m_contactList.count() ); 269 QArray<int> m_currentQuery( m_contactList.count() );
267 QValueListConstIterator<OContact> it; 270 QValueListConstIterator<OContact> it;
268 uint arraycounter = 0; 271 uint arraycounter = 0;
269 272
270 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 273 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
271 if ( (*it).match( r ) ){ 274 if ( (*it).match( r ) ){
272 m_currentQuery[arraycounter++] = (*it).uid(); 275 m_currentQuery[arraycounter++] = (*it).uid();
273 } 276 }
274 277
275 } 278 }
276 // Shrink to fit.. 279 // Shrink to fit..
277 m_currentQuery.resize(arraycounter); 280 m_currentQuery.resize(arraycounter);
278 281
279 return m_currentQuery; 282 return m_currentQuery;
280 } 283 }
281 284
282 const uint querySettings() 285 const uint querySettings()
283 { 286 {
284 return ( OContactAccess::WildCards 287 return ( OContactAccess::WildCards
285 & OContactAccess::IgnoreCase 288 & OContactAccess::IgnoreCase
286 & OContactAccess::RegExp 289 & OContactAccess::RegExp
287 & OContactAccess::ExactMatch ); 290 & OContactAccess::ExactMatch );
288 } 291 }
289 292
290 bool hasQuerySettings (uint querySettings) const 293 bool hasQuerySettings (uint querySettings) const
291 { 294 {
292 /* OContactAccess::IgnoreCase may be added with one 295 /* OContactAccess::IgnoreCase may be added with one
293 * of the other settings, but never used alone. 296 * of the other settings, but never used alone.
294 * The other settings are just valid alone... 297 * The other settings are just valid alone...
295 */ 298 */
296 switch ( querySettings & ~OContactAccess::IgnoreCase ){ 299 switch ( querySettings & ~OContactAccess::IgnoreCase ){
297 case OContactAccess::RegExp: 300 case OContactAccess::RegExp:
298 return ( true ); 301 return ( true );
299 case OContactAccess::WildCards: 302 case OContactAccess::WildCards:
300 return ( true ); 303 return ( true );
301 case OContactAccess::ExactMatch: 304 case OContactAccess::ExactMatch:
302 return ( true ); 305 return ( true );
303 default: 306 default:
304 return ( false ); 307 return ( false );
305 } 308 }
306 } 309 }
307 310
308 // Currently only asc implemented.. 311 // Currently only asc implemented..
309 QArray<int> sorted( bool asc, int , int , int ) 312 QArray<int> sorted( bool asc, int , int , int )
310 { 313 {
311 QMap<QString, int> nameToUid; 314 QMap<QString, int> nameToUid;
312 QStringList names; 315 QStringList names;
313 QArray<int> m_currentQuery( m_contactList.count() ); 316 QArray<int> m_currentQuery( m_contactList.count() );
314 317
315 // First fill map and StringList with all Names ( better LastNames ? ) 318 // First fill map and StringList with all Names
316 // Afterwards sort namelist and use map to fill array to return.. 319 // Afterwards sort namelist and use map to fill array to return..
317 QValueListConstIterator<OContact> it; 320 QValueListConstIterator<OContact> it;
318 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 321 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
319 names.append( (*it).lastName() ); 322 names.append( (*it).fileAs() );
320 nameToUid.insert( (*it).lastName(), (*it).uid() ); 323 nameToUid.insert( (*it).fileAs(), (*it).uid() );
321 } 324 }
322 names.sort(); 325 names.sort();
323 326
324 int i = 0; 327 int i = 0;
325 if ( asc ){ 328 if ( asc ){
326 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) 329 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
327 m_currentQuery[i++] = nameToUid[ (*it) ]; 330 m_currentQuery[i++] = nameToUid[ (*it) ];
328 }else{ 331 }else{
329 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it ) 332 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
330 m_currentQuery[i++] = nameToUid[ (*it) ]; 333 m_currentQuery[i++] = nameToUid[ (*it) ];
331 } 334 }
332 335
333 return m_currentQuery; 336 return m_currentQuery;
334 337
335 } 338 }
336 bool add ( const OContact &newcontact ) 339 bool add ( const OContact &newcontact )
337 { 340 {
338 //qWarning("odefaultbackend: ACTION::ADD"); 341 //qWarning("odefaultbackend: ACTION::ADD");
339 updateJournal (newcontact, OContact::ACTION_ADD); 342 updateJournal (newcontact, OContact::ACTION_ADD);
340 addContact_p( newcontact ); 343 addContact_p( newcontact );
341 344
342 m_changed = true; 345 m_changed = true;
343 346
344 return true; 347 return true;
345 } 348 }
346 349
347 bool replace ( const OContact &contact ) 350 bool replace ( const OContact &contact )
348 { 351 {
349 m_changed = true; 352 m_changed = true;
350 353
351 bool found = false; 354 bool found = false;
352 355
353 QValueListIterator<OContact> it; 356 QValueListIterator<OContact> it;
354 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 357 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
355 if ( (*it).uid() == contact.uid() ){ 358 if ( (*it).uid() == contact.uid() ){
356 found = true; 359 found = true;
357 break; 360 break;
358 } 361 }
359 } 362 }
360 if (found) { 363 if (found) {
361 updateJournal (contact, OContact::ACTION_REPLACE); 364 updateJournal (contact, OContact::ACTION_REPLACE);
362 m_contactList.remove (it); 365 m_contactList.remove (it);
363 m_contactList.append (contact); 366 m_contactList.append (contact);
364 return true; 367 return true;
365 } else 368 } else
366 return false; 369 return false;
367 } 370 }
368 371
369 bool remove ( int uid ) 372 bool remove ( int uid )
370 { 373 {
371 m_changed = true; 374 m_changed = true;
372 375
373 bool found = false; 376 bool found = false;
374 QValueListIterator<OContact> it; 377 QValueListIterator<OContact> it;
375 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 378 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
376 if ((*it).uid() == uid){ 379 if ((*it).uid() == uid){
377 found = true; 380 found = true;
378 break; 381 break;
379 } 382 }
380 } 383 }
381 if (found) { 384 if (found) {
382 updateJournal ( *it, OContact::ACTION_REMOVE); 385 updateJournal ( *it, OContact::ACTION_REMOVE);
383 m_contactList.remove (it); 386 m_contactList.remove (it);
384 return true; 387 return true;
385 } else 388 } else
386 return false; 389 return false;
387 } 390 }
388 391
389 bool reload(){ 392 bool reload(){
390 /* Reload is the same as load in this implementation */ 393 /* Reload is the same as load in this implementation */
391 return ( load() ); 394 return ( load() );
392 } 395 }
393 396
394 private: 397 private:
395 void addContact_p( const OContact &newcontact ){ 398 void addContact_p( const OContact &newcontact ){
396 m_contactList.append (newcontact); 399 m_contactList.append (newcontact);
397 } 400 }
398 401
399 /* This function loads the xml-database and the journalfile */ 402 /* This function loads the xml-database and the journalfile */
400 bool load( const QString filename, bool isJournal ) { 403 bool load( const QString filename, bool isJournal ) {
401 404
402 /* We use the time of the last read to check if the file was 405 /* We use the time of the last read to check if the file was
403 * changed externally. 406 * changed externally.
404 */ 407 */
405 if ( !isJournal ){ 408 if ( !isJournal ){
406 QFileInfo fi( filename ); 409 QFileInfo fi( filename );
407 m_readtime = fi.lastModified (); 410 m_readtime = fi.lastModified ();
408 } 411 }
409 412
410 const int JOURNALACTION = Qtopia::Notes + 1; 413 const int JOURNALACTION = Qtopia::Notes + 1;
411 const int JOURNALROW = JOURNALACTION + 1; 414 const int JOURNALROW = JOURNALACTION + 1;
412 415
413 bool foundAction = false; 416 bool foundAction = false;
414 OContact::journal_action action = OContact::ACTION_ADD; 417 OContact::journal_action action = OContact::ACTION_ADD;
415 int journalKey = 0; 418 int journalKey = 0;
416 QMap<int, QString> contactMap; 419 QMap<int, QString> contactMap;
417 QMap<QString, QString> customMap; 420 QMap<QString, QString> customMap;
418 QMap<QString, QString>::Iterator customIt; 421 QMap<QString, QString>::Iterator customIt;
419 QAsciiDict<int> dict( 47 ); 422 QAsciiDict<int> dict( 47 );
420 423
421 dict.setAutoDelete( TRUE ); 424 dict.setAutoDelete( TRUE );
422 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 425 dict.insert( "Uid", new int(Qtopia::AddressUid) );
423 dict.insert( "Title", new int(Qtopia::Title) ); 426 dict.insert( "Title", new int(Qtopia::Title) );
424 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 427 dict.insert( "FirstName", new int(Qtopia::FirstName) );
425 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 428 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
426 dict.insert( "LastName", new int(Qtopia::LastName) ); 429 dict.insert( "LastName", new int(Qtopia::LastName) );
427 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 430 dict.insert( "Suffix", new int(Qtopia::Suffix) );
428 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 431 dict.insert( "FileAs", new int(Qtopia::FileAs) );
429 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 432 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
430 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 433 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
431 dict.insert( "Emails", new int(Qtopia::Emails) ); 434 dict.insert( "Emails", new int(Qtopia::Emails) );
432 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 435 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
433 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 436 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
434 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 437 dict.insert( "HomeState", new int(Qtopia::HomeState) );
435 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 438 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
436 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 439 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
437 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 440 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
438 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 441 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
439 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 442 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
440 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 443 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
441 dict.insert( "Company", new int(Qtopia::Company) ); 444 dict.insert( "Company", new int(Qtopia::Company) );
442 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 445 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
443 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 446 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
444 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 447 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
445 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 448 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
446 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 449 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
447 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 450 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
448 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 451 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
449 dict.insert( "Department", new int(Qtopia::Department) ); 452 dict.insert( "Department", new int(Qtopia::Department) );
450 dict.insert( "Office", new int(Qtopia::Office) ); 453 dict.insert( "Office", new int(Qtopia::Office) );
451 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 454 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
452 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 455 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
453 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 456 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
454 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 457 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
455 dict.insert( "Profession", new int(Qtopia::Profession) ); 458 dict.insert( "Profession", new int(Qtopia::Profession) );
456 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 459 dict.insert( "Assistant", new int(Qtopia::Assistant) );
457 dict.insert( "Manager", new int(Qtopia::Manager) ); 460 dict.insert( "Manager", new int(Qtopia::Manager) );
458 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 461 dict.insert( "Spouse", new int(Qtopia::Spouse) );
459 dict.insert( "Children", new int(Qtopia::Children) ); 462 dict.insert( "Children", new int(Qtopia::Children) );
460 dict.insert( "Gender", new int(Qtopia::Gender) ); 463 dict.insert( "Gender", new int(Qtopia::Gender) );
461 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 464 dict.insert( "Birthday", new int(Qtopia::Birthday) );
462 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 465 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
463 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 466 dict.insert( "Nickname", new int(Qtopia::Nickname) );
464 dict.insert( "Notes", new int(Qtopia::Notes) ); 467 dict.insert( "Notes", new int(Qtopia::Notes) );
465 dict.insert( "action", new int(JOURNALACTION) ); 468 dict.insert( "action", new int(JOURNALACTION) );
466 dict.insert( "actionrow", new int(JOURNALROW) ); 469 dict.insert( "actionrow", new int(JOURNALROW) );
467 470
468 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() ); 471 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
469 472
470 XMLElement *root = XMLElement::load( filename ); 473 XMLElement *root = XMLElement::load( filename );
471 if(root != 0l ){ // start parsing 474 if(root != 0l ){ // start parsing
472 /* Parse all XML-Elements and put the data into the 475 /* Parse all XML-Elements and put the data into the
473 * Contact-Class 476 * Contact-Class
474 */ 477 */
475 XMLElement *element = root->firstChild(); 478 XMLElement *element = root->firstChild();
476 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() ); 479 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
477 element = element->firstChild(); 480 element = element->firstChild();
478 481
479 /* Search Tag "Contacts" which is the parent of all Contacts */ 482 /* Search Tag "Contacts" which is the parent of all Contacts */
480 while( element && !isJournal ){ 483 while( element && !isJournal ){
481 if( element->tagName() != QString::fromLatin1("Contacts") ){ 484 if( element->tagName() != QString::fromLatin1("Contacts") ){
482 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s", 485 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
483 // element->tagName().latin1()); 486 // element->tagName().latin1());
484 element = element->nextChild(); 487 element = element->nextChild();
485 } else { 488 } else {
486 element = element->firstChild(); 489 element = element->firstChild();
487 break; 490 break;
488 } 491 }
489 } 492 }
490 /* Parse all Contacts and ignore unknown tags */ 493 /* Parse all Contacts and ignore unknown tags */
491 while( element ){ 494 while( element ){
492 if( element->tagName() != QString::fromLatin1("Contact") ){ 495 if( element->tagName() != QString::fromLatin1("Contact") ){
493 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s", 496 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
494 // element->tagName().latin1()); 497 // element->tagName().latin1());
495 element = element->nextChild(); 498 element = element->nextChild();
496 continue; 499 continue;
497 } 500 }
498 /* Found alement with tagname "contact", now parse and store all 501 /* Found alement with tagname "contact", now parse and store all
499 * attributes contained 502 * attributes contained
500 */ 503 */
501 //qWarning("OContactDefBack::load element tagName() : %s", 504 //qWarning("OContactDefBack::load element tagName() : %s",
502 // element->tagName().latin1() ); 505 // element->tagName().latin1() );
503 QString dummy; 506 QString dummy;
504 foundAction = false; 507 foundAction = false;
505 508
506 XMLElement::AttributeMap aMap = element->attributes(); 509 XMLElement::AttributeMap aMap = element->attributes();
507 XMLElement::AttributeMap::Iterator it; 510 XMLElement::AttributeMap::Iterator it;
508 contactMap.clear(); 511 contactMap.clear();
509 customMap.clear(); 512 customMap.clear();
510 for( it = aMap.begin(); it != aMap.end(); ++it ){ 513 for( it = aMap.begin(); it != aMap.end(); ++it ){
511 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1()); 514 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
512 515
513 int *find = dict[ it.key() ]; 516 int *find = dict[ it.key() ];
514 /* Unknown attributes will be stored as "Custom" elements */ 517 /* Unknown attributes will be stored as "Custom" elements */
515 if ( !find ) { 518 if ( !find ) {
516 qWarning("Attribute %s not known.", it.key().latin1()); 519 qWarning("Attribute %s not known.", it.key().latin1());
517 //contact.setCustomField(it.key(), it.data()); 520 //contact.setCustomField(it.key(), it.data());
518 customMap.insert( it.key(), it.data() ); 521 customMap.insert( it.key(), it.data() );
519 continue; 522 continue;
520 } 523 }
521 524
522 /* Check if special conversion is needed and add attribute 525 /* Check if special conversion is needed and add attribute
523 * into Contact class 526 * into Contact class
524 */ 527 */
525 switch( *find ) { 528 switch( *find ) {
526 /* 529 /*
527 case Qtopia::AddressUid: 530 case Qtopia::AddressUid:
528 contact.setUid( it.data().toInt() ); 531 contact.setUid( it.data().toInt() );
529 break; 532 break;
530 case Qtopia::AddressCategory: 533 case Qtopia::AddressCategory:
531 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 534 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
532 break; 535 break;
533 */ 536 */
534 case JOURNALACTION: 537 case JOURNALACTION:
535 action = OContact::journal_action(it.data().toInt()); 538 action = OContact::journal_action(it.data().toInt());
536 foundAction = true; 539 foundAction = true;
537 qWarning ("ODefBack(journal)::ACTION found: %d", action); 540 qWarning ("ODefBack(journal)::ACTION found: %d", action);
538 break; 541 break;
539 case JOURNALROW: 542 case JOURNALROW:
540 journalKey = it.data().toInt(); 543 journalKey = it.data().toInt();
541 break; 544 break;
542 default: // no conversion needed add them to the map 545 default: // no conversion needed add them to the map
543 contactMap.insert( *find, it.data() ); 546 contactMap.insert( *find, it.data() );
544 break; 547 break;
545 } 548 }
546 } 549 }
547 /* now generate the Contact contact */ 550 /* now generate the Contact contact */
548 OContact contact( contactMap ); 551 OContact contact( contactMap );
549 552
550 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) { 553 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
551 contact.setCustomField( customIt.key(), customIt.data() ); 554 contact.setCustomField( customIt.key(), customIt.data() );
552 } 555 }
553 556
554 if (foundAction){ 557 if (foundAction){
555 foundAction = false; 558 foundAction = false;
556 switch ( action ) { 559 switch ( action ) {
557 case OContact::ACTION_ADD: 560 case OContact::ACTION_ADD:
558 addContact_p (contact); 561 addContact_p (contact);
559 break; 562 break;
560 case OContact::ACTION_REMOVE: 563 case OContact::ACTION_REMOVE:
561 if ( !remove (contact.uid()) ) 564 if ( !remove (contact.uid()) )
562 qWarning ("ODefBack(journal)::Unable to remove uid: %d", 565 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
563 contact.uid() ); 566 contact.uid() );
564 break; 567 break;
565 case OContact::ACTION_REPLACE: 568 case OContact::ACTION_REPLACE:
566 if ( !replace ( contact ) ) 569 if ( !replace ( contact ) )
567 qWarning ("ODefBack(journal)::Unable to replace uid: %d", 570 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
568 contact.uid() ); 571 contact.uid() );
569 break; 572 break;
570 default: 573 default:
571 qWarning ("Unknown action: ignored !"); 574 qWarning ("Unknown action: ignored !");
572 break; 575 break;
573 } 576 }
574 }else{ 577 }else{
575 /* Add contact to list */ 578 /* Add contact to list */
576 addContact_p (contact); 579 addContact_p (contact);
577 } 580 }
578 581
579 /* Move to next element */ 582 /* Move to next element */
580 element = element->nextChild(); 583 element = element->nextChild();
581 } 584 }
582 }else { 585 }else {
583 qWarning("ODefBack::could not load"); 586 qWarning("ODefBack::could not load");
584 } 587 }
585 delete root; 588 delete root;
586 qWarning("returning from loading" ); 589 qWarning("returning from loading" );
587 return true; 590 return true;
588 } 591 }
589 592
590 593
591 void updateJournal( const OContact& cnt, 594 void updateJournal( const OContact& cnt,
592 OContact::journal_action action ) { 595 OContact::journal_action action ) {
593 QFile f( m_journalName ); 596 QFile f( m_journalName );
594 bool created = !f.exists(); 597 bool created = !f.exists();
595 if ( !f.open(IO_WriteOnly|IO_Append) ) 598 if ( !f.open(IO_WriteOnly|IO_Append) )
596 return; 599 return;
597 600
598 QString buf; 601 QString buf;
599 QCString str; 602 QCString str;
600 603
601 // if the file was created, we have to set the Tag "<CONTACTS>" to 604 // if the file was created, we have to set the Tag "<CONTACTS>" to
602 // get a XML-File which is readable by our parser. 605 // get a XML-File which is readable by our parser.
603 // This is just a cheat, but better than rewrite the parser. 606 // This is just a cheat, but better than rewrite the parser.
604 if ( created ){ 607 if ( created ){
605 buf = "<Contacts>"; 608 buf = "<Contacts>";
606 QCString cstr = buf.utf8(); 609 QCString cstr = buf.utf8();
607 f.writeBlock( cstr.data(), cstr.length() ); 610 f.writeBlock( cstr.data(), cstr.length() );
608 } 611 }
609 612
610 buf = "<Contact "; 613 buf = "<Contact ";
611 cnt.save( buf ); 614 cnt.save( buf );
612 buf += " action=\"" + QString::number( (int)action ) + "\" "; 615 buf += " action=\"" + QString::number( (int)action ) + "\" ";
613 buf += "/>\n"; 616 buf += "/>\n";
614 QCString cstr = buf.utf8(); 617 QCString cstr = buf.utf8();
615 f.writeBlock( cstr.data(), cstr.length() ); 618 f.writeBlock( cstr.data(), cstr.length() );
616 } 619 }
617 620
618 void removeJournal() 621 void removeJournal()
619 { 622 {
620 QFile f ( m_journalName ); 623 QFile f ( m_journalName );
621 if ( f.exists() ) 624 if ( f.exists() )
622 f.remove(); 625 f.remove();
623 } 626 }
624 627
625 protected: 628 protected:
626 bool m_changed; 629 bool m_changed;
627 QString m_journalName; 630 QString m_journalName;
628 QString m_fileName; 631 QString m_fileName;
629 QString m_appName; 632 QString m_appName;
630 QValueList<OContact> m_contactList; 633 QValueList<OContact> m_contactList;
631 QDateTime m_readtime; 634 QDateTime m_readtime;
632}; 635};
633 636
634#endif 637#endif