summaryrefslogtreecommitdiff
authoreilers <eilers>2003-03-21 10:33:09 (UTC)
committer eilers <eilers>2003-03-21 10:33:09 (UTC)
commit8136284c38384b169cd2843ee61480d45b6c1cba (patch) (unidiff)
treead798e3df8dc27a41f431a2130dbf50947fbca49
parent6f5f148ff9eac1e4d76bea4460a7984d1e3069b7 (diff)
downloadopie-8136284c38384b169cd2843ee61480d45b6c1cba.zip
opie-8136284c38384b169cd2843ee61480d45b6c1cba.tar.gz
opie-8136284c38384b169cd2843ee61480d45b6c1cba.tar.bz2
Merged speed optimized xml backend for contacts to main.
Added QDateTime to querybyexample. For instance, it is now possible to get all Birthdays/Anniversaries between two dates. This should be used to show all birthdays in the datebook.. This change is sourcecode backward compatible but you have to upgrade the binaries for today-addressbook.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/libopie.pro1
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.cpp10
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.h10
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.cpp166
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h677
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.cpp2
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.h2
-rw-r--r--libopie/pim/opimaccessbackend.h6
-rw-r--r--libopie/pim/opimaccesstemplate.h6
-rw-r--r--libopie/pim/otodoaccesssql.cpp2
-rw-r--r--libopie/pim/otodoaccesssql.h2
-rw-r--r--libopie/pim/otodoaccessvcal.cpp2
-rw-r--r--libopie/pim/otodoaccessvcal.h2
-rw-r--r--libopie/pim/otodoaccessxml.cpp2
-rw-r--r--libopie/pim/otodoaccessxml.h2
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp10
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.h10
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp166
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.h677
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp2
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.h2
-rw-r--r--libopie2/opiepim/backend/opimaccessbackend.h6
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.h2
-rw-r--r--libopie2/opiepim/backend/otodoaccessvcal.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccessvcal.h2
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.h2
-rw-r--r--libopie2/opiepim/core/opimaccesstemplate.h6
29 files changed, 347 insertions, 1436 deletions
diff --git a/libopie/libopie.pro b/libopie/libopie.pro
index 391f30e..2bf9985 100644
--- a/libopie/libopie.pro
+++ b/libopie/libopie.pro
@@ -65,6 +65,7 @@ SOURCES = ofontmenu.cc \
65 pim/ocontact.cpp \ 65 pim/ocontact.cpp \
66 pim/ocontactaccess.cpp \ 66 pim/ocontactaccess.cpp \
67 pim/ocontactaccessbackend_vcard.cpp \ 67 pim/ocontactaccessbackend_vcard.cpp \
68 pim/ocontactaccessbackend_xml.cpp \
68 pim/otodoaccessvcal.cpp \ 69 pim/otodoaccessvcal.cpp \
69 pim/orecur.cpp \ 70 pim/orecur.cpp \
70 pim/opimstate.cpp \ 71 pim/opimstate.cpp \
diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp
index e537269..f24523f 100644
--- a/libopie/pim/ocontactaccessbackend_vcard.cpp
+++ b/libopie/pim/ocontactaccessbackend_vcard.cpp
@@ -17,6 +17,14 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.9 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
20 * Revision 1.8 2003/02/21 16:52:49 zecke 28 * Revision 1.8 2003/02/21 16:52:49 zecke
21 * -Remove old Todo classes they're deprecated and today I already using the 29 * -Remove old Todo classes they're deprecated and today I already using the
22 * new API 30 * new API
@@ -189,7 +197,7 @@ QArray<int> OContactAccessBackend_VCard::allRecords() const
189} 197}
190 198
191// Not implemented 199// Not implemented
192QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int ) 200QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
193{ 201{
194 QArray<int> ar(0); 202 QArray<int> ar(0);
195 return ar; 203 return ar;
diff --git a/libopie/pim/ocontactaccessbackend_vcard.h b/libopie/pim/ocontactaccessbackend_vcard.h
index 236da00..93e2da3 100644
--- a/libopie/pim/ocontactaccessbackend_vcard.h
+++ b/libopie/pim/ocontactaccessbackend_vcard.h
@@ -17,6 +17,14 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.5 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
20 * Revision 1.4 2002/12/07 13:26:22 eilers 28 * Revision 1.4 2002/12/07 13:26:22 eilers
21 * Fixing bug in storing anniversary.. 29 * Fixing bug in storing anniversary..
22 * 30 *
@@ -54,7 +62,7 @@ class OContactAccessBackend_VCard : public OContactAccessBackend {
54 62
55 OContact find ( int uid ) const; 63 OContact find ( int uid ) const;
56 QArray<int> allRecords() const; 64 QArray<int> allRecords() const;
57 QArray<int> queryByExample ( const OContact &query, int settings ); 65 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
58 QArray<int> matchRegexp( const QRegExp &r ) const; 66 QArray<int> matchRegexp( const QRegExp &r ) const;
59 67
60 const uint querySettings(); 68 const uint querySettings();
diff --git a/libopie/pim/ocontactaccessbackend_xml.cpp b/libopie/pim/ocontactaccessbackend_xml.cpp
index 2df6757..4abf4d9 100644
--- a/libopie/pim/ocontactaccessbackend_xml.cpp
+++ b/libopie/pim/ocontactaccessbackend_xml.cpp
@@ -17,6 +17,20 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.2 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
28 * Revision 1.1.2.2 2003/02/11 12:17:28 eilers
29 * Speed optimization. Removed the sequential search loops.
30 *
31 * Revision 1.1.2.1 2003/02/10 15:31:38 eilers
32 * Writing offsets to debug output..
33 *
20 * Revision 1.1 2003/02/09 15:05:01 eilers 34 * Revision 1.1 2003/02/09 15:05:01 eilers
21 * Nothing happened.. Just some cleanup before I will start.. 35 * Nothing happened.. Just some cleanup before I will start..
22 * 36 *
@@ -89,6 +103,11 @@ using namespace Opie;
89OContactAccessBackend_XML::OContactAccessBackend_XML ( QString appname, QString filename = 0l ): 103OContactAccessBackend_XML::OContactAccessBackend_XML ( QString appname, QString filename = 0l ):
90 m_changed( false ) 104 m_changed( false )
91{ 105{
106 // Just m_contactlist should call delete if an entry
107 // is removed.
108 m_contactList.setAutoDelete( true );
109 m_uidToContact.setAutoDelete( false );
110
92 m_appName = appname; 111 m_appName = appname;
93 112
94 /* Set journalfile name ... */ 113 /* Set journalfile name ... */
@@ -117,19 +136,29 @@ bool OContactAccessBackend_XML::save()
117 return false; 136 return false;
118 137
119 int total_written; 138 int total_written;
139 int idx_offset = 0;
120 QString out; 140 QString out;
141
142 // Write Header
121 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 143 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
122 " <Groups>\n" 144 " <Groups>\n"
123 " </Groups>\n" 145 " </Groups>\n"
124 " <Contacts>\n"; 146 " <Contacts>\n";
125 //QValueList<Contact>::iterator it; 147 QCString cstr = out.utf8();
126 QValueListConstIterator<OContact> it; 148 f.writeBlock( cstr.data(), cstr.length() );
127 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 149 idx_offset += cstr.length();
150 out = "";
151
152 // Write all contacts
153 QListIterator<OContact> it( m_contactList );
154 for ( ; it.current(); ++it ) {
155 qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset );
128 out += "<Contact "; 156 out += "<Contact ";
129 (*it).save( out ); 157 (*it)->save( out );
130 out += "/>\n"; 158 out += "/>\n";
131 QCString cstr = out.utf8(); 159 cstr = out.utf8();
132 total_written = f.writeBlock( cstr.data(), cstr.length() ); 160 total_written = f.writeBlock( cstr.data(), cstr.length() );
161 idx_offset += cstr.length();
133 if ( total_written != int(cstr.length()) ) { 162 if ( total_written != int(cstr.length()) ) {
134 f.close(); 163 f.close();
135 QFile::remove( strNewFile ); 164 QFile::remove( strNewFile );
@@ -139,7 +168,8 @@ bool OContactAccessBackend_XML::save()
139 } 168 }
140 out += " </Contacts>\n</AddressBook>\n"; 169 out += " </Contacts>\n</AddressBook>\n";
141 170
142 QCString cstr = out.utf8(); 171 // Write Footer
172 cstr = out.utf8();
143 total_written = f.writeBlock( cstr.data(), cstr.length() ); 173 total_written = f.writeBlock( cstr.data(), cstr.length() );
144 if ( total_written != int( cstr.length() ) ) { 174 if ( total_written != int( cstr.length() ) ) {
145 f.close(); 175 f.close();
@@ -167,6 +197,7 @@ bool OContactAccessBackend_XML::save()
167bool OContactAccessBackend_XML::load () 197bool OContactAccessBackend_XML::load ()
168{ 198{
169 m_contactList.clear(); 199 m_contactList.clear();
200 m_uidToContact.clear();
170 201
171 /* Load XML-File and journal if it exists */ 202 /* Load XML-File and journal if it exists */
172 if ( !load ( m_fileName, false ) ) 203 if ( !load ( m_fileName, false ) )
@@ -185,8 +216,9 @@ bool OContactAccessBackend_XML::load ()
185void OContactAccessBackend_XML::clear () 216void OContactAccessBackend_XML::clear ()
186{ 217{
187 m_contactList.clear(); 218 m_contactList.clear();
219 m_uidToContact.clear();
220
188 m_changed = false; 221 m_changed = false;
189
190} 222}
191 223
192bool OContactAccessBackend_XML::wasChangedExternally() 224bool OContactAccessBackend_XML::wasChangedExternally()
@@ -203,9 +235,9 @@ QArray<int> OContactAccessBackend_XML::allRecords() const
203 QArray<int> uid_list( m_contactList.count() ); 235 QArray<int> uid_list( m_contactList.count() );
204 236
205 uint counter = 0; 237 uint counter = 0;
206 QValueListConstIterator<OContact> it; 238 QListIterator<OContact> it( m_contactList );
207 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 239 for( ; it.current(); ++it ){
208 uid_list[counter++] = (*it).uid(); 240 uid_list[counter++] = (*it)->uid();
209 } 241 }
210 242
211 return ( uid_list ); 243 return ( uid_list );
@@ -213,31 +245,26 @@ QArray<int> OContactAccessBackend_XML::allRecords() const
213 245
214OContact OContactAccessBackend_XML::find ( int uid ) const 246OContact OContactAccessBackend_XML::find ( int uid ) const
215{ 247{
216 bool found = false;
217 OContact foundContact; //Create empty contact 248 OContact foundContact; //Create empty contact
218 249
219 QValueListConstIterator<OContact> it; 250 OContact* found = m_uidToContact.find( QString().setNum( uid ) );
220 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 251
221 if ((*it).uid() == uid){
222 found = true;
223 break;
224 }
225 }
226 if ( found ){ 252 if ( found ){
227 foundContact = *it; 253 foundContact = *found;
228 } 254 }
229 255
230 return ( foundContact ); 256 return ( foundContact );
231} 257}
232 258
233QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings ) 259QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
260 const QDateTime& d )
234{ 261{
235 262
236 QArray<int> m_currentQuery( m_contactList.count() ); 263 QArray<int> m_currentQuery( m_contactList.count() );
237 QValueListConstIterator<OContact> it; 264 QListIterator<OContact> it( m_contactList );
238 uint arraycounter = 0; 265 uint arraycounter = 0;
239 266
240 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 267 for( ; it.current(); ++it ){
241 /* Search all fields and compare them with query object. Store them into list 268 /* Search all fields and compare them with query object. Store them into list
242 * if all fields matches. 269 * if all fields matches.
243 */ 270 */
@@ -250,11 +277,11 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
250 switch ( i ){ 277 switch ( i ){
251 case Qtopia::Birthday: 278 case Qtopia::Birthday:
252 queryDate = new QDate( query.birthday() ); 279 queryDate = new QDate( query.birthday() );
253 checkDate = new QDate( (*it).birthday() ); 280 checkDate = new QDate( (*it)->birthday() );
254 case Qtopia::Anniversary: 281 case Qtopia::Anniversary:
255 if ( queryDate == 0l ){ 282 if ( queryDate == 0l ){
256 queryDate = new QDate( query.anniversary() ); 283 queryDate = new QDate( query.anniversary() );
257 checkDate = new QDate( (*it).anniversary() ); 284 checkDate = new QDate( (*it)->anniversary() );
258 } 285 }
259 286
260 if ( queryDate->isValid() ){ 287 if ( queryDate->isValid() ){
@@ -272,7 +299,15 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
272 allcorrect = false; 299 allcorrect = false;
273 } 300 }
274 if ( settings & OContactAccess::DateDiff ) { 301 if ( settings & OContactAccess::DateDiff ) {
275 QDate current = QDate::currentDate(); 302 QDate current;
303 // If we get an additional date, we
304 // will take this date instead of
305 // the current one..
306 if ( !d.date().isValid() )
307 current = QDate::currentDate();
308 else
309 current = d.date();
310
276 // We have to equalize the year, otherwise 311 // We have to equalize the year, otherwise
277 // the search will fail.. 312 // the search will fail..
278 checkDate->setYMD( current.year(), 313 checkDate->setYMD( current.year(),
@@ -282,6 +317,10 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
282 checkDate->setYMD( current.year()+1, 317 checkDate->setYMD( current.year()+1,
283 checkDate->month(), 318 checkDate->month(),
284 checkDate->day() ); 319 checkDate->day() );
320
321 // Check whether the birthday/anniversary date is between
322 // the current/given date and the maximum date
323 // ( maximum time range ) !
285 qWarning("Checking if %s is between %s and %s ! ", 324 qWarning("Checking if %s is between %s and %s ! ",
286 checkDate->toString().latin1(), 325 checkDate->toString().latin1(),
287 current.toString().latin1(), 326 current.toString().latin1(),
@@ -295,7 +334,7 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
295 } 334 }
296 } 335 }
297 } else{ 336 } else{
298 // checkDate is invalid. Therfore this entry is always rejected 337 // checkDate is invalid. Therefore this entry is always rejected
299 allcorrect = false; 338 allcorrect = false;
300 } 339 }
301 } 340 }
@@ -320,7 +359,7 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
320 QRegExp expr ( query.field(i), 359 QRegExp expr ( query.field(i),
321 !(settings & OContactAccess::IgnoreCase), 360 !(settings & OContactAccess::IgnoreCase),
322 false ); 361 false );
323 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 362 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
324 allcorrect = false; 363 allcorrect = false;
325 } 364 }
326 break; 365 break;
@@ -328,17 +367,17 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
328 QRegExp expr ( query.field(i), 367 QRegExp expr ( query.field(i),
329 !(settings & OContactAccess::IgnoreCase), 368 !(settings & OContactAccess::IgnoreCase),
330 true ); 369 true );
331 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 370 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
332 allcorrect = false; 371 allcorrect = false;
333 } 372 }
334 break; 373 break;
335 case OContactAccess::ExactMatch:{ 374 case OContactAccess::ExactMatch:{
336 if (settings & OContactAccess::IgnoreCase){ 375 if (settings & OContactAccess::IgnoreCase){
337 if ( query.field(i).upper() != 376 if ( query.field(i).upper() !=
338 (*it).field(i).upper() ) 377 (*it)->field(i).upper() )
339 allcorrect = false; 378 allcorrect = false;
340 }else{ 379 }else{
341 if ( query.field(i) != (*it).field(i) ) 380 if ( query.field(i) != (*it)->field(i) )
342 allcorrect = false; 381 allcorrect = false;
343 } 382 }
344 } 383 }
@@ -348,7 +387,7 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
348 } 387 }
349 } 388 }
350 if ( allcorrect ){ 389 if ( allcorrect ){
351 m_currentQuery[arraycounter++] = (*it).uid(); 390 m_currentQuery[arraycounter++] = (*it)->uid();
352 } 391 }
353 } 392 }
354 393
@@ -361,12 +400,12 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
361QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const 400QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
362{ 401{
363 QArray<int> m_currentQuery( m_contactList.count() ); 402 QArray<int> m_currentQuery( m_contactList.count() );
364 QValueListConstIterator<OContact> it; 403 QListIterator<OContact> it( m_contactList );
365 uint arraycounter = 0; 404 uint arraycounter = 0;
366 405
367 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 406 for( ; it.current(); ++it ){
368 if ( (*it).match( r ) ){ 407 if ( (*it)->match( r ) ){
369 m_currentQuery[arraycounter++] = (*it).uid(); 408 m_currentQuery[arraycounter++] = (*it)->uid();
370 } 409 }
371 410
372 } 411 }
@@ -426,10 +465,10 @@ QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
426 465
427 // First fill map and StringList with all Names 466 // First fill map and StringList with all Names
428 // Afterwards sort namelist and use map to fill array to return.. 467 // Afterwards sort namelist and use map to fill array to return..
429 QValueListConstIterator<OContact> it; 468 QListIterator<OContact> it( m_contactList );
430 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 469 for( ; it.current(); ++it ){
431 names.append( (*it).fileAs() + QString::number( (*it).uid() ) ); 470 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
432 nameToUid.insert( (*it).fileAs() + QString::number( (*it).uid() ), (*it).uid() ); 471 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
433 } 472 }
434 names.sort(); 473 names.sort();
435 474
@@ -461,19 +500,19 @@ bool OContactAccessBackend_XML::replace ( const OContact &contact )
461{ 500{
462 m_changed = true; 501 m_changed = true;
463 502
464 bool found = false; 503 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
465 504
466 QValueListIterator<OContact> it; 505 if ( found ) {
467 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 506 OContact* newCont = new OContact( contact );
468 if ( (*it).uid() == contact.uid() ){ 507
469 found = true; 508 updateJournal ( *newCont, ACTION_REPLACE);
470 break; 509 m_contactList.removeRef ( found );
471 } 510 m_contactList.append ( newCont );
472 } 511 m_uidToContact.remove( QString().setNum( contact.uid() ) );
473 if (found) { 512 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
474 updateJournal (contact, ACTION_REPLACE); 513
475 m_contactList.remove (it); 514 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
476 m_contactList.append (contact); 515
477 return true; 516 return true;
478 } else 517 } else
479 return false; 518 return false;
@@ -483,17 +522,13 @@ bool OContactAccessBackend_XML::remove ( int uid )
483{ 522{
484 m_changed = true; 523 m_changed = true;
485 524
486 bool found = false; 525 OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
487 QValueListIterator<OContact> it; 526
488 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 527 if ( found ) {
489 if ((*it).uid() == uid){ 528 updateJournal ( *found, ACTION_REMOVE);
490 found = true; 529 m_contactList.removeRef ( found );
491 break; 530 m_uidToContact.remove( QString().setNum( uid ) );
492 } 531
493 }
494 if (found) {
495 updateJournal ( *it, ACTION_REMOVE);
496 m_contactList.remove (it);
497 return true; 532 return true;
498 } else 533 } else
499 return false; 534 return false;
@@ -506,7 +541,10 @@ bool OContactAccessBackend_XML::reload(){
506 541
507void OContactAccessBackend_XML::addContact_p( const OContact &newcontact ) 542void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
508{ 543{
509 m_contactList.append (newcontact); 544 OContact* contRef = new OContact( newcontact );
545
546 m_contactList.append ( contRef );
547 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
510} 548}
511 549
512/* This function loads the xml-database and the journalfile */ 550/* This function loads the xml-database and the journalfile */
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 6477705..4d6a7ef 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -17,6 +17,20 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.13 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
28 * Revision 1.12.2.2 2003/02/11 12:17:28 eilers
29 * Speed optimization. Removed the sequential search loops.
30 *
31 * Revision 1.12.2.1 2003/02/09 15:05:01 eilers
32 * Nothing happened.. Just some cleanup before I will start..
33 *
20 * Revision 1.12 2003/01/03 16:58:03 eilers 34 * Revision 1.12 2003/01/03 16:58:03 eilers
21 * Reenable debug output 35 * Reenable debug output
22 * 36 *
@@ -63,681 +77,68 @@
63#ifndef _OContactAccessBackend_XML_ 77#ifndef _OContactAccessBackend_XML_
64#define _OContactAccessBackend_XML_ 78#define _OContactAccessBackend_XML_
65 79
66#include <qasciidict.h>
67#include <qdatetime.h>
68#include <qfile.h>
69#include <qfileinfo.h>
70#include <qregexp.h>
71#include <qarray.h>
72#include <qmap.h>
73#include <qdatetime.h>
74
75#include <qpe/global.h>
76
77#include <opie/xmltree.h>
78#include "ocontactaccessbackend.h" 80#include "ocontactaccessbackend.h"
79#include "ocontactaccess.h" 81#include "ocontactaccess.h"
80 82
81#include <stdlib.h> 83#include <qlist.h>
82#include <errno.h> 84#include <qdict.h>
83
84using namespace Opie;
85 85
86/* the default xml implementation */ 86/* the default xml implementation */
87class OContactAccessBackend_XML : public OContactAccessBackend { 87class OContactAccessBackend_XML : public OContactAccessBackend {
88 public: 88 public:
89 OContactAccessBackend_XML ( QString appname, QString filename = 0l ): 89 OContactAccessBackend_XML ( QString appname, QString filename = 0l );
90 m_changed( false )
91 {
92 m_appName = appname;
93
94 /* Set journalfile name ... */
95 m_journalName = getenv("HOME");
96 m_journalName +="/.abjournal" + appname;
97
98 /* Expecting to access the default filename if nothing else is set */
99 if ( filename.isEmpty() ){
100 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
101 } else
102 m_fileName = filename;
103
104 /* Load Database now */
105 load ();
106 }
107 90
108 bool save() { 91 bool save();
109
110 if ( !m_changed )
111 return true;
112
113 QString strNewFile = m_fileName + ".new";
114 QFile f( strNewFile );
115 if ( !f.open( IO_WriteOnly|IO_Raw ) )
116 return false;
117
118 int total_written;
119 QString out;
120 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
121 " <Groups>\n"
122 " </Groups>\n"
123 " <Contacts>\n";
124 //QValueList<Contact>::iterator it;
125 QValueListConstIterator<OContact> it;
126 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
127 out += "<Contact ";
128 (*it).save( out );
129 out += "/>\n";
130 QCString cstr = out.utf8();
131 total_written = f.writeBlock( cstr.data(), cstr.length() );
132 if ( total_written != int(cstr.length()) ) {
133 f.close();
134 QFile::remove( strNewFile );
135 return false;
136 }
137 out = "";
138 }
139 out += " </Contacts>\n</AddressBook>\n";
140
141 QCString cstr = out.utf8();
142 total_written = f.writeBlock( cstr.data(), cstr.length() );
143 if ( total_written != int( cstr.length() ) ) {
144 f.close();
145 QFile::remove( strNewFile );
146 return false;
147 }
148 f.close();
149
150 // move the file over, I'm just going to use the system call
151 // because, I don't feel like using QDir.
152 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
153 qWarning( "problem renaming file %s to %s, errno: %d",
154 strNewFile.latin1(), m_journalName.latin1(), errno );
155 // remove the tmp file...
156 QFile::remove( strNewFile );
157 }
158
159 /* The journalfile should be removed now... */
160 removeJournal();
161
162 m_changed = false;
163 return true;
164 }
165 92
166 bool load () { 93 bool load ();
167 m_contactList.clear();
168
169 /* Load XML-File and journal if it exists */
170 if ( !load ( m_fileName, false ) )
171 return false;
172 /* The returncode of the journalfile is ignored due to the
173 * fact that it does not exist when this class is instantiated !
174 * But there may such a file exist, if the application crashed.
175 * Therefore we try to load it to get the changes before the #
176 * crash happened...
177 */
178 load (m_journalName, true);
179
180 return true;
181 }
182
183 void clear () {
184 m_contactList.clear();
185 m_changed = false;
186 94
187 } 95 void clear ();
188 96
189 bool wasChangedExternally() 97 bool wasChangedExternally();
190 {
191 QFileInfo fi( m_fileName );
192
193 QDateTime lastmod = fi.lastModified ();
194
195 return (lastmod != m_readtime);
196 }
197 98
198 QArray<int> allRecords() const { 99 QArray<int> allRecords() const;
199 QArray<int> uid_list( m_contactList.count() );
200
201 uint counter = 0;
202 QValueListConstIterator<OContact> it;
203 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
204 uid_list[counter++] = (*it).uid();
205 }
206
207 return ( uid_list );
208 }
209 100
210 OContact find ( int uid ) const 101 OContact find ( int uid ) const;
211 {
212 bool found = false;
213 OContact foundContact; //Create empty contact
214
215 QValueListConstIterator<OContact> it;
216 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
217 if ((*it).uid() == uid){
218 found = true;
219 break;
220 }
221 }
222 if ( found ){
223 foundContact = *it;
224 }
225
226 return ( foundContact );
227 }
228 102
229 QArray<int> queryByExample ( const OContact &query, int settings ){ 103 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
230
231 QArray<int> m_currentQuery( m_contactList.count() );
232 QValueListConstIterator<OContact> it;
233 uint arraycounter = 0;
234
235 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
236 /* Search all fields and compare them with query object. Store them into list
237 * if all fields matches.
238 */
239 QDate* queryDate = 0l;
240 QDate* checkDate = 0l;
241 bool allcorrect = true;
242 for ( int i = 0; i < Qtopia::Groups; i++ ) {
243 // Birthday and anniversary are special nonstring fields and should
244 // be handled specially
245 switch ( i ){
246 case Qtopia::Birthday:
247 queryDate = new QDate( query.birthday() );
248 checkDate = new QDate( (*it).birthday() );
249 case Qtopia::Anniversary:
250 if ( queryDate == 0l ){
251 queryDate = new QDate( query.anniversary() );
252 checkDate = new QDate( (*it).anniversary() );
253 }
254
255 if ( queryDate->isValid() ){
256 if( checkDate->isValid() ){
257 if ( settings & OContactAccess::DateYear ){
258 if ( queryDate->year() != checkDate->year() )
259 allcorrect = false;
260 }
261 if ( settings & OContactAccess::DateMonth ){
262 if ( queryDate->month() != checkDate->month() )
263 allcorrect = false;
264 }
265 if ( settings & OContactAccess::DateDay ){
266 if ( queryDate->day() != checkDate->day() )
267 allcorrect = false;
268 }
269 if ( settings & OContactAccess::DateDiff ) {
270 QDate current = QDate::currentDate();
271 // We have to equalize the year, otherwise
272 // the search will fail..
273 checkDate->setYMD( current.year(),
274 checkDate->month(),
275 checkDate->day() );
276 if ( *checkDate < current )
277 checkDate->setYMD( current.year()+1,
278 checkDate->month(),
279 checkDate->day() );
280 qWarning("Checking if %s is between %s and %s ! ",
281 checkDate->toString().latin1(),
282 current.toString().latin1(),
283 queryDate->toString().latin1() );
284 if ( current.daysTo( *queryDate ) > 0 ){
285 if ( !( ( *checkDate >= current ) &&
286 ( *checkDate <= *queryDate ) ) ){
287 allcorrect = false;
288 qWarning (" Nope!..");
289 }
290 }
291 }
292 } else{
293 // checkDate is invalid. Therfore this entry is always rejected
294 allcorrect = false;
295 }
296 }
297
298 delete queryDate;
299 queryDate = 0l;
300 delete checkDate;
301 checkDate = 0l;
302 break;
303 default:
304 /* Just compare fields which are not empty in the query object */
305 if ( !query.field(i).isEmpty() ){
306 switch ( settings & ~( OContactAccess::IgnoreCase
307 | OContactAccess::DateDiff
308 | OContactAccess::DateYear
309 | OContactAccess::DateMonth
310 | OContactAccess::DateDay
311 | OContactAccess::MatchOne
312 ) ){
313 104
314 case OContactAccess::RegExp:{ 105 QArray<int> matchRegexp( const QRegExp &r ) const;
315 QRegExp expr ( query.field(i),
316 !(settings & OContactAccess::IgnoreCase),
317 false );
318 if ( expr.find ( (*it).field(i), 0 ) == -1 )
319 allcorrect = false;
320 }
321 break;
322 case OContactAccess::WildCards:{
323 QRegExp expr ( query.field(i),
324 !(settings & OContactAccess::IgnoreCase),
325 true );
326 if ( expr.find ( (*it).field(i), 0 ) == -1 )
327 allcorrect = false;
328 }
329 break;
330 case OContactAccess::ExactMatch:{
331 if (settings & OContactAccess::IgnoreCase){
332 if ( query.field(i).upper() !=
333 (*it).field(i).upper() )
334 allcorrect = false;
335 }else{
336 if ( query.field(i) != (*it).field(i) )
337 allcorrect = false;
338 }
339 }
340 break;
341 }
342 }
343 }
344 }
345 if ( allcorrect ){
346 m_currentQuery[arraycounter++] = (*it).uid();
347 }
348 }
349
350 // Shrink to fit..
351 m_currentQuery.resize(arraycounter);
352 106
353 return m_currentQuery; 107 const uint querySettings();
354 }
355
356 QArray<int> matchRegexp( const QRegExp &r ) const{
357 QArray<int> m_currentQuery( m_contactList.count() );
358 QValueListConstIterator<OContact> it;
359 uint arraycounter = 0;
360
361 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
362 if ( (*it).match( r ) ){
363 m_currentQuery[arraycounter++] = (*it).uid();
364 }
365
366 }
367 // Shrink to fit..
368 m_currentQuery.resize(arraycounter);
369
370 return m_currentQuery;
371 }
372
373 const uint querySettings()
374 {
375 return ( OContactAccess::WildCards
376 | OContactAccess::IgnoreCase
377 | OContactAccess::RegExp
378 | OContactAccess::ExactMatch
379 | OContactAccess::DateDiff
380 | OContactAccess::DateYear
381 | OContactAccess::DateMonth
382 | OContactAccess::DateDay
383 );
384 }
385 108
386 bool hasQuerySettings (uint querySettings) const 109 bool hasQuerySettings (uint querySettings) const;
387 {
388 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
389 * may be added with any of the other settings. IgnoreCase should never used alone.
390 * Wildcards, RegExp, ExactMatch should never used at the same time...
391 */
392
393 if ( querySettings == OContactAccess::IgnoreCase )
394 return false;
395
396 switch ( querySettings & ~( OContactAccess::IgnoreCase
397 | OContactAccess::DateDiff
398 | OContactAccess::DateYear
399 | OContactAccess::DateMonth
400 | OContactAccess::DateDay
401 )
402 ){
403 case OContactAccess::RegExp:
404 return ( true );
405 case OContactAccess::WildCards:
406 return ( true );
407 case OContactAccess::ExactMatch:
408 return ( true );
409 default:
410 return ( false );
411 }
412 }
413 110
414 // Currently only asc implemented.. 111 // Currently only asc implemented..
415 QArray<int> sorted( bool asc, int , int , int ) 112 QArray<int> sorted( bool asc, int , int , int );
416 { 113 bool add ( const OContact &newcontact );
417 QMap<QString, int> nameToUid;
418 QStringList names;
419 QArray<int> m_currentQuery( m_contactList.count() );
420
421 // First fill map and StringList with all Names
422 // Afterwards sort namelist and use map to fill array to return..
423 QValueListConstIterator<OContact> it;
424 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
425 names.append( (*it).fileAs() + QString::number( (*it).uid() ) );
426 nameToUid.insert( (*it).fileAs() + QString::number( (*it).uid() ), (*it).uid() );
427 }
428 names.sort();
429
430 int i = 0;
431 if ( asc ){
432 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
433 m_currentQuery[i++] = nameToUid[ (*it) ];
434 }else{
435 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
436 m_currentQuery[i++] = nameToUid[ (*it) ];
437 }
438
439 return m_currentQuery;
440
441 }
442 bool add ( const OContact &newcontact )
443 {
444 //qWarning("odefaultbackend: ACTION::ADD");
445 updateJournal (newcontact, ACTION_ADD);
446 addContact_p( newcontact );
447
448 m_changed = true;
449
450 return true;
451 }
452
453 bool replace ( const OContact &contact )
454 {
455 m_changed = true;
456
457 bool found = false;
458
459 QValueListIterator<OContact> it;
460 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
461 if ( (*it).uid() == contact.uid() ){
462 found = true;
463 break;
464 }
465 }
466 if (found) {
467 updateJournal (contact, ACTION_REPLACE);
468 m_contactList.remove (it);
469 m_contactList.append (contact);
470 return true;
471 } else
472 return false;
473 }
474 114
475 bool remove ( int uid ) 115 bool replace ( const OContact &contact );
476 {
477 m_changed = true;
478
479 bool found = false;
480 QValueListIterator<OContact> it;
481 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
482 if ((*it).uid() == uid){
483 found = true;
484 break;
485 }
486 }
487 if (found) {
488 updateJournal ( *it, ACTION_REMOVE);
489 m_contactList.remove (it);
490 return true;
491 } else
492 return false;
493 }
494 116
495 bool reload(){ 117 bool remove ( int uid );
496 /* Reload is the same as load in this implementation */ 118 bool reload();
497 return ( load() );
498 }
499 119
500 private: 120 private:
501 121
502 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; 122 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
503 123
504 void addContact_p( const OContact &newcontact ){ 124 void addContact_p( const OContact &newcontact );
505 m_contactList.append (newcontact);
506 }
507 125
508 /* This function loads the xml-database and the journalfile */ 126 /* This function loads the xml-database and the journalfile */
509 bool load( const QString filename, bool isJournal ) { 127 bool load( const QString filename, bool isJournal );
510
511 /* We use the time of the last read to check if the file was
512 * changed externally.
513 */
514 if ( !isJournal ){
515 QFileInfo fi( filename );
516 m_readtime = fi.lastModified ();
517 }
518
519 const int JOURNALACTION = Qtopia::Notes + 1;
520 const int JOURNALROW = JOURNALACTION + 1;
521
522 bool foundAction = false;
523 journal_action action = ACTION_ADD;
524 int journalKey = 0;
525 QMap<int, QString> contactMap;
526 QMap<QString, QString> customMap;
527 QMap<QString, QString>::Iterator customIt;
528 QAsciiDict<int> dict( 47 );
529
530 dict.setAutoDelete( TRUE );
531 dict.insert( "Uid", new int(Qtopia::AddressUid) );
532 dict.insert( "Title", new int(Qtopia::Title) );
533 dict.insert( "FirstName", new int(Qtopia::FirstName) );
534 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
535 dict.insert( "LastName", new int(Qtopia::LastName) );
536 dict.insert( "Suffix", new int(Qtopia::Suffix) );
537 dict.insert( "FileAs", new int(Qtopia::FileAs) );
538 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
539 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
540 dict.insert( "Emails", new int(Qtopia::Emails) );
541 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
542 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
543 dict.insert( "HomeState", new int(Qtopia::HomeState) );
544 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
545 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
546 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
547 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
548 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
549 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
550 dict.insert( "Company", new int(Qtopia::Company) );
551 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
552 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
553 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
554 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
555 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
556 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
557 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
558 dict.insert( "Department", new int(Qtopia::Department) );
559 dict.insert( "Office", new int(Qtopia::Office) );
560 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
561 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
562 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
563 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
564 dict.insert( "Profession", new int(Qtopia::Profession) );
565 dict.insert( "Assistant", new int(Qtopia::Assistant) );
566 dict.insert( "Manager", new int(Qtopia::Manager) );
567 dict.insert( "Spouse", new int(Qtopia::Spouse) );
568 dict.insert( "Children", new int(Qtopia::Children) );
569 dict.insert( "Gender", new int(Qtopia::Gender) );
570 dict.insert( "Birthday", new int(Qtopia::Birthday) );
571 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
572 dict.insert( "Nickname", new int(Qtopia::Nickname) );
573 dict.insert( "Notes", new int(Qtopia::Notes) );
574 dict.insert( "action", new int(JOURNALACTION) );
575 dict.insert( "actionrow", new int(JOURNALROW) );
576
577 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
578
579 XMLElement *root = XMLElement::load( filename );
580 if(root != 0l ){ // start parsing
581 /* Parse all XML-Elements and put the data into the
582 * Contact-Class
583 */
584 XMLElement *element = root->firstChild();
585 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
586 element = element->firstChild();
587
588 /* Search Tag "Contacts" which is the parent of all Contacts */
589 while( element && !isJournal ){
590 if( element->tagName() != QString::fromLatin1("Contacts") ){
591 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
592 // element->tagName().latin1());
593 element = element->nextChild();
594 } else {
595 element = element->firstChild();
596 break;
597 }
598 }
599 /* Parse all Contacts and ignore unknown tags */
600 while( element ){
601 if( element->tagName() != QString::fromLatin1("Contact") ){
602 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
603 // element->tagName().latin1());
604 element = element->nextChild();
605 continue;
606 }
607 /* Found alement with tagname "contact", now parse and store all
608 * attributes contained
609 */
610 //qWarning("OContactDefBack::load element tagName() : %s",
611 // element->tagName().latin1() );
612 QString dummy;
613 foundAction = false;
614
615 XMLElement::AttributeMap aMap = element->attributes();
616 XMLElement::AttributeMap::Iterator it;
617 contactMap.clear();
618 customMap.clear();
619 for( it = aMap.begin(); it != aMap.end(); ++it ){
620 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
621
622 int *find = dict[ it.key() ];
623 /* Unknown attributes will be stored as "Custom" elements */
624 if ( !find ) {
625 qWarning("Attribute %s not known.", it.key().latin1());
626 //contact.setCustomField(it.key(), it.data());
627 customMap.insert( it.key(), it.data() );
628 continue;
629 }
630
631 /* Check if special conversion is needed and add attribute
632 * into Contact class
633 */
634 switch( *find ) {
635 /*
636 case Qtopia::AddressUid:
637 contact.setUid( it.data().toInt() );
638 break;
639 case Qtopia::AddressCategory:
640 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
641 break;
642 */
643 case JOURNALACTION:
644 action = journal_action(it.data().toInt());
645 foundAction = true;
646 qWarning ("ODefBack(journal)::ACTION found: %d", action);
647 break;
648 case JOURNALROW:
649 journalKey = it.data().toInt();
650 break;
651 default: // no conversion needed add them to the map
652 contactMap.insert( *find, it.data() );
653 break;
654 }
655 }
656 /* now generate the Contact contact */
657 OContact contact( contactMap );
658
659 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
660 contact.setCustomField( customIt.key(), customIt.data() );
661 }
662
663 if (foundAction){
664 foundAction = false;
665 switch ( action ) {
666 case ACTION_ADD:
667 addContact_p (contact);
668 break;
669 case ACTION_REMOVE:
670 if ( !remove (contact.uid()) )
671 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
672 contact.uid() );
673 break;
674 case ACTION_REPLACE:
675 if ( !replace ( contact ) )
676 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
677 contact.uid() );
678 break;
679 default:
680 qWarning ("Unknown action: ignored !");
681 break;
682 }
683 }else{
684 /* Add contact to list */
685 addContact_p (contact);
686 }
687
688 /* Move to next element */
689 element = element->nextChild();
690 }
691 }else {
692 qWarning("ODefBack::could not load");
693 }
694 delete root;
695 qWarning("returning from loading" );
696 return true;
697 }
698
699 128
700 void updateJournal( const OContact& cnt,
701 journal_action action ) {
702 QFile f( m_journalName );
703 bool created = !f.exists();
704 if ( !f.open(IO_WriteOnly|IO_Append) )
705 return;
706
707 QString buf;
708 QCString str;
709
710 // if the file was created, we have to set the Tag "<CONTACTS>" to
711 // get a XML-File which is readable by our parser.
712 // This is just a cheat, but better than rewrite the parser.
713 if ( created ){
714 buf = "<Contacts>";
715 QCString cstr = buf.utf8();
716 f.writeBlock( cstr.data(), cstr.length() );
717 }
718
719 buf = "<Contact ";
720 cnt.save( buf );
721 buf += " action=\"" + QString::number( (int)action ) + "\" ";
722 buf += "/>\n";
723 QCString cstr = buf.utf8();
724 f.writeBlock( cstr.data(), cstr.length() );
725 }
726 129
727 void removeJournal() 130 void updateJournal( const OContact& cnt, journal_action action );
728 { 131 void removeJournal();
729 QFile f ( m_journalName );
730 if ( f.exists() )
731 f.remove();
732 }
733 132
734 protected: 133 protected:
735 bool m_changed; 134 bool m_changed;
736 QString m_journalName; 135 QString m_journalName;
737 QString m_fileName; 136 QString m_fileName;
738 QString m_appName; 137 QString m_appName;
739 QValueList<OContact> m_contactList; 138 QList<OContact> m_contactList;
740 QDateTime m_readtime; 139 QDateTime m_readtime;
140
141 QDict<OContact> m_uidToContact;
741}; 142};
742 143
743#endif 144#endif
diff --git a/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp
index 4a6b7b8..11e19d9 100644
--- a/libopie/pim/odatebookaccessbackend_xml.cpp
+++ b/libopie/pim/odatebookaccessbackend_xml.cpp
@@ -244,7 +244,7 @@ QArray<int> ODateBookAccessBackend_XML::allRecords()const {
244 244
245 return ints; 245 return ints;
246} 246}
247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { 247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
248 return QArray<int>(); 248 return QArray<int>();
249} 249}
250void ODateBookAccessBackend_XML::clear() { 250void ODateBookAccessBackend_XML::clear() {
diff --git a/libopie/pim/odatebookaccessbackend_xml.h b/libopie/pim/odatebookaccessbackend_xml.h
index 40f69d8..563c31f 100644
--- a/libopie/pim/odatebookaccessbackend_xml.h
+++ b/libopie/pim/odatebookaccessbackend_xml.h
@@ -16,7 +16,7 @@ public:
16 bool save(); 16 bool save();
17 17
18 QArray<int> allRecords()const; 18 QArray<int> allRecords()const;
19 QArray<int> queryByExample( const OEvent&, int ); 19 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
20 OEvent find( int uid )const; 20 OEvent find( int uid )const;
21 void clear(); 21 void clear();
22 bool add( const OEvent& ev ); 22 bool add( const OEvent& ev );
diff --git a/libopie/pim/opimaccessbackend.h b/libopie/pim/opimaccessbackend.h
index e268f4f..01a0c86 100644
--- a/libopie/pim/opimaccessbackend.h
+++ b/libopie/pim/opimaccessbackend.h
@@ -47,10 +47,10 @@ public:
47 virtual QArray<int> allRecords()const = 0; 47 virtual QArray<int> allRecords()const = 0;
48 48
49 /** 49 /**
50 * queryByExample for T with the SortOrder 50 * queryByExample for T with the given Settings
51 * sort 51 *
52 */ 52 */
53 virtual QArray<int> queryByExample( const T& t, int sort ) = 0; 53 virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0;
54 54
55 /** 55 /**
56 * find the OPimRecord with uid @param uid 56 * find the OPimRecord with uid @param uid
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
index 259e2c1..6a3a0db 100644
--- a/libopie/pim/opimaccesstemplate.h
+++ b/libopie/pim/opimaccesstemplate.h
@@ -74,7 +74,7 @@ public:
74 * queryByExample. 74 * queryByExample.
75 * @see otodoaccess, ocontactaccess 75 * @see otodoaccess, ocontactaccess
76 */ 76 */
77 virtual List queryByExample( const T& t, int querySettings ); 77 virtual List queryByExample( const T& t, int querySettings, const QDateTime& d = QDateTime() );
78 78
79 /** 79 /**
80 * find the OPimRecord uid 80 * find the OPimRecord uid
@@ -186,8 +186,8 @@ QArray<int> OPimAccessTemplate<T>::records()const {
186} 186}
187template <class T> 187template <class T>
188typename OPimAccessTemplate<T>::List 188typename OPimAccessTemplate<T>::List
189OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 189OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime& d ) {
190 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 190 QArray<int> ints = m_backEnd->queryByExample( t, settings, d );
191 191
192 List lis(ints, this ); 192 List lis(ints, this );
193 return lis; 193 return lis;
diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp
index 761d7d8..ec9c14c 100644
--- a/libopie/pim/otodoaccesssql.cpp
+++ b/libopie/pim/otodoaccesssql.cpp
@@ -277,7 +277,7 @@ QArray<int> OTodoAccessBackendSQL::allRecords()const {
277 277
278 return m_uids; 278 return m_uids;
279} 279}
280QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int ){ 280QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
281 QArray<int> ints(0); 281 QArray<int> ints(0);
282 return ints; 282 return ints;
283} 283}
diff --git a/libopie/pim/otodoaccesssql.h b/libopie/pim/otodoaccesssql.h
index 0f6dd2c..6a4257c 100644
--- a/libopie/pim/otodoaccesssql.h
+++ b/libopie/pim/otodoaccesssql.h
@@ -18,7 +18,7 @@ public:
18 bool save(); 18 bool save();
19 QArray<int> allRecords()const; 19 QArray<int> allRecords()const;
20 20
21 QArray<int> queryByExample( const OTodo& t, int sort ); 21 QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() );
22 OTodo find(int uid)const; 22 OTodo find(int uid)const;
23 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 23 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
24 void clear(); 24 void clear();
diff --git a/libopie/pim/otodoaccessvcal.cpp b/libopie/pim/otodoaccessvcal.cpp
index 309f9e1..2136283 100644
--- a/libopie/pim/otodoaccessvcal.cpp
+++ b/libopie/pim/otodoaccessvcal.cpp
@@ -185,7 +185,7 @@ QArray<int> OTodoAccessVCal::allRecords()const {
185 } 185 }
186 return ar; 186 return ar;
187} 187}
188QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int ) { 188QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int, const QDateTime& ) {
189 QArray<int> ar(0); 189 QArray<int> ar(0);
190 return ar; 190 return ar;
191} 191}
diff --git a/libopie/pim/otodoaccessvcal.h b/libopie/pim/otodoaccessvcal.h
index 452f602..a90ee9c 100644
--- a/libopie/pim/otodoaccessvcal.h
+++ b/libopie/pim/otodoaccessvcal.h
@@ -13,7 +13,7 @@ public:
13 bool save(); 13 bool save();
14 14
15 QArray<int> allRecords()const; 15 QArray<int> allRecords()const;
16 QArray<int> queryByExample( const OTodo& t, int sort ); 16 QArray<int> queryByExample( const OTodo& t, int sort, const QDateTime& d = QDateTime() );
17 QArray<int> effectiveToDos( const QDate& start, 17 QArray<int> effectiveToDos( const QDate& start,
18 const QDate& end, 18 const QDate& end,
19 bool includeNoDates ); 19 bool includeNoDates );
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index cda300b..71e8787 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -255,7 +255,7 @@ QArray<int> OTodoAccessXML::allRecords()const {
255 } 255 }
256 return ids; 256 return ids;
257} 257}
258QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { 258QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
259 QArray<int> ids(0); 259 QArray<int> ids(0);
260 return ids; 260 return ids;
261} 261}
diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h
index 93609fe..1032c92 100644
--- a/libopie/pim/otodoaccessxml.h
+++ b/libopie/pim/otodoaccessxml.h
@@ -24,7 +24,7 @@ public:
24 bool save(); 24 bool save();
25 25
26 QArray<int> allRecords()const; 26 QArray<int> allRecords()const;
27 QArray<int> queryByExample( const OTodo&, int querysettings ); 27 QArray<int> queryByExample( const OTodo&, int querysettings, const QDateTime& d = QDateTime() );
28 OTodo find( int uid )const; 28 OTodo find( int uid )const;
29 void clear(); 29 void clear();
30 bool add( const OTodo& ); 30 bool add( const OTodo& );
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
index e537269..f24523f 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
@@ -17,6 +17,14 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.9 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
20 * Revision 1.8 2003/02/21 16:52:49 zecke 28 * Revision 1.8 2003/02/21 16:52:49 zecke
21 * -Remove old Todo classes they're deprecated and today I already using the 29 * -Remove old Todo classes they're deprecated and today I already using the
22 * new API 30 * new API
@@ -189,7 +197,7 @@ QArray<int> OContactAccessBackend_VCard::allRecords() const
189} 197}
190 198
191// Not implemented 199// Not implemented
192QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int ) 200QArray<int> OContactAccessBackend_VCard::queryByExample ( const OContact&, int, const QDateTime& )
193{ 201{
194 QArray<int> ar(0); 202 QArray<int> ar(0);
195 return ar; 203 return ar;
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
index 236da00..93e2da3 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
@@ -17,6 +17,14 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.5 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
20 * Revision 1.4 2002/12/07 13:26:22 eilers 28 * Revision 1.4 2002/12/07 13:26:22 eilers
21 * Fixing bug in storing anniversary.. 29 * Fixing bug in storing anniversary..
22 * 30 *
@@ -54,7 +62,7 @@ class OContactAccessBackend_VCard : public OContactAccessBackend {
54 62
55 OContact find ( int uid ) const; 63 OContact find ( int uid ) const;
56 QArray<int> allRecords() const; 64 QArray<int> allRecords() const;
57 QArray<int> queryByExample ( const OContact &query, int settings ); 65 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
58 QArray<int> matchRegexp( const QRegExp &r ) const; 66 QArray<int> matchRegexp( const QRegExp &r ) const;
59 67
60 const uint querySettings(); 68 const uint querySettings();
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
index 2df6757..4abf4d9 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
@@ -17,6 +17,20 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.2 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
28 * Revision 1.1.2.2 2003/02/11 12:17:28 eilers
29 * Speed optimization. Removed the sequential search loops.
30 *
31 * Revision 1.1.2.1 2003/02/10 15:31:38 eilers
32 * Writing offsets to debug output..
33 *
20 * Revision 1.1 2003/02/09 15:05:01 eilers 34 * Revision 1.1 2003/02/09 15:05:01 eilers
21 * Nothing happened.. Just some cleanup before I will start.. 35 * Nothing happened.. Just some cleanup before I will start..
22 * 36 *
@@ -89,6 +103,11 @@ using namespace Opie;
89OContactAccessBackend_XML::OContactAccessBackend_XML ( QString appname, QString filename = 0l ): 103OContactAccessBackend_XML::OContactAccessBackend_XML ( QString appname, QString filename = 0l ):
90 m_changed( false ) 104 m_changed( false )
91{ 105{
106 // Just m_contactlist should call delete if an entry
107 // is removed.
108 m_contactList.setAutoDelete( true );
109 m_uidToContact.setAutoDelete( false );
110
92 m_appName = appname; 111 m_appName = appname;
93 112
94 /* Set journalfile name ... */ 113 /* Set journalfile name ... */
@@ -117,19 +136,29 @@ bool OContactAccessBackend_XML::save()
117 return false; 136 return false;
118 137
119 int total_written; 138 int total_written;
139 int idx_offset = 0;
120 QString out; 140 QString out;
141
142 // Write Header
121 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 143 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
122 " <Groups>\n" 144 " <Groups>\n"
123 " </Groups>\n" 145 " </Groups>\n"
124 " <Contacts>\n"; 146 " <Contacts>\n";
125 //QValueList<Contact>::iterator it; 147 QCString cstr = out.utf8();
126 QValueListConstIterator<OContact> it; 148 f.writeBlock( cstr.data(), cstr.length() );
127 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) { 149 idx_offset += cstr.length();
150 out = "";
151
152 // Write all contacts
153 QListIterator<OContact> it( m_contactList );
154 for ( ; it.current(); ++it ) {
155 qWarning(" Uid %d at Offset: %x", (*it)->uid(), idx_offset );
128 out += "<Contact "; 156 out += "<Contact ";
129 (*it).save( out ); 157 (*it)->save( out );
130 out += "/>\n"; 158 out += "/>\n";
131 QCString cstr = out.utf8(); 159 cstr = out.utf8();
132 total_written = f.writeBlock( cstr.data(), cstr.length() ); 160 total_written = f.writeBlock( cstr.data(), cstr.length() );
161 idx_offset += cstr.length();
133 if ( total_written != int(cstr.length()) ) { 162 if ( total_written != int(cstr.length()) ) {
134 f.close(); 163 f.close();
135 QFile::remove( strNewFile ); 164 QFile::remove( strNewFile );
@@ -139,7 +168,8 @@ bool OContactAccessBackend_XML::save()
139 } 168 }
140 out += " </Contacts>\n</AddressBook>\n"; 169 out += " </Contacts>\n</AddressBook>\n";
141 170
142 QCString cstr = out.utf8(); 171 // Write Footer
172 cstr = out.utf8();
143 total_written = f.writeBlock( cstr.data(), cstr.length() ); 173 total_written = f.writeBlock( cstr.data(), cstr.length() );
144 if ( total_written != int( cstr.length() ) ) { 174 if ( total_written != int( cstr.length() ) ) {
145 f.close(); 175 f.close();
@@ -167,6 +197,7 @@ bool OContactAccessBackend_XML::save()
167bool OContactAccessBackend_XML::load () 197bool OContactAccessBackend_XML::load ()
168{ 198{
169 m_contactList.clear(); 199 m_contactList.clear();
200 m_uidToContact.clear();
170 201
171 /* Load XML-File and journal if it exists */ 202 /* Load XML-File and journal if it exists */
172 if ( !load ( m_fileName, false ) ) 203 if ( !load ( m_fileName, false ) )
@@ -185,8 +216,9 @@ bool OContactAccessBackend_XML::load ()
185void OContactAccessBackend_XML::clear () 216void OContactAccessBackend_XML::clear ()
186{ 217{
187 m_contactList.clear(); 218 m_contactList.clear();
219 m_uidToContact.clear();
220
188 m_changed = false; 221 m_changed = false;
189
190} 222}
191 223
192bool OContactAccessBackend_XML::wasChangedExternally() 224bool OContactAccessBackend_XML::wasChangedExternally()
@@ -203,9 +235,9 @@ QArray<int> OContactAccessBackend_XML::allRecords() const
203 QArray<int> uid_list( m_contactList.count() ); 235 QArray<int> uid_list( m_contactList.count() );
204 236
205 uint counter = 0; 237 uint counter = 0;
206 QValueListConstIterator<OContact> it; 238 QListIterator<OContact> it( m_contactList );
207 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 239 for( ; it.current(); ++it ){
208 uid_list[counter++] = (*it).uid(); 240 uid_list[counter++] = (*it)->uid();
209 } 241 }
210 242
211 return ( uid_list ); 243 return ( uid_list );
@@ -213,31 +245,26 @@ QArray<int> OContactAccessBackend_XML::allRecords() const
213 245
214OContact OContactAccessBackend_XML::find ( int uid ) const 246OContact OContactAccessBackend_XML::find ( int uid ) const
215{ 247{
216 bool found = false;
217 OContact foundContact; //Create empty contact 248 OContact foundContact; //Create empty contact
218 249
219 QValueListConstIterator<OContact> it; 250 OContact* found = m_uidToContact.find( QString().setNum( uid ) );
220 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 251
221 if ((*it).uid() == uid){
222 found = true;
223 break;
224 }
225 }
226 if ( found ){ 252 if ( found ){
227 foundContact = *it; 253 foundContact = *found;
228 } 254 }
229 255
230 return ( foundContact ); 256 return ( foundContact );
231} 257}
232 258
233QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings ) 259QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, int settings,
260 const QDateTime& d )
234{ 261{
235 262
236 QArray<int> m_currentQuery( m_contactList.count() ); 263 QArray<int> m_currentQuery( m_contactList.count() );
237 QValueListConstIterator<OContact> it; 264 QListIterator<OContact> it( m_contactList );
238 uint arraycounter = 0; 265 uint arraycounter = 0;
239 266
240 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 267 for( ; it.current(); ++it ){
241 /* Search all fields and compare them with query object. Store them into list 268 /* Search all fields and compare them with query object. Store them into list
242 * if all fields matches. 269 * if all fields matches.
243 */ 270 */
@@ -250,11 +277,11 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
250 switch ( i ){ 277 switch ( i ){
251 case Qtopia::Birthday: 278 case Qtopia::Birthday:
252 queryDate = new QDate( query.birthday() ); 279 queryDate = new QDate( query.birthday() );
253 checkDate = new QDate( (*it).birthday() ); 280 checkDate = new QDate( (*it)->birthday() );
254 case Qtopia::Anniversary: 281 case Qtopia::Anniversary:
255 if ( queryDate == 0l ){ 282 if ( queryDate == 0l ){
256 queryDate = new QDate( query.anniversary() ); 283 queryDate = new QDate( query.anniversary() );
257 checkDate = new QDate( (*it).anniversary() ); 284 checkDate = new QDate( (*it)->anniversary() );
258 } 285 }
259 286
260 if ( queryDate->isValid() ){ 287 if ( queryDate->isValid() ){
@@ -272,7 +299,15 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
272 allcorrect = false; 299 allcorrect = false;
273 } 300 }
274 if ( settings & OContactAccess::DateDiff ) { 301 if ( settings & OContactAccess::DateDiff ) {
275 QDate current = QDate::currentDate(); 302 QDate current;
303 // If we get an additional date, we
304 // will take this date instead of
305 // the current one..
306 if ( !d.date().isValid() )
307 current = QDate::currentDate();
308 else
309 current = d.date();
310
276 // We have to equalize the year, otherwise 311 // We have to equalize the year, otherwise
277 // the search will fail.. 312 // the search will fail..
278 checkDate->setYMD( current.year(), 313 checkDate->setYMD( current.year(),
@@ -282,6 +317,10 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
282 checkDate->setYMD( current.year()+1, 317 checkDate->setYMD( current.year()+1,
283 checkDate->month(), 318 checkDate->month(),
284 checkDate->day() ); 319 checkDate->day() );
320
321 // Check whether the birthday/anniversary date is between
322 // the current/given date and the maximum date
323 // ( maximum time range ) !
285 qWarning("Checking if %s is between %s and %s ! ", 324 qWarning("Checking if %s is between %s and %s ! ",
286 checkDate->toString().latin1(), 325 checkDate->toString().latin1(),
287 current.toString().latin1(), 326 current.toString().latin1(),
@@ -295,7 +334,7 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
295 } 334 }
296 } 335 }
297 } else{ 336 } else{
298 // checkDate is invalid. Therfore this entry is always rejected 337 // checkDate is invalid. Therefore this entry is always rejected
299 allcorrect = false; 338 allcorrect = false;
300 } 339 }
301 } 340 }
@@ -320,7 +359,7 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
320 QRegExp expr ( query.field(i), 359 QRegExp expr ( query.field(i),
321 !(settings & OContactAccess::IgnoreCase), 360 !(settings & OContactAccess::IgnoreCase),
322 false ); 361 false );
323 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 362 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
324 allcorrect = false; 363 allcorrect = false;
325 } 364 }
326 break; 365 break;
@@ -328,17 +367,17 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
328 QRegExp expr ( query.field(i), 367 QRegExp expr ( query.field(i),
329 !(settings & OContactAccess::IgnoreCase), 368 !(settings & OContactAccess::IgnoreCase),
330 true ); 369 true );
331 if ( expr.find ( (*it).field(i), 0 ) == -1 ) 370 if ( expr.find ( (*it)->field(i), 0 ) == -1 )
332 allcorrect = false; 371 allcorrect = false;
333 } 372 }
334 break; 373 break;
335 case OContactAccess::ExactMatch:{ 374 case OContactAccess::ExactMatch:{
336 if (settings & OContactAccess::IgnoreCase){ 375 if (settings & OContactAccess::IgnoreCase){
337 if ( query.field(i).upper() != 376 if ( query.field(i).upper() !=
338 (*it).field(i).upper() ) 377 (*it)->field(i).upper() )
339 allcorrect = false; 378 allcorrect = false;
340 }else{ 379 }else{
341 if ( query.field(i) != (*it).field(i) ) 380 if ( query.field(i) != (*it)->field(i) )
342 allcorrect = false; 381 allcorrect = false;
343 } 382 }
344 } 383 }
@@ -348,7 +387,7 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
348 } 387 }
349 } 388 }
350 if ( allcorrect ){ 389 if ( allcorrect ){
351 m_currentQuery[arraycounter++] = (*it).uid(); 390 m_currentQuery[arraycounter++] = (*it)->uid();
352 } 391 }
353 } 392 }
354 393
@@ -361,12 +400,12 @@ QArray<int> OContactAccessBackend_XML::queryByExample ( const OContact &query, i
361QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const 400QArray<int> OContactAccessBackend_XML::matchRegexp( const QRegExp &r ) const
362{ 401{
363 QArray<int> m_currentQuery( m_contactList.count() ); 402 QArray<int> m_currentQuery( m_contactList.count() );
364 QValueListConstIterator<OContact> it; 403 QListIterator<OContact> it( m_contactList );
365 uint arraycounter = 0; 404 uint arraycounter = 0;
366 405
367 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 406 for( ; it.current(); ++it ){
368 if ( (*it).match( r ) ){ 407 if ( (*it)->match( r ) ){
369 m_currentQuery[arraycounter++] = (*it).uid(); 408 m_currentQuery[arraycounter++] = (*it)->uid();
370 } 409 }
371 410
372 } 411 }
@@ -426,10 +465,10 @@ QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
426 465
427 // First fill map and StringList with all Names 466 // First fill map and StringList with all Names
428 // Afterwards sort namelist and use map to fill array to return.. 467 // Afterwards sort namelist and use map to fill array to return..
429 QValueListConstIterator<OContact> it; 468 QListIterator<OContact> it( m_contactList );
430 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 469 for( ; it.current(); ++it ){
431 names.append( (*it).fileAs() + QString::number( (*it).uid() ) ); 470 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
432 nameToUid.insert( (*it).fileAs() + QString::number( (*it).uid() ), (*it).uid() ); 471 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
433 } 472 }
434 names.sort(); 473 names.sort();
435 474
@@ -461,19 +500,19 @@ bool OContactAccessBackend_XML::replace ( const OContact &contact )
461{ 500{
462 m_changed = true; 501 m_changed = true;
463 502
464 bool found = false; 503 OContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
465 504
466 QValueListIterator<OContact> it; 505 if ( found ) {
467 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 506 OContact* newCont = new OContact( contact );
468 if ( (*it).uid() == contact.uid() ){ 507
469 found = true; 508 updateJournal ( *newCont, ACTION_REPLACE);
470 break; 509 m_contactList.removeRef ( found );
471 } 510 m_contactList.append ( newCont );
472 } 511 m_uidToContact.remove( QString().setNum( contact.uid() ) );
473 if (found) { 512 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
474 updateJournal (contact, ACTION_REPLACE); 513
475 m_contactList.remove (it); 514 qWarning("Nur zur Sicherheit: %d == %d ?",contact.uid(), newCont->uid());
476 m_contactList.append (contact); 515
477 return true; 516 return true;
478 } else 517 } else
479 return false; 518 return false;
@@ -483,17 +522,13 @@ bool OContactAccessBackend_XML::remove ( int uid )
483{ 522{
484 m_changed = true; 523 m_changed = true;
485 524
486 bool found = false; 525 OContact* found = m_uidToContact.find ( QString().setNum( uid ) );
487 QValueListIterator<OContact> it; 526
488 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){ 527 if ( found ) {
489 if ((*it).uid() == uid){ 528 updateJournal ( *found, ACTION_REMOVE);
490 found = true; 529 m_contactList.removeRef ( found );
491 break; 530 m_uidToContact.remove( QString().setNum( uid ) );
492 } 531
493 }
494 if (found) {
495 updateJournal ( *it, ACTION_REMOVE);
496 m_contactList.remove (it);
497 return true; 532 return true;
498 } else 533 } else
499 return false; 534 return false;
@@ -506,7 +541,10 @@ bool OContactAccessBackend_XML::reload(){
506 541
507void OContactAccessBackend_XML::addContact_p( const OContact &newcontact ) 542void OContactAccessBackend_XML::addContact_p( const OContact &newcontact )
508{ 543{
509 m_contactList.append (newcontact); 544 OContact* contRef = new OContact( newcontact );
545
546 m_contactList.append ( contRef );
547 m_uidToContact.insert( QString().setNum( newcontact.uid() ), contRef );
510} 548}
511 549
512/* This function loads the xml-database and the journalfile */ 550/* This function loads the xml-database and the journalfile */
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
index 6477705..4d6a7ef 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
@@ -17,6 +17,20 @@
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.13 2003/03/21 10:33:09 eilers
21 * Merged speed optimized xml backend for contacts to main.
22 * Added QDateTime to querybyexample. For instance, it is now possible to get
23 * all Birthdays/Anniversaries between two dates. This should be used
24 * to show all birthdays in the datebook..
25 * This change is sourcecode backward compatible but you have to upgrade
26 * the binaries for today-addressbook.
27 *
28 * Revision 1.12.2.2 2003/02/11 12:17:28 eilers
29 * Speed optimization. Removed the sequential search loops.
30 *
31 * Revision 1.12.2.1 2003/02/09 15:05:01 eilers
32 * Nothing happened.. Just some cleanup before I will start..
33 *
20 * Revision 1.12 2003/01/03 16:58:03 eilers 34 * Revision 1.12 2003/01/03 16:58:03 eilers
21 * Reenable debug output 35 * Reenable debug output
22 * 36 *
@@ -63,681 +77,68 @@
63#ifndef _OContactAccessBackend_XML_ 77#ifndef _OContactAccessBackend_XML_
64#define _OContactAccessBackend_XML_ 78#define _OContactAccessBackend_XML_
65 79
66#include <qasciidict.h>
67#include <qdatetime.h>
68#include <qfile.h>
69#include <qfileinfo.h>
70#include <qregexp.h>
71#include <qarray.h>
72#include <qmap.h>
73#include <qdatetime.h>
74
75#include <qpe/global.h>
76
77#include <opie/xmltree.h>
78#include "ocontactaccessbackend.h" 80#include "ocontactaccessbackend.h"
79#include "ocontactaccess.h" 81#include "ocontactaccess.h"
80 82
81#include <stdlib.h> 83#include <qlist.h>
82#include <errno.h> 84#include <qdict.h>
83
84using namespace Opie;
85 85
86/* the default xml implementation */ 86/* the default xml implementation */
87class OContactAccessBackend_XML : public OContactAccessBackend { 87class OContactAccessBackend_XML : public OContactAccessBackend {
88 public: 88 public:
89 OContactAccessBackend_XML ( QString appname, QString filename = 0l ): 89 OContactAccessBackend_XML ( QString appname, QString filename = 0l );
90 m_changed( false )
91 {
92 m_appName = appname;
93
94 /* Set journalfile name ... */
95 m_journalName = getenv("HOME");
96 m_journalName +="/.abjournal" + appname;
97
98 /* Expecting to access the default filename if nothing else is set */
99 if ( filename.isEmpty() ){
100 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
101 } else
102 m_fileName = filename;
103
104 /* Load Database now */
105 load ();
106 }
107 90
108 bool save() { 91 bool save();
109
110 if ( !m_changed )
111 return true;
112
113 QString strNewFile = m_fileName + ".new";
114 QFile f( strNewFile );
115 if ( !f.open( IO_WriteOnly|IO_Raw ) )
116 return false;
117
118 int total_written;
119 QString out;
120 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
121 " <Groups>\n"
122 " </Groups>\n"
123 " <Contacts>\n";
124 //QValueList<Contact>::iterator it;
125 QValueListConstIterator<OContact> it;
126 for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
127 out += "<Contact ";
128 (*it).save( out );
129 out += "/>\n";
130 QCString cstr = out.utf8();
131 total_written = f.writeBlock( cstr.data(), cstr.length() );
132 if ( total_written != int(cstr.length()) ) {
133 f.close();
134 QFile::remove( strNewFile );
135 return false;
136 }
137 out = "";
138 }
139 out += " </Contacts>\n</AddressBook>\n";
140
141 QCString cstr = out.utf8();
142 total_written = f.writeBlock( cstr.data(), cstr.length() );
143 if ( total_written != int( cstr.length() ) ) {
144 f.close();
145 QFile::remove( strNewFile );
146 return false;
147 }
148 f.close();
149
150 // move the file over, I'm just going to use the system call
151 // because, I don't feel like using QDir.
152 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
153 qWarning( "problem renaming file %s to %s, errno: %d",
154 strNewFile.latin1(), m_journalName.latin1(), errno );
155 // remove the tmp file...
156 QFile::remove( strNewFile );
157 }
158
159 /* The journalfile should be removed now... */
160 removeJournal();
161
162 m_changed = false;
163 return true;
164 }
165 92
166 bool load () { 93 bool load ();
167 m_contactList.clear();
168
169 /* Load XML-File and journal if it exists */
170 if ( !load ( m_fileName, false ) )
171 return false;
172 /* The returncode of the journalfile is ignored due to the
173 * fact that it does not exist when this class is instantiated !
174 * But there may such a file exist, if the application crashed.
175 * Therefore we try to load it to get the changes before the #
176 * crash happened...
177 */
178 load (m_journalName, true);
179
180 return true;
181 }
182
183 void clear () {
184 m_contactList.clear();
185 m_changed = false;
186 94
187 } 95 void clear ();
188 96
189 bool wasChangedExternally() 97 bool wasChangedExternally();
190 {
191 QFileInfo fi( m_fileName );
192
193 QDateTime lastmod = fi.lastModified ();
194
195 return (lastmod != m_readtime);
196 }
197 98
198 QArray<int> allRecords() const { 99 QArray<int> allRecords() const;
199 QArray<int> uid_list( m_contactList.count() );
200
201 uint counter = 0;
202 QValueListConstIterator<OContact> it;
203 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
204 uid_list[counter++] = (*it).uid();
205 }
206
207 return ( uid_list );
208 }
209 100
210 OContact find ( int uid ) const 101 OContact find ( int uid ) const;
211 {
212 bool found = false;
213 OContact foundContact; //Create empty contact
214
215 QValueListConstIterator<OContact> it;
216 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
217 if ((*it).uid() == uid){
218 found = true;
219 break;
220 }
221 }
222 if ( found ){
223 foundContact = *it;
224 }
225
226 return ( foundContact );
227 }
228 102
229 QArray<int> queryByExample ( const OContact &query, int settings ){ 103 QArray<int> queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() );
230
231 QArray<int> m_currentQuery( m_contactList.count() );
232 QValueListConstIterator<OContact> it;
233 uint arraycounter = 0;
234
235 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
236 /* Search all fields and compare them with query object. Store them into list
237 * if all fields matches.
238 */
239 QDate* queryDate = 0l;
240 QDate* checkDate = 0l;
241 bool allcorrect = true;
242 for ( int i = 0; i < Qtopia::Groups; i++ ) {
243 // Birthday and anniversary are special nonstring fields and should
244 // be handled specially
245 switch ( i ){
246 case Qtopia::Birthday:
247 queryDate = new QDate( query.birthday() );
248 checkDate = new QDate( (*it).birthday() );
249 case Qtopia::Anniversary:
250 if ( queryDate == 0l ){
251 queryDate = new QDate( query.anniversary() );
252 checkDate = new QDate( (*it).anniversary() );
253 }
254
255 if ( queryDate->isValid() ){
256 if( checkDate->isValid() ){
257 if ( settings & OContactAccess::DateYear ){
258 if ( queryDate->year() != checkDate->year() )
259 allcorrect = false;
260 }
261 if ( settings & OContactAccess::DateMonth ){
262 if ( queryDate->month() != checkDate->month() )
263 allcorrect = false;
264 }
265 if ( settings & OContactAccess::DateDay ){
266 if ( queryDate->day() != checkDate->day() )
267 allcorrect = false;
268 }
269 if ( settings & OContactAccess::DateDiff ) {
270 QDate current = QDate::currentDate();
271 // We have to equalize the year, otherwise
272 // the search will fail..
273 checkDate->setYMD( current.year(),
274 checkDate->month(),
275 checkDate->day() );
276 if ( *checkDate < current )
277 checkDate->setYMD( current.year()+1,
278 checkDate->month(),
279 checkDate->day() );
280 qWarning("Checking if %s is between %s and %s ! ",
281 checkDate->toString().latin1(),
282 current.toString().latin1(),
283 queryDate->toString().latin1() );
284 if ( current.daysTo( *queryDate ) > 0 ){
285 if ( !( ( *checkDate >= current ) &&
286 ( *checkDate <= *queryDate ) ) ){
287 allcorrect = false;
288 qWarning (" Nope!..");
289 }
290 }
291 }
292 } else{
293 // checkDate is invalid. Therfore this entry is always rejected
294 allcorrect = false;
295 }
296 }
297
298 delete queryDate;
299 queryDate = 0l;
300 delete checkDate;
301 checkDate = 0l;
302 break;
303 default:
304 /* Just compare fields which are not empty in the query object */
305 if ( !query.field(i).isEmpty() ){
306 switch ( settings & ~( OContactAccess::IgnoreCase
307 | OContactAccess::DateDiff
308 | OContactAccess::DateYear
309 | OContactAccess::DateMonth
310 | OContactAccess::DateDay
311 | OContactAccess::MatchOne
312 ) ){
313 104
314 case OContactAccess::RegExp:{ 105 QArray<int> matchRegexp( const QRegExp &r ) const;
315 QRegExp expr ( query.field(i),
316 !(settings & OContactAccess::IgnoreCase),
317 false );
318 if ( expr.find ( (*it).field(i), 0 ) == -1 )
319 allcorrect = false;
320 }
321 break;
322 case OContactAccess::WildCards:{
323 QRegExp expr ( query.field(i),
324 !(settings & OContactAccess::IgnoreCase),
325 true );
326 if ( expr.find ( (*it).field(i), 0 ) == -1 )
327 allcorrect = false;
328 }
329 break;
330 case OContactAccess::ExactMatch:{
331 if (settings & OContactAccess::IgnoreCase){
332 if ( query.field(i).upper() !=
333 (*it).field(i).upper() )
334 allcorrect = false;
335 }else{
336 if ( query.field(i) != (*it).field(i) )
337 allcorrect = false;
338 }
339 }
340 break;
341 }
342 }
343 }
344 }
345 if ( allcorrect ){
346 m_currentQuery[arraycounter++] = (*it).uid();
347 }
348 }
349
350 // Shrink to fit..
351 m_currentQuery.resize(arraycounter);
352 106
353 return m_currentQuery; 107 const uint querySettings();
354 }
355
356 QArray<int> matchRegexp( const QRegExp &r ) const{
357 QArray<int> m_currentQuery( m_contactList.count() );
358 QValueListConstIterator<OContact> it;
359 uint arraycounter = 0;
360
361 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
362 if ( (*it).match( r ) ){
363 m_currentQuery[arraycounter++] = (*it).uid();
364 }
365
366 }
367 // Shrink to fit..
368 m_currentQuery.resize(arraycounter);
369
370 return m_currentQuery;
371 }
372
373 const uint querySettings()
374 {
375 return ( OContactAccess::WildCards
376 | OContactAccess::IgnoreCase
377 | OContactAccess::RegExp
378 | OContactAccess::ExactMatch
379 | OContactAccess::DateDiff
380 | OContactAccess::DateYear
381 | OContactAccess::DateMonth
382 | OContactAccess::DateDay
383 );
384 }
385 108
386 bool hasQuerySettings (uint querySettings) const 109 bool hasQuerySettings (uint querySettings) const;
387 {
388 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
389 * may be added with any of the other settings. IgnoreCase should never used alone.
390 * Wildcards, RegExp, ExactMatch should never used at the same time...
391 */
392
393 if ( querySettings == OContactAccess::IgnoreCase )
394 return false;
395
396 switch ( querySettings & ~( OContactAccess::IgnoreCase
397 | OContactAccess::DateDiff
398 | OContactAccess::DateYear
399 | OContactAccess::DateMonth
400 | OContactAccess::DateDay
401 )
402 ){
403 case OContactAccess::RegExp:
404 return ( true );
405 case OContactAccess::WildCards:
406 return ( true );
407 case OContactAccess::ExactMatch:
408 return ( true );
409 default:
410 return ( false );
411 }
412 }
413 110
414 // Currently only asc implemented.. 111 // Currently only asc implemented..
415 QArray<int> sorted( bool asc, int , int , int ) 112 QArray<int> sorted( bool asc, int , int , int );
416 { 113 bool add ( const OContact &newcontact );
417 QMap<QString, int> nameToUid;
418 QStringList names;
419 QArray<int> m_currentQuery( m_contactList.count() );
420
421 // First fill map and StringList with all Names
422 // Afterwards sort namelist and use map to fill array to return..
423 QValueListConstIterator<OContact> it;
424 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
425 names.append( (*it).fileAs() + QString::number( (*it).uid() ) );
426 nameToUid.insert( (*it).fileAs() + QString::number( (*it).uid() ), (*it).uid() );
427 }
428 names.sort();
429
430 int i = 0;
431 if ( asc ){
432 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
433 m_currentQuery[i++] = nameToUid[ (*it) ];
434 }else{
435 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
436 m_currentQuery[i++] = nameToUid[ (*it) ];
437 }
438
439 return m_currentQuery;
440
441 }
442 bool add ( const OContact &newcontact )
443 {
444 //qWarning("odefaultbackend: ACTION::ADD");
445 updateJournal (newcontact, ACTION_ADD);
446 addContact_p( newcontact );
447
448 m_changed = true;
449
450 return true;
451 }
452
453 bool replace ( const OContact &contact )
454 {
455 m_changed = true;
456
457 bool found = false;
458
459 QValueListIterator<OContact> it;
460 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
461 if ( (*it).uid() == contact.uid() ){
462 found = true;
463 break;
464 }
465 }
466 if (found) {
467 updateJournal (contact, ACTION_REPLACE);
468 m_contactList.remove (it);
469 m_contactList.append (contact);
470 return true;
471 } else
472 return false;
473 }
474 114
475 bool remove ( int uid ) 115 bool replace ( const OContact &contact );
476 {
477 m_changed = true;
478
479 bool found = false;
480 QValueListIterator<OContact> it;
481 for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
482 if ((*it).uid() == uid){
483 found = true;
484 break;
485 }
486 }
487 if (found) {
488 updateJournal ( *it, ACTION_REMOVE);
489 m_contactList.remove (it);
490 return true;
491 } else
492 return false;
493 }
494 116
495 bool reload(){ 117 bool remove ( int uid );
496 /* Reload is the same as load in this implementation */ 118 bool reload();
497 return ( load() );
498 }
499 119
500 private: 120 private:
501 121
502 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; 122 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
503 123
504 void addContact_p( const OContact &newcontact ){ 124 void addContact_p( const OContact &newcontact );
505 m_contactList.append (newcontact);
506 }
507 125
508 /* This function loads the xml-database and the journalfile */ 126 /* This function loads the xml-database and the journalfile */
509 bool load( const QString filename, bool isJournal ) { 127 bool load( const QString filename, bool isJournal );
510
511 /* We use the time of the last read to check if the file was
512 * changed externally.
513 */
514 if ( !isJournal ){
515 QFileInfo fi( filename );
516 m_readtime = fi.lastModified ();
517 }
518
519 const int JOURNALACTION = Qtopia::Notes + 1;
520 const int JOURNALROW = JOURNALACTION + 1;
521
522 bool foundAction = false;
523 journal_action action = ACTION_ADD;
524 int journalKey = 0;
525 QMap<int, QString> contactMap;
526 QMap<QString, QString> customMap;
527 QMap<QString, QString>::Iterator customIt;
528 QAsciiDict<int> dict( 47 );
529
530 dict.setAutoDelete( TRUE );
531 dict.insert( "Uid", new int(Qtopia::AddressUid) );
532 dict.insert( "Title", new int(Qtopia::Title) );
533 dict.insert( "FirstName", new int(Qtopia::FirstName) );
534 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
535 dict.insert( "LastName", new int(Qtopia::LastName) );
536 dict.insert( "Suffix", new int(Qtopia::Suffix) );
537 dict.insert( "FileAs", new int(Qtopia::FileAs) );
538 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
539 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
540 dict.insert( "Emails", new int(Qtopia::Emails) );
541 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
542 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
543 dict.insert( "HomeState", new int(Qtopia::HomeState) );
544 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
545 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
546 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
547 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
548 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
549 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
550 dict.insert( "Company", new int(Qtopia::Company) );
551 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
552 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
553 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
554 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
555 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
556 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
557 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
558 dict.insert( "Department", new int(Qtopia::Department) );
559 dict.insert( "Office", new int(Qtopia::Office) );
560 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
561 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
562 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
563 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
564 dict.insert( "Profession", new int(Qtopia::Profession) );
565 dict.insert( "Assistant", new int(Qtopia::Assistant) );
566 dict.insert( "Manager", new int(Qtopia::Manager) );
567 dict.insert( "Spouse", new int(Qtopia::Spouse) );
568 dict.insert( "Children", new int(Qtopia::Children) );
569 dict.insert( "Gender", new int(Qtopia::Gender) );
570 dict.insert( "Birthday", new int(Qtopia::Birthday) );
571 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
572 dict.insert( "Nickname", new int(Qtopia::Nickname) );
573 dict.insert( "Notes", new int(Qtopia::Notes) );
574 dict.insert( "action", new int(JOURNALACTION) );
575 dict.insert( "actionrow", new int(JOURNALROW) );
576
577 //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
578
579 XMLElement *root = XMLElement::load( filename );
580 if(root != 0l ){ // start parsing
581 /* Parse all XML-Elements and put the data into the
582 * Contact-Class
583 */
584 XMLElement *element = root->firstChild();
585 //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
586 element = element->firstChild();
587
588 /* Search Tag "Contacts" which is the parent of all Contacts */
589 while( element && !isJournal ){
590 if( element->tagName() != QString::fromLatin1("Contacts") ){
591 //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
592 // element->tagName().latin1());
593 element = element->nextChild();
594 } else {
595 element = element->firstChild();
596 break;
597 }
598 }
599 /* Parse all Contacts and ignore unknown tags */
600 while( element ){
601 if( element->tagName() != QString::fromLatin1("Contact") ){
602 //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
603 // element->tagName().latin1());
604 element = element->nextChild();
605 continue;
606 }
607 /* Found alement with tagname "contact", now parse and store all
608 * attributes contained
609 */
610 //qWarning("OContactDefBack::load element tagName() : %s",
611 // element->tagName().latin1() );
612 QString dummy;
613 foundAction = false;
614
615 XMLElement::AttributeMap aMap = element->attributes();
616 XMLElement::AttributeMap::Iterator it;
617 contactMap.clear();
618 customMap.clear();
619 for( it = aMap.begin(); it != aMap.end(); ++it ){
620 // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
621
622 int *find = dict[ it.key() ];
623 /* Unknown attributes will be stored as "Custom" elements */
624 if ( !find ) {
625 qWarning("Attribute %s not known.", it.key().latin1());
626 //contact.setCustomField(it.key(), it.data());
627 customMap.insert( it.key(), it.data() );
628 continue;
629 }
630
631 /* Check if special conversion is needed and add attribute
632 * into Contact class
633 */
634 switch( *find ) {
635 /*
636 case Qtopia::AddressUid:
637 contact.setUid( it.data().toInt() );
638 break;
639 case Qtopia::AddressCategory:
640 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
641 break;
642 */
643 case JOURNALACTION:
644 action = journal_action(it.data().toInt());
645 foundAction = true;
646 qWarning ("ODefBack(journal)::ACTION found: %d", action);
647 break;
648 case JOURNALROW:
649 journalKey = it.data().toInt();
650 break;
651 default: // no conversion needed add them to the map
652 contactMap.insert( *find, it.data() );
653 break;
654 }
655 }
656 /* now generate the Contact contact */
657 OContact contact( contactMap );
658
659 for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
660 contact.setCustomField( customIt.key(), customIt.data() );
661 }
662
663 if (foundAction){
664 foundAction = false;
665 switch ( action ) {
666 case ACTION_ADD:
667 addContact_p (contact);
668 break;
669 case ACTION_REMOVE:
670 if ( !remove (contact.uid()) )
671 qWarning ("ODefBack(journal)::Unable to remove uid: %d",
672 contact.uid() );
673 break;
674 case ACTION_REPLACE:
675 if ( !replace ( contact ) )
676 qWarning ("ODefBack(journal)::Unable to replace uid: %d",
677 contact.uid() );
678 break;
679 default:
680 qWarning ("Unknown action: ignored !");
681 break;
682 }
683 }else{
684 /* Add contact to list */
685 addContact_p (contact);
686 }
687
688 /* Move to next element */
689 element = element->nextChild();
690 }
691 }else {
692 qWarning("ODefBack::could not load");
693 }
694 delete root;
695 qWarning("returning from loading" );
696 return true;
697 }
698
699 128
700 void updateJournal( const OContact& cnt,
701 journal_action action ) {
702 QFile f( m_journalName );
703 bool created = !f.exists();
704 if ( !f.open(IO_WriteOnly|IO_Append) )
705 return;
706
707 QString buf;
708 QCString str;
709
710 // if the file was created, we have to set the Tag "<CONTACTS>" to
711 // get a XML-File which is readable by our parser.
712 // This is just a cheat, but better than rewrite the parser.
713 if ( created ){
714 buf = "<Contacts>";
715 QCString cstr = buf.utf8();
716 f.writeBlock( cstr.data(), cstr.length() );
717 }
718
719 buf = "<Contact ";
720 cnt.save( buf );
721 buf += " action=\"" + QString::number( (int)action ) + "\" ";
722 buf += "/>\n";
723 QCString cstr = buf.utf8();
724 f.writeBlock( cstr.data(), cstr.length() );
725 }
726 129
727 void removeJournal() 130 void updateJournal( const OContact& cnt, journal_action action );
728 { 131 void removeJournal();
729 QFile f ( m_journalName );
730 if ( f.exists() )
731 f.remove();
732 }
733 132
734 protected: 133 protected:
735 bool m_changed; 134 bool m_changed;
736 QString m_journalName; 135 QString m_journalName;
737 QString m_fileName; 136 QString m_fileName;
738 QString m_appName; 137 QString m_appName;
739 QValueList<OContact> m_contactList; 138 QList<OContact> m_contactList;
740 QDateTime m_readtime; 139 QDateTime m_readtime;
140
141 QDict<OContact> m_uidToContact;
741}; 142};
742 143
743#endif 144#endif
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index 4a6b7b8..11e19d9 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -244,7 +244,7 @@ QArray<int> ODateBookAccessBackend_XML::allRecords()const {
244 244
245 return ints; 245 return ints;
246} 246}
247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int ) { 247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
248 return QArray<int>(); 248 return QArray<int>();
249} 249}
250void ODateBookAccessBackend_XML::clear() { 250void ODateBookAccessBackend_XML::clear() {
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
index 40f69d8..563c31f 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
@@ -16,7 +16,7 @@ public:
16 bool save(); 16 bool save();
17 17
18 QArray<int> allRecords()const; 18 QArray<int> allRecords()const;
19 QArray<int> queryByExample( const OEvent&, int ); 19 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
20 OEvent find( int uid )const; 20 OEvent find( int uid )const;
21 void clear(); 21 void clear();
22 bool add( const OEvent& ev ); 22 bool add( const OEvent& ev );
diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h
index e268f4f..01a0c86 100644
--- a/libopie2/opiepim/backend/opimaccessbackend.h
+++ b/libopie2/opiepim/backend/opimaccessbackend.h
@@ -47,10 +47,10 @@ public:
47 virtual QArray<int> allRecords()const = 0; 47 virtual QArray<int> allRecords()const = 0;
48 48
49 /** 49 /**
50 * queryByExample for T with the SortOrder 50 * queryByExample for T with the given Settings
51 * sort 51 *
52 */ 52 */
53 virtual QArray<int> queryByExample( const T& t, int sort ) = 0; 53 virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0;
54 54
55 /** 55 /**
56 * find the OPimRecord with uid @param uid 56 * find the OPimRecord with uid @param uid
diff --git a/libopie2/opiepim/backend/otodoaccesssql.cpp b/libopie2/opiepim/backend/otodoaccesssql.cpp
index 761d7d8..ec9c14c 100644
--- a/libopie2/opiepim/backend/otodoaccesssql.cpp
+++ b/libopie2/opiepim/backend/otodoaccesssql.cpp
@@ -277,7 +277,7 @@ QArray<int> OTodoAccessBackendSQL::allRecords()const {
277 277
278 return m_uids; 278 return m_uids;
279} 279}
280QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int ){ 280QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
281 QArray<int> ints(0); 281 QArray<int> ints(0);
282 return ints; 282 return ints;
283} 283}
diff --git a/libopie2/opiepim/backend/otodoaccesssql.h b/libopie2/opiepim/backend/otodoaccesssql.h
index 0f6dd2c..6a4257c 100644
--- a/libopie2/opiepim/backend/otodoaccesssql.h
+++ b/libopie2/opiepim/backend/otodoaccesssql.h
@@ -18,7 +18,7 @@ public:
18 bool save(); 18 bool save();
19 QArray<int> allRecords()const; 19 QArray<int> allRecords()const;
20 20
21 QArray<int> queryByExample( const OTodo& t, int sort ); 21 QArray<int> queryByExample( const OTodo& t, int settings, const QDateTime& d = QDateTime() );
22 OTodo find(int uid)const; 22 OTodo find(int uid)const;
23 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 23 OTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
24 void clear(); 24 void clear();
diff --git a/libopie2/opiepim/backend/otodoaccessvcal.cpp b/libopie2/opiepim/backend/otodoaccessvcal.cpp
index 309f9e1..2136283 100644
--- a/libopie2/opiepim/backend/otodoaccessvcal.cpp
+++ b/libopie2/opiepim/backend/otodoaccessvcal.cpp
@@ -185,7 +185,7 @@ QArray<int> OTodoAccessVCal::allRecords()const {
185 } 185 }
186 return ar; 186 return ar;
187} 187}
188QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int ) { 188QArray<int> OTodoAccessVCal::queryByExample( const OTodo&, int, const QDateTime& ) {
189 QArray<int> ar(0); 189 QArray<int> ar(0);
190 return ar; 190 return ar;
191} 191}
diff --git a/libopie2/opiepim/backend/otodoaccessvcal.h b/libopie2/opiepim/backend/otodoaccessvcal.h
index 452f602..a90ee9c 100644
--- a/libopie2/opiepim/backend/otodoaccessvcal.h
+++ b/libopie2/opiepim/backend/otodoaccessvcal.h
@@ -13,7 +13,7 @@ public:
13 bool save(); 13 bool save();
14 14
15 QArray<int> allRecords()const; 15 QArray<int> allRecords()const;
16 QArray<int> queryByExample( const OTodo& t, int sort ); 16 QArray<int> queryByExample( const OTodo& t, int sort, const QDateTime& d = QDateTime() );
17 QArray<int> effectiveToDos( const QDate& start, 17 QArray<int> effectiveToDos( const QDate& start,
18 const QDate& end, 18 const QDate& end,
19 bool includeNoDates ); 19 bool includeNoDates );
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp
index cda300b..71e8787 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.cpp
+++ b/libopie2/opiepim/backend/otodoaccessxml.cpp
@@ -255,7 +255,7 @@ QArray<int> OTodoAccessXML::allRecords()const {
255 } 255 }
256 return ids; 256 return ids;
257} 257}
258QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int ) { 258QArray<int> OTodoAccessXML::queryByExample( const OTodo&, int, const QDateTime& ) {
259 QArray<int> ids(0); 259 QArray<int> ids(0);
260 return ids; 260 return ids;
261} 261}
diff --git a/libopie2/opiepim/backend/otodoaccessxml.h b/libopie2/opiepim/backend/otodoaccessxml.h
index 93609fe..1032c92 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.h
+++ b/libopie2/opiepim/backend/otodoaccessxml.h
@@ -24,7 +24,7 @@ public:
24 bool save(); 24 bool save();
25 25
26 QArray<int> allRecords()const; 26 QArray<int> allRecords()const;
27 QArray<int> queryByExample( const OTodo&, int querysettings ); 27 QArray<int> queryByExample( const OTodo&, int querysettings, const QDateTime& d = QDateTime() );
28 OTodo find( int uid )const; 28 OTodo find( int uid )const;
29 void clear(); 29 void clear();
30 bool add( const OTodo& ); 30 bool add( const OTodo& );
diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h
index 259e2c1..6a3a0db 100644
--- a/libopie2/opiepim/core/opimaccesstemplate.h
+++ b/libopie2/opiepim/core/opimaccesstemplate.h
@@ -74,7 +74,7 @@ public:
74 * queryByExample. 74 * queryByExample.
75 * @see otodoaccess, ocontactaccess 75 * @see otodoaccess, ocontactaccess
76 */ 76 */
77 virtual List queryByExample( const T& t, int querySettings ); 77 virtual List queryByExample( const T& t, int querySettings, const QDateTime& d = QDateTime() );
78 78
79 /** 79 /**
80 * find the OPimRecord uid 80 * find the OPimRecord uid
@@ -186,8 +186,8 @@ QArray<int> OPimAccessTemplate<T>::records()const {
186} 186}
187template <class T> 187template <class T>
188typename OPimAccessTemplate<T>::List 188typename OPimAccessTemplate<T>::List
189OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 189OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime& d ) {
190 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 190 QArray<int> ints = m_backEnd->queryByExample( t, settings, d );
191 191
192 List lis(ints, this ); 192 List lis(ints, this );
193 return lis; 193 return lis;