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