summaryrefslogtreecommitdiff
path: root/libopie2
authoreilers <eilers>2003-03-21 10:33:09 (UTC)
committer eilers <eilers>2003-03-21 10:33:09 (UTC)
commit8136284c38384b169cd2843ee61480d45b6c1cba (patch) (unidiff)
treead798e3df8dc27a41f431a2130dbf50947fbca49 /libopie2
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 (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-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
14 files changed, 173 insertions, 718 deletions
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
@@ -1,67 +1,75 @@
1/* 1/*
2 * VCard Backend for the OPIE-Contact Database. 2 * VCard Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved. 4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 * 6 *
7 * ===================================================================== 7 * =====================================================================
8 *This program is free software; you can redistribute it and/or 8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public 9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version. 11 * version 2 of the License, or (at your option) any later version.
12 * ===================================================================== 12 * =====================================================================
13 * ToDo: 13 * ToDo:
14 * 14 *
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
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
23 * -Guard against self assignment in OTodo 31 * -Guard against self assignment in OTodo
24 * -Add test apps for OPIM 32 * -Add test apps for OPIM
25 * -Opiefied Event classes 33 * -Opiefied Event classes
26 * -Added TimeZone handling and pinning of TimeZones to OEvent 34 * -Added TimeZone handling and pinning of TimeZones to OEvent
27 * -Adjust ORecur and the widget to better timezone behaviour 35 * -Adjust ORecur and the widget to better timezone behaviour
28 * 36 *
29 * Revision 1.7 2003/02/16 22:25:46 zecke 37 * Revision 1.7 2003/02/16 22:25:46 zecke
30 * 0000276 Fix for that bug.. or better temp workaround 38 * 0000276 Fix for that bug.. or better temp workaround
31 * A Preferred Number is HOME|VOICE 39 * A Preferred Number is HOME|VOICE
32 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test 40 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test
33 * triggers both 41 * triggers both
34 * and the cell phone number overrides the other entries.. 42 * and the cell phone number overrides the other entries..
35 * 43 *
36 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the 44 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the
37 * number 45 * number
38 * 46 *
39 * The right and final fix would be to reorder the if statement to make it 47 * The right and final fix would be to reorder the if statement to make it
40 * if else based and the less common thing put to the bottom 48 * if else based and the less common thing put to the bottom
41 * 49 *
42 * OTodoAccessVcal fix the date for beaming 50 * OTodoAccessVcal fix the date for beaming
43 * 51 *
44 * Revision 1.6 2003/01/13 15:49:31 eilers 52 * Revision 1.6 2003/01/13 15:49:31 eilers
45 * Fixing crash when businesscard.vcf is missing.. 53 * Fixing crash when businesscard.vcf is missing..
46 * 54 *
47 * Revision 1.5 2002/12/07 13:26:22 eilers 55 * Revision 1.5 2002/12/07 13:26:22 eilers
48 * Fixing bug in storing anniversary.. 56 * Fixing bug in storing anniversary..
49 * 57 *
50 * Revision 1.4 2002/11/13 14:14:51 eilers 58 * Revision 1.4 2002/11/13 14:14:51 eilers
51 * Added sorted for Contacts.. 59 * Added sorted for Contacts..
52 * 60 *
53 * Revision 1.3 2002/11/11 16:41:09 kergoth 61 * Revision 1.3 2002/11/11 16:41:09 kergoth
54 * no default arguments in implementation 62 * no default arguments in implementation
55 * 63 *
56 * Revision 1.2 2002/11/10 15:41:53 eilers 64 * Revision 1.2 2002/11/10 15:41:53 eilers
57 * Bugfixes.. 65 * Bugfixes..
58 * 66 *
59 * Revision 1.1 2002/11/09 14:34:52 eilers 67 * Revision 1.1 2002/11/09 14:34:52 eilers
60 * Added VCard Backend. 68 * Added VCard Backend.
61 * 69 *
62 */ 70 */
63#include "ocontactaccessbackend_vcard.h" 71#include "ocontactaccessbackend_vcard.h"
64#include "../../library/backend/vobject_p.h" 72#include "../../library/backend/vobject_p.h"
65#include "../../library/backend/qfiledirect_p.h" 73#include "../../library/backend/qfiledirect_p.h"
66 74
67#include <qpe/timeconversion.h> 75#include <qpe/timeconversion.h>
@@ -144,97 +152,97 @@ bool OContactAccessBackend_VCard::save()
144 152
145 153
146} 154}
147void OContactAccessBackend_VCard::clear () 155void OContactAccessBackend_VCard::clear ()
148{ 156{
149 m_map.clear(); 157 m_map.clear();
150 m_dirty = true; // ??? sure ? (se) 158 m_dirty = true; // ??? sure ? (se)
151} 159}
152 160
153bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) 161bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
154{ 162{
155 m_map.insert( newcontact.uid(), newcontact ); 163 m_map.insert( newcontact.uid(), newcontact );
156 m_dirty = true; 164 m_dirty = true;
157 return true; 165 return true;
158} 166}
159 167
160bool OContactAccessBackend_VCard::remove ( int uid ) 168bool OContactAccessBackend_VCard::remove ( int uid )
161{ 169{
162 m_map.remove( uid ); 170 m_map.remove( uid );
163 m_dirty = true; 171 m_dirty = true;
164 return true; 172 return true;
165} 173}
166 174
167bool OContactAccessBackend_VCard::replace ( const OContact &contact ) 175bool OContactAccessBackend_VCard::replace ( const OContact &contact )
168{ 176{
169 m_map.replace( contact.uid(), contact ); 177 m_map.replace( contact.uid(), contact );
170 m_dirty = true; 178 m_dirty = true;
171 return true; 179 return true;
172} 180}
173 181
174OContact OContactAccessBackend_VCard::find ( int uid ) const 182OContact OContactAccessBackend_VCard::find ( int uid ) const
175{ 183{
176 return m_map[uid]; 184 return m_map[uid];
177} 185}
178 186
179QArray<int> OContactAccessBackend_VCard::allRecords() const 187QArray<int> OContactAccessBackend_VCard::allRecords() const
180{ 188{
181 QArray<int> ar( m_map.count() ); 189 QArray<int> ar( m_map.count() );
182 QMap<int, OContact>::ConstIterator it; 190 QMap<int, OContact>::ConstIterator it;
183 int i = 0; 191 int i = 0;
184 for ( it = m_map.begin(); it != m_map.end(); ++it ) { 192 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
185 ar[i] = it.key(); 193 ar[i] = it.key();
186 i++; 194 i++;
187 } 195 }
188 return ar; 196 return ar;
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;
196} 204}
197 205
198// Not implemented 206// Not implemented
199QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const 207QArray<int> OContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
200{ 208{
201 QArray<int> ar(0); 209 QArray<int> ar(0);
202 return ar; 210 return ar;
203} 211}
204 212
205const uint OContactAccessBackend_VCard::querySettings() 213const uint OContactAccessBackend_VCard::querySettings()
206{ 214{
207 return 0; // No search possible 215 return 0; // No search possible
208} 216}
209 217
210bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const 218bool OContactAccessBackend_VCard::hasQuerySettings (uint ) const
211{ 219{
212 return false; // No search possible, therefore all settings invalid ;) 220 return false; // No search possible, therefore all settings invalid ;)
213} 221}
214 222
215bool OContactAccessBackend_VCard::wasChangedExternally() 223bool OContactAccessBackend_VCard::wasChangedExternally()
216{ 224{
217 return false; // Don't expect concurrent access 225 return false; // Don't expect concurrent access
218} 226}
219 227
220// Not implemented 228// Not implemented
221QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int ) 229QArray<int> OContactAccessBackend_VCard::sorted( bool , int, int, int )
222{ 230{
223 QArray<int> ar(0); 231 QArray<int> ar(0);
224 return ar; 232 return ar;
225} 233}
226 234
227// *** Private stuff *** 235// *** Private stuff ***
228 236
229 237
230OContact OContactAccessBackend_VCard::parseVObject( VObject *obj ) 238OContact OContactAccessBackend_VCard::parseVObject( VObject *obj )
231{ 239{
232 OContact c; 240 OContact c;
233 241
234 VObjectIterator it; 242 VObjectIterator it;
235 initPropIterator( &it, obj ); 243 initPropIterator( &it, obj );
236 while( moreIteration( &it ) ) { 244 while( moreIteration( &it ) ) {
237 VObject *o = nextVObject( &it ); 245 VObject *o = nextVObject( &it );
238 QCString name = vObjectName( o ); 246 QCString name = vObjectName( o );
239 QCString value = vObjectStringZValue( o ); 247 QCString value = vObjectStringZValue( o );
240 if ( name == VCNameProp ) { 248 if ( name == VCNameProp ) {
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
@@ -1,78 +1,86 @@
1/* 1/*
2 * VCard Backend for the OPIE-Contact Database. 2 * VCard Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved. 4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 * 6 *
7 * ===================================================================== 7 * =====================================================================
8 *This program is free software; you can redistribute it and/or 8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public 9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version. 11 * version 2 of the License, or (at your option) any later version.
12 * ===================================================================== 12 * =====================================================================
13 * ToDo: 13 * ToDo:
14 * 14 *
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.5 2003/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 *
23 * Revision 1.3 2002/11/13 14:14:51 eilers 31 * Revision 1.3 2002/11/13 14:14:51 eilers
24 * Added sorted for Contacts.. 32 * Added sorted for Contacts..
25 * 33 *
26 * Revision 1.2 2002/11/10 15:41:53 eilers 34 * Revision 1.2 2002/11/10 15:41:53 eilers
27 * Bugfixes.. 35 * Bugfixes..
28 * 36 *
29 * Revision 1.1 2002/11/09 14:34:52 eilers 37 * Revision 1.1 2002/11/09 14:34:52 eilers
30 * Added VCard Backend. 38 * Added VCard Backend.
31 * 39 *
32 */ 40 */
33#ifndef __OCONTACTACCESSBACKEND_VCARD_H_ 41#ifndef __OCONTACTACCESSBACKEND_VCARD_H_
34#define __OCONTACTACCESSBACKEND_VCARD_H_ 42#define __OCONTACTACCESSBACKEND_VCARD_H_
35 43
36#include <opie/ocontact.h> 44#include <opie/ocontact.h>
37 45
38#include "ocontactaccessbackend.h" 46#include "ocontactaccessbackend.h"
39 47
40class VObject; 48class VObject;
41 49
42class OContactAccessBackend_VCard : public OContactAccessBackend { 50class OContactAccessBackend_VCard : public OContactAccessBackend {
43 public: 51 public:
44 OContactAccessBackend_VCard ( QString appname, QString filename = 0l ); 52 OContactAccessBackend_VCard ( QString appname, QString filename = 0l );
45 53
46 bool load (); 54 bool load ();
47 bool reload(); 55 bool reload();
48 bool save(); 56 bool save();
49 void clear (); 57 void clear ();
50 58
51 bool add ( const OContact& newcontact ); 59 bool add ( const OContact& newcontact );
52 bool remove ( int uid ); 60 bool remove ( int uid );
53 bool replace ( const OContact& contact ); 61 bool replace ( const OContact& contact );
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();
61 bool hasQuerySettings (uint querySettings) const; 69 bool hasQuerySettings (uint querySettings) const;
62 QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat ); 70 QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat );
63 bool wasChangedExternally(); 71 bool wasChangedExternally();
64 72
65private: 73private:
66 OContact parseVObject( VObject* obj ); 74 OContact parseVObject( VObject* obj );
67 VObject* createVObject( const OContact& c ); 75 VObject* createVObject( const OContact& c );
68 QString convDateToVCardDate( const QDate& c ) const; 76 QString convDateToVCardDate( const QDate& c ) const;
69 QDate convVCardDateToDate( const QString& datestr ); 77 QDate convVCardDateToDate( const QString& datestr );
70 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value ); 78 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
71 VObject *safeAddProp( VObject* o, const char* prop); 79 VObject *safeAddProp( VObject* o, const char* prop);
72 80
73 bool m_dirty : 1; 81 bool m_dirty : 1;
74 QString m_file; 82 QString m_file;
75 QMap<int, OContact> m_map; 83 QMap<int, OContact> m_map;
76}; 84};
77 85
78#endif 86#endif
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
@@ -1,557 +1,595 @@
1/* 1/*
2 * XML Backend for the OPIE-Contact Database. 2 * XML Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * ToDo: XML-Backend: Automatic reload if something was changed... 12 * ToDo: XML-Backend: Automatic reload if something was changed...
13 * 13 *
14 * 14 *
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.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 *
23 * Revision 1.12 2003/01/03 16:58:03 eilers 37 * Revision 1.12 2003/01/03 16:58:03 eilers
24 * Reenable debug output 38 * Reenable debug output
25 * 39 *
26 * Revision 1.11 2003/01/03 12:31:28 eilers 40 * Revision 1.11 2003/01/03 12:31:28 eilers
27 * Bugfix for calculating data diffs.. 41 * Bugfix for calculating data diffs..
28 * 42 *
29 * Revision 1.10 2003/01/02 14:27:12 eilers 43 * Revision 1.10 2003/01/02 14:27:12 eilers
30 * Improved query by example: Search by date is possible.. First step 44 * Improved query by example: Search by date is possible.. First step
31 * for a today plugin for birthdays.. 45 * for a today plugin for birthdays..
32 * 46 *
33 * Revision 1.9 2002/12/08 12:48:57 eilers 47 * Revision 1.9 2002/12/08 12:48:57 eilers
34 * Moved journal-enum from ocontact into i the xml-backend.. 48 * Moved journal-enum from ocontact into i the xml-backend..
35 * 49 *
36 * Revision 1.8 2002/11/14 17:04:24 eilers 50 * Revision 1.8 2002/11/14 17:04:24 eilers
37 * Sorting will now work if fullname is identical on some entries 51 * Sorting will now work if fullname is identical on some entries
38 * 52 *
39 * Revision 1.7 2002/11/13 15:02:46 eilers 53 * Revision 1.7 2002/11/13 15:02:46 eilers
40 * Small Bug in sorted fixed 54 * Small Bug in sorted fixed
41 * 55 *
42 * Revision 1.6 2002/11/13 14:14:51 eilers 56 * Revision 1.6 2002/11/13 14:14:51 eilers
43 * Added sorted for Contacts.. 57 * Added sorted for Contacts..
44 * 58 *
45 * Revision 1.5 2002/11/01 15:10:42 eilers 59 * Revision 1.5 2002/11/01 15:10:42 eilers
46 * Added regExp-search in database for all fields in a contact. 60 * Added regExp-search in database for all fields in a contact.
47 * 61 *
48 * Revision 1.4 2002/10/16 10:52:40 eilers 62 * Revision 1.4 2002/10/16 10:52:40 eilers
49 * Added some docu to the interface and now using the cache infrastucture by zecke.. :) 63 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
50 * 64 *
51 * Revision 1.3 2002/10/14 16:21:54 eilers 65 * Revision 1.3 2002/10/14 16:21:54 eilers
52 * Some minor interface updates 66 * Some minor interface updates
53 * 67 *
54 * Revision 1.2 2002/10/07 17:34:24 eilers 68 * Revision 1.2 2002/10/07 17:34:24 eilers
55 * added OBackendFactory for advanced backend access 69 * added OBackendFactory for advanced backend access
56 * 70 *
57 * Revision 1.1 2002/09/27 17:11:44 eilers 71 * Revision 1.1 2002/09/27 17:11:44 eilers
58 * Added API for accessing the Contact-Database ! It is compiling, but 72 * Added API for accessing the Contact-Database ! It is compiling, but
59 * please do not expect that anything is working ! 73 * please do not expect that anything is working !
60 * I will debug that stuff in the next time .. 74 * I will debug that stuff in the next time ..
61 * Please read README_COMPILE for compiling ! 75 * Please read README_COMPILE for compiling !
62 * 76 *
63 * 77 *
64 */ 78 */
65 79
66#include "ocontactaccessbackend_xml.h" 80#include "ocontactaccessbackend_xml.h"
67 81
68#include <qasciidict.h> 82#include <qasciidict.h>
69#include <qdatetime.h> 83#include <qdatetime.h>
70#include <qfile.h> 84#include <qfile.h>
71#include <qfileinfo.h> 85#include <qfileinfo.h>
72#include <qregexp.h> 86#include <qregexp.h>
73#include <qarray.h> 87#include <qarray.h>
74#include <qmap.h> 88#include <qmap.h>
75#include <qdatetime.h> 89#include <qdatetime.h>
76 90
77#include <qpe/global.h> 91#include <qpe/global.h>
78 92
79#include <opie/xmltree.h> 93#include <opie/xmltree.h>
80#include "ocontactaccessbackend.h" 94#include "ocontactaccessbackend.h"
81#include "ocontactaccess.h" 95#include "ocontactaccess.h"
82 96
83#include <stdlib.h> 97#include <stdlib.h>
84#include <errno.h> 98#include <errno.h>
85 99
86using namespace Opie; 100using namespace Opie;
87 101
88 102
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 ... */
95 m_journalName = getenv("HOME"); 114 m_journalName = getenv("HOME");
96 m_journalName +="/.abjournal" + appname; 115 m_journalName +="/.abjournal" + appname;
97 116
98 /* Expecting to access the default filename if nothing else is set */ 117 /* Expecting to access the default filename if nothing else is set */
99 if ( filename.isEmpty() ){ 118 if ( filename.isEmpty() ){
100 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" ); 119 m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
101 } else 120 } else
102 m_fileName = filename; 121 m_fileName = filename;
103 122
104 /* Load Database now */ 123 /* Load Database now */
105 load (); 124 load ();
106} 125}
107 126
108bool OContactAccessBackend_XML::save() 127bool OContactAccessBackend_XML::save()
109{ 128{
110 129
111 if ( !m_changed ) 130 if ( !m_changed )
112 return true; 131 return true;
113 132
114 QString strNewFile = m_fileName + ".new"; 133 QString strNewFile = m_fileName + ".new";
115 QFile f( strNewFile ); 134 QFile f( strNewFile );
116 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 135 if ( !f.open( IO_WriteOnly|IO_Raw ) )
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 );
136 return false; 165 return false;
137 } 166 }
138 out = ""; 167 out = "";
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();
146 QFile::remove( strNewFile ); 176 QFile::remove( strNewFile );
147 return false; 177 return false;
148 } 178 }
149 f.close(); 179 f.close();
150 180
151 // move the file over, I'm just going to use the system call 181 // move the file over, I'm just going to use the system call
152 // because, I don't feel like using QDir. 182 // because, I don't feel like using QDir.
153 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 183 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
154 qWarning( "problem renaming file %s to %s, errno: %d", 184 qWarning( "problem renaming file %s to %s, errno: %d",
155 strNewFile.latin1(), m_journalName.latin1(), errno ); 185 strNewFile.latin1(), m_journalName.latin1(), errno );
156 // remove the tmp file... 186 // remove the tmp file...
157 QFile::remove( strNewFile ); 187 QFile::remove( strNewFile );
158 } 188 }
159 189
160 /* The journalfile should be removed now... */ 190 /* The journalfile should be removed now... */
161 removeJournal(); 191 removeJournal();
162 192
163 m_changed = false; 193 m_changed = false;
164 return true; 194 return true;
165} 195}
166 196
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 ) )
173 return false; 204 return false;
174 /* The returncode of the journalfile is ignored due to the 205 /* The returncode of the journalfile is ignored due to the
175 * fact that it does not exist when this class is instantiated ! 206 * fact that it does not exist when this class is instantiated !
176 * But there may such a file exist, if the application crashed. 207 * But there may such a file exist, if the application crashed.
177 * Therefore we try to load it to get the changes before the # 208 * Therefore we try to load it to get the changes before the #
178 * crash happened... 209 * crash happened...
179 */ 210 */
180 load (m_journalName, true); 211 load (m_journalName, true);
181 212
182 return true; 213 return true;
183} 214}
184 215
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()
193{ 225{
194 QFileInfo fi( m_fileName ); 226 QFileInfo fi( m_fileName );
195 227
196 QDateTime lastmod = fi.lastModified (); 228 QDateTime lastmod = fi.lastModified ();
197 229
198 return (lastmod != m_readtime); 230 return (lastmod != m_readtime);
199} 231}
200 232
201QArray<int> OContactAccessBackend_XML::allRecords() const 233QArray<int> OContactAccessBackend_XML::allRecords() const
202{ 234{
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 );
212} 244}
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 */
244 QDate* queryDate = 0l; 271 QDate* queryDate = 0l;
245 QDate* checkDate = 0l; 272 QDate* checkDate = 0l;
246 bool allcorrect = true; 273 bool allcorrect = true;
247 for ( int i = 0; i < Qtopia::Groups; i++ ) { 274 for ( int i = 0; i < Qtopia::Groups; i++ ) {
248 // Birthday and anniversary are special nonstring fields and should 275 // Birthday and anniversary are special nonstring fields and should
249 // be handled specially 276 // be handled specially
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() ){
261 if( checkDate->isValid() ){ 288 if( checkDate->isValid() ){
262 if ( settings & OContactAccess::DateYear ){ 289 if ( settings & OContactAccess::DateYear ){
263 if ( queryDate->year() != checkDate->year() ) 290 if ( queryDate->year() != checkDate->year() )
264 allcorrect = false; 291 allcorrect = false;
265 } 292 }
266 if ( settings & OContactAccess::DateMonth ){ 293 if ( settings & OContactAccess::DateMonth ){
267 if ( queryDate->month() != checkDate->month() ) 294 if ( queryDate->month() != checkDate->month() )
268 allcorrect = false; 295 allcorrect = false;
269 } 296 }
270 if ( settings & OContactAccess::DateDay ){ 297 if ( settings & OContactAccess::DateDay ){
271 if ( queryDate->day() != checkDate->day() ) 298 if ( queryDate->day() != checkDate->day() )
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(),
279 checkDate->month(), 314 checkDate->month(),
280 checkDate->day() ); 315 checkDate->day() );
281 if ( *checkDate < current ) 316 if ( *checkDate < current )
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(),
288 queryDate->toString().latin1() ); 327 queryDate->toString().latin1() );
289 if ( current.daysTo( *queryDate ) > 0 ){ 328 if ( current.daysTo( *queryDate ) > 0 ){
290 if ( !( ( *checkDate >= current ) && 329 if ( !( ( *checkDate >= current ) &&
291 ( *checkDate <= *queryDate ) ) ){ 330 ( *checkDate <= *queryDate ) ) ){
292 allcorrect = false; 331 allcorrect = false;
293 qWarning (" Nope!.."); 332 qWarning (" Nope!..");
294 } 333 }
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 }
302 341
303 delete queryDate; 342 delete queryDate;
304 queryDate = 0l; 343 queryDate = 0l;
305 delete checkDate; 344 delete checkDate;
306 checkDate = 0l; 345 checkDate = 0l;
307 break; 346 break;
308 default: 347 default:
309 /* Just compare fields which are not empty in the query object */ 348 /* Just compare fields which are not empty in the query object */
310 if ( !query.field(i).isEmpty() ){ 349 if ( !query.field(i).isEmpty() ){
311 switch ( settings & ~( OContactAccess::IgnoreCase 350 switch ( settings & ~( OContactAccess::IgnoreCase
312 | OContactAccess::DateDiff 351 | OContactAccess::DateDiff
313 | OContactAccess::DateYear 352 | OContactAccess::DateYear
314 | OContactAccess::DateMonth 353 | OContactAccess::DateMonth
315 | OContactAccess::DateDay 354 | OContactAccess::DateDay
316 | OContactAccess::MatchOne 355 | OContactAccess::MatchOne
317 ) ){ 356 ) ){
318 357
319 case OContactAccess::RegExp:{ 358 case OContactAccess::RegExp:{
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;
327 case OContactAccess::WildCards:{ 366 case OContactAccess::WildCards:{
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 }
345 break; 384 break;
346 } 385 }
347 } 386 }
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
355 // Shrink to fit.. 394 // Shrink to fit..
356 m_currentQuery.resize(arraycounter); 395 m_currentQuery.resize(arraycounter);
357 396
358 return m_currentQuery; 397 return m_currentQuery;
359} 398}
360 399
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 }
373 // Shrink to fit.. 412 // Shrink to fit..
374 m_currentQuery.resize(arraycounter); 413 m_currentQuery.resize(arraycounter);
375 414
376 return m_currentQuery; 415 return m_currentQuery;
377} 416}
378 417
379const uint OContactAccessBackend_XML::querySettings() 418const uint OContactAccessBackend_XML::querySettings()
380{ 419{
381 return ( OContactAccess::WildCards 420 return ( OContactAccess::WildCards
382 | OContactAccess::IgnoreCase 421 | OContactAccess::IgnoreCase
383 | OContactAccess::RegExp 422 | OContactAccess::RegExp
384 | OContactAccess::ExactMatch 423 | OContactAccess::ExactMatch
385 | OContactAccess::DateDiff 424 | OContactAccess::DateDiff
386 | OContactAccess::DateYear 425 | OContactAccess::DateYear
387 | OContactAccess::DateMonth 426 | OContactAccess::DateMonth
388 | OContactAccess::DateDay 427 | OContactAccess::DateDay
389 ); 428 );
390} 429}
391 430
392bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const 431bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
393{ 432{
394 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay 433 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
395 * may be added with any of the other settings. IgnoreCase should never used alone. 434 * may be added with any of the other settings. IgnoreCase should never used alone.
396 * Wildcards, RegExp, ExactMatch should never used at the same time... 435 * Wildcards, RegExp, ExactMatch should never used at the same time...
397 */ 436 */
398 437
399 if ( querySettings == OContactAccess::IgnoreCase ) 438 if ( querySettings == OContactAccess::IgnoreCase )
400 return false; 439 return false;
401 440
402 switch ( querySettings & ~( OContactAccess::IgnoreCase 441 switch ( querySettings & ~( OContactAccess::IgnoreCase
403 | OContactAccess::DateDiff 442 | OContactAccess::DateDiff
404 | OContactAccess::DateYear 443 | OContactAccess::DateYear
405 | OContactAccess::DateMonth 444 | OContactAccess::DateMonth
406 | OContactAccess::DateDay 445 | OContactAccess::DateDay
407 ) 446 )
408 ){ 447 ){
409 case OContactAccess::RegExp: 448 case OContactAccess::RegExp:
410 return ( true ); 449 return ( true );
411 case OContactAccess::WildCards: 450 case OContactAccess::WildCards:
412 return ( true ); 451 return ( true );
413 case OContactAccess::ExactMatch: 452 case OContactAccess::ExactMatch:
414 return ( true ); 453 return ( true );
415 default: 454 default:
416 return ( false ); 455 return ( false );
417 } 456 }
418} 457}
419 458
420// Currently only asc implemented.. 459// Currently only asc implemented..
421QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int ) 460QArray<int> OContactAccessBackend_XML::sorted( bool asc, int , int , int )
422{ 461{
423 QMap<QString, int> nameToUid; 462 QMap<QString, int> nameToUid;
424 QStringList names; 463 QStringList names;
425 QArray<int> m_currentQuery( m_contactList.count() ); 464 QArray<int> m_currentQuery( m_contactList.count() );
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
436 int i = 0; 475 int i = 0;
437 if ( asc ){ 476 if ( asc ){
438 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) 477 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
439 m_currentQuery[i++] = nameToUid[ (*it) ]; 478 m_currentQuery[i++] = nameToUid[ (*it) ];
440 }else{ 479 }else{
441 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it ) 480 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
442 m_currentQuery[i++] = nameToUid[ (*it) ]; 481 m_currentQuery[i++] = nameToUid[ (*it) ];
443 } 482 }
444 483
445 return m_currentQuery; 484 return m_currentQuery;
446 485
447} 486}
448 487
449bool OContactAccessBackend_XML::add ( const OContact &newcontact ) 488bool OContactAccessBackend_XML::add ( const OContact &newcontact )
450{ 489{
451 //qWarning("odefaultbackend: ACTION::ADD"); 490 //qWarning("odefaultbackend: ACTION::ADD");
452 updateJournal (newcontact, ACTION_ADD); 491 updateJournal (newcontact, ACTION_ADD);
453 addContact_p( newcontact ); 492 addContact_p( newcontact );
454 493
455 m_changed = true; 494 m_changed = true;
456 495
457 return true; 496 return true;
458} 497}
459 498
460bool OContactAccessBackend_XML::replace ( const OContact &contact ) 499bool 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;
480} 519}
481 520
482bool OContactAccessBackend_XML::remove ( int uid ) 521bool 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;
500} 535}
501 536
502bool OContactAccessBackend_XML::reload(){ 537bool OContactAccessBackend_XML::reload(){
503 /* Reload is the same as load in this implementation */ 538 /* Reload is the same as load in this implementation */
504 return ( load() ); 539 return ( load() );
505} 540}
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 */
513bool OContactAccessBackend_XML::load( const QString filename, bool isJournal ) 551bool OContactAccessBackend_XML::load( const QString filename, bool isJournal )
514{ 552{
515 553
516 /* We use the time of the last read to check if the file was 554 /* We use the time of the last read to check if the file was
517 * changed externally. 555 * changed externally.
518 */ 556 */
519 if ( !isJournal ){ 557 if ( !isJournal ){
520 QFileInfo fi( filename ); 558 QFileInfo fi( filename );
521 m_readtime = fi.lastModified (); 559 m_readtime = fi.lastModified ();
522 } 560 }
523 561
524 const int JOURNALACTION = Qtopia::Notes + 1; 562 const int JOURNALACTION = Qtopia::Notes + 1;
525 const int JOURNALROW = JOURNALACTION + 1; 563 const int JOURNALROW = JOURNALACTION + 1;
526 564
527 bool foundAction = false; 565 bool foundAction = false;
528 journal_action action = ACTION_ADD; 566 journal_action action = ACTION_ADD;
529 int journalKey = 0; 567 int journalKey = 0;
530 QMap<int, QString> contactMap; 568 QMap<int, QString> contactMap;
531 QMap<QString, QString> customMap; 569 QMap<QString, QString> customMap;
532 QMap<QString, QString>::Iterator customIt; 570 QMap<QString, QString>::Iterator customIt;
533 QAsciiDict<int> dict( 47 ); 571 QAsciiDict<int> dict( 47 );
534 572
535 dict.setAutoDelete( TRUE ); 573 dict.setAutoDelete( TRUE );
536 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 574 dict.insert( "Uid", new int(Qtopia::AddressUid) );
537 dict.insert( "Title", new int(Qtopia::Title) ); 575 dict.insert( "Title", new int(Qtopia::Title) );
538 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 576 dict.insert( "FirstName", new int(Qtopia::FirstName) );
539 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 577 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
540 dict.insert( "LastName", new int(Qtopia::LastName) ); 578 dict.insert( "LastName", new int(Qtopia::LastName) );
541 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 579 dict.insert( "Suffix", new int(Qtopia::Suffix) );
542 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 580 dict.insert( "FileAs", new int(Qtopia::FileAs) );
543 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 581 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
544 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 582 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
545 dict.insert( "Emails", new int(Qtopia::Emails) ); 583 dict.insert( "Emails", new int(Qtopia::Emails) );
546 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 584 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
547 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 585 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
548 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 586 dict.insert( "HomeState", new int(Qtopia::HomeState) );
549 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 587 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
550 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 588 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
551 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 589 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
552 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 590 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
553 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 591 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
554 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 592 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
555 dict.insert( "Company", new int(Qtopia::Company) ); 593 dict.insert( "Company", new int(Qtopia::Company) );
556 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 594 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
557 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 595 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
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
@@ -1,743 +1,144 @@
1/* 1/*
2 * XML Backend for the OPIE-Contact Database. 2 * XML Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * ToDo: XML-Backend: Automatic reload if something was changed... 12 * ToDo: XML-Backend: Automatic reload if something was changed...
13 * 13 *
14 * 14 *
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.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 *
23 * Revision 1.11 2003/01/03 12:31:28 eilers 37 * Revision 1.11 2003/01/03 12:31:28 eilers
24 * Bugfix for calculating data diffs.. 38 * Bugfix for calculating data diffs..
25 * 39 *
26 * Revision 1.10 2003/01/02 14:27:12 eilers 40 * Revision 1.10 2003/01/02 14:27:12 eilers
27 * Improved query by example: Search by date is possible.. First step 41 * Improved query by example: Search by date is possible.. First step
28 * for a today plugin for birthdays.. 42 * for a today plugin for birthdays..
29 * 43 *
30 * Revision 1.9 2002/12/08 12:48:57 eilers 44 * Revision 1.9 2002/12/08 12:48:57 eilers
31 * Moved journal-enum from ocontact into i the xml-backend.. 45 * Moved journal-enum from ocontact into i the xml-backend..
32 * 46 *
33 * Revision 1.8 2002/11/14 17:04:24 eilers 47 * Revision 1.8 2002/11/14 17:04:24 eilers
34 * Sorting will now work if fullname is identical on some entries 48 * Sorting will now work if fullname is identical on some entries
35 * 49 *
36 * Revision 1.7 2002/11/13 15:02:46 eilers 50 * Revision 1.7 2002/11/13 15:02:46 eilers
37 * Small Bug in sorted fixed 51 * Small Bug in sorted fixed
38 * 52 *
39 * Revision 1.6 2002/11/13 14:14:51 eilers 53 * Revision 1.6 2002/11/13 14:14:51 eilers
40 * Added sorted for Contacts.. 54 * Added sorted for Contacts..
41 * 55 *
42 * Revision 1.5 2002/11/01 15:10:42 eilers 56 * Revision 1.5 2002/11/01 15:10:42 eilers
43 * Added regExp-search in database for all fields in a contact. 57 * Added regExp-search in database for all fields in a contact.
44 * 58 *
45 * Revision 1.4 2002/10/16 10:52:40 eilers 59 * Revision 1.4 2002/10/16 10:52:40 eilers
46 * Added some docu to the interface and now using the cache infrastucture by zecke.. :) 60 * Added some docu to the interface and now using the cache infrastucture by zecke.. :)
47 * 61 *
48 * Revision 1.3 2002/10/14 16:21:54 eilers 62 * Revision 1.3 2002/10/14 16:21:54 eilers
49 * Some minor interface updates 63 * Some minor interface updates
50 * 64 *
51 * Revision 1.2 2002/10/07 17:34:24 eilers 65 * Revision 1.2 2002/10/07 17:34:24 eilers
52 * added OBackendFactory for advanced backend access 66 * added OBackendFactory for advanced backend access
53 * 67 *
54 * Revision 1.1 2002/09/27 17:11:44 eilers 68 * Revision 1.1 2002/09/27 17:11:44 eilers
55 * Added API for accessing the Contact-Database ! It is compiling, but 69 * Added API for accessing the Contact-Database ! It is compiling, but
56 * please do not expect that anything is working ! 70 * please do not expect that anything is working !
57 * I will debug that stuff in the next time .. 71 * I will debug that stuff in the next time ..
58 * Please read README_COMPILE for compiling ! 72 * Please read README_COMPILE for compiling !
59 * 73 *
60 * 74 *
61 */ 75 */
62 76
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
@@ -199,97 +199,97 @@ bool ODateBookAccessBackend_XML::save() {
199 return false; 199 return false;
200 } 200 }
201 201
202 if (!forAll( m_raw, f ) ) { 202 if (!forAll( m_raw, f ) ) {
203 f.close(); 203 f.close();
204 QFile::remove( strFileNew ); 204 QFile::remove( strFileNew );
205 return false; 205 return false;
206 } 206 }
207 if (!forAll( m_rep, f ) ) { 207 if (!forAll( m_rep, f ) ) {
208 f.close(); 208 f.close();
209 QFile::remove( strFileNew ); 209 QFile::remove( strFileNew );
210 return false; 210 return false;
211 } 211 }
212 212
213 buf = "</events>\n</DATEBOOK>\n"; 213 buf = "</events>\n</DATEBOOK>\n";
214 str = buf.utf8(); 214 str = buf.utf8();
215 total_written = f.writeBlock( str.data(), str.length() ); 215 total_written = f.writeBlock( str.data(), str.length() );
216 if ( total_written != int(str.length() ) ) { 216 if ( total_written != int(str.length() ) ) {
217 f.close(); 217 f.close();
218 QFile::remove( strFileNew ); 218 QFile::remove( strFileNew );
219 return false; 219 return false;
220 } 220 }
221 f.close(); 221 f.close();
222 222
223 if ( ::rename( strFileNew, m_name ) < 0 ) { 223 if ( ::rename( strFileNew, m_name ) < 0 ) {
224 QFile::remove( strFileNew ); 224 QFile::remove( strFileNew );
225 return false; 225 return false;
226 } 226 }
227 227
228 m_changed = false; 228 m_changed = false;
229 return true; 229 return true;
230} 230}
231QArray<int> ODateBookAccessBackend_XML::allRecords()const { 231QArray<int> ODateBookAccessBackend_XML::allRecords()const {
232 QArray<int> ints( m_raw.count()+ m_rep.count() ); 232 QArray<int> ints( m_raw.count()+ m_rep.count() );
233 uint i = 0; 233 uint i = 0;
234 QMap<int, OEvent>::ConstIterator it; 234 QMap<int, OEvent>::ConstIterator it;
235 235
236 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 236 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
237 ints[i] = it.key(); 237 ints[i] = it.key();
238 i++; 238 i++;
239 } 239 }
240 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 240 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
241 ints[i] = it.key(); 241 ints[i] = it.key();
242 i++; 242 i++;
243 } 243 }
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() {
251 m_raw.clear(); 251 m_raw.clear();
252 m_rep.clear(); 252 m_rep.clear();
253} 253}
254OEvent ODateBookAccessBackend_XML::find( int uid ) const{ 254OEvent ODateBookAccessBackend_XML::find( int uid ) const{
255 if ( m_raw.contains( uid ) ) 255 if ( m_raw.contains( uid ) )
256 return m_raw[uid]; 256 return m_raw[uid];
257 else 257 else
258 return m_rep[uid]; 258 return m_rep[uid];
259} 259}
260bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { 260bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
261 m_changed = true; 261 m_changed = true;
262 if (ev.hasRecurrence() ) 262 if (ev.hasRecurrence() )
263 m_rep.insert( ev.uid(), ev ); 263 m_rep.insert( ev.uid(), ev );
264 else 264 else
265 m_raw.insert( ev.uid(), ev ); 265 m_raw.insert( ev.uid(), ev );
266 266
267 return true; 267 return true;
268} 268}
269bool ODateBookAccessBackend_XML::remove( int uid ) { 269bool ODateBookAccessBackend_XML::remove( int uid ) {
270 m_changed = true; 270 m_changed = true;
271 m_rep.remove( uid ); 271 m_rep.remove( uid );
272 m_rep.remove( uid ); 272 m_rep.remove( uid );
273 273
274 return true; 274 return true;
275} 275}
276bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { 276bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
277 replace( ev.uid() ); 277 replace( ev.uid() );
278 return add( ev ); 278 return add( ev );
279} 279}
280QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 280QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
281 return allRecords(); 281 return allRecords();
282} 282}
283QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 283QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
284 QArray<int> ints( m_rep.count() ); 284 QArray<int> ints( m_rep.count() );
285 uint i = 0; 285 uint i = 0;
286 QMap<int, OEvent>::ConstIterator it; 286 QMap<int, OEvent>::ConstIterator it;
287 287
288 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 288 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
289 ints[i] = it.key(); 289 ints[i] = it.key();
290 i++; 290 i++;
291 } 291 }
292 292
293 return ints; 293 return ints;
294} 294}
295QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 295QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
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
@@ -1,48 +1,48 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H 1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H 2#define OPIE_DATE_BOOK_ACCESS_BACKEND_XML__H
3 3
4#include <qmap.h> 4#include <qmap.h>
5 5
6#include "odatebookaccessbackend.h" 6#include "odatebookaccessbackend.h"
7 7
8class ODateBookAccessBackend_XML : public ODateBookAccessBackend { 8class ODateBookAccessBackend_XML : public ODateBookAccessBackend {
9public: 9public:
10 ODateBookAccessBackend_XML( const QString& appName, 10 ODateBookAccessBackend_XML( const QString& appName,
11 const QString& fileName = QString::null); 11 const QString& fileName = QString::null);
12 ~ODateBookAccessBackend_XML(); 12 ~ODateBookAccessBackend_XML();
13 13
14 bool load(); 14 bool load();
15 bool reload(); 15 bool reload();
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 );
23 bool remove( int uid ); 23 bool remove( int uid );
24 bool replace( const OEvent& ev ); 24 bool replace( const OEvent& ev );
25 25
26 QArray<UID> rawEvents()const; 26 QArray<UID> rawEvents()const;
27 QArray<UID> rawRepeats()const; 27 QArray<UID> rawRepeats()const;
28 QArray<UID> nonRepeats()const; 28 QArray<UID> nonRepeats()const;
29 29
30 OEvent::ValueList directNonRepeats(); 30 OEvent::ValueList directNonRepeats();
31 OEvent::ValueList directRawRepeats(); 31 OEvent::ValueList directRawRepeats();
32 32
33private: 33private:
34 bool m_changed :1 ; 34 bool m_changed :1 ;
35 bool loadFile(); 35 bool loadFile();
36 inline void finalizeRecord( OEvent& ev ); 36 inline void finalizeRecord( OEvent& ev );
37 inline void setField( OEvent&, int field, const QString& val ); 37 inline void setField( OEvent&, int field, const QString& val );
38 QString m_name; 38 QString m_name;
39 QMap<int, OEvent> m_raw; 39 QMap<int, OEvent> m_raw;
40 QMap<int, OEvent> m_rep; 40 QMap<int, OEvent> m_rep;
41 41
42 struct Data; 42 struct Data;
43 Data* data; 43 Data* data;
44 class Private; 44 class Private;
45 Private *d; 45 Private *d;
46}; 46};
47 47
48#endif 48#endif
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
@@ -2,100 +2,100 @@
2#define OPIE_PIM_ACCESS_BACKEND 2#define OPIE_PIM_ACCESS_BACKEND
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/otemplatebase.h> 6#include <opie/otemplatebase.h>
7#include <opie/opimrecord.h> 7#include <opie/opimrecord.h>
8 8
9 9
10/** 10/**
11 * OPimAccessBackend is the base class 11 * OPimAccessBackend is the base class
12 * for all private backends 12 * for all private backends
13 * it operates on OPimRecord as the base class 13 * it operates on OPimRecord as the base class
14 * and it's responsible for fast manipulating 14 * and it's responsible for fast manipulating
15 * the resource the implementation takes care 15 * the resource the implementation takes care
16 * of 16 * of
17 */ 17 */
18template <class T = OPimRecord> 18template <class T = OPimRecord>
19class OPimAccessBackend { 19class OPimAccessBackend {
20public: 20public:
21 typedef OTemplateBase<T> Frontend; 21 typedef OTemplateBase<T> Frontend;
22 22
23 /** The access hint from the frontend */ 23 /** The access hint from the frontend */
24 OPimAccessBackend(int access = 0); 24 OPimAccessBackend(int access = 0);
25 virtual ~OPimAccessBackend(); 25 virtual ~OPimAccessBackend();
26 26
27 /** 27 /**
28 * load the resource 28 * load the resource
29 */ 29 */
30 virtual bool load() = 0; 30 virtual bool load() = 0;
31 31
32 /** 32 /**
33 * reload the resource 33 * reload the resource
34 */ 34 */
35 virtual bool reload() = 0; 35 virtual bool reload() = 0;
36 36
37 /** 37 /**
38 * save the resource and 38 * save the resource and
39 * all it's changes 39 * all it's changes
40 */ 40 */
41 virtual bool save() = 0; 41 virtual bool save() = 0;
42 42
43 /** 43 /**
44 * return an array of 44 * return an array of
45 * all available uids 45 * all available uids
46 */ 46 */
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
57 * returns T and T.isEmpty() if nothing was found 57 * returns T and T.isEmpty() if nothing was found
58 */ 58 */
59 virtual T find(int uid )const = 0; 59 virtual T find(int uid )const = 0;
60 60
61 virtual T find(int uid, const QArray<int>& items, 61 virtual T find(int uid, const QArray<int>& items,
62 uint current, typename Frontend::CacheDirection )const ; 62 uint current, typename Frontend::CacheDirection )const ;
63 /** 63 /**
64 * clear the back end 64 * clear the back end
65 */ 65 */
66 virtual void clear() = 0; 66 virtual void clear() = 0;
67 67
68 /** 68 /**
69 * add T 69 * add T
70 */ 70 */
71 virtual bool add( const T& t ) = 0; 71 virtual bool add( const T& t ) = 0;
72 72
73 /** 73 /**
74 * remove 74 * remove
75 */ 75 */
76 virtual bool remove( int uid ) = 0; 76 virtual bool remove( int uid ) = 0;
77 77
78 /** 78 /**
79 * replace a record with T.uid() 79 * replace a record with T.uid()
80 */ 80 */
81 virtual bool replace( const T& t ) = 0; 81 virtual bool replace( const T& t ) = 0;
82 82
83 /* 83 /*
84 * setTheFrontEnd!!! 84 * setTheFrontEnd!!!
85 */ 85 */
86 void setFrontend( Frontend* front ); 86 void setFrontend( Frontend* front );
87 87
88 /** 88 /**
89 * set the read ahead count 89 * set the read ahead count
90 */ 90 */
91 void setReadAhead( uint count ); 91 void setReadAhead( uint count );
92protected: 92protected:
93 int access()const; 93 int access()const;
94 void cache( const T& t )const; 94 void cache( const T& t )const;
95 95
96 /** 96 /**
97 * use a prime number here! 97 * use a prime number here!
98 */ 98 */
99 void setSaneCacheSize( int ); 99 void setSaneCacheSize( int );
100 100
101 uint readAhead()const; 101 uint readAhead()const;
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
@@ -232,97 +232,97 @@ namespace {
232 } 232 }
233 QString EffQuery::out()const { 233 QString EffQuery::out()const {
234 QString str; 234 QString str;
235 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'") 235 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
236 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() ) 236 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
237 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() ); 237 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
238 238
239 return str; 239 return str;
240 } 240 }
241}; 241};
242 242
243OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file ) 243OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
244 : OTodoAccessBackend(), m_dict(15), m_dirty(true) 244 : OTodoAccessBackend(), m_dict(15), m_dirty(true)
245{ 245{
246 QString fi = file; 246 QString fi = file;
247 if ( fi.isEmpty() ) 247 if ( fi.isEmpty() )
248 fi = Global::applicationFileName( "todolist", "todolist.db" ); 248 fi = Global::applicationFileName( "todolist", "todolist.db" );
249 OSQLManager man; 249 OSQLManager man;
250 m_driver = man.standard(); 250 m_driver = man.standard();
251 m_driver->setUrl(fi); 251 m_driver->setUrl(fi);
252 fillDict(); 252 fillDict();
253} 253}
254 254
255OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){ 255OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
256} 256}
257bool OTodoAccessBackendSQL::load(){ 257bool OTodoAccessBackendSQL::load(){
258 if (!m_driver->open() ) 258 if (!m_driver->open() )
259 return false; 259 return false;
260 260
261 CreateQuery creat; 261 CreateQuery creat;
262 OSQLResult res = m_driver->query(&creat ); 262 OSQLResult res = m_driver->query(&creat );
263 263
264 m_dirty = true; 264 m_dirty = true;
265 return true; 265 return true;
266} 266}
267bool OTodoAccessBackendSQL::reload(){ 267bool OTodoAccessBackendSQL::reload(){
268 return load(); 268 return load();
269} 269}
270 270
271bool OTodoAccessBackendSQL::save(){ 271bool OTodoAccessBackendSQL::save(){
272 return m_driver->close(); 272 return m_driver->close();
273} 273}
274QArray<int> OTodoAccessBackendSQL::allRecords()const { 274QArray<int> OTodoAccessBackendSQL::allRecords()const {
275 if (m_dirty ) 275 if (m_dirty )
276 update(); 276 update();
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}
284OTodo OTodoAccessBackendSQL::find(int uid ) const{ 284OTodo OTodoAccessBackendSQL::find(int uid ) const{
285 FindQuery query( uid ); 285 FindQuery query( uid );
286 return todo( m_driver->query(&query) ); 286 return todo( m_driver->query(&query) );
287 287
288} 288}
289OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, 289OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
290 uint cur, Frontend::CacheDirection dir ) const{ 290 uint cur, Frontend::CacheDirection dir ) const{
291 int CACHE = readAhead(); 291 int CACHE = readAhead();
292 qWarning("searching for %d", uid ); 292 qWarning("searching for %d", uid );
293 QArray<int> search( CACHE ); 293 QArray<int> search( CACHE );
294 uint size =0; 294 uint size =0;
295 OTodo to; 295 OTodo to;
296 296
297 // we try to cache CACHE items 297 // we try to cache CACHE items
298 switch( dir ) { 298 switch( dir ) {
299 /* forward */ 299 /* forward */
300 case 0: 300 case 0:
301 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { 301 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
302 qWarning("size %d %d", size, ints[i] ); 302 qWarning("size %d %d", size, ints[i] );
303 search[size] = ints[i]; 303 search[size] = ints[i];
304 size++; 304 size++;
305 } 305 }
306 break; 306 break;
307 /* reverse */ 307 /* reverse */
308 case 1: 308 case 1:
309 for (uint i = cur; i != 0 && size < CACHE; i-- ) { 309 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
310 search[size] = ints[i]; 310 search[size] = ints[i];
311 size++; 311 size++;
312 } 312 }
313 break; 313 break;
314 } 314 }
315 search.resize( size ); 315 search.resize( size );
316 FindQuery query( search ); 316 FindQuery query( search );
317 OSQLResult res = m_driver->query( &query ); 317 OSQLResult res = m_driver->query( &query );
318 if ( res.state() != OSQLResult::Success ) 318 if ( res.state() != OSQLResult::Success )
319 return to; 319 return to;
320 320
321 return todo( res ); 321 return todo( res );
322} 322}
323void OTodoAccessBackendSQL::clear() { 323void OTodoAccessBackendSQL::clear() {
324 ClearQuery cle; 324 ClearQuery cle;
325 OSQLResult res = m_driver->query( &cle ); 325 OSQLResult res = m_driver->query( &cle );
326 CreateQuery qu; 326 CreateQuery qu;
327 res = m_driver->query(&qu); 327 res = m_driver->query(&qu);
328} 328}
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
@@ -1,50 +1,50 @@
1#ifndef OPIE_PIM_ACCESS_SQL_H 1#ifndef OPIE_PIM_ACCESS_SQL_H
2#define OPIE_PIM_ACCESS_SQL_H 2#define OPIE_PIM_ACCESS_SQL_H
3 3
4#include <qasciidict.h> 4#include <qasciidict.h>
5 5
6#include "otodoaccessbackend.h" 6#include "otodoaccessbackend.h"
7 7
8class OSQLDriver; 8class OSQLDriver;
9class OSQLResult; 9class OSQLResult;
10class OSQLResultItem; 10class OSQLResultItem;
11class OTodoAccessBackendSQL : public OTodoAccessBackend { 11class OTodoAccessBackendSQL : public OTodoAccessBackend {
12public: 12public:
13 OTodoAccessBackendSQL( const QString& file ); 13 OTodoAccessBackendSQL( const QString& file );
14 ~OTodoAccessBackendSQL(); 14 ~OTodoAccessBackendSQL();
15 15
16 bool load(); 16 bool load();
17 bool reload(); 17 bool reload();
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();
25 bool add( const OTodo& t ); 25 bool add( const OTodo& t );
26 bool remove( int uid ); 26 bool remove( int uid );
27 bool replace( const OTodo& t ); 27 bool replace( const OTodo& t );
28 28
29 QArray<int> overDue(); 29 QArray<int> overDue();
30 QArray<int> effectiveToDos( const QDate& start, 30 QArray<int> effectiveToDos( const QDate& start,
31 const QDate& end, bool includeNoDates ); 31 const QDate& end, bool includeNoDates );
32 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat ); 32 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat );
33 33
34private: 34private:
35 void update()const; 35 void update()const;
36 void fillDict(); 36 void fillDict();
37 inline bool date( QDate& date, const QString& )const; 37 inline bool date( QDate& date, const QString& )const;
38 inline OTodo todo( const OSQLResult& )const; 38 inline OTodo todo( const OSQLResult& )const;
39 inline OTodo todo( OSQLResultItem& )const; 39 inline OTodo todo( OSQLResultItem& )const;
40 inline QArray<int> uids( const OSQLResult& )const; 40 inline QArray<int> uids( const OSQLResult& )const;
41 OTodo todo( int uid )const; 41 OTodo todo( int uid )const;
42 42
43 QAsciiDict<int> m_dict; 43 QAsciiDict<int> m_dict;
44 OSQLDriver* m_driver; 44 OSQLDriver* m_driver;
45 QArray<int> m_uids; 45 QArray<int> m_uids;
46 bool m_dirty : 1; 46 bool m_dirty : 1;
47}; 47};
48 48
49 49
50#endif 50#endif
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
@@ -140,62 +140,62 @@ bool OTodoAccessVCal::save() {
140 cleanVObject( obj ); 140 cleanVObject( obj );
141 cleanStrTbl(); 141 cleanStrTbl();
142 142
143 m_dirty = false; 143 m_dirty = false;
144 return true; 144 return true;
145} 145}
146void OTodoAccessVCal::clear() { 146void OTodoAccessVCal::clear() {
147 m_map.clear(); 147 m_map.clear();
148 m_dirty = true; 148 m_dirty = true;
149} 149}
150bool OTodoAccessVCal::add( const OTodo& to ) { 150bool OTodoAccessVCal::add( const OTodo& to ) {
151 m_map.insert( to.uid(), to ); 151 m_map.insert( to.uid(), to );
152 m_dirty = true; 152 m_dirty = true;
153 return true; 153 return true;
154} 154}
155bool OTodoAccessVCal::remove( int uid ) { 155bool OTodoAccessVCal::remove( int uid ) {
156 m_map.remove( uid ); 156 m_map.remove( uid );
157 m_dirty = true; 157 m_dirty = true;
158 return true; 158 return true;
159} 159}
160void OTodoAccessVCal::removeAllCompleted() { 160void OTodoAccessVCal::removeAllCompleted() {
161 for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) { 161 for ( QMap<int, OTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) {
162 if ( (*it).isCompleted() ) 162 if ( (*it).isCompleted() )
163 m_map.remove( it ); 163 m_map.remove( it );
164 } 164 }
165} 165}
166bool OTodoAccessVCal::replace( const OTodo& to ) { 166bool OTodoAccessVCal::replace( const OTodo& to ) {
167 m_map.replace( to.uid(), to ); 167 m_map.replace( to.uid(), to );
168 m_dirty = true; 168 m_dirty = true;
169 return true; 169 return true;
170} 170}
171OTodo OTodoAccessVCal::find(int uid )const { 171OTodo OTodoAccessVCal::find(int uid )const {
172 return m_map[uid]; 172 return m_map[uid];
173} 173}
174QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) { 174QArray<int> OTodoAccessVCal::sorted( bool, int, int, int ) {
175 QArray<int> ar(0); 175 QArray<int> ar(0);
176 return ar; 176 return ar;
177} 177}
178QArray<int> OTodoAccessVCal::allRecords()const { 178QArray<int> OTodoAccessVCal::allRecords()const {
179 QArray<int> ar( m_map.count() ); 179 QArray<int> ar( m_map.count() );
180 QMap<int, OTodo>::ConstIterator it; 180 QMap<int, OTodo>::ConstIterator it;
181 int i = 0; 181 int i = 0;
182 for ( it = m_map.begin(); it != m_map.end(); ++it ) { 182 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
183 ar[i] = it.key(); 183 ar[i] = it.key();
184 i++; 184 i++;
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}
192QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& , 192QArray<int> OTodoAccessVCal::effectiveToDos( const QDate& ,
193 const QDate& , 193 const QDate& ,
194 bool ) { 194 bool ) {
195 QArray<int> ar(0); 195 QArray<int> ar(0);
196 return ar; 196 return ar;
197} 197}
198QArray<int> OTodoAccessVCal::overDue() { 198QArray<int> OTodoAccessVCal::overDue() {
199 QArray<int> ar(0); 199 QArray<int> ar(0);
200 return ar; 200 return ar;
201} 201}
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
@@ -1,37 +1,37 @@
1#ifndef OPIE_OTODO_ACCESS_VCAL_H 1#ifndef OPIE_OTODO_ACCESS_VCAL_H
2#define OPIE_OTODO_ACCESS_VCAL_H 2#define OPIE_OTODO_ACCESS_VCAL_H
3 3
4#include "otodoaccessbackend.h" 4#include "otodoaccessbackend.h"
5 5
6class OTodoAccessVCal : public OTodoAccessBackend { 6class OTodoAccessVCal : public OTodoAccessBackend {
7public: 7public:
8 OTodoAccessVCal(const QString& ); 8 OTodoAccessVCal(const QString& );
9 ~OTodoAccessVCal(); 9 ~OTodoAccessVCal();
10 10
11 bool load(); 11 bool load();
12 bool reload(); 12 bool reload();
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 );
20 QArray<int> overDue(); 20 QArray<int> overDue();
21 QArray<int> sorted( bool asc, int sortOrder, int sortFilter, 21 QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
22 int cat ); 22 int cat );
23 OTodo find(int uid)const; 23 OTodo find(int uid)const;
24 void clear(); 24 void clear();
25 bool add( const OTodo& ); 25 bool add( const OTodo& );
26 bool remove( int uid ); 26 bool remove( int uid );
27 bool replace( const OTodo& ); 27 bool replace( const OTodo& );
28 28
29 void removeAllCompleted(); 29 void removeAllCompleted();
30 30
31private: 31private:
32 bool m_dirty : 1; 32 bool m_dirty : 1;
33 QString m_file; 33 QString m_file;
34 QMap<int, OTodo> m_map; 34 QMap<int, OTodo> m_map;
35}; 35};
36 36
37#endif 37#endif
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
@@ -210,97 +210,97 @@ bool OTodoAccessXML::save() {
210 210
211 // for all todos 211 // for all todos
212 QMap<int, OTodo>::Iterator it; 212 QMap<int, OTodo>::Iterator it;
213 for (it = m_events.begin(); it != m_events.end(); ++it ) { 213 for (it = m_events.begin(); it != m_events.end(); ++it ) {
214 out+= "<Task " + toString( (*it) ) + " />\n"; 214 out+= "<Task " + toString( (*it) ) + " />\n";
215 QCString cstr = out.utf8(); 215 QCString cstr = out.utf8();
216 written = f.writeBlock( cstr.data(), cstr.length() ); 216 written = f.writeBlock( cstr.data(), cstr.length() );
217 217
218 /* less written then we wanted */ 218 /* less written then we wanted */
219 if ( written != (int)cstr.length() ) { 219 if ( written != (int)cstr.length() ) {
220 f.close(); 220 f.close();
221 QFile::remove( strNewFile ); 221 QFile::remove( strNewFile );
222 return false; 222 return false;
223 } 223 }
224 out = QString::null; 224 out = QString::null;
225 } 225 }
226 226
227 out += "</Tasks>"; 227 out += "</Tasks>";
228 QCString cstr = out.utf8(); 228 QCString cstr = out.utf8();
229 written = f.writeBlock( cstr.data(), cstr.length() ); 229 written = f.writeBlock( cstr.data(), cstr.length() );
230 230
231 if ( written != (int)cstr.length() ) { 231 if ( written != (int)cstr.length() ) {
232 f.close(); 232 f.close();
233 QFile::remove( strNewFile ); 233 QFile::remove( strNewFile );
234 return false; 234 return false;
235 } 235 }
236 /* flush before renaming */ 236 /* flush before renaming */
237 f.close(); 237 f.close();
238 238
239 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 239 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
240// qWarning("error renaming"); 240// qWarning("error renaming");
241 QFile::remove( strNewFile ); 241 QFile::remove( strNewFile );
242 } 242 }
243 243
244 m_changed = false; 244 m_changed = false;
245 return true; 245 return true;
246} 246}
247QArray<int> OTodoAccessXML::allRecords()const { 247QArray<int> OTodoAccessXML::allRecords()const {
248 QArray<int> ids( m_events.count() ); 248 QArray<int> ids( m_events.count() );
249 QMap<int, OTodo>::ConstIterator it; 249 QMap<int, OTodo>::ConstIterator it;
250 int i = 0; 250 int i = 0;
251 251
252 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 252 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
253 ids[i] = it.key(); 253 ids[i] = it.key();
254 i++; 254 i++;
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}
262OTodo OTodoAccessXML::find( int uid )const { 262OTodo OTodoAccessXML::find( int uid )const {
263 OTodo todo; 263 OTodo todo;
264 todo.setUid( 0 ); // isEmpty() 264 todo.setUid( 0 ); // isEmpty()
265 QMap<int, OTodo>::ConstIterator it = m_events.find( uid ); 265 QMap<int, OTodo>::ConstIterator it = m_events.find( uid );
266 if ( it != m_events.end() ) 266 if ( it != m_events.end() )
267 todo = it.data(); 267 todo = it.data();
268 268
269 return todo; 269 return todo;
270} 270}
271void OTodoAccessXML::clear() { 271void OTodoAccessXML::clear() {
272 if (m_opened ) 272 if (m_opened )
273 m_changed = true; 273 m_changed = true;
274 274
275 m_events.clear(); 275 m_events.clear();
276} 276}
277bool OTodoAccessXML::add( const OTodo& todo ) { 277bool OTodoAccessXML::add( const OTodo& todo ) {
278// qWarning("add"); 278// qWarning("add");
279 m_changed = true; 279 m_changed = true;
280 m_events.insert( todo.uid(), todo ); 280 m_events.insert( todo.uid(), todo );
281 281
282 return true; 282 return true;
283} 283}
284bool OTodoAccessXML::remove( int uid ) { 284bool OTodoAccessXML::remove( int uid ) {
285 m_changed = true; 285 m_changed = true;
286 m_events.remove( uid ); 286 m_events.remove( uid );
287 287
288 return true; 288 return true;
289} 289}
290bool OTodoAccessXML::replace( const OTodo& todo) { 290bool OTodoAccessXML::replace( const OTodo& todo) {
291 m_changed = true; 291 m_changed = true;
292 m_events.replace( todo.uid(), todo ); 292 m_events.replace( todo.uid(), todo );
293 293
294 return true; 294 return true;
295} 295}
296QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start, 296QArray<int> OTodoAccessXML::effectiveToDos( const QDate& start,
297 const QDate& end, 297 const QDate& end,
298 bool includeNoDates ) { 298 bool includeNoDates ) {
299 QArray<int> ids( m_events.count() ); 299 QArray<int> ids( m_events.count() );
300 QMap<int, OTodo>::Iterator it; 300 QMap<int, OTodo>::Iterator it;
301 301
302 int i = 0; 302 int i = 0;
303 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 303 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
304 if ( !it.data().hasDueDate() ) { 304 if ( !it.data().hasDueDate() ) {
305 if ( includeNoDates ) { 305 if ( includeNoDates ) {
306 ids[i] = it.key(); 306 ids[i] = it.key();
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
@@ -1,57 +1,57 @@
1#ifndef OPIE_TODO_ACCESS_XML_H 1#ifndef OPIE_TODO_ACCESS_XML_H
2#define OPIE_TODO_ACCESS_XML_H 2#define OPIE_TODO_ACCESS_XML_H
3 3
4#include <qasciidict.h> 4#include <qasciidict.h>
5#include <qmap.h> 5#include <qmap.h>
6 6
7#include "otodoaccessbackend.h" 7#include "otodoaccessbackend.h"
8 8
9namespace Opie { 9namespace Opie {
10 class XMLElement; 10 class XMLElement;
11}; 11};
12 12
13class OTodoAccessXML : public OTodoAccessBackend { 13class OTodoAccessXML : public OTodoAccessBackend {
14public: 14public:
15 /** 15 /**
16 * fileName if Empty we will use the default path 16 * fileName if Empty we will use the default path
17 */ 17 */
18 OTodoAccessXML( const QString& appName, 18 OTodoAccessXML( const QString& appName,
19 const QString& fileName = QString::null ); 19 const QString& fileName = QString::null );
20 ~OTodoAccessXML(); 20 ~OTodoAccessXML();
21 21
22 bool load(); 22 bool load();
23 bool reload(); 23 bool reload();
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& );
31 bool remove( int uid ); 31 bool remove( int uid );
32 void removeAllCompleted(); 32 void removeAllCompleted();
33 bool replace( const OTodo& ); 33 bool replace( const OTodo& );
34 34
35 /* our functions */ 35 /* our functions */
36 QArray<int> effectiveToDos( const QDate& start, 36 QArray<int> effectiveToDos( const QDate& start,
37 const QDate& end, 37 const QDate& end,
38 bool includeNoDates ); 38 bool includeNoDates );
39 QArray<int> overDue(); 39 QArray<int> overDue();
40 QArray<int> sorted( bool asc, int sortOrder, 40 QArray<int> sorted( bool asc, int sortOrder,
41 int sortFilter, int cat ); 41 int sortFilter, int cat );
42private: 42private:
43 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& ); 43 void todo( QAsciiDict<int>*, OTodo&,const QCString&,const QString& );
44 QString toString( const OTodo& )const; 44 QString toString( const OTodo& )const;
45 QString toString( const QArray<int>& ints ) const; 45 QString toString( const QArray<int>& ints ) const;
46 QMap<int, OTodo> m_events; 46 QMap<int, OTodo> m_events;
47 QString m_file; 47 QString m_file;
48 QString m_app; 48 QString m_app;
49 bool m_opened : 1; 49 bool m_opened : 1;
50 bool m_changed : 1; 50 bool m_changed : 1;
51 class OTodoAccessXMLPrivate; 51 class OTodoAccessXMLPrivate;
52 OTodoAccessXMLPrivate* d; 52 OTodoAccessXMLPrivate* d;
53 int m_year, m_month, m_day; 53 int m_year, m_month, m_day;
54 54
55}; 55};
56 56
57#endif 57#endif
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
@@ -29,97 +29,97 @@ public:
29 typedef ORecordList<T> List; 29 typedef ORecordList<T> List;
30 typedef OPimAccessBackend<T> BackEnd; 30 typedef OPimAccessBackend<T> BackEnd;
31 typedef OPimCache<T> Cache; 31 typedef OPimCache<T> Cache;
32 32
33 /** 33 /**
34 * c'tor BackEnd 34 * c'tor BackEnd
35 * enum Access a small hint on how to handle the backend 35 * enum Access a small hint on how to handle the backend
36 */ 36 */
37 OPimAccessTemplate( BackEnd* end); 37 OPimAccessTemplate( BackEnd* end);
38 38
39 virtual ~OPimAccessTemplate(); 39 virtual ~OPimAccessTemplate();
40 40
41 /** 41 /**
42 * load from the backend 42 * load from the backend
43 */ 43 */
44 bool load(); 44 bool load();
45 45
46 /** Reload database. 46 /** Reload database.
47 * You should execute this function if the external database 47 * You should execute this function if the external database
48 * was changed. 48 * was changed.
49 * This function will load the external database and afterwards 49 * This function will load the external database and afterwards
50 * rejoin the local changes. Therefore the local database will be set consistent. 50 * rejoin the local changes. Therefore the local database will be set consistent.
51 */ 51 */
52 virtual bool reload(); 52 virtual bool reload();
53 53
54 /** Save contacts database. 54 /** Save contacts database.
55 * Save is more a "commit". After calling this function, all changes are public available. 55 * Save is more a "commit". After calling this function, all changes are public available.
56 * @return true if successful 56 * @return true if successful
57 */ 57 */
58 bool save(); 58 bool save();
59 59
60 /** 60 /**
61 * if the resource was changed externally 61 * if the resource was changed externally
62 * You should use the signal handling instead of polling possible changes ! 62 * You should use the signal handling instead of polling possible changes !
63 * zecke: Do you implement a signal for otodoaccess ? 63 * zecke: Do you implement a signal for otodoaccess ?
64 */ 64 */
65 bool wasChangedExternally()const; 65 bool wasChangedExternally()const;
66 66
67 /** 67 /**
68 * return a List of records 68 * return a List of records
69 * you can iterate over them 69 * you can iterate over them
70 */ 70 */
71 virtual List allRecords()const; 71 virtual List allRecords()const;
72 72
73 /** 73 /**
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
81 */ 81 */
82 virtual T find( int uid )const; 82 virtual T find( int uid )const;
83 83
84 /** 84 /**
85 * read ahead cache find method ;) 85 * read ahead cache find method ;)
86 */ 86 */
87 virtual T find( int uid, const QArray<int>&, 87 virtual T find( int uid, const QArray<int>&,
88 uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const; 88 uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const;
89 89
90 /* invalidate cache here */ 90 /* invalidate cache here */
91 /** 91 /**
92 * clears the backend and invalidates the backend 92 * clears the backend and invalidates the backend
93 */ 93 */
94 void clear() ; 94 void clear() ;
95 95
96 /** 96 /**
97 * add T to the backend 97 * add T to the backend
98 * @param t The item to add. 98 * @param t The item to add.
99 * @return <i>true</i> if added successfully. 99 * @return <i>true</i> if added successfully.
100 */ 100 */
101 virtual bool add( const T& t ) ; 101 virtual bool add( const T& t ) ;
102 bool add( const OPimRecord& ); 102 bool add( const OPimRecord& );
103 103
104 /* only the uid matters */ 104 /* only the uid matters */
105 /** 105 /**
106 * remove T from the backend 106 * remove T from the backend
107 * @param t The item to remove 107 * @param t The item to remove
108 * @return <i>true</i> if successful. 108 * @return <i>true</i> if successful.
109 */ 109 */
110 virtual bool remove( const T& t ); 110 virtual bool remove( const T& t );
111 111
112 /** 112 /**
113 * remove the OPimRecord with uid 113 * remove the OPimRecord with uid
114 * @param uid The ID of the item to remove 114 * @param uid The ID of the item to remove
115 * @return <i>true</i> if successful. 115 * @return <i>true</i> if successful.
116 */ 116 */
117 bool remove( int uid ); 117 bool remove( int uid );
118 bool remove( const OPimRecord& ); 118 bool remove( const OPimRecord& );
119 119
120 /** 120 /**
121 * replace T from backend 121 * replace T from backend
122 * @param t The item to replace 122 * @param t The item to replace
123 * @return <i>true</i> if successful. 123 * @return <i>true</i> if successful.
124 */ 124 */
125 virtual bool replace( const T& t) ; 125 virtual bool replace( const T& t) ;
@@ -141,98 +141,98 @@ protected:
141 void setBackEnd( BackEnd* end ); 141 void setBackEnd( BackEnd* end );
142 /** 142 /**
143 * returns the backend 143 * returns the backend
144 */ 144 */
145 BackEnd* backEnd(); 145 BackEnd* backEnd();
146 BackEnd* m_backEnd; 146 BackEnd* m_backEnd;
147 Cache m_cache; 147 Cache m_cache;
148 148
149}; 149};
150 150
151template <class T> 151template <class T>
152OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) 152OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
153 : OTemplateBase<T>(), m_backEnd( end ) 153 : OTemplateBase<T>(), m_backEnd( end )
154{ 154{
155 if (end ) 155 if (end )
156 end->setFrontend( this ); 156 end->setFrontend( this );
157} 157}
158template <class T> 158template <class T>
159OPimAccessTemplate<T>::~OPimAccessTemplate() { 159OPimAccessTemplate<T>::~OPimAccessTemplate() {
160 qWarning("~OPimAccessTemplate<T>"); 160 qWarning("~OPimAccessTemplate<T>");
161 delete m_backEnd; 161 delete m_backEnd;
162} 162}
163template <class T> 163template <class T>
164bool OPimAccessTemplate<T>::load() { 164bool OPimAccessTemplate<T>::load() {
165 invalidateCache(); 165 invalidateCache();
166 return m_backEnd->load(); 166 return m_backEnd->load();
167} 167}
168template <class T> 168template <class T>
169bool OPimAccessTemplate<T>::reload() { 169bool OPimAccessTemplate<T>::reload() {
170 invalidateCache(); // zecke: I think this should be added (se) 170 invalidateCache(); // zecke: I think this should be added (se)
171 return m_backEnd->reload(); 171 return m_backEnd->reload();
172} 172}
173template <class T> 173template <class T>
174bool OPimAccessTemplate<T>::save() { 174bool OPimAccessTemplate<T>::save() {
175 return m_backEnd->save(); 175 return m_backEnd->save();
176} 176}
177template <class T> 177template <class T>
178typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { 178typename OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
179 QArray<int> ints = m_backEnd->allRecords(); 179 QArray<int> ints = m_backEnd->allRecords();
180 List lis(ints, this ); 180 List lis(ints, this );
181 return lis; 181 return lis;
182} 182}
183template <class T> 183template <class T>
184QArray<int> OPimAccessTemplate<T>::records()const { 184QArray<int> OPimAccessTemplate<T>::records()const {
185 return m_backEnd->allRecords(); 185 return m_backEnd->allRecords();
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;
194} 194}
195template <class T> 195template <class T>
196T OPimAccessTemplate<T>::find( int uid ) const{ 196T OPimAccessTemplate<T>::find( int uid ) const{
197 T t = m_backEnd->find( uid ); 197 T t = m_backEnd->find( uid );
198 cache( t ); 198 cache( t );
199 return t; 199 return t;
200} 200}
201template <class T> 201template <class T>
202T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar, 202T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
203 uint current, typename OTemplateBase<T>::CacheDirection dir )const { 203 uint current, typename OTemplateBase<T>::CacheDirection dir )const {
204 /* 204 /*
205 * better do T.isEmpty() 205 * better do T.isEmpty()
206 * after a find this way we would 206 * after a find this way we would
207 * avoid two finds in QCache... 207 * avoid two finds in QCache...
208 */ 208 */
209 // qWarning("find it now %d", uid ); 209 // qWarning("find it now %d", uid );
210 if (m_cache.contains( uid ) ) { 210 if (m_cache.contains( uid ) ) {
211 return m_cache.find( uid ); 211 return m_cache.find( uid );
212 } 212 }
213 213
214 T t = m_backEnd->find( uid, ar, current, dir ); 214 T t = m_backEnd->find( uid, ar, current, dir );
215 cache( t ); 215 cache( t );
216 return t; 216 return t;
217} 217}
218template <class T> 218template <class T>
219void OPimAccessTemplate<T>::clear() { 219void OPimAccessTemplate<T>::clear() {
220 invalidateCache(); 220 invalidateCache();
221 m_backEnd->clear(); 221 m_backEnd->clear();
222} 222}
223template <class T> 223template <class T>
224bool OPimAccessTemplate<T>::add( const T& t ) { 224bool OPimAccessTemplate<T>::add( const T& t ) {
225 cache( t ); 225 cache( t );
226 return m_backEnd->add( t ); 226 return m_backEnd->add( t );
227} 227}
228template <class T> 228template <class T>
229bool OPimAccessTemplate<T>::add( const OPimRecord& rec) { 229bool OPimAccessTemplate<T>::add( const OPimRecord& rec) {
230 /* same type */ 230 /* same type */
231 if ( rec.rtti() == T::rtti() ) { 231 if ( rec.rtti() == T::rtti() ) {
232 const T &t = static_cast<const T&>(rec); 232 const T &t = static_cast<const T&>(rec);
233 return add(t); 233 return add(t);
234 } 234 }
235 return false; 235 return false;
236} 236}
237template <class T> 237template <class T>
238bool OPimAccessTemplate<T>::remove( const T& t ) { 238bool OPimAccessTemplate<T>::remove( const T& t ) {