summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/libopie.pro1
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.cpp10
-rw-r--r--libopie/pim/ocontactaccessbackend_vcard.h10
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.cpp166
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h677
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.cpp2
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.h2
-rw-r--r--libopie/pim/opimaccessbackend.h6
-rw-r--r--libopie/pim/opimaccesstemplate.h6
-rw-r--r--libopie/pim/otodoaccesssql.cpp2
-rw-r--r--libopie/pim/otodoaccesssql.h2
-rw-r--r--libopie/pim/otodoaccessvcal.cpp2
-rw-r--r--libopie/pim/otodoaccessvcal.h2
-rw-r--r--libopie/pim/otodoaccessxml.cpp2
-rw-r--r--libopie/pim/otodoaccessxml.h2
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp10
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.h10
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp166
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.h677
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp2
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.h2
-rw-r--r--libopie2/opiepim/backend/opimaccessbackend.h6
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.h2
-rw-r--r--libopie2/opiepim/backend/otodoaccessvcal.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccessvcal.h2
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp2
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.h2
-rw-r--r--libopie2/opiepim/core/opimaccesstemplate.h6
29 files changed, 347 insertions, 1436 deletions
diff --git a/libopie/libopie.pro b/libopie/libopie.pro
index 391f30e..2bf9985 100644
--- a/libopie/libopie.pro
+++ b/libopie/libopie.pro
@@ -52,32 +52,33 @@ SOURCES = ofontmenu.cc \
52 ofiledialog.cc ofileselector.cc \ 52 ofiledialog.cc ofileselector.cc \
53 ocheckitem.cpp \ 53 ocheckitem.cpp \
54 colordialog.cpp \ 54 colordialog.cpp \
55 colorpopupmenu.cpp oclickablelabel.cpp \ 55 colorpopupmenu.cpp oclickablelabel.cpp \
56 oprocctrl.cpp oprocess.cpp \ 56 oprocctrl.cpp oprocess.cpp \
57 odevice.cpp odevicebutton.cpp otimepicker.cpp \ 57 odevice.cpp odevicebutton.cpp otimepicker.cpp \
58 otabwidget.cpp otabbar.cpp \ 58 otabwidget.cpp otabbar.cpp \
59 ofontselector.cpp \ 59 ofontselector.cpp \
60 pim/otodo.cpp \ 60 pim/otodo.cpp \
61 pim/opimrecord.cpp \ 61 pim/opimrecord.cpp \
62 pim/otodoaccess.cpp \ 62 pim/otodoaccess.cpp \
63 pim/otodoaccessbackend.cpp \ 63 pim/otodoaccessbackend.cpp \
64 pim/otodoaccessxml.cpp \ 64 pim/otodoaccessxml.cpp \
65 pim/ocontact.cpp \ 65 pim/ocontact.cpp \
66 pim/ocontactaccess.cpp \ 66 pim/ocontactaccess.cpp \
67 pim/ocontactaccessbackend_vcard.cpp \ 67 pim/ocontactaccessbackend_vcard.cpp \
68 pim/ocontactaccessbackend_xml.cpp \
68 pim/otodoaccessvcal.cpp \ 69 pim/otodoaccessvcal.cpp \
69 pim/orecur.cpp \ 70 pim/orecur.cpp \
70 pim/opimstate.cpp \ 71 pim/opimstate.cpp \
71 pim/opimxrefpartner.cpp \ 72 pim/opimxrefpartner.cpp \
72 pim/opimxref.cpp \ 73 pim/opimxref.cpp \
73 pim/opimxrefmanager.cpp \ 74 pim/opimxrefmanager.cpp \
74 pim/opimmaintainer.cpp \ 75 pim/opimmaintainer.cpp \
75 pim/opimnotify.cpp \ 76 pim/opimnotify.cpp \
76 pim/opimnotifymanager.cpp \ 77 pim/opimnotifymanager.cpp \
77 pim/opimmainwindow.cpp \ 78 pim/opimmainwindow.cpp \
78 pim/opimresolver.cpp \ 79 pim/opimresolver.cpp \
79 pim/oevent.cpp \ 80 pim/oevent.cpp \
80 pim/otimezone.cpp \ 81 pim/otimezone.cpp \
81 pim/odatebookaccess.cpp \ 82 pim/odatebookaccess.cpp \
82 pim/odatebookaccessbackend.cpp \ 83 pim/odatebookaccessbackend.cpp \
83 pim/odatebookaccessbackend_xml.cpp \ 84 pim/odatebookaccessbackend_xml.cpp \
diff --git a/libopie/pim/ocontactaccessbackend_vcard.cpp b/libopie/pim/ocontactaccessbackend_vcard.cpp
index e537269..f24523f 100644
--- a/libopie/pim/ocontactaccessbackend_vcard.cpp
+++ b/libopie/pim/ocontactaccessbackend_vcard.cpp
@@ -4,32 +4,40 @@
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 *
@@ -176,33 +184,33 @@ OContact OContactAccessBackend_VCard::find ( int uid ) const
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}
diff --git a/libopie/pim/ocontactaccessbackend_vcard.h b/libopie/pim/ocontactaccessbackend_vcard.h
index 236da00..93e2da3 100644
--- a/libopie/pim/ocontactaccessbackend_vcard.h
+++ b/libopie/pim/ocontactaccessbackend_vcard.h
@@ -4,32 +4,40 @@
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
@@ -41,33 +49,33 @@ class 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;
diff --git a/libopie/pim/ocontactaccessbackend_xml.cpp b/libopie/pim/ocontactaccessbackend_xml.cpp
index 2df6757..4abf4d9 100644
--- a/libopie/pim/ocontactaccessbackend_xml.cpp
+++ b/libopie/pim/ocontactaccessbackend_xml.cpp
@@ -4,32 +4,46 @@
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 *
@@ -76,310 +90,335 @@
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
@@ -413,113 +452,112 @@ bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
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;
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
index 6477705..4d6a7ef 100644
--- a/libopie/pim/ocontactaccessbackend_xml.h
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -4,32 +4,46 @@
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 *
@@ -50,694 +64,81 @@
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/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp
index 4a6b7b8..11e19d9 100644
--- a/libopie/pim/odatebookaccessbackend_xml.cpp
+++ b/libopie/pim/odatebookaccessbackend_xml.cpp
@@ -231,33 +231,33 @@ bool ODateBookAccessBackend_XML::save() {
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 );
diff --git a/libopie/pim/odatebookaccessbackend_xml.h b/libopie/pim/odatebookaccessbackend_xml.h
index 40f69d8..563c31f 100644
--- a/libopie/pim/odatebookaccessbackend_xml.h
+++ b/libopie/pim/odatebookaccessbackend_xml.h
@@ -3,33 +3,33 @@
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();
diff --git a/libopie/pim/opimaccessbackend.h b/libopie/pim/opimaccessbackend.h
index e268f4f..01a0c86 100644
--- a/libopie/pim/opimaccessbackend.h
+++ b/libopie/pim/opimaccessbackend.h
@@ -34,36 +34,36 @@ public:
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
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
index 259e2c1..6a3a0db 100644
--- a/libopie/pim/opimaccesstemplate.h
+++ b/libopie/pim/opimaccesstemplate.h
@@ -61,33 +61,33 @@ public:
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 */
@@ -173,34 +173,34 @@ bool OPimAccessTemplate<T>::reload() {
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
diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp
index 761d7d8..ec9c14c 100644
--- a/libopie/pim/otodoaccesssql.cpp
+++ b/libopie/pim/otodoaccesssql.cpp
@@ -264,33 +264,33 @@ bool OTodoAccessBackendSQL::load(){
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
diff --git a/libopie/pim/otodoaccesssql.h b/libopie/pim/otodoaccesssql.h
index 0f6dd2c..6a4257c 100644
--- a/libopie/pim/otodoaccesssql.h
+++ b/libopie/pim/otodoaccesssql.h
@@ -5,33 +5,33 @@
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;
diff --git a/libopie/pim/otodoaccessvcal.cpp b/libopie/pim/otodoaccessvcal.cpp
index 309f9e1..2136283 100644
--- a/libopie/pim/otodoaccessvcal.cpp
+++ b/libopie/pim/otodoaccessvcal.cpp
@@ -172,30 +172,30 @@ OTodo 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/libopie/pim/otodoaccessvcal.h b/libopie/pim/otodoaccessvcal.h
index 452f602..a90ee9c 100644
--- a/libopie/pim/otodoaccessvcal.h
+++ b/libopie/pim/otodoaccessvcal.h
@@ -1,32 +1,32 @@
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;
diff --git a/libopie/pim/otodoaccessxml.cpp b/libopie/pim/otodoaccessxml.cpp
index cda300b..71e8787 100644
--- a/libopie/pim/otodoaccessxml.cpp
+++ b/libopie/pim/otodoaccessxml.cpp
@@ -242,33 +242,33 @@ bool OTodoAccessXML::save() {
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
diff --git a/libopie/pim/otodoaccessxml.h b/libopie/pim/otodoaccessxml.h
index 93609fe..1032c92 100644
--- a/libopie/pim/otodoaccessxml.h
+++ b/libopie/pim/otodoaccessxml.h
@@ -11,33 +11,33 @@ namespace Opie {
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& );
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
@@ -4,32 +4,40 @@
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 *
@@ -176,33 +184,33 @@ OContact OContactAccessBackend_VCard::find ( int uid ) const
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}
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
@@ -4,32 +4,40 @@
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
@@ -41,33 +49,33 @@ class 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;
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
@@ -4,32 +4,46 @@
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 *
@@ -76,310 +90,335 @@
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
@@ -413,113 +452,112 @@ bool OContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
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;
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
@@ -4,32 +4,46 @@
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 *
@@ -50,694 +64,81 @@
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
@@ -231,33 +231,33 @@ bool ODateBookAccessBackend_XML::save() {
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 );
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
@@ -3,33 +3,33 @@
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();
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
@@ -34,36 +34,36 @@ public:
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
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
@@ -264,33 +264,33 @@ bool OTodoAccessBackendSQL::load(){
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
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
@@ -5,33 +5,33 @@
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;
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
@@ -172,30 +172,30 @@ OTodo 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,32 +1,32 @@
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;
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
@@ -242,33 +242,33 @@ bool OTodoAccessXML::save() {
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
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
@@ -11,33 +11,33 @@ namespace Opie {
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& );
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
@@ -61,33 +61,33 @@ public:
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 */
@@ -173,34 +173,34 @@ bool OPimAccessTemplate<T>::reload() {
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