summaryrefslogtreecommitdiff
path: root/libopie2
authorzecke <zecke>2004-11-18 21:49:23 (UTC)
committer zecke <zecke>2004-11-18 21:49:23 (UTC)
commit1e7f8f22fc10e3ed85b6563332ddc348c95792d0 (patch) (unidiff)
tree59498ba1d4a7dbff05228c09bebcf0c849e916be /libopie2
parent41fa1c196965f17f9748f835d90c307b7e594883 (diff)
downloadopie-1e7f8f22fc10e3ed85b6563332ddc348c95792d0.zip
opie-1e7f8f22fc10e3ed85b6563332ddc348c95792d0.tar.gz
opie-1e7f8f22fc10e3ed85b6563332ddc348c95792d0.tar.bz2
Backend Changes:
Each Backend can: -Sort and Filter a set of Records/AllRecords (which can be filtered again) -QueryByExample by every Backend -Occurrences for a period of time and a QDateTime -More common implementation -OPimBackendOccurrence with common splitting to OPimOccurrence
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/backend/backends.pro5
-rw-r--r--libopie2/opiepim/backend/obackendfactory.h42
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend.cpp121
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend.h80
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp26
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.h3
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp29
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_xml.h5
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend.cpp228
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend.h47
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp15
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_sql.h5
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp12
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.h4
-rw-r--r--libopie2/opiepim/backend/opimaccessbackend.h361
-rw-r--r--libopie2/opiepim/backend/opimbackendoccurrence.cpp241
-rw-r--r--libopie2/opiepim/backend/opimbackendoccurrence.h108
-rw-r--r--libopie2/opiepim/backend/otodoaccessbackend.cpp114
-rw-r--r--libopie2/opiepim/backend/otodoaccessbackend.h40
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.cpp135
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.h37
-rw-r--r--libopie2/opiepim/backend/otodoaccessvcal.cpp40
-rw-r--r--libopie2/opiepim/backend/otodoaccessvcal.h10
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.cpp316
-rw-r--r--libopie2/opiepim/backend/otodoaccessxml.h13
25 files changed, 1218 insertions, 819 deletions
diff --git a/libopie2/opiepim/backend/backends.pro b/libopie2/opiepim/backend/backends.pro
index 42d807c..739f74e 100644
--- a/libopie2/opiepim/backend/backends.pro
+++ b/libopie2/opiepim/backend/backends.pro
@@ -1,33 +1,36 @@
1SOURCES += \ 1SOURCES += \
2 backend/ocontactaccessbackend.cpp \
2 backend/ocontactaccessbackend_vcard.cpp \ 3 backend/ocontactaccessbackend_vcard.cpp \
3 backend/ocontactaccessbackend_xml.cpp \ 4 backend/ocontactaccessbackend_xml.cpp \
4 backend/odatebookaccessbackend.cpp \ 5 backend/odatebookaccessbackend.cpp \
5 backend/odatebookaccessbackend_xml.cpp \ 6 backend/odatebookaccessbackend_xml.cpp \
7 backend/opimbackendoccurrence.cpp \
6 backend/otodoaccessbackend.cpp \ 8 backend/otodoaccessbackend.cpp \
7 backend/otodoaccessvcal.cpp \ 9 backend/otodoaccessvcal.cpp \
8 backend/otodoaccessxml.cpp 10 backend/otodoaccessxml.cpp
9 11
10HEADERS += \ 12HEADERS += \
11 backend/obackendfactory.h \ 13 backend/obackendfactory.h \
12 backend/ocontactaccessbackend.h \ 14 backend/ocontactaccessbackend.h \
13 backend/ocontactaccessbackend_vcard.h \ 15 backend/ocontactaccessbackend_vcard.h \
14 backend/ocontactaccessbackend_xml.h \ 16 backend/ocontactaccessbackend_xml.h \
15 backend/odatebookaccessbackend.h \ 17 backend/odatebookaccessbackend.h \
16 backend/odatebookaccessbackend_xml.h \ 18 backend/odatebookaccessbackend_xml.h \
17 backend/opimaccessbackend.h \ 19 backend/opimaccessbackend.h \
20 backend/opimbackendoccurrence.h \
18 backend/otodoaccessbackend.h \ 21 backend/otodoaccessbackend.h \
19 backend/otodoaccessvcal.h \ 22 backend/otodoaccessvcal.h \
20 backend/otodoaccessxml.h 23 backend/otodoaccessxml.h
21 24
22contains( ENABLE_SQL_PIM_BACKEND, y ) { 25contains( ENABLE_SQL_PIM_BACKEND, y ) {
23 message ( Enabling the SQL Backend for libopiepim2 ) 26 message ( Enabling the SQL Backend for libopiepim2 )
24 DEFINES += __USE_SQL 27 DEFINES += __USE_SQL
25 LIBS += -lopiedb2 28 LIBS += -lopiedb2
26 HEADERS += backend/otodoaccesssql.h \ 29 HEADERS += backend/otodoaccesssql.h \
27 backend/ocontactaccessbackend_sql.h \ 30 backend/ocontactaccessbackend_sql.h \
28 backend/odatebookaccessbackend_sql.h 31 backend/odatebookaccessbackend_sql.h
29 SOURCES += backend/otodoaccesssql.cpp \ 32 SOURCES += backend/otodoaccesssql.cpp \
30 backend/ocontactaccessbackend_sql.cpp \ 33 backend/ocontactaccessbackend_sql.cpp \
31 backend/odatebookaccessbackend_sql.cpp 34 backend/odatebookaccessbackend_sql.cpp
32} 35}
33 36
diff --git a/libopie2/opiepim/backend/obackendfactory.h b/libopie2/opiepim/backend/obackendfactory.h
index 9f3a823..25e247b 100644
--- a/libopie2/opiepim/backend/obackendfactory.h
+++ b/libopie2/opiepim/backend/obackendfactory.h
@@ -49,76 +49,78 @@
49#include <opie2/ocontactaccessbackend_sql.h> 49#include <opie2/ocontactaccessbackend_sql.h>
50#include <opie2/odatebookaccessbackend_sql.h> 50#include <opie2/odatebookaccessbackend_sql.h>
51#endif 51#endif
52 52
53#include <qpe/config.h> 53#include <qpe/config.h>
54 54
55/* QT */ 55/* QT */
56#include <qstring.h> 56#include <qstring.h>
57#include <qasciidict.h> 57#include <qasciidict.h>
58 58
59 59
60 60
61using namespace Opie; 61using namespace Opie;
62using namespace Opie::Pim; 62using namespace Opie::Pim;
63 63
64namespace Opie { 64namespace Opie {
65 65
66class OBackendPrivate; 66class OBackendPrivate;
67 67
68/** 68/**
69 * This class is our factory. It will give us the default implementations 69 * This class is our factory. It will give us the default implementations
70 * of at least Todolist, Contacts and Datebook. In the future this class will 70 * of at least Todolist, Contacts and Datebook. In the future this class will
71 * allow users to switch the backend with ( XML->SQLite ) without the need 71 * allow users to switch the backend with ( XML->SQLite ) without the need
72 * to recompile.# 72 * to recompile.#
73 * This class - as the whole PIM Api - is making use of templates 73 * This class - as the whole PIM Api - is making use of templates
74 * 74 *
75 * <pre> 75 * <pre>
76 * OPimTodoAccessBackend* backend = OBackEndFactory<OPimTodoAccessBackend>::Default( OPimGlobal::TODOLIST, QString::null ); 76 * OPimTodoAccessBackend* backend = OBackEndFactory<OPimTodoAccessBackend>::Default( OPimGlobal::TODOLIST, QString::null );
77 * backend->load(); 77 * backend->load();
78 * </pre> 78 * </pre>
79 * 79 *
80 * @author Stefan Eilers 80 * @author Stefan Eilers
81 * @version 0.1 81 * @version 0.1
82 */ 82 */
83 template<class T> 83 template<class T>
84 class OBackendFactory 84 class OBackendFactory
85 { 85 {
86 public: 86 public:
87 OBackendFactory() {}; 87 OBackendFactory() {};
88 88
89 /** 89 /**
90 * Returns a selected backend implementation 90 * Returns a selected backend implementation
91 * @param type the type of the backend 91 * @param type the type of the backend
92 * @param database the type of the used database 92 * @param database the type of the used database
93 * @param appName The name of your application. It will be passed on to the backend. 93 * @param appName The name of your application. It will be passed on to the backend.
94 * @param filename Filename of the database file if you don't want to access the default 94 * @param filename Filename of the database file if you don't want to access the default
95 * @see OPimGlobal() 95 * @see OPimGlobal()
96 */ 96 */
97 static T* create( OPimGlobal::PimType type, OPimGlobal::DatabaseStyle database, 97 static T* create( OPimGlobal::PimType type, OPimGlobal::DatabaseStyle database,
98 const QString& appName, const QString& filename = QString::null ){ 98 const QString& appName, const QString& filename = QString::null ){
99 owarn << "Selected backend for " << type << " is: " << database << oendl; 99 owarn << "Selected backend for " << type << " is: " <<
100 // If we should use the dafult database style, we have to request it 100database << oendl;
101
102 // If we should use the dafult database style, we have to request it
101 OPimGlobal::DatabaseStyle use_database = database; 103 OPimGlobal::DatabaseStyle use_database = database;
102 if ( use_database == OPimGlobal::DEFAULT ){ 104 if ( use_database == OPimGlobal::DEFAULT ){
103 use_database = defaultDB( type ); 105 use_database = defaultDB( type );
104 } 106 }
105 107
106 switch ( type ){ 108 switch ( type ){
107 case OPimGlobal::TODOLIST: 109 case OPimGlobal::TODOLIST:
108 110
109 switch ( use_database ){ 111 switch ( use_database ){
110 default: // Use SQL if something weird is given. 112 default: // Use SQL if something weird is given.
111 // Fall through !! 113 // Fall through !!
112 case OPimGlobal::SQL: 114 case OPimGlobal::SQL:
113#ifdef __USE_SQL 115#ifdef __USE_SQL
114 return (T*) new OPimTodoAccessBackendSQL( filename ); 116 return (T*) new OPimTodoAccessBackendSQL( filename );
115 break; 117 break;
116#else 118#else
117 owarn << "OBackendFactory:: sql Backend for TODO not implemented! Using XML instead!" << oendl; 119 owarn << "OBackendFactory:: sql Backend for TODO not implemented! Using XML instead!" << oendl;
118 // Fall through !! 120 // Fall through !!
119#endif 121#endif
120 case OPimGlobal::XML: 122 case OPimGlobal::XML:
121 return (T*) new OPimTodoAccessXML( appName, filename ); 123 return (T*) new OPimTodoAccessXML( appName, filename );
122 break; 124 break;
123 case OPimGlobal::VCARD: 125 case OPimGlobal::VCARD:
124 return (T*) new OPimTodoAccessVCal( filename ); 126 return (T*) new OPimTodoAccessVCal( filename );
@@ -153,78 +155,78 @@ class OBackendPrivate;
153 break; 155 break;
154#else 156#else
155 owarn << "OBackendFactory:: sql Backend for DATEBOOK not implemented! Using XML instead!" << oendl; 157 owarn << "OBackendFactory:: sql Backend for DATEBOOK not implemented! Using XML instead!" << oendl;
156 // Fall through !! 158 // Fall through !!
157#endif 159#endif
158 case OPimGlobal::XML: 160 case OPimGlobal::XML:
159 return (T*) new ODateBookAccessBackend_XML( appName, filename ); 161 return (T*) new ODateBookAccessBackend_XML( appName, filename );
160 break; 162 break;
161 case OPimGlobal::VCARD: 163 case OPimGlobal::VCARD:
162 owarn << "OBackendFactory:: VCal Backend for DATEBOOK not implemented!" << oendl; 164 owarn << "OBackendFactory:: VCal Backend for DATEBOOK not implemented!" << oendl;
163 return (T*) NULL; 165 return (T*) NULL;
164 break; 166 break;
165 } 167 }
166 default: 168 default:
167 return (T*) NULL; 169 return (T*) NULL;
168 } 170 }
169 171
170 } 172 }
171 173
172 /** 174 /**
173 * Returns the style of the default database which is used to contact PIM data. 175 * Returns the style of the default database which is used to contact PIM data.
174 * @param type the type of the backend 176 * @param type the type of the backend
175 * @see OPimGlobal() 177 * @see OPimGlobal()
176 */ 178 */
177 static OPimGlobal::DatabaseStyle defaultDB( OPimGlobal::PimType type ){ 179 static OPimGlobal::DatabaseStyle defaultDB( OPimGlobal::PimType type ){
178 QString group_name; 180 QString group_name;
179 switch ( type ){ 181 switch ( type ){
180 case OPimGlobal::TODOLIST: 182 case OPimGlobal::TODOLIST:
181 group_name = "todo"; 183 group_name = "todo";
182 break; 184 break;
183 case OPimGlobal::CONTACTLIST: 185 case OPimGlobal::CONTACTLIST:
184 group_name = "contact"; 186 group_name = "contact";
185 break; 187 break;
186 case OPimGlobal::DATEBOOK: 188 case OPimGlobal::DATEBOOK:
187 group_name = "datebook"; 189 group_name = "datebook";
188 break; 190 break;
189 default: 191 default:
190 group_name = "unknown"; 192 group_name = "unknown";
191 } 193 }
192 194
193 Config config( "pimaccess" ); 195 Config config( "pimaccess" );
194 config.setGroup ( group_name ); 196 config.setGroup ( group_name );
195 QString db_String = config.readEntry( "usebackend", "xml" ); 197 QString db_String = config.readEntry( "usebackend", "xml" );
196 198
197 QAsciiDict<int> dictDbTypes( OPimGlobal::_END_DatabaseStyle ); 199 QAsciiDict<int> dictDbTypes( OPimGlobal::_END_DatabaseStyle );
198 dictDbTypes.setAutoDelete( TRUE ); 200 dictDbTypes.setAutoDelete( TRUE );
199 201
200 dictDbTypes.insert( "xml", new int (OPimGlobal::XML) ); 202 dictDbTypes.insert( "xml", new int (OPimGlobal::XML) );
201 dictDbTypes.insert( "sql", new int (OPimGlobal::SQL) ); 203 dictDbTypes.insert( "sql", new int (OPimGlobal::SQL) );
202 dictDbTypes.insert( "vcard", new int (OPimGlobal::VCARD) ); 204 dictDbTypes.insert( "vcard", new int (OPimGlobal::VCARD) );
203 205
204 int* db_find = dictDbTypes[ db_String ]; 206 int* db_find = dictDbTypes[ db_String ];
205 207
206 if ( !db_find ) 208 if ( !db_find )
207 return OPimGlobal::UNKNOWN; 209 return OPimGlobal::UNKNOWN;
208 210
209 return (OPimGlobal::DatabaseStyle) *db_find; 211 return (OPimGlobal::DatabaseStyle) *db_find;
210 } 212 }
211 213
212 214
213 /** 215 /**
214 * Returns the default backend implementation for backendName. Which one is used, is defined 216 * Returns the default backend implementation for backendName. Which one is used, is defined
215 * by the configfile "pimaccess.conf". 217 * by the configfile "pimaccess.conf".
216 * @param type The type of the backend (@see OPimGlobal()) 218 * @param type The type of the backend (@see OPimGlobal())
217 * @param appName The name of your application. It will be passed on to the backend 219 * @param appName The name of your application. It will be passed on to the backend
218 * @see OPimGlobal() 220 * @see OPimGlobal()
219 */ 221 */
220 static T* defaultBackend( OPimGlobal::PimType type, const QString& appName ){ 222 static T* defaultBackend( OPimGlobal::PimType type, const QString& appName ){
221 return create( type, OPimGlobal::DEFAULT, appName ); 223 return create( type, OPimGlobal::DEFAULT, appName );
222 } 224 }
223 private: 225 private:
224 OBackendPrivate* d; 226 OBackendPrivate* d;
225 227
226 }; 228 };
227 229
228} 230}
229 231
230#endif 232#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.cpp b/libopie2/opiepim/backend/ocontactaccessbackend.cpp
new file mode 100644
index 0000000..6ef60eb
--- a/dev/null
+++ b/libopie2/opiepim/backend/ocontactaccessbackend.cpp
@@ -0,0 +1,121 @@
1/*
2 This file is part of the Opie Project
3 Copyright (C) 2004 Holger Freyther <freyther@handhelds.org>
4 =. Copyright (C) The Opie Team <opie-devel@handhelds.org>
5 .=l.
6 .>+-=
7 _;:, .> :=|. This program is free software; you can
8.> <`_, > . <= redistribute it and/or modify it under
9:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
10.="- .-=="i, .._ License as published by the Free Software
11 - . .-<_> .<> Foundation; either version 2 of the License,
12 ._= =} : or (at your option) any later version.
13 .%`+i> _;_.
14 .i_,=:_. -<s. This program is distributed in the hope that
15 + . -:. = it will be useful, but WITHOUT ANY WARRANTY;
16 : .. .:, . . . without even the implied warranty of
17 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A
18 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.= = ; Library General Public License for more
20++= -. .` .: details.
21 : = ...= . :.=-
22 -. .:....=;==+<; You should have received a copy of the GNU
23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28*/
29
30#include "ocontactaccessbackend.h"
31#include <opie2/private/opimcontactsortvector.h>
32#include <opie2/ocontactaccess.h>
33
34#include <opie2/odebug.h>
35
36namespace Opie {
37OPimContactAccessBackend::OPimContactAccessBackend() {}
38
39UIDArray
40OPimContactAccessBackend::queryByExample( const OPimContact&, int,
41 const QDateTime& )const {
42 return UIDArray();
43}
44
45UIDArray
46OPimContactAccessBackend::sorted( const UIDArray& ar, bool asc, int sortOrder,
47 int filter, const QArray<int>& categories)const {
48 odebug << "Using Unaccelerated OPimContactAccessBackend sorted Implementation" << oendl;
49
50 Internal::OPimContactSortVector vector(ar.count(), asc, sortOrder );
51
52 int item = 0;
53 uint cat_count = categories.count();
54 uint eve_count = ar.count();
55 bool bCat = filter & OPimContactAccess::FilterCategory ? true : false;
56 bool catPassed = false;
57 int cat;
58
59 for ( uint i = 0; i < eve_count; ++i ) {
60 OPimContact contact = find( ar[i], ar, i, Frontend::Forward );
61 if ( contact.isEmpty() )
62 continue;
63
64 /* show category */
65 /* -1 == unfiled */
66 catPassed = false;
67 for ( uint cat_nu = 0; cat_nu < cat_count; ++cat_nu ) {
68 cat = categories[cat_nu];
69 if ( bCat && cat == -1 ) {
70 if(!contact.categories().isEmpty() )
71 continue;
72 } else if ( bCat && cat != 0)
73 if (!contact.categories().contains( cat ) )
74 continue;
75 catPassed = true;
76 break;
77 }
78
79 /*
80 * If none of the Categories matched
81 * continue
82 */
83 if ( !catPassed )
84 continue;
85
86 vector.insert(item++, contact );
87 }
88
89 vector.resize( item );
90 /* sort it now */
91 vector.sort();
92 /* now get the uids */
93 UIDArray array( vector.count() );
94 for (uint i= 0; i < vector.count(); i++ )
95 array[i] = vector.uidAt( i );
96
97 return array;
98}
99
100OPimBackendOccurrence::List OPimContactAccessBackend::occurrences( const QDate& start,
101 const QDate& end)const {
102 OPimBackendOccurrence::List lst;
103
104 UIDArray records = allRecords();
105 const uint count = records.count();
106 int uid;
107
108 for ( uint i = 0; i < count; ++i ) {
109 uid = records[i];
110 OPimContact contact = find(uid, records, i, Frontend::Forward );
111
112 QDate date = contact.anniversary();
113 date = QDate( start.year(), date.month(),date.day() );
114
115// if ( date.isValid() && date.) {
116// }
117 }
118
119 return lst;
120}
121}
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend.h b/libopie2/opiepim/backend/ocontactaccessbackend.h
index 8436adc..efb04c7 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend.h
@@ -44,71 +44,65 @@
44 44
45#include <qregexp.h> 45#include <qregexp.h>
46 46
47namespace Opie { 47namespace Opie {
48/** 48/**
49 * This class represents the interface of all Contact Backends. 49 * This class represents the interface of all Contact Backends.
50 * Derivates of this class will be used to access the contacts. 50 * Derivates of this class will be used to access the contacts.
51 * As implementation currently XML and vCard exist. This class needs to be implemented 51 * As implementation currently XML and vCard exist. This class needs to be implemented
52 * if you want to provide your own storage. 52 * if you want to provide your own storage.
53 * In all queries a list of uids is passed on instead of loading the actual record! 53 * In all queries a list of uids is passed on instead of loading the actual record!
54 * 54 *
55 * @see OPimContactAccessBackend_VCard 55 * @see OPimContactAccessBackend_VCard
56 * @see OPimContactAccessBackend_XML 56 * @see OPimContactAccessBackend_XML
57 */ 57 */
58class OPimContactAccessBackend: public OPimAccessBackend<OPimContact> { 58class OPimContactAccessBackend: public OPimAccessBackend<OPimContact> {
59 public: 59 public:
60 /** 60 OPimContactAccessBackend();
61 * @todo make non line in regard to BC guide of KDE
62 */
63 OPimContactAccessBackend() {}
64 /**
65 * @todo make non inline in regard to the BC guide of KDE
66 */
67 virtual ~OPimContactAccessBackend() {}
68 61
69 62
70 /** 63 /**
71 * Return if database was changed externally. 64 * Return if database was changed externally.
72 * This may just make sense on file based databases like a XML-File. 65 * This may just make sense on file based databases like a XML-File.
73 * It is used to prevent to overwrite the current database content 66 * It is used to prevent to overwrite the current database content
74 * if the file was already changed by something else ! 67 * if the file was already changed by something else !
75 * If this happens, we have to reload before save our data. 68 * If this happens, we have to reload before save our data.
76 * If we use real databases, this should be handled by the database 69 * If we use real databases, this should be handled by the database
77 * management system themselve, therefore this function should always return false in 70 * management system themselve, therefore this function should always return false in
78 * this case. It is not our problem to handle this conflict ... 71 * this case. It is not our problem to handle this conflict ...
79 * @return <i>true</i> if the database was changed and if save without reload will 72 * @return <i>true</i> if the database was changed and if save without reload will
80 * be dangerous. <i>false</i> if the database was not changed or it is save to write 73 * be dangerous. <i>false</i> if the database was not changed or it is save to write
81 * in this situation. 74 * in this situation.
82 */ 75 */
83 virtual bool wasChangedExternally() = 0; 76 virtual bool wasChangedExternally() = 0;
84 77
85 virtual QArray<int> matchRegexp( const QRegExp &r ) const = 0; 78 /**
79 * Return all possible settings.
80 * @return All settings provided by the current backend
81 * (i.e.: query_WildCards & query_IgnoreCase)
82 */
83 virtual const uint querySettings() = 0;
86 84
87 /** 85 /**
88 * Return all possible settings. 86 * Check whether settings are correct.
89 * @return All settings provided by the current backend 87 * @return <i>true</i> if the given settings are correct and possible.
90 * (i.e.: query_WildCards & query_IgnoreCase) 88 */
91 */ 89 virtual bool hasQuerySettings (uint querySettings) const = 0;
92 virtual const uint querySettings() = 0; 90
91 /**
92 * Slow and inefficent default implementation
93 */
94//@{
95 UIDArray queryByExample( const OPimContact&, int settings, const QDateTime& d = QDateTime() )const;
96 UIDArray sorted( const UIDArray&, bool asc, int, int, const QArray<int>& )const;
97 OPimBackendOccurrence::List occurrences( const QDate&, const QDate& )const;
98//@}
93 99
94 /**
95 * Check whether settings are correct.
96 * @return <i>true</i> if the given settings are correct and possible.
97 */
98 virtual bool hasQuerySettings (uint querySettings) const = 0;
99 100
100 /**
101 * FIXME!!!
102 * Returns a sorted list of records either ascendinf or descending for a giving criteria and category
103 */
104 virtual QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat ) = 0;
105
106
107private: 101private:
108 class Private; 102 class Private;
109 Private *d; 103 Private *d;
110}; 104};
111 105
112} 106}
113 107
114#endif 108#endif
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
index af77a05..43e530a 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
@@ -154,71 +154,48 @@ OPimContact OPimContactAccessBackend_VCard::find ( int uid ) const
154{ 154{
155 return m_map[uid]; 155 return m_map[uid];
156} 156}
157 157
158QArray<int> OPimContactAccessBackend_VCard::allRecords() const 158QArray<int> OPimContactAccessBackend_VCard::allRecords() const
159{ 159{
160 QArray<int> ar( m_map.count() ); 160 QArray<int> ar( m_map.count() );
161 QMap<int, OPimContact>::ConstIterator it; 161 QMap<int, OPimContact>::ConstIterator it;
162 int i = 0; 162 int i = 0;
163 for ( it = m_map.begin(); it != m_map.end(); ++it ) { 163 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
164 ar[i] = it.key(); 164 ar[i] = it.key();
165 i++; 165 i++;
166 } 166 }
167 return ar; 167 return ar;
168} 168}
169 169
170// Not implemented
171QArray<int> OPimContactAccessBackend_VCard::queryByExample ( const OPimContact&, int, const QDateTime& )
172{
173 QArray<int> ar(0);
174 return ar;
175}
176
177// Not implemented
178QArray<int> OPimContactAccessBackend_VCard::matchRegexp( const QRegExp& ) const
179{
180 QArray<int> ar(0);
181 return ar;
182}
183
184const uint OPimContactAccessBackend_VCard::querySettings() 170const uint OPimContactAccessBackend_VCard::querySettings()
185{ 171{
186 return 0; // No search possible 172 return 0; // No search possible
187} 173}
188 174
189bool OPimContactAccessBackend_VCard::hasQuerySettings (uint ) const 175bool OPimContactAccessBackend_VCard::hasQuerySettings (uint ) const
190{ 176{
191 return false; // No search possible, therefore all settings invalid ;) 177 return false; // No search possible, therefore all settings invalid ;)
192} 178}
193 179
194bool OPimContactAccessBackend_VCard::wasChangedExternally() 180bool OPimContactAccessBackend_VCard::wasChangedExternally()
195{ 181{
196 return false; // Don't expect concurrent access 182 return false; // Don't expect concurrent access
197} 183}
198 184
199// Not implemented
200QArray<int> OPimContactAccessBackend_VCard::sorted( bool , int, int, int )
201{
202 QArray<int> ar(0);
203 return ar;
204}
205
206// *** Private stuff *** 185// *** Private stuff ***
207
208
209OPimContact OPimContactAccessBackend_VCard::parseVObject( VObject *obj ) 186OPimContact OPimContactAccessBackend_VCard::parseVObject( VObject *obj )
210{ 187{
211 OPimContact c; 188 OPimContact c;
212 189
213 VObjectIterator it; 190 VObjectIterator it;
214 initPropIterator( &it, obj ); 191 initPropIterator( &it, obj );
215 while( moreIteration( &it ) ) { 192 while( moreIteration( &it ) ) {
216 VObject *o = nextVObject( &it ); 193 VObject *o = nextVObject( &it );
217 QCString name = vObjectName( o ); 194 QCString name = vObjectName( o );
218 QString value = QString::fromUtf8( vObjectStringZValue( o ) ); 195 QString value = QString::fromUtf8( vObjectStringZValue( o ) );
219 odebug << "(1)Read: %s" << QString( value ).latin1() << oendl; 196 odebug << "(1)Read: %s" << QString( value ).latin1() << oendl;
220 if ( name == VCNameProp ) { 197 if ( name == VCNameProp ) {
221 VObjectIterator nit; 198 VObjectIterator nit;
222 initPropIterator( &nit, o ); 199 initPropIterator( &nit, o );
223 while( moreIteration( &nit ) ) { 200 while( moreIteration( &nit ) ) {
224 VObject *o = nextVObject( &nit ); 201 VObject *o = nextVObject( &nit );
@@ -307,33 +284,32 @@ OPimContact OPimContactAccessBackend_VCard::parseVObject( VObject *obj )
307 type |= CELL; 284 type |= CELL;
308 else if ( name == VCFaxProp ) 285 else if ( name == VCFaxProp )
309 type |= FAX; 286 type |= FAX;
310 else if ( name == VCPagerProp ) 287 else if ( name == VCPagerProp )
311 type |= PAGER; 288 type |= PAGER;
312 else if ( name == VCPreferredProp ) 289 else if ( name == VCPreferredProp )
313 ; 290 ;
314 else 291 else
315 type |= UNKNOWN; 292 type |= UNKNOWN;
316 } 293 }
317 if ( (type & UNKNOWN) != UNKNOWN ) { 294 if ( (type & UNKNOWN) != UNKNOWN ) {
318 if ( ( type & (HOME|WORK) ) == 0 ) // default 295 if ( ( type & (HOME|WORK) ) == 0 ) // default
319 type |= HOME; 296 type |= HOME;
320 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default 297 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
321 type |= VOICE; 298 type |= VOICE;
322 299
323 owarn << "value %s %d" << value.data() << type << oendl;
324 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) ) 300 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) && (type & (CELL|HOME) ) != (CELL|HOME) )
325 c.setHomePhone( value ); 301 c.setHomePhone( value );
326 if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) 302 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
327 c.setHomeFax( value ); 303 c.setHomeFax( value );
328 if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) 304 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
329 c.setHomeMobile( value ); 305 c.setHomeMobile( value );
330 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) ) 306 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) && (type & (CELL|WORK) ) != (CELL|WORK) )
331 c.setBusinessPhone( value ); 307 c.setBusinessPhone( value );
332 if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) 308 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
333 c.setBusinessFax( value ); 309 c.setBusinessFax( value );
334 if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) 310 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
335 c.setBusinessMobile( value ); 311 c.setBusinessMobile( value );
336 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) 312 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
337 c.setBusinessPager( value ); 313 c.setBusinessPager( value );
338 } 314 }
339 } 315 }
@@ -512,52 +488,50 @@ VObject* OPimContactAccessBackend_VCard::createVObject( const OPimContact &c )
512 488
513 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() ); 489 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
514 safeAddProp( title, VCWorkProp ); 490 safeAddProp( title, VCWorkProp );
515 491
516 492
517 QStringList emails = c.emailList(); 493 QStringList emails = c.emailList();
518 // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045 494 // emails.prepend( c.defaultEmail() ); Fix for bugreport #1045
519 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) { 495 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
520 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it ); 496 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
521 safeAddProp( email, VCInternetProp ); 497 safeAddProp( email, VCInternetProp );
522 } 498 }
523 499
524 safeAddPropValue( vcard, VCNoteProp, c.notes() ); 500 safeAddPropValue( vcard, VCNoteProp, c.notes() );
525 501
526 // Exporting Birthday regarding RFC 2425 (5.8.4) 502 // Exporting Birthday regarding RFC 2425 (5.8.4)
527 if ( c.birthday().isValid() ){ 503 if ( c.birthday().isValid() ){
528 owarn << "Exporting birthday as: " << convDateToVCardDate( c.birthday() ) << "" << oendl;
529 safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) ); 504 safeAddPropValue( vcard, VCBirthDateProp, convDateToVCardDate( c.birthday() ) );
530 } 505 }
531 506
532 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) { 507 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
533 VObject *org = safeAddProp( vcard, VCOrgProp ); 508 VObject *org = safeAddProp( vcard, VCOrgProp );
534 safeAddPropValue( org, VCOrgNameProp, c.company() ); 509 safeAddPropValue( org, VCOrgNameProp, c.company() );
535 safeAddPropValue( org, VCOrgUnitProp, c.department() ); 510 safeAddPropValue( org, VCOrgUnitProp, c.department() );
536 safeAddPropValue( org, VCOrgUnit2Prop, c.office() ); 511 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
537 } 512 }
538 513
539 // some values we have to export as custom fields 514 // some values we have to export as custom fields
540 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() ); 515 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
541 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() ); 516 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
542 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() ); 517 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
543 518
544 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() ); 519 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
545 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() ); 520 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
546 if ( c.anniversary().isValid() ){ 521 if ( c.anniversary().isValid() ){
547 owarn << "Exporting anniversary as: " << convDateToVCardDate( c.anniversary() ) << "" << oendl;
548 safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) ); 522 safeAddPropValue( vcard, "X-Qtopia-Anniversary", convDateToVCardDate( c.anniversary() ) );
549 } 523 }
550 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() ); 524 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
551 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() ); 525 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
552 526
553 return vcard; 527 return vcard;
554} 528}
555 529
556QString OPimContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const 530QString OPimContactAccessBackend_VCard::convDateToVCardDate( const QDate& d ) const
557{ 531{
558 QString str_rfc2425 = QString("%1-%2-%3") 532 QString str_rfc2425 = QString("%1-%2-%3")
559 .arg( d.year() ) 533 .arg( d.year() )
560 .arg( d.month(), 2 ) 534 .arg( d.month(), 2 )
561 .arg( d.day(), 2 ); 535 .arg( d.day(), 2 );
562 // Now replace spaces with "0"... 536 // Now replace spaces with "0"...
563 int pos = 0; 537 int pos = 0;
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
index 2a786af..1faf747 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.h
@@ -46,38 +46,35 @@ namespace Opie {
46 */ 46 */
47class OPimContactAccessBackend_VCard : public OPimContactAccessBackend { 47class OPimContactAccessBackend_VCard : public OPimContactAccessBackend {
48 public: 48 public:
49 OPimContactAccessBackend_VCard ( const QString& appname, const QString& filename = QString::null ); 49 OPimContactAccessBackend_VCard ( const QString& appname, const QString& filename = QString::null );
50 50
51 bool load (); 51 bool load ();
52 bool reload(); 52 bool reload();
53 bool save(); 53 bool save();
54 void clear (); 54 void clear ();
55 55
56 bool add ( const OPimContact& newcontact ); 56 bool add ( const OPimContact& newcontact );
57 bool remove ( int uid ); 57 bool remove ( int uid );
58 bool replace ( const OPimContact& contact ); 58 bool replace ( const OPimContact& contact );
59 59
60 OPimContact find ( int uid ) const; 60 OPimContact find ( int uid ) const;
61 QArray<int> allRecords() const; 61 QArray<int> allRecords() const;
62 QArray<int> queryByExample ( const OPimContact &query, int settings, const QDateTime& d = QDateTime() );
63 QArray<int> matchRegexp( const QRegExp &r ) const;
64 62
65 const uint querySettings(); 63 const uint querySettings();
66 bool hasQuerySettings (uint querySettings) const; 64 bool hasQuerySettings (uint querySettings) const;
67 QArray<int> sorted( bool ascending, int sortOrder, int sortFilter, int cat );
68 bool wasChangedExternally(); 65 bool wasChangedExternally();
69 66
70private: 67private:
71 OPimContact parseVObject( VObject* obj ); 68 OPimContact parseVObject( VObject* obj );
72 VObject* createVObject( const OPimContact& c ); 69 VObject* createVObject( const OPimContact& c );
73 QString convDateToVCardDate( const QDate& c ) const; 70 QString convDateToVCardDate( const QDate& c ) const;
74 QDate convVCardDateToDate( const QString& datestr ); 71 QDate convVCardDateToDate( const QString& datestr );
75 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value ); 72 VObject *safeAddPropValue( VObject *o, const char* prop, const QString& value );
76 VObject *safeAddProp( VObject* o, const char* prop); 73 VObject *safeAddProp( VObject* o, const char* prop);
77 74
78 bool m_dirty : 1; 75 bool m_dirty : 1;
79 QString m_file; 76 QString m_file;
80 QMap<int, OPimContact> m_map; 77 QMap<int, OPimContact> m_map;
81}; 78};
82 79
83} 80}
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
index 18113c2..5df7253 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.cpp
@@ -95,63 +95,60 @@ bool OPimContactAccessBackend_XML::save()
95 int idx_offset = 0; 95 int idx_offset = 0;
96 QString out; 96 QString out;
97 97
98 // Write Header 98 // Write Header
99 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 99 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
100 " <Groups>\n" 100 " <Groups>\n"
101 " </Groups>\n" 101 " </Groups>\n"
102 " <Contacts>\n"; 102 " <Contacts>\n";
103 QCString cstr = out.utf8(); 103 QCString cstr = out.utf8();
104 f.writeBlock( cstr.data(), cstr.length() ); 104 f.writeBlock( cstr.data(), cstr.length() );
105 idx_offset += cstr.length(); 105 idx_offset += cstr.length();
106 out = ""; 106 out = "";
107 107
108 // Write all contacts 108 // Write all contacts
109 QListIterator<OPimContact> it( m_contactList ); 109 QListIterator<OPimContact> it( m_contactList );
110 for ( ; it.current(); ++it ) { 110 for ( ; it.current(); ++it ) {
111 // owarn << " Uid " << (*it)->uid() << " at Offset: " << idx_offset << "" << oendl;
112 out += "<Contact "; 111 out += "<Contact ";
113 (*it)->save( out ); 112 (*it)->save( out );
114 out += "/>\n"; 113 out += "/>\n";
115 cstr = out.utf8(); 114 cstr = out.utf8();
116 total_written = f.writeBlock( cstr.data(), cstr.length() ); 115 total_written = f.writeBlock( cstr.data(), cstr.length() );
117 idx_offset += cstr.length(); 116 idx_offset += cstr.length();
118 if ( total_written != int(cstr.length()) ) { 117 if ( total_written != int(cstr.length()) ) {
119 f.close(); 118 f.close();
120 QFile::remove( strNewFile ); 119 QFile::remove( strNewFile );
121 return false; 120 return false;
122 } 121 }
123 out = ""; 122 out = "";
124 } 123 }
125 out += " </Contacts>\n</AddressBook>\n"; 124 out += " </Contacts>\n</AddressBook>\n";
126 125
127 // Write Footer 126 // Write Footer
128 cstr = out.utf8(); 127 cstr = out.utf8();
129 total_written = f.writeBlock( cstr.data(), cstr.length() ); 128 total_written = f.writeBlock( cstr.data(), cstr.length() );
130 if ( total_written != int( cstr.length() ) ) { 129 if ( total_written != int( cstr.length() ) ) {
131 f.close(); 130 f.close();
132 QFile::remove( strNewFile ); 131 QFile::remove( strNewFile );
133 return false; 132 return false;
134 } 133 }
135 f.close(); 134 f.close();
136 135
137 // move the file over, I'm just going to use the system call 136 // move the file over, I'm just going to use the system call
138 // because, I don't feel like using QDir. 137 // because, I don't feel like using QDir.
139 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) { 138 if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
140 owarn << "problem renaming file " << strNewFile << " to " << m_journalName
141 << ", errno: " << errno << oendl;
142 // remove the tmp file... 139 // remove the tmp file...
143 QFile::remove( strNewFile ); 140 QFile::remove( strNewFile );
144 } 141 }
145 142
146 /* The journalfile should be removed now... */ 143 /* The journalfile should be removed now... */
147 removeJournal(); 144 removeJournal();
148 145
149 m_changed = false; 146 m_changed = false;
150 return true; 147 return true;
151} 148}
152 149
153bool OPimContactAccessBackend_XML::load () 150bool OPimContactAccessBackend_XML::load ()
154{ 151{
155 m_contactList.clear(); 152 m_contactList.clear();
156 m_uidToContact.clear(); 153 m_uidToContact.clear();
157 154
@@ -200,35 +197,34 @@ QArray<int> OPimContactAccessBackend_XML::allRecords() const
200} 197}
201 198
202OPimContact OPimContactAccessBackend_XML::find ( int uid ) const 199OPimContact OPimContactAccessBackend_XML::find ( int uid ) const
203{ 200{
204 OPimContact foundContact; //Create empty contact 201 OPimContact foundContact; //Create empty contact
205 202
206 OPimContact* found = m_uidToContact.find( QString().setNum( uid ) ); 203 OPimContact* found = m_uidToContact.find( QString().setNum( uid ) );
207 204
208 if ( found ){ 205 if ( found ){
209 foundContact = *found; 206 foundContact = *found;
210 } 207 }
211 208
212 return ( foundContact ); 209 return ( foundContact );
213} 210}
214 211
215QArray<int> OPimContactAccessBackend_XML::queryByExample ( const OPimContact &query, int settings, 212QArray<int> OPimContactAccessBackend_XML::queryByExample ( const OPimContact &query, int settings,
216 const QDateTime& d ) 213 const QDateTime& d )const
217{ 214{
218
219 QArray<int> m_currentQuery( m_contactList.count() ); 215 QArray<int> m_currentQuery( m_contactList.count() );
220 QListIterator<OPimContact> it( m_contactList ); 216 QListIterator<OPimContact> it( m_contactList );
221 uint arraycounter = 0; 217 uint arraycounter = 0;
222 218
223 for( ; it.current(); ++it ){ 219 for( ; it.current(); ++it ){
224 /* Search all fields and compare them with query object. Store them into list 220 /* Search all fields and compare them with query object. Store them into list
225 * if all fields matches. 221 * if all fields matches.
226 */ 222 */
227 QDate* queryDate = 0l; 223 QDate* queryDate = 0l;
228 QDate* checkDate = 0l; 224 QDate* checkDate = 0l;
229 bool allcorrect = true; 225 bool allcorrect = true;
230 for ( int i = 0; i < Qtopia::Groups; i++ ) { 226 for ( int i = 0; i < Qtopia::Groups; i++ ) {
231 // Birthday and anniversary are special nonstring fields and should 227 // Birthday and anniversary are special nonstring fields and should
232 // be handled specially 228 // be handled specially
233 switch ( i ){ 229 switch ( i ){
234 case Qtopia::Birthday: 230 case Qtopia::Birthday:
@@ -265,39 +261,36 @@ QArray<int> OPimContactAccessBackend_XML::queryByExample ( const OPimContact &qu
265 else 261 else
266 current = d.date(); 262 current = d.date();
267 263
268 // We have to equalize the year, otherwise 264 // We have to equalize the year, otherwise
269 // the search will fail.. 265 // the search will fail..
270 checkDate->setYMD( current.year(), 266 checkDate->setYMD( current.year(),
271 checkDate->month(), 267 checkDate->month(),
272 checkDate->day() ); 268 checkDate->day() );
273 if ( *checkDate < current ) 269 if ( *checkDate < current )
274 checkDate->setYMD( current.year()+1, 270 checkDate->setYMD( current.year()+1,
275 checkDate->month(), 271 checkDate->month(),
276 checkDate->day() ); 272 checkDate->day() );
277 273
278 // Check whether the birthday/anniversary date is between 274 // Check whether the birthday/anniversary date is between
279 // the current/given date and the maximum date 275 // the current/given date and the maximum date
280 // ( maximum time range ) ! 276 // ( maximum time range ) !
281 owarn << "Checking if " << checkDate->toString() << " is between " << current.toString()
282 << " and " << queryDate->toString() << " ! " << oendl;
283 if ( current.daysTo( *queryDate ) >= 0 ){ 277 if ( current.daysTo( *queryDate ) >= 0 ){
284 if ( !( ( *checkDate >= current ) && 278 if ( !( ( *checkDate >= current ) &&
285 ( *checkDate <= *queryDate ) ) ){ 279 ( *checkDate <= *queryDate ) ) ){
286 allcorrect = false; 280 allcorrect = false;
287 owarn << " Nope!.." << oendl;
288 } 281 }
289 } 282 }
290 } 283 }
291 } else{ 284 } else{
292 // checkDate is invalid. Therefore this entry is always rejected 285 // checkDate is invalid. Therefore this entry is always rejected
293 allcorrect = false; 286 allcorrect = false;
294 } 287 }
295 } 288 }
296 289
297 delete queryDate; 290 delete queryDate;
298 queryDate = 0l; 291 queryDate = 0l;
299 delete checkDate; 292 delete checkDate;
300 checkDate = 0l; 293 checkDate = 0l;
301 break; 294 break;
302 default: 295 default:
303 /* Just compare fields which are not empty in the query object */ 296 /* Just compare fields which are not empty in the query object */
@@ -417,89 +410,89 @@ bool OPimContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
417 | OPimContactAccess::DateDay 410 | OPimContactAccess::DateDay
418 ) 411 )
419 ){ 412 ){
420 case OPimContactAccess::RegExp: 413 case OPimContactAccess::RegExp:
421 return ( true ); 414 return ( true );
422 case OPimContactAccess::WildCards: 415 case OPimContactAccess::WildCards:
423 return ( true ); 416 return ( true );
424 case OPimContactAccess::ExactMatch: 417 case OPimContactAccess::ExactMatch:
425 return ( true ); 418 return ( true );
426 case 0: // one of the upper removed bits were set.. 419 case 0: // one of the upper removed bits were set..
427 return ( true ); 420 return ( true );
428 default: 421 default:
429 return ( false ); 422 return ( false );
430 } 423 }
431} 424}
432 425
426#if 0
433// Currently only asc implemented.. 427// Currently only asc implemented..
434QArray<int> OPimContactAccessBackend_XML::sorted( bool asc, int , int , int ) 428QArray<int> OPimContactAccessBackend_XML::sorted( bool asc, int , int , int )
435{ 429{
436 QMap<QString, int> nameToUid; 430 QMap<QString, int> nameToUid;
437 QStringList names; 431 QStringList names;
438 QArray<int> m_currentQuery( m_contactList.count() ); 432 QArray<int> m_currentQuery( m_contactList.count() );
439 433
440 // First fill map and StringList with all Names 434 // First fill map and StringList with all Names
441 // Afterwards sort namelist and use map to fill array to return.. 435 // Afterwards sort namelist and use map to fill array to return..
442 QListIterator<OPimContact> it( m_contactList ); 436 QListIterator<OPimContact> it( m_contactList );
443 for( ; it.current(); ++it ){ 437 for( ; it.current(); ++it ){
444 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) ); 438 names.append( (*it)->fileAs() + QString::number( (*it)->uid() ) );
445 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() ); 439 nameToUid.insert( (*it)->fileAs() + QString::number( (*it)->uid() ), (*it)->uid() );
446 } 440 }
447 names.sort(); 441 names.sort();
448 442
449 int i = 0; 443 int i = 0;
450 if ( asc ){ 444 if ( asc ){
451 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it ) 445 for ( QStringList::Iterator it = names.begin(); it != names.end(); ++it )
452 m_currentQuery[i++] = nameToUid[ (*it) ]; 446 m_currentQuery[i++] = nameToUid[ (*it) ];
453 }else{ 447 }else{
454 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it ) 448 for ( QStringList::Iterator it = names.end(); it != names.begin(); --it )
455 m_currentQuery[i++] = nameToUid[ (*it) ]; 449 m_currentQuery[i++] = nameToUid[ (*it) ];
456 } 450 }
457 451
458 return m_currentQuery; 452 return m_currentQuery;
459 453
460} 454}
455#endif
456
461 457
462bool OPimContactAccessBackend_XML::add ( const OPimContact &newcontact ) 458bool OPimContactAccessBackend_XML::add ( const OPimContact &newcontact )
463{ 459{
464 //owarn << "odefaultbackend: ACTION::ADD" << oendl;
465 updateJournal (newcontact, ACTION_ADD); 460 updateJournal (newcontact, ACTION_ADD);
466 addContact_p( newcontact ); 461 addContact_p( newcontact );
467 462
468 m_changed = true; 463 m_changed = true;
469 464
470 return true; 465 return true;
471} 466}
472 467
473bool OPimContactAccessBackend_XML::replace ( const OPimContact &contact ) 468bool OPimContactAccessBackend_XML::replace ( const OPimContact &contact )
474{ 469{
475 m_changed = true; 470 m_changed = true;
476 471
477 OPimContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) ); 472 OPimContact* found = m_uidToContact.find ( QString().setNum( contact.uid() ) );
478 473
479 if ( found ) { 474 if ( found ) {
480 OPimContact* newCont = new OPimContact( contact ); 475 OPimContact* newCont = new OPimContact( contact );
481 476
482 updateJournal ( *newCont, ACTION_REPLACE); 477 updateJournal ( *newCont, ACTION_REPLACE);
483 m_contactList.removeRef ( found ); 478 m_contactList.removeRef ( found );
484 m_contactList.append ( newCont ); 479 m_contactList.append ( newCont );
485 m_uidToContact.remove( QString().setNum( contact.uid() ) ); 480 m_uidToContact.remove( QString().setNum( contact.uid() ) );
486 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont ); 481 m_uidToContact.insert( QString().setNum( newCont->uid() ), newCont );
487 482
488 owarn << "Nur zur Sicherheit: " << contact.uid() << " == " << newCont->uid() << " ?" << oendl;
489
490 return true; 483 return true;
491 } else 484 } else
492 return false; 485 return false;
493} 486}
494 487
495bool OPimContactAccessBackend_XML::remove ( int uid ) 488bool OPimContactAccessBackend_XML::remove ( int uid )
496{ 489{
497 m_changed = true; 490 m_changed = true;
498 491
499 OPimContact* found = m_uidToContact.find ( QString().setNum( uid ) ); 492 OPimContact* found = m_uidToContact.find ( QString().setNum( uid ) );
500 493
501 if ( found ) { 494 if ( found ) {
502 updateJournal ( *found, ACTION_REMOVE); 495 updateJournal ( *found, ACTION_REMOVE);
503 m_contactList.removeRef ( found ); 496 m_contactList.removeRef ( found );
504 m_uidToContact.remove( QString().setNum( uid ) ); 497 m_uidToContact.remove( QString().setNum( uid ) );
505 498
@@ -578,81 +571,69 @@ bool OPimContactAccessBackend_XML::load( const QString filename, bool isJournal
578 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 571 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
579 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 572 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
580 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 573 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
581 dict.insert( "Profession", new int(Qtopia::Profession) ); 574 dict.insert( "Profession", new int(Qtopia::Profession) );
582 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 575 dict.insert( "Assistant", new int(Qtopia::Assistant) );
583 dict.insert( "Manager", new int(Qtopia::Manager) ); 576 dict.insert( "Manager", new int(Qtopia::Manager) );
584 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 577 dict.insert( "Spouse", new int(Qtopia::Spouse) );
585 dict.insert( "Children", new int(Qtopia::Children) ); 578 dict.insert( "Children", new int(Qtopia::Children) );
586 dict.insert( "Gender", new int(Qtopia::Gender) ); 579 dict.insert( "Gender", new int(Qtopia::Gender) );
587 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 580 dict.insert( "Birthday", new int(Qtopia::Birthday) );
588 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 581 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
589 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 582 dict.insert( "Nickname", new int(Qtopia::Nickname) );
590 dict.insert( "Notes", new int(Qtopia::Notes) ); 583 dict.insert( "Notes", new int(Qtopia::Notes) );
591 dict.insert( "action", new int(JOURNALACTION) ); 584 dict.insert( "action", new int(JOURNALACTION) );
592 dict.insert( "actionrow", new int(JOURNALROW) ); 585 dict.insert( "actionrow", new int(JOURNALROW) );
593 586
594 //owarn << "OPimContactDefaultBackEnd::loading " << filename << "" << oendl;
595
596 XMLElement *root = XMLElement::load( filename ); 587 XMLElement *root = XMLElement::load( filename );
597 if(root != 0l ){ // start parsing 588 if(root != 0l ){ // start parsing
598 /* Parse all XML-Elements and put the data into the 589 /* Parse all XML-Elements and put the data into the
599 * Contact-Class 590 * Contact-Class
600 */ 591 */
601 XMLElement *element = root->firstChild(); 592 XMLElement *element = root->firstChild();
602 //owarn << "OPimContactAccess::load tagName(): " << root->tagName() << "" << oendl;
603 element = element ? element->firstChild() : 0; 593 element = element ? element->firstChild() : 0;
604 594
605 /* Search Tag "Contacts" which is the parent of all Contacts */ 595 /* Search Tag "Contacts" which is the parent of all Contacts */
606 while( element && !isJournal ){ 596 while( element && !isJournal ){
607 if( element->tagName() != QString::fromLatin1("Contacts") ){ 597 if( element->tagName() != QString::fromLatin1("Contacts") ){
608 //owarn << "OPimContactDefBack::Searching for Tag \"Contacts\"! Found: "
609 // << element->tagName() << oendl;
610 element = element->nextChild(); 598 element = element->nextChild();
611 } else { 599 } else {
612 element = element->firstChild(); 600 element = element->firstChild();
613 break; 601 break;
614 } 602 }
615 } 603 }
616 /* Parse all Contacts and ignore unknown tags */ 604 /* Parse all Contacts and ignore unknown tags */
617 while( element ){ 605 while( element ){
618 if( element->tagName() != QString::fromLatin1("Contact") ){ 606 if( element->tagName() != QString::fromLatin1("Contact") ){
619 //owarn << "OPimContactDefBack::Searching for Tag \"Contact\"! Found: "
620 // << element->tagName() << oendl;
621 element = element->nextChild(); 607 element = element->nextChild();
622 continue; 608 continue;
623 } 609 }
624 /* Found alement with tagname "contact", now parse and store all 610 /* Found alement with tagname "contact", now parse and store all
625 * attributes contained 611 * attributes contained
626 */ 612 */
627 //owarn << "OPimContactDefBack::load element tagName() : "
628 // << element->tagName() << oendl;
629 QString dummy; 613 QString dummy;
630 foundAction = false; 614 foundAction = false;
631 615
632 XMLElement::AttributeMap aMap = element->attributes(); 616 XMLElement::AttributeMap aMap = element->attributes();
633 XMLElement::AttributeMap::Iterator it; 617 XMLElement::AttributeMap::Iterator it;
634 contactMap.clear(); 618 contactMap.clear();
635 customMap.clear(); 619 customMap.clear();
636 for( it = aMap.begin(); it != aMap.end(); ++it ){ 620 for( it = aMap.begin(); it != aMap.end(); ++it ){
637 // owarn << "Read Attribute: " << it.key() << "=" << it.data() << oendl;
638
639 int *find = dict[ it.key() ]; 621 int *find = dict[ it.key() ];
640 /* Unknown attributes will be stored as "Custom" elements */ 622 /* Unknown attributes will be stored as "Custom" elements */
641 if ( !find ) { 623 if ( !find ) {
642 // owarn << "Attribute " << it.key() << " not known." << oendl;
643 //contact.setCustomField(it.key(), it.data()); 624 //contact.setCustomField(it.key(), it.data());
644 customMap.insert( it.key(), it.data() ); 625 customMap.insert( it.key(), it.data() );
645 continue; 626 continue;
646 } 627 }
647 628
648 /* Check if special conversion is needed and add attribute 629 /* Check if special conversion is needed and add attribute
649 * into Contact class 630 * into Contact class
650 */ 631 */
651 switch( *find ) { 632 switch( *find ) {
652 /* 633 /*
653 case Qtopia::AddressUid: 634 case Qtopia::AddressUid:
654 contact.setUid( it.data().toInt() ); 635 contact.setUid( it.data().toInt() );
655 break; 636 break;
656 case Qtopia::AddressCategory: 637 case Qtopia::AddressCategory:
657 contact.setCategories( Qtopia::Record::idsFromString( it.data( ))); 638 contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
658 break; 639 break;
@@ -691,36 +672,34 @@ bool OPimContactAccessBackend_XML::load( const QString filename, bool isJournal
691 if ( !replace ( contact ) ) 672 if ( !replace ( contact ) )
692 owarn << "ODefBack(journal)::Unable to replace uid: " << contact.uid() << oendl; 673 owarn << "ODefBack(journal)::Unable to replace uid: " << contact.uid() << oendl;
693 break; 674 break;
694 default: 675 default:
695 owarn << "Unknown action: ignored !" << oendl; 676 owarn << "Unknown action: ignored !" << oendl;
696 break; 677 break;
697 } 678 }
698 }else{ 679 }else{
699 /* Add contact to list */ 680 /* Add contact to list */
700 addContact_p (contact); 681 addContact_p (contact);
701 } 682 }
702 683
703 /* Move to next element */ 684 /* Move to next element */
704 element = element->nextChild(); 685 element = element->nextChild();
705 } 686 }
706 }else { 687 }else {
707 owarn << "ODefBack::could not load" << oendl;
708 } 688 }
709 delete root; 689 delete root;
710 owarn << "returning from loading" << oendl;
711 return true; 690 return true;
712} 691}
713 692
714 693
715void OPimContactAccessBackend_XML::updateJournal( const OPimContact& cnt, 694void OPimContactAccessBackend_XML::updateJournal( const OPimContact& cnt,
716 journal_action action ) 695 journal_action action )
717{ 696{
718 QFile f( m_journalName ); 697 QFile f( m_journalName );
719 bool created = !f.exists(); 698 bool created = !f.exists();
720 if ( !f.open(IO_WriteOnly|IO_Append) ) 699 if ( !f.open(IO_WriteOnly|IO_Append) )
721 return; 700 return;
722 701
723 QString buf; 702 QString buf;
724 QCString str; 703 QCString str;
725 704
726 // if the file was created, we have to set the Tag "<CONTACTS>" to 705 // if the file was created, we have to set the Tag "<CONTACTS>" to
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
index eaea352..3e4f1e1 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_xml.h
@@ -49,42 +49,39 @@ namespace Opie {
49class OPimContactAccessBackend_XML : public OPimContactAccessBackend { 49class OPimContactAccessBackend_XML : public OPimContactAccessBackend {
50 public: 50 public:
51 OPimContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null ); 51 OPimContactAccessBackend_XML ( const QString& appname, const QString& filename = QString::null );
52 52
53 bool save(); 53 bool save();
54 54
55 bool load (); 55 bool load ();
56 56
57 void clear (); 57 void clear ();
58 58
59 bool wasChangedExternally(); 59 bool wasChangedExternally();
60 60
61 QArray<int> allRecords() const; 61 QArray<int> allRecords() const;
62 62
63 OPimContact find ( int uid ) const; 63 OPimContact find ( int uid ) const;
64 64
65 QArray<int> queryByExample ( const OPimContact &query, int settings, const QDateTime& d = QDateTime() ); 65 QArray<int> queryByExample ( const OPimContact &query, int settings, const QDateTime& d )const;
66
67 QArray<int> matchRegexp( const QRegExp &r ) const; 66 QArray<int> matchRegexp( const QRegExp &r ) const;
68 67
69 const uint querySettings(); 68 const uint querySettings();
70 69
71 bool hasQuerySettings (uint querySettings) const; 70 bool hasQuerySettings (uint querySettings) const;
72 71
73 // Currently only asc implemented..
74 QArray<int> sorted( bool asc, int , int , int );
75 bool add ( const OPimContact &newcontact ); 72 bool add ( const OPimContact &newcontact );
76 73
77 bool replace ( const OPimContact &contact ); 74 bool replace ( const OPimContact &contact );
78 75
79 bool remove ( int uid ); 76 bool remove ( int uid );
80 bool reload(); 77 bool reload();
81 78
82 private: 79 private:
83 80
84 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; 81 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
85 82
86 void addContact_p( const OPimContact &newcontact ); 83 void addContact_p( const OPimContact &newcontact );
87 84
88 /* This function loads the xml-database and the journalfile */ 85 /* This function loads the xml-database and the journalfile */
89 bool load( const QString filename, bool isJournal ); 86 bool load( const QString filename, bool isJournal );
90 87
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend.cpp b/libopie2/opiepim/backend/odatebookaccessbackend.cpp
index f3b7b5f..73c7059 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend.cpp
@@ -23,194 +23,142 @@
23 -_. . . )=. = Library General Public License along with 23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB. 24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation, 25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330, 26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. 27 Boston, MA 02111-1307, USA.
28*/ 28*/
29#include <qtl.h> 29#include <qtl.h>
30 30
31#include <opie2/opimrecurrence.h> 31#include <opie2/opimrecurrence.h>
32 32
33#include <opie2/odatebookaccessbackend.h> 33#include <opie2/odatebookaccessbackend.h>
34 34
35using namespace Opie; 35using namespace Opie;
36 36
37namespace { 37namespace {
38/* a small helper to get all NonRepeating events for a range of time */ 38/* a small helper to get all NonRepeating events for a range of time */
39 void events( OEffectiveEvent::ValueList& tmpList, const OPimEvent::ValueList& events, 39void events( OPimBackendOccurrence::List& tmpList,
40 const QDate& from, const QDate& to ) { 40 const OPimEvent::ValueList& events,
41 QDateTime dtStart, dtEnd; 41 const QDate& from, const QDate& to ) {
42 42 QDateTime dtStart, dtEnd;
43 for ( OPimEvent::ValueList::ConstIterator it = events.begin(); it != events.end(); ++it ) { 43
44 dtStart = (*it).startDateTime(); 44 for ( OPimEvent::ValueList::ConstIterator it = events.begin(); it != events.end(); ++it ) {
45 dtEnd = (*it).endDateTime(); 45 dtStart = (*it).startDateTime();
46 46 dtEnd = (*it).endDateTime();
47 /* 47
48 * If in range 48 /*
49 */ 49 * If in range
50 if (dtStart.date() >= from && dtEnd.date() <= to ) { 50 */
51 OEffectiveEvent eff; 51 if (dtStart.date() >= from && dtEnd.date() <= to ) {
52 eff.setEvent( (*it) ); 52 OPimBackendOccurrence eff( dtStart, dtEnd, (*it).uid() );;
53 eff.setDate( dtStart.date() ); 53 tmpList.append( eff );
54 eff.setStartTime( dtStart.time() );
55
56 /* if not on the same day */
57 if ( dtStart.date() != dtEnd.date() )
58 eff.setEndTime( QTime(23, 59, 0 ) );
59 else
60 eff.setEndTime( dtEnd.time() );
61
62 tmpList.append( eff );
63 }
64
65 /* we must also check for end date information... */
66 if ( dtEnd.date() != dtStart.date() && dtEnd.date() >= from ) {
67 QDateTime dt = dtStart.addDays( 1 );
68 dt.setTime( QTime(0, 0, 0 ) );
69 QDateTime dtStop;
70 if ( dtEnd > to )
71 dtStop = to;
72 else
73 dtStop = dtEnd;
74
75 while ( dt <= dtStop ) {
76 OEffectiveEvent eff;
77 eff.setEvent( (*it) );
78 eff.setDate( dt.date() );
79
80 if ( dt >= from ) {
81 eff.setStartTime( QTime(0, 0, 0 ) );
82 if ( dt.date() == dtEnd.date() )
83 eff.setEndTime( dtEnd.time() );
84 else
85 eff.setEndTime( QTime(23, 59, 0 ) );
86 tmpList.append( eff );
87 }
88 dt = dt.addDays( 1 );
89 }
90 }
91 } 54 }
92 } 55 }
56}
93 57
94 void repeat( OEffectiveEvent::ValueList& tmpList, const OPimEvent::ValueList& list, 58void repeat( OPimBackendOccurrence::List& tmpList, const OPimEvent::ValueList& list,
95 const QDate& from, const QDate& to ) { 59 const QDate& from, const QDate& to ) {
96 QDate repeat; 60 QDate repeat;
97 for ( OPimEvent::ValueList::ConstIterator it = list.begin(); it != list.end(); ++it ) { 61 for ( OPimEvent::ValueList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
98 int dur = (*it).startDateTime().date().daysTo( (*it).endDateTime().date() ); 62 int dur = (*it).startDateTime().date().daysTo( (*it).endDateTime().date() );
99 QDate itDate = from.addDays(-dur ); 63 QDate itDate = from.addDays(-dur );
100 OPimRecurrence rec = (*it).recurrence(); 64 OPimRecurrence rec = (*it).recurrence();
101 if ( !rec.hasEndDate() || rec.endDate() > to ) { 65 if ( !rec.hasEndDate() || rec.endDate() > to ) {
102 rec.setEndDate( to ); 66 rec.setEndDate( to );
103 rec.setHasEndDate( true ); 67 rec.setHasEndDate( true );
104 } 68 }
105 while (rec.nextOcurrence(itDate, repeat ) ) { 69
106 if (repeat > to ) break; 70 QDateTime start, end;
107 OEffectiveEvent eff; 71 while (rec.nextOcurrence(itDate, repeat ) ) {
108 eff.setDate( repeat ); 72 if (repeat > to ) break;
109 if ( (*it).isAllDay() ) { 73
110 eff.setStartTime( QTime(0, 0, 0 ) ); 74 OPimEvent event = *it;
111 eff.setEndTime( QTime(23, 59, 59 ) ); 75 start = QDateTime( repeat, event.startDateTime().time() );
112 }else { 76 end = QDateTime( repeat.addDays(dur), event.endDateTime().time() );
113 /* we only occur by days, not hours/minutes/seconds. Hence 77 OPimBackendOccurrence eff(start, end, event.uid() );
114 * the actual end and start times will be the same for 78 tmpList.append( eff );
115 * every repeated event. For multi day events this is
116 * fixed up later if on wronge day span
117 */
118 eff.setStartTime( (*it).startDateTime().time() );
119 eff.setEndTime( (*it).endDateTime().time() );
120 }
121 if ( dur != 0 ) {
122 // multi-day repeating events
123 QDate sub_it = QMAX( repeat, from );
124 QDate startDate = repeat;
125 QDate endDate = startDate.addDays( dur );
126
127 while ( sub_it <= endDate && sub_it <= to ) {
128 OEffectiveEvent tmpEff = eff;
129 tmpEff.setEvent( (*it) );
130 if ( sub_it != startDate )
131 tmpEff.setStartTime( QTime(0, 0, 0 ) );
132 if ( sub_it != endDate )
133 tmpEff.setEndTime( QTime( 23, 59, 59 ) );
134
135 tmpEff.setDate( sub_it );
136 tmpEff.setEffectiveDates( startDate, endDate );
137 tmpList.append( tmpEff );
138
139 sub_it = sub_it.addDays( 1 );
140 }
141 itDate = endDate;
142 }else {
143 eff.setEvent( (*it) );
144 tmpList.append( eff );
145 itDate = repeat.addDays( 1 );
146 }
147 }
148 } 79 }
149 } 80 }
150} 81}
82}
151 83
152namespace Opie { 84namespace Opie {
153 85
154ODateBookAccessBackend::ODateBookAccessBackend() 86ODateBookAccessBackend::ODateBookAccessBackend()
155 : OPimAccessBackend<OPimEvent>() 87 : OPimAccessBackend<OPimEvent>()
156{ 88{
157 89
158} 90}
159ODateBookAccessBackend::~ODateBookAccessBackend() { 91ODateBookAccessBackend::~ODateBookAccessBackend() {
160 92
161} 93}
162OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDate& from, 94OPimBackendOccurrence::List ODateBookAccessBackend::occurrences( const QDate& from,
163 const QDate& to ) { 95 const QDate& to )const {
164 OEffectiveEvent::ValueList tmpList; 96 OPimBackendOccurrence::List tmpList;
165 OPimEvent::ValueList list = directNonRepeats();
166 97
167 events( tmpList, list, from, to ); 98 events( tmpList, directNonRepeats(), from, to );
168 repeat( tmpList, directRawRepeats(),from,to ); 99 repeat( tmpList, directRawRepeats(),from,to );
169 100
170 list = directRawRepeats(); // Useless, isn't it ? (eilers)
171
172 qHeapSort( tmpList );
173 return tmpList; 101 return tmpList;
174} 102}
175OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveEvents( const QDateTime& dt ) { 103OPimBackendOccurrence::List ODateBookAccessBackend::occurrences( const QDateTime& dt )const {
176 OEffectiveEvent::ValueList day = effectiveEvents( dt.date(), dt.date() ); 104 OPimBackendOccurrence::List day = occurrences( dt.date(), dt.date() );
177 OEffectiveEvent::ValueList::Iterator it;
178
179 OEffectiveEvent::ValueList tmpList;
180 QDateTime dtTmp;
181 for ( it = day.begin(); it != day.end(); ++it ) {
182 dtTmp = QDateTime( (*it).date(), (*it).startTime() );
183 if ( QABS(dt.secsTo(dtTmp) ) < 60 )
184 tmpList.append( (*it) );
185 }
186 105
187 return tmpList; 106 return filterOccurrences( day, dt );
188} 107}
189 108
190OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDate& from, 109OPimBackendOccurrence::List ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDate& from,
191 const QDate& to ) { 110 const QDate& to )const {
192 OEffectiveEvent::ValueList tmpList; 111 OPimBackendOccurrence::List tmpList;
193 OPimEvent::ValueList list = directNonRepeats(); 112 OPimEvent::ValueList list = directNonRepeats();
194 113
195 events( tmpList, list, from, to ); 114 events( tmpList, list, from, to );
196 115
197 qHeapSort( tmpList );
198 return tmpList; 116 return tmpList;
199} 117}
200 118
201OEffectiveEvent::ValueList ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDateTime& dt ) { 119OPimBackendOccurrence::List ODateBookAccessBackend::effectiveNonRepeatingEvents( const QDateTime& dt )const {
202 OEffectiveEvent::ValueList day = effectiveNonRepeatingEvents( dt.date(), dt.date() ); 120 OPimBackendOccurrence::List day = effectiveNonRepeatingEvents( dt.date(), dt.date() );
203 OEffectiveEvent::ValueList::Iterator it; 121 return filterOccurrences( day,dt );
122}
123
124
125UIDArray ODateBookAccessBackend::queryByExample( const OPimEvent&, int settings,
126 const QDateTime& d )const {
127 return UIDArray();
128}
129
130UIDArray ODateBookAccessBackend::sorted( const UIDArray&, bool asc, int, int, const QArray<int>& )const {
131 return UIDArray();
132}
204 133
205 OEffectiveEvent::ValueList tmpList; 134OPimBackendOccurrence::List ODateBookAccessBackend::filterOccurrences( const OPimBackendOccurrence::List dayList,
206 QDateTime dtTmp; 135 const QDateTime& dt ) {
207 for ( it = day.begin(); it != day.end(); ++it ) { 136 OPimBackendOccurrence::List tmpList;
208 dtTmp = QDateTime( (*it).date(), (*it).startTime() ); 137 OPimBackendOccurrence::List::ConstIterator it;
209 if ( QABS(dt.secsTo(dtTmp) ) < 60 ) 138
210 tmpList.append( (*it) ); 139 for ( it = dayList.begin(); it != dayList.end(); ++it ) {
140 OPimBackendOccurrence occ = *it;
141
142 /*
143 * Let us find occurrences that are 'now'!
144 * If the dt.date() is on the same day as start or end of the Occurrence
145 * check how near start/end are.
146 * If it is in the middle of a multiday occurrence list it.
147 *
148 * We might want to 'lose' the sixty second offset and list
149 * all Events which are active at that time.
150 */
151 if ( dt.date() == occ.startDateTime().date() ) {
152 if ( QABS( dt.time().secsTo( occ.startDateTime().time() ) ) < 60 )
153 tmpList.append( occ );
154 }else if ( dt.date() == occ.endDateTime().date() ) {
155 if ( QABS( dt.time().secsTo( occ.endDateTime().time() ) ) < 60 )
156 tmpList.append( occ );
157 }else if ( dt.date() >= occ.startDateTime().date() &&
158 dt.date() >= occ.endDateTime().date() )
159 tmpList.append( occ );
211 } 160 }
212 161
213 return tmpList; 162 return tmpList;
214} 163}
215
216} 164}
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend.h b/libopie2/opiepim/backend/odatebookaccessbackend.h
index a9cce6a..8927ca1 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend.h
+++ b/libopie2/opiepim/backend/odatebookaccessbackend.h
@@ -29,93 +29,86 @@
29#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H 29#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_H
30#define OPIE_DATE_BOOK_ACCESS_BACKEND_H 30#define OPIE_DATE_BOOK_ACCESS_BACKEND_H
31 31
32#include <qarray.h> 32#include <qarray.h>
33 33
34#include <opie2/opimaccessbackend.h> 34#include <opie2/opimaccessbackend.h>
35#include <opie2/opimevent.h> 35#include <opie2/opimevent.h>
36 36
37namespace Opie { 37namespace Opie {
38/** 38/**
39 * This class is the interface to the storage of Events. 39 * This class is the interface to the storage of Events.
40 * @see OPimAccessBackend 40 * @see OPimAccessBackend
41 * 41 *
42 */ 42 */
43class ODateBookAccessBackend : public OPimAccessBackend<OPimEvent> { 43class ODateBookAccessBackend : public OPimAccessBackend<OPimEvent> {
44public: 44public:
45 typedef int UID;
46
47 /** 45 /**
48 * c'tor without parameter 46 * c'tor without parameter
49 */ 47 */
50 ODateBookAccessBackend(); 48 ODateBookAccessBackend();
51 ~ODateBookAccessBackend(); 49 ~ODateBookAccessBackend();
52 50
53 /** 51 /**
54 * This method should return a list of UIDs containing 52 * This method should return a list of UIDs containing
55 * all events. No filter should be applied
56 * @return list of events
57 */
58 virtual QArray<UID> rawEvents()const = 0;
59
60 /**
61 * This method should return a list of UIDs containing
62 * all repeating events. No filter should be applied 53 * all repeating events. No filter should be applied
63 * @return list of repeating events 54 * @return list of repeating events
64 */ 55 */
65 virtual QArray<UID> rawRepeats()const = 0; 56 virtual UIDArray rawRepeats()const = 0;
66 57
67 /** 58 /**
68 * This mthod should return a list of UIDs containing all non 59 * This mthod should return a list of UIDs containing all non
69 * repeating events. No filter should be applied 60 * repeating events. No filter should be applied
70 * @return list of nonrepeating events 61 * @return list of nonrepeating events
71 */ 62 */
72 virtual QArray<UID> nonRepeats() const = 0; 63 virtual UIDArray nonRepeats() const = 0;
73 64
74 /** 65 /**
75 * If you do not want to implement the effectiveEvents methods below 66 * If you do not want to implement the effectiveEvents methods below
76 * you need to supply it with directNonRepeats. 67 * you need to supply it with directNonRepeats.
77 * This method can return empty lists if effectiveEvents is implememted 68 * This method can return empty lists if effectiveEvents is implememted
78 */ 69 */
79 virtual OPimEvent::ValueList directNonRepeats() = 0; 70 virtual OPimEvent::ValueList directNonRepeats()const = 0;
80 71
81 /** 72 /**
82 * Same as above but return raw repeats! 73 * Same as above but return raw repeats!
83 */ 74 */
84 virtual OPimEvent::ValueList directRawRepeats() = 0; 75 virtual OPimEvent::ValueList directRawRepeats()const = 0;
85 76
86 /* is implemented by default but you can reimplement it*/ 77 /* is implemented by default but you can reimplement it*/
87 /** 78 /**
88 * Effective Events are special event occuring during a time frame. This method does calcualte 79 * Effective Events are special event occuring during a time frame. This method does calcualte
89 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method 80 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
90 * yourself 81 * yourself
91 */ 82 */
92 virtual OEffectiveEvent::ValueList effectiveEvents( const QDate& from, const QDate& to ); 83 virtual OPimBackendOccurrence::List effectiveNonRepeatingEvents( const QDate& from, const QDate& to )const;
93 84
94 /** 85 /**
95 * this is an overloaded member function 86 * this is an overloaded member function
96 * @see effectiveEvents( const QDate& from, const QDate& to ) 87 * @see effectiveNonRepeatingEvents( const QDate& from, const QDate& to )
97 */
98 virtual OEffectiveEvent::ValueList effectiveEvents( const QDateTime& start );
99
100 /**
101 * Effective Events are special event occuring during a time frame. This method does calcualte
102 * EffectiveEvents bases on the directNonRepeats and directRawRepeats. You may implement this method
103 * yourself
104 */ 88 */
105 virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDate& from, const QDate& to ); 89 virtual OPimBackendOccurrence::List effectiveNonRepeatingEvents( const QDateTime& start )const;
106 90
107 /** 91 /**
108 * this is an overloaded member function 92 * Common and probably inefficent implementation
109 * @see effectiveNonRepeatingEvents( const QDate& from, const QDate& to ) 93 * for queryByExample, sorted
94 * and occurrences
110 */ 95 */
111 virtual OEffectiveEvent::ValueList effectiveNonRepeatingEvents( const QDateTime& start ); 96//@{
112 97 UIDArray queryByExample( const OPimEvent&, int settings, const QDateTime& d = QDateTime() )const;
98 UIDArray sorted( const UIDArray&, bool asc, int, int, const QArray<int>& )const;
99 OPimBackendOccurrence::List occurrences( const QDate&, const QDate& end )const;
100 OPimBackendOccurrence::List occurrences( const QDateTime& )const;
101//@}
102
103protected:
104 static OPimBackendOccurrence::List filterOccurrences(const OPimBackendOccurrence::List,
105 const QDateTime& time );
113private: 106private:
114 class Private; 107 class Private;
115 Private *d; 108 Private *d;
116 109
117}; 110};
118 111
119} 112}
120 113
121#endif 114#endif
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
index 105c106..41b714e 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
@@ -154,34 +154,32 @@ bool ODateBookAccessBackend_SQL::load()
154 if (!m_driver->open() ) 154 if (!m_driver->open() )
155 return false; 155 return false;
156 156
157 // Don't expect that the database exists. 157 // Don't expect that the database exists.
158 // It is save here to create the table, even if it 158 // It is save here to create the table, even if it
159 // do exist. ( Is that correct for all databases ?? ) 159 // do exist. ( Is that correct for all databases ?? )
160 QString qu = "create table datebook( uid INTEGER PRIMARY KEY "; 160 QString qu = "create table datebook( uid INTEGER PRIMARY KEY ";
161 161
162 QMap<int, QString>::Iterator it; 162 QMap<int, QString>::Iterator it;
163 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){ 163 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
164 qu += QString( ",%1 VARCHAR(10)" ).arg( it.data() ); 164 qu += QString( ",%1 VARCHAR(10)" ).arg( it.data() );
165 } 165 }
166 qu += " );"; 166 qu += " );";
167 167
168 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), priority INTEGER, value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );"; 168 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), priority INTEGER, value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
169 169
170 owarn << "command: " << qu << "" << oendl;
171
172 OSQLRawQuery raw( qu ); 170 OSQLRawQuery raw( qu );
173 OSQLResult res = m_driver->query( &raw ); 171 OSQLResult res = m_driver->query( &raw );
174 if ( res.state() != OSQLResult::Success ) 172 if ( res.state() != OSQLResult::Success )
175 return false; 173 return false;
176 174
177 update(); 175 update();
178 176
179 return true; 177 return true;
180} 178}
181 179
182void ODateBookAccessBackend_SQL::update() 180void ODateBookAccessBackend_SQL::update()
183{ 181{
184 182
185 QString qu = "select uid from datebook"; 183 QString qu = "select uid from datebook";
186 OSQLRawQuery raw( qu ); 184 OSQLRawQuery raw( qu );
187 OSQLResult res = m_driver->query( &raw ); 185 OSQLResult res = m_driver->query( &raw );
@@ -275,33 +273,32 @@ bool ODateBookAccessBackend_SQL::add( const OPimEvent& ev )
275 int id = 0; 273 int id = 0;
276 QMap<QString, QString> customMap = ev.toExtraMap(); 274 QMap<QString, QString> customMap = ev.toExtraMap();
277 for( QMap<QString, QString>::Iterator it = customMap.begin(); 275 for( QMap<QString, QString>::Iterator it = customMap.begin();
278 it != customMap.end(); ++it ){ 276 it != customMap.end(); ++it ){
279 qu += "insert into custom_data VALUES(" 277 qu += "insert into custom_data VALUES("
280 + QString::number( ev.uid() ) 278 + QString::number( ev.uid() )
281 + "," 279 + ","
282 + QString::number( id++ ) 280 + QString::number( id++ )
283 + ",'" 281 + ",'"
284 + it.key() //.latin1() 282 + it.key() //.latin1()
285 + "'," 283 + "',"
286 + "0" // Priority for future enhancements 284 + "0" // Priority for future enhancements
287 + ",'" 285 + ",'"
288 + it.data() //.latin1() 286 + it.data() //.latin1()
289 + "');"; 287 + "');";
290 } 288 }
291 owarn << "add " << qu << "" << oendl;
292 289
293 OSQLRawQuery raw( qu ); 290 OSQLRawQuery raw( qu );
294 OSQLResult res = m_driver->query( &raw ); 291 OSQLResult res = m_driver->query( &raw );
295 if ( res.state() != OSQLResult::Success ){ 292 if ( res.state() != OSQLResult::Success ){
296 return false; 293 return false;
297 } 294 }
298 295
299 // Update list of uid's 296 // Update list of uid's
300 update(); 297 update();
301 298
302 return true; 299 return true;
303} 300}
304 301
305// FIXME: Speed up update of uid's.. 302// FIXME: Speed up update of uid's..
306bool ODateBookAccessBackend_SQL::remove( int uid ) 303bool ODateBookAccessBackend_SQL::remove( int uid )
307{ 304{
@@ -315,76 +312,72 @@ bool ODateBookAccessBackend_SQL::remove( int uid )
315 if ( res.state() != OSQLResult::Success ){ 312 if ( res.state() != OSQLResult::Success ){
316 return false; 313 return false;
317 } 314 }
318 315
319 // Update list of uid's 316 // Update list of uid's
320 update(); 317 update();
321 318
322 return true; 319 return true;
323} 320}
324 321
325bool ODateBookAccessBackend_SQL::replace( const OPimEvent& ev ) 322bool ODateBookAccessBackend_SQL::replace( const OPimEvent& ev )
326{ 323{
327 remove( ev.uid() ); 324 remove( ev.uid() );
328 return add( ev ); 325 return add( ev );
329} 326}
330 327
331QArray<int> ODateBookAccessBackend_SQL::rawEvents()const
332{
333 return allRecords();
334}
335 328
336QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const 329QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const
337{ 330{
338 QString qu = "select uid from datebook where RType!=\"\" AND RType!=\"NoRepeat\""; 331 QString qu = "select uid from datebook where RType!=\"\" AND RType!=\"NoRepeat\"";
339 OSQLRawQuery raw( qu ); 332 OSQLRawQuery raw( qu );
340 OSQLResult res = m_driver->query( &raw ); 333 OSQLResult res = m_driver->query( &raw );
341 if ( res.state() != OSQLResult::Success ){ 334 if ( res.state() != OSQLResult::Success ){
342 QArray<int> nix; 335 QArray<int> nix;
343 return nix; 336 return nix;
344 } 337 }
345 338
346 return extractUids( res ); 339 return extractUids( res );
347} 340}
348 341
349QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const 342QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const
350{ 343{
351 QString qu = "select uid from datebook where RType=\"\" or RType=\"NoRepeat\""; 344 QString qu = "select uid from datebook where RType=\"\" or RType=\"NoRepeat\"";
352 OSQLRawQuery raw( qu ); 345 OSQLRawQuery raw( qu );
353 OSQLResult res = m_driver->query( &raw ); 346 OSQLResult res = m_driver->query( &raw );
354 if ( res.state() != OSQLResult::Success ){ 347 if ( res.state() != OSQLResult::Success ){
355 QArray<int> nix; 348 QArray<int> nix;
356 return nix; 349 return nix;
357 } 350 }
358 351
359 return extractUids( res ); 352 return extractUids( res );
360} 353}
361 354
362OPimEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats() 355OPimEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats()const
363{ 356{
364 QArray<int> nonRepUids = nonRepeats(); 357 QArray<int> nonRepUids = nonRepeats();
365 OPimEvent::ValueList list; 358 OPimEvent::ValueList list;
366 359
367 for (uint i = 0; i < nonRepUids.count(); ++i ){ 360 for (uint i = 0; i < nonRepUids.count(); ++i ){
368 list.append( find( nonRepUids[i] ) ); 361 list.append( find( nonRepUids[i] ) );
369 } 362 }
370 363
371 return list; 364 return list;
372 365
373} 366}
374OPimEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats() 367OPimEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats()const
375{ 368{
376 QArray<int> rawRepUids = rawRepeats(); 369 QArray<int> rawRepUids = rawRepeats();
377 OPimEvent::ValueList list; 370 OPimEvent::ValueList list;
378 371
379 for (uint i = 0; i < rawRepUids.count(); ++i ){ 372 for (uint i = 0; i < rawRepUids.count(); ++i ){
380 list.append( find( rawRepUids[i] ) ); 373 list.append( find( rawRepUids[i] ) );
381 } 374 }
382 375
383 return list; 376 return list;
384} 377}
385 378
386 379
387QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const 380QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
388{ 381{
389 382
390 QString qu = "SELECT uid FROM datebook WHERE ("; 383 QString qu = "SELECT uid FROM datebook WHERE (";
@@ -397,63 +390,59 @@ QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
397 390
398 odebug << "query: " << qu << "" << oendl; 391 odebug << "query: " << qu << "" << oendl;
399 392
400 OSQLRawQuery raw( qu ); 393 OSQLRawQuery raw( qu );
401 OSQLResult res = m_driver->query( &raw ); 394 OSQLResult res = m_driver->query( &raw );
402 395
403 return extractUids( res ); 396 return extractUids( res );
404 397
405 398
406 399
407} 400}
408 401
409/* ===== Private Functions ========================================== */ 402/* ===== Private Functions ========================================== */
410 403
411QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const 404QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
412{ 405{
413 owarn << "extractUids" << oendl;
414 QTime t; 406 QTime t;
415 t.start(); 407 t.start();
416 OSQLResultItem::ValueList list = res.results(); 408 OSQLResultItem::ValueList list = res.results();
417 OSQLResultItem::ValueList::Iterator it; 409 OSQLResultItem::ValueList::Iterator it;
418 QArray<int> ints(list.count() ); 410 QArray<int> ints(list.count() );
419 owarn << " count = " << list.count() << "" << oendl;
420 411
421 int i = 0; 412 int i = 0;
422 for (it = list.begin(); it != list.end(); ++it ) { 413 for (it = list.begin(); it != list.end(); ++it ) {
423 ints[i] = (*it).data("uid").toInt(); 414 ints[i] = (*it).data("uid").toInt();
424 i++; 415 i++;
425 } 416 }
426 owarn << "extractUids ready: count2 = " << i << " needs " << t.elapsed() << " ms" << oendl;
427 417
428 return ints; 418 return ints;
429 419
430} 420}
431 421
432QMap<QString, QString> ODateBookAccessBackend_SQL::requestCustom( int uid ) const 422QMap<QString, QString> ODateBookAccessBackend_SQL::requestCustom( int uid ) const
433{ 423{
434 QTime t; 424 QTime t;
435 t.start(); 425 t.start();
436 426
437 QMap<QString, QString> customMap; 427 QMap<QString, QString> customMap;
438 428
439 FindCustomQuery query( uid ); 429 FindCustomQuery query( uid );
440 OSQLResult res_custom = m_driver->query( &query ); 430 OSQLResult res_custom = m_driver->query( &query );
441 431
442 if ( res_custom.state() == OSQLResult::Failure ) { 432 if ( res_custom.state() == OSQLResult::Failure ) {
443 owarn << "OSQLResult::Failure in find query !!" << oendl;
444 QMap<QString, QString> empty; 433 QMap<QString, QString> empty;
445 return empty; 434 return empty;
446 } 435 }
447 436
448 OSQLResultItem::ValueList list = res_custom.results(); 437 OSQLResultItem::ValueList list = res_custom.results();
449 OSQLResultItem::ValueList::Iterator it = list.begin(); 438 OSQLResultItem::ValueList::Iterator it = list.begin();
450 for ( ; it != list.end(); ++it ) { 439 for ( ; it != list.end(); ++it ) {
451 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) ); 440 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
452 } 441 }
453 442
454 odebug << "RequestCustom needed: " << t.elapsed() << " ms" << oendl; 443 odebug << "RequestCustom needed: " << t.elapsed() << " ms" << oendl;
455 return customMap; 444 return customMap;
456} 445}
457 446
458 447
459} 448}
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_sql.h b/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
index b624159..a649d25 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
@@ -53,38 +53,37 @@ public:
53 const QString& fileName = QString::null); 53 const QString& fileName = QString::null);
54 ~ODateBookAccessBackend_SQL(); 54 ~ODateBookAccessBackend_SQL();
55 55
56 bool load(); 56 bool load();
57 bool reload(); 57 bool reload();
58 bool save(); 58 bool save();
59 59
60 QArray<int> allRecords()const; 60 QArray<int> allRecords()const;
61 QArray<int> matchRegexp(const QRegExp &r) const; 61 QArray<int> matchRegexp(const QRegExp &r) const;
62 QArray<int> queryByExample( const OPimEvent&, int, const QDateTime& d = QDateTime() ); 62 QArray<int> queryByExample( const OPimEvent&, int, const QDateTime& d = QDateTime() );
63 OPimEvent find( int uid )const; 63 OPimEvent find( int uid )const;
64 void clear(); 64 void clear();
65 bool add( const OPimEvent& ev ); 65 bool add( const OPimEvent& ev );
66 bool remove( int uid ); 66 bool remove( int uid );
67 bool replace( const OPimEvent& ev ); 67 bool replace( const OPimEvent& ev );
68 68
69 QArray<UID> rawEvents()const;
70 QArray<UID> rawRepeats()const; 69 QArray<UID> rawRepeats()const;
71 QArray<UID> nonRepeats()const; 70 QArray<UID> nonRepeats()const;
72 71
73 OPimEvent::ValueList directNonRepeats(); 72 OPimEvent::ValueList directNonRepeats()const;
74 OPimEvent::ValueList directRawRepeats(); 73 OPimEvent::ValueList directRawRepeats()const;
75 74
76private: 75private:
77 bool loadFile(); 76 bool loadFile();
78 QString m_fileName; 77 QString m_fileName;
79 QArray<int> m_uids; 78 QArray<int> m_uids;
80 79
81 QMap<int, QString> m_fieldMap; 80 QMap<int, QString> m_fieldMap;
82 QMap<QString, int> m_reverseFieldMap; 81 QMap<QString, int> m_reverseFieldMap;
83 82
84 Opie::DB::OSQLDriver* m_driver; 83 Opie::DB::OSQLDriver* m_driver;
85 84
86 class Private; 85 class Private;
87 Private *d; 86 Private *d;
88 87
89 void initFields(); 88 void initFields();
90 void update(); 89 void update();
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index 0f99d50..55e47e2 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -109,33 +109,32 @@ namespace {
109 FRPosition, 109 FRPosition,
110 FRFreq, 110 FRFreq,
111 FRHasEndDate, 111 FRHasEndDate,
112 FREndDate, 112 FREndDate,
113 FRStart, 113 FRStart,
114 FREnd, 114 FREnd,
115 FNote, 115 FNote,
116 FCreated, // Should't this be called FRCreated ? 116 FCreated, // Should't this be called FRCreated ?
117 FTimeZone, 117 FTimeZone,
118 FRecParent, 118 FRecParent,
119 FRecChildren, 119 FRecChildren,
120 FExceptions 120 FExceptions
121 }; 121 };
122 122
123 // FIXME: Use OPimEvent::toMap() here !! (eilers) 123 // FIXME: Use OPimEvent::toMap() here !! (eilers)
124 static void save( const OPimEvent& ev, QString& buf ) { 124 static void save( const OPimEvent& ev, QString& buf ) {
125 owarn << "Saving " << ev.uid() << " " << ev.description() << "" << oendl;
126 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\""; 125 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
127 if (!ev.location().isEmpty() ) 126 if (!ev.location().isEmpty() )
128 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\""; 127 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
129 128
130 if (!ev.categories().isEmpty() ) 129 if (!ev.categories().isEmpty() )
131 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\""; 130 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
132 131
133 buf += " uid=\"" + QString::number( ev.uid() ) + "\""; 132 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
134 133
135 if (ev.isAllDay() ) 134 if (ev.isAllDay() )
136 buf += " type=\"AllDay\""; // is that all ?? (eilers) 135 buf += " type=\"AllDay\""; // is that all ?? (eilers)
137 136
138 if (ev.hasNotifiers() ) { 137 if (ev.hasNotifiers() ) {
139 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first 138 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
140 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60; 139 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
141 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\""; 140 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
@@ -313,68 +312,66 @@ bool ODateBookAccessBackend_XML::add( const OPimEvent& ev ) {
313 else 312 else
314 m_raw.insert( ev.uid(), ev ); 313 m_raw.insert( ev.uid(), ev );
315 314
316 return true; 315 return true;
317} 316}
318bool ODateBookAccessBackend_XML::remove( int uid ) { 317bool ODateBookAccessBackend_XML::remove( int uid ) {
319 m_changed = true; 318 m_changed = true;
320 m_raw.remove( uid ); 319 m_raw.remove( uid );
321 m_rep.remove( uid ); 320 m_rep.remove( uid );
322 321
323 return true; 322 return true;
324} 323}
325bool ODateBookAccessBackend_XML::replace( const OPimEvent& ev ) { 324bool ODateBookAccessBackend_XML::replace( const OPimEvent& ev ) {
326 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers) 325 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
327 return add( ev ); 326 return add( ev );
328} 327}
329QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 328
330 return allRecords();
331}
332QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 329QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
333 QArray<int> ints( m_rep.count() ); 330 QArray<int> ints( m_rep.count() );
334 uint i = 0; 331 uint i = 0;
335 QMap<int, OPimEvent>::ConstIterator it; 332 QMap<int, OPimEvent>::ConstIterator it;
336 333
337 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 334 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
338 ints[i] = it.key(); 335 ints[i] = it.key();
339 i++; 336 i++;
340 } 337 }
341 338
342 return ints; 339 return ints;
343} 340}
344QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 341QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
345 QArray<int> ints( m_raw.count() ); 342 QArray<int> ints( m_raw.count() );
346 uint i = 0; 343 uint i = 0;
347 QMap<int, OPimEvent>::ConstIterator it; 344 QMap<int, OPimEvent>::ConstIterator it;
348 345
349 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 346 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
350 ints[i] = it.key(); 347 ints[i] = it.key();
351 i++; 348 i++;
352 } 349 }
353 350
354 return ints; 351 return ints;
355} 352}
356OPimEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { 353OPimEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats()const {
357 OPimEvent::ValueList list; 354 OPimEvent::ValueList list;
358 QMap<int, OPimEvent>::ConstIterator it; 355 QMap<int, OPimEvent>::ConstIterator it;
359 for (it = m_raw.begin(); it != m_raw.end(); ++it ) 356 for (it = m_raw.begin(); it != m_raw.end(); ++it )
360 list.append( it.data() ); 357 list.append( it.data() );
361 358
362 return list; 359 return list;
363} 360}
364OPimEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { 361OPimEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats()const {
365 OPimEvent::ValueList list; 362 OPimEvent::ValueList list;
366 QMap<int, OPimEvent>::ConstIterator it; 363 QMap<int, OPimEvent>::ConstIterator it;
367 for (it = m_rep.begin(); it != m_rep.end(); ++it ) 364 for (it = m_rep.begin(); it != m_rep.end(); ++it )
368 list.append( it.data() ); 365 list.append( it.data() );
369 366
370 return list; 367 return list;
371} 368}
372 369
373// FIXME: Use OPimEvent::fromMap() (eilers) 370// FIXME: Use OPimEvent::fromMap() (eilers)
374bool ODateBookAccessBackend_XML::loadFile() { 371bool ODateBookAccessBackend_XML::loadFile() {
375 m_changed = false; 372 m_changed = false;
376 373
377 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); 374 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
378 if ( fd < 0 ) return false; 375 if ( fd < 0 ) return false;
379 376
380 struct stat attribute; 377 struct stat attribute;
@@ -526,44 +523,42 @@ void ODateBookAccessBackend_XML::finalizeRecord( OPimEvent& ev ) {
526 } 523 }
527 if ( rec && rec->doesRecur() ) { 524 if ( rec && rec->doesRecur() ) {
528 OPimTimeZone utc = OPimTimeZone::utc(); 525 OPimTimeZone utc = OPimTimeZone::utc();
529 OPimRecurrence recu( *rec ); // call copy c'tor; 526 OPimRecurrence recu( *rec ); // call copy c'tor;
530 recu.setEndDate ( utc.toDateTime( rp_end ).date() ); 527 recu.setEndDate ( utc.toDateTime( rp_end ).date() );
531 recu.setCreatedDateTime( utc.toDateTime( created ) ); 528 recu.setCreatedDateTime( utc.toDateTime( created ) );
532 recu.setStart( ev.startDateTime().date() ); 529 recu.setStart( ev.startDateTime().date() );
533 ev.setRecurrence( recu ); 530 ev.setRecurrence( recu );
534 } 531 }
535 532
536 if (alarmTime != -1 ) { 533 if (alarmTime != -1 ) {
537 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); 534 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
538 OPimAlarm al( snd , dt ); 535 OPimAlarm al( snd , dt );
539 ev.notifiers().add( al ); 536 ev.notifiers().add( al );
540 } 537 }
541 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { 538 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
542 owarn << "already contains assign uid" << oendl;
543 ev.setUid( 1 ); 539 ev.setUid( 1 );
544 } 540 }
545 541
546 if ( ev.hasRecurrence() ) 542 if ( ev.hasRecurrence() )
547 m_rep.insert( ev.uid(), ev ); 543 m_rep.insert( ev.uid(), ev );
548 else 544 else
549 m_raw.insert( ev.uid(), ev ); 545 m_raw.insert( ev.uid(), ev );
550 546
551} 547}
552void ODateBookAccessBackend_XML::setField( OPimEvent& e, int id, const QString& value) { 548void ODateBookAccessBackend_XML::setField( OPimEvent& e, int id, const QString& value) {
553// owarn << " setting " << value << "" << oendl;
554 switch( id ) { 549 switch( id ) {
555 case FDescription: 550 case FDescription:
556 e.setDescription( value ); 551 e.setDescription( value );
557 break; 552 break;
558 case FLocation: 553 case FLocation:
559 e.setLocation( value ); 554 e.setLocation( value );
560 break; 555 break;
561 case FCategories: 556 case FCategories:
562 e.setCategories( e.idsFromString( value ) ); 557 e.setCategories( e.idsFromString( value ) );
563 break; 558 break;
564 case FUid: 559 case FUid:
565 e.setUid( value.toInt() ); 560 e.setUid( value.toInt() );
566 break; 561 break;
567 case FType: 562 case FType:
568 if ( value == "AllDay" ) { 563 if ( value == "AllDay" ) {
569 e.setAllDay( true ); 564 e.setAllDay( true );
@@ -621,33 +616,32 @@ void ODateBookAccessBackend_XML::setField( OPimEvent& e, int id, const QString&
621 created = value.toInt(); 616 created = value.toInt();
622 break; 617 break;
623 case FRecParent: 618 case FRecParent:
624 e.setParent( value.toInt() ); 619 e.setParent( value.toInt() );
625 break; 620 break;
626 case FRecChildren:{ 621 case FRecChildren:{
627 QStringList list = QStringList::split(' ', value ); 622 QStringList list = QStringList::split(' ', value );
628 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 623 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
629 e.addChild( (*it).toInt() ); 624 e.addChild( (*it).toInt() );
630 } 625 }
631 } 626 }
632 break; 627 break;
633 case FExceptions:{ 628 case FExceptions:{
634 QStringList list = QStringList::split(' ', value ); 629 QStringList list = QStringList::split(' ', value );
635 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 630 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
636 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() ); 631 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
637 owarn << "adding exception " << date.toString() << "" << oendl;
638 recur()->exceptions().append( date ); 632 recur()->exceptions().append( date );
639 } 633 }
640 } 634 }
641 break; 635 break;
642 case FTimeZone: 636 case FTimeZone:
643 m_noTimeZone = false; 637 m_noTimeZone = false;
644 if ( value != "None" ) 638 if ( value != "None" )
645 e.setTimeZone( value ); 639 e.setTimeZone( value );
646 break; 640 break;
647 default: 641 default:
648 break; 642 break;
649 } 643 }
650} 644}
651QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const 645QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
652{ 646{
653 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() ); 647 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
index af5b114..cb19f76 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.h
@@ -50,34 +50,34 @@ public:
50 bool reload(); 50 bool reload();
51 bool save(); 51 bool save();
52 52
53 QArray<int> allRecords()const; 53 QArray<int> allRecords()const;
54 QArray<int> matchRegexp(const QRegExp &r) const; 54 QArray<int> matchRegexp(const QRegExp &r) const;
55 QArray<int> queryByExample( const OPimEvent&, int, const QDateTime& d = QDateTime() ); 55 QArray<int> queryByExample( const OPimEvent&, int, const QDateTime& d = QDateTime() );
56 OPimEvent find( int uid )const; 56 OPimEvent find( int uid )const;
57 void clear(); 57 void clear();
58 bool add( const OPimEvent& ev ); 58 bool add( const OPimEvent& ev );
59 bool remove( int uid ); 59 bool remove( int uid );
60 bool replace( const OPimEvent& ev ); 60 bool replace( const OPimEvent& ev );
61 61
62 QArray<UID> rawEvents()const; 62 QArray<UID> rawEvents()const;
63 QArray<UID> rawRepeats()const; 63 QArray<UID> rawRepeats()const;
64 QArray<UID> nonRepeats()const; 64 QArray<UID> nonRepeats()const;
65 65
66 OPimEvent::ValueList directNonRepeats(); 66 OPimEvent::ValueList directNonRepeats()const;
67 OPimEvent::ValueList directRawRepeats(); 67 OPimEvent::ValueList directRawRepeats()const;
68 68
69private: 69private:
70 bool m_changed :1 ; 70 bool m_changed :1 ;
71 bool m_noTimeZone : 1; 71 bool m_noTimeZone : 1;
72 72
73 bool loadFile(); 73 bool loadFile();
74 inline void finalizeRecord( OPimEvent& ev ); 74 inline void finalizeRecord( OPimEvent& ev );
75 inline void setField( OPimEvent&, int field, const QString& val ); 75 inline void setField( OPimEvent&, int field, const QString& val );
76 QString m_name; 76 QString m_name;
77 QMap<int, OPimEvent> m_raw; 77 QMap<int, OPimEvent> m_raw;
78 QMap<int, OPimEvent> m_rep; 78 QMap<int, OPimEvent> m_rep;
79 79
80 struct Data; 80 struct Data;
81 Data* data; 81 Data* data;
82 class Private; 82 class Private;
83 Private *d; 83 Private *d;
diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h
index 26af762..0d112c9 100644
--- a/libopie2/opiepim/backend/opimaccessbackend.h
+++ b/libopie2/opiepim/backend/opimaccessbackend.h
@@ -21,176 +21,403 @@
21 : = ...= . :.=- 21 : = ...= . :.=-
22 -. .:....=;==+<; You should have received a copy of the GNU 22 -. .:....=;==+<; You should have received a copy of the GNU
23 -_. . . )=. = Library General Public License along with 23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB. 24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation, 25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330, 26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. 27 Boston, MA 02111-1307, USA.
28*/ 28*/
29#ifndef OPIE_PIM_ACCESS_BACKEND 29#ifndef OPIE_PIM_ACCESS_BACKEND
30#define OPIE_PIM_ACCESS_BACKEND 30#define OPIE_PIM_ACCESS_BACKEND
31 31
32#include <qarray.h> 32#include <qarray.h>
33#include <qdatetime.h> 33#include <qdatetime.h>
34 34
35#include <opie2/opimtemplatebase.h> 35#include <opie2/opimtemplatebase.h>
36#include <opie2/opimrecord.h> 36#include <opie2/opimrecord.h>
37 37#include <opie2/opimbackendoccurrence.h>
38 38
39namespace Opie { 39namespace Opie {
40class OPimAccessBackendPrivate; 40class OPimAccessBackendPrivate;
41
41/** 42/**
42 * OPimAccessBackend is the base class 43 * OPimAccessBackend is the Backend Interface to be used
43 * for all private backends 44 * by OTemplateBase based Frontends.
44 * it operates on OPimRecord as the base class 45 * For efficency reasons and to support delayed loading
45 * and it's responsible for fast manipulating 46 * most of the Frontend functions can be implemented
46 * the resource the implementation takes care 47 * by this backend.
47 * of 48 * This allows to utilise the best method on each backend.
49 * For example we can use SQL queries instead of self made
50 * query which is first more efficent and also uses less memory.
48 */ 51 */
49template <class T = OPimRecord> 52template <class T = OPimRecord>
50class OPimAccessBackend { 53class OPimAccessBackend {
51public: 54public:
52 typedef OTemplateBase<T> Frontend; 55 typedef OTemplateBase<T> Frontend;
53 56
54 /** The access hint from the frontend */ 57 //@{
55 OPimAccessBackend(int access = 0); 58 OPimAccessBackend(int access = 0);
56 virtual ~OPimAccessBackend(); 59 virtual ~OPimAccessBackend();
60 //@}
57 61
58 /** 62 //@{
59 * load the resource
60 */
61 virtual bool load() = 0; 63 virtual bool load() = 0;
62
63 /**
64 * reload the resource
65 */
66 virtual bool reload() = 0; 64 virtual bool reload() = 0;
67
68 /**
69 * save the resource and
70 * all it's changes
71 */
72 virtual bool save() = 0; 65 virtual bool save() = 0;
66 virtual void clear() = 0;
67 //@}
73 68
74 /**
75 * return an array of
76 * all available uids
77 */
78 virtual QArray<int> allRecords()const = 0;
79 69
80 /** 70 //@{
81 * return a List of records 71 virtual UIDArray allRecords()const = 0;
82 * that match the regex 72 virtual UIDArray matchRegexp(const QRegExp &r) const;
83 */ 73 virtual UIDArray queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() )const = 0;
84 virtual QArray<int> matchRegexp(const QRegExp &r) const = 0; 74 virtual UIDArray queryByExample( const OPimRecord* rec, int, const QDateTime& d = QDateTime() )const;
75 virtual UIDArray sorted( const UIDArray&, bool asc, int sortOrder, int sortFilter, const QArray<int>& cats )const;
76 virtual UIDArray sorted( bool asc, int sortOrder, int sortFilter, const QArray<int>& cats )const;
77 virtual OPimBackendOccurrence::List occurrences( const QDate& start, const QDate& end)const;
78 virtual OPimBackendOccurrence::List occurrences( const QDateTime& dt )const;
79 //@}
85 80
86 /**
87 * queryByExample for T with the given Settings
88 *
89 */
90 virtual QArray<int> queryByExample( const T& t, int settings, const QDateTime& d = QDateTime() ) = 0;
91 81
92 /** 82 //@{
93 * find the OPimRecord with uid @param uid 83 virtual T find(UID uid )const = 0;
94 * returns T and T.isEmpty() if nothing was found 84 virtual T find(UID uid, const QArray<UID>& items,
95 */ 85 uint current, typename Frontend::CacheDirection )const ;
96 virtual T find( int uid )const = 0; 86 //@}
97 87
98 virtual T find( int uid, const QArray<int>& items,
99 uint current, typename Frontend::CacheDirection ) const;
100 /**
101 * clear the back end
102 */
103 virtual void clear() = 0;
104 88
105 /** 89 //@{
106 * add T
107 */
108 virtual bool add( const T& t ) = 0; 90 virtual bool add( const T& t ) = 0;
91 virtual bool remove( UID uid ) = 0;
92 virtual bool replace( const T& t ) = 0;
93 //@}
109 94
110 /**
111 * remove
112 */
113 virtual bool remove( int uid ) = 0;
114 95
115 /**
116 * replace a record with T.uid()
117 */
118 virtual bool replace( const T& t ) = 0;
119 96
120 /*
121 * setTheFrontEnd!!!
122 */
123 void setFrontend( Frontend* front ); 97 void setFrontend( Frontend* front );
124 98
125 /** 99 /**
126 * set the read ahead count 100 * set the read ahead count
127 */ 101 */
128 void setReadAhead( uint count ); 102 void setReadAhead( uint count );
129protected: 103protected:
104 //@{
130 int access()const; 105 int access()const;
131
132 void cache( const T& t )const; 106 void cache( const T& t )const;
133
134 /**
135 * use a prime number here!
136 */
137 void setSaneCacheSize( int ); 107 void setSaneCacheSize( int );
138
139 uint readAhead()const; 108 uint readAhead()const;
109 //@}
140 110
141private: 111private:
142 OPimAccessBackendPrivate *d; 112 OPimAccessBackendPrivate *d;
143 Frontend* m_front; 113 Frontend* m_front;
144 uint m_read; 114 uint m_read;
145 int m_acc; 115 int m_acc;
146 116
147}; 117};
148 118
149template <class T> 119template <class T>
150OPimAccessBackend<T>::OPimAccessBackend(int acc) 120OPimAccessBackend<T>::OPimAccessBackend(int acc)
151 : m_acc( acc ) 121 : m_acc( acc )
152{ 122{
153 m_front = 0l; 123 m_front = 0l;
154} 124}
155template <class T> 125template <class T>
156OPimAccessBackend<T>::~OPimAccessBackend() { 126OPimAccessBackend<T>::~OPimAccessBackend() {
157 127
158} 128}
129
130/*
131 * Slow but default matchRegexp Implementation
132 * Create a Big Enough QArray and then iterate
133 * over all Records and matchRegexp them.
134 * At the end we will resize the array to the actual
135 * number of items
136 */
137template <class T>
138UIDArray OPimAccessBackend<T>::matchRegexp( const QRegExp& reg )const {
139 UIDArray all_rec = allRecords();
140 UIDArray result( all_rec.count() );
141 uint used_records = 0, all_rec_count = all_rec.count();
142
143 for ( uint i = 0; i < all_rec_count; ++i )
144 if (find( all_rec[i], all_rec, i, Frontend::Forward ).match( reg ) )
145 result[used_records++] = all_rec[i];
146
147 /* shrink to fit */
148 result.resize( used_records );
149 return result;
150}
151
152template <class T>
153UIDArray OPimAccessBackend<T>::queryByExample( const OPimRecord* rec, int settings,
154 const QDateTime& datetime )const {
155 T* tmp_rec = T::safeCast( rec );
156 UIDArray ar;
157 if ( tmp_rec )
158 ar = queryByExample( *tmp_rec, settings, datetime );
159
160 return ar;
161}
162
163template <class T>
164UIDArray OPimAccessBackend<T>::sorted( const UIDArray& ids, bool,
165 int, int, const QArray<int>& ) const {
166 return ids;
167}
168
169template <class T>
170UIDArray OPimAccessBackend<T>::sorted( bool asc, int order, int filter,
171 const QArray<int>& cats )const {
172 return sorted( allRecords(), asc, order, filter, cats );
173}
174
175template<class T>
176OPimBackendOccurrence::List OPimAccessBackend<T>::occurrences( const QDate&,
177 const QDate& )const {
178 return OPimBackendOccurrence::List();
179}
180
181template<class T>
182OPimBackendOccurrence::List OPimAccessBackend<T>::occurrences( const QDateTime& dt )const {
183 QDate date = dt.date();
184 return occurrences( date, date );
185}
186
159template <class T> 187template <class T>
160void OPimAccessBackend<T>::setFrontend( Frontend* fr ) { 188void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
161 m_front = fr; 189 m_front = fr;
162} 190}
163template <class T> 191template <class T>
164void OPimAccessBackend<T>::cache( const T& t )const { 192void OPimAccessBackend<T>::cache( const T& t )const {
165 if ( m_front ) 193 if ( m_front )
166 m_front->cache( t ); 194 m_front->cache( t );
167} 195}
168 196
169
170template <class T> 197template <class T>
171void OPimAccessBackend<T>::setSaneCacheSize( int size) { 198void OPimAccessBackend<T>::setSaneCacheSize( int size) {
172 if ( m_front ) 199 if ( m_front )
173 m_front->setSaneCacheSize( size ); 200 m_front->setSaneCacheSize( size );
174} 201}
175template <class T> 202template <class T>
176T OPimAccessBackend<T>::find( int uid, const QArray<int>&, 203T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
177 uint, typename Frontend::CacheDirection ) const{ 204 uint, typename Frontend::CacheDirection ) const{
178 qDebug( "*** Lookahead feature not supported. Fallback to default find!!" ); 205 qDebug( "*** Lookahead feature not supported. Fallback to default find!!" );
179 return find( uid ); 206 return find( uid );
180} 207}
181template <class T> 208template <class T>
182void OPimAccessBackend<T>::setReadAhead( uint count ) { 209void OPimAccessBackend<T>::setReadAhead( uint count ) {
183 m_read = count; 210 m_read = count;
184} 211}
185template <class T> 212template <class T>
186uint OPimAccessBackend<T>::readAhead()const { 213uint OPimAccessBackend<T>::readAhead()const {
187 return m_read; 214 return m_read;
188} 215}
189template <class T> 216template <class T>
190int OPimAccessBackend<T>::access()const { 217int OPimAccessBackend<T>::access()const {
191 return m_acc; 218 return m_acc;
192} 219}
193 220
194} 221}
195 222
223/**
224 * \fn template <class T> OPimAccessBackend<T>::OPimAccessBackend(int hint )
225 * @param hint The access hint from the frontend
226 */
227
228/**
229 * \fn template <class T> bool OPimAccessBackend<T>::load()
230 * Opens the DataBase and does necessary
231 * initialisation of internal structures.
232 *
233 * @return true If the DataBase could be opened and
234 * Information was successfully loaded
235 */
236
237/**
238 * \fn template <class T> bool OPimAccessBackend<T>::reload()
239 * Reinitialise the DataBase and merges the external changes
240 * with your local changes.
241 *
242 * @return True if the DataBase was reloaded.
243 *
244 */
245
246/**
247 * \fn template <class T> bool OPimAccessBackend<T>::save()
248 *
249 * Save the changes to storage. In case of memory or
250 * disk shortage, return false.
251 *
252 *
253 * @return True if the DataBase could be saved to storage.
254 */
255
256/**
257 * \fn template <class T> bool OPimAccessBackend<T>::clear()
258 * Until a \sa save() changes shouldn't be comitted
259 *
260 *
261 * @return True if the DataBase could be cleared
262 * @todo Introduce a 'Commit'
263 */
264
265/**
266 * \fn template <class T> QArray<UID> OPimAccessBackend<T>::allRecords()const
267 * Return an array of all available uids in the loaded
268 * DataBase.
269 * @see load
270 */
271
272/**
273 * \fn template <class T> QArray<UID> OPimAccessBackend<T>::matchRegexp(const QRegExp& r)const
274 * Return a List of records that match the regex \par r.
275 *
276 * @param r The QRegExp to match.
277 */
278
279/**
280 * \fn template <class T> QArray<UID> OPimAccessBackend<T>::queryByExample(const T& t, int settings, const QDateTime& d = QDateTime() )
281 *
282 * Implement QueryByExample. An Example record is filled and with the
283 * settings and QDateTime it is determined how the query should be executed.
284 * Return a list of UIDs that match the Example
285 *
286 * @param t The Example record
287 * @param settings Gives
288 *
289 */
290
291/**
292 * \fn template<class T> QArray<UID> OPimAccessBackend<T>::sorted(const QArray<UID>& ids, bool asc, int sortOrder, int sortFilter, int cat)
293 * \brief Sort the List of records according to the preference
294 *
295 * Implement sorting in your backend. The default implementation is
296 * to return the list as it was passed.
297 * The default Backend Implementation should do unaccelerated filtering
298 *
299 *
300 * @param ids The Records to sort
301 * @param asc Sort ascending or descending
302 * @param sortOrder
303 * @param sortFilter Sort filter
304 * @param cat The Category to include
305 */
306
307/**
308 * \fn template <class T> T OPimAccessBackend<T>::find(UID uid)const
309 * \brief Find the Record with the UID
310 *
311 * Find the UID in the database and return the record.
312 * @param uid The uid to be searched for
313 * @return The record or an empty record (T.isEmpty())
314 *
315 */
316
317/**
318 * \fn template <class T> T OPimAccessBackend<T>::find( UID uid, const QArray<UID>& items, uint current, typename Frontend::CacheDirection d)const
319 * \brief find a Record and do a read ahead or read behind
320 *
321 * @param uid The UID to search for
322 * @param items The list of items from where your search
323 * @param current The index of \param uid
324 * @param d The direction to search for
325 *
326 * @see find
327 */
328
329
330/**
331 * \fn template<class T> bool OPimAccessBackend<T>::add(const T& t)
332 *
333 * \brief Add the record to the internal database
334 *
335 * If an record with the same t.uid() is already present internally
336 * the behaviour is undefined but the state of the database
337 * needs to be stable.
338 * For modifying a record use \sa replace.
339 *
340 *
341 * @return true if the record could be added or false if not
342 * @todo Eilers your opinion on readd/replace
343 */
344
345/**
346 * \fn template<class T> bool OPimAccessBackend<T>::remove(UID uid)
347 * \brief Remove a record by its UID
348 *
349 * Remove the records with UID from the internal Database.
350 *
351 * @return True if the record could be removed.
352 *
353 */
354
355/**
356 * \fn template<class T> bool OPimAccessBackend<T>::replace(const T& t)
357 * \brief Take this Record and replace the old version.
358 *
359 * Take \param t as the new record for t.uid(). It is not described
360 * what happens if the record is not present in the database.
361 * Normally the record is determined by the UID.
362 *
363 * @param t The record to use internally.
364 */
365
366/**
367 * \fn template<class T> void OPimAccessBackend<T>::setFrontend( Frontend* fron)
368 * \@aram fron The Frontend that uses this backend
369 *
370 * This function is called by the frontend and is used
371 */
372
373/**
374 * \fn template<class T> void OPimAccessBackend<T>::setReadAhead(uint count)
375 * \brief Set the number of items to Read-Ahead/Read-Behind
376 *
377 * @param count The number of records to read ahead
378 */
379
380/**
381 * \fn template<class T> void OPimAccessBackend<T>::cache( const T& t)const
382 * \brief Add the Record to the PIM Cache
383 *
384 * This will add the Record to the PIM cache, which is owned
385 * by the FrontEnd. If no FrontEnd is available the item will
386 * not be cached.
387 *
388 *
389 * @param t The Item to be added to the Cache
390 */
391
392/**
393 * \fn template<class T> void OPimAccessBackend<T>::setSaneCacheSize(int items)
394 * \brief Give a hint on the number of too cached items
395 *
396 * Give the Frontend a hint on the number of items to be cached. Use
397 * a prime number for best performance.
398 *
399 * @param items The number of items to be cached
400 */
401
402/**
403 * \fn template<class T> uint OPimAccessBackend<T>::readAhead()const
404 * \brief Return the number of Items to be ReadAhead
405 *
406 * @return The number of Items to read ahead/read behind
407 */
408
409/**
410 * \fn template<class T> QArray<OPimBackendOccurence> OPimAccessBackend<T>::occurrences(const QDateTime& start,const QDateTime& end)
411 * \brief Get a List of Occurrences for a period of time
412 *
413 * Return an Array of OPimBackendOccurence for a period of time. If start == end date
414 * return only occurrences for the start date. If end is smaller the start date
415 * the result is not defined. You could switch dates or return an empty list.
416 *
417 * @return Return an array of OPimBackendOccurence for the period specified by the parameters
418 * @param start The start of the period.
419 * @param end The end of the period.
420 *
421 */
422
196#endif 423#endif
diff --git a/libopie2/opiepim/backend/opimbackendoccurrence.cpp b/libopie2/opiepim/backend/opimbackendoccurrence.cpp
new file mode 100644
index 0000000..8af930d
--- a/dev/null
+++ b/libopie2/opiepim/backend/opimbackendoccurrence.cpp
@@ -0,0 +1,241 @@
1/*
2 This file is part of the Opie Project
3 Copyright (C) 2004 Holger Hans Peter Freyther <zecke@handhelds.org>
4 =. Copyright (C) The Opie Team <opie-devel@handhelds.org>
5 .=l.
6 .>+-=
7 _;:, .> :=|. This program is free software; you can
8.> <`_, > . <= redistribute it and/or modify it under
9:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
10.="- .-=="i, .._ License as published by the Free Software
11 - . .-<_> .<> Foundation; either version 2 of the License,
12 ._= =} : or (at your option) any later version.
13 .%`+i> _;_.
14 .i_,=:_. -<s. This program is distributed in the hope that
15 + . -:. = it will be useful, but WITHOUT ANY WARRANTY;
16 : .. .:, . . . without even the implied warranty of
17 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A
18 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.= = ; Library General Public License for more
20++= -. .` .: details.
21 : = ...= . :.=-
22 -. .:....=;==+<; You should have received a copy of the GNU
23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28*/
29
30#include "opimbackendoccurrence.h"
31
32namespace Opie {
33
34OPimBackendOccurrence::OPimBackendOccurrence() {}
35/**
36 * \brief The occurence is only on the specefic Day
37 *
38 * If an occurrence is only a day without any time associated
39 * use this Constructor.
40 * \sa timeAssociated() will return false.
41 *
42 * @param date The Date this Occurence takes place
43 * @param uid The \sa UID of the associated OPimRecord
44 * @param sum The optional summary
45 *
46 */
47OPimBackendOccurrence::OPimBackendOccurrence( const QDate& date,
48 const UID& uid,
49 const QString& sum )
50 : m_start( date ), m_end( date ), m_uid( uid ),
51 m_haveTime(false ), m_summary( sum )
52{}
53
54/**
55 * \brief An Occurrence with a start day and end day without time
56 *
57 * Overloaded Constructor. Use this if you've a start date and
58 * end date but no time. If you need to overwrite the summary
59 * use setSummary.
60 * \sa timeAssociated() will return false.
61 *
62 * @param date The Start Date
63 * @param end Tne End Date
64 * @param uid The UID of the associated record
65 *
66 * @see setSummary
67 */
68OPimBackendOccurrence::OPimBackendOccurrence( const QDate& date,
69 const QDate& end,
70 const UID& uid)
71 : m_start( date ), m_end( end ), m_uid( uid ), m_haveTime( false )
72{}
73
74
75/**
76 * \brief Use Start and End Date with Time
77 *
78 * Overloaded Constructor to use Dates with Time time associated
79 * to it. \sa timeAssociated() will return true.
80 *
81 * @param date The Start Date and Time of the occurrence
82 * @param end The End Date and Time of the occurrence
83 * @param uid The UID of the \sa OPimRecord.
84 */
85OPimBackendOccurrence::OPimBackendOccurrence( const QDateTime& date,
86 const QDateTime& end,
87 const UID& uid )
88 : m_start( date ), m_end( end ), m_uid( uid ), m_haveTime( true )
89{}
90
91/**
92 * \brief Return the Start Date and Time
93 *
94 * @return This method will return the start
95 * Date and Time. Time is only valid if
96 * \sa timeAssociated() is true.
97 *
98 */
99QDateTime OPimBackendOccurrence::startDateTime()const {
100 return m_start;
101}
102
103/**
104 * \brief Return the Start Date and Time
105 *
106 * @return This will return the end Date and Time. The
107 * limitation for Time is the same as in startDateTime
108 *
109 * @see startDateTime()
110 */
111QDateTime OPimBackendOccurrence::endDateTime()const {
112 return m_end;
113}
114
115/**
116 * \brief Return the UID of the Associated OPimRecord
117 *
118 * @return the associated OPimRecord
119 */
120UID OPimBackendOccurrence::uid()const {
121 return m_uid;
122}
123
124/**
125 * \brief Return if there is a time associated or not
126 *
127 * If a time is present with start and end date this method
128 * will return true. There is no direct way to manipulate
129 * that attribute. But \sa setStartDate and \sa setStartDateTime
130 * will change it.
131 *
132 * @return Return true if a time is available with the date
133 *
134 */
135bool OPimBackendOccurrence::isAllDay()const {
136 return m_haveTime;
137}
138
139/**
140 * @return The special summary that will overwrite OPimRecord::summary
141 */
142QString OPimBackendOccurrence::summary()const {
143 return m_summary;
144}
145
146QString OPimBackendOccurrence::location()const {
147 return m_location;
148}
149
150QString OPimBackendOccurrence::note()const {
151 return m_note;
152}
153
154/**
155 * \brief Set the Start Date
156 *
157 * This method will set the start date and internally will mark
158 * this occurrence to have no time associated to both start
159 * and end date.
160 * A call to timeAssociated will return false after using this
161 * method.
162 *
163 * @param start The Start Date
164 *
165 */
166void OPimBackendOccurrence::setStartDate( const QDate& start) {
167 m_start = start;
168 m_haveTime = false;
169}
170
171/**
172 * \brief Set the Start Date and Time
173 *
174 * Set the Start Date and Time. After this call
175 * \sa timeAssociated will return true.
176 *
177 * @param dt The Start Date and Time to be set
178 */
179void OPimBackendOccurrence::setStartDateTime( const QDateTime& dt ) {
180 m_start = dt;
181 m_haveTime = true;
182}
183
184/**
185 * \brief This will set the End Date.
186 *
187 * This method will set the End Date. The timeAssociated attribute
188 * will not be changed.
189 *
190 * @param end The End Date to be set
191 */
192void OPimBackendOccurrence::setEndDate( const QDate& end ) {
193 m_end = end;
194}
195
196/**
197 * \brief Set the End Date and Time of the occurrence
198 *
199 * This will set the End Date and Time but will not change
200 * the timeAssociated attribute.
201 *
202 * @param dt The End Date and Time to be set.
203 */
204void OPimBackendOccurrence::setEndDateTime( const QDateTime& dt ) {
205 m_end = dt;
206}
207
208/**
209 * \brief This method will set the UID of the Record
210 *
211 * Set the UID of the OPimRecord to be associated with
212 * this OPimRecurrence.
213 *
214 * @param uid The UID of the associated OPimRecord to be set
215 */
216void OPimBackendOccurrence::setUid( const UID& uid ) {
217 m_uid = uid;
218}
219
220
221/**
222 * \brief Set a special summary instead of \sa OPimRecord::summary()
223 *
224 * If \sa OPimRecord::summary() doesn't describe the occurrence
225 * reason you can set a custom summary for the Occurrence.
226 *
227 * @param str The to be set Summary
228 */
229void OPimBackendOccurrence::setSummary( const QString& str ) {
230 m_summary = str;
231}
232
233void OPimBackendOccurrence::setLocation( const QString& str ) {
234 m_location = str;
235}
236
237void OPimBackendOccurrence::setNote( const QString& str ) {
238 m_note = str;
239}
240
241}
diff --git a/libopie2/opiepim/backend/opimbackendoccurrence.h b/libopie2/opiepim/backend/opimbackendoccurrence.h
new file mode 100644
index 0000000..08c3cdf
--- a/dev/null
+++ b/libopie2/opiepim/backend/opimbackendoccurrence.h
@@ -0,0 +1,108 @@
1/*
2 This file is part of the Opie Project
3 Copyright (C) 2004 Holger Hans Peter Freyther <zecke@handhelds.org>
4 =. Copyright (C) The Opie Team <opie-devel@handhelds.org>
5 .=l.
6 .>+-=
7 _;:, .> :=|. This program is free software; you can
8.> <`_, > . <= redistribute it and/or modify it under
9:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
10.="- .-=="i, .._ License as published by the Free Software
11 - . .-<_> .<> Foundation; either version 2 of the License,
12 ._= =} : or (at your option) any later version.
13 .%`+i> _;_.
14 .i_,=:_. -<s. This program is distributed in the hope that
15 + . -:. = it will be useful, but WITHOUT ANY WARRANTY;
16 : .. .:, . . . without even the implied warranty of
17 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A
18 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.= = ; Library General Public License for more
20++= -. .` .: details.
21 : = ...= . :.=-
22 -. .:....=;==+<; You should have received a copy of the GNU
23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA.
28*/
29
30#ifndef OPIE_PIM_BACKEND_OCCURRENCE_H
31#define OPIE_PIM_BACKEND_OCCURRENCE_H
32
33#include <opie2/opimglobal.h>
34
35#include <qarray.h>
36#include <qdatetime.h>
37#include <qvaluelist.h>
38
39namespace Opie {
40
41/**
42 * \brief Internal representation of an Occurence
43 *
44 * This class is used by the Backends to express
45 * Occurences for the Period Based Query to
46 * the by the Backend represanted Database.
47 * In the Frontend this single representation is splitted
48 * into per day \sa OPimOccurrence 's.
49 * OPimBackendOccurrence can be understand as a hint to
50 * the Frontend and must contain the \sa UID, the Start Date
51 * and End Date of the Occurence. If you have no time associated
52 * to the datetime use the QDate constructors.
53 * If OPimRecord::summary() does not describe the Occurrence
54 * right you can call setSummary() and then the supplied
55 * summary will be used.
56 * All Dates and Times are in the local time.
57 *
58 * @version 1.0
59 * @author Holger Hans Peter Freyther zecke@handhelds.org
60 */
61class OPimBackendOccurrence {
62public:
63 typedef QValueList<OPimBackendOccurrence> List;
64
65 //@{
66 OPimBackendOccurrence();
67 OPimBackendOccurrence( const QDate& date,
68 const UID& , const QString& = QString::null );
69 OPimBackendOccurrence( const QDate& date, const QDate& end,
70 const UID& );
71 OPimBackendOccurrence( const QDateTime& start,
72 const QDateTime& end,
73 const UID& uid );
74 //@}
75
76 //@{
77 QDateTime startDateTime()const;
78 QDateTime endDateTime()const;
79 UID uid()const;
80 bool isAllDay()const;
81 QString summary()const;
82 QString location()const;
83 QString note()const;
84 //@}
85
86 //@{
87 void setStartDate( const QDate& );
88 void setStartDateTime( const QDateTime& dt );
89 void setEndDate( const QDate& );
90 void setEndDateTime( const QDateTime& dt );
91 void setUid( const UID& );
92 void setSummary( const QString& );
93 void setLocation( const QString& );
94 void setNote( const QString& );
95 //@}
96
97private:
98 QDateTime m_start, m_end;
99 UID m_uid;
100 bool m_haveTime : 1;
101 QString m_summary, m_note, m_location;
102
103 struct Private;
104 Private *d;
105};
106}
107
108#endif
diff --git a/libopie2/opiepim/backend/otodoaccessbackend.cpp b/libopie2/opiepim/backend/otodoaccessbackend.cpp
index 790a764..5f86be9 100644
--- a/libopie2/opiepim/backend/otodoaccessbackend.cpp
+++ b/libopie2/opiepim/backend/otodoaccessbackend.cpp
@@ -15,27 +15,141 @@
15 + . -:. = it will be useful, but WITHOUT ANY WARRANTY; 15 + . -:. = it will be useful, but WITHOUT ANY WARRANTY;
16 : .. .:, . . . without even the implied warranty of 16 : .. .:, . . . without even the implied warranty of
17 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A 17 =_ + =;=|` MERCHANTABILITY or FITNESS FOR A
18 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU 18 _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU
19..}^=.= = ; Library General Public License for more 19..}^=.= = ; Library General Public License for more
20++= -. .` .: details. 20++= -. .` .: details.
21 : = ...= . :.=- 21 : = ...= . :.=-
22 -. .:....=;==+<; You should have received a copy of the GNU 22 -. .:....=;==+<; You should have received a copy of the GNU
23 -_. . . )=. = Library General Public License along with 23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB. 24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation, 25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330, 26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. 27 Boston, MA 02111-1307, USA.
28*/ 28*/
29 29
30#include <opie2/otodoaccessbackend.h> 30#include <opie2/otodoaccessbackend.h>
31#include <opie2/private/opimtodosortvector.h>
32#include <opie2/otodoaccess.h>
33
34#include <qintdict.h>
31 35
32namespace Opie { 36namespace Opie {
33OPimTodoAccessBackend::OPimTodoAccessBackend() 37OPimTodoAccessBackend::OPimTodoAccessBackend()
34 : OPimAccessBackend<OPimTodo>() 38 : OPimAccessBackend<OPimTodo>()
35{ 39{
36} 40}
37OPimTodoAccessBackend::~OPimTodoAccessBackend() { 41OPimTodoAccessBackend::~OPimTodoAccessBackend() {
38 42
39} 43}
40 44
45UIDArray OPimTodoAccessBackend::queryByExample( const OPimTodo&, int settings,
46 const QDateTime& d)const {
47 return UIDArray();
48}
49
50UIDArray OPimTodoAccessBackend::sorted( const UIDArray& events, bool asc,
51 int sortOrder, int sortFilter,
52 const QArray<int>& categories )const {
53 odebug << "Using Unaccelerated TodoList sorted Implementation" << oendl;
54 Internal::OPimTodoSortVector vector(events.count(), asc,sortOrder );
55 int item = 0;
56
57 bool bCat = sortFilter & OPimTodoAccess::FilterCategory ? true : false;
58 bool bOnly = sortFilter & OPimTodoAccess::OnlyOverDue ? true : false;
59 bool comp = sortFilter & OPimTodoAccess::DoNotShowCompleted ? true : false;
60 bool catPassed = false;
61 int cat;
62
63 for ( uint i = 0; i < events.count(); ++i ) {
64 OPimTodo todo = find( events[i], events, i, Frontend::Forward );
65 if ( todo.isEmpty() )
66 continue;
67
68 /* show category */
69 /* -1 == unfiled */
70 catPassed = false;
71 for ( uint cat_nu = 0; cat_nu < categories.count(); ++cat_nu ) {
72 cat = categories[cat_nu];
73 if ( bCat && cat == -1 ) {
74 if(!todo.categories().isEmpty() )
75 continue;
76 } else if ( bCat && cat != 0)
77 if (!todo.categories().contains( cat ) )
78 continue;
79 catPassed = true;
80 break;
81 }
82
83 /*
84 * If none of the Categories matched
85 * continue
86 */
87 if ( !catPassed )
88 continue;
89 if ( !todo.isOverdue() && bOnly )
90 continue;
91 if (todo.isCompleted() && comp )
92 continue;
93
94 vector.insert(item++, todo );
95 }
96
97 vector.resize( item );
98 /* sort it now */
99 vector.sort();
100 /* now get the uids */
101 UIDArray array( vector.count() );
102 for (uint i= 0; i < vector.count(); i++ )
103 array[i] = vector.uidAt( i );
104
105 return array;
106}
107
108OPimBackendOccurrence::List OPimTodoAccessBackend::occurrences( const QDate& start,
109 const QDate& end )const {
110 OPimBackendOccurrence::List lst;
111 UIDArray effective = effectiveToDos( start, end, false );
112 UIDArray overdue = overDue();
113 uint count = effective.count();
114 int uid;
115 QIntDict<int> hash;
116 hash.setAutoDelete( true );
117 OPimTodo todo;
118
119 for ( uint i = 0; i < count; ++i ) {
120 uid = effective[i];
121 todo = find( uid, effective, i, Frontend::Forward );
122 /*
123 * If isOverdue but in the 'normal' range we will fill
124 * the hash so we won't have duplicates in OPimBackendOccurrence
125 */
126 if ( todo.isOverdue() )
127 hash.insert( uid, new int(6) );
128 OPimBackendOccurrence oc = todo.hasStartDate() ?
129 OPimBackendOccurrence( todo.startDate(),
130 todo.dueDate(), uid ) :
131 OPimBackendOccurrence( todo.dueDate(), uid, QString::null );
132 oc.setSummary( todo.summary() );
133 lst.append( oc );
134 }
135
136 /*
137 * Create the OverDue items but skip
138 * the already handled Records
139 */
140 if ( !overdue.isEmpty() ) {
141 QDate today = QDate::currentDate();
142 QDate dueDate = (start >= today && today <= end ) ? today : start;
143 count = overdue.count();
144 for ( uint i = 0; i < count; ++i ) {
145 uid = overdue[i];
146 if (!hash.find( uid ) )
147 continue;
148 todo = find( uid, overdue, i, Frontend::Forward );
149 lst.append( OPimBackendOccurrence(dueDate, uid, todo.summary() ) );
150 }
151 }
152
153 return lst;
154}
41} 155}
diff --git a/libopie2/opiepim/backend/otodoaccessbackend.h b/libopie2/opiepim/backend/otodoaccessbackend.h
index 9dfda45..66297bb 100644
--- a/libopie2/opiepim/backend/otodoaccessbackend.h
+++ b/libopie2/opiepim/backend/otodoaccessbackend.h
@@ -26,34 +26,54 @@
26 Inc., 59 Temple Place - Suite 330, 26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. 27 Boston, MA 02111-1307, USA.
28*/ 28*/
29#ifndef OPIE_TODO_ACCESS_BACKEND_H 29#ifndef OPIE_TODO_ACCESS_BACKEND_H
30#define OPIE_TODO_ACCESS_BACKEND_H 30#define OPIE_TODO_ACCESS_BACKEND_H
31 31
32#include <qbitarray.h> 32#include <qbitarray.h>
33 33
34#include <opie2/opimtodo.h> 34#include <opie2/opimtodo.h>
35#include <opie2/opimaccessbackend.h> 35#include <opie2/opimaccessbackend.h>
36 36
37namespace Opie { 37namespace Opie {
38class OPimTodoAccessBackend : public OPimAccessBackend<OPimTodo> { 38class OPimTodoAccessBackend : public OPimAccessBackend<OPimTodo> {
39public: 39public:
40 OPimTodoAccessBackend(); 40 OPimTodoAccessBackend();
41 ~OPimTodoAccessBackend(); 41 ~OPimTodoAccessBackend();
42 virtual QArray<int> effectiveToDos( const QDate& start, 42 virtual UIDArray effectiveToDos( const QDate& start,
43 const QDate& end, 43 const QDate& end,
44 bool includeNoDates ) = 0; 44 bool includeNoDates )const = 0;
45 virtual QArray<int> overDue() = 0; 45 virtual UIDArray overDue()const = 0;
46 virtual QArray<int> sorted( bool asc, int sortOrder, int sortFilter, 46 virtual void removeAllCompleted() = 0;
47 int cat ) = 0; 47
48 virtual void removeAllCompleted() = 0; 48 /**
49 virtual QBitArray supports()const = 0; 49 * Common and probably inefficent implementation
50 50 * for queryByExample, matchRegexp, sorted
51 * and occurrences
52 */
53 //@{
54 UIDArray queryByExample( const OPimTodo&, int settings, const QDateTime& d = QDateTime() )const;
55 UIDArray sorted( const UIDArray&, bool asc, int, int, const QArray<int>& )const;
56 OPimBackendOccurrence::List occurrences( const QDate&, const QDate& )const;
57 //@}
58
51private: 59private:
52 class Private; 60 class Private;
53 Private *d; 61 Private *d;
54 62
55}; 63};
56
57} 64}
58 65
66
67/**
68 * \fn Opie::OPimBackendOccurrence::List Opie::OPimTodoAccessBackend::occurrences(const QDate& start,const QDate& end)const
69 * \brief Return occurrences for a period of time
70 *
71 * This method will return the 'effective' Todos and also
72 * 'Overdue' Todos. Overdues will be shown on the 'current'
73 * day if it is in the range or on \par start. If the overdue
74 * is inside the 'Effective Todos' we will skip the
75 * special overdue handling.
76 *
77 *
78 */
59#endif 79#endif
diff --git a/libopie2/opiepim/backend/otodoaccesssql.cpp b/libopie2/opiepim/backend/otodoaccesssql.cpp
index 4e3e47b..2bcab29 100644
--- a/libopie2/opiepim/backend/otodoaccesssql.cpp
+++ b/libopie2/opiepim/backend/otodoaccesssql.cpp
@@ -442,241 +442,238 @@ bool OPimTodoAccessBackendSQL::reload(){
442bool OPimTodoAccessBackendSQL::save(){ 442bool OPimTodoAccessBackendSQL::save(){
443 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers) 443 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
444} 444}
445QArray<int> OPimTodoAccessBackendSQL::allRecords()const { 445QArray<int> OPimTodoAccessBackendSQL::allRecords()const {
446 if (m_dirty ) 446 if (m_dirty )
447 update(); 447 update();
448 448
449 return m_uids; 449 return m_uids;
450} 450}
451QArray<int> OPimTodoAccessBackendSQL::queryByExample( const OPimTodo& , int, const QDateTime& ){ 451QArray<int> OPimTodoAccessBackendSQL::queryByExample( const OPimTodo& , int, const QDateTime& ){
452 QArray<int> ints(0); 452 QArray<int> ints(0);
453 return ints; 453 return ints;
454} 454}
455OPimTodo OPimTodoAccessBackendSQL::find(int uid ) const{ 455OPimTodo OPimTodoAccessBackendSQL::find(int uid ) const{
456 FindQuery query( uid ); 456 FindQuery query( uid );
457 return parseResultAndCache( uid, m_driver->query(&query) ); 457 return parseResultAndCache( uid, m_driver->query(&query) );
458
459} 458}
460 459
461// Remember: uid is already in the list of uids, called ints ! 460// Remember: uid is already in the list of uids, called ints !
462OPimTodo OPimTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, 461OPimTodo OPimTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
463 uint cur, Frontend::CacheDirection dir ) const{ 462 uint cur, Frontend::CacheDirection dir ) const{
464 uint CACHE = readAhead(); 463 uint CACHE = readAhead();
465 odebug << "searching for " << uid << "" << oendl; 464 odebug << "searching for " << uid << "" << oendl;
466 QArray<int> search( CACHE ); 465 QArray<int> search( CACHE );
467 uint size =0; 466 uint size =0;
468 OPimTodo to;
469 467
470 // we try to cache CACHE items 468 // we try to cache CACHE items
471 switch( dir ) { 469 switch( dir ) {
472 /* forward */ 470 /* forward */
473 case Frontend::Forward: 471 case Frontend::Forward:
474 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { 472 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
475 odebug << "size " << size << " " << ints[i] << "" << oendl;
476 search[size] = ints[i]; 473 search[size] = ints[i];
477 size++; 474 size++;
478 } 475 }
479 break; 476 break;
480 /* reverse */ 477 /* reverse */
481 case Frontend::Reverse: 478 case Frontend::Reverse:
482 for (uint i = cur; i != 0 && size < CACHE; i-- ) { 479 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
483 search[size] = ints[i]; 480 search[size] = ints[i];
484 size++; 481 size++;
485 } 482 }
486 break; 483 break;
487 } 484 }
488 485
489 search.resize( size ); 486 search.resize( size );
490 FindQuery query( search ); 487 FindQuery query( search );
491 OSQLResult res = m_driver->query( &query ); 488 OSQLResult res = m_driver->query( &query );
492 if ( res.state() != OSQLResult::Success ) 489 if ( res.state() != OSQLResult::Success )
493 return to; 490 return OPimTodo();
494 491
495 return parseResultAndCache( uid, res ); 492 return parseResultAndCache( uid, res );
496} 493}
497 494
498void OPimTodoAccessBackendSQL::clear() { 495void OPimTodoAccessBackendSQL::clear() {
499 ClearQuery cle; 496 ClearQuery cle;
500 OSQLResult res = m_driver->query( &cle ); 497 OSQLResult res = m_driver->query( &cle );
501 CreateQuery qu; 498 CreateQuery qu;
502 res = m_driver->query(&qu); 499 res = m_driver->query(&qu);
503} 500}
504bool OPimTodoAccessBackendSQL::add( const OPimTodo& t) { 501bool OPimTodoAccessBackendSQL::add( const OPimTodo& t) {
505 InsertQuery ins( t ); 502 InsertQuery ins( t );
506 OSQLResult res = m_driver->query( &ins ); 503 OSQLResult res = m_driver->query( &ins );
507 504
508 if ( res.state() == OSQLResult::Failure ) 505 if ( res.state() == OSQLResult::Failure )
509 return false; 506 return false;
507
510 int c = m_uids.count(); 508 int c = m_uids.count();
511 m_uids.resize( c+1 ); 509 m_uids.resize( c+1 );
512 m_uids[c] = t.uid(); 510 m_uids[c] = t.uid();
513 511
514 return true; 512 return true;
515} 513}
516bool OPimTodoAccessBackendSQL::remove( int uid ) { 514bool OPimTodoAccessBackendSQL::remove( int uid ) {
517 RemoveQuery rem( uid ); 515 RemoveQuery rem( uid );
518 OSQLResult res = m_driver->query(&rem ); 516 OSQLResult res = m_driver->query(&rem );
519 517
520 if ( res.state() == OSQLResult::Failure ) 518 if ( res.state() == OSQLResult::Failure )
521 return false; 519 return false;
522 520
523 m_dirty = true; 521 m_dirty = true;
524 return true; 522 return true;
525} 523}
526/* 524/*
527 * FIXME better set query 525 * FIXME better set query
528 * but we need the cache for that 526 * but we need the cache for that
529 * now we remove 527 * now we remove
530 */ 528 */
531bool OPimTodoAccessBackendSQL::replace( const OPimTodo& t) { 529bool OPimTodoAccessBackendSQL::replace( const OPimTodo& t) {
532 remove( t.uid() ); 530 remove( t.uid() );
533 bool b= add(t); 531 bool b= add(t);
534 m_dirty = false; // we changed some stuff but the UID stayed the same 532 m_dirty = false; // we changed some stuff but the UID stayed the same
535 return b; 533 return b;
536} 534}
537QArray<int> OPimTodoAccessBackendSQL::overDue() { 535QArray<int> OPimTodoAccessBackendSQL::overDue()const {
538 OverDueQuery qu; 536 OverDueQuery qu;
539 return uids( m_driver->query(&qu ) ); 537 return uids( m_driver->query(&qu ) );
540} 538}
541QArray<int> OPimTodoAccessBackendSQL::effectiveToDos( const QDate& s, 539QArray<int> OPimTodoAccessBackendSQL::effectiveToDos( const QDate& s,
542 const QDate& t, 540 const QDate& t,
543 bool u) { 541 bool u)const {
544 EffQuery ef(s, t, u ); 542 EffQuery ef(s, t, u );
545 return uids (m_driver->query(&ef) ); 543 return uids (m_driver->query(&ef) );
546} 544}
545
546#if 0
547/* 547/*
548 * 548 *
549 */ 549 */
550QArray<int> OPimTodoAccessBackendSQL::sorted( bool asc, int sortOrder, 550QArray<int> OPimTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
551 int sortFilter, int cat ) { 551 int sortFilter, int cat ) {
552 odebug << "sorted " << asc << ", " << sortOrder << "" << oendl; 552 odebug << "sorted " << asc << ", " << sortOrder << "" << oendl;
553 QString query; 553 QString query;
554 query = "select uid from todolist WHERE "; 554 query = "select uid from todolist WHERE ";
555 555
556 /* 556 /*
557 * Sort Filter stuff 557 * Sort Filter stuff
558 * not that straight forward 558 * not that straight forward
559 * FIXME: Replace magic numbers 559 * FIXME: Replace magic numbers
560 * 560 *
561 */ 561 */
562 /* Category */ 562 /* Category */
563 if ( sortFilter & 1 ) { 563 if ( sortFilter & OPimTodoAccess::FilterCategory ) {
564 QString str; 564 QString str;
565 if (cat != 0 ) str = QString::number( cat ); 565 if (cat != 0 ) str = QString::number( cat );
566 query += " categories like '%" +str+"%' AND"; 566 query += " categories like '%" +str+"%' AND";
567 } 567 }
568 /* Show only overdue */ 568 /* Show only overdue */
569 if ( sortFilter & 2 ) { 569 if ( sortFilter & OPimTodoAccess::OnlyOverDue ) {
570 QDate date = QDate::currentDate(); 570 QDate date = QDate::currentDate();
571 QString due; 571 QString due;
572 QString base; 572 QString base;
573 base = QString("DueDate <= '%1-%2-%3' AND completed = 0") 573 base = QString("DueDate <= '%1-%2-%3' AND completed = 0")
574 .arg( QString::number( date.year() ).rightJustify( 4, '0' ) ) 574 .arg( QString::number( date.year() ).rightJustify( 4, '0' ) )
575 .arg( QString::number( date.month() ).rightJustify( 2, '0' ) ) 575 .arg( QString::number( date.month() ).rightJustify( 2, '0' ) )
576 .arg( QString::number( date.day() ).rightJustify( 2, '0' ) ); 576 .arg( QString::number( date.day() ).rightJustify( 2, '0' ) );
577 query += " " + base + " AND"; 577 query += " " + base + " AND";
578 } 578 }
579 /* not show completed */ 579 /* not show completed */
580 if ( sortFilter & 4 ) { 580 if ( sortFilter & OPimTodoAccess::DoNotShowCompleted ) {
581 query += " completed = 0 AND"; 581 query += " completed = 0 AND";
582 }else{ 582 }else{
583 query += " ( completed = 1 OR completed = 0) AND"; 583 query += " ( completed = 1 OR completed = 0) AND";
584 } 584 }
585 /* strip the end */ 585 /* strip the end */
586 query = query.remove( query.length()-3, 3 ); 586 query = query.remove( query.length()-3, 3 );
587 587
588 588
589 /* 589 /*
590 * sort order stuff 590 * sort order stuff
591 * quite straight forward 591 * quite straight forward
592 */ 592 */
593 query += "ORDER BY "; 593 query += "ORDER BY ";
594 switch( sortOrder ) { 594 switch( sortOrder ) {
595 /* completed */ 595 /* completed */
596 case 0: 596 case OPimTodoAccess::Completed:
597 query += "completed"; 597 query += "completed";
598 break; 598 break;
599 case 1: 599 case OPimTodoAccess::Priority:
600 query += "priority"; 600 query += "priority";
601 break; 601 break;
602 case 2: 602 case OPimTodoAccess::SortSummary:
603 query += "summary"; 603 query += "summary";
604 break; 604 break;
605 case 3: 605 case OPimTodoAccess::Deadline:
606 query += "DueDate"; 606 query += "DueDate";
607 break; 607 break;
608 } 608 }
609 609
610 if ( !asc ) { 610 if ( !asc )
611 odebug << "not ascending!" << oendl;
612 query += " DESC"; 611 query += " DESC";
613 } 612
614 613
615 odebug << query << oendl; 614 odebug << query << oendl;
616 OSQLRawQuery raw(query ); 615 OSQLRawQuery raw(query );
617 return uids( m_driver->query(&raw) ); 616 return uids( m_driver->query(&raw) );
618} 617}
618#endif
619
620
619bool OPimTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{ 621bool OPimTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
620 if ( str == "0-0-0" ) 622 if ( str == "0-0-0" )
621 return false; 623 return false;
622 else{ 624 else{
623 int day, year, month; 625 int day, year, month;
624 QStringList list = QStringList::split("-", str ); 626 QStringList list = QStringList::split("-", str );
625 year = list[0].toInt(); 627 year = list[0].toInt();
626 month = list[1].toInt(); 628 month = list[1].toInt();
627 day = list[2].toInt(); 629 day = list[2].toInt();
628 da.setYMD( year, month, day ); 630 da.setYMD( year, month, day );
629 return true; 631 return true;
630 } 632 }
631} 633}
634
635
632OPimTodo OPimTodoAccessBackendSQL::parseResultAndCache( int uid, const OSQLResult& res ) const{ 636OPimTodo OPimTodoAccessBackendSQL::parseResultAndCache( int uid, const OSQLResult& res ) const{
633 if ( res.state() == OSQLResult::Failure ) { 637 if ( res.state() == OSQLResult::Failure ) {
634 OPimTodo to; 638 OPimTodo to;
635 return to; 639 return to;
636 } 640 }
637 641
638 OPimTodo retTodo; 642 OPimTodo retTodo;
639 643
640 OSQLResultItem::ValueList list = res.results(); 644 OSQLResultItem::ValueList list = res.results();
641 OSQLResultItem::ValueList::Iterator it = list.begin(); 645 OSQLResultItem::ValueList::Iterator it = list.begin();
642 odebug << "todo1" << oendl; 646 OPimTodo to, tmp;
643 OPimTodo to = todo( (*it) );
644 cache( to );
645 ++it;
646 647
647 for ( ; it != list.end(); ++it ) { 648 for ( ; it != list.end(); ++it ) {
648 odebug << "caching" << oendl; 649 OPimTodo newTodo = parse( (*it) );
649 OPimTodo newTodo = todo( (*it) );
650 cache( newTodo ); 650 cache( newTodo );
651 if ( newTodo.uid() == uid ) 651 if ( newTodo.uid() == uid )
652 retTodo = newTodo; 652 retTodo = newTodo;
653 } 653 }
654 return retTodo; 654 return retTodo;
655} 655}
656OPimTodo OPimTodoAccessBackendSQL::todo( OSQLResultItem& item )const { 656OPimTodo OPimTodoAccessBackendSQL::parse( OSQLResultItem& item )const {
657 odebug << "todo(ResultItem)" << oendl;
658 657
659 // Request information from addressbook table and create the OPimTodo-object. 658 // Request information from addressbook table and create the OPimTodo-object.
660 659
661 bool hasDueDate = false; QDate dueDate = QDate::currentDate(); 660 bool hasDueDate = false; QDate dueDate = QDate::currentDate();
662 hasDueDate = date( dueDate, item.data("DueDate") ); 661 hasDueDate = date( dueDate, item.data("DueDate") );
663 QStringList cats = QStringList::split(";", item.data("categories") ); 662 QStringList cats = QStringList::split(";", item.data("categories") );
664 663
665 odebug << "Item is completed: " << item.data("completed").toInt() << "" << oendl;
666
667 OPimTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(), 664 OPimTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
668 cats, item.data("summary"), item.data("description"), 665 cats, item.data("summary"), item.data("description"),
669 item.data("progress").toUShort(), hasDueDate, dueDate, 666 item.data("progress").toUShort(), hasDueDate, dueDate,
670 item.data("uid").toInt() ); 667 item.data("uid").toInt() );
671 668
672 bool isOk; 669 bool isOk;
673 int prioInt = QString( item.data("priority") ).toInt( &isOk ); 670 int prioInt = QString( item.data("priority") ).toInt( &isOk );
674 if ( isOk ) 671 if ( isOk )
675 to.setPriority( prioInt ); 672 to.setPriority( prioInt );
676 673
677 bool hasStartDate = false; QDate startDate = QDate::currentDate(); 674 bool hasStartDate = false; QDate startDate = QDate::currentDate();
678 hasStartDate = date( startDate, item.data("startdate") ); 675 hasStartDate = date( startDate, item.data("startdate") );
679 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate(); 676 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
680 hasCompletedDate = date( completedDate, item.data("completeddate") ); 677 hasCompletedDate = date( completedDate, item.data("completeddate") );
681 678
682 if ( hasStartDate ) 679 if ( hasStartDate )
@@ -704,192 +701,130 @@ OPimTodo OPimTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
704 701
705 OPimRecurrence recur; 702 OPimRecurrence recur;
706 recur.fromMap( recMap ); 703 recur.fromMap( recMap );
707 to.setRecurrence( recur ); 704 to.setRecurrence( recur );
708 705
709 // Finally load the custom-entries for this UID and put it into the created object 706 // Finally load the custom-entries for this UID and put it into the created object
710 to.setExtraMap( requestCustom( to.uid() ) ); 707 to.setExtraMap( requestCustom( to.uid() ) );
711 708
712 return to; 709 return to;
713} 710}
714 711
715// FIXME: Where is the difference to "find" ? (eilers) 712// FIXME: Where is the difference to "find" ? (eilers)
716OPimTodo OPimTodoAccessBackendSQL::todo( int uid )const { 713OPimTodo OPimTodoAccessBackendSQL::todo( int uid )const {
717 FindQuery find( uid ); 714 FindQuery find( uid );
718 return parseResultAndCache( uid, m_driver->query(&find) ); 715 return parseResultAndCache( uid, m_driver->query(&find) );
719} 716}
720/*
721 * update the dict
722 */
723void OPimTodoAccessBackendSQL::fillDict() {
724 717
725#if 0
726 /* initialize dict */
727 /*
728 * UPDATE dict if you change anything!!!
729 * FIXME: Isn't this dict obsolete ? (eilers)
730 */
731 m_dict.setAutoDelete( TRUE );
732 m_dict.insert("Categories" , new int(OPimTodo::Category) );
733 m_dict.insert("Uid" , new int(OPimTodo::Uid) );
734 m_dict.insert("HasDate" , new int(OPimTodo::HasDate) );
735 m_dict.insert("Completed" , new int(OPimTodo::Completed) );
736 m_dict.insert("Description" , new int(OPimTodo::Description) );
737 m_dict.insert("Summary" , new int(OPimTodo::Summary) );
738 m_dict.insert("Priority" , new int(OPimTodo::Priority) );
739 m_dict.insert("DateDay" , new int(OPimTodo::DateDay) );
740 m_dict.insert("DateMonth" , new int(OPimTodo::DateMonth) );
741 m_dict.insert("DateYear" , new int(OPimTodo::DateYear) );
742 m_dict.insert("Progress" , new int(OPimTodo::Progress) );
743 m_dict.insert("Completed", new int(OPimTodo::Completed) ); // Why twice ? (eilers)
744 m_dict.insert("CrossReference", new int(OPimTodo::CrossReference) );
745// m_dict.insert("HasAlarmDateTime",new int(OPimTodo::HasAlarmDateTime) ); // old stuff (eilers)
746// m_dict.insert("AlarmDateTime", new int(OPimTodo::AlarmDateTime) ); // old stuff (eilers)
747 718
748#endif
749}
750/* 719/*
751 * need to be const so let's fool the 720 * need to be const so let's fool the
752 * compiler :( 721 * compiler :(
753 */ 722 */
754void OPimTodoAccessBackendSQL::update()const { 723void OPimTodoAccessBackendSQL::update()const {
755 ((OPimTodoAccessBackendSQL*)this)->m_dirty = false; 724 ((OPimTodoAccessBackendSQL*)this)->m_dirty = false;
756 LoadQuery lo; 725 LoadQuery lo;
757 OSQLResult res = m_driver->query(&lo); 726 OSQLResult res = m_driver->query(&lo);
758 if ( res.state() != OSQLResult::Success ) 727 if ( res.state() != OSQLResult::Success )
759 return; 728 return;
760 729
761 ((OPimTodoAccessBackendSQL*)this)->m_uids = uids( res ); 730 ((OPimTodoAccessBackendSQL*)this)->m_uids = uids( res );
762} 731}
763QArray<int> OPimTodoAccessBackendSQL::uids( const OSQLResult& res) const{ 732QArray<int> OPimTodoAccessBackendSQL::uids( const OSQLResult& res) const{
764 733
765 OSQLResultItem::ValueList list = res.results(); 734 OSQLResultItem::ValueList list = res.results();
766 OSQLResultItem::ValueList::Iterator it; 735 OSQLResultItem::ValueList::Iterator it;
767 QArray<int> ints(list.count() ); 736 QArray<int> ints(list.count() );
768 odebug << " count = " << list.count() << "" << oendl;
769 737
770 int i = 0; 738 int i = 0;
771 for (it = list.begin(); it != list.end(); ++it ) { 739 for (it = list.begin(); it != list.end(); ++it ) {
772 ints[i] = (*it).data("uid").toInt(); 740 ints[i] = (*it).data("uid").toInt();
773 i++; 741 i++;
774 } 742 }
775 return ints; 743 return ints;
776} 744}
777 745
778QArray<int> OPimTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const 746QArray<int> OPimTodoAccessBackendSQL::matchRegexp( const QRegExp &r ) const
779{ 747{
780
781#if 0
782 QArray<int> empty;
783 return empty;
784
785#else
786 QString qu = "SELECT uid FROM todolist WHERE ("; 748 QString qu = "SELECT uid FROM todolist WHERE (";
787 749
788 // Do it make sense to search other fields, too ? 750 // Does it make sense to search other fields, too ?
789 qu += " rlike(\""+ r.pattern() + "\",\"description\") OR"; 751 qu += " rlike(\""+ r.pattern() + "\",\"description\") OR";
790 qu += " rlike(\""+ r.pattern() + "\",\"summary\")"; 752 qu += " rlike(\""+ r.pattern() + "\",\"summary\")";
791 753
792 qu += ")"; 754 qu += ")";
793 755
794 odebug << "query: " << qu << "" << oendl;
795
796 OSQLRawQuery raw( qu ); 756 OSQLRawQuery raw( qu );
797 OSQLResult res = m_driver->query( &raw ); 757 OSQLResult res = m_driver->query( &raw );
798 758
799 return uids( res ); 759 return uids( res );
800
801
802#endif
803
804}
805QBitArray OPimTodoAccessBackendSQL::supports()const {
806
807 return sup();
808}
809
810QBitArray OPimTodoAccessBackendSQL::sup() const{
811
812 QBitArray ar( OPimTodo::CompletedDate + 1 );
813 ar.fill( true );
814 ar[OPimTodo::CrossReference] = false;
815 ar[OPimTodo::State ] = false;
816 ar[OPimTodo::Reminders] = false;
817 ar[OPimTodo::Notifiers] = false;
818 ar[OPimTodo::Maintainer] = false;
819
820 return ar;
821} 760}
822 761
823void OPimTodoAccessBackendSQL::removeAllCompleted(){ 762void OPimTodoAccessBackendSQL::removeAllCompleted(){
824 // First we need the uids from all entries which are 763 // First we need the uids from all entries which are
825 // completed. Then, we just have to remove them... 764 // completed. Then, we just have to remove them...
826 765
827 QString qu = "SELECT uid FROM todolist WHERE completed = 1"; 766 QString qu = "SELECT uid FROM todolist WHERE completed = 1";
828 767
829 OSQLRawQuery raw( qu ); 768 OSQLRawQuery raw( qu );
830 OSQLResult res = m_driver->query( &raw ); 769 OSQLResult res = m_driver->query( &raw );
831 770
832 QArray<int> completed_uids = uids( res ); 771 QArray<int> completed_uids = uids( res );
833 772
834 odebug << "Number of completed: " << completed_uids.size() << "" << oendl;
835
836 if ( completed_uids.size() == 0 ) 773 if ( completed_uids.size() == 0 )
837 return; 774 return;
838 775
839 qu = "DELETE FROM todolist WHERE ("; 776 qu = "DELETE FROM todolist WHERE (";
840 QString query; 777 QString query;
841 778
842 for ( int i = 0; i < completed_uids.size(); i++ ){ 779 for ( uint i = 0; i < completed_uids.size(); i++ ){
843 if ( !query.isEmpty() ) 780 if ( !query.isEmpty() )
844 query += " OR "; 781 query += " OR ";
845 query += QString( "uid = %1" ).arg( completed_uids[i] ); 782 query += QString( "uid = %1" ).arg( completed_uids[i] );
846 } 783 }
847 qu += query + " );"; 784 qu += query + " );";
848 785
849 // Put remove of custom entries in this query to speed up.. 786 // Put remove of custom entries in this query to speed up..
850 qu += "DELETE FORM custom_data WHERE ("; 787 qu += "DELETE FORM custom_data WHERE (";
851 query = ""; 788 query = "";
852 789
853 for ( int i = 0; i < completed_uids.size(); i++ ){ 790 for ( uint i = 0; i < completed_uids.size(); i++ ){
854 if ( !query.isEmpty() ) 791 if ( !query.isEmpty() )
855 query += " OR "; 792 query += " OR ";
856 query += QString( "uid = %1" ).arg( completed_uids[i] ); 793 query += QString( "uid = %1" ).arg( completed_uids[i] );
857 } 794 }
858 qu += query + " );"; 795 qu += query + " );";
859 796
860 odebug << "query: " << qu << "" << oendl;
861
862 OSQLRawQuery raw2( qu ); 797 OSQLRawQuery raw2( qu );
863 res = m_driver->query( &raw2 ); 798 res = m_driver->query( &raw2 );
864 if ( res.state() == OSQLResult::Failure ) { 799
800 if ( res.state() == OSQLResult::Failure )
865 owarn << "OPimTodoAccessBackendSQL::removeAllCompleted():Failure in query: " << qu << "" << oendl; 801 owarn << "OPimTodoAccessBackendSQL::removeAllCompleted():Failure in query: " << qu << "" << oendl;
866 } 802
867} 803}
868 804
869 805
870QMap<QString, QString> OPimTodoAccessBackendSQL::requestCustom( int uid ) const 806QMap<QString, QString> OPimTodoAccessBackendSQL::requestCustom( int uid ) const
871{ 807{
872 QMap<QString, QString> customMap; 808 QMap<QString, QString> customMap;
873 809
874 FindCustomQuery query( uid ); 810 FindCustomQuery query( uid );
875 OSQLResult res_custom = m_driver->query( &query ); 811 OSQLResult res_custom = m_driver->query( &query );
876 812
877 if ( res_custom.state() == OSQLResult::Failure ) { 813 if ( res_custom.state() == OSQLResult::Failure ) {
878 owarn << "OSQLResult::Failure in find query !!" << oendl; 814 owarn << "OSQLResult::Failure in find query !!" << oendl;
879 QMap<QString, QString> empty; 815 return QMap<QString, QString>();
880 return empty;
881 } 816 }
882 817
883 OSQLResultItem::ValueList list = res_custom.results(); 818 OSQLResultItem::ValueList list = res_custom.results();
884 OSQLResultItem::ValueList::Iterator it = list.begin(); 819 OSQLResultItem::ValueList::Iterator it = list.begin();
885 for ( ; it != list.end(); ++it ) { 820 for ( ; it != list.end(); ++it )
886 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) ); 821 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
887 } 822
888 823
889 return customMap; 824 return customMap;
890} 825}
891 826
892 827
893 828
894 829
895} 830}
diff --git a/libopie2/opiepim/backend/otodoaccesssql.h b/libopie2/opiepim/backend/otodoaccesssql.h
index 415f791..0ba8f3a 100644
--- a/libopie2/opiepim/backend/otodoaccesssql.h
+++ b/libopie2/opiepim/backend/otodoaccesssql.h
@@ -38,56 +38,51 @@ namespace DB {
38class OSQLDriver; 38class OSQLDriver;
39class OSQLResult; 39class OSQLResult;
40class OSQLResultItem; 40class OSQLResultItem;
41} 41}
42} 42}
43 43
44namespace Opie { 44namespace Opie {
45 45
46class OPimTodoAccessBackendSQL : public OPimTodoAccessBackend { 46class OPimTodoAccessBackendSQL : public OPimTodoAccessBackend {
47public: 47public:
48 OPimTodoAccessBackendSQL( const QString& file ); 48 OPimTodoAccessBackendSQL( const QString& file );
49 ~OPimTodoAccessBackendSQL(); 49 ~OPimTodoAccessBackendSQL();
50 50
51 bool load(); 51 bool load();
52 bool reload(); 52 bool reload();
53 bool save(); 53 bool save();
54 QArray<int> allRecords()const; 54 QArray<UID> allRecords()const;
55 55
56 QArray<int> queryByExample( const OPimTodo& t, int settings, const QDateTime& d = QDateTime() ); 56 QArray<UID> queryByExample( const OPimTodo& t, int settings, const QDateTime& d = QDateTime() );
57 OPimTodo find(int uid)const; 57 OPimTodo find(UID uid)const;
58 OPimTodo find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 58 OPimTodo find(UID uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
59 void clear(); 59 void clear();
60 bool add( const OPimTodo& t ); 60 bool add( const OPimTodo& t );
61 bool remove( int uid ); 61 bool remove( UID uid );
62 bool replace( const OPimTodo& t ); 62 bool replace( const OPimTodo& t );
63 63
64 QArray<int> overDue(); 64 QArray<UID> overDue()const;
65 QArray<int> effectiveToDos( const QDate& start, 65 QArray<UID> effectiveToDos( const QDate& start,
66 const QDate& end, bool includeNoDates ); 66 const QDate& end, bool includeNoDates )const;
67 QArray<int> sorted(bool asc, int sortOrder, int sortFilter, int cat ); 67 QArray<UID> matchRegexp( const QRegExp &r ) const;
68
69 QBitArray supports()const;
70 QArray<int> matchRegexp( const QRegExp &r ) const;
71 void removeAllCompleted(); 68 void removeAllCompleted();
72 69
73 70
74private: 71private:
75 void update()const; 72 void update()const;
76 void fillDict();
77 inline bool date( QDate& date, const QString& )const; 73 inline bool date( QDate& date, const QString& )const;
78 inline OPimTodo parseResultAndCache( int uid, const Opie::DB::OSQLResult& )const; 74 inline OPimTodo parseResultAndCache( UID uid, const Opie::DB::OSQLResult& )const;
79 inline OPimTodo todo( Opie::DB::OSQLResultItem& )const; 75 inline OPimTodo parse( Opie::DB::OSQLResultItem& )const;
80 inline QArray<int> uids( const Opie::DB::OSQLResult& )const; 76 inline QArray<UID> uids( const Opie::DB::OSQLResult& )const;
81 OPimTodo todo( int uid )const; 77 OPimTodo todo( UID uid )const;
82 QBitArray sup() const; 78 QMap<QString, QString> requestCustom( UID uid ) const;
83 QMap<QString, QString> requestCustom( int uid ) const;
84 79
85 // QAsciiDict<int> m_dict; 80 // QAsciiDict<int> m_dict;
86 Opie::DB::OSQLDriver* m_driver; 81 Opie::DB::OSQLDriver* m_driver;
87 QArray<int> m_uids; 82 QArray<UID> m_uids;
88 bool m_dirty : 1; 83 bool m_dirty : 1;
89}; 84};
90 85
91} 86}
92 87
93#endif 88#endif
diff --git a/libopie2/opiepim/backend/otodoaccessvcal.cpp b/libopie2/opiepim/backend/otodoaccessvcal.cpp
index 7d58a40..aa8a7eb 100644
--- a/libopie2/opiepim/backend/otodoaccessvcal.cpp
+++ b/libopie2/opiepim/backend/otodoaccessvcal.cpp
@@ -79,33 +79,32 @@ namespace {
79 event.setCompleted( false ); 79 event.setCompleted( false );
80 // priority 80 // priority
81 if ((ob = isAPropertyOf(obj, VCPriorityProp))) { 81 if ((ob = isAPropertyOf(obj, VCPriorityProp))) {
82 name = vObjectStringZValue( ob ); 82 name = vObjectStringZValue( ob );
83 bool ok; 83 bool ok;
84 event.setPriority(name.toInt(&ok) ); 84 event.setPriority(name.toInt(&ok) );
85 } 85 }
86 //due date 86 //due date
87 if((ob = isAPropertyOf(obj, VCDueProp)) ){ 87 if((ob = isAPropertyOf(obj, VCDueProp)) ){
88 event.setHasDueDate( true ); 88 event.setHasDueDate( true );
89 name = vObjectStringZValue( ob ); 89 name = vObjectStringZValue( ob );
90 event.setDueDate( TimeConversion::fromISO8601( name).date() ); 90 event.setDueDate( TimeConversion::fromISO8601( name).date() );
91 } 91 }
92 // categories 92 // categories
93 if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){ 93 if((ob = isAPropertyOf( obj, VCCategoriesProp )) != 0 ){
94 name = vObjectStringZValue( ob ); 94 name = vObjectStringZValue( ob );
95 owarn << "Categories:" << name.data() << "" << oendl;
96 } 95 }
97 96
98 event.setUid( 1 ); 97 event.setUid( 1 );
99 return event; 98 return event;
100 }; 99 };
101 static VObject *vobjByEvent( const OPimTodo &event ) { 100 static VObject *vobjByEvent( const OPimTodo &event ) {
102 VObject *task = newVObject( VCTodoProp ); 101 VObject *task = newVObject( VCTodoProp );
103 if( task == 0 ) 102 if( task == 0 )
104 return 0l; 103 return 0l;
105 104
106 if( event.hasDueDate() ) { 105 if( event.hasDueDate() ) {
107 QTime time(0, 0, 0); 106 QTime time(0, 0, 0);
108 QDateTime date(event.dueDate(), time ); 107 QDateTime date(event.dueDate(), time );
109 addPropValue( task, VCDueProp, 108 addPropValue( task, VCDueProp,
110 TimeConversion::toISO8601( date ) ); 109 TimeConversion::toISO8601( date ) );
111 } 110 }
@@ -220,70 +219,41 @@ bool OPimTodoAccessVCal::remove( int uid ) {
220 return true; 219 return true;
221} 220}
222void OPimTodoAccessVCal::removeAllCompleted() { 221void OPimTodoAccessVCal::removeAllCompleted() {
223 for ( QMap<int, OPimTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) { 222 for ( QMap<int, OPimTodo>::Iterator it = m_map.begin(); it != m_map.end(); ++it ) {
224 if ( (*it).isCompleted() ) 223 if ( (*it).isCompleted() )
225 m_map.remove( it ); 224 m_map.remove( it );
226 } 225 }
227} 226}
228bool OPimTodoAccessVCal::replace( const OPimTodo& to ) { 227bool OPimTodoAccessVCal::replace( const OPimTodo& to ) {
229 m_map.replace( to.uid(), to ); 228 m_map.replace( to.uid(), to );
230 m_dirty = true; 229 m_dirty = true;
231 return true; 230 return true;
232} 231}
233OPimTodo OPimTodoAccessVCal::find(int uid )const { 232OPimTodo OPimTodoAccessVCal::find(int uid )const {
234 return m_map[uid]; 233 return m_map[uid];
235} 234}
236QArray<int> OPimTodoAccessVCal::sorted( bool, int, int, int ) { 235
237 QArray<int> ar(0);
238 return ar;
239}
240QArray<int> OPimTodoAccessVCal::allRecords()const { 236QArray<int> OPimTodoAccessVCal::allRecords()const {
241 QArray<int> ar( m_map.count() ); 237 QArray<int> ar( m_map.count() );
242 QMap<int, OPimTodo>::ConstIterator it; 238 QMap<int, OPimTodo>::ConstIterator it;
243 int i = 0; 239 int i = 0;
244 for ( it = m_map.begin(); it != m_map.end(); ++it ) { 240 for ( it = m_map.begin(); it != m_map.end(); ++it ) {
245 ar[i] = it.key(); 241 ar[i] = it.key();
246 i++; 242 i++;
247 } 243 }
248 return ar; 244 return ar;
249} 245}
250QArray<int> OPimTodoAccessVCal::matchRegexp(const QRegExp& /* r */)const { 246
251 QArray<int> ar(0);
252 return ar;
253}
254QArray<int> OPimTodoAccessVCal::queryByExample( const OPimTodo&, int, const QDateTime& ) {
255 QArray<int> ar(0);
256 return ar;
257}
258QArray<int> OPimTodoAccessVCal::effectiveToDos( const QDate& , 247QArray<int> OPimTodoAccessVCal::effectiveToDos( const QDate& ,
259 const QDate& , 248 const QDate& ,
260 bool ) { 249 bool )const {
261 QArray<int> ar(0);
262 return ar;
263}
264QArray<int> OPimTodoAccessVCal::overDue() {
265 QArray<int> ar(0); 250 QArray<int> ar(0);
266 return ar; 251 return ar;
267} 252}
268QBitArray OPimTodoAccessVCal::supports()const {
269 static QBitArray ar = sup();
270
271 return ar;
272}
273QBitArray OPimTodoAccessVCal::sup() {
274 QBitArray ar ( OPimTodo::CompletedDate +1 );
275 ar.fill( true );
276
277 ar[OPimTodo::CrossReference] = false;
278 ar[OPimTodo::State ] = false;
279 ar[OPimTodo::Reminders] = false;
280 ar[OPimTodo::Notifiers] = false;
281 ar[OPimTodo::Maintainer] = false;
282 ar[OPimTodo::Progress] = false;
283 ar[OPimTodo::Alarms ] = false;
284 ar[OPimTodo::Recurrence] = false;
285 253
254QArray<int> OPimTodoAccessVCal::overDue()const {
255 QArray<int> ar(0);
286 return ar; 256 return ar;
287} 257}
288 258
289} 259}
diff --git a/libopie2/opiepim/backend/otodoaccessvcal.h b/libopie2/opiepim/backend/otodoaccessvcal.h
index 1e106d3..05dd76b 100644
--- a/libopie2/opiepim/backend/otodoaccessvcal.h
+++ b/libopie2/opiepim/backend/otodoaccessvcal.h
@@ -30,43 +30,37 @@
30#define OPIE_OTODO_ACCESS_VCAL_H 30#define OPIE_OTODO_ACCESS_VCAL_H
31 31
32#include <opie2/otodoaccessbackend.h> 32#include <opie2/otodoaccessbackend.h>
33 33
34namespace Opie { 34namespace Opie {
35 35
36class OPimTodoAccessVCal : public OPimTodoAccessBackend { 36class OPimTodoAccessVCal : public OPimTodoAccessBackend {
37public: 37public:
38 OPimTodoAccessVCal(const QString& ); 38 OPimTodoAccessVCal(const QString& );
39 ~OPimTodoAccessVCal(); 39 ~OPimTodoAccessVCal();
40 40
41 bool load(); 41 bool load();
42 bool reload(); 42 bool reload();
43 bool save(); 43 bool save();
44 44
45 QArray<int> allRecords()const; 45 QArray<int> allRecords()const;
46 QArray<int> matchRegexp(const QRegExp &r) const;
47 QArray<int> queryByExample( const OPimTodo& t, int sort, const QDateTime& d = QDateTime() );
48 QArray<int> effectiveToDos( const QDate& start, 46 QArray<int> effectiveToDos( const QDate& start,
49 const QDate& end, 47 const QDate& end,
50 bool includeNoDates ); 48 bool includeNoDates )const;
51 QArray<int> overDue(); 49 QArray<int> overDue()const;
52 QArray<int> sorted( bool asc, int sortOrder, int sortFilter,
53 int cat );
54 OPimTodo find(int uid)const; 50 OPimTodo find(int uid)const;
55 void clear(); 51 void clear();
56 bool add( const OPimTodo& ); 52 bool add( const OPimTodo& );
57 bool remove( int uid ); 53 bool remove( int uid );
58 bool replace( const OPimTodo& ); 54 bool replace( const OPimTodo& );
59 55
60 void removeAllCompleted(); 56 void removeAllCompleted();
61 virtual QBitArray supports()const;
62 57
63private: 58private:
64 static QBitArray sup();
65 bool m_dirty : 1; 59 bool m_dirty : 1;
66 QString m_file; 60 QString m_file;
67 QMap<int, OPimTodo> m_map; 61 QMap<int, OPimTodo> m_map;
68}; 62};
69 63
70} 64}
71 65
72#endif 66#endif
diff --git a/libopie2/opiepim/backend/otodoaccessxml.cpp b/libopie2/opiepim/backend/otodoaccessxml.cpp
index 3e06d88..273f91a 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.cpp
+++ b/libopie2/opiepim/backend/otodoaccessxml.cpp
@@ -21,34 +21,37 @@
21 : = ...= . :.=- 21 : = ...= . :.=-
22 -. .:....=;==+<; You should have received a copy of the GNU 22 -. .:....=;==+<; You should have received a copy of the GNU
23 -_. . . )=. = Library General Public License along with 23 -_. . . )=. = Library General Public License along with
24 -- :-=` this library; see the file COPYING.LIB. 24 -- :-=` this library; see the file COPYING.LIB.
25 If not, write to the Free Software Foundation, 25 If not, write to the Free Software Foundation,
26 Inc., 59 Temple Place - Suite 330, 26 Inc., 59 Temple Place - Suite 330,
27 Boston, MA 02111-1307, USA. 27 Boston, MA 02111-1307, USA.
28*/ 28*/
29 29
30/* OPIE */ 30/* OPIE */
31#include <opie2/opimdateconversion.h> 31#include <opie2/opimdateconversion.h>
32#include <opie2/opimstate.h> 32#include <opie2/opimstate.h>
33#include <opie2/opimtimezone.h> 33#include <opie2/opimtimezone.h>
34#include <opie2/opimnotifymanager.h> 34#include <opie2/opimnotifymanager.h>
35#include <opie2/opimrecurrence.h> 35#include <opie2/opimrecurrence.h>
36#include <opie2/otodoaccessxml.h> 36#include <opie2/otodoaccessxml.h>
37#include <opie2/otodoaccess.h>
37#include <opie2/odebug.h> 38#include <opie2/odebug.h>
38 39
40#include <opie2/private/opimtodosortvector.h>
41
39#include <qpe/global.h> 42#include <qpe/global.h>
40#include <qpe/stringutil.h> 43#include <qpe/stringutil.h>
41#include <qpe/timeconversion.h> 44#include <qpe/timeconversion.h>
42 45
43/* QT */ 46/* QT */
44#include <qfile.h> 47#include <qfile.h>
45#include <qvector.h> 48#include <qvector.h>
46 49
47/* STD */ 50/* STD */
48#include <errno.h> 51#include <errno.h>
49#include <fcntl.h> 52#include <fcntl.h>
50 53
51#include <sys/mman.h> 54#include <sys/mman.h>
52#include <sys/stat.h> 55#include <sys/stat.h>
53#include <sys/types.h> 56#include <sys/types.h>
54 57
@@ -129,33 +132,32 @@ bool OPimTodoAccessXML::load() {
129 dict.insert("Uid" , new int(OPimTodo::Uid) ); 132 dict.insert("Uid" , new int(OPimTodo::Uid) );
130 dict.insert("HasDate" , new int(OPimTodo::HasDate) ); 133 dict.insert("HasDate" , new int(OPimTodo::HasDate) );
131 dict.insert("Completed" , new int(OPimTodo::Completed) ); 134 dict.insert("Completed" , new int(OPimTodo::Completed) );
132 dict.insert("Description" , new int(OPimTodo::Description) ); 135 dict.insert("Description" , new int(OPimTodo::Description) );
133 dict.insert("Summary" , new int(OPimTodo::Summary) ); 136 dict.insert("Summary" , new int(OPimTodo::Summary) );
134 dict.insert("Priority" , new int(OPimTodo::Priority) ); 137 dict.insert("Priority" , new int(OPimTodo::Priority) );
135 dict.insert("DateDay" , new int(OPimTodo::DateDay) ); 138 dict.insert("DateDay" , new int(OPimTodo::DateDay) );
136 dict.insert("DateMonth" , new int(OPimTodo::DateMonth) ); 139 dict.insert("DateMonth" , new int(OPimTodo::DateMonth) );
137 dict.insert("DateYear" , new int(OPimTodo::DateYear) ); 140 dict.insert("DateYear" , new int(OPimTodo::DateYear) );
138 dict.insert("Progress" , new int(OPimTodo::Progress) ); 141 dict.insert("Progress" , new int(OPimTodo::Progress) );
139 dict.insert("CompletedDate", new int(OPimTodo::CompletedDate) ); 142 dict.insert("CompletedDate", new int(OPimTodo::CompletedDate) );
140 dict.insert("StartDate", new int(OPimTodo::StartDate) ); 143 dict.insert("StartDate", new int(OPimTodo::StartDate) );
141 dict.insert("CrossReference", new int(OPimTodo::CrossReference) ); 144 dict.insert("CrossReference", new int(OPimTodo::CrossReference) );
142 dict.insert("State", new int(OPimTodo::State) ); 145 dict.insert("State", new int(OPimTodo::State) );
143 dict.insert("Alarms", new int(OPimTodo::Alarms) ); 146 dict.insert("Alarms", new int(OPimTodo::Alarms) );
144 dict.insert("Reminders", new int(OPimTodo::Reminders) ); 147 dict.insert("Reminders", new int(OPimTodo::Reminders) );
145 dict.insert("Notifiers", new int(OPimTodo::Notifiers) );
146 dict.insert("Maintainer", new int(OPimTodo::Maintainer) ); 148 dict.insert("Maintainer", new int(OPimTodo::Maintainer) );
147 dict.insert("rtype", new int(FRType) ); 149 dict.insert("rtype", new int(FRType) );
148 dict.insert("rweekdays", new int(FRWeekdays) ); 150 dict.insert("rweekdays", new int(FRWeekdays) );
149 dict.insert("rposition", new int(FRPosition) ); 151 dict.insert("rposition", new int(FRPosition) );
150 dict.insert("rfreq", new int(FRFreq) ); 152 dict.insert("rfreq", new int(FRFreq) );
151 dict.insert("start", new int(FRStart) ); 153 dict.insert("start", new int(FRStart) );
152 dict.insert("rhasenddate", new int(FRHasEndDate) ); 154 dict.insert("rhasenddate", new int(FRHasEndDate) );
153 dict.insert("enddt", new int(FREndDate) ); 155 dict.insert("enddt", new int(FREndDate) );
154 156
155 // here the custom XML parser from TT it's GPL 157 // here the custom XML parser from TT it's GPL
156 // but we want to push OpiePIM... to TT..... 158 // but we want to push OpiePIM... to TT.....
157 // mmap part from zecke :) 159 // mmap part from zecke :)
158 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY ); 160 int fd = ::open( QFile::encodeName(m_file).data(), O_RDONLY );
159 struct stat attribut; 161 struct stat attribut;
160 if ( fd < 0 ) return false; 162 if ( fd < 0 ) return false;
161 163
@@ -169,33 +171,32 @@ bool OPimTodoAccessXML::load() {
169 return false; 171 return false;
170 } 172 }
171 /* advise the kernel who we want to read it */ 173 /* advise the kernel who we want to read it */
172 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL ); 174 ::madvise( map_addr, attribut.st_size, MADV_SEQUENTIAL );
173 /* we do not the file any more */ 175 /* we do not the file any more */
174 ::close( fd ); 176 ::close( fd );
175 177
176 char* dt = (char*)map_addr; 178 char* dt = (char*)map_addr;
177 int len = attribut.st_size; 179 int len = attribut.st_size;
178 int i = 0; 180 int i = 0;
179 char *point; 181 char *point;
180 const char* collectionString = "<Task "; 182 const char* collectionString = "<Task ";
181 int strLen = strlen(collectionString); 183 int strLen = strlen(collectionString);
182 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) { 184 while ( ( point = strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0l ) {
183 i = point -dt; 185 i = point -dt;
184 i+= strLen; 186 i+= strLen;
185 owarn << "Found a start at " << i << " " << (point-dt) << "" << oendl;
186 187
187 OPimTodo ev; 188 OPimTodo ev;
188 m_year = m_month = m_day = 0; 189 m_year = m_month = m_day = 0;
189 190
190 while ( TRUE ) { 191 while ( TRUE ) {
191 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 192 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
192 ++i; 193 ++i;
193 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 194 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
194 break; 195 break;
195 196
196 // we have another attribute, read it. 197 // we have another attribute, read it.
197 int j = i; 198 int j = i;
198 while ( j < len && dt[j] != '=' ) 199 while ( j < len && dt[j] != '=' )
199 ++j; 200 ++j;
200 QCString attr( dt+i, j-i+1); 201 QCString attr( dt+i, j-i+1);
201 202
@@ -225,66 +226,62 @@ bool OPimTodoAccessXML::load() {
225 i = j + 1; 226 i = j + 1;
226 227
227 QString str = (haveUtf ? QString::fromUtf8( value ) 228 QString str = (haveUtf ? QString::fromUtf8( value )
228 : QString::fromLatin1( value ) ); 229 : QString::fromLatin1( value ) );
229 if ( haveEnt ) 230 if ( haveEnt )
230 str = Qtopia::plainString( str ); 231 str = Qtopia::plainString( str );
231 232
232 /* 233 /*
233 * add key + value 234 * add key + value
234 */ 235 */
235 todo( &dict, ev, attr, str ); 236 todo( &dict, ev, attr, str );
236 237
237 } 238 }
238 /* 239 /*
239 * now add it 240 * now add it
240 */ 241 */
241 owarn << "End at " << i << "" << oendl;
242 if (m_events.contains( ev.uid() ) || ev.uid() == 0) { 242 if (m_events.contains( ev.uid() ) || ev.uid() == 0) {
243 ev.setUid( 1 ); 243 ev.setUid( 1 );
244 m_changed = true; 244 m_changed = true;
245 } 245 }
246 if ( ev.hasDueDate() ) { 246 if ( ev.hasDueDate() ) {
247 ev.setDueDate( QDate(m_year, m_month, m_day) ); 247 ev.setDueDate( QDate(m_year, m_month, m_day) );
248 } 248 }
249 if ( rec && rec->doesRecur() ) { 249 if ( rec && rec->doesRecur() ) {
250 OPimTimeZone utc = OPimTimeZone::utc(); 250 OPimTimeZone utc = OPimTimeZone::utc();
251 OPimRecurrence recu( *rec ); // call copy c'tor 251 OPimRecurrence recu( *rec ); // call copy c'tor
252 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() ); 252 recu.setEndDate( utc.fromUTCDateTime( rp_end ).date() );
253 recu.setStart( ev.dueDate() ); 253 recu.setStart( ev.dueDate() );
254 ev.setRecurrence( recu ); 254 ev.setRecurrence( recu );
255 } 255 }
256 m_events.insert(ev.uid(), ev ); 256 m_events.insert(ev.uid(), ev );
257 m_year = m_month = m_day = -1; 257 m_year = m_month = m_day = -1;
258 delete rec; 258 delete rec;
259 rec = 0; 259 rec = 0;
260 } 260 }
261 261
262 munmap(map_addr, attribut.st_size ); 262 munmap(map_addr, attribut.st_size );
263 263
264 owarn << "counts " << m_events.count() << " records loaded!" << oendl;
265 return true; 264 return true;
266} 265}
267bool OPimTodoAccessXML::reload() { 266bool OPimTodoAccessXML::reload() {
268 m_events.clear(); 267 m_events.clear();
269 return load(); 268 return load();
270} 269}
271bool OPimTodoAccessXML::save() { 270bool OPimTodoAccessXML::save() {
272// owarn << "saving" << oendl;
273 if (!m_opened || !m_changed ) { 271 if (!m_opened || !m_changed ) {
274// owarn << "not saving" << oendl;
275 return true; 272 return true;
276 } 273 }
277 QString strNewFile = m_file + ".new"; 274 QString strNewFile = m_file + ".new";
278 QFile f( strNewFile ); 275 QFile f( strNewFile );
279 if (!f.open( IO_WriteOnly|IO_Raw ) ) 276 if (!f.open( IO_WriteOnly|IO_Raw ) )
280 return false; 277 return false;
281 278
282 int written; 279 int written;
283 QString out; 280 QString out;
284 out = "<!DOCTYPE Tasks>\n<Tasks>\n"; 281 out = "<!DOCTYPE Tasks>\n<Tasks>\n";
285 282
286 // for all todos 283 // for all todos
287 QMap<int, OPimTodo>::Iterator it; 284 QMap<int, OPimTodo>::Iterator it;
288 for (it = m_events.begin(); it != m_events.end(); ++it ) { 285 for (it = m_events.begin(); it != m_events.end(); ++it ) {
289 out+= "<Task " + toString( (*it) ) + " />\n"; 286 out+= "<Task " + toString( (*it) ) + " />\n";
290 QCString cstr = out.utf8(); 287 QCString cstr = out.utf8();
@@ -299,136 +296,128 @@ bool OPimTodoAccessXML::save() {
299 out = QString::null; 296 out = QString::null;
300 } 297 }
301 298
302 out += "</Tasks>"; 299 out += "</Tasks>";
303 QCString cstr = out.utf8(); 300 QCString cstr = out.utf8();
304 written = f.writeBlock( cstr.data(), cstr.length() ); 301 written = f.writeBlock( cstr.data(), cstr.length() );
305 302
306 if ( written != (int)cstr.length() ) { 303 if ( written != (int)cstr.length() ) {
307 f.close(); 304 f.close();
308 QFile::remove( strNewFile ); 305 QFile::remove( strNewFile );
309 return false; 306 return false;
310 } 307 }
311 /* flush before renaming */ 308 /* flush before renaming */
312 f.close(); 309 f.close();
313 310
314 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) { 311 if( ::rename( strNewFile.latin1(), m_file.latin1() ) < 0 ) {
315// owarn << "error renaming" << oendl;
316 QFile::remove( strNewFile ); 312 QFile::remove( strNewFile );
317 } 313 }
318 314
319 m_changed = false; 315 m_changed = false;
320 return true; 316 return true;
321} 317}
322QArray<int> OPimTodoAccessXML::allRecords()const { 318QArray<int> OPimTodoAccessXML::allRecords()const {
323 QArray<int> ids( m_events.count() ); 319 QArray<int> ids( m_events.count() );
324 QMap<int, OPimTodo>::ConstIterator it; 320 QMap<int, OPimTodo>::ConstIterator it;
325 int i = 0; 321 int i = 0;
326 322
327 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 323 for ( it = m_events.begin(); it != m_events.end(); ++it )
328 ids[i] = it.key(); 324 ids[i++] = it.key();
329 i++; 325
330 } 326
331 return ids; 327 return ids;
332} 328}
333QArray<int> OPimTodoAccessXML::queryByExample( const OPimTodo&, int, const QDateTime& ) { 329QArray<int> OPimTodoAccessXML::queryByExample( const OPimTodo&, int, const QDateTime& ) {
334 QArray<int> ids(0); 330 QArray<int> ids(0);
335 return ids; 331 return ids;
336} 332}
337OPimTodo OPimTodoAccessXML::find( int uid )const { 333OPimTodo OPimTodoAccessXML::find( int uid )const {
338 OPimTodo todo; 334 OPimTodo todo;
339 todo.setUid( 0 ); // isEmpty() 335 todo.setUid( 0 ); // isEmpty()
340 QMap<int, OPimTodo>::ConstIterator it = m_events.find( uid ); 336 QMap<int, OPimTodo>::ConstIterator it = m_events.find( uid );
341 if ( it != m_events.end() ) 337 if ( it != m_events.end() )
342 todo = it.data(); 338 todo = it.data();
343 339
344 return todo; 340 return todo;
345} 341}
346void OPimTodoAccessXML::clear() { 342void OPimTodoAccessXML::clear() {
347 if (m_opened ) 343 if (m_opened )
348 m_changed = true; 344 m_changed = true;
349 345
350 m_events.clear(); 346 m_events.clear();
351} 347}
352bool OPimTodoAccessXML::add( const OPimTodo& todo ) { 348bool OPimTodoAccessXML::add( const OPimTodo& todo ) {
353// owarn << "add" << oendl;
354 m_changed = true; 349 m_changed = true;
355 m_events.insert( todo.uid(), todo ); 350 m_events.insert( todo.uid(), todo );
356 351
357 return true; 352 return true;
358} 353}
359bool OPimTodoAccessXML::remove( int uid ) { 354bool OPimTodoAccessXML::remove( int uid ) {
360 m_changed = true; 355 m_changed = true;
361 m_events.remove( uid ); 356 m_events.remove( uid );
362 357
363 return true; 358 return true;
364} 359}
365bool OPimTodoAccessXML::replace( const OPimTodo& todo) { 360bool OPimTodoAccessXML::replace( const OPimTodo& todo) {
366 m_changed = true; 361 m_changed = true;
367 m_events.replace( todo.uid(), todo ); 362 m_events.replace( todo.uid(), todo );
368 363
369 return true; 364 return true;
370} 365}
371QArray<int> OPimTodoAccessXML::effectiveToDos( const QDate& start, 366QArray<int> OPimTodoAccessXML::effectiveToDos( const QDate& start,
372 const QDate& end, 367 const QDate& end,
373 bool includeNoDates ) { 368 bool includeNoDates )const {
374 QArray<int> ids( m_events.count() ); 369 QArray<int> ids( m_events.count() );
375 QMap<int, OPimTodo>::Iterator it; 370 QMap<int, OPimTodo>::ConstIterator it;
376 371
377 int i = 0; 372 int i = 0;
378 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 373 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
379 if ( !it.data().hasDueDate() ) { 374 if ( !it.data().hasDueDate() && includeNoDates) {
380 if ( includeNoDates ) { 375 ids[i++] = it.key();
381 ids[i] = it.key();
382 i++;
383 }
384 }else if ( it.data().dueDate() >= start && 376 }else if ( it.data().dueDate() >= start &&
385 it.data().dueDate() <= end ) { 377 it.data().dueDate() <= end ) {
386 ids[i] = it.key(); 378 ids[i++] = it.key();
387 i++;
388 } 379 }
389 } 380 }
390 ids.resize( i ); 381 ids.resize( i );
391 return ids; 382 return ids;
392} 383}
393QArray<int> OPimTodoAccessXML::overDue() { 384QArray<int> OPimTodoAccessXML::overDue()const {
394 QArray<int> ids( m_events.count() ); 385 QArray<int> ids( m_events.count() );
395 int i = 0; 386 int i = 0;
396 387
397 QMap<int, OPimTodo>::Iterator it; 388 QMap<int, OPimTodo>::ConstIterator it;
398 for ( it = m_events.begin(); it != m_events.end(); ++it ) { 389 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
399 if ( it.data().isOverdue() ) { 390 if ( it.data().isOverdue() ) {
400 ids[i] = it.key(); 391 ids[i] = it.key();
401 i++; 392 i++;
402 } 393 }
403 } 394 }
404 ids.resize( i ); 395 ids.resize( i );
405 return ids; 396 return ids;
406} 397}
407 398
408 399
409/* private */ 400/* private */
410void OPimTodoAccessXML::todo( QAsciiDict<int>* dict, OPimTodo& ev, 401void OPimTodoAccessXML::todo( QAsciiDict<int>* dict, OPimTodo& ev,
411 const QCString& attr, const QString& val) { 402 const QCString& attr, const QString& val) {
412// owarn << "parse to do from XMLElement" << oendl;
413 403
414 int *find=0; 404 int *find=0;
415 405
416 find = (*dict)[ attr.data() ]; 406 find = (*dict)[ attr.data() ];
417 if (!find ) { 407 if (!find ) {
418// owarn << "Unknown option" + it.key() << oendl;
419 ev.setCustomField( attr, val ); 408 ev.setCustomField( attr, val );
420 return; 409 return;
421 } 410 }
422 411
423 switch( *find ) { 412 switch( *find ) {
424 case OPimTodo::Uid: 413 case OPimTodo::Uid:
425 ev.setUid( val.toInt() ); 414 ev.setUid( val.toInt() );
426 break; 415 break;
427 case OPimTodo::Category: 416 case OPimTodo::Category:
428 ev.setCategories( ev.idsFromString( val ) ); 417 ev.setCategories( ev.idsFromString( val ) );
429 break; 418 break;
430 case OPimTodo::HasDate: 419 case OPimTodo::HasDate:
431 ev.setHasDueDate( val.toInt() ); 420 ev.setHasDueDate( val.toInt() );
432 break; 421 break;
433 case OPimTodo::Completed: 422 case OPimTodo::Completed:
434 ev.setCompleted( val.toInt() ); 423 ev.setCompleted( val.toInt() );
@@ -455,34 +444,32 @@ void OPimTodoAccessXML::todo( QAsciiDict<int>* dict, OPimTodo& ev,
455 ev.setProgress( val.toInt() ); 444 ev.setProgress( val.toInt() );
456 break; 445 break;
457 case OPimTodo::CompletedDate: 446 case OPimTodo::CompletedDate:
458 ev.setCompletedDate( OPimDateConversion::dateFromString( val ) ); 447 ev.setCompletedDate( OPimDateConversion::dateFromString( val ) );
459 break; 448 break;
460 case OPimTodo::StartDate: 449 case OPimTodo::StartDate:
461 ev.setStartDate( OPimDateConversion::dateFromString( val ) ); 450 ev.setStartDate( OPimDateConversion::dateFromString( val ) );
462 break; 451 break;
463 case OPimTodo::State: 452 case OPimTodo::State:
464 ev.setState( val.toInt() ); 453 ev.setState( val.toInt() );
465 break; 454 break;
466 case OPimTodo::Alarms:{ 455 case OPimTodo::Alarms:{
467 OPimNotifyManager &manager = ev.notifiers(); 456 OPimNotifyManager &manager = ev.notifiers();
468 QStringList als = QStringList::split(";", val ); 457 QStringList als = QStringList::split(";", val );
469 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) { 458 for (QStringList::Iterator it = als.begin(); it != als.end(); ++it ) {
470 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty 459 QStringList alarm = QStringList::split(":", (*it), TRUE ); // allow empty
471 owarn << "alarm: " << alarm.join("___") << "" << oendl;
472 owarn << "alarm[0]: " << alarm[0] << " " << OPimDateConversion::dateTimeFromString( alarm[0] ).toString() << "" << oendl;
473 OPimAlarm al( alarm[2].toInt(), OPimDateConversion::dateTimeFromString( alarm[0] ), alarm[1].toInt() ); 460 OPimAlarm al( alarm[2].toInt(), OPimDateConversion::dateTimeFromString( alarm[0] ), alarm[1].toInt() );
474 manager.add( al ); 461 manager.add( al );
475 } 462 }
476 } 463 }
477 break; 464 break;
478 case OPimTodo::Reminders:{ 465 case OPimTodo::Reminders:{
479 OPimNotifyManager &manager = ev.notifiers(); 466 OPimNotifyManager &manager = ev.notifiers();
480 QStringList rems = QStringList::split(";", val ); 467 QStringList rems = QStringList::split(";", val );
481 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) { 468 for (QStringList::Iterator it = rems.begin(); it != rems.end(); ++it ) {
482 OPimReminder rem( (*it).toInt() ); 469 OPimReminder rem( (*it).toInt() );
483 manager.add( rem ); 470 manager.add( rem );
484 } 471 }
485 } 472 }
486 break; 473 break;
487 case OPimTodo::CrossReference: 474 case OPimTodo::CrossReference:
488 { 475 {
@@ -529,66 +516,63 @@ void OPimTodoAccessXML::todo( QAsciiDict<int>* dict, OPimTodo& ev,
529 recur()->setHasEndDate( val.toInt() ); 516 recur()->setHasEndDate( val.toInt() );
530 break; 517 break;
531 case FREndDate: { 518 case FREndDate: {
532 rp_end = (time_t) val.toLong(); 519 rp_end = (time_t) val.toLong();
533 break; 520 break;
534 } 521 }
535 default: 522 default:
536 ev.setCustomField( attr, val ); 523 ev.setCustomField( attr, val );
537 break; 524 break;
538 } 525 }
539} 526}
540 527
541// from PalmtopRecord... GPL ### FIXME 528// from PalmtopRecord... GPL ### FIXME
542namespace { 529namespace {
543QString customToXml(const QMap<QString, QString>& customMap ) 530QString customToXml(const QMap<QString, QString>& customMap )
544{ 531{
545 //owarn << QString("writing custom %1").arg(customMap.count()) << oendl;
546 QString buf(" "); 532 QString buf(" ");
547 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin(); 533 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
548 cit != customMap.end(); ++cit) { 534 cit != customMap.end(); ++cit) {
549// owarn << ".ITEM." << oendl;
550 buf += cit.key(); 535 buf += cit.key();
551 buf += "=\""; 536 buf += "=\"";
552 buf += Qtopia::escapeString(cit.data()); 537 buf += Qtopia::escapeString(cit.data());
553 buf += "\" "; 538 buf += "\" ";
554 } 539 }
555 return buf; 540 return buf;
556} 541}
557 542
558 543
559} 544}
560 545
561QString OPimTodoAccessXML::toString( const OPimTodo& ev )const { 546QString OPimTodoAccessXML::toString( const OPimTodo& ev )const {
562 QString str; 547 QString str;
563 548
564 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" "; 549 str += "Completed=\"" + QString::number( ev.isCompleted() ) + "\" ";
565 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" "; 550 str += "HasDate=\"" + QString::number( ev.hasDueDate() ) + "\" ";
566 str += "Priority=\"" + QString::number( ev.priority() ) + "\" "; 551 str += "Priority=\"" + QString::number( ev.priority() ) + "\" ";
567 str += "Progress=\"" + QString::number(ev.progress() ) + "\" "; 552 str += "Progress=\"" + QString::number(ev.progress() ) + "\" ";
568 553
569 str += "Categories=\"" + toString( ev.categories() ) + "\" "; 554 str += "Categories=\"" + toString( ev.categories() ) + "\" ";
570 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" "; 555 str += "Description=\"" + Qtopia::escapeString( ev.description() ) + "\" ";
571 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" "; 556 str += "Summary=\"" + Qtopia::escapeString( ev.summary() ) + "\" ";
572 557
573 if ( ev.hasDueDate() ) { 558 if ( ev.hasDueDate() ) {
574 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" "; 559 str += "DateYear=\"" + QString::number( ev.dueDate().year() ) + "\" ";
575 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" "; 560 str += "DateMonth=\"" + QString::number( ev.dueDate().month() ) + "\" ";
576 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" "; 561 str += "DateDay=\"" + QString::number( ev.dueDate().day() ) + "\" ";
577 } 562 }
578// owarn << "Uid " << ev.uid() << "" << oendl;
579 str += "Uid=\"" + QString::number( ev.uid() ) + "\" "; 563 str += "Uid=\"" + QString::number( ev.uid() ) + "\" ";
580 564
581// append the extra options 565// append the extra options
582 /* FIXME Qtopia::Record this is currently not 566 /* FIXME Qtopia::Record this is currently not
583 * possible you can set custom fields 567 * possible you can set custom fields
584 * but don' iterate over the list 568 * but don' iterate over the list
585 * I may do #define private protected 569 * I may do #define private protected
586 * for this case - cough --zecke 570 * for this case - cough --zecke
587 */ 571 */
588 /* 572 /*
589 QMap<QString, QString> extras = ev.extras(); 573 QMap<QString, QString> extras = ev.extras();
590 QMap<QString, QString>::Iterator extIt; 574 QMap<QString, QString>::Iterator extIt;
591 for (extIt = extras.begin(); extIt != extras.end(); ++extIt ) 575 for (extIt = extras.begin(); extIt != extras.end(); ++extIt )
592 str += extIt.key() + "=\"" + extIt.data() + "\" "; 576 str += extIt.key() + "=\"" + extIt.data() + "\" ";
593 */ 577 */
594 // cross refernce 578 // cross refernce
@@ -609,306 +593,128 @@ QString OPimTodoAccessXML::toString( const OPimTodo& ev )const {
609 if ( ev.hasNotifiers() ) { 593 if ( ev.hasNotifiers() ) {
610 OPimNotifyManager manager = ev.notifiers(); 594 OPimNotifyManager manager = ev.notifiers();
611 OPimNotifyManager::Alarms alarms = manager.alarms(); 595 OPimNotifyManager::Alarms alarms = manager.alarms();
612 if (!alarms.isEmpty() ) { 596 if (!alarms.isEmpty() ) {
613 QStringList als; 597 QStringList als;
614 OPimNotifyManager::Alarms::Iterator it = alarms.begin(); 598 OPimNotifyManager::Alarms::Iterator it = alarms.begin();
615 for ( ; it != alarms.end(); ++it ) { 599 for ( ; it != alarms.end(); ++it ) {
616 /* only if time is valid */ 600 /* only if time is valid */
617 if ( (*it).dateTime().isValid() ) { 601 if ( (*it).dateTime().isValid() ) {
618 als << OPimDateConversion::dateTimeToString( (*it).dateTime() ) 602 als << OPimDateConversion::dateTimeToString( (*it).dateTime() )
619 + ":" + QString::number( (*it).duration() ) 603 + ":" + QString::number( (*it).duration() )
620 + ":" + QString::number( (*it).sound() ) 604 + ":" + QString::number( (*it).sound() )
621 + ":"; 605 + ":";
622 } 606 }
623 } 607 }
624 // now write the list 608 // now write the list
625 owarn << "als: " << als.join("____________") << "" << oendl;
626 str += "Alarms=\""+als.join(";") +"\" "; 609 str += "Alarms=\""+als.join(";") +"\" ";
627 } 610 }
628 611
629 /* 612 /*
630 * now the same for reminders but more easy. We just save the uid of the OPimEvent. 613 * now the same for reminders but more easy. We just save the uid of the OPimEvent.
631 */ 614 */
632 OPimNotifyManager::Reminders reminders = manager.reminders(); 615 OPimNotifyManager::Reminders reminders = manager.reminders();
633 if (!reminders.isEmpty() ) { 616 if (!reminders.isEmpty() ) {
634 OPimNotifyManager::Reminders::Iterator it = reminders.begin(); 617 OPimNotifyManager::Reminders::Iterator it = reminders.begin();
635 QStringList records; 618 QStringList records;
636 for ( ; it != reminders.end(); ++it ) { 619 for ( ; it != reminders.end(); ++it ) {
637 records << QString::number( (*it).recordUid() ); 620 records << QString::number( (*it).recordUid() );
638 } 621 }
639 str += "Reminders=\""+ records.join(";") +"\" "; 622 str += "Reminders=\""+ records.join(";") +"\" ";
640 } 623 }
641 } 624 }
642 str += customToXml( ev.toExtraMap() ); 625 str += customToXml( ev.toExtraMap() );
643 626
644 627
645 return str; 628 return str;
646} 629}
647QString OPimTodoAccessXML::toString( const QArray<int>& ints ) const { 630QString OPimTodoAccessXML::toString( const QArray<int>& ints ) const {
648 return Qtopia::Record::idsToString( ints ); 631 return Qtopia::Record::idsToString( ints );
649} 632}
650 633
651/* internal class for sorting
652 *
653 * Inspired by todoxmlio.cpp from TT
654 */
655 634
656struct OPimTodoXMLContainer { 635QArray<int> OPimTodoAccessXML::sorted( const UIDArray& events, bool asc,
657 OPimTodo todo; 636 int sortOrder,int sortFilter,
658}; 637 const QArray<int>& categories )const {
638 Internal::OPimTodoSortVector vector(events.count(), asc,sortOrder );
639 int item = 0;
659 640
660namespace { 641 bool bCat = sortFilter & OPimTodoAccess::FilterCategory ? true : false;
661 inline QString string( const OPimTodo& todo) { 642 bool bOnly = sortFilter & OPimTodoAccess::OnlyOverDue ? true : false;
662 return todo.summary().isEmpty() ? 643 bool comp = sortFilter & OPimTodoAccess::DoNotShowCompleted ? true : false;
663 todo.description().left(20 ) : 644 bool catPassed = false;
664 todo.summary(); 645 int cat;
665 }
666 inline int completed( const OPimTodo& todo1, const OPimTodo& todo2) {
667 int ret = 0;
668 if ( todo1.isCompleted() ) ret++;
669 if ( todo2.isCompleted() ) ret--;
670 return ret;
671 }
672 inline int priority( const OPimTodo& t1, const OPimTodo& t2) {
673 return ( t1.priority() - t2.priority() );
674 }
675 inline int description( const OPimTodo& t1, const OPimTodo& t2) {
676 return QString::compare( string(t1), string(t2) );
677 }
678 inline int deadline( const OPimTodo& t1, const OPimTodo& t2) {
679 int ret = 0;
680 if ( t1.hasDueDate() &&
681 t2.hasDueDate() )
682 ret = t2.dueDate().daysTo( t1.dueDate() );
683 else if ( t1.hasDueDate() )
684 ret = -1;
685 else if ( t2.hasDueDate() )
686 ret = 1;
687 else
688 ret = 0;
689 646
690 return ret; 647 for ( uint i = 0; i < events.count(); ++i ) {
691 } 648 /* Guard against creating a new item... */
649 if ( !m_events.contains( events[i] ) )
650 continue;
692 651
693}; 652 OPimTodo todo = m_events[events[i]];
694 653
695/* 654 /* show category */
696 * Returns: 655 /* -1 == unfiled */
697 * 0 if item1 == item2 656 catPassed = false;
698 * 657 for ( uint cat_nu = 0; cat_nu < categories.count(); ++cat_nu ) {
699 * non-zero if item1 != item2 658 cat = categories[cat_nu];
700 * 659 if ( bCat && cat == -1 ) {
701 * This function returns int rather than bool so that reimplementations 660 if(!todo.categories().isEmpty() )
702 * can return one of three values and use it to sort by: 661 continue;
703 * 662 } else if ( bCat && cat != 0)
704 * 0 if item1 == item2 663 if (!todo.categories().contains( cat ) )
705 * 664 continue;
706 * > 0 (positive integer) if item1 > item2 665 catPassed = true;
707 *
708 * < 0 (negative integer) if item1 < item2
709 *
710 */
711class OPimTodoXMLVector : public QVector<OPimTodoXMLContainer> {
712public:
713 OPimTodoXMLVector(int size, bool asc, int sort)
714 : QVector<OPimTodoXMLContainer>( size )
715 {
716 setAutoDelete( true );
717 m_asc = asc;
718 m_sort = sort;
719 }
720 /* return the summary/description */
721 QString string( const OPimTodo& todo) {
722 return todo.summary().isEmpty() ?
723 todo.description().left(20 ) :
724 todo.summary();
725 }
726 /**
727 * we take the sortorder( switch on it )
728 *
729 */
730 int compareItems( Item d1, Item d2 ) {
731 bool seComp, sePrio, seDesc, seDeadline;
732 seComp = sePrio = seDeadline = seDesc = false;
733 int ret =0;
734 OPimTodoXMLContainer* con1 = (OPimTodoXMLContainer*)d1;
735 OPimTodoXMLContainer* con2 = (OPimTodoXMLContainer*)d2;
736
737 /* same item */
738 if ( con1->todo.uid() == con2->todo.uid() )
739 return 0;
740
741 switch ( m_sort ) {
742 /* completed */
743 case 0: {
744 ret = completed( con1->todo, con2->todo );
745 seComp = TRUE;
746 break;
747 }
748 /* priority */
749 case 1: {
750 ret = priority( con1->todo, con2->todo );
751 sePrio = TRUE;
752 break;
753 }
754 /* description */
755 case 2: {
756 ret = description( con1->todo, con2->todo );
757 seDesc = TRUE;
758 break;
759 }
760 /* deadline */
761 case 3: {
762 ret = deadline( con1->todo, con2->todo );
763 seDeadline = TRUE;
764 break; 666 break;
765 } 667 }
766 default:
767 ret = 0;
768 break;
769 };
770 /*
771 * FIXME do better sorting if the first sort criteria
772 * ret equals 0 start with complete and so on...
773 */
774
775 /* twist it we're not ascending*/
776 if (!m_asc)
777 ret = ret * -1;
778 668
779 if ( ret )
780 return ret;
781
782 // default did not gave difference let's try it other way around
783 /* 669 /*
784 * General try if already checked if not test 670 * If none of the Categories matched
785 * and return 671 * continue
786 * 1.Completed
787 * 2.Priority
788 * 3.Description
789 * 4.DueDate
790 */ 672 */
791 if (!seComp ) { 673 if ( !catPassed )
792 if ( (ret = completed( con1->todo, con2->todo ) ) ) {
793 if (!m_asc ) ret *= -1;
794 return ret;
795 }
796 }
797 if (!sePrio ) {
798 if ( (ret = priority( con1->todo, con2->todo ) ) ) {
799 if (!m_asc ) ret *= -1;
800 return ret;
801 }
802 }
803 if (!seDesc ) {
804 if ( (ret = description(con1->todo, con2->todo ) ) ) {
805 if (!m_asc) ret *= -1;
806 return ret;
807 }
808 }
809 if (!seDeadline) {
810 if ( (ret = deadline( con1->todo, con2->todo ) ) ) {
811 if (!m_asc) ret *= -1;
812 return ret;
813 }
814 }
815
816 return 0;
817 }
818 private:
819 bool m_asc;
820 int m_sort;
821
822};
823
824QArray<int> OPimTodoAccessXML::sorted( bool asc, int sortOrder,
825 int sortFilter, int cat ) {
826 OPimTodoXMLVector vector(m_events.count(), asc,sortOrder );
827 QMap<int, OPimTodo>::Iterator it;
828 int item = 0;
829
830 bool bCat = sortFilter & 1 ? true : false;
831 bool bOnly = sortFilter & 2 ? true : false;
832 bool comp = sortFilter & 4 ? true : false;
833 for ( it = m_events.begin(); it != m_events.end(); ++it ) {
834
835 /* show category */
836 /* -1 == unfiled */
837 if ( bCat && cat == -1 ) {
838 if(!(*it).categories().isEmpty() )
839 continue;
840 }else if ( bCat && cat != 0)
841 if (!(*it).categories().contains( cat ) ) {
842 continue;
843 }
844 /* isOverdue but we should not show overdue - why?*/
845/* if ( (*it).isOverdue() && !bOnly ) {
846 owarn << "item is overdue but !bOnly" << oendl;
847 continue; 674 continue;
848 } 675 if ( !todo.isOverdue() && bOnly )
849*/
850 if ( !(*it).isOverdue() && bOnly ) {
851 continue; 676 continue;
852 } 677 if (todo.isCompleted() && comp )
853
854 if ((*it).isCompleted() && comp ) {
855 continue; 678 continue;
856 }
857 679
858 680 vector.insert(item++, todo );
859 OPimTodoXMLContainer* con = new OPimTodoXMLContainer();
860 con->todo = (*it);
861 vector.insert(item, con );
862 item++;
863 } 681 }
682
864 vector.resize( item ); 683 vector.resize( item );
865 /* sort it now */ 684 /* sort it now */
866 vector.sort(); 685 vector.sort();
867 /* now get the uids */ 686 /* now get the uids */
868 QArray<int> array( vector.count() ); 687 UIDArray array( vector.count() );
869 for (uint i= 0; i < vector.count(); i++ ) { 688 for (uint i= 0; i < vector.count(); i++ )
870 array[i] = ( vector.at(i) )->todo.uid(); 689 array[i] = vector.uidAt( i );
871 } 690
872 return array; 691 return array;
873}; 692}
693
874void OPimTodoAccessXML::removeAllCompleted() { 694void OPimTodoAccessXML::removeAllCompleted() {
875 QMap<int, OPimTodo> events = m_events; 695 QMap<int, OPimTodo> events = m_events;
876 for ( QMap<int, OPimTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) { 696 for ( QMap<int, OPimTodo>::Iterator it = m_events.begin(); it != m_events.end(); ++it ) {
877 if ( (*it).isCompleted() ) 697 if ( (*it).isCompleted() )
878 events.remove( it.key() ); 698 events.remove( it.key() );
879 } 699 }
880 m_events = events; 700 m_events = events;
881} 701}
882QBitArray OPimTodoAccessXML::supports()const { 702
883 static QBitArray ar = sup();
884 return ar;
885}
886QBitArray OPimTodoAccessXML::sup() {
887 QBitArray ar( OPimTodo::CompletedDate +1 );
888 ar.fill( true );
889 ar[OPimTodo::CrossReference] = false;
890 ar[OPimTodo::State ] = false;
891 ar[OPimTodo::Reminders] = false;
892 ar[OPimTodo::Notifiers] = false;
893 ar[OPimTodo::Maintainer] = false;
894
895 return ar;
896}
897QArray<int> OPimTodoAccessXML::matchRegexp( const QRegExp &r ) const 703QArray<int> OPimTodoAccessXML::matchRegexp( const QRegExp &r ) const
898{ 704{
899 QArray<int> m_currentQuery( m_events.count() ); 705 QArray<int> currentQuery( m_events.count() );
900 uint arraycounter = 0; 706 uint arraycounter = 0;
901 707
902 QMap<int, OPimTodo>::ConstIterator it; 708 QMap<int, OPimTodo>::ConstIterator it;
903 for (it = m_events.begin(); it != m_events.end(); ++it ) { 709 for (it = m_events.begin(); it != m_events.end(); ++it ) {
904 if ( it.data().match( r ) ) 710 if ( it.data().match( r ) )
905 m_currentQuery[arraycounter++] = it.data().uid(); 711 currentQuery[arraycounter++] = it.data().uid();
906 712
907 } 713 }
908 // Shrink to fit.. 714 // Shrink to fit..
909 m_currentQuery.resize(arraycounter); 715 currentQuery.resize(arraycounter);
910 716
911 return m_currentQuery; 717 return currentQuery;
912} 718}
913 719
914} 720}
diff --git a/libopie2/opiepim/backend/otodoaccessxml.h b/libopie2/opiepim/backend/otodoaccessxml.h
index 3a51543..134a21a 100644
--- a/libopie2/opiepim/backend/otodoaccessxml.h
+++ b/libopie2/opiepim/backend/otodoaccessxml.h
@@ -50,40 +50,39 @@ public:
50 bool reload(); 50 bool reload();
51 bool save(); 51 bool save();
52 52
53 QArray<int> allRecords()const; 53 QArray<int> allRecords()const;
54 QArray<int> matchRegexp(const QRegExp &r) const; 54 QArray<int> matchRegexp(const QRegExp &r) const;
55 QArray<int> queryByExample( const OPimTodo&, int querysettings, const QDateTime& d = QDateTime() ); 55 QArray<int> queryByExample( const OPimTodo&, int querysettings, const QDateTime& d = QDateTime() );
56 OPimTodo find( int uid )const; 56 OPimTodo find( int uid )const;
57 void clear(); 57 void clear();
58 bool add( const OPimTodo& ); 58 bool add( const OPimTodo& );
59 bool remove( int uid ); 59 bool remove( int uid );
60 void removeAllCompleted(); 60 void removeAllCompleted();
61 bool replace( const OPimTodo& ); 61 bool replace( const OPimTodo& );
62 62
63 /* our functions */ 63 /* our functions */
64 QArray<int> effectiveToDos( const QDate& start, 64 QArray<int> effectiveToDos( const QDate& start,
65 const QDate& end, 65 const QDate& end,
66 bool includeNoDates ); 66 bool includeNoDates )const;
67 QArray<int> overDue(); 67 QArray<int> overDue()const;
68 QArray<int> sorted( bool asc, int sortOrder, 68
69 int sortFilter, int cat ); 69//@{
70 QBitArray supports()const; 70 UIDArray sorted( const UIDArray&, bool, int, int, const QArray<int>& )const;
71//@}
71private: 72private:
72 static QBitArray sup();
73 void todo( QAsciiDict<int>*, OPimTodo&,const QCString&,const QString& ); 73 void todo( QAsciiDict<int>*, OPimTodo&,const QCString&,const QString& );
74 QString toString( const OPimTodo& )const; 74 QString toString( const OPimTodo& )const;
75 QString toString( const QArray<int>& ints ) const; 75 QString toString( const QArray<int>& ints ) const;
76 QMap<int, OPimTodo> m_events; 76 QMap<int, OPimTodo> m_events;
77 QString m_file; 77 QString m_file;
78 QString m_app; 78 QString m_app;
79 bool m_opened : 1; 79 bool m_opened : 1;
80 bool m_changed : 1; 80 bool m_changed : 1;
81 class OPimTodoAccessXMLPrivate; 81 class OPimTodoAccessXMLPrivate;
82 OPimTodoAccessXMLPrivate* d; 82 OPimTodoAccessXMLPrivate* d;
83 int m_year, m_month, m_day; 83 int m_year, m_month, m_day;
84
85}; 84};
86 85
87}; 86};
88 87
89#endif 88#endif